strsafe.h 201 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266
  1. //
  2. // Copyright (c) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  4. //
  5. /*++
  6. --*/
  7. /******************************************************************
  8. * *
  9. * strsafe.h -- This module defines safer C library string *
  10. * routine replacements. These are meant to make C *
  11. * a bit more safe in reference to security and *
  12. * robustness *
  13. * *
  14. ******************************************************************/
  15. #ifndef _STRSAFE_H_INCLUDED_
  16. #define _STRSAFE_H_INCLUDED_
  17. #ifdef _MSC_VER
  18. #pragma once
  19. #endif
  20. #if defined(PLATFORM_UNIX) && !defined (FEATURE_PAL)
  21. #define _NATIVE_WCHAR_T_DEFINED
  22. #endif // defined(PLATFORM_UNIX) && !defined (FEATURE_PAL)
  23. #if defined(PLATFORM_UNIX) && !defined (FEATURE_PAL)
  24. #define _vsnprintf vsnprintf
  25. #endif // defined(PLATFORM_UNIX) && !defined (FEATURE_PAL)
  26. #include <stdio.h> // for _vsnprintf, _vsnwprintf, getc, getwc
  27. #include <string.h> // for memset
  28. #include <stdarg.h> // for va_start, etc.
  29. #ifndef _SIZE_T_DEFINED
  30. #ifdef _WIN64
  31. typedef unsigned __int64 size_t;
  32. #else
  33. typedef __w64 unsigned int size_t;
  34. #endif // !_WIN64
  35. #define _SIZE_T_DEFINED
  36. #endif // !_SIZE_T_DEFINED
  37. #if !defined(PAL_WCHAR_T_DEFINED) && !defined(_NATIVE_WCHAR_T_DEFINED)
  38. #error Unexpected define.
  39. typedef char16_t WCHAR;
  40. #define PAL_WCHAR_T_DEFINED
  41. #endif
  42. #ifndef FEATURE_PAL
  43. #ifndef _HRESULT_DEFINED
  44. #define _HRESULT_DEFINED
  45. typedef LONG HRESULT;
  46. #endif // !_HRESULT_DEFINED
  47. #endif // !FEATURE_PAL
  48. #ifndef SUCCEEDED
  49. #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
  50. #endif
  51. #ifndef FAILED
  52. #define FAILED(hr) ((HRESULT)(hr) < 0)
  53. #endif
  54. #ifndef S_OK
  55. #define S_OK ((HRESULT)0x00000000L)
  56. #endif
  57. #ifdef __cplusplus
  58. #define _STRSAFE_EXTERN_C extern "C"
  59. #else
  60. #define _STRSAFE_EXTERN_C extern
  61. #endif
  62. // If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then
  63. // #define STRSAFE_LIB before including this header file.
  64. #if defined(STRSAFE_LIB)
  65. #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall
  66. #pragma comment(lib, "strsafe.lib")
  67. #elif defined(STRSAFE_LIB_IMPL)
  68. #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall
  69. #else
  70. #define STRSAFEAPI __inline HRESULT __stdcall
  71. #define STRSAFE_INLINE
  72. #endif
  73. // Some functions always run inline because they use stdin and we want to avoid building multiple
  74. // versions of strsafe lib depending on if you use msvcrt, libcmt, etc.
  75. #define STRSAFE_INLINE_API __inline HRESULT __stdcall
  76. // The user can request no "Cb" or no "Cch" fuctions, but not both!
  77. #if defined(STRSAFE_NO_CB_FUNCTIONS) && defined(STRSAFE_NO_CCH_FUNCTIONS)
  78. #error cannot specify both STRSAFE_NO_CB_FUNCTIONS and STRSAFE_NO_CCH_FUNCTIONS !!
  79. #endif
  80. // This should only be defined when we are building strsafe.lib
  81. #ifdef STRSAFE_LIB_IMPL
  82. #define STRSAFE_INLINE
  83. #endif
  84. #define STRSAFE_MAX_CCH 2147483647 // max # of characters we support (same as INT_MAX)
  85. // STRSAFE error return codes
  86. //
  87. #define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER
  88. #define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) // 0x57 = 87L = ERROR_INVALID_PARAMETER
  89. #define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) // 0x26 = 38L = ERROR_HANDLE_EOF
  90. // Flags for controling the Ex functions
  91. //
  92. // STRSAFE_FILL_BYTE(0xFF) 0x000000FF // bottom byte specifies fill pattern
  93. #define STRSAFE_IGNORE_NULLS 0x00000100 // treat null as TEXT("") -- don't fault on NULL buffers
  94. #define STRSAFE_FILL_BEHIND_NULL 0x00000200 // fill in extra space behind the null terminator
  95. #define STRSAFE_FILL_ON_FAILURE 0x00000400 // on failure, overwrite pszDest with fill pattern and null terminate it
  96. #define STRSAFE_NULL_ON_FAILURE 0x00000800 // on failure, set *pszDest = TEXT('\0')
  97. #define STRSAFE_NO_TRUNCATION 0x00001000 // instead of returning a truncated result, copy/append nothing to pszDest and null terminate it
  98. #define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)
  99. // helper macro to set the fill character and specify buffer filling
  100. #define STRSAFE_FILL_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL))
  101. #define STRSAFE_FAILURE_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_ON_FAILURE))
  102. #define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)(dwFlags & 0x000000FF))
  103. // prototypes for the worker functions
  104. #ifdef STRSAFE_INLINE
  105. STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc);
  106. STRSAFEAPI StringCopyWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc);
  107. STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  108. STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  109. STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc);
  110. STRSAFEAPI StringCopyNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc);
  111. STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  112. STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  113. STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc);
  114. STRSAFEAPI StringCatWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc);
  115. STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  116. STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  117. STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend);
  118. STRSAFEAPI StringCatNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend);
  119. STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  120. STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  121. STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList);
  122. STRSAFEAPI StringVPrintfWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList);
  123. STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
  124. STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList);
  125. STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch);
  126. STRSAFEAPI StringLengthWorkerW(const WCHAR* psz, size_t cchMax, size_t* pcch);
  127. #endif // STRSAFE_INLINE
  128. #ifndef STRSAFE_LIB_IMPL
  129. #ifndef FEATURE_PAL
  130. // these functions are always inline
  131. STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  132. STRSAFE_INLINE_API StringGetsExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  133. #endif // !FEATURE_PAL
  134. #endif
  135. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  136. /*++
  137. STDAPI StringCchCopy(LPTSTR pszDest,
  138. size_t cchDest,
  139. LPCTSTR pszSrc);
  140. Routine Description:
  141. This routine is a safer version of the C built-in function 'strcpy'.
  142. The size of the destination buffer (in characters) is a parameter and
  143. this function will not write past the end of this buffer and it will
  144. ALWAYS null terminate the destination buffer (unless it is zero length).
  145. This routine is not a replacement for strncpy. That function will pad the
  146. destination string with extra null termination characters if the count is
  147. greater than the length of the source string, and it will fail to null
  148. terminate the destination string if the source string length is greater
  149. than or equal to the count. You can not blindly use this instead of strncpy:
  150. it is common for code to use it to "patch" strings and you would introduce
  151. errors if the code started null terminating in the middle of the string.
  152. This function returns a hresult, and not a pointer. It returns a S_OK
  153. if the string was copied without truncation and null terminated, otherwise
  154. it will return a failure code. In failure cases as much of pszSrc will be
  155. copied to pszDest as possible, and pszDest will be null terminated.
  156. Arguments:
  157. pszDest - destination string
  158. cchDest - size of destination buffer in characters.
  159. length must be = (_tcslen(src) + 1) to hold all of the
  160. source including the null terminator
  161. pszSrc - source string which must be null terminated
  162. Notes:
  163. Behavior is undefined if source and destination strings overlap.
  164. pszDest and pszSrc should not be NULL. See StringCchCopyEx if you require
  165. the handling of NULL values.
  166. Return Value:
  167. S_OK - if there was source data and it was all copied and the
  168. resultant dest string was null terminated
  169. failure - you can use the macro HRESULT_CODE() to get a win32 error
  170. code for all hresult falure cases
  171. STRSAFE_E_INSUFFICIENT_BUFFER /
  172. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  173. - this return value is an indication that the copy operation
  174. failed due to insufficient space. When this error occurs,
  175. the destination buffer is modified to contain a truncated
  176. version of the ideal result and is null terminated. This
  177. is useful for situations where truncation is ok
  178. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  179. return value of this function.
  180. --*/
  181. STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc);
  182. STRSAFEAPI StringCchCopyW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc);
  183. #ifdef UNICODE
  184. #define StringCchCopy StringCchCopyW
  185. #else
  186. #define StringCchCopy StringCchCopyA
  187. #endif // !UNICODE
  188. #ifdef STRSAFE_INLINE
  189. STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc)
  190. {
  191. HRESULT hr;
  192. if (cchDest > STRSAFE_MAX_CCH)
  193. {
  194. hr = STRSAFE_E_INVALID_PARAMETER;
  195. }
  196. else
  197. {
  198. hr = StringCopyWorkerA(pszDest, cchDest, pszSrc);
  199. }
  200. return hr;
  201. }
  202. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  203. STRSAFEAPI StringCchCopyW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc)
  204. {
  205. HRESULT hr;
  206. if (cchDest > STRSAFE_MAX_CCH)
  207. {
  208. hr = STRSAFE_E_INVALID_PARAMETER;
  209. }
  210. else
  211. {
  212. hr = StringCopyWorkerW(pszDest, cchDest, pszSrc);
  213. }
  214. return hr;
  215. }
  216. #endif // FEATURE_PAL || !PLATFORM_UNIX
  217. #endif // STRSAFE_INLINE
  218. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  219. #ifndef STRSAFE_NO_CB_FUNCTIONS
  220. /*++
  221. STDAPI StringCbCopy(LPTSTR pszDest,
  222. size_t cbDest,
  223. LPCTSTR pszSrc);
  224. Routine Description:
  225. This routine is a safer version of the C built-in function 'strcpy'.
  226. The size of the destination buffer (in bytes) is a parameter and this
  227. function will not write past the end of this buffer and it will ALWAYS
  228. null terminate the destination buffer (unless it is zero length).
  229. This routine is not a replacement for strncpy. That function will pad the
  230. destination string with extra null termination characters if the count is
  231. greater than the length of the source string, and it will fail to null
  232. terminate the destination string if the source string length is greater
  233. than or equal to the count. You can not blindly use this instead of strncpy:
  234. it is common for code to use it to "patch" strings and you would introduce
  235. errors if the code started null terminating in the middle of the string.
  236. This function returns a hresult, and not a pointer. It returns a S_OK
  237. if the string was copied without truncation and null terminated, otherwise
  238. it will return a failure code. In failure cases as much of pszSrc will be
  239. copied to pszDest as possible, and pszDest will be null terminated.
  240. Arguments:
  241. pszDest - destination string
  242. cbDest - size of destination buffer in bytes.
  243. length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to
  244. hold all of the source including the null terminator
  245. pszSrc - source string which must be null terminated
  246. Notes:
  247. Behavior is undefined if source and destination strings overlap.
  248. pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require
  249. the handling of NULL values.
  250. Return Value:
  251. S_OK - if there was source data and it was all copied and the
  252. resultant dest string was null terminated
  253. failure - you can use the macro HRESULT_CODE() to get a win32 error
  254. code for all hresult falure cases
  255. STRSAFE_E_INSUFFICIENT_BUFFER /
  256. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  257. - this return value is an indication that the copy operation
  258. failed due to insufficient space. When this error occurs,
  259. the destination buffer is modified to contain a truncated
  260. version of the ideal result and is null terminated. This
  261. is useful for situations where truncation is ok
  262. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  263. return value of this function.
  264. --*/
  265. STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc);
  266. STRSAFEAPI StringCbCopyW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc);
  267. #ifdef UNICODE
  268. #define StringCbCopy StringCbCopyW
  269. #else
  270. #define StringCbCopy StringCbCopyA
  271. #endif // !UNICODE
  272. #ifdef STRSAFE_INLINE
  273. STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc)
  274. {
  275. HRESULT hr;
  276. size_t cchDest;
  277. // convert to count of characters
  278. cchDest = cbDest / sizeof(char);
  279. if (cchDest > STRSAFE_MAX_CCH)
  280. {
  281. hr = STRSAFE_E_INVALID_PARAMETER;
  282. }
  283. else
  284. {
  285. hr = StringCopyWorkerA(pszDest, cchDest, pszSrc);
  286. }
  287. return hr;
  288. }
  289. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  290. STRSAFEAPI StringCbCopyW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc)
  291. {
  292. HRESULT hr;
  293. size_t cchDest;
  294. // convert to count of characters
  295. cchDest = cbDest / sizeof(WCHAR);
  296. if (cchDest > STRSAFE_MAX_CCH)
  297. {
  298. hr = STRSAFE_E_INVALID_PARAMETER;
  299. }
  300. else
  301. {
  302. hr = StringCopyWorkerW(pszDest, cchDest, pszSrc);
  303. }
  304. return hr;
  305. }
  306. #endif // FEATURE_PAL || !PLATFORM_UNIX
  307. #endif // STRSAFE_INLINE
  308. #endif // !STRSAFE_NO_CB_FUNCTIONS
  309. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  310. /*++
  311. STDAPI StringCchCopyEx(TCHAR pszDest,
  312. size_t cchDest,
  313. LPCTSTR pszSrc,
  314. LPTSTR* ppszDestEnd,
  315. size_t* pcchRemaining,
  316. DWORD dwFlags);
  317. Routine Description:
  318. This routine is a safer version of the C built-in function 'strcpy' with
  319. some additional parameters. In addition to functionality provided by
  320. StringCchCopy, this routine also returns a pointer to the end of the
  321. destination string and the number of characters left in the destination string
  322. including the null terminator. The flags parameter allows additional controls.
  323. Arguments:
  324. pszDest - destination string
  325. cchDest - size of destination buffer in characters.
  326. length must be = (_tcslen(pszSrc) + 1) to hold all of
  327. the source including the null terminator
  328. pszSrc - source string which must be null terminated
  329. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  330. pointer to the end of the destination string. If the
  331. function copied any data, the result will point to the
  332. null termination character
  333. pcchRemaining - if pcchRemaining is non-null, the function will return the
  334. number of characters left in the destination string,
  335. including the null terminator
  336. dwFlags - controls some details of the string copy:
  337. STRSAFE_FILL_BEHIND_NULL
  338. if the function succeeds, the low byte of dwFlags will be
  339. used to fill the uninitialize part of destination buffer
  340. behind the null terminator
  341. STRSAFE_IGNORE_NULLS
  342. treat NULL string pointers like empty strings (TEXT("")).
  343. this flag is useful for emulating functions like lstrcpy
  344. STRSAFE_FILL_ON_FAILURE
  345. if the function fails, the low byte of dwFlags will be
  346. used to fill all of the destination buffer, and it will
  347. be null terminated. This will overwrite any truncated
  348. string returned when the failure is
  349. STRSAFE_E_INSUFFICIENT_BUFFER
  350. STRSAFE_NO_TRUNCATION /
  351. STRSAFE_NULL_ON_FAILURE
  352. if the function fails, the destination buffer will be set
  353. to the empty string. This will overwrite any truncated string
  354. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  355. Notes:
  356. Behavior is undefined if source and destination strings overlap.
  357. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  358. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  359. may be NULL. An error may still be returned even though NULLS are ignored
  360. due to insufficient space.
  361. Return Value:
  362. S_OK - if there was source data and it was all copied and the
  363. resultant dest string was null terminated
  364. failure - you can use the macro HRESULT_CODE() to get a win32 error
  365. code for all falure cases
  366. STRSAFE_E_INSUFFICIENT_BUFFER /
  367. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  368. - this return value is an indication that the copy operation
  369. failed due to insufficient space. When this error occurs,
  370. the destination buffer is modified to contain a truncated
  371. version of the ideal result and is null terminated. This
  372. is useful for situations where truncation is ok.
  373. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  374. return value of this function
  375. --*/
  376. STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  377. STRSAFEAPI StringCchCopyExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  378. #ifdef UNICODE
  379. #define StringCchCopyEx StringCchCopyExW
  380. #else
  381. #define StringCchCopyEx StringCchCopyExA
  382. #endif // !UNICODE
  383. #ifdef STRSAFE_INLINE
  384. STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  385. {
  386. HRESULT hr;
  387. if (cchDest > STRSAFE_MAX_CCH)
  388. {
  389. hr = STRSAFE_E_INVALID_PARAMETER;
  390. }
  391. else
  392. {
  393. size_t cbDest;
  394. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  395. cbDest = cchDest * sizeof(char);
  396. hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
  397. }
  398. return hr;
  399. }
  400. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  401. STRSAFEAPI StringCchCopyExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  402. {
  403. HRESULT hr;
  404. if (cchDest > STRSAFE_MAX_CCH)
  405. {
  406. hr = STRSAFE_E_INVALID_PARAMETER;
  407. }
  408. else
  409. {
  410. size_t cbDest;
  411. // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  412. cbDest = cchDest * sizeof(WCHAR);
  413. hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
  414. }
  415. return hr;
  416. }
  417. #endif // FEATURE_PAL || !PLATFORM_UNIX
  418. #endif // STRSAFE_INLINE
  419. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  420. #ifndef STRSAFE_NO_CB_FUNCTIONS
  421. /*++
  422. STDAPI StringCbCopyEx(TCHAR pszDest,
  423. size_t cbDest,
  424. LPCTSTR pszSrc,
  425. LPTSTR* ppszDestEnd,
  426. size_t* pcbRemaining,
  427. DWORD dwFlags);
  428. Routine Description:
  429. This routine is a safer version of the C built-in function 'strcpy' with
  430. some additional parameters. In addition to functionality provided by
  431. StringCbCopy, this routine also returns a pointer to the end of the
  432. destination string and the number of bytes left in the destination string
  433. including the null terminator. The flags parameter allows additional controls.
  434. Arguments:
  435. pszDest - destination string
  436. cbDest - size of destination buffer in bytes.
  437. length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to
  438. hold all of the source including the null terminator
  439. pszSrc - source string which must be null terminated
  440. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  441. pointer to the end of the destination string. If the
  442. function copied any data, the result will point to the
  443. null termination character
  444. pcbRemaining - pcbRemaining is non-null,the function will return the
  445. number of bytes left in the destination string,
  446. including the null terminator
  447. dwFlags - controls some details of the string copy:
  448. STRSAFE_FILL_BEHIND_NULL
  449. if the function succeeds, the low byte of dwFlags will be
  450. used to fill the uninitialize part of destination buffer
  451. behind the null terminator
  452. STRSAFE_IGNORE_NULLS
  453. treat NULL string pointers like empty strings (TEXT("")).
  454. this flag is useful for emulating functions like lstrcpy
  455. STRSAFE_FILL_ON_FAILURE
  456. if the function fails, the low byte of dwFlags will be
  457. used to fill all of the destination buffer, and it will
  458. be null terminated. This will overwrite any truncated
  459. string returned when the failure is
  460. STRSAFE_E_INSUFFICIENT_BUFFER
  461. STRSAFE_NO_TRUNCATION /
  462. STRSAFE_NULL_ON_FAILURE
  463. if the function fails, the destination buffer will be set
  464. to the empty string. This will overwrite any truncated string
  465. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  466. Notes:
  467. Behavior is undefined if source and destination strings overlap.
  468. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  469. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  470. may be NULL. An error may still be returned even though NULLS are ignored
  471. due to insufficient space.
  472. Return Value:
  473. S_OK - if there was source data and it was all copied and the
  474. resultant dest string was null terminated
  475. failure - you can use the macro HRESULT_CODE() to get a win32 error
  476. code for all falure cases
  477. STRSAFE_E_INSUFFICIENT_BUFFER /
  478. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  479. - this return value is an indication that the copy operation
  480. failed due to insufficient space. When this error occurs,
  481. the destination buffer is modified to contain a truncated
  482. version of the ideal result and is null terminated. This
  483. is useful for situations where truncation is ok.
  484. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  485. return value of this function
  486. --*/
  487. STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  488. STRSAFEAPI StringCbCopyExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  489. #ifdef UNICODE
  490. #define StringCbCopyEx StringCbCopyExW
  491. #else
  492. #define StringCbCopyEx StringCbCopyExA
  493. #endif // !UNICODE
  494. #ifdef STRSAFE_INLINE
  495. STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  496. {
  497. HRESULT hr;
  498. size_t cchDest;
  499. size_t cchRemaining = 0;
  500. cchDest = cbDest / sizeof(char);
  501. if (cchDest > STRSAFE_MAX_CCH)
  502. {
  503. hr = STRSAFE_E_INVALID_PARAMETER;
  504. }
  505. else
  506. {
  507. hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
  508. }
  509. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  510. {
  511. if (pcbRemaining)
  512. {
  513. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  514. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  515. }
  516. }
  517. return hr;
  518. }
  519. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  520. STRSAFEAPI StringCbCopyExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  521. {
  522. HRESULT hr;
  523. size_t cchDest;
  524. size_t cchRemaining = 0;
  525. cchDest = cbDest / sizeof(WCHAR);
  526. if (cchDest > STRSAFE_MAX_CCH)
  527. {
  528. hr = STRSAFE_E_INVALID_PARAMETER;
  529. }
  530. else
  531. {
  532. hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
  533. }
  534. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  535. {
  536. if (pcbRemaining)
  537. {
  538. // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  539. *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR));
  540. }
  541. }
  542. return hr;
  543. }
  544. #endif // FEATURE_PAL || !PLATFORM_UNIX
  545. #endif // STRSAFE_INLINE
  546. #endif // !STRSAFE_NO_CB_FUNCTIONS
  547. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  548. /*++
  549. STDAPI StringCchCopyN(LPTSTR pszDest,
  550. size_t cchDest,
  551. LPCTSTR pszSrc,
  552. size_t cchSrc);
  553. Routine Description:
  554. This routine is a safer version of the C built-in function 'strncpy'.
  555. The size of the destination buffer (in characters) is a parameter and
  556. this function will not write past the end of this buffer and it will
  557. ALWAYS null terminate the destination buffer (unless it is zero length).
  558. This routine is meant as a replacement for strncpy, but it does behave
  559. differently. This function will not pad the destination buffer with extra
  560. null termination characters if cchSrc is greater than the length of pszSrc.
  561. This function returns a hresult, and not a pointer. It returns a S_OK
  562. if the entire string or the first cchSrc characters were copied without
  563. truncation and the resultant destination string was null terminated, otherwise
  564. it will return a failure code. In failure cases as much of pszSrc will be
  565. copied to pszDest as possible, and pszDest will be null terminated.
  566. Arguments:
  567. pszDest - destination string
  568. cchDest - size of destination buffer in characters.
  569. length must be = (_tcslen(src) + 1) to hold all of the
  570. source including the null terminator
  571. pszSrc - source string
  572. cchSrc - maximum number of characters to copy from source string
  573. Notes:
  574. Behavior is undefined if source and destination strings overlap.
  575. pszDest and pszSrc should not be NULL. See StringCchCopyNEx if you require
  576. the handling of NULL values.
  577. Return Value:
  578. S_OK - if there was source data and it was all copied and the
  579. resultant dest string was null terminated
  580. failure - you can use the macro HRESULT_CODE() to get a win32 error
  581. code for all hresult falure cases
  582. STRSAFE_E_INSUFFICIENT_BUFFER /
  583. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  584. - this return value is an indication that the copy operation
  585. failed due to insufficient space. When this error occurs,
  586. the destination buffer is modified to contain a truncated
  587. version of the ideal result and is null terminated. This
  588. is useful for situations where truncation is ok
  589. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  590. return value of this function.
  591. --*/
  592. STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc);
  593. STRSAFEAPI StringCchCopyNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc);
  594. #ifdef UNICODE
  595. #define StringCchCopyN StringCchCopyNW
  596. #else
  597. #define StringCchCopyN StringCchCopyNA
  598. #endif // !UNICODE
  599. #ifdef STRSAFE_INLINE
  600. STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc)
  601. {
  602. HRESULT hr;
  603. if ((cchDest > STRSAFE_MAX_CCH) ||
  604. (cchSrc > STRSAFE_MAX_CCH))
  605. {
  606. hr = STRSAFE_E_INVALID_PARAMETER;
  607. }
  608. else
  609. {
  610. hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc);
  611. }
  612. return hr;
  613. }
  614. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  615. STRSAFEAPI StringCchCopyNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc)
  616. {
  617. HRESULT hr;
  618. if ((cchDest > STRSAFE_MAX_CCH) ||
  619. (cchSrc > STRSAFE_MAX_CCH))
  620. {
  621. hr = STRSAFE_E_INVALID_PARAMETER;
  622. }
  623. else
  624. {
  625. hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc);
  626. }
  627. return hr;
  628. }
  629. #endif // FEATURE_PAL || !PLATFORM_UNIX
  630. #endif // STRSAFE_INLINE
  631. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  632. #ifndef STRSAFE_NO_CB_FUNCTIONS
  633. /*++
  634. STDAPI StringCbCopyN(LPTSTR pszDest,
  635. size_t cbDest,
  636. LPCTSTR pszSrc,
  637. size_t cbSrc);
  638. Routine Description:
  639. This routine is a safer version of the C built-in function 'strncpy'.
  640. The size of the destination buffer (in bytes) is a parameter and this
  641. function will not write past the end of this buffer and it will ALWAYS
  642. null terminate the destination buffer (unless it is zero length).
  643. This routine is meant as a replacement for strncpy, but it does behave
  644. differently. This function will not pad the destination buffer with extra
  645. null termination characters if cbSrc is greater than the size of pszSrc.
  646. This function returns a hresult, and not a pointer. It returns a S_OK
  647. if the entire string or the first cbSrc characters were copied without
  648. truncation and the resultant destination string was null terminated, otherwise
  649. it will return a failure code. In failure cases as much of pszSrc will be
  650. copied to pszDest as possible, and pszDest will be null terminated.
  651. Arguments:
  652. pszDest - destination string
  653. cbDest - size of destination buffer in bytes.
  654. length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to
  655. hold all of the source including the null terminator
  656. pszSrc - source string
  657. cbSrc - maximum number of bytes to copy from source string
  658. Notes:
  659. Behavior is undefined if source and destination strings overlap.
  660. pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require
  661. the handling of NULL values.
  662. Return Value:
  663. S_OK - if there was source data and it was all copied and the
  664. resultant dest string was null terminated
  665. failure - you can use the macro HRESULT_CODE() to get a win32 error
  666. code for all hresult falure cases
  667. STRSAFE_E_INSUFFICIENT_BUFFER /
  668. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  669. - this return value is an indication that the copy operation
  670. failed due to insufficient space. When this error occurs,
  671. the destination buffer is modified to contain a truncated
  672. version of the ideal result and is null terminated. This
  673. is useful for situations where truncation is ok
  674. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  675. return value of this function.
  676. --*/
  677. STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc);
  678. STRSAFEAPI StringCbCopyNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc);
  679. #ifdef UNICODE
  680. #define StringCbCopyN StringCbCopyNW
  681. #else
  682. #define StringCbCopyN StringCbCopyNA
  683. #endif // !UNICODE
  684. #ifdef STRSAFE_INLINE
  685. STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc)
  686. {
  687. HRESULT hr;
  688. size_t cchDest;
  689. size_t cchSrc;
  690. // convert to count of characters
  691. cchDest = cbDest / sizeof(char);
  692. cchSrc = cbSrc / sizeof(char);
  693. if ((cchDest > STRSAFE_MAX_CCH) ||
  694. (cchSrc > STRSAFE_MAX_CCH))
  695. {
  696. hr = STRSAFE_E_INVALID_PARAMETER;
  697. }
  698. else
  699. {
  700. hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc);
  701. }
  702. return hr;
  703. }
  704. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  705. STRSAFEAPI StringCbCopyNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc)
  706. {
  707. HRESULT hr;
  708. size_t cchDest;
  709. size_t cchSrc;
  710. // convert to count of characters
  711. cchDest = cbDest / sizeof(WCHAR);
  712. cchSrc = cbSrc / sizeof(WCHAR);
  713. if ((cchDest > STRSAFE_MAX_CCH) ||
  714. (cchSrc > STRSAFE_MAX_CCH))
  715. {
  716. hr = STRSAFE_E_INVALID_PARAMETER;
  717. }
  718. else
  719. {
  720. hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc);
  721. }
  722. return hr;
  723. }
  724. #endif // FEATURE_PAL || !PLATFORM_UNIX
  725. #endif // STRSAFE_INLINE
  726. #endif // !STRSAFE_NO_CB_FUNCTIONS
  727. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  728. /*++
  729. STDAPI StringCchCopyNEx(TCHAR pszDest,
  730. size_t cchDest,
  731. LPCTSTR pszSrc,
  732. size_t cchSrc,
  733. LPTSTR* ppszDestEnd,
  734. size_t* pcchRemaining,
  735. DWORD dwFlags);
  736. Routine Description:
  737. This routine is a safer version of the C built-in function 'strncpy' with
  738. some additional parameters. In addition to functionality provided by
  739. StringCchCopyN, this routine also returns a pointer to the end of the
  740. destination string and the number of characters left in the destination
  741. string including the null terminator. The flags parameter allows
  742. additional controls.
  743. This routine is meant as a replacement for strncpy, but it does behave
  744. differently. This function will not pad the destination buffer with extra
  745. null termination characters if cchSrc is greater than the length of pszSrc.
  746. Arguments:
  747. pszDest - destination string
  748. cchDest - size of destination buffer in characters.
  749. length must be = (_tcslen(pszSrc) + 1) to hold all of
  750. the source including the null terminator
  751. pszSrc - source string
  752. cchSrc - maximum number of characters to copy from the source
  753. string
  754. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  755. pointer to the end of the destination string. If the
  756. function copied any data, the result will point to the
  757. null termination character
  758. pcchRemaining - if pcchRemaining is non-null, the function will return the
  759. number of characters left in the destination string,
  760. including the null terminator
  761. dwFlags - controls some details of the string copy:
  762. STRSAFE_FILL_BEHIND_NULL
  763. if the function succeeds, the low byte of dwFlags will be
  764. used to fill the uninitialize part of destination buffer
  765. behind the null terminator
  766. STRSAFE_IGNORE_NULLS
  767. treat NULL string pointers like empty strings (TEXT("")).
  768. this flag is useful for emulating functions like lstrcpy
  769. STRSAFE_FILL_ON_FAILURE
  770. if the function fails, the low byte of dwFlags will be
  771. used to fill all of the destination buffer, and it will
  772. be null terminated. This will overwrite any truncated
  773. string returned when the failure is
  774. STRSAFE_E_INSUFFICIENT_BUFFER
  775. STRSAFE_NO_TRUNCATION /
  776. STRSAFE_NULL_ON_FAILURE
  777. if the function fails, the destination buffer will be set
  778. to the empty string. This will overwrite any truncated string
  779. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  780. Notes:
  781. Behavior is undefined if source and destination strings overlap.
  782. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  783. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  784. may be NULL. An error may still be returned even though NULLS are ignored
  785. due to insufficient space.
  786. Return Value:
  787. S_OK - if there was source data and it was all copied and the
  788. resultant dest string was null terminated
  789. failure - you can use the macro HRESULT_CODE() to get a win32 error
  790. code for all falure cases
  791. STRSAFE_E_INSUFFICIENT_BUFFER /
  792. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  793. - this return value is an indication that the copy operation
  794. failed due to insufficient space. When this error occurs,
  795. the destination buffer is modified to contain a truncated
  796. version of the ideal result and is null terminated. This
  797. is useful for situations where truncation is ok.
  798. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  799. return value of this function
  800. --*/
  801. STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  802. STRSAFEAPI StringCchCopyNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  803. #ifdef UNICODE
  804. #define StringCchCopyNEx StringCchCopyNExW
  805. #else
  806. #define StringCchCopyNEx StringCchCopyNExA
  807. #endif // !UNICODE
  808. #ifdef STRSAFE_INLINE
  809. STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  810. {
  811. HRESULT hr;
  812. if ((cchDest > STRSAFE_MAX_CCH) ||
  813. (cchSrc > STRSAFE_MAX_CCH))
  814. {
  815. hr = STRSAFE_E_INVALID_PARAMETER;
  816. }
  817. else
  818. {
  819. size_t cbDest;
  820. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  821. cbDest = cchDest * sizeof(char);
  822. hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags);
  823. }
  824. return hr;
  825. }
  826. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  827. STRSAFEAPI StringCchCopyNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  828. {
  829. HRESULT hr;
  830. if ((cchDest > STRSAFE_MAX_CCH) ||
  831. (cchSrc > STRSAFE_MAX_CCH))
  832. {
  833. hr = STRSAFE_E_INVALID_PARAMETER;
  834. }
  835. else
  836. {
  837. size_t cbDest;
  838. // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  839. cbDest = cchDest * sizeof(WCHAR);
  840. hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags);
  841. }
  842. return hr;
  843. }
  844. #endif // FEATURE_PAL || !PLATFORM_UNIX
  845. #endif // STRSAFE_INLINE
  846. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  847. #ifndef STRSAFE_NO_CB_FUNCTIONS
  848. /*++
  849. STDAPI StringCbCopyNEx(TCHAR pszDest,
  850. size_t cbDest,
  851. LPCTSTR pszSrc,
  852. size_t cbSrc,
  853. LPTSTR* ppszDestEnd,
  854. size_t* pcbRemaining,
  855. DWORD dwFlags);
  856. Routine Description:
  857. This routine is a safer version of the C built-in function 'strncpy' with
  858. some additional parameters. In addition to functionality provided by
  859. StringCbCopyN, this routine also returns a pointer to the end of the
  860. destination string and the number of bytes left in the destination string
  861. including the null terminator. The flags parameter allows additional controls.
  862. This routine is meant as a replacement for strncpy, but it does behave
  863. differently. This function will not pad the destination buffer with extra
  864. null termination characters if cbSrc is greater than the size of pszSrc.
  865. Arguments:
  866. pszDest - destination string
  867. cbDest - size of destination buffer in bytes.
  868. length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to
  869. hold all of the source including the null terminator
  870. pszSrc - source string
  871. cbSrc - maximum number of bytes to copy from source string
  872. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  873. pointer to the end of the destination string. If the
  874. function copied any data, the result will point to the
  875. null termination character
  876. pcbRemaining - pcbRemaining is non-null,the function will return the
  877. number of bytes left in the destination string,
  878. including the null terminator
  879. dwFlags - controls some details of the string copy:
  880. STRSAFE_FILL_BEHIND_NULL
  881. if the function succeeds, the low byte of dwFlags will be
  882. used to fill the uninitialize part of destination buffer
  883. behind the null terminator
  884. STRSAFE_IGNORE_NULLS
  885. treat NULL string pointers like empty strings (TEXT("")).
  886. this flag is useful for emulating functions like lstrcpy
  887. STRSAFE_FILL_ON_FAILURE
  888. if the function fails, the low byte of dwFlags will be
  889. used to fill all of the destination buffer, and it will
  890. be null terminated. This will overwrite any truncated
  891. string returned when the failure is
  892. STRSAFE_E_INSUFFICIENT_BUFFER
  893. STRSAFE_NO_TRUNCATION /
  894. STRSAFE_NULL_ON_FAILURE
  895. if the function fails, the destination buffer will be set
  896. to the empty string. This will overwrite any truncated string
  897. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  898. Notes:
  899. Behavior is undefined if source and destination strings overlap.
  900. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  901. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  902. may be NULL. An error may still be returned even though NULLS are ignored
  903. due to insufficient space.
  904. Return Value:
  905. S_OK - if there was source data and it was all copied and the
  906. resultant dest string was null terminated
  907. failure - you can use the macro HRESULT_CODE() to get a win32 error
  908. code for all falure cases
  909. STRSAFE_E_INSUFFICIENT_BUFFER /
  910. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  911. - this return value is an indication that the copy operation
  912. failed due to insufficient space. When this error occurs,
  913. the destination buffer is modified to contain a truncated
  914. version of the ideal result and is null terminated. This
  915. is useful for situations where truncation is ok.
  916. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  917. return value of this function
  918. --*/
  919. STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  920. STRSAFEAPI StringCbCopyNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  921. #ifdef UNICODE
  922. #define StringCbCopyNEx StringCbCopyNExW
  923. #else
  924. #define StringCbCopyNEx StringCbCopyNExA
  925. #endif // !UNICODE
  926. #ifdef STRSAFE_INLINE
  927. STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  928. {
  929. HRESULT hr;
  930. size_t cchDest;
  931. size_t cchSrc;
  932. size_t cchRemaining = 0;
  933. cchDest = cbDest / sizeof(char);
  934. cchSrc = cbSrc / sizeof(char);
  935. if ((cchDest > STRSAFE_MAX_CCH) ||
  936. (cchSrc > STRSAFE_MAX_CCH))
  937. {
  938. hr = STRSAFE_E_INVALID_PARAMETER;
  939. }
  940. else
  941. {
  942. hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags);
  943. }
  944. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  945. {
  946. if (pcbRemaining)
  947. {
  948. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  949. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  950. }
  951. }
  952. return hr;
  953. }
  954. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  955. STRSAFEAPI StringCbCopyNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  956. {
  957. HRESULT hr;
  958. size_t cchDest;
  959. size_t cchSrc;
  960. size_t cchRemaining = 0;
  961. cchDest = cbDest / sizeof(WCHAR);
  962. cchSrc = cbSrc / sizeof(WCHAR);
  963. if ((cchDest > STRSAFE_MAX_CCH) ||
  964. (cchSrc > STRSAFE_MAX_CCH))
  965. {
  966. hr = STRSAFE_E_INVALID_PARAMETER;
  967. }
  968. else
  969. {
  970. hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags);
  971. }
  972. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  973. {
  974. if (pcbRemaining)
  975. {
  976. // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  977. *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR));
  978. }
  979. }
  980. return hr;
  981. }
  982. #endif // FEATURE_PAL || !PLATFORM_UNIX
  983. #endif // STRSAFE_INLINE
  984. #endif // !STRSAFE_NO_CB_FUNCTIONS
  985. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  986. /*++
  987. STDAPI StringCchCat(LPTSTR pszDest,
  988. size_t cchDest,
  989. LPCTSTR pszSrc);
  990. Routine Description:
  991. This routine is a safer version of the C built-in function 'strcat'.
  992. The size of the destination buffer (in characters) is a parameter and this
  993. function will not write past the end of this buffer and it will ALWAYS
  994. null terminate the destination buffer (unless it is zero length).
  995. This function returns a hresult, and not a pointer. It returns a S_OK
  996. if the string was concatenated without truncation and null terminated, otherwise
  997. it will return a failure code. In failure cases as much of pszSrc will be
  998. appended to pszDest as possible, and pszDest will be null terminated.
  999. Arguments:
  1000. pszDest - destination string which must be null terminated
  1001. cchDest - size of destination buffer in characters.
  1002. length must be = (_tcslen(pszDest) + _tcslen(pszSrc) + 1)
  1003. to hold all of the combine string plus the null
  1004. terminator
  1005. pszSrc - source string which must be null terminated
  1006. Notes:
  1007. Behavior is undefined if source and destination strings overlap.
  1008. pszDest and pszSrc should not be NULL. See StringCchCatEx if you require
  1009. the handling of NULL values.
  1010. Return Value:
  1011. S_OK - if there was source data and it was all concatenated and the
  1012. resultant dest string was null terminated
  1013. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1014. code for all falure cases
  1015. STRSAFE_E_INSUFFICIENT_BUFFER /
  1016. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1017. - this return value is an indication that the operation
  1018. failed due to insufficient space. When this error occurs,
  1019. the destination buffer is modified to contain a truncated
  1020. version of the ideal result and is null terminated. This
  1021. is useful for situations where truncation is ok.
  1022. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1023. return value of this function
  1024. --*/
  1025. STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc);
  1026. STRSAFEAPI StringCchCatW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc);
  1027. #ifdef UNICODE
  1028. #define StringCchCat StringCchCatW
  1029. #else
  1030. #define StringCchCat StringCchCatA
  1031. #endif // !UNICODE
  1032. #ifdef STRSAFE_INLINE
  1033. STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc)
  1034. {
  1035. HRESULT hr;
  1036. if (cchDest > STRSAFE_MAX_CCH)
  1037. {
  1038. hr = STRSAFE_E_INVALID_PARAMETER;
  1039. }
  1040. else
  1041. {
  1042. hr = StringCatWorkerA(pszDest, cchDest, pszSrc);
  1043. }
  1044. return hr;
  1045. }
  1046. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1047. STRSAFEAPI StringCchCatW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc)
  1048. {
  1049. HRESULT hr;
  1050. if (cchDest > STRSAFE_MAX_CCH)
  1051. {
  1052. hr = STRSAFE_E_INVALID_PARAMETER;
  1053. }
  1054. else
  1055. {
  1056. hr = StringCatWorkerW(pszDest, cchDest, pszSrc);
  1057. }
  1058. return hr;
  1059. }
  1060. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1061. #endif // STRSAFE_INLINE
  1062. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1063. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1064. /*++
  1065. STDAPI StringCbCat(LPTSTR pszDest,
  1066. size_t cbDest,
  1067. LPCTSTR pszSrc);
  1068. Routine Description:
  1069. This routine is a safer version of the C built-in function 'strcat'.
  1070. The size of the destination buffer (in bytes) is a parameter and this
  1071. function will not write past the end of this buffer and it will ALWAYS
  1072. null terminate the destination buffer (unless it is zero length).
  1073. This function returns a hresult, and not a pointer. It returns a S_OK
  1074. if the string was concatenated without truncation and null terminated, otherwise
  1075. it will return a failure code. In failure cases as much of pszSrc will be
  1076. appended to pszDest as possible, and pszDest will be null terminated.
  1077. Arguments:
  1078. pszDest - destination string which must be null terminated
  1079. cbDest - size of destination buffer in bytes.
  1080. length must be = ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR)
  1081. to hold all of the combine string plus the null
  1082. terminator
  1083. pszSrc - source string which must be null terminated
  1084. Notes:
  1085. Behavior is undefined if source and destination strings overlap.
  1086. pszDest and pszSrc should not be NULL. See StringCbCatEx if you require
  1087. the handling of NULL values.
  1088. Return Value:
  1089. S_OK - if there was source data and it was all concatenated and the
  1090. resultant dest string was null terminated
  1091. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1092. code for all falure cases
  1093. STRSAFE_E_INSUFFICIENT_BUFFER /
  1094. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1095. - this return value is an indication that the operation
  1096. failed due to insufficient space. When this error occurs,
  1097. the destination buffer is modified to contain a truncated
  1098. version of the ideal result and is null terminated. This
  1099. is useful for situations where truncation is ok.
  1100. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1101. return value of this function
  1102. --*/
  1103. STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc);
  1104. STRSAFEAPI StringCbCatW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc);
  1105. #ifdef UNICODE
  1106. #define StringCbCat StringCbCatW
  1107. #else
  1108. #define StringCbCat StringCbCatA
  1109. #endif // !UNICODE
  1110. #ifdef STRSAFE_INLINE
  1111. STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc)
  1112. {
  1113. HRESULT hr;
  1114. size_t cchDest;
  1115. cchDest = cbDest / sizeof(char);
  1116. if (cchDest > STRSAFE_MAX_CCH)
  1117. {
  1118. hr = STRSAFE_E_INVALID_PARAMETER;
  1119. }
  1120. else
  1121. {
  1122. hr = StringCatWorkerA(pszDest, cchDest, pszSrc);
  1123. }
  1124. return hr;
  1125. }
  1126. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1127. STRSAFEAPI StringCbCatW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc)
  1128. {
  1129. HRESULT hr;
  1130. size_t cchDest;
  1131. cchDest = cbDest / sizeof(WCHAR);
  1132. if (cchDest > STRSAFE_MAX_CCH)
  1133. {
  1134. hr = STRSAFE_E_INVALID_PARAMETER;
  1135. }
  1136. else
  1137. {
  1138. hr = StringCatWorkerW(pszDest, cchDest, pszSrc);
  1139. }
  1140. return hr;
  1141. }
  1142. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1143. #endif // STRSAFE_INLINE
  1144. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1145. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1146. /*++
  1147. STDAPI StringCchCatEx(LPTSTR pszDest,
  1148. size_t cchDest,
  1149. LPCTSTR pszSrc,
  1150. LPTSTR* ppszDestEnd,
  1151. size_t* pcchRemaining,
  1152. DWORD dwFlags);
  1153. Routine Description:
  1154. This routine is a safer version of the C built-in function 'strcat' with
  1155. some additional parameters. In addition to functionality provided by
  1156. StringCchCat, this routine also returns a pointer to the end of the
  1157. destination string and the number of characters left in the destination string
  1158. including the null terminator. The flags parameter allows additional controls.
  1159. Arguments:
  1160. pszDest - destination string which must be null terminated
  1161. cchDest - size of destination buffer in characters
  1162. length must be (_tcslen(pszDest) + _tcslen(pszSrc) + 1)
  1163. to hold all of the combine string plus the null
  1164. terminator.
  1165. pszSrc - source string which must be null terminated
  1166. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1167. pointer to the end of the destination string. If the
  1168. function appended any data, the result will point to the
  1169. null termination character
  1170. pcchRemaining - if pcchRemaining is non-null, the function will return the
  1171. number of characters left in the destination string,
  1172. including the null terminator
  1173. dwFlags - controls some details of the string copy:
  1174. STRSAFE_FILL_BEHIND_NULL
  1175. if the function succeeds, the low byte of dwFlags will be
  1176. used to fill the uninitialize part of destination buffer
  1177. behind the null terminator
  1178. STRSAFE_IGNORE_NULLS
  1179. treat NULL string pointers like empty strings (TEXT("")).
  1180. this flag is useful for emulating functions like lstrcat
  1181. STRSAFE_FILL_ON_FAILURE
  1182. if the function fails, the low byte of dwFlags will be
  1183. used to fill all of the destination buffer, and it will
  1184. be null terminated. This will overwrite any pre-existing
  1185. or truncated string
  1186. STRSAFE_NULL_ON_FAILURE
  1187. if the function fails, the destination buffer will be set
  1188. to the empty string. This will overwrite any pre-existing or
  1189. truncated string
  1190. STRSAFE_NO_TRUNCATION
  1191. if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
  1192. will not contain a truncated string, it will remain unchanged.
  1193. Notes:
  1194. Behavior is undefined if source and destination strings overlap.
  1195. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  1196. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  1197. may be NULL. An error may still be returned even though NULLS are ignored
  1198. due to insufficient space.
  1199. Return Value:
  1200. S_OK - if there was source data and it was all concatenated and the
  1201. resultant dest string was null terminated
  1202. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1203. code for all falure cases
  1204. STRSAFE_E_INSUFFICIENT_BUFFER /
  1205. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1206. - this return value is an indication that the operation
  1207. failed due to insufficient space. When this error occurs,
  1208. the destination buffer is modified to contain a truncated
  1209. version of the ideal result and is null terminated. This
  1210. is useful for situations where truncation is ok.
  1211. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1212. return value of this function
  1213. --*/
  1214. STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  1215. STRSAFEAPI StringCchCatExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  1216. #ifdef UNICODE
  1217. #define StringCchCatEx StringCchCatExW
  1218. #else
  1219. #define StringCchCatEx StringCchCatExA
  1220. #endif // !UNICODE
  1221. #ifdef STRSAFE_INLINE
  1222. STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  1223. {
  1224. HRESULT hr;
  1225. if (cchDest > STRSAFE_MAX_CCH)
  1226. {
  1227. hr = STRSAFE_E_INVALID_PARAMETER;
  1228. }
  1229. else
  1230. {
  1231. size_t cbDest;
  1232. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  1233. cbDest = cchDest * sizeof(char);
  1234. hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
  1235. }
  1236. return hr;
  1237. }
  1238. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1239. STRSAFEAPI StringCchCatExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  1240. {
  1241. HRESULT hr;
  1242. if (cchDest > STRSAFE_MAX_CCH)
  1243. {
  1244. hr = STRSAFE_E_INVALID_PARAMETER;
  1245. }
  1246. else
  1247. {
  1248. size_t cbDest;
  1249. // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  1250. cbDest = cchDest * sizeof(WCHAR);
  1251. hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
  1252. }
  1253. return hr;
  1254. }
  1255. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1256. #endif // STRSAFE_INLINE
  1257. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1258. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1259. /*++
  1260. STDAPI StringCbCatEx(LPTSTR pszDest,
  1261. size_t cbDest,
  1262. LPCTSTR pszSrc,
  1263. LPTSTR* ppszDestEnd,
  1264. size_t* pcbRemaining,
  1265. DWORD dwFlags);
  1266. Routine Description:
  1267. This routine is a safer version of the C built-in function 'strcat' with
  1268. some additional parameters. In addition to functionality provided by
  1269. StringCbCat, this routine also returns a pointer to the end of the
  1270. destination string and the number of bytes left in the destination string
  1271. including the null terminator. The flags parameter allows additional controls.
  1272. Arguments:
  1273. pszDest - destination string which must be null terminated
  1274. cbDest - size of destination buffer in bytes.
  1275. length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR)
  1276. to hold all of the combine string plus the null
  1277. terminator.
  1278. pszSrc - source string which must be null terminated
  1279. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1280. pointer to the end of the destination string. If the
  1281. function appended any data, the result will point to the
  1282. null termination character
  1283. pcbRemaining - if pcbRemaining is non-null, the function will return
  1284. the number of bytes left in the destination string,
  1285. including the null terminator
  1286. dwFlags - controls some details of the string copy:
  1287. STRSAFE_FILL_BEHIND_NULL
  1288. if the function succeeds, the low byte of dwFlags will be
  1289. used to fill the uninitialize part of destination buffer
  1290. behind the null terminator
  1291. STRSAFE_IGNORE_NULLS
  1292. treat NULL string pointers like empty strings (TEXT("")).
  1293. this flag is useful for emulating functions like lstrcat
  1294. STRSAFE_FILL_ON_FAILURE
  1295. if the function fails, the low byte of dwFlags will be
  1296. used to fill all of the destination buffer, and it will
  1297. be null terminated. This will overwrite any pre-existing
  1298. or truncated string
  1299. STRSAFE_NULL_ON_FAILURE
  1300. if the function fails, the destination buffer will be set
  1301. to the empty string. This will overwrite any pre-existing or
  1302. truncated string
  1303. STRSAFE_NO_TRUNCATION
  1304. if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
  1305. will not contain a truncated string, it will remain unchanged.
  1306. Notes:
  1307. Behavior is undefined if source and destination strings overlap.
  1308. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  1309. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  1310. may be NULL. An error may still be returned even though NULLS are ignored
  1311. due to insufficient space.
  1312. Return Value:
  1313. S_OK - if there was source data and it was all concatenated and the
  1314. resultant dest string was null terminated
  1315. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1316. code for all falure cases
  1317. STRSAFE_E_INSUFFICIENT_BUFFER /
  1318. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1319. - this return value is an indication that the operation
  1320. failed due to insufficient space. When this error occurs,
  1321. the destination buffer is modified to contain a truncated
  1322. version of the ideal result and is null terminated. This
  1323. is useful for situations where truncation is ok.
  1324. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1325. return value of this function
  1326. --*/
  1327. STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  1328. STRSAFEAPI StringCbCatExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  1329. #ifdef UNICODE
  1330. #define StringCbCatEx StringCbCatExW
  1331. #else
  1332. #define StringCbCatEx StringCbCatExA
  1333. #endif // !UNICODE
  1334. #ifdef STRSAFE_INLINE
  1335. STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  1336. {
  1337. HRESULT hr;
  1338. size_t cchDest;
  1339. size_t cchRemaining = 0;
  1340. cchDest = cbDest / sizeof(char);
  1341. if (cchDest > STRSAFE_MAX_CCH)
  1342. {
  1343. hr = STRSAFE_E_INVALID_PARAMETER;
  1344. }
  1345. else
  1346. {
  1347. hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
  1348. }
  1349. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  1350. {
  1351. if (pcbRemaining)
  1352. {
  1353. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  1354. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  1355. }
  1356. }
  1357. return hr;
  1358. }
  1359. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1360. STRSAFEAPI StringCbCatExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  1361. {
  1362. HRESULT hr;
  1363. size_t cchDest;
  1364. size_t cchRemaining = 0;
  1365. cchDest = cbDest / sizeof(WCHAR);
  1366. if (cchDest > STRSAFE_MAX_CCH)
  1367. {
  1368. hr = STRSAFE_E_INVALID_PARAMETER;
  1369. }
  1370. else
  1371. {
  1372. hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
  1373. }
  1374. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  1375. {
  1376. if (pcbRemaining)
  1377. {
  1378. // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  1379. *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR));
  1380. }
  1381. }
  1382. return hr;
  1383. }
  1384. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1385. #endif // STRSAFE_INLINE
  1386. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1387. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1388. /*++
  1389. STDAPI StringCchCatN(LPTSTR pszDest,
  1390. size_t cchDest,
  1391. LPCTSTR pszSrc,
  1392. size_t cchMaxAppend);
  1393. Routine Description:
  1394. This routine is a safer version of the C built-in function 'strncat'.
  1395. The size of the destination buffer (in characters) is a parameter as well as
  1396. the maximum number of characters to append, excluding the null terminator.
  1397. This function will not write past the end of the destination buffer and it will
  1398. ALWAYS null terminate pszDest (unless it is zero length).
  1399. This function returns a hresult, and not a pointer. It returns a S_OK
  1400. if all of pszSrc or the first cchMaxAppend characters were appended to the
  1401. destination string and it was null terminated, otherwise it will return a
  1402. failure code. In failure cases as much of pszSrc will be appended to pszDest
  1403. as possible, and pszDest will be null terminated.
  1404. Arguments:
  1405. pszDest - destination string which must be null terminated
  1406. cchDest - size of destination buffer in characters.
  1407. length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1)
  1408. to hold all of the combine string plus the null
  1409. terminator.
  1410. pszSrc - source string
  1411. cchMaxAppend - maximum number of characters to append
  1412. Notes:
  1413. Behavior is undefined if source and destination strings overlap.
  1414. pszDest and pszSrc should not be NULL. See StringCchCatNEx if you require
  1415. the handling of NULL values.
  1416. Return Value:
  1417. S_OK - if all of pszSrc or the first cchMaxAppend characters were
  1418. concatenated to pszDest and the resultant dest string was
  1419. null terminated
  1420. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1421. code for all falure cases
  1422. STRSAFE_E_INSUFFICIENT_BUFFER /
  1423. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1424. - this return value is an indication that the operation
  1425. failed due to insufficient space. When this error occurs,
  1426. the destination buffer is modified to contain a truncated
  1427. version of the ideal result and is null terminated. This
  1428. is useful for situations where truncation is ok.
  1429. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1430. return value of this function
  1431. --*/
  1432. STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend);
  1433. STRSAFEAPI StringCchCatNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend);
  1434. #ifdef UNICODE
  1435. #define StringCchCatN StringCchCatNW
  1436. #else
  1437. #define StringCchCatN StringCchCatNA
  1438. #endif // !UNICODE
  1439. #ifdef STRSAFE_INLINE
  1440. STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend)
  1441. {
  1442. HRESULT hr;
  1443. if (cchDest > STRSAFE_MAX_CCH)
  1444. {
  1445. hr = STRSAFE_E_INVALID_PARAMETER;
  1446. }
  1447. else
  1448. {
  1449. hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend);
  1450. }
  1451. return hr;
  1452. }
  1453. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1454. STRSAFEAPI StringCchCatNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend)
  1455. {
  1456. HRESULT hr;
  1457. if (cchDest > STRSAFE_MAX_CCH)
  1458. {
  1459. hr = STRSAFE_E_INVALID_PARAMETER;
  1460. }
  1461. else
  1462. {
  1463. hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend);
  1464. }
  1465. return hr;
  1466. }
  1467. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1468. #endif // STRSAFE_INLINE
  1469. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1470. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1471. /*++
  1472. STDAPI StringCbCatN(LPTSTR pszDest,
  1473. size_t cbDest,
  1474. LPCTSTR pszSrc,
  1475. size_t cbMaxAppend);
  1476. Routine Description:
  1477. This routine is a safer version of the C built-in function 'strncat'.
  1478. The size of the destination buffer (in bytes) is a parameter as well as
  1479. the maximum number of bytes to append, excluding the null terminator.
  1480. This function will not write past the end of the destination buffer and it will
  1481. ALWAYS null terminate pszDest (unless it is zero length).
  1482. This function returns a hresult, and not a pointer. It returns a S_OK
  1483. if all of pszSrc or the first cbMaxAppend bytes were appended to the
  1484. destination string and it was null terminated, otherwise it will return a
  1485. failure code. In failure cases as much of pszSrc will be appended to pszDest
  1486. as possible, and pszDest will be null terminated.
  1487. Arguments:
  1488. pszDest - destination string which must be null terminated
  1489. cbDest - size of destination buffer in bytes.
  1490. length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR)
  1491. to hold all of the combine string plus the null
  1492. terminator.
  1493. pszSrc - source string
  1494. cbMaxAppend - maximum number of bytes to append
  1495. Notes:
  1496. Behavior is undefined if source and destination strings overlap.
  1497. pszDest and pszSrc should not be NULL. See StringCbCatNEx if you require
  1498. the handling of NULL values.
  1499. Return Value:
  1500. S_OK - if all of pszSrc or the first cbMaxAppend bytes were
  1501. concatenated to pszDest and the resultant dest string was
  1502. null terminated
  1503. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1504. code for all falure cases
  1505. STRSAFE_E_INSUFFICIENT_BUFFER /
  1506. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1507. - this return value is an indication that the operation
  1508. failed due to insufficient space. When this error occurs,
  1509. the destination buffer is modified to contain a truncated
  1510. version of the ideal result and is null terminated. This
  1511. is useful for situations where truncation is ok.
  1512. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1513. return value of this function
  1514. --*/
  1515. STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend);
  1516. STRSAFEAPI StringCbCatNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbMaxAppend);
  1517. #ifdef UNICODE
  1518. #define StringCbCatN StringCbCatNW
  1519. #else
  1520. #define StringCbCatN StringCbCatNA
  1521. #endif // !UNICODE
  1522. #ifdef STRSAFE_INLINE
  1523. STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend)
  1524. {
  1525. HRESULT hr;
  1526. size_t cchDest;
  1527. cchDest = cbDest / sizeof(char);
  1528. if (cchDest > STRSAFE_MAX_CCH)
  1529. {
  1530. hr = STRSAFE_E_INVALID_PARAMETER;
  1531. }
  1532. else
  1533. {
  1534. size_t cchMaxAppend;
  1535. cchMaxAppend = cbMaxAppend / sizeof(char);
  1536. hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend);
  1537. }
  1538. return hr;
  1539. }
  1540. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1541. STRSAFEAPI StringCbCatNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbMaxAppend)
  1542. {
  1543. HRESULT hr;
  1544. size_t cchDest;
  1545. cchDest = cbDest / sizeof(WCHAR);
  1546. if (cchDest > STRSAFE_MAX_CCH)
  1547. {
  1548. hr = STRSAFE_E_INVALID_PARAMETER;
  1549. }
  1550. else
  1551. {
  1552. size_t cchMaxAppend;
  1553. cchMaxAppend = cbMaxAppend / sizeof(WCHAR);
  1554. hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend);
  1555. }
  1556. return hr;
  1557. }
  1558. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1559. #endif // STRSAFE_INLINE
  1560. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1561. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1562. /*++
  1563. STDAPI StringCchCatNEx(LPTSTR pszDest,
  1564. size_t cchDest,
  1565. LPCTSTR pszSrc,
  1566. size_t cchMaxAppend,
  1567. LPTSTR* ppszDestEnd,
  1568. size_t* pcchRemaining,
  1569. DWORD dwFlags);
  1570. Routine Description:
  1571. This routine is a safer version of the C built-in function 'strncat', with
  1572. some additional parameters. In addition to functionality provided by
  1573. StringCchCatN, this routine also returns a pointer to the end of the
  1574. destination string and the number of characters left in the destination string
  1575. including the null terminator. The flags parameter allows additional controls.
  1576. Arguments:
  1577. pszDest - destination string which must be null terminated
  1578. cchDest - size of destination buffer in characters.
  1579. length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1)
  1580. to hold all of the combine string plus the null
  1581. terminator.
  1582. pszSrc - source string
  1583. cchMaxAppend - maximum number of characters to append
  1584. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1585. pointer to the end of the destination string. If the
  1586. function appended any data, the result will point to the
  1587. null termination character
  1588. pcchRemaining - if pcchRemaining is non-null, the function will return the
  1589. number of characters left in the destination string,
  1590. including the null terminator
  1591. dwFlags - controls some details of the string copy:
  1592. STRSAFE_FILL_BEHIND_NULL
  1593. if the function succeeds, the low byte of dwFlags will be
  1594. used to fill the uninitialize part of destination buffer
  1595. behind the null terminator
  1596. STRSAFE_IGNORE_NULLS
  1597. treat NULL string pointers like empty strings (TEXT(""))
  1598. STRSAFE_FILL_ON_FAILURE
  1599. if the function fails, the low byte of dwFlags will be
  1600. used to fill all of the destination buffer, and it will
  1601. be null terminated. This will overwrite any pre-existing
  1602. or truncated string
  1603. STRSAFE_NULL_ON_FAILURE
  1604. if the function fails, the destination buffer will be set
  1605. to the empty string. This will overwrite any pre-existing or
  1606. truncated string
  1607. STRSAFE_NO_TRUNCATION
  1608. if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
  1609. will not contain a truncated string, it will remain unchanged.
  1610. Notes:
  1611. Behavior is undefined if source and destination strings overlap.
  1612. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  1613. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  1614. may be NULL. An error may still be returned even though NULLS are ignored
  1615. due to insufficient space.
  1616. Return Value:
  1617. S_OK - if all of pszSrc or the first cchMaxAppend characters were
  1618. concatenated to pszDest and the resultant dest string was
  1619. null terminated
  1620. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1621. code for all falure cases
  1622. STRSAFE_E_INSUFFICIENT_BUFFER /
  1623. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1624. - this return value is an indication that the operation
  1625. failed due to insufficient space. When this error occurs,
  1626. the destination buffer is modified to contain a truncated
  1627. version of the ideal result and is null terminated. This
  1628. is useful for situations where truncation is ok.
  1629. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1630. return value of this function
  1631. --*/
  1632. STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  1633. STRSAFEAPI StringCchCatNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  1634. #ifdef UNICODE
  1635. #define StringCchCatNEx StringCchCatNExW
  1636. #else
  1637. #define StringCchCatNEx StringCchCatNExA
  1638. #endif // !UNICODE
  1639. #ifdef STRSAFE_INLINE
  1640. STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  1641. {
  1642. HRESULT hr;
  1643. if (cchDest > STRSAFE_MAX_CCH)
  1644. {
  1645. hr = STRSAFE_E_INVALID_PARAMETER;
  1646. }
  1647. else
  1648. {
  1649. size_t cbDest;
  1650. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  1651. cbDest = cchDest * sizeof(char);
  1652. hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags);
  1653. }
  1654. return hr;
  1655. }
  1656. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1657. STRSAFEAPI StringCchCatNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  1658. {
  1659. HRESULT hr;
  1660. if (cchDest > STRSAFE_MAX_CCH)
  1661. {
  1662. hr = STRSAFE_E_INVALID_PARAMETER;
  1663. }
  1664. else
  1665. {
  1666. size_t cbDest;
  1667. // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  1668. cbDest = cchDest * sizeof(WCHAR);
  1669. hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags);
  1670. }
  1671. return hr;
  1672. }
  1673. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1674. #endif // STRSAFE_INLINE
  1675. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1676. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1677. /*++
  1678. STDAPI StringCbCatNEx(LPTSTR pszDest,
  1679. size_t cbDest,
  1680. LPCTSTR pszSrc,
  1681. size_t cbMaxAppend
  1682. LPTSTR* ppszDestEnd,
  1683. size_t* pcchRemaining,
  1684. DWORD dwFlags);
  1685. Routine Description:
  1686. This routine is a safer version of the C built-in function 'strncat', with
  1687. some additional parameters. In addition to functionality provided by
  1688. StringCbCatN, this routine also returns a pointer to the end of the
  1689. destination string and the number of bytes left in the destination string
  1690. including the null terminator. The flags parameter allows additional controls.
  1691. Arguments:
  1692. pszDest - destination string which must be null terminated
  1693. cbDest - size of destination buffer in bytes.
  1694. length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR)
  1695. to hold all of the combine string plus the null
  1696. terminator.
  1697. pszSrc - source string
  1698. cbMaxAppend - maximum number of bytes to append
  1699. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1700. pointer to the end of the destination string. If the
  1701. function appended any data, the result will point to the
  1702. null termination character
  1703. pcbRemaining - if pcbRemaining is non-null, the function will return the
  1704. number of bytes left in the destination string,
  1705. including the null terminator
  1706. dwFlags - controls some details of the string copy:
  1707. STRSAFE_FILL_BEHIND_NULL
  1708. if the function succeeds, the low byte of dwFlags will be
  1709. used to fill the uninitialize part of destination buffer
  1710. behind the null terminator
  1711. STRSAFE_IGNORE_NULLS
  1712. treat NULL string pointers like empty strings (TEXT(""))
  1713. STRSAFE_FILL_ON_FAILURE
  1714. if the function fails, the low byte of dwFlags will be
  1715. used to fill all of the destination buffer, and it will
  1716. be null terminated. This will overwrite any pre-existing
  1717. or truncated string
  1718. STRSAFE_NULL_ON_FAILURE
  1719. if the function fails, the destination buffer will be set
  1720. to the empty string. This will overwrite any pre-existing or
  1721. truncated string
  1722. STRSAFE_NO_TRUNCATION
  1723. if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
  1724. will not contain a truncated string, it will remain unchanged.
  1725. Notes:
  1726. Behavior is undefined if source and destination strings overlap.
  1727. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  1728. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  1729. may be NULL. An error may still be returned even though NULLS are ignored
  1730. due to insufficient space.
  1731. Return Value:
  1732. S_OK - if all of pszSrc or the first cbMaxAppend bytes were
  1733. concatenated to pszDest and the resultant dest string was
  1734. null terminated
  1735. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1736. code for all falure cases
  1737. STRSAFE_E_INSUFFICIENT_BUFFER /
  1738. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1739. - this return value is an indication that the operation
  1740. failed due to insufficient space. When this error occurs,
  1741. the destination buffer is modified to contain a truncated
  1742. version of the ideal result and is null terminated. This
  1743. is useful for situations where truncation is ok.
  1744. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1745. return value of this function
  1746. --*/
  1747. STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  1748. STRSAFEAPI StringCbCatNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbMaxAppend, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  1749. #ifdef UNICODE
  1750. #define StringCbCatNEx StringCbCatNExW
  1751. #else
  1752. #define StringCbCatNEx StringCbCatNExA
  1753. #endif // !UNICODE
  1754. #ifdef STRSAFE_INLINE
  1755. STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  1756. {
  1757. HRESULT hr;
  1758. size_t cchDest;
  1759. size_t cchRemaining = 0;
  1760. cchDest = cbDest / sizeof(char);
  1761. if (cchDest > STRSAFE_MAX_CCH)
  1762. {
  1763. hr = STRSAFE_E_INVALID_PARAMETER;
  1764. }
  1765. else
  1766. {
  1767. size_t cchMaxAppend;
  1768. cchMaxAppend = cbMaxAppend / sizeof(char);
  1769. hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags);
  1770. }
  1771. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  1772. {
  1773. if (pcbRemaining)
  1774. {
  1775. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  1776. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  1777. }
  1778. }
  1779. return hr;
  1780. }
  1781. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1782. STRSAFEAPI StringCbCatNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbMaxAppend, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  1783. {
  1784. HRESULT hr;
  1785. size_t cchDest;
  1786. size_t cchRemaining = 0;
  1787. cchDest = cbDest / sizeof(WCHAR);
  1788. if (cchDest > STRSAFE_MAX_CCH)
  1789. {
  1790. hr = STRSAFE_E_INVALID_PARAMETER;
  1791. }
  1792. else
  1793. {
  1794. size_t cchMaxAppend;
  1795. cchMaxAppend = cbMaxAppend / sizeof(WCHAR);
  1796. hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags);
  1797. }
  1798. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  1799. {
  1800. if (pcbRemaining)
  1801. {
  1802. // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  1803. *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR));
  1804. }
  1805. }
  1806. return hr;
  1807. }
  1808. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1809. #endif // STRSAFE_INLINE
  1810. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1811. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1812. /*++
  1813. STDAPI StringCchVPrintf(LPTSTR pszDest,
  1814. size_t cchDest,
  1815. LPCTSTR pszFormat,
  1816. va_list argList);
  1817. Routine Description:
  1818. This routine is a safer version of the C built-in function 'vsprintf'.
  1819. The size of the destination buffer (in characters) is a parameter and
  1820. this function will not write past the end of this buffer and it will
  1821. ALWAYS null terminate the destination buffer (unless it is zero length).
  1822. This function returns a hresult, and not a pointer. It returns a S_OK
  1823. if the string was printed without truncation and null terminated, otherwise
  1824. it will return a failure code. In failure cases it will return a truncated
  1825. version of the ideal result.
  1826. Arguments:
  1827. pszDest - destination string
  1828. cchDest - size of destination buffer in characters
  1829. length must be sufficient to hold the resulting formatted
  1830. string, including the null terminator.
  1831. pszFormat - format string which must be null terminated
  1832. argList - va_list from the variable arguments according to the
  1833. stdarg.h convention
  1834. Notes:
  1835. Behavior is undefined if destination, format strings or any arguments
  1836. strings overlap.
  1837. pszDest and pszFormat should not be NULL. See StringCchVPrintfEx if you
  1838. require the handling of NULL values.
  1839. Return Value:
  1840. S_OK - if there was sufficient space in the dest buffer for
  1841. the resultant string and it was null terminated.
  1842. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1843. code for all falure cases
  1844. STRSAFE_E_INSUFFICIENT_BUFFER /
  1845. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1846. - this return value is an indication that the print operation
  1847. failed due to insufficient space. When this error occurs,
  1848. the destination buffer is modified to contain a truncated
  1849. version of the ideal result and is null terminated. This
  1850. is useful for situations where truncation is ok.
  1851. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1852. return value of this function
  1853. --*/
  1854. STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList);
  1855. STRSAFEAPI StringCchVPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList);
  1856. #ifdef UNICODE
  1857. #define StringCchVPrintf StringCchVPrintfW
  1858. #else
  1859. #define StringCchVPrintf StringCchVPrintfA
  1860. #endif // !UNICODE
  1861. #ifdef STRSAFE_INLINE
  1862. STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList)
  1863. {
  1864. HRESULT hr;
  1865. if (cchDest > STRSAFE_MAX_CCH)
  1866. {
  1867. hr = STRSAFE_E_INVALID_PARAMETER;
  1868. }
  1869. else
  1870. {
  1871. hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
  1872. }
  1873. return hr;
  1874. }
  1875. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1876. STRSAFEAPI StringCchVPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList)
  1877. {
  1878. HRESULT hr;
  1879. if (cchDest > STRSAFE_MAX_CCH)
  1880. {
  1881. hr = STRSAFE_E_INVALID_PARAMETER;
  1882. }
  1883. else
  1884. {
  1885. hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
  1886. }
  1887. return hr;
  1888. }
  1889. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1890. #endif // STRSAFE_INLINE
  1891. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1892. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1893. /*++
  1894. STDAPI StringCbVPrintf(LPTSTR pszDest,
  1895. size_t cbDest,
  1896. LPCTSTR pszFormat,
  1897. va_list argList);
  1898. Routine Description:
  1899. This routine is a safer version of the C built-in function 'vsprintf'.
  1900. The size of the destination buffer (in bytes) is a parameter and
  1901. this function will not write past the end of this buffer and it will
  1902. ALWAYS null terminate the destination buffer (unless it is zero length).
  1903. This function returns a hresult, and not a pointer. It returns a S_OK
  1904. if the string was printed without truncation and null terminated, otherwise
  1905. it will return a failure code. In failure cases it will return a truncated
  1906. version of the ideal result.
  1907. Arguments:
  1908. pszDest - destination string
  1909. cbDest - size of destination buffer in bytes
  1910. length must be sufficient to hold the resulting formatted
  1911. string, including the null terminator.
  1912. pszFormat - format string which must be null terminated
  1913. argList - va_list from the variable arguments according to the
  1914. stdarg.h convention
  1915. Notes:
  1916. Behavior is undefined if destination, format strings or any arguments
  1917. strings overlap.
  1918. pszDest and pszFormat should not be NULL. See StringCbVPrintfEx if you
  1919. require the handling of NULL values.
  1920. Return Value:
  1921. S_OK - if there was sufficient space in the dest buffer for
  1922. the resultant string and it was null terminated.
  1923. failure - you can use the macro HRESULT_CODE() to get a win32 error
  1924. code for all falure cases
  1925. STRSAFE_E_INSUFFICIENT_BUFFER /
  1926. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1927. - this return value is an indication that the print operation
  1928. failed due to insufficient space. When this error occurs,
  1929. the destination buffer is modified to contain a truncated
  1930. version of the ideal result and is null terminated. This
  1931. is useful for situations where truncation is ok.
  1932. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1933. return value of this function
  1934. --*/
  1935. STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList);
  1936. STRSAFEAPI StringCbVPrintfW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszFormat, va_list argList);
  1937. #ifdef UNICODE
  1938. #define StringCbVPrintf StringCbVPrintfW
  1939. #else
  1940. #define StringCbVPrintf StringCbVPrintfA
  1941. #endif // !UNICODE
  1942. #ifdef STRSAFE_INLINE
  1943. STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList)
  1944. {
  1945. HRESULT hr;
  1946. size_t cchDest;
  1947. cchDest = cbDest / sizeof(char);
  1948. if (cchDest > STRSAFE_MAX_CCH)
  1949. {
  1950. hr = STRSAFE_E_INVALID_PARAMETER;
  1951. }
  1952. else
  1953. {
  1954. hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
  1955. }
  1956. return hr;
  1957. }
  1958. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  1959. STRSAFEAPI StringCbVPrintfW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszFormat, va_list argList)
  1960. {
  1961. HRESULT hr;
  1962. size_t cchDest;
  1963. cchDest = cbDest / sizeof(WCHAR);
  1964. if (cchDest > STRSAFE_MAX_CCH)
  1965. {
  1966. hr = STRSAFE_E_INVALID_PARAMETER;
  1967. }
  1968. else
  1969. {
  1970. hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
  1971. }
  1972. return hr;
  1973. }
  1974. #endif // FEATURE_PAL || !PLATFORM_UNIX
  1975. #endif // STRSAFE_INLINE
  1976. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1977. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1978. /*++
  1979. STDAPI StringCchPrintf(LPTSTR pszDest,
  1980. size_t cchDest,
  1981. LPCTSTR pszFormat,
  1982. ...);
  1983. Routine Description:
  1984. This routine is a safer version of the C built-in function 'sprintf'.
  1985. The size of the destination buffer (in characters) is a parameter and
  1986. this function will not write past the end of this buffer and it will
  1987. ALWAYS null terminate the destination buffer (unless it is zero length).
  1988. This function returns a hresult, and not a pointer. It returns a S_OK
  1989. if the string was printed without truncation and null terminated, otherwise
  1990. it will return a failure code. In failure cases it will return a truncated
  1991. version of the ideal result.
  1992. Arguments:
  1993. pszDest - destination string
  1994. cchDest - size of destination buffer in characters
  1995. length must be sufficient to hold the resulting formatted
  1996. string, including the null terminator.
  1997. pszFormat - format string which must be null terminated
  1998. ... - additional parameters to be formatted according to
  1999. the format string
  2000. Notes:
  2001. Behavior is undefined if destination, format strings or any arguments
  2002. strings overlap.
  2003. pszDest and pszFormat should not be NULL. See StringCchPrintfEx if you
  2004. require the handling of NULL values.
  2005. Return Value:
  2006. S_OK - if there was sufficient space in the dest buffer for
  2007. the resultant string and it was null terminated.
  2008. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2009. code for all falure cases
  2010. STRSAFE_E_INSUFFICIENT_BUFFER /
  2011. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2012. - this return value is an indication that the print operation
  2013. failed due to insufficient space. When this error occurs,
  2014. the destination buffer is modified to contain a truncated
  2015. version of the ideal result and is null terminated. This
  2016. is useful for situations where truncation is ok.
  2017. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2018. return value of this function
  2019. --*/
  2020. STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...);
  2021. STRSAFEAPI StringCchPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, ...);
  2022. #ifdef UNICODE
  2023. #define StringCchPrintf StringCchPrintfW
  2024. #else
  2025. #define StringCchPrintf StringCchPrintfA
  2026. #endif // !UNICODE
  2027. #ifdef STRSAFE_INLINE
  2028. STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...)
  2029. {
  2030. HRESULT hr;
  2031. if (cchDest > STRSAFE_MAX_CCH)
  2032. {
  2033. hr = STRSAFE_E_INVALID_PARAMETER;
  2034. }
  2035. else
  2036. {
  2037. va_list argList;
  2038. va_start(argList, pszFormat);
  2039. hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
  2040. va_end(argList);
  2041. }
  2042. return hr;
  2043. }
  2044. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2045. STRSAFEAPI StringCchPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, ...)
  2046. {
  2047. HRESULT hr;
  2048. if (cchDest > STRSAFE_MAX_CCH)
  2049. {
  2050. hr = STRSAFE_E_INVALID_PARAMETER;
  2051. }
  2052. else
  2053. {
  2054. va_list argList;
  2055. va_start(argList, pszFormat);
  2056. hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
  2057. va_end(argList);
  2058. }
  2059. return hr;
  2060. }
  2061. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2062. #endif // STRSAFE_INLINE
  2063. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2064. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2065. /*++
  2066. STDAPI StringCbPrintf(LPTSTR pszDest,
  2067. size_t cbDest,
  2068. LPCTSTR pszFormat,
  2069. ...);
  2070. Routine Description:
  2071. This routine is a safer version of the C built-in function 'sprintf'.
  2072. The size of the destination buffer (in bytes) is a parameter and
  2073. this function will not write past the end of this buffer and it will
  2074. ALWAYS null terminate the destination buffer (unless it is zero length).
  2075. This function returns a hresult, and not a pointer. It returns a S_OK
  2076. if the string was printed without truncation and null terminated, otherwise
  2077. it will return a failure code. In failure cases it will return a truncated
  2078. version of the ideal result.
  2079. Arguments:
  2080. pszDest - destination string
  2081. cbDest - size of destination buffer in bytes
  2082. length must be sufficient to hold the resulting formatted
  2083. string, including the null terminator.
  2084. pszFormat - format string which must be null terminated
  2085. ... - additional parameters to be formatted according to
  2086. the format string
  2087. Notes:
  2088. Behavior is undefined if destination, format strings or any arguments
  2089. strings overlap.
  2090. pszDest and pszFormat should not be NULL. See StringCbPrintfEx if you
  2091. require the handling of NULL values.
  2092. Return Value:
  2093. S_OK - if there was sufficient space in the dest buffer for
  2094. the resultant string and it was null terminated.
  2095. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2096. code for all falure cases
  2097. STRSAFE_E_INSUFFICIENT_BUFFER /
  2098. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2099. - this return value is an indication that the print operation
  2100. failed due to insufficient space. When this error occurs,
  2101. the destination buffer is modified to contain a truncated
  2102. version of the ideal result and is null terminated. This
  2103. is useful for situations where truncation is ok.
  2104. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2105. return value of this function
  2106. --*/
  2107. STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...);
  2108. STRSAFEAPI StringCbPrintfW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszFormat, ...);
  2109. #ifdef UNICODE
  2110. #define StringCbPrintf StringCbPrintfW
  2111. #else
  2112. #define StringCbPrintf StringCbPrintfA
  2113. #endif // !UNICODE
  2114. #ifdef STRSAFE_INLINE
  2115. STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...)
  2116. {
  2117. HRESULT hr;
  2118. size_t cchDest;
  2119. cchDest = cbDest / sizeof(char);
  2120. if (cchDest > STRSAFE_MAX_CCH)
  2121. {
  2122. hr = STRSAFE_E_INVALID_PARAMETER;
  2123. }
  2124. else
  2125. {
  2126. va_list argList;
  2127. va_start(argList, pszFormat);
  2128. hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
  2129. va_end(argList);
  2130. }
  2131. return hr;
  2132. }
  2133. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2134. STRSAFEAPI StringCbPrintfW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszFormat, ...)
  2135. {
  2136. HRESULT hr;
  2137. size_t cchDest;
  2138. cchDest = cbDest / sizeof(WCHAR);
  2139. if (cchDest > STRSAFE_MAX_CCH)
  2140. {
  2141. hr = STRSAFE_E_INVALID_PARAMETER;
  2142. }
  2143. else
  2144. {
  2145. va_list argList;
  2146. va_start(argList, pszFormat);
  2147. hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
  2148. va_end(argList);
  2149. }
  2150. return hr;
  2151. }
  2152. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2153. #endif // STRSAFE_INLINE
  2154. #endif // !STRSAFE_NO_CB_FUNCTIONS
  2155. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  2156. /*++
  2157. STDAPI StringCchPrintfEx(LPTSTR pszDest,
  2158. size_t cchDest,
  2159. LPTSTR* ppszDestEnd,
  2160. size_t* pcchRemaining,
  2161. DWORD dwFlags,
  2162. LPCTSTR pszFormat,
  2163. ...);
  2164. Routine Description:
  2165. This routine is a safer version of the C built-in function 'sprintf' with
  2166. some additional parameters. In addition to functionality provided by
  2167. StringCchPrintf, this routine also returns a pointer to the end of the
  2168. destination string and the number of characters left in the destination string
  2169. including the null terminator. The flags parameter allows additional controls.
  2170. Arguments:
  2171. pszDest - destination string
  2172. cchDest - size of destination buffer in characters.
  2173. length must be sufficient to contain the resulting
  2174. formatted string plus the null terminator.
  2175. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  2176. pointer to the end of the destination string. If the
  2177. function printed any data, the result will point to the
  2178. null termination character
  2179. pcchRemaining - if pcchRemaining is non-null, the function will return
  2180. the number of characters left in the destination string,
  2181. including the null terminator
  2182. dwFlags - controls some details of the string copy:
  2183. STRSAFE_FILL_BEHIND_NULL
  2184. if the function succeeds, the low byte of dwFlags will be
  2185. used to fill the uninitialize part of destination buffer
  2186. behind the null terminator
  2187. STRSAFE_IGNORE_NULLS
  2188. treat NULL string pointers like empty strings (TEXT(""))
  2189. STRSAFE_FILL_ON_FAILURE
  2190. if the function fails, the low byte of dwFlags will be
  2191. used to fill all of the destination buffer, and it will
  2192. be null terminated. This will overwrite any truncated
  2193. string returned when the failure is
  2194. STRSAFE_E_INSUFFICIENT_BUFFER
  2195. STRSAFE_NO_TRUNCATION /
  2196. STRSAFE_NULL_ON_FAILURE
  2197. if the function fails, the destination buffer will be set
  2198. to the empty string. This will overwrite any truncated string
  2199. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  2200. pszFormat - format string which must be null terminated
  2201. ... - additional parameters to be formatted according to
  2202. the format string
  2203. Notes:
  2204. Behavior is undefined if destination, format strings or any arguments
  2205. strings overlap.
  2206. pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
  2207. flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and
  2208. pszFormat may be NULL. An error may still be returned even though NULLS
  2209. are ignored due to insufficient space.
  2210. Return Value:
  2211. S_OK - if there was source data and it was all concatenated and the
  2212. resultant dest string was null terminated
  2213. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2214. code for all falure cases
  2215. STRSAFE_E_INSUFFICIENT_BUFFER /
  2216. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2217. - this return value is an indication that the print operation
  2218. failed due to insufficient space. When this error occurs,
  2219. the destination buffer is modified to contain a truncated
  2220. version of the ideal result and is null terminated. This
  2221. is useful for situations where truncation is ok.
  2222. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2223. return value of this function
  2224. --*/
  2225. STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...);
  2226. STRSAFEAPI StringCchPrintfExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, ...);
  2227. #ifdef UNICODE
  2228. #define StringCchPrintfEx StringCchPrintfExW
  2229. #else
  2230. #define StringCchPrintfEx StringCchPrintfExA
  2231. #endif // !UNICODE
  2232. #ifdef STRSAFE_INLINE
  2233. STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...)
  2234. {
  2235. HRESULT hr;
  2236. if (cchDest > STRSAFE_MAX_CCH)
  2237. {
  2238. hr = STRSAFE_E_INVALID_PARAMETER;
  2239. }
  2240. else
  2241. {
  2242. size_t cbDest;
  2243. va_list argList;
  2244. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  2245. cbDest = cchDest * sizeof(char);
  2246. va_start(argList, pszFormat);
  2247. hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
  2248. va_end(argList);
  2249. }
  2250. return hr;
  2251. }
  2252. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2253. STRSAFEAPI StringCchPrintfExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, ...)
  2254. {
  2255. HRESULT hr;
  2256. if (cchDest > STRSAFE_MAX_CCH)
  2257. {
  2258. hr = STRSAFE_E_INVALID_PARAMETER;
  2259. }
  2260. else
  2261. {
  2262. size_t cbDest;
  2263. va_list argList;
  2264. // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  2265. cbDest = cchDest * sizeof(WCHAR);
  2266. va_start(argList, pszFormat);
  2267. hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
  2268. va_end(argList);
  2269. }
  2270. return hr;
  2271. }
  2272. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2273. #endif // STRSAFE_INLINE
  2274. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2275. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2276. /*++
  2277. STDAPI StringCbPrintfEx(LPTSTR pszDest,
  2278. size_t cbDest,
  2279. LPTSTR* ppszDestEnd,
  2280. size_t* pcbRemaining,
  2281. DWORD dwFlags,
  2282. LPCTSTR pszFormat,
  2283. ...);
  2284. Routine Description:
  2285. This routine is a safer version of the C built-in function 'sprintf' with
  2286. some additional parameters. In addition to functionality provided by
  2287. StringCbPrintf, this routine also returns a pointer to the end of the
  2288. destination string and the number of bytes left in the destination string
  2289. including the null terminator. The flags parameter allows additional controls.
  2290. Arguments:
  2291. pszDest - destination string
  2292. cbDest - size of destination buffer in bytes.
  2293. length must be sufficient to contain the resulting
  2294. formatted string plus the null terminator.
  2295. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  2296. pointer to the end of the destination string. If the
  2297. function printed any data, the result will point to the
  2298. null termination character
  2299. pcbRemaining - if pcbRemaining is non-null, the function will return
  2300. the number of bytes left in the destination string,
  2301. including the null terminator
  2302. dwFlags - controls some details of the string copy:
  2303. STRSAFE_FILL_BEHIND_NULL
  2304. if the function succeeds, the low byte of dwFlags will be
  2305. used to fill the uninitialize part of destination buffer
  2306. behind the null terminator
  2307. STRSAFE_IGNORE_NULLS
  2308. treat NULL string pointers like empty strings (TEXT(""))
  2309. STRSAFE_FILL_ON_FAILURE
  2310. if the function fails, the low byte of dwFlags will be
  2311. used to fill all of the destination buffer, and it will
  2312. be null terminated. This will overwrite any truncated
  2313. string returned when the failure is
  2314. STRSAFE_E_INSUFFICIENT_BUFFER
  2315. STRSAFE_NO_TRUNCATION /
  2316. STRSAFE_NULL_ON_FAILURE
  2317. if the function fails, the destination buffer will be set
  2318. to the empty string. This will overwrite any truncated string
  2319. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  2320. pszFormat - format string which must be null terminated
  2321. ... - additional parameters to be formatted according to
  2322. the format string
  2323. Notes:
  2324. Behavior is undefined if destination, format strings or any arguments
  2325. strings overlap.
  2326. pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
  2327. flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and
  2328. pszFormat may be NULL. An error may still be returned even though NULLS
  2329. are ignored due to insufficient space.
  2330. Return Value:
  2331. S_OK - if there was source data and it was all concatenated and the
  2332. resultant dest string was null terminated
  2333. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2334. code for all falure cases
  2335. STRSAFE_E_INSUFFICIENT_BUFFER /
  2336. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2337. - this return value is an indication that the print operation
  2338. failed due to insufficient space. When this error occurs,
  2339. the destination buffer is modified to contain a truncated
  2340. version of the ideal result and is null terminated. This
  2341. is useful for situations where truncation is ok.
  2342. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2343. return value of this function
  2344. --*/
  2345. STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...);
  2346. STRSAFEAPI StringCbPrintfExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const WCHAR* pszFormat, ...);
  2347. #ifdef UNICODE
  2348. #define StringCbPrintfEx StringCbPrintfExW
  2349. #else
  2350. #define StringCbPrintfEx StringCbPrintfExA
  2351. #endif // !UNICODE
  2352. #ifdef STRSAFE_INLINE
  2353. STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...)
  2354. {
  2355. HRESULT hr;
  2356. size_t cchDest;
  2357. size_t cchRemaining = 0;
  2358. cchDest = cbDest / sizeof(char);
  2359. if (cchDest > STRSAFE_MAX_CCH)
  2360. {
  2361. hr = STRSAFE_E_INVALID_PARAMETER;
  2362. }
  2363. else
  2364. {
  2365. va_list argList;
  2366. va_start(argList, pszFormat);
  2367. hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
  2368. va_end(argList);
  2369. }
  2370. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  2371. {
  2372. if (pcbRemaining)
  2373. {
  2374. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  2375. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  2376. }
  2377. }
  2378. return hr;
  2379. }
  2380. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2381. STRSAFEAPI StringCbPrintfExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const WCHAR* pszFormat, ...)
  2382. {
  2383. HRESULT hr;
  2384. size_t cchDest;
  2385. size_t cchRemaining = 0;
  2386. cchDest = cbDest / sizeof(WCHAR);
  2387. if (cchDest > STRSAFE_MAX_CCH)
  2388. {
  2389. hr = STRSAFE_E_INVALID_PARAMETER;
  2390. }
  2391. else
  2392. {
  2393. va_list argList;
  2394. va_start(argList, pszFormat);
  2395. hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
  2396. va_end(argList);
  2397. }
  2398. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  2399. {
  2400. if (pcbRemaining)
  2401. {
  2402. // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  2403. *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR));
  2404. }
  2405. }
  2406. return hr;
  2407. }
  2408. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2409. #endif // STRSAFE_INLINE
  2410. #endif // !STRSAFE_NO_CB_FUNCTIONS
  2411. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  2412. /*++
  2413. STDAPI StringCchVPrintfEx(LPTSTR pszDest,
  2414. size_t cchDest,
  2415. LPTSTR* ppszDestEnd,
  2416. size_t* pcchRemaining,
  2417. DWORD dwFlags,
  2418. LPCTSTR pszFormat,
  2419. va_list argList);
  2420. Routine Description:
  2421. This routine is a safer version of the C built-in function 'vsprintf' with
  2422. some additional parameters. In addition to functionality provided by
  2423. StringCchVPrintf, this routine also returns a pointer to the end of the
  2424. destination string and the number of characters left in the destination string
  2425. including the null terminator. The flags parameter allows additional controls.
  2426. Arguments:
  2427. pszDest - destination string
  2428. cchDest - size of destination buffer in characters.
  2429. length must be sufficient to contain the resulting
  2430. formatted string plus the null terminator.
  2431. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  2432. pointer to the end of the destination string. If the
  2433. function printed any data, the result will point to the
  2434. null termination character
  2435. pcchRemaining - if pcchRemaining is non-null, the function will return
  2436. the number of characters left in the destination string,
  2437. including the null terminator
  2438. dwFlags - controls some details of the string copy:
  2439. STRSAFE_FILL_BEHIND_NULL
  2440. if the function succeeds, the low byte of dwFlags will be
  2441. used to fill the uninitialize part of destination buffer
  2442. behind the null terminator
  2443. STRSAFE_IGNORE_NULLS
  2444. treat NULL string pointers like empty strings (TEXT(""))
  2445. STRSAFE_FILL_ON_FAILURE
  2446. if the function fails, the low byte of dwFlags will be
  2447. used to fill all of the destination buffer, and it will
  2448. be null terminated. This will overwrite any truncated
  2449. string returned when the failure is
  2450. STRSAFE_E_INSUFFICIENT_BUFFER
  2451. STRSAFE_NO_TRUNCATION /
  2452. STRSAFE_NULL_ON_FAILURE
  2453. if the function fails, the destination buffer will be set
  2454. to the empty string. This will overwrite any truncated string
  2455. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  2456. pszFormat - format string which must be null terminated
  2457. argList - va_list from the variable arguments according to the
  2458. stdarg.h convention
  2459. Notes:
  2460. Behavior is undefined if destination, format strings or any arguments
  2461. strings overlap.
  2462. pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
  2463. flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and
  2464. pszFormat may be NULL. An error may still be returned even though NULLS
  2465. are ignored due to insufficient space.
  2466. Return Value:
  2467. S_OK - if there was source data and it was all concatenated and the
  2468. resultant dest string was null terminated
  2469. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2470. code for all falure cases
  2471. STRSAFE_E_INSUFFICIENT_BUFFER /
  2472. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2473. - this return value is an indication that the print operation
  2474. failed due to insufficient space. When this error occurs,
  2475. the destination buffer is modified to contain a truncated
  2476. version of the ideal result and is null terminated. This
  2477. is useful for situations where truncation is ok.
  2478. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2479. return value of this function
  2480. --*/
  2481. STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
  2482. STRSAFEAPI StringCchVPrintfExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList);
  2483. #ifdef UNICODE
  2484. #define StringCchVPrintfEx StringCchVPrintfExW
  2485. #else
  2486. #define StringCchVPrintfEx StringCchVPrintfExA
  2487. #endif // !UNICODE
  2488. #ifdef STRSAFE_INLINE
  2489. STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
  2490. {
  2491. HRESULT hr;
  2492. if (cchDest > STRSAFE_MAX_CCH)
  2493. {
  2494. hr = STRSAFE_E_INVALID_PARAMETER;
  2495. }
  2496. else
  2497. {
  2498. size_t cbDest;
  2499. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  2500. cbDest = cchDest * sizeof(char);
  2501. hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
  2502. }
  2503. return hr;
  2504. }
  2505. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2506. STRSAFEAPI StringCchVPrintfExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList)
  2507. {
  2508. HRESULT hr;
  2509. if (cchDest > STRSAFE_MAX_CCH)
  2510. {
  2511. hr = STRSAFE_E_INVALID_PARAMETER;
  2512. }
  2513. else
  2514. {
  2515. size_t cbDest;
  2516. // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  2517. cbDest = cchDest * sizeof(WCHAR);
  2518. hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
  2519. }
  2520. return hr;
  2521. }
  2522. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2523. #endif // STRSAFE_INLINE
  2524. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2525. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2526. /*++
  2527. STDAPI StringCbVPrintfEx(LPTSTR pszDest,
  2528. size_t cbDest,
  2529. LPTSTR* ppszDestEnd,
  2530. size_t* pcbRemaining,
  2531. DWORD dwFlags,
  2532. LPCTSTR pszFormat,
  2533. va_list argList);
  2534. Routine Description:
  2535. This routine is a safer version of the C built-in function 'vsprintf' with
  2536. some additional parameters. In addition to functionality provided by
  2537. StringCbVPrintf, this routine also returns a pointer to the end of the
  2538. destination string and the number of characters left in the destination string
  2539. including the null terminator. The flags parameter allows additional controls.
  2540. Arguments:
  2541. pszDest - destination string
  2542. cbDest - size of destination buffer in bytes.
  2543. length must be sufficient to contain the resulting
  2544. formatted string plus the null terminator.
  2545. ppszDestEnd - if ppszDestEnd is non-null, the function will return
  2546. a pointer to the end of the destination string. If the
  2547. function printed any data, the result will point to the
  2548. null termination character
  2549. pcbRemaining - if pcbRemaining is non-null, the function will return
  2550. the number of bytes left in the destination string,
  2551. including the null terminator
  2552. dwFlags - controls some details of the string copy:
  2553. STRSAFE_FILL_BEHIND_NULL
  2554. if the function succeeds, the low byte of dwFlags will be
  2555. used to fill the uninitialize part of destination buffer
  2556. behind the null terminator
  2557. STRSAFE_IGNORE_NULLS
  2558. treat NULL string pointers like empty strings (TEXT(""))
  2559. STRSAFE_FILL_ON_FAILURE
  2560. if the function fails, the low byte of dwFlags will be
  2561. used to fill all of the destination buffer, and it will
  2562. be null terminated. This will overwrite any truncated
  2563. string returned when the failure is
  2564. STRSAFE_E_INSUFFICIENT_BUFFER
  2565. STRSAFE_NO_TRUNCATION /
  2566. STRSAFE_NULL_ON_FAILURE
  2567. if the function fails, the destination buffer will be set
  2568. to the empty string. This will overwrite any truncated string
  2569. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  2570. pszFormat - format string which must be null terminated
  2571. argList - va_list from the variable arguments according to the
  2572. stdarg.h convention
  2573. Notes:
  2574. Behavior is undefined if destination, format strings or any arguments
  2575. strings overlap.
  2576. pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
  2577. flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and
  2578. pszFormat may be NULL. An error may still be returned even though NULLS
  2579. are ignored due to insufficient space.
  2580. Return Value:
  2581. S_OK - if there was source data and it was all concatenated and the
  2582. resultant dest string was null terminated
  2583. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2584. code for all falure cases
  2585. STRSAFE_E_INSUFFICIENT_BUFFER /
  2586. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2587. - this return value is an indication that the print operation
  2588. failed due to insufficient space. When this error occurs,
  2589. the destination buffer is modified to contain a truncated
  2590. version of the ideal result and is null terminated. This
  2591. is useful for situations where truncation is ok.
  2592. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2593. return value of this function
  2594. --*/
  2595. STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
  2596. STRSAFEAPI StringCbVPrintfExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList);
  2597. #ifdef UNICODE
  2598. #define StringCbVPrintfEx StringCbVPrintfExW
  2599. #else
  2600. #define StringCbVPrintfEx StringCbVPrintfExA
  2601. #endif // !UNICODE
  2602. #ifdef STRSAFE_INLINE
  2603. STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
  2604. {
  2605. HRESULT hr;
  2606. size_t cchDest;
  2607. size_t cchRemaining = 0;
  2608. cchDest = cbDest / sizeof(char);
  2609. if (cchDest > STRSAFE_MAX_CCH)
  2610. {
  2611. hr = STRSAFE_E_INVALID_PARAMETER;
  2612. }
  2613. else
  2614. {
  2615. hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
  2616. }
  2617. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  2618. {
  2619. if (pcbRemaining)
  2620. {
  2621. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  2622. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  2623. }
  2624. }
  2625. return hr;
  2626. }
  2627. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2628. STRSAFEAPI StringCbVPrintfExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList)
  2629. {
  2630. HRESULT hr;
  2631. size_t cchDest;
  2632. size_t cchRemaining = 0;
  2633. cchDest = cbDest / sizeof(WCHAR);
  2634. if (cchDest > STRSAFE_MAX_CCH)
  2635. {
  2636. hr = STRSAFE_E_INVALID_PARAMETER;
  2637. }
  2638. else
  2639. {
  2640. hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
  2641. }
  2642. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  2643. {
  2644. if (pcbRemaining)
  2645. {
  2646. // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  2647. *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR));
  2648. }
  2649. }
  2650. return hr;
  2651. }
  2652. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2653. #endif // STRSAFE_INLINE
  2654. #endif // !STRSAFE_NO_CB_FUNCTIONS
  2655. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  2656. /*++
  2657. STDAPI StringCchGets(LPTSTR pszDest,
  2658. size_t cchDest);
  2659. Routine Description:
  2660. This routine is a safer version of the C built-in function 'gets'.
  2661. The size of the destination buffer (in characters) is a parameter and
  2662. this function will not write past the end of this buffer and it will
  2663. ALWAYS null terminate the destination buffer (unless it is zero length).
  2664. This routine is not a replacement for fgets. That function does not replace
  2665. newline characters with a null terminator.
  2666. This function returns a hresult, and not a pointer. It returns a S_OK
  2667. if any characters were read from stdin and copied to pszDest and pszDest was
  2668. null terminated, otherwise it will return a failure code.
  2669. Arguments:
  2670. pszDest - destination string
  2671. cchDest - size of destination buffer in characters.
  2672. Notes:
  2673. pszDest should not be NULL. See StringCchGetsEx if you require the handling
  2674. of NULL values.
  2675. cchDest must be > 1 for this function to succeed.
  2676. Return Value:
  2677. S_OK - data was read from stdin and copied, and the resultant dest
  2678. string was null terminated
  2679. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2680. code for all hresult falure cases
  2681. STRSAFE_E_END_OF_FILE
  2682. - this return value indicates an error or end-of-file condition,
  2683. use feof or ferror to determine which one has occurred.
  2684. STRSAFE_E_INSUFFICIENT_BUFFER /
  2685. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2686. - this return value is an indication that there was insufficient
  2687. space in the destination buffer to copy any data
  2688. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2689. return value of this function.
  2690. --*/
  2691. #ifndef FEATURE_PAL
  2692. #ifndef STRSAFE_LIB_IMPL
  2693. STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest);
  2694. STRSAFE_INLINE_API StringCchGetsW(WCHAR* pszDest, size_t cchDest);
  2695. #ifdef UNICODE
  2696. #define StringCchGets StringCchGetsW
  2697. #else
  2698. #define StringCchGets StringCchGetsA
  2699. #endif // !UNICODE
  2700. STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest)
  2701. {
  2702. HRESULT hr;
  2703. if (cchDest > STRSAFE_MAX_CCH)
  2704. {
  2705. hr = STRSAFE_E_INVALID_PARAMETER;
  2706. }
  2707. else
  2708. {
  2709. size_t cbDest;
  2710. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  2711. cbDest = cchDest * sizeof(char);
  2712. hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0);
  2713. }
  2714. return hr;
  2715. }
  2716. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2717. STRSAFE_INLINE_API StringCchGetsW(WCHAR* pszDest, size_t cchDest)
  2718. {
  2719. HRESULT hr;
  2720. if (cchDest > STRSAFE_MAX_CCH)
  2721. {
  2722. hr = STRSAFE_E_INVALID_PARAMETER;
  2723. }
  2724. else
  2725. {
  2726. size_t cbDest;
  2727. // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  2728. cbDest = cchDest * sizeof(WCHAR);
  2729. hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, NULL, NULL, 0);
  2730. }
  2731. return hr;
  2732. }
  2733. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2734. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2735. #endif // !STRSAFE_LIB_IMPL
  2736. #endif // !FEATURE_PAL
  2737. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2738. /*++
  2739. STDAPI StringCbGets(LPTSTR pszDest,
  2740. size_t cbDest);
  2741. Routine Description:
  2742. This routine is a safer version of the C built-in function 'gets'.
  2743. The size of the destination buffer (in bytes) is a parameter and
  2744. this function will not write past the end of this buffer and it will
  2745. ALWAYS null terminate the destination buffer (unless it is zero length).
  2746. This routine is not a replacement for fgets. That function does not replace
  2747. newline characters with a null terminator.
  2748. This function returns a hresult, and not a pointer. It returns a S_OK
  2749. if any characters were read from stdin and copied to pszDest and pszDest was
  2750. null terminated, otherwise it will return a failure code.
  2751. Arguments:
  2752. pszDest - destination string
  2753. cbDest - size of destination buffer in bytes.
  2754. Notes:
  2755. pszDest should not be NULL. See StringCbGetsEx if you require the handling
  2756. of NULL values.
  2757. cbDest must be > sizeof(TCHAR) for this function to succeed.
  2758. Return Value:
  2759. S_OK - data was read from stdin and copied, and the resultant dest
  2760. string was null terminated
  2761. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2762. code for all hresult falure cases
  2763. STRSAFE_E_END_OF_FILE
  2764. - this return value indicates an error or end-of-file condition,
  2765. use feof or ferror to determine which one has occurred.
  2766. STRSAFE_E_INSUFFICIENT_BUFFER /
  2767. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2768. - this return value is an indication that there was insufficient
  2769. space in the destination buffer to copy any data
  2770. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2771. return value of this function.
  2772. --*/
  2773. #ifndef FEATURE_PAL
  2774. #ifndef STRSAFE_LIB_IMPL
  2775. STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest);
  2776. STRSAFE_INLINE_API StringCbGetsW(WCHAR* pszDest, size_t cbDest);
  2777. #ifdef UNICODE
  2778. #define StringCbGets StringCbGetsW
  2779. #else
  2780. #define StringCbGets StringCbGetsA
  2781. #endif // !UNICODE
  2782. STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest)
  2783. {
  2784. HRESULT hr;
  2785. size_t cchDest;
  2786. // convert to count of characters
  2787. cchDest = cbDest / sizeof(char);
  2788. if (cchDest > STRSAFE_MAX_CCH)
  2789. {
  2790. hr = STRSAFE_E_INVALID_PARAMETER;
  2791. }
  2792. else
  2793. {
  2794. hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0);
  2795. }
  2796. return hr;
  2797. }
  2798. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2799. STRSAFE_INLINE_API StringCbGetsW(WCHAR* pszDest, size_t cbDest)
  2800. {
  2801. HRESULT hr;
  2802. size_t cchDest;
  2803. // convert to count of characters
  2804. cchDest = cbDest / sizeof(WCHAR);
  2805. if (cchDest > STRSAFE_MAX_CCH)
  2806. {
  2807. hr = STRSAFE_E_INVALID_PARAMETER;
  2808. }
  2809. else
  2810. {
  2811. hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, NULL, NULL, 0);
  2812. }
  2813. return hr;
  2814. }
  2815. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2816. #endif // !STRSAFE_NO_CB_FUNCTIONS
  2817. #endif // !STRSAFE_LIB_IMPL
  2818. #endif // !FEATURE_PAL
  2819. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  2820. /*++
  2821. STDAPI StringCchGetsEx(LPTSTR pszDest,
  2822. size_t cchDest,
  2823. LPTSTR* ppszDestEnd,
  2824. size_t* pcchRemaining,
  2825. DWORD dwFlags);
  2826. Routine Description:
  2827. This routine is a safer version of the C built-in function 'gets' with
  2828. some additional parameters. In addition to functionality provided by
  2829. StringCchGets, this routine also returns a pointer to the end of the
  2830. destination string and the number of characters left in the destination string
  2831. including the null terminator. The flags parameter allows additional controls.
  2832. Arguments:
  2833. pszDest - destination string
  2834. cchDest - size of destination buffer in characters.
  2835. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  2836. pointer to the end of the destination string. If the
  2837. function copied any data, the result will point to the
  2838. null termination character
  2839. pcchRemaining - if pcchRemaining is non-null, the function will return the
  2840. number of characters left in the destination string,
  2841. including the null terminator
  2842. dwFlags - controls some details of the string copy:
  2843. STRSAFE_FILL_BEHIND_NULL
  2844. if the function succeeds, the low byte of dwFlags will be
  2845. used to fill the uninitialize part of destination buffer
  2846. behind the null terminator
  2847. STRSAFE_IGNORE_NULLS
  2848. treat NULL string pointers like empty strings (TEXT("")).
  2849. STRSAFE_FILL_ON_FAILURE
  2850. if the function fails, the low byte of dwFlags will be
  2851. used to fill all of the destination buffer, and it will
  2852. be null terminated.
  2853. STRSAFE_NO_TRUNCATION /
  2854. STRSAFE_NULL_ON_FAILURE
  2855. if the function fails, the destination buffer will be set
  2856. to the empty string.
  2857. Notes:
  2858. pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified.
  2859. If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be
  2860. returned even though NULLS are ignored
  2861. cchDest must be > 1 for this function to succeed.
  2862. Return Value:
  2863. S_OK - data was read from stdin and copied, and the resultant dest
  2864. string was null terminated
  2865. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2866. code for all hresult falure cases
  2867. STRSAFE_E_END_OF_FILE
  2868. - this return value indicates an error or end-of-file condition,
  2869. use feof or ferror to determine which one has occurred.
  2870. STRSAFE_E_INSUFFICIENT_BUFFER /
  2871. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2872. - this return value is an indication that there was insufficient
  2873. space in the destination buffer to copy any data
  2874. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2875. return value of this function.
  2876. --*/
  2877. #ifndef FEATURE_PAL
  2878. #ifndef STRSAFE_LIB_IMPL
  2879. STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  2880. STRSAFE_INLINE_API StringCchGetsExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  2881. #ifdef UNICODE
  2882. #define StringCchGetsEx StringCchGetsExW
  2883. #else
  2884. #define StringCchGetsEx StringCchGetsExA
  2885. #endif // !UNICODE
  2886. STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  2887. {
  2888. HRESULT hr;
  2889. if (cchDest > STRSAFE_MAX_CCH)
  2890. {
  2891. hr = STRSAFE_E_INVALID_PARAMETER;
  2892. }
  2893. else
  2894. {
  2895. size_t cbDest;
  2896. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  2897. cbDest = cchDest * sizeof(char);
  2898. hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags);
  2899. }
  2900. return hr;
  2901. }
  2902. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  2903. STRSAFE_INLINE_API StringCchGetsExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  2904. {
  2905. HRESULT hr;
  2906. if (cchDest > STRSAFE_MAX_CCH)
  2907. {
  2908. hr = STRSAFE_E_INVALID_PARAMETER;
  2909. }
  2910. else
  2911. {
  2912. size_t cbDest;
  2913. // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  2914. cbDest = cchDest * sizeof(WCHAR);
  2915. hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags);
  2916. }
  2917. return hr;
  2918. }
  2919. #endif // FEATURE_PAL || !PLATFORM_UNIX
  2920. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2921. #endif // !STRSAFE_LIB_IMPL
  2922. #endif // !FEATURE_PAL
  2923. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2924. /*++
  2925. STDAPI StringCbGetsEx(LPTSTR pszDest,
  2926. size_t cbDest,
  2927. LPTSTR* ppszDestEnd,
  2928. size_t* pcbRemaining,
  2929. DWORD dwFlags);
  2930. Routine Description:
  2931. This routine is a safer version of the C built-in function 'gets' with
  2932. some additional parameters. In addition to functionality provided by
  2933. StringCbGets, this routine also returns a pointer to the end of the
  2934. destination string and the number of characters left in the destination string
  2935. including the null terminator. The flags parameter allows additional controls.
  2936. Arguments:
  2937. pszDest - destination string
  2938. cbDest - size of destination buffer in bytes.
  2939. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  2940. pointer to the end of the destination string. If the
  2941. function copied any data, the result will point to the
  2942. null termination character
  2943. pcbRemaining - if pbRemaining is non-null, the function will return the
  2944. number of bytes left in the destination string,
  2945. including the null terminator
  2946. dwFlags - controls some details of the string copy:
  2947. STRSAFE_FILL_BEHIND_NULL
  2948. if the function succeeds, the low byte of dwFlags will be
  2949. used to fill the uninitialize part of destination buffer
  2950. behind the null terminator
  2951. STRSAFE_IGNORE_NULLS
  2952. treat NULL string pointers like empty strings (TEXT("")).
  2953. STRSAFE_FILL_ON_FAILURE
  2954. if the function fails, the low byte of dwFlags will be
  2955. used to fill all of the destination buffer, and it will
  2956. be null terminated.
  2957. STRSAFE_NO_TRUNCATION /
  2958. STRSAFE_NULL_ON_FAILURE
  2959. if the function fails, the destination buffer will be set
  2960. to the empty string.
  2961. Notes:
  2962. pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified.
  2963. If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be
  2964. returned even though NULLS are ignored
  2965. cbDest must be > sizeof(TCHAR) for this function to succeed
  2966. Return Value:
  2967. S_OK - data was read from stdin and copied, and the resultant dest
  2968. string was null terminated
  2969. failure - you can use the macro HRESULT_CODE() to get a win32 error
  2970. code for all hresult falure cases
  2971. STRSAFE_E_END_OF_FILE
  2972. - this return value indicates an error or end-of-file condition,
  2973. use feof or ferror to determine which one has occurred.
  2974. STRSAFE_E_INSUFFICIENT_BUFFER /
  2975. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2976. - this return value is an indication that there was insufficient
  2977. space in the destination buffer to copy any data
  2978. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2979. return value of this function.
  2980. --*/
  2981. #ifndef FEATURE_PAL
  2982. #ifndef STRSAFE_LIB_IMPL
  2983. STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pbRemaining, unsigned long dwFlags);
  2984. STRSAFE_INLINE_API StringCbGetsExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  2985. #ifdef UNICODE
  2986. #define StringCbGetsEx StringCbGetsExW
  2987. #else
  2988. #define StringCbGetsEx StringCbGetsExA
  2989. #endif // !UNICODE
  2990. STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  2991. {
  2992. HRESULT hr;
  2993. size_t cchDest;
  2994. size_t cchRemaining = 0;
  2995. cchDest = cbDest / sizeof(char);
  2996. if (cchDest > STRSAFE_MAX_CCH)
  2997. {
  2998. hr = STRSAFE_E_INVALID_PARAMETER;
  2999. }
  3000. else
  3001. {
  3002. hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags);
  3003. }
  3004. if (SUCCEEDED(hr) ||
  3005. (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
  3006. (hr == STRSAFE_E_END_OF_FILE))
  3007. {
  3008. if (pcbRemaining)
  3009. {
  3010. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  3011. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  3012. }
  3013. }
  3014. return hr;
  3015. }
  3016. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3017. STRSAFE_INLINE_API StringCbGetsExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  3018. {
  3019. HRESULT hr;
  3020. size_t cchDest;
  3021. size_t cchRemaining = 0;
  3022. cchDest = cbDest / sizeof(WCHAR);
  3023. if (cchDest > STRSAFE_MAX_CCH)
  3024. {
  3025. hr = STRSAFE_E_INVALID_PARAMETER;
  3026. }
  3027. else
  3028. {
  3029. hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags);
  3030. }
  3031. if (SUCCEEDED(hr) ||
  3032. (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
  3033. (hr == STRSAFE_E_END_OF_FILE))
  3034. {
  3035. if (pcbRemaining)
  3036. {
  3037. // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  3038. *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR));
  3039. }
  3040. }
  3041. return hr;
  3042. }
  3043. #endif // FEATURE_PAL || !PLATFORM_UNIX
  3044. #endif // !STRSAFE_NO_CB_FUNCTIONS
  3045. #endif // !STRSAFE_LIB_IMPL
  3046. #endif // !FEATURE_PAL
  3047. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  3048. /*++
  3049. STDAPI StringCchLength(LPCTSTR psz,
  3050. size_t cchMax,
  3051. size_t* pcch);
  3052. Routine Description:
  3053. This routine is a safer version of the C built-in function 'strlen'.
  3054. It is used to make sure a string is not larger than a given length, and
  3055. it optionally returns the current length in characters not including
  3056. the null terminator.
  3057. This function returns a hresult, and not a pointer. It returns a S_OK
  3058. if the string is non-null and the length including the null terminator is
  3059. less than or equal to cchMax characters.
  3060. Arguments:
  3061. psz - string to check the length of
  3062. cchMax - maximum number of characters including the null terminator
  3063. that psz is allowed to contain
  3064. pcch - if the function succeeds and pcch is non-null, the current length
  3065. in characters of psz excluding the null terminator will be returned.
  3066. This out parameter is equivalent to the return value of strlen(psz)
  3067. Notes:
  3068. psz can be null but the function will fail
  3069. cchMax should be greater than zero or the function will fail
  3070. Return Value:
  3071. S_OK - psz is non-null and the length including the null terminator is
  3072. less than or equal to cchMax characters
  3073. failure - you can use the macro HRESULT_CODE() to get a win32 error
  3074. code for all hresult falure cases
  3075. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  3076. return value of this function.
  3077. --*/
  3078. STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch);
  3079. STRSAFEAPI StringCchLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch);
  3080. #ifdef UNICODE
  3081. #define StringCchLength StringCchLengthW
  3082. #else
  3083. #define StringCchLength StringCchLengthA
  3084. #endif // !UNICODE
  3085. #ifdef STRSAFE_INLINE
  3086. STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch)
  3087. {
  3088. HRESULT hr;
  3089. if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
  3090. {
  3091. hr = STRSAFE_E_INVALID_PARAMETER;
  3092. }
  3093. else
  3094. {
  3095. hr = StringLengthWorkerA(psz, cchMax, pcch);
  3096. }
  3097. return hr;
  3098. }
  3099. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3100. STRSAFEAPI StringCchLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch)
  3101. {
  3102. HRESULT hr;
  3103. if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
  3104. {
  3105. hr = STRSAFE_E_INVALID_PARAMETER;
  3106. }
  3107. else
  3108. {
  3109. hr = StringLengthWorkerW(psz, cchMax, pcch);
  3110. }
  3111. return hr;
  3112. }
  3113. #endif // FEATURE_PAL || !PLATFORM_UNIX
  3114. #endif // STRSAFE_INLINE
  3115. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  3116. #ifndef STRSAFE_NO_CB_FUNCTIONS
  3117. /*++
  3118. STDAPI StringCbLength(LPCTSTR psz,
  3119. size_t cbMax,
  3120. size_t* pcb);
  3121. Routine Description:
  3122. This routine is a safer version of the C built-in function 'strlen'.
  3123. It is used to make sure a string is not larger than a given length, and
  3124. it optionally returns the current length in bytes not including
  3125. the null terminator.
  3126. This function returns a hresult, and not a pointer. It returns a S_OK
  3127. if the string is non-null and the length including the null terminator is
  3128. less than or equal to cbMax bytes.
  3129. Arguments:
  3130. psz - string to check the length of
  3131. cbMax - maximum number of bytes including the null terminator
  3132. that psz is allowed to contain
  3133. pcb - if the function succeeds and pcb is non-null, the current length
  3134. in bytes of psz excluding the null terminator will be returned.
  3135. This out parameter is equivalent to the return value of strlen(psz) * sizeof(TCHAR)
  3136. Notes:
  3137. psz can be null but the function will fail
  3138. cbMax should be greater than or equal to sizeof(TCHAR) or the function will fail
  3139. Return Value:
  3140. S_OK - psz is non-null and the length including the null terminator is
  3141. less than or equal to cbMax bytes
  3142. failure - you can use the macro HRESULT_CODE() to get a win32 error
  3143. code for all hresult falure cases
  3144. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  3145. return value of this function.
  3146. --*/
  3147. STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch);
  3148. STRSAFEAPI StringCbLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch);
  3149. #ifdef UNICODE
  3150. #define StringCbLength StringCbLengthW
  3151. #else
  3152. #define StringCbLength StringCbLengthA
  3153. #endif // !UNICODE
  3154. #ifdef STRSAFE_INLINE
  3155. STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb)
  3156. {
  3157. HRESULT hr;
  3158. size_t cchMax;
  3159. size_t cch = 0;
  3160. cchMax = cbMax / sizeof(char);
  3161. if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
  3162. {
  3163. hr = STRSAFE_E_INVALID_PARAMETER;
  3164. }
  3165. else
  3166. {
  3167. hr = StringLengthWorkerA(psz, cchMax, &cch);
  3168. }
  3169. if (SUCCEEDED(hr) && pcb)
  3170. {
  3171. // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1
  3172. *pcb = cch * sizeof(char);
  3173. }
  3174. return hr;
  3175. }
  3176. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3177. STRSAFEAPI StringCbLengthW(const WCHAR* psz, size_t cbMax, size_t* pcb)
  3178. {
  3179. HRESULT hr;
  3180. size_t cchMax;
  3181. size_t cch = 0;
  3182. cchMax = cbMax / sizeof(WCHAR);
  3183. if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
  3184. {
  3185. hr = STRSAFE_E_INVALID_PARAMETER;
  3186. }
  3187. else
  3188. {
  3189. hr = StringLengthWorkerW(psz, cchMax, &cch);
  3190. }
  3191. if (SUCCEEDED(hr) && pcb)
  3192. {
  3193. // safe to multiply cch * sizeof(WCHAR) since cch < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2
  3194. *pcb = cch * sizeof(WCHAR);
  3195. }
  3196. return hr;
  3197. }
  3198. #endif // FEATURE_PAL || !PLATFORM_UNIX
  3199. #endif // STRSAFE_INLINE
  3200. #endif // !STRSAFE_NO_CB_FUNCTIONS
  3201. // these are the worker functions that actually do the work
  3202. #ifdef STRSAFE_INLINE
  3203. STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc)
  3204. {
  3205. HRESULT hr = S_OK;
  3206. if (cchDest == 0)
  3207. {
  3208. // can not null terminate a zero-byte dest buffer
  3209. hr = STRSAFE_E_INVALID_PARAMETER;
  3210. }
  3211. else
  3212. {
  3213. while (cchDest && (*pszSrc != '\0'))
  3214. {
  3215. *pszDest++ = *pszSrc++;
  3216. cchDest--;
  3217. }
  3218. if (cchDest == 0)
  3219. {
  3220. // we are going to truncate pszDest
  3221. pszDest--;
  3222. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3223. }
  3224. *pszDest= '\0';
  3225. }
  3226. return hr;
  3227. }
  3228. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3229. STRSAFEAPI StringCopyWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc)
  3230. {
  3231. HRESULT hr = S_OK;
  3232. if (cchDest == 0)
  3233. {
  3234. // can not null terminate a zero-byte dest buffer
  3235. hr = STRSAFE_E_INVALID_PARAMETER;
  3236. }
  3237. else
  3238. {
  3239. while (cchDest && (*pszSrc != L'\0'))
  3240. {
  3241. *pszDest++ = *pszSrc++;
  3242. cchDest--;
  3243. }
  3244. if (cchDest == 0)
  3245. {
  3246. // we are going to truncate pszDest
  3247. pszDest--;
  3248. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3249. }
  3250. *pszDest= L'\0';
  3251. }
  3252. return hr;
  3253. }
  3254. #endif // FEATURE_PAL || !PLATFORM_UNIX
  3255. STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  3256. {
  3257. HRESULT hr = S_OK;
  3258. char* pszDestEnd = pszDest;
  3259. size_t cchRemaining = 0;
  3260. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  3261. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  3262. // only accept valid flags
  3263. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3264. {
  3265. hr = STRSAFE_E_INVALID_PARAMETER;
  3266. }
  3267. else
  3268. {
  3269. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3270. {
  3271. if (pszDest == NULL)
  3272. {
  3273. if ((cchDest != 0) || (cbDest != 0))
  3274. {
  3275. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3276. hr = STRSAFE_E_INVALID_PARAMETER;
  3277. }
  3278. }
  3279. if (pszSrc == NULL)
  3280. {
  3281. pszSrc = "";
  3282. }
  3283. }
  3284. if (SUCCEEDED(hr))
  3285. {
  3286. if (cchDest == 0)
  3287. {
  3288. pszDestEnd = pszDest;
  3289. cchRemaining = 0;
  3290. // only fail if there was actually src data to copy
  3291. if (*pszSrc != '\0')
  3292. {
  3293. if (pszDest == NULL)
  3294. {
  3295. hr = STRSAFE_E_INVALID_PARAMETER;
  3296. }
  3297. else
  3298. {
  3299. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3300. }
  3301. }
  3302. }
  3303. else
  3304. {
  3305. pszDestEnd = pszDest;
  3306. cchRemaining = cchDest;
  3307. while (cchRemaining && (*pszSrc != '\0'))
  3308. {
  3309. *pszDestEnd++= *pszSrc++;
  3310. cchRemaining--;
  3311. }
  3312. if (cchRemaining > 0)
  3313. {
  3314. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  3315. {
  3316. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
  3317. }
  3318. }
  3319. else
  3320. {
  3321. // we are going to truncate pszDest
  3322. pszDestEnd--;
  3323. cchRemaining++;
  3324. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3325. }
  3326. *pszDestEnd = '\0';
  3327. }
  3328. }
  3329. }
  3330. if (FAILED(hr))
  3331. {
  3332. if (pszDest)
  3333. {
  3334. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  3335. {
  3336. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  3337. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  3338. {
  3339. pszDestEnd = pszDest;
  3340. cchRemaining = cchDest;
  3341. }
  3342. else if (cchDest > 0)
  3343. {
  3344. pszDestEnd = pszDest + cchDest - 1;
  3345. cchRemaining = 1;
  3346. // null terminate the end of the string
  3347. *pszDestEnd = '\0';
  3348. }
  3349. }
  3350. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  3351. {
  3352. if (cchDest > 0)
  3353. {
  3354. pszDestEnd = pszDest;
  3355. cchRemaining = cchDest;
  3356. // null terminate the beginning of the string
  3357. *pszDestEnd = '\0';
  3358. }
  3359. }
  3360. }
  3361. }
  3362. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  3363. {
  3364. if (ppszDestEnd)
  3365. {
  3366. *ppszDestEnd = pszDestEnd;
  3367. }
  3368. if (pcchRemaining)
  3369. {
  3370. *pcchRemaining = cchRemaining;
  3371. }
  3372. }
  3373. return hr;
  3374. }
  3375. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3376. STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  3377. {
  3378. HRESULT hr = S_OK;
  3379. WCHAR* pszDestEnd = pszDest;
  3380. size_t cchRemaining = 0;
  3381. // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) ||
  3382. // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  3383. // only accept valid flags
  3384. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3385. {
  3386. hr = STRSAFE_E_INVALID_PARAMETER;
  3387. }
  3388. else
  3389. {
  3390. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3391. {
  3392. if (pszDest == NULL)
  3393. {
  3394. if ((cchDest != 0) || (cbDest != 0))
  3395. {
  3396. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3397. hr = STRSAFE_E_INVALID_PARAMETER;
  3398. }
  3399. }
  3400. if (pszSrc == NULL)
  3401. {
  3402. pszSrc = u"";
  3403. }
  3404. }
  3405. if (SUCCEEDED(hr))
  3406. {
  3407. if (cchDest == 0)
  3408. {
  3409. pszDestEnd = pszDest;
  3410. cchRemaining = 0;
  3411. // only fail if there was actually src data to copy
  3412. if (*pszSrc != u'\0')
  3413. {
  3414. if (pszDest == NULL)
  3415. {
  3416. hr = STRSAFE_E_INVALID_PARAMETER;
  3417. }
  3418. else
  3419. {
  3420. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3421. }
  3422. }
  3423. }
  3424. else
  3425. {
  3426. pszDestEnd = pszDest;
  3427. cchRemaining = cchDest;
  3428. while (cchRemaining && (*pszSrc != u'\0'))
  3429. {
  3430. *pszDestEnd++= *pszSrc++;
  3431. cchRemaining--;
  3432. }
  3433. if (cchRemaining > 0)
  3434. {
  3435. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  3436. {
  3437. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  3438. }
  3439. }
  3440. else
  3441. {
  3442. // we are going to truncate pszDest
  3443. pszDestEnd--;
  3444. cchRemaining++;
  3445. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3446. }
  3447. *pszDestEnd = u'\0';
  3448. }
  3449. }
  3450. }
  3451. if (FAILED(hr))
  3452. {
  3453. if (pszDest)
  3454. {
  3455. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  3456. {
  3457. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  3458. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  3459. {
  3460. pszDestEnd = pszDest;
  3461. cchRemaining = cchDest;
  3462. }
  3463. else if (cchDest > 0)
  3464. {
  3465. pszDestEnd = pszDest + cchDest - 1;
  3466. cchRemaining = 1;
  3467. // null terminate the end of the string
  3468. *pszDestEnd = L'\0';
  3469. }
  3470. }
  3471. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  3472. {
  3473. if (cchDest > 0)
  3474. {
  3475. pszDestEnd = pszDest;
  3476. cchRemaining = cchDest;
  3477. // null terminate the beginning of the string
  3478. *pszDestEnd = L'\0';
  3479. }
  3480. }
  3481. }
  3482. }
  3483. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  3484. {
  3485. if (ppszDestEnd)
  3486. {
  3487. *ppszDestEnd = pszDestEnd;
  3488. }
  3489. if (pcchRemaining)
  3490. {
  3491. *pcchRemaining = cchRemaining;
  3492. }
  3493. }
  3494. return hr;
  3495. }
  3496. #endif // FEATURE_PAL || !PLATFORM_UNIX
  3497. STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc)
  3498. {
  3499. HRESULT hr = S_OK;
  3500. if (cchDest == 0)
  3501. {
  3502. // can not null terminate a zero-byte dest buffer
  3503. hr = STRSAFE_E_INVALID_PARAMETER;
  3504. }
  3505. else
  3506. {
  3507. while (cchDest && cchSrc && (*pszSrc != '\0'))
  3508. {
  3509. *pszDest++= *pszSrc++;
  3510. cchDest--;
  3511. cchSrc--;
  3512. }
  3513. if (cchDest == 0)
  3514. {
  3515. // we are going to truncate pszDest
  3516. pszDest--;
  3517. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3518. }
  3519. *pszDest= '\0';
  3520. }
  3521. return hr;
  3522. }
  3523. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3524. STRSAFEAPI StringCopyNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc)
  3525. {
  3526. HRESULT hr = S_OK;
  3527. if (cchDest == 0)
  3528. {
  3529. // can not null terminate a zero-byte dest buffer
  3530. hr = STRSAFE_E_INVALID_PARAMETER;
  3531. }
  3532. else
  3533. {
  3534. while (cchDest && cchSrc && (*pszSrc != L'\0'))
  3535. {
  3536. *pszDest++= *pszSrc++;
  3537. cchDest--;
  3538. cchSrc--;
  3539. }
  3540. if (cchDest == 0)
  3541. {
  3542. // we are going to truncate pszDest
  3543. pszDest--;
  3544. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3545. }
  3546. *pszDest= L'\0';
  3547. }
  3548. return hr;
  3549. }
  3550. #endif // FEATURE_PAL || !PLATFORM_UNIX
  3551. STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  3552. {
  3553. HRESULT hr = S_OK;
  3554. char* pszDestEnd = pszDest;
  3555. size_t cchRemaining = 0;
  3556. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  3557. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  3558. // only accept valid flags
  3559. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3560. {
  3561. hr = STRSAFE_E_INVALID_PARAMETER;
  3562. }
  3563. else
  3564. {
  3565. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3566. {
  3567. if (pszDest == NULL)
  3568. {
  3569. if ((cchDest != 0) || (cbDest != 0))
  3570. {
  3571. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3572. hr = STRSAFE_E_INVALID_PARAMETER;
  3573. }
  3574. }
  3575. if (pszSrc == NULL)
  3576. {
  3577. pszSrc = "";
  3578. }
  3579. }
  3580. if (SUCCEEDED(hr))
  3581. {
  3582. if (cchDest == 0)
  3583. {
  3584. pszDestEnd = pszDest;
  3585. cchRemaining = 0;
  3586. // only fail if there was actually src data to copy
  3587. if (*pszSrc != '\0')
  3588. {
  3589. if (pszDest == NULL)
  3590. {
  3591. hr = STRSAFE_E_INVALID_PARAMETER;
  3592. }
  3593. else
  3594. {
  3595. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3596. }
  3597. }
  3598. }
  3599. else
  3600. {
  3601. pszDestEnd = pszDest;
  3602. cchRemaining = cchDest;
  3603. while (cchRemaining && cchSrc && (*pszSrc != '\0'))
  3604. {
  3605. *pszDestEnd++= *pszSrc++;
  3606. cchRemaining--;
  3607. cchSrc--;
  3608. }
  3609. if (cchRemaining > 0)
  3610. {
  3611. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  3612. {
  3613. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
  3614. }
  3615. }
  3616. else
  3617. {
  3618. // we are going to truncate pszDest
  3619. pszDestEnd--;
  3620. cchRemaining++;
  3621. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3622. }
  3623. *pszDestEnd = '\0';
  3624. }
  3625. }
  3626. }
  3627. if (FAILED(hr))
  3628. {
  3629. if (pszDest)
  3630. {
  3631. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  3632. {
  3633. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  3634. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  3635. {
  3636. pszDestEnd = pszDest;
  3637. cchRemaining = cchDest;
  3638. }
  3639. else if (cchDest > 0)
  3640. {
  3641. pszDestEnd = pszDest + cchDest - 1;
  3642. cchRemaining = 1;
  3643. // null terminate the end of the string
  3644. *pszDestEnd = '\0';
  3645. }
  3646. }
  3647. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  3648. {
  3649. if (cchDest > 0)
  3650. {
  3651. pszDestEnd = pszDest;
  3652. cchRemaining = cchDest;
  3653. // null terminate the beginning of the string
  3654. *pszDestEnd = '\0';
  3655. }
  3656. }
  3657. }
  3658. }
  3659. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  3660. {
  3661. if (ppszDestEnd)
  3662. {
  3663. *ppszDestEnd = pszDestEnd;
  3664. }
  3665. if (pcchRemaining)
  3666. {
  3667. *pcchRemaining = cchRemaining;
  3668. }
  3669. }
  3670. return hr;
  3671. }
  3672. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3673. STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  3674. {
  3675. HRESULT hr = S_OK;
  3676. WCHAR* pszDestEnd = pszDest;
  3677. size_t cchRemaining = 0;
  3678. // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) ||
  3679. // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  3680. // only accept valid flags
  3681. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3682. {
  3683. hr = STRSAFE_E_INVALID_PARAMETER;
  3684. }
  3685. else
  3686. {
  3687. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3688. {
  3689. if (pszDest == NULL)
  3690. {
  3691. if ((cchDest != 0) || (cbDest != 0))
  3692. {
  3693. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3694. hr = STRSAFE_E_INVALID_PARAMETER;
  3695. }
  3696. }
  3697. if (pszSrc == NULL)
  3698. {
  3699. pszSrc = u"";
  3700. }
  3701. }
  3702. if (SUCCEEDED(hr))
  3703. {
  3704. if (cchDest == 0)
  3705. {
  3706. pszDestEnd = pszDest;
  3707. cchRemaining = 0;
  3708. // only fail if there was actually src data to copy
  3709. if (*pszSrc != L'\0')
  3710. {
  3711. if (pszDest == NULL)
  3712. {
  3713. hr = STRSAFE_E_INVALID_PARAMETER;
  3714. }
  3715. else
  3716. {
  3717. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3718. }
  3719. }
  3720. }
  3721. else
  3722. {
  3723. pszDestEnd = pszDest;
  3724. cchRemaining = cchDest;
  3725. while (cchRemaining && cchSrc && (*pszSrc != L'\0'))
  3726. {
  3727. *pszDestEnd++= *pszSrc++;
  3728. cchRemaining--;
  3729. cchSrc--;
  3730. }
  3731. if (cchRemaining > 0)
  3732. {
  3733. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  3734. {
  3735. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  3736. }
  3737. }
  3738. else
  3739. {
  3740. // we are going to truncate pszDest
  3741. pszDestEnd--;
  3742. cchRemaining++;
  3743. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3744. }
  3745. *pszDestEnd = L'\0';
  3746. }
  3747. }
  3748. }
  3749. if (FAILED(hr))
  3750. {
  3751. if (pszDest)
  3752. {
  3753. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  3754. {
  3755. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  3756. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  3757. {
  3758. pszDestEnd = pszDest;
  3759. cchRemaining = cchDest;
  3760. }
  3761. else if (cchDest > 0)
  3762. {
  3763. pszDestEnd = pszDest + cchDest - 1;
  3764. cchRemaining = 1;
  3765. // null terminate the end of the string
  3766. *pszDestEnd = L'\0';
  3767. }
  3768. }
  3769. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  3770. {
  3771. if (cchDest > 0)
  3772. {
  3773. pszDestEnd = pszDest;
  3774. cchRemaining = cchDest;
  3775. // null terminate the beginning of the string
  3776. *pszDestEnd = L'\0';
  3777. }
  3778. }
  3779. }
  3780. }
  3781. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  3782. {
  3783. if (ppszDestEnd)
  3784. {
  3785. *ppszDestEnd = pszDestEnd;
  3786. }
  3787. if (pcchRemaining)
  3788. {
  3789. *pcchRemaining = cchRemaining;
  3790. }
  3791. }
  3792. return hr;
  3793. }
  3794. #endif // FEATURE_PAL || !PLATFORM_UNIX
  3795. STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc)
  3796. {
  3797. HRESULT hr;
  3798. size_t cchDestCurrent;
  3799. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  3800. if (SUCCEEDED(hr))
  3801. {
  3802. hr = StringCopyWorkerA(pszDest + cchDestCurrent,
  3803. cchDest - cchDestCurrent,
  3804. pszSrc);
  3805. }
  3806. return hr;
  3807. }
  3808. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3809. STRSAFEAPI StringCatWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc)
  3810. {
  3811. HRESULT hr;
  3812. size_t cchDestCurrent;
  3813. hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
  3814. if (SUCCEEDED(hr))
  3815. {
  3816. hr = StringCopyWorkerW(pszDest + cchDestCurrent,
  3817. cchDest - cchDestCurrent,
  3818. pszSrc);
  3819. }
  3820. return hr;
  3821. }
  3822. #endif // FEATURE_PAL || !PLATFORM_UNIX
  3823. STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  3824. {
  3825. HRESULT hr = S_OK;
  3826. char* pszDestEnd = pszDest;
  3827. size_t cchRemaining = 0;
  3828. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  3829. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  3830. // only accept valid flags
  3831. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3832. {
  3833. hr = STRSAFE_E_INVALID_PARAMETER;
  3834. }
  3835. else
  3836. {
  3837. size_t cchDestCurrent;
  3838. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3839. {
  3840. if (pszDest == NULL)
  3841. {
  3842. if ((cchDest == 0) && (cbDest == 0))
  3843. {
  3844. cchDestCurrent = 0;
  3845. }
  3846. else
  3847. {
  3848. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3849. hr = STRSAFE_E_INVALID_PARAMETER;
  3850. }
  3851. }
  3852. else
  3853. {
  3854. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  3855. if (SUCCEEDED(hr))
  3856. {
  3857. pszDestEnd = pszDest + cchDestCurrent;
  3858. cchRemaining = cchDest - cchDestCurrent;
  3859. }
  3860. }
  3861. if (pszSrc == NULL)
  3862. {
  3863. pszSrc = "";
  3864. }
  3865. }
  3866. else
  3867. {
  3868. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  3869. if (SUCCEEDED(hr))
  3870. {
  3871. pszDestEnd = pszDest + cchDestCurrent;
  3872. cchRemaining = cchDest - cchDestCurrent;
  3873. }
  3874. }
  3875. if (SUCCEEDED(hr))
  3876. {
  3877. if (cchDest == 0)
  3878. {
  3879. // only fail if there was actually src data to append
  3880. if (*pszSrc != '\0')
  3881. {
  3882. if (pszDest == NULL)
  3883. {
  3884. hr = STRSAFE_E_INVALID_PARAMETER;
  3885. }
  3886. else
  3887. {
  3888. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3889. }
  3890. }
  3891. }
  3892. else
  3893. {
  3894. // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
  3895. // those flags through
  3896. hr = StringCopyExWorkerA(pszDestEnd,
  3897. cchRemaining,
  3898. (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)),
  3899. pszSrc,
  3900. &pszDestEnd,
  3901. &cchRemaining,
  3902. dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
  3903. }
  3904. }
  3905. }
  3906. if (FAILED(hr))
  3907. {
  3908. if (pszDest)
  3909. {
  3910. // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA()
  3911. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  3912. {
  3913. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  3914. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  3915. {
  3916. pszDestEnd = pszDest;
  3917. cchRemaining = cchDest;
  3918. }
  3919. else
  3920. if (cchDest > 0)
  3921. {
  3922. pszDestEnd = pszDest + cchDest - 1;
  3923. cchRemaining = 1;
  3924. // null terminate the end of the string
  3925. *pszDestEnd = '\0';
  3926. }
  3927. }
  3928. if (dwFlags & STRSAFE_NULL_ON_FAILURE)
  3929. {
  3930. if (cchDest > 0)
  3931. {
  3932. pszDestEnd = pszDest;
  3933. cchRemaining = cchDest;
  3934. // null terminate the beginning of the string
  3935. *pszDestEnd = '\0';
  3936. }
  3937. }
  3938. }
  3939. }
  3940. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  3941. {
  3942. if (ppszDestEnd)
  3943. {
  3944. *ppszDestEnd = pszDestEnd;
  3945. }
  3946. if (pcchRemaining)
  3947. {
  3948. *pcchRemaining = cchRemaining;
  3949. }
  3950. }
  3951. return hr;
  3952. }
  3953. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  3954. STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  3955. {
  3956. HRESULT hr = S_OK;
  3957. WCHAR* pszDestEnd = pszDest;
  3958. size_t cchRemaining = 0;
  3959. // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) ||
  3960. // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  3961. // only accept valid flags
  3962. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3963. {
  3964. hr = STRSAFE_E_INVALID_PARAMETER;
  3965. }
  3966. else
  3967. {
  3968. size_t cchDestCurrent;
  3969. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3970. {
  3971. if (pszDest == NULL)
  3972. {
  3973. if ((cchDest == 0) && (cbDest == 0))
  3974. {
  3975. cchDestCurrent = 0;
  3976. }
  3977. else
  3978. {
  3979. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3980. hr = STRSAFE_E_INVALID_PARAMETER;
  3981. }
  3982. }
  3983. else
  3984. {
  3985. hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
  3986. if (SUCCEEDED(hr))
  3987. {
  3988. pszDestEnd = pszDest + cchDestCurrent;
  3989. cchRemaining = cchDest - cchDestCurrent;
  3990. }
  3991. }
  3992. if (pszSrc == NULL)
  3993. {
  3994. pszSrc = u"";
  3995. }
  3996. }
  3997. else
  3998. {
  3999. hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
  4000. if (SUCCEEDED(hr))
  4001. {
  4002. pszDestEnd = pszDest + cchDestCurrent;
  4003. cchRemaining = cchDest - cchDestCurrent;
  4004. }
  4005. }
  4006. if (SUCCEEDED(hr))
  4007. {
  4008. if (cchDest == 0)
  4009. {
  4010. // only fail if there was actually src data to append
  4011. if (*pszSrc != L'\0')
  4012. {
  4013. if (pszDest == NULL)
  4014. {
  4015. hr = STRSAFE_E_INVALID_PARAMETER;
  4016. }
  4017. else
  4018. {
  4019. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4020. }
  4021. }
  4022. }
  4023. else
  4024. {
  4025. // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
  4026. // those flags through
  4027. hr = StringCopyExWorkerW(pszDestEnd,
  4028. cchRemaining,
  4029. (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)),
  4030. pszSrc,
  4031. &pszDestEnd,
  4032. &cchRemaining,
  4033. dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
  4034. }
  4035. }
  4036. }
  4037. if (FAILED(hr))
  4038. {
  4039. if (pszDest)
  4040. {
  4041. // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerW()
  4042. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  4043. {
  4044. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  4045. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  4046. {
  4047. pszDestEnd = pszDest;
  4048. cchRemaining = cchDest;
  4049. }
  4050. else if (cchDest > 0)
  4051. {
  4052. pszDestEnd = pszDest + cchDest - 1;
  4053. cchRemaining = 1;
  4054. // null terminate the end of the string
  4055. *pszDestEnd = L'\0';
  4056. }
  4057. }
  4058. if (dwFlags & STRSAFE_NULL_ON_FAILURE)
  4059. {
  4060. if (cchDest > 0)
  4061. {
  4062. pszDestEnd = pszDest;
  4063. cchRemaining = cchDest;
  4064. // null terminate the beginning of the string
  4065. *pszDestEnd = L'\0';
  4066. }
  4067. }
  4068. }
  4069. }
  4070. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  4071. {
  4072. if (ppszDestEnd)
  4073. {
  4074. *ppszDestEnd = pszDestEnd;
  4075. }
  4076. if (pcchRemaining)
  4077. {
  4078. *pcchRemaining = cchRemaining;
  4079. }
  4080. }
  4081. return hr;
  4082. }
  4083. #endif // FEATURE_PAL || !PLATFORM_UNIX
  4084. STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend)
  4085. {
  4086. HRESULT hr;
  4087. size_t cchDestCurrent;
  4088. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  4089. if (SUCCEEDED(hr))
  4090. {
  4091. hr = StringCopyNWorkerA(pszDest + cchDestCurrent,
  4092. cchDest - cchDestCurrent,
  4093. pszSrc,
  4094. cchMaxAppend);
  4095. }
  4096. return hr;
  4097. }
  4098. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  4099. STRSAFEAPI StringCatNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend)
  4100. {
  4101. HRESULT hr;
  4102. size_t cchDestCurrent;
  4103. hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
  4104. if (SUCCEEDED(hr))
  4105. {
  4106. hr = StringCopyNWorkerW(pszDest + cchDestCurrent,
  4107. cchDest - cchDestCurrent,
  4108. pszSrc,
  4109. cchMaxAppend);
  4110. }
  4111. return hr;
  4112. }
  4113. #endif // FEATURE_PAL || !PLATFORM_UNIX
  4114. STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  4115. {
  4116. HRESULT hr = S_OK;
  4117. char* pszDestEnd = pszDest;
  4118. size_t cchRemaining = 0;
  4119. size_t cchDestCurrent = 0;
  4120. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  4121. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  4122. // only accept valid flags
  4123. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  4124. {
  4125. hr = STRSAFE_E_INVALID_PARAMETER;
  4126. }
  4127. else
  4128. {
  4129. if (dwFlags & STRSAFE_IGNORE_NULLS)
  4130. {
  4131. if (pszDest == NULL)
  4132. {
  4133. if ((cchDest == 0) && (cbDest == 0))
  4134. {
  4135. cchDestCurrent = 0;
  4136. }
  4137. else
  4138. {
  4139. // NULL pszDest and non-zero cchDest/cbDest is invalid
  4140. hr = STRSAFE_E_INVALID_PARAMETER;
  4141. }
  4142. }
  4143. else
  4144. {
  4145. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  4146. if (SUCCEEDED(hr))
  4147. {
  4148. pszDestEnd = pszDest + cchDestCurrent;
  4149. cchRemaining = cchDest - cchDestCurrent;
  4150. }
  4151. }
  4152. if (pszSrc == NULL)
  4153. {
  4154. pszSrc = "";
  4155. }
  4156. }
  4157. else
  4158. {
  4159. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  4160. if (SUCCEEDED(hr))
  4161. {
  4162. pszDestEnd = pszDest + cchDestCurrent;
  4163. cchRemaining = cchDest - cchDestCurrent;
  4164. }
  4165. }
  4166. if (SUCCEEDED(hr))
  4167. {
  4168. if (cchDest == 0)
  4169. {
  4170. // only fail if there was actually src data to append
  4171. if (*pszSrc != '\0')
  4172. {
  4173. if (pszDest == NULL)
  4174. {
  4175. hr = STRSAFE_E_INVALID_PARAMETER;
  4176. }
  4177. else
  4178. {
  4179. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4180. }
  4181. }
  4182. }
  4183. else
  4184. {
  4185. // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
  4186. // those flags through
  4187. hr = StringCopyNExWorkerA(pszDestEnd,
  4188. cchRemaining,
  4189. (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)),
  4190. pszSrc,
  4191. cchMaxAppend,
  4192. &pszDestEnd,
  4193. &cchRemaining,
  4194. dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
  4195. }
  4196. }
  4197. }
  4198. if (FAILED(hr))
  4199. {
  4200. if (pszDest)
  4201. {
  4202. // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA()
  4203. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  4204. {
  4205. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  4206. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  4207. {
  4208. pszDestEnd = pszDest;
  4209. cchRemaining = cchDest;
  4210. }
  4211. else if (cchDest > 0)
  4212. {
  4213. pszDestEnd = pszDest + cchDest - 1;
  4214. cchRemaining = 1;
  4215. // null terminate the end of the string
  4216. *pszDestEnd = '\0';
  4217. }
  4218. }
  4219. if (dwFlags & (STRSAFE_NULL_ON_FAILURE))
  4220. {
  4221. if (cchDest > 0)
  4222. {
  4223. pszDestEnd = pszDest;
  4224. cchRemaining = cchDest;
  4225. // null terminate the beginning of the string
  4226. *pszDestEnd = '\0';
  4227. }
  4228. }
  4229. }
  4230. }
  4231. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  4232. {
  4233. if (ppszDestEnd)
  4234. {
  4235. *ppszDestEnd = pszDestEnd;
  4236. }
  4237. if (pcchRemaining)
  4238. {
  4239. *pcchRemaining = cchRemaining;
  4240. }
  4241. }
  4242. return hr;
  4243. }
  4244. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  4245. STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  4246. {
  4247. HRESULT hr = S_OK;
  4248. WCHAR* pszDestEnd = pszDest;
  4249. size_t cchRemaining = 0;
  4250. size_t cchDestCurrent = 0;
  4251. // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) ||
  4252. // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  4253. // only accept valid flags
  4254. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  4255. {
  4256. hr = STRSAFE_E_INVALID_PARAMETER;
  4257. }
  4258. else
  4259. {
  4260. if (dwFlags & STRSAFE_IGNORE_NULLS)
  4261. {
  4262. if (pszDest == NULL)
  4263. {
  4264. if ((cchDest == 0) && (cbDest == 0))
  4265. {
  4266. cchDestCurrent = 0;
  4267. }
  4268. else
  4269. {
  4270. // NULL pszDest and non-zero cchDest/cbDest is invalid
  4271. hr = STRSAFE_E_INVALID_PARAMETER;
  4272. }
  4273. }
  4274. else
  4275. {
  4276. hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
  4277. if (SUCCEEDED(hr))
  4278. {
  4279. pszDestEnd = pszDest + cchDestCurrent;
  4280. cchRemaining = cchDest - cchDestCurrent;
  4281. }
  4282. }
  4283. if (pszSrc == NULL)
  4284. {
  4285. pszSrc = u"";
  4286. }
  4287. }
  4288. else
  4289. {
  4290. hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent);
  4291. if (SUCCEEDED(hr))
  4292. {
  4293. pszDestEnd = pszDest + cchDestCurrent;
  4294. cchRemaining = cchDest - cchDestCurrent;
  4295. }
  4296. }
  4297. if (SUCCEEDED(hr))
  4298. {
  4299. if (cchDest == 0)
  4300. {
  4301. // only fail if there was actually src data to append
  4302. if (*pszSrc != L'\0')
  4303. {
  4304. if (pszDest == NULL)
  4305. {
  4306. hr = STRSAFE_E_INVALID_PARAMETER;
  4307. }
  4308. else
  4309. {
  4310. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4311. }
  4312. }
  4313. }
  4314. else
  4315. {
  4316. // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
  4317. // those flags through
  4318. hr = StringCopyNExWorkerW(pszDestEnd,
  4319. cchRemaining,
  4320. (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)),
  4321. pszSrc,
  4322. cchMaxAppend,
  4323. &pszDestEnd,
  4324. &cchRemaining,
  4325. dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
  4326. }
  4327. }
  4328. }
  4329. if (FAILED(hr))
  4330. {
  4331. if (pszDest)
  4332. {
  4333. // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerW()
  4334. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  4335. {
  4336. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  4337. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  4338. {
  4339. pszDestEnd = pszDest;
  4340. cchRemaining = cchDest;
  4341. }
  4342. else if (cchDest > 0)
  4343. {
  4344. pszDestEnd = pszDest + cchDest - 1;
  4345. cchRemaining = 1;
  4346. // null terminate the end of the string
  4347. *pszDestEnd = L'\0';
  4348. }
  4349. }
  4350. if (dwFlags & (STRSAFE_NULL_ON_FAILURE))
  4351. {
  4352. if (cchDest > 0)
  4353. {
  4354. pszDestEnd = pszDest;
  4355. cchRemaining = cchDest;
  4356. // null terminate the beginning of the string
  4357. *pszDestEnd = L'\0';
  4358. }
  4359. }
  4360. }
  4361. }
  4362. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  4363. {
  4364. if (ppszDestEnd)
  4365. {
  4366. *ppszDestEnd = pszDestEnd;
  4367. }
  4368. if (pcchRemaining)
  4369. {
  4370. *pcchRemaining = cchRemaining;
  4371. }
  4372. }
  4373. return hr;
  4374. }
  4375. #endif // FEATURE_PAL || !PLATFORM_UNIX
  4376. STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList)
  4377. {
  4378. HRESULT hr = S_OK;
  4379. if (cchDest == 0)
  4380. {
  4381. // can not null terminate a zero-byte dest buffer
  4382. hr = STRSAFE_E_INVALID_PARAMETER;
  4383. }
  4384. else
  4385. {
  4386. int iRet;
  4387. size_t cchMax;
  4388. // leave the last space for the null terminator
  4389. cchMax = cchDest - 1;
  4390. iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList);
  4391. // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
  4392. if ((iRet < 0) || (((size_t)iRet) > cchMax))
  4393. {
  4394. // need to null terminate the string
  4395. pszDest += cchMax;
  4396. *pszDest = '\0';
  4397. // we have truncated pszDest
  4398. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4399. }
  4400. else if (((size_t)iRet) == cchMax)
  4401. {
  4402. // need to null terminate the string
  4403. pszDest += cchMax;
  4404. *pszDest = '\0';
  4405. }
  4406. }
  4407. return hr;
  4408. }
  4409. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  4410. STRSAFEAPI StringVPrintfWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList)
  4411. {
  4412. HRESULT hr = S_OK;
  4413. if (cchDest == 0)
  4414. {
  4415. // can not null terminate a zero-byte dest buffer
  4416. hr = STRSAFE_E_INVALID_PARAMETER;
  4417. }
  4418. else
  4419. {
  4420. int iRet;
  4421. size_t cchMax;
  4422. // leave the last space for the null terminator
  4423. cchMax = cchDest - 1;
  4424. iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
  4425. // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
  4426. if ((iRet < 0) || (((size_t)iRet) > cchMax))
  4427. {
  4428. // need to null terminate the string
  4429. pszDest += cchMax;
  4430. *pszDest = L'\0';
  4431. // we have truncated pszDest
  4432. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4433. }
  4434. else if (((size_t)iRet) == cchMax)
  4435. {
  4436. // need to null terminate the string
  4437. pszDest += cchMax;
  4438. *pszDest = L'\0';
  4439. }
  4440. }
  4441. return hr;
  4442. }
  4443. #endif // FEATURE_PAL || !PLATFORM_UNIX
  4444. STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
  4445. {
  4446. HRESULT hr = S_OK;
  4447. char* pszDestEnd = pszDest;
  4448. size_t cchRemaining = 0;
  4449. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  4450. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  4451. // only accept valid flags
  4452. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  4453. {
  4454. hr = STRSAFE_E_INVALID_PARAMETER;
  4455. }
  4456. else
  4457. {
  4458. if (dwFlags & STRSAFE_IGNORE_NULLS)
  4459. {
  4460. if (pszDest == NULL)
  4461. {
  4462. if ((cchDest != 0) || (cbDest != 0))
  4463. {
  4464. // NULL pszDest and non-zero cchDest/cbDest is invalid
  4465. hr = STRSAFE_E_INVALID_PARAMETER;
  4466. }
  4467. }
  4468. if (pszFormat == NULL)
  4469. {
  4470. pszFormat = "";
  4471. }
  4472. }
  4473. if (SUCCEEDED(hr))
  4474. {
  4475. if (cchDest == 0)
  4476. {
  4477. pszDestEnd = pszDest;
  4478. cchRemaining = 0;
  4479. // only fail if there was actually a non-empty format string
  4480. if (*pszFormat != '\0')
  4481. {
  4482. if (pszDest == NULL)
  4483. {
  4484. hr = STRSAFE_E_INVALID_PARAMETER;
  4485. }
  4486. else
  4487. {
  4488. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4489. }
  4490. }
  4491. }
  4492. else
  4493. {
  4494. int iRet;
  4495. size_t cchMax;
  4496. // leave the last space for the null terminator
  4497. cchMax = cchDest - 1;
  4498. iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList);
  4499. // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
  4500. if ((iRet < 0) || (((size_t)iRet) > cchMax))
  4501. {
  4502. // we have truncated pszDest
  4503. pszDestEnd = pszDest + cchMax;
  4504. cchRemaining = 1;
  4505. // need to null terminate the string
  4506. *pszDestEnd = '\0';
  4507. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4508. }
  4509. else if (((size_t)iRet) == cchMax)
  4510. {
  4511. // string fit perfectly
  4512. pszDestEnd = pszDest + cchMax;
  4513. cchRemaining = 1;
  4514. // need to null terminate the string
  4515. *pszDestEnd = '\0';
  4516. }
  4517. else if (((size_t)iRet) < cchMax)
  4518. {
  4519. // there is extra room
  4520. pszDestEnd = pszDest + iRet;
  4521. cchRemaining = cchDest - iRet;
  4522. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  4523. {
  4524. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
  4525. }
  4526. }
  4527. }
  4528. }
  4529. }
  4530. if (FAILED(hr))
  4531. {
  4532. if (pszDest)
  4533. {
  4534. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  4535. {
  4536. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  4537. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  4538. {
  4539. pszDestEnd = pszDest;
  4540. cchRemaining = cchDest;
  4541. }
  4542. else if (cchDest > 0)
  4543. {
  4544. pszDestEnd = pszDest + cchDest - 1;
  4545. cchRemaining = 1;
  4546. // null terminate the end of the string
  4547. *pszDestEnd = '\0';
  4548. }
  4549. }
  4550. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  4551. {
  4552. if (cchDest > 0)
  4553. {
  4554. pszDestEnd = pszDest;
  4555. cchRemaining = cchDest;
  4556. // null terminate the beginning of the string
  4557. *pszDestEnd = '\0';
  4558. }
  4559. }
  4560. }
  4561. }
  4562. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  4563. {
  4564. if (ppszDestEnd)
  4565. {
  4566. *ppszDestEnd = pszDestEnd;
  4567. }
  4568. if (pcchRemaining)
  4569. {
  4570. *pcchRemaining = cchRemaining;
  4571. }
  4572. }
  4573. return hr;
  4574. }
  4575. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  4576. STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList)
  4577. {
  4578. HRESULT hr = S_OK;
  4579. WCHAR* pszDestEnd = pszDest;
  4580. size_t cchRemaining = 0;
  4581. // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) ||
  4582. // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  4583. // only accept valid flags
  4584. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  4585. {
  4586. hr = STRSAFE_E_INVALID_PARAMETER;
  4587. }
  4588. else
  4589. {
  4590. if (dwFlags & STRSAFE_IGNORE_NULLS)
  4591. {
  4592. if (pszDest == NULL)
  4593. {
  4594. if ((cchDest != 0) || (cbDest != 0))
  4595. {
  4596. // NULL pszDest and non-zero cchDest/cbDest is invalid
  4597. hr = STRSAFE_E_INVALID_PARAMETER;
  4598. }
  4599. }
  4600. if (pszFormat == NULL)
  4601. {
  4602. pszFormat = u"";
  4603. }
  4604. }
  4605. if (SUCCEEDED(hr))
  4606. {
  4607. if (cchDest == 0)
  4608. {
  4609. pszDestEnd = pszDest;
  4610. cchRemaining = 0;
  4611. // only fail if there was actually a non-empty format string
  4612. if (*pszFormat != L'\0')
  4613. {
  4614. if (pszDest == NULL)
  4615. {
  4616. hr = STRSAFE_E_INVALID_PARAMETER;
  4617. }
  4618. else
  4619. {
  4620. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4621. }
  4622. }
  4623. }
  4624. else
  4625. {
  4626. int iRet;
  4627. size_t cchMax;
  4628. // leave the last space for the null terminator
  4629. cchMax = cchDest - 1;
  4630. iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
  4631. // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
  4632. if ((iRet < 0) || (((size_t)iRet) > cchMax))
  4633. {
  4634. // we have truncated pszDest
  4635. pszDestEnd = pszDest + cchMax;
  4636. cchRemaining = 1;
  4637. // need to null terminate the string
  4638. *pszDestEnd = L'\0';
  4639. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4640. }
  4641. else if (((size_t)iRet) == cchMax)
  4642. {
  4643. // string fit perfectly
  4644. pszDestEnd = pszDest + cchMax;
  4645. cchRemaining = 1;
  4646. // need to null terminate the string
  4647. *pszDestEnd = L'\0';
  4648. }
  4649. else if (((size_t)iRet) < cchMax)
  4650. {
  4651. // there is extra room
  4652. pszDestEnd = pszDest + iRet;
  4653. cchRemaining = cchDest - iRet;
  4654. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  4655. {
  4656. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  4657. }
  4658. }
  4659. }
  4660. }
  4661. }
  4662. if (FAILED(hr))
  4663. {
  4664. if (pszDest)
  4665. {
  4666. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  4667. {
  4668. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  4669. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  4670. {
  4671. pszDestEnd = pszDest;
  4672. cchRemaining = cchDest;
  4673. }
  4674. else if (cchDest > 0)
  4675. {
  4676. pszDestEnd = pszDest + cchDest - 1;
  4677. cchRemaining = 1;
  4678. // null terminate the end of the string
  4679. *pszDestEnd = L'\0';
  4680. }
  4681. }
  4682. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  4683. {
  4684. if (cchDest > 0)
  4685. {
  4686. pszDestEnd = pszDest;
  4687. cchRemaining = cchDest;
  4688. // null terminate the beginning of the string
  4689. *pszDestEnd = L'\0';
  4690. }
  4691. }
  4692. }
  4693. }
  4694. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  4695. {
  4696. if (ppszDestEnd)
  4697. {
  4698. *ppszDestEnd = pszDestEnd;
  4699. }
  4700. if (pcchRemaining)
  4701. {
  4702. *pcchRemaining = cchRemaining;
  4703. }
  4704. }
  4705. return hr;
  4706. }
  4707. #endif // FEATURE_PAL || !PLATFORM_UNIX
  4708. STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch)
  4709. {
  4710. HRESULT hr = S_OK;
  4711. size_t cchMaxPrev = cchMax;
  4712. while (cchMax && (*psz != '\0'))
  4713. {
  4714. psz++;
  4715. cchMax--;
  4716. }
  4717. if (cchMax == 0)
  4718. {
  4719. // the string is longer than cchMax
  4720. hr = STRSAFE_E_INVALID_PARAMETER;
  4721. }
  4722. if (SUCCEEDED(hr) && pcch)
  4723. {
  4724. *pcch = cchMaxPrev - cchMax;
  4725. }
  4726. return hr;
  4727. }
  4728. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  4729. STRSAFEAPI StringLengthWorkerW(const WCHAR* psz, size_t cchMax, size_t* pcch)
  4730. {
  4731. HRESULT hr = S_OK;
  4732. size_t cchMaxPrev = cchMax;
  4733. while (cchMax && (*psz != L'\0'))
  4734. {
  4735. psz++;
  4736. cchMax--;
  4737. }
  4738. if (cchMax == 0)
  4739. {
  4740. // the string is longer than cchMax
  4741. hr = STRSAFE_E_INVALID_PARAMETER;
  4742. }
  4743. if (SUCCEEDED(hr) && pcch)
  4744. {
  4745. *pcch = cchMaxPrev - cchMax;
  4746. }
  4747. return hr;
  4748. }
  4749. #endif // FEATURE_PAL || !PLATFORM_UNIX
  4750. #endif // STRSAFE_INLINE
  4751. #ifndef STRSAFE_LIB_IMPL
  4752. #ifndef FEATURE_PAL
  4753. STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  4754. {
  4755. HRESULT hr = S_OK;
  4756. char* pszDestEnd = pszDest;
  4757. size_t cchRemaining = 0;
  4758. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  4759. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  4760. // only accept valid flags
  4761. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  4762. {
  4763. hr = STRSAFE_E_INVALID_PARAMETER;
  4764. }
  4765. else
  4766. {
  4767. if (dwFlags & STRSAFE_IGNORE_NULLS)
  4768. {
  4769. if (pszDest == NULL)
  4770. {
  4771. if ((cchDest != 0) || (cbDest != 0))
  4772. {
  4773. // NULL pszDest and non-zero cchDest/cbDest is invalid
  4774. hr = STRSAFE_E_INVALID_PARAMETER;
  4775. }
  4776. }
  4777. }
  4778. if (SUCCEEDED(hr))
  4779. {
  4780. if (cchDest <= 1)
  4781. {
  4782. pszDestEnd = pszDest;
  4783. cchRemaining = cchDest;
  4784. if (cchDest == 1)
  4785. {
  4786. *pszDestEnd = '\0';
  4787. }
  4788. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4789. }
  4790. else
  4791. {
  4792. char ch;
  4793. pszDestEnd = pszDest;
  4794. cchRemaining = cchDest;
  4795. while ((cchRemaining > 1) && (ch = (char)getc(stdin)) != '\n')
  4796. {
  4797. if (ch == EOF)
  4798. {
  4799. if (pszDestEnd == pszDest)
  4800. {
  4801. // we failed to read anything from stdin
  4802. hr = STRSAFE_E_END_OF_FILE;
  4803. }
  4804. break;
  4805. }
  4806. *pszDestEnd = ch;
  4807. pszDestEnd++;
  4808. cchRemaining--;
  4809. }
  4810. if (cchRemaining > 0)
  4811. {
  4812. // there is extra room
  4813. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  4814. {
  4815. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
  4816. }
  4817. }
  4818. *pszDestEnd = '\0';
  4819. }
  4820. }
  4821. }
  4822. if (FAILED(hr))
  4823. {
  4824. if (pszDest)
  4825. {
  4826. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  4827. {
  4828. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  4829. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  4830. {
  4831. pszDestEnd = pszDest;
  4832. cchRemaining = cchDest;
  4833. }
  4834. else if (cchDest > 0)
  4835. {
  4836. pszDestEnd = pszDest + cchDest - 1;
  4837. cchRemaining = 1;
  4838. // null terminate the end of the string
  4839. *pszDestEnd = '\0';
  4840. }
  4841. }
  4842. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  4843. {
  4844. if (cchDest > 0)
  4845. {
  4846. pszDestEnd = pszDest;
  4847. cchRemaining = cchDest;
  4848. // null terminate the beginning of the string
  4849. *pszDestEnd = '\0';
  4850. }
  4851. }
  4852. }
  4853. }
  4854. if (SUCCEEDED(hr) ||
  4855. (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
  4856. (hr == STRSAFE_E_END_OF_FILE))
  4857. {
  4858. if (ppszDestEnd)
  4859. {
  4860. *ppszDestEnd = pszDestEnd;
  4861. }
  4862. if (pcchRemaining)
  4863. {
  4864. *pcchRemaining = cchRemaining;
  4865. }
  4866. }
  4867. return hr;
  4868. }
  4869. #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX)
  4870. STRSAFE_INLINE_API StringGetsExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  4871. {
  4872. HRESULT hr = S_OK;
  4873. WCHAR* pszDestEnd = pszDest;
  4874. size_t cchRemaining = 0;
  4875. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  4876. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  4877. // only accept valid flags
  4878. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  4879. {
  4880. hr = STRSAFE_E_INVALID_PARAMETER;
  4881. }
  4882. else
  4883. {
  4884. if (dwFlags & STRSAFE_IGNORE_NULLS)
  4885. {
  4886. if (pszDest == NULL)
  4887. {
  4888. if ((cchDest != 0) || (cbDest != 0))
  4889. {
  4890. // NULL pszDest and non-zero cchDest/cbDest is invalid
  4891. hr = STRSAFE_E_INVALID_PARAMETER;
  4892. }
  4893. }
  4894. }
  4895. if (SUCCEEDED(hr))
  4896. {
  4897. if (cchDest <= 1)
  4898. {
  4899. pszDestEnd = pszDest;
  4900. cchRemaining = cchDest;
  4901. if (cchDest == 1)
  4902. {
  4903. *pszDestEnd = L'\0';
  4904. }
  4905. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  4906. }
  4907. else
  4908. {
  4909. WCHAR ch;
  4910. pszDestEnd = pszDest;
  4911. cchRemaining = cchDest;
  4912. while ((cchRemaining > 1) && (ch = (WCHAR)getwc(stdin)) != L'\n')
  4913. {
  4914. if (ch == EOF)
  4915. {
  4916. if (pszDestEnd == pszDest)
  4917. {
  4918. // we failed to read anything from stdin
  4919. hr = STRSAFE_E_END_OF_FILE;
  4920. }
  4921. break;
  4922. }
  4923. *pszDestEnd = ch;
  4924. pszDestEnd++;
  4925. cchRemaining--;
  4926. }
  4927. if (cchRemaining > 0)
  4928. {
  4929. // there is extra room
  4930. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  4931. {
  4932. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)));
  4933. }
  4934. }
  4935. *pszDestEnd = L'\0';
  4936. }
  4937. }
  4938. }
  4939. if (FAILED(hr))
  4940. {
  4941. if (pszDest)
  4942. {
  4943. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  4944. {
  4945. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  4946. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  4947. {
  4948. pszDestEnd = pszDest;
  4949. cchRemaining = cchDest;
  4950. }
  4951. else if (cchDest > 0)
  4952. {
  4953. pszDestEnd = pszDest + cchDest - 1;
  4954. cchRemaining = 1;
  4955. // null terminate the end of the string
  4956. *pszDestEnd = L'\0';
  4957. }
  4958. }
  4959. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  4960. {
  4961. if (cchDest > 0)
  4962. {
  4963. pszDestEnd = pszDest;
  4964. cchRemaining = cchDest;
  4965. // null terminate the beginning of the string
  4966. *pszDestEnd = L'\0';
  4967. }
  4968. }
  4969. }
  4970. }
  4971. if (SUCCEEDED(hr) ||
  4972. (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
  4973. (hr == STRSAFE_E_END_OF_FILE))
  4974. {
  4975. if (ppszDestEnd)
  4976. {
  4977. *ppszDestEnd = pszDestEnd;
  4978. }
  4979. if (pcchRemaining)
  4980. {
  4981. *pcchRemaining = cchRemaining;
  4982. }
  4983. }
  4984. return hr;
  4985. }
  4986. #endif // FEATURE_PAL || !PLATFORM_UNIX
  4987. #endif // !FEATURE_PAL
  4988. #endif // !STRSAFE_LIB_IMPL
  4989. #endif // _STRSAFE_H_INCLUDED_