Changed output and intermediate directories, tuned up compile parameters for Windows...
[pwlib.git] / src / ptlib / msos / wincfg.cxx
blob7f0e2fa84a3b255633bf1baeff23aa858c81bcf6
1 /*
2 * wincfg.cxx
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
18 * under the License.
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): ______________________________________.
29 * $Log$
30 * Revision 1.18 2006/06/21 04:20:07 csoutheren
31 * Fixes for VS.net
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
83 * Initial revision
87 #include <ptlib.h>
88 #include <ptlib/pprocess.h>
90 #include <winuser.h>
91 #include <winnls.h>
93 #include <process.h>
94 #include <fcntl.h>
95 #include <errno.h>
96 #include <sys/stat.h>
98 #define new PNEW
101 const char LocalMachineStr[] = "HKEY_LOCAL_MACHINE\\";
102 const char CurrentUserStr[] = "HKEY_CURRENT_USER\\";
104 ///////////////////////////////////////////////////////////////////////////////
105 // Configuration files
107 #ifndef _WIN32_WCE
108 class SecurityID
110 public:
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
133 &sidptr))
134 sidptr = NULL;
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
144 DWORD len = 1024;
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
154 )) {
155 LocalFree(sidptr);
156 sidptr = NULL;
160 ~SecurityID()
162 FreeSid(sidptr);
165 operator PSID() const
167 return sidptr;
170 DWORD GetLength() const
172 return GetLengthSid(sidptr);
175 BOOL IsValid() const
177 return sidptr != NULL && IsValidSid(sidptr);
180 private:
181 PSID 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,
195 0, 0, 0, 0, 0, 0);
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;
214 char szDomain[100];
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;
249 DWORD disposition;
251 return RegCreateKeyEx(rootKey, subkey, 0, "", REG_OPTION_NON_VOLATILE,
252 KEY_ALL_ACCESS, &secattr, &key, &disposition);
254 #endif // _WIN32_WCE
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;
262 DWORD error;
264 PString subkey;
265 HKEY basekey;
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;
274 else {
275 subkey = subkeyname;
276 PINDEX lastCharPos = subkey.GetLength()-1;
277 while (lastCharPos > 0 && subkey[lastCharPos] == '\\')
278 subkey.Delete(lastCharPos--, 1);
279 basekey = NULL;
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)
287 return;
289 #if PTRACING
290 if (error == ERROR_ACCESS_DENIED)
291 PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_CURRENT_USER\\" << keyname);
292 #endif
294 error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, access, &key);
295 if (error == ERROR_SUCCESS)
296 return;
298 #if PTRACING
299 if (error == ERROR_ACCESS_DENIED)
300 PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_LOCAL_MACHINE\\" << keyname);
301 #endif
304 error = RegOpenKeyEx(HKEY_CURRENT_USER, subkey, 0, access, &key);
305 if (error == ERROR_SUCCESS)
306 return;
308 #if PTRACING
309 if (error == ERROR_ACCESS_DENIED)
310 PTRACE(1, "PTLib\tAccess denied accessing registry entry HKEY_CURRENT_USER\\" << subkey);
311 #endif
314 error = RegOpenKeyEx(basekey != NULL ? basekey : HKEY_LOCAL_MACHINE,
315 subkey, 0, access, &key);
316 if (error == ERROR_SUCCESS)
317 return;
319 #if PTRACING
320 if (error == ERROR_ACCESS_DENIED)
321 PTRACE(1, "PTLib\tAccess denied accessing registry entry "
322 << (basekey != NULL ? "" : LocalMachineStr) << subkey);
323 #endif
325 key = NULL;
326 if (mode != Create)
327 return;
329 if (basekey == NULL) {
330 if (PProcess::Current().IsServiceProcess())
331 basekey = HKEY_LOCAL_MACHINE;
332 else
333 basekey = HKEY_CURRENT_USER;
336 #ifndef _WIN32_WCE
337 error = SecureCreateKey(basekey, subkey, key);
338 if (error != ERROR_SUCCESS) {
339 #endif
341 DWORD disposition;
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);
347 key = NULL;
349 #ifndef _WIN32_WCE
351 #endif // _WIN32_WCE
355 RegistryKey::~RegistryKey()
357 if (key != NULL)
358 RegCloseKey(key);
362 BOOL RegistryKey::EnumKey(PINDEX idx, PString & str)
364 if (key == NULL)
365 return FALSE;
367 #ifndef _WIN32_WCE
368 if( RegEnumKey(key, idx, str.GetPointer(MAX_PATH),MAX_PATH) != ERROR_SUCCESS)
370 #else // CE has only Unicode based API
371 USES_CONVERSION;
372 TCHAR tstr[MAX_PATH];
373 LONG lResult = RegEnumKey(key, idx, tstr, MAX_PATH);
374 str = T2A(tstr);
375 if( lResult != ERROR_SUCCESS )
376 #endif
377 return FALSE;
379 str.MakeMinimumSize();
380 return TRUE;
384 BOOL RegistryKey::EnumValue(PINDEX idx, PString & str)
386 if (key == NULL)
387 return FALSE;
389 DWORD sizeofname = MAX_PATH;
390 #ifndef _WIN32_WCE
391 if (RegEnumValue(key, idx, str.GetPointer(sizeofname),
392 &sizeofname, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
394 #else // CE has only Unicode based API
395 USES_CONVERSION;
396 TCHAR tstr[MAX_PATH];
397 LONG lResult = RegEnumValueCe(key, idx, tstr,
398 &sizeofname, NULL, NULL, NULL, NULL);
399 str = T2A(tstr);
400 if( lResult != ERROR_SUCCESS )
401 #endif
402 return FALSE;
404 str.MakeMinimumSize();
405 return TRUE;
409 BOOL RegistryKey::DeleteKey(const PString & subkey)
411 if (key == NULL)
412 return TRUE;
414 return RegDeleteKey(key, subkey) == ERROR_SUCCESS;
418 BOOL RegistryKey::DeleteValue(const PString & value)
420 if (key == NULL)
421 return TRUE;
423 return RegDeleteValue(key, (char *)(const char *)value) == ERROR_SUCCESS;
427 BOOL RegistryKey::QueryValue(const PString & value, PString & str)
429 if (key == NULL)
430 return FALSE;
432 DWORD type, size;
433 if (RegQueryValueEx(key, (char *)(const char *)value,
434 NULL, &type, NULL, &size) != ERROR_SUCCESS)
435 return FALSE;
437 switch (type) {
438 case REG_SZ :
439 case REG_MULTI_SZ :
440 case REG_EXPAND_SZ :
441 case REG_BINARY :
442 #ifndef _WIN32_WCE
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 )
450 str = T2A(tstr);
451 return TRUE;
454 #endif
455 case REG_DWORD : {
456 DWORD num;
457 size = sizeof(num);
458 if (RegQueryValueEx(key, (char *)(const char *)value, NULL,
459 &type, (LPBYTE)&num, &size) == ERROR_SUCCESS) {
460 str = PString(PString::Signed, num);
461 return TRUE;
464 default :
465 PAssertAlways("Unsupported registry type.");
467 return FALSE;
471 BOOL RegistryKey::QueryValue(const PString & value, DWORD & num, BOOL boolean)
473 if (key == NULL)
474 return FALSE;
476 DWORD type, size;
477 if (RegQueryValueEx(key, (char *)(const char *)value,
478 NULL, &type, NULL, &size) != ERROR_SUCCESS)
479 return FALSE;
481 switch (type) {
482 case REG_BINARY :
483 if (size > sizeof(DWORD))
484 return FALSE;
486 num = 0;
487 // Do REG_DWORD case
489 case REG_DWORD :
490 return RegQueryValueEx(key, (char *)(const char *)value, NULL,
491 &type, (LPBYTE)&num, &size) == ERROR_SUCCESS;
493 case REG_SZ : {
494 PString str;
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';
502 return TRUE;
504 break;
506 default :
507 PAssertAlways("Unsupported registry type.");
510 return FALSE;
514 BOOL RegistryKey::SetValue(const PString & value, const PString & str)
516 if (key == NULL)
517 return FALSE;
519 #ifndef _WIN32_WCE
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
523 USES_CONVERSION;
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) )
527 ) == ERROR_SUCCESS;
528 #endif
532 BOOL RegistryKey::SetValue(const PString & value, DWORD num)
534 if (key == NULL)
535 return FALSE;
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))
568 return path;
569 PFilePath cfgFile = PDirectory(path) + iniFilename;
570 if (PFile::Exists(cfgFile))
571 return cfgFile;
574 return PString();
578 ///////////////////////////////////////////////////////////////////////////////
580 void PConfig::Construct(Source src, const PString & appname, const PString & manuf)
582 source = Application;
584 switch (src) {
585 case System :
586 if (IsRegistryPath(appname))
587 location = appname;
588 else {
589 PString dir;
590 GetWindowsDirectory(dir.GetPointer(_MAX_PATH), _MAX_PATH);
591 Construct(PDirectory(dir)+"WIN.INI");
593 break;
595 case Application :
596 if (IsRegistryPath(defaultSection))
597 location = PString();
598 else {
599 PProcess & proc = PProcess::Current();
600 PString cfgPath = proc.GetConfigurationFile();
601 if (IsRegistryPath(cfgPath))
602 location = cfgPath;
603 else if (!cfgPath) {
604 source = NumSources; // Make a file based config
605 location = cfgPath;
607 else {
608 location = "SOFTWARE\\";
609 if (!manuf)
610 location += manuf;
611 else if (!proc.GetManufacturer())
612 location += proc.GetManufacturer();
613 else
614 location += "PWLib";
615 location += PDIR_SEPARATOR;
616 if (appname.IsEmpty())
617 location += proc.GetName();
618 else
619 location += appname;
620 location += "\\CurrentVersion\\";
623 break;
625 default :
626 source = src;
631 void PConfig::Construct(const PFilePath & filename)
633 location = filename;
634 source = NumSources;
638 static void RecurseRegistryKeys(const PString & location,
639 PINDEX baseLength,
640 PStringList &sections)
642 RegistryKey registry(location, RegistryKey::ReadOnly);
643 PString name;
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)
656 PString buffer;
658 DWORD numNulls = lpAppName != NULL && lpKeyName != NULL ? 1 : 2;
659 DWORD size = 100;
660 while (size <= 100000 &&
661 ::GetPrivateProfileString(lpAppName, lpKeyName, lpDefault,
662 buffer.GetPointer(size+numNulls), size+numNulls,
663 lpFileName) == size)
664 size *= 10;
666 return buffer;
670 PStringList PConfig::GetSections() const
672 PStringList sections;
674 switch (source) {
675 case Application :
676 RecurseRegistryKeys(location, location.GetLength(), sections);
677 break;
679 case NumSources :
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;
686 break;
689 return sections;
693 PStringList PConfig::GetKeys(const PString & section) const
695 PStringList keys;
697 switch (source) {
698 case Environment : {
699 char ** ptr = _environ;
700 while (*ptr != NULL) {
701 PString buf = *ptr++;
702 keys.AppendString(buf.Left(buf.Find('=')));
704 break;
707 case Application : {
708 PAssert(!section.IsEmpty(), PInvalidParameter);
709 RegistryKey registry(location + section, RegistryKey::ReadOnly);
710 PString name;
711 for (PINDEX idx = 0; registry.EnumValue(idx, name); idx++)
712 keys.AppendString(name);
713 break;
716 case NumSources :
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;
726 return keys;
730 void PConfig::DeleteSection(const PString & section)
732 switch (source) {
733 case Application : {
734 PAssert(!section.IsEmpty(), PInvalidParameter);
735 RegistryKey registry(location, RegistryKey::ReadWrite);
736 registry.DeleteKey(section);
737 break;
740 case NumSources :
741 PAssert(!section.IsEmpty(), PInvalidParameter);
742 PAssertOS(WritePrivateProfileString(section, NULL, NULL, location));
747 void PConfig::DeleteKey(const PString & section, const PString & key)
749 switch (source) {
750 case Environment :
751 PAssert(!key.IsEmpty() && key.Find('=') == P_MAX_INDEX, PInvalidParameter);
752 _putenv(key + "=");
753 break;
755 case Application : {
756 PAssert(!section.IsEmpty(), PInvalidParameter);
757 RegistryKey registry(location + section, RegistryKey::ReadWrite);
758 registry.DeleteValue(key);
759 break;
762 case NumSources :
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
772 switch (source) {
773 case Environment :
774 PAssert(!key.IsEmpty(), PInvalidParameter);
775 return getenv(key) != NULL;
777 case Application : {
778 PAssert(!section.IsEmpty(), PInvalidParameter);
779 RegistryKey registry(location + section, RegistryKey::ReadOnly);
780 PString dummy;
781 return registry.QueryValue(key, dummy);
784 case NumSources :
785 PAssert(!key.IsEmpty() && !section.IsEmpty(), PInvalidParameter);
786 static const char dflt[] = "<<<<<====---PConfig::DefaultValueString---====>>>>>";
787 return PGetPrivateProfileString(section, key, dflt, location) != dflt;
790 return FALSE;
794 PString PConfig::GetString(const PString & section,
795 const PString & key, const PString & dflt) const
797 PString str;
799 switch (source) {
800 case Environment : {
801 PAssert(!key.IsEmpty() && key.Find('=') == P_MAX_INDEX, PInvalidParameter);
802 char * env = getenv(key);
803 if (env != NULL)
804 str = env;
805 else
806 str = dflt;
807 break;
810 case Application : {
811 PAssert(!section.IsEmpty(), PInvalidParameter);
812 RegistryKey registry(location + section, RegistryKey::ReadOnly);
813 if (!registry.QueryValue(key, str))
814 str = dflt;
815 break;
818 case NumSources :
819 PAssert(!key.IsEmpty() && !section.IsEmpty(), PInvalidParameter);
820 str = PGetPrivateProfileString(section, key, dflt, location);
821 str.MakeMinimumSize();
824 return str;
828 void PConfig::SetString(const PString & section,
829 const PString & key, const PString & value)
831 switch (source) {
832 case Environment :
833 PAssert(!key.IsEmpty() && key.Find('=') == P_MAX_INDEX, PInvalidParameter);
834 _putenv(key + "=" + value);
835 break;
837 case Application : {
838 PAssert(!section.IsEmpty(), PInvalidParameter);
839 RegistryKey registry(location + section, RegistryKey::Create);
840 registry.SetValue(key, value);
841 break;
844 case NumSources :
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);
863 DWORD value;
864 if (!registry.QueryValue(key, value, TRUE))
865 return dflt;
867 return value != 0;
871 void PConfig::SetBoolean(const PString & section, const PString & key, BOOL value)
873 if (source != Application)
874 SetString(section, key, value ? "True" : "False");
875 else {
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);
894 DWORD value;
895 if (!registry.QueryValue(key, value, FALSE))
896 return dflt;
898 return value;
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);
908 else {
909 PAssert(!section.IsEmpty(), PInvalidParameter);
910 RegistryKey registry(location + section, RegistryKey::Create);
911 registry.SetValue(key, value);
916 // End Of File ///////////////////////////////////////////////////////////////