Archive

Posts Tagged ‘MultiByteToWideChar’

Testing for possible Unicode – ANSI code page compatibility

May 13th, 2009 Christian Etter 9 comments

When dealing with a recent ExifTool remoting task, there was a question whether or not a given Unicode file name could be safely represented in the system ANSI code page. Only if the file name was fully convertible it could be passed to the application directly.

In case the file name cannot be converted to the current code page, an application which does not utilize the CreateFileW() API will not be able to open the file with this name. In case the file system supports old style DOS 8.3 filenames, the application should resort to using those instead.

BOOL IsConvertibleText( PCWSTR sFile )
{
    BOOL bRet = FALSE;
    if ( sFile )
    {
        int iBuffer = WideCharToMultiByte( CP_ACP, 0, sFile, -1, NULL, 0, NULL, NULL );
        if ( iBuffer != 0 )
        {
            iBuffer += 1;
            PSTR a = (PSTR)HeapAlloc( GetProcessHeap(), 0, iBuffer );
            if ( a )
            {
                if ( WideCharToMultiByte( CP_ACP, 0, sFile, -1, a, iBuffer, NULL, NULL ) )
                {
                    iBuffer = MultiByteToWideChar( CP_ACP, 0, a, -1, NULL, 0 );
                    if ( iBuffer != 0 )
                    {
                        iBuffer = ( iBuffer + 1 ) * sizeof(WCHAR);
                        PWSTR w = (PWSTR)HeapAlloc( GetProcessHeap(), 0, iBuffer );
                        if ( w )
                            if ( MultiByteToWideChar( CP_ACP, 0, a, -1, w, iBuffer ) )
                                if ( CompareStringW( LOCALE_SYSTEM_DEFAULT, 0, sFile, -1, w, -1 ) == CSTR_EQUAL )
                                    bRet = TRUE;
                        HeapFree( GetProcessHeap(), 0, w );
                    }
                }
                HeapFree( GetProcessHeap(), 0, a );
            }
        }
    }
    return bRet;
}

For those using C#:

bool IsConvertibleText( string sFile )
{
    byte[] b = Encoding.Default.GetBytes( sFile );
    string s = Encoding.Default.GetString( b );
    return sFile.Equals( s, StringComparison.InvariantCulture );
}

See also: Post in CPAN::Forum
Win32API::File Unicode support bug