xref: /AOO41X/main/sal/osl/w32/file_url.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #define UNICODE
29*cdf0e10cSrcweir #define _UNICODE
30*cdf0e10cSrcweir #define _WIN32_WINNT_0x0500
31*cdf0e10cSrcweir #include "systools/win32/uwinapi.h"
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include "file_url.h"
34*cdf0e10cSrcweir #include "file_error.h"
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir #include "rtl/alloc.h"
37*cdf0e10cSrcweir #include "osl/diagnose.h"
38*cdf0e10cSrcweir #include "osl/file.h"
39*cdf0e10cSrcweir #include "osl/mutex.h"
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include "path_helper.hxx"
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir #include <stdio.h>
44*cdf0e10cSrcweir #include <tchar.h>
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
47*cdf0e10cSrcweir #define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ?  (void)0 : _osl_warnFile( msg, file ) )
48*cdf0e10cSrcweir #else
49*cdf0e10cSrcweir #define OSL_ENSURE_FILE( cond, msg, file ) ((void)0)
50*cdf0e10cSrcweir #endif
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir #define WSTR_SYSTEM_ROOT_PATH				L"\\\\.\\"
55*cdf0e10cSrcweir #define WSTR_LONG_PATH_PREFIX				L"\\\\?\\"
56*cdf0e10cSrcweir #define WSTR_LONG_PATH_PREFIX_UNC			L"\\\\?\\UNC\\"
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir //##################################################################
60*cdf0e10cSrcweir // FileURL functions
61*cdf0e10cSrcweir //##################################################################
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir extern "C" oslMutex g_CurrentDirectoryMutex; /* Initialized in dllentry.c */
64*cdf0e10cSrcweir oslMutex g_CurrentDirectoryMutex = 0;
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir //#####################################################
67*cdf0e10cSrcweir static BOOL IsValidFilePathComponent(
68*cdf0e10cSrcweir     LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags)
69*cdf0e10cSrcweir {
70*cdf0e10cSrcweir 	    LPCTSTR	lpComponentEnd = NULL;
71*cdf0e10cSrcweir 	    LPCTSTR	lpCurrent = lpComponent;
72*cdf0e10cSrcweir 	    BOOL	fValid = TRUE;	/* Assume success */
73*cdf0e10cSrcweir 	    TCHAR	cLast = 0;
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir 	    /* Path component length must not exceed MAX_PATH even if long path with "\\?\" prefix is used */
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir 	    while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < MAX_PATH )
78*cdf0e10cSrcweir 	    {
79*cdf0e10cSrcweir 		    switch ( *lpCurrent )
80*cdf0e10cSrcweir 		    {
81*cdf0e10cSrcweir 			    /* Both backslash and slash determine the end of a path component */
82*cdf0e10cSrcweir 		    case '\0':
83*cdf0e10cSrcweir 		    case '/':
84*cdf0e10cSrcweir 		    case '\\':
85*cdf0e10cSrcweir 			    switch ( cLast )
86*cdf0e10cSrcweir 			    {
87*cdf0e10cSrcweir 				    /* Component must not end with '.' or blank and can't be empty */
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir 			    case '.':
90*cdf0e10cSrcweir 				    if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE )
91*cdf0e10cSrcweir 				    {
92*cdf0e10cSrcweir 					    if ( 1 == lpCurrent - lpComponent )
93*cdf0e10cSrcweir 					    {
94*cdf0e10cSrcweir 						    /* Current directory is O.K. */
95*cdf0e10cSrcweir 						    lpComponentEnd = lpCurrent;
96*cdf0e10cSrcweir 						    break;
97*cdf0e10cSrcweir 					    }
98*cdf0e10cSrcweir 					    else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent )
99*cdf0e10cSrcweir 					    {
100*cdf0e10cSrcweir 						    /* Parent directory is O.K. */
101*cdf0e10cSrcweir 						    lpComponentEnd = lpCurrent;
102*cdf0e10cSrcweir 						    break;
103*cdf0e10cSrcweir 					    }
104*cdf0e10cSrcweir 				    }
105*cdf0e10cSrcweir 			    case 0:
106*cdf0e10cSrcweir 			    case ' ':
107*cdf0e10cSrcweir 				    lpComponentEnd = lpCurrent - 1;
108*cdf0e10cSrcweir 				    fValid = FALSE;
109*cdf0e10cSrcweir 				    break;
110*cdf0e10cSrcweir 			    default:
111*cdf0e10cSrcweir 				    lpComponentEnd = lpCurrent;
112*cdf0e10cSrcweir 				    break;
113*cdf0e10cSrcweir 			    }
114*cdf0e10cSrcweir 			    break;
115*cdf0e10cSrcweir 			    /* '?' and '*' are valid wildcards but not valid file name characters */
116*cdf0e10cSrcweir 		    case '?':
117*cdf0e10cSrcweir 		    case '*':
118*cdf0e10cSrcweir 			    if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS )
119*cdf0e10cSrcweir 				    break;
120*cdf0e10cSrcweir 			    /* The following characters are reserved */
121*cdf0e10cSrcweir 		    case '<':
122*cdf0e10cSrcweir 		    case '>':
123*cdf0e10cSrcweir 		    case '\"':
124*cdf0e10cSrcweir 		    case '|':
125*cdf0e10cSrcweir 		    case ':':
126*cdf0e10cSrcweir 			    lpComponentEnd = lpCurrent;
127*cdf0e10cSrcweir 			    fValid = FALSE;
128*cdf0e10cSrcweir 			    break;
129*cdf0e10cSrcweir 		    default:
130*cdf0e10cSrcweir 			    /* Characters below ASCII 32 are not allowed */
131*cdf0e10cSrcweir 			    if ( *lpCurrent < ' ' )
132*cdf0e10cSrcweir 			    {
133*cdf0e10cSrcweir 				    lpComponentEnd = lpCurrent;
134*cdf0e10cSrcweir 				    fValid = FALSE;
135*cdf0e10cSrcweir 			    }
136*cdf0e10cSrcweir 			    break;
137*cdf0e10cSrcweir 		    }
138*cdf0e10cSrcweir 		    cLast = *lpCurrent++;
139*cdf0e10cSrcweir 	    }
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir 	    /*	If we don't reached the end of the component the length of the component was to long
142*cdf0e10cSrcweir 		    ( See condition of while loop ) */
143*cdf0e10cSrcweir 	    if ( !lpComponentEnd )
144*cdf0e10cSrcweir 	    {
145*cdf0e10cSrcweir 		    fValid = FALSE;
146*cdf0e10cSrcweir 		    lpComponentEnd = lpCurrent;
147*cdf0e10cSrcweir 	    }
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir 		/* Test wether the component specifies a device name what is not allowed */
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir 		// MT: PERFORMANCE:
152*cdf0e10cSrcweir 		// This is very expensive. A lot of calls to _tcsicmp.
153*cdf0e10cSrcweir 		// in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp!
154*cdf0e10cSrcweir 		// Possible optimizations
155*cdf0e10cSrcweir 		// - Array should be const static
156*cdf0e10cSrcweir 		// - Sorted array, use binary search
157*cdf0e10cSrcweir 		// - More intelligent check for com1-9, lpt1-9
158*cdf0e10cSrcweir 		// Maybe make szComponent upper case, don't search case intensitive
159*cdf0e10cSrcweir 		// Talked to HRO: Could be removed. Shouldn't be used in OOo, and if used for something like a filename, it will lead to an error anyway.
160*cdf0e10cSrcweir 		/*
161*cdf0e10cSrcweir 	    if ( fValid )
162*cdf0e10cSrcweir 	    {
163*cdf0e10cSrcweir 		    LPCTSTR	alpDeviceNames[] =
164*cdf0e10cSrcweir 		    {
165*cdf0e10cSrcweir 			    TEXT("CON"),
166*cdf0e10cSrcweir 			    TEXT("PRN"),
167*cdf0e10cSrcweir 			    TEXT("AUX"),
168*cdf0e10cSrcweir 			    TEXT("CLOCK$"),
169*cdf0e10cSrcweir 			    TEXT("NUL"),
170*cdf0e10cSrcweir 			    TEXT("LPT1"),
171*cdf0e10cSrcweir 			    TEXT("LPT2"),
172*cdf0e10cSrcweir 			    TEXT("LPT3"),
173*cdf0e10cSrcweir 			    TEXT("LPT4"),
174*cdf0e10cSrcweir 			    TEXT("LPT5"),
175*cdf0e10cSrcweir 			    TEXT("LPT6"),
176*cdf0e10cSrcweir 			    TEXT("LPT7"),
177*cdf0e10cSrcweir 			    TEXT("LPT8"),
178*cdf0e10cSrcweir 			    TEXT("LPT9"),
179*cdf0e10cSrcweir 			    TEXT("COM1"),
180*cdf0e10cSrcweir 			    TEXT("COM2"),
181*cdf0e10cSrcweir 			    TEXT("COM3"),
182*cdf0e10cSrcweir 			    TEXT("COM4"),
183*cdf0e10cSrcweir 			    TEXT("COM5"),
184*cdf0e10cSrcweir 			    TEXT("COM6"),
185*cdf0e10cSrcweir 			    TEXT("COM7"),
186*cdf0e10cSrcweir 			    TEXT("COM8"),
187*cdf0e10cSrcweir 			    TEXT("COM9")
188*cdf0e10cSrcweir 		    };
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir 		    TCHAR	szComponent[MAX_PATH];
191*cdf0e10cSrcweir 		    int		nComponentLength;
192*cdf0e10cSrcweir 		    LPCTSTR	lpDot;
193*cdf0e10cSrcweir 		    int		i;
194*cdf0e10cSrcweir 
195*cdf0e10cSrcweir 		    // A device name with an extension is also invalid
196*cdf0e10cSrcweir 		    lpDot = _tcschr( lpComponent, '.' );
197*cdf0e10cSrcweir 
198*cdf0e10cSrcweir 		    if ( !lpDot || lpDot > lpComponentEnd )
199*cdf0e10cSrcweir 			    nComponentLength = lpComponentEnd - lpComponent;
200*cdf0e10cSrcweir 		    else
201*cdf0e10cSrcweir 			    nComponentLength = lpDot - lpComponent;
202*cdf0e10cSrcweir 
203*cdf0e10cSrcweir 		    _tcsncpy( szComponent, lpComponent, nComponentLength );
204*cdf0e10cSrcweir 		    szComponent[nComponentLength] = 0;
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir 		    for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ )
207*cdf0e10cSrcweir 		    {
208*cdf0e10cSrcweir 			    if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) )
209*cdf0e10cSrcweir 			    {
210*cdf0e10cSrcweir 				    lpComponentEnd = lpComponent;
211*cdf0e10cSrcweir 				    fValid = FALSE;
212*cdf0e10cSrcweir 				    break;
213*cdf0e10cSrcweir 			    }
214*cdf0e10cSrcweir 		    }
215*cdf0e10cSrcweir 	    }
216*cdf0e10cSrcweir 	    */
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir 		if ( fValid )
219*cdf0e10cSrcweir 		{
220*cdf0e10cSrcweir 			// Empty components are not allowed
221*cdf0e10cSrcweir 			if ( lpComponentEnd - lpComponent < 1 )
222*cdf0e10cSrcweir 				fValid = FALSE;
223*cdf0e10cSrcweir 
224*cdf0e10cSrcweir 			// If we reached the end of the string NULL is returned
225*cdf0e10cSrcweir 			else if ( !*lpComponentEnd )
226*cdf0e10cSrcweir 				lpComponentEnd = NULL;
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir 		}
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir 	    if ( lppComponentEnd )
231*cdf0e10cSrcweir 		    *lppComponentEnd = lpComponentEnd;
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir 	    return fValid;
234*cdf0e10cSrcweir }
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir //#####################################################
237*cdf0e10cSrcweir #define	CHARSET_SEPARATOR TEXT("\\/")
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir DWORD IsValidFilePath(rtl_uString *path, LPCTSTR *lppError, DWORD dwFlags, rtl_uString **corrected)
240*cdf0e10cSrcweir {
241*cdf0e10cSrcweir         LPCTSTR lpszPath = reinterpret_cast< LPCTSTR >(path->buffer);
242*cdf0e10cSrcweir 	    LPCTSTR	lpComponent = lpszPath;
243*cdf0e10cSrcweir 	    BOOL	fValid = TRUE;
244*cdf0e10cSrcweir 	    DWORD	dwPathType = PATHTYPE_ERROR;
245*cdf0e10cSrcweir         sal_Int32 nLength = rtl_uString_getLength( path );
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir 	    if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
248*cdf0e10cSrcweir 		    dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE;
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir 	    if ( !lpszPath )
251*cdf0e10cSrcweir 		    fValid = FALSE;
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 	    DWORD	dwCandidatPathType = PATHTYPE_ERROR;
254*cdf0e10cSrcweir 
255*cdf0e10cSrcweir         if ( 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( path->buffer, nLength, reinterpret_cast<const sal_Unicode *>(WSTR_LONG_PATH_PREFIX_UNC), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1 ) )
256*cdf0e10cSrcweir         {
257*cdf0e10cSrcweir             /* This is long path in UNC notation */
258*cdf0e10cSrcweir             lpComponent = lpszPath + ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1;
259*cdf0e10cSrcweir             dwCandidatPathType = PATHTYPE_ABSOLUTE_UNC | PATHTYPE_IS_LONGPATH;
260*cdf0e10cSrcweir         }
261*cdf0e10cSrcweir         else if ( 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( path->buffer, nLength, reinterpret_cast<const sal_Unicode *>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1 ) )
262*cdf0e10cSrcweir         {
263*cdf0e10cSrcweir             /* This is long path */
264*cdf0e10cSrcweir             lpComponent = lpszPath + ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1;
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir             if ( _istalpha( lpComponent[0] ) && ':' == lpComponent[1] )
267*cdf0e10cSrcweir             {
268*cdf0e10cSrcweir                 lpComponent += 2;
269*cdf0e10cSrcweir                 dwCandidatPathType = PATHTYPE_ABSOLUTE_LOCAL | PATHTYPE_IS_LONGPATH;
270*cdf0e10cSrcweir             }
271*cdf0e10cSrcweir         }
272*cdf0e10cSrcweir 	    else if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) )
273*cdf0e10cSrcweir         {
274*cdf0e10cSrcweir             /* The UNC path notation */
275*cdf0e10cSrcweir             lpComponent = lpszPath + 2;
276*cdf0e10cSrcweir             dwCandidatPathType = PATHTYPE_ABSOLUTE_UNC;
277*cdf0e10cSrcweir         }
278*cdf0e10cSrcweir 	    else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] )
279*cdf0e10cSrcweir         {
280*cdf0e10cSrcweir             /* Local path verification. Must start with <drive>: */
281*cdf0e10cSrcweir 		    lpComponent = lpszPath + 2;
282*cdf0e10cSrcweir             dwCandidatPathType = PATHTYPE_ABSOLUTE_LOCAL;
283*cdf0e10cSrcweir         }
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir 	    if ( ( dwCandidatPathType & PATHTYPE_MASK_TYPE ) == PATHTYPE_ABSOLUTE_UNC )
286*cdf0e10cSrcweir 	    {
287*cdf0e10cSrcweir 		    fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE );
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir 		    /* So far we have a valid servername. Now let's see if we also have a network resource */
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir 		    dwPathType = dwCandidatPathType;
292*cdf0e10cSrcweir 
293*cdf0e10cSrcweir 		    if ( fValid )
294*cdf0e10cSrcweir 		    {
295*cdf0e10cSrcweir 			    if ( lpComponent &&	 !*++lpComponent )
296*cdf0e10cSrcweir 				    lpComponent = NULL;
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir 			    if ( !lpComponent )
299*cdf0e10cSrcweir 			    {
300*cdf0e10cSrcweir     #if 0
301*cdf0e10cSrcweir 				    /* We only have a Server specification what is invalid */
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir 				    lpComponent = lpszPath;
304*cdf0e10cSrcweir 				    fValid = FALSE;
305*cdf0e10cSrcweir     #else
306*cdf0e10cSrcweir 				    dwPathType |= PATHTYPE_IS_SERVER;
307*cdf0e10cSrcweir     #endif
308*cdf0e10cSrcweir 			    }
309*cdf0e10cSrcweir 			    else
310*cdf0e10cSrcweir 			    {
311*cdf0e10cSrcweir 				    /* Now test the network resource */
312*cdf0e10cSrcweir 
313*cdf0e10cSrcweir 				    fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 );
314*cdf0e10cSrcweir 
315*cdf0e10cSrcweir 				    /* If we now reached the end of the path, everything is O.K. */
316*cdf0e10cSrcweir 
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir 				    if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) )
319*cdf0e10cSrcweir 				    {
320*cdf0e10cSrcweir 					    lpComponent = NULL;
321*cdf0e10cSrcweir 					    dwPathType |= PATHTYPE_IS_VOLUME;
322*cdf0e10cSrcweir 				    }
323*cdf0e10cSrcweir 			    }
324*cdf0e10cSrcweir 		    }
325*cdf0e10cSrcweir 	    }
326*cdf0e10cSrcweir 	    else if (  ( dwCandidatPathType & PATHTYPE_MASK_TYPE ) == PATHTYPE_ABSOLUTE_LOCAL )
327*cdf0e10cSrcweir 	    {
328*cdf0e10cSrcweir 		    if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
329*cdf0e10cSrcweir 			    lpComponent++;
330*cdf0e10cSrcweir 		    else if ( *lpComponent )
331*cdf0e10cSrcweir 			    fValid = FALSE;
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir 		    dwPathType = dwCandidatPathType;
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir 		    /* Now we are behind the backslash or it was a simple drive without backslash */
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir 		    if ( fValid && !*lpComponent )
338*cdf0e10cSrcweir 		    {
339*cdf0e10cSrcweir 			    lpComponent = NULL;
340*cdf0e10cSrcweir 			    dwPathType |= PATHTYPE_IS_VOLUME;
341*cdf0e10cSrcweir 		    }
342*cdf0e10cSrcweir 	    }
343*cdf0e10cSrcweir 	    else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
344*cdf0e10cSrcweir 	    {
345*cdf0e10cSrcweir             /* Can be a relative path */
346*cdf0e10cSrcweir 		    lpComponent = lpszPath;
347*cdf0e10cSrcweir 
348*cdf0e10cSrcweir 		    /* Relative path can start with a backslash */
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir 		    if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
351*cdf0e10cSrcweir 		    {
352*cdf0e10cSrcweir 			    lpComponent++;
353*cdf0e10cSrcweir 			    if ( !*lpComponent )
354*cdf0e10cSrcweir 				    lpComponent = NULL;
355*cdf0e10cSrcweir 		    }
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir 		    dwPathType = PATHTYPE_RELATIVE;
358*cdf0e10cSrcweir 	    }
359*cdf0e10cSrcweir 	    else
360*cdf0e10cSrcweir 	    {
361*cdf0e10cSrcweir             /* Anything else is an error */
362*cdf0e10cSrcweir 		    fValid = FALSE;
363*cdf0e10cSrcweir 		    lpComponent = lpszPath;
364*cdf0e10cSrcweir 	    }
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir 	    /* Now validate each component of the path */
367*cdf0e10cSrcweir 	    while ( fValid && lpComponent )
368*cdf0e10cSrcweir 	    {
369*cdf0e10cSrcweir             // Correct path by merging consecutive slashes:
370*cdf0e10cSrcweir             if (*lpComponent == '\\' && corrected != NULL) {
371*cdf0e10cSrcweir                 sal_Int32 i = lpComponent - lpszPath;
372*cdf0e10cSrcweir                 rtl_uString_newReplaceStrAt(corrected, path, i, 1, NULL);
373*cdf0e10cSrcweir                     //TODO: handle out-of-memory
374*cdf0e10cSrcweir                 lpszPath = reinterpret_cast< LPCTSTR >((*corrected)->buffer);
375*cdf0e10cSrcweir                 lpComponent = lpszPath + i;
376*cdf0e10cSrcweir             }
377*cdf0e10cSrcweir 
378*cdf0e10cSrcweir 		    fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags );
379*cdf0e10cSrcweir 
380*cdf0e10cSrcweir 		    if ( fValid && lpComponent )
381*cdf0e10cSrcweir 		    {
382*cdf0e10cSrcweir 			    lpComponent++;
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir 			    /* If the string behind the backslash is empty, we've done */
385*cdf0e10cSrcweir 
386*cdf0e10cSrcweir 			    if ( !*lpComponent )
387*cdf0e10cSrcweir 				    lpComponent = NULL;
388*cdf0e10cSrcweir 		    }
389*cdf0e10cSrcweir 	    }
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir         /* The path can be longer than MAX_PATH only in case it has the longpath prefix */
392*cdf0e10cSrcweir 	    if ( fValid && !( dwPathType &  PATHTYPE_IS_LONGPATH ) && _tcslen( lpszPath ) >= MAX_PATH )
393*cdf0e10cSrcweir 	    {
394*cdf0e10cSrcweir 		    fValid = FALSE;
395*cdf0e10cSrcweir 		    lpComponent = lpszPath + MAX_PATH;
396*cdf0e10cSrcweir 	    }
397*cdf0e10cSrcweir 
398*cdf0e10cSrcweir 	    if ( lppError )
399*cdf0e10cSrcweir 		    *lppError = lpComponent;
400*cdf0e10cSrcweir 
401*cdf0e10cSrcweir 	    return fValid ? dwPathType : PATHTYPE_ERROR;
402*cdf0e10cSrcweir }
403*cdf0e10cSrcweir 
404*cdf0e10cSrcweir //#####################################################
405*cdf0e10cSrcweir static sal_Int32 PathRemoveFileSpec(LPTSTR lpPath, LPTSTR lpFileName, sal_Int32 nFileBufLen )
406*cdf0e10cSrcweir {
407*cdf0e10cSrcweir     sal_Int32 nRemoved = 0;
408*cdf0e10cSrcweir 
409*cdf0e10cSrcweir     if ( nFileBufLen )
410*cdf0e10cSrcweir     {
411*cdf0e10cSrcweir         lpFileName[0] = 0;
412*cdf0e10cSrcweir         LPTSTR	lpLastBkSlash = _tcsrchr( lpPath, '\\' );
413*cdf0e10cSrcweir         LPTSTR	lpLastSlash = _tcsrchr( lpPath, '/' );
414*cdf0e10cSrcweir         LPTSTR	lpLastDelimiter = lpLastSlash > lpLastBkSlash ? lpLastSlash : lpLastBkSlash;
415*cdf0e10cSrcweir 
416*cdf0e10cSrcweir         if ( lpLastDelimiter )
417*cdf0e10cSrcweir         {
418*cdf0e10cSrcweir                 sal_Int32 nDelLen = _tcslen( lpLastDelimiter );
419*cdf0e10cSrcweir                 if ( 1 == nDelLen )
420*cdf0e10cSrcweir                 {
421*cdf0e10cSrcweir                     if ( lpLastDelimiter > lpPath && *(lpLastDelimiter - 1) != ':' )
422*cdf0e10cSrcweir                     {
423*cdf0e10cSrcweir                         *lpLastDelimiter = 0;
424*cdf0e10cSrcweir                         *lpFileName = 0;
425*cdf0e10cSrcweir                         nRemoved = nDelLen;
426*cdf0e10cSrcweir                     }
427*cdf0e10cSrcweir                 }
428*cdf0e10cSrcweir                 else if ( nDelLen && nDelLen - 1 < nFileBufLen )
429*cdf0e10cSrcweir                 {
430*cdf0e10cSrcweir                     _tcscpy( lpFileName, lpLastDelimiter + 1 );
431*cdf0e10cSrcweir                     *(++lpLastDelimiter) = 0;
432*cdf0e10cSrcweir                     nRemoved = nDelLen - 1;
433*cdf0e10cSrcweir                 }
434*cdf0e10cSrcweir         }
435*cdf0e10cSrcweir     }
436*cdf0e10cSrcweir 
437*cdf0e10cSrcweir     return nRemoved;
438*cdf0e10cSrcweir }
439*cdf0e10cSrcweir 
440*cdf0e10cSrcweir //#####################################################
441*cdf0e10cSrcweir // Undocumented in SHELL32.DLL ordinal 32
442*cdf0e10cSrcweir static LPTSTR PathAddBackslash(LPTSTR lpPath, sal_Int32 nBufLen)
443*cdf0e10cSrcweir {
444*cdf0e10cSrcweir     LPTSTR	lpEndPath = NULL;
445*cdf0e10cSrcweir 
446*cdf0e10cSrcweir     if ( lpPath )
447*cdf0e10cSrcweir     {
448*cdf0e10cSrcweir 		    int		nLen = _tcslen(lpPath);
449*cdf0e10cSrcweir 
450*cdf0e10cSrcweir 		    if ( !nLen || lpPath[nLen-1] != '\\' && lpPath[nLen-1] != '/' && nLen < nBufLen - 1 )
451*cdf0e10cSrcweir 		    {
452*cdf0e10cSrcweir 			    lpEndPath = lpPath + nLen;
453*cdf0e10cSrcweir 			    *lpEndPath++ = '\\';
454*cdf0e10cSrcweir 			    *lpEndPath = 0;
455*cdf0e10cSrcweir 		    }
456*cdf0e10cSrcweir     }
457*cdf0e10cSrcweir     return lpEndPath;
458*cdf0e10cSrcweir }
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir //#####################################################
461*cdf0e10cSrcweir // Same as GetLongPathName but also 95/NT4
462*cdf0e10cSrcweir static DWORD GetCaseCorrectPathNameEx(
463*cdf0e10cSrcweir     LPTSTR	lpszPath,	// path buffer to convert
464*cdf0e10cSrcweir     DWORD	cchBuffer,		// size of path buffer
465*cdf0e10cSrcweir     DWORD	nSkipLevels,
466*cdf0e10cSrcweir     BOOL bCheckExistence )
467*cdf0e10cSrcweir {
468*cdf0e10cSrcweir         ::osl::LongPathBuffer< WCHAR > szFile( MAX_PATH + 1 );
469*cdf0e10cSrcweir 	    sal_Int32 nRemoved = PathRemoveFileSpec( lpszPath, szFile, MAX_PATH + 1 );
470*cdf0e10cSrcweir         sal_Int32 nLastStepRemoved = nRemoved;
471*cdf0e10cSrcweir         while ( nLastStepRemoved && szFile[0] == 0 )
472*cdf0e10cSrcweir         {
473*cdf0e10cSrcweir             // remove separators
474*cdf0e10cSrcweir 	        nLastStepRemoved = PathRemoveFileSpec( lpszPath, szFile, MAX_PATH + 1 );
475*cdf0e10cSrcweir             nRemoved += nLastStepRemoved;
476*cdf0e10cSrcweir         }
477*cdf0e10cSrcweir 
478*cdf0e10cSrcweir 	    if ( nRemoved )
479*cdf0e10cSrcweir 	    {
480*cdf0e10cSrcweir             BOOL bSkipThis = FALSE;
481*cdf0e10cSrcweir 
482*cdf0e10cSrcweir 		    if ( 0 == _tcscmp( szFile, TEXT("..") ) )
483*cdf0e10cSrcweir 		    {
484*cdf0e10cSrcweir 			    bSkipThis = TRUE;
485*cdf0e10cSrcweir 			    nSkipLevels += 1;
486*cdf0e10cSrcweir 		    }
487*cdf0e10cSrcweir             else if ( 0 == _tcscmp( szFile, TEXT(".") ) )
488*cdf0e10cSrcweir             {
489*cdf0e10cSrcweir 			    bSkipThis = TRUE;
490*cdf0e10cSrcweir             }
491*cdf0e10cSrcweir 		    else if ( nSkipLevels )
492*cdf0e10cSrcweir 		    {
493*cdf0e10cSrcweir 			    bSkipThis = TRUE;
494*cdf0e10cSrcweir 			    nSkipLevels--;
495*cdf0e10cSrcweir 		    }
496*cdf0e10cSrcweir 		    else
497*cdf0e10cSrcweir 			    bSkipThis = FALSE;
498*cdf0e10cSrcweir 
499*cdf0e10cSrcweir 		    GetCaseCorrectPathNameEx( lpszPath, cchBuffer, nSkipLevels, bCheckExistence );
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir 		    PathAddBackslash( lpszPath, cchBuffer );
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir 		    /* Analyze parent if not only a trailing backslash was cutted but a real file spec */
504*cdf0e10cSrcweir 		    if ( !bSkipThis )
505*cdf0e10cSrcweir 		    {
506*cdf0e10cSrcweir                 if ( bCheckExistence )
507*cdf0e10cSrcweir                 {
508*cdf0e10cSrcweir                     ::osl::LongPathBuffer< WCHAR > aShortPath( MAX_LONG_PATH );
509*cdf0e10cSrcweir                     _tcscpy( aShortPath, lpszPath );
510*cdf0e10cSrcweir                     _tcscat( aShortPath, szFile );
511*cdf0e10cSrcweir 
512*cdf0e10cSrcweir                     WIN32_FIND_DATA	aFindFileData;
513*cdf0e10cSrcweir                     HANDLE	hFind = FindFirstFile( aShortPath, &aFindFileData );
514*cdf0e10cSrcweir 
515*cdf0e10cSrcweir                     if ( IsValidHandle(hFind) )
516*cdf0e10cSrcweir                     {
517*cdf0e10cSrcweir                         _tcscat( lpszPath, aFindFileData.cFileName[0] ? aFindFileData.cFileName : aFindFileData.cAlternateFileName );
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir                         FindClose( hFind );
520*cdf0e10cSrcweir                     }
521*cdf0e10cSrcweir                     else
522*cdf0e10cSrcweir                         lpszPath[0] = 0;
523*cdf0e10cSrcweir                 }
524*cdf0e10cSrcweir                 else
525*cdf0e10cSrcweir                 {
526*cdf0e10cSrcweir                     /* add the segment name back */
527*cdf0e10cSrcweir                     _tcscat( lpszPath, szFile );
528*cdf0e10cSrcweir                 }
529*cdf0e10cSrcweir 		    }
530*cdf0e10cSrcweir 	    }
531*cdf0e10cSrcweir 	    else
532*cdf0e10cSrcweir 	    {
533*cdf0e10cSrcweir 		    /* File specification can't be removed therefore the short path is either a drive
534*cdf0e10cSrcweir 			   or a network share. If still levels to skip are left, the path specification
535*cdf0e10cSrcweir 			   tries to travel below the file system root */
536*cdf0e10cSrcweir 		    if ( nSkipLevels )
537*cdf0e10cSrcweir                     lpszPath[0] = 0;
538*cdf0e10cSrcweir             else
539*cdf0e10cSrcweir                 _tcsupr( lpszPath );
540*cdf0e10cSrcweir 	    }
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir 	    return _tcslen( lpszPath );
543*cdf0e10cSrcweir }
544*cdf0e10cSrcweir 
545*cdf0e10cSrcweir //#####################################################
546*cdf0e10cSrcweir #define WSTR_SYSTEM_ROOT_PATH				L"\\\\.\\"
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir DWORD GetCaseCorrectPathName(
549*cdf0e10cSrcweir     LPCTSTR	lpszShortPath,	// file name
550*cdf0e10cSrcweir     LPTSTR	lpszLongPath,	// path buffer
551*cdf0e10cSrcweir     DWORD	cchBuffer,		// size of path buffer
552*cdf0e10cSrcweir     BOOL bCheckExistence
553*cdf0e10cSrcweir )
554*cdf0e10cSrcweir {
555*cdf0e10cSrcweir     /* Special handling for "\\.\" as system root */
556*cdf0e10cSrcweir     if ( lpszShortPath && 0 == wcscmp( lpszShortPath, WSTR_SYSTEM_ROOT_PATH ) )
557*cdf0e10cSrcweir     {
558*cdf0e10cSrcweir         if ( cchBuffer >= ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) )
559*cdf0e10cSrcweir         {
560*cdf0e10cSrcweir             wcscpy( lpszLongPath, WSTR_SYSTEM_ROOT_PATH );
561*cdf0e10cSrcweir             return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
562*cdf0e10cSrcweir         }
563*cdf0e10cSrcweir         else
564*cdf0e10cSrcweir         {
565*cdf0e10cSrcweir             return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
566*cdf0e10cSrcweir         }
567*cdf0e10cSrcweir     }
568*cdf0e10cSrcweir     else if ( lpszShortPath )
569*cdf0e10cSrcweir     {
570*cdf0e10cSrcweir         if ( _tcslen( lpszShortPath ) <= cchBuffer )
571*cdf0e10cSrcweir         {
572*cdf0e10cSrcweir             _tcscpy( lpszLongPath, lpszShortPath );
573*cdf0e10cSrcweir             return GetCaseCorrectPathNameEx( lpszLongPath, cchBuffer, 0, bCheckExistence );
574*cdf0e10cSrcweir         }
575*cdf0e10cSrcweir     }
576*cdf0e10cSrcweir 
577*cdf0e10cSrcweir     return 0;
578*cdf0e10cSrcweir }
579*cdf0e10cSrcweir 
580*cdf0e10cSrcweir 
581*cdf0e10cSrcweir //#############################################
582*cdf0e10cSrcweir static sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL )
583*cdf0e10cSrcweir {
584*cdf0e10cSrcweir     sal_Char		*pBuffer;
585*cdf0e10cSrcweir     const sal_Char	*pSrcEnd;
586*cdf0e10cSrcweir     const sal_Char	*pSrc;
587*cdf0e10cSrcweir     sal_Char		*pDest;
588*cdf0e10cSrcweir     sal_Int32		nSrcLen;
589*cdf0e10cSrcweir     sal_Bool		bValidEncoded = sal_True;	/* Assume success */
590*cdf0e10cSrcweir 
591*cdf0e10cSrcweir     /* The resulting decoded string length is shorter or equal to the source length */
592*cdf0e10cSrcweir 
593*cdf0e10cSrcweir     nSrcLen = rtl_string_getLength(strUTF8);
594*cdf0e10cSrcweir     pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1));
595*cdf0e10cSrcweir 
596*cdf0e10cSrcweir     pDest = pBuffer;
597*cdf0e10cSrcweir     pSrc = rtl_string_getStr(strUTF8);
598*cdf0e10cSrcweir     pSrcEnd = pSrc + nSrcLen;
599*cdf0e10cSrcweir 
600*cdf0e10cSrcweir     /* Now decode the URL what should result in an UTF8 string */
601*cdf0e10cSrcweir     while ( bValidEncoded && pSrc < pSrcEnd )
602*cdf0e10cSrcweir     {
603*cdf0e10cSrcweir         switch ( *pSrc )
604*cdf0e10cSrcweir         {
605*cdf0e10cSrcweir         case '%':
606*cdf0e10cSrcweir             {
607*cdf0e10cSrcweir                 sal_Char	aToken[3];
608*cdf0e10cSrcweir                 sal_Char	aChar;
609*cdf0e10cSrcweir 
610*cdf0e10cSrcweir                 pSrc++;
611*cdf0e10cSrcweir                 aToken[0] = *pSrc++;
612*cdf0e10cSrcweir                 aToken[1] = *pSrc++;
613*cdf0e10cSrcweir                 aToken[2] = 0;
614*cdf0e10cSrcweir 
615*cdf0e10cSrcweir                 aChar = (sal_Char)strtoul( aToken, NULL, 16 );
616*cdf0e10cSrcweir 
617*cdf0e10cSrcweir                 /* The chars are path delimiters and must not be encoded */
618*cdf0e10cSrcweir 
619*cdf0e10cSrcweir                 if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar )
620*cdf0e10cSrcweir                     bValidEncoded = sal_False;
621*cdf0e10cSrcweir                 else
622*cdf0e10cSrcweir                     *pDest++ = aChar;
623*cdf0e10cSrcweir             }
624*cdf0e10cSrcweir             break;
625*cdf0e10cSrcweir         default:
626*cdf0e10cSrcweir             *pDest++ = *pSrc++;
627*cdf0e10cSrcweir             break;
628*cdf0e10cSrcweir         }
629*cdf0e10cSrcweir     }
630*cdf0e10cSrcweir 
631*cdf0e10cSrcweir     *pDest++ = 0;
632*cdf0e10cSrcweir 
633*cdf0e10cSrcweir     if ( bValidEncoded )
634*cdf0e10cSrcweir     {
635*cdf0e10cSrcweir         rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
636*cdf0e10cSrcweir         OSL_ASSERT(*pstrDecodedURL != 0);
637*cdf0e10cSrcweir     }
638*cdf0e10cSrcweir 
639*cdf0e10cSrcweir     rtl_freeMemory( pBuffer );
640*cdf0e10cSrcweir 
641*cdf0e10cSrcweir     return bValidEncoded;
642*cdf0e10cSrcweir }
643*cdf0e10cSrcweir 
644*cdf0e10cSrcweir //#############################################
645*cdf0e10cSrcweir static void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL )
646*cdf0e10cSrcweir {
647*cdf0e10cSrcweir     /* Encode non ascii characters within the URL */
648*cdf0e10cSrcweir 
649*cdf0e10cSrcweir     rtl_String		*strUTF8 = NULL;
650*cdf0e10cSrcweir     sal_Char		*pszEncodedURL;
651*cdf0e10cSrcweir     const sal_Char	*pURLScan;
652*cdf0e10cSrcweir     sal_Char		*pURLDest;
653*cdf0e10cSrcweir     sal_Int32		nURLScanLen;
654*cdf0e10cSrcweir     sal_Int32		nURLScanCount;
655*cdf0e10cSrcweir 
656*cdf0e10cSrcweir     rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
657*cdf0e10cSrcweir 
658*cdf0e10cSrcweir     pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1)  * sizeof(sal_Char) );
659*cdf0e10cSrcweir 
660*cdf0e10cSrcweir     pURLDest = pszEncodedURL;
661*cdf0e10cSrcweir     pURLScan = rtl_string_getStr( strUTF8 );
662*cdf0e10cSrcweir     nURLScanLen = rtl_string_getLength( strUTF8 );
663*cdf0e10cSrcweir     nURLScanCount = 0;
664*cdf0e10cSrcweir 
665*cdf0e10cSrcweir     while ( nURLScanCount < nURLScanLen )
666*cdf0e10cSrcweir     {
667*cdf0e10cSrcweir         sal_Char cCurrent = *pURLScan;
668*cdf0e10cSrcweir         switch ( cCurrent )
669*cdf0e10cSrcweir         {
670*cdf0e10cSrcweir         default:
671*cdf0e10cSrcweir             if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) )
672*cdf0e10cSrcweir             {
673*cdf0e10cSrcweir                 sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent );
674*cdf0e10cSrcweir                 pURLDest += 3;
675*cdf0e10cSrcweir                 break;
676*cdf0e10cSrcweir             }
677*cdf0e10cSrcweir         case '!':
678*cdf0e10cSrcweir         case '\'':
679*cdf0e10cSrcweir         case '(':
680*cdf0e10cSrcweir         case ')':
681*cdf0e10cSrcweir         case '*':
682*cdf0e10cSrcweir         case '-':
683*cdf0e10cSrcweir         case '.':
684*cdf0e10cSrcweir         case '_':
685*cdf0e10cSrcweir         case '~':
686*cdf0e10cSrcweir         case '$':
687*cdf0e10cSrcweir         case '&':
688*cdf0e10cSrcweir         case '+':
689*cdf0e10cSrcweir         case ',':
690*cdf0e10cSrcweir         case '=':
691*cdf0e10cSrcweir         case '@':
692*cdf0e10cSrcweir         case ':':
693*cdf0e10cSrcweir         case '/':
694*cdf0e10cSrcweir         case '\\':
695*cdf0e10cSrcweir         case '|':
696*cdf0e10cSrcweir             *pURLDest++ = cCurrent;
697*cdf0e10cSrcweir             break;
698*cdf0e10cSrcweir         case 0:
699*cdf0e10cSrcweir             break;
700*cdf0e10cSrcweir         }
701*cdf0e10cSrcweir 
702*cdf0e10cSrcweir         pURLScan++;
703*cdf0e10cSrcweir         nURLScanCount++;
704*cdf0e10cSrcweir     }
705*cdf0e10cSrcweir 
706*cdf0e10cSrcweir     *pURLDest = 0;
707*cdf0e10cSrcweir 
708*cdf0e10cSrcweir     rtl_string_release( strUTF8 );
709*cdf0e10cSrcweir     rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL );
710*cdf0e10cSrcweir     rtl_freeMemory( pszEncodedURL );
711*cdf0e10cSrcweir }
712*cdf0e10cSrcweir 
713*cdf0e10cSrcweir //#############################################
714*cdf0e10cSrcweir 
715*cdf0e10cSrcweir oslFileError _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative )
716*cdf0e10cSrcweir {
717*cdf0e10cSrcweir     rtl_String			*strUTF8 = NULL;
718*cdf0e10cSrcweir     rtl_uString			*strDecodedURL = NULL;
719*cdf0e10cSrcweir     rtl_uString			*strTempPath = NULL;
720*cdf0e10cSrcweir     const sal_Unicode	*pDecodedURL;
721*cdf0e10cSrcweir     sal_uInt32			nDecodedLen;
722*cdf0e10cSrcweir     sal_Bool			bValidEncoded;
723*cdf0e10cSrcweir     oslFileError		nError = osl_File_E_INVAL;	/* Assume failure */
724*cdf0e10cSrcweir 
725*cdf0e10cSrcweir     /*  If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from
726*cdf0e10cSrcweir         having a mixed encoded URL later */
727*cdf0e10cSrcweir 
728*cdf0e10cSrcweir     rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
729*cdf0e10cSrcweir 
730*cdf0e10cSrcweir     /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */
731*cdf0e10cSrcweir 
732*cdf0e10cSrcweir     OSL_ENSURE_FILE(
733*cdf0e10cSrcweir         strUTF8->length == strURL->length ||
734*cdf0e10cSrcweir         0 != rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 )
735*cdf0e10cSrcweir         ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL );
736*cdf0e10cSrcweir 
737*cdf0e10cSrcweir     bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL );
738*cdf0e10cSrcweir 
739*cdf0e10cSrcweir     /* Release the encoded UTF8 string */
740*cdf0e10cSrcweir     rtl_string_release( strUTF8 );
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir     if ( bValidEncoded )
743*cdf0e10cSrcweir     {
744*cdf0e10cSrcweir         /* Replace backslashes and pipes */
745*cdf0e10cSrcweir 
746*cdf0e10cSrcweir         rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' );
747*cdf0e10cSrcweir         rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' );
748*cdf0e10cSrcweir 
749*cdf0e10cSrcweir         pDecodedURL = rtl_uString_getStr( strDecodedURL );
750*cdf0e10cSrcweir         nDecodedLen = rtl_uString_getLength( strDecodedURL );
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir         /* Must start with "file://" */
753*cdf0e10cSrcweir         if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) )
754*cdf0e10cSrcweir         {
755*cdf0e10cSrcweir             sal_uInt32	nSkip;
756*cdf0e10cSrcweir 
757*cdf0e10cSrcweir             if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) )
758*cdf0e10cSrcweir                 nSkip = 8;
759*cdf0e10cSrcweir             else if (
760*cdf0e10cSrcweir                 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) ||
761*cdf0e10cSrcweir                 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 )
762*cdf0e10cSrcweir                       )
763*cdf0e10cSrcweir                 nSkip = 17;
764*cdf0e10cSrcweir             else
765*cdf0e10cSrcweir                 nSkip = 5;
766*cdf0e10cSrcweir 
767*cdf0e10cSrcweir             /* Indicates local root */
768*cdf0e10cSrcweir             if ( nDecodedLen == nSkip )
769*cdf0e10cSrcweir                 rtl_uString_newFromStr_WithLength( &strTempPath, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 );
770*cdf0e10cSrcweir             else
771*cdf0e10cSrcweir             {
772*cdf0e10cSrcweir                 /* do not separate the directory and file case, so the maximal path lengs without prefix is MAX_PATH-12 */
773*cdf0e10cSrcweir                 if ( nDecodedLen - nSkip <= MAX_PATH - 12 )
774*cdf0e10cSrcweir                 {
775*cdf0e10cSrcweir                     rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip );
776*cdf0e10cSrcweir                 }
777*cdf0e10cSrcweir                 else
778*cdf0e10cSrcweir                 {
779*cdf0e10cSrcweir                     ::osl::LongPathBuffer< sal_Unicode > aBuf( MAX_LONG_PATH );
780*cdf0e10cSrcweir                     sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>(pDecodedURL + nSkip),
781*cdf0e10cSrcweir                                                                  ::osl::mingw_reinterpret_cast<LPTSTR>(aBuf),
782*cdf0e10cSrcweir                                                                  aBuf.getBufSizeInSymbols(),
783*cdf0e10cSrcweir                                                                  sal_False );
784*cdf0e10cSrcweir 
785*cdf0e10cSrcweir                     if ( nNewLen <= MAX_PATH - 12
786*cdf0e10cSrcweir                       || 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL + nSkip, nDecodedLen - nSkip, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1, ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 )
787*cdf0e10cSrcweir                       || 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL + nSkip, nDecodedLen - nSkip, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1 ) )
788*cdf0e10cSrcweir                     {
789*cdf0e10cSrcweir                         rtl_uString_newFromStr_WithLength( &strTempPath, aBuf, nNewLen );
790*cdf0e10cSrcweir                     }
791*cdf0e10cSrcweir                     else if ( pDecodedURL[nSkip] == (sal_Unicode)'\\' && pDecodedURL[nSkip+1] == (sal_Unicode)'\\' )
792*cdf0e10cSrcweir                     {
793*cdf0e10cSrcweir                         /* it should be an UNC path, use the according prefix */
794*cdf0e10cSrcweir                         rtl_uString *strSuffix = NULL;
795*cdf0e10cSrcweir                         rtl_uString *strPrefix = NULL;
796*cdf0e10cSrcweir                         rtl_uString_newFromStr_WithLength( &strPrefix, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX_UNC), ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX_UNC ) - 1 );
797*cdf0e10cSrcweir                         rtl_uString_newFromStr_WithLength( &strSuffix, aBuf + 2, nNewLen - 2 );
798*cdf0e10cSrcweir 
799*cdf0e10cSrcweir                         rtl_uString_newConcat( &strTempPath, strPrefix, strSuffix );
800*cdf0e10cSrcweir 
801*cdf0e10cSrcweir                         rtl_uString_release( strPrefix );
802*cdf0e10cSrcweir                         rtl_uString_release( strSuffix );
803*cdf0e10cSrcweir                     }
804*cdf0e10cSrcweir                     else
805*cdf0e10cSrcweir                     {
806*cdf0e10cSrcweir                         rtl_uString *strSuffix = NULL;
807*cdf0e10cSrcweir                         rtl_uString *strPrefix = NULL;
808*cdf0e10cSrcweir                         rtl_uString_newFromStr_WithLength( &strPrefix, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX ) - 1 );
809*cdf0e10cSrcweir                         rtl_uString_newFromStr_WithLength( &strSuffix, aBuf, nNewLen );
810*cdf0e10cSrcweir 
811*cdf0e10cSrcweir                         rtl_uString_newConcat( &strTempPath, strPrefix, strSuffix );
812*cdf0e10cSrcweir 
813*cdf0e10cSrcweir                         rtl_uString_release( strPrefix );
814*cdf0e10cSrcweir                         rtl_uString_release( strSuffix );
815*cdf0e10cSrcweir                     }
816*cdf0e10cSrcweir                 }
817*cdf0e10cSrcweir             }
818*cdf0e10cSrcweir 
819*cdf0e10cSrcweir             if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) )
820*cdf0e10cSrcweir                 nError = osl_File_E_None;
821*cdf0e10cSrcweir         }
822*cdf0e10cSrcweir         else if ( bAllowRelative )	/* This maybe a relative file URL */
823*cdf0e10cSrcweir         {
824*cdf0e10cSrcweir             /* In future the relative path could be converted to absolute if it is too long */
825*cdf0e10cSrcweir             rtl_uString_assign( &strTempPath, strDecodedURL );
826*cdf0e10cSrcweir 
827*cdf0e10cSrcweir             if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) )
828*cdf0e10cSrcweir                 nError = osl_File_E_None;
829*cdf0e10cSrcweir         }
830*cdf0e10cSrcweir         /*
831*cdf0e10cSrcweir           else
832*cdf0e10cSrcweir           OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL );
833*cdf0e10cSrcweir         */
834*cdf0e10cSrcweir 
835*cdf0e10cSrcweir     }
836*cdf0e10cSrcweir 
837*cdf0e10cSrcweir     if ( strDecodedURL )
838*cdf0e10cSrcweir         rtl_uString_release( strDecodedURL );
839*cdf0e10cSrcweir 
840*cdf0e10cSrcweir     if ( osl_File_E_None == nError )
841*cdf0e10cSrcweir         rtl_uString_assign( pustrPath, strTempPath );
842*cdf0e10cSrcweir 
843*cdf0e10cSrcweir     if ( strTempPath )
844*cdf0e10cSrcweir         rtl_uString_release( strTempPath );
845*cdf0e10cSrcweir 
846*cdf0e10cSrcweir     /*
847*cdf0e10cSrcweir       OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL );
848*cdf0e10cSrcweir     */
849*cdf0e10cSrcweir 
850*cdf0e10cSrcweir     return nError;
851*cdf0e10cSrcweir }
852*cdf0e10cSrcweir 
853*cdf0e10cSrcweir //#############################################
854*cdf0e10cSrcweir oslFileError _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL )
855*cdf0e10cSrcweir {
856*cdf0e10cSrcweir     oslFileError nError = osl_File_E_INVAL; /* Assume failure */
857*cdf0e10cSrcweir     rtl_uString	*strTempURL = NULL;
858*cdf0e10cSrcweir     DWORD dwPathType = PATHTYPE_ERROR;
859*cdf0e10cSrcweir 
860*cdf0e10cSrcweir     if (strPath)
861*cdf0e10cSrcweir         dwPathType = IsValidFilePath(strPath, NULL, VALIDATEPATH_ALLOW_RELATIVE, NULL);
862*cdf0e10cSrcweir 
863*cdf0e10cSrcweir     if (dwPathType)
864*cdf0e10cSrcweir     {
865*cdf0e10cSrcweir         rtl_uString	*strTempPath = NULL;
866*cdf0e10cSrcweir 
867*cdf0e10cSrcweir         if ( dwPathType & PATHTYPE_IS_LONGPATH )
868*cdf0e10cSrcweir         {
869*cdf0e10cSrcweir             rtl_uString *strBuffer = NULL;
870*cdf0e10cSrcweir             sal_uInt32 nIgnore = 0;
871*cdf0e10cSrcweir             sal_uInt32 nLength = 0;
872*cdf0e10cSrcweir 
873*cdf0e10cSrcweir             /* the path has the longpath prefix, lets remove it */
874*cdf0e10cSrcweir             switch ( dwPathType & PATHTYPE_MASK_TYPE )
875*cdf0e10cSrcweir             {
876*cdf0e10cSrcweir                 case PATHTYPE_ABSOLUTE_UNC:
877*cdf0e10cSrcweir                     nIgnore = ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX_UNC ) - 1;
878*cdf0e10cSrcweir                     OSL_ENSURE( nIgnore == 8, "Unexpected long path UNC prefix!" );
879*cdf0e10cSrcweir 
880*cdf0e10cSrcweir                     /* generate the normal UNC path */
881*cdf0e10cSrcweir                     nLength = rtl_uString_getLength( strPath );
882*cdf0e10cSrcweir                     rtl_uString_newFromStr_WithLength( &strBuffer, strPath->buffer + nIgnore - 2, nLength - nIgnore + 2 );
883*cdf0e10cSrcweir                     strBuffer->buffer[0] = '\\';
884*cdf0e10cSrcweir 
885*cdf0e10cSrcweir                     rtl_uString_newReplace( &strTempPath, strBuffer, '\\', '/' );
886*cdf0e10cSrcweir                     rtl_uString_release( strBuffer );
887*cdf0e10cSrcweir                     break;
888*cdf0e10cSrcweir 
889*cdf0e10cSrcweir                 case PATHTYPE_ABSOLUTE_LOCAL:
890*cdf0e10cSrcweir                     nIgnore = ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX ) - 1;
891*cdf0e10cSrcweir                     OSL_ENSURE( nIgnore == 4, "Unexpected long path prefix!" );
892*cdf0e10cSrcweir 
893*cdf0e10cSrcweir                     /* generate the normal path */
894*cdf0e10cSrcweir                     nLength = rtl_uString_getLength( strPath );
895*cdf0e10cSrcweir                     rtl_uString_newFromStr_WithLength( &strBuffer, strPath->buffer + nIgnore, nLength - nIgnore );
896*cdf0e10cSrcweir 
897*cdf0e10cSrcweir                     rtl_uString_newReplace( &strTempPath, strBuffer, '\\', '/' );
898*cdf0e10cSrcweir                     rtl_uString_release( strBuffer );
899*cdf0e10cSrcweir                     break;
900*cdf0e10cSrcweir 
901*cdf0e10cSrcweir                 default:
902*cdf0e10cSrcweir                     OSL_ASSERT( "Unexpected long path format!" );
903*cdf0e10cSrcweir                     rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
904*cdf0e10cSrcweir                     break;
905*cdf0e10cSrcweir             }
906*cdf0e10cSrcweir         }
907*cdf0e10cSrcweir         else
908*cdf0e10cSrcweir         {
909*cdf0e10cSrcweir             /* Replace backslashes */
910*cdf0e10cSrcweir             rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
911*cdf0e10cSrcweir         }
912*cdf0e10cSrcweir 
913*cdf0e10cSrcweir         switch ( dwPathType & PATHTYPE_MASK_TYPE )
914*cdf0e10cSrcweir         {
915*cdf0e10cSrcweir         case PATHTYPE_RELATIVE:
916*cdf0e10cSrcweir             rtl_uString_assign( &strTempURL, strTempPath );
917*cdf0e10cSrcweir             nError = osl_File_E_None;
918*cdf0e10cSrcweir             break;
919*cdf0e10cSrcweir         case PATHTYPE_ABSOLUTE_UNC:
920*cdf0e10cSrcweir             rtl_uString_newFromAscii( &strTempURL, "file:" );
921*cdf0e10cSrcweir             rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
922*cdf0e10cSrcweir             nError = osl_File_E_None;
923*cdf0e10cSrcweir             break;
924*cdf0e10cSrcweir         case PATHTYPE_ABSOLUTE_LOCAL:
925*cdf0e10cSrcweir             rtl_uString_newFromAscii( &strTempURL, "file:///" );
926*cdf0e10cSrcweir             rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
927*cdf0e10cSrcweir             nError = osl_File_E_None;
928*cdf0e10cSrcweir             break;
929*cdf0e10cSrcweir         default:
930*cdf0e10cSrcweir             break;
931*cdf0e10cSrcweir         }
932*cdf0e10cSrcweir 
933*cdf0e10cSrcweir         /* Release temp path */
934*cdf0e10cSrcweir         rtl_uString_release( strTempPath );
935*cdf0e10cSrcweir     }
936*cdf0e10cSrcweir 
937*cdf0e10cSrcweir     if ( osl_File_E_None == nError )
938*cdf0e10cSrcweir     {
939*cdf0e10cSrcweir         rtl_String	*strEncodedURL = NULL;
940*cdf0e10cSrcweir 
941*cdf0e10cSrcweir         /* Encode the URL */
942*cdf0e10cSrcweir         _osl_encodeURL( strTempURL, &strEncodedURL );
943*cdf0e10cSrcweir 
944*cdf0e10cSrcweir         /* Provide URL via unicode string */
945*cdf0e10cSrcweir         rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
946*cdf0e10cSrcweir         OSL_ASSERT(*pstrURL != 0);
947*cdf0e10cSrcweir         rtl_string_release( strEncodedURL );
948*cdf0e10cSrcweir     }
949*cdf0e10cSrcweir 
950*cdf0e10cSrcweir     /* Release temp URL */
951*cdf0e10cSrcweir     if ( strTempURL )
952*cdf0e10cSrcweir         rtl_uString_release( strTempURL );
953*cdf0e10cSrcweir 
954*cdf0e10cSrcweir     /*
955*cdf0e10cSrcweir       OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath );
956*cdf0e10cSrcweir     */
957*cdf0e10cSrcweir     return nError;
958*cdf0e10cSrcweir }
959*cdf0e10cSrcweir 
960*cdf0e10cSrcweir //#####################################################
961*cdf0e10cSrcweir oslFileError SAL_CALL osl_getFileURLFromSystemPath(
962*cdf0e10cSrcweir     rtl_uString* ustrPath, rtl_uString** pustrURL )
963*cdf0e10cSrcweir {
964*cdf0e10cSrcweir 	return _osl_getFileURLFromSystemPath( ustrPath, pustrURL );
965*cdf0e10cSrcweir }
966*cdf0e10cSrcweir 
967*cdf0e10cSrcweir //#####################################################
968*cdf0e10cSrcweir oslFileError SAL_CALL osl_getSystemPathFromFileURL(
969*cdf0e10cSrcweir     rtl_uString *ustrURL, rtl_uString **pustrPath)
970*cdf0e10cSrcweir {
971*cdf0e10cSrcweir 	return _osl_getSystemPathFromFileURL( ustrURL, pustrPath, sal_True );
972*cdf0e10cSrcweir }
973*cdf0e10cSrcweir 
974*cdf0e10cSrcweir //#####################################################
975*cdf0e10cSrcweir oslFileError SAL_CALL osl_searchFileURL(
976*cdf0e10cSrcweir     rtl_uString *ustrFileName,
977*cdf0e10cSrcweir     rtl_uString *ustrSystemSearchPath,
978*cdf0e10cSrcweir     rtl_uString **pustrPath)
979*cdf0e10cSrcweir {
980*cdf0e10cSrcweir 	rtl_uString		*ustrUNCPath = NULL;
981*cdf0e10cSrcweir 	rtl_uString		*ustrSysPath = NULL;
982*cdf0e10cSrcweir 	oslFileError	error;
983*cdf0e10cSrcweir 
984*cdf0e10cSrcweir 	/* First try to interpret the file name as an URL even a relative one */
985*cdf0e10cSrcweir 	error = _osl_getSystemPathFromFileURL( ustrFileName, &ustrUNCPath, sal_True );
986*cdf0e10cSrcweir 
987*cdf0e10cSrcweir 	/* So far we either have an UNC path or something invalid
988*cdf0e10cSrcweir 	   Now create a system path */
989*cdf0e10cSrcweir 	if ( osl_File_E_None == error )
990*cdf0e10cSrcweir 		error = _osl_getSystemPathFromFileURL( ustrUNCPath, &ustrSysPath, sal_True );
991*cdf0e10cSrcweir 
992*cdf0e10cSrcweir 	if ( osl_File_E_None == error )
993*cdf0e10cSrcweir 	{
994*cdf0e10cSrcweir 		DWORD	nBufferLength;
995*cdf0e10cSrcweir 		DWORD	dwResult;
996*cdf0e10cSrcweir 		LPTSTR	lpBuffer = NULL;
997*cdf0e10cSrcweir 		LPTSTR	lpszFilePart;
998*cdf0e10cSrcweir 
999*cdf0e10cSrcweir 		/* Repeat calling SearchPath ...
1000*cdf0e10cSrcweir 		   Start with MAX_PATH for the buffer. In most cases this
1001*cdf0e10cSrcweir 		   will be enough and does not force the loop to runtwice */
1002*cdf0e10cSrcweir 		dwResult = MAX_PATH;
1003*cdf0e10cSrcweir 
1004*cdf0e10cSrcweir 		do
1005*cdf0e10cSrcweir 		{
1006*cdf0e10cSrcweir 			/* If search path is empty use a NULL pointer instead according to MSDN documentation of SearchPath */
1007*cdf0e10cSrcweir 			LPCTSTR	lpszSearchPath = ustrSystemSearchPath && ustrSystemSearchPath->length ? reinterpret_cast<LPCTSTR>(ustrSystemSearchPath->buffer) : NULL;
1008*cdf0e10cSrcweir 			LPCTSTR	lpszSearchFile = reinterpret_cast<LPCTSTR>(ustrSysPath->buffer);
1009*cdf0e10cSrcweir 
1010*cdf0e10cSrcweir 			/* Allocate space for buffer according to previous returned count of required chars */
1011*cdf0e10cSrcweir 			/* +1 is not neccessary if we follow MSDN documentation but for robustness we do so */
1012*cdf0e10cSrcweir 			nBufferLength = dwResult + 1;
1013*cdf0e10cSrcweir 			lpBuffer = lpBuffer ?
1014*cdf0e10cSrcweir 			    reinterpret_cast<LPTSTR>(rtl_reallocateMemory(lpBuffer, nBufferLength * sizeof(TCHAR))) :
1015*cdf0e10cSrcweir 			    reinterpret_cast<LPTSTR>(rtl_allocateMemory(nBufferLength * sizeof(TCHAR)));
1016*cdf0e10cSrcweir 
1017*cdf0e10cSrcweir 			dwResult = SearchPath( lpszSearchPath, lpszSearchFile, NULL, nBufferLength, lpBuffer, &lpszFilePart );
1018*cdf0e10cSrcweir 		} while ( dwResult && dwResult >= nBufferLength );
1019*cdf0e10cSrcweir 
1020*cdf0e10cSrcweir 		/*	... until an error occures or buffer is large enough.
1021*cdf0e10cSrcweir 			dwResult == nBufferLength can not happen according to documentation but lets be robust ;-) */
1022*cdf0e10cSrcweir 
1023*cdf0e10cSrcweir 		if ( dwResult )
1024*cdf0e10cSrcweir 		{
1025*cdf0e10cSrcweir 			rtl_uString_newFromStr( &ustrSysPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) );
1026*cdf0e10cSrcweir 			error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath );
1027*cdf0e10cSrcweir 		}
1028*cdf0e10cSrcweir 		else
1029*cdf0e10cSrcweir 		{
1030*cdf0e10cSrcweir 			WIN32_FIND_DATA	aFindFileData;
1031*cdf0e10cSrcweir 			HANDLE	hFind;
1032*cdf0e10cSrcweir 
1033*cdf0e10cSrcweir 			/* Somthing went wrong, perhaps the path was absolute */
1034*cdf0e10cSrcweir 			error = oslTranslateFileError( GetLastError() );
1035*cdf0e10cSrcweir 
1036*cdf0e10cSrcweir 			hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(ustrSysPath->buffer), &aFindFileData );
1037*cdf0e10cSrcweir 
1038*cdf0e10cSrcweir 			if ( IsValidHandle(hFind) )
1039*cdf0e10cSrcweir 			{
1040*cdf0e10cSrcweir 				error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath );
1041*cdf0e10cSrcweir 				FindClose( hFind );
1042*cdf0e10cSrcweir 			}
1043*cdf0e10cSrcweir 		}
1044*cdf0e10cSrcweir 
1045*cdf0e10cSrcweir 		rtl_freeMemory( lpBuffer );
1046*cdf0e10cSrcweir 	}
1047*cdf0e10cSrcweir 
1048*cdf0e10cSrcweir 	if ( ustrSysPath )
1049*cdf0e10cSrcweir 		rtl_uString_release( ustrSysPath );
1050*cdf0e10cSrcweir 
1051*cdf0e10cSrcweir 	if ( ustrUNCPath )
1052*cdf0e10cSrcweir 		rtl_uString_release( ustrUNCPath );
1053*cdf0e10cSrcweir 
1054*cdf0e10cSrcweir 	return error;
1055*cdf0e10cSrcweir }
1056*cdf0e10cSrcweir 
1057*cdf0e10cSrcweir //#####################################################
1058*cdf0e10cSrcweir 
1059*cdf0e10cSrcweir oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL )
1060*cdf0e10cSrcweir {
1061*cdf0e10cSrcweir 	oslFileError	eError;
1062*cdf0e10cSrcweir 	rtl_uString		*ustrRelSysPath = NULL;
1063*cdf0e10cSrcweir 	rtl_uString		*ustrBaseSysPath = NULL;
1064*cdf0e10cSrcweir 
1065*cdf0e10cSrcweir 	if ( ustrBaseURL && ustrBaseURL->length )
1066*cdf0e10cSrcweir 	{
1067*cdf0e10cSrcweir 		eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False );
1068*cdf0e10cSrcweir 		OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" );
1069*cdf0e10cSrcweir 
1070*cdf0e10cSrcweir 		eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True );
1071*cdf0e10cSrcweir 	}
1072*cdf0e10cSrcweir 	else
1073*cdf0e10cSrcweir 	{
1074*cdf0e10cSrcweir 		eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False );
1075*cdf0e10cSrcweir 		OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" );
1076*cdf0e10cSrcweir 	}
1077*cdf0e10cSrcweir 
1078*cdf0e10cSrcweir 	if ( !eError )
1079*cdf0e10cSrcweir 	{
1080*cdf0e10cSrcweir         ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
1081*cdf0e10cSrcweir         ::osl::LongPathBuffer< sal_Unicode > aCurrentDir( MAX_LONG_PATH );
1082*cdf0e10cSrcweir 		LPTSTR	lpFilePart = NULL;
1083*cdf0e10cSrcweir 		DWORD	dwResult;
1084*cdf0e10cSrcweir 
1085*cdf0e10cSrcweir /*@@@ToDo
1086*cdf0e10cSrcweir   Bad, bad hack, this only works if the base path
1087*cdf0e10cSrcweir   really exists which is not necessary according
1088*cdf0e10cSrcweir   to RFC2396
1089*cdf0e10cSrcweir   The whole FileURL implementation should be merged
1090*cdf0e10cSrcweir   with the rtl/uri class.
1091*cdf0e10cSrcweir */
1092*cdf0e10cSrcweir 		if ( ustrBaseSysPath )
1093*cdf0e10cSrcweir 		{
1094*cdf0e10cSrcweir 			osl_acquireMutex( g_CurrentDirectoryMutex );
1095*cdf0e10cSrcweir 
1096*cdf0e10cSrcweir 			GetCurrentDirectoryW( aCurrentDir.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aCurrentDir) );
1097*cdf0e10cSrcweir 			SetCurrentDirectoryW( reinterpret_cast<LPCWSTR>(ustrBaseSysPath->buffer) );
1098*cdf0e10cSrcweir 		}
1099*cdf0e10cSrcweir 
1100*cdf0e10cSrcweir 		dwResult = GetFullPathNameW( reinterpret_cast<LPCWSTR>(ustrRelSysPath->buffer), aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), &lpFilePart );
1101*cdf0e10cSrcweir 
1102*cdf0e10cSrcweir 		if ( ustrBaseSysPath )
1103*cdf0e10cSrcweir 		{
1104*cdf0e10cSrcweir 			SetCurrentDirectoryW( ::osl::mingw_reinterpret_cast<LPCWSTR>(aCurrentDir) );
1105*cdf0e10cSrcweir 
1106*cdf0e10cSrcweir 			osl_releaseMutex( g_CurrentDirectoryMutex );
1107*cdf0e10cSrcweir 		}
1108*cdf0e10cSrcweir 
1109*cdf0e10cSrcweir 		if ( dwResult )
1110*cdf0e10cSrcweir 		{
1111*cdf0e10cSrcweir 			if ( dwResult >= aBuffer.getBufSizeInSymbols() )
1112*cdf0e10cSrcweir 				eError = osl_File_E_INVAL;
1113*cdf0e10cSrcweir 			else
1114*cdf0e10cSrcweir 			{
1115*cdf0e10cSrcweir 				rtl_uString	*ustrAbsSysPath = NULL;
1116*cdf0e10cSrcweir 
1117*cdf0e10cSrcweir 				rtl_uString_newFromStr( &ustrAbsSysPath, aBuffer );
1118*cdf0e10cSrcweir 
1119*cdf0e10cSrcweir 				eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL );
1120*cdf0e10cSrcweir 
1121*cdf0e10cSrcweir 				if ( ustrAbsSysPath )
1122*cdf0e10cSrcweir 					rtl_uString_release( ustrAbsSysPath );
1123*cdf0e10cSrcweir 			}
1124*cdf0e10cSrcweir 		}
1125*cdf0e10cSrcweir 		else
1126*cdf0e10cSrcweir 			eError = oslTranslateFileError( GetLastError() );
1127*cdf0e10cSrcweir 	}
1128*cdf0e10cSrcweir 
1129*cdf0e10cSrcweir 	if ( ustrBaseSysPath )
1130*cdf0e10cSrcweir 		rtl_uString_release( ustrBaseSysPath );
1131*cdf0e10cSrcweir 
1132*cdf0e10cSrcweir 	if ( ustrRelSysPath )
1133*cdf0e10cSrcweir 		rtl_uString_release( ustrRelSysPath );
1134*cdf0e10cSrcweir 
1135*cdf0e10cSrcweir 	return	eError;
1136*cdf0e10cSrcweir }
1137*cdf0e10cSrcweir 
1138*cdf0e10cSrcweir //#####################################################
1139*cdf0e10cSrcweir oslFileError SAL_CALL osl_getCanonicalName( rtl_uString *strRequested, rtl_uString **strValid )
1140*cdf0e10cSrcweir {
1141*cdf0e10cSrcweir 	rtl_uString_newFromString(strValid, strRequested);
1142*cdf0e10cSrcweir 	return osl_File_E_None;
1143*cdf0e10cSrcweir }
1144