On 24 Aug 2015, at 5:19 , Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:


On 24 Aug 2015, at 4:59 , Ben Coman <btc@openInWorld.com> wrote:


(CC'd vm-dev)

On Mon, Aug 24, 2015 at 12:09 AM, Nicolai Hess <nicolaihess@web.de> wrote:
And If you want to review the changes:

https://github.com/nicolaihess/pharo-vm/compare/master...nicolaihess:win-long-filename

I don't have a Windows machine to test on, but I perused the changes.
one spelling defect ../platforms/win32/vm/sqWin32.h, line 452 "functiosn"

Now my curiosity is aroused regarding sqFileDeleteNameSize() in [1].
Where does its parameter "char* fileNameIndex" get its null termination?
I can only guess maybe the following definition in primitiveFileDelete.st [2]
   <var: 'nameIndex' type: 'char *'>
automatically appends a null to the Smalltalk string. My understanding
is that the Smalltalk string's internal representation is not null
terminated.

I ask since the sqFileDeleteNameSize()'s comment "convert the file
name into a null-terminated C string" indicates the null is added by
MultiByteToWideChar(), but [3] indicates that is not true -- that the
output of MultiByteToWideChar() is only null terminated if the input
is null terminated.


That's not what 3 indicates, the way I read it:
"cbMultiByte [in]
Size, in bytes, of the string indicated by the lpMultiByteStr parameter. Alternatively, this parameter can be set to -1 if the string is null-terminated. "
"cchWideChar [in] 
Size, in characters, of the buffer indicated by lpWideCharStr. If this value is 0, the function returns the required buffer size, in characters, including any terminating null character"

So we first make a call using cbMultiByte > 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)
Then create that buffer, assign it to win32Path, and convert into it the CONVERT_MULTIBYTE_TO_WIDECHAR_PATH macro.

The Win APIs are written in a way that they seldom (never?) allocate memory, instead you'll see this pattern of "call me once with size = NULL to get the required size, then allocate and call me again with the actual pointer/size"

Cheers,
Henry

And I guess I would be wrong, reading a bit further:
"MultiByteToWideChar 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."

It is handled in the macro though, which adds the null terminator:

buffer = (WCHAR*)malloc((size+ LONG_PATH_PREFIX_SIZE +1)*sizeof(WCHAR));\ buffer[size + 4] = 0;\

Cheers,Henry