Author: dchapyshev
Date: Sat Dec 27 02:34:30 2008
New Revision: 38368
URL:
http://svn.reactos.org/svn/reactos?rev=38368&view=rev
Log:
- Partial sync with Wine. It fixes 37 tests ("kernel32_winetest profile")
Modified:
trunk/reactos/dll/win32/kernel32/misc/profile.c
Modified: trunk/reactos/dll/win32/kernel32/misc/profile.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/misc/pr…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/misc/profile.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/misc/profile.c [iso-8859-1] Sat Dec 27 02:34:30 2008
@@ -88,17 +88,18 @@
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_WriteMarker(HANDLE hFile, ENCODING encoding)
{
DWORD dwBytesWritten;
- DWORD bom;
+ WCHAR bom;
switch (encoding)
{
case ENCODING_ANSI:
@@ -283,12 +284,8 @@
/* 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 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 @@
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))
- {
- HeapFree(GetProcessHeap(), 0, pBuffer);
+ if (!ReadFile(hFile, buffer_base, dwFileSize, &dwFileSize, NULL))
+ {
+ 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 @@
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 @@
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 @@
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 @@
{
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 @@
{
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 @@
/* 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 @@
}
if (szFile != pBuffer)
HeapFree(GetProcessHeap(), 0, szFile);
- HeapFree(GetProcessHeap(), 0, pBuffer);
+ HeapFree(GetProcessHeap(), 0, buffer_base);
return first_section;
}
@@ -688,7 +686,8 @@
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)
{
@@ -725,11 +724,32 @@
/***********************************************************************
+ *
+ * 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 @@
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 @@
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 @@
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 @@
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 @@
/* strip any trailing ' ' of def_val. */
if (def_val)
{
- LPCWSTR p = &def_val[wcslen(def_val)]; /* even "" works ! */
-
- while (p > def_val)
- {
+ LPCWSTR p = def_val + wcslen(def_val) - 1;
+
+ while (p > def_val && *p == ' ')
p--;
- if ((*p) != ' ')
- break;
- }
-
- if (*p == ' ') /* ouch, contained trailing ' ' */
- {
- int len = (int)(p - def_val);
- LPWSTR p;
-
- 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;
- }
- }
-
- if (!pDefVal)
- pDefVal = (LPCWSTR)def_val;
+
+ if (p >= def_val)
+ {
+ int len = (int)(p - def_val) + 1;
+
+ 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;
+ }
+ }
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 @@
return (UINT)def_val;
RtlInitUnicodeString( &bufferW, buffer );
- RtlUnicodeStringToInteger( &bufferW, 10, &result);
+ RtlUnicodeStringToInteger( &bufferW, 0, &result); // 10
return result;
}
@@ -1350,7 +1360,7 @@
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 @@
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 @@
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 @@
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename ))
+ if (PROFILE_Open( filename, FALSE ))
ret = PROFILE_GetSectionNames(buffer, size);
RtlLeaveCriticalSection( &PROFILE_CritSect );
@@ -1685,7 +1695,7 @@
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 @@
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename ))
+ if (PROFILE_Open( filename, TRUE ))
{
ret = PROFILE_SetString( section, key, outstring, FALSE);
PROFILE_FlushFile();