    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Use UTF-16 Interfaces to Ship Windows Code</title>
        <link>https://members.accu.org/index.php/articles/2660</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #151 - June 2019</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c399/">o151</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-399/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+399/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Use UTF-16 Interfaces to Ship Windows Code</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 03 June 2019 19:01:46 +01:00 or Mon, 03 June 2019 19:01:46 +01:00</p>
<p><strong>Summary:</strong>&nbsp;Character encoding can cause problems. PÃ©ter Ã‰sik explains why UTF-16 interfaces help on Windows.</p>
<p><strong>Body:</strong>&nbsp;<p>Listing 1 is a small program that takes a file path as a parameter, and queries its size. Even though <code>stat</code> is a POSIX function, it happens to be available on Windows as well, so this small program works on both POSIX platforms and Windows. Or does it? Letâ€™s try it out with two test files. For <span class="filename">test.txt</span>, it correctly reports the fileâ€™s size. For <span class="filename">Hello, </span>Ð¼Ð¸Ñ€<span class="filename">.txt</span>, however, the <code>stat</code> call fails (on my machine), even though the file clearly exists (see Figure 1). Why is that?</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;sys/stat.h&gt;

int main (int /*argc*/, char* argv[])
{
  struct stat fileInfo;
  if (stat (argv[1], &amp;fileInfo) == 0) {
     std::cout &lt;&lt; &quot;The file's size is: &quot; 
       &lt;&lt; fileInfo.st_size &lt;&lt; &quot; bytes\n&quot;;
  } else {
    std::cout &lt;&lt; &quot;Unable to stat file (maybe it
      doesn't exist?)\n&quot;;
  }
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<table class="sidebartable">
	<tr>
		<td><img src="/content/images/journals/ol151/Esik/Esik-01.png" /></td>
	</tr>
	<tr>
		<td class="title">Figure 1</td>
	</tr>
</table>

<h2>The â€˜ANSIâ€™ vs. UTF-16 story in five minutes (or less)</h2>

<p>Back in the day, character encodings were quite rudimentary. The first encoding widely adopted by computer systems was ASCII [<a href="#[Wikipedia-1]">Wikipedia-1</a>] (a 7-bit encoding) , capable of encoding the English alphabet and some other characters (numbers, mathematical symbols, control characters, etc.). Of course, the obvious need arose to encode more characters as users expected computers to speak their language, to type their native letters in e-mails, etc. 8-bit encodings provided a partial solution: code points 0â€“127 were the same as ASCII (for compatibility), while extra characters were encoded in the range 128â€“255.<a href="#FN01"><sup>1</sup></a> Those extra 128 code points were not enough to encode all letters of all languages at once, so character mappings were applied, most commonly known as code pages.</p>

<p>This means that a character or a string thatâ€™s encoded like this has no meaning in itself, you need to know what code page to interpret it with (this is somewhat analogous with files and their extensions). For example, code point 0x8A means Ã¤ (lowercase a with an umlaut) if you interpret it using the Macintosh Central European encoding [<a href="#[Wikipedia-2]">Wikipedia-2</a>], but encodes Å  (uppercase S with caron) if you use the Windows-1252 [<a href="#[Wikipedia-3]">Wikipedia-3</a>] (Latin alphabet) code page.</p>

<p>This approach has two obvious problems: first, itâ€™s easy to get encodings wrong (for instance, .txt files have no header, so you simply canâ€™t store the code page used), resulting in so-called mojibake [<a href="#[Wikipedia-4]">Wikipedia-4</a>]. Second, you canâ€™t mix and match characters with different encodings easily. For example, if you wanted to encode the string &quot;Ð¨Ð½ÑƒÑ€ÐºÐ¸ means cipÅ‘fÅ±zÅ‘&quot; (with Windows code pages), you would have to encode &quot;Ð¨Ð½ÑƒÑ€ÐºÐ¸&quot; with code page 1251 (Windows Cyrillic) [<a href="#[Wikipedia-5]">Wikipedia-5</a>], &quot; means &quot; with a code page of your choice (as it contains ASCII characters only), and &quot;cipÅ‘fÅ±zÅ‘&quot; with code page 1250 (Windows Central European) [<a href="#[Wikipedia-6]">Wikipedia-6</a>]. To correctly decode and display this string later, you would have to store which code pages were used for which parts, making string handling inefficient and extremely complex.</p>

<p>Because of problems like these, encodings were desired that could represent â€˜allâ€™ characters at once. One of these emerging encodings was UCS-2 (by the Unicode working group), which used 16-bit wide code units and code points. Windows adopted UCS-2 quite early, Windows NT 3.1 (the very first OS of the NT series, released in 1993) and its file system, NTFS, used it internally. Even though the 32-bit Windows API debuted with NT 3.1 as brand new, support for 8-bit encodings was still necessary.<a href="#FN02"><sup>2</sup></a> As UCS-2 used 16-bit code units, and the C language does not support function overloading, Microsoft introduced two versions of every API function that had to work with strings (either directly or indirectly): a UCS-2 version, with a W suffix (â€˜wideâ€™, working with <code>wchar_t</code> strings), and one for 8-bit code paged strings, with an A suffix (â€˜ANSIâ€™<a href="#FN03"><sup>3</sup></a>, working with <code>char</code> strings).</p>

<p>The A functions act as mere wrappers, usually<a href="#FN04"><sup>4</sup></a> they just convert the string parameters and forward the call to the corresponding W version. So for example, there is no such function as <code>MessageBox</code>, there is only <code>MessageBoxA</code>, and <code>MessageBoxW</code>. Depending on the strings you have, you need to call the appropriate version of the two.<a href="#FN05"><sup>5</sup></a></p>

<p>Which code page is used to interpret strings in the A family of functions? Is there a code page parameter passed? No, they use a system-wide setting called the <em>active code page</em>, located in the registry at HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\ACP. This value is decided based on your region you choose at installation time, but can also be changed later in the Control Panel.</p>

<p>Eventually, UCS-2 evolved into UTF-16, and starting with Windows 2000, the OS had support for it. Since UCS-2 is fully compatible with UTF-16, programs didnâ€™t need to be rewritten or even recompiled.</p>

<h2>Back to the test program</h2>

<p>Armed with this knowledge, itâ€™s easy to see why the small test program doesnâ€™t work for certain files. This is what happens:</p>

<ol>
	<li>The program is started (with whatever parameters).</li>
	<li>Very early in the startup phase, Windows converts the (native) UTF-16 command line to an â€˜ANSIâ€™ string using the active code page, and stores it in a global variable.</li>
	<li>Because regular <code>main</code> was used (with â€˜narrowâ€™, <code>char</code> parameters) in this application, early in the startup phase the CRT queries the command line with <code>GetCommandLineA</code> (this just returns the global that was set up by the previous step), converts it into an array, and passes it down to <code>main</code>.</li>
</ol>

<p>The problem is that there might be characters in the UTF-16 command line that have no representation in the currently active code page. For example, my computerâ€™s locale is set to Hungarian, therefore my ACP is 1250 (Windows Central European) [<a href="#[Wikipedia-6]">Wikipedia-6</a>]. Cyrillic characters such as Ð¼, Ð¸, and Ñ€ have no representation in this encoding, so when the UTF-16 to â€˜ANSIâ€™ conversion is performed, these characters are replaced with question marks (see Figure 2).<a href="#FN06"><sup>6</sup></a> When <code>stat</code> is called with the string <code>&quot;D:\temp\temp\Hello, ???.txt&quot;</code> (which by the way involves an â€˜ANSIâ€™ to UTF-16 conversion internally), of course it fails, because there is no file named <span class="filename">Hello, ???.txt</span> in that directory.</p>

<table class="sidebartable">
	<tr>
		<td><img src="/content/images/journals/ol151/Esik/Esik-02.png" /></td>
	</tr>
	<tr>
		<td class="title">Figure 2</td>
	</tr>
</table>

<h2>cURL</h2>

<p>Itâ€™s not that hard to bump into applications or libraries suffering from these problems. cURL, for example, is one of them. Now donâ€™t get me wrong, Iâ€™m in no way saying that itâ€™s a badly written piece of software, quite the contrary. Itâ€™s a battle-tested, popular open source project with a long history and a plethora of users. Actually, I think this is what makes it a perfect example: even if your code is spot on, this aspect of shipping to Windows is very easy to overlook.</p>

<p>For file IO, cURL uses standard C functions (such as <code>fopen</code>). This means that for example, if you want your requestâ€™s result written into an output file, it will fail if the fileâ€™s path contains characters not representable with the systemâ€™s current â€˜ANSIâ€™ code page.</p>

<p>Another example is IDN (internationalized domain name) handling. cURL does support IDNs, but letâ€™s see what happens if I try it out using the standalone command line version (see Figure 3).</p>

<table class="sidebartable">
	<tr>
		<td><img src="/content/images/journals/ol151/Esik/Esik-03.png" /></td>
	</tr>
	<tr>
		<td class="title">Figure 3</td>
	</tr>
</table>

<p> Even though <span class="filename">magyarorszÃ¡g.icom.museum</span> exists, and its string form is perfectly representable with my machineâ€™s ACP (1250), cURL fails with an error. Looking at the source code quickly reveals the culprit:</p>

<ul>
	<li>cURL needs to convert the IDN to so-called Punycode [<a href="#[Wikipedia-7]"></a>Wikipedia-7] before issuing the request.</li>
	<li>It does so with <code>IdnToAscii</code> [<a href="#[WindowsDev]">WindowsDev</a>], but this function expects a UTF-16 input string.</li>
	<li>Even though the original string (which originates from the command line parameter) is an â€˜ANSIâ€™ string, conversion to UTF-16 is attempted assuming itâ€™s UTF-8. This makes the conversion fail, and thus cURL aborts with an error message.</li>
</ul>

<p>cURL developers are aware of this category of problems: itâ€™s listed on their known bugs page [<a href="#[curl]">curl</a>].</p>

<h2>Solution</h2>

<p>The solution is in the title of this article: use UTF-16 (native) interfaces on Windows. That is:</p>

<ul>
	<li>Instead of regular <code>main</code>, use <code>wmain</code> as an entry point, which has <code>wchar_t</code> string arguments.</li>
	
	<li>Always use the wide version of runtime functions (<code>_wfopen_s</code> over plain <code>fopen</code>, <code>wcslen</code> instead of <code>strlen</code>, etc.).</li>
	
	<li>If you need to call Win32 functions directly, never use the â€˜ANSIâ€™ version with the A suffix, use their UTF-16 counterparts (ending with W).</li>
</ul>

<p>While this sounds great on paper, there is a catch. You can only use these functions on Windows, as:</p>

<ul>
	<li>Some of the widechar runtime functions are Windows-only (such as <code>_wfopen</code>).</li>
	
	<li>The size and semantics of <code>wchar_t</code> are implementation defined. While on Windows itâ€™s a 2-byte type representing a UTF-16 code unit, on POSIX systems itâ€™s usually 4 bytes in size, embodying a UTF-32 code unit.</li>
</ul>

<p>One possible solution is to utilize <code>typedef</code>s and macros. See Listing 2.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#ifdef _WIN32

using nchar = wchar_t;
using nstring = std::wstring;

#define NSTRLITERAL(str) L##str
#define nfopen _wfopen
/* ... */

#else

using nchar = char;
using nstring = std::string;

#define NSTRLITERAL(str) str
#define nfopen fopen
/* ... */

#endif  // #ifdef _WIN32
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>This simple technique can go a long way (it can be done somewhat more elegantly, but you get the idea), unless you need to exchange strings between different platforms (over the network, serialization, etc.).</p>

<h2>Closing thoughts</h2>

<p>I know some people think that the problem presented in this article is marginal, and using <code>char</code> strings and â€˜ANSIâ€™ interfaces on Windows is â€˜good enoughâ€™. Keep in mind though that in commercial environments the following situation is not that rare:</p>

<ul>
	<li>Company X outsources work to company Y, but they reside in different parts of the world.</li>
	
	<li>Therefore, the computers of company Y have a different ACP from those of company X.</li>
	
	<li>Itâ€™s very likely that the outsourced work involves using strings in company Xâ€™s locale, which will be problematic on Windows, if the software(s) used for doing said work misbehaves in this situation.</li>
</ul>

<p>Donâ€™t be surprised if a potential client of yours turns down a license purchase because of problems like this.</p>

<h2>References</h2>

<p class="bibliomixed"><a id="[curl]"></a>[curl] â€˜Known Bugsâ€™, curl: <a href="https://curl.haxx.se/docs/knownbugs.html#can_t_handle_Unicode_arguments_i">https://curl.haxx.se/docs/knownbugs.html#can_t_handle_Unicode_arguments_i</a></p>

<p class="bibliomixed"><a id="[Microsoft18]"></a>[Microsoft18] â€˜Working with stringsâ€™, published on 31 May 2018 at <a href="https://docs.microsoft.com/en-gb/windows/desktop/LearnWin32/working-with-strings">https://docs.microsoft.com/en-gb/windows/desktop/LearnWin32/working-with-strings</a></p>

<p class="bibliomixed"><a id="[Wikipedia-1]"></a>[Wikipedia-1] ASCII: <a href="https://en.wikipedia.org/wiki/ASCII">https://en.wikipedia.org/wiki/ASCII</a></p>

<p class="bibliomixed"><a id="[Wikipedia-2]"></a>[Wikipedia-2] Macintosh Central European Encoding: <a href="https://en.wikipedia.org/wiki/Macintosh_Central_European_encoding">https://en.wikipedia.org/wiki/Macintosh_Central_European_encoding</a></p>

<p class="bibliomixed"><a id="[Wikipedia-3]"></a>[Wikipedia-3] Windows -1252 code page: <a href="https://en.wikipedia.org/wiki/Windows-1252">https://en.wikipedia.org/wiki/Windows-1252</a></p>

<p class="bibliomixed"><a id="[Wikipedia-4]"></a>[Wikipedia-4] Mojibake: <a href="https://en.wikipedia.org/wiki/Mojibake">https://en.wikipedia.org/wiki/Mojibake</a></p>

<p class="bibliomixed"><a id="[Wikipedia-5]"></a>[Wikipedia-5] Windows-1251: <a href="https://en.wikipedia.org/wiki/Windows-1251">https://en.wikipedia.org/wiki/Windows-1251</a></p>

<p class="bibliomixed"><a id="[Wikipedia-6]"></a>[Wikipedia-6] Windows-1250: <a href="https://en.wikipedia.org/wiki/Windows-1250">https://en.wikipedia.org/wiki/Windows-1250</a></p>

<p class="bibliomixed"><a id="[Wikipedia-7]"></a>[Wikipedia-7] Punycode: <a href="https://en.wikipedia.org/wiki/Punycode">https://en.wikipedia.org/wiki/Punycode</a></p>

<p class="bibliomixed"><a id="[WindowsDev]"></a>[WindowsDev] IdnToAscii function, Windows Dev Center: <a href="https://docs.microsoft.com/en-gb/windows/desktop/api/winnls/nf-winnls-idntoascii">https://docs.microsoft.com/en-gb/windows/desktop/api/winnls/nf-winnls-idntoascii</a></p>

<p class="footnote"></p>

<ol>
	<li><a id="FN01"></a>There are some languages with much more symbols than 128 or 255 (Japanese, Chinese, etc.), which led to the invention of DBCS/MBCS character sets. Iâ€™m not mentioning them here for simplicity.</li>
	
	<li><a id="FN02"></a>One major reason for this was (other than UCS-2 not being widespread at the time) that the consumer line of Windows OSes (95, 98, etc.) had very limited support for UCS-2, but applications targeting Win32 had to run on both lines of Windows.</li>
	
	<li><a id="FN03"></a>Technically, itâ€™s not correct to call these functions â€˜ANSIâ€™ versions, as none of the supported code pages are ANSI standards. This term has historical roots, as the first Windows code page (1252) was based on an ANSI draft. On recent versions of Windows 10, the ACP can be set to UTF-8. Therefore, itâ€™s best to think about â€˜ANSI code pagesâ€™ as â€˜some encoding thatâ€™s not UTF-16â€™.</li>
	
	<li><a id="FN04"></a>One exception I know of is <code>OutputDebugString</code>, where the â€˜ANSIâ€™ version is the native one (<code>OutputDebugStringW</code> will convert to â€˜ANSIâ€™ and call <code>OutputDebugStringA</code>)</li>
	
	<li><a id="FN05"></a>Itâ€™s possible to create programs that can be compiled to support either the W or A interfaces without source changes, using predefined macros [<a href="#[Microsoft18]">Microsoft18</a>]. Nowadays, however, thatâ€™s highly irrelevant. If you are writing programs that target modern Windows versions (only NT), there is almost absolutely no reason to use A interfaces.</li>
	
	<li><a id="FN06"></a>The exact mappings are defined in <span class="filename">.nls</span> files located in the System32 directory.</li>
</ol>

<p class="bio"><span class="author"><b>PÃ©ter Ã‰sik</b></span> PÃ©ter has been working as a C++ software developer for 5 years. He has a knack for everything low level, including (but not limited to) OS internals, assembly, and post-mortem crash analysis. His blog can be found at <a href="http://peteronprogramming.wordpress.com">http://peteronprogramming.wordpress.com.</a></p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
