<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 24, 2015 at 11:44 PM, Henrik Johansen <span dir="ltr">&lt;<a href="mailto:henrik.s.johansen@veloxit.no" target="_blank">henrik.s.johansen@veloxit.no</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br><div style="word-wrap:break-word"><br><div><blockquote type="cite"><div>On 24 Aug 2015, at 5:19 , Henrik Johansen &lt;<a href="mailto:henrik.s.johansen@veloxit.no" target="_blank">henrik.s.johansen@veloxit.no</a>&gt; wrote:</div><br><div><div style="word-wrap:break-word"><br><div><div><blockquote type="cite"><div>On 24 Aug 2015, at 4:59 , Ben Coman &lt;<a href="mailto:btc@openInWorld.com" target="_blank">btc@openInWorld.com</a>&gt; wrote:</div><br><div><br>(CC&#39;d vm-dev)<br><br>On Mon, Aug 24, 2015 at 12:09 AM, Nicolai Hess &lt;<a href="mailto:nicolaihess@web.de" target="_blank">nicolaihess@web.de</a>&gt; wrote:<br><blockquote type="cite">And If you want to review the changes:<br><br><a href="https://github.com/nicolaihess/pharo-vm/compare/master...nicolaihess:win-long-filename" target="_blank">https://github.com/nicolaihess/pharo-vm/compare/master...nicolaihess:win-long-filename</a><br></blockquote><br>I don&#39;t have a Windows machine to test on, but I perused the changes.<br>one spelling defect ../platforms/win32/vm/sqWin32.h, line 452 &quot;functiosn&quot;<br><br>Now my curiosity is aroused regarding sqFileDeleteNameSize() in [1].<br>Where does its parameter &quot;char* fileNameIndex&quot; get its null termination?<br>I can only guess maybe the following definition in primitiveFileDelete.st [2]<br>    &lt;var: &#39;nameIndex&#39; type: &#39;char *&#39;&gt;<br>automatically appends a null to the Smalltalk string. My understanding<br>is that the Smalltalk string&#39;s internal representation is not null<br>terminated.<br><br>I ask since the sqFileDeleteNameSize()&#39;s comment &quot;convert the file<br>name into a null-terminated C string&quot; indicates the null is added by<br>MultiByteToWideChar(), but [3] indicates that is not true -- that the<br>output of MultiByteToWideChar() is only null terminated if the input<br>is null terminated.</div></blockquote><br></div><div><br></div><div>That&#39;s not what 3 indicates, the way I read it:<div>&quot;<em style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0059986114502px">cbMultiByte</em><span style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0059986114502px"> </span><span style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0059986114502px">[in]</span><dd style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0059986114502px"><div style="margin:0px;padding-bottom:15px;line-height:1.429em!important">Size, in bytes, of the string indicated by the <em>lpMultiByteStr</em> parameter. Alternatively, this parameter can be set to -1 <b>if the string is null-terminated.</b> &quot;</div></dd></div><div><em style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0059986114502px">&quot;cchWideChar</em><span style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0059986114502px"> [in] </span></div><div><span style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0060005187988px"><span style="white-space:pre-wrap">        </span>Size, in characters, of the buffer indicated by </span><em style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0060005187988px">lpWideCharStr</em><span style="color:rgb(69,69,69);font-family:&#39;Segoe UI&#39;,&#39;Lucida Grande&#39;,Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:20.0060005187988px">. If this value is 0, the function returns the required buffer size, in characters, <b>including any terminating null character</b>&quot;</span></div></div><br></div><div>So we first make a call using cbMultiByte &gt; 0  and cchWideChar = 0, which then returns the size of null-terminated WCHAR-buffer needed to hold the conversion of non-null terminated (but sized) parameter. (sz = size)</div><div>Then create that buffer, assign it to win32Path, and convert into it the <span style="line-height:16.7999992370605px;white-space:pre-wrap;background-color:rgb(234,255,234)">CONVERT_MULTIBYTE_TO_WIDECHAR_PATH macro.</span></div><div><span style="line-height:16.7999992370605px;white-space:pre-wrap;background-color:rgb(234,255,234)"><br></span></div><div><span style="line-height:16.7999992370605px;white-space:pre-wrap;background-color:rgb(234,255,234)">The Win APIs are written in a way that they seldom (never?) allocate memory, instead you&#39;ll see this pattern of &quot;call me once with size = NULL to get the required size, then allocate and call me again with the actual pointer/size&quot;</span></div><div><span style="line-height:16.7999992370605px;white-space:pre-wrap;background-color:rgb(234,255,234)"><br></span></div><div><span style="line-height:16.7999992370605px;white-space:pre-wrap;background-color:rgb(234,255,234)">Cheers,</span></div><div><span style="line-height:16.7999992370605px;white-space:pre-wrap;background-color:rgb(234,255,234)">Henry</span></div></div></div></blockquote><br></div><div>And I guess I would be wrong, reading a bit further:</div><div><strong style="color:rgb(69,69,69);line-height:20.0060005187988px">&quot;MultiByteToWideChar</strong><span style="color:rgb(69,69,69);line-height:20.0060005187988px"> does not null-terminate an output string if the input string length is explicitly specified without a terminating null character. To null-terminate an output string for this function, the application should pass in -1 or explicitly count the terminating null character for the input string.&quot;</span></div><br><div>It is handled in the macro though, which adds the null terminator:</div><div><br></div><div><table style="border-spacing:0px;width:918px;color:rgb(51,51,51);font-family:Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:13px;line-height:18.2000007629395px;background-color:rgb(255,255,255)"><tbody><tr><td style="padding:0px 10px;vertical-align:top;background-color:rgb(234,255,234)"><span style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:12px;white-space:pre-wrap;overflow:visible;word-wrap:normal">buffer = (WCHAR*)<span style="color:rgb(0,134,179)">malloc</span>((size+ <span style="color:rgb(121,93,163);line-height:16.7999992370605px">LONG_PATH_PREFIX_SIZE</span> <span style="line-height:18.2000007629395px">+</span><span style="line-height:18.2000007629395px;color:rgb(0,134,179)">1</span><span style="line-height:18.2000007629395px">)*</span><span style="line-height:18.2000007629395px;color:rgb(167,29,93)">sizeof</span><span style="line-height:18.2000007629395px">(WCHAR));\</span><font color="#0086b3">
</font>buffer[size + <span style="color:rgb(0,134,179)">4</span>] = <span style="color:rgb(0,134,179)">0</span>;\<br></span></td></tr></tbody></table><div><br></div></div><div><br></div></div></blockquote><div><br></div><div>doh! I was looking for that and didn&#39;t recognise it. </div><div>Thanks Henry.</div></div><br></div></div>