/*
* wincfg.cxx
*
* Miscellaneous implementation of classes for Win32
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: wincfg.cxx,v $
* Revision 1.16 2005/11/30 12:47:42 csoutheren
* Removed tabs, reformatted some code, and changed tags for Doxygen
*
* Revision 1.15 2005/09/24 09:11:42 dominance
* use unix-style slashes to not confuse mingw on win32
*
* Revision 1.14 2003/03/19 01:35:42 robertj
* Fixed bug getting large private .ini file data, thanks Michal Zygmuntowicz
*
* Revision 1.13 2003/02/12 01:59:44 robertj
* Changed to allow for very large private .INI files.
*
* Revision 1.12 2001/08/17 20:09:12 yurik
* Fixed RegEnumValue name clash with system function
*
* Revision 1.11 2001/08/14 21:56:39 yurik
* More CE Unicode Registry API bug fixes
*
* Revision 1.10 2001/08/14 15:41:13 yurik
* Fixed bug in EnumKey for CE
*
* Revision 1.9 2001/03/15 23:41:22 robertj
* Fixed bug just introduced so can access regisrtry directly again from PConfig.
*
* Revision 1.8 2001/03/09 05:50:48 robertj
* Added ability to set default PConfig file or path to find it.
*
* Revision 1.7 2001/01/24 06:45:41 yurik
* Windows CE port-related changes
*
* Revision 1.6 2000/09/05 02:28:38 robertj
* Removed PAssert with registry access denied error, changed to PTRACE.
*
* Revision 1.5 2000/08/03 22:47:48 robertj
* Removed assert for empty key name so can set registry default key for a section.
*
* Revision 1.4 2000/05/25 11:08:46 robertj
* Added PConfig::HasKey() function to determine if value actually set.
* Fixed "system" PConfig to use the win.ini file in correct directory.
*
* Revision 1.3 1999/12/30 00:32:48 robertj
* Allowed absolute registry paths in PConfig::Application instances.
*
* Revision 1.2 1998/12/04 10:10:48 robertj
* Added virtual for determining if process is a service. Fixes linkage problem.
*
* Revision 1.1 1998/11/30 05:35:28 robertj
* Initial revision
*
*/
#include <ptlib.h>
#include <winuser.h>
#include <winnls.h>
#include <process.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#define new PNEW
const char LocalMachineStr[] = "HKEY_LOCAL_MACHINE\\";
const char CurrentUserStr[] = "HKEY_CURRENT_USER\\";
///////////////////////////////////////////////////////////////////////////////
// Configuration files
#ifndef _WIN32_WCE
class SecurityID
{
public:
SecurityID(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, // pointer to identifier authority
BYTE nSubAuthorityCount, // count of subauthorities
DWORD dwSubAuthority0, // subauthority 0
DWORD dwSubAuthority1, // subauthority 1
DWORD dwSubAuthority2, // subauthority 2
DWORD dwSubAuthority3, // subauthority 3
DWORD dwSubAuthority4, // subauthority 4
DWORD dwSubAuthority5, // subauthority 5
DWORD dwSubAuthority6, // subauthority 6
DWORD dwSubAuthority7 // subauthority 7
)
{
if (!AllocateAndInitializeSid(pIdentifierAuthority, // pointer to identifier authority
nSubAuthorityCount, // count of subauthorities
dwSubAuthority0, // subauthority 0
dwSubAuthority1, // subauthority 1
dwSubAuthority2, // subauthority 2
dwSubAuthority3, // subauthority 3
dwSubAuthority4, // subauthority 4
dwSubAuthority5, // subauthority 5
dwSubAuthority6, // subauthority 6
dwSubAuthority7, // subauthority 7
&sidptr))
sidptr = NULL;
}
SecurityID(LPCTSTR lpSystemName, // address of string for system name
LPCTSTR lpAccountName, // address of string for account name
LPTSTR ReferencedDomainName, // address of string for referenced domain
LPDWORD cbReferencedDomainName, // address of size of domain string
PSID_NAME_USE peUse // address of SID-type indicator
)
{
DWORD len = 1024;
sidptr = (PSID)LocalAlloc(LPTR, len);
if (sidptr != NULL) {
if (!LookupAccountName(lpSystemName, // address of string for system name
lpAccountName, // address of string for account name
sidptr, // address of security identifier
&len, // address of size of security identifier
ReferencedDomainName, // address of string for referenced domain
cbReferencedDomainName, // address of size of domain string
peUse // address of SID-type indicator
)) {
LocalFree(sidptr);
sidptr = NULL;
}
}
}
~SecurityID()
{
FreeSid(sidptr);
}
operator PSID() const
{
return sidptr;
}
DWORD GetLength() const
{
return GetLengthSid(sidptr);
}
BOOL IsValid() const
{
return sidptr != NULL && IsValidSid(sidptr);
}
private:
PSID sidptr;
};
static DWORD SecureCreateKey(HKEY rootKey, const PString & subkey, HKEY & key)
{
SECURITY_DESCRIPTOR secdesc;
if (!InitializeSecurityDescriptor(&secdesc, SECURITY_DESCRIPTOR_REVISION))
return GetLastError();
static SID_IDENTIFIER_AUTHORITY siaNTAuthority = SECURITY_NT_AUTHORITY;
SecurityID adminID(&siaNTAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0);
if (!adminID.IsValid())
return GetLastError();
static SID_IDENTIFIER_AUTHORITY siaSystemAuthority = SECURITY_NT_AUTHORITY;
SecurityID systemID(&siaSystemAuthority, 1,
SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0);
if (!systemID.IsValid())
return GetLastError();
static SID_IDENTIFIER_AUTHORITY siaCreatorAuthority = SECURITY_CREATOR_SID_AUTHORITY;
SecurityID creatorID(&siaCreatorAuthority, 1,
SECURITY_CREATOR_OWNER_RID,
0, 0, 0, 0, 0, 0, 0);
if (!creatorID.IsValid())
return GetLastError();
SID_NAME_USE snuType;
char szDomain[100];
DWORD cchDomainName = sizeof(szDomain);
SecurityID userID(NULL, PProcess::Current().GetUserName(),
szDomain, &cchDomainName, &snuType);
if (!userID.IsValid())
return GetLastError();
DWORD acl_len = sizeof(ACL) + 4*sizeof(ACCESS_ALLOWED_ACE) +
adminID.GetLength() + creatorID.GetLength() +
systemID.GetLength() + userID.GetLength();
PBYTEArray dacl_buf(acl_len);
PACL dacl = (PACL)dacl_buf.GetPointer(acl_len);
if (!InitializeAcl(dacl, acl_len, ACL_REVISION2))
return GetLastError();
if (!AddAccessAllowedAce(dacl, ACL_REVISION2, KEY_ALL_ACCESS, adminID))
return GetLastError();
if (!AddAccessAllowedAce(dacl, ACL_REVISION2, KEY_ALL_ACCESS, systemID))
return GetLastError();
if (!AddAccessAllowedAce(dacl, ACL_REVISION2, KEY_ALL_ACCESS, creatorID))
return GetLastError();
if (!AddAccessAllowedAce(dacl, ACL_REVISION2, KEY_ALL_ACCESS, userID))
return GetLastError();
if (!SetSecurityDescriptorDacl(&secdesc, TRUE, dacl, FALSE))
return GetLastError();
SECURITY_ATTRIBUTES secattr;
secattr.nLength = sizeof(secattr);
secattr.lpSecurityDescriptor = &secdesc;
secattr.bInheritHandle = FALSE;
DWORD disposition;
return RegCreateKeyEx(rootKey, subkey, 0, "", REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, &secattr, &key, &disposition);
}
#endif // _WIN32_WCE
RegistryKey::RegistryKey(const PString & subkeyname, OpenMode mode)
{
PAssert(!subkeyname.IsEmpty(), PInvalidParameter);
PProcess & proc = PProcess::Current();
DWORD access = mode == ReadOnly ? KEY_READ : KEY_ALL_ACCESS;
DWORD error;
PString subkey;
HKEY basekey;
if (subkeyname.Find(LocalMachineStr) == 0) {
subkey = subkeyname.Mid(19);
basekey = HKEY_LOCAL_MACHINE;
}
else if (subkeyname.Find(CurrentUserStr) == 0) {
subkey = subkeyname.Mid(18);
basekey = HKEY_CURRENT_USER;
}
else {
subkey = subkeyname;
PINDEX lastCharPos = subkey.GetLength()-1;
while (lastCharPos > 0 && subkey[lastCharPos] == '\\')
subkey.Delete(lastCharPos--, 1);
basekey = NULL;
if (!proc.GetVersion(FALSE).IsEmpty()) {
PString keyname = subkey;
keyname.Replace("CurrentVersion", proc.GetVersion(FALSE));
error = RegOpenKeyEx(HKEY_CURRENT_USER, keyname, 0, access, &key);
if (error == ERROR_SUCCESS)
return;
#if PTRACING
if (error == ERROR_ACCESS_DENIED)
PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_CURRENT_USER\\" << keyname);
#endif
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, access, &key);
if (error == ERROR_SUCCESS)
return;
#if PTRACING
if (error == ERROR_ACCESS_DENIED)
PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_LOCAL_MACHINE\\" << keyname);
#endif
}
error = RegOpenKeyEx(HKEY_CURRENT_USER, subkey, 0, access, &key);
if (error == ERROR_SUCCESS)
return;
#if PTRACING
if (error == ERROR_ACCESS_DENIED)
PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_CURRENT_USER\\" << subkey);
#endif
}
error = RegOpenKeyEx(basekey != NULL ? basekey : HKEY_LOCAL_MACHINE,
subkey, 0, access, &key);
if (error == ERROR_SUCCESS)
return;
#if PTRACING
if (error == ERROR_ACCESS_DENIED)
PTRACE(1, "PTLib\tAccess denied accessing registry entry "
<< (basekey != NULL ? "" : LocalMachineStr) << subkey);
#endif
key = NULL;
if (mode != Create)
return;
if (basekey == NULL) {
if (PProcess::Current().IsServiceProcess())
basekey = HKEY_LOCAL_MACHINE;
else
basekey = HKEY_CURRENT_USER;
}
#ifndef _WIN32_WCE
error = SecureCreateKey(basekey, subkey, key);
if (error != ERROR_SUCCESS) {
#endif
DWORD disposition;
error = RegCreateKeyEx(basekey, subkey, 0, "", REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &key, &disposition);
if (error != ERROR_SUCCESS) {
PTRACE(1, "PTLib\tCould not create registry entry "
<< (basekey != NULL ? "" : LocalMachineStr) << subkey);
key = NULL;
}
#ifndef _WIN32_WCE
}
#endif // _WIN32_WCE
}
RegistryKey::~RegistryKey()
{
if (key != NULL)
RegCloseKey(key);
}
BOOL RegistryKey::EnumKey(PINDEX idx, PString & str)
{
if (key == NULL)
return FALSE;
#ifndef _WIN32_WCE
if( RegEnumKey(key, idx, str.GetPointer(MAX_PATH),MAX_PATH) != ERROR_SUCCESS)
#else // CE has only Unicode based API
USES_CONVERSION;
TCHAR tstr[MAX_PATH];
LONG lResult = RegEnumKey(key, idx, tstr, MAX_PATH);
str = T2A(tstr);
if( lResult != ERROR_SUCCESS )
#endif
return FALSE;
str.MakeMinimumSize();
return TRUE;
}
BOOL RegistryKey::EnumValue(PINDEX idx, PString & str)
{
if (key == NULL)
return FALSE;
DWORD sizeofname = MAX_PATH;
#ifndef _WIN32_WCE
if (RegEnumValue(key, idx, str.GetPointer(sizeofname),
&sizeofname, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
#else // CE has only Unicode based API
USES_CONVERSION;
TCHAR tstr[MAX_PATH];
LONG lResult = RegEnumValueCe(key, idx, tstr,
&sizeofname, NULL, NULL, NULL, NULL);
str = T2A(tstr);
if( lResult != ERROR_SUCCESS )
#endif
return FALSE;
str.MakeMinimumSize();
return TRUE;
}
BOOL RegistryKey::DeleteKey(const PString & subkey)
{
if (key == NULL)
return TRUE;
return RegDeleteKey(key, subkey) == ERROR_SUCCESS;
}
BOOL RegistryKey::DeleteValue(const PString & value)
{
if (key == NULL)
return TRUE;
return RegDeleteValue(key, (char *)(const char *)value) == ERROR_SUCCESS;
}
BOOL RegistryKey::QueryValue(const PString & value, PString & str)
{
if (key == NULL)
return FALSE;
DWORD type, size;
if (RegQueryValueEx(key, (char *)(const char *)value,
NULL, &type, NULL, &size) != ERROR_SUCCESS)
return FALSE;
switch (type) {
case REG_SZ :
case REG_MULTI_SZ :
case REG_EXPAND_SZ :
case REG_BINARY :
#ifndef _WIN32_WCE
return RegQueryValueEx(key, (char *)(const char *)value, NULL,
&type, (LPBYTE)str.GetPointer(size), &size) == ERROR_SUCCESS;
#else // CE has only Unicode based API
{ USES_CONVERSION; TCHAR tstr[MAX_PATH];
if( RegQueryValueEx(key, (char *)(const char *)value, NULL,
&type, (LPBYTE) tstr, &size) == ERROR_SUCCESS )
{
str = T2A(tstr);
return TRUE;
}
}
#endif
case REG_DWORD : {
DWORD num;
size = sizeof(num);
if (RegQueryValueEx(key, (char *)(const char *)value, NULL,
&type, (LPBYTE)&num, &size) == ERROR_SUCCESS) {
str = PString(PString::Signed, num);
return TRUE;
}
}
default :
PAssertAlways("Unsupported registry type.");
}
return FALSE;
}
BOOL RegistryKey::QueryValue(const PString & value, DWORD & num, BOOL boolean)
{
if (key == NULL)
return FALSE;
DWORD type, size;
if (RegQueryValueEx(key, (char *)(const char *)value,
NULL, &type, NULL, &size) != ERROR_SUCCESS)
return FALSE;
switch (type) {
case REG_BINARY :
if (size > sizeof(DWORD))
return FALSE;
num = 0;
// Do REG_DWORD case
case REG_DWORD :
return RegQueryValueEx(key, (char *)(const char *)value, NULL,
&type, (LPBYTE)&num, &size) == ERROR_SUCCESS;
case REG_SZ : {
PString str;
if (RegQueryValueEx(key, (char *)(const char *)value, NULL,
&type, (LPBYTE)str.GetPointer(size), &size) == ERROR_SUCCESS) {
num = str.AsInteger();
if (num == 0 && boolean) {
int c = toupper(str[0]);
num = c == 'T' || c == 'Y';
}
return TRUE;
}
break;
}
default :
PAssertAlways("Unsupported registry type.");
}
return FALSE;
}
BOOL RegistryKey::SetValue(const PString & value, const PString & str)
{
if (key == NULL)
return FALSE;
#ifndef _WIN32_WCE
return RegSetValueEx(key, (char *)(const char *)value, 0, REG_SZ,
(LPBYTE)(const char *)str, str.GetLength()+1) == ERROR_SUCCESS;
#else // CE has only Unicode based API
USES_CONVERSION;
return RegSetValueEx(key, (char *)(const char *)value, 0, REG_SZ,
(LPBYTE) A2T((const char *)str),
( (str.GetLength()+1) * sizeof(TCHAR)/sizeof(char) )
) == ERROR_SUCCESS;
#endif
}
BOOL RegistryKey::SetValue(const PString & value, DWORD num)
{
if (key == NULL)
return FALSE;
return RegSetValueEx(key, (char *)(const char *)value,
0, REG_DWORD, (LPBYTE)&num, sizeof(num)) == ERROR_SUCCESS;
}
static BOOL IsRegistryPath(const PString & path)
{
return (path.Find(LocalMachineStr) == 0 && path != LocalMachineStr) ||
(path.Find(CurrentUserStr) == 0 && path != CurrentUserStr);
}
///////////////////////////////////////////////////////////////////////////////
PString PProcess::GetConfigurationFile()
{
// No paths set, use defaults
if (configurationPaths.IsEmpty()) {
configurationPaths.AppendString(executableFile.GetVolume() + executableFile.GetPath());
configurationPaths.AppendString(CurrentUserStr);
}
// See if explicit filename
if (configurationPaths.GetSize() == 1 && !PDirectory::Exists(configurationPaths[0]))
return configurationPaths[0];
PString iniFilename = executableFile.GetTitle() + ".INI";
for (PINDEX i = 0; i < configurationPaths.GetSize(); i++) {
PString path = configurationPaths[i];
if (IsRegistryPath(path))
return path;
PFilePath cfgFile = PDirectory(path) + iniFilename;
if (PFile::Exists(cfgFile))
return cfgFile;
}
return PString();
}
///////////////////////////////////////////////////////////////////////////////
void PConfig::Construct(Source src, const PString & appname, const PString & manuf)
{
source = Application;
switch (src) {
case System :
if (IsRegistryPath(appname))
location = appname;
else {
PString dir;
GetWindowsDirectory(dir.GetPointer(_MAX_PATH), _MAX_PATH);
Construct(PDirectory(dir)+"WIN.INI");
}
break;
case Application :
if (IsRegistryPath(defaultSection))
location = PString();
else {
PProcess & proc = PProcess::Current();
PString cfgPath = proc.GetConfigurationFile();
if (IsRegistryPath(cfgPath))
location = cfgPath;
else if (!cfgPath) {
source = NumSources; // Make a file based config
location = cfgPath;
}
else {
location = "SOFTWARE\\";
if (!manuf)
location += manuf;
else if (!proc.GetManufacturer())
location += proc.GetManufacturer();
else
location += "PWLib";
location += PDIR_SEPARATOR;
if (appname.IsEmpty())
location += proc.GetName();
else
location += appname;
location += "\\CurrentVersion\\";
}
}
break;
default :
source = src;
}
}
void PConfig::Construct(const PFilePath & filename)
{
location = filename;
source = NumSources;
}
static void RecurseRegistryKeys(const PString & location,
PINDEX baseLength,
PStringList §ions)
{
RegistryKey registry(location, RegistryKey::ReadOnly);
PString name;
for (PINDEX idx = 0; registry.EnumKey(idx, name); idx++) {
RecurseRegistryKeys(location + name + '\\', baseLength, sections);
sections.AppendString(location.Mid(baseLength) + name);
}
}
static PString PGetPrivateProfileString(const char * lpAppName,
const char * lpKeyName,
const char * lpDefault,
const char * lpFileName)
{
PString buffer;
DWORD numNulls = lpAppName != NULL && lpKeyName != NULL ? 1 : 2;
DWORD size = 100;
while (size <= 100000 &&
::GetPrivateProfileString(lpAppName, lpKeyName, lpDefault,
buffer.GetPointer(size+numNulls), size+numNulls,
lpFileName) == size)
size *= 10;
return buffer;
}
PStringList PConfig::GetSections() const
{
PStringList sections;
switch (source) {
case Application :
RecurseRegistryKeys(location, location.GetLength(), sections);
break;
case NumSources :
PString buffer = PGetPrivateProfileString(NULL, NULL, "", location);
char * ptr = buffer.GetPointer();
while (*ptr != '\0') {
sections.AppendString(ptr);
ptr += strlen(ptr)+1;
}
break;
}
return sections;
}
PStringList PConfig::GetKeys(const PString & section) const
{
PStringList keys;
switch (source) {
case Environment : {
char ** ptr = _environ;
while (*ptr != NULL) {
PString buf = *ptr++;
keys.AppendString(buf.Left(buf.Find('=')));
}
break;
}
case Application : {
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::ReadOnly);
PString name;
for (PINDEX idx = 0; registry.EnumValue(idx, name); idx++)
keys.AppendString(name);
break;
}
case NumSources :
PAssert(!section.IsEmpty(), PInvalidParameter);
PString buffer = PGetPrivateProfileString(section, NULL, "", location);
char * ptr = buffer.GetPointer();
while (*ptr != '\0') {
keys.AppendString(ptr);
ptr += strlen(ptr)+1;
}
}
return keys;
}
void PConfig::DeleteSection(const PString & section)
{
switch (source) {
case Application : {
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location, RegistryKey::ReadWrite);
registry.DeleteKey(section);
break;
}
case NumSources :
PAssert(!section.IsEmpty(), PInvalidParameter);
PAssertOS(WritePrivateProfileString(section, NULL, NULL, location));
}
}
void PConfig::DeleteKey(const PString & section, const PString & key)
{
switch (source) {
case Environment :
PAssert(!key.IsEmpty() && key.Find('=') == P_MAX_INDEX, PInvalidParameter);
putenv(key + "=");
break;
case Application : {
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::ReadWrite);
registry.DeleteValue(key);
break;
}
case NumSources :
PAssert(!key.IsEmpty(), PInvalidParameter);
PAssert(!section.IsEmpty(), PInvalidParameter);
PAssertOS(WritePrivateProfileString(section, key, NULL, location));
}
}
BOOL PConfig::HasKey(const PString & section, const PString & key) const
{
switch (source) {
case Environment :
PAssert(!key.IsEmpty(), PInvalidParameter);
return getenv(key) != NULL;
case Application : {
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::ReadOnly);
PString dummy;
return registry.QueryValue(key, dummy);
}
case NumSources :
PAssert(!key.IsEmpty() && !section.IsEmpty(), PInvalidParameter);
static const char dflt[] = "<<<<<====---PConfig::DefaultValueString---====>>>>>";
return PGetPrivateProfileString(section, key, dflt, location) != dflt;
}
return FALSE;
}
PString PConfig::GetString(const PString & section,
const PString & key, const PString & dflt) const
{
PString str;
switch (source) {
case Environment : {
PAssert(!key.IsEmpty() && key.Find('=') == P_MAX_INDEX, PInvalidParameter);
char * env = getenv(key);
if (env != NULL)
str = env;
else
str = dflt;
break;
}
case Application : {
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::ReadOnly);
if (!registry.QueryValue(key, str))
str = dflt;
break;
}
case NumSources :
PAssert(!key.IsEmpty() && !section.IsEmpty(), PInvalidParameter);
str = PGetPrivateProfileString(section, key, dflt, location);
str.MakeMinimumSize();
}
return str;
}
void PConfig::SetString(const PString & section,
const PString & key, const PString & value)
{
switch (source) {
case Environment :
PAssert(!key.IsEmpty() && key.Find('=') == P_MAX_INDEX, PInvalidParameter);
putenv(key + "=" + value);
break;
case Application : {
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::Create);
registry.SetValue(key, value);
break;
}
case NumSources :
PAssert(!key.IsEmpty() && !section.IsEmpty(), PInvalidParameter);
PAssertOS(WritePrivateProfileString(section, key, value, location));
}
}
BOOL PConfig::GetBoolean(const PString & section,
const PString & key, BOOL dflt) const
{
if (source != Application) {
PString str = GetString(section, key, dflt ? "T" : "F").ToUpper();
int c = toupper(str[0]);
return c == 'T' || c == 'Y' || str.AsInteger() != 0;
}
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::ReadOnly);
DWORD value;
if (!registry.QueryValue(key, value, TRUE))
return dflt;
return value != 0;
}
void PConfig::SetBoolean(const PString & section, const PString & key, BOOL value)
{
if (source != Application)
SetString(section, key, value ? "True" : "False");
else {
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::Create);
registry.SetValue(key, value ? 1 : 0);
}
}
long PConfig::GetInteger(const PString & section,
const PString & key, long dflt) const
{
if (source != Application) {
PString str(PString::Signed, dflt);
return GetString(section, key, str).AsInteger();
}
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::ReadOnly);
DWORD value;
if (!registry.QueryValue(key, value, FALSE))
return dflt;
return value;
}
void PConfig::SetInteger(const PString & section, const PString & key, long value)
{
if (source != Application) {
PString str(PString::Signed, value);
SetString(section, key, str);
}
else {
PAssert(!section.IsEmpty(), PInvalidParameter);
RegistryKey registry(location + section, RegistryKey::Create);
registry.SetValue(key, value);
}
}
// End Of File ///////////////////////////////////////////////////////////////
syntax highlighted by Code2HTML, v. 0.9.1