Juan Lang wrote:
I'm trying to figure out why CompareStringA returns CSTR_EQUAL for the strings "\1" and "\2". (See bug 5469, and the todo_wine test case in dlls/kernel/tests/locale.c)
CompareStringA does the usual thing, calls MultiByteToWideChar and calls CompareStringW. So CompareStringW is comparing L"\0001" to L"\0002".
CompareStringW calls wine_compare_string, in libs/unicode/sortkey.c That calls compare_unicode_weights. That has this little bit of code: ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)]; ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
With the strings L"\0001" and L"\0002", *str1 is 0x0001, and *str2 is 0x0002. So *str1 >> 8 is 0, and *str2 >> 8 is 0. *str1 & 0xff is 0x01, *str2 & 0xff is 0x02. So, ce1 == collation_table[1], which is 0x00000300 (in collation.c), and ce2 == collation_table[2], which is 0x00000400.
You missed the two collation_table lookups. The first lookup is to find an index (the table is stored with some trivial compression). This will be 0x200 for both *str1 and *str2. Then the second lookup is done for collation_table[0x201] and collation_table[0x202] and these are both 0 (see the data beginning with line /* 0x0000 .. 0x00ff */ in collation.c).
Note that on Windows using CompareString on L"\0001\0002" and L"\0002\0001" gives a result of CSTR_EQUAL, so I don't think the bug is in the collation tables.