tdf#154546 skip dispatch when presenter controller is not set
[LibreOffice.git] / sal / osl / w32 / profile.cxx
bloba0790c3de6328105d4c15c24d401aefd68618433
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "system.h"
22 #include "file_url.hxx"
23 #include "path_helper.hxx"
25 #include <string.h>
26 #include <osl/diagnose.h>
27 #include <osl/profile.h>
28 #include <osl/process.h>
29 #include <osl/thread.h>
30 #include <osl/file.h>
31 #include <rtl/alloc.h>
32 #include <sal/macros.h>
33 #include <sal/log.hxx>
34 #include <o3tl/char16_t2wchar_t.hxx>
35 #include <algorithm>
36 #include <vector>
37 using std::min;
38 static void copy_ustr_n( void *dest, const void *source, size_t length ) { memcpy(dest, source, length*sizeof(sal_Unicode)); }
40 #define LINES_INI 32
41 #define LINES_ADD 10
42 #define SECTIONS_INI 5
43 #define SECTIONS_ADD 3
44 #define ENTRIES_INI 5
45 #define ENTRIES_ADD 3
47 #define STR_INI_EXTENSION L".ini"
48 #define STR_INI_METAHOME "?~"
49 #define STR_INI_METASYS "?$"
50 #define STR_INI_METACFG "?^"
51 #define STR_INI_METAINS "?#"
53 #define STR_INI_BOOLYES "yes"
54 #define STR_INI_BOOLON "on"
55 #define STR_INI_BOOLONE "1"
56 #define STR_INI_BOOLNO "no"
57 #define STR_INI_BOOLOFF "off"
58 #define STR_INI_BOOLZERO "0"
60 #define FLG_USER 0x00FF
61 #define FLG_AUTOOPEN 0x0100
62 #define FLG_MODIFIED 0x0200
64 #define SVERSION_LOCATION STR_INI_METACFG
65 #define SVERSION_FALLBACK STR_INI_METASYS
66 #define SVERSION_NAME "sversion"
67 #define SVERSION_SECTION "Versions"
68 #define SVERSION_SOFFICE "StarOffice"
69 #define SVERSION_PROFILE "soffice.ini"
70 #define SVERSION_DIRS { "bin", "program" }
71 #define SVERSION_USER "user"
73 /*#define DEBUG_OSL_PROFILE 1*/
75 typedef FILETIME osl_TStamp;
77 namespace {
79 enum osl_TLockMode
81 un_lock, read_lock, write_lock
84 struct osl_TFile
86 HANDLE m_Handle;
87 char* m_pReadPtr;
88 char m_ReadBuf[512];
89 char* m_pWriteBuf;
90 sal_uInt32 m_nWriteBufLen;
91 sal_uInt32 m_nWriteBufFree;
94 struct osl_TProfileEntry
96 sal_uInt32 m_Line;
97 sal_uInt32 m_Offset;
98 sal_uInt32 m_Len;
101 struct osl_TProfileSection
103 sal_uInt32 m_Line;
104 sal_uInt32 m_Offset;
105 sal_uInt32 m_Len;
106 sal_uInt32 m_NoEntries;
107 sal_uInt32 m_MaxEntries;
108 osl_TProfileEntry* m_Entries;
112 Profile-data structure hidden behind oslProfile:
114 struct osl_TProfileImpl
116 sal_uInt32 m_Flags;
117 osl_TFile* m_pFile;
118 osl_TStamp m_Stamp;
119 sal_uInt32 m_NoLines;
120 sal_uInt32 m_MaxLines;
121 sal_uInt32 m_NoSections;
122 sal_uInt32 m_MaxSections;
123 char** m_Lines;
124 rtl_uString *m_strFileName;
125 osl_TProfileSection* m_Sections;
130 static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags );
131 static osl_TStamp closeFileImpl(osl_TFile* pFile);
132 static bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
133 static bool rewindFile(osl_TFile* pFile, bool bTruncate);
134 static osl_TStamp getFileStamp(osl_TFile* pFile);
136 static bool getLine(osl_TFile* pFile, char *pszLine, int MaxLen);
137 static bool putLine(osl_TFile* pFile, const char *pszLine);
138 static const char* stripBlanks(const char* String, sal_uInt32* pLen);
139 static const char* addLine(osl_TProfileImpl* pProfile, const char* Line);
140 static const char* insertLine(osl_TProfileImpl* pProfile, const char* Line, sal_uInt32 LineNo);
141 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
142 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
143 sal_uInt32 NoEntry, sal_uInt32 Line,
144 const char* Entry, sal_uInt32 Len);
145 static bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
146 int Line, const char* Entry, sal_uInt32 Len);
147 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
148 static bool addSection(osl_TProfileImpl* pProfile, int Line, const char* Section, sal_uInt32 Len);
149 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
150 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const char* Section,
151 const char* Entry, sal_uInt32 *pNoEntry);
152 static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
153 static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup);
154 static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable);
155 static bool releaseProfile(osl_TProfileImpl* pProfile);
156 static bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile);
158 static bool writeProfileImpl (osl_TFile* pFile);
159 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
160 static bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
161 static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension);
163 static bool osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName);
165 oslProfile SAL_CALL osl_openProfile(rtl_uString *strProfileName, oslProfileOption Flags)
167 osl_TFile* pFile = nullptr;
168 osl_TProfileImpl* pProfile;
169 rtl_uString *FileName=nullptr;
171 OSL_VERIFY(strProfileName);
173 if (rtl_uString_getLength(strProfileName) == 0 )
175 OSL_VERIFY(osl_getProfileName(nullptr, nullptr, &FileName));
177 else
179 rtl_uString_assign(&FileName, strProfileName);
182 osl_getSystemPathFromFileURL(FileName, &FileName);
184 #ifdef DEBUG_OSL_PROFILE
185 Flags=osl_Profile_FLUSHWRITE;
187 if ( Flags == osl_Profile_DEFAULT )
189 SAL_INFO("sal.osl", "with osl_Profile_DEFAULT");
191 if ( Flags & osl_Profile_SYSTEM )
193 SAL_INFO("sal.osl", "with osl_Profile_SYSTEM");
195 if ( Flags & osl_Profile_READLOCK )
197 SAL_INFO("sal.osl", "with osl_Profile_READLOCK");
199 if ( Flags & osl_Profile_WRITELOCK )
201 SAL_INFO("sal.osl", "with osl_Profile_WRITELOCK");
203 if ( Flags & osl_Profile_FLUSHWRITE )
205 SAL_INFO("sal.osl", "with osl_Profile_FLUSHWRITE");
207 #endif
209 if ( (! (Flags & osl_Profile_SYSTEM)) && ( (pFile = openFileImpl(FileName, Flags) ) == nullptr ) )
211 if( FileName)
212 rtl_uString_release( FileName);
214 return nullptr;
217 pProfile = static_cast<osl_TProfileImpl*>(calloc(1, sizeof(osl_TProfileImpl)));
218 if (!pProfile)
219 return nullptr;
221 pProfile->m_Flags = Flags & FLG_USER;
222 osl_getSystemPathFromFileURL(strProfileName, &pProfile->m_strFileName);
224 if (Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ))
225 pProfile->m_pFile = pFile;
227 pProfile->m_Stamp = getFileStamp(pFile);
229 loadProfile(pFile, pProfile);
231 if (pProfile->m_pFile == nullptr)
232 closeFileImpl(pFile);
234 if( FileName)
235 rtl_uString_release( FileName);
237 return pProfile;
240 sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
242 osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
245 if ( Profile == nullptr )
247 return false;
250 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
252 pProfile = acquireProfile(Profile,true);
254 if ( pProfile != nullptr )
256 if ( !( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
258 storeProfile(pProfile, false);
261 else
263 pProfile = acquireProfile(Profile,false);
266 if ( pProfile == nullptr )
268 return false;
271 if (pProfile->m_pFile != nullptr)
272 closeFileImpl(pProfile->m_pFile);
275 pProfile->m_pFile = nullptr;
276 rtl_uString_release(pProfile->m_strFileName);
277 pProfile->m_strFileName = nullptr;
279 /* release whole profile data types memory */
280 if ( pProfile->m_NoLines > 0)
282 unsigned int index=0;
283 if ( pProfile->m_Lines != nullptr )
285 for ( index = 0 ; index < pProfile->m_NoLines ; ++index)
287 if ( pProfile->m_Lines[index] != nullptr )
289 free(pProfile->m_Lines[index]);
292 free(pProfile->m_Lines);
294 if ( pProfile->m_Sections != nullptr )
296 for ( index = 0 ; index < pProfile->m_NoSections ; ++index )
298 if ( pProfile->m_Sections[index].m_Entries != nullptr )
299 free(pProfile->m_Sections[index].m_Entries);
301 free(pProfile->m_Sections);
305 free(pProfile);
307 return true;
310 sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
312 osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
313 osl_TFile* pFile;
314 bool bRet = false;
317 if ( pProfile == nullptr )
319 return false;
322 pFile = pProfile->m_pFile;
323 if ( pFile == nullptr || pFile->m_Handle == INVALID_HANDLE_VALUE )
325 return false;
328 if ( pProfile->m_Flags & FLG_MODIFIED )
330 #ifdef DEBUG_OSL_PROFILE
331 SAL_INFO("sal.osl", "swapping to storeprofile");
332 #endif
333 bRet = storeProfile(pProfile,false);
336 return bRet;
339 static bool writeProfileImpl(osl_TFile* pFile)
341 DWORD BytesWritten=0;
342 bool bRet;
344 if ( pFile == nullptr || pFile->m_Handle == INVALID_HANDLE_VALUE || ( pFile->m_pWriteBuf == nullptr ) )
346 return false;
349 bRet=WriteFile(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree,&BytesWritten,nullptr);
351 if ( !bRet || BytesWritten == 0 )
353 OSL_ENSURE(bRet,"WriteFile failed!!!");
354 SAL_WARN("sal.osl", "write failed " << strerror(errno));
356 return false;
359 free(pFile->m_pWriteBuf);
360 pFile->m_pWriteBuf=nullptr;
361 pFile->m_nWriteBufLen=0;
362 pFile->m_nWriteBufFree=0;
364 return true;
367 namespace {
368 // Use Unicode version of GetPrivateProfileString, to work with Multi-language paths
369 DWORD GetPrivateProfileStringWrapper(const osl_TProfileImpl* pProfile,
370 const char* pszSection, const char* pszEntry,
371 char* pszString, sal_uInt32 MaxLen,
372 const char* pszDefault)
374 OSL_ASSERT(pProfile && (!MaxLen || pszString));
376 rtl_uString *pSection = nullptr, *pEntry = nullptr, *pDefault = nullptr;
377 if (pszSection)
379 rtl_string2UString(&pSection, pszSection, strlen(pszSection), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
380 OSL_ASSERT(pSection);
382 if (pszEntry)
384 rtl_string2UString(&pEntry, pszEntry, strlen(pszEntry), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
385 OSL_ASSERT(pEntry);
387 if (pszDefault)
389 rtl_string2UString(&pDefault, pszDefault, strlen(pszDefault), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
390 OSL_ASSERT(pDefault);
393 LPCWSTR pWSection = (pSection ? o3tl::toW(rtl_uString_getStr(pSection)) : nullptr),
394 pWEntry = (pEntry ? o3tl::toW(rtl_uString_getStr(pEntry)) : nullptr),
395 pWDefault = (pDefault ? o3tl::toW(rtl_uString_getStr(pDefault)) : nullptr);
397 std::vector<wchar_t> aBuf(MaxLen + 1);
398 GetPrivateProfileStringW(pWSection, pWEntry, pWDefault, aBuf.data(), MaxLen, o3tl::toW(rtl_uString_getStr(pProfile->m_strFileName)));
400 if (pDefault)
401 rtl_uString_release(pDefault);
402 if (pEntry)
403 rtl_uString_release(pEntry);
404 if (pSection)
405 rtl_uString_release(pSection);
407 return WideCharToMultiByte(CP_ACP, 0, aBuf.data(), -1, pszString, MaxLen, nullptr, nullptr);
410 // Use Unicode version of WritePrivateProfileString, to work with Multi-language paths
411 bool WritePrivateProfileStringWrapper(const osl_TProfileImpl* pProfile,
412 const char* pszSection, const char* pszEntry,
413 const char* pszString)
415 OSL_ASSERT(pProfile && pszSection);
416 rtl_uString *pSection, *pEntry = nullptr, *pString = nullptr;
417 rtl_string2UString(&pSection, pszSection, strlen(pszSection), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
418 OSL_ASSERT(pSection);
419 if (pszEntry)
421 rtl_string2UString(&pEntry, pszEntry, strlen(pszEntry), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
422 OSL_ASSERT(pEntry);
424 if (pszString)
426 rtl_string2UString(&pString, pszString, strlen(pszString), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS);
427 OSL_ASSERT(pString);
430 LPCWSTR pWSection = o3tl::toW(pSection->buffer),
431 pWEntry = (pEntry ? o3tl::toW(rtl_uString_getStr(pEntry)) : nullptr),
432 pWString = (pString ? o3tl::toW(rtl_uString_getStr(pString)) : nullptr);
434 bool bResult = WritePrivateProfileStringW(pWSection, pWEntry, pWString, o3tl::toW(rtl_uString_getStr(pProfile->m_strFileName)));
436 if (pString)
437 rtl_uString_release(pString);
438 if (pEntry)
439 rtl_uString_release(pEntry);
440 rtl_uString_release(pSection);
442 return bResult;
446 sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
447 const char* pszSection, const char* pszEntry,
448 char* pszString, sal_uInt32 MaxLen,
449 const char* pszDefault)
451 sal_uInt32 NoEntry;
452 const char* pStr = nullptr;
453 osl_TProfileImpl* pProfile = nullptr;
455 pProfile = acquireProfile(Profile, false);
457 if (pProfile == nullptr)
459 return false;
462 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
464 osl_TProfileSection* pSec;
465 if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != nullptr) &&
466 (NoEntry < pSec->m_NoEntries) &&
467 ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
468 '=')) != nullptr))
469 pStr++;
470 else
471 pStr = pszDefault;
473 if ( pStr != nullptr )
475 pStr = stripBlanks(pStr, nullptr);
476 MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
477 pStr = stripBlanks(pStr, &MaxLen);
478 strncpy(pszString, pStr, MaxLen);
479 pszString[MaxLen] = '\0';
482 else
484 if (GetPrivateProfileStringWrapper(pProfile, pszSection, pszEntry, pszString, MaxLen, pszDefault) > 0)
485 pStr = pszString; // required to return true below
488 releaseProfile(pProfile);
490 if ( pStr == nullptr )
492 return false;
495 return true;
498 sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
499 const char* pszSection, const char* pszEntry,
500 sal_Bool Default)
502 char Line[32];
504 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
506 if ((stricmp(Line, STR_INI_BOOLYES) == 0) ||
507 (stricmp(Line, STR_INI_BOOLON) == 0) ||
508 (stricmp(Line, STR_INI_BOOLONE) == 0))
509 Default = true;
510 else
511 if ((stricmp(Line, STR_INI_BOOLNO) == 0) ||
512 (stricmp(Line, STR_INI_BOOLOFF) == 0) ||
513 (stricmp(Line, STR_INI_BOOLZERO) == 0))
514 Default = false;
517 return Default;
520 sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
521 const char* pszSection, const char* pszEntry,
522 sal_uInt32 FirstId, const char* Strings[],
523 sal_uInt32 Default)
525 sal_uInt32 i;
526 char Line[256];
528 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
530 i = 0;
531 while (Strings[i] != nullptr)
533 if (stricmp(Line, Strings[i]) == 0)
535 Default = i + FirstId;
536 break;
538 i++;
542 return Default;
545 sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
546 const char* pszSection, const char* pszEntry,
547 const char* pszString)
549 sal_uInt32 i;
550 bool bRet = false;
551 sal_uInt32 NoEntry;
552 const char* pStr;
553 char Line[4096];
554 osl_TProfileSection* pSec;
555 osl_TProfileImpl* pProfile = nullptr;
557 pProfile = acquireProfile(Profile, true);
559 if (pProfile == nullptr)
561 return false;
564 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
566 if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == nullptr)
568 Line[0] = '\0';
569 addLine(pProfile, Line);
571 Line[0] = '[';
572 strcpy(&Line[1], pszSection);
573 Line[1 + strlen(pszSection)] = ']';
574 Line[2 + strlen(pszSection)] = '\0';
576 if (((pStr = addLine(pProfile, Line)) == nullptr) ||
577 (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
579 releaseProfile(pProfile);
580 return false;
583 pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
584 NoEntry = pSec->m_NoEntries;
587 Line[0] = '\0';
588 strcpy(&Line[0], pszEntry);
589 Line[0 + strlen(pszEntry)] = '=';
590 strcpy(&Line[1 + strlen(pszEntry)], pszString);
592 if (NoEntry >= pSec->m_NoEntries)
594 if (pSec->m_NoEntries > 0)
595 i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
596 else
597 i = pSec->m_Line + 1;
599 if (((pStr = insertLine(pProfile, Line, i)) == nullptr) ||
600 (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
602 releaseProfile(pProfile);
603 return false;
606 pProfile->m_Flags |= FLG_MODIFIED;
608 else
610 i = pSec->m_Entries[NoEntry].m_Line;
611 free(pProfile->m_Lines[i]);
612 pProfile->m_Lines[i] = strdup(Line);
613 setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
615 pProfile->m_Flags |= FLG_MODIFIED;
618 else
620 WritePrivateProfileStringWrapper(pProfile, pszSection, pszEntry, pszString);
623 bRet = releaseProfile(pProfile);
624 return bRet;
627 sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
628 const char* pszSection, const char* pszEntry,
629 sal_Bool Value)
631 bool bRet = false;
633 if (Value)
634 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
635 else
636 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
638 return bRet;
641 sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
642 const char* pszSection, const char* pszEntry,
643 sal_uInt32 FirstId, const char* Strings[],
644 sal_uInt32 Value)
646 int i, n;
647 bool bRet = false;
649 for (n = 0; Strings[n] != nullptr; n++);
651 if ((i = Value - FirstId) >= n)
652 bRet=false;
653 else
654 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
656 return bRet;
659 sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
660 const char *pszSection, const char *pszEntry)
662 sal_uInt32 NoEntry;
663 osl_TProfileImpl* pProfile = nullptr;
664 bool bRet = false;
666 pProfile = acquireProfile(Profile, true);
668 if (pProfile == nullptr)
669 return false;
671 if (!(pProfile->m_Flags & osl_Profile_SYSTEM))
673 osl_TProfileSection* pSec;
674 if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != nullptr) &&
675 (NoEntry < pSec->m_NoEntries))
677 removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
678 removeEntry(pSec, NoEntry);
679 if (pSec->m_NoEntries == 0)
681 removeLine(pProfile, pSec->m_Line);
683 /* remove any empty separation line */
684 if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
685 removeLine(pProfile, pSec->m_Line - 1);
687 removeSection(pProfile, pSec);
690 pProfile->m_Flags |= FLG_MODIFIED;
693 else
695 WritePrivateProfileStringWrapper(pProfile, pszSection, pszEntry, nullptr);
698 bRet = releaseProfile(pProfile);
699 return bRet;
702 sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const char *pszSection,
703 char* pszBuffer, sal_uInt32 MaxLen)
705 sal_uInt32 i, n = 0;
706 sal_uInt32 NoEntry;
707 osl_TProfileImpl* pProfile = nullptr;
709 pProfile = acquireProfile(Profile, false);
711 if (pProfile == nullptr)
712 return 0;
714 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
716 osl_TProfileSection* pSec;
717 if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != nullptr)
719 if (MaxLen != 0)
721 for (i = 0; i < pSec->m_NoEntries; i++)
723 if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
725 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
726 [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
727 n += pSec->m_Entries[i].m_Len;
728 pszBuffer[n++] = '\0';
730 else
732 break;
737 pszBuffer[n++] = '\0';
739 else
741 for (i = 0; i < pSec->m_NoEntries; i++)
743 n += pSec->m_Entries[i].m_Len + 1;
746 n += 1;
749 else
751 n = 0;
754 else
756 n = GetPrivateProfileStringWrapper(pProfile, pszSection, nullptr, pszBuffer, MaxLen, nullptr);
759 releaseProfile(pProfile);
761 return n;
764 bool osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName)
766 bool bFailed;
767 ::osl::LongPathBuffer< sal_Unicode > aFile( MAX_LONG_PATH );
768 ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
769 sal_uInt32 nFileLen = 0;
770 sal_uInt32 nPathLen = 0;
772 rtl_uString * strTmp = nullptr;
773 oslFileError nError;
775 /* build file name */
776 if (strName && strName->length)
778 if( ::sal::static_int_cast< sal_uInt32 >( strName->length ) >= aFile.getBufSizeInSymbols() )
779 return false;
781 copy_ustr_n( aFile, strName->buffer, strName->length+1);
782 nFileLen = strName->length;
784 if (rtl_ustr_indexOfChar( aFile, L'.' ) == -1)
786 if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
787 return false;
789 /* add default extension */
790 copy_ustr_n( aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1 );
791 nFileLen += wcslen(STR_INI_EXTENSION);
794 else
796 rtl_uString *strProgName = nullptr;
797 sal_Unicode *pProgName;
798 sal_Int32 nOffset = 0;
799 sal_Int32 nLen;
800 sal_Int32 nPos;
802 if (osl_getExecutableFile(&strProgName) != osl_Process_E_None)
803 return false;
805 /* remove path and extension from filename */
806 pProgName = strProgName->buffer;
807 nLen = strProgName->length ;
809 if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'/' )) != -1)
810 nOffset = nPos + 1;
811 else if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L':' )) != -1)
812 nOffset = nPos + 1;
814 if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'.' )) != -1 )
815 nLen -= 4;
817 if ((nFileLen = nLen - nOffset) >= aFile.getBufSizeInSymbols())
818 return false;
820 copy_ustr_n(aFile, pProgName + nOffset, nFileLen);
822 if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
823 return false;
825 /* add default extension */
826 copy_ustr_n(aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1);
827 nFileLen += wcslen(STR_INI_EXTENSION);
829 rtl_uString_release( strProgName );
832 if (aFile[0] == 0)
833 return false;
835 /* build directory path */
836 if (strPath && strPath->length)
838 sal_Unicode *pPath = rtl_uString_getStr(strPath);
839 sal_Int32 nLen = rtl_uString_getLength(strPath);
841 if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAHOME) , STR_INI_METAHOME) == 0) &&
842 ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)] == '/')))
844 rtl_uString * strHome = nullptr;
845 oslSecurity security = osl_getCurrentSecurity();
847 bFailed = ! osl_getHomeDir(security, &strHome);
848 osl_freeSecurityHandle(security);
850 if (bFailed) return false;
852 if ( ::sal::static_int_cast< sal_uInt32 >( strHome->length ) >= aPath.getBufSizeInSymbols())
853 return false;
855 copy_ustr_n( aPath, strHome->buffer, strHome->length+1);
856 nPathLen = strHome->length;
858 if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METAHOME))
860 pPath += RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
861 nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
863 if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
864 return false;
866 copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
867 nPathLen += nLen;
870 rtl_uString_release(strHome);
873 else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METACFG), STR_INI_METACFG) == 0) &&
874 ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METACFG)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METACFG)] == '/')))
876 rtl_uString * strConfig = nullptr;
877 oslSecurity security = osl_getCurrentSecurity();
879 bFailed = ! osl_getConfigDir(security, &strConfig);
880 osl_freeSecurityHandle(security);
882 if (bFailed) return false;
884 if ( ::sal::static_int_cast< sal_uInt32 >( strConfig->length ) >= aPath.getBufSizeInSymbols())
885 return false;
887 copy_ustr_n( aPath, strConfig->buffer, strConfig->length+1 );
888 nPathLen = strConfig->length;
890 if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METACFG))
892 pPath += RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
893 nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
895 if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
896 return false;
898 copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
899 nPathLen += nLen;
902 rtl_uString_release(strConfig);
905 else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METASYS), STR_INI_METASYS) == 0) &&
906 ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METASYS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METASYS)] == '/')))
908 if (((nPathLen = GetWindowsDirectoryW(o3tl::toW(aPath), aPath.getBufSizeInSymbols())) == 0) || (nPathLen >= aPath.getBufSizeInSymbols()))
909 return false;
911 if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METASYS))
913 pPath += RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
914 nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
916 if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
917 return false;
919 copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
920 nPathLen += nLen;
924 else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAINS), STR_INI_METAINS) == 0) &&
925 ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAINS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '/') ||
926 (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '"') ) )
928 if (! lookupProfile(pPath + RTL_CONSTASCII_LENGTH(STR_INI_METAINS), aFile, aPath))
929 return false;
931 nPathLen = rtl_ustr_getLength(aPath);
934 else if( ::sal::static_int_cast< sal_uInt32 >( nLen ) < aPath.getBufSizeInSymbols())
936 copy_ustr_n(aPath, pPath, nLen+1);
937 nPathLen = rtl_ustr_getLength(aPath);
939 else
940 return false;
942 else
944 rtl_uString * strConfigDir = nullptr;
945 oslSecurity security = osl_getCurrentSecurity();
947 bFailed = ! osl_getConfigDir(security, &strConfigDir);
948 osl_freeSecurityHandle(security);
950 if (bFailed) return false;
951 if ( ::sal::static_int_cast< sal_uInt32 >( strConfigDir->length ) >= aPath.getBufSizeInSymbols() )
952 return false;
954 copy_ustr_n(aPath, strConfigDir->buffer, strConfigDir->length+1);
955 nPathLen = strConfigDir->length;
958 if (nPathLen && (aPath[nPathLen - 1] != L'/') && (aPath[nPathLen - 1] != L'\\'))
960 aPath[nPathLen++] = L'\\';
961 aPath[nPathLen] = 0;
964 if (nPathLen + nFileLen >= aPath.getBufSizeInSymbols())
965 return false;
967 /* append file name */
968 copy_ustr_n(aPath + nPathLen, aFile, nFileLen+1);
969 nPathLen += nFileLen;
971 /* copy filename */
972 rtl_uString_newFromStr_WithLength(&strTmp, aPath, nPathLen);
973 nError = osl_getFileURLFromSystemPath(strTmp, strProfileName);
974 rtl_uString_release(strTmp);
976 return nError == osl_File_E_None;
979 sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, char* pszBuffer, sal_uInt32 MaxLen)
981 sal_uInt32 i, n = 0;
982 osl_TProfileImpl* pProfile = acquireProfile(Profile, false);
984 if (pProfile == nullptr)
985 return 0;
987 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
989 if (MaxLen != 0)
991 for (i = 0; i < pProfile->m_NoSections; i++)
993 osl_TProfileSection* pSec = &pProfile->m_Sections[i];
995 if ((n + pSec->m_Len + 1) < MaxLen)
997 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
998 pSec->m_Len);
999 n += pSec->m_Len;
1000 pszBuffer[n++] = '\0';
1002 else
1003 break;
1006 pszBuffer[n++] = '\0';
1008 else
1010 for (i = 0; i < pProfile->m_NoSections; i++)
1011 n += pProfile->m_Sections[i].m_Len + 1;
1013 n += 1;
1016 else
1018 std::vector<wchar_t> aBuf(MaxLen + 1);
1019 GetPrivateProfileSectionNamesW(aBuf.data(), MaxLen, o3tl::toW(rtl_uString_getStr(pProfile->m_strFileName)));
1021 n = WideCharToMultiByte(CP_ACP, 0, aBuf.data(), -1, pszBuffer, MaxLen, nullptr, nullptr);
1024 releaseProfile(pProfile);
1026 return n;
1029 static osl_TStamp getFileStamp(osl_TFile* pFile)
1031 FILETIME FileTime;
1033 if ((pFile->m_Handle == INVALID_HANDLE_VALUE) ||
1034 (! GetFileTime(pFile->m_Handle, nullptr, nullptr, &FileTime)))
1035 memset(&FileTime, 0, sizeof(FileTime));
1037 return FileTime;
1040 static bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
1042 bool status = false;
1043 OVERLAPPED Overlapped = {};
1045 if (pFile->m_Handle == INVALID_HANDLE_VALUE)
1046 return false;
1048 switch (eMode)
1050 case un_lock:
1051 status = UnlockFileEx(
1052 pFile->m_Handle, 0, 0xFFFFFFFF, 0, &Overlapped);
1053 break;
1055 case read_lock:
1056 status = LockFileEx(
1057 pFile->m_Handle, 0, 0, 0xFFFFFFFF, 0, &Overlapped);
1058 break;
1060 case write_lock:
1061 status = LockFileEx(
1062 pFile->m_Handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 0xFFFFFFFF, 0,
1063 &Overlapped);
1064 break;
1067 return status;
1070 static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags )
1072 osl_TFile* pFile = static_cast< osl_TFile*>( calloc( 1, sizeof(osl_TFile) ) );
1073 if (!pFile)
1074 return nullptr;
1075 bool bWriteable = false;
1077 if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
1079 #ifdef DEBUG_OSL_PROFILE
1080 SAL_INFO("sal.osl", "setting bWriteable to TRUE");
1081 #endif
1082 bWriteable=true;
1085 if (! bWriteable)
1087 pFile->m_Handle = CreateFileW( o3tl::toW(rtl_uString_getStr( strFileName )), GENERIC_READ,
1088 FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
1089 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
1091 /* mfe: argghh!!! do not check if the file could be opened */
1092 /* default mode expects it that way!!! */
1094 else
1096 #ifdef DEBUG_OSL_PROFILE
1097 SAL_INFO("sal.osl", "opening read/write " << pszFilename);
1098 #endif
1100 if ((pFile->m_Handle = CreateFileW( o3tl::toW(rtl_uString_getStr( strFileName )), GENERIC_READ | GENERIC_WRITE,
1101 FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
1102 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr))
1103 == INVALID_HANDLE_VALUE)
1105 free(pFile);
1106 return nullptr;
1110 pFile->m_pWriteBuf=nullptr;
1111 pFile->m_nWriteBufFree=0;
1112 pFile->m_nWriteBufLen=0;
1114 if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1116 #ifdef DEBUG_OSL_PROFILE
1117 SAL_INFO("sal.osl", "locking file " << pszFilename);
1118 #endif
1120 lockFile(pFile, bWriteable ? write_lock : read_lock);
1123 return pFile;
1126 static osl_TStamp closeFileImpl(osl_TFile* pFile)
1128 osl_TStamp stamp = {0, 0};
1130 if ( pFile == nullptr )
1132 return stamp;
1135 if (pFile->m_Handle != INVALID_HANDLE_VALUE)
1137 stamp = getFileStamp(pFile);
1139 lockFile(pFile, un_lock);
1141 CloseHandle(pFile->m_Handle);
1142 pFile->m_Handle = INVALID_HANDLE_VALUE;
1145 if ( pFile->m_pWriteBuf != nullptr )
1147 free(pFile->m_pWriteBuf);
1150 free(pFile);
1152 return stamp;
1155 static bool rewindFile(osl_TFile* pFile, bool bTruncate)
1157 if (pFile->m_Handle != INVALID_HANDLE_VALUE)
1159 pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1161 SetFilePointer(pFile->m_Handle, 0, nullptr, FILE_BEGIN);
1163 if (bTruncate)
1164 SetEndOfFile(pFile->m_Handle);
1167 return true;
1170 static bool getLine(osl_TFile* pFile, char *pszLine, int MaxLen)
1172 DWORD Max;
1173 size_t Free;
1174 char* pChr;
1175 char* pLine = pszLine;
1177 if (pFile->m_Handle == INVALID_HANDLE_VALUE)
1178 return false;
1180 MaxLen -= 1;
1184 size_t Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
1186 if (Bytes <= 1)
1188 /* refill buffer */
1189 memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
1190 pFile->m_pReadPtr = pFile->m_ReadBuf;
1192 Free = sizeof(pFile->m_ReadBuf) - Bytes;
1194 if (! ReadFile(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free, &Max, nullptr))
1196 *pLine = '\0';
1197 return false;
1200 if (Max < Free)
1202 if ((Max == 0) && (pLine == pszLine))
1204 *pLine = '\0';
1205 return false;
1208 pFile->m_ReadBuf[Bytes + Max] = '\0';
1212 for (pChr = pFile->m_pReadPtr;
1213 (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
1214 (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
1215 pChr++);
1217 Max = min(static_cast<int>(pChr - pFile->m_pReadPtr), MaxLen);
1218 memcpy(pLine, pFile->m_pReadPtr, Max);
1219 MaxLen -= Max;
1220 pLine += Max;
1222 if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
1224 if (*pChr != '\0')
1226 if ((pChr[0] == '\r') && (pChr[1] == '\n'))
1227 pChr += 2;
1228 else
1229 pChr += 1;
1232 if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
1233 (*pChr == '\0'))
1234 pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1236 *pLine = '\0';
1238 /* setting MaxLen to -1 indicates terminating read loop */
1239 MaxLen = -1;
1242 pFile->m_pReadPtr = pChr;
1244 while (MaxLen > 0);
1246 return true;
1249 static bool putLine(osl_TFile* pFile, const char *pszLine)
1251 unsigned int Len = strlen(pszLine);
1253 if ( pFile == nullptr || pFile->m_Handle == INVALID_HANDLE_VALUE )
1255 return false;
1258 if ( pFile->m_pWriteBuf == nullptr )
1260 pFile->m_pWriteBuf = static_cast<char*>(malloc(Len+3));
1261 pFile->m_nWriteBufLen = Len+3;
1262 pFile->m_nWriteBufFree = Len+3;
1264 else
1266 if ( pFile->m_nWriteBufFree <= Len + 3 )
1268 char* pTmp;
1270 pTmp=static_cast<char*>(realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) ));
1271 if ( pTmp == nullptr )
1273 return false;
1275 pFile->m_pWriteBuf = pTmp;
1276 pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
1277 pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
1278 memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
1282 memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
1284 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\r';
1285 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\n';
1286 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 2]='\0';
1288 pFile->m_nWriteBufFree-=Len+2;
1290 return true;
1293 /* platform specific end */
1295 static const char* stripBlanks(const char* String, sal_uInt32* pLen)
1297 if ( (pLen != nullptr) && ( *pLen != 0 ) )
1299 while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
1300 (*pLen)--;
1302 while ((*String == ' ') || (*String == '\t'))
1304 String++;
1305 (*pLen)--;
1308 else
1309 while ((*String == ' ') || (*String == '\t'))
1310 String++;
1312 return String;
1315 static const char* addLine(osl_TProfileImpl* pProfile, const char* Line)
1317 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1319 if (pProfile->m_Lines == nullptr)
1321 pProfile->m_MaxLines = LINES_INI;
1322 pProfile->m_Lines = static_cast<char **>(calloc(pProfile->m_MaxLines, sizeof(char *)));
1324 else
1326 unsigned int index=0;
1327 unsigned int oldmax=pProfile->m_MaxLines;
1329 pProfile->m_MaxLines += LINES_ADD;
1330 if (auto p = static_cast<char **>(realloc(pProfile->m_Lines, pProfile->m_MaxLines * sizeof(char *))))
1332 pProfile->m_Lines = p;
1334 for ( index = oldmax ; index < pProfile->m_MaxLines ; ++index )
1336 pProfile->m_Lines[index]=nullptr;
1339 else
1341 free(pProfile->m_Lines);
1342 pProfile->m_Lines = nullptr;
1346 if (pProfile->m_Lines == nullptr)
1348 pProfile->m_NoLines = 0;
1349 pProfile->m_MaxLines = 0;
1350 return nullptr;
1355 if ( pProfile->m_Lines != nullptr && pProfile->m_Lines[pProfile->m_NoLines] != nullptr )
1357 free(pProfile->m_Lines[pProfile->m_NoLines]);
1359 pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
1361 return pProfile->m_Lines[pProfile->m_NoLines - 1];
1364 static const char* insertLine(osl_TProfileImpl* pProfile, const char* Line, sal_uInt32 LineNo)
1366 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1368 if (pProfile->m_Lines == nullptr)
1370 pProfile->m_MaxLines = LINES_INI;
1371 pProfile->m_Lines = static_cast<char **>(calloc(pProfile->m_MaxLines, sizeof(char *)));
1373 else
1375 pProfile->m_MaxLines += LINES_ADD;
1376 if (auto p = static_cast<char**>(
1377 realloc(pProfile->m_Lines, pProfile->m_MaxLines * sizeof(char*))))
1379 pProfile->m_Lines = p;
1381 memset(&pProfile->m_Lines[pProfile->m_NoLines], 0,
1382 (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(char*));
1384 else
1386 free(pProfile->m_Lines);
1387 pProfile->m_Lines = nullptr;
1391 if (pProfile->m_Lines == nullptr)
1393 pProfile->m_NoLines = 0;
1394 pProfile->m_MaxLines = 0;
1395 return nullptr;
1399 LineNo = std::min(LineNo, pProfile->m_NoLines);
1401 if (LineNo < pProfile->m_NoLines)
1403 sal_uInt32 i, n;
1405 memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
1406 (pProfile->m_NoLines - LineNo) * sizeof(char *));
1408 /* adjust line references */
1409 for (i = 0; i < pProfile->m_NoSections; i++)
1411 osl_TProfileSection* pSec = &pProfile->m_Sections[i];
1413 if (pSec->m_Line >= LineNo)
1414 pSec->m_Line++;
1416 for (n = 0; n < pSec->m_NoEntries; n++)
1417 if (pSec->m_Entries[n].m_Line >= LineNo)
1418 pSec->m_Entries[n].m_Line++;
1422 pProfile->m_NoLines++;
1424 pProfile->m_Lines[LineNo] = strdup(Line);
1426 return pProfile->m_Lines[LineNo];
1429 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
1431 if (LineNo < pProfile->m_NoLines)
1433 free(pProfile->m_Lines[LineNo]);
1434 pProfile->m_Lines[LineNo]=nullptr;
1435 if (pProfile->m_NoLines - LineNo > 1)
1437 sal_uInt32 i, n;
1439 memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
1440 (pProfile->m_NoLines - LineNo - 1) * sizeof(char *));
1442 memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
1444 (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(char*));
1446 /* adjust line references */
1447 for (i = 0; i < pProfile->m_NoSections; i++)
1449 osl_TProfileSection* pSec = &pProfile->m_Sections[i];
1451 if (pSec->m_Line > LineNo)
1452 pSec->m_Line--;
1454 for (n = 0; n < pSec->m_NoEntries; n++)
1455 if (pSec->m_Entries[n].m_Line > LineNo)
1456 pSec->m_Entries[n].m_Line--;
1459 else
1461 pProfile->m_Lines[LineNo] = nullptr;
1464 pProfile->m_NoLines--;
1467 return;
1470 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
1471 sal_uInt32 NoEntry, sal_uInt32 Line,
1472 const char* Entry, sal_uInt32 Len)
1474 Entry = stripBlanks(Entry, &Len);
1475 pSection->m_Entries[NoEntry].m_Line = Line;
1476 pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
1477 pSection->m_Entries[NoEntry].m_Len = Len;
1479 return;
1482 static bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
1483 int Line, const char* Entry, sal_uInt32 Len)
1485 if (pSection != nullptr)
1487 if (pSection->m_NoEntries >= pSection->m_MaxEntries)
1489 if (pSection->m_Entries == nullptr)
1491 pSection->m_MaxEntries = ENTRIES_INI;
1492 pSection->m_Entries = static_cast<osl_TProfileEntry *>(malloc(
1493 pSection->m_MaxEntries * sizeof(osl_TProfileEntry)));
1495 else
1497 pSection->m_MaxEntries += ENTRIES_ADD;
1498 if (auto p = static_cast<osl_TProfileEntry*>(realloc(
1499 pSection->m_Entries, pSection->m_MaxEntries * sizeof(osl_TProfileEntry))))
1500 pSection->m_Entries = p;
1501 else
1503 free(pSection->m_Entries);
1504 pSection->m_Entries = nullptr;
1508 if (pSection->m_Entries == nullptr)
1510 pSection->m_NoEntries = 0;
1511 pSection->m_MaxEntries = 0;
1512 return false;
1516 pSection->m_NoEntries++;
1518 Entry = stripBlanks(Entry, &Len);
1519 setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
1520 Entry, Len);
1522 return true;
1525 return false;
1528 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
1530 if (NoEntry < pSection->m_NoEntries)
1532 if (pSection->m_NoEntries - NoEntry > 1)
1534 memmove(&pSection->m_Entries[NoEntry],
1535 &pSection->m_Entries[NoEntry + 1],
1536 (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
1537 pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
1538 pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
1539 pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
1542 pSection->m_NoEntries--;
1545 return;
1548 static bool addSection(osl_TProfileImpl* pProfile, int Line, const char* Section, sal_uInt32 Len)
1550 if (pProfile->m_NoSections >= pProfile->m_MaxSections)
1552 if (pProfile->m_Sections == nullptr)
1554 pProfile->m_MaxSections = SECTIONS_INI;
1555 pProfile->m_Sections = static_cast<osl_TProfileSection*>(calloc(pProfile->m_MaxSections, sizeof(osl_TProfileSection)));
1557 else
1559 unsigned int index=0;
1560 unsigned int oldmax=pProfile->m_MaxSections;
1562 pProfile->m_MaxSections += SECTIONS_ADD;
1563 if (auto p = static_cast<osl_TProfileSection*>(realloc(
1564 pProfile->m_Sections, pProfile->m_MaxSections * sizeof(osl_TProfileSection))))
1566 pProfile->m_Sections = p;
1567 for ( index = oldmax ; index < pProfile->m_MaxSections ; ++index )
1569 pProfile->m_Sections[index].m_Entries=nullptr;
1572 else
1574 free(pProfile->m_Sections);
1575 pProfile->m_Sections = nullptr;
1579 if (pProfile->m_Sections == nullptr)
1581 pProfile->m_NoSections = 0;
1582 pProfile->m_MaxSections = 0;
1583 return false;
1587 pProfile->m_NoSections++;
1589 if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != nullptr )
1591 free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
1593 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = nullptr;
1594 pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
1595 pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
1597 Section = stripBlanks(Section, &Len);
1598 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
1599 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
1600 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
1602 return true;
1605 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
1607 sal_uInt32 Section;
1609 if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
1611 free (pSection->m_Entries);
1612 pSection->m_Entries=nullptr;
1613 if (pProfile->m_NoSections - Section > 1)
1615 memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
1616 (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
1618 memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
1620 (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
1621 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = nullptr;
1623 else
1625 pSection->m_Entries = nullptr;
1628 pProfile->m_NoSections--;
1631 return;
1634 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const char* Section,
1635 const char* Entry, sal_uInt32 *pNoEntry)
1637 static sal_uInt32 Sect = 0;
1638 sal_uInt32 i, n;
1639 sal_uInt32 Len;
1640 osl_TProfileSection* pSec = nullptr;
1642 Len = strlen(Section);
1643 Section = stripBlanks(Section, &Len);
1645 n = Sect;
1647 for (i = 0; i < pProfile->m_NoSections; i++)
1649 n %= pProfile->m_NoSections;
1650 pSec = &pProfile->m_Sections[n];
1651 if ((Len == pSec->m_Len) &&
1652 (strnicmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
1653 == 0))
1654 break;
1655 n++;
1658 Sect = n;
1660 if (i < pProfile->m_NoSections)
1662 Len = strlen(Entry);
1663 Entry = stripBlanks(Entry, &Len);
1665 *pNoEntry = pSec->m_NoEntries;
1667 for (i = 0; i < pSec->m_NoEntries; i++)
1669 const char* pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
1670 [pSec->m_Entries[i].m_Offset];
1671 if ((Len == pSec->m_Entries[i].m_Len) &&
1672 (strnicmp(Entry, pStr, pSec->m_Entries[i].m_Len)
1673 == 0))
1675 *pNoEntry = i;
1676 break;
1680 else
1681 pSec = nullptr;
1683 return pSec;
1686 static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
1688 sal_uInt32 i;
1689 char const * pStr;
1690 char const * pChar;
1691 char Line[4096];
1693 pProfile->m_NoLines = 0;
1694 pProfile->m_NoSections = 0;
1696 OSL_VERIFY(rewindFile(pFile, false));
1698 while (getLine(pFile, Line, sizeof(Line)))
1700 if (! addLine(pProfile, Line))
1701 return false;
1704 for (i = 0; i < pProfile->m_NoLines; i++)
1706 pStr = stripBlanks(pProfile->m_Lines[i], nullptr);
1708 if ((*pStr == '\0') || (*pStr == ';'))
1709 continue;
1711 if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == nullptr) ||
1712 ((pChar - pStr) <= 2))
1714 /* insert entry */
1716 if (pProfile->m_NoSections < 1)
1717 continue;
1719 if ((pChar = strchr(pStr, '=')) == nullptr)
1720 pChar = pStr + strlen(pStr);
1722 if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
1723 i, pStr, pChar - pStr))
1724 return false;
1726 else
1728 /* new section */
1729 if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
1730 return false;
1734 return true;
1737 static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup)
1739 if (pProfile->m_Lines != nullptr)
1741 if (pProfile->m_Flags & FLG_MODIFIED)
1743 sal_uInt32 i;
1745 osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
1747 if ( pTmpFile == nullptr )
1749 return false;
1752 OSL_VERIFY(rewindFile(pTmpFile, true));
1754 for (i = 0; i < pProfile->m_NoLines; i++)
1756 OSL_VERIFY(putLine(pTmpFile, pProfile->m_Lines[i]));
1759 if ( ! writeProfileImpl(pTmpFile) )
1761 if ( pTmpFile->m_pWriteBuf != nullptr )
1763 free(pTmpFile->m_pWriteBuf);
1766 pTmpFile->m_pWriteBuf=nullptr;
1767 pTmpFile->m_nWriteBufLen=0;
1768 pTmpFile->m_nWriteBufFree=0;
1770 closeFileImpl(pTmpFile);
1772 return false;
1775 pProfile->m_Flags &= ~FLG_MODIFIED;
1777 closeFileImpl(pProfile->m_pFile);
1778 closeFileImpl(pTmpFile);
1780 osl_ProfileSwapProfileNames(pProfile);
1782 pProfile->m_pFile = openFileImpl(pProfile->m_strFileName,pProfile->m_Flags);
1786 if (bCleanup)
1788 while (pProfile->m_NoLines > 0)
1789 removeLine(pProfile, pProfile->m_NoLines - 1);
1791 free(pProfile->m_Lines);
1792 pProfile->m_Lines = nullptr;
1793 pProfile->m_MaxLines = 0;
1795 while (pProfile->m_NoSections > 0)
1796 removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
1798 free(pProfile->m_Sections);
1799 pProfile->m_Sections = nullptr;
1800 pProfile->m_MaxSections = 0;
1804 return true;
1807 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
1809 osl_TFile* pFile=nullptr;
1810 rtl_uString* ustrExtension=nullptr;
1811 rtl_uString* ustrTmpName=nullptr;
1812 oslProfileOption PFlags=0;
1814 rtl_uString_newFromAscii(&ustrExtension,"tmp");
1816 /* generate tmp profilename */
1817 ustrTmpName=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
1818 rtl_uString_release(ustrExtension);
1820 if (ustrTmpName == nullptr)
1821 return nullptr;
1823 if (!(pProfile->m_Flags & osl_Profile_READLOCK))
1824 PFlags |= osl_Profile_WRITELOCK;
1826 /* open this file */
1827 pFile = openFileImpl(ustrTmpName,pProfile->m_Flags | PFlags);
1829 /* return new pFile */
1830 return pFile;
1833 static bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
1835 rtl_uString* ustrBakFile=nullptr;
1836 rtl_uString* ustrTmpFile=nullptr;
1837 rtl_uString* ustrIniFile=nullptr;
1838 rtl_uString* ustrExtension=nullptr;
1840 rtl_uString_newFromAscii(&ustrExtension,"bak");
1842 ustrBakFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
1843 rtl_uString_release(ustrExtension);
1844 ustrExtension=nullptr;
1846 rtl_uString_newFromAscii(&ustrExtension,"ini");
1848 ustrIniFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
1849 rtl_uString_release(ustrExtension);
1850 ustrExtension=nullptr;
1852 rtl_uString_newFromAscii(&ustrExtension,"tmp");
1854 ustrTmpFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
1855 rtl_uString_release(ustrExtension);
1856 ustrExtension=nullptr;
1858 /* unlink bak */
1859 DeleteFileW( o3tl::toW(rtl_uString_getStr( ustrBakFile )) );
1861 /* rename ini bak */
1862 MoveFileExW( o3tl::toW(rtl_uString_getStr( ustrIniFile )), o3tl::toW(rtl_uString_getStr( ustrBakFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
1864 /* rename tmp ini */
1865 MoveFileExW( o3tl::toW(rtl_uString_getStr( ustrTmpFile )), o3tl::toW(rtl_uString_getStr( ustrIniFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
1867 return false;
1870 static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension)
1872 rtl_uString* ustrNewFileName = nullptr;
1873 rtl_uString* ustrOldExtension = nullptr;
1875 sal_Unicode* pFileNameBuf = rtl_uString_getStr(ustrFileName);
1877 rtl_uString_newFromAscii(&ustrOldExtension, ".");
1879 sal_Unicode* pExtensionBuf = rtl_uString_getStr(ustrOldExtension);
1881 sal_Int32 nIndex = rtl_ustr_lastIndexOfChar(pFileNameBuf, *pExtensionBuf);
1883 rtl_uString_newReplaceStrAt(&ustrNewFileName,
1884 ustrFileName,
1885 nIndex+1,
1887 ustrExtension);
1889 return ustrNewFileName;
1892 static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable)
1894 osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
1895 oslProfileOption PFlags=0;
1897 if ( bWriteable )
1899 PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
1901 else
1903 PFlags = osl_Profile_DEFAULT;
1906 if (pProfile == nullptr)
1908 #ifdef DEBUG_OSL_PROFILE
1909 SAL_INFO("sal.osl", "AUTOOPEN MODE");
1910 #endif
1912 if ( ( pProfile = static_cast<osl_TProfileImpl*>(osl_openProfile( nullptr, PFlags )) ) != nullptr )
1914 pProfile->m_Flags |= FLG_AUTOOPEN;
1917 else
1919 #ifdef DEBUG_OSL_PROFILE
1920 SAL_INFO("sal.osl", "try to acquire");
1921 #endif
1923 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
1925 if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
1926 osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
1928 osl_TStamp Stamp;
1929 #ifdef DEBUG_OSL_PROFILE
1930 SAL_INFO("sal.osl", "DEFAULT MODE");
1931 #endif
1932 pProfile->m_pFile = openFileImpl(
1933 pProfile->m_strFileName, pProfile->m_Flags | PFlags);
1934 if (!pProfile->m_pFile)
1935 return nullptr;
1937 Stamp = getFileStamp(pProfile->m_pFile);
1939 if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
1941 pProfile->m_Stamp = Stamp;
1943 loadProfile(pProfile->m_pFile, pProfile);
1946 else
1948 #ifdef DEBUG_OSL_PROFILE
1949 SAL_INFO("sal.osl", "READ/WRITELOCK MODE");
1950 #endif
1952 /* A readlock file could not be written */
1953 if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
1955 return nullptr;
1961 return pProfile;
1964 static bool releaseProfile(osl_TProfileImpl* pProfile)
1966 if ( pProfile == nullptr )
1968 return false;
1971 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
1973 if (pProfile->m_Flags & FLG_AUTOOPEN)
1975 return osl_closeProfile(static_cast<oslProfile>(pProfile));
1977 else
1979 #ifdef DEBUG_OSL_PROFILE
1980 SAL_INFO("sal.osl", "DEFAULT MODE");
1981 #endif
1982 if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
1983 osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
1985 if (pProfile->m_Flags & FLG_MODIFIED)
1986 storeProfile(pProfile, false);
1988 closeFileImpl(pProfile->m_pFile);
1989 pProfile->m_pFile = nullptr;
1994 return true;
1997 static bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile)
1999 char *pChr;
2000 char Buffer[4096] = "";
2001 char Product[132] = "";
2003 ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
2004 aPath[0] = 0;
2006 if (*strPath == L'"')
2008 int i = 0;
2010 strPath++;
2012 while ((strPath[i] != L'"') && (strPath[i] != L'\0'))
2013 i++;
2015 WideCharToMultiByte(CP_ACP,0, o3tl::toW(strPath), i, Product, sizeof(Product), nullptr, nullptr);
2016 Product[i] = '\0';
2017 strPath += i;
2019 if (*strPath == L'"')
2020 strPath++;
2022 if ( (*strPath == L'/') || (*strPath == L'\\') )
2024 strPath++;
2028 else
2030 /* if we have not product identification, do a special handling for soffice.ini */
2031 if (rtl_ustr_ascii_compare(strFile, SVERSION_PROFILE) == 0)
2033 rtl_uString * strSVProfile = nullptr;
2034 rtl_uString * strSVFallback = nullptr;
2035 rtl_uString * strSVLocation = nullptr;
2036 rtl_uString * strSVName = nullptr;
2037 ::osl::LongPathBuffer< char > aDir( MAX_LONG_PATH );
2038 oslProfile hProfile;
2040 rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
2041 rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
2042 rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
2044 /* open sversion.ini in the system directory, and try to locate the entry
2045 with the highest version for StarOffice */
2046 if (osl_getProfileName( strSVFallback, strSVName, &strSVProfile))
2048 hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
2049 if (hProfile)
2051 osl_getProfileSectionEntries(
2052 hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
2054 for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
2056 if ((strnicmp(
2057 pChr, SVERSION_SOFFICE,
2058 sizeof(SVERSION_SOFFICE) - 1)
2059 == 0)
2060 && (stricmp(Product, pChr) < 0))
2062 osl_readProfileString(
2063 hProfile, SVERSION_SECTION, pChr, aDir,
2064 aDir.getBufSizeInSymbols(), "");
2066 /* check for existence of path */
2067 if (access(aDir, 0) >= 0)
2068 strcpy(Product, pChr);
2072 osl_closeProfile(hProfile);
2074 rtl_uString_release(strSVProfile);
2075 strSVProfile = nullptr;
2078 /* open sversion.ini in the users directory, and try to locate the entry
2079 with the highest version for StarOffice */
2080 if ( osl_getProfileName(strSVLocation, strSVName, &strSVProfile) )
2082 hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
2083 if (hProfile)
2085 osl_getProfileSectionEntries(
2086 hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
2088 for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
2090 if ((strnicmp(
2091 pChr, SVERSION_SOFFICE,
2092 sizeof(SVERSION_SOFFICE) - 1)
2093 == 0)
2094 && (stricmp(Product, pChr) < 0))
2096 osl_readProfileString(
2097 hProfile, SVERSION_SECTION, pChr, aDir,
2098 aDir.getBufSizeInSymbols(), "");
2100 /* check for existence of path */
2101 if (access(aDir, 0) >= 0)
2102 strcpy(Product, pChr);
2106 osl_closeProfile(hProfile);
2108 rtl_uString_release(strSVProfile);
2111 rtl_uString_release(strSVFallback);
2112 rtl_uString_release(strSVLocation);
2113 rtl_uString_release(strSVName);
2115 /* remove any trailing build number */
2116 if ((pChr = strrchr(Product, '/')) != nullptr)
2117 *pChr = '\0';
2121 rtl_uString * strExecutable = nullptr;
2122 rtl_uString * strTmp = nullptr;
2123 sal_Int32 nPos;
2125 /* try to find the file in the directory of the executable */
2126 if (osl_getExecutableFile(&strTmp) != osl_Process_E_None)
2127 return false;
2129 /* convert to native path */
2130 if (osl_getSystemPathFromFileURL(strTmp, &strExecutable) != osl_File_E_None)
2132 rtl_uString_release(strTmp);
2133 return false;
2136 rtl_uString_release(strTmp);
2138 DWORD dwPathLen = 0;
2140 /* separate path from filename */
2141 if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L'\\')) == -1)
2143 if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L':')) == -1)
2145 rtl_uString_release(strExecutable);
2146 return false;
2148 else
2150 copy_ustr_n(aPath, strExecutable->buffer, nPos);
2151 aPath[nPos] = 0;
2152 dwPathLen = nPos;
2155 else
2157 copy_ustr_n(aPath, strExecutable->buffer, nPos);
2158 dwPathLen = nPos;
2159 aPath[dwPathLen] = 0;
2162 /* if we have no product identification use the executable file name */
2163 if (*Product == 0)
2165 WideCharToMultiByte(CP_ACP,0, o3tl::toW(strExecutable->buffer + nPos + 1), -1, Product, sizeof(Product), nullptr, nullptr);
2167 /* remove extension */
2168 if ((pChr = strrchr(Product, '.')) != nullptr)
2169 *pChr = '\0';
2172 rtl_uString_release(strExecutable);
2174 /* remember last subdir */
2175 nPos = rtl_ustr_lastIndexOfChar(aPath, L'\\');
2177 copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
2179 if (*strPath)
2181 copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
2182 dwPathLen += rtl_ustr_getLength(strPath);
2186 ::osl::LongPathBuffer< char > aTmpPath( MAX_LONG_PATH );
2188 WideCharToMultiByte(CP_ACP,0, o3tl::toW(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), nullptr, nullptr);
2190 /* if file not exists, remove any specified subdirectories
2191 like "bin" or "program" */
2193 if (((access(aTmpPath, 0) < 0) && (nPos != -1)) || (*strPath == 0))
2195 static const char *SubDirs[] = SVERSION_DIRS;
2197 unsigned i = 0;
2198 char *pStr = aTmpPath + nPos;
2200 for (i = 0; i < SAL_N_ELEMENTS(SubDirs); i++)
2201 if (strnicmp(pStr + 1, SubDirs[i], strlen(SubDirs[i])) == 0)
2203 if ( *strPath == 0)
2205 strcpy(pStr + 1,SVERSION_USER);
2206 if ( access(aTmpPath, 0) < 0 )
2208 *(pStr+1)='\0';
2210 else
2212 dwPathLen = nPos + MultiByteToWideChar( CP_ACP, 0, SVERSION_USER, -1, o3tl::toW(aPath + nPos + 1), aPath.getBufSizeInSymbols() - (nPos + 1) );
2215 else
2217 copy_ustr_n(aPath + nPos + 1, strPath, rtl_ustr_getLength(strPath)+1);
2218 dwPathLen = nPos + 1 + rtl_ustr_getLength(strPath);
2221 break;
2226 if ((aPath[dwPathLen - 1] != L'/') && (aPath[dwPathLen - 1] != L'\\'))
2228 aPath[dwPathLen++] = L'\\';
2229 aPath[dwPathLen] = 0;
2232 copy_ustr_n(aPath + dwPathLen, strFile, rtl_ustr_getLength(strFile)+1);
2235 ::osl::LongPathBuffer< char > aTmpPath( MAX_LONG_PATH );
2237 WideCharToMultiByte(CP_ACP,0, o3tl::toW(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), nullptr, nullptr);
2239 if ((access(aTmpPath, 0) < 0) && (Product[0] != '\0'))
2241 rtl_uString * strSVFallback = nullptr;
2242 rtl_uString * strSVProfile = nullptr;
2243 rtl_uString * strSVLocation = nullptr;
2244 rtl_uString * strSVName = nullptr;
2245 oslProfile hProfile;
2247 rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
2248 rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
2249 rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
2251 /* open sversion.ini in the system directory, and try to locate the entry
2252 with the highest version for StarOffice */
2253 if (osl_getProfileName(strSVLocation, strSVName, &strSVProfile))
2255 hProfile = osl_openProfile(
2256 strSVProfile, osl_Profile_READLOCK);
2257 if (hProfile)
2259 osl_readProfileString(
2260 hProfile, SVERSION_SECTION, Product, Buffer,
2261 sizeof(Buffer), "");
2262 osl_closeProfile(hProfile);
2264 /* if not found, try the fallback */
2265 if (Buffer[0] == '\0')
2267 if (osl_getProfileName(
2268 strSVFallback, strSVName, &strSVProfile))
2270 hProfile = osl_openProfile(
2271 strSVProfile, osl_Profile_READLOCK);
2272 if (hProfile)
2274 osl_readProfileString(
2275 hProfile, SVERSION_SECTION, Product,
2276 Buffer, sizeof(Buffer), "");
2280 osl_closeProfile(hProfile);
2283 if (Buffer[0] != '\0')
2285 dwPathLen = MultiByteToWideChar(
2286 CP_ACP, 0, Buffer, -1, o3tl::toW(aPath), aPath.getBufSizeInSymbols() );
2287 dwPathLen -=1;
2289 /* build full path */
2290 if ((aPath[dwPathLen - 1] != L'/')
2291 && (aPath[dwPathLen - 1] != L'\\'))
2293 copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
2296 if (*strPath)
2298 copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
2299 dwPathLen += rtl_ustr_getLength(strPath);
2301 else
2303 ::osl::LongPathBuffer< char > aTmpPath2( MAX_LONG_PATH );
2304 int n;
2306 if ((n = WideCharToMultiByte(
2307 CP_ACP,0, o3tl::toW(aPath), -1, aTmpPath2,
2308 aTmpPath2.getBufSizeInSymbols(), nullptr, nullptr))
2309 > 0)
2311 strcpy(aTmpPath2 + n, SVERSION_USER);
2312 if (access(aTmpPath2, 0) >= 0)
2314 dwPathLen += MultiByteToWideChar(
2315 CP_ACP, 0, SVERSION_USER, -1,
2316 o3tl::toW(aPath + dwPathLen),
2317 aPath.getBufSizeInSymbols() - dwPathLen );
2324 rtl_uString_release(strSVProfile);
2327 rtl_uString_release(strSVFallback);
2328 rtl_uString_release(strSVLocation);
2329 rtl_uString_release(strSVName);
2333 aPath[dwPathLen] = 0;
2335 /* copy filename */
2336 copy_ustr_n(strProfile, aPath, dwPathLen+1);
2338 return true;
2341 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */