*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <k32.h>
#define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
static const WCHAR emptystringW[] = {0};
+static const WCHAR wininiW[] = { 'w','i','n','.','i','n','i',0 };
static RTL_CRITICAL_SECTION PROFILE_CritSect;
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &PROFILE_CritSect,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
- 0, 0, 0, 0
+ 0, 0, 0, 0, 0
};
static RTL_CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };
static const char hex[16] = "0123456789ABCDEF";
-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 NULL;
-}
-
-static __inline WCHAR *memrchrW( const WCHAR *ptr, WCHAR ch, size_t n )
-{
- const WCHAR *end, *ret = NULL;
- for (end = ptr + n; ptr < end; ptr++)
- if (*ptr == ch)
- ret = ptr;
- return (WCHAR *)ret;
-}
-
/***********************************************************************
* PROFILE_CopyEntry
*
if (quote && (len >= (int)wcslen(value))) buffer[wcslen(buffer)-1] = '\0';
}
-
/* byte-swaps shorts in-place in a buffer. len is in WCHARs */
static __inline void PROFILE_ByteSwapShortBuffer(WCHAR * buffer, int len)
{
int i;
- USHORT * shortbuffer = (USHORT *)buffer;
+ USHORT * shortbuffer = buffer;
for (i = 0; i < len; i++)
shortbuffer[i] = RtlUshortByteSwap(shortbuffer[i]);
}
-
/* writes any necessary encoding marker to the file */
static __inline void PROFILE_WriteMarker(HANDLE hFile, ENCODING encoding)
{
DWORD dwBytesWritten;
- DWORD bom;
+ WCHAR bom;
switch (encoding)
{
case ENCODING_ANSI:
}
}
-
static void PROFILE_WriteLine( HANDLE hFile, WCHAR * szLine, int len, ENCODING encoding)
{
char * write_buffer;
}
}
-
/***********************************************************************
* PROFILE_Save
*
{
int len = 0;
- if (section->name[0]) len += wcslen(section->name) + 6;
+ if (section->name[0]) len += wcslen(section->name) + 4;
for (key = section->key; key; key = key->next)
{
p = buffer;
if (section->name[0])
{
- *p++ = '\r';
- *p++ = '\n';
*p++ = '[';
wcscpy( p, section->name );
p += wcslen(p);
*p++ = '\r';
*p++ = '\n';
}
+
for (key = section->key; key; key = key->next)
{
wcscpy( p, key->name );
}
}
-
/* 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;
}
-
static __inline ENCODING PROFILE_DetectTextEncoding(const void * buffer, int * len)
{
INT flags = IS_TEXT_UNICODE_SIGNATURE |
IS_TEXT_UNICODE_REVERSE_SIGNATURE |
IS_TEXT_UNICODE_ODD_LENGTH;
- if (*len >= (int)sizeof(bom_utf8) && !memcmp(buffer, bom_utf8, sizeof(bom_utf8)))
+ if (*len >= sizeof(bom_utf8) && !memcmp(buffer, bom_utf8, sizeof(bom_utf8)))
{
*len = sizeof(bom_utf8);
return ENCODING_UTF8;
*/
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;
DPRINT("%p\n", hFile);
dwFileSize = GetFileSize(hFile, NULL);
- if (dwFileSize == INVALID_FILE_SIZE)
+ if (dwFileSize == INVALID_FILE_SIZE || dwFileSize == 0)
return NULL;
- pBuffer = HeapAlloc(GetProcessHeap(), 0 , dwFileSize);
- if (!pBuffer)
- return NULL;
-
- if (!ReadFile(hFile, pBuffer, dwFileSize, &dwFileSize, NULL))
+ buffer_base = HeapAlloc(GetProcessHeap(), 0 , dwFileSize);
+ if (!buffer_base) return 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)
{
case ENCODING_ANSI:
DPRINT("ANSI encoding\n");
- len = MultiByteToWideChar(CP_ACP, 0, (char *)pBuffer, dwFileSize, NULL, 0);
+ len = MultiByteToWideChar(CP_ACP, 0, pBuffer, dwFileSize, NULL, 0);
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);
+ MultiByteToWideChar(CP_ACP, 0, pBuffer, dwFileSize, szFile, len);
szEnd = szFile + len;
break;
-
case ENCODING_UTF8:
DPRINT("UTF8 encoding\n");
- len = MultiByteToWideChar(CP_UTF8, 0, (char *)pBuffer, dwFileSize, NULL, 0);
+ len = MultiByteToWideChar(CP_UTF8, 0, pBuffer, dwFileSize, NULL, 0);
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);
+ MultiByteToWideChar(CP_UTF8, 0, pBuffer, dwFileSize, szFile, len);
szEnd = szFile + len;
break;
-
case ENCODING_UTF16LE:
DPRINT("UTF16 Little Endian encoding\n");
- szFile = (WCHAR *)pBuffer + 1;
+ szFile = pBuffer;
szEnd = (WCHAR *)((char *)pBuffer + dwFileSize);
break;
-
case ENCODING_UTF16BE:
DPRINT("UTF16 Big Endian encoding\n");
- szFile = (WCHAR *)pBuffer + 1;
+ szFile = pBuffer;
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;
}
first_section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) );
- if (first_section == NULL)
+ if(first_section == NULL)
{
if (szFile != pBuffer)
HeapFree(GetProcessHeap(), 0, szFile);
- HeapFree(GetProcessHeap(), 0, pBuffer);
+ HeapFree(GetProcessHeap(), 0, buffer_base);
return NULL;
}
first_section->name[0] = 0;
{
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;
/* 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;
+ if (szLineStart >= szLineEnd) continue;
if (*szLineStart == '[') /* section start */
{
{
len = (int)(szLineEnd - szValueStart);
key->value = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
+ if (!key->value) break;
memcpy(key->value, szValueStart, len * sizeof(WCHAR));
key->value[len] = '\0';
}
}
if (szFile != pBuffer)
HeapFree(GetProcessHeap(), 0, szFile);
- HeapFree(GetProcessHeap(), 0, pBuffer);
+ HeapFree(GetProcessHeap(), 0, buffer_base);
return first_section;
}
int seclen, keylen;
while (PROFILE_isspaceW(*section_name)) section_name++;
- p = section_name + wcslen(section_name) - 1;
+ if (*section_name)
+ p = section_name + wcslen(section_name) - 1;
+ else
+ p = section_name;
+
while ((p > section_name) && PROFILE_isspaceW(*p)) p--;
seclen = p - section_name + 1;
while (PROFILE_isspaceW(*key_name)) key_name++;
- p = key_name + wcslen(key_name) - 1;
+ if (*key_name)
+ p = key_name + wcslen(key_name) - 1;
+ else
+ p = key_name;
+
while ((p > key_name) && PROFILE_isspaceW(*p)) p--;
keylen = p - key_name + 1;
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)
{
ZeroMemory(&CurProfile->LastWriteTime, sizeof(CurProfile->LastWriteTime));
}
+/***********************************************************************
+ *
+ * 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];
GetWindowsDirectoryW( windirW, MAX_PATH );
if (!filename)
- filename = L"win.ini";
+ filename = wininiW;
if ((RtlDetermineDosPathNameType_U(filename) == RtlPathTypeRelative) &&
!wcschr(filename, '\\') && !wcschr(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))
{
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);
+ PROFILE_Free(CurProfile->section);
+ CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding);
+ CurProfile->LastWriteTime = LastWriteTime;
+ }
+ CloseHandle(hFile);
+ }
+ else DPRINT("(%S): already opened (mru = %d)\n", buffer, i );
+
return TRUE;
}
}
MRUProfile[i] = MRUProfile[i-1];
CurProfile=tempProfile;
}
-
- if (CurProfile->filename)
- PROFILE_ReleaseFile();
+ if(CurProfile->filename) PROFILE_ReleaseFile();
/* OK, now that CurProfile is definitely free we assign it our new file */
CurProfile->filename = HeapAlloc( GetProcessHeap(), 0, (wcslen(buffer)+1) * sizeof(WCHAR) );
* If return_values is TRUE, also include the corresponding values.
*/
static INT PROFILE_GetSection( PROFILESECTION *section, LPCWSTR section_name,
- LPWSTR buffer, UINT len, BOOL return_values, BOOL return_noequalkeys )
+ LPWSTR buffer, UINT len, BOOL return_values )
{
PROFILEKEY *key;
- if (!buffer)
- return 0;
+ if(!buffer) return 0;
DPRINT("%S,%p,%u\n", section_name, buffer, len);
if (len <= 2) break;
if (!*key->name) continue; /* Skip empty lines */
if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
- if (!return_noequalkeys && !return_values && !key->value) continue; /* Skip lines w.o. '=' */
+ if (!return_values && !key->value) continue; /* Skip lines w.o. '=' */
PROFILE_CopyEntry( buffer, key->name, len - 1, 0 );
len -= wcslen(buffer) + 1;
buffer += wcslen(buffer) + 1;
*
*/
static INT PROFILE_GetString( LPCWSTR section, LPCWSTR key_name,
- LPCWSTR def_val, LPWSTR buffer, UINT len, BOOL win32 )
+ LPCWSTR def_val, LPWSTR buffer, UINT len )
{
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,
/* no "else" here ! */
if (section && section[0])
{
- INT ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, FALSE, !win32);
+ INT ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, FALSE);
if (!buffer[0]) /* no luck -> def_val */
{
PROFILE_CopyEntry(buffer, def_val, len, TRUE);
return GetPrivateProfileIntW( section, entry, def_val, L"win.ini" );
}
-/*
- * if win32, copy:
- * - Section names if 'section' is NULL
- * - Keys in a Section if 'entry' is NULL
- * (see MSDN doc for GetPrivateProfileString)
+/***********************************************************************
+ * GetPrivateProfileStringW (KERNEL32.@)
*/
-static int PROFILE_GetPrivateProfileString( LPCWSTR section, LPCWSTR entry,
- LPCWSTR def_val, LPWSTR buffer,
- UINT len, LPCWSTR filename,
- BOOL win32 )
+DWORD WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
+ LPCWSTR def_val, LPWSTR buffer,
+ DWORD len, LPCWSTR filename )
{
int ret;
- LPCWSTR pDefVal = NULL;
+ LPWSTR defval_tmp = NULL;
DPRINT("%S, %S, %S, %p, %u, %S\n",
- section, entry,
- def_val, buffer, len, filename);
+ section, entry, def_val, buffer, len, filename);
/* 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;
-
- 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;
+ int len = (int)(p - def_val) + 1;
+
+ defval_tmp = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
+ if (!defval_tmp) return 0;
+ 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 (win32 && (section == NULL))
+ if (PROFILE_Open( filename, FALSE )) {
+ if (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 );
+ } 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);
return ret;
}
-
/***********************************************************************
* GetPrivateProfileStringA (KERNEL32.@)
*/
filenameW.Buffer);
if (len)
{
- ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW + 1, buffer, len, NULL, NULL);
- if (!ret)
+ if (retW)
{
- ret = len - 1;
- buffer[ret] = 0;
+ ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW, buffer, len - 1, NULL, NULL);
+ if (!ret)
+ ret = len - 1;
}
- else
- ret--; /* strip terminating 0 */
+ buffer[ret] = 0;
}
RtlFreeUnicodeString(§ionW);
return ret;
}
-
-/***********************************************************************
- * GetPrivateProfileStringW (KERNEL32.@)
- */
-DWORD WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
- LPCWSTR def_val, LPWSTR buffer,
- DWORD len, LPCWSTR filename )
-{
- DPRINT("(%S, %S, %S, %p, %d, %S)\n",
- section, entry, def_val, buffer, len, filename);
-
- return PROFILE_GetPrivateProfileString( section, entry, def_val,
- buffer, len, filename, TRUE );
-}
-
-
/***********************************************************************
* GetProfileStringA (KERNEL32.@)
*/
buffer, len, "win.ini" );
}
-
/***********************************************************************
* GetProfileStringW (KERNEL32.@)
*/
filename )))
return def_val;
- if (len+1 == sizeof(buffer)/sizeof(WCHAR))
- DPRINT1("result may be wrong!\n");
-
/* FIXME: if entry can be found but it's empty, then Win16 is
* supposed to return 0 instead of def_val ! Difficult/problematic
* to implement (every other failure also returns zero buffer),
* thus wait until testing framework avail for making sure nothing
* else gets broken that way. */
- if (!buffer[0])
- return (UINT)def_val;
+ if (!buffer[0]) return (UINT)def_val;
RtlInitUnicodeString( &bufferW, buffer );
- RtlUnicodeStringToInteger( &bufferW, 10, &result);
+ RtlUnicodeStringToInteger( &bufferW, 0, &result);
return result;
}
return res;
}
-
/***********************************************************************
* GetPrivateProfileSectionW (KERNEL32.@)
*/
return 0;
}
- DPRINT("(%S, %p, %ld, %S)\n",
- section, buffer, len, filename);
+ DPRINT("(%S, %p, %ld, %S)\n", section, buffer, len, filename);
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename ))
- ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, TRUE, FALSE);
+ if (PROFILE_Open( filename, FALSE ))
+ ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, TRUE);
RtlLeaveCriticalSection( &PROFILE_CritSect );
return ret;
}
-
/***********************************************************************
* GetPrivateProfileSectionA (KERNEL32.@)
*/
return 0;
}
- bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ bufferW = HeapAlloc(GetProcessHeap(), 0, len * 2 * sizeof(WCHAR));
+ if (!bufferW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+
RtlCreateUnicodeStringFromAsciiz(§ionW, section);
if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename);
else filenameW.Buffer = NULL;
- retW = GetPrivateProfileSectionW(sectionW.Buffer, bufferW, len, filenameW.Buffer);
- if (len > 2)
+ retW = GetPrivateProfileSectionW(sectionW.Buffer, bufferW, len * 2, filenameW.Buffer);
+ if (retW)
{
+ if (retW == len * 2 - 2) retW++; /* overflow */
ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW + 1, buffer, len, NULL, NULL);
- if (ret > 2)
- ret -= 1;
- else
+ if (!ret || ret == len) /* overflow */
{
- ret = 0;
+ ret = len - 2;
buffer[len-2] = 0;
buffer[len-1] = 0;
}
+ else ret--;
}
else
{
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",
- entry, string, filename);
+ SetLastError(ERROR_FILE_NOT_FOUND);
} else {
ret = PROFILE_SetString( section, entry, string, FALSE);
PROFILE_FlushFile();
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();
*/
BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values)
{
- return WritePrivateProfileSectionW(section, keys_n_values, L"win.ini");
+ return WritePrivateProfileSectionW(section, keys_n_values, wininiW);
}
* Win95:
* - if the buffer is 0 or 1 character long then it is as if it was of
* infinite length.
- * - otherwise, if the buffer is to small only the section names that fit
+ * - otherwise, if the buffer is too small only the section names that fit
* are returned.
- * - note that this means if the buffer was to small to return even just
+ * - note that this means if the buffer was too small to return even just
* the first section name then a single '\0' will be returned.
* - the return value is the number of characters written in the buffer,
- * except if the buffer was too smal in which case len-2 is returned
+ * except if the buffer was too small in which case len-2 is returned
*
* Win2000:
* - if the buffer is 0, 1 or 2 characters long then it is filled with
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename ))
+ if (PROFILE_Open( filename, FALSE ))
ret = PROFILE_GetSectionNames(buffer, size);
RtlLeaveCriticalSection( &PROFILE_CritSect );
INT retW, ret = 0;
bufferW = buffer ? HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)) : NULL;
- if (filename)
- RtlCreateUnicodeStringFromAsciiz(&filenameW, filename);
- else
- filenameW.Buffer = NULL;
+ if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename);
+ else filenameW.Buffer = NULL;
retW = GetPrivateProfileSectionNamesW(bufferW, size, filenameW.Buffer);
if (retW && size)
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename ))
+ if (PROFILE_Open( filename, FALSE ))
{
PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE, FALSE);
if (k)
{
BOOL highnibble = TRUE;
BYTE b = 0, val;
- LPBYTE binbuf = (LPBYTE)buf;
+ LPBYTE binbuf = buf;
end -= 2; /* don't include checksum in output data */
/* translate ASCII hex format into binary data */
}
+
/***********************************************************************
* WritePrivateProfileStructW (KERNEL32.@)
*/
RtlEnterCriticalSection( &PROFILE_CritSect );
- if (PROFILE_Open( filename ))
+ if (PROFILE_Open( filename, TRUE ))
{
ret = PROFILE_SetString( section, key, outstring, FALSE);
PROFILE_FlushFile();
return ret;
}
-
/***********************************************************************
* WritePrivateProfileStructA (KERNEL32.@)
*/
/***********************************************************************
- * CloseProfileUserMapping
+ * OpenProfileUserMapping (KERNEL32.@)
*/
-BOOL WINAPI
-CloseProfileUserMapping(VOID)
+BOOL WINAPI OpenProfileUserMapping(VOID)
+{
+ DPRINT1("(), stub!\n");
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+/***********************************************************************
+ * CloseProfileUserMapping (KERNEL32.@)
+ */
+BOOL WINAPI CloseProfileUserMapping(VOID)
{
DPRINT1("(), stub!\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
* @unimplemented
*/
BOOL
-STDCALL
+WINAPI
QueryWin31IniFilesMappedToRegistry(DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2,