summaryrefslogtreecommitdiffstats
path: root/sal/osl/w32/profile.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sal/osl/w32/profile.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sal/osl/w32/profile.cxx')
-rw-r--r--sal/osl/w32/profile.cxx2341
1 files changed, 2341 insertions, 0 deletions
diff --git a/sal/osl/w32/profile.cxx b/sal/osl/w32/profile.cxx
new file mode 100644
index 000000000..17540f65e
--- /dev/null
+++ b/sal/osl/w32/profile.cxx
@@ -0,0 +1,2341 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "system.h"
+
+#include "file_url.hxx"
+#include "path_helper.hxx"
+
+#include <string.h>
+#include <osl/diagnose.h>
+#include <osl/profile.h>
+#include <osl/process.h>
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <rtl/alloc.h>
+#include <sal/macros.h>
+#include <sal/log.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+#include <algorithm>
+#include <vector>
+using std::min;
+static void copy_ustr_n( void *dest, const void *source, size_t length ) { memcpy(dest, source, length*sizeof(sal_Unicode)); }
+
+#define LINES_INI 32
+#define LINES_ADD 10
+#define SECTIONS_INI 5
+#define SECTIONS_ADD 3
+#define ENTRIES_INI 5
+#define ENTRIES_ADD 3
+
+#define STR_INI_EXTENSION L".ini"
+#define STR_INI_METAHOME "?~"
+#define STR_INI_METASYS "?$"
+#define STR_INI_METACFG "?^"
+#define STR_INI_METAINS "?#"
+
+#define STR_INI_BOOLYES "yes"
+#define STR_INI_BOOLON "on"
+#define STR_INI_BOOLONE "1"
+#define STR_INI_BOOLNO "no"
+#define STR_INI_BOOLOFF "off"
+#define STR_INI_BOOLZERO "0"
+
+#define FLG_USER 0x00FF
+#define FLG_AUTOOPEN 0x0100
+#define FLG_MODIFIED 0x0200
+
+#define SVERSION_LOCATION STR_INI_METACFG
+#define SVERSION_FALLBACK STR_INI_METASYS
+#define SVERSION_NAME "sversion"
+#define SVERSION_SECTION "Versions"
+#define SVERSION_SOFFICE "StarOffice"
+#define SVERSION_PROFILE "soffice.ini"
+#define SVERSION_DIRS { "bin", "program" }
+#define SVERSION_USER "user"
+
+/*#define DEBUG_OSL_PROFILE 1*/
+
+typedef FILETIME osl_TStamp;
+
+namespace {
+
+enum osl_TLockMode
+{
+ un_lock, read_lock, write_lock
+};
+
+struct osl_TFile
+{
+ HANDLE m_Handle;
+ char* m_pReadPtr;
+ char m_ReadBuf[512];
+ char* m_pWriteBuf;
+ sal_uInt32 m_nWriteBufLen;
+ sal_uInt32 m_nWriteBufFree;
+};
+
+struct osl_TProfileEntry
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+};
+
+struct osl_TProfileSection
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+ sal_uInt32 m_NoEntries;
+ sal_uInt32 m_MaxEntries;
+ osl_TProfileEntry* m_Entries;
+};
+
+/*
+ Profile-data structure hidden behind oslProfile:
+*/
+struct osl_TProfileImpl
+{
+ sal_uInt32 m_Flags;
+ osl_TFile* m_pFile;
+ osl_TStamp m_Stamp;
+ sal_uInt32 m_NoLines;
+ sal_uInt32 m_MaxLines;
+ sal_uInt32 m_NoSections;
+ sal_uInt32 m_MaxSections;
+ char** m_Lines;
+ rtl_uString *m_strFileName;
+ osl_TProfileSection* m_Sections;
+};
+
+}
+
+static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags );
+static osl_TStamp closeFileImpl(osl_TFile* pFile);
+static bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
+static bool rewindFile(osl_TFile* pFile, bool bTruncate);
+static osl_TStamp getFileStamp(osl_TFile* pFile);
+
+static bool getLine(osl_TFile* pFile, char *pszLine, int MaxLen);
+static bool putLine(osl_TFile* pFile, const char *pszLine);
+static const char* stripBlanks(const char* String, sal_uInt32* pLen);
+static const char* addLine(osl_TProfileImpl* pProfile, const char* Line);
+static const char* insertLine(osl_TProfileImpl* pProfile, const char* Line, sal_uInt32 LineNo);
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ const char* Entry, sal_uInt32 Len);
+static bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, const char* Entry, sal_uInt32 Len);
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
+static bool addSection(osl_TProfileImpl* pProfile, int Line, const char* Section, sal_uInt32 Len);
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const char* Section,
+ const char* Entry, sal_uInt32 *pNoEntry);
+static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
+static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup);
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable);
+static bool releaseProfile(osl_TProfileImpl* pProfile);
+static bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile);
+
+static bool writeProfileImpl (osl_TFile* pFile);
+static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
+static bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
+static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension);
+
+static bool osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName);
+
+oslProfile SAL_CALL osl_openProfile(rtl_uString *strProfileName, oslProfileOption Flags)
+{
+ osl_TFile* pFile = nullptr;
+ osl_TProfileImpl* pProfile;
+ rtl_uString *FileName=nullptr;
+
+ OSL_VERIFY(strProfileName);
+
+ if (rtl_uString_getLength(strProfileName) == 0 )
+ {
+ OSL_VERIFY(osl_getProfileName(nullptr, nullptr, &FileName));
+ }
+ else
+ {
+ rtl_uString_assign(&FileName, strProfileName);
+ }
+
+ osl_getSystemPathFromFileURL(FileName, &FileName);
+
+#ifdef DEBUG_OSL_PROFILE
+ Flags=osl_Profile_FLUSHWRITE;
+
+ if ( Flags == osl_Profile_DEFAULT )
+ {
+ SAL_INFO("sal.osl", "with osl_Profile_DEFAULT");
+ }
+ if ( Flags & osl_Profile_SYSTEM )
+ {
+ SAL_INFO("sal.osl", "with osl_Profile_SYSTEM");
+ }
+ if ( Flags & osl_Profile_READLOCK )
+ {
+ SAL_INFO("sal.osl", "with osl_Profile_READLOCK");
+ }
+ if ( Flags & osl_Profile_WRITELOCK )
+ {
+ SAL_INFO("sal.osl", "with osl_Profile_WRITELOCK");
+ }
+ if ( Flags & osl_Profile_FLUSHWRITE )
+ {
+ SAL_INFO("sal.osl", "with osl_Profile_FLUSHWRITE");
+ }
+#endif
+
+ if ( (! (Flags & osl_Profile_SYSTEM)) && ( (pFile = openFileImpl(FileName, Flags) ) == nullptr ) )
+ {
+ if( FileName)
+ rtl_uString_release( FileName);
+
+ return nullptr;
+ }
+
+ pProfile = static_cast<osl_TProfileImpl*>(calloc(1, sizeof(osl_TProfileImpl)));
+ if (!pProfile)
+ return nullptr;
+
+ pProfile->m_Flags = Flags & FLG_USER;
+ osl_getSystemPathFromFileURL(strProfileName, &pProfile->m_strFileName);
+
+ if (Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ))
+ pProfile->m_pFile = pFile;
+
+ pProfile->m_Stamp = getFileStamp(pFile);
+
+ loadProfile(pFile, pProfile);
+
+ if (pProfile->m_pFile == nullptr)
+ closeFileImpl(pFile);
+
+ if( FileName)
+ rtl_uString_release( FileName);
+
+ return pProfile;
+}
+
+sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
+
+
+ if ( Profile == nullptr )
+ {
+ return false;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ pProfile = acquireProfile(Profile,true);
+
+ if ( pProfile != nullptr )
+ {
+ if ( !( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
+ {
+ storeProfile(pProfile, false);
+ }
+ }
+ else
+ {
+ pProfile = acquireProfile(Profile,false);
+ }
+
+ if ( pProfile == nullptr )
+ {
+ return false;
+ }
+
+ if (pProfile->m_pFile != nullptr)
+ closeFileImpl(pProfile->m_pFile);
+ }
+
+ pProfile->m_pFile = nullptr;
+ rtl_uString_release(pProfile->m_strFileName);
+ pProfile->m_strFileName = nullptr;
+
+ /* release whole profile data types memory */
+ if ( pProfile->m_NoLines > 0)
+ {
+ unsigned int index=0;
+ if ( pProfile->m_Lines != nullptr )
+ {
+ for ( index = 0 ; index < pProfile->m_NoLines ; ++index)
+ {
+ if ( pProfile->m_Lines[index] != nullptr )
+ {
+ free(pProfile->m_Lines[index]);
+ }
+ }
+ free(pProfile->m_Lines);
+ }
+ if ( pProfile->m_Sections != nullptr )
+ {
+ for ( index = 0 ; index < pProfile->m_NoSections ; ++index )
+ {
+ if ( pProfile->m_Sections[index].m_Entries != nullptr )
+ free(pProfile->m_Sections[index].m_Entries);
+ }
+ free(pProfile->m_Sections);
+ }
+
+ }
+ free(pProfile);
+
+ return true;
+}
+
+sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
+ osl_TFile* pFile;
+ bool bRet = false;
+
+
+ if ( pProfile == nullptr )
+ {
+ return false;
+ }
+
+ pFile = pProfile->m_pFile;
+ if ( pFile == nullptr || pFile->m_Handle == INVALID_HANDLE_VALUE )
+ {
+ return false;
+ }
+
+ if ( pProfile->m_Flags & FLG_MODIFIED )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "swapping to storeprofile");
+#endif
+ bRet = storeProfile(pProfile,false);
+ }
+
+ return bRet;
+}
+
+static bool writeProfileImpl(osl_TFile* pFile)
+{
+ DWORD BytesWritten=0;
+ bool bRet;
+
+ if ( pFile == nullptr || pFile->m_Handle == INVALID_HANDLE_VALUE || ( pFile->m_pWriteBuf == nullptr ) )
+ {
+ return false;
+ }
+
+ bRet=WriteFile(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree,&BytesWritten,nullptr);
+
+ if ( !bRet || BytesWritten == 0 )
+ {
+ OSL_ENSURE(bRet,"WriteFile failed!!!");
+ SAL_WARN("sal.osl", "write failed " << strerror(errno));
+
+ return false;
+ }
+
+ free(pFile->m_pWriteBuf);
+ pFile->m_pWriteBuf=nullptr;
+ pFile->m_nWriteBufLen=0;
+ pFile->m_nWriteBufFree=0;
+
+ return true;
+}
+
+namespace {
+// Use Unicode version of GetPrivateProfileString, to work with Multi-language paths
+DWORD GetPrivateProfileStringWrapper(const osl_TProfileImpl* pProfile,
+ const char* pszSection, const char* pszEntry,
+ char* pszString, sal_uInt32 MaxLen,
+ const char* pszDefault)
+{
+ OSL_ASSERT(pProfile && (!MaxLen || pszString));
+
+ rtl_uString *pSection = nullptr, *pEntry = nullptr, *pDefault = nullptr;
+ if (pszSection)
+ {
+ rtl_string2UString(&pSection, pszSection, strlen(pszSection), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(pSection);
+ }
+ if (pszEntry)
+ {
+ rtl_string2UString(&pEntry, pszEntry, strlen(pszEntry), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(pEntry);
+ }
+ if (pszDefault)
+ {
+ rtl_string2UString(&pDefault, pszDefault, strlen(pszDefault), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(pDefault);
+ }
+
+ LPCWSTR pWSection = (pSection ? o3tl::toW(rtl_uString_getStr(pSection)) : nullptr),
+ pWEntry = (pEntry ? o3tl::toW(rtl_uString_getStr(pEntry)) : nullptr),
+ pWDefault = (pDefault ? o3tl::toW(rtl_uString_getStr(pDefault)) : nullptr);
+
+ std::vector<wchar_t> aBuf(MaxLen + 1);
+ GetPrivateProfileStringW(pWSection, pWEntry, pWDefault, aBuf.data(), MaxLen, o3tl::toW(rtl_uString_getStr(pProfile->m_strFileName)));
+
+ if (pDefault)
+ rtl_uString_release(pDefault);
+ if (pEntry)
+ rtl_uString_release(pEntry);
+ if (pSection)
+ rtl_uString_release(pSection);
+
+ return WideCharToMultiByte(CP_ACP, 0, aBuf.data(), -1, pszString, MaxLen, nullptr, nullptr);
+}
+
+// Use Unicode version of WritePrivateProfileString, to work with Multi-language paths
+bool WritePrivateProfileStringWrapper(const osl_TProfileImpl* pProfile,
+ const char* pszSection, const char* pszEntry,
+ const char* pszString)
+{
+ OSL_ASSERT(pProfile && pszSection);
+ rtl_uString *pSection, *pEntry = nullptr, *pString = nullptr;
+ rtl_string2UString(&pSection, pszSection, strlen(pszSection), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(pSection);
+ if (pszEntry)
+ {
+ rtl_string2UString(&pEntry, pszEntry, strlen(pszEntry), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(pEntry);
+ }
+ if (pszString)
+ {
+ rtl_string2UString(&pString, pszString, strlen(pszString), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(pString);
+ }
+
+ LPCWSTR pWSection = o3tl::toW(pSection->buffer),
+ pWEntry = (pEntry ? o3tl::toW(rtl_uString_getStr(pEntry)) : nullptr),
+ pWString = (pString ? o3tl::toW(rtl_uString_getStr(pString)) : nullptr);
+
+ bool bResult = WritePrivateProfileStringW(pWSection, pWEntry, pWString, o3tl::toW(rtl_uString_getStr(pProfile->m_strFileName)));
+
+ if (pString)
+ rtl_uString_release(pString);
+ if (pEntry)
+ rtl_uString_release(pEntry);
+ rtl_uString_release(pSection);
+
+ return bResult;
+}
+}
+
+sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
+ const char* pszSection, const char* pszEntry,
+ char* pszString, sal_uInt32 MaxLen,
+ const char* pszDefault)
+{
+ sal_uInt32 NoEntry;
+ const char* pStr = nullptr;
+ osl_TProfileImpl* pProfile = nullptr;
+
+ pProfile = acquireProfile(Profile, false);
+
+ if (pProfile == nullptr)
+ {
+ return false;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ osl_TProfileSection* pSec;
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != nullptr) &&
+ (NoEntry < pSec->m_NoEntries) &&
+ ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
+ '=')) != nullptr))
+ pStr++;
+ else
+ pStr = pszDefault;
+
+ if ( pStr != nullptr )
+ {
+ pStr = stripBlanks(pStr, nullptr);
+ MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
+ pStr = stripBlanks(pStr, &MaxLen);
+ strncpy(pszString, pStr, MaxLen);
+ pszString[MaxLen] = '\0';
+ }
+ }
+ else
+ {
+ if (GetPrivateProfileStringWrapper(pProfile, pszSection, pszEntry, pszString, MaxLen, pszDefault) > 0)
+ pStr = pszString; // required to return true below
+ }
+
+ releaseProfile(pProfile);
+
+ if ( pStr == nullptr )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
+ const char* pszSection, const char* pszEntry,
+ sal_Bool Default)
+{
+ char Line[32];
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ if ((stricmp(Line, STR_INI_BOOLYES) == 0) ||
+ (stricmp(Line, STR_INI_BOOLON) == 0) ||
+ (stricmp(Line, STR_INI_BOOLONE) == 0))
+ Default = true;
+ else
+ if ((stricmp(Line, STR_INI_BOOLNO) == 0) ||
+ (stricmp(Line, STR_INI_BOOLOFF) == 0) ||
+ (stricmp(Line, STR_INI_BOOLZERO) == 0))
+ Default = false;
+ }
+
+ return Default;
+}
+
+sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
+ const char* pszSection, const char* pszEntry,
+ sal_uInt32 FirstId, const char* Strings[],
+ sal_uInt32 Default)
+{
+ sal_uInt32 i;
+ char Line[256];
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ i = 0;
+ while (Strings[i] != nullptr)
+ {
+ if (stricmp(Line, Strings[i]) == 0)
+ {
+ Default = i + FirstId;
+ break;
+ }
+ i++;
+ }
+ }
+
+ return Default;
+}
+
+sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
+ const char* pszSection, const char* pszEntry,
+ const char* pszString)
+{
+ sal_uInt32 i;
+ bool bRet = false;
+ sal_uInt32 NoEntry;
+ const char* pStr;
+ char Line[4096];
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = nullptr;
+
+ pProfile = acquireProfile(Profile, true);
+
+ if (pProfile == nullptr)
+ {
+ return false;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == nullptr)
+ {
+ Line[0] = '\0';
+ addLine(pProfile, Line);
+
+ Line[0] = '[';
+ strcpy(&Line[1], pszSection);
+ Line[1 + strlen(pszSection)] = ']';
+ Line[2 + strlen(pszSection)] = '\0';
+
+ if (((pStr = addLine(pProfile, Line)) == nullptr) ||
+ (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
+ {
+ releaseProfile(pProfile);
+ return false;
+ }
+
+ pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
+ NoEntry = pSec->m_NoEntries;
+ }
+
+ Line[0] = '\0';
+ strcpy(&Line[0], pszEntry);
+ Line[0 + strlen(pszEntry)] = '=';
+ strcpy(&Line[1 + strlen(pszEntry)], pszString);
+
+ if (NoEntry >= pSec->m_NoEntries)
+ {
+ if (pSec->m_NoEntries > 0)
+ i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
+ else
+ i = pSec->m_Line + 1;
+
+ if (((pStr = insertLine(pProfile, Line, i)) == nullptr) ||
+ (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
+ {
+ releaseProfile(pProfile);
+ return false;
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ else
+ {
+ i = pSec->m_Entries[NoEntry].m_Line;
+ free(pProfile->m_Lines[i]);
+ pProfile->m_Lines[i] = strdup(Line);
+ setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ {
+ WritePrivateProfileStringWrapper(pProfile, pszSection, pszEntry, pszString);
+ }
+
+ bRet = releaseProfile(pProfile);
+ return bRet;
+}
+
+sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
+ const char* pszSection, const char* pszEntry,
+ sal_Bool Value)
+{
+ bool bRet = false;
+
+ if (Value)
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
+
+ return bRet;
+}
+
+sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
+ const char* pszSection, const char* pszEntry,
+ sal_uInt32 FirstId, const char* Strings[],
+ sal_uInt32 Value)
+{
+ int i, n;
+ bool bRet = false;
+
+ for (n = 0; Strings[n] != nullptr; n++);
+
+ if ((i = Value - FirstId) >= n)
+ bRet=false;
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
+
+ return bRet;
+}
+
+sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
+ const char *pszSection, const char *pszEntry)
+{
+ sal_uInt32 NoEntry;
+ osl_TProfileImpl* pProfile = nullptr;
+ bool bRet = false;
+
+ pProfile = acquireProfile(Profile, true);
+
+ if (pProfile == nullptr)
+ return false;
+
+ if (!(pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ osl_TProfileSection* pSec;
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != nullptr) &&
+ (NoEntry < pSec->m_NoEntries))
+ {
+ removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
+ removeEntry(pSec, NoEntry);
+ if (pSec->m_NoEntries == 0)
+ {
+ removeLine(pProfile, pSec->m_Line);
+
+ /* remove any empty separation line */
+ if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
+ removeLine(pProfile, pSec->m_Line - 1);
+
+ removeSection(pProfile, pSec);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ {
+ WritePrivateProfileStringWrapper(pProfile, pszSection, pszEntry, nullptr);
+ }
+
+ bRet = releaseProfile(pProfile);
+ return bRet;
+}
+
+sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const char *pszSection,
+ char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ sal_uInt32 NoEntry;
+ osl_TProfileImpl* pProfile = nullptr;
+
+ pProfile = acquireProfile(Profile, false);
+
+ if (pProfile == nullptr)
+ return 0;
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ osl_TProfileSection* pSec;
+ if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != nullptr)
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
+ n += pSec->m_Entries[i].m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ break;
+ }
+
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ n += pSec->m_Entries[i].m_Len + 1;
+ }
+
+ n += 1;
+ }
+ }
+ else
+ {
+ n = 0;
+ }
+ }
+ else
+ {
+ n = GetPrivateProfileStringWrapper(pProfile, pszSection, nullptr, pszBuffer, MaxLen, nullptr);
+ }
+
+ releaseProfile(pProfile);
+
+ return n;
+}
+
+bool osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName)
+{
+ bool bFailed;
+ ::osl::LongPathBuffer< sal_Unicode > aFile( MAX_LONG_PATH );
+ ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
+ sal_uInt32 nFileLen = 0;
+ sal_uInt32 nPathLen = 0;
+
+ rtl_uString * strTmp = nullptr;
+ oslFileError nError;
+
+ /* build file name */
+ if (strName && strName->length)
+ {
+ if( ::sal::static_int_cast< sal_uInt32 >( strName->length ) >= aFile.getBufSizeInSymbols() )
+ return false;
+
+ copy_ustr_n( aFile, strName->buffer, strName->length+1);
+ nFileLen = strName->length;
+
+ if (rtl_ustr_indexOfChar( aFile, L'.' ) == -1)
+ {
+ if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
+ return false;
+
+ /* add default extension */
+ copy_ustr_n( aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1 );
+ nFileLen += wcslen(STR_INI_EXTENSION);
+ }
+ }
+ else
+ {
+ rtl_uString *strProgName = nullptr;
+ sal_Unicode *pProgName;
+ sal_Int32 nOffset = 0;
+ sal_Int32 nLen;
+ sal_Int32 nPos;
+
+ if (osl_getExecutableFile(&strProgName) != osl_Process_E_None)
+ return false;
+
+ /* remove path and extension from filename */
+ pProgName = strProgName->buffer;
+ nLen = strProgName->length ;
+
+ if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'/' )) != -1)
+ nOffset = nPos + 1;
+ else if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L':' )) != -1)
+ nOffset = nPos + 1;
+
+ if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'.' )) != -1 )
+ nLen -= 4;
+
+ if ((nFileLen = nLen - nOffset) >= aFile.getBufSizeInSymbols())
+ return false;
+
+ copy_ustr_n(aFile, pProgName + nOffset, nFileLen);
+
+ if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
+ return false;
+
+ /* add default extension */
+ copy_ustr_n(aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1);
+ nFileLen += wcslen(STR_INI_EXTENSION);
+
+ rtl_uString_release( strProgName );
+ }
+
+ if (aFile[0] == 0)
+ return false;
+
+ /* build directory path */
+ if (strPath && strPath->length)
+ {
+ sal_Unicode *pPath = rtl_uString_getStr(strPath);
+ sal_Int32 nLen = rtl_uString_getLength(strPath);
+
+ if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAHOME) , STR_INI_METAHOME) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)] == '/')))
+ {
+ rtl_uString * strHome = nullptr;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getHomeDir(security, &strHome);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return false;
+
+ if ( ::sal::static_int_cast< sal_uInt32 >( strHome->length ) >= aPath.getBufSizeInSymbols())
+ return false;
+
+ copy_ustr_n( aPath, strHome->buffer, strHome->length+1);
+ nPathLen = strHome->length;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METAHOME))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return false;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+
+ rtl_uString_release(strHome);
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METACFG), STR_INI_METACFG) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METACFG)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METACFG)] == '/')))
+ {
+ rtl_uString * strConfig = nullptr;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getConfigDir(security, &strConfig);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return false;
+
+ if ( ::sal::static_int_cast< sal_uInt32 >( strConfig->length ) >= aPath.getBufSizeInSymbols())
+ return false;
+
+ copy_ustr_n( aPath, strConfig->buffer, strConfig->length+1 );
+ nPathLen = strConfig->length;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METACFG))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return false;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+
+ rtl_uString_release(strConfig);
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METASYS), STR_INI_METASYS) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METASYS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METASYS)] == '/')))
+ {
+ if (((nPathLen = GetWindowsDirectoryW(o3tl::toW(aPath), aPath.getBufSizeInSymbols())) == 0) || (nPathLen >= aPath.getBufSizeInSymbols()))
+ return false;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METASYS))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return false;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAINS), STR_INI_METAINS) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAINS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '/') ||
+ (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '"') ) )
+ {
+ if (! lookupProfile(pPath + RTL_CONSTASCII_LENGTH(STR_INI_METAINS), aFile, aPath))
+ return false;
+
+ nPathLen = rtl_ustr_getLength(aPath);
+ }
+
+ else if( ::sal::static_int_cast< sal_uInt32 >( nLen ) < aPath.getBufSizeInSymbols())
+ {
+ copy_ustr_n(aPath, pPath, nLen+1);
+ nPathLen = rtl_ustr_getLength(aPath);
+ }
+ else
+ return false;
+ }
+ else
+ {
+ rtl_uString * strConfigDir = nullptr;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getConfigDir(security, &strConfigDir);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return false;
+ if ( ::sal::static_int_cast< sal_uInt32 >( strConfigDir->length ) >= aPath.getBufSizeInSymbols() )
+ return false;
+
+ copy_ustr_n(aPath, strConfigDir->buffer, strConfigDir->length+1);
+ nPathLen = strConfigDir->length;
+ }
+
+ if (nPathLen && (aPath[nPathLen - 1] != L'/') && (aPath[nPathLen - 1] != L'\\'))
+ {
+ aPath[nPathLen++] = L'\\';
+ aPath[nPathLen] = 0;
+ }
+
+ if (nPathLen + nFileLen >= aPath.getBufSizeInSymbols())
+ return false;
+
+ /* append file name */
+ copy_ustr_n(aPath + nPathLen, aFile, nFileLen+1);
+ nPathLen += nFileLen;
+
+ /* copy filename */
+ rtl_uString_newFromStr_WithLength(&strTmp, aPath, nPathLen);
+ nError = osl_getFileURLFromSystemPath(strTmp, strProfileName);
+ rtl_uString_release(strTmp);
+
+ return nError == osl_File_E_None;
+}
+
+sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ osl_TProfileImpl* pProfile = acquireProfile(Profile, false);
+
+ if (pProfile == nullptr)
+ return 0;
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ osl_TProfileSection* pSec = &pProfile->m_Sections[i];
+
+ if ((n + pSec->m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
+ pSec->m_Len);
+ n += pSec->m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ n += pProfile->m_Sections[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ {
+ std::vector<wchar_t> aBuf(MaxLen + 1);
+ GetPrivateProfileSectionNamesW(aBuf.data(), MaxLen, o3tl::toW(rtl_uString_getStr(pProfile->m_strFileName)));
+
+ n = WideCharToMultiByte(CP_ACP, 0, aBuf.data(), -1, pszBuffer, MaxLen, nullptr, nullptr);
+ }
+
+ releaseProfile(pProfile);
+
+ return n;
+}
+
+static osl_TStamp getFileStamp(osl_TFile* pFile)
+{
+ FILETIME FileTime;
+
+ if ((pFile->m_Handle == INVALID_HANDLE_VALUE) ||
+ (! GetFileTime(pFile->m_Handle, nullptr, nullptr, &FileTime)))
+ memset(&FileTime, 0, sizeof(FileTime));
+
+ return FileTime;
+}
+
+static bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
+{
+ bool status = false;
+ OVERLAPPED Overlapped = {};
+
+ if (pFile->m_Handle == INVALID_HANDLE_VALUE)
+ return false;
+
+ switch (eMode)
+ {
+ case un_lock:
+ status = UnlockFileEx(
+ pFile->m_Handle, 0, 0xFFFFFFFF, 0, &Overlapped);
+ break;
+
+ case read_lock:
+ status = LockFileEx(
+ pFile->m_Handle, 0, 0, 0xFFFFFFFF, 0, &Overlapped);
+ break;
+
+ case write_lock:
+ status = LockFileEx(
+ pFile->m_Handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 0xFFFFFFFF, 0,
+ &Overlapped);
+ break;
+ }
+
+ return status;
+}
+
+static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags )
+{
+ osl_TFile* pFile = static_cast< osl_TFile*>( calloc( 1, sizeof(osl_TFile) ) );
+ if (!pFile)
+ return nullptr;
+ bool bWriteable = false;
+
+ if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "setting bWriteable to TRUE");
+#endif
+ bWriteable=true;
+ }
+
+ if (! bWriteable)
+ {
+ pFile->m_Handle = CreateFileW( o3tl::toW(rtl_uString_getStr( strFileName )), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+
+ /* mfe: argghh!!! do not check if the file could be opened */
+ /* default mode expects it that way!!! */
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "opening read/write " << pszFilename);
+#endif
+
+ if ((pFile->m_Handle = CreateFileW( o3tl::toW(rtl_uString_getStr( strFileName )), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr))
+ == INVALID_HANDLE_VALUE)
+ {
+ free(pFile);
+ return nullptr;
+ }
+ }
+
+ pFile->m_pWriteBuf=nullptr;
+ pFile->m_nWriteBufFree=0;
+ pFile->m_nWriteBufLen=0;
+
+ if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "locking file " << pszFilename);
+#endif
+
+ lockFile(pFile, bWriteable ? write_lock : read_lock);
+ }
+
+ return pFile;
+}
+
+static osl_TStamp closeFileImpl(osl_TFile* pFile)
+{
+ osl_TStamp stamp = {0, 0};
+
+ if ( pFile == nullptr )
+ {
+ return stamp;
+ }
+
+ if (pFile->m_Handle != INVALID_HANDLE_VALUE)
+ {
+ stamp = getFileStamp(pFile);
+
+ lockFile(pFile, un_lock);
+
+ CloseHandle(pFile->m_Handle);
+ pFile->m_Handle = INVALID_HANDLE_VALUE;
+ }
+
+ if ( pFile->m_pWriteBuf != nullptr )
+ {
+ free(pFile->m_pWriteBuf);
+ }
+
+ free(pFile);
+
+ return stamp;
+}
+
+static bool rewindFile(osl_TFile* pFile, bool bTruncate)
+{
+ if (pFile->m_Handle != INVALID_HANDLE_VALUE)
+ {
+ pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ SetFilePointer(pFile->m_Handle, 0, nullptr, FILE_BEGIN);
+
+ if (bTruncate)
+ SetEndOfFile(pFile->m_Handle);
+ }
+
+ return true;
+}
+
+static bool getLine(osl_TFile* pFile, char *pszLine, int MaxLen)
+{
+ DWORD Max;
+ size_t Free;
+ char* pChr;
+ char* pLine = pszLine;
+
+ if (pFile->m_Handle == INVALID_HANDLE_VALUE)
+ return false;
+
+ MaxLen -= 1;
+
+ do
+ {
+ size_t Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
+
+ if (Bytes <= 1)
+ {
+ /* refill buffer */
+ memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
+ pFile->m_pReadPtr = pFile->m_ReadBuf;
+
+ Free = sizeof(pFile->m_ReadBuf) - Bytes;
+
+ if (! ReadFile(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free, &Max, nullptr))
+ {
+ *pLine = '\0';
+ return false;
+ }
+
+ if (Max < Free)
+ {
+ if ((Max == 0) && (pLine == pszLine))
+ {
+ *pLine = '\0';
+ return false;
+ }
+
+ pFile->m_ReadBuf[Bytes + Max] = '\0';
+ }
+ }
+
+ for (pChr = pFile->m_pReadPtr;
+ (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
+ (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
+ pChr++);
+
+ Max = min(static_cast<int>(pChr - pFile->m_pReadPtr), MaxLen);
+ memcpy(pLine, pFile->m_pReadPtr, Max);
+ MaxLen -= Max;
+ pLine += Max;
+
+ if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
+ {
+ if (*pChr != '\0')
+ {
+ if ((pChr[0] == '\r') && (pChr[1] == '\n'))
+ pChr += 2;
+ else
+ pChr += 1;
+ }
+
+ if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
+ (*pChr == '\0'))
+ pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ *pLine = '\0';
+
+ /* setting MaxLen to -1 indicates terminating read loop */
+ MaxLen = -1;
+ }
+
+ pFile->m_pReadPtr = pChr;
+ }
+ while (MaxLen > 0);
+
+ return true;
+}
+
+static bool putLine(osl_TFile* pFile, const char *pszLine)
+{
+ unsigned int Len = strlen(pszLine);
+
+ if ( pFile == nullptr || pFile->m_Handle == INVALID_HANDLE_VALUE )
+ {
+ return false;
+ }
+
+ if ( pFile->m_pWriteBuf == nullptr )
+ {
+ pFile->m_pWriteBuf = static_cast<char*>(malloc(Len+3));
+ pFile->m_nWriteBufLen = Len+3;
+ pFile->m_nWriteBufFree = Len+3;
+ }
+ else
+ {
+ if ( pFile->m_nWriteBufFree <= Len + 3 )
+ {
+ char* pTmp;
+
+ pTmp=static_cast<char*>(realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) ));
+ if ( pTmp == nullptr )
+ {
+ return false;
+ }
+ pFile->m_pWriteBuf = pTmp;
+ pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
+ pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
+ memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
+ }
+ }
+
+ memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
+
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\r';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\n';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 2]='\0';
+
+ pFile->m_nWriteBufFree-=Len+2;
+
+ return true;
+}
+
+/* platform specific end */
+
+static const char* stripBlanks(const char* String, sal_uInt32* pLen)
+{
+ if ( (pLen != nullptr) && ( *pLen != 0 ) )
+ {
+ while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
+ (*pLen)--;
+
+ while ((*String == ' ') || (*String == '\t'))
+ {
+ String++;
+ (*pLen)--;
+ }
+ }
+ else
+ while ((*String == ' ') || (*String == '\t'))
+ String++;
+
+ return String;
+}
+
+static const char* addLine(osl_TProfileImpl* pProfile, const char* Line)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == nullptr)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = static_cast<char **>(calloc(pProfile->m_MaxLines, sizeof(char *)));
+ }
+ else
+ {
+ unsigned int index=0;
+ unsigned int oldmax=pProfile->m_MaxLines;
+
+ pProfile->m_MaxLines += LINES_ADD;
+ if (auto p = static_cast<char **>(realloc(pProfile->m_Lines, pProfile->m_MaxLines * sizeof(char *))))
+ {
+ pProfile->m_Lines = p;
+
+ for ( index = oldmax ; index < pProfile->m_MaxLines ; ++index )
+ {
+ pProfile->m_Lines[index]=nullptr;
+ }
+ }
+ else
+ {
+ free(pProfile->m_Lines);
+ pProfile->m_Lines = nullptr;
+ }
+ }
+
+ if (pProfile->m_Lines == nullptr)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return nullptr;
+ }
+
+ }
+
+ if ( pProfile->m_Lines != nullptr && pProfile->m_Lines[pProfile->m_NoLines] != nullptr )
+ {
+ free(pProfile->m_Lines[pProfile->m_NoLines]);
+ }
+ pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
+
+ return pProfile->m_Lines[pProfile->m_NoLines - 1];
+}
+
+static const char* insertLine(osl_TProfileImpl* pProfile, const char* Line, sal_uInt32 LineNo)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == nullptr)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = static_cast<char **>(calloc(pProfile->m_MaxLines, sizeof(char *)));
+ }
+ else
+ {
+ pProfile->m_MaxLines += LINES_ADD;
+ if (auto p = static_cast<char**>(
+ realloc(pProfile->m_Lines, pProfile->m_MaxLines * sizeof(char*))))
+ {
+ pProfile->m_Lines = p;
+
+ memset(&pProfile->m_Lines[pProfile->m_NoLines], 0,
+ (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(char*));
+ }
+ else
+ {
+ free(pProfile->m_Lines);
+ pProfile->m_Lines = nullptr;
+ }
+ }
+
+ if (pProfile->m_Lines == nullptr)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return nullptr;
+ }
+ }
+
+ LineNo = std::min(LineNo, pProfile->m_NoLines);
+
+ if (LineNo < pProfile->m_NoLines)
+ {
+ sal_uInt32 i, n;
+
+ memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
+ (pProfile->m_NoLines - LineNo) * sizeof(char *));
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ osl_TProfileSection* pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line >= LineNo)
+ pSec->m_Line++;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line >= LineNo)
+ pSec->m_Entries[n].m_Line++;
+ }
+ }
+
+ pProfile->m_NoLines++;
+
+ pProfile->m_Lines[LineNo] = strdup(Line);
+
+ return pProfile->m_Lines[LineNo];
+}
+
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
+{
+ if (LineNo < pProfile->m_NoLines)
+ {
+ free(pProfile->m_Lines[LineNo]);
+ pProfile->m_Lines[LineNo]=nullptr;
+ if (pProfile->m_NoLines - LineNo > 1)
+ {
+ sal_uInt32 i, n;
+
+ memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
+ (pProfile->m_NoLines - LineNo - 1) * sizeof(char *));
+
+ memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
+ 0,
+ (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(char*));
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ osl_TProfileSection* pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line > LineNo)
+ pSec->m_Line--;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line > LineNo)
+ pSec->m_Entries[n].m_Line--;
+ }
+ }
+ else
+ {
+ pProfile->m_Lines[LineNo] = nullptr;
+ }
+
+ pProfile->m_NoLines--;
+ }
+
+ return;
+}
+
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ const char* Entry, sal_uInt32 Len)
+{
+ Entry = stripBlanks(Entry, &Len);
+ pSection->m_Entries[NoEntry].m_Line = Line;
+ pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
+ pSection->m_Entries[NoEntry].m_Len = Len;
+
+ return;
+}
+
+static bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, const char* Entry, sal_uInt32 Len)
+{
+ if (pSection != nullptr)
+ {
+ if (pSection->m_NoEntries >= pSection->m_MaxEntries)
+ {
+ if (pSection->m_Entries == nullptr)
+ {
+ pSection->m_MaxEntries = ENTRIES_INI;
+ pSection->m_Entries = static_cast<osl_TProfileEntry *>(malloc(
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry)));
+ }
+ else
+ {
+ pSection->m_MaxEntries += ENTRIES_ADD;
+ if (auto p = static_cast<osl_TProfileEntry*>(realloc(
+ pSection->m_Entries, pSection->m_MaxEntries * sizeof(osl_TProfileEntry))))
+ pSection->m_Entries = p;
+ else
+ {
+ free(pSection->m_Entries);
+ pSection->m_Entries = nullptr;
+ }
+ }
+
+ if (pSection->m_Entries == nullptr)
+ {
+ pSection->m_NoEntries = 0;
+ pSection->m_MaxEntries = 0;
+ return false;
+ }
+ }
+
+ pSection->m_NoEntries++;
+
+ Entry = stripBlanks(Entry, &Len);
+ setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
+ Entry, Len);
+
+ return true;
+ }
+
+ return false;
+}
+
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
+{
+ if (NoEntry < pSection->m_NoEntries)
+ {
+ if (pSection->m_NoEntries - NoEntry > 1)
+ {
+ memmove(&pSection->m_Entries[NoEntry],
+ &pSection->m_Entries[NoEntry + 1],
+ (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
+ }
+
+ pSection->m_NoEntries--;
+ }
+
+ return;
+}
+
+static bool addSection(osl_TProfileImpl* pProfile, int Line, const char* Section, sal_uInt32 Len)
+{
+ if (pProfile->m_NoSections >= pProfile->m_MaxSections)
+ {
+ if (pProfile->m_Sections == nullptr)
+ {
+ pProfile->m_MaxSections = SECTIONS_INI;
+ pProfile->m_Sections = static_cast<osl_TProfileSection*>(calloc(pProfile->m_MaxSections, sizeof(osl_TProfileSection)));
+ }
+ else
+ {
+ unsigned int index=0;
+ unsigned int oldmax=pProfile->m_MaxSections;
+
+ pProfile->m_MaxSections += SECTIONS_ADD;
+ if (auto p = static_cast<osl_TProfileSection*>(realloc(
+ pProfile->m_Sections, pProfile->m_MaxSections * sizeof(osl_TProfileSection))))
+ {
+ pProfile->m_Sections = p;
+ for ( index = oldmax ; index < pProfile->m_MaxSections ; ++index )
+ {
+ pProfile->m_Sections[index].m_Entries=nullptr;
+ }
+ }
+ else
+ {
+ free(pProfile->m_Sections);
+ pProfile->m_Sections = nullptr;
+ }
+ }
+
+ if (pProfile->m_Sections == nullptr)
+ {
+ pProfile->m_NoSections = 0;
+ pProfile->m_MaxSections = 0;
+ return false;
+ }
+ }
+
+ pProfile->m_NoSections++;
+
+ if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != nullptr )
+ {
+ free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
+ }
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = nullptr;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
+
+ Section = stripBlanks(Section, &Len);
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
+
+ return true;
+}
+
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
+{
+ sal_uInt32 Section;
+
+ if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
+ {
+ free (pSection->m_Entries);
+ pSection->m_Entries=nullptr;
+ if (pProfile->m_NoSections - Section > 1)
+ {
+ memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
+ (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
+
+ memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
+ 0,
+ (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = nullptr;
+ }
+ else
+ {
+ pSection->m_Entries = nullptr;
+ }
+
+ pProfile->m_NoSections--;
+ }
+
+ return;
+}
+
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const char* Section,
+ const char* Entry, sal_uInt32 *pNoEntry)
+{
+ static sal_uInt32 Sect = 0;
+ sal_uInt32 i, n;
+ sal_uInt32 Len;
+ osl_TProfileSection* pSec = nullptr;
+
+ Len = strlen(Section);
+ Section = stripBlanks(Section, &Len);
+
+ n = Sect;
+
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ n %= pProfile->m_NoSections;
+ pSec = &pProfile->m_Sections[n];
+ if ((Len == pSec->m_Len) &&
+ (strnicmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
+ == 0))
+ break;
+ n++;
+ }
+
+ Sect = n;
+
+ if (i < pProfile->m_NoSections)
+ {
+ Len = strlen(Entry);
+ Entry = stripBlanks(Entry, &Len);
+
+ *pNoEntry = pSec->m_NoEntries;
+
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ const char* pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset];
+ if ((Len == pSec->m_Entries[i].m_Len) &&
+ (strnicmp(Entry, pStr, pSec->m_Entries[i].m_Len)
+ == 0))
+ {
+ *pNoEntry = i;
+ break;
+ }
+ }
+ }
+ else
+ pSec = nullptr;
+
+ return pSec;
+}
+
+static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
+{
+ sal_uInt32 i;
+ char const * pStr;
+ char const * pChar;
+ char Line[4096];
+
+ pProfile->m_NoLines = 0;
+ pProfile->m_NoSections = 0;
+
+ OSL_VERIFY(rewindFile(pFile, false));
+
+ while (getLine(pFile, Line, sizeof(Line)))
+ {
+ if (! addLine(pProfile, Line))
+ return false;
+ }
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ {
+ pStr = stripBlanks(pProfile->m_Lines[i], nullptr);
+
+ if ((*pStr == '\0') || (*pStr == ';'))
+ continue;
+
+ if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == nullptr) ||
+ ((pChar - pStr) <= 2))
+ {
+ /* insert entry */
+
+ if (pProfile->m_NoSections < 1)
+ continue;
+
+ if ((pChar = strchr(pStr, '=')) == nullptr)
+ pChar = pStr + strlen(pStr);
+
+ if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
+ i, pStr, pChar - pStr))
+ return false;
+ }
+ else
+ {
+ /* new section */
+ if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup)
+{
+ if (pProfile->m_Lines != nullptr)
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ {
+ sal_uInt32 i;
+
+ osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
+
+ if ( pTmpFile == nullptr )
+ {
+ return false;
+ }
+
+ OSL_VERIFY(rewindFile(pTmpFile, true));
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ {
+ OSL_VERIFY(putLine(pTmpFile, pProfile->m_Lines[i]));
+ }
+
+ if ( ! writeProfileImpl(pTmpFile) )
+ {
+ if ( pTmpFile->m_pWriteBuf != nullptr )
+ {
+ free(pTmpFile->m_pWriteBuf);
+ }
+
+ pTmpFile->m_pWriteBuf=nullptr;
+ pTmpFile->m_nWriteBufLen=0;
+ pTmpFile->m_nWriteBufFree=0;
+
+ closeFileImpl(pTmpFile);
+
+ return false;
+ }
+
+ pProfile->m_Flags &= ~FLG_MODIFIED;
+
+ closeFileImpl(pProfile->m_pFile);
+ closeFileImpl(pTmpFile);
+
+ osl_ProfileSwapProfileNames(pProfile);
+
+ pProfile->m_pFile = openFileImpl(pProfile->m_strFileName,pProfile->m_Flags);
+
+ }
+
+ if (bCleanup)
+ {
+ while (pProfile->m_NoLines > 0)
+ removeLine(pProfile, pProfile->m_NoLines - 1);
+
+ free(pProfile->m_Lines);
+ pProfile->m_Lines = nullptr;
+ pProfile->m_MaxLines = 0;
+
+ while (pProfile->m_NoSections > 0)
+ removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
+
+ free(pProfile->m_Sections);
+ pProfile->m_Sections = nullptr;
+ pProfile->m_MaxSections = 0;
+ }
+ }
+
+ return true;
+}
+
+static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
+{
+ osl_TFile* pFile=nullptr;
+ rtl_uString* ustrExtension=nullptr;
+ rtl_uString* ustrTmpName=nullptr;
+ oslProfileOption PFlags=0;
+
+ rtl_uString_newFromAscii(&ustrExtension,"tmp");
+
+ /* generate tmp profilename */
+ ustrTmpName=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+
+ if (ustrTmpName == nullptr)
+ return nullptr;
+
+ if (!(pProfile->m_Flags & osl_Profile_READLOCK))
+ PFlags |= osl_Profile_WRITELOCK;
+
+ /* open this file */
+ pFile = openFileImpl(ustrTmpName,pProfile->m_Flags | PFlags);
+
+ /* return new pFile */
+ return pFile;
+}
+
+static bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
+{
+ rtl_uString* ustrBakFile=nullptr;
+ rtl_uString* ustrTmpFile=nullptr;
+ rtl_uString* ustrIniFile=nullptr;
+ rtl_uString* ustrExtension=nullptr;
+
+ rtl_uString_newFromAscii(&ustrExtension,"bak");
+
+ ustrBakFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=nullptr;
+
+ rtl_uString_newFromAscii(&ustrExtension,"ini");
+
+ ustrIniFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=nullptr;
+
+ rtl_uString_newFromAscii(&ustrExtension,"tmp");
+
+ ustrTmpFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=nullptr;
+
+ /* unlink bak */
+ DeleteFileW( o3tl::toW(rtl_uString_getStr( ustrBakFile )) );
+
+ /* rename ini bak */
+ MoveFileExW( o3tl::toW(rtl_uString_getStr( ustrIniFile )), o3tl::toW(rtl_uString_getStr( ustrBakFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
+
+ /* rename tmp ini */
+ MoveFileExW( o3tl::toW(rtl_uString_getStr( ustrTmpFile )), o3tl::toW(rtl_uString_getStr( ustrIniFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
+
+ return false;
+}
+
+static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension)
+{
+ rtl_uString* ustrNewFileName = nullptr;
+ rtl_uString* ustrOldExtension = nullptr;
+
+ sal_Unicode* pFileNameBuf = rtl_uString_getStr(ustrFileName);
+
+ rtl_uString_newFromAscii(&ustrOldExtension, ".");
+
+ sal_Unicode* pExtensionBuf = rtl_uString_getStr(ustrOldExtension);
+
+ sal_Int32 nIndex = rtl_ustr_lastIndexOfChar(pFileNameBuf, *pExtensionBuf);
+
+ rtl_uString_newReplaceStrAt(&ustrNewFileName,
+ ustrFileName,
+ nIndex+1,
+ 3,
+ ustrExtension);
+
+ return ustrNewFileName;
+}
+
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable)
+{
+ osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
+ oslProfileOption PFlags=0;
+
+ if ( bWriteable )
+ {
+ PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
+ }
+ else
+ {
+ PFlags = osl_Profile_DEFAULT;
+ }
+
+ if (pProfile == nullptr)
+ {
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "AUTOOPEN MODE");
+#endif
+
+ if ( ( pProfile = static_cast<osl_TProfileImpl*>(osl_openProfile( nullptr, PFlags )) ) != nullptr )
+ {
+ pProfile->m_Flags |= FLG_AUTOOPEN;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "try to acquire");
+#endif
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
+ osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
+ {
+ osl_TStamp Stamp;
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "DEFAULT MODE");
+#endif
+ pProfile->m_pFile = openFileImpl(
+ pProfile->m_strFileName, pProfile->m_Flags | PFlags);
+ if (!pProfile->m_pFile)
+ return nullptr;
+
+ Stamp = getFileStamp(pProfile->m_pFile);
+
+ if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
+ {
+ pProfile->m_Stamp = Stamp;
+
+ loadProfile(pProfile->m_pFile, pProfile);
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "READ/WRITELOCK MODE");
+#endif
+
+ /* A readlock file could not be written */
+ if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
+ {
+ return nullptr;
+ }
+ }
+ }
+ }
+
+ return pProfile;
+}
+
+static bool releaseProfile(osl_TProfileImpl* pProfile)
+{
+ if ( pProfile == nullptr )
+ {
+ return false;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (pProfile->m_Flags & FLG_AUTOOPEN)
+ {
+ return osl_closeProfile(static_cast<oslProfile>(pProfile));
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ SAL_INFO("sal.osl", "DEFAULT MODE");
+#endif
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
+ osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ storeProfile(pProfile, false);
+
+ closeFileImpl(pProfile->m_pFile);
+ pProfile->m_pFile = nullptr;
+ }
+ }
+ }
+
+ return true;
+}
+
+static bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile)
+{
+ char *pChr;
+ char Buffer[4096] = "";
+ char Product[132] = "";
+
+ ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
+ aPath[0] = 0;
+
+ if (*strPath == L'"')
+ {
+ int i = 0;
+
+ strPath++;
+
+ while ((strPath[i] != L'"') && (strPath[i] != L'\0'))
+ i++;
+
+ WideCharToMultiByte(CP_ACP,0, o3tl::toW(strPath), i, Product, sizeof(Product), nullptr, nullptr);
+ Product[i] = '\0';
+ strPath += i;
+
+ if (*strPath == L'"')
+ strPath++;
+
+ if ( (*strPath == L'/') || (*strPath == L'\\') )
+ {
+ strPath++;
+ }
+ }
+
+ else
+ {
+ /* if we have not product identification, do a special handling for soffice.ini */
+ if (rtl_ustr_ascii_compare(strFile, SVERSION_PROFILE) == 0)
+ {
+ rtl_uString * strSVProfile = nullptr;
+ rtl_uString * strSVFallback = nullptr;
+ rtl_uString * strSVLocation = nullptr;
+ rtl_uString * strSVName = nullptr;
+ ::osl::LongPathBuffer< char > aDir( MAX_LONG_PATH );
+ oslProfile hProfile;
+
+ rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
+ rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
+ rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
+
+ /* open sversion.ini in the system directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if (osl_getProfileName( strSVFallback, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_getProfileSectionEntries(
+ hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ {
+ if ((strnicmp(
+ pChr, SVERSION_SOFFICE,
+ sizeof(SVERSION_SOFFICE) - 1)
+ == 0)
+ && (stricmp(Product, pChr) < 0))
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, pChr, aDir,
+ aDir.getBufSizeInSymbols(), "");
+
+ /* check for existence of path */
+ if (access(aDir, 0) >= 0)
+ strcpy(Product, pChr);
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+ rtl_uString_release(strSVProfile);
+ strSVProfile = nullptr;
+ }
+
+ /* open sversion.ini in the users directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if ( osl_getProfileName(strSVLocation, strSVName, &strSVProfile) )
+ {
+ hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_getProfileSectionEntries(
+ hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ {
+ if ((strnicmp(
+ pChr, SVERSION_SOFFICE,
+ sizeof(SVERSION_SOFFICE) - 1)
+ == 0)
+ && (stricmp(Product, pChr) < 0))
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, pChr, aDir,
+ aDir.getBufSizeInSymbols(), "");
+
+ /* check for existence of path */
+ if (access(aDir, 0) >= 0)
+ strcpy(Product, pChr);
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+ rtl_uString_release(strSVProfile);
+ }
+
+ rtl_uString_release(strSVFallback);
+ rtl_uString_release(strSVLocation);
+ rtl_uString_release(strSVName);
+
+ /* remove any trailing build number */
+ if ((pChr = strrchr(Product, '/')) != nullptr)
+ *pChr = '\0';
+ }
+ }
+
+ rtl_uString * strExecutable = nullptr;
+ rtl_uString * strTmp = nullptr;
+ sal_Int32 nPos;
+
+ /* try to find the file in the directory of the executable */
+ if (osl_getExecutableFile(&strTmp) != osl_Process_E_None)
+ return false;
+
+ /* convert to native path */
+ if (osl_getSystemPathFromFileURL(strTmp, &strExecutable) != osl_File_E_None)
+ {
+ rtl_uString_release(strTmp);
+ return false;
+ }
+
+ rtl_uString_release(strTmp);
+
+ DWORD dwPathLen = 0;
+
+ /* separate path from filename */
+ if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L'\\')) == -1)
+ {
+ if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L':')) == -1)
+ {
+ rtl_uString_release(strExecutable);
+ return false;
+ }
+ else
+ {
+ copy_ustr_n(aPath, strExecutable->buffer, nPos);
+ aPath[nPos] = 0;
+ dwPathLen = nPos;
+ }
+ }
+ else
+ {
+ copy_ustr_n(aPath, strExecutable->buffer, nPos);
+ dwPathLen = nPos;
+ aPath[dwPathLen] = 0;
+ }
+
+ /* if we have no product identification use the executable file name */
+ if (*Product == 0)
+ {
+ WideCharToMultiByte(CP_ACP,0, o3tl::toW(strExecutable->buffer + nPos + 1), -1, Product, sizeof(Product), nullptr, nullptr);
+
+ /* remove extension */
+ if ((pChr = strrchr(Product, '.')) != nullptr)
+ *pChr = '\0';
+ }
+
+ rtl_uString_release(strExecutable);
+
+ /* remember last subdir */
+ nPos = rtl_ustr_lastIndexOfChar(aPath, L'\\');
+
+ copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
+
+ if (*strPath)
+ {
+ copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen += rtl_ustr_getLength(strPath);
+ }
+
+ {
+ ::osl::LongPathBuffer< char > aTmpPath( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, o3tl::toW(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), nullptr, nullptr);
+
+ /* if file not exists, remove any specified subdirectories
+ like "bin" or "program" */
+
+ if (((access(aTmpPath, 0) < 0) && (nPos != -1)) || (*strPath == 0))
+ {
+ static const char *SubDirs[] = SVERSION_DIRS;
+
+ unsigned i = 0;
+ char *pStr = aTmpPath + nPos;
+
+ for (i = 0; i < SAL_N_ELEMENTS(SubDirs); i++)
+ if (strnicmp(pStr + 1, SubDirs[i], strlen(SubDirs[i])) == 0)
+ {
+ if ( *strPath == 0)
+ {
+ strcpy(pStr + 1,SVERSION_USER);
+ if ( access(aTmpPath, 0) < 0 )
+ {
+ *(pStr+1)='\0';
+ }
+ else
+ {
+ dwPathLen = nPos + MultiByteToWideChar( CP_ACP, 0, SVERSION_USER, -1, o3tl::toW(aPath + nPos + 1), aPath.getBufSizeInSymbols() - (nPos + 1) );
+ }
+ }
+ else
+ {
+ copy_ustr_n(aPath + nPos + 1, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen = nPos + 1 + rtl_ustr_getLength(strPath);
+ }
+
+ break;
+ }
+ }
+ }
+
+ if ((aPath[dwPathLen - 1] != L'/') && (aPath[dwPathLen - 1] != L'\\'))
+ {
+ aPath[dwPathLen++] = L'\\';
+ aPath[dwPathLen] = 0;
+ }
+
+ copy_ustr_n(aPath + dwPathLen, strFile, rtl_ustr_getLength(strFile)+1);
+
+ {
+ ::osl::LongPathBuffer< char > aTmpPath( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, o3tl::toW(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), nullptr, nullptr);
+
+ if ((access(aTmpPath, 0) < 0) && (Product[0] != '\0'))
+ {
+ rtl_uString * strSVFallback = nullptr;
+ rtl_uString * strSVProfile = nullptr;
+ rtl_uString * strSVLocation = nullptr;
+ rtl_uString * strSVName = nullptr;
+ oslProfile hProfile;
+
+ rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
+ rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
+ rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
+
+ /* open sversion.ini in the system directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if (osl_getProfileName(strSVLocation, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(
+ strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, Product, Buffer,
+ sizeof(Buffer), "");
+ osl_closeProfile(hProfile);
+
+ /* if not found, try the fallback */
+ if (Buffer[0] == '\0')
+ {
+ if (osl_getProfileName(
+ strSVFallback, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(
+ strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, Product,
+ Buffer, sizeof(Buffer), "");
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+
+ if (Buffer[0] != '\0')
+ {
+ dwPathLen = MultiByteToWideChar(
+ CP_ACP, 0, Buffer, -1, o3tl::toW(aPath), aPath.getBufSizeInSymbols() );
+ dwPathLen -=1;
+
+ /* build full path */
+ if ((aPath[dwPathLen - 1] != L'/')
+ && (aPath[dwPathLen - 1] != L'\\'))
+ {
+ copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
+ }
+
+ if (*strPath)
+ {
+ copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen += rtl_ustr_getLength(strPath);
+ }
+ else
+ {
+ ::osl::LongPathBuffer< char > aTmpPath2( MAX_LONG_PATH );
+ int n;
+
+ if ((n = WideCharToMultiByte(
+ CP_ACP,0, o3tl::toW(aPath), -1, aTmpPath2,
+ aTmpPath2.getBufSizeInSymbols(), nullptr, nullptr))
+ > 0)
+ {
+ strcpy(aTmpPath2 + n, SVERSION_USER);
+ if (access(aTmpPath2, 0) >= 0)
+ {
+ dwPathLen += MultiByteToWideChar(
+ CP_ACP, 0, SVERSION_USER, -1,
+ o3tl::toW(aPath + dwPathLen),
+ aPath.getBufSizeInSymbols() - dwPathLen );
+ }
+ }
+ }
+ }
+ }
+
+ rtl_uString_release(strSVProfile);
+ }
+
+ rtl_uString_release(strSVFallback);
+ rtl_uString_release(strSVLocation);
+ rtl_uString_release(strSVName);
+ }
+ }
+
+ aPath[dwPathLen] = 0;
+
+ /* copy filename */
+ copy_ustr_n(strProfile, aPath, dwPathLen+1);
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */