2021-09-21 17:00:21 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Applications Manager
|
|
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
|
|
* PURPOSE: Config parser
|
2021-09-30 18:19:21 +00:00
|
|
|
* COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
|
2021-09-21 17:00:21 +00:00
|
|
|
* Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
|
2021-09-30 18:19:21 +00:00
|
|
|
* Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
|
|
|
|
* Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
|
2021-09-21 17:00:21 +00:00
|
|
|
*/
|
2021-12-29 00:05:00 +00:00
|
|
|
|
2021-09-21 17:00:21 +00:00
|
|
|
#include "rapps.h"
|
2021-09-30 18:19:21 +00:00
|
|
|
#include <debug.h>
|
2021-09-21 17:00:21 +00:00
|
|
|
|
2021-09-30 18:19:21 +00:00
|
|
|
struct CLocaleSections
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2021-09-30 18:19:21 +00:00
|
|
|
CStringW Locale;
|
|
|
|
CStringW LocaleNeutral;
|
|
|
|
CStringW Section;
|
|
|
|
};
|
2021-09-21 17:00:21 +00:00
|
|
|
|
2021-09-30 18:19:21 +00:00
|
|
|
struct CSectionNames
|
|
|
|
{
|
|
|
|
CLocaleSections ArchSpecific;
|
|
|
|
CLocaleSections ArchNeutral;
|
|
|
|
};
|
|
|
|
static CSectionNames g_Names;
|
|
|
|
|
2021-12-29 00:05:00 +00:00
|
|
|
CConfigParser::CConfigParser(const CStringW &FilePath) : szConfigPath(FilePath)
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2021-09-30 18:19:21 +00:00
|
|
|
CacheINI();
|
2021-09-21 17:00:21 +00:00
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
void
|
|
|
|
CConfigParser::ReadSection(CStringW &Buffer, const CStringW &Section, BOOL isArch)
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2021-09-30 18:19:21 +00:00
|
|
|
DWORD len = 512;
|
|
|
|
DWORD result;
|
|
|
|
|
|
|
|
do
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2021-09-30 18:19:21 +00:00
|
|
|
len *= 2;
|
|
|
|
|
|
|
|
result = GetPrivateProfileSectionW(Section, Buffer.GetBuffer(len), len, szConfigPath);
|
|
|
|
Buffer.ReleaseBuffer(result);
|
|
|
|
} while (result == len - 2);
|
|
|
|
|
|
|
|
len = 0;
|
|
|
|
while (len < result)
|
|
|
|
{
|
|
|
|
// Explicitly use the null terminator!
|
|
|
|
CString tmp = Buffer.GetBuffer() + len;
|
|
|
|
if (tmp.GetLength() > 0)
|
|
|
|
{
|
|
|
|
len += tmp.GetLength() + 1;
|
|
|
|
|
|
|
|
int idx = tmp.Find('=');
|
|
|
|
if (idx >= 0)
|
|
|
|
{
|
|
|
|
CString key = tmp.Left(idx);
|
|
|
|
|
|
|
|
#ifndef _M_IX86
|
|
|
|
// On non-x86 architecture we need the architecture specific URL
|
|
|
|
if (!isArch && key == "URLDownload")
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Is this key already present from a more specific translation?
|
|
|
|
if (m_Keys.FindKey(key) >= 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
CString value = tmp.Mid(idx + 1);
|
2021-09-30 18:19:21 +00:00
|
|
|
m_Keys.Add(key, value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("ERROR: invalid key/value pair: '%S'\n", tmp.GetString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2021-09-30 18:19:21 +00:00
|
|
|
break;
|
2021-09-21 17:00:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CConfigParser::CacheINI()
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2021-09-30 18:19:21 +00:00
|
|
|
// Cache section names
|
|
|
|
if (g_Names.ArchSpecific.Locale.IsEmpty())
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2021-09-30 18:19:21 +00:00
|
|
|
CString szLocaleID;
|
|
|
|
const INT cchLocaleSize = 5;
|
|
|
|
|
|
|
|
GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE, szLocaleID.GetBuffer(cchLocaleSize), cchLocaleSize);
|
|
|
|
szLocaleID.ReleaseBuffer();
|
|
|
|
CString INISectionLocale = L"Section." + szLocaleID;
|
|
|
|
|
|
|
|
g_Names.ArchSpecific.Locale = INISectionLocale + L"." CurrentArchitecture;
|
|
|
|
g_Names.ArchNeutral.Locale = INISectionLocale;
|
|
|
|
|
|
|
|
// turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part
|
|
|
|
if (szLocaleID.GetLength() >= 2)
|
|
|
|
{
|
|
|
|
g_Names.ArchSpecific.LocaleNeutral = L"Section." + szLocaleID.Right(2) + L"." CurrentArchitecture;
|
|
|
|
g_Names.ArchNeutral.LocaleNeutral = L"Section." + szLocaleID.Right(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_Names.ArchSpecific.Section = L"Section." CurrentArchitecture;
|
|
|
|
g_Names.ArchNeutral.Section = L"Section";
|
2021-09-21 17:00:21 +00:00
|
|
|
}
|
|
|
|
|
2021-09-30 18:19:21 +00:00
|
|
|
// Use a shared buffer so that we don't have to re-allocate it every time
|
|
|
|
CStringW Buffer;
|
|
|
|
|
|
|
|
ReadSection(Buffer, g_Names.ArchSpecific.Locale, TRUE);
|
|
|
|
if (!g_Names.ArchSpecific.LocaleNeutral.IsEmpty())
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2021-09-30 18:19:21 +00:00
|
|
|
ReadSection(Buffer, g_Names.ArchSpecific.LocaleNeutral, TRUE);
|
|
|
|
}
|
|
|
|
ReadSection(Buffer, g_Names.ArchSpecific.Section, TRUE);
|
|
|
|
|
|
|
|
ReadSection(Buffer, g_Names.ArchNeutral.Locale, FALSE);
|
|
|
|
if (!g_Names.ArchNeutral.LocaleNeutral.IsEmpty())
|
|
|
|
{
|
|
|
|
ReadSection(Buffer, g_Names.ArchNeutral.LocaleNeutral, FALSE);
|
|
|
|
}
|
|
|
|
ReadSection(Buffer, g_Names.ArchNeutral.Section, FALSE);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CConfigParser::GetString(const CStringW &KeyName, CStringW &ResultString)
|
2021-09-30 18:19:21 +00:00
|
|
|
{
|
|
|
|
int nIndex = m_Keys.FindKey(KeyName);
|
|
|
|
if (nIndex >= 0)
|
|
|
|
{
|
|
|
|
ResultString = m_Keys.GetValueAt(nIndex);
|
|
|
|
return TRUE;
|
2021-09-21 17:00:21 +00:00
|
|
|
}
|
|
|
|
|
2021-09-30 18:19:21 +00:00
|
|
|
ResultString.Empty();
|
|
|
|
return FALSE;
|
2021-09-21 17:00:21 +00:00
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CConfigParser::GetInt(const CStringW &KeyName, INT &iResult)
|
2021-09-21 17:00:21 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW Buffer;
|
2021-09-21 17:00:21 +00:00
|
|
|
|
|
|
|
iResult = 0;
|
|
|
|
|
|
|
|
// grab the text version of our entry
|
|
|
|
if (!GetString(KeyName, Buffer))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (Buffer.IsEmpty())
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
// convert it to an actual integer
|
|
|
|
iResult = StrToIntW(Buffer.GetString());
|
|
|
|
|
|
|
|
// we only care about values > 0
|
|
|
|
return (iResult > 0);
|
|
|
|
}
|