Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- dlls/kernel32/profile.c | 126 +++++++++++++++++++--------------- dlls/kernel32/tests/profile.c | 109 ++++++++++++++++++++++++++--- 2 files changed, 169 insertions(+), 66 deletions(-)
diff --git a/dlls/kernel32/profile.c b/dlls/kernel32/profile.c index 462d64e5f0..3defaf6bef 100644 --- a/dlls/kernel32/profile.c +++ b/dlls/kernel32/profile.c @@ -68,6 +68,7 @@ typedef struct WCHAR *filename; FILETIME LastWriteTime; ENCODING encoding; + BOOL is_unicode; } PROFILE;
@@ -149,7 +150,7 @@ static inline void PROFILE_WriteMarker(HANDLE hFile, ENCODING encoding) } }
-static void PROFILE_WriteLine( HANDLE hFile, WCHAR * szLine, int len, ENCODING encoding) +static void PROFILE_WriteLine(HANDLE hFile, WCHAR *szLine, int len, ENCODING encoding, BOOL is_unicode) { char * write_buffer; int write_buffer_len; @@ -160,10 +161,10 @@ static void PROFILE_WriteLine( HANDLE hFile, WCHAR * szLine, int len, ENCODING e switch (encoding) { case ENCODING_ANSI: - write_buffer_len = WideCharToMultiByte(CP_ACP, 0, szLine, len, NULL, 0, NULL, NULL); + write_buffer_len = WideCharToMultiByte(is_unicode ? CP_ACP : 1252, 0, szLine, len, NULL, 0, NULL, NULL); write_buffer = HeapAlloc(GetProcessHeap(), 0, write_buffer_len); if (!write_buffer) return; - len = WideCharToMultiByte(CP_ACP, 0, szLine, len, write_buffer, write_buffer_len, NULL, NULL); + len = WideCharToMultiByte(is_unicode ? CP_ACP : 1252, 0, szLine, len, write_buffer, write_buffer_len, NULL, NULL); WriteFile(hFile, write_buffer, len, &dwBytesWritten, NULL); HeapFree(GetProcessHeap(), 0, write_buffer); break; @@ -192,7 +193,7 @@ static void PROFILE_WriteLine( HANDLE hFile, WCHAR * szLine, int len, ENCODING e * * Save a profile tree to a file. */ -static void PROFILE_Save( HANDLE hFile, const PROFILESECTION *section, ENCODING encoding ) +static void PROFILE_Save(HANDLE hFile, const PROFILESECTION *section, ENCODING encoding, BOOL is_unicode) { PROFILEKEY *key; WCHAR *buffer, *p; @@ -238,7 +239,7 @@ static void PROFILE_Save( HANDLE hFile, const PROFILESECTION *section, ENCODING *p++ = '\r'; *p++ = '\n'; } - PROFILE_WriteLine( hFile, buffer, len, encoding ); + PROFILE_WriteLine(hFile, buffer, len, encoding, is_unicode); HeapFree(GetProcessHeap(), 0, buffer); } } @@ -305,7 +306,7 @@ static inline ENCODING PROFILE_DetectTextEncoding(const void * buffer, int * len * * Load a profile tree from a file. */ -static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding) +static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING *pEncoding, BOOL is_unicode) { void *buffer_base, *pBuffer; WCHAR * szFile; @@ -343,14 +344,14 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding) case ENCODING_ANSI: TRACE("ANSI encoding\n");
- len = MultiByteToWideChar(CP_ACP, 0, pBuffer, dwFileSize, NULL, 0); + len = MultiByteToWideChar(is_unicode ? CP_ACP : 1252, 0, pBuffer, dwFileSize, NULL, 0); szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); if (!szFile) { HeapFree(GetProcessHeap(), 0, buffer_base); return NULL; } - MultiByteToWideChar(CP_ACP, 0, pBuffer, dwFileSize, szFile, len); + MultiByteToWideChar(is_unicode ? CP_ACP : 1252, 0, pBuffer, dwFileSize, szFile, len); szEnd = szFile + len; break; case ENCODING_UTF8: @@ -678,7 +679,7 @@ static BOOL PROFILE_FlushFile(void) }
TRACE("Saving %s\n", debugstr_w(CurProfile->filename)); - PROFILE_Save( hFile, CurProfile->section, CurProfile->encoding ); + PROFILE_Save(hFile, CurProfile->section, CurProfile->encoding, CurProfile->is_unicode); if(GetFileTime(hFile, NULL, NULL, &LastWriteTime)) CurProfile->LastWriteTime=LastWriteTime; CloseHandle( hFile ); @@ -729,7 +730,7 @@ static BOOL is_not_current(FILETIME * ft) * * Open a profile file, checking the cached file first. */ -static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access ) +static BOOL PROFILE_Open(LPCWSTR filename, BOOL write_access, BOOL is_unicode) { WCHAR buffer[MAX_PATH]; HANDLE hFile = INVALID_HANDLE_VALUE; @@ -750,6 +751,7 @@ static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access ) MRUProfile[i]->section=NULL; MRUProfile[i]->filename=NULL; MRUProfile[i]->encoding=ENCODING_ANSI; + MRUProfile[i]->is_unicode = is_unicode; ZeroMemory(&MRUProfile[i]->LastWriteTime, sizeof(FILETIME)); }
@@ -786,7 +788,8 @@ static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access )
for(i=0;i<N_CACHED_PROFILES;i++) { - if ((MRUProfile[i]->filename && !strcmpiW( buffer, MRUProfile[i]->filename ))) + if ((MRUProfile[i]->filename && !strcmpiW(buffer, MRUProfile[i]->filename) && + (MRUProfile[i]->is_unicode == is_unicode))) { TRACE("MRU Filename: %s, new filename: %s\n", debugstr_w(MRUProfile[i]->filename), debugstr_w(buffer)); if(i) @@ -810,7 +813,7 @@ static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access ) TRACE("(%s): already opened, needs refreshing (mru=%d)\n", debugstr_w(buffer), i); PROFILE_Free(CurProfile->section); - CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding); + CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding, CurProfile->is_unicode); CurProfile->LastWriteTime = LastWriteTime; } CloseHandle(hFile); @@ -840,7 +843,8 @@ static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access )
if (hFile != INVALID_HANDLE_VALUE) { - CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding); + CurProfile->is_unicode = is_unicode; + CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding, CurProfile->is_unicode); GetFileTime(hFile, NULL, NULL, &CurProfile->LastWriteTime); CloseHandle(hFile); } @@ -1062,6 +1066,19 @@ static BOOL PROFILE_SetString( LPCWSTR section_name, LPCWSTR key_name, return TRUE; }
+static LPWSTR c2w(LPCSTR string) +{ + INT lenW; + LPWSTR stringW = NULL; + + if (!string) + return stringW; + + lenW = MultiByteToWideChar(1252, 0, string, -1, NULL, 0); + if ((stringW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR)))) + MultiByteToWideChar(1252, 0, string, -1, stringW, lenW); + return stringW; +}
/********************* API functions **********************************/
@@ -1083,13 +1100,13 @@ UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val ) }
static int get_private_profile_string(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, - LPWSTR buffer, UINT len, LPCWSTR filename) + LPWSTR buffer, UINT len, LPCWSTR filename, BOOL is_unicode) { int ret; LPWSTR defval_tmp = NULL;
- TRACE("(%s, %s, %s, %p, %u, %s)\n", debugstr_w(section), debugstr_w(entry), - debugstr_w(def_val), buffer, len, debugstr_w(filename)); + TRACE("(%s, %s, %s, %p, %u, %s, %d)\n", debugstr_w(section), debugstr_w(entry), + debugstr_w(def_val), buffer, len, debugstr_w(filename), is_unicode);
/* strip any trailing ' ' of def_val. */ if (def_val) @@ -1112,7 +1129,7 @@ static int get_private_profile_string(LPCWSTR section, LPCWSTR entry, LPCWSTR de
RtlEnterCriticalSection(&PROFILE_CritSect);
- if (PROFILE_Open(filename, FALSE)) + if (PROFILE_Open(filename, FALSE, is_unicode)) { if (section == NULL) ret = PROFILE_GetSectionNames(buffer, len); @@ -1145,7 +1162,7 @@ INT WINAPI GetPrivateProfileStringW(LPCWSTR section, LPCWSTR entry, UINT len, LPCWSTR filename) { return get_private_profile_string(section, entry, def_val, buffer, - len, filename); + len, filename, TRUE); }
/*********************************************************************** @@ -1155,39 +1172,35 @@ INT WINAPI GetPrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR def_val, LPSTR buffer, UINT len, LPCSTR filename) { - UNICODE_STRING sectionW, entryW, def_valW, filenameW; - LPWSTR bufferW; + UNICODE_STRING filenameW; + LPWSTR bufferW, sectionW, entryW, def_valW; INT retW, ret = 0;
bufferW = buffer ? HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)) : NULL; - if (section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); - else sectionW.Buffer = NULL; - if (entry) RtlCreateUnicodeStringFromAsciiz(&entryW, entry); - else entryW.Buffer = NULL; - if (def_val) RtlCreateUnicodeStringFromAsciiz(&def_valW, def_val); - else def_valW.Buffer = NULL; + sectionW = c2w(section); + entryW = c2w(entry); + def_valW = c2w(def_val); if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); else filenameW.Buffer = NULL;
- retW = get_private_profile_string(sectionW.Buffer, entryW.Buffer, - def_valW.Buffer, bufferW, len, - filenameW.Buffer); + retW = get_private_profile_string(sectionW, entryW, def_valW, bufferW, len, + filenameW.Buffer, FALSE); if (len && buffer) { if (retW) { - ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW, buffer, len - 1, NULL, NULL); + ret = WideCharToMultiByte(1252, 0, bufferW, retW, buffer, len - 1, NULL, NULL); if (!ret) ret = len - 1; } buffer[ret] = 0; }
- RtlFreeUnicodeString(§ionW); - RtlFreeUnicodeString(&entryW); - RtlFreeUnicodeString(&def_valW); RtlFreeUnicodeString(&filenameW); HeapFree(GetProcessHeap(), 0, bufferW); + HeapFree(GetProcessHeap(), 0, sectionW); + HeapFree(GetProcessHeap(), 0, entryW); + HeapFree(GetProcessHeap(), 0, def_valW); return ret; }
@@ -1298,7 +1311,7 @@ INT WINAPI GetPrivateProfileSectionW( LPCWSTR section, LPWSTR buffer,
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename, FALSE )) + if (PROFILE_Open(filename, FALSE, TRUE)) ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, TRUE);
RtlLeaveCriticalSection( &PROFILE_CritSect ); @@ -1369,23 +1382,23 @@ INT WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len ) }
static BOOL write_private_profile_string(LPCWSTR section, LPCWSTR entry, LPCWSTR string, - LPCWSTR filename) + LPCWSTR filename, BOOL is_unicode) { BOOL ret = FALSE;
- TRACE("(%s, %s, %s, %s)\n", debugstr_w(section), debugstr_w(entry), - debugstr_w(string), debugstr_w(filename)); + TRACE("(%s, %s, %s, %s, %d)\n", debugstr_w(section), debugstr_w(entry), + debugstr_w(string), debugstr_w(filename), is_unicode);
RtlEnterCriticalSection(&PROFILE_CritSect);
if (!section && !entry && !string) /* documented "file flush" case */ { - if (!filename || PROFILE_Open(filename, TRUE)) + if (!filename || PROFILE_Open(filename, TRUE, is_unicode)) { if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */ } } - else if (PROFILE_Open(filename, TRUE)) + else if (PROFILE_Open(filename, TRUE, is_unicode)) { if (!section) { SetLastError(ERROR_FILE_NOT_FOUND); @@ -1406,7 +1419,7 @@ BOOL WINAPI WritePrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string, LPCWSTR filename) { return write_private_profile_string(section, entry, string, - filename); + filename, TRUE); }
/*********************************************************************** @@ -1415,23 +1428,22 @@ BOOL WINAPI WritePrivateProfileStringW(LPCWSTR section, LPCWSTR entry, BOOL WINAPI DECLSPEC_HOTPATCH WritePrivateProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR string, LPCSTR filename ) { - UNICODE_STRING sectionW, entryW, stringW, filenameW; + UNICODE_STRING filenameW; + LPWSTR sectionW, entryW, stringW; BOOL ret;
- if (section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); - else sectionW.Buffer = NULL; - if (entry) RtlCreateUnicodeStringFromAsciiz(&entryW, entry); - else entryW.Buffer = NULL; - if (string) RtlCreateUnicodeStringFromAsciiz(&stringW, string); - else stringW.Buffer = NULL; + sectionW = c2w(section); + entryW = c2w(entry); + stringW = c2w(string); if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); else filenameW.Buffer = NULL;
- ret = write_private_profile_string(sectionW.Buffer, entryW.Buffer, - stringW.Buffer, filenameW.Buffer); - RtlFreeUnicodeString(§ionW); - RtlFreeUnicodeString(&entryW); - RtlFreeUnicodeString(&stringW); + ret = write_private_profile_string(sectionW, entryW, stringW, + filenameW.Buffer, FALSE); + + HeapFree(GetProcessHeap(), 0, sectionW); + HeapFree(GetProcessHeap(), 0, entryW); + HeapFree(GetProcessHeap(), 0, stringW); RtlFreeUnicodeString(&filenameW); return ret; } @@ -1449,12 +1461,12 @@ BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
if (!section && !string) { - if (!filename || PROFILE_Open( filename, TRUE )) + if (!filename || PROFILE_Open(filename, TRUE, TRUE)) { if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */ } } - else if (PROFILE_Open( filename, TRUE )) { + else if (PROFILE_Open(filename, TRUE, TRUE)) { if (!string) {/* delete the named section*/ ret = PROFILE_SetString(section,NULL,NULL, FALSE); } else { @@ -1576,7 +1588,7 @@ DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename, FALSE )) + if (PROFILE_Open(filename, FALSE, TRUE)) ret = PROFILE_GetSectionNames(buffer, size);
RtlLeaveCriticalSection( &PROFILE_CritSect ); @@ -1631,7 +1643,7 @@ BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename, FALSE )) { + if (PROFILE_Open(filename, FALSE, TRUE)) { PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE, FALSE); if (k) { TRACE("value (at %p): %s\n", k->value, debugstr_w(k->value)); @@ -1751,7 +1763,7 @@ BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename, TRUE )) { + if (PROFILE_Open(filename, TRUE, TRUE)) { ret = PROFILE_SetString( section, key, outstring, FALSE); if (ret) ret = PROFILE_FlushFile(); } diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c index 8a0089bb1b..761817cb9c 100644 --- a/dlls/kernel32/tests/profile.c +++ b/dlls/kernel32/tests/profile.c @@ -592,7 +592,12 @@ static void test_GetPrivateProfileString(const char *content, const char *descri empty string and check for modification */ CHAR emptystr[MAX_PATH] = ""; LPSTR tempfile; - + WCHAR bufW[MAX_PATH], expected_valW[MAX_PATH]; + static const WCHAR section_schineseW[] = {0xe6,0xae,0xb5,0x31,0}; + static const WCHAR name5W[] = {'n','a','m','e','5',0}; + static const WCHAR filenameW[] = {'.','\','w','i','n','e','t','e','s','t','.','i','n','i',0}; + static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0}; + static const WCHAR expected_val_enW[] = {0x00e9,0x2026,0x2019,'.',0}; static const char filename[] = ".\winetest.ini";
trace("test_GetPrivateProfileStringA: %s\n", descript); @@ -620,12 +625,12 @@ static void test_GetPrivateProfileString(const char *content, const char *descri lstrcpyA(buf, "kumquat"); ret = GetPrivateProfileStringA(NULL, "name1", "default", buf, MAX_PATH, filename); - ok(ret == 18 || - broken(ret == 19), /* Win9x and WinME */ - "Expected 18, got %d\n", ret); - len = lstrlenA("section1") + sizeof(CHAR) + lstrlenA("section2") + 2 * sizeof(CHAR); - ok(!memcmp(buf, "section1\0section2\0\0", len), - "Expected "section1\0section2\0\0", got "%s"\n", buf); + ok(ret == 23 || + broken(ret == 24), /* Win9x and WinME */ + "Expected 23, got %d\n", ret); + len = lstrlenA("section1") + lstrlenA("section2") + lstrlenA("\xe6\xae\xb5\x31") + 4 * sizeof(CHAR); + ok(!memcmp(buf, "section1\0section2\0\xe6\xae\xb5\x31\0\0", len), + "Expected "section1\0section2\0\xe6\xae\xb5\x31\0\0", got "%s"\n", buf);
/* lpAppName is empty */ memset(buf, 0xc, sizeof(buf)); @@ -827,6 +832,59 @@ static void test_GetPrivateProfileString(const char *content, const char *descri ok(ret == 0, "Expected 0, got %d\n", ret); ok(!lstrcmpA(buf, ""), "Expected "", got "%s"\n", buf);
+ memset(buf, 0xc, sizeof(buf)); + lstrcpyA(buf, "kumquat"); + ret = GetPrivateProfileStringA("\xe6\xae\xb5\x31", "name5", "default", + buf, MAX_PATH, filename); + ok(ret == 4, "Expected 4, got %d\n", ret); + ok(!lstrcmpA(buf, "\xe9\x85\x92\x2e"), + "Expected "\xe9\x85\x92\x2e", got "%s"\n", buf); + + memset(buf, 0xc,sizeof(buf)); + lstrcpyA(buf, "kumquat"); + ret = GetPrivateProfileStringA("\xe6\xae\xb5\x31", "\xe5\xa7\x93", "default", + buf, MAX_PATH, filename); + ok(ret == 4, "Expected 4, got %d\n", ret); + ok(!lstrcmpA(buf, "\xe6\x9b\xbe\x2e"), + "Expected "\xe6\x9b\xbe\x2e", got "%s"\n", buf); + + memset(buf, 0xc, sizeof(buf)); + lstrcpyA(buf, "kumquat"); + ret = GetPrivateProfileStringA("\xe6\xae\xb5\x31", "name6", "default", + buf, MAX_PATH, filename); + ok(ret == 7, "Expected 7, got %d\n", ret); + ok(!lstrcmpA(buf, "\xd7\x99\xd7\x99\xd7\x9f\x2e"), + "Expected "\xd7\x99\xd7\x99\xd7\x9f\x2e", got "%s"\n", buf); + + + memset(bufW, 0xc, sizeof(bufW)); + ret = GetPrivateProfileStringW(section_schineseW, name5W, defaultW, + bufW, MAX_PATH, filenameW); + switch (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()))) + { + case LANG_CHINESE: + case LANG_HEBREW: + case LANG_JAPANESE: + trace("on Chinese, Hebrew or Japanese system.\n"); + lstrcpyW(expected_valW, defaultW); + len = lstrlenW(expected_valW); + ok(ret == len, "Expected %d, got %d\n", len, ret); + ok(!lstrcmpW(bufW, expected_valW), "Expected "%s", got "%s"\n", + wine_dbgstr_w(expected_valW), wine_dbgstr_w(bufW)); + break; + case LANG_ENGLISH: + case LANG_FRENCH: + trace("on English or French system.\n"); + lstrcpyW(expected_valW, expected_val_enW); + len = lstrlenW(expected_valW); + ok(ret == len, "Expected %d, got %d\n", len, ret); + ok(!lstrcmpW(bufW, expected_valW), "Expected "%s", got "%s"\n", + wine_dbgstr_w(expected_valW), wine_dbgstr_w(bufW)); + break; + default: + skip("Unknown system language.\n"); + } + /* lpAppName is NULL, not enough room for final section name */ memset(buf, 0xc,sizeof(buf)); lstrcpyA(buf, "kumquat"); @@ -1171,6 +1229,31 @@ static void test_WritePrivateProfileString(void) "key1=string1" /* 14 bytes */ , 59)), "File doesn't match\n"); DeleteFileA(path); + + data = "[section1]\r\n" + "name=\xe9\x85\x92\x2e\r\n"; + GetTempFileNameA(temp, "wine", 0, path); + ret = WritePrivateProfileStringA("section1", "name", "\xe9\x85\x92\x2e", path); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + ok(check_file_data(path, data), "File doesn't match\n"); + + data = "[section1]\r\n" + "name=\xe9\x85\x92\x2e\r\n" + "\xe5\xa7\x93=\xe6\x9b\xbe\x2e\r\n"; + ret = WritePrivateProfileStringA("section1", "\xe5\xa7\x93", "\xe6\x9b\xbe\x2e", path); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + ok(check_file_data(path, data), "File doesn't match\n"); + + data = "[section1]\r\n" + "name=\xe9\x85\x92\x2e\r\n" + "\xe5\xa7\x93=\xe6\x9b\xbe\x2e\r\n" + "[\xe6\xae\xb5\x31]\r\n" + "name2=\xe6\x9b\xbe\x2e\r\n"; + ret = WritePrivateProfileStringA("\xe6\xae\xb5\x31", "name2", "\xe6\x9b\xbe\x2e", path); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + ok(check_file_data(path, data), "File doesn't match\n"); + + DeleteFileA(path); }
START_TEST(profile) @@ -1189,7 +1272,11 @@ START_TEST(profile) "name2="val2"\r\n" "name3\r\n" "name4=a\r\n" - "[section2]\r\n", + "[section2]\r\n" + "[\xe6\xae\xb5\x31]\r\n" /* Simplified Chinese in UTF-8 */ + "name5=\xe9\x85\x92\x2e\r\n" /* Simplified Chinese in UTF-8 */ + "\xe5\xa7\x93=\xe6\x9b\xbe\x2e\r\n" /* Simplified Chinese in UTF-8 */ + "name6=\xd7\x99\xd7\x99\xd7\x9f\x2e\r\n", /* Hebrew in UTF-8 */ "CR+LF"); test_GetPrivateProfileString( "[section1]\r" @@ -1197,7 +1284,11 @@ START_TEST(profile) "name2="val2"\r" "name3\r" "name4=a\r" - "[section2]\r", + "[section2]\r" + "[\xe6\xae\xb5\x31]\r" /* Simplified Chinese in UTF-8 */ + "name5=\xe9\x85\x92\x2e\r" /* Simplified Chinese in UTF-8 */ + "\xe5\xa7\x93=\xe6\x9b\xbe\x2e\r" /* Simplified Chinese in UTF-8 */ + "name6=\xd7\x99\xd7\x99\xd7\x9f\x2e\r", /* Hebrew in UTF-8 */ "CR only"); test_WritePrivateProfileString(); }
Jactry Zeng jzeng@codeweavers.com wrote:
+static LPWSTR c2w(LPCSTR string) +{
- INT lenW;
- LPWSTR stringW = NULL;
- if (!string)
return stringW;
- lenW = MultiByteToWideChar(1252, 0, string, -1, NULL, 0);
- if ((stringW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR))))
MultiByteToWideChar(1252, 0, string, -1, stringW, lenW);
- return stringW;
+}
As mentioned before tis will break a lot of apps that write profile strings using system locale.
@@ -1189,7 +1272,11 @@ START_TEST(profile) "name2="val2"\r\n" "name3\r\n" "name4=a\r\n"
"[section2]\r\n",
"[section2]\r\n"
"[\xe6\xae\xb5\x31]\r\n" /* Simplified Chinese in UTF-8 */
"name5=\xe9\x85\x92\x2e\r\n" /* Simplified Chinese in UTF-8 */
"\xe5\xa7\x93=\xe6\x9b\xbe\x2e\r\n" /* Simplified Chinese in UTF-8 */
test_GetPrivateProfileString( "[section1]\r""name6=\xd7\x99\xd7\x99\xd7\x9f\x2e\r\n", /* Hebrew in UTF-8 */ "CR+LF");
@@ -1197,7 +1284,11 @@ START_TEST(profile) "name2="val2"\r" "name3\r" "name4=a\r"
"[section2]\r",
"[section2]\r"
"[\xe6\xae\xb5\x31]\r" /* Simplified Chinese in UTF-8 */
"name5=\xe9\x85\x92\x2e\r" /* Simplified Chinese in UTF-8 */
"\xe5\xa7\x93=\xe6\x9b\xbe\x2e\r" /* Simplified Chinese in UTF-8 */
"name6=\xd7\x99\xd7\x99\xd7\x9f\x2e\r", /* Hebrew in UTF-8 */
Why are you testing with UTF-8 encoded strings but the implementation uses code page 1252? This is clearly broken.
Please add the convincing set of the tests first to show the problem, at the moment I fail to see what exactly you are trying trying to fix, and only then try to think about the possible ways to fix the spotted bug(s).
Hi Dmitry,
Thanks for review and comment.
On 2019/4/30 下午2:05, Dmitry Timoshkov wrote:
Please add the convincing set of the tests first to show the problem, at the moment I fail to see what exactly you are trying trying to fix, and only then try to think about the possible ways to fix the spotted bug(s).
I think the tests already exposed some problems, some applications were trying to use GetPrivateProfileStringA() for getting values from an UTF-8 profile.
Attachment is an independent testcase. On Windows, printing out result isn't locale related(I tested it on English and Chinese Windows). But on current Wine, the result is locale related. For example: $ LC_ALL=zh_CN.UTF-8 LANG=zh_CN.UTF-8 wine test_GetPrivateProfileStringA.exe will print out:
ffffffe4 ffffffb8 003f
when on Wine with en_US.UTF-8 and on Windows it was:
ffffffe4 ffffffb8 ffffff8a 003a
I'm quite not sure how to fix it correctly, any thoughts or suggest will be appreciated.
Jactry Zeng jzeng@codeweavers.com wrote:
On 2019/4/30 下午2:05, Dmitry Timoshkov wrote:
Please add the convincing set of the tests first to show the problem, at the moment I fail to see what exactly you are trying trying to fix, and only then try to think about the possible ways to fix the spotted bug(s).
I think the tests already exposed some problems, some applications were trying to use GetPrivateProfileStringA() for getting values from an UTF-8 profile.
Attachment is an independent testcase. On Windows, printing out result isn't locale related(I tested it on English and Chinese Windows). But on current Wine, the result is locale related. For example: $ LC_ALL=zh_CN.UTF-8 LANG=zh_CN.UTF-8 wine test_GetPrivateProfileStringA.exe will print out:
ffffffe4 ffffffb8 003f
when on Wine with en_US.UTF-8 and on Windows it was:
ffffffe4 ffffffb8 ffffff8a 003a
I'm quite not sure how to fix it correctly, any thoughts or suggest will be appreciated.
As usually the very first thing to do is to add minimal test case that shows the problem, that way it would be clearer what is going on.