Microsoft's Implementation of Lstrcmpi and Unicode Characters
I'm Trying to Understand Whether What I'm Seeing Is a Bug, or Some Accepted Behaviour of the Microsoft's Lstrcmpi Function? I Can Illustrate It with the Code...
I'm trying to understand whether what I'm seeing is a bug, or some accepted behaviour of the Microsoft's lstrcmpi function?
I can illustrate it with the code:
WCHAR buff1[] = L"abc ";
WCHAR buff2[] = L"abc ";
buff1[3] = 0xFFFF;
buff2[3] = 0x0;
int res = lstrcmpi(buff1, buff2);
//res is 0 or equality!
EDIT: Addition for the comment below:
2 Answers
lstrcmpi calls CompareString with the current locale (from thread or user) and returns "a linguistically appropriate result".
From Michael Kaplans blog:
... Now if the functions were named lstrcoll and lstrcolli then perhaps the function would not be so commonly misused
and:
Remember that when checking for equality, especially on an item like a registry value where OS semantics are involved, the best answer is CompareStringOrdinal, with a fallback to RtlCompareUnicodeString or even better RtlEqualUnicodeString or if you absolutely must wcsicmp (with awareness that there is one character it can be wrong about) for anything that has to run pre-Vista.
Because if you are calling lstrcmpi for appropriate reasons (i.e. you wanted to get linguistically meaningful results, say in the sorting of a list in a user interface) but you wanted to have behavior that did not vary with different locales, then CompareString with LOCALE_INVARIANT is a good answer.
But if you wanted almost anything else, including all of the non-linguistic purposes hinted at earlier, then CompareStringOrdinal or RtlCompareUnicodeString is a much better choice.
How it handles non-characters has actually changed over time.
The Unicode FFFF character is a noncharacter in the Unicode spec, so it is probably being ignored during the string comparison. This results in both strings being equal.