Winapi 如何使用CompareString功能使其在Windows XP和Windows 7上都能工作

Winapi 如何使用CompareString功能使其在Windows XP和Windows 7上都能工作,winapi,windows-7,string-comparison,windows-xp-sp3,Winapi,Windows 7,String Comparison,Windows Xp Sp3,我有一个基于Windows7SP1和VisualStudio2010SP1构建的应用程序 在Windows 7和Windows XP上,CompareString的工作方式似乎不同。我正在创建一个EndsWith/StartsWith-like(请参见C#String.EndsWith)方法,但它在Windows 7上按预期工作,但在Windows XP上不工作 这是我的开始与和结束与: bool String::StartsWith( const String& value, bool

我有一个基于Windows7SP1和VisualStudio2010SP1构建的应用程序

在Windows 7和Windows XP上,
CompareString
的工作方式似乎不同。我正在创建一个
EndsWith
/
StartsWith
-like(请参见C#
String.EndsWith
)方法,但它在Windows 7上按预期工作,但在Windows XP上不工作

这是我的
开始与
结束与

bool String::StartsWith( const String& value, bool bCaseSensitive ) const
{
    if(this->strLen == 0 || value.strLen == 0)
        return false;

    DWORD flags;
    if(bCaseSensitive == false)
        flags = LINGUISTIC_IGNORECASE;
    else
        flags = NORM_LINGUISTIC_CASING;

    if( CSTR_EQUAL == CompareStringW(LOCALE_USER_DEFAULT, flags, this->_str, static_cast<int>(value.strLen), value._str, static_cast<int>(value.strLen)) )
        return true;
    else if(CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, flags, this->_str, static_cast<int>(value.strLen), value._str, static_cast<int>(value.strLen)))
        return true;
    else if(CSTR_EQUAL == CompareStringW(GetThreadLocale(), flags, this->_str, static_cast<int>(value.strLen), value._str, static_cast<int>(value.strLen)))
        return true;
    else
        return false;
}
bool String::StartsWith(const String&value,bool bCaseSensitive)const
{
if(this->strLen==0 | | value.strLen==0)
返回false;
德沃德旗;
if(bCaseSensitive==false)
标志=语言符号;
其他的
标志=标准语言外壳;
if(CSTR_EQUAL==CompareStringW(区域设置_USER_默认值,标志,this->_str,static_cast(value.strLen),value._str,static_cast(value.strLen)))
返回true;
else if(CSTR_EQUAL==CompareStringW(LOCALE_SYSTEM_DEFAULT,flags,this->_str,static_cast(value.strLen),value._str,static_cast(value.strLen)))
返回true;
else if(CSTR_EQUAL==CompareStringW(GetThreadLocale(),flags,this->_str,static_cast(value.strLen),value._str,static_cast(value.strLen)))
返回true;
其他的
返回false;
}

bool String::EndsWith(常量字符串和值,bool bCaseSensitive)常量
{
if(this->strLen==0 | | value.strLen==0)
返回false;
德沃德旗;
if(bCaseSensitive==false)
标志=语言符号;
其他的
标志=标准语言外壳;
最大尺寸;
如果(此->strLenstrLen;
其他的
maxLen=value.strLen;
LPCWSTR SZSTARTOFSET;
如果(maxLen==this->strLen)
szStartOffset=此->\u str;
其他的
szStartOffset=(this->str+(this->strLen-value.strLen));
if(CSTR_EQUAL==CompareStringW(区域设置_USER_DEFAULT,标志,szStartOffset,静态_cast(maxLen),值._str,静态_cast(maxLen)))
返回true;
else if(CSTR_EQUAL==CompareStringW(LOCALE_SYSTEM_DEFAULT,flags,szStartOffset,static_cast(maxLen),value._str,static_cast(maxLen)))
返回true;
else if(CSTR_EQUAL==CompareStringW(GetThreadLocale(),flags,szStartOffset,static_cast(maxLen),value._str,static_cast(maxLen)))
返回true;
其他的
返回false;
}

如果有人能帮助我,我将非常感激。

所以有很多事情

首先,CompareString在出错时返回0,正如您所看到的,我没有检查它。在Windows XP上,它确实失败了,GetLastError()设置为1004=“无效标志。”。这个错误是下一个问题的线索

其次,我总是使用一个或另一个标志,在Windows XP上,NORM_language_casting会导致1004错误。由于此函数的默认行为区分大小写,因此在大多数情况下实际上不需要此标志,并且标志可以设置为0

我创建了一个演示程序,它实现了StartsWith:stringtest.cpp

// cl /MTd /DUNICODE /D_UNICODE_ stringtest.cpp
// MTd  - statically compile libcrt to binary, this way you don't have to copy msvcrtd100.dll etc to the XP machine.

#include <windows.h>
#include <cstdio>

int StartsWith(LCID locale, const WCHAR* szOrg, const WCHAR* szValue, bool sensitive, bool expected /* Can be used for asserts. */)
{
    int retval(0)
    DWORD flags = sensitive ? 0 : NORM_IGNORECASE; // You could replace 0 with NORM_LINGUISTIC_CASING to make it fail on Windows XP.

    int cchValue = lstrlenW(szValue);

    // if szOrg can't hold szValue, it doesn't start with szValue.
    if( cchValue > lstrlenW(szOrg) )
        return CSTR_LESS_THAN;

    // We trick CompareString to think szOrg is the same length as szValue.
    // This is how we check only the cchValue first characters of szOrg.
    retval = CompareStringW(locale, flags, szOrg, cchValue, szValue, cchValue);

    // You could assert on retval and parameter 'expected '.

    return(retval);
}

// Some compiler magic..
#define SHOWBOOL(expr)  { \
                            int ret = expr; \
                            DWORD gle=GetLastError(); /* Cache GLE in case printf changes it. */ \
                            printf( "%s = %s\r\n", ( ret == CSTR_EQUAL ? "true" : "false"), #expr ); \
                            printf("GetLastError() = %d - ret = %d\r\n\r\n", gle, ret); \
                        }

// Named this way since we get the expression to console, easier to read.
bool ExpectsTrue = true;
bool ExpectsFalse = false;

bool Sensitive = true;
bool Insensitive = false;

int main(int argc, WCHAR* argv[])
{
    SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
    SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"hello", Sensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"hello", Insensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );

    SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
    SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"hello", Sensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"hello", Insensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );

    SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
    SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"hello", Sensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"hello", Insensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );

    SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
    SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"hello", Sensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"hello", Insensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );

    return(NO_ERROR);
}
//cl/MTd/DUNICODE/D_UNICODE_uustringtest.cpp
//MTd-静态地将libcrt编译为二进制,这样您就不必将msvcrtd100.dll等复制到XP机器上。
#包括
#包括
int StartsWith(LCID区域设置、常量WCHAR*szOrg、常量WCHAR*szValue、bool敏感、bool预期/*可用于资产。*/)
{
int retval(0)
DWORD flags=sensitive?0:NORM\u IGNORECASE;//您可以用NORM\u language\u大小写替换0,使其在Windows XP上失败。
int cchValue=lstrlenW(szValue);
//如果szOrg不能保存szValue,它就不会以szValue开头。
如果(cchValue>lstrlenW(szOrg))
返回CSTR_小于;
//我们欺骗CompareString,认为szOrg的长度与szValue的长度相同。
//这就是我们仅检查szOrg的cchValue第一个字符的方式。
retval=CompareStringW(区域设置、标志、szog、cchValue、szValue、cchValue);
//您可以在retval和参数'expected'上断言。
返回(retval);
}
//一些编译器的魔法。。
#定义SHOWBOOL(expr){\
int-ret=expr\
DWORD gle=GetLastError();/*缓存gle,以防printf更改它。*/\
printf(“%s=%s\r\n”,(ret==CSTR_EQUAL?“true”):“false”),#expr)\
printf(“GetLastError()=%d-ret=%d\r\n\r\n”,gle,ret)\
}
//这样命名是因为我们将表达式放到控制台,更易于阅读。
bool ExpectsTrue=true;
bool-ExpectsFalse=false;
布尔敏感=真;
布尔不敏感=假;
int main(int argc,WCHAR*argv[]
{
SHOWBOOL(StartsWith(LOCALE\u USER\u DEFAULT,L“Hello World”,L“Hello”,Sensitive,ExpectsTrue));
SHOWBOOL(StartsWith(LOCALE\u USER\u DEFAULT,L“Hello World”,L“Hello”,Sensitive,ExpectsFalse));
SHOWBOOL(StartsWith(LOCALE\u USER\u DEFAULT,L“Hello World”,L“Hello”,不敏感,ExpectsFalse));
SHOWBOOL(StartsWith(LOCALE\u USER\u DEFAULT,L“Hello World”,L“1Hello”,Sensitive,ExpectsFalse));
SHOWBOOL(StartsWith(LOCALE\u SYSTEM\u DEFAULT,L“Hello World”,L“Hello”,Sensitive,ExpectsTrue));
SHOWBOOL(StartsWith(LOCALE\u SYSTEM\u DEFAULT,L“Hello World”,L“Hello”,Sensitive,ExpectsFalse));
SHOWBOOL(StartsWith(LOCALE\u SYSTEM\u DEFAULT,L“Hello World”,L“Hello”,不敏感,ExpectsFalse));
SHOWBOOL(StartsWith(LOCALE\u SYSTEM\u DEFAULT,L“Hello World”,L“1Hello”,Sensitive,ExpectsFalse));
SHOWBOOL(StartsWith(GetThreadLocale(),L“Hello World”,L“Hello”,Sensitive,ExpectsTrue));
SHOWBOOL(StartsWith(GetThreadLocale(),L“Hello World”,L“Hello”,Sensitive,ExpectsFalse));
SHOWBOOL(StartsWith(GetThreadLocale(),L“Hello World”,L“Hello”,不敏感,ExpectsFalse));
SHOWBOOL(StartsWith(GetThreadLocale(),L“Hello World”,L“1Hello”,Sensitive,ExpectsFalse));
SHOWBOOL(StartsWith(GetSystemDefaultLCID(),L“He
// cl /MTd /DUNICODE /D_UNICODE_ stringtest.cpp
// MTd  - statically compile libcrt to binary, this way you don't have to copy msvcrtd100.dll etc to the XP machine.

#include <windows.h>
#include <cstdio>

int StartsWith(LCID locale, const WCHAR* szOrg, const WCHAR* szValue, bool sensitive, bool expected /* Can be used for asserts. */)
{
    int retval(0)
    DWORD flags = sensitive ? 0 : NORM_IGNORECASE; // You could replace 0 with NORM_LINGUISTIC_CASING to make it fail on Windows XP.

    int cchValue = lstrlenW(szValue);

    // if szOrg can't hold szValue, it doesn't start with szValue.
    if( cchValue > lstrlenW(szOrg) )
        return CSTR_LESS_THAN;

    // We trick CompareString to think szOrg is the same length as szValue.
    // This is how we check only the cchValue first characters of szOrg.
    retval = CompareStringW(locale, flags, szOrg, cchValue, szValue, cchValue);

    // You could assert on retval and parameter 'expected '.

    return(retval);
}

// Some compiler magic..
#define SHOWBOOL(expr)  { \
                            int ret = expr; \
                            DWORD gle=GetLastError(); /* Cache GLE in case printf changes it. */ \
                            printf( "%s = %s\r\n", ( ret == CSTR_EQUAL ? "true" : "false"), #expr ); \
                            printf("GetLastError() = %d - ret = %d\r\n\r\n", gle, ret); \
                        }

// Named this way since we get the expression to console, easier to read.
bool ExpectsTrue = true;
bool ExpectsFalse = false;

bool Sensitive = true;
bool Insensitive = false;

int main(int argc, WCHAR* argv[])
{
    SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
    SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"hello", Sensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"hello", Insensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );

    SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
    SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"hello", Sensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"hello", Insensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );

    SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
    SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"hello", Sensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"hello", Insensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );

    SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
    SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"hello", Sensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"hello", Insensitive, ExpectsFalse) );
    SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );

    return(NO_ERROR);
}