wstream.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. wstream.c
  9. Abstract:
  10. This module implements support for wide character stream operations.
  11. Author:
  12. Evan Green 28-Aug-2013
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "libcp.h"
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <limits.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // ------------------------------------------------------ Data Type Definitions
  31. //
  32. //
  33. // ----------------------------------------------- Internal Function Prototypes
  34. //
  35. BOOL
  36. ClpFileFormatWriteWideCharacter (
  37. INT Character,
  38. PPRINT_FORMAT_CONTEXT Context
  39. );
  40. //
  41. // -------------------------------------------------------------------- Globals
  42. //
  43. //
  44. // ------------------------------------------------------------------ Functions
  45. //
  46. LIBC_API
  47. wint_t
  48. fgetwc (
  49. FILE *Stream
  50. )
  51. /*++
  52. Routine Description:
  53. This routine retrieves the next wide character from the given file stream.
  54. Arguments:
  55. Stream - Supplies a pointer to the file stream.
  56. Return Value:
  57. Returns the next wide character in stream on success.
  58. WEOF on failure or if the end of the file was reached. The error or end of
  59. file indicators will be set on the stream.
  60. --*/
  61. {
  62. wint_t Result;
  63. ClpLockStream(Stream);
  64. Result = fgetwc_unlocked(Stream);
  65. ClpUnlockStream(Stream);
  66. return Result;
  67. }
  68. LIBC_API
  69. wint_t
  70. fgetwc_unlocked (
  71. FILE *Stream
  72. )
  73. /*++
  74. Routine Description:
  75. This routine retrieves the next wide character from the given file stream,
  76. without acquiring the stream lock.
  77. Arguments:
  78. Stream - Supplies a pointer to the file stream.
  79. Return Value:
  80. Returns the next wide character in stream on success.
  81. WEOF on failure or if the end of the file was reached. The error or end of
  82. file indicators will be set on the stream.
  83. --*/
  84. {
  85. int Character;
  86. CHAR MultibyteBuffer[MB_LEN_MAX];
  87. ULONG MultibyteSize;
  88. int Result;
  89. wchar_t WideCharacter;
  90. ORIENT_STREAM(Stream, FILE_FLAG_WIDE_ORIENTED);
  91. //
  92. // If there's an unget character, return that.
  93. //
  94. if ((Stream->Flags & FILE_FLAG_UNGET_VALID) != 0) {
  95. Stream->Flags &= ~FILE_FLAG_UNGET_VALID;
  96. return Stream->UngetCharacter;
  97. }
  98. //
  99. // Loop getting normal characters, adding them to the buffer, and then
  100. // attempting to convert to a wide character.
  101. //
  102. MultibyteSize = 0;
  103. while (MultibyteSize < MB_LEN_MAX) {
  104. Character = fgetc_unlocked(Stream);
  105. if (Character == EOF) {
  106. return EOF;
  107. }
  108. MultibyteBuffer[MultibyteSize] = (CHAR)Character;
  109. MultibyteSize += 1;
  110. Result = mbrtowc(&WideCharacter,
  111. MultibyteBuffer,
  112. MultibyteSize,
  113. &(Stream->ShiftState));
  114. if (Result == 0) {
  115. return L'\0';
  116. } else if (Result > 0) {
  117. assert(Result == MultibyteSize);
  118. return WideCharacter;
  119. } else if (Result == -1) {
  120. Stream->Flags |= FILE_FLAG_ERROR;
  121. return WEOF;
  122. }
  123. //
  124. // -2 means the conversion function needs more characters. Anything
  125. // else is unexpected.
  126. //
  127. assert(Result == -2);
  128. }
  129. //
  130. // It would be weird if the max weren't really enough to convert any
  131. // characters.
  132. //
  133. assert(FALSE);
  134. Stream->Flags |= FILE_FLAG_ERROR;
  135. errno = EILSEQ;
  136. return WEOF;
  137. }
  138. LIBC_API
  139. wint_t
  140. getwchar (
  141. void
  142. )
  143. /*++
  144. Routine Description:
  145. This routine reads one wide character from standard in.
  146. Arguments:
  147. None.
  148. Return Value:
  149. Returns the wide character from standard in on success.
  150. WEOF on failure or the end of the file, and errno will contain more
  151. information.
  152. --*/
  153. {
  154. return fgetwc(stdin);
  155. }
  156. LIBC_API
  157. wint_t
  158. getwc (
  159. FILE *Stream
  160. )
  161. /*++
  162. Routine Description:
  163. This routine reads one wide character from the given file stream. It is
  164. equivalent to the fgetwc function.
  165. Arguments:
  166. Stream - Supplies a pointer to the open file stream.
  167. Return Value:
  168. Returns the wide character on success.
  169. WEOF on failure or the end of the file, and errno will contain more
  170. information.
  171. --*/
  172. {
  173. return fgetwc(Stream);
  174. }
  175. LIBC_API
  176. wchar_t *
  177. fgetws (
  178. wchar_t *Buffer,
  179. int ElementCount,
  180. FILE *Stream
  181. )
  182. /*++
  183. Routine Description:
  184. This routine reads wide characters out of the given stream until a newline
  185. or the maximum number of elements minus one is read. Then the string is
  186. null terminated.
  187. Arguments:
  188. Buffer - Supplies a pointer to the wide character array where the read
  189. characters will be returned.
  190. ElementCount - Supplies the maximum number of wide characters to return in
  191. the given buffer.
  192. Stream - Supplies a pointer to the file stream to read from.
  193. Return Value:
  194. Returns a pointer to the input buffer on success.
  195. NULL if a read error occurs or the end of the file is reached. If at the
  196. end of the file, the end of file indicator will be set on the stream. If an
  197. error occurs, he error indicator will be set for the stream, and the errno
  198. variable will be set to provide more information.
  199. --*/
  200. {
  201. wchar_t *Result;
  202. ClpLockStream(Stream);
  203. Result = fgetws_unlocked(Buffer, ElementCount, Stream);
  204. ClpUnlockStream(Stream);
  205. return Result;
  206. }
  207. LIBC_API
  208. wchar_t *
  209. fgetws_unlocked (
  210. wchar_t *Buffer,
  211. int ElementCount,
  212. FILE *Stream
  213. )
  214. /*++
  215. Routine Description:
  216. This routine reads wide characters out of the given stream until a newline
  217. or the maximum number of elements minus one is read. Then the string is
  218. null terminated. This routine does not acquire the stream lock.
  219. Arguments:
  220. Buffer - Supplies a pointer to the wide character array where the read
  221. characters will be returned.
  222. ElementCount - Supplies the maximum number of wide characters to return in
  223. the given buffer.
  224. Stream - Supplies a pointer to the file stream to read from.
  225. Return Value:
  226. Returns a pointer to the input buffer on success.
  227. NULL if a read error occurs or the end of the file is reached. If at the
  228. end of the file, the end of file indicator will be set on the stream. If an
  229. error occurs, he error indicator will be set for the stream, and the errno
  230. variable will be set to provide more information.
  231. --*/
  232. {
  233. wint_t Character;
  234. int Index;
  235. Character = WEOF;
  236. if ((Buffer == NULL) || (ElementCount < 1)) {
  237. return NULL;
  238. }
  239. //
  240. // Loop reading in characters until the buffer is full.
  241. //
  242. for (Index = 0; Index < ElementCount - 1; Index += 1) {
  243. Character = fgetwc_unlocked(Stream);
  244. if (Character == WEOF) {
  245. break;
  246. }
  247. Buffer[Index] = Character;
  248. Index += 1;
  249. if (Character == L'\n') {
  250. break;
  251. }
  252. }
  253. Buffer[Index] = L'\0';
  254. if (Character == WEOF) {
  255. return NULL;
  256. }
  257. return Buffer;
  258. }
  259. LIBC_API
  260. wint_t
  261. fputwc (
  262. wchar_t WideCharacter,
  263. FILE *Stream
  264. )
  265. /*++
  266. Routine Description:
  267. This routine writes the given wide character out to the given stream.
  268. Arguments:
  269. WideCharacter - Supplies the wide character to write.
  270. Stream - Supplies the stream to write to.
  271. Return Value:
  272. Returns the wide character on success.
  273. EOF on error. The error indicator for the stream will be set and errno will
  274. be set to contain more information.
  275. --*/
  276. {
  277. wint_t Result;
  278. ClpLockStream(Stream);
  279. Result = fputwc_unlocked(WideCharacter, Stream);
  280. ClpUnlockStream(Stream);
  281. return Result;
  282. }
  283. LIBC_API
  284. wint_t
  285. fputwc_unlocked (
  286. wchar_t WideCharacter,
  287. FILE *Stream
  288. )
  289. /*++
  290. Routine Description:
  291. This routine writes the given wide character out to the given stream
  292. without acquiring the stream lock.
  293. Arguments:
  294. WideCharacter - Supplies the wide character to write.
  295. Stream - Supplies the stream to write to.
  296. Return Value:
  297. Returns the wide character on success.
  298. WEOF on error. The error indicator for the stream will be set and errno will
  299. be set to contain more information.
  300. --*/
  301. {
  302. CHAR Buffer[MB_LEN_MAX];
  303. ULONG ByteIndex;
  304. size_t Length;
  305. size_t Result;
  306. ORIENT_STREAM(Stream, FILE_FLAG_WIDE_ORIENTED);
  307. //
  308. // Convert the wide character to a multibyte sequence.
  309. //
  310. Length = wcrtomb(Buffer, WideCharacter, &(Stream->ShiftState));
  311. if (Length == -1) {
  312. Stream->Flags |= FILE_FLAG_ERROR;
  313. return WEOF;
  314. }
  315. //
  316. // Write the bytes out.
  317. //
  318. for (ByteIndex = 0; ByteIndex < Length; ByteIndex += 1) {
  319. Result = fputc_unlocked(Buffer[ByteIndex], Stream);
  320. if (Result == EOF) {
  321. return WEOF;
  322. }
  323. }
  324. return WideCharacter;
  325. }
  326. LIBC_API
  327. wint_t
  328. putwc (
  329. wchar_t Character,
  330. FILE *Stream
  331. )
  332. /*++
  333. Routine Description:
  334. This routine writes a wide character to the given file stream. It is
  335. equivalent to the fputwc function.
  336. Arguments:
  337. Character - Supplies the character to write.
  338. Stream - Supplies the stream to write the character to.
  339. Return Value:
  340. Returns the character it has written on success.
  341. WEOF on failure, and errno will contain more information.
  342. --*/
  343. {
  344. return fputwc(Character, Stream);
  345. }
  346. LIBC_API
  347. wint_t
  348. putwchar (
  349. wchar_t Character
  350. )
  351. /*++
  352. Routine Description:
  353. This routine writes a wide character to standard out. This routine is
  354. equivalent to fputwc(Character, stdout).
  355. Arguments:
  356. Character - Supplies the character to write.
  357. Return Value:
  358. Returns the character it has written on success.
  359. WEOF on failure, and errno will contain more information.
  360. --*/
  361. {
  362. return fputwc(Character, stdout);
  363. }
  364. LIBC_API
  365. int
  366. fputws (
  367. const wchar_t *WideString,
  368. FILE *Stream
  369. )
  370. /*++
  371. Routine Description:
  372. This routine writes the given null-terminated wide character string to the
  373. given stream.
  374. Arguments:
  375. WideString - Supplies a pointer to the null terminated wide string to write.
  376. The null terminator itself will not be written.
  377. Stream - Supplies the stream to write to.
  378. Return Value:
  379. Returns a non-negative number on success.
  380. -1 on failure, and errno will be set to contain more information. The error
  381. indicator for the stream will also be set.
  382. --*/
  383. {
  384. int Result;
  385. ClpLockStream(Stream);
  386. Result = fputws_unlocked(WideString, Stream);
  387. ClpUnlockStream(Stream);
  388. return Result;
  389. }
  390. LIBC_API
  391. int
  392. fputws_unlocked (
  393. const wchar_t *WideString,
  394. FILE *Stream
  395. )
  396. /*++
  397. Routine Description:
  398. This routine writes the given null-terminated wide character string to the
  399. given stream. This routine does not acquire the stream lock.
  400. Arguments:
  401. WideString - Supplies a pointer to the null terminated wide string to write.
  402. The null terminator itself will not be written.
  403. Stream - Supplies the stream to write to.
  404. Return Value:
  405. Returns a non-negative number on success.
  406. -1 on failure, and errno will be set to contain more information. The error
  407. indicator for the stream will also be set.
  408. --*/
  409. {
  410. wint_t Result;
  411. if (WideString == NULL) {
  412. return 0;
  413. }
  414. while (*WideString != L'\0') {
  415. Result = fputwc_unlocked(*WideString, Stream);
  416. if (Result == WEOF) {
  417. return -1;
  418. }
  419. WideString += 1;
  420. }
  421. return 0;
  422. }
  423. LIBC_API
  424. wint_t
  425. ungetwc (
  426. wint_t Character,
  427. FILE *Stream
  428. )
  429. /*++
  430. Routine Description:
  431. This routine pushes the specified wide character back onto the input
  432. stream. The pushed back character shall be returned by subsequent reads on
  433. that stream in the reverse order of their pushing. A successful intervening
  434. call seek or flush will discard any pushed back bytes for the stream. One
  435. character of push back is provided.
  436. Arguments:
  437. Character - Supplies the character (converted to a wchar_t) to push back.
  438. Stream - Supplies the stream to push the character on to.
  439. Return Value:
  440. Returns the character pushed back on success.
  441. EOF on failure, and errno will contain more information.
  442. --*/
  443. {
  444. int Result;
  445. ClpLockStream(Stream);
  446. Result = ungetwc_unlocked(Character, Stream);
  447. ClpUnlockStream(Stream);
  448. return Result;
  449. }
  450. LIBC_API
  451. wint_t
  452. ungetwc_unlocked (
  453. wint_t Character,
  454. FILE *Stream
  455. )
  456. /*++
  457. Routine Description:
  458. This routine pushes the specified wide character back onto the input
  459. stream. The pushed back character shall be returned by subsequent reads on
  460. that stream in the reverse order of their pushing. A successful intervening
  461. call seek or flush will discard any pushed back bytes for the stream. One
  462. character of push back is provided. This routine does not acquire the
  463. internal stream lock.
  464. Arguments:
  465. Character - Supplies the character (converted to a wchar_t) to push back.
  466. Stream - Supplies the stream to push the character on to.
  467. Return Value:
  468. Returns the character pushed back on success.
  469. EOF on failure, and errno will contain more information.
  470. --*/
  471. {
  472. if (Character == WEOF) {
  473. return WEOF;
  474. }
  475. ORIENT_STREAM(Stream, FILE_FLAG_BYTE_ORIENTED);
  476. if ((Stream->Flags & FILE_FLAG_UNGET_VALID) == 0) {
  477. Stream->Flags |= FILE_FLAG_UNGET_VALID;
  478. Stream->Flags &= ~FILE_FLAG_END_OF_FILE;
  479. Stream->UngetCharacter = (wchar_t)Character;
  480. return (wchar_t)Character;
  481. }
  482. return WEOF;
  483. }
  484. LIBC_API
  485. int
  486. fwide (
  487. FILE *Stream,
  488. int Mode
  489. )
  490. /*++
  491. Routine Description:
  492. This routine determines and potentially sets the orientation of the given
  493. stream.
  494. Arguments:
  495. Stream - Supplies a pointer to the stream.
  496. Mode - Supplies an operation to perform. If this parameter is greater than
  497. zero, then this routine will attempt to make the stream wide-oriented.
  498. If this parameter is less than zero, this routine will attempt to make
  499. the stream byte oriented. If this parameter is 0, no change will be
  500. made to the stream's orientation.
  501. Return Value:
  502. >0 if after this call the stream is wide-oriented.
  503. <0 if after this call the stream is byte-oriented.
  504. 0 if the stream has no orientation.
  505. --*/
  506. {
  507. ULONG OrientationFlags;
  508. if (Mode > 0) {
  509. ORIENT_STREAM(Stream, FILE_FLAG_WIDE_ORIENTED);
  510. } else if (Mode < 0) {
  511. ORIENT_STREAM(Stream, FILE_FLAG_BYTE_ORIENTED);
  512. }
  513. OrientationFlags = Stream->Flags;
  514. if ((OrientationFlags & FILE_FLAG_WIDE_ORIENTED) != 0) {
  515. return 1;
  516. } else if ((OrientationFlags & FILE_FLAG_BYTE_ORIENTED) != 0) {
  517. return -1;
  518. }
  519. return 0;
  520. }
  521. LIBC_API
  522. int
  523. wprintf (
  524. const wchar_t *Format,
  525. ...
  526. )
  527. /*++
  528. Routine Description:
  529. This routine prints a formatted wide string to the standard output file
  530. stream.
  531. Arguments:
  532. Format - Supplies the printf wide format string.
  533. ... - Supplies a variable number of arguments, as required by the printf
  534. format string argument.
  535. Return Value:
  536. Returns the number of wide characters successfully converted, not
  537. including the null terminator.
  538. Returns a negative number if an error was encountered.
  539. --*/
  540. {
  541. va_list Arguments;
  542. int Result;
  543. va_start(Arguments, Format);
  544. Result = vfwprintf(stdout, Format, Arguments);
  545. va_end(Arguments);
  546. return Result;
  547. }
  548. LIBC_API
  549. int
  550. fwprintf (
  551. FILE *Stream,
  552. const wchar_t *Format,
  553. ...
  554. )
  555. /*++
  556. Routine Description:
  557. This routine prints a formatted wide string to the given file stream.
  558. Arguments:
  559. Stream - Supplies the file stream to print to.
  560. Format - Supplies the printf wide format string.
  561. ... - Supplies a variable number of arguments, as required by the printf
  562. format string argument.
  563. Return Value:
  564. Returns the number of wide characters successfully converted, not
  565. including the null terminator.
  566. Returns a negative number if an error was encountered.
  567. --*/
  568. {
  569. va_list Arguments;
  570. int Result;
  571. va_start(Arguments, Format);
  572. Result = vfwprintf(Stream, Format, Arguments);
  573. va_end(Arguments);
  574. return Result;
  575. }
  576. LIBC_API
  577. int
  578. vfwprintf (
  579. FILE *File,
  580. const wchar_t *Format,
  581. va_list Arguments
  582. )
  583. /*++
  584. Routine Description:
  585. This routine prints a formatted wide string to the given file pointer.
  586. Arguments:
  587. File - Supplies a pointer to the file stream to output to.
  588. Format - Supplies the printf wide format string.
  589. Arguments - Supplies the argument list to the format string. The va_end
  590. macro is not invoked on this list.
  591. Return Value:
  592. Returns the number of wide characters successfully converted, not
  593. including the null terminator.
  594. Returns a negative number if an error was encountered.
  595. --*/
  596. {
  597. int Result;
  598. ClpLockStream(File);
  599. Result = vfwprintf_unlocked(File, Format, Arguments);
  600. ClpUnlockStream(File);
  601. return Result;
  602. }
  603. LIBC_API
  604. int
  605. vfwprintf_unlocked (
  606. FILE *File,
  607. const wchar_t *Format,
  608. va_list Arguments
  609. )
  610. /*++
  611. Routine Description:
  612. This routine prints a formatted wide string to the given file pointer. This
  613. routine does not acquire the stream lock.
  614. Arguments:
  615. File - Supplies a pointer to the file stream to output to.
  616. Format - Supplies the printf wide format string.
  617. Arguments - Supplies the argument list to the format string. The va_end
  618. macro is not invoked on this list.
  619. Return Value:
  620. Returns the number of wide characters successfully converted, not
  621. including the null terminator.
  622. Returns a negative number if an error was encountered.
  623. --*/
  624. {
  625. PRINT_FORMAT_CONTEXT PrintContext;
  626. memset(&PrintContext, 0, sizeof(PRINT_FORMAT_CONTEXT));
  627. PrintContext.Context = File;
  628. PrintContext.WriteCharacter = ClpFileFormatWriteWideCharacter;
  629. RtlFormatWide(&PrintContext, (PWSTR)Format, Arguments);
  630. return PrintContext.CharactersWritten;
  631. }
  632. LIBC_API
  633. int
  634. vwprintf (
  635. const wchar_t *Format,
  636. va_list Arguments
  637. )
  638. /*++
  639. Routine Description:
  640. This routine prints a formatted wide string to the standard output file
  641. stream.
  642. Arguments:
  643. Format - Supplies the printf wide format string.
  644. Arguments - Supplies the argument list to the format string. The va_end
  645. macro is not invoked on this list.
  646. Return Value:
  647. Returns the number of wide characters successfully converted, not
  648. including the null terminator.
  649. Returns a negative number if an error was encountered.
  650. --*/
  651. {
  652. return vfwprintf(stdout, Format, Arguments);
  653. }
  654. LIBC_API
  655. int
  656. swprintf (
  657. wchar_t *OutputString,
  658. size_t OutputStringCount,
  659. const wchar_t *Format,
  660. ...
  661. )
  662. /*++
  663. Routine Description:
  664. This routine prints a formatted wide string to the given bounded buffer.
  665. Arguments:
  666. OutputString - Supplies the buffer where the formatted wide string will be
  667. returned.
  668. OutputStringCount - Supplies the number of wide characters that can fit in
  669. the output buffer.
  670. Format - Supplies the printf wide format string.
  671. ... - Supplies a variable number of arguments, as required by the printf
  672. format string argument.
  673. Return Value:
  674. Returns the number of wide characters successfully converted, not
  675. including the null terminator.
  676. Returns a negative number if OutputStringCount or more wide characters
  677. needed to be converted or if an error was encountered.
  678. --*/
  679. {
  680. va_list Arguments;
  681. int Result;
  682. va_start(Arguments, Format);
  683. Result = vswprintf(OutputString, OutputStringCount, Format, Arguments);
  684. va_end(Arguments);
  685. return Result;
  686. }
  687. LIBC_API
  688. int
  689. vswprintf (
  690. wchar_t *OutputString,
  691. size_t OutputStringSize,
  692. const wchar_t *Format,
  693. va_list Arguments
  694. )
  695. /*++
  696. Routine Description:
  697. This routine implements the core string print format function.
  698. Arguments:
  699. OutputString - Supplies a pointer to the buffer where the resulting string
  700. will be written.
  701. OutputStringSize - Supplies the size of the output string buffer, in bytes.
  702. If the format is too long for the output buffer, the resulting string
  703. will be truncated and the last byte will always be a null terminator.
  704. Format - Supplies the printf format string.
  705. Arguments - Supplies the argument list to the format string. The va_end
  706. macro is not invoked on this list.
  707. Return Value:
  708. Returns the number of wide characters successfully converted, not
  709. including the null terminator.
  710. Returns a negative number if OutputStringCount or more wide characters
  711. needed to be converted or if an error was encountered.
  712. --*/
  713. {
  714. ULONG Result;
  715. Result = RtlFormatStringWide(OutputString,
  716. OutputStringSize,
  717. CharacterEncodingDefault,
  718. (PWSTR)Format,
  719. Arguments);
  720. if (Result > OutputStringSize) {
  721. return -1;
  722. }
  723. return Result - 1;
  724. }
  725. //
  726. // --------------------------------------------------------- Internal Functions
  727. //
  728. BOOL
  729. ClpFileFormatWriteWideCharacter (
  730. INT Character,
  731. PPRINT_FORMAT_CONTEXT Context
  732. )
  733. /*++
  734. Routine Description:
  735. This routine writes a wide character to the output during a printf-style
  736. formatting operation.
  737. Arguments:
  738. Character - Supplies the character to be written.
  739. Context - Supplies a pointer to the printf-context.
  740. Return Value:
  741. TRUE on success.
  742. FALSE on failure.
  743. --*/
  744. {
  745. if (fputwc_unlocked(Character, Context->Context) == -1) {
  746. return FALSE;
  747. }
  748. return TRUE;
  749. }