Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  profile.cxx   Sprache: C

 
/* -*- 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 <systools/win32/extended_max_path.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)
{
    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)
{
    assert(pProfile && pszSection);
    rtl_uString *pSection, *pEntry = nullptr, *pString = nullptr;
    rtl_string2UString(&pSection, pszSection, strlen(pszSection), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
    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(EXTENDED_MAX_PATH);
    osl::LongPathBuffer<sal_Unicode> aPath(EXTENDED_MAX_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));
        assert(pFile->m_pWriteBuf && "Don't handle OOM conditions");
        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[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(EXTENDED_MAX_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(EXTENDED_MAX_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 */
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge