4 * Miscellaneous implementation of classes for Win32
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.18 2006/06/21 04:20:07 csoutheren
33 * Revision 1.17 2006/04/09 11:04:00 csoutheren
34 * Remove warnings on VS.net 2005
36 * Revision 1.16 2005/11/30 12:47:42 csoutheren
37 * Removed tabs, reformatted some code, and changed tags for Doxygen
39 * Revision 1.15 2005/09/24 09:11:42 dominance
40 * use unix-style slashes to not confuse mingw on win32
42 * Revision 1.14 2003/03/19 01:35:42 robertj
43 * Fixed bug getting large private .ini file data, thanks Michal Zygmuntowicz
45 * Revision 1.13 2003/02/12 01:59:44 robertj
46 * Changed to allow for very large private .INI files.
48 * Revision 1.12 2001/08/17 20:09:12 yurik
49 * Fixed RegEnumValue name clash with system function
51 * Revision 1.11 2001/08/14 21:56:39 yurik
52 * More CE Unicode Registry API bug fixes
54 * Revision 1.10 2001/08/14 15:41:13 yurik
55 * Fixed bug in EnumKey for CE
57 * Revision 1.9 2001/03/15 23:41:22 robertj
58 * Fixed bug just introduced so can access regisrtry directly again from PConfig.
60 * Revision 1.8 2001/03/09 05:50:48 robertj
61 * Added ability to set default PConfig file or path to find it.
63 * Revision 1.7 2001/01/24 06:45:41 yurik
64 * Windows CE port-related changes
66 * Revision 1.6 2000/09/05 02:28:38 robertj
67 * Removed PAssert with registry access denied error, changed to PTRACE.
69 * Revision 1.5 2000/08/03 22:47:48 robertj
70 * Removed assert for empty key name so can set registry default key for a section.
72 * Revision 1.4 2000/05/25 11:08:46 robertj
73 * Added PConfig::HasKey() function to determine if value actually set.
74 * Fixed "system" PConfig to use the win.ini file in correct directory.
76 * Revision 1.3 1999/12/30 00:32:48 robertj
77 * Allowed absolute registry paths in PConfig::Application instances.
79 * Revision 1.2 1998/12/04 10:10:48 robertj
80 * Added virtual for determining if process is a service. Fixes linkage problem.
82 * Revision 1.1 1998/11/30 05:35:28 robertj
88 #include <ptlib/pprocess.h>
101 const char LocalMachineStr
[] = "HKEY_LOCAL_MACHINE\\";
102 const char CurrentUserStr
[] = "HKEY_CURRENT_USER\\";
104 ///////////////////////////////////////////////////////////////////////////////
105 // Configuration files
111 SecurityID(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority
, // pointer to identifier authority
112 BYTE nSubAuthorityCount
, // count of subauthorities
113 DWORD dwSubAuthority0
, // subauthority 0
114 DWORD dwSubAuthority1
, // subauthority 1
115 DWORD dwSubAuthority2
, // subauthority 2
116 DWORD dwSubAuthority3
, // subauthority 3
117 DWORD dwSubAuthority4
, // subauthority 4
118 DWORD dwSubAuthority5
, // subauthority 5
119 DWORD dwSubAuthority6
, // subauthority 6
120 DWORD dwSubAuthority7
// subauthority 7
123 if (!AllocateAndInitializeSid(pIdentifierAuthority
, // pointer to identifier authority
124 nSubAuthorityCount
, // count of subauthorities
125 dwSubAuthority0
, // subauthority 0
126 dwSubAuthority1
, // subauthority 1
127 dwSubAuthority2
, // subauthority 2
128 dwSubAuthority3
, // subauthority 3
129 dwSubAuthority4
, // subauthority 4
130 dwSubAuthority5
, // subauthority 5
131 dwSubAuthority6
, // subauthority 6
132 dwSubAuthority7
, // subauthority 7
137 SecurityID(LPCTSTR lpSystemName
, // address of string for system name
138 LPCTSTR lpAccountName
, // address of string for account name
139 LPTSTR ReferencedDomainName
, // address of string for referenced domain
140 LPDWORD cbReferencedDomainName
, // address of size of domain string
141 PSID_NAME_USE peUse
// address of SID-type indicator
145 sidptr
= (PSID
)LocalAlloc(LPTR
, len
);
146 if (sidptr
!= NULL
) {
147 if (!LookupAccountName(lpSystemName
, // address of string for system name
148 lpAccountName
, // address of string for account name
149 sidptr
, // address of security identifier
150 &len
, // address of size of security identifier
151 ReferencedDomainName
, // address of string for referenced domain
152 cbReferencedDomainName
, // address of size of domain string
153 peUse
// address of SID-type indicator
165 operator PSID() const
170 DWORD
GetLength() const
172 return GetLengthSid(sidptr
);
177 return sidptr
!= NULL
&& IsValidSid(sidptr
);
185 static DWORD
SecureCreateKey(HKEY rootKey
, const PString
& subkey
, HKEY
& key
)
187 SECURITY_DESCRIPTOR secdesc
;
188 if (!InitializeSecurityDescriptor(&secdesc
, SECURITY_DESCRIPTOR_REVISION
))
189 return GetLastError();
191 static SID_IDENTIFIER_AUTHORITY siaNTAuthority
= SECURITY_NT_AUTHORITY
;
192 SecurityID
adminID(&siaNTAuthority
, 2,
193 SECURITY_BUILTIN_DOMAIN_RID
,
194 DOMAIN_ALIAS_RID_ADMINS
,
196 if (!adminID
.IsValid())
197 return GetLastError();
199 static SID_IDENTIFIER_AUTHORITY siaSystemAuthority
= SECURITY_NT_AUTHORITY
;
200 SecurityID
systemID(&siaSystemAuthority
, 1,
201 SECURITY_LOCAL_SYSTEM_RID
,
202 0, 0, 0, 0, 0, 0, 0);
203 if (!systemID
.IsValid())
204 return GetLastError();
206 static SID_IDENTIFIER_AUTHORITY siaCreatorAuthority
= SECURITY_CREATOR_SID_AUTHORITY
;
207 SecurityID
creatorID(&siaCreatorAuthority
, 1,
208 SECURITY_CREATOR_OWNER_RID
,
209 0, 0, 0, 0, 0, 0, 0);
210 if (!creatorID
.IsValid())
211 return GetLastError();
213 SID_NAME_USE snuType
;
215 DWORD cchDomainName
= sizeof(szDomain
);
216 SecurityID
userID(NULL
, PProcess::Current().GetUserName(),
217 szDomain
, &cchDomainName
, &snuType
);
218 if (!userID
.IsValid())
219 return GetLastError();
221 DWORD acl_len
= sizeof(ACL
) + 4*sizeof(ACCESS_ALLOWED_ACE
) +
222 adminID
.GetLength() + creatorID
.GetLength() +
223 systemID
.GetLength() + userID
.GetLength();
224 PBYTEArray
dacl_buf(acl_len
);
225 PACL dacl
= (PACL
)dacl_buf
.GetPointer(acl_len
);
226 if (!InitializeAcl(dacl
, acl_len
, ACL_REVISION2
))
227 return GetLastError();
229 if (!AddAccessAllowedAce(dacl
, ACL_REVISION2
, KEY_ALL_ACCESS
, adminID
))
230 return GetLastError();
232 if (!AddAccessAllowedAce(dacl
, ACL_REVISION2
, KEY_ALL_ACCESS
, systemID
))
233 return GetLastError();
235 if (!AddAccessAllowedAce(dacl
, ACL_REVISION2
, KEY_ALL_ACCESS
, creatorID
))
236 return GetLastError();
238 if (!AddAccessAllowedAce(dacl
, ACL_REVISION2
, KEY_ALL_ACCESS
, userID
))
239 return GetLastError();
241 if (!SetSecurityDescriptorDacl(&secdesc
, TRUE
, dacl
, FALSE
))
242 return GetLastError();
244 SECURITY_ATTRIBUTES secattr
;
245 secattr
.nLength
= sizeof(secattr
);
246 secattr
.lpSecurityDescriptor
= &secdesc
;
247 secattr
.bInheritHandle
= FALSE
;
251 return RegCreateKeyEx(rootKey
, subkey
, 0, "", REG_OPTION_NON_VOLATILE
,
252 KEY_ALL_ACCESS
, &secattr
, &key
, &disposition
);
256 RegistryKey::RegistryKey(const PString
& subkeyname
, OpenMode mode
)
258 PAssert(!subkeyname
.IsEmpty(), PInvalidParameter
);
260 PProcess
& proc
= PProcess::Current();
261 DWORD access
= mode
== ReadOnly
? KEY_READ
: KEY_ALL_ACCESS
;
266 if (subkeyname
.Find(LocalMachineStr
) == 0) {
267 subkey
= subkeyname
.Mid(19);
268 basekey
= HKEY_LOCAL_MACHINE
;
270 else if (subkeyname
.Find(CurrentUserStr
) == 0) {
271 subkey
= subkeyname
.Mid(18);
272 basekey
= HKEY_CURRENT_USER
;
276 PINDEX lastCharPos
= subkey
.GetLength()-1;
277 while (lastCharPos
> 0 && subkey
[lastCharPos
] == '\\')
278 subkey
.Delete(lastCharPos
--, 1);
281 if (!proc
.GetVersion(FALSE
).IsEmpty()) {
282 PString keyname
= subkey
;
283 keyname
.Replace("CurrentVersion", proc
.GetVersion(FALSE
));
285 error
= RegOpenKeyEx(HKEY_CURRENT_USER
, keyname
, 0, access
, &key
);
286 if (error
== ERROR_SUCCESS
)
290 if (error
== ERROR_ACCESS_DENIED
)
291 PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_CURRENT_USER\\" << keyname
);
294 error
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, keyname
, 0, access
, &key
);
295 if (error
== ERROR_SUCCESS
)
299 if (error
== ERROR_ACCESS_DENIED
)
300 PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_LOCAL_MACHINE\\" << keyname
);
304 error
= RegOpenKeyEx(HKEY_CURRENT_USER
, subkey
, 0, access
, &key
);
305 if (error
== ERROR_SUCCESS
)
309 if (error
== ERROR_ACCESS_DENIED
)
310 PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_CURRENT_USER\\" << subkey
);
314 error
= RegOpenKeyEx(basekey
!= NULL
? basekey
: HKEY_LOCAL_MACHINE
,
315 subkey
, 0, access
, &key
);
316 if (error
== ERROR_SUCCESS
)
320 if (error
== ERROR_ACCESS_DENIED
)
321 PTRACE(1, "PTLib\tAccess denied accessing registry entry "
322 << (basekey
!= NULL
? "" : LocalMachineStr
) << subkey
);
329 if (basekey
== NULL
) {
330 if (PProcess::Current().IsServiceProcess())
331 basekey
= HKEY_LOCAL_MACHINE
;
333 basekey
= HKEY_CURRENT_USER
;
337 error
= SecureCreateKey(basekey
, subkey
, key
);
338 if (error
!= ERROR_SUCCESS
) {
342 error
= RegCreateKeyEx(basekey
, subkey
, 0, "", REG_OPTION_NON_VOLATILE
,
343 KEY_ALL_ACCESS
, NULL
, &key
, &disposition
);
344 if (error
!= ERROR_SUCCESS
) {
345 PTRACE(1, "PTLib\tCould not create registry entry "
346 << (basekey
!= NULL
? "" : LocalMachineStr
) << subkey
);
355 RegistryKey::~RegistryKey()
362 BOOL
RegistryKey::EnumKey(PINDEX idx
, PString
& str
)
368 if( RegEnumKey(key
, idx
, str
.GetPointer(MAX_PATH
),MAX_PATH
) != ERROR_SUCCESS
)
370 #else // CE has only Unicode based API
372 TCHAR tstr
[MAX_PATH
];
373 LONG lResult
= RegEnumKey(key
, idx
, tstr
, MAX_PATH
);
375 if( lResult
!= ERROR_SUCCESS
)
379 str
.MakeMinimumSize();
384 BOOL
RegistryKey::EnumValue(PINDEX idx
, PString
& str
)
389 DWORD sizeofname
= MAX_PATH
;
391 if (RegEnumValue(key
, idx
, str
.GetPointer(sizeofname
),
392 &sizeofname
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
394 #else // CE has only Unicode based API
396 TCHAR tstr
[MAX_PATH
];
397 LONG lResult
= RegEnumValueCe(key
, idx
, tstr
,
398 &sizeofname
, NULL
, NULL
, NULL
, NULL
);
400 if( lResult
!= ERROR_SUCCESS
)
404 str
.MakeMinimumSize();
409 BOOL
RegistryKey::DeleteKey(const PString
& subkey
)
414 return RegDeleteKey(key
, subkey
) == ERROR_SUCCESS
;
418 BOOL
RegistryKey::DeleteValue(const PString
& value
)
423 return RegDeleteValue(key
, (char *)(const char *)value
) == ERROR_SUCCESS
;
427 BOOL
RegistryKey::QueryValue(const PString
& value
, PString
& str
)
433 if (RegQueryValueEx(key
, (char *)(const char *)value
,
434 NULL
, &type
, NULL
, &size
) != ERROR_SUCCESS
)
443 return RegQueryValueEx(key
, (char *)(const char *)value
, NULL
,
444 &type
, (LPBYTE
)str
.GetPointer(size
), &size
) == ERROR_SUCCESS
;
445 #else // CE has only Unicode based API
446 { USES_CONVERSION
; TCHAR tstr
[MAX_PATH
];
447 if( RegQueryValueEx(key
, (char *)(const char *)value
, NULL
,
448 &type
, (LPBYTE
) tstr
, &size
) == ERROR_SUCCESS
)
458 if (RegQueryValueEx(key
, (char *)(const char *)value
, NULL
,
459 &type
, (LPBYTE
)&num
, &size
) == ERROR_SUCCESS
) {
460 str
= PString(PString::Signed
, num
);
465 PAssertAlways("Unsupported registry type.");
471 BOOL
RegistryKey::QueryValue(const PString
& value
, DWORD
& num
, BOOL boolean
)
477 if (RegQueryValueEx(key
, (char *)(const char *)value
,
478 NULL
, &type
, NULL
, &size
) != ERROR_SUCCESS
)
483 if (size
> sizeof(DWORD
))
490 return RegQueryValueEx(key
, (char *)(const char *)value
, NULL
,
491 &type
, (LPBYTE
)&num
, &size
) == ERROR_SUCCESS
;
495 if (RegQueryValueEx(key
, (char *)(const char *)value
, NULL
,
496 &type
, (LPBYTE
)str
.GetPointer(size
), &size
) == ERROR_SUCCESS
) {
497 num
= str
.AsInteger();
498 if (num
== 0 && boolean
) {
499 int c
= toupper(str
[0]);
500 num
= c
== 'T' || c
== 'Y';
507 PAssertAlways("Unsupported registry type.");
514 BOOL
RegistryKey::SetValue(const PString
& value
, const PString
& str
)
520 return RegSetValueEx(key
, (char *)(const char *)value
, 0, REG_SZ
,
521 (LPBYTE
)(const char *)str
, str
.GetLength()+1) == ERROR_SUCCESS
;
522 #else // CE has only Unicode based API
524 return RegSetValueEx(key
, (char *)(const char *)value
, 0, REG_SZ
,
525 (LPBYTE
) A2T((const char *)str
),
526 ( (str
.GetLength()+1) * sizeof(TCHAR
)/sizeof(char) )
532 BOOL
RegistryKey::SetValue(const PString
& value
, DWORD num
)
537 return RegSetValueEx(key
, (char *)(const char *)value
,
538 0, REG_DWORD
, (LPBYTE
)&num
, sizeof(num
)) == ERROR_SUCCESS
;
542 static BOOL
IsRegistryPath(const PString
& path
)
544 return (path
.Find(LocalMachineStr
) == 0 && path
!= LocalMachineStr
) ||
545 (path
.Find(CurrentUserStr
) == 0 && path
!= CurrentUserStr
);
549 ///////////////////////////////////////////////////////////////////////////////
551 PString
PProcess::GetConfigurationFile()
553 // No paths set, use defaults
554 if (configurationPaths
.IsEmpty()) {
555 configurationPaths
.AppendString(executableFile
.GetVolume() + executableFile
.GetPath());
556 configurationPaths
.AppendString(CurrentUserStr
);
559 // See if explicit filename
560 if (configurationPaths
.GetSize() == 1 && !PDirectory::Exists(configurationPaths
[0]))
561 return configurationPaths
[0];
563 PString iniFilename
= executableFile
.GetTitle() + ".INI";
565 for (PINDEX i
= 0; i
< configurationPaths
.GetSize(); i
++) {
566 PString path
= configurationPaths
[i
];
567 if (IsRegistryPath(path
))
569 PFilePath cfgFile
= PDirectory(path
) + iniFilename
;
570 if (PFile::Exists(cfgFile
))
578 ///////////////////////////////////////////////////////////////////////////////
580 void PConfig::Construct(Source src
, const PString
& appname
, const PString
& manuf
)
582 source
= Application
;
586 if (IsRegistryPath(appname
))
590 GetWindowsDirectory(dir
.GetPointer(_MAX_PATH
), _MAX_PATH
);
591 Construct(PDirectory(dir
)+"WIN.INI");
596 if (IsRegistryPath(defaultSection
))
597 location
= PString();
599 PProcess
& proc
= PProcess::Current();
600 PString cfgPath
= proc
.GetConfigurationFile();
601 if (IsRegistryPath(cfgPath
))
604 source
= NumSources
; // Make a file based config
608 location
= "SOFTWARE\\";
611 else if (!proc
.GetManufacturer())
612 location
+= proc
.GetManufacturer();
615 location
+= PDIR_SEPARATOR
;
616 if (appname
.IsEmpty())
617 location
+= proc
.GetName();
620 location
+= "\\CurrentVersion\\";
631 void PConfig::Construct(const PFilePath
& filename
)
638 static void RecurseRegistryKeys(const PString
& location
,
640 PStringList
§ions
)
642 RegistryKey
registry(location
, RegistryKey::ReadOnly
);
644 for (PINDEX idx
= 0; registry
.EnumKey(idx
, name
); idx
++) {
645 RecurseRegistryKeys(location
+ name
+ '\\', baseLength
, sections
);
646 sections
.AppendString(location
.Mid(baseLength
) + name
);
651 static PString
PGetPrivateProfileString(const char * lpAppName
,
652 const char * lpKeyName
,
653 const char * lpDefault
,
654 const char * lpFileName
)
658 DWORD numNulls
= lpAppName
!= NULL
&& lpKeyName
!= NULL
? 1 : 2;
660 while (size
<= 100000 &&
661 ::GetPrivateProfileString(lpAppName
, lpKeyName
, lpDefault
,
662 buffer
.GetPointer(size
+numNulls
), size
+numNulls
,
670 PStringList
PConfig::GetSections() const
672 PStringList sections
;
676 RecurseRegistryKeys(location
, location
.GetLength(), sections
);
680 PString buffer
= PGetPrivateProfileString(NULL
, NULL
, "", location
);
681 char * ptr
= buffer
.GetPointer();
682 while (*ptr
!= '\0') {
683 sections
.AppendString(ptr
);
684 ptr
+= strlen(ptr
)+1;
693 PStringList
PConfig::GetKeys(const PString
& section
) const
699 char ** ptr
= _environ
;
700 while (*ptr
!= NULL
) {
701 PString buf
= *ptr
++;
702 keys
.AppendString(buf
.Left(buf
.Find('=')));
708 PAssert(!section
.IsEmpty(), PInvalidParameter
);
709 RegistryKey
registry(location
+ section
, RegistryKey::ReadOnly
);
711 for (PINDEX idx
= 0; registry
.EnumValue(idx
, name
); idx
++)
712 keys
.AppendString(name
);
717 PAssert(!section
.IsEmpty(), PInvalidParameter
);
718 PString buffer
= PGetPrivateProfileString(section
, NULL
, "", location
);
719 char * ptr
= buffer
.GetPointer();
720 while (*ptr
!= '\0') {
721 keys
.AppendString(ptr
);
722 ptr
+= strlen(ptr
)+1;
730 void PConfig::DeleteSection(const PString
& section
)
734 PAssert(!section
.IsEmpty(), PInvalidParameter
);
735 RegistryKey
registry(location
, RegistryKey::ReadWrite
);
736 registry
.DeleteKey(section
);
741 PAssert(!section
.IsEmpty(), PInvalidParameter
);
742 PAssertOS(WritePrivateProfileString(section
, NULL
, NULL
, location
));
747 void PConfig::DeleteKey(const PString
& section
, const PString
& key
)
751 PAssert(!key
.IsEmpty() && key
.Find('=') == P_MAX_INDEX
, PInvalidParameter
);
756 PAssert(!section
.IsEmpty(), PInvalidParameter
);
757 RegistryKey
registry(location
+ section
, RegistryKey::ReadWrite
);
758 registry
.DeleteValue(key
);
763 PAssert(!key
.IsEmpty(), PInvalidParameter
);
764 PAssert(!section
.IsEmpty(), PInvalidParameter
);
765 PAssertOS(WritePrivateProfileString(section
, key
, NULL
, location
));
770 BOOL
PConfig::HasKey(const PString
& section
, const PString
& key
) const
774 PAssert(!key
.IsEmpty(), PInvalidParameter
);
775 return getenv(key
) != NULL
;
778 PAssert(!section
.IsEmpty(), PInvalidParameter
);
779 RegistryKey
registry(location
+ section
, RegistryKey::ReadOnly
);
781 return registry
.QueryValue(key
, dummy
);
785 PAssert(!key
.IsEmpty() && !section
.IsEmpty(), PInvalidParameter
);
786 static const char dflt
[] = "<<<<<====---PConfig::DefaultValueString---====>>>>>";
787 return PGetPrivateProfileString(section
, key
, dflt
, location
) != dflt
;
794 PString
PConfig::GetString(const PString
& section
,
795 const PString
& key
, const PString
& dflt
) const
801 PAssert(!key
.IsEmpty() && key
.Find('=') == P_MAX_INDEX
, PInvalidParameter
);
802 char * env
= getenv(key
);
811 PAssert(!section
.IsEmpty(), PInvalidParameter
);
812 RegistryKey
registry(location
+ section
, RegistryKey::ReadOnly
);
813 if (!registry
.QueryValue(key
, str
))
819 PAssert(!key
.IsEmpty() && !section
.IsEmpty(), PInvalidParameter
);
820 str
= PGetPrivateProfileString(section
, key
, dflt
, location
);
821 str
.MakeMinimumSize();
828 void PConfig::SetString(const PString
& section
,
829 const PString
& key
, const PString
& value
)
833 PAssert(!key
.IsEmpty() && key
.Find('=') == P_MAX_INDEX
, PInvalidParameter
);
834 _putenv(key
+ "=" + value
);
838 PAssert(!section
.IsEmpty(), PInvalidParameter
);
839 RegistryKey
registry(location
+ section
, RegistryKey::Create
);
840 registry
.SetValue(key
, value
);
845 PAssert(!key
.IsEmpty() && !section
.IsEmpty(), PInvalidParameter
);
846 PAssertOS(WritePrivateProfileString(section
, key
, value
, location
));
851 BOOL
PConfig::GetBoolean(const PString
& section
,
852 const PString
& key
, BOOL dflt
) const
854 if (source
!= Application
) {
855 PString str
= GetString(section
, key
, dflt
? "T" : "F").ToUpper();
856 int c
= toupper(str
[0]);
857 return c
== 'T' || c
== 'Y' || str
.AsInteger() != 0;
860 PAssert(!section
.IsEmpty(), PInvalidParameter
);
861 RegistryKey
registry(location
+ section
, RegistryKey::ReadOnly
);
864 if (!registry
.QueryValue(key
, value
, TRUE
))
871 void PConfig::SetBoolean(const PString
& section
, const PString
& key
, BOOL value
)
873 if (source
!= Application
)
874 SetString(section
, key
, value
? "True" : "False");
876 PAssert(!section
.IsEmpty(), PInvalidParameter
);
877 RegistryKey
registry(location
+ section
, RegistryKey::Create
);
878 registry
.SetValue(key
, value
? 1 : 0);
883 long PConfig::GetInteger(const PString
& section
,
884 const PString
& key
, long dflt
) const
886 if (source
!= Application
) {
887 PString
str(PString::Signed
, dflt
);
888 return GetString(section
, key
, str
).AsInteger();
891 PAssert(!section
.IsEmpty(), PInvalidParameter
);
892 RegistryKey
registry(location
+ section
, RegistryKey::ReadOnly
);
895 if (!registry
.QueryValue(key
, value
, FALSE
))
902 void PConfig::SetInteger(const PString
& section
, const PString
& key
, long value
)
904 if (source
!= Application
) {
905 PString
str(PString::Signed
, value
);
906 SetString(section
, key
, str
);
909 PAssert(!section
.IsEmpty(), PInvalidParameter
);
910 RegistryKey
registry(location
+ section
, RegistryKey::Create
);
911 registry
.SetValue(key
, value
);
916 // End Of File ///////////////////////////////////////////////////////////////