1
0

strsafe.h 210 KB

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