mirror of
https://github.com/reactos/reactos.git
synced 2025-04-25 16:10:29 +00:00
- Partial sync with Wine. It fixes 37 tests ("kernel32_winetest profile")
svn path=/trunk/; revision=38368
This commit is contained in:
parent
77f0be0bc8
commit
d3294eb866
1 changed files with 93 additions and 83 deletions
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue