- Partial sync with Wine. It fixes 37 tests ("kernel32_winetest profile")

svn path=/trunk/; revision=38368
This commit is contained in:
Dmitry Chapyshev 2008-12-27 08:34:30 +00:00
parent 77f0be0bc8
commit d3294eb866

View file

@ -88,17 +88,18 @@ static __inline WCHAR *memchrW( const WCHAR *ptr, WCHAR ch, size_t n )
const WCHAR *end;
for (end = ptr + n; ptr < end; ptr++)
if (*ptr == ch)
return (WCHAR *)ptr;
return (WCHAR *)(ULONG_PTR)ptr;
return NULL;
}
static __inline WCHAR *memrchrW( const WCHAR *ptr, WCHAR ch, size_t n )
{
const WCHAR *end, *ret = NULL;
const WCHAR *end;
WCHAR *ret = NULL;
for (end = ptr + n; ptr < end; ptr++)
if (*ptr == ch)
ret = ptr;
return (WCHAR *)ret;
ret = (WCHAR *)(ULONG_PTR)ptr;
return ret;
}
/***********************************************************************
@ -139,7 +140,7 @@ static __inline void PROFILE_ByteSwapShortBuffer(WCHAR * buffer, int len)
static __inline void PROFILE_WriteMarker(HANDLE hFile, ENCODING encoding)
{
DWORD dwBytesWritten;
DWORD bom;
WCHAR bom;
switch (encoding)
{
case ENCODING_ANSI:
@ -283,12 +284,8 @@ static void PROFILE_Free( PROFILESECTION *section )
/* returns 1 if a character white space else 0 */
static __inline int PROFILE_isspaceW(WCHAR c)
{
if (iswspace(c))
return 1;
if (c=='\r' || c==0x1a)
return 1;
/* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
return 0;
/* ^Z (DOS EOF) is a space too (found on CD-ROMs) */
return isspace(c) || c == 0x1a;
}
@ -325,7 +322,7 @@ static __inline ENCODING PROFILE_DetectTextEncoding(const void * buffer, int * l
*/
static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
{
void *pBuffer;
void *buffer_base, *pBuffer;
WCHAR * szFile;
const WCHAR *szLineStart, *szLineEnd;
const WCHAR *szValueStart, *szEnd, *next_line;
@ -341,22 +338,22 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
if (dwFileSize == INVALID_FILE_SIZE)
return NULL;
pBuffer = HeapAlloc(GetProcessHeap(), 0 , dwFileSize);
if (!pBuffer)
buffer_base = HeapAlloc(GetProcessHeap(), 0 , dwFileSize);
if (!buffer_base)
return NULL;
if (!ReadFile(hFile, pBuffer, dwFileSize, &dwFileSize, NULL))
if (!ReadFile(hFile, buffer_base, dwFileSize, &dwFileSize, NULL))
{
HeapFree(GetProcessHeap(), 0, pBuffer);
HeapFree(GetProcessHeap(), 0, buffer_base);
DPRINT("Error %ld reading file\n", GetLastError());
return NULL;
}
len = dwFileSize;
*pEncoding = PROFILE_DetectTextEncoding(pBuffer, &len);
*pEncoding = PROFILE_DetectTextEncoding(buffer_base, &len);
/* len is set to the number of bytes in the character marker.
* we want to skip these bytes */
pBuffer = (char *)pBuffer + len;
pBuffer = (char *)buffer_base + len;
dwFileSize -= len;
switch (*pEncoding)
{
@ -367,7 +364,7 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (!szFile)
{
HeapFree(GetProcessHeap(), 0, pBuffer);
HeapFree(GetProcessHeap(), 0, buffer_base);
return NULL;
}
MultiByteToWideChar(CP_ACP, 0, (char *)pBuffer, dwFileSize, szFile, len);
@ -381,7 +378,7 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (!szFile)
{
HeapFree(GetProcessHeap(), 0, pBuffer);
HeapFree(GetProcessHeap(), 0, buffer_base);
return NULL;
}
MultiByteToWideChar(CP_UTF8, 0, (char *)pBuffer, dwFileSize, szFile, len);
@ -390,20 +387,20 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
case ENCODING_UTF16LE:
DPRINT("UTF16 Little Endian encoding\n");
szFile = (WCHAR *)pBuffer + 1;
szFile = (WCHAR *)pBuffer;// + 1;
szEnd = (WCHAR *)((char *)pBuffer + dwFileSize);
break;
case ENCODING_UTF16BE:
DPRINT("UTF16 Big Endian encoding\n");
szFile = (WCHAR *)pBuffer + 1;
szFile = (WCHAR *)pBuffer;// + 1;
szEnd = (WCHAR *)((char *)pBuffer + dwFileSize);
PROFILE_ByteSwapShortBuffer(szFile, dwFileSize / sizeof(WCHAR));
break;
default:
DPRINT("encoding type %d not implemented\n", *pEncoding);
HeapFree(GetProcessHeap(), 0, pBuffer);
HeapFree(GetProcessHeap(), 0, buffer_base);
return NULL;
}
@ -412,7 +409,7 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
{
if (szFile != pBuffer)
HeapFree(GetProcessHeap(), 0, szFile);
HeapFree(GetProcessHeap(), 0, pBuffer);
HeapFree(GetProcessHeap(), 0, buffer_base);
return NULL;
}
first_section->name[0] = 0;
@ -427,6 +424,7 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
{
szLineStart = next_line;
next_line = memchrW(szLineStart, '\n', szEnd - szLineStart);
if (!next_line) next_line = memchrW(szLineStart, '\r', szEnd - szLineStart);
if (!next_line) next_line = szEnd;
else next_line++;
szLineEnd = next_line;
@ -435,7 +433,7 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
/* get rid of white space */
while (szLineStart < szLineEnd && PROFILE_isspaceW(*szLineStart)) szLineStart++;
while ((szLineEnd > szLineStart) && ((szLineEnd[-1] == '\n') || (PROFILE_isspaceW(szLineEnd[-1]) && szLineEnd[-1] != ' '))) szLineEnd--;
while ((szLineEnd > szLineStart) && PROFILE_isspaceW(szLineEnd[-1])) szLineEnd--;
if (szLineStart >= szLineEnd)
continue;
@ -510,7 +508,7 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
}
if (szFile != pBuffer)
HeapFree(GetProcessHeap(), 0, szFile);
HeapFree(GetProcessHeap(), 0, pBuffer);
HeapFree(GetProcessHeap(), 0, buffer_base);
return first_section;
}
@ -688,7 +686,8 @@ static BOOL PROFILE_FlushFile(void)
if (!CurProfile->changed) return TRUE;
hFile = CreateFileW(CurProfile->filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
hFile = CreateFileW(CurProfile->filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
@ -724,12 +723,33 @@ static void PROFILE_ReleaseFile(void)
}
/***********************************************************************
*
* Compares a file time with the current time. If the file time is
* at least 2.1 seconds in the past, return true.
*
* Intended as cache safety measure: The time resolution on FAT is
* two seconds, so files that are not at least two seconds old might
* keep their time even on modification, so don't cache them.
*/
static BOOL is_not_current(FILETIME * ft)
{
FILETIME Now;
LONGLONG ftll, nowll;
GetSystemTimeAsFileTime(&Now);
ftll = ((LONGLONG)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
nowll = ((LONGLONG)Now.dwHighDateTime << 32) + Now.dwLowDateTime;
DPRINT("%08x;%08x\n",(unsigned)ftll+21000000,(unsigned)nowll);
return ftll + 21000000 < nowll;
}
/***********************************************************************
* PROFILE_Open
*
* Open a profile file, checking the cached file first.
*/
static BOOL PROFILE_Open( LPCWSTR filename )
static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access )
{
WCHAR windirW[MAX_PATH];
WCHAR buffer[MAX_PATH];
@ -775,7 +795,9 @@ static BOOL PROFILE_Open( LPCWSTR filename )
DPRINT("path: %S\n", buffer);
hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hFile = CreateFileW(buffer, GENERIC_READ | (write_access ? GENERIC_WRITE : 0),
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if ((hFile == INVALID_HANDLE_VALUE) && (GetLastError() != ERROR_FILE_NOT_FOUND))
{
@ -797,21 +819,21 @@ static BOOL PROFILE_Open( LPCWSTR filename )
CurProfile=tempProfile;
}
if (hFile != INVALID_HANDLE_VALUE)
{
GetFileTime(hFile, NULL, NULL, &LastWriteTime);
else
LastWriteTime.dwHighDateTime = LastWriteTime.dwLowDateTime = 0;
if (memcmp(&CurProfile->LastWriteTime, &LastWriteTime, sizeof(FILETIME)))
{
DPRINT("(%S): already opened (mru = %d)\n",
buffer, i );
}
else
{
DPRINT("(%S): already opened, needs refreshing (mru = %d)\n",
buffer, i );
}
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
if (!memcmp( &CurProfile->LastWriteTime, &LastWriteTime, sizeof(FILETIME) ) &&
is_not_current(&LastWriteTime))
DPRINT("(%S): already opened (mru=%d)\n", buffer, i);
else
{
DPRINT("(%S): already opened, needs refreshing (mru=%d)\n", buffer, i);
CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding);
CurProfile->LastWriteTime = LastWriteTime;
}
CloseHandle(hFile);
}
else DPRINT("(%S): already opened (mru = %d)\n", buffer, i );
return TRUE;
}
}
@ -984,15 +1006,15 @@ static INT PROFILE_GetString( LPCWSTR section, LPCWSTR key_name,
PROFILEKEY *key = NULL;
static const WCHAR empty_strW[] = { 0 };
if (!buffer) return 0;
if (!buffer || !len) return 0;
if (!def_val) def_val = empty_strW;
if (key_name)
{
if (!key_name[0])
{
/* Win95 returns 0 on keyname "". Tested with Likse32 bon 000227 */
return 0;
PROFILE_CopyEntry(buffer, def_val, len, TRUE);
return wcslen(buffer);
}
key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE, FALSE);
PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
@ -1112,7 +1134,7 @@ static int PROFILE_GetPrivateProfileString( LPCWSTR section, LPCWSTR entry,
BOOL win32 )
{
int ret;
LPCWSTR pDefVal = NULL;
LPWSTR defval_tmp = NULL;
DPRINT("%S, %S, %S, %p, %u, %S\n",
section, entry,
@ -1121,52 +1143,40 @@ static int PROFILE_GetPrivateProfileString( LPCWSTR section, LPCWSTR entry,
/* strip any trailing ' ' of def_val. */
if (def_val)
{
LPCWSTR p = &def_val[wcslen(def_val)]; /* even "" works ! */
LPCWSTR p = def_val + wcslen(def_val) - 1;
while (p > def_val)
{
while (p > def_val && *p == ' ')
p--;
if ((*p) != ' ')
break;
}
if (*p == ' ') /* ouch, contained trailing ' ' */
if (p >= def_val)
{
int len = (int)(p - def_val);
LPWSTR p;
int len = (int)(p - def_val) + 1;
p = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
if(p == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
memcpy(p, def_val, len * sizeof(WCHAR));
p[len] = '\0';
pDefVal = p;
defval_tmp = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
memcpy(defval_tmp, def_val, len * sizeof(WCHAR));
defval_tmp[len] = '\0';
def_val = defval_tmp;
}
}
if (!pDefVal)
pDefVal = (LPCWSTR)def_val;
RtlEnterCriticalSection( &PROFILE_CritSect );
if (PROFILE_Open( filename )) {
if (PROFILE_Open( filename, FALSE )) {
if (win32 && (section == NULL))
ret = PROFILE_GetSectionNames(buffer, len);
else
/* PROFILE_GetString can handle the 'entry == NULL' case */
ret = PROFILE_GetString( section, entry, pDefVal, buffer, len, win32 );
} else {
lstrcpynW( buffer, pDefVal, len );
ret = PROFILE_GetString( section, entry, def_val, buffer, len, win32 );
} else if (buffer && def_val) {
lstrcpynW( buffer, def_val, len );
ret = wcslen( buffer );
}
else
ret = 0;
RtlLeaveCriticalSection( &PROFILE_CritSect );
if (pDefVal != def_val) /* allocated */
HeapFree(GetProcessHeap(), 0, (void*)pDefVal);
HeapFree(GetProcessHeap(), 0, defval_tmp);
DPRINT("returning %S, %d\n", buffer, ret);
@ -1302,7 +1312,7 @@ UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry,
return (UINT)def_val;
RtlInitUnicodeString( &bufferW, buffer );
RtlUnicodeStringToInteger( &bufferW, 10, &result);
RtlUnicodeStringToInteger( &bufferW, 0, &result); // 10
return result;
}
@ -1350,7 +1360,7 @@ DWORD WINAPI GetPrivateProfileSectionW( LPCWSTR section, LPWSTR buffer,
RtlEnterCriticalSection( &PROFILE_CritSect );
if (PROFILE_Open( filename ))
if (PROFILE_Open( filename, FALSE ))
ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, TRUE, FALSE);
RtlLeaveCriticalSection( &PROFILE_CritSect );
@ -1434,12 +1444,12 @@ BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
if (!section && !entry && !string) /* documented "file flush" case */
{
if (!filename || PROFILE_Open( filename ))
if (!filename || PROFILE_Open( filename, TRUE ))
{
if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */
}
}
else if (PROFILE_Open( filename ))
else if (PROFILE_Open( filename, TRUE ))
{
if (!section) {
DPRINT1("(NULL?, %S, %S, %S)?\n",
@ -1494,12 +1504,12 @@ BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section,
if (!section && !string)
{
if (!filename || PROFILE_Open( filename ))
if (!filename || PROFILE_Open( filename, TRUE ))
{
if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */
}
}
else if (PROFILE_Open( filename )) {
else if (PROFILE_Open( filename, TRUE )) {
if (!string) {/* delete the named section*/
ret = PROFILE_SetString(section,NULL,NULL, FALSE);
PROFILE_FlushFile();
@ -1628,7 +1638,7 @@ DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size,
RtlEnterCriticalSection( &PROFILE_CritSect );
if (PROFILE_Open( filename ))
if (PROFILE_Open( filename, FALSE ))
ret = PROFILE_GetSectionNames(buffer, size);
RtlLeaveCriticalSection( &PROFILE_CritSect );
@ -1685,7 +1695,7 @@ BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key,
RtlEnterCriticalSection( &PROFILE_CritSect );
if (PROFILE_Open( filename ))
if (PROFILE_Open( filename, FALSE ))
{
PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE, FALSE);
if (k)
@ -1814,7 +1824,7 @@ BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key,
RtlEnterCriticalSection( &PROFILE_CritSect );
if (PROFILE_Open( filename ))
if (PROFILE_Open( filename, TRUE ))
{
ret = PROFILE_SetString( section, key, outstring, FALSE);
PROFILE_FlushFile();