xref: /aoo41x/main/sal/osl/w32/profile.cxx (revision cdf0e10c)
1 /*************************************************************************
2 *
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
6 *
7 * OpenOffice.org - a multi-platform office productivity suite
8 *
9 * This file is part of OpenOffice.org.
10 *
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
14 *
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org.  If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
25 *
26 ************************************************************************/
27 
28 #include "system.h"
29 
30 #include "file_url.h"
31 #include "path_helper.hxx"
32 
33 #include <osl/diagnose.h>
34 #include <osl/profile.h>
35 #include <osl/process.h>
36 #include <osl/file.h>
37 #include <osl/util.h>
38 #include <rtl/alloc.h>
39 #include <algorithm>
40 using std::min;
41 static inline void copy_ustr_n( void *dest, const void *source, size_t length ) { rtl_copyMemory(dest, source, length*sizeof(sal_Unicode)); }
42 
43 #define LINES_INI       32
44 #define LINES_ADD       10
45 #define SECTIONS_INI    5
46 #define SECTIONS_ADD    3
47 #define ENTRIES_INI     5
48 #define ENTRIES_ADD     3
49 
50 
51 #define STR_INI_EXTENSION   L".ini"
52 #define STR_INI_METAHOME	"?~"
53 #define STR_INI_METASYS		"?$"
54 #define STR_INI_METACFG		"?^"
55 #define STR_INI_METAINS		"?#"
56 
57 #define STR_INI_BOOLYES     "yes"
58 #define STR_INI_BOOLON      "on"
59 #define STR_INI_BOOLONE     "1"
60 #define STR_INI_BOOLNO      "no"
61 #define STR_INI_BOOLOFF     "off"
62 #define STR_INI_BOOLZERO    "0"
63 
64 #define FLG_USER            0x00FF
65 #define FLG_AUTOOPEN        0x0100
66 #define FLG_MODIFIED        0x0200
67 
68 #define SVERSION_LOCATION   STR_INI_METACFG
69 #define SVERSION_FALLBACK   STR_INI_METASYS
70 #define SVERSION_NAME   	"sversion"
71 #define SVERSION_SECTION    "Versions"
72 #define SVERSION_SOFFICE    "StarOffice"
73 #define SVERSION_PROFILE    "soffice.ini"
74 #define SVERSION_OPTION     "userid:"
75 #define SVERSION_DIRS		{ "bin", "program" }
76 #define SVERSION_USER       "user"
77 
78 #define DEFAULT_PMODE   (_S_IREAD | _S_IWRITE)
79 
80 #define _BUILD_STR_(n)	# n
81 #define BUILD_STR(n)	_BUILD_STR_(n)
82 
83 
84 /*#define DEBUG_OSL_PROFILE 1*/
85 /*#define TRACE_OSL_PROFILE 1*/
86 
87 
88 /*****************************************************************************/
89 /* Data Type Definition */
90 /*****************************************************************************/
91 
92 typedef FILETIME osl_TStamp;
93 
94 typedef enum _osl_TLockMode
95 {
96 	un_lock, read_lock, write_lock
97 } osl_TLockMode;
98 
99 typedef struct _osl_TFile
100 {
101 	HANDLE  m_Handle;
102 	sal_Char*   m_pReadPtr;
103 	sal_Char    m_ReadBuf[512];
104 /*  	sal_Char*   m_pWritePtr; */
105 /*  	sal_Char    m_WriteBuf[512]; */
106     sal_Char*   m_pWriteBuf;
107     sal_uInt32  m_nWriteBufLen;
108     sal_uInt32  m_nWriteBufFree;
109 } osl_TFile;
110 
111 typedef struct _osl_TProfileEntry
112 {
113 	sal_uInt32   	m_Line;
114 	sal_uInt32    	m_Offset;
115 	sal_uInt32      m_Len;
116 } osl_TProfileEntry;
117 
118 typedef struct _osl_TProfileSection
119 {
120 	sal_uInt32          m_Line;
121 	sal_uInt32          m_Offset;
122 	sal_uInt32          m_Len;
123 	sal_uInt32          m_NoEntries;
124 	sal_uInt32          m_MaxEntries;
125 	osl_TProfileEntry*  m_Entries;
126 } osl_TProfileSection;
127 
128 
129 /*
130 	Profile-data structure hidden behind oslProfile:
131 */
132 typedef struct _osl_TProfileImpl
133 {
134 	sal_uInt32  m_Flags;
135 	osl_TFile*  m_pFile;
136 	osl_TStamp  m_Stamp;
137 	sal_uInt32  m_NoLines;
138 	sal_uInt32  m_MaxLines;
139 	sal_uInt32  m_NoSections;
140 	sal_uInt32  m_MaxSections;
141 	sal_Char**  m_Lines;
142 	rtl_uString *m_strFileName;
143 	osl_TProfileSection* m_Sections;
144 } osl_TProfileImpl;
145 
146 
147 /*****************************************************************************/
148 /* Static Module Function Declarations */
149 /*****************************************************************************/
150 
151 static osl_TFile*           openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags  );
152 static osl_TStamp           closeFileImpl(osl_TFile* pFile);
153 static sal_Bool             lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
154 static sal_Bool             rewindFile(osl_TFile* pFile, sal_Bool bTruncate);
155 static osl_TStamp           getFileStamp(osl_TFile* pFile);
156 
157 static sal_Bool             getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen);
158 static sal_Bool             putLine(osl_TFile* pFile, const sal_Char *pszLine);
159 static const sal_Char*      stripBlanks(const sal_Char* String, sal_uInt32* pLen);
160 static const sal_Char*      addLine(osl_TProfileImpl* pProfile, const sal_Char* Line);
161 static const sal_Char*      insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo);
162 static void                 removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
163 static void                 setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
164                                      sal_uInt32 NoEntry, sal_uInt32 Line,
165                                      const sal_Char* Entry, sal_uInt32 Len);
166 static sal_Bool             addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
167                                      int Line, const sal_Char* Entry, sal_uInt32 Len);
168 static void                 removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
169 static sal_Bool             addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len);
170 static void                 removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
171 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
172                                       const sal_Char* Entry, sal_uInt32 *pNoEntry);
173 static sal_Bool             loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
174 static sal_Bool             storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup);
175 static osl_TProfileImpl*    acquireProfile(oslProfile Profile, sal_Bool bWriteable);
176 static sal_Bool             releaseProfile(osl_TProfileImpl* pProfile);
177 static sal_Bool             lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile);
178 
179 static sal_Bool writeProfileImpl (osl_TFile* pFile);
180 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
181 static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
182 static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension);
183 
184 static sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName);
185 
186 /*****************************************************************************/
187 /* Exported Module Functions */
188 /*****************************************************************************/
189 
190 oslProfile SAL_CALL osl_openProfile(rtl_uString *strProfileName, sal_uInt32 Flags)
191 {
192 	osl_TFile*        pFile = NULL;
193 	osl_TProfileImpl* pProfile;
194 	rtl_uString		  *FileName=NULL;
195 
196 #ifdef TRACE_OSL_PROFILE
197     OSL_TRACE("In  osl_openProfile\n");
198 #endif
199 	OSL_VERIFY(strProfileName);
200 
201 	if (rtl_uString_getLength(strProfileName) == 0 )
202 	{
203 		OSL_VERIFY(osl_getProfileName(NULL, NULL, &FileName));
204 	}
205 	else
206 	{
207 		rtl_uString_assign(&FileName, strProfileName);
208 	}
209 
210 
211 	osl_getSystemPathFromFileURL(FileName, &FileName);
212 
213 
214 #ifdef DEBUG_OSL_PROFILE
215     Flags=osl_Profile_FLUSHWRITE;
216 
217     // OSL_TRACE("opening '%s'\n",FileName);
218     if ( Flags == osl_Profile_DEFAULT )
219     {
220         OSL_TRACE("with osl_Profile_DEFAULT \n");
221     }
222     if ( Flags & osl_Profile_SYSTEM )
223     {
224         OSL_TRACE("with osl_Profile_SYSTEM \n");
225     }
226     if ( Flags & osl_Profile_READLOCK )
227     {
228         OSL_TRACE("with osl_Profile_READLOCK \n");
229     }
230     if ( Flags & osl_Profile_WRITELOCK )
231     {
232         OSL_TRACE("with osl_Profile_WRITELOCK \n");
233     }
234 /*      if ( Flags & osl_Profile_READWRITE ) */
235 /*      { */
236 /*          OSL_TRACE("with osl_Profile_READWRITE \n"); */
237 /*      } */
238     if ( Flags & osl_Profile_FLUSHWRITE )
239     {
240         OSL_TRACE("with osl_Profile_FLUSHWRITE \n");
241     }
242 #endif
243 
244     if ( (! (Flags & osl_Profile_SYSTEM)) && ( (pFile = openFileImpl(FileName, Flags) ) == NULL ) )
245     {
246 #ifdef TRACE_OSL_PROFILE
247 	    OSL_TRACE("Out osl_openProfile [not opened]\n");
248 #endif
249 		if( FileName)
250 			rtl_uString_release( FileName);
251 
252         return (NULL);
253     }
254 
255 
256 	pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl));
257 
258 
259 	pProfile->m_Flags = Flags & FLG_USER;
260 	osl_getSystemPathFromFileURL(strProfileName, &pProfile->m_strFileName);
261 //	rtl_uString_assign(&pProfile->m_strFileName, strProfileName);
262 
263 	if (Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ))
264 		pProfile->m_pFile = pFile;
265 
266 	pProfile->m_Stamp = getFileStamp(pFile);
267 
268 	loadProfile(pFile, pProfile);
269 
270 	if (pProfile->m_pFile == NULL)
271 		closeFileImpl(pFile);
272 
273 #ifdef TRACE_OSL_PROFILE
274     OSL_TRACE("Out osl_openProfile [ok]\n");
275 #endif
276 	if( FileName)
277 		rtl_uString_release( FileName);
278 
279 	return (pProfile);
280 }
281 
282 sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
283 {
284 	osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
285 
286 #ifdef TRACE_OSL_PROFILE
287     OSL_TRACE("In  osl_closeProfile\n");
288 #endif
289 
290     if ( Profile == 0 )
291     {
292 #ifdef TRACE_OSL_PROFILE
293         OSL_TRACE("Out osl_closeProfile [profile==0]\n");
294 #endif
295         return sal_False;
296     }
297 
298 	if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
299 	{
300         pProfile = acquireProfile(Profile,sal_True);
301 
302         if ( pProfile != 0 )
303         {
304 			if ( !( pProfile->m_Flags & osl_Profile_READLOCK )  && ( pProfile->m_Flags & FLG_MODIFIED ) )
305 			{
306 /*  				if (pProfile->m_pFile == NULL) */
307 /*  					pProfile->m_pFile = openFileImpl(pProfile->m_Filename, sal_True); */
308 
309 				storeProfile(pProfile, sal_False);
310 			}
311 		}
312 		else
313 		{
314 			pProfile = acquireProfile(Profile,sal_False);
315 		}
316 
317 		if ( pProfile == 0 )
318 		{
319 #ifdef TRACE_OSL_PROFILE
320 			OSL_TRACE("Out osl_closeProfile [pProfile==0]\n");
321 #endif
322 			return sal_False;
323 		}
324 
325 		if (pProfile->m_pFile != NULL)
326 			closeFileImpl(pProfile->m_pFile);
327 	}
328 
329 	pProfile->m_pFile = NULL;
330 	rtl_uString_release(pProfile->m_strFileName);
331 	pProfile->m_strFileName = NULL;
332 
333 	/* release whole profile data types memory */
334 	if ( pProfile->m_NoLines > 0)
335 	{
336 		unsigned int index=0;
337 		if ( pProfile->m_Lines != 0 )
338 		{
339 			for ( index = 0 ; index < pProfile->m_NoLines ; ++index)
340 			{
341 				if ( pProfile->m_Lines[index] != 0 )
342 				{
343 					free(pProfile->m_Lines[index]);
344 				}
345 			}
346 			free(pProfile->m_Lines);
347 		}
348 		if ( pProfile->m_Sections != 0 )
349 		{
350 			/*osl_TProfileSection* pSections=pProfile->m_Sections;*/
351 			for ( index = 0 ; index < pProfile->m_NoSections ; ++index )
352 			{
353 				if ( pProfile->m_Sections[index].m_Entries != 0 )
354 				{
355 					free(pProfile->m_Sections[index].m_Entries);
356 				}
357 			}
358 			free(pProfile->m_Sections);
359 		}
360 
361 	}
362 	free(pProfile);
363 
364 #ifdef TRACE_OSL_PROFILE
365     OSL_TRACE("Out osl_closeProfile [ok]\n");
366 #endif
367 	return (sal_True);
368 }
369 
370 
371 sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
372 {
373 	osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile;
374 	osl_TFile* pFile;
375 	sal_Bool bRet = sal_False;
376 
377 #ifdef TRACE_OSL_PROFILE
378     OSL_TRACE("In  osl_flushProfile()\n");
379 #endif
380 
381     if ( pProfile == 0 )
382     {
383 #ifdef TRACE_OSL_PROFILE
384         OSL_TRACE("Out osl_flushProfile() [pProfile == 0]\n");
385 #endif
386         return sal_False;
387     }
388 
389 	pFile = pProfile->m_pFile;
390     if ( !( pFile != 0 && pFile->m_Handle >= 0 ) )
391     {
392 #ifdef TRACE_OSL_PROFILE
393         OSL_TRACE("Out osl_flushProfile() [invalid file]\n");
394 #endif
395         return sal_False;
396     }
397 
398 	if ( pProfile->m_Flags & FLG_MODIFIED )
399 	{
400 #ifdef DEBUG_OSL_PROFILE
401         OSL_TRACE("swapping to storeprofile\n");
402 #endif
403 		bRet = storeProfile(pProfile,sal_False);
404 	}
405 
406 #ifdef TRACE_OSL_PROFILE
407     OSL_TRACE("Out osl_flushProfile() [ok]\n");
408 #endif
409     return bRet;
410 }
411 
412 static sal_Bool writeProfileImpl(osl_TFile* pFile)
413 {
414 	DWORD BytesWritten=0;
415 	BOOL bRet;
416 
417 #ifdef TRACE_OSL_PROFILE
418     OSL_TRACE("In  osl_writeProfileImpl()\n");
419 #endif
420 
421     if ( !( pFile != 0 && pFile->m_Handle != INVALID_HANDLE_VALUE ) || ( pFile->m_pWriteBuf == 0 ) )
422     {
423 #ifdef TRACE_OSL_PROFILE
424         OSL_TRACE("Out osl_writeProfileImpl() [invalid args]\n");
425 #endif
426         return sal_False;
427     }
428 
429 #ifdef DEBUG_OSL_PROFILE
430 /*    OSL_TRACE("File Buffer in writeProfileImpl '%s' size == '%i' '%i'(%i)\n",
431       pFile->m_pWriteBuf,pFile->m_nWriteBufLen,strlen(pFile->m_pWriteBuf),pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);*/
432 #endif
433 
434     bRet=WriteFile(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree,&BytesWritten,NULL);
435 
436     if ( bRet == 0 || BytesWritten <= 0 )
437     {
438 		OSL_ENSURE(bRet,"WriteFile failed!!!");
439 
440         OSL_TRACE("write failed '%s'\n",strerror(errno));
441 
442 /*        OSL_TRACE("Out osl_writeProfileImpl() [write '%s']\n",strerror(errno));*/
443         return (sal_False);
444     }
445 
446     free(pFile->m_pWriteBuf);
447     pFile->m_pWriteBuf=0;
448 	pFile->m_nWriteBufLen=0;
449 	pFile->m_nWriteBufFree=0;
450 
451 #ifdef TRACE_OSL_PROFILE
452     OSL_TRACE("Out osl_writeProfileImpl() [ok]\n");
453 #endif
454     return sal_True;
455 }
456 
457 
458 sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
459 							  const sal_Char* pszSection, const sal_Char* pszEntry,
460 							  sal_Char* pszString, sal_uInt32 MaxLen,
461 							  const sal_Char* pszDefault)
462 {
463 	sal_uInt32    NoEntry;
464 	const sal_Char* pStr = 0;
465 	osl_TProfileSection* pSec;
466 	osl_TProfileImpl*    pProfile = 0;
467 
468 
469 #ifdef TRACE_OSL_PROFILE
470     OSL_TRACE("In  osl_readProfileString\n");
471 #endif
472 
473     pProfile = acquireProfile(Profile, sal_False);
474 
475 	if (pProfile == NULL)
476     {
477 #ifdef TRACE_OSL_PROFILE
478         OSL_TRACE("Out osl_readProfileString [pProfile==0]\n");
479 #endif
480 
481 
482 		return (sal_False);
483     }
484 
485 
486 	if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
487 	{
488 		if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
489 			(NoEntry < pSec->m_NoEntries) &&
490 			((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
491 							'=')) != NULL))
492 			pStr++;
493 		else
494 			pStr = pszDefault;
495 
496 		if ( pStr != 0 )
497 		{
498 			pStr = stripBlanks(pStr, NULL);
499 			MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
500 			pStr = stripBlanks(pStr, &MaxLen);
501 			strncpy(pszString, pStr, MaxLen);
502 			pszString[MaxLen] = '\0';
503 		}
504 	}
505 	else
506 	{
507         ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
508 
509 		WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
510 		GetPrivateProfileString(pszSection, pszEntry, pszDefault, pszString, MaxLen, aFileName);
511 	}
512 
513 	releaseProfile(pProfile);
514 
515 	if ( pStr == 0 )
516     {
517 #ifdef TRACE_OSL_PROFILE
518         OSL_TRACE("Out osl_readProfileString [pStr==0]\n");
519 #endif
520 
521 
522 		return (sal_False);
523     }
524 
525 #ifdef TRACE_OSL_PROFILE
526     OSL_TRACE("Out osl_readProfileString [ok]\n");
527 #endif
528 
529 
530 
531 
532 	return (sal_True);
533 }
534 
535 
536 sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
537 							const sal_Char* pszSection, const sal_Char* pszEntry,
538 							sal_Bool Default)
539 {
540 	sal_Char Line[32];
541 
542 #ifdef TRACE_OSL_PROFILE
543     OSL_TRACE("In  osl_readProfileBool\n");
544 #endif
545 
546 	if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
547 	{
548 		if ((stricmp(Line, STR_INI_BOOLYES) == 0) ||
549 			(stricmp(Line, STR_INI_BOOLON)  == 0) ||
550 			(stricmp(Line, STR_INI_BOOLONE) == 0))
551 			Default = sal_True;
552 		else
553 			if ((stricmp(Line, STR_INI_BOOLNO)   == 0) ||
554 				(stricmp(Line, STR_INI_BOOLOFF)  == 0) ||
555 				(stricmp(Line, STR_INI_BOOLZERO) == 0))
556 				Default = sal_False;
557 	}
558 
559 #ifdef TRACE_OSL_PROFILE
560     OSL_TRACE("Out osl_readProfileBool [ok]\n");
561 #endif
562 
563 	return (Default);
564 }
565 
566 
567 sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
568 							  const sal_Char* pszSection, const sal_Char* pszEntry,
569 							  sal_uInt32 FirstId, const sal_Char* Strings[],
570 							  sal_uInt32 Default)
571 {
572 	sal_uInt32    i;
573 	sal_Char        Line[256];
574 
575 #ifdef TRACE_OSL_PROFILE
576     OSL_TRACE("In  osl_readProfileIdent\n");
577 #endif
578 
579 	if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
580 	{
581 		i = 0;
582 		while (Strings[i] != NULL)
583 		{
584 			if (stricmp(Line, Strings[i]) == 0)
585 			{
586 				Default = i + FirstId;
587 				break;
588 			}
589 			i++;
590 		}
591 	}
592 
593 #ifdef TRACE_OSL_PROFILE
594     OSL_TRACE("Out osl_readProfileIdent [ok]\n");
595 #endif
596 	return (Default);
597 }
598 
599 sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
600 							   const sal_Char* pszSection, const sal_Char* pszEntry,
601 							   const sal_Char* pszString)
602 {
603 	sal_uInt32    i;
604     sal_Bool bRet = sal_False;
605 	sal_uInt32    NoEntry;
606 	const sal_Char* pStr;
607 	sal_Char        Line[4096];
608 	osl_TProfileSection* pSec;
609 	osl_TProfileImpl*    pProfile = 0;
610 
611 #ifdef TRACE_OSL_PROFILE
612     OSL_TRACE("In  osl_writeProfileString\n");
613 #endif
614 
615     pProfile = acquireProfile(Profile, sal_True);
616 
617 	if (pProfile == NULL)
618     {
619 #ifdef TRACE_OSL_PROFILE
620         OSL_TRACE("Out osl_writeProfileString [pProfile==0]\n");
621 #endif
622 		return (sal_False);
623     }
624 
625 
626 	if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
627 	{
628 		if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL)
629 		{
630 			Line[0] = '\0';
631 			addLine(pProfile, Line);
632 
633 			Line[0] = '[';
634 			strcpy(&Line[1], pszSection);
635 			Line[1 + strlen(pszSection)] = ']';
636 			Line[2 + strlen(pszSection)] = '\0';
637 
638 			if (((pStr = addLine(pProfile, Line)) == NULL) ||
639 				(! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
640 			{
641 				releaseProfile(pProfile);
642 #ifdef TRACE_OSL_PROFILE
643                 OSL_TRACE("Out osl_writeProfileString [not added]\n");
644 #endif
645 				return (sal_False);
646 			}
647 
648 			pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
649 			NoEntry = pSec->m_NoEntries;
650 		}
651 
652 		Line[0] = '\0';
653 		strcpy(&Line[0], pszEntry);
654 		Line[0 + strlen(pszEntry)] = '=';
655 		strcpy(&Line[1 + strlen(pszEntry)], pszString);
656 
657 		if (NoEntry >= pSec->m_NoEntries)
658 		{
659 			if (pSec->m_NoEntries > 0)
660 				i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
661 			else
662 				i = pSec->m_Line + 1;
663 
664 			if (((pStr = insertLine(pProfile, Line, i)) == NULL) ||
665 				(! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
666 			{
667 				releaseProfile(pProfile);
668 #ifdef TRACE_OSL_PROFILE
669                 OSL_TRACE("Out osl_writeProfileString [not inserted]\n");
670 #endif
671 				return (sal_False);
672 			}
673 
674 			pProfile->m_Flags |= FLG_MODIFIED;
675 		}
676 		else
677 		{
678 			i = pSec->m_Entries[NoEntry].m_Line;
679 			free(pProfile->m_Lines[i]);
680 			pProfile->m_Lines[i] = strdup(Line);
681 			setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
682 
683 			pProfile->m_Flags |= FLG_MODIFIED;
684 		}
685 	}
686 	else
687 	{
688         ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
689 
690 		WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
691 		WritePrivateProfileString(pszSection, pszEntry, pszString, aFileName);
692 	}
693 
694     bRet = releaseProfile(pProfile);
695 #ifdef TRACE_OSL_PROFILE
696     OSL_TRACE("Out osl_writeProfileString [ok]\n");
697 #endif
698 	return bRet;
699 }
700 
701 
702 sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
703 							 const sal_Char* pszSection, const sal_Char* pszEntry,
704 							 sal_Bool Value)
705 {
706     sal_Bool bRet = sal_False;
707 
708 #ifdef TRACE_OSL_PROFILE
709     OSL_TRACE("In  osl_writeProfileBool\n");
710 #endif
711 
712 	if (Value)
713 		bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
714 	else
715 		bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
716 
717 #ifdef TRACE_OSL_PROFILE
718     OSL_TRACE("Out osl_writeProfileBool [ok]\n");
719 #endif
720 
721     return bRet;
722 }
723 
724 
725 sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
726 							  const sal_Char* pszSection, const sal_Char* pszEntry,
727 							  sal_uInt32 FirstId, const sal_Char* Strings[],
728 							  sal_uInt32 Value)
729 {
730 	int i, n;
731     sal_Bool bRet = sal_False;
732 
733 #ifdef TRACE_OSL_PROFILE
734     OSL_TRACE("In  osl_writeProfileIdent\n");
735 #endif
736 
737 	for (n = 0; Strings[n] != NULL; n++);
738 
739 	if ((i = Value - FirstId) >= n)
740 		bRet=sal_False;
741 	else
742 		bRet=osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
743 
744 #ifdef TRACE_OSL_PROFILE
745     OSL_TRACE("Out osl_writeProfileIdent\n");
746 #endif
747     return bRet;
748 }
749 
750 
751 sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
752 							   const sal_Char *pszSection, const sal_Char *pszEntry)
753 {
754 	sal_uInt32    NoEntry;
755 	osl_TProfileSection* pSec;
756 	osl_TProfileImpl*    pProfile = 0;
757     sal_Bool bRet = sal_False;
758 
759 #ifdef TRACE_OSL_PROFILE
760     OSL_TRACE("In  osl_removeProfileEntry\n");
761 #endif
762 
763     pProfile = acquireProfile(Profile, sal_True);
764 
765 	if (pProfile == NULL)
766     {
767 #ifdef TRACE_OSL_PROFILE
768         OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n");
769 #endif
770 
771 
772 		return (sal_False);
773     }
774 
775 
776 	if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
777 	{
778 		if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
779 			(NoEntry < pSec->m_NoEntries))
780 		{
781 			removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
782 			removeEntry(pSec, NoEntry);
783 			if (pSec->m_NoEntries == 0)
784 			{
785 				removeLine(pProfile, pSec->m_Line);
786 
787 				/* remove any empty separation line */
788 				if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
789 		            removeLine(pProfile, pSec->m_Line - 1);
790 
791 				removeSection(pProfile, pSec);
792 			}
793 
794 			pProfile->m_Flags |= FLG_MODIFIED;
795 		}
796 	}
797 	else
798 	{
799         ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
800 
801 		WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
802 		WritePrivateProfileString(pszSection, pszEntry, NULL, aFileName);
803 	}
804 
805     bRet = releaseProfile(pProfile);
806 #ifdef TRACE_OSL_PROFILE
807     OSL_TRACE("Out osl_removeProfileEntry [ok]\n");
808 #endif
809 	return bRet;
810 }
811 
812 
813 sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const sal_Char *pszSection,
814 	   							    sal_Char* pszBuffer, sal_uInt32 MaxLen)
815 {
816 	sal_uInt32    i, n = 0;
817 	sal_uInt32    NoEntry;
818 	osl_TProfileSection* pSec;
819 	osl_TProfileImpl*    pProfile = 0;
820 
821 #ifdef TRACE_OSL_PROFILE
822     OSL_TRACE("In  osl_getProfileSectionEntries\n");
823 #endif
824 
825     pProfile = acquireProfile(Profile, sal_False);
826 
827     if (pProfile == NULL)
828     {
829 #ifdef TRACE_OSL_PROFILE
830         OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]\n");
831 #endif
832 
833 
834 		return (0);
835     }
836 
837 
838 	if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
839 	{
840 		if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL)
841 		{
842 			if (MaxLen != 0)
843 			{
844 				for (i = 0; i < pSec->m_NoEntries; i++)
845 				{
846 					if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
847 					{
848 						strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
849 								[pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
850 						n += pSec->m_Entries[i].m_Len;
851 						pszBuffer[n++] = '\0';
852 					}
853 					else
854 						break;
855 
856 				}
857 
858 				pszBuffer[n++] = '\0';
859 			}
860 			else
861 			{
862 				for (i = 0; i < pSec->m_NoEntries; i++)
863 					n += pSec->m_Entries[i].m_Len + 1;
864 
865 				n += 1;
866 			}
867 		}
868 		else
869 			n = 0;
870 	}
871 	else
872 	{
873         ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
874 
875 		WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
876 		n = GetPrivateProfileString(pszSection, NULL, NULL, pszBuffer, MaxLen, aFileName);
877 	}
878 
879 	releaseProfile(pProfile);
880 
881 #ifdef TRACE_OSL_PROFILE
882     OSL_TRACE("Out osl_getProfileSectionEntries [ok]\n");
883 #endif
884 
885 	return (n);
886 }
887 
888 
889 sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName)
890 {
891 	sal_Bool bFailed;
892     ::osl::LongPathBuffer< sal_Unicode > aFile( MAX_LONG_PATH );
893     ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
894 	sal_uInt32  nFileLen = 0;
895 	sal_uInt32  nPathLen = 0;
896 
897 	rtl_uString * strTmp = NULL;
898 	oslFileError nError;
899 
900 	/* build file name */
901 	if (strName && strName->length)
902 	{
903 		if( ::sal::static_int_cast< sal_uInt32 >( strName->length ) >= aFile.getBufSizeInSymbols() )
904 			return sal_False;
905 
906 		copy_ustr_n( aFile, strName->buffer, strName->length+1);
907 		nFileLen = strName->length;
908 
909 		if (rtl_ustr_indexOfChar( aFile, L'.' ) == -1)
910 		{
911 			if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
912 				return sal_False;
913 
914 			/* add default extension */
915 			copy_ustr_n( aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1 );
916 			nFileLen += wcslen(STR_INI_EXTENSION);
917 		}
918 	}
919 	else
920 	{
921 		rtl_uString *strProgName = NULL;
922 		sal_Unicode *pProgName;
923 		sal_Int32 nOffset = 0;
924 		sal_Int32 nLen;
925 		sal_Int32 nPos;
926 
927 		if (osl_getExecutableFile(&strProgName) != osl_Process_E_None)
928 			return sal_False;
929 
930 		/* remove path and extension from filename */
931 		pProgName = strProgName->buffer;
932 		nLen = strProgName->length ;
933 
934 		if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'/' )) != -1)
935 			nOffset = nPos + 1;
936 		else if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L':' )) != -1)
937 			nOffset = nPos + 1;
938 
939 		if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'.' )) != -1 )
940 			nLen -= 4;
941 
942 		if ((nFileLen = nLen - nOffset) >= aFile.getBufSizeInSymbols())
943 			return sal_False;
944 
945 		copy_ustr_n(aFile, pProgName + nOffset, nFileLen);
946 
947 		if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
948 			return sal_False;
949 
950 		/* add default extension */
951 		copy_ustr_n(aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1);
952 		nFileLen += wcslen(STR_INI_EXTENSION);
953 
954 		rtl_uString_release( strProgName );
955 	}
956 
957 	if (aFile[0] == 0)
958 		return sal_False;
959 
960 	/* build directory path */
961 	if (strPath && strPath->length)
962 	{
963 		sal_Unicode *pPath = rtl_uString_getStr(strPath);
964 		sal_Int32 nLen = rtl_uString_getLength(strPath);
965 
966 		if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAHOME) , STR_INI_METAHOME) == 0) &&
967             ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)] == '/')))
968 		{
969 			rtl_uString * strHome = NULL;
970 			oslSecurity security = osl_getCurrentSecurity();
971 
972 			bFailed = ! osl_getHomeDir(security, &strHome);
973 			osl_freeSecurityHandle(security);
974 
975 			if (bFailed) return (sal_False);
976 
977 			if ( ::sal::static_int_cast< sal_uInt32 >( strHome->length ) >= aPath.getBufSizeInSymbols())
978 				return sal_False;
979 
980 			copy_ustr_n( aPath, strHome->buffer, strHome->length+1);
981 			nPathLen = strHome->length;
982 
983 			if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METAHOME))
984 			{
985 				pPath += RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
986 				nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
987 
988 				if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
989 					return sal_False;
990 
991 				copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
992 				nPathLen += nLen;
993 			}
994 
995 			rtl_uString_release(strHome);
996 		}
997 
998 		else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METACFG), STR_INI_METACFG) == 0) &&
999 			((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METACFG)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METACFG)] == '/')))
1000 		{
1001 			rtl_uString * strConfig = NULL;
1002 			oslSecurity security = osl_getCurrentSecurity();
1003 
1004 			bFailed = ! osl_getConfigDir(security, &strConfig);
1005 			osl_freeSecurityHandle(security);
1006 
1007 			if (bFailed) return (sal_False);
1008 
1009 			if ( ::sal::static_int_cast< sal_uInt32 >( strConfig->length ) >= aPath.getBufSizeInSymbols())
1010 				return sal_False;
1011 
1012 			copy_ustr_n( aPath, strConfig->buffer, strConfig->length+1 );
1013 			nPathLen = strConfig->length;
1014 
1015 			if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METACFG))
1016 			{
1017 				pPath += RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
1018 				nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
1019 
1020 				if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
1021 					return sal_False;
1022 
1023 				copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
1024 				nPathLen += nLen;
1025 			}
1026 
1027 			rtl_uString_release(strConfig);
1028 		}
1029 
1030 		else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METASYS), STR_INI_METASYS) == 0) &&
1031 			((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METASYS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METASYS)] == '/')))
1032 		{
1033 			if (((nPathLen = GetWindowsDirectoryW(::osl::mingw_reinterpret_cast<LPWSTR>(aPath), aPath.getBufSizeInSymbols())) == 0) || (nPathLen >= aPath.getBufSizeInSymbols()))
1034 				return (sal_False);
1035 
1036 			if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METASYS))
1037 			{
1038 				pPath += RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
1039 				nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
1040 
1041 				if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
1042 					return sal_False;
1043 
1044 				copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
1045 				nPathLen += nLen;
1046 			}
1047 		}
1048 
1049 		else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAINS), STR_INI_METAINS) == 0) &&
1050             ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAINS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '/') ||
1051                 (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '"') ) )
1052 		{
1053 			if (! lookupProfile(pPath + RTL_CONSTASCII_LENGTH(STR_INI_METAINS), aFile, aPath))
1054 				return (sal_False);
1055 
1056 			nPathLen = rtl_ustr_getLength(aPath);
1057 		}
1058 
1059 		else if( ::sal::static_int_cast< sal_uInt32 >( nLen ) < aPath.getBufSizeInSymbols())
1060 		{
1061 			copy_ustr_n(aPath, pPath, nLen+1);
1062 			nPathLen = rtl_ustr_getLength(aPath);
1063 		}
1064 		else
1065 			return sal_False;
1066 	}
1067 	else
1068 	{
1069 		rtl_uString * strConfigDir = NULL;
1070 		oslSecurity security = osl_getCurrentSecurity();
1071 
1072 		bFailed = ! osl_getConfigDir(security, &strConfigDir);
1073 		osl_freeSecurityHandle(security);
1074 
1075 		if (bFailed) return (sal_False);
1076 		if ( ::sal::static_int_cast< sal_uInt32 >( strConfigDir->length ) >= aPath.getBufSizeInSymbols() )
1077 			return sal_False;
1078 
1079 		copy_ustr_n(aPath, strConfigDir->buffer, strConfigDir->length+1);
1080 		nPathLen = strConfigDir->length;
1081 	}
1082 
1083 	if (nPathLen && (aPath[nPathLen - 1] != L'/') && (aPath[nPathLen - 1] != L'\\'))
1084 	{
1085 		aPath[nPathLen++] = L'\\';
1086 		aPath[nPathLen] = 0;
1087 	}
1088 
1089 	if (nPathLen + nFileLen >= aPath.getBufSizeInSymbols())
1090 		return sal_False;
1091 
1092 	/* append file name */
1093 	copy_ustr_n(aPath + nPathLen, aFile, nFileLen+1);
1094 	nPathLen += nFileLen;
1095 
1096 	/* copy filename */
1097 	rtl_uString_newFromStr_WithLength(&strTmp, aPath, nPathLen);
1098 	nError = osl_getFileURLFromSystemPath(strTmp, strProfileName);
1099 	rtl_uString_release(strTmp);
1100 
1101 	return (sal_Bool) (nError == osl_File_E_None);
1102 }
1103 
1104 
1105 sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, sal_Char* pszBuffer, sal_uInt32 MaxLen)
1106 {
1107 	sal_uInt32    i, n = 0;
1108 	osl_TProfileSection* pSec;
1109 	osl_TProfileImpl*    pProfile = acquireProfile(Profile, sal_False);
1110 
1111 	if (pProfile == NULL)
1112 		return (0);
1113 
1114 	if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
1115 	{
1116 		if (MaxLen != 0)
1117 		{
1118  			for (i = 0; i < pProfile->m_NoSections; i++)
1119 			{
1120 				pSec = &pProfile->m_Sections[i];
1121 
1122 				if ((n + pSec->m_Len + 1) < MaxLen)
1123 				{
1124 					strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
1125 					        pSec->m_Len);
1126 					n += pSec->m_Len;
1127 					pszBuffer[n++] = '\0';
1128 				}
1129 				else
1130 					break;
1131 			}
1132 
1133 			pszBuffer[n++] = '\0';
1134 		}
1135 		else
1136 		{
1137  			for (i = 0; i < pProfile->m_NoSections; i++)
1138 				n += pProfile->m_Sections[i].m_Len + 1;
1139 
1140 			n += 1;
1141 		}
1142 	}
1143 	else
1144 	{
1145         ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
1146 
1147 		WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
1148 		n = GetPrivateProfileSectionNames(pszBuffer, MaxLen, aFileName);
1149 	}
1150 
1151 	releaseProfile(pProfile);
1152 
1153 	return (n);
1154 }
1155 
1156 
1157 
1158 
1159 /*****************************************************************************/
1160 /* Static Module Functions */
1161 /*****************************************************************************/
1162 
1163 static osl_TStamp getFileStamp(osl_TFile* pFile)
1164 {
1165 	FILETIME FileTime;
1166 
1167 	if ((pFile->m_Handle == INVALID_HANDLE_VALUE) ||
1168 		(! GetFileTime(pFile->m_Handle, NULL, NULL, &FileTime)))
1169 		memset(&FileTime, 0, sizeof(FileTime));
1170 
1171 	return (FileTime);
1172 }
1173 
1174 
1175 
1176 static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
1177 {
1178 	sal_Bool     status = sal_False;
1179 	OVERLAPPED  Overlapped;
1180 
1181 	if (pFile->m_Handle == INVALID_HANDLE_VALUE)
1182 		return (sal_False);
1183 
1184 	memset(&Overlapped, 0, sizeof(Overlapped));
1185 
1186 	switch (eMode)
1187 	{
1188 		case un_lock:
1189 			status = (sal_Bool) UnlockFileEx(
1190                 pFile->m_Handle, 0, 0xFFFFFFFF, 0, &Overlapped);
1191 			break;
1192 
1193 		case read_lock:
1194 			status = (sal_Bool) LockFileEx(
1195                 pFile->m_Handle, 0, 0, 0xFFFFFFFF, 0, &Overlapped);
1196 			break;
1197 
1198 		case write_lock:
1199 			status = (sal_Bool) LockFileEx(
1200                 pFile->m_Handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 0xFFFFFFFF, 0,
1201                 &Overlapped);
1202 			break;
1203 	}
1204 
1205 	return (status);
1206 }
1207 
1208 
1209 
1210 
1211 
1212 
1213 
1214 
1215 
1216 
1217 
1218 
1219 
1220 
1221 
1222 
1223 
1224 
1225 
1226 
1227 
1228 
1229 
1230 
1231 
1232 
1233 
1234 
1235 
1236 
1237 
1238 
1239 
1240 
1241 
1242 
1243 
1244 
1245 
1246 
1247 
1248 
1249 
1250 
1251 
1252 
1253 
1254 
1255 
1256 
1257 
1258 
1259 
1260 
1261 static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags )
1262 {
1263 	osl_TFile* pFile = reinterpret_cast< osl_TFile*>( calloc( 1, sizeof(osl_TFile) ) );
1264 	sal_Bool bWriteable = sal_False;
1265 
1266 /*    if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE | osl_Profile_READWRITE ) )*/
1267     if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
1268     {
1269 #ifdef DEBUG_OSL_PROFILE
1270         OSL_TRACE("setting bWriteable to TRUE\n");
1271 #endif
1272         bWriteable=sal_True;
1273     }
1274 
1275 	if (! bWriteable)
1276 	{
1277 #if 0
1278 //#ifdef DEBUG_OSL_PROFILE
1279         OSL_TRACE("opening '%s' read only\n",pszFilename);
1280 #endif
1281 
1282 		pFile->m_Handle = CreateFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strFileName )), GENERIC_READ,
1283 										  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1284 										  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1285 
1286         /* mfe: argghh!!! do not check if the file could be openend */
1287         /*      default mode expects it that way!!!                 */
1288 	}
1289 	else
1290 	{
1291 #ifdef DEBUG_OSL_PROFILE
1292         OSL_TRACE("opening '%s' read/write\n",pszFilename);
1293 #endif
1294 
1295 		if ((pFile->m_Handle = CreateFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strFileName )), GENERIC_READ | GENERIC_WRITE,
1296 											   FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1297 											   OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
1298 			== INVALID_HANDLE_VALUE)
1299 		{
1300 			free(pFile);
1301 			return (NULL);
1302 		}
1303 	}
1304 
1305 	pFile->m_pWriteBuf=0;
1306 	pFile->m_nWriteBufFree=0;
1307 	pFile->m_nWriteBufLen=0;
1308 
1309     if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1310     {
1311 #ifdef DEBUG_OSL_PROFILE
1312         OSL_TRACE("locking '%s' file\n",pszFilename);
1313 #endif
1314 
1315 		lockFile(pFile, bWriteable ? write_lock : read_lock);
1316 	}
1317 
1318     /* mfe: new WriteBuf obsolete */
1319 /*	pFile->m_pWritePtr = pFile->m_Buf;*/
1320 /*	pFile->m_pReadPtr  = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);*/
1321 
1322 	return (pFile);
1323 }
1324 
1325 
1326 
1327 
1328 
1329 
1330 
1331 
1332 
1333 static osl_TStamp closeFileImpl(osl_TFile* pFile)
1334 {
1335 	osl_TStamp stamp = {0, 0};
1336 
1337     if ( pFile == 0 )
1338     {
1339         return stamp;
1340     }
1341 
1342 	if (pFile->m_Handle != INVALID_HANDLE_VALUE)
1343 	{
1344        /* mfe: new WriteBuf obsolete */
1345         /* we just closing the file here, DO NOT write, it has to be handled in higher levels */
1346 /*		if (pFile->m_pWritePtr > pFile->m_Buf)*/
1347 /*		{*/
1348 /*			DWORD Bytes;*/
1349 
1350 /*			WriteFile(pFile->m_Handle, pFile->m_WriteBuf,*/
1351 /*					  pFile->m_pWritePtr - pFile->m_WriteBuf,*/
1352 /*					  &Bytes, NULL);*/
1353 /*		}*/
1354 
1355 		stamp = getFileStamp(pFile);
1356 
1357 		lockFile(pFile, un_lock);
1358 
1359 		CloseHandle(pFile->m_Handle);
1360 		pFile->m_Handle = INVALID_HANDLE_VALUE;
1361 	}
1362 
1363 	if ( pFile->m_pWriteBuf != 0 )
1364 	{
1365 		free(pFile->m_pWriteBuf);
1366 	}
1367 
1368 	free(pFile);
1369 
1370 	return(stamp);
1371 }
1372 
1373 
1374 
1375 
1376 
1377 
1378 
1379 
1380 static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate)
1381 {
1382 	if (pFile->m_Handle != INVALID_HANDLE_VALUE)
1383 	{
1384         /* mfe: new WriteBuf obsolete */
1385         /* we just closing the file here, DO NOT write, it has to be handled in higher levels */
1386 /*		if (pFile->m_pWritePtr > pFile->m_WriteBuf)*/
1387 /*		{*/
1388 /*			DWORD Bytes;*/
1389 
1390 /*			WriteFile(pFile->m_Handle, pFile->m_WriteBuf,*/
1391 /*					  pFile->m_pWritePtr - pFile->m_WriteBuf,*/
1392 /*					  &Bytes, NULL);*/
1393 
1394 /*			pFile->m_pWritePtr = pFile->m_WriteBuf;*/
1395 /*		}*/
1396 
1397 		pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1398 
1399 		SetFilePointer(pFile->m_Handle, 0, NULL, FILE_BEGIN);
1400 
1401 		if (bTruncate)
1402 			SetEndOfFile(pFile->m_Handle);
1403 	}
1404 
1405 	return (sal_True);
1406 }
1407 
1408 
1409 
1410 
1411 
1412 
1413 
1414 
1415 
1416 
1417 static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen)
1418 {
1419     DWORD Max;
1420 	size_t Free, Bytes;
1421 	sal_Char* pChr;
1422 	sal_Char* pLine = (sal_Char *)pszLine;
1423 
1424 	if (pFile->m_Handle == INVALID_HANDLE_VALUE)
1425 		return (sal_False);
1426 
1427 	MaxLen -= 1;
1428 
1429 	do
1430 	{
1431 		Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
1432 
1433 		if (Bytes <= 1)
1434 		{
1435 			/* refill buffer */
1436 			memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
1437 			pFile->m_pReadPtr = pFile->m_ReadBuf;
1438 
1439 			Free = sizeof(pFile->m_ReadBuf) - Bytes;
1440 
1441 			if (! ReadFile(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free, &Max, NULL))
1442 			{
1443 				*pLine = '\0';
1444 				return (sal_False);
1445 			}
1446 
1447 			if (Max < Free)
1448 			{
1449 				if ((Max == 0) && (pLine == pszLine))
1450 				{
1451 					*pLine = '\0';
1452 					return (sal_False);
1453 				}
1454 
1455 				pFile->m_ReadBuf[Bytes + Max] = '\0';
1456 			}
1457 		}
1458 
1459 		for (pChr = pFile->m_pReadPtr;
1460 			 (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
1461 			 (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
1462 			 pChr++);
1463 
1464 		Max = min(pChr - pFile->m_pReadPtr, MaxLen);
1465 		memcpy(pLine, pFile->m_pReadPtr, Max);
1466 		MaxLen -= Max;
1467 		pLine  += Max;
1468 
1469 		if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
1470 		{
1471 			if (*pChr != '\0')
1472 			{
1473 				if ((pChr[0] == '\r') && (pChr[1] == '\n'))
1474 					pChr += 2;
1475 				else
1476 					pChr += 1;
1477 			}
1478 
1479 			if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
1480 				(*pChr == '\0'))
1481 				pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1482 
1483 			*pLine = '\0';
1484 
1485 			/* setting MaxLen to -1 indicates terminating read loop */
1486 			MaxLen = -1;
1487 		}
1488 
1489 		pFile->m_pReadPtr = pChr;
1490 	}
1491 	while (MaxLen > 0);
1492 
1493 	return (sal_True);
1494 }
1495 
1496 
1497 
1498 
1499 
1500 
1501 
1502 
1503 
1504 
1505 static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine)
1506 {
1507 	unsigned int Len = strlen(pszLine);
1508 
1509 #ifdef DEBUG_OSL_PROFILE
1510 	int strLen=0;
1511 #endif
1512 
1513 	if ( pFile == 0 || pFile->m_Handle < 0 )
1514     {
1515 		return (sal_False);
1516     }
1517 
1518     if ( pFile->m_pWriteBuf == 0 )
1519     {
1520         pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3);
1521         pFile->m_nWriteBufLen = Len+3;
1522 		pFile->m_nWriteBufFree = Len+3;
1523     }
1524     else
1525     {
1526         if ( pFile->m_nWriteBufFree <= Len + 3 )
1527         {
1528             sal_Char* pTmp;
1529 
1530             pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) );
1531             if ( pTmp == 0 )
1532             {
1533                 return sal_False;
1534             }
1535             pFile->m_pWriteBuf = pTmp;
1536             pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
1537             pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
1538             memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
1539         }
1540     }
1541 
1542 
1543 
1544     memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
1545 #ifdef DEBUG_OSL_PROFILE
1546 	strLen = strlen(pFile->m_pWriteBuf);
1547 #endif
1548     pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\r';
1549     pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\n';
1550     pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 2]='\0';
1551 
1552     pFile->m_nWriteBufFree-=Len+2;
1553 
1554 #ifdef DEBUG_OSL_PROFILE
1555 /*    OSL_TRACE("File Buffer in _putLine '%s' '%i'(%i)\n",pFile->m_pWriteBuf,strlen(pFile->m_pWriteBuf),pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);*/
1556 #endif
1557 
1558 	return (sal_True);
1559 }
1560 
1561 /* platform specific end */
1562 
1563 
1564 static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen)
1565 {
1566 	if ( (pLen != NULL) && ( *pLen != 0 ) )
1567 	{
1568 		while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
1569 			(*pLen)--;
1570 
1571 		while ((*String == ' ') || (*String == '\t'))
1572 		{
1573 			String++;
1574 			(*pLen)--;
1575 		}
1576 	}
1577 	else
1578 		while ((*String == ' ') || (*String == '\t'))
1579 			String++;
1580 
1581 	return (String);
1582 }
1583 
1584 static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line)
1585 {
1586 	if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1587 	{
1588 		if (pProfile->m_Lines == NULL)
1589 		{
1590 			pProfile->m_MaxLines = LINES_INI;
1591 			pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
1592 			memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
1593 		}
1594 		else
1595 		{
1596 			unsigned int index=0;
1597 			unsigned int oldmax=pProfile->m_MaxLines;
1598 
1599 			pProfile->m_MaxLines += LINES_ADD;
1600 			pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines, pProfile->m_MaxLines * sizeof(sal_Char *));
1601 
1602 			for ( index = oldmax ; index < pProfile->m_MaxLines ; ++index )
1603 			{
1604 				pProfile->m_Lines[index]=0;
1605 			}
1606 		}
1607 
1608 		if (pProfile->m_Lines == NULL)
1609 		{
1610 			pProfile->m_NoLines  = 0;
1611 			pProfile->m_MaxLines = 0;
1612 			return (NULL);
1613 		}
1614 
1615 	}
1616 
1617 	if ( pProfile->m_Lines != 0 && pProfile->m_Lines[pProfile->m_NoLines] != 0 )
1618 	{
1619 			free(pProfile->m_Lines[pProfile->m_NoLines]);
1620 	}
1621 	pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
1622 
1623 	return (pProfile->m_Lines[pProfile->m_NoLines - 1]);
1624 }
1625 
1626 static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo)
1627 {
1628 	if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1629 	{
1630 		if (pProfile->m_Lines == NULL)
1631 		{
1632 			pProfile->m_MaxLines = LINES_INI;
1633 			pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
1634 			memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
1635 		}
1636 		else
1637 		{
1638 			pProfile->m_MaxLines += LINES_ADD;
1639 			pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
1640 												 pProfile->m_MaxLines * sizeof(sal_Char *));
1641 
1642 			memset(&pProfile->m_Lines[pProfile->m_NoLines],
1643 				0,
1644 				(pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(sal_Char*));
1645 		}
1646 
1647 		if (pProfile->m_Lines == NULL)
1648 		{
1649 			pProfile->m_NoLines  = 0;
1650 			pProfile->m_MaxLines = 0;
1651 			return (NULL);
1652 		}
1653 	}
1654 
1655 	LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo;
1656 
1657 	if (LineNo < pProfile->m_NoLines)
1658 	{
1659 		sal_uInt32 i, n;
1660 		osl_TProfileSection* pSec;
1661 
1662 		memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
1663 				(pProfile->m_NoLines - LineNo) * sizeof(sal_Char *));
1664 
1665 
1666 		/* adjust line references */
1667 		for (i = 0; i < pProfile->m_NoSections; i++)
1668 		{
1669 			pSec = &pProfile->m_Sections[i];
1670 
1671 			if (pSec->m_Line >= LineNo)
1672 				pSec->m_Line++;
1673 
1674 			for (n = 0; n < pSec->m_NoEntries; n++)
1675 				if (pSec->m_Entries[n].m_Line >= LineNo)
1676 					pSec->m_Entries[n].m_Line++;
1677 		}
1678 	}
1679 
1680 	pProfile->m_NoLines++;
1681 
1682 	pProfile->m_Lines[LineNo] = strdup(Line);
1683 
1684 	return (pProfile->m_Lines[LineNo]);
1685 }
1686 
1687 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
1688 {
1689 	if (LineNo < pProfile->m_NoLines)
1690 	{
1691 		free(pProfile->m_Lines[LineNo]);
1692 		pProfile->m_Lines[LineNo]=0;
1693 		if (pProfile->m_NoLines - LineNo > 1)
1694 		{
1695 			sal_uInt32 i, n;
1696 			osl_TProfileSection* pSec;
1697 
1698 			memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
1699 					(pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *));
1700 
1701 			memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
1702 				0,
1703 				(pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(sal_Char*));
1704 
1705 			/* adjust line references */
1706 			for (i = 0; i < pProfile->m_NoSections; i++)
1707 			{
1708 				pSec = &pProfile->m_Sections[i];
1709 
1710 				if (pSec->m_Line > LineNo)
1711 					pSec->m_Line--;
1712 
1713 				for (n = 0; n < pSec->m_NoEntries; n++)
1714 					if (pSec->m_Entries[n].m_Line > LineNo)
1715 						pSec->m_Entries[n].m_Line--;
1716 			}
1717 		}
1718 		else
1719 		{
1720 			pProfile->m_Lines[LineNo] = 0;
1721 		}
1722 
1723 		pProfile->m_NoLines--;
1724 	}
1725 
1726 	return;
1727 }
1728 
1729 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
1730 					 sal_uInt32 NoEntry, sal_uInt32 Line,
1731 					 const sal_Char* Entry, sal_uInt32 Len)
1732 {
1733 	Entry = stripBlanks(Entry, &Len);
1734 	pSection->m_Entries[NoEntry].m_Line   = Line;
1735 	pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
1736 	pSection->m_Entries[NoEntry].m_Len    = Len;
1737 
1738 	return;
1739 }
1740 
1741 static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
1742 						int Line, const sal_Char* Entry, sal_uInt32 Len)
1743 {
1744 	if (pSection != NULL)
1745 	{
1746 		if (pSection->m_NoEntries >= pSection->m_MaxEntries)
1747 		{
1748 			if (pSection->m_Entries == NULL)
1749 			{
1750 				pSection->m_MaxEntries = ENTRIES_INI;
1751 				pSection->m_Entries = (osl_TProfileEntry *)malloc(
1752 								pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
1753 			}
1754 			else
1755 			{
1756 				pSection->m_MaxEntries += ENTRIES_ADD;
1757 				pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries,
1758 								pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
1759 			}
1760 
1761 			if (pSection->m_Entries == NULL)
1762 			{
1763 				pSection->m_NoEntries  = 0;
1764 				pSection->m_MaxEntries = 0;
1765 				return (sal_False);
1766 			}
1767 		}
1768 
1769 		pSection->m_NoEntries++;
1770 
1771 		Entry = stripBlanks(Entry, &Len);
1772 		setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
1773 				 Entry, Len);
1774 
1775 		return (sal_True);
1776 	}
1777 
1778 	return (sal_False);
1779 }
1780 
1781 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
1782 {
1783 	if (NoEntry < pSection->m_NoEntries)
1784 	{
1785 		if (pSection->m_NoEntries - NoEntry > 1)
1786 		{
1787 			memmove(&pSection->m_Entries[NoEntry],
1788 					&pSection->m_Entries[NoEntry + 1],
1789 					(pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
1790 			pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
1791 			pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
1792 			pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
1793 		}
1794 
1795 		pSection->m_NoEntries--;
1796 	}
1797 
1798 	return;
1799 }
1800 
1801 static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len)
1802 {
1803 	if (pProfile->m_NoSections >= pProfile->m_MaxSections)
1804 	{
1805 		if (pProfile->m_Sections == NULL)
1806 		{
1807 			pProfile->m_MaxSections = SECTIONS_INI;
1808 			pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1809 			memset(pProfile->m_Sections,0,pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1810 		}
1811 		else
1812 		{
1813 			unsigned int index=0;
1814 			unsigned int oldmax=pProfile->m_MaxSections;
1815 
1816 			pProfile->m_MaxSections += SECTIONS_ADD;
1817 			pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections,
1818 										  pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1819 			for ( index = oldmax ; index < pProfile->m_MaxSections ; ++index )
1820 			{
1821 				pProfile->m_Sections[index].m_Entries=0;
1822 			}
1823 		}
1824 
1825 		if (pProfile->m_Sections == NULL)
1826 		{
1827 			pProfile->m_NoSections = 0;
1828 			pProfile->m_MaxSections = 0;
1829 			return (sal_False);
1830 		}
1831 	}
1832 
1833 	pProfile->m_NoSections++;
1834 
1835 	if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != 0 )
1836 	{
1837 		free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
1838 	}
1839 	pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries    = NULL;
1840 	pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries  = 0;
1841 	pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
1842 
1843 	Section = (sal_Char *)stripBlanks(Section, &Len);
1844 	pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
1845 	pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
1846 	pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
1847 
1848 	return (sal_True);
1849 }
1850 
1851 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
1852 {
1853 	sal_uInt32 Section;
1854 
1855 	if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
1856 	{
1857 		free (pSection->m_Entries);
1858 		pSection->m_Entries=0;
1859 		if (pProfile->m_NoSections - Section > 1)
1860 		{
1861 			memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
1862 					(pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
1863 
1864 			memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
1865 				0,
1866 				(pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
1867 			pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = 0;
1868 		}
1869 		else
1870 		{
1871 			pSection->m_Entries = 0;
1872 		}
1873 
1874 		pProfile->m_NoSections--;
1875 	}
1876 
1877 	return;
1878 }
1879 
1880 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
1881                                       const sal_Char* Entry, sal_uInt32 *pNoEntry)
1882 {
1883 static  sal_uInt32    Sect = 0;
1884 		sal_uInt32    i, n;
1885 		sal_uInt32    Len;
1886 		const sal_Char* pStr;
1887 		osl_TProfileSection* pSec = NULL;
1888 
1889 	Len = strlen(Section);
1890 	Section = (sal_Char *)stripBlanks(Section, &Len);
1891 
1892 	n = Sect;
1893 
1894 	for (i = 0; i < pProfile->m_NoSections; i++)
1895 	{
1896 		n %= pProfile->m_NoSections;
1897 		pSec = &pProfile->m_Sections[n];
1898 		if ((Len == pSec->m_Len) &&
1899 			(strnicmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
1900 			 == 0))
1901 			break;
1902 		n++;
1903 	}
1904 
1905 	Sect = n;
1906 
1907 	if (i < pProfile->m_NoSections)
1908 	{
1909 		Len = strlen(Entry);
1910 		Entry = stripBlanks(Entry, &Len);
1911 
1912 		*pNoEntry = pSec->m_NoEntries;
1913 
1914 		for (i = 0; i < pSec->m_NoEntries; i++)
1915 		{
1916 			pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
1917 									 [pSec->m_Entries[i].m_Offset];
1918 			if ((Len == pSec->m_Entries[i].m_Len) &&
1919 				(strnicmp(Entry, pStr, pSec->m_Entries[i].m_Len)
1920 				 == 0))
1921 			{
1922 				*pNoEntry = i;
1923 				break;
1924 			}
1925 		}
1926 	}
1927 	else
1928 		pSec = NULL;
1929 
1930 	return (pSec);
1931 }
1932 
1933 static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
1934 {
1935 	sal_uInt32    i;
1936 	sal_Char*       pStr;
1937 	sal_Char*       pChar;
1938 	sal_Char        Line[4096];
1939 
1940 	pProfile->m_NoLines    = 0;
1941 	pProfile->m_NoSections = 0;
1942 
1943 	OSL_VERIFY(rewindFile(pFile, sal_False));
1944 
1945 	while (getLine(pFile, Line, sizeof(Line)))
1946 	{
1947 		if (! addLine(pProfile, Line))
1948 			return (sal_False);
1949 	}
1950 
1951 	for (i = 0; i < pProfile->m_NoLines; i++)
1952 	{
1953 		pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL);
1954 
1955 		if ((*pStr == '\0') || (*pStr == ';'))
1956 			continue;
1957 
1958 		if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) ||
1959 			((pChar - pStr) <= 2))
1960 		{
1961 			/* insert entry */
1962 
1963 			if (pProfile->m_NoSections < 1)
1964 				continue;
1965 
1966 			if ((pChar = strchr(pStr, '=')) == NULL)
1967 				pChar = pStr + strlen(pStr);
1968 
1969 			if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
1970 						   i, pStr, pChar - pStr))
1971 				return (sal_False);
1972 		}
1973 		else
1974 		{
1975 			/* new section */
1976 
1977 			if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
1978 				return (sal_False);
1979 		}
1980 	}
1981 
1982 	return (sal_True);
1983 }
1984 
1985 
1986 
1987 
1988 
1989 static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup)
1990 {
1991 #ifdef TRACE_OSL_PROFILE
1992     OSL_TRACE("In  storeProfile\n");
1993 #endif
1994 
1995 	if (pProfile->m_Lines != NULL)
1996 	{
1997 		if (pProfile->m_Flags & FLG_MODIFIED)
1998 		{
1999 			sal_uInt32 i;
2000 
2001 			osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
2002 
2003 			if ( pTmpFile == 0 )
2004 			{
2005 				return sal_False;
2006 			}
2007 
2008 			OSL_VERIFY(rewindFile(pTmpFile, sal_True));
2009 
2010 			for (i = 0; i < pProfile->m_NoLines; i++)
2011 			{
2012 				OSL_VERIFY(putLine(pTmpFile, pProfile->m_Lines[i]));
2013 			}
2014 
2015 			if ( ! writeProfileImpl(pTmpFile) )
2016             {
2017 				if ( pTmpFile->m_pWriteBuf != 0 )
2018 				{
2019 					free(pTmpFile->m_pWriteBuf);
2020 				}
2021 
2022 				pTmpFile->m_pWriteBuf=0;
2023 				pTmpFile->m_nWriteBufLen=0;
2024 				pTmpFile->m_nWriteBufFree=0;
2025 
2026 #ifdef TRACE_OSL_PROFILE
2027                 OSL_TRACE("Out storeProfile [not flushed]\n");
2028 #endif
2029 				closeFileImpl(pTmpFile);
2030 
2031                 return sal_False;
2032             }
2033 
2034 			pProfile->m_Flags &= ~FLG_MODIFIED;
2035 
2036 			closeFileImpl(pProfile->m_pFile);
2037 			closeFileImpl(pTmpFile);
2038 
2039 			osl_ProfileSwapProfileNames(pProfile);
2040 
2041 /*			free(pProfile->m_pFile);*/
2042 /*			free(pTmpFile);*/
2043 
2044 			pProfile->m_pFile = openFileImpl(pProfile->m_strFileName,pProfile->m_Flags);
2045 
2046 		}
2047 
2048 		if (bCleanup)
2049 		{
2050 			while (pProfile->m_NoLines > 0)
2051 				removeLine(pProfile, pProfile->m_NoLines - 1);
2052 
2053 			free(pProfile->m_Lines);
2054 			pProfile->m_Lines = NULL;
2055 			pProfile->m_MaxLines = 0;
2056 
2057 			while (pProfile->m_NoSections > 0)
2058 				removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
2059 
2060 			free(pProfile->m_Sections);
2061 			pProfile->m_Sections = NULL;
2062 			pProfile->m_MaxSections = 0;
2063 		}
2064 	}
2065 
2066 #ifdef TRACE_OSL_PROFILE
2067     OSL_TRACE("Out storeProfile [ok]\n");
2068 #endif
2069 	return (sal_True);
2070 }
2071 
2072 
2073 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
2074 {
2075 	osl_TFile* pFile=0;
2076 	rtl_uString* ustrExtension=0;
2077 	rtl_uString* ustrTmpName=0;
2078 	oslProfileOption PFlags=0;
2079 
2080 	rtl_uString_newFromAscii(&ustrExtension,"tmp");
2081 
2082 
2083 	/* generate tmp profilename */
2084 	ustrTmpName=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
2085 	rtl_uString_release(ustrExtension);
2086 
2087 	if ( ustrTmpName == 0 )
2088 	{
2089 		return 0;
2090 	}
2091 
2092 
2093 	if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
2094 	{
2095 		PFlags |= osl_Profile_WRITELOCK;
2096 	}
2097 
2098 	/* open this file */
2099 	pFile = openFileImpl(ustrTmpName,pProfile->m_Flags | PFlags);
2100 
2101 
2102 	/* return new pFile */
2103 	return pFile;
2104 }
2105 
2106 
2107 static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
2108 {
2109 	sal_Bool bRet = sal_False;
2110 
2111 	rtl_uString* ustrBakFile=0;
2112 	rtl_uString* ustrTmpFile=0;
2113 	rtl_uString* ustrIniFile=0;
2114 	rtl_uString* ustrExtension=0;
2115 
2116 
2117 	rtl_uString_newFromAscii(&ustrExtension,"bak");
2118 
2119 	ustrBakFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
2120 	rtl_uString_release(ustrExtension);
2121 	ustrExtension=0;
2122 
2123 
2124 	rtl_uString_newFromAscii(&ustrExtension,"ini");
2125 
2126 	ustrIniFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
2127 	rtl_uString_release(ustrExtension);
2128 	ustrExtension=0;
2129 
2130 
2131 	rtl_uString_newFromAscii(&ustrExtension,"tmp");
2132 
2133 	ustrTmpFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
2134 	rtl_uString_release(ustrExtension);
2135 	ustrExtension=0;
2136 
2137 
2138 	/* unlink bak */
2139 	DeleteFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrBakFile )) );
2140 
2141 	/* rename ini bak */
2142 	MoveFileExW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrIniFile )), reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrBakFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
2143 
2144 	/* rename tmp ini */
2145 	MoveFileExW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrTmpFile )), reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrIniFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
2146 
2147 	return bRet;
2148 }
2149 
2150 
2151 static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension)
2152 {
2153 	rtl_uString* ustrNewFileName=0;
2154 	rtl_uString* ustrOldExtension = 0;
2155 	sal_Unicode* pExtensionBuf = 0;
2156 	sal_Unicode* pFileNameBuf  = 0;
2157 	sal_Int32 nIndex = -1;
2158 
2159 	pFileNameBuf = rtl_uString_getStr(ustrFileName);
2160 
2161 	rtl_uString_newFromAscii(&ustrOldExtension,".");
2162 
2163 	pExtensionBuf = rtl_uString_getStr(ustrOldExtension);
2164 
2165 	nIndex = rtl_ustr_lastIndexOfChar(pFileNameBuf,*pExtensionBuf);
2166 
2167 	rtl_uString_newReplaceStrAt(&ustrNewFileName,
2168 								ustrFileName,
2169 								nIndex+1,
2170 								3,
2171 								ustrExtension);
2172 
2173 	return ustrNewFileName;
2174 }
2175 
2176 
2177 static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable)
2178 {
2179 	osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
2180     oslProfileOption PFlags=0;
2181 
2182 
2183     if ( bWriteable )
2184     {
2185 /*          PFlags = osl_Profile_DEFAULT | osl_Profile_READWRITE; */
2186         PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
2187     }
2188     else
2189     {
2190         PFlags = osl_Profile_DEFAULT;
2191     }
2192 
2193 
2194 	if (pProfile == NULL)
2195 	{
2196 #ifdef DEBUG_OSL_PROFILE
2197         OSL_TRACE("AUTOOPEN MODE\n");
2198 #endif
2199 
2200 
2201 
2202 		if ( ( pProfile = (osl_TProfileImpl*)osl_openProfile( NULL, PFlags ) ) != NULL )
2203         {
2204 			pProfile->m_Flags |= FLG_AUTOOPEN;
2205         }
2206 	}
2207 	else
2208 	{
2209 #ifdef DEBUG_OSL_PROFILE
2210         OSL_TRACE("try to acquire\n");
2211 #endif
2212 
2213 
2214 
2215 		if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
2216 		{
2217 			if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
2218                                         osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
2219 			{
2220 				osl_TStamp Stamp;
2221 #ifdef DEBUG_OSL_PROFILE
2222                 OSL_TRACE("DEFAULT MODE\n");
2223 #endif
2224                 pProfile->m_pFile = openFileImpl(
2225                     pProfile->m_strFileName, pProfile->m_Flags | PFlags);
2226 				if (!pProfile->m_pFile)
2227 					return NULL;
2228 
2229 				Stamp = getFileStamp(pProfile->m_pFile);
2230 
2231 				if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
2232 				{
2233 					pProfile->m_Stamp = Stamp;
2234 
2235 					loadProfile(pProfile->m_pFile, pProfile);
2236 				}
2237 			}
2238 			else
2239             {
2240 #ifdef DEBUG_OSL_PROFILE
2241                 OSL_TRACE("READ/WRITELOCK MODE\n");
2242 #endif
2243 
2244 
2245 				/* A readlock file could not be written */
2246                 if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
2247                 {
2248                     return (NULL);
2249                 }
2250             }
2251 		}
2252 	}
2253 
2254 	return (pProfile);
2255 }
2256 
2257 static sal_Bool releaseProfile(osl_TProfileImpl* pProfile)
2258 {
2259 #ifdef TRACE_OSL_PROFILE
2260     OSL_TRACE("In  releaseProfile\n");
2261 #endif
2262 
2263     if ( pProfile == 0 )
2264     {
2265 #ifdef TRACE_OSL_PROFILE
2266         OSL_TRACE("Out releaseProfile [profile==0]\n");
2267 #endif
2268         return sal_False;
2269     }
2270 
2271 	if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
2272 	{
2273 		if (pProfile->m_Flags & FLG_AUTOOPEN)
2274         {
2275 #ifdef TRACE_OSL_PROFILE
2276         OSL_TRACE("Out releaseProfile [AUTOOPEN]\n");
2277 #endif
2278 			return (osl_closeProfile((oslProfile)pProfile));
2279         }
2280 		else
2281 		{
2282 #ifdef DEBUG_OSL_PROFILE
2283         OSL_TRACE("DEFAULT MODE\n");
2284 #endif
2285         if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
2286                                     osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
2287 			{
2288 				if (pProfile->m_Flags & FLG_MODIFIED)
2289 					storeProfile(pProfile, sal_False);
2290 
2291 				closeFileImpl(pProfile->m_pFile);
2292 				pProfile->m_pFile = NULL;
2293 			}
2294 		}
2295 	}
2296 
2297 #ifdef TRACE_OSL_PROFILE
2298     OSL_TRACE("Out releaseProfile [ok]\n");
2299 #endif
2300 	return (sal_True);
2301 }
2302 
2303 static sal_Bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile)
2304 {
2305 	sal_Char *pChr, *pStr;
2306 	sal_Char Buffer[4096] = "";
2307 	sal_Char Product[132] = "";
2308 
2309     ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
2310     aPath[0] = 0;
2311 	DWORD dwPathLen = 0;
2312 
2313 	if (*strPath == L'"')
2314 	{
2315 		int i = 0;
2316 
2317 		strPath++;
2318 
2319 		while ((strPath[i] != L'"') && (strPath[i] != L'\0'))
2320 			i++;
2321 
2322 		WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(strPath), i, Product, sizeof(Product), NULL, NULL);
2323 		Product[i] = '\0';
2324 		strPath += i;
2325 
2326 		if (*strPath == L'"')
2327 			strPath++;
2328 
2329 		if ( (*strPath == L'/') || (*strPath == L'\\') )
2330 		{
2331 			strPath++;
2332 		}
2333 	}
2334 
2335 	else
2336 	{
2337 		/* if we have not product identfication, do a special handling for soffice.ini */
2338 		if (rtl_ustr_ascii_compare(strFile, SVERSION_PROFILE) == 0)
2339 		{
2340 			rtl_uString * strSVProfile  = NULL;
2341 			rtl_uString * strSVFallback = NULL;
2342 			rtl_uString * strSVLocation = NULL;
2343 			rtl_uString * strSVName     = NULL;
2344             ::osl::LongPathBuffer< sal_Char > aDir( MAX_LONG_PATH );
2345 			oslProfile hProfile;
2346 
2347 			rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
2348 			rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
2349 			rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
2350 
2351 			/* open sversion.ini in the system directory, and try to locate the entry
2352 			   with the highest version for StarOffice */
2353 			if (osl_getProfileName( strSVFallback, strSVName, &strSVProfile))
2354             {
2355 				hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
2356                 if (hProfile)
2357                 {
2358                     osl_getProfileSectionEntries(
2359                         hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
2360 
2361                     for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
2362                     {
2363                         if ((strnicmp(
2364                                  pChr, SVERSION_SOFFICE,
2365                                  sizeof(SVERSION_SOFFICE) - 1)
2366                              == 0)
2367                             && (stricmp(Product, pChr) < 0))
2368                         {
2369                             osl_readProfileString(
2370                                 hProfile, SVERSION_SECTION, pChr, aDir,
2371                                 aDir.getBufSizeInSymbols(), "");
2372 
2373                             /* check for existence of path */
2374                             if (access(aDir, 0) >= 0)
2375                                 strcpy(Product, pChr);
2376                         }
2377                     }
2378 
2379                     osl_closeProfile(hProfile);
2380                 }
2381 				rtl_uString_release(strSVProfile);
2382 				strSVProfile = NULL;
2383 			}
2384 
2385 			/* open sversion.ini in the users directory, and try to locate the entry
2386 			   with the highest version for StarOffice */
2387 			if ((strcmp(SVERSION_LOCATION, SVERSION_FALLBACK) != 0) &&
2388 			    (osl_getProfileName(strSVLocation, strSVName, &strSVProfile)))
2389             {
2390 				hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
2391                 if (hProfile)
2392                 {
2393                     osl_getProfileSectionEntries(
2394                         hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
2395 
2396                     for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
2397                     {
2398                         if ((strnicmp(
2399                                  pChr, SVERSION_SOFFICE,
2400                                  sizeof(SVERSION_SOFFICE) - 1)
2401                              == 0)
2402                             && (stricmp(Product, pChr) < 0))
2403                         {
2404                             osl_readProfileString(
2405                                 hProfile, SVERSION_SECTION, pChr, aDir,
2406                                 aDir.getBufSizeInSymbols(), "");
2407 
2408                             /* check for existence of path */
2409                             if (access(aDir, 0) >= 0)
2410                                 strcpy(Product, pChr);
2411                         }
2412                     }
2413 
2414                     osl_closeProfile(hProfile);
2415                 }
2416 				rtl_uString_release(strSVProfile);
2417 			}
2418 
2419 			rtl_uString_release(strSVFallback);
2420 			rtl_uString_release(strSVLocation);
2421 			rtl_uString_release(strSVName);
2422 
2423 			/* remove any trailing build number */
2424 			if ((pChr = strrchr(Product, '/')) != NULL)
2425 				*pChr = '\0';
2426 		}
2427 	}
2428 
2429 	/* if we have an userid option eg. "-userid:rh[/usr/home/rh/staroffice]",
2430 	   this will supercede all other locations */
2431 	{
2432 		sal_uInt32 n, nArgs = osl_getCommandArgCount();
2433 
2434 		for (n = 0; n < nArgs; n++)
2435 		{
2436 			rtl_uString * strCommandArg = NULL;
2437 
2438 			if ((osl_getCommandArg( n, &strCommandArg ) == osl_Process_E_None) &&
2439 				((strCommandArg->buffer[0] == L'-') || (strCommandArg->buffer[0] == L'+')) &&
2440 				(rtl_ustr_ascii_compare_WithLength(strCommandArg->buffer, RTL_CONSTASCII_LENGTH(SVERSION_OPTION), SVERSION_OPTION)))
2441 			{
2442 				sal_Unicode *pCommandArg = strCommandArg->buffer + RTL_CONSTASCII_LENGTH(SVERSION_OPTION);
2443 				sal_Int32 nStart, nEnd;
2444 
2445 				if (((nStart = rtl_ustr_indexOfChar(pCommandArg, L'[')) != -1) &&
2446 					((nEnd = rtl_ustr_indexOfChar(pCommandArg + nStart + 1, L']')) != -1))
2447 				{
2448 					dwPathLen = nEnd;
2449 				    copy_ustr_n(aPath, pCommandArg + nStart + 1, dwPathLen);
2450 					aPath[dwPathLen] = 0;
2451 
2452 					/* build full path */
2453 					if ((aPath[dwPathLen - 1] != L'/') && (aPath[dwPathLen - 1] != L'\\'))
2454 					{
2455 						copy_ustr_n(aPath + dwPathLen++, L"/", 2);
2456 					}
2457 
2458 					if (*strPath)
2459 					{
2460 						copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
2461 						dwPathLen += rtl_ustr_getLength(strPath);
2462 					}
2463 					else
2464 					{
2465                         ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
2466 						int n;
2467 
2468 						if ((n = WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL)) > 0)
2469 						{
2470 							strcpy(aTmpPath + n, SVERSION_USER);
2471 							if (access(aTmpPath, 0) >= 0)
2472 							{
2473 								dwPathLen += MultiByteToWideChar( CP_ACP, 0, SVERSION_USER, -1, reinterpret_cast<LPWSTR>(aPath + dwPathLen), aPath.getBufSizeInSymbols() - dwPathLen );
2474 							}
2475 						}
2476 					}
2477 
2478 					break;
2479 				}
2480 			}
2481 		}
2482 	}
2483 
2484 
2485 	if (dwPathLen == 0)
2486 	{
2487 		rtl_uString * strExecutable = NULL;
2488 		rtl_uString * strTmp = NULL;
2489 		sal_Int32 nPos;
2490 
2491 		/* try to find the file in the directory of the executbale */
2492 		if (osl_getExecutableFile(&strTmp) != osl_Process_E_None)
2493 			return (sal_False);
2494 
2495 		/* convert to native path */
2496 		if (osl_getSystemPathFromFileURL(strTmp, &strExecutable) != osl_File_E_None)
2497 		{
2498 			rtl_uString_release(strTmp);
2499 			return sal_False;
2500 		}
2501 
2502 		rtl_uString_release(strTmp);
2503 
2504 		/* seperate path from filename */
2505 		if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L'\\')) == -1)
2506 		{
2507 			if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L':')) == -1)
2508 			{
2509 				return sal_False;
2510 			}
2511 			else
2512 			{
2513                 copy_ustr_n(aPath, strExecutable->buffer, nPos);
2514                 aPath[nPos] = 0;
2515                 dwPathLen = nPos;
2516 			}
2517 		}
2518 		else
2519 		{
2520             copy_ustr_n(aPath, strExecutable->buffer, nPos);
2521             dwPathLen = nPos;
2522 			aPath[dwPathLen] = 0;
2523 		}
2524 
2525 		/* if we have no product identification use the executable file name */
2526 		if (*Product == 0)
2527 		{
2528 			WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(strExecutable->buffer + nPos + 1), -1, Product, sizeof(Product), NULL, NULL);
2529 
2530 			/* remove extension */
2531 			if ((pChr = strrchr(Product, '.')) != NULL)
2532 				*pChr = '\0';
2533 		}
2534 
2535 		rtl_uString_release(strExecutable);
2536 
2537 		/* remember last subdir */
2538 		nPos = rtl_ustr_lastIndexOfChar(aPath, L'\\');
2539 
2540 		copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
2541 
2542 		if (*strPath)
2543 		{
2544 			copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
2545 			dwPathLen += rtl_ustr_getLength(strPath);
2546 		}
2547 
2548 		{
2549             ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
2550 
2551 			WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL);
2552 
2553 			/* if file not exists, remove any specified subdirectories
2554 			   like "bin" or "program" */
2555 
2556 			if (((access(aTmpPath, 0) < 0) && (nPos != -1)) || (*strPath == 0))
2557 			{
2558 				static sal_Char *SubDirs[] = SVERSION_DIRS;
2559 
2560 				int i = 0;
2561 				pStr = aTmpPath + nPos;
2562 
2563 				for (i = 0; i < (sizeof(SubDirs) / sizeof(SubDirs[0])); i++)
2564 					if (strnicmp(pStr + 1, SubDirs[i], strlen(SubDirs[i])) == 0)
2565 					{
2566 						if ( *strPath == 0)
2567 						{
2568 							strcpy(pStr + 1,SVERSION_USER);
2569 							if ( access(aTmpPath, 0) < 0 )
2570 							{
2571 								*(pStr+1)='\0';
2572 							}
2573 							else
2574 							{
2575                                 dwPathLen = nPos + MultiByteToWideChar( CP_ACP, 0, SVERSION_USER, -1, reinterpret_cast<LPWSTR>(aPath + nPos + 1), aPath.getBufSizeInSymbols() - (nPos + 1) );
2576 							}
2577 						}
2578 						else
2579 						{
2580 							copy_ustr_n(aPath + nPos + 1, strPath, rtl_ustr_getLength(strPath)+1);
2581 							dwPathLen = nPos + 1 + rtl_ustr_getLength(strPath);
2582 						}
2583 
2584 						break;
2585 					}
2586 			}
2587 		}
2588 
2589 		if ((aPath[dwPathLen - 1] != L'/') && (aPath[dwPathLen - 1] != L'\\'))
2590 		{
2591             aPath[dwPathLen++] = L'\\';
2592 			aPath[dwPathLen] = 0;
2593 		}
2594 
2595 		copy_ustr_n(aPath + dwPathLen, strFile, rtl_ustr_getLength(strFile)+1);
2596 
2597 		{
2598             ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
2599 
2600 			WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL);
2601 
2602 			if ((access(aTmpPath, 0) < 0) && (strlen(Product) > 0))
2603 			{
2604 				rtl_uString * strSVFallback = NULL;
2605 				rtl_uString * strSVProfile  = NULL;
2606 				rtl_uString * strSVLocation = NULL;
2607 				rtl_uString * strSVName     = NULL;
2608 				oslProfile hProfile;
2609 
2610 				rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
2611 				rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
2612 				rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
2613 
2614 				/* open sversion.ini in the system directory, and try to locate the entry
2615 				   with the highest version for StarOffice */
2616 				if (osl_getProfileName(strSVLocation, strSVName, &strSVProfile))
2617                 {
2618 					hProfile = osl_openProfile(
2619                         strSVProfile, osl_Profile_READLOCK);
2620                     if (hProfile)
2621                     {
2622                         osl_readProfileString(
2623                             hProfile, SVERSION_SECTION, Product, Buffer,
2624                             sizeof(Buffer), "");
2625                         osl_closeProfile(hProfile);
2626 
2627                         /* if not found, try the fallback */
2628                         if ((strlen(Buffer) <= 0)
2629                             && (strcmp(SVERSION_LOCATION, SVERSION_FALLBACK)
2630                                 != 0))
2631                         {
2632                             if (osl_getProfileName(
2633                                     strSVFallback, strSVName, &strSVProfile))
2634                             {
2635                                 hProfile = osl_openProfile(
2636                                     strSVProfile, osl_Profile_READLOCK);
2637                                 if (hProfile)
2638                                 {
2639                                     osl_readProfileString(
2640                                         hProfile, SVERSION_SECTION, Product,
2641                                         Buffer, sizeof(Buffer), "");
2642                                 }
2643                             }
2644 
2645                             osl_closeProfile(hProfile);
2646                         }
2647 
2648                         if (strlen(Buffer) > 0)
2649                         {
2650                             dwPathLen = MultiByteToWideChar(
2651                                 CP_ACP, 0, Buffer, -1, ::osl::mingw_reinterpret_cast<LPWSTR>(aPath), aPath.getBufSizeInSymbols() );
2652                             dwPathLen -=1;
2653 
2654                             /* build full path */
2655                             if ((aPath[dwPathLen - 1] != L'/')
2656                                 && (aPath[dwPathLen - 1] != L'\\'))
2657                             {
2658                                 copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
2659                             }
2660 
2661                             if (*strPath)
2662                             {
2663                                 copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
2664                                 dwPathLen += rtl_ustr_getLength(strPath);
2665                             }
2666                             else
2667                             {
2668                                 ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
2669                                 int n;
2670 
2671                                 if ((n = WideCharToMultiByte(
2672                                          CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath,
2673                                          aTmpPath.getBufSizeInSymbols(), NULL, NULL))
2674                                     > 0)
2675                                 {
2676                                     strcpy(aTmpPath + n, SVERSION_USER);
2677                                     if (access(aTmpPath, 0) >= 0)
2678                                     {
2679                                         dwPathLen += MultiByteToWideChar(
2680                                             CP_ACP, 0, SVERSION_USER, -1,
2681                                             reinterpret_cast<LPWSTR>(aPath + dwPathLen),
2682                                             aPath.getBufSizeInSymbols() - dwPathLen );
2683                                     }
2684                                 }
2685                             }
2686                         }
2687                     }
2688 
2689 					rtl_uString_release(strSVProfile);
2690 				}
2691 
2692 				rtl_uString_release(strSVFallback);
2693 				rtl_uString_release(strSVLocation);
2694 				rtl_uString_release(strSVName);
2695 			}
2696 		}
2697 
2698 		aPath[dwPathLen] = 0;
2699 	}
2700 
2701 	/* copy filename */
2702 	copy_ustr_n(strProfile, aPath, dwPathLen+1);
2703 
2704 	return sal_True;
2705 }
2706 
2707 
2708