Hi Rob,
This is the reply from Hervé.
1) Windows doesn't have a isspaceW method, so I tested the iswspace method, which should be equivalent.
Test program: #include <stdio.h> #include <ctype.h>
int main(int argc, char *argv[]) { int space; space = iswspace(0xfeff); printf("iswspace(0xfeff) = %s\n", space ? "yes" : "no"); space = iswspace(L'a'); printf("iswspace(L'a') = %s\n", space ? "yes" : "no"); space = iswspace(L' '); printf("iswspace(L' ') = %s\n", space ? "yes" : "no"); return 0; }
Output on Windows XP SP2: iswspace(0xfeff) = no iswspace(L'a') = no iswspace(L' ') = yes
Output on ReactOS r18023 (2005/09/24) iswspace(0xfeff) = no iswspace(L'a') = no iswspace(L' ') = yes
Output on Wine 20050830 iswspace(0xfeff) = yes iswspace(L'a') = no iswspace(L' ') = yes
According to these results, I'm sure that the Wine implementation of iswspace is broken for some reason. I encourage Rob to use the above simple test program to make sure it works properly in Wine.
2) 0xfeff/0xfeff at the start of an UNICODE file is a BOM (Byte Order Marking). It tells you in which byte order is written the file. See http://www.elfdata.com/plugin/unicodefaqdata.html#whatisbom You can notice that "... The BOM can only be written at the start of a text file, before any other bytes. ..."
See also http://www.elfdata.com/plugin/unicodefaqdata.html#Z about the Zero-Width Non-breaking Space you were mentionning
3) - else err = parse_buffer( file, buffer, (WCHAR *)((char *)buffer + size), error_line ); + else + { + WCHAR *new_buff = (WCHAR *)buffer; + /* Some UNICODE files may start with the UNICODE marker */ + if (*new_buff == 0xfeff) + new_buff++; + err = parse_buffer( file, new_buff, (WCHAR *)((char *)new_buff + size), error_line ); + }
My patch skips only the BOM (when it exists). The patch is not related to ZWNBSP, so I don't want to use iswspace. I also don't intend to change the whole parsing of .inf file, as it already seems correct to me. If you prefer, I may change the patch to skip this 0xfeff header in parse_buffer (setupapi/parser.c), but I need to add a new state like file_start_state (FILE_START). However, my proposition seems ways lighter.
4) To finish this mail, you're right when you say that the following change is incorrect: WCHAR *new_buff = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ); if (new_buff) { - DWORD len = MultiByteToWideChar( CP_ACP, 0, buffer, size, new_buff, size ); + DWORD len = MultiByteToWideChar( CP_ACP, 0, buffer, size, new_buff, + size * sizeof(WCHAR) ); err = parse_buffer( file, new_buff, new_buff + len, error_line ); HeapFree( GetProcessHeap(), 0, new_buff ); } I shouldn't have done this change
Regards,
Hervé