2004-06-13 20:04:56 +00:00
|
|
|
/* $Id: profile.c,v 1.12 2004/06/13 20:04:56 navaraf Exp $
|
2004-01-30 21:48:09 +00:00
|
|
|
*
|
|
|
|
* Imported from Wine
|
|
|
|
* Copyright 1993 Miguel de Icaza
|
|
|
|
* Copyright 1996 Alexandre Julliard
|
2001-03-31 01:17:30 +00:00
|
|
|
*
|
|
|
|
* PROJECT: ReactOS system libraries
|
|
|
|
* FILE: lib/kernel32/misc/profile.c
|
|
|
|
* PURPOSE: Profiles functions
|
|
|
|
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
|
|
|
* modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
|
|
|
|
* UPDATE HISTORY:
|
|
|
|
* Created 01/11/98
|
|
|
|
*/
|
|
|
|
|
2003-01-15 21:24:36 +00:00
|
|
|
#include <k32.h>
|
2001-03-31 01:17:30 +00:00
|
|
|
|
2004-01-30 22:12:47 +00:00
|
|
|
#define NDEBUG
|
2004-01-30 21:48:09 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
static CRITICAL_SECTION ProfileLock;
|
|
|
|
|
|
|
|
typedef struct tagPROFILEKEY
|
|
|
|
{
|
|
|
|
WCHAR *Value;
|
|
|
|
struct tagPROFILEKEY *Next;
|
|
|
|
WCHAR Name[1];
|
|
|
|
} PROFILEKEY;
|
|
|
|
|
|
|
|
typedef struct tagPROFILESECTION
|
|
|
|
{
|
|
|
|
struct tagPROFILEKEY *Key;
|
|
|
|
struct tagPROFILESECTION *Next;
|
|
|
|
WCHAR Name[1];
|
|
|
|
} PROFILESECTION;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
BOOL Changed;
|
|
|
|
PROFILESECTION *Section;
|
|
|
|
WCHAR *FullName;
|
|
|
|
FILETIME LastWriteTime;
|
|
|
|
} PROFILE;
|
|
|
|
|
|
|
|
|
|
|
|
#define N_CACHED_PROFILES 10
|
|
|
|
|
|
|
|
/* Cached profile files */
|
|
|
|
static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL};
|
|
|
|
|
|
|
|
#define CurProfile (MRUProfile[0])
|
|
|
|
|
|
|
|
#define PROFILE_MAX_LINE_LEN 1024
|
|
|
|
|
|
|
|
/* Check for comments in profile */
|
|
|
|
#define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
|
2001-06-07 21:27:45 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2004-01-30 21:48:09 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_CopyEntry
|
|
|
|
*
|
|
|
|
* Copy the content of an entry into a buffer, removing quotes, and possibly
|
|
|
|
* translating environment variables.
|
|
|
|
*/
|
|
|
|
STATIC void FASTCALL
|
|
|
|
PROFILE_CopyEntry(LPWSTR Buffer, LPCWSTR Value, int Len, BOOL StripQuote)
|
|
|
|
{
|
|
|
|
WCHAR Quote = L'\0';
|
|
|
|
|
|
|
|
if (NULL == Buffer)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StripQuote && (L'\'' == *Value || L'\"' == *Value))
|
|
|
|
{
|
|
|
|
if (L'\0' != Value[1] && (Value[wcslen(Value) - 1] == *Value))
|
|
|
|
{
|
|
|
|
Quote = *Value++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lstrcpynW(Buffer, Value, Len);
|
|
|
|
if (L'\0' != Quote && wcslen(Value) <= Len)
|
|
|
|
{
|
|
|
|
Buffer[wcslen(Buffer) - 1] = L'\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_Save
|
|
|
|
*
|
|
|
|
* Save a profile tree to a file.
|
|
|
|
*/
|
|
|
|
STATIC void FASTCALL
|
|
|
|
PROFILE_Save(HANDLE File, PROFILESECTION *Section)
|
|
|
|
{
|
|
|
|
PROFILEKEY *Key;
|
|
|
|
char Buffer[PROFILE_MAX_LINE_LEN];
|
|
|
|
DWORD BytesWritten;
|
|
|
|
|
|
|
|
for ( ; NULL != Section; Section = Section->Next)
|
|
|
|
{
|
|
|
|
if (L'\0' != Section->Name[0])
|
|
|
|
{
|
|
|
|
strcpy(Buffer, "\r\n[");
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, Section->Name, -1, Buffer + 3, sizeof(Buffer) - 6, NULL, NULL);
|
|
|
|
strcat(Buffer, "]\r\n");
|
|
|
|
WriteFile(File, Buffer, strlen(Buffer), &BytesWritten, NULL);
|
|
|
|
}
|
|
|
|
for (Key = Section->Key; NULL != Key; Key = Key->Next)
|
|
|
|
{
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, Key->Name, -1, Buffer, sizeof(Buffer) - 3, NULL, NULL);
|
|
|
|
if (Key->Value)
|
|
|
|
{
|
|
|
|
strcat(Buffer, "=");
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, Key->Value, -1, Buffer + strlen(Buffer),
|
|
|
|
sizeof(Buffer) - strlen(Buffer) - 2, NULL, NULL);
|
|
|
|
}
|
|
|
|
strcat(Buffer, "\r\n");
|
|
|
|
WriteFile(File, Buffer, strlen(Buffer), &BytesWritten, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_Free
|
|
|
|
*
|
|
|
|
* Free a profile tree.
|
|
|
|
*/
|
|
|
|
STATIC void FASTCALL
|
|
|
|
PROFILE_Free(PROFILESECTION *Section)
|
|
|
|
{
|
|
|
|
PROFILESECTION *NextSection;
|
|
|
|
PROFILEKEY *Key, *NextKey;
|
|
|
|
|
|
|
|
for ( ; NULL != Section; Section = NextSection)
|
|
|
|
{
|
|
|
|
for (Key = Section->Key; NULL != Key; Key = NextKey)
|
|
|
|
{
|
|
|
|
NextKey = Key->Next;
|
|
|
|
if (NULL != Key->Value)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, Key->Value);
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, Key);
|
|
|
|
}
|
|
|
|
NextSection = Section->Next;
|
|
|
|
HeapFree(GetProcessHeap(), 0, Section);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC inline int
|
|
|
|
PROFILE_isspace(char c)
|
|
|
|
{
|
|
|
|
if (isspace(c))
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if ('\r' == c || 0x1a == c)
|
|
|
|
{
|
|
|
|
/* CR and ^Z (DOS EOF) are spaces too (found on CD-ROMs) */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_Load
|
|
|
|
*
|
|
|
|
* Load a profile tree from a file.
|
|
|
|
*/
|
|
|
|
static PROFILESECTION * FASTCALL
|
|
|
|
PROFILE_Load(HANDLE File)
|
|
|
|
{
|
|
|
|
char *p, *p2;
|
|
|
|
int Len;
|
|
|
|
PROFILESECTION *Section, *FirstSection;
|
|
|
|
PROFILESECTION **NextSection;
|
|
|
|
PROFILEKEY *Key, *PrevKey, **NextKey;
|
|
|
|
LARGE_INTEGER FileSize;
|
|
|
|
HANDLE Mapping;
|
|
|
|
PVOID BaseAddress;
|
|
|
|
char *Input, *End;
|
|
|
|
|
|
|
|
FileSize.u.LowPart = GetFileSize(File, &FileSize.u.HighPart);
|
|
|
|
if (INVALID_FILE_SIZE == FileSize.u.LowPart && 0 != GetLastError())
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
FirstSection = HeapAlloc(GetProcessHeap(), 0, sizeof(*Section));
|
|
|
|
if (NULL == FirstSection)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
FirstSection->Name[0] = L'\0';
|
|
|
|
FirstSection->Key = NULL;
|
|
|
|
FirstSection->Next = NULL;
|
|
|
|
NextSection = &FirstSection->Next;
|
|
|
|
NextKey = &FirstSection->Key;
|
|
|
|
PrevKey = NULL;
|
|
|
|
|
|
|
|
if (0 == FileSize.QuadPart)
|
|
|
|
{
|
|
|
|
return FirstSection;
|
|
|
|
}
|
|
|
|
Mapping = CreateFileMappingW(File, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
|
|
|
|
if (NULL == Mapping)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, FirstSection);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
BaseAddress = MapViewOfFile(Mapping, FILE_MAP_READ, 0, 0, 0);
|
|
|
|
if (NULL == BaseAddress)
|
|
|
|
{
|
|
|
|
CloseHandle(Mapping);
|
|
|
|
HeapFree(GetProcessHeap(), 0, FirstSection);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Input = (char *) BaseAddress;
|
|
|
|
End = Input + FileSize.QuadPart;
|
|
|
|
while (Input < End)
|
|
|
|
{
|
|
|
|
while (Input < End && PROFILE_isspace(*Input))
|
|
|
|
{
|
|
|
|
Input++;
|
|
|
|
}
|
|
|
|
if (End <= Input)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ('[' == *Input) /* section start */
|
|
|
|
{
|
|
|
|
p = ++Input;
|
|
|
|
while (p < End && ']' != *p && '\n' != *p)
|
|
|
|
{
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (p < End && ']' == *p)
|
|
|
|
{
|
|
|
|
Len = p - Input;
|
|
|
|
if (NULL == (Section = HeapAlloc(GetProcessHeap(), 0,
|
|
|
|
sizeof(*Section) + Len * sizeof(WCHAR))))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, Input, Len, Section->Name, Len);
|
|
|
|
Section->Name[Len] = L'\0';
|
|
|
|
Section->Key = NULL;
|
|
|
|
Section->Next = NULL;
|
|
|
|
*NextSection = Section;
|
|
|
|
NextSection = &Section->Next;
|
|
|
|
NextKey = &Section->Key;
|
|
|
|
PrevKey = NULL;
|
|
|
|
|
|
|
|
DPRINT("New section: %S\n", Section->Name);
|
|
|
|
|
|
|
|
}
|
|
|
|
Input = p;
|
|
|
|
while (Input < End && '\n' != *Input)
|
|
|
|
{
|
|
|
|
Input++;
|
|
|
|
}
|
|
|
|
Input++; /* Skip past the \n */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = Input;
|
|
|
|
p2 = p;
|
|
|
|
while (p < End && '=' != *p && '\n' != *p)
|
|
|
|
{
|
|
|
|
if (! PROFILE_isspace(*p))
|
|
|
|
{
|
|
|
|
p2 = p;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < End && '=' == *p)
|
|
|
|
{
|
|
|
|
Len = p2 - Input + 1;
|
|
|
|
if (NULL == (Key = HeapAlloc(GetProcessHeap(), 0,
|
|
|
|
sizeof(*Key) + Len * sizeof(WCHAR))))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, Input, Len, Key->Name, Len);
|
|
|
|
Key->Name[Len] = L'\0';
|
|
|
|
Input = p + 1;
|
|
|
|
while (Input < End && '\n' != *Input && PROFILE_isspace(*Input))
|
|
|
|
{
|
|
|
|
Input++;
|
|
|
|
}
|
|
|
|
if (End <= Input || '\n' == *Input)
|
|
|
|
{
|
|
|
|
Key->Value = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p2 = Input;
|
|
|
|
p = Input + 1;
|
|
|
|
while (p < End && '\n' != *p)
|
|
|
|
{
|
|
|
|
if (! PROFILE_isspace(*p))
|
|
|
|
{
|
|
|
|
p2 = p;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
Len = p2 - Input + 1;
|
|
|
|
if (NULL == (Key->Value = HeapAlloc(GetProcessHeap(), 0,
|
|
|
|
(Len + 1) * sizeof(WCHAR))))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, Input, Len, Key->Value, Len);
|
|
|
|
Key->Value[Len] = L'\0';
|
|
|
|
|
|
|
|
Key->Next = NULL;
|
|
|
|
*NextKey = Key;
|
|
|
|
NextKey = &Key->Next;
|
|
|
|
PrevKey = Key;
|
|
|
|
|
|
|
|
DPRINT("New key: name=%S, value=%S\n",
|
|
|
|
Key->Name, NULL != Key->Value ? Key->Value : L"(none)");
|
|
|
|
|
|
|
|
Input = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (Input < End && '\n' != *Input)
|
|
|
|
{
|
|
|
|
Input++;
|
|
|
|
}
|
|
|
|
Input++; /* Skip past the \n */
|
|
|
|
}
|
|
|
|
|
|
|
|
UnmapViewOfFile(BaseAddress);
|
|
|
|
CloseHandle(Mapping);
|
|
|
|
|
|
|
|
return FirstSection;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_Find
|
|
|
|
*
|
|
|
|
* Find a key in a profile tree, optionally creating it.
|
|
|
|
*/
|
|
|
|
static PROFILEKEY * FASTCALL
|
|
|
|
PROFILE_Find(PROFILESECTION **Section, LPCWSTR SectionName,
|
|
|
|
LPCWSTR KeyName, BOOL Create, BOOL CreateAlways)
|
|
|
|
{
|
|
|
|
LPCWSTR p;
|
|
|
|
int SecLen, KeyLen;
|
|
|
|
|
|
|
|
while (PROFILE_isspace(*SectionName))
|
|
|
|
{
|
|
|
|
SectionName++;
|
|
|
|
}
|
|
|
|
p = SectionName + wcslen(SectionName) - 1;
|
|
|
|
while (SectionName < p && PROFILE_isspace(*p))
|
|
|
|
{
|
|
|
|
p--;
|
|
|
|
}
|
|
|
|
SecLen = p - SectionName + 1;
|
|
|
|
|
|
|
|
while (PROFILE_isspace(*KeyName))
|
|
|
|
{
|
|
|
|
KeyName++;
|
|
|
|
}
|
|
|
|
p = KeyName + wcslen(KeyName) - 1;
|
|
|
|
while (KeyName < p && PROFILE_isspace(*p))
|
|
|
|
{
|
|
|
|
p--;
|
|
|
|
}
|
|
|
|
KeyLen = p - KeyName + 1;
|
|
|
|
|
|
|
|
while (NULL != *Section)
|
|
|
|
{
|
|
|
|
if (L'\0' != ((*Section)->Name[0])
|
|
|
|
&& 0 == _wcsnicmp((*Section)->Name, SectionName, SecLen)
|
|
|
|
&& L'\0' == ((*Section)->Name)[SecLen])
|
|
|
|
{
|
|
|
|
PROFILEKEY **Key = &(*Section)->Key;
|
|
|
|
|
|
|
|
while (NULL != *Key)
|
|
|
|
{
|
|
|
|
/* If create_always is FALSE then we check if the keyname
|
|
|
|
* already exists. Otherwise we add it regardless of its
|
|
|
|
* existence, to allow keys to be added more than once in
|
|
|
|
* some cases.
|
|
|
|
*/
|
|
|
|
if (! CreateAlways)
|
|
|
|
{
|
|
|
|
if (0 == _wcsnicmp((*Key)->Name, KeyName, KeyLen)
|
|
|
|
&& L'\0' == ((*Key)->Name)[KeyLen])
|
|
|
|
{
|
|
|
|
return *Key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Key = &(*Key)->Next;
|
|
|
|
}
|
|
|
|
if (! Create)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (NULL == (*Key = HeapAlloc(GetProcessHeap(), 0,
|
|
|
|
sizeof(PROFILEKEY) + wcslen(KeyName) * sizeof(WCHAR))))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
wcscpy((*Key)->Name, KeyName);
|
|
|
|
(*Key)->Value = NULL;
|
|
|
|
(*Key)->Next = NULL;
|
|
|
|
return *Key;
|
|
|
|
}
|
|
|
|
Section = &(*Section)->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! Create)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
*Section = HeapAlloc(GetProcessHeap(), 0,
|
|
|
|
sizeof(PROFILESECTION) + wcslen(SectionName) * sizeof(WCHAR));
|
|
|
|
if (NULL == *Section)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
wcscpy((*Section)->Name, SectionName);
|
|
|
|
(*Section)->Next = NULL;
|
|
|
|
if (NULL == ((*Section)->Key = HeapAlloc(GetProcessHeap(), 0,
|
|
|
|
sizeof(PROFILEKEY) + wcslen(KeyName) * sizeof(WCHAR))))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, *Section);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
wcscpy((*Section)->Key->Name, KeyName );
|
|
|
|
(*Section)->Key->Value = NULL;
|
|
|
|
(*Section)->Key->Next = NULL;
|
|
|
|
|
|
|
|
return (*Section)->Key;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_FlushFile
|
|
|
|
*
|
|
|
|
* Flush the current profile to disk if changed.
|
|
|
|
*/
|
|
|
|
STATIC BOOL FASTCALL
|
|
|
|
PROFILE_FlushFile(void)
|
|
|
|
{
|
|
|
|
HANDLE File = INVALID_HANDLE_VALUE;
|
|
|
|
FILETIME LastWriteTime;
|
|
|
|
|
|
|
|
if (NULL == CurProfile)
|
|
|
|
{
|
|
|
|
DPRINT("No current profile!\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! CurProfile->Changed || NULL == CurProfile->FullName)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
File = CreateFileW(CurProfile->FullName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE == File)
|
|
|
|
{
|
|
|
|
DPRINT1("could not save profile file %s\n", CurProfile->FullName);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("Saving %S\n", CurProfile->FullName);
|
|
|
|
PROFILE_Save(File, CurProfile->Section);
|
|
|
|
if (GetFileTime(File, NULL, NULL, &LastWriteTime))
|
|
|
|
{
|
|
|
|
CurProfile->LastWriteTime.dwLowDateTime = LastWriteTime.dwLowDateTime;
|
|
|
|
CurProfile->LastWriteTime.dwHighDateTime = LastWriteTime.dwHighDateTime;
|
|
|
|
}
|
|
|
|
CurProfile->Changed = FALSE;
|
|
|
|
CloseHandle(File);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_ReleaseFile
|
|
|
|
*
|
|
|
|
* Flush the current profile to disk and remove it from the cache.
|
|
|
|
*/
|
|
|
|
STATIC void FASTCALL
|
|
|
|
PROFILE_ReleaseFile(void)
|
|
|
|
{
|
|
|
|
PROFILE_FlushFile();
|
|
|
|
PROFILE_Free(CurProfile->Section);
|
|
|
|
if (NULL != CurProfile->FullName)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, CurProfile->FullName);
|
|
|
|
}
|
|
|
|
CurProfile->Changed = FALSE;
|
|
|
|
CurProfile->Section = NULL;
|
|
|
|
CurProfile->FullName = NULL;
|
|
|
|
CurProfile->LastWriteTime.dwLowDateTime = 0;
|
|
|
|
CurProfile->LastWriteTime.dwHighDateTime = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_Open
|
|
|
|
*
|
|
|
|
* Open a profile file, checking the cached file first.
|
|
|
|
*/
|
|
|
|
STATIC BOOL FASTCALL
|
|
|
|
PROFILE_Open(LPCWSTR FileName)
|
|
|
|
{
|
|
|
|
WCHAR FullName[MAX_PATH];
|
|
|
|
HANDLE File = INVALID_HANDLE_VALUE;
|
|
|
|
int i, j;
|
|
|
|
PROFILE *TempProfile;
|
|
|
|
DWORD FullLen;
|
|
|
|
FILETIME LastWriteTime;
|
|
|
|
|
|
|
|
/* Build full path name */
|
|
|
|
|
|
|
|
if (wcschr(FileName, L'/') || wcschr(FileName, L'\\') ||
|
|
|
|
wcschr(FileName, L':'))
|
|
|
|
{
|
|
|
|
FullLen = GetFullPathNameW(FileName, MAX_PATH, FullName, NULL);
|
|
|
|
if (0 == FullLen || MAX_PATH < FullLen)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FullLen = GetWindowsDirectoryW(FullName, MAX_PATH);
|
|
|
|
if (0 == FullLen || MAX_PATH < FullLen + 1 + wcslen(FileName))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
wcscat(FullName, L"\\");
|
|
|
|
wcscat(FullName, FileName);
|
|
|
|
}
|
|
|
|
#if 0 /* FIXME: Not yet implemented */
|
|
|
|
FullLen = GetLongPathNameW(FullName, FullName, MAX_PATH);
|
|
|
|
if (0 == FullLen || MAX_PATH < FullLen)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Check for a match */
|
|
|
|
|
|
|
|
for (i = 0; i < N_CACHED_PROFILES; i++)
|
|
|
|
{
|
|
|
|
if (NULL != MRUProfile[i]->FullName && 0 == wcscmp(FullName, MRUProfile[i]->FullName))
|
|
|
|
{
|
|
|
|
if (0 != i)
|
|
|
|
{
|
|
|
|
PROFILE_FlushFile();
|
|
|
|
TempProfile = MRUProfile[i];
|
|
|
|
for(j = i; j > 0; j--)
|
|
|
|
{
|
|
|
|
MRUProfile[j] = MRUProfile[j - 1];
|
|
|
|
}
|
|
|
|
CurProfile = TempProfile;
|
|
|
|
}
|
|
|
|
File = CreateFileW(FullName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
NULL, OPEN_EXISTING, 0, NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE == File)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (GetFileTime(File, NULL, NULL, &LastWriteTime) &&
|
|
|
|
LastWriteTime.dwLowDateTime == CurProfile->LastWriteTime.dwLowDateTime &&
|
|
|
|
LastWriteTime.dwHighDateTime == CurProfile->LastWriteTime.dwHighDateTime)
|
|
|
|
{
|
|
|
|
DPRINT("(%S): already opened (mru = %d)\n", FileName, i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT("(%S): already opened, needs refreshing (mru = %d)\n", FileName, i);
|
|
|
|
}
|
|
|
|
CloseHandle(File);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Flush the old current profile */
|
|
|
|
PROFILE_FlushFile();
|
|
|
|
|
|
|
|
/* Make the oldest profile the current one only in order to get rid of it */
|
|
|
|
if (N_CACHED_PROFILES == i)
|
|
|
|
{
|
|
|
|
TempProfile = MRUProfile[N_CACHED_PROFILES - 1];
|
|
|
|
for(i = N_CACHED_PROFILES - 1; i > 0; i--)
|
|
|
|
{
|
|
|
|
MRUProfile[i] = MRUProfile[i - 1];
|
|
|
|
}
|
|
|
|
CurProfile = TempProfile;
|
|
|
|
}
|
|
|
|
if (NULL != CurProfile->FullName)
|
|
|
|
{
|
|
|
|
PROFILE_ReleaseFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* OK, now that CurProfile is definitely free we assign it our new file */
|
|
|
|
CurProfile->FullName = HeapAlloc(GetProcessHeap(), 0, (wcslen(FullName) + 1) * sizeof(WCHAR));
|
|
|
|
if (NULL != CurProfile->FullName)
|
|
|
|
{
|
|
|
|
wcscpy(CurProfile->FullName, FullName);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to open the profile file */
|
|
|
|
File = CreateFileW(FullName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE != File)
|
|
|
|
{
|
|
|
|
CurProfile->Section = PROFILE_Load(File);
|
|
|
|
if (GetFileTime(File, NULL, NULL, &LastWriteTime))
|
|
|
|
{
|
|
|
|
CurProfile->LastWriteTime.dwLowDateTime = LastWriteTime.dwLowDateTime;
|
|
|
|
CurProfile->LastWriteTime.dwHighDateTime = LastWriteTime.dwHighDateTime;
|
|
|
|
}
|
|
|
|
CloseHandle(File);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Does not exist yet, we will create it in PROFILE_FlushFile */
|
|
|
|
DPRINT("profile file %S not found\n", FileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_GetSection
|
|
|
|
*
|
|
|
|
* Returns all keys of a section.
|
|
|
|
* If ReturnValues is TRUE, also include the corresponding values.
|
|
|
|
*/
|
|
|
|
static INT FASTCALL
|
|
|
|
PROFILE_GetSection(PROFILESECTION *Section, LPCWSTR SectionName,
|
|
|
|
LPWSTR Buffer, UINT Len, BOOL ReturnValues )
|
|
|
|
{
|
|
|
|
PROFILEKEY *Key;
|
|
|
|
|
|
|
|
if (NULL == Buffer)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("%S,%p,%u\n", SectionName, Buffer, Len);
|
|
|
|
|
|
|
|
while (NULL != Section)
|
|
|
|
{
|
|
|
|
if (L'\0' != Section->Name[0] && 0 == _wcsicmp(Section->Name, SectionName))
|
|
|
|
{
|
|
|
|
UINT OldLen = Len;
|
|
|
|
for (Key = Section->Key; NULL != Key; Key = Key->Next)
|
|
|
|
{
|
|
|
|
if (Len <= 2)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (L'\0' == *Key->Name)
|
|
|
|
{
|
|
|
|
continue; /* Skip empty lines */
|
|
|
|
}
|
|
|
|
if (IS_ENTRY_COMMENT(Key->Name))
|
|
|
|
{
|
|
|
|
continue; /* Skip comments */
|
|
|
|
}
|
|
|
|
PROFILE_CopyEntry(Buffer, Key->Name, Len - 1, FALSE);
|
|
|
|
Len -= wcslen(Buffer) + 1;
|
|
|
|
Buffer += wcslen(Buffer) + 1;
|
|
|
|
if (Len < 2)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ReturnValues && NULL != Key->Value)
|
|
|
|
{
|
|
|
|
Buffer[-1] = L'=';
|
|
|
|
PROFILE_CopyEntry(Buffer, Key->Value, Len - 1, 0);
|
|
|
|
Len -= wcslen(Buffer) + 1;
|
|
|
|
Buffer += wcslen(Buffer) + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*Buffer = L'\0';
|
|
|
|
if (Len <= 1)
|
|
|
|
/*If either lpszSection or lpszKey is NULL and the supplied
|
|
|
|
destination buffer is too small to hold all the strings,
|
|
|
|
the last string is truncated and followed by two null characters.
|
|
|
|
In this case, the return value is equal to cchReturnBuffer
|
|
|
|
minus two. */
|
|
|
|
{
|
|
|
|
Buffer[-1] = L'\0';
|
|
|
|
return OldLen - 2;
|
|
|
|
}
|
|
|
|
return OldLen - Len;
|
|
|
|
}
|
|
|
|
Section = Section->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
Buffer[0] = Buffer[1] = L'\0';
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See GetPrivateProfileSectionNamesW for documentation */
|
|
|
|
STATIC INT FASTCALL
|
|
|
|
PROFILE_GetSectionNames(LPWSTR Buffer, UINT Len)
|
|
|
|
{
|
|
|
|
LPWSTR Buf;
|
|
|
|
UINT f,l;
|
|
|
|
PROFILESECTION *Section;
|
|
|
|
|
|
|
|
if (NULL == Buffer || 0 == Len)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (1 == Len)
|
|
|
|
{
|
|
|
|
*Buffer = L'\0';
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
f = Len - 1;
|
|
|
|
Buf = Buffer;
|
|
|
|
Section = CurProfile->Section;
|
|
|
|
while (NULL != Section)
|
|
|
|
{
|
|
|
|
if (L'\0' != Section->Name[0])
|
|
|
|
{
|
|
|
|
l = wcslen(Section->Name) + 1;
|
|
|
|
if (f < l)
|
|
|
|
{
|
|
|
|
if (0 < f)
|
|
|
|
{
|
|
|
|
wcsncpy(Buf, Section->Name, f - 1);
|
|
|
|
Buf += f - 1;
|
|
|
|
*Buf++ = L'\0';
|
|
|
|
}
|
|
|
|
*Buf = L'\0';
|
|
|
|
return Len-2;
|
|
|
|
}
|
|
|
|
wcscpy(Buf, Section->Name);
|
|
|
|
Buf += l;
|
|
|
|
f -= l;
|
|
|
|
}
|
|
|
|
Section = Section->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
*Buf='\0';
|
|
|
|
return Buf - Buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_GetString
|
|
|
|
*
|
|
|
|
* Get a profile string.
|
|
|
|
*/
|
|
|
|
static INT FASTCALL
|
|
|
|
PROFILE_GetString(LPCWSTR Section, LPCWSTR KeyName,
|
|
|
|
LPCWSTR DefVal, LPWSTR Buffer, UINT Len)
|
|
|
|
{
|
|
|
|
PROFILEKEY *Key = NULL;
|
|
|
|
|
|
|
|
if (NULL == Buffer)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL == DefVal)
|
|
|
|
{
|
|
|
|
DefVal = L"";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != KeyName)
|
|
|
|
{
|
|
|
|
if (L'\0' == KeyName[0])
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
Key = PROFILE_Find(&CurProfile->Section, Section, KeyName, FALSE, FALSE);
|
|
|
|
PROFILE_CopyEntry(Buffer, (NULL != Key && NULL != Key->Value) ? Key->Value : DefVal,
|
|
|
|
Len, TRUE );
|
|
|
|
DPRINT("(%S,%S,%S): returning %S\n", Section, KeyName, DefVal, Buffer);
|
|
|
|
return wcslen(Buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != Section && L'\0' != Section[0])
|
|
|
|
{
|
|
|
|
INT Ret = PROFILE_GetSection(CurProfile->Section, Section, Buffer, Len, FALSE);
|
|
|
|
if (L'\0' == Buffer[0]) /* no luck -> def_val */
|
|
|
|
{
|
|
|
|
PROFILE_CopyEntry(Buffer, DefVal, Len, TRUE);
|
|
|
|
Ret = wcslen(Buffer);
|
|
|
|
}
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
Buffer[0] = '\0';
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-01-31 23:52:42 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_DeleteSection
|
|
|
|
*
|
|
|
|
* Delete a section from a profile tree.
|
|
|
|
*/
|
|
|
|
STATIC BOOL FASTCALL
|
|
|
|
PROFILE_DeleteSection(PROFILESECTION **Section, LPCWSTR Name)
|
|
|
|
{
|
|
|
|
while (NULL != *Section)
|
|
|
|
{
|
|
|
|
if (L'\0' != (*Section)->Name[0] && 0 == _wcsicmp((*Section)->Name, Name))
|
|
|
|
{
|
|
|
|
PROFILESECTION *ToDel = *Section;
|
|
|
|
*Section = ToDel->Next;
|
|
|
|
ToDel->Next = NULL;
|
|
|
|
PROFILE_Free(ToDel);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
Section = &(*Section)->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_DeleteKey
|
|
|
|
*
|
|
|
|
* Delete a key from a profile tree.
|
|
|
|
*/
|
|
|
|
STATIC BOOL FASTCALL
|
|
|
|
PROFILE_DeleteKey(PROFILESECTION **Section,
|
|
|
|
LPCWSTR SectionName, LPCWSTR KeyName)
|
|
|
|
{
|
|
|
|
while (*Section)
|
|
|
|
{
|
|
|
|
if (L'\0' != (*Section)->Name[0] && 0 == _wcsicmp((*Section)->Name, SectionName))
|
|
|
|
{
|
|
|
|
PROFILEKEY **Key = &(*Section)->Key;
|
|
|
|
while (NULL != *Key)
|
|
|
|
{
|
|
|
|
if (0 == _wcsicmp((*Key)->Name, KeyName))
|
|
|
|
{
|
|
|
|
PROFILEKEY *ToDel = *Key;
|
|
|
|
*Key = ToDel->Next;
|
|
|
|
if (NULL != ToDel->Value)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, ToDel->Value);
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, ToDel);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
Key = &(*Key)->Next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Section = &(*Section)->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* PROFILE_SetString
|
|
|
|
*
|
|
|
|
* Set a profile string.
|
|
|
|
*/
|
|
|
|
STATIC BOOL FASTCALL
|
|
|
|
PROFILE_SetString(LPCWSTR SectionName, LPCWSTR KeyName,
|
|
|
|
LPCWSTR Value, BOOL CreateAlways )
|
|
|
|
{
|
|
|
|
PROFILEKEY *Key;
|
|
|
|
|
|
|
|
if (NULL == KeyName) /* Delete a whole section */
|
|
|
|
{
|
|
|
|
DPRINT("(%S)\n", SectionName);
|
|
|
|
CurProfile->Changed |= PROFILE_DeleteSection(&CurProfile->Section,
|
|
|
|
SectionName);
|
|
|
|
return TRUE; /* Even if PROFILE_DeleteSection() has failed,
|
|
|
|
this is not an error on application's level.*/
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL == Value) /* Delete a key */
|
|
|
|
{
|
|
|
|
DPRINT("(%S,%S)\n", SectionName, KeyName);
|
|
|
|
CurProfile->Changed |= PROFILE_DeleteKey(&CurProfile->Section,
|
|
|
|
SectionName, KeyName);
|
|
|
|
return TRUE; /* same error handling as above */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the key value */
|
|
|
|
Key = PROFILE_Find(&CurProfile->Section, SectionName,
|
|
|
|
KeyName, TRUE, CreateAlways);
|
|
|
|
DPRINT("(%S,%S,%S):\n", SectionName, KeyName, Value);
|
|
|
|
if (NULL == Key)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (NULL != Key->Value)
|
|
|
|
{
|
|
|
|
/* strip the leading spaces. We can safely strip \n\r and
|
|
|
|
* friends too, they should not happen here anyway. */
|
|
|
|
while (PROFILE_isspace(*Value))
|
|
|
|
{
|
|
|
|
Value++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 == wcscmp(Key->Value, Value))
|
|
|
|
{
|
|
|
|
DPRINT(" no change needed\n");
|
|
|
|
return TRUE; /* No change needed */
|
|
|
|
}
|
|
|
|
DPRINT(" replacing %S\n", Key->Value);
|
|
|
|
HeapFree(GetProcessHeap(), 0, Key->Value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT(" creating key\n" );
|
|
|
|
}
|
|
|
|
Key->Value = HeapAlloc(GetProcessHeap(), 0, (wcslen(Value) + 1) * sizeof(WCHAR));
|
|
|
|
wcscpy(Key->Value, Value);
|
|
|
|
CurProfile->Changed = TRUE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2004-01-30 21:48:09 +00:00
|
|
|
/*
|
|
|
|
* if AllowSectionNameCopy is TRUE, allow the copying :
|
|
|
|
* - of Section names if 'section' is NULL
|
|
|
|
* - of Keys in a Section if 'entry' is NULL
|
|
|
|
* (see MSDN doc for GetPrivateProfileString)
|
|
|
|
*/
|
|
|
|
STATIC int FASTCALL
|
|
|
|
PROFILE_GetPrivateProfileString(LPCWSTR Section, LPCWSTR Entry,
|
|
|
|
LPCWSTR DefVal, LPWSTR Buffer,
|
|
|
|
UINT Len, LPCWSTR Filename,
|
|
|
|
BOOL AllowSectionNameCopy)
|
|
|
|
{
|
|
|
|
int Ret;
|
|
|
|
LPWSTR pDefVal = NULL;
|
|
|
|
|
|
|
|
if (NULL == Filename)
|
|
|
|
{
|
|
|
|
Filename = L"win.ini";
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("%S,%S,%S,%p,%u,%S\n", Section, Entry, DefVal, Buffer, Len, Filename);
|
|
|
|
|
|
|
|
/* strip any trailing ' ' of DefVal. */
|
|
|
|
if (NULL != DefVal)
|
|
|
|
{
|
|
|
|
LPCWSTR p = &DefVal[wcslen(DefVal)]; /* even "" works ! */
|
|
|
|
|
|
|
|
while (DefVal < p)
|
|
|
|
{
|
|
|
|
p--;
|
|
|
|
if (' ' != (*p))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (' ' == *p) /* ouch, contained trailing ' ' */
|
|
|
|
{
|
|
|
|
int NewLen = (int)(p - DefVal);
|
|
|
|
pDefVal = HeapAlloc(GetProcessHeap(), 0, (NewLen + 1) * sizeof(WCHAR));
|
|
|
|
wcsncpy(pDefVal, DefVal, NewLen);
|
|
|
|
pDefVal[Len] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL == pDefVal)
|
|
|
|
{
|
|
|
|
pDefVal = (LPWSTR) DefVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProfileLock);
|
|
|
|
|
|
|
|
if (PROFILE_Open(Filename))
|
|
|
|
{
|
|
|
|
if ((AllowSectionNameCopy) && (NULL == Section))
|
|
|
|
{
|
|
|
|
Ret = PROFILE_GetSectionNames(Buffer, Len);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* PROFILE_GetString already handles the 'entry == NULL' case */
|
|
|
|
Ret = PROFILE_GetString(Section, Entry, pDefVal, Buffer, Len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lstrcpynW(Buffer, pDefVal, Len);
|
|
|
|
Ret = wcslen(Buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&ProfileLock);
|
|
|
|
|
|
|
|
if (pDefVal != DefVal) /* allocated */
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, pDefVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("returning %S, %d\n", Buffer, Ret);
|
|
|
|
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL FASTCALL
|
|
|
|
PROFILE_Init()
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
RtlInitializeCriticalSection(&ProfileLock);
|
|
|
|
|
|
|
|
for (i = 0; i < N_CACHED_PROFILES; i++)
|
|
|
|
{
|
|
|
|
MRUProfile[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(PROFILE));
|
|
|
|
if (NULL == MRUProfile[i])
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
MRUProfile[i]->Changed = FALSE;
|
|
|
|
MRUProfile[i]->Section = NULL;
|
|
|
|
MRUProfile[i]->FullName = NULL;
|
|
|
|
MRUProfile[i]->LastWriteTime.dwLowDateTime = 0;
|
|
|
|
MRUProfile[i]->LastWriteTime.dwHighDateTime = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2001-05-27 15:40:31 +00:00
|
|
|
BOOL STDCALL
|
2001-06-07 21:27:45 +00:00
|
|
|
CloseProfileUserMapping(VOID)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2001-06-07 21:27:45 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
UINT STDCALL
|
2004-01-30 21:48:09 +00:00
|
|
|
GetPrivateProfileIntW(
|
|
|
|
LPCWSTR AppName,
|
|
|
|
LPCWSTR KeyName,
|
|
|
|
INT Default,
|
|
|
|
LPCWSTR FileName
|
2001-03-31 01:17:30 +00:00
|
|
|
)
|
|
|
|
{
|
2004-01-30 21:48:09 +00:00
|
|
|
WCHAR Buffer[30];
|
|
|
|
UNICODE_STRING BufferW;
|
|
|
|
INT Len;
|
|
|
|
ULONG Result;
|
|
|
|
|
|
|
|
if (0 == (Len = GetPrivateProfileStringW(AppName, KeyName, L"",
|
|
|
|
Buffer, sizeof(Buffer)/sizeof(WCHAR),
|
|
|
|
FileName)))
|
|
|
|
{
|
|
|
|
return (UINT) Default;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 (L'\0' == Buffer[0])
|
|
|
|
{
|
|
|
|
return (UINT) Default;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&BufferW, Buffer);
|
|
|
|
RtlUnicodeStringToInteger(&BufferW, 10, &Result);
|
|
|
|
|
|
|
|
return Result;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
UINT STDCALL
|
2004-01-30 21:48:09 +00:00
|
|
|
GetPrivateProfileIntA(
|
|
|
|
LPCSTR AppName,
|
|
|
|
LPCSTR KeyName,
|
|
|
|
INT Default,
|
|
|
|
LPCSTR FileName
|
2001-03-31 01:17:30 +00:00
|
|
|
)
|
|
|
|
{
|
2004-01-30 21:48:09 +00:00
|
|
|
UNICODE_STRING KeyNameW, FileNameW, AppNameW;
|
|
|
|
UINT Res;
|
|
|
|
|
|
|
|
if (NULL != KeyName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&KeyNameW, (PCSZ) KeyName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KeyNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != FileName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&FileNameW, (PCSZ) FileName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FileNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != AppName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&AppNameW, (PCSZ) AppName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AppNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Res = GetPrivateProfileIntW(AppNameW.Buffer, KeyNameW.Buffer, Default,
|
|
|
|
FileNameW.Buffer);
|
|
|
|
|
|
|
|
RtlFreeUnicodeString(&AppNameW);
|
|
|
|
RtlFreeUnicodeString(&FileNameW);
|
|
|
|
RtlFreeUnicodeString(&KeyNameW);
|
|
|
|
|
|
|
|
return Res;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
2001-03-31 01:17:30 +00:00
|
|
|
GetPrivateProfileSectionW (
|
|
|
|
LPCWSTR lpAppName,
|
|
|
|
LPWSTR lpReturnedString,
|
|
|
|
DWORD nSize,
|
|
|
|
LPCWSTR lpFileName
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
2001-03-31 01:17:30 +00:00
|
|
|
GetPrivateProfileSectionA (
|
|
|
|
LPCSTR lpAppName,
|
|
|
|
LPSTR lpReturnedString,
|
|
|
|
DWORD nSize,
|
|
|
|
LPCSTR lpFileName
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-30 21:48:09 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* GetPrivateProfileSectionNamesW (KERNEL32.@)
|
|
|
|
*
|
|
|
|
* Returns the section names contained in the specified file.
|
|
|
|
* The section names are returned as a list of strings with an extra
|
|
|
|
* '\0' to mark the end of the list.
|
|
|
|
*
|
|
|
|
* - if the buffer is 0, 1 or 2 characters long then it is filled with
|
|
|
|
* '\0' and the return value is 0
|
|
|
|
* - otherwise if the buffer is too small then the first section name that
|
|
|
|
* does not fit is truncated so that the string list can be terminated
|
|
|
|
* correctly (double '\0')
|
|
|
|
* - the return value is the number of characters written in the buffer
|
|
|
|
* except for the trailing '\0'. If the buffer is too small, then the
|
|
|
|
* return value is len-2
|
|
|
|
* - Win2000 has a bug that triggers when the section names and the
|
|
|
|
* trailing '\0' fit exactly in the buffer. In that case the trailing
|
|
|
|
* '\0' is missing.
|
|
|
|
*
|
|
|
|
* Note that when the buffer is big enough then the return value may be any
|
|
|
|
* value between 1 and len-1 , including len-2.
|
|
|
|
*
|
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
2004-01-30 21:48:09 +00:00
|
|
|
GetPrivateProfileSectionNamesW(
|
|
|
|
LPWSTR Buffer,
|
|
|
|
DWORD Size,
|
|
|
|
LPCWSTR FileName
|
2001-03-31 01:17:30 +00:00
|
|
|
)
|
|
|
|
{
|
2004-01-30 21:48:09 +00:00
|
|
|
DWORD Ret = 0;
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProfileLock);
|
|
|
|
|
|
|
|
if (PROFILE_Open(FileName))
|
|
|
|
{
|
|
|
|
Ret = PROFILE_GetSectionNames(Buffer, Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&ProfileLock);
|
|
|
|
|
|
|
|
return Ret;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
2004-01-30 21:48:09 +00:00
|
|
|
GetPrivateProfileSectionNamesA(
|
|
|
|
LPSTR Buffer,
|
|
|
|
DWORD Size,
|
|
|
|
LPCSTR FileName
|
2001-03-31 01:17:30 +00:00
|
|
|
)
|
|
|
|
{
|
2004-01-30 21:48:09 +00:00
|
|
|
UNICODE_STRING FileNameW;
|
|
|
|
LPWSTR BufferW;
|
|
|
|
INT RetW, Ret = 0;
|
|
|
|
|
|
|
|
BufferW = Buffer ? HeapAlloc(GetProcessHeap(), 0, Size * sizeof(WCHAR)) : NULL;
|
|
|
|
if (NULL != FileName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&FileNameW, (PCSZ) FileName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FileNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
RetW = GetPrivateProfileSectionNamesW(BufferW, Size, FileNameW.Buffer);
|
|
|
|
if (0 != RetW && 0 != Size)
|
|
|
|
{
|
|
|
|
Ret = WideCharToMultiByte(CP_ACP, 0, BufferW, RetW, Buffer, Size, NULL, NULL);
|
|
|
|
if (0 == Ret)
|
|
|
|
{
|
|
|
|
Ret = Size;
|
|
|
|
Buffer[Size - 1] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlFreeUnicodeString(&FileNameW);
|
|
|
|
if (NULL != BufferW)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, BufferW);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ret;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
2004-01-30 21:48:09 +00:00
|
|
|
GetPrivateProfileStringW(
|
|
|
|
LPCWSTR AppName,
|
|
|
|
LPCWSTR KeyName,
|
|
|
|
LPCWSTR Default,
|
|
|
|
LPWSTR ReturnedString,
|
|
|
|
DWORD Size,
|
|
|
|
LPCWSTR FileName
|
2001-03-31 01:17:30 +00:00
|
|
|
)
|
|
|
|
{
|
2004-01-30 21:48:09 +00:00
|
|
|
return PROFILE_GetPrivateProfileString(AppName, KeyName, Default,
|
|
|
|
ReturnedString, Size, FileName, TRUE);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
2004-01-30 21:48:09 +00:00
|
|
|
GetPrivateProfileStringA(
|
|
|
|
LPCSTR AppName,
|
|
|
|
LPCSTR KeyName,
|
|
|
|
LPCSTR Default,
|
|
|
|
LPSTR ReturnedString,
|
|
|
|
DWORD Size,
|
|
|
|
LPCSTR FileName
|
2001-03-31 01:17:30 +00:00
|
|
|
)
|
|
|
|
{
|
2004-01-30 21:48:09 +00:00
|
|
|
UNICODE_STRING AppNameW, KeyNameW, DefaultW, FileNameW;
|
|
|
|
LPWSTR ReturnedStringW;
|
|
|
|
INT RetW, Ret = 0;
|
|
|
|
|
|
|
|
ReturnedStringW = (NULL != ReturnedString
|
|
|
|
? HeapAlloc(GetProcessHeap(), 0, Size * sizeof(WCHAR)) : NULL);
|
|
|
|
if (NULL != AppName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&AppNameW, (PCSZ) AppName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AppNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != KeyName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&KeyNameW, (PCSZ) KeyName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KeyNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != Default)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&DefaultW, (PCSZ) Default);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DefaultW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != FileName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&FileNameW, (PCSZ) FileName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FileNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
RetW = GetPrivateProfileStringW(AppNameW.Buffer, KeyNameW.Buffer,
|
|
|
|
DefaultW.Buffer, ReturnedStringW, Size,
|
|
|
|
FileNameW.Buffer);
|
|
|
|
if (0 != Size)
|
|
|
|
{
|
|
|
|
Ret = WideCharToMultiByte(CP_ACP, 0, ReturnedStringW, RetW + 1, ReturnedString, Size, NULL, NULL);
|
|
|
|
if (0 == Ret)
|
|
|
|
{
|
|
|
|
Ret = Size - 1;
|
|
|
|
ReturnedString[Ret] = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Ret--; /* strip terminating 0 */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlFreeUnicodeString(&AppNameW);
|
|
|
|
RtlFreeUnicodeString(&KeyNameW);
|
|
|
|
RtlFreeUnicodeString(&DefaultW);
|
|
|
|
RtlFreeUnicodeString(&FileNameW);
|
|
|
|
if (NULL != ReturnedStringW)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, ReturnedStringW);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ret;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
2002-09-08 10:23:54 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-06-13 20:04:56 +00:00
|
|
|
BOOL STDCALL
|
2001-03-31 01:17:30 +00:00
|
|
|
GetPrivateProfileStructW (
|
2004-06-13 20:04:56 +00:00
|
|
|
IN LPCWSTR Section,
|
|
|
|
IN LPCWSTR Key,
|
|
|
|
OUT LPVOID Struct,
|
|
|
|
IN UINT StructSize,
|
|
|
|
IN LPCWSTR File
|
2001-03-31 01:17:30 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-06-13 20:04:56 +00:00
|
|
|
BOOL STDCALL
|
2001-03-31 01:17:30 +00:00
|
|
|
GetPrivateProfileStructA (
|
2004-06-13 20:04:56 +00:00
|
|
|
IN LPCSTR Section,
|
|
|
|
IN LPCSTR Key,
|
|
|
|
OUT LPVOID Struct,
|
|
|
|
IN UINT StructSize,
|
|
|
|
IN LPCSTR File
|
2001-03-31 01:17:30 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
|
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
UINT STDCALL
|
|
|
|
GetProfileIntW(LPCWSTR lpAppName,
|
|
|
|
LPCWSTR lpKeyName,
|
|
|
|
INT nDefault)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2004-01-30 21:48:09 +00:00
|
|
|
return GetPrivateProfileIntW(lpAppName,
|
|
|
|
lpKeyName,
|
|
|
|
nDefault,
|
|
|
|
L"win.ini");
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
UINT STDCALL
|
|
|
|
GetProfileIntA(LPCSTR lpAppName,
|
|
|
|
LPCSTR lpKeyName,
|
|
|
|
INT nDefault)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2004-01-30 21:48:09 +00:00
|
|
|
return GetPrivateProfileIntA(lpAppName,
|
|
|
|
lpKeyName,
|
|
|
|
nDefault,
|
|
|
|
"win.ini");
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
GetProfileSectionW(LPCWSTR lpAppName,
|
|
|
|
LPWSTR lpReturnedString,
|
|
|
|
DWORD nSize)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2001-06-07 21:27:45 +00:00
|
|
|
return GetPrivateProfileSectionW(lpAppName,
|
|
|
|
lpReturnedString,
|
|
|
|
nSize,
|
|
|
|
NULL);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
GetProfileSectionA(LPCSTR lpAppName,
|
|
|
|
LPSTR lpReturnedString,
|
|
|
|
DWORD nSize)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2001-06-07 21:27:45 +00:00
|
|
|
return GetPrivateProfileSectionA(lpAppName,
|
|
|
|
lpReturnedString,
|
|
|
|
nSize,
|
|
|
|
NULL);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
GetProfileStringW(LPCWSTR lpAppName,
|
|
|
|
LPCWSTR lpKeyName,
|
|
|
|
LPCWSTR lpDefault,
|
|
|
|
LPWSTR lpReturnedString,
|
|
|
|
DWORD nSize)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2001-06-07 21:27:45 +00:00
|
|
|
return GetPrivateProfileStringW(lpAppName,
|
|
|
|
lpKeyName,
|
|
|
|
lpDefault,
|
|
|
|
lpReturnedString,
|
|
|
|
nSize,
|
|
|
|
NULL);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-30 21:48:09 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
GetProfileStringA(LPCSTR lpAppName,
|
|
|
|
LPCSTR lpKeyName,
|
|
|
|
LPCSTR lpDefault,
|
|
|
|
LPSTR lpReturnedString,
|
|
|
|
DWORD nSize)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2001-06-07 21:27:45 +00:00
|
|
|
return GetPrivateProfileStringA(lpAppName,
|
|
|
|
lpKeyName,
|
|
|
|
lpDefault,
|
|
|
|
lpReturnedString,
|
|
|
|
nSize,
|
|
|
|
NULL);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
2001-06-07 21:27:45 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2001-06-07 21:27:45 +00:00
|
|
|
BOOL STDCALL
|
2001-03-31 01:17:30 +00:00
|
|
|
OpenProfileUserMapping (VOID)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-06-07 21:27:45 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2001-03-31 01:17:30 +00:00
|
|
|
QueryWin31IniFilesMappedToRegistry (
|
|
|
|
DWORD Unknown0,
|
|
|
|
DWORD Unknown1,
|
|
|
|
DWORD Unknown2,
|
|
|
|
DWORD Unknown3
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2001-06-07 21:27:45 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2001-03-31 01:17:30 +00:00
|
|
|
WritePrivateProfileSectionA (
|
|
|
|
LPCSTR lpAppName,
|
|
|
|
LPCSTR lpString,
|
|
|
|
LPCSTR lpFileName
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2001-03-31 01:17:30 +00:00
|
|
|
WritePrivateProfileSectionW (
|
|
|
|
LPCWSTR lpAppName,
|
|
|
|
LPCWSTR lpString,
|
|
|
|
LPCWSTR lpFileName
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-31 23:52:42 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2004-01-31 23:52:42 +00:00
|
|
|
WritePrivateProfileStringA(LPCSTR AppName,
|
|
|
|
LPCSTR KeyName,
|
|
|
|
LPCSTR String,
|
|
|
|
LPCSTR FileName)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2004-01-31 23:52:42 +00:00
|
|
|
UNICODE_STRING AppNameW, KeyNameW, StringW, FileNameW;
|
|
|
|
BOOL Ret;
|
|
|
|
|
|
|
|
if (NULL != AppName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&AppNameW, (PCSZ) AppName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AppNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != KeyName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&KeyNameW, (PCSZ) KeyName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KeyNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != String)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&StringW, (PCSZ) String);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StringW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != FileName)
|
|
|
|
{
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&FileNameW, (PCSZ) FileName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FileNameW.Buffer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ret = WritePrivateProfileStringW(AppNameW.Buffer, KeyNameW.Buffer,
|
|
|
|
StringW.Buffer, FileNameW.Buffer);
|
|
|
|
|
|
|
|
RtlFreeUnicodeString(&AppNameW);
|
|
|
|
RtlFreeUnicodeString(&KeyNameW);
|
|
|
|
RtlFreeUnicodeString(&StringW);
|
|
|
|
RtlFreeUnicodeString(&FileNameW);
|
|
|
|
|
|
|
|
return Ret;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-31 23:52:42 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2004-01-31 23:52:42 +00:00
|
|
|
WritePrivateProfileStringW(LPCWSTR AppName,
|
|
|
|
LPCWSTR KeyName,
|
|
|
|
LPCWSTR String,
|
|
|
|
LPCWSTR FileName)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2004-01-31 23:52:42 +00:00
|
|
|
BOOL Ret = FALSE;
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProfileLock);
|
|
|
|
|
|
|
|
if (PROFILE_Open(FileName))
|
|
|
|
{
|
|
|
|
if (NULL == AppName && NULL == KeyName && NULL == String) /* documented "file flush" case */
|
|
|
|
{
|
|
|
|
PROFILE_FlushFile();
|
|
|
|
PROFILE_ReleaseFile(); /* always return FALSE in this case */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (NULL == AppName)
|
|
|
|
{
|
|
|
|
DPRINT1("(NULL?,%s,%s,%s)?\n", KeyName, String, FileName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Ret = PROFILE_SetString(AppName, KeyName, String, FALSE);
|
|
|
|
PROFILE_FlushFile();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&ProfileLock);
|
|
|
|
|
|
|
|
return Ret;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2002-09-08 10:23:54 +00:00
|
|
|
WritePrivateProfileStructA (
|
2004-06-13 20:04:56 +00:00
|
|
|
IN LPCSTR Section,
|
|
|
|
IN LPCSTR Key,
|
|
|
|
IN LPVOID Struct,
|
|
|
|
IN UINT StructSize,
|
|
|
|
IN LPCSTR File
|
2002-09-08 10:23:54 +00:00
|
|
|
)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2002-09-08 10:23:54 +00:00
|
|
|
WritePrivateProfileStructW (
|
2004-06-13 20:04:56 +00:00
|
|
|
IN LPCWSTR Section,
|
|
|
|
IN LPCWSTR Key,
|
|
|
|
IN LPVOID Struct,
|
|
|
|
IN UINT StructSize,
|
|
|
|
IN LPCWSTR File
|
2002-09-08 10:23:54 +00:00
|
|
|
)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2001-06-07 21:27:45 +00:00
|
|
|
WriteProfileSectionA(LPCSTR lpAppName,
|
|
|
|
LPCSTR lpString)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2001-06-07 21:27:45 +00:00
|
|
|
return WritePrivateProfileSectionA(lpAppName,
|
|
|
|
lpString,
|
|
|
|
NULL);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2001-06-07 21:27:45 +00:00
|
|
|
WriteProfileSectionW(LPCWSTR lpAppName,
|
|
|
|
LPCWSTR lpString)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2001-06-07 21:27:45 +00:00
|
|
|
return WritePrivateProfileSectionW(lpAppName,
|
|
|
|
lpString,
|
|
|
|
NULL);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-31 23:52:42 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2004-01-31 23:52:42 +00:00
|
|
|
WriteProfileStringA(LPCSTR AppName,
|
|
|
|
LPCSTR KeyName,
|
|
|
|
LPCSTR String)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2004-01-31 23:52:42 +00:00
|
|
|
return WritePrivateProfileStringA(AppName,
|
|
|
|
KeyName,
|
|
|
|
String,
|
2001-06-07 21:27:45 +00:00
|
|
|
NULL);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-01-31 23:52:42 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL STDCALL
|
2004-01-31 23:52:42 +00:00
|
|
|
WriteProfileStringW(LPCWSTR AppName,
|
|
|
|
LPCWSTR KeyName,
|
|
|
|
LPCWSTR String)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2004-01-31 23:52:42 +00:00
|
|
|
return WritePrivateProfileStringW(AppName,
|
|
|
|
KeyName,
|
|
|
|
String,
|
2001-06-07 21:27:45 +00:00
|
|
|
NULL);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|