strsafe.h 150 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497
  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. #pragma once
  13. #ifdef _WIN32
  14. #include <strsafe.h>
  15. #else
  16. #pragma once
  17. #include <stdio.h> // for _vsnprintf, _vsnwprintf, getc, getwc
  18. #include <string.h> // for memset
  19. #include <stdarg.h> // for va_start, etc.
  20. #include <wchar.h>
  21. #include <stdint.h>
  22. #ifndef _HRESULT_DEFINED
  23. #define _HRESULT_DEFINED
  24. typedef long HRESULT;
  25. #endif // !_HRESULT_DEFINED
  26. #ifndef SUCCEEDED
  27. #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
  28. #endif
  29. #ifndef FAILED
  30. #define FAILED(hr) ((HRESULT)(hr) < 0)
  31. #endif
  32. #ifndef S_OK
  33. #define S_OK ((HRESULT)0x00000000L)
  34. #endif
  35. #ifdef __cplusplus
  36. #define _STRSAFE_EXTERN_C extern "C"
  37. #else
  38. #define _STRSAFE_EXTERN_C extern
  39. #endif
  40. // If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then
  41. // #define STRSAFE_LIB before including this header file.
  42. #ifndef _WIN32
  43. #define __inline inline
  44. #define __stdcall
  45. #endif
  46. #if defined(STRSAFE_LIB)
  47. #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall
  48. #pragma comment(lib, "./strsafe.lib")
  49. #elif defined(STRSAFE_LIB_IMPL)
  50. #define STRSAFEAPI _STRSAFE_EXTERN_C __declspec(dllexport) HRESULT __stdcall
  51. #else
  52. #define STRSAFEAPI __inline HRESULT __stdcall
  53. #define STRSAFE_INLINE
  54. #endif
  55. // Some functions always run inline because they use stdin and we want to avoid building multiple
  56. // versions of strsafe lib depending on if you use msvcrt, libcmt, etc.
  57. #define STRSAFE_INLINE_API __inline HRESULT __stdcall
  58. // The user can request no "Cb" or no "Cch" fuctions, but not both!
  59. #if defined(STRSAFE_NO_CB_FUNCTIONS) && defined(STRSAFE_NO_CCH_FUNCTIONS)
  60. #error cannot specify both STRSAFE_NO_CB_FUNCTIONS and STRSAFE_NO_CCH_FUNCTIONS !!
  61. #endif
  62. // This should only be defined when we are building strsafe.lib
  63. #ifdef STRSAFE_LIB_IMPL
  64. #define STRSAFE_INLINE
  65. #endif
  66. // If both strsafe.h and ntstrsafe.h are included, only use definitions from one.
  67. #ifndef _NTSTRSAFE_H_INCLUDED_
  68. #define STRSAFE_MAX_CCH 2147483647 // max # of characters we support (same as INT_MAX)
  69. // Flags for controling the Ex functions
  70. //
  71. // STRSAFE_FILL_BYTE(0xFF) 0x000000FF // bottom byte specifies fill pattern
  72. #define STRSAFE_IGNORE_NULLS 0x00000100 // treat null as TEXT("") -- don't fault on NULL buffers
  73. #define STRSAFE_FILL_BEHIND_NULL 0x00000200 // fill in extra space behind the null terminator
  74. #define STRSAFE_FILL_ON_FAILURE 0x00000400 // on failure, overwrite pszDest with fill pattern and null terminate it
  75. #define STRSAFE_NULL_ON_FAILURE 0x00000800 // on failure, set *pszDest = TEXT('\0')
  76. #define STRSAFE_NO_TRUNCATION 0x00001000 // instead of returning a truncated result, copy/append nothing to pszDest and null terminate it
  77. #define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)
  78. // helper macro to set the fill character and specify buffer filling
  79. #define STRSAFE_FILL_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL))
  80. #define STRSAFE_FAILURE_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_ON_FAILURE))
  81. #define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)(dwFlags & 0x000000FF))
  82. #endif // _NTSTRSAFE_H_INCLUDED_
  83. // STRSAFE error return codes
  84. //
  85. #define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER
  86. #define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) // 0x57 = 87L = ERROR_INVALID_PARAMETER
  87. #define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) // 0x26 = 38L = ERROR_HANDLE_EOF
  88. // prototypes for the worker functions
  89. #ifdef STRSAFE_INLINE
  90. STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc);
  91. STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  92. STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc);
  93. STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  94. STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc);
  95. STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  96. STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend);
  97. STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  98. STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList);
  99. STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
  100. STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch);
  101. #endif // STRSAFE_INLINE
  102. #ifndef STRSAFE_LIB_IMPL
  103. // these functions are always inline
  104. STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  105. #endif
  106. #ifdef _NTSTRSAFE_H_INCLUDED_
  107. #pragma warning(push)
  108. #pragma warning(disable : 4995)
  109. #endif // _NTSTRSAFE_H_INCLUDED_
  110. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  111. /*++
  112. STDAPI
  113. StringCchCopy(
  114. OUT LPTSTR pszDest,
  115. IN size_t cchDest,
  116. IN LPCTSTR pszSrc
  117. );
  118. Routine Description:
  119. This routine is a safer version of the C built-in function 'strcpy'.
  120. The size of the destination buffer (in characters) is a parameter and
  121. this function will not write past the end of this buffer and it will
  122. ALWAYS null terminate the destination buffer (unless it is zero length).
  123. This routine is not a replacement for strncpy. That function will pad the
  124. destination string with extra null termination characters if the count is
  125. greater than the length of the source string, and it will fail to null
  126. terminate the destination string if the source string length is greater
  127. than or equal to the count. You can not blindly use this instead of strncpy:
  128. it is common for code to use it to "patch" strings and you would introduce
  129. errors if the code started null terminating in the middle of the string.
  130. This function returns a hresult, and not a pointer. It returns
  131. S_OK if the string was copied without truncation and null terminated,
  132. otherwise it will return a failure code. In failure cases as much of
  133. pszSrc will be copied to pszDest as possible, and pszDest will be null
  134. terminated.
  135. Arguments:
  136. pszDest - destination string
  137. cchDest - size of destination buffer in characters.
  138. length must be = (_tcslen(src) + 1) to hold all of the
  139. source including the null terminator
  140. pszSrc - source string which must be null terminated
  141. Notes:
  142. Behavior is undefined if source and destination strings overlap.
  143. pszDest and pszSrc should not be NULL. See StringCchCopyEx if you require
  144. the handling of NULL values.
  145. Return Value:
  146. S_OK - if there was source data and it was all copied and the
  147. resultant dest string was null terminated
  148. failure - you can use the macro HRESULT_CODE() to get a win32
  149. error code for all hresult failure cases
  150. STRSAFE_E_INSUFFICIENT_BUFFER /
  151. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  152. - this return value is an indication that the copy
  153. operation failed due to insufficient space. When this
  154. error occurs, the destination buffer is modified to
  155. contain a truncated version of the ideal result and is
  156. null terminated. This is useful for situations where
  157. truncation is ok
  158. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  159. return value of this function.
  160. --*/
  161. STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc);
  162. #define StringCchCopy StringCchCopyA
  163. #ifdef STRSAFE_INLINE
  164. STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc)
  165. {
  166. HRESULT hr;
  167. if (cchDest > STRSAFE_MAX_CCH)
  168. {
  169. hr = STRSAFE_E_INVALID_PARAMETER;
  170. }
  171. else
  172. {
  173. hr = StringCopyWorkerA(pszDest, cchDest, pszSrc);
  174. }
  175. return hr;
  176. }
  177. #endif // STRSAFE_INLINE
  178. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  179. #ifndef STRSAFE_NO_CB_FUNCTIONS
  180. /*++
  181. STDAPI
  182. StringCbCopy(
  183. OUT LPTSTR pszDest,
  184. IN size_t cbDest,
  185. IN LPCTSTR pszSrc
  186. );
  187. Routine Description:
  188. This routine is a safer version of the C built-in function 'strcpy'.
  189. The size of the destination buffer (in bytes) is a parameter and this
  190. function will not write past the end of this buffer and it will ALWAYS
  191. null terminate the destination buffer (unless it is zero length).
  192. This routine is not a replacement for strncpy. That function will pad the
  193. destination string with extra null termination characters if the count is
  194. greater than the length of the source string, and it will fail to null
  195. terminate the destination string if the source string length is greater
  196. than or equal to the count. You can not blindly use this instead of strncpy:
  197. it is common for code to use it to "patch" strings and you would introduce
  198. errors if the code started null terminating in the middle of the string.
  199. This function returns a hresult, and not a pointer. It returns
  200. S_OK if the string was copied without truncation and null terminated,
  201. otherwise it will return a failure code. In failure cases as much of pszSrc
  202. will be copied to pszDest as possible, and pszDest will be null terminated.
  203. Arguments:
  204. pszDest - destination string
  205. cbDest - size of destination buffer in bytes.
  206. length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to
  207. hold all of the source including the null terminator
  208. pszSrc - source string which must be null terminated
  209. Notes:
  210. Behavior is undefined if source and destination strings overlap.
  211. pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require
  212. the handling of NULL values.
  213. Return Value:
  214. S_OK - if there was source data and it was all copied and the
  215. resultant dest string was null terminated
  216. failure - you can use the macro HRESULT_CODE() to get a win32
  217. error code for all hresult failure cases
  218. STRSAFE_E_INSUFFICIENT_BUFFER /
  219. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  220. - this return value is an indication that the copy
  221. operation failed due to insufficient space. When this
  222. error occurs, the destination buffer is modified to
  223. contain a truncated version of the ideal result and is
  224. null terminated. This is useful for situations where
  225. truncation is ok
  226. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  227. return value of this function.
  228. --*/
  229. STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc);
  230. #define StringCbCopy StringCbCopyA
  231. #ifdef STRSAFE_INLINE
  232. STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc)
  233. {
  234. HRESULT hr;
  235. size_t cchDest;
  236. // convert to count of characters
  237. cchDest = cbDest / sizeof(char);
  238. if (cchDest > STRSAFE_MAX_CCH)
  239. {
  240. hr = STRSAFE_E_INVALID_PARAMETER;
  241. }
  242. else
  243. {
  244. hr = StringCopyWorkerA(pszDest, cchDest, pszSrc);
  245. }
  246. return hr;
  247. }
  248. #endif // STRSAFE_INLINE
  249. #endif // !STRSAFE_NO_CB_FUNCTIONS
  250. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  251. /*++
  252. STDAPI
  253. StringCchCopyEx(
  254. OUT LPTSTR pszDest OPTIONAL,
  255. IN size_t cchDest,
  256. IN LPCTSTR pszSrc OPTIONAL,
  257. OUT LPTSTR* ppszDestEnd OPTIONAL,
  258. OUT size_t* pcchRemaining OPTIONAL,
  259. IN DWORD dwFlags
  260. );
  261. Routine Description:
  262. This routine is a safer version of the C built-in function 'strcpy' with
  263. some additional parameters. In addition to functionality provided by
  264. StringCchCopy, this routine also returns a pointer to the end of the
  265. destination string and the number of characters left in the destination string
  266. including the null terminator. The flags parameter allows additional controls.
  267. Arguments:
  268. pszDest - destination string
  269. cchDest - size of destination buffer in characters.
  270. length must be = (_tcslen(pszSrc) + 1) to hold all of
  271. the source including the null terminator
  272. pszSrc - source string which must be null terminated
  273. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  274. pointer to the end of the destination string. If the
  275. function copied any data, the result will point to the
  276. null termination character
  277. pcchRemaining - if pcchRemaining is non-null, the function will return the
  278. number of characters left in the destination string,
  279. including the null terminator
  280. dwFlags - controls some details of the string copy:
  281. STRSAFE_FILL_BEHIND_NULL
  282. if the function succeeds, the low byte of dwFlags will be
  283. used to fill the uninitialize part of destination buffer
  284. behind the null terminator
  285. STRSAFE_IGNORE_NULLS
  286. treat NULL string pointers like empty strings (TEXT("")).
  287. this flag is useful for emulating functions like lstrcpy
  288. STRSAFE_FILL_ON_FAILURE
  289. if the function fails, the low byte of dwFlags will be
  290. used to fill all of the destination buffer, and it will
  291. be null terminated. This will overwrite any truncated
  292. string returned when the failure is
  293. STRSAFE_E_INSUFFICIENT_BUFFER
  294. STRSAFE_NO_TRUNCATION /
  295. STRSAFE_NULL_ON_FAILURE
  296. if the function fails, the destination buffer will be set
  297. to the empty string. This will overwrite any truncated string
  298. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  299. Notes:
  300. Behavior is undefined if source and destination strings overlap.
  301. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  302. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  303. may be NULL. An error may still be returned even though NULLS are ignored
  304. due to insufficient space.
  305. Return Value:
  306. S_OK - if there was source data and it was all copied and the
  307. resultant dest string was null terminated
  308. failure - you can use the macro HRESULT_CODE() to get a win32
  309. error code for all hresult failure cases
  310. STRSAFE_E_INSUFFICIENT_BUFFER /
  311. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  312. - this return value is an indication that the copy
  313. operation failed due to insufficient space. When this
  314. error occurs, the destination buffer is modified to
  315. contain a truncated version of the ideal result and is
  316. null terminated. This is useful for situations where
  317. truncation is ok.
  318. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  319. return value of this function
  320. --*/
  321. STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  322. #define StringCchCopyEx StringCchCopyExA
  323. #ifdef STRSAFE_INLINE
  324. STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  325. {
  326. HRESULT hr;
  327. if (cchDest > STRSAFE_MAX_CCH)
  328. {
  329. hr = STRSAFE_E_INVALID_PARAMETER;
  330. }
  331. else
  332. {
  333. size_t cbDest;
  334. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  335. cbDest = cchDest * sizeof(char);
  336. hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
  337. }
  338. return hr;
  339. }
  340. #endif // STRSAFE_INLINE
  341. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  342. #ifndef STRSAFE_NO_CB_FUNCTIONS
  343. /*++
  344. STDAPI
  345. StringCbCopyEx(
  346. OUT LPTSTR pszDest OPTIONAL,
  347. IN size_t cbDest,
  348. IN LPCTSTR pszSrc OPTIONAL,
  349. OUT LPTSTR* ppszDestEnd OPTIONAL,
  350. OUT size_t* pcbRemaining OPTIONAL,
  351. IN DWORD dwFlags
  352. );
  353. Routine Description:
  354. This routine is a safer version of the C built-in function 'strcpy' with
  355. some additional parameters. In addition to functionality provided by
  356. StringCbCopy, this routine also returns a pointer to the end of the
  357. destination string and the number of bytes left in the destination string
  358. including the null terminator. The flags parameter allows additional controls.
  359. Arguments:
  360. pszDest - destination string
  361. cbDest - size of destination buffer in bytes.
  362. length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to
  363. hold all of the source including the null terminator
  364. pszSrc - source string which must be null terminated
  365. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  366. pointer to the end of the destination string. If the
  367. function copied any data, the result will point to the
  368. null termination character
  369. pcbRemaining - pcbRemaining is non-null,the function will return the
  370. number of bytes left in the destination string,
  371. including the null terminator
  372. dwFlags - controls some details of the string copy:
  373. STRSAFE_FILL_BEHIND_NULL
  374. if the function succeeds, the low byte of dwFlags will be
  375. used to fill the uninitialize part of destination buffer
  376. behind the null terminator
  377. STRSAFE_IGNORE_NULLS
  378. treat NULL string pointers like empty strings (TEXT("")).
  379. this flag is useful for emulating functions like lstrcpy
  380. STRSAFE_FILL_ON_FAILURE
  381. if the function fails, the low byte of dwFlags will be
  382. used to fill all of the destination buffer, and it will
  383. be null terminated. This will overwrite any truncated
  384. string returned when the failure is
  385. STRSAFE_E_INSUFFICIENT_BUFFER
  386. STRSAFE_NO_TRUNCATION /
  387. STRSAFE_NULL_ON_FAILURE
  388. if the function fails, the destination buffer will be set
  389. to the empty string. This will overwrite any truncated string
  390. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  391. Notes:
  392. Behavior is undefined if source and destination strings overlap.
  393. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  394. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  395. may be NULL. An error may still be returned even though NULLS are ignored
  396. due to insufficient space.
  397. Return Value:
  398. S_OK - if there was source data and it was all copied and the
  399. resultant dest string was null terminated
  400. failure - you can use the macro HRESULT_CODE() to get a win32
  401. error code for all hresult failure cases
  402. STRSAFE_E_INSUFFICIENT_BUFFER /
  403. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  404. - this return value is an indication that the copy
  405. operation failed due to insufficient space. When this
  406. error occurs, the destination buffer is modified to
  407. contain a truncated version of the ideal result and is
  408. null terminated. This is useful for situations where
  409. truncation is ok.
  410. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  411. return value of this function
  412. --*/
  413. STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  414. #define StringCbCopyEx StringCbCopyExA
  415. #ifdef STRSAFE_INLINE
  416. STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  417. {
  418. HRESULT hr;
  419. size_t cchDest;
  420. size_t cchRemaining = 0;
  421. cchDest = cbDest / sizeof(char);
  422. if (cchDest > STRSAFE_MAX_CCH)
  423. {
  424. hr = STRSAFE_E_INVALID_PARAMETER;
  425. }
  426. else
  427. {
  428. hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
  429. }
  430. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  431. {
  432. if (pcbRemaining)
  433. {
  434. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  435. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  436. }
  437. }
  438. return hr;
  439. }
  440. #endif // STRSAFE_INLINE
  441. #endif // !STRSAFE_NO_CB_FUNCTIONS
  442. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  443. /*++
  444. STDAPI
  445. StringCchCopyN(
  446. OUT LPTSTR pszDest,
  447. IN size_t cchDest,
  448. IN LPCTSTR pszSrc,
  449. IN size_t cchSrc
  450. );
  451. Routine Description:
  452. This routine is a safer version of the C built-in function 'strncpy'.
  453. The size of the destination buffer (in characters) is a parameter and
  454. this function will not write past the end of this buffer and it will
  455. ALWAYS null terminate the destination buffer (unless it is zero length).
  456. This routine is meant as a replacement for strncpy, but it does behave
  457. differently. This function will not pad the destination buffer with extra
  458. null termination characters if cchSrc is greater than the length of pszSrc.
  459. This function returns a hresult, and not a pointer. It returns
  460. S_OK if the entire string or the first cchSrc characters were copied
  461. without truncation and the resultant destination string was null terminated,
  462. otherwise it will return a failure code. In failure cases as much of pszSrc
  463. will be copied to pszDest as possible, and pszDest will be null terminated.
  464. Arguments:
  465. pszDest - destination string
  466. cchDest - size of destination buffer in characters.
  467. length must be = (_tcslen(src) + 1) to hold all of the
  468. source including the null terminator
  469. pszSrc - source string
  470. cchSrc - maximum number of characters to copy from source string,
  471. not including the null terminator.
  472. Notes:
  473. Behavior is undefined if source and destination strings overlap.
  474. pszDest and pszSrc should not be NULL. See StringCchCopyNEx if you require
  475. the handling of NULL values.
  476. Return Value:
  477. S_OK - if there was source data and it was all copied and the
  478. resultant dest string was null terminated
  479. failure - you can use the macro HRESULT_CODE() to get a win32
  480. error code for all hresult failure cases
  481. STRSAFE_E_INSUFFICIENT_BUFFER /
  482. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  483. - this return value is an indication that the copy
  484. operation failed due to insufficient space. When this
  485. error occurs, the destination buffer is modified to
  486. contain a truncated version of the ideal result and is
  487. null terminated. This is useful for situations where
  488. truncation is ok
  489. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  490. return value of this function.
  491. --*/
  492. STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc);
  493. #define StringCchCopyN StringCchCopyNA
  494. #ifdef STRSAFE_INLINE
  495. STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc)
  496. {
  497. HRESULT hr;
  498. if ((cchDest > STRSAFE_MAX_CCH) ||
  499. (cchSrc > STRSAFE_MAX_CCH))
  500. {
  501. hr = STRSAFE_E_INVALID_PARAMETER;
  502. }
  503. else
  504. {
  505. hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc);
  506. }
  507. return hr;
  508. }
  509. #endif // STRSAFE_INLINE
  510. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  511. #ifndef STRSAFE_NO_CB_FUNCTIONS
  512. /*++
  513. STDAPI
  514. StringCbCopyN(
  515. OUT LPTSTR pszDest,
  516. IN size_t cbDest,
  517. IN LPCTSTR pszSrc,
  518. IN size_t cbSrc
  519. );
  520. Routine Description:
  521. This routine is a safer version of the C built-in function 'strncpy'.
  522. The size of the destination buffer (in bytes) is a parameter and this
  523. function will not write past the end of this buffer and it will ALWAYS
  524. null terminate the destination buffer (unless it is zero length).
  525. This routine is meant as a replacement for strncpy, but it does behave
  526. differently. This function will not pad the destination buffer with extra
  527. null termination characters if cbSrc is greater than the size of pszSrc.
  528. This function returns a hresult, and not a pointer. It returns
  529. S_OK if the entire string or the first cbSrc characters were
  530. copied without truncation and the resultant destination string was null
  531. terminated, otherwise it will return a failure code. In failure cases as
  532. much of pszSrc will be copied to pszDest as possible, and pszDest will be
  533. null terminated.
  534. Arguments:
  535. pszDest - destination string
  536. cbDest - size of destination buffer in bytes.
  537. length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to
  538. hold all of the source including the null terminator
  539. pszSrc - source string
  540. cbSrc - maximum number of bytes to copy from source string,
  541. not including the null terminator.
  542. Notes:
  543. Behavior is undefined if source and destination strings overlap.
  544. pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require
  545. the handling of NULL values.
  546. Return Value:
  547. S_OK - if there was source data and it was all copied and the
  548. resultant dest string was null terminated
  549. failure - you can use the macro HRESULT_CODE() to get a win32
  550. error code for all hresult failure cases
  551. STRSAFE_E_INSUFFICIENT_BUFFER /
  552. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  553. - this return value is an indication that the copy
  554. operation failed due to insufficient space. When this
  555. error occurs, the destination buffer is modified to
  556. contain a truncated version of the ideal result and is
  557. null terminated. This is useful for situations where
  558. truncation is ok
  559. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  560. return value of this function.
  561. --*/
  562. STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc);
  563. #define StringCbCopyN StringCbCopyNA
  564. #ifdef STRSAFE_INLINE
  565. STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc)
  566. {
  567. HRESULT hr;
  568. size_t cchDest;
  569. size_t cchSrc;
  570. // convert to count of characters
  571. cchDest = cbDest / sizeof(char);
  572. cchSrc = cbSrc / sizeof(char);
  573. if ((cchDest > STRSAFE_MAX_CCH) ||
  574. (cchSrc > STRSAFE_MAX_CCH))
  575. {
  576. hr = STRSAFE_E_INVALID_PARAMETER;
  577. }
  578. else
  579. {
  580. hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc);
  581. }
  582. return hr;
  583. }
  584. #endif // STRSAFE_INLINE
  585. #endif // !STRSAFE_NO_CB_FUNCTIONS
  586. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  587. /*++
  588. STDAPI
  589. StringCchCopyNEx(
  590. OUT LPTSTR pszDest OPTIONAL,
  591. IN size_t cchDest,
  592. IN LPCTSTR pszSrc OPTIONAL,
  593. IN size_t cchSrc,
  594. OUT LPTSTR* ppszDestEnd OPTIONAL,
  595. OUT size_t* pcchRemaining OPTIONAL,
  596. IN DWORD dwFlags
  597. );
  598. Routine Description:
  599. This routine is a safer version of the C built-in function 'strncpy' with
  600. some additional parameters. In addition to functionality provided by
  601. StringCchCopyN, this routine also returns a pointer to the end of the
  602. destination string and the number of characters left in the destination
  603. string including the null terminator. The flags parameter allows
  604. additional controls.
  605. This routine is meant as a replacement for strncpy, but it does behave
  606. differently. This function will not pad the destination buffer with extra
  607. null termination characters if cchSrc is greater than the length of pszSrc.
  608. Arguments:
  609. pszDest - destination string
  610. cchDest - size of destination buffer in characters.
  611. length must be = (_tcslen(pszSrc) + 1) to hold all of
  612. the source including the null terminator
  613. pszSrc - source string
  614. cchSrc - maximum number of characters to copy from the source
  615. string
  616. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  617. pointer to the end of the destination string. If the
  618. function copied any data, the result will point to the
  619. null termination character
  620. pcchRemaining - if pcchRemaining is non-null, the function will return the
  621. number of characters left in the destination string,
  622. including the null terminator
  623. dwFlags - controls some details of the string copy:
  624. STRSAFE_FILL_BEHIND_NULL
  625. if the function succeeds, the low byte of dwFlags will be
  626. used to fill the uninitialize part of destination buffer
  627. behind the null terminator
  628. STRSAFE_IGNORE_NULLS
  629. treat NULL string pointers like empty strings (TEXT("")).
  630. this flag is useful for emulating functions like lstrcpy
  631. STRSAFE_FILL_ON_FAILURE
  632. if the function fails, the low byte of dwFlags will be
  633. used to fill all of the destination buffer, and it will
  634. be null terminated. This will overwrite any truncated
  635. string returned when the failure is
  636. STRSAFE_E_INSUFFICIENT_BUFFER
  637. STRSAFE_NO_TRUNCATION /
  638. STRSAFE_NULL_ON_FAILURE
  639. if the function fails, the destination buffer will be set
  640. to the empty string. This will overwrite any truncated string
  641. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  642. Notes:
  643. Behavior is undefined if source and destination strings overlap.
  644. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  645. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  646. may be NULL. An error may still be returned even though NULLS are ignored
  647. due to insufficient space.
  648. Return Value:
  649. S_OK - if there was source data and it was all copied and the
  650. resultant dest string was null terminated
  651. failure - you can use the macro HRESULT_CODE() to get a win32
  652. error code for all hresult failure cases
  653. STRSAFE_E_INSUFFICIENT_BUFFER /
  654. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  655. - this return value is an indication that the copy
  656. operation failed due to insufficient space. When this
  657. error occurs, the destination buffer is modified to
  658. contain a truncated version of the ideal result and is
  659. null terminated. This is useful for situations where
  660. truncation is ok.
  661. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  662. return value of this function
  663. --*/
  664. STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  665. #define StringCchCopyNEx StringCchCopyNExA
  666. #ifdef STRSAFE_INLINE
  667. STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  668. {
  669. HRESULT hr;
  670. if ((cchDest > STRSAFE_MAX_CCH) ||
  671. (cchSrc > STRSAFE_MAX_CCH))
  672. {
  673. hr = STRSAFE_E_INVALID_PARAMETER;
  674. }
  675. else
  676. {
  677. size_t cbDest;
  678. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  679. cbDest = cchDest * sizeof(char);
  680. hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags);
  681. }
  682. return hr;
  683. }
  684. #endif // STRSAFE_INLINE
  685. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  686. #ifndef STRSAFE_NO_CB_FUNCTIONS
  687. /*++
  688. STDAPI
  689. StringCbCopyNEx(
  690. OUT LPTSTR pszDest OPTIONAL,
  691. IN size_t cbDest,
  692. IN LPCTSTR pszSrc OPTIONAL,
  693. IN size_t cbSrc,
  694. OUT LPTSTR* ppszDestEnd OPTIONAL,
  695. OUT size_t* pcbRemaining OPTIONAL,
  696. IN DWORD dwFlags
  697. );
  698. Routine Description:
  699. This routine is a safer version of the C built-in function 'strncpy' with
  700. some additional parameters. In addition to functionality provided by
  701. StringCbCopyN, this routine also returns a pointer to the end of the
  702. destination string and the number of bytes left in the destination string
  703. including the null terminator. The flags parameter allows additional controls.
  704. This routine is meant as a replacement for strncpy, but it does behave
  705. differently. This function will not pad the destination buffer with extra
  706. null termination characters if cbSrc is greater than the size of pszSrc.
  707. Arguments:
  708. pszDest - destination string
  709. cbDest - size of destination buffer in bytes.
  710. length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to
  711. hold all of the source including the null terminator
  712. pszSrc - source string
  713. cbSrc - maximum number of bytes to copy from source string
  714. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  715. pointer to the end of the destination string. If the
  716. function copied any data, the result will point to the
  717. null termination character
  718. pcbRemaining - pcbRemaining is non-null,the function will return the
  719. number of bytes left in the destination string,
  720. including the null terminator
  721. dwFlags - controls some details of the string copy:
  722. STRSAFE_FILL_BEHIND_NULL
  723. if the function succeeds, the low byte of dwFlags will be
  724. used to fill the uninitialize part of destination buffer
  725. behind the null terminator
  726. STRSAFE_IGNORE_NULLS
  727. treat NULL string pointers like empty strings (TEXT("")).
  728. this flag is useful for emulating functions like lstrcpy
  729. STRSAFE_FILL_ON_FAILURE
  730. if the function fails, the low byte of dwFlags will be
  731. used to fill all of the destination buffer, and it will
  732. be null terminated. This will overwrite any truncated
  733. string returned when the failure is
  734. STRSAFE_E_INSUFFICIENT_BUFFER
  735. STRSAFE_NO_TRUNCATION /
  736. STRSAFE_NULL_ON_FAILURE
  737. if the function fails, the destination buffer will be set
  738. to the empty string. This will overwrite any truncated string
  739. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  740. Notes:
  741. Behavior is undefined if source and destination strings overlap.
  742. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  743. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  744. may be NULL. An error may still be returned even though NULLS are ignored
  745. due to insufficient space.
  746. Return Value:
  747. S_OK - if there was source data and it was all copied and the
  748. resultant dest string was null terminated
  749. failure - you can use the macro HRESULT_CODE() to get a win32
  750. error code for all hresult failure cases
  751. STRSAFE_E_INSUFFICIENT_BUFFER /
  752. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  753. - this return value is an indication that the copy
  754. operation failed due to insufficient space. When this
  755. error occurs, the destination buffer is modified to
  756. contain a truncated version of the ideal result and is
  757. null terminated. This is useful for situations where
  758. truncation is ok.
  759. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  760. return value of this function
  761. --*/
  762. STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  763. #define StringCbCopyNEx StringCbCopyNExA
  764. #ifdef STRSAFE_INLINE
  765. STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  766. {
  767. HRESULT hr;
  768. size_t cchDest;
  769. size_t cchSrc;
  770. size_t cchRemaining = 0;
  771. cchDest = cbDest / sizeof(char);
  772. cchSrc = cbSrc / sizeof(char);
  773. if ((cchDest > STRSAFE_MAX_CCH) ||
  774. (cchSrc > STRSAFE_MAX_CCH))
  775. {
  776. hr = STRSAFE_E_INVALID_PARAMETER;
  777. }
  778. else
  779. {
  780. hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags);
  781. }
  782. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  783. {
  784. if (pcbRemaining)
  785. {
  786. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  787. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  788. }
  789. }
  790. return hr;
  791. }
  792. #endif // STRSAFE_INLINE
  793. #endif // !STRSAFE_NO_CB_FUNCTIONS
  794. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  795. /*++
  796. STDAPI
  797. StringCchCat(
  798. IN OUT LPTSTR pszDest,
  799. IN size_t cchDest,
  800. IN LPCTSTR pszSrc
  801. );
  802. Routine Description:
  803. This routine is a safer version of the C built-in function 'strcat'.
  804. The size of the destination buffer (in characters) is a parameter and this
  805. function will not write past the end of this buffer and it will ALWAYS
  806. null terminate the destination buffer (unless it is zero length).
  807. This function returns a hresult, and not a pointer. It returns
  808. S_OK if the string was concatenated without truncation and null terminated,
  809. otherwise it will return a failure code. In failure cases as much of pszSrc
  810. will be appended to pszDest as possible, and pszDest will be null
  811. terminated.
  812. Arguments:
  813. pszDest - destination string which must be null terminated
  814. cchDest - size of destination buffer in characters.
  815. length must be = (_tcslen(pszDest) + _tcslen(pszSrc) + 1)
  816. to hold all of the combine string plus the null
  817. terminator
  818. pszSrc - source string which must be null terminated
  819. Notes:
  820. Behavior is undefined if source and destination strings overlap.
  821. pszDest and pszSrc should not be NULL. See StringCchCatEx if you require
  822. the handling of NULL values.
  823. Return Value:
  824. S_OK - if there was source data and it was all concatenated and
  825. the resultant dest string was null terminated
  826. failure - you can use the macro HRESULT_CODE() to get a win32
  827. error code for all hresult failure cases
  828. STRSAFE_E_INSUFFICIENT_BUFFER /
  829. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  830. - this return value is an indication that the operation
  831. failed due to insufficient space. When this error occurs,
  832. the destination buffer is modified to contain a truncated
  833. version of the ideal result and is null terminated. This
  834. is useful for situations where truncation is ok.
  835. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  836. return value of this function
  837. --*/
  838. STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc);
  839. #define StringCchCat StringCchCatA
  840. #ifdef STRSAFE_INLINE
  841. STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc)
  842. {
  843. HRESULT hr;
  844. if (cchDest > STRSAFE_MAX_CCH)
  845. {
  846. hr = STRSAFE_E_INVALID_PARAMETER;
  847. }
  848. else
  849. {
  850. hr = StringCatWorkerA(pszDest, cchDest, pszSrc);
  851. }
  852. return hr;
  853. }
  854. #endif // STRSAFE_INLINE
  855. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  856. #ifndef STRSAFE_NO_CB_FUNCTIONS
  857. /*++
  858. STDAPI
  859. StringCbCat(
  860. IN OUT LPTSTR pszDest,
  861. IN size_t cbDest,
  862. IN LPCTSTR pszSrc
  863. );
  864. Routine Description:
  865. This routine is a safer version of the C built-in function 'strcat'.
  866. The size of the destination buffer (in bytes) is a parameter and this
  867. function will not write past the end of this buffer and it will ALWAYS
  868. null terminate the destination buffer (unless it is zero length).
  869. This function returns a hresult, and not a pointer. It returns
  870. S_OK if the string was concatenated without truncation and null terminated,
  871. otherwise it will return a failure code. In failure cases as much of pszSrc
  872. will be appended to pszDest as possible, and pszDest will be null
  873. terminated.
  874. Arguments:
  875. pszDest - destination string which must be null terminated
  876. cbDest - size of destination buffer in bytes.
  877. length must be = ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR)
  878. to hold all of the combine string plus the null
  879. terminator
  880. pszSrc - source string which must be null terminated
  881. Notes:
  882. Behavior is undefined if source and destination strings overlap.
  883. pszDest and pszSrc should not be NULL. See StringCbCatEx if you require
  884. the handling of NULL values.
  885. Return Value:
  886. S_OK - if there was source data and it was all concatenated and
  887. the resultant dest string was null terminated
  888. failure - you can use the macro HRESULT_CODE() to get a win32
  889. error code for all hresult failure cases
  890. STRSAFE_E_INSUFFICIENT_BUFFER /
  891. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  892. - this return value is an indication that the operation
  893. failed due to insufficient space. When this error occurs,
  894. the destination buffer is modified to contain a truncated
  895. version of the ideal result and is null terminated. This
  896. is useful for situations where truncation is ok.
  897. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  898. return value of this function
  899. --*/
  900. STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc);
  901. #define StringCbCat StringCbCatA
  902. #ifdef STRSAFE_INLINE
  903. STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc)
  904. {
  905. HRESULT hr;
  906. size_t cchDest;
  907. cchDest = cbDest / sizeof(char);
  908. if (cchDest > STRSAFE_MAX_CCH)
  909. {
  910. hr = STRSAFE_E_INVALID_PARAMETER;
  911. }
  912. else
  913. {
  914. hr = StringCatWorkerA(pszDest, cchDest, pszSrc);
  915. }
  916. return hr;
  917. }
  918. #endif // STRSAFE_INLINE
  919. #endif // !STRSAFE_NO_CB_FUNCTIONS
  920. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  921. /*++
  922. STDAPI
  923. StringCchCatEx(
  924. IN OUT LPTSTR pszDest OPTIONAL,
  925. IN size_t cchDest,
  926. IN LPCTSTR pszSrc OPTIONAL,
  927. OUT LPTSTR* ppszDestEnd OPTIONAL,
  928. OUT size_t* pcchRemaining OPTIONAL,
  929. IN DWORD dwFlags
  930. );
  931. Routine Description:
  932. This routine is a safer version of the C built-in function 'strcat' with
  933. some additional parameters. In addition to functionality provided by
  934. StringCchCat, this routine also returns a pointer to the end of the
  935. destination string and the number of characters left in the destination string
  936. including the null terminator. The flags parameter allows additional controls.
  937. Arguments:
  938. pszDest - destination string which must be null terminated
  939. cchDest - size of destination buffer in characters
  940. length must be (_tcslen(pszDest) + _tcslen(pszSrc) + 1)
  941. to hold all of the combine string plus the null
  942. terminator.
  943. pszSrc - source string which must be null terminated
  944. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  945. pointer to the end of the destination string. If the
  946. function appended any data, the result will point to the
  947. null termination character
  948. pcchRemaining - if pcchRemaining is non-null, the function will return the
  949. number of characters left in the destination string,
  950. including the null terminator
  951. dwFlags - controls some details of the string copy:
  952. STRSAFE_FILL_BEHIND_NULL
  953. if the function succeeds, the low byte of dwFlags will be
  954. used to fill the uninitialize part of destination buffer
  955. behind the null terminator
  956. STRSAFE_IGNORE_NULLS
  957. treat NULL string pointers like empty strings (TEXT("")).
  958. this flag is useful for emulating functions like lstrcat
  959. STRSAFE_FILL_ON_FAILURE
  960. if the function fails, the low byte of dwFlags will be
  961. used to fill all of the destination buffer, and it will
  962. be null terminated. This will overwrite any pre-existing
  963. or truncated string
  964. STRSAFE_NULL_ON_FAILURE
  965. if the function fails, the destination buffer will be set
  966. to the empty string. This will overwrite any pre-existing or
  967. truncated string
  968. STRSAFE_NO_TRUNCATION
  969. if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
  970. will not contain a truncated string, it will remain unchanged.
  971. Notes:
  972. Behavior is undefined if source and destination strings overlap.
  973. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  974. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  975. may be NULL. An error may still be returned even though NULLS are ignored
  976. due to insufficient space.
  977. Return Value:
  978. S_OK - if there was source data and it was all concatenated and
  979. the resultant dest string was null terminated
  980. failure - you can use the macro HRESULT_CODE() to get a win32
  981. error code for all hresult failure cases
  982. STRSAFE_E_INSUFFICIENT_BUFFER /
  983. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  984. - this return value is an indication that the operation
  985. failed due to insufficient space. When this error
  986. occurs, the destination buffer is modified to contain
  987. a truncated version of the ideal result and is null
  988. terminated. This is useful for situations where
  989. truncation is ok.
  990. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  991. return value of this function
  992. --*/
  993. STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  994. #define StringCchCatEx StringCchCatExA
  995. #ifdef STRSAFE_INLINE
  996. STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  997. {
  998. HRESULT hr;
  999. if (cchDest > STRSAFE_MAX_CCH)
  1000. {
  1001. hr = STRSAFE_E_INVALID_PARAMETER;
  1002. }
  1003. else
  1004. {
  1005. size_t cbDest;
  1006. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  1007. cbDest = cchDest * sizeof(char);
  1008. hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
  1009. }
  1010. return hr;
  1011. }
  1012. #endif // STRSAFE_INLINE
  1013. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1014. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1015. /*++
  1016. STDAPI
  1017. StringCbCatEx(
  1018. IN OUT LPTSTR pszDest OPTIONAL,
  1019. IN size_t cbDest,
  1020. IN LPCTSTR pszSrc OPTIONAL,
  1021. OUT LPTSTR* ppszDestEnd OPTIONAL,
  1022. OUT size_t* pcbRemaining OPTIONAL,
  1023. IN DWORD dwFlags
  1024. );
  1025. Routine Description:
  1026. This routine is a safer version of the C built-in function 'strcat' with
  1027. some additional parameters. In addition to functionality provided by
  1028. StringCbCat, this routine also returns a pointer to the end of the
  1029. destination string and the number of bytes left in the destination string
  1030. including the null terminator. The flags parameter allows additional controls.
  1031. Arguments:
  1032. pszDest - destination string which must be null terminated
  1033. cbDest - size of destination buffer in bytes.
  1034. length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR)
  1035. to hold all of the combine string plus the null
  1036. terminator.
  1037. pszSrc - source string which must be null terminated
  1038. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1039. pointer to the end of the destination string. If the
  1040. function appended any data, the result will point to the
  1041. null termination character
  1042. pcbRemaining - if pcbRemaining is non-null, the function will return
  1043. the number of bytes left in the destination string,
  1044. including the null terminator
  1045. dwFlags - controls some details of the string copy:
  1046. STRSAFE_FILL_BEHIND_NULL
  1047. if the function succeeds, the low byte of dwFlags will be
  1048. used to fill the uninitialize part of destination buffer
  1049. behind the null terminator
  1050. STRSAFE_IGNORE_NULLS
  1051. treat NULL string pointers like empty strings (TEXT("")).
  1052. this flag is useful for emulating functions like lstrcat
  1053. STRSAFE_FILL_ON_FAILURE
  1054. if the function fails, the low byte of dwFlags will be
  1055. used to fill all of the destination buffer, and it will
  1056. be null terminated. This will overwrite any pre-existing
  1057. or truncated string
  1058. STRSAFE_NULL_ON_FAILURE
  1059. if the function fails, the destination buffer will be set
  1060. to the empty string. This will overwrite any pre-existing or
  1061. truncated string
  1062. STRSAFE_NO_TRUNCATION
  1063. if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
  1064. will not contain a truncated string, it will remain unchanged.
  1065. Notes:
  1066. Behavior is undefined if source and destination strings overlap.
  1067. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  1068. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  1069. may be NULL. An error may still be returned even though NULLS are ignored
  1070. due to insufficient space.
  1071. Return Value:
  1072. S_OK - if there was source data and it was all concatenated
  1073. and the resultant dest string was null terminated
  1074. failure - you can use the macro HRESULT_CODE() to get a win32
  1075. error code for all hresult failure cases
  1076. STRSAFE_E_INSUFFICIENT_BUFFER /
  1077. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1078. - this return value is an indication that the operation
  1079. failed due to insufficient space. When this error
  1080. occurs, the destination buffer is modified to contain
  1081. a truncated version of the ideal result and is null
  1082. terminated. This is useful for situations where
  1083. truncation is ok.
  1084. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1085. return value of this function
  1086. --*/
  1087. STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  1088. #define StringCbCatEx StringCbCatExA
  1089. #ifdef STRSAFE_INLINE
  1090. STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  1091. {
  1092. HRESULT hr;
  1093. size_t cchDest;
  1094. size_t cchRemaining = 0;
  1095. cchDest = cbDest / sizeof(char);
  1096. if (cchDest > STRSAFE_MAX_CCH)
  1097. {
  1098. hr = STRSAFE_E_INVALID_PARAMETER;
  1099. }
  1100. else
  1101. {
  1102. hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
  1103. }
  1104. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  1105. {
  1106. if (pcbRemaining)
  1107. {
  1108. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  1109. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  1110. }
  1111. }
  1112. return hr;
  1113. }
  1114. #endif // STRSAFE_INLINE
  1115. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1116. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1117. /*++
  1118. STDAPI
  1119. StringCchCatN(
  1120. IN OUT LPTSTR pszDest,
  1121. IN size_t cchDest,
  1122. IN LPCTSTR pszSrc,
  1123. IN size_t cchMaxAppend
  1124. );
  1125. Routine Description:
  1126. This routine is a safer version of the C built-in function 'strncat'.
  1127. The size of the destination buffer (in characters) is a parameter as well as
  1128. the maximum number of characters to append, excluding the null terminator.
  1129. This function will not write past the end of the destination buffer and it will
  1130. ALWAYS null terminate pszDest (unless it is zero length).
  1131. This function returns a hresult, and not a pointer. It returns
  1132. S_OK if all of pszSrc or the first cchMaxAppend characters were appended
  1133. to the destination string and it was null terminated, otherwise it will
  1134. return a failure code. In failure cases as much of pszSrc will be appended
  1135. to pszDest as possible, and pszDest will be null terminated.
  1136. Arguments:
  1137. pszDest - destination string which must be null terminated
  1138. cchDest - size of destination buffer in characters.
  1139. length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1)
  1140. to hold all of the combine string plus the null
  1141. terminator.
  1142. pszSrc - source string
  1143. cchMaxAppend - maximum number of characters to append
  1144. Notes:
  1145. Behavior is undefined if source and destination strings overlap.
  1146. pszDest and pszSrc should not be NULL. See StringCchCatNEx if you require
  1147. the handling of NULL values.
  1148. Return Value:
  1149. S_OK - if all of pszSrc or the first cchMaxAppend characters
  1150. were concatenated to pszDest and the resultant dest
  1151. string was null terminated
  1152. failure - you can use the macro HRESULT_CODE() to get a win32
  1153. error code for all hresult failure cases
  1154. STRSAFE_E_INSUFFICIENT_BUFFER /
  1155. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1156. - this return value is an indication that the operation
  1157. failed due to insufficient space. When this error
  1158. occurs, the destination buffer is modified to contain
  1159. a truncated version of the ideal result and is null
  1160. terminated. This is useful for situations where
  1161. truncation is ok.
  1162. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1163. return value of this function
  1164. --*/
  1165. STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend);
  1166. #define StringCchCatN StringCchCatNA
  1167. #ifdef STRSAFE_INLINE
  1168. STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend)
  1169. {
  1170. HRESULT hr;
  1171. if (cchDest > STRSAFE_MAX_CCH)
  1172. {
  1173. hr = STRSAFE_E_INVALID_PARAMETER;
  1174. }
  1175. else
  1176. {
  1177. hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend);
  1178. }
  1179. return hr;
  1180. }
  1181. #endif // STRSAFE_INLINE
  1182. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1183. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1184. /*++
  1185. STDAPI
  1186. StringCbCatN(
  1187. IN OUT LPTSTR pszDest,
  1188. IN size_t cbDest,
  1189. IN LPCTSTR pszSrc,
  1190. IN size_t cbMaxAppend
  1191. );
  1192. Routine Description:
  1193. This routine is a safer version of the C built-in function 'strncat'.
  1194. The size of the destination buffer (in bytes) is a parameter as well as
  1195. the maximum number of bytes to append, excluding the null terminator.
  1196. This function will not write past the end of the destination buffer and it will
  1197. ALWAYS null terminate pszDest (unless it is zero length).
  1198. This function returns a hresult, and not a pointer. It returns
  1199. S_OK if all of pszSrc or the first cbMaxAppend bytes were appended
  1200. to the destination string and it was null terminated, otherwise it will
  1201. return a failure code. In failure cases as much of pszSrc will be appended
  1202. to pszDest as possible, and pszDest will be null terminated.
  1203. Arguments:
  1204. pszDest - destination string which must be null terminated
  1205. cbDest - size of destination buffer in bytes.
  1206. length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR)
  1207. to hold all of the combine string plus the null
  1208. terminator.
  1209. pszSrc - source string
  1210. cbMaxAppend - maximum number of bytes to append
  1211. Notes:
  1212. Behavior is undefined if source and destination strings overlap.
  1213. pszDest and pszSrc should not be NULL. See StringCbCatNEx if you require
  1214. the handling of NULL values.
  1215. Return Value:
  1216. S_OK - if all of pszSrc or the first cbMaxAppend bytes were
  1217. concatenated to pszDest and the resultant dest string
  1218. was null terminated
  1219. failure - you can use the macro HRESULT_CODE() to get a win32
  1220. error code for all hresult failure cases
  1221. STRSAFE_E_INSUFFICIENT_BUFFER /
  1222. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1223. - this return value is an indication that the operation
  1224. failed due to insufficient space. When this error
  1225. occurs, the destination buffer is modified to contain
  1226. a truncated version of the ideal result and is null
  1227. terminated. This is useful for situations where
  1228. truncation is ok.
  1229. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1230. return value of this function
  1231. --*/
  1232. STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend);
  1233. #define StringCbCatN StringCbCatNA
  1234. #ifdef STRSAFE_INLINE
  1235. STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend)
  1236. {
  1237. HRESULT hr;
  1238. size_t cchDest;
  1239. cchDest = cbDest / sizeof(char);
  1240. if (cchDest > STRSAFE_MAX_CCH)
  1241. {
  1242. hr = STRSAFE_E_INVALID_PARAMETER;
  1243. }
  1244. else
  1245. {
  1246. size_t cchMaxAppend;
  1247. cchMaxAppend = cbMaxAppend / sizeof(char);
  1248. hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend);
  1249. }
  1250. return hr;
  1251. }
  1252. #endif // STRSAFE_INLINE
  1253. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1254. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1255. /*++
  1256. STDAPI
  1257. StringCchCatNEx(
  1258. IN OUT LPTSTR pszDest OPTIONAL,
  1259. IN size_t cchDest,
  1260. IN LPCTSTR pszSrc OPTIONAL,
  1261. IN size_t cchMaxAppend,
  1262. OUT LPTSTR* ppszDestEnd OPTIONAL,
  1263. OUT size_t* pcchRemaining OPTIONAL,
  1264. IN DWORD dwFlags
  1265. );
  1266. Routine Description:
  1267. This routine is a safer version of the C built-in function 'strncat', with
  1268. some additional parameters. In addition to functionality provided by
  1269. StringCchCatN, this routine also returns a pointer to the end of the
  1270. destination string and the number of characters left in the destination string
  1271. including the null terminator. The flags parameter allows additional controls.
  1272. Arguments:
  1273. pszDest - destination string which must be null terminated
  1274. cchDest - size of destination buffer in characters.
  1275. length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1)
  1276. to hold all of the combine string plus the null
  1277. terminator.
  1278. pszSrc - source string
  1279. cchMaxAppend - maximum number of characters to append
  1280. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1281. pointer to the end of the destination string. If the
  1282. function appended any data, the result will point to the
  1283. null termination character
  1284. pcchRemaining - if pcchRemaining is non-null, the function will return the
  1285. number of characters left in the destination string,
  1286. including the null terminator
  1287. dwFlags - controls some details of the string copy:
  1288. STRSAFE_FILL_BEHIND_NULL
  1289. if the function succeeds, the low byte of dwFlags will be
  1290. used to fill the uninitialize part of destination buffer
  1291. behind the null terminator
  1292. STRSAFE_IGNORE_NULLS
  1293. treat NULL string pointers like empty strings (TEXT(""))
  1294. STRSAFE_FILL_ON_FAILURE
  1295. if the function fails, the low byte of dwFlags will be
  1296. used to fill all of the destination buffer, and it will
  1297. be null terminated. This will overwrite any pre-existing
  1298. or truncated string
  1299. STRSAFE_NULL_ON_FAILURE
  1300. if the function fails, the destination buffer will be set
  1301. to the empty string. This will overwrite any pre-existing or
  1302. truncated string
  1303. STRSAFE_NO_TRUNCATION
  1304. if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
  1305. will not contain a truncated string, it will remain unchanged.
  1306. Notes:
  1307. Behavior is undefined if source and destination strings overlap.
  1308. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  1309. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  1310. may be NULL. An error may still be returned even though NULLS are ignored
  1311. due to insufficient space.
  1312. Return Value:
  1313. S_OK - if all of pszSrc or the first cchMaxAppend characters
  1314. were concatenated to pszDest and the resultant dest
  1315. string was null terminated
  1316. failure - you can use the macro HRESULT_CODE() to get a win32
  1317. error code for all hresult failure cases
  1318. STRSAFE_E_INSUFFICIENT_BUFFER /
  1319. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1320. - this return value is an indication that the operation
  1321. failed due to insufficient space. When this error
  1322. occurs, the destination buffer is modified to contain
  1323. a truncated version of the ideal result and is null
  1324. terminated. This is useful for situations where
  1325. truncation is ok.
  1326. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1327. return value of this function
  1328. --*/
  1329. STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  1330. #define StringCchCatNEx StringCchCatNExA
  1331. #ifdef STRSAFE_INLINE
  1332. STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  1333. {
  1334. HRESULT hr;
  1335. if (cchDest > STRSAFE_MAX_CCH)
  1336. {
  1337. hr = STRSAFE_E_INVALID_PARAMETER;
  1338. }
  1339. else
  1340. {
  1341. size_t cbDest;
  1342. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  1343. cbDest = cchDest * sizeof(char);
  1344. hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags);
  1345. }
  1346. return hr;
  1347. }
  1348. #endif // STRSAFE_INLINE
  1349. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1350. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1351. /*++
  1352. STDAPI
  1353. StringCbCatNEx(
  1354. IN OUT LPTSTR pszDest OPTIONAL,
  1355. IN size_t cbDest,
  1356. IN LPCTSTR pszSrc OPTIONAL,
  1357. IN size_t cbMaxAppend,
  1358. OUT LPTSTR* ppszDestEnd OPTIONAL,
  1359. OUT size_t* pcchRemaining OPTIONAL,
  1360. IN DWORD dwFlags
  1361. );
  1362. Routine Description:
  1363. This routine is a safer version of the C built-in function 'strncat', with
  1364. some additional parameters. In addition to functionality provided by
  1365. StringCbCatN, this routine also returns a pointer to the end of the
  1366. destination string and the number of bytes left in the destination string
  1367. including the null terminator. The flags parameter allows additional controls.
  1368. Arguments:
  1369. pszDest - destination string which must be null terminated
  1370. cbDest - size of destination buffer in bytes.
  1371. length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR)
  1372. to hold all of the combine string plus the null
  1373. terminator.
  1374. pszSrc - source string
  1375. cbMaxAppend - maximum number of bytes to append
  1376. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1377. pointer to the end of the destination string. If the
  1378. function appended any data, the result will point to the
  1379. null termination character
  1380. pcbRemaining - if pcbRemaining is non-null, the function will return the
  1381. number of bytes left in the destination string,
  1382. including the null terminator
  1383. dwFlags - controls some details of the string copy:
  1384. STRSAFE_FILL_BEHIND_NULL
  1385. if the function succeeds, the low byte of dwFlags will be
  1386. used to fill the uninitialize part of destination buffer
  1387. behind the null terminator
  1388. STRSAFE_IGNORE_NULLS
  1389. treat NULL string pointers like empty strings (TEXT(""))
  1390. STRSAFE_FILL_ON_FAILURE
  1391. if the function fails, the low byte of dwFlags will be
  1392. used to fill all of the destination buffer, and it will
  1393. be null terminated. This will overwrite any pre-existing
  1394. or truncated string
  1395. STRSAFE_NULL_ON_FAILURE
  1396. if the function fails, the destination buffer will be set
  1397. to the empty string. This will overwrite any pre-existing or
  1398. truncated string
  1399. STRSAFE_NO_TRUNCATION
  1400. if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest
  1401. will not contain a truncated string, it will remain unchanged.
  1402. Notes:
  1403. Behavior is undefined if source and destination strings overlap.
  1404. pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag
  1405. is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc
  1406. may be NULL. An error may still be returned even though NULLS are ignored
  1407. due to insufficient space.
  1408. Return Value:
  1409. S_OK - if all of pszSrc or the first cbMaxAppend bytes were
  1410. concatenated to pszDest and the resultant dest string
  1411. was null terminated
  1412. failure - you can use the macro HRESULT_CODE() to get a win32
  1413. error code for all hresult failure cases
  1414. STRSAFE_E_INSUFFICIENT_BUFFER /
  1415. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1416. - this return value is an indication that the operation
  1417. failed due to insufficient space. When this error
  1418. occurs, the destination buffer is modified to contain
  1419. a truncated version of the ideal result and is null
  1420. terminated. This is useful for situations where
  1421. truncation is ok.
  1422. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1423. return value of this function
  1424. --*/
  1425. STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags);
  1426. #define StringCbCatNEx StringCbCatNExA
  1427. #ifdef STRSAFE_INLINE
  1428. STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  1429. {
  1430. HRESULT hr;
  1431. size_t cchDest;
  1432. size_t cchRemaining = 0;
  1433. cchDest = cbDest / sizeof(char);
  1434. if (cchDest > STRSAFE_MAX_CCH)
  1435. {
  1436. hr = STRSAFE_E_INVALID_PARAMETER;
  1437. }
  1438. else
  1439. {
  1440. size_t cchMaxAppend;
  1441. cchMaxAppend = cbMaxAppend / sizeof(char);
  1442. hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags);
  1443. }
  1444. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  1445. {
  1446. if (pcbRemaining)
  1447. {
  1448. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  1449. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  1450. }
  1451. }
  1452. return hr;
  1453. }
  1454. #endif // STRSAFE_INLINE
  1455. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1456. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1457. /*++
  1458. STDAPI
  1459. StringCchVPrintf(
  1460. OUT LPTSTR pszDest,
  1461. IN size_t cchDest,
  1462. IN LPCTSTR pszFormat,
  1463. IN va_list argList
  1464. );
  1465. Routine Description:
  1466. This routine is a safer version of the C built-in function 'vsprintf'.
  1467. The size of the destination buffer (in characters) is a parameter and
  1468. this function will not write past the end of this buffer and it will
  1469. ALWAYS null terminate the destination buffer (unless it is zero length).
  1470. This function returns a hresult, and not a pointer. It returns
  1471. S_OK if the string was printed without truncation and null terminated,
  1472. otherwise it will return a failure code. In failure cases it will return
  1473. a truncated version of the ideal result.
  1474. Arguments:
  1475. pszDest - destination string
  1476. cchDest - size of destination buffer in characters
  1477. length must be sufficient to hold the resulting formatted
  1478. string, including the null terminator.
  1479. pszFormat - format string which must be null terminated
  1480. argList - va_list from the variable arguments according to the
  1481. stdarg.h convention
  1482. Notes:
  1483. Behavior is undefined if destination, format strings or any arguments
  1484. strings overlap.
  1485. pszDest and pszFormat should not be NULL. See StringCchVPrintfEx if you
  1486. require the handling of NULL values.
  1487. Return Value:
  1488. S_OK - if there was sufficient space in the dest buffer for
  1489. the resultant string and it was null terminated.
  1490. failure - you can use the macro HRESULT_CODE() to get a win32
  1491. error code for all hresult failure cases
  1492. STRSAFE_E_INSUFFICIENT_BUFFER /
  1493. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1494. - this return value is an indication that the print
  1495. operation failed due to insufficient space. When this
  1496. error occurs, the destination buffer is modified to
  1497. contain a truncated version of the ideal result and is
  1498. null terminated. This is useful for situations where
  1499. truncation is ok.
  1500. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1501. return value of this function
  1502. --*/
  1503. STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList);
  1504. #define StringCchVPrintf StringCchVPrintfA
  1505. #ifdef STRSAFE_INLINE
  1506. STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList)
  1507. {
  1508. HRESULT hr;
  1509. if (cchDest > STRSAFE_MAX_CCH)
  1510. {
  1511. hr = STRSAFE_E_INVALID_PARAMETER;
  1512. }
  1513. else
  1514. {
  1515. hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
  1516. }
  1517. return hr;
  1518. }
  1519. #endif // STRSAFE_INLINE
  1520. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1521. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1522. /*++
  1523. STDAPI
  1524. StringCbVPrintf(
  1525. OUT LPTSTR pszDest,
  1526. IN size_t cbDest,
  1527. IN LPCTSTR pszFormat,
  1528. IN va_list argList
  1529. );
  1530. Routine Description:
  1531. This routine is a safer version of the C built-in function 'vsprintf'.
  1532. The size of the destination buffer (in bytes) is a parameter and
  1533. this function will not write past the end of this buffer and it will
  1534. ALWAYS null terminate the destination buffer (unless it is zero length).
  1535. This function returns a hresult, and not a pointer. It returns
  1536. S_OK if the string was printed without truncation and null terminated,
  1537. otherwise it will return a failure code. In failure cases it will return
  1538. a truncated version of the ideal result.
  1539. Arguments:
  1540. pszDest - destination string
  1541. cbDest - size of destination buffer in bytes
  1542. length must be sufficient to hold the resulting formatted
  1543. string, including the null terminator.
  1544. pszFormat - format string which must be null terminated
  1545. argList - va_list from the variable arguments according to the
  1546. stdarg.h convention
  1547. Notes:
  1548. Behavior is undefined if destination, format strings or any arguments
  1549. strings overlap.
  1550. pszDest and pszFormat should not be NULL. See StringCbVPrintfEx if you
  1551. require the handling of NULL values.
  1552. Return Value:
  1553. S_OK - if there was sufficient space in the dest buffer for
  1554. the resultant string and it was null terminated.
  1555. failure - you can use the macro HRESULT_CODE() to get a win32
  1556. error code for all hresult failure cases
  1557. STRSAFE_E_INSUFFICIENT_BUFFER /
  1558. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1559. - this return value is an indication that the print
  1560. operation failed due to insufficient space. When this
  1561. error occurs, the destination buffer is modified to
  1562. contain a truncated version of the ideal result and is
  1563. null terminated. This is useful for situations where
  1564. truncation is ok.
  1565. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1566. return value of this function
  1567. --*/
  1568. STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList);
  1569. #define StringCbVPrintf StringCbVPrintfA
  1570. #ifdef STRSAFE_INLINE
  1571. STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList)
  1572. {
  1573. HRESULT hr;
  1574. size_t cchDest;
  1575. cchDest = cbDest / sizeof(char);
  1576. if (cchDest > STRSAFE_MAX_CCH)
  1577. {
  1578. hr = STRSAFE_E_INVALID_PARAMETER;
  1579. }
  1580. else
  1581. {
  1582. hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
  1583. }
  1584. return hr;
  1585. }
  1586. #endif // STRSAFE_INLINE
  1587. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1588. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1589. /*++
  1590. STDAPI
  1591. StringCchPrintf(
  1592. OUT LPTSTR pszDest,
  1593. IN size_t cchDest,
  1594. IN LPCTSTR pszFormat,
  1595. ...
  1596. );
  1597. Routine Description:
  1598. This routine is a safer version of the C built-in function 'sprintf'.
  1599. The size of the destination buffer (in characters) is a parameter and
  1600. this function will not write past the end of this buffer and it will
  1601. ALWAYS null terminate the destination buffer (unless it is zero length).
  1602. This function returns a hresult, and not a pointer. It returns
  1603. S_OK if the string was printed without truncation and null terminated,
  1604. otherwise it will return a failure code. In failure cases it will return
  1605. a truncated version of the ideal result.
  1606. Arguments:
  1607. pszDest - destination string
  1608. cchDest - size of destination buffer in characters
  1609. length must be sufficient to hold the resulting formatted
  1610. string, including the null terminator.
  1611. pszFormat - format string which must be null terminated
  1612. ... - additional parameters to be formatted according to
  1613. the format string
  1614. Notes:
  1615. Behavior is undefined if destination, format strings or any arguments
  1616. strings overlap.
  1617. pszDest and pszFormat should not be NULL. See StringCchPrintfEx if you
  1618. require the handling of NULL values.
  1619. Return Value:
  1620. S_OK - if there was sufficient space in the dest buffer for
  1621. the resultant string and it was null terminated.
  1622. failure - you can use the macro HRESULT_CODE() to get a win32
  1623. error code for all hresult failure cases
  1624. STRSAFE_E_INSUFFICIENT_BUFFER /
  1625. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1626. - this return value is an indication that the print
  1627. operation failed due to insufficient space. When this
  1628. error occurs, the destination buffer is modified to
  1629. contain a truncated version of the ideal result and is
  1630. null terminated. This is useful for situations where
  1631. truncation is ok.
  1632. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1633. return value of this function
  1634. --*/
  1635. STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...);
  1636. #define StringCchPrintf StringCchPrintfA
  1637. #ifdef STRSAFE_INLINE
  1638. STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...)
  1639. {
  1640. HRESULT hr;
  1641. if (cchDest > STRSAFE_MAX_CCH)
  1642. {
  1643. hr = STRSAFE_E_INVALID_PARAMETER;
  1644. }
  1645. else
  1646. {
  1647. va_list argList;
  1648. va_start(argList, pszFormat);
  1649. hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
  1650. va_end(argList);
  1651. }
  1652. return hr;
  1653. }
  1654. #endif // STRSAFE_INLINE
  1655. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1656. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1657. /*++
  1658. STDAPI
  1659. StringCbPrintf(
  1660. OUT LPTSTR pszDest,
  1661. IN size_t cbDest,
  1662. IN LPCTSTR pszFormat,
  1663. ...
  1664. );
  1665. Routine Description:
  1666. This routine is a safer version of the C built-in function 'sprintf'.
  1667. The size of the destination buffer (in bytes) is a parameter and
  1668. this function will not write past the end of this buffer and it will
  1669. ALWAYS null terminate the destination buffer (unless it is zero length).
  1670. This function returns a hresult, and not a pointer. It returns
  1671. S_OK if the string was printed without truncation and null terminated,
  1672. otherwise it will return a failure code. In failure cases it will return
  1673. a truncated version of the ideal result.
  1674. Arguments:
  1675. pszDest - destination string
  1676. cbDest - size of destination buffer in bytes
  1677. length must be sufficient to hold the resulting formatted
  1678. string, including the null terminator.
  1679. pszFormat - format string which must be null terminated
  1680. ... - additional parameters to be formatted according to
  1681. the format string
  1682. Notes:
  1683. Behavior is undefined if destination, format strings or any arguments
  1684. strings overlap.
  1685. pszDest and pszFormat should not be NULL. See StringCbPrintfEx if you
  1686. require the handling of NULL values.
  1687. Return Value:
  1688. S_OK - if there was sufficient space in the dest buffer for
  1689. the resultant string and it was null terminated.
  1690. failure - you can use the macro HRESULT_CODE() to get a win32
  1691. error code for all hresult failure cases
  1692. STRSAFE_E_INSUFFICIENT_BUFFER /
  1693. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1694. - this return value is an indication that the print
  1695. operation failed due to insufficient space. When this
  1696. error occurs, the destination buffer is modified to
  1697. contain a truncated version of the ideal result and is
  1698. null terminated. This is useful for situations where
  1699. truncation is ok.
  1700. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1701. return value of this function
  1702. --*/
  1703. STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...);
  1704. #define StringCbPrintf StringCbPrintfA
  1705. #ifdef STRSAFE_INLINE
  1706. STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...)
  1707. {
  1708. HRESULT hr;
  1709. size_t cchDest;
  1710. cchDest = cbDest / sizeof(char);
  1711. if (cchDest > STRSAFE_MAX_CCH)
  1712. {
  1713. hr = STRSAFE_E_INVALID_PARAMETER;
  1714. }
  1715. else
  1716. {
  1717. va_list argList;
  1718. va_start(argList, pszFormat);
  1719. hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
  1720. va_end(argList);
  1721. }
  1722. return hr;
  1723. }
  1724. #endif // STRSAFE_INLINE
  1725. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1726. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1727. /*++
  1728. STDAPI
  1729. StringCchPrintfEx(
  1730. OUT LPTSTR pszDest OPTIONAL,
  1731. IN size_t cchDest,
  1732. OUT LPTSTR* ppszDestEnd OPTIONAL,
  1733. OUT size_t* pcchRemaining OPTIONAL,
  1734. IN DWORD dwFlags,
  1735. IN LPCTSTR pszFormat OPTIONAL,
  1736. ...
  1737. );
  1738. Routine Description:
  1739. This routine is a safer version of the C built-in function 'sprintf' with
  1740. some additional parameters. In addition to functionality provided by
  1741. StringCchPrintf, this routine also returns a pointer to the end of the
  1742. destination string and the number of characters left in the destination string
  1743. including the null terminator. The flags parameter allows additional controls.
  1744. Arguments:
  1745. pszDest - destination string
  1746. cchDest - size of destination buffer in characters.
  1747. length must be sufficient to contain the resulting
  1748. formatted string plus the null terminator.
  1749. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1750. pointer to the end of the destination string. If the
  1751. function printed any data, the result will point to the
  1752. null termination character
  1753. pcchRemaining - if pcchRemaining is non-null, the function will return
  1754. the number of characters left in the destination string,
  1755. including the null terminator
  1756. dwFlags - controls some details of the string copy:
  1757. STRSAFE_FILL_BEHIND_NULL
  1758. if the function succeeds, the low byte of dwFlags will be
  1759. used to fill the uninitialize part of destination buffer
  1760. behind the null terminator
  1761. STRSAFE_IGNORE_NULLS
  1762. treat NULL string pointers like empty strings (TEXT(""))
  1763. STRSAFE_FILL_ON_FAILURE
  1764. if the function fails, the low byte of dwFlags will be
  1765. used to fill all of the destination buffer, and it will
  1766. be null terminated. This will overwrite any truncated
  1767. string returned when the failure is
  1768. STRSAFE_E_INSUFFICIENT_BUFFER
  1769. STRSAFE_NO_TRUNCATION /
  1770. STRSAFE_NULL_ON_FAILURE
  1771. if the function fails, the destination buffer will be set
  1772. to the empty string. This will overwrite any truncated string
  1773. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  1774. pszFormat - format string which must be null terminated
  1775. ... - additional parameters to be formatted according to
  1776. the format string
  1777. Notes:
  1778. Behavior is undefined if destination, format strings or any arguments
  1779. strings overlap.
  1780. pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
  1781. flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and
  1782. pszFormat may be NULL. An error may still be returned even though NULLS
  1783. are ignored due to insufficient space.
  1784. Return Value:
  1785. S_OK - if there was source data and it was all concatenated and
  1786. the resultant dest string was null terminated
  1787. failure - you can use the macro HRESULT_CODE() to get a win32
  1788. error code for all hresult failure cases
  1789. STRSAFE_E_INSUFFICIENT_BUFFER /
  1790. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1791. - this return value is an indication that the print
  1792. operation failed due to insufficient space. When this
  1793. error occurs, the destination buffer is modified to
  1794. contain a truncated version of the ideal result and is
  1795. null terminated. This is useful for situations where
  1796. truncation is ok.
  1797. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  1798. return value of this function
  1799. --*/
  1800. STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...);
  1801. #define StringCchPrintfEx StringCchPrintfExA
  1802. #ifdef STRSAFE_INLINE
  1803. STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...)
  1804. {
  1805. HRESULT hr;
  1806. if (cchDest > STRSAFE_MAX_CCH)
  1807. {
  1808. hr = STRSAFE_E_INVALID_PARAMETER;
  1809. }
  1810. else
  1811. {
  1812. size_t cbDest;
  1813. va_list argList;
  1814. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  1815. cbDest = cchDest * sizeof(char);
  1816. va_start(argList, pszFormat);
  1817. hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
  1818. va_end(argList);
  1819. }
  1820. return hr;
  1821. }
  1822. #endif // STRSAFE_INLINE
  1823. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  1824. #ifndef STRSAFE_NO_CB_FUNCTIONS
  1825. /*++
  1826. STDAPI
  1827. StringCbPrintfEx(
  1828. OUT LPTSTR pszDest OPTIONAL,
  1829. IN size_t cbDest,
  1830. OUT LPTSTR* ppszDestEnd OPTIONAL,
  1831. OUT size_t* pcbRemaining OPTIONAL,
  1832. IN DWORD dwFlags,
  1833. IN LPCTSTR pszFormat OPTIONAL,
  1834. ...
  1835. );
  1836. Routine Description:
  1837. This routine is a safer version of the C built-in function 'sprintf' with
  1838. some additional parameters. In addition to functionality provided by
  1839. StringCbPrintf, this routine also returns a pointer to the end of the
  1840. destination string and the number of bytes left in the destination string
  1841. including the null terminator. The flags parameter allows additional controls.
  1842. Arguments:
  1843. pszDest - destination string
  1844. cbDest - size of destination buffer in bytes.
  1845. length must be sufficient to contain the resulting
  1846. formatted string plus the null terminator.
  1847. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1848. pointer to the end of the destination string. If the
  1849. function printed any data, the result will point to the
  1850. null termination character
  1851. pcbRemaining - if pcbRemaining is non-null, the function will return
  1852. the number of bytes left in the destination string,
  1853. including the null terminator
  1854. dwFlags - controls some details of the string copy:
  1855. STRSAFE_FILL_BEHIND_NULL
  1856. if the function succeeds, the low byte of dwFlags will be
  1857. used to fill the uninitialize part of destination buffer
  1858. behind the null terminator
  1859. STRSAFE_IGNORE_NULLS
  1860. treat NULL string pointers like empty strings (TEXT(""))
  1861. STRSAFE_FILL_ON_FAILURE
  1862. if the function fails, the low byte of dwFlags will be
  1863. used to fill all of the destination buffer, and it will
  1864. be null terminated. This will overwrite any truncated
  1865. string returned when the failure is
  1866. STRSAFE_E_INSUFFICIENT_BUFFER
  1867. STRSAFE_NO_TRUNCATION /
  1868. STRSAFE_NULL_ON_FAILURE
  1869. if the function fails, the destination buffer will be set
  1870. to the empty string. This will overwrite any truncated string
  1871. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  1872. pszFormat - format string which must be null terminated
  1873. ... - additional parameters to be formatted according to
  1874. the format string
  1875. Notes:
  1876. Behavior is undefined if destination, format strings or any arguments
  1877. strings overlap.
  1878. pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
  1879. flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and
  1880. pszFormat may be NULL. An error may still be returned even though NULLS
  1881. are ignored due to insufficient space.
  1882. Return Value:
  1883. S_OK - if there was source data and it was all concatenated and
  1884. the resultant dest string 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 StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...);
  1899. #define StringCbPrintfEx StringCbPrintfExA
  1900. #ifdef STRSAFE_INLINE
  1901. STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...)
  1902. {
  1903. HRESULT hr;
  1904. size_t cchDest;
  1905. size_t cchRemaining = 0;
  1906. cchDest = cbDest / sizeof(char);
  1907. if (cchDest > STRSAFE_MAX_CCH)
  1908. {
  1909. hr = STRSAFE_E_INVALID_PARAMETER;
  1910. }
  1911. else
  1912. {
  1913. va_list argList;
  1914. va_start(argList, pszFormat);
  1915. hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
  1916. va_end(argList);
  1917. }
  1918. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  1919. {
  1920. if (pcbRemaining)
  1921. {
  1922. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  1923. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  1924. }
  1925. }
  1926. return hr;
  1927. }
  1928. #endif // STRSAFE_INLINE
  1929. #endif // !STRSAFE_NO_CB_FUNCTIONS
  1930. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  1931. /*++
  1932. STDAPI
  1933. StringCchVPrintfEx(
  1934. OUT LPTSTR pszDest OPTIONAL,
  1935. IN size_t cchDest,
  1936. OUT LPTSTR* ppszDestEnd OPTIONAL,
  1937. OUT size_t* pcchRemaining OPTIONAL,
  1938. IN DWORD dwFlags,
  1939. IN LPCTSTR pszFormat OPTIONAL,
  1940. IN va_list argList
  1941. );
  1942. Routine Description:
  1943. This routine is a safer version of the C built-in function 'vsprintf' with
  1944. some additional parameters. In addition to functionality provided by
  1945. StringCchVPrintf, this routine also returns a pointer to the end of the
  1946. destination string and the number of characters left in the destination string
  1947. including the null terminator. The flags parameter allows additional controls.
  1948. Arguments:
  1949. pszDest - destination string
  1950. cchDest - size of destination buffer in characters.
  1951. length must be sufficient to contain the resulting
  1952. formatted string plus the null terminator.
  1953. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  1954. pointer to the end of the destination string. If the
  1955. function printed any data, the result will point to the
  1956. null termination character
  1957. pcchRemaining - if pcchRemaining is non-null, the function will return
  1958. the number of characters left in the destination string,
  1959. including the null terminator
  1960. dwFlags - controls some details of the string copy:
  1961. STRSAFE_FILL_BEHIND_NULL
  1962. if the function succeeds, the low byte of dwFlags will be
  1963. used to fill the uninitialize part of destination buffer
  1964. behind the null terminator
  1965. STRSAFE_IGNORE_NULLS
  1966. treat NULL string pointers like empty strings (TEXT(""))
  1967. STRSAFE_FILL_ON_FAILURE
  1968. if the function fails, the low byte of dwFlags will be
  1969. used to fill all of the destination buffer, and it will
  1970. be null terminated. This will overwrite any truncated
  1971. string returned when the failure is
  1972. STRSAFE_E_INSUFFICIENT_BUFFER
  1973. STRSAFE_NO_TRUNCATION /
  1974. STRSAFE_NULL_ON_FAILURE
  1975. if the function fails, the destination buffer will be set
  1976. to the empty string. This will overwrite any truncated string
  1977. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  1978. pszFormat - format string which must be null terminated
  1979. argList - va_list from the variable arguments according to the
  1980. stdarg.h convention
  1981. Notes:
  1982. Behavior is undefined if destination, format strings or any arguments
  1983. strings overlap.
  1984. pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
  1985. flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and
  1986. pszFormat may be NULL. An error may still be returned even though NULLS
  1987. are ignored due to insufficient space.
  1988. Return Value:
  1989. S_OK - if there was source data and it was all concatenated and
  1990. the resultant dest string was null terminated
  1991. failure - you can use the macro HRESULT_CODE() to get a win32
  1992. error code for all hresult failure cases
  1993. STRSAFE_E_INSUFFICIENT_BUFFER /
  1994. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  1995. - this return value is an indication that the print
  1996. operation failed due to insufficient space. When this
  1997. error occurs, the destination buffer is modified to
  1998. contain a truncated version of the ideal result and is
  1999. null terminated. This is useful for situations where
  2000. truncation is ok.
  2001. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2002. return value of this function
  2003. --*/
  2004. STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
  2005. #define StringCchVPrintfEx StringCchVPrintfExA
  2006. #ifdef STRSAFE_INLINE
  2007. STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
  2008. {
  2009. HRESULT hr;
  2010. if (cchDest > STRSAFE_MAX_CCH)
  2011. {
  2012. hr = STRSAFE_E_INVALID_PARAMETER;
  2013. }
  2014. else
  2015. {
  2016. size_t cbDest;
  2017. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  2018. cbDest = cchDest * sizeof(char);
  2019. hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
  2020. }
  2021. return hr;
  2022. }
  2023. #endif // STRSAFE_INLINE
  2024. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2025. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2026. /*++
  2027. STDAPI
  2028. StringCbVPrintfEx(
  2029. OUT LPTSTR pszDest OPTIONAL,
  2030. IN size_t cbDest,
  2031. OUT LPTSTR* ppszDestEnd OPTIONAL,
  2032. OUT size_t* pcbRemaining OPTIONAL,
  2033. IN DWORD dwFlags,
  2034. IN LPCTSTR pszFormat OPTIONAL,
  2035. IN va_list argList
  2036. );
  2037. Routine Description:
  2038. This routine is a safer version of the C built-in function 'vsprintf' with
  2039. some additional parameters. In addition to functionality provided by
  2040. StringCbVPrintf, this routine also returns a pointer to the end of the
  2041. destination string and the number of characters left in the destination string
  2042. including the null terminator. The flags parameter allows additional controls.
  2043. Arguments:
  2044. pszDest - destination string
  2045. cbDest - size of destination buffer in bytes.
  2046. length must be sufficient to contain the resulting
  2047. formatted string plus the null terminator.
  2048. ppszDestEnd - if ppszDestEnd is non-null, the function will return
  2049. a pointer to the end of the destination string. If the
  2050. function printed any data, the result will point to the
  2051. null termination character
  2052. pcbRemaining - if pcbRemaining is non-null, the function will return
  2053. the number of bytes left in the destination string,
  2054. including the null terminator
  2055. dwFlags - controls some details of the string copy:
  2056. STRSAFE_FILL_BEHIND_NULL
  2057. if the function succeeds, the low byte of dwFlags will be
  2058. used to fill the uninitialize part of destination buffer
  2059. behind the null terminator
  2060. STRSAFE_IGNORE_NULLS
  2061. treat NULL string pointers like empty strings (TEXT(""))
  2062. STRSAFE_FILL_ON_FAILURE
  2063. if the function fails, the low byte of dwFlags will be
  2064. used to fill all of the destination buffer, and it will
  2065. be null terminated. This will overwrite any truncated
  2066. string returned when the failure is
  2067. STRSAFE_E_INSUFFICIENT_BUFFER
  2068. STRSAFE_NO_TRUNCATION /
  2069. STRSAFE_NULL_ON_FAILURE
  2070. if the function fails, the destination buffer will be set
  2071. to the empty string. This will overwrite any truncated string
  2072. returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER.
  2073. pszFormat - format string which must be null terminated
  2074. argList - va_list from the variable arguments according to the
  2075. stdarg.h convention
  2076. Notes:
  2077. Behavior is undefined if destination, format strings or any arguments
  2078. strings overlap.
  2079. pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS
  2080. flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and
  2081. pszFormat may be NULL. An error may still be returned even though NULLS
  2082. are ignored due to insufficient space.
  2083. Return Value:
  2084. S_OK - if there was source data and it was all concatenated and
  2085. the resultant dest string was null terminated
  2086. failure - you can use the macro HRESULT_CODE() to get a win32
  2087. error code for all hresult failure cases
  2088. STRSAFE_E_INSUFFICIENT_BUFFER /
  2089. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2090. - this return value is an indication that the print
  2091. operation failed due to insufficient space. When this
  2092. error occurs, the destination buffer is modified to
  2093. contain a truncated version of the ideal result and is
  2094. null terminated. This is useful for situations where
  2095. truncation is ok.
  2096. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2097. return value of this function
  2098. --*/
  2099. STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList);
  2100. #define StringCbVPrintfEx StringCbVPrintfExA
  2101. #ifdef STRSAFE_INLINE
  2102. STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
  2103. {
  2104. HRESULT hr;
  2105. size_t cchDest;
  2106. size_t cchRemaining = 0;
  2107. cchDest = cbDest / sizeof(char);
  2108. if (cchDest > STRSAFE_MAX_CCH)
  2109. {
  2110. hr = STRSAFE_E_INVALID_PARAMETER;
  2111. }
  2112. else
  2113. {
  2114. hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
  2115. }
  2116. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  2117. {
  2118. if (pcbRemaining)
  2119. {
  2120. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  2121. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  2122. }
  2123. }
  2124. return hr;
  2125. }
  2126. #endif // STRSAFE_INLINE
  2127. #endif // !STRSAFE_NO_CB_FUNCTIONS
  2128. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  2129. /*++
  2130. STDAPI
  2131. StringCchGets(
  2132. OUT LPTSTR pszDest,
  2133. IN size_t cchDest
  2134. );
  2135. Routine Description:
  2136. This routine is a safer version of the C built-in function 'gets'.
  2137. The size of the destination buffer (in characters) is a parameter and
  2138. this function will not write past the end of this buffer and it will
  2139. ALWAYS null terminate the destination buffer (unless it is zero length).
  2140. This routine is not a replacement for fgets. That function does not replace
  2141. newline characters with a null terminator.
  2142. This function returns a hresult, and not a pointer. It returns
  2143. S_OK if any characters were read from stdin and copied to pszDest and
  2144. pszDest was null terminated, otherwise it will return a failure code.
  2145. Arguments:
  2146. pszDest - destination string
  2147. cchDest - size of destination buffer in characters.
  2148. Notes:
  2149. pszDest should not be NULL. See StringCchGetsEx if you require the handling
  2150. of NULL values.
  2151. cchDest must be > 1 for this function to succeed.
  2152. Return Value:
  2153. S_OK - data was read from stdin and copied, and the resultant
  2154. dest string was null terminated
  2155. failure - you can use the macro HRESULT_CODE() to get a win32
  2156. error code for all hresult failure cases
  2157. STRSAFE_E_END_OF_FILE /
  2158. HRESULT_CODE(hr) == ERROR_HANDLE_EOF
  2159. - this return value indicates an error or end-of-file
  2160. condition, use feof or ferror to determine which one has
  2161. occured.
  2162. STRSAFE_E_INSUFFICIENT_BUFFER /
  2163. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2164. - this return value is an indication that there was
  2165. insufficient space in the destination buffer to copy any
  2166. data
  2167. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2168. return value of this function.
  2169. --*/
  2170. #ifndef STRSAFE_LIB_IMPL
  2171. STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest);
  2172. #define StringCchGets StringCchGetsA
  2173. STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest)
  2174. {
  2175. HRESULT hr;
  2176. if (cchDest > STRSAFE_MAX_CCH)
  2177. {
  2178. hr = STRSAFE_E_INVALID_PARAMETER;
  2179. }
  2180. else
  2181. {
  2182. size_t cbDest;
  2183. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  2184. cbDest = cchDest * sizeof(char);
  2185. hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0);
  2186. }
  2187. return hr;
  2188. }
  2189. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2190. #endif // !STRSAFE_LIB_IMPL
  2191. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2192. /*++
  2193. STDAPI
  2194. StringCbGets(
  2195. OUT LPTSTR pszDest,
  2196. IN size_t cbDest
  2197. );
  2198. Routine Description:
  2199. This routine is a safer version of the C built-in function 'gets'.
  2200. The size of the destination buffer (in bytes) is a parameter and
  2201. this function will not write past the end of this buffer and it will
  2202. ALWAYS null terminate the destination buffer (unless it is zero length).
  2203. This routine is not a replacement for fgets. That function does not replace
  2204. newline characters with a null terminator.
  2205. This function returns a hresult, and not a pointer. It returns
  2206. S_OK if any characters were read from stdin and copied to pszDest
  2207. and pszDest was null terminated, otherwise it will return a failure code.
  2208. Arguments:
  2209. pszDest - destination string
  2210. cbDest - size of destination buffer in bytes.
  2211. Notes:
  2212. pszDest should not be NULL. See StringCbGetsEx if you require the handling
  2213. of NULL values.
  2214. cbDest must be > sizeof(TCHAR) for this function to succeed.
  2215. Return Value:
  2216. S_OK - data was read from stdin and copied, and the resultant
  2217. dest string was null terminated
  2218. failure - you can use the macro HRESULT_CODE() to get a win32
  2219. error code for all hresult failure cases
  2220. STRSAFE_E_END_OF_FILE /
  2221. HRESULT_CODE(hr) == ERROR_HANDLE_EOF
  2222. - this return value indicates an error or end-of-file
  2223. condition, use feof or ferror to determine which one has
  2224. occured.
  2225. STRSAFE_E_INSUFFICIENT_BUFFER /
  2226. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2227. - this return value is an indication that there was
  2228. insufficient space in the destination buffer to copy any
  2229. data
  2230. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2231. return value of this function.
  2232. --*/
  2233. #ifndef STRSAFE_LIB_IMPL
  2234. STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest);
  2235. #define StringCbGets StringCbGetsA
  2236. STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest)
  2237. {
  2238. HRESULT hr;
  2239. size_t cchDest;
  2240. // convert to count of characters
  2241. cchDest = cbDest / sizeof(char);
  2242. if (cchDest > STRSAFE_MAX_CCH)
  2243. {
  2244. hr = STRSAFE_E_INVALID_PARAMETER;
  2245. }
  2246. else
  2247. {
  2248. hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0);
  2249. }
  2250. return hr;
  2251. }
  2252. #endif // !STRSAFE_NO_CB_FUNCTIONS
  2253. #endif // !STRSAFE_LIB_IMPL
  2254. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  2255. /*++
  2256. STDAPI
  2257. StringCchGetsEx(
  2258. OUT LPTSTR pszDest OPTIONAL,
  2259. IN size_t cchDest,
  2260. OUT LPTSTR* ppszDestEnd OPTIONAL,
  2261. OUT size_t* pcchRemaining OPTIONAL,
  2262. IN DWORD dwFlags
  2263. );
  2264. Routine Description:
  2265. This routine is a safer version of the C built-in function 'gets' with
  2266. some additional parameters. In addition to functionality provided by
  2267. StringCchGets, this routine also returns a pointer to the end of the
  2268. destination string and the number of characters left in the destination string
  2269. including the null terminator. The flags parameter allows additional controls.
  2270. Arguments:
  2271. pszDest - destination string
  2272. cchDest - size of destination buffer in characters.
  2273. ppszDestEnd - if ppszDestEnd is non-null, the function will return a
  2274. pointer to the end of the destination string. If the
  2275. function copied any data, the result will point to the
  2276. null termination character
  2277. pcchRemaining - if pcchRemaining is non-null, the function will return the
  2278. number of characters left in the destination string,
  2279. including the null terminator
  2280. dwFlags - controls some details of the string copy:
  2281. STRSAFE_FILL_BEHIND_NULL
  2282. if the function succeeds, the low byte of dwFlags will be
  2283. used to fill the uninitialize part of destination buffer
  2284. behind the null terminator
  2285. STRSAFE_IGNORE_NULLS
  2286. treat NULL string pointers like empty strings (TEXT("")).
  2287. STRSAFE_FILL_ON_FAILURE
  2288. if the function fails, the low byte of dwFlags will be
  2289. used to fill all of the destination buffer, and it will
  2290. be null terminated.
  2291. STRSAFE_NO_TRUNCATION /
  2292. STRSAFE_NULL_ON_FAILURE
  2293. if the function fails, the destination buffer will be set
  2294. to the empty string.
  2295. Notes:
  2296. pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified.
  2297. If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be
  2298. returned even though NULLS are ignored
  2299. cchDest must be > 1 for this function to succeed.
  2300. Return Value:
  2301. S_OK - data was read from stdin and copied, and the resultant
  2302. dest string was null terminated
  2303. failure - you can use the macro HRESULT_CODE() to get a win32
  2304. error code for all hresult failure cases
  2305. STRSAFE_E_END_OF_FILE /
  2306. HRESULT_CODE(hr) == ERROR_HANDLE_EOF
  2307. - this return value indicates an error or end-of-file
  2308. condition, use feof or ferror to determine which one has
  2309. occured.
  2310. STRSAFE_E_INSUFFICIENT_BUFFER /
  2311. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2312. - this return value is an indication that there was
  2313. insufficient space in the destination buffer to copy any
  2314. data
  2315. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2316. return value of this function.
  2317. --*/
  2318. #ifndef STRSAFE_LIB_IMPL
  2319. STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags);
  2320. #define StringCchGetsEx StringCchGetsExA
  2321. STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  2322. {
  2323. HRESULT hr;
  2324. if (cchDest > STRSAFE_MAX_CCH)
  2325. {
  2326. hr = STRSAFE_E_INVALID_PARAMETER;
  2327. }
  2328. else
  2329. {
  2330. size_t cbDest;
  2331. // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1
  2332. cbDest = cchDest * sizeof(char);
  2333. hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags);
  2334. }
  2335. return hr;
  2336. }
  2337. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2338. #endif // !STRSAFE_LIB_IMPL
  2339. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2340. /*++
  2341. STDAPI
  2342. StringCbGetsEx(
  2343. OUT LPTSTR pszDest OPTIONAL,
  2344. IN size_t cbDest,
  2345. OUT LPTSTR* ppszDestEnd OPTIONAL,
  2346. OUT size_t* pcbRemaining OPTIONAL,
  2347. IN DWORD dwFlags
  2348. );
  2349. Routine Description:
  2350. This routine is a safer version of the C built-in function 'gets' with
  2351. some additional parameters. In addition to functionality provided by
  2352. StringCbGets, this routine also returns a pointer to the end of the
  2353. destination string and the number of characters left in the destination string
  2354. including the null terminator. The flags parameter allows additional controls.
  2355. Arguments:
  2356. pszDest - destination string
  2357. cbDest - size of destination buffer in bytes.
  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 copied any data, the result will point to the
  2361. null termination character
  2362. pcbRemaining - if pbRemaining is non-null, the function will return the
  2363. 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.
  2376. STRSAFE_NO_TRUNCATION /
  2377. STRSAFE_NULL_ON_FAILURE
  2378. if the function fails, the destination buffer will be set
  2379. to the empty string.
  2380. Notes:
  2381. pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified.
  2382. If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be
  2383. returned even though NULLS are ignored
  2384. cbDest must be > sizeof(TCHAR) for this function to succeed
  2385. Return Value:
  2386. S_OK - data was read from stdin and copied, and the resultant
  2387. dest string was null terminated
  2388. failure - you can use the macro HRESULT_CODE() to get a win32
  2389. error code for all hresult failure cases
  2390. STRSAFE_E_END_OF_FILE /
  2391. HRESULT_CODE(hr) == ERROR_HANDLE_EOF
  2392. - this return value indicates an error or end-of-file
  2393. condition, use feof or ferror to determine which one has
  2394. occured.
  2395. STRSAFE_E_INSUFFICIENT_BUFFER /
  2396. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER
  2397. - this return value is an indication that there was
  2398. insufficient space in the destination buffer to copy any
  2399. data
  2400. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2401. return value of this function.
  2402. --*/
  2403. #ifndef STRSAFE_LIB_IMPL
  2404. STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pbRemaining, unsigned long dwFlags);
  2405. #define StringCbGetsEx StringCbGetsExA
  2406. STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags)
  2407. {
  2408. HRESULT hr;
  2409. size_t cchDest;
  2410. size_t cchRemaining = 0;
  2411. cchDest = cbDest / sizeof(char);
  2412. if (cchDest > STRSAFE_MAX_CCH)
  2413. {
  2414. hr = STRSAFE_E_INVALID_PARAMETER;
  2415. }
  2416. else
  2417. {
  2418. hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags);
  2419. }
  2420. if (SUCCEEDED(hr) ||
  2421. (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
  2422. (hr == STRSAFE_E_END_OF_FILE))
  2423. {
  2424. if (pcbRemaining)
  2425. {
  2426. // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1
  2427. *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
  2428. }
  2429. }
  2430. return hr;
  2431. }
  2432. #endif // !STRSAFE_NO_CB_FUNCTIONS
  2433. #endif // !STRSAFE_LIB_IMPL
  2434. #ifndef STRSAFE_NO_CCH_FUNCTIONS
  2435. /*++
  2436. STDAPI
  2437. StringCchLength(
  2438. IN LPCTSTR psz,
  2439. IN size_t cchMax,
  2440. OUT size_t* pcch OPTIONAL
  2441. );
  2442. Routine Description:
  2443. This routine is a safer version of the C built-in function 'strlen'.
  2444. It is used to make sure a string is not larger than a given length, and
  2445. it optionally returns the current length in characters not including
  2446. the null terminator.
  2447. This function returns a hresult, and not a pointer. It returns
  2448. S_OK if the string is non-null and the length including the null
  2449. terminator is less than or equal to cchMax characters.
  2450. Arguments:
  2451. psz - string to check the length of
  2452. cchMax - maximum number of characters including the null terminator
  2453. that psz is allowed to contain
  2454. pcch - if the function succeeds and pcch is non-null, the current length
  2455. in characters of psz excluding the null terminator will be returned.
  2456. This out parameter is equivalent to the return value of strlen(psz)
  2457. Notes:
  2458. psz can be null but the function will fail
  2459. cchMax should be greater than zero or the function will fail
  2460. Return Value:
  2461. S_OK - psz is non-null and the length including the null
  2462. terminator is less than or equal to cchMax characters
  2463. failure - you can use the macro HRESULT_CODE() to get a win32
  2464. error code for all hresult failure cases
  2465. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2466. return value of this function.
  2467. --*/
  2468. STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch);
  2469. #define StringCchLength StringCchLengthA
  2470. #ifdef STRSAFE_INLINE
  2471. STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch)
  2472. {
  2473. HRESULT hr;
  2474. if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
  2475. {
  2476. hr = STRSAFE_E_INVALID_PARAMETER;
  2477. }
  2478. else
  2479. {
  2480. hr = StringLengthWorkerA(psz, cchMax, pcch);
  2481. }
  2482. return hr;
  2483. }
  2484. #endif // STRSAFE_INLINE
  2485. #endif // !STRSAFE_NO_CCH_FUNCTIONS
  2486. #ifndef STRSAFE_NO_CB_FUNCTIONS
  2487. /*++
  2488. STDAPI
  2489. StringCbLength(
  2490. IN LPCTSTR psz,
  2491. IN size_t cbMax,
  2492. OUT size_t* pcb OPTIONAL
  2493. );
  2494. Routine Description:
  2495. This routine is a safer version of the C built-in function 'strlen'.
  2496. It is used to make sure a string is not larger than a given length, and
  2497. it optionally returns the current length in bytes not including
  2498. the null terminator.
  2499. This function returns a hresult, and not a pointer. It returns
  2500. S_OK if the string is non-null and the length including the null
  2501. terminator is less than or equal to cbMax bytes.
  2502. Arguments:
  2503. psz - string to check the length of
  2504. cbMax - maximum number of bytes including the null terminator
  2505. that psz is allowed to contain
  2506. pcb - if the function succeeds and pcb is non-null, the current length
  2507. in bytes of psz excluding the null terminator will be returned.
  2508. This out parameter is equivalent to the return value of strlen(psz) * sizeof(TCHAR)
  2509. Notes:
  2510. psz can be null but the function will fail
  2511. cbMax should be greater than or equal to sizeof(TCHAR) or the function will fail
  2512. Return Value:
  2513. S_OK - psz is non-null and the length including the null
  2514. terminator is less than or equal to cbMax bytes
  2515. failure - you can use the macro HRESULT_CODE() to get a win32
  2516. error code for all hresult failure cases
  2517. It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the
  2518. return value of this function.
  2519. --*/
  2520. STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch);
  2521. #define StringCbLength StringCbLengthA
  2522. #ifdef STRSAFE_INLINE
  2523. STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb)
  2524. {
  2525. HRESULT hr;
  2526. size_t cchMax;
  2527. size_t cch = 0;
  2528. cchMax = cbMax / sizeof(char);
  2529. if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH))
  2530. {
  2531. hr = STRSAFE_E_INVALID_PARAMETER;
  2532. }
  2533. else
  2534. {
  2535. hr = StringLengthWorkerA(psz, cchMax, &cch);
  2536. }
  2537. if (SUCCEEDED(hr) && pcb)
  2538. {
  2539. // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1
  2540. *pcb = cch * sizeof(char);
  2541. }
  2542. return hr;
  2543. }
  2544. #endif // STRSAFE_INLINE
  2545. #endif // !STRSAFE_NO_CB_FUNCTIONS
  2546. // these are the worker functions that actually do the work
  2547. #ifdef STRSAFE_INLINE
  2548. STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc)
  2549. {
  2550. HRESULT hr = S_OK;
  2551. if (cchDest == 0)
  2552. {
  2553. // can not null terminate a zero-byte dest buffer
  2554. hr = STRSAFE_E_INVALID_PARAMETER;
  2555. }
  2556. else
  2557. {
  2558. while (cchDest && (*pszSrc != '\0'))
  2559. {
  2560. *pszDest++ = *pszSrc++;
  2561. cchDest--;
  2562. }
  2563. if (cchDest == 0)
  2564. {
  2565. // we are going to truncate pszDest
  2566. pszDest--;
  2567. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  2568. }
  2569. *pszDest= '\0';
  2570. }
  2571. return hr;
  2572. }
  2573. STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  2574. {
  2575. HRESULT hr = S_OK;
  2576. char* pszDestEnd = pszDest;
  2577. size_t cchRemaining = 0;
  2578. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  2579. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  2580. // only accept valid flags
  2581. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  2582. {
  2583. hr = STRSAFE_E_INVALID_PARAMETER;
  2584. }
  2585. else
  2586. {
  2587. if (dwFlags & STRSAFE_IGNORE_NULLS)
  2588. {
  2589. if (pszDest == NULL)
  2590. {
  2591. if ((cchDest != 0) || (cbDest != 0))
  2592. {
  2593. // NULL pszDest and non-zero cchDest/cbDest is invalid
  2594. hr = STRSAFE_E_INVALID_PARAMETER;
  2595. }
  2596. }
  2597. if (pszSrc == NULL)
  2598. {
  2599. pszSrc = "";
  2600. }
  2601. }
  2602. if (SUCCEEDED(hr))
  2603. {
  2604. if (cchDest == 0)
  2605. {
  2606. pszDestEnd = pszDest;
  2607. cchRemaining = 0;
  2608. // only fail if there was actually src data to copy
  2609. if (*pszSrc != '\0')
  2610. {
  2611. if (pszDest == NULL)
  2612. {
  2613. hr = STRSAFE_E_INVALID_PARAMETER;
  2614. }
  2615. else
  2616. {
  2617. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  2618. }
  2619. }
  2620. }
  2621. else
  2622. {
  2623. pszDestEnd = pszDest;
  2624. cchRemaining = cchDest;
  2625. while (cchRemaining && (*pszSrc != '\0'))
  2626. {
  2627. *pszDestEnd++= *pszSrc++;
  2628. cchRemaining--;
  2629. }
  2630. if (cchRemaining > 0)
  2631. {
  2632. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  2633. {
  2634. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
  2635. }
  2636. }
  2637. else
  2638. {
  2639. // we are going to truncate pszDest
  2640. pszDestEnd--;
  2641. cchRemaining++;
  2642. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  2643. }
  2644. *pszDestEnd = '\0';
  2645. }
  2646. }
  2647. }
  2648. if (FAILED(hr))
  2649. {
  2650. if (pszDest)
  2651. {
  2652. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  2653. {
  2654. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  2655. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  2656. {
  2657. pszDestEnd = pszDest;
  2658. cchRemaining = cchDest;
  2659. }
  2660. else if (cchDest > 0)
  2661. {
  2662. pszDestEnd = pszDest + cchDest - 1;
  2663. cchRemaining = 1;
  2664. // null terminate the end of the string
  2665. *pszDestEnd = '\0';
  2666. }
  2667. }
  2668. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  2669. {
  2670. if (cchDest > 0)
  2671. {
  2672. pszDestEnd = pszDest;
  2673. cchRemaining = cchDest;
  2674. // null terminate the beginning of the string
  2675. *pszDestEnd = '\0';
  2676. }
  2677. }
  2678. }
  2679. }
  2680. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  2681. {
  2682. if (ppszDestEnd)
  2683. {
  2684. *ppszDestEnd = pszDestEnd;
  2685. }
  2686. if (pcchRemaining)
  2687. {
  2688. *pcchRemaining = cchRemaining;
  2689. }
  2690. }
  2691. return hr;
  2692. }
  2693. STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc)
  2694. {
  2695. HRESULT hr = S_OK;
  2696. if (cchDest == 0)
  2697. {
  2698. // can not null terminate a zero-byte dest buffer
  2699. hr = STRSAFE_E_INVALID_PARAMETER;
  2700. }
  2701. else
  2702. {
  2703. while (cchDest && cchSrc && (*pszSrc != '\0'))
  2704. {
  2705. *pszDest++= *pszSrc++;
  2706. cchDest--;
  2707. cchSrc--;
  2708. }
  2709. if (cchDest == 0)
  2710. {
  2711. // we are going to truncate pszDest
  2712. pszDest--;
  2713. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  2714. }
  2715. *pszDest= '\0';
  2716. }
  2717. return hr;
  2718. }
  2719. STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  2720. {
  2721. HRESULT hr = S_OK;
  2722. char* pszDestEnd = pszDest;
  2723. size_t cchRemaining = 0;
  2724. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  2725. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  2726. // only accept valid flags
  2727. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  2728. {
  2729. hr = STRSAFE_E_INVALID_PARAMETER;
  2730. }
  2731. else
  2732. {
  2733. if (dwFlags & STRSAFE_IGNORE_NULLS)
  2734. {
  2735. if (pszDest == NULL)
  2736. {
  2737. if ((cchDest != 0) || (cbDest != 0))
  2738. {
  2739. // NULL pszDest and non-zero cchDest/cbDest is invalid
  2740. hr = STRSAFE_E_INVALID_PARAMETER;
  2741. }
  2742. }
  2743. if (pszSrc == NULL)
  2744. {
  2745. pszSrc = "";
  2746. }
  2747. }
  2748. if (SUCCEEDED(hr))
  2749. {
  2750. if (cchDest == 0)
  2751. {
  2752. pszDestEnd = pszDest;
  2753. cchRemaining = 0;
  2754. // only fail if there was actually src data to copy
  2755. if (*pszSrc != '\0')
  2756. {
  2757. if (pszDest == NULL)
  2758. {
  2759. hr = STRSAFE_E_INVALID_PARAMETER;
  2760. }
  2761. else
  2762. {
  2763. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  2764. }
  2765. }
  2766. }
  2767. else
  2768. {
  2769. pszDestEnd = pszDest;
  2770. cchRemaining = cchDest;
  2771. while (cchRemaining && cchSrc && (*pszSrc != '\0'))
  2772. {
  2773. *pszDestEnd++= *pszSrc++;
  2774. cchRemaining--;
  2775. cchSrc--;
  2776. }
  2777. if (cchRemaining > 0)
  2778. {
  2779. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  2780. {
  2781. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
  2782. }
  2783. }
  2784. else
  2785. {
  2786. // we are going to truncate pszDest
  2787. pszDestEnd--;
  2788. cchRemaining++;
  2789. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  2790. }
  2791. *pszDestEnd = '\0';
  2792. }
  2793. }
  2794. }
  2795. if (FAILED(hr))
  2796. {
  2797. if (pszDest)
  2798. {
  2799. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  2800. {
  2801. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  2802. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  2803. {
  2804. pszDestEnd = pszDest;
  2805. cchRemaining = cchDest;
  2806. }
  2807. else if (cchDest > 0)
  2808. {
  2809. pszDestEnd = pszDest + cchDest - 1;
  2810. cchRemaining = 1;
  2811. // null terminate the end of the string
  2812. *pszDestEnd = '\0';
  2813. }
  2814. }
  2815. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  2816. {
  2817. if (cchDest > 0)
  2818. {
  2819. pszDestEnd = pszDest;
  2820. cchRemaining = cchDest;
  2821. // null terminate the beginning of the string
  2822. *pszDestEnd = '\0';
  2823. }
  2824. }
  2825. }
  2826. }
  2827. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  2828. {
  2829. if (ppszDestEnd)
  2830. {
  2831. *ppszDestEnd = pszDestEnd;
  2832. }
  2833. if (pcchRemaining)
  2834. {
  2835. *pcchRemaining = cchRemaining;
  2836. }
  2837. }
  2838. return hr;
  2839. }
  2840. STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc)
  2841. {
  2842. HRESULT hr;
  2843. size_t cchDestCurrent;
  2844. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  2845. if (SUCCEEDED(hr))
  2846. {
  2847. hr = StringCopyWorkerA(pszDest + cchDestCurrent,
  2848. cchDest - cchDestCurrent,
  2849. pszSrc);
  2850. }
  2851. return hr;
  2852. }
  2853. STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  2854. {
  2855. HRESULT hr = S_OK;
  2856. char* pszDestEnd = pszDest;
  2857. size_t cchRemaining = 0;
  2858. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  2859. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  2860. // only accept valid flags
  2861. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  2862. {
  2863. hr = STRSAFE_E_INVALID_PARAMETER;
  2864. }
  2865. else
  2866. {
  2867. size_t cchDestCurrent;
  2868. if (dwFlags & STRSAFE_IGNORE_NULLS)
  2869. {
  2870. if (pszDest == NULL)
  2871. {
  2872. if ((cchDest == 0) && (cbDest == 0))
  2873. {
  2874. cchDestCurrent = 0;
  2875. }
  2876. else
  2877. {
  2878. // NULL pszDest and non-zero cchDest/cbDest is invalid
  2879. hr = STRSAFE_E_INVALID_PARAMETER;
  2880. }
  2881. }
  2882. else
  2883. {
  2884. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  2885. if (SUCCEEDED(hr))
  2886. {
  2887. pszDestEnd = pszDest + cchDestCurrent;
  2888. cchRemaining = cchDest - cchDestCurrent;
  2889. }
  2890. }
  2891. if (pszSrc == NULL)
  2892. {
  2893. pszSrc = "";
  2894. }
  2895. }
  2896. else
  2897. {
  2898. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  2899. if (SUCCEEDED(hr))
  2900. {
  2901. pszDestEnd = pszDest + cchDestCurrent;
  2902. cchRemaining = cchDest - cchDestCurrent;
  2903. }
  2904. }
  2905. if (SUCCEEDED(hr))
  2906. {
  2907. if (cchDest == 0)
  2908. {
  2909. // only fail if there was actually src data to append
  2910. if (*pszSrc != '\0')
  2911. {
  2912. if (pszDest == NULL)
  2913. {
  2914. hr = STRSAFE_E_INVALID_PARAMETER;
  2915. }
  2916. else
  2917. {
  2918. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  2919. }
  2920. }
  2921. }
  2922. else
  2923. {
  2924. // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
  2925. // those flags through
  2926. hr = StringCopyExWorkerA(pszDestEnd,
  2927. cchRemaining,
  2928. (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)),
  2929. pszSrc,
  2930. &pszDestEnd,
  2931. &cchRemaining,
  2932. dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
  2933. }
  2934. }
  2935. }
  2936. if (FAILED(hr))
  2937. {
  2938. if (pszDest)
  2939. {
  2940. // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA()
  2941. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  2942. {
  2943. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  2944. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  2945. {
  2946. pszDestEnd = pszDest;
  2947. cchRemaining = cchDest;
  2948. }
  2949. else
  2950. if (cchDest > 0)
  2951. {
  2952. pszDestEnd = pszDest + cchDest - 1;
  2953. cchRemaining = 1;
  2954. // null terminate the end of the string
  2955. *pszDestEnd = '\0';
  2956. }
  2957. }
  2958. if (dwFlags & STRSAFE_NULL_ON_FAILURE)
  2959. {
  2960. if (cchDest > 0)
  2961. {
  2962. pszDestEnd = pszDest;
  2963. cchRemaining = cchDest;
  2964. // null terminate the beginning of the string
  2965. *pszDestEnd = '\0';
  2966. }
  2967. }
  2968. }
  2969. }
  2970. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  2971. {
  2972. if (ppszDestEnd)
  2973. {
  2974. *ppszDestEnd = pszDestEnd;
  2975. }
  2976. if (pcchRemaining)
  2977. {
  2978. *pcchRemaining = cchRemaining;
  2979. }
  2980. }
  2981. return hr;
  2982. }
  2983. STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend)
  2984. {
  2985. HRESULT hr;
  2986. size_t cchDestCurrent;
  2987. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  2988. if (SUCCEEDED(hr))
  2989. {
  2990. hr = StringCopyNWorkerA(pszDest + cchDestCurrent,
  2991. cchDest - cchDestCurrent,
  2992. pszSrc,
  2993. cchMaxAppend);
  2994. }
  2995. return hr;
  2996. }
  2997. STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  2998. {
  2999. HRESULT hr = S_OK;
  3000. char* pszDestEnd = pszDest;
  3001. size_t cchRemaining = 0;
  3002. size_t cchDestCurrent = 0;
  3003. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  3004. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  3005. // only accept valid flags
  3006. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3007. {
  3008. hr = STRSAFE_E_INVALID_PARAMETER;
  3009. }
  3010. else
  3011. {
  3012. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3013. {
  3014. if (pszDest == NULL)
  3015. {
  3016. if ((cchDest == 0) && (cbDest == 0))
  3017. {
  3018. cchDestCurrent = 0;
  3019. }
  3020. else
  3021. {
  3022. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3023. hr = STRSAFE_E_INVALID_PARAMETER;
  3024. }
  3025. }
  3026. else
  3027. {
  3028. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  3029. if (SUCCEEDED(hr))
  3030. {
  3031. pszDestEnd = pszDest + cchDestCurrent;
  3032. cchRemaining = cchDest - cchDestCurrent;
  3033. }
  3034. }
  3035. if (pszSrc == NULL)
  3036. {
  3037. pszSrc = "";
  3038. }
  3039. }
  3040. else
  3041. {
  3042. hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent);
  3043. if (SUCCEEDED(hr))
  3044. {
  3045. pszDestEnd = pszDest + cchDestCurrent;
  3046. cchRemaining = cchDest - cchDestCurrent;
  3047. }
  3048. }
  3049. if (SUCCEEDED(hr))
  3050. {
  3051. if (cchDest == 0)
  3052. {
  3053. // only fail if there was actually src data to append
  3054. if (*pszSrc != '\0')
  3055. {
  3056. if (pszDest == NULL)
  3057. {
  3058. hr = STRSAFE_E_INVALID_PARAMETER;
  3059. }
  3060. else
  3061. {
  3062. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3063. }
  3064. }
  3065. }
  3066. else
  3067. {
  3068. // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass
  3069. // those flags through
  3070. hr = StringCopyNExWorkerA(pszDestEnd,
  3071. cchRemaining,
  3072. (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)),
  3073. pszSrc,
  3074. cchMaxAppend,
  3075. &pszDestEnd,
  3076. &cchRemaining,
  3077. dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
  3078. }
  3079. }
  3080. }
  3081. if (FAILED(hr))
  3082. {
  3083. if (pszDest)
  3084. {
  3085. // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA()
  3086. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  3087. {
  3088. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  3089. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  3090. {
  3091. pszDestEnd = pszDest;
  3092. cchRemaining = cchDest;
  3093. }
  3094. else if (cchDest > 0)
  3095. {
  3096. pszDestEnd = pszDest + cchDest - 1;
  3097. cchRemaining = 1;
  3098. // null terminate the end of the string
  3099. *pszDestEnd = '\0';
  3100. }
  3101. }
  3102. if (dwFlags & (STRSAFE_NULL_ON_FAILURE))
  3103. {
  3104. if (cchDest > 0)
  3105. {
  3106. pszDestEnd = pszDest;
  3107. cchRemaining = cchDest;
  3108. // null terminate the beginning of the string
  3109. *pszDestEnd = '\0';
  3110. }
  3111. }
  3112. }
  3113. }
  3114. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  3115. {
  3116. if (ppszDestEnd)
  3117. {
  3118. *ppszDestEnd = pszDestEnd;
  3119. }
  3120. if (pcchRemaining)
  3121. {
  3122. *pcchRemaining = cchRemaining;
  3123. }
  3124. }
  3125. return hr;
  3126. }
  3127. STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList)
  3128. {
  3129. HRESULT hr = S_OK;
  3130. if (cchDest == 0)
  3131. {
  3132. // can not null terminate a zero-byte dest buffer
  3133. hr = STRSAFE_E_INVALID_PARAMETER;
  3134. }
  3135. else
  3136. {
  3137. int iRet;
  3138. size_t cchMax;
  3139. // leave the last space for the null terminator
  3140. cchMax = cchDest - 1;
  3141. iRet = vsnprintf(pszDest, cchMax, pszFormat, argList);
  3142. // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
  3143. if ((iRet < 0) || (((size_t)iRet) > cchMax))
  3144. {
  3145. // need to null terminate the string
  3146. pszDest += cchMax;
  3147. *pszDest = '\0';
  3148. // we have truncated pszDest
  3149. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3150. }
  3151. else if (((size_t)iRet) == cchMax)
  3152. {
  3153. // need to null terminate the string
  3154. pszDest += cchMax;
  3155. *pszDest = '\0';
  3156. }
  3157. }
  3158. return hr;
  3159. }
  3160. STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList)
  3161. {
  3162. HRESULT hr = S_OK;
  3163. char* pszDestEnd = pszDest;
  3164. size_t cchRemaining = 0;
  3165. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  3166. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  3167. // only accept valid flags
  3168. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3169. {
  3170. hr = STRSAFE_E_INVALID_PARAMETER;
  3171. }
  3172. else
  3173. {
  3174. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3175. {
  3176. if (pszDest == NULL)
  3177. {
  3178. if ((cchDest != 0) || (cbDest != 0))
  3179. {
  3180. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3181. hr = STRSAFE_E_INVALID_PARAMETER;
  3182. }
  3183. }
  3184. if (pszFormat == NULL)
  3185. {
  3186. pszFormat = "";
  3187. }
  3188. }
  3189. if (SUCCEEDED(hr))
  3190. {
  3191. if (cchDest == 0)
  3192. {
  3193. pszDestEnd = pszDest;
  3194. cchRemaining = 0;
  3195. // only fail if there was actually a non-empty format string
  3196. if (*pszFormat != '\0')
  3197. {
  3198. if (pszDest == NULL)
  3199. {
  3200. hr = STRSAFE_E_INVALID_PARAMETER;
  3201. }
  3202. else
  3203. {
  3204. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3205. }
  3206. }
  3207. }
  3208. else
  3209. {
  3210. int iRet;
  3211. size_t cchMax;
  3212. // leave the last space for the null terminator
  3213. cchMax = cchDest - 1;
  3214. iRet = vsnprintf(pszDest, cchMax, pszFormat, argList);
  3215. // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax));
  3216. if ((iRet < 0) || (((size_t)iRet) > cchMax))
  3217. {
  3218. // we have truncated pszDest
  3219. pszDestEnd = pszDest + cchMax;
  3220. cchRemaining = 1;
  3221. // need to null terminate the string
  3222. *pszDestEnd = '\0';
  3223. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3224. }
  3225. else if (((size_t)iRet) == cchMax)
  3226. {
  3227. // string fit perfectly
  3228. pszDestEnd = pszDest + cchMax;
  3229. cchRemaining = 1;
  3230. // need to null terminate the string
  3231. *pszDestEnd = '\0';
  3232. }
  3233. else if (((size_t)iRet) < cchMax)
  3234. {
  3235. // there is extra room
  3236. pszDestEnd = pszDest + iRet;
  3237. cchRemaining = cchDest - iRet;
  3238. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  3239. {
  3240. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
  3241. }
  3242. }
  3243. }
  3244. }
  3245. }
  3246. if (FAILED(hr))
  3247. {
  3248. if (pszDest)
  3249. {
  3250. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  3251. {
  3252. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  3253. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  3254. {
  3255. pszDestEnd = pszDest;
  3256. cchRemaining = cchDest;
  3257. }
  3258. else if (cchDest > 0)
  3259. {
  3260. pszDestEnd = pszDest + cchDest - 1;
  3261. cchRemaining = 1;
  3262. // null terminate the end of the string
  3263. *pszDestEnd = '\0';
  3264. }
  3265. }
  3266. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  3267. {
  3268. if (cchDest > 0)
  3269. {
  3270. pszDestEnd = pszDest;
  3271. cchRemaining = cchDest;
  3272. // null terminate the beginning of the string
  3273. *pszDestEnd = '\0';
  3274. }
  3275. }
  3276. }
  3277. }
  3278. if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER))
  3279. {
  3280. if (ppszDestEnd)
  3281. {
  3282. *ppszDestEnd = pszDestEnd;
  3283. }
  3284. if (pcchRemaining)
  3285. {
  3286. *pcchRemaining = cchRemaining;
  3287. }
  3288. }
  3289. return hr;
  3290. }
  3291. STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch)
  3292. {
  3293. HRESULT hr = S_OK;
  3294. size_t cchMaxPrev = cchMax;
  3295. while (cchMax && (*psz != '\0'))
  3296. {
  3297. psz++;
  3298. cchMax--;
  3299. }
  3300. if (cchMax == 0)
  3301. {
  3302. // the string is longer than cchMax
  3303. hr = STRSAFE_E_INVALID_PARAMETER;
  3304. }
  3305. if (SUCCEEDED(hr) && pcch)
  3306. {
  3307. *pcch = cchMaxPrev - cchMax;
  3308. }
  3309. return hr;
  3310. }
  3311. #endif // STRSAFE_INLINE
  3312. #ifndef STRSAFE_LIB_IMPL
  3313. STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags)
  3314. {
  3315. HRESULT hr = S_OK;
  3316. char* pszDestEnd = pszDest;
  3317. size_t cchRemaining = 0;
  3318. // ASSERT(cbDest == (cchDest * sizeof(char)) ||
  3319. // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char)));
  3320. // only accept valid flags
  3321. if (dwFlags & (~STRSAFE_VALID_FLAGS))
  3322. {
  3323. hr = STRSAFE_E_INVALID_PARAMETER;
  3324. }
  3325. else
  3326. {
  3327. if (dwFlags & STRSAFE_IGNORE_NULLS)
  3328. {
  3329. if (pszDest == NULL)
  3330. {
  3331. if ((cchDest != 0) || (cbDest != 0))
  3332. {
  3333. // NULL pszDest and non-zero cchDest/cbDest is invalid
  3334. hr = STRSAFE_E_INVALID_PARAMETER;
  3335. }
  3336. }
  3337. }
  3338. if (SUCCEEDED(hr))
  3339. {
  3340. if (cchDest <= 1)
  3341. {
  3342. pszDestEnd = pszDest;
  3343. cchRemaining = cchDest;
  3344. if (cchDest == 1)
  3345. {
  3346. *pszDestEnd = '\0';
  3347. }
  3348. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  3349. }
  3350. else
  3351. {
  3352. char ch;
  3353. pszDestEnd = pszDest;
  3354. cchRemaining = cchDest;
  3355. while ((cchRemaining > 1) && (ch = (char)getc(stdin)) != '\n')
  3356. {
  3357. if (ch == EOF)
  3358. {
  3359. if (pszDestEnd == pszDest)
  3360. {
  3361. // we failed to read anything from stdin
  3362. hr = STRSAFE_E_END_OF_FILE;
  3363. }
  3364. break;
  3365. }
  3366. *pszDestEnd = ch;
  3367. pszDestEnd++;
  3368. cchRemaining--;
  3369. }
  3370. if (cchRemaining > 0)
  3371. {
  3372. // there is extra room
  3373. if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
  3374. {
  3375. memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
  3376. }
  3377. }
  3378. *pszDestEnd = '\0';
  3379. }
  3380. }
  3381. }
  3382. if (FAILED(hr))
  3383. {
  3384. if (pszDest)
  3385. {
  3386. if (dwFlags & STRSAFE_FILL_ON_FAILURE)
  3387. {
  3388. memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
  3389. if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
  3390. {
  3391. pszDestEnd = pszDest;
  3392. cchRemaining = cchDest;
  3393. }
  3394. else if (cchDest > 0)
  3395. {
  3396. pszDestEnd = pszDest + cchDest - 1;
  3397. cchRemaining = 1;
  3398. // null terminate the end of the string
  3399. *pszDestEnd = '\0';
  3400. }
  3401. }
  3402. if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
  3403. {
  3404. if (cchDest > 0)
  3405. {
  3406. pszDestEnd = pszDest;
  3407. cchRemaining = cchDest;
  3408. // null terminate the beginning of the string
  3409. *pszDestEnd = '\0';
  3410. }
  3411. }
  3412. }
  3413. }
  3414. if (SUCCEEDED(hr) ||
  3415. (hr == STRSAFE_E_INSUFFICIENT_BUFFER) ||
  3416. (hr == STRSAFE_E_END_OF_FILE))
  3417. {
  3418. if (ppszDestEnd)
  3419. {
  3420. *ppszDestEnd = pszDestEnd;
  3421. }
  3422. if (pcchRemaining)
  3423. {
  3424. *pcchRemaining = cchRemaining;
  3425. }
  3426. }
  3427. return hr;
  3428. }
  3429. #endif // !STRSAFE_LIB_IMPL
  3430. // Do not call these functions, they are worker functions for internal use within this file
  3431. #ifdef DEPRECATE_SUPPORTED
  3432. #pragma deprecated(StringCopyWorkerA)
  3433. #pragma deprecated(StringCopyWorkerW)
  3434. #pragma deprecated(StringCopyExWorkerA)
  3435. #pragma deprecated(StringCopyExWorkerW)
  3436. #pragma deprecated(StringCatWorkerA)
  3437. #pragma deprecated(StringCatWorkerW)
  3438. #pragma deprecated(StringCatExWorkerA)
  3439. #pragma deprecated(StringCatExWorkerW)
  3440. #pragma deprecated(StringCatNWorkerA)
  3441. #pragma deprecated(StringCatNWorkerW)
  3442. #pragma deprecated(StringCatNExWorkerA)
  3443. #pragma deprecated(StringCatNExWorkerW)
  3444. #pragma deprecated(StringVPrintfWorkerA)
  3445. #pragma deprecated(StringVPrintfWorkerW)
  3446. #pragma deprecated(StringVPrintfExWorkerA)
  3447. #pragma deprecated(StringVPrintfExWorkerW)
  3448. #pragma deprecated(StringLengthWorkerA)
  3449. #pragma deprecated(StringLengthWorkerW)
  3450. #else
  3451. #define StringCopyWorkerA StringCopyWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
  3452. #define StringCopyWorkerW StringCopyWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
  3453. #define StringCopyExWorkerA StringCopyExWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
  3454. #define StringCopyExWorkerW StringCopyExWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
  3455. #define StringCatWorkerA StringCatWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
  3456. #define StringCatWorkerW StringCatWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
  3457. #define StringCatExWorkerA StringCatExWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
  3458. #define StringCatExWorkerW StringCatExWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
  3459. #define StringCatNWorkerA StringCatNWorkerA_instead_use_StringCchCatNA_or_StrincCbCatNA;
  3460. #define StringCatNWorkerW StringCatNWorkerW_instead_use_StringCchCatNW_or_StringCbCatNW;
  3461. #define StringCatNExWorkerA StringCatNExWorkerA_instead_use_StringCchCatNExA_or_StringCbCatNExA;
  3462. #define StringCatNExWorkerW StringCatNExWorkerW_instead_use_StringCchCatNExW_or_StringCbCatNExW;
  3463. #define StringVPrintfWorkerA StringVPrintfWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
  3464. #define StringVPrintfWorkerW StringVPrintfWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
  3465. #define StringVPrintfExWorkerA StringVPrintfExWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
  3466. #define StringVPrintfExWorkerW StringVPrintfExWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
  3467. #define StringLengthWorkerA StringLengthWorkerA_instead_use_StringCchLengthA_or_StringCbLengthA;
  3468. #define StringLengthWorkerW StringLengthWorkerW_instead_use_StringCchLengthW_or_StringCbLengthW;
  3469. #endif // !DEPRECATE_SUPPORTED
  3470. #ifdef _NTSTRSAFE_H_INCLUDED_
  3471. #pragma warning(pop)
  3472. #endif // _NTSTRSAFE_H_INCLUDED_
  3473. #endif