xref: /trunk/main/sal/osl/w32/file_dirvol.cxx (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #define UNICODE
25 #define _UNICODE
26 #define _WIN32_WINNT_0x0500
27 #include "systools/win32/uwinapi.h"
28 
29 #include "osl/file.h"
30 
31 #include "file_url.h"
32 #include "file_error.h"
33 
34 #include "path_helper.hxx"
35 
36 #include "osl/diagnose.h"
37 #include "osl/time.h"
38 #include "rtl/alloc.h"
39 #include "rtl/ustring.hxx"
40 
41 #include <tchar.h>
42 #ifdef __MINGW32__
43 #include <ctype.h>
44 #endif
45 
46 //#####################################################
47 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
48 
49 static const wchar_t UNC_PREFIX[] = L"\\\\";
50 static const wchar_t BACKSLASH = '\\';
51 static const wchar_t SLASH = '/';
52 
53 //#####################################################
TimeValueToFileTime(const TimeValue * cpTimeVal,FILETIME * pFTime)54 extern "C" BOOL TimeValueToFileTime(const TimeValue *cpTimeVal, FILETIME *pFTime)
55 {
56 	SYSTEMTIME	BaseSysTime;
57 	FILETIME	BaseFileTime;
58 	FILETIME	FTime;
59 	__int64		localTime;
60 	BOOL		fSuccess = FALSE;
61 
62 	BaseSysTime.wYear         = 1970;
63 	BaseSysTime.wMonth        = 1;
64     BaseSysTime.wDayOfWeek    = 0;
65     BaseSysTime.wDay          = 1;
66     BaseSysTime.wHour         = 0;
67     BaseSysTime.wMinute       = 0;
68     BaseSysTime.wSecond       = 0;
69     BaseSysTime.wMilliseconds = 0;
70 
71 	if (cpTimeVal==NULL)
72 		return fSuccess;
73 
74 	if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
75 	{
76 		__int64 timeValue;
77 		localTime=cpTimeVal->Seconds*(__int64)10000000+cpTimeVal->Nanosec/100;
78 		*(__int64 *)&FTime=localTime;
79 		fSuccess = 0 <= (timeValue= *((__int64 *)&BaseFileTime) + *((__int64 *) &FTime));
80 		if (fSuccess)
81 			*(__int64 *)pFTime=timeValue;
82 	}
83 	return fSuccess;
84 }
85 
86 //#####################################################
FileTimeToTimeValue(const FILETIME * cpFTime,TimeValue * pTimeVal)87 extern "C" BOOL FileTimeToTimeValue(const FILETIME *cpFTime, TimeValue *pTimeVal)
88 {
89 	SYSTEMTIME	BaseSysTime;
90 	FILETIME	BaseFileTime;
91 	BOOL		fSuccess = FALSE;	/* Assume failure */
92 
93 	BaseSysTime.wYear         = 1970;
94 	BaseSysTime.wMonth        = 1;
95     BaseSysTime.wDayOfWeek    = 0;
96     BaseSysTime.wDay          = 1;
97     BaseSysTime.wHour         = 0;
98     BaseSysTime.wMinute       = 0;
99     BaseSysTime.wSecond       = 0;
100     BaseSysTime.wMilliseconds = 0;
101 
102 	if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
103 	{
104 		__int64		Value;
105 
106 		fSuccess = 0 <= (Value = *((__int64 *)cpFTime) - *((__int64 *)&BaseFileTime));
107 
108 		if ( fSuccess )
109 		{
110 			pTimeVal->Seconds  = (unsigned long) (Value / 10000000L);
111 			pTimeVal->Nanosec  = (unsigned long)((Value % 10000000L) * 100);
112 		}
113 	}
114 	return fSuccess;
115 }
116 
117 //#####################################################
118 namespace /* private */
119 {
120     //#####################################################
121 	struct Component
122     {
Component__anon1d5b1b750111::Component123         Component() :
124             begin_(0), end_(0)
125         {}
126 
isPresent__anon1d5b1b750111::Component127         bool isPresent() const
128         { return (static_cast<sal_IntPtr>(end_ - begin_) > 0); }
129 
130         const sal_Unicode* begin_;
131         const sal_Unicode* end_;
132     };
133 
134     //#####################################################
135     struct UNCComponents
136     {
137         Component server_;
138         Component share_;
139         Component resource_;
140     };
141 
142     //#####################################################
is_UNC_path(const sal_Unicode * path)143     inline bool is_UNC_path(const sal_Unicode* path)
144     { return (0 == wcsncmp(UNC_PREFIX, reinterpret_cast<LPCWSTR>(path), ELEMENTS_OF_ARRAY(UNC_PREFIX) - 1)); }
145 
146     //#####################################################
is_UNC_path(const rtl::OUString & path)147     inline bool is_UNC_path(const rtl::OUString& path)
148     { return is_UNC_path(path.getStr()); }
149 
150     //#####################################################
parse_UNC_path(const sal_Unicode * path,UNCComponents * puncc)151     void parse_UNC_path(const sal_Unicode* path, UNCComponents* puncc)
152     {
153         OSL_PRECOND(is_UNC_path(path), "Precondition violated: No UNC path");
154         OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) == -1, "Path must not contain slashes");
155 
156         const sal_Unicode* pend = path + rtl_ustr_getLength(path);
157         const sal_Unicode* ppos = path + 2;
158 
159         puncc->server_.begin_ = ppos;
160         while ((ppos < pend) && (*ppos != BACKSLASH))
161             ppos++;
162 
163         puncc->server_.end_ = ppos;
164 
165         if (BACKSLASH == *ppos)
166         {
167             puncc->share_.begin_ = ++ppos;
168             while ((ppos < pend) && (*ppos != BACKSLASH))
169                 ppos++;
170 
171             puncc->share_.end_ = ppos;
172 
173             if (BACKSLASH == *ppos)
174             {
175                 puncc->resource_.begin_ = ++ppos;
176                 while (ppos < pend)
177                     ppos++;
178 
179                 puncc->resource_.end_ = ppos;
180             }
181         }
182 
183         OSL_POSTCOND(puncc->server_.isPresent() && puncc->share_.isPresent(), \
184         "Postcondition violated: Invalid UNC path detected");
185     }
186 
187     //#####################################################
parse_UNC_path(const rtl::OUString & path,UNCComponents * puncc)188     void parse_UNC_path(const rtl::OUString& path, UNCComponents* puncc)
189     { parse_UNC_path(path.getStr(), puncc); }
190 
191 
192     //#####################################################
has_path_parent(const sal_Unicode * path)193     bool has_path_parent(const sal_Unicode* path)
194     {
195 		// Has the given path a parent or are we already there,
196 		// e.g. 'c:\' or '\\server\share\'?
197 
198         bool has_parent = false;
199         if (is_UNC_path(path))
200         {
201             UNCComponents unc_comp;
202             parse_UNC_path(path, &unc_comp);
203             has_parent = unc_comp.resource_.isPresent();
204         }
205         else
206         {
207             has_parent = !osl::systemPathIsLogicalDrivePattern(path);
208         }
209         return has_parent;
210     }
211 
212     //#####################################################
has_path_parent(const rtl::OUString & path)213     inline bool has_path_parent(const rtl::OUString& path)
214     { return has_path_parent(path.getStr()); }
215 
216 } // end namespace private
217 
218 //#####################################################
219 // volume handling functions
220 //#####################################################
221 
222 //#####################################################
osl_unmountVolumeDevice(oslVolumeDeviceHandle Handle)223 oslFileError SAL_CALL osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
224 {
225 	if ( Handle )
226 		return osl_File_E_None;
227 	else
228 		return osl_File_E_INVAL;
229 }
230 
231 //#####################################################
osl_automountVolumeDevice(oslVolumeDeviceHandle Handle)232 oslFileError SAL_CALL osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
233 {
234 	if ( Handle )
235 		return osl_File_E_None;
236 	else
237 		return osl_File_E_INVAL;
238 }
239 
240 //#####################################################
osl_acquireVolumeDeviceHandle(oslVolumeDeviceHandle Handle)241 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
242 {
243 	if ( Handle )
244 	{
245 		rtl_uString_acquire( (rtl_uString *)Handle );
246 		return osl_File_E_None;
247 	}
248 	else
249 		return osl_File_E_INVAL;
250 }
251 
252 //#####################################################
osl_releaseVolumeDeviceHandle(oslVolumeDeviceHandle Handle)253 oslFileError SAL_CALL osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
254 {
255 	if ( Handle )
256 	{
257 		rtl_uString_release( (rtl_uString *)Handle );
258 		return osl_File_E_None;
259 	}
260 	else
261 		return osl_File_E_INVAL;
262 }
263 
264 //#####################################################
osl_getVolumeDeviceMountPath(oslVolumeDeviceHandle Handle,rtl_uString ** pstrPath)265 oslFileError SAL_CALL osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
266 {
267 	if ( Handle && pstrPath )
268 	{
269 		rtl_uString_assign( pstrPath, (rtl_uString *)Handle );
270 		return osl_File_E_None;
271 	}
272 	else
273 		return osl_File_E_INVAL;
274 }
275 
276 //##################################################################
277 // directory handling functions
278 //##################################################################
279 
280 #define DIRECTORYITEM_DRIVE		0
281 #define DIRECTORYITEM_FILE		1
282 #define DIRECTORYITEM_SERVER	2
283 
284 struct DirectoryItem_Impl
285 {
286 	UINT uType;
287 	union {
288 		WIN32_FIND_DATA	FindData;
289 		TCHAR			cDriveString[MAX_PATH];
290 	};
291     rtl_uString*    m_pFullPath;
292 	BOOL			bFullPathNormalized;
293 	int				nRefCount;
294 };
295 
296 //#####################################################
297 
298 #define	DIRECTORYTYPE_LOCALROOT	    0
299 #define	DIRECTORYTYPE_NETROOT		1
300 #define	DIRECTORYTYPE_NETRESORCE	2
301 #define	DIRECTORYTYPE_FILESYSTEM	3
302 
303 struct Directory_Impl
304 {
305 	UINT uType;
306 	union {
307 		HANDLE	hDirectory;
308 		HANDLE	hEnumDrives;
309 	};
310     rtl_uString*    m_pDirectoryPath;
311 };
312 
313 //#####################################################
314 
315 typedef struct tagDRIVEENUM
316 {
317 	LPCTSTR	lpIdent;
318 	TCHAR	cBuffer[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
319 	LPCTSTR	lpCurrent;
320 } DRIVEENUM, * PDRIVEENUM, FAR * LPDRIVEENUM;
321 
322 //#####################################################
323 
OpenLogicalDrivesEnum(void)324 static HANDLE WINAPI OpenLogicalDrivesEnum(void)
325 {
326 	LPDRIVEENUM	pEnum = (LPDRIVEENUM)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM) );
327 	if ( pEnum )
328 	{
329 		DWORD dwNumCopied = GetLogicalDriveStrings( (sizeof(pEnum->cBuffer) - 1) / sizeof(TCHAR), pEnum->cBuffer );
330 
331 		if ( dwNumCopied && dwNumCopied < sizeof(pEnum->cBuffer) / sizeof(TCHAR) )
332 		{
333 			pEnum->lpCurrent = pEnum->cBuffer;
334 			pEnum->lpIdent = L"tagDRIVEENUM";
335 		}
336 		else
337 		{
338 			HeapFree( GetProcessHeap(), 0, pEnum );
339 			pEnum = NULL;
340 		}
341 	}
342 	return pEnum ? (HANDLE)pEnum : INVALID_HANDLE_VALUE;
343 }
344 
345 //#####################################################
EnumLogicalDrives(HANDLE hEnum,LPTSTR lpBuffer)346 static BOOL WINAPI EnumLogicalDrives(HANDLE hEnum, LPTSTR lpBuffer)
347 {
348 	BOOL		fSuccess = FALSE;
349 	LPDRIVEENUM	pEnum = (LPDRIVEENUM)hEnum;
350 
351 	if ( pEnum )
352 	{
353 		int	nLen = _tcslen( pEnum->lpCurrent );
354 
355 		if ( nLen )
356 		{
357 			CopyMemory( lpBuffer, pEnum->lpCurrent, (nLen + 1) * sizeof(TCHAR) );
358 			pEnum->lpCurrent += nLen + 1;
359 			fSuccess = TRUE;
360 		}
361 		else
362 			SetLastError( ERROR_NO_MORE_FILES );
363 	}
364 	else
365 		SetLastError( ERROR_INVALID_HANDLE );
366 
367 	return fSuccess;
368 }
369 
370 //#####################################################
CloseLogicalDrivesEnum(HANDLE hEnum)371 static BOOL WINAPI CloseLogicalDrivesEnum(HANDLE hEnum)
372 {
373 	BOOL		fSuccess = FALSE;
374 	LPDRIVEENUM	pEnum = (LPDRIVEENUM)hEnum;
375 
376 	if ( pEnum )
377 	{
378 		HeapFree( GetProcessHeap(), 0, pEnum );
379 		fSuccess = TRUE;
380 	}
381 	else
382 		SetLastError( ERROR_INVALID_HANDLE );
383 
384 	return fSuccess;
385 }
386 
387 //#####################################################
388 typedef struct tagDIRECTORY
389 {
390 	HANDLE          hFind;
391 	WIN32_FIND_DATA aFirstData;
392 } DIRECTORY, *PDIRECTORY, FAR *LPDIRECTORY;
393 
394 //#####################################################
OpenDirectory(rtl_uString * pPath)395 static HANDLE WINAPI OpenDirectory( rtl_uString* pPath)
396 {
397 	LPDIRECTORY	pDirectory = NULL;
398 
399 	if ( pPath )
400 	{
401         sal_uInt32 nLen = rtl_uString_getLength( pPath );
402         if ( nLen )
403         {
404             TCHAR* pSuffix = 0;
405             sal_uInt32 nSuffLen = 0;
406 
407             if ( pPath->buffer[nLen - 1] != L'\\' )
408             {
409                 pSuffix = L"\\*.*";
410                 nSuffLen = 4;
411             }
412             else
413             {
414                 pSuffix = L"*.*";
415                 nSuffLen = 3;
416             }
417 
418             TCHAR* szFileMask = reinterpret_cast< TCHAR* >( rtl_allocateMemory( sizeof( TCHAR ) * ( nLen + nSuffLen + 1 ) ) );
419 
420 		    _tcscpy( szFileMask, reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pPath ) ) );
421             _tcscat( szFileMask, pSuffix );
422 
423             pDirectory = (LPDIRECTORY)HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY));
424             pDirectory->hFind = FindFirstFile(szFileMask, &pDirectory->aFirstData);
425 
426             if (!IsValidHandle(pDirectory->hFind))
427             {
428                 if ( GetLastError() != ERROR_NO_MORE_FILES )
429                 {
430                     HeapFree(GetProcessHeap(), 0, pDirectory);
431                     pDirectory = NULL;
432                 }
433             }
434 
435             rtl_freeMemory(szFileMask);  // #119939#, memory leak
436         }
437 	}
438 
439 	return (HANDLE)pDirectory;
440 }
441 
442 //#####################################################
EnumDirectory(HANDLE hDirectory,LPWIN32_FIND_DATA pFindData)443 BOOL WINAPI EnumDirectory(HANDLE hDirectory, LPWIN32_FIND_DATA pFindData)
444 {
445 	BOOL		fSuccess = FALSE;
446 	LPDIRECTORY	pDirectory = (LPDIRECTORY)hDirectory;
447 
448 	if ( pDirectory )
449 	{
450 		BOOL	fValid;
451 
452 		do
453 		{
454 			if ( pDirectory->aFirstData.cFileName[0] )
455 			{
456 				*pFindData = pDirectory->aFirstData;
457 				fSuccess = TRUE;
458 				pDirectory->aFirstData.cFileName[0] = 0;
459 			}
460 			else if ( IsValidHandle( pDirectory->hFind ) )
461 				fSuccess = FindNextFile( pDirectory->hFind, pFindData );
462 			else
463 			{
464 				fSuccess = FALSE;
465 				SetLastError( ERROR_NO_MORE_FILES );
466 			}
467 
468 			fValid = fSuccess && _tcscmp( TEXT("."), pFindData->cFileName ) != 0 && _tcscmp( TEXT(".."), pFindData->cFileName ) != 0;
469 
470 		} while( fSuccess && !fValid );
471 	}
472 	else
473 		SetLastError( ERROR_INVALID_HANDLE );
474 
475 	return fSuccess;
476 }
477 
478 //#####################################################
CloseDirectory(HANDLE hDirectory)479 static BOOL WINAPI CloseDirectory(HANDLE hDirectory)
480 {
481 	BOOL		fSuccess = FALSE;
482 	LPDIRECTORY	pDirectory = (LPDIRECTORY)hDirectory;
483 
484 	if (pDirectory)
485 	{
486 		if (IsValidHandle(pDirectory->hFind))
487 			fSuccess = FindClose(pDirectory->hFind);
488 
489 		fSuccess = HeapFree(GetProcessHeap(), 0, pDirectory) && fSuccess;
490 	}
491 	else
492 		SetLastError(ERROR_INVALID_HANDLE);
493 
494 	return fSuccess;
495 }
496 
497 //#####################################################
osl_openLocalRoot(rtl_uString * strDirectoryPath,oslDirectory * pDirectory)498 static oslFileError osl_openLocalRoot(
499     rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
500 {
501     rtl_uString		*strSysPath = NULL;
502     oslFileError	error;
503 
504     if ( !pDirectory )
505         return osl_File_E_INVAL;
506 
507     *pDirectory = NULL;
508 
509     error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysPath, sal_False );
510     if ( osl_File_E_None == error )
511     {
512         Directory_Impl	*pDirImpl;
513 
514         pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory( sizeof(Directory_Impl)));
515         ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
516         rtl_uString_newFromString( &pDirImpl->m_pDirectoryPath, strSysPath );
517 
518         /* Append backslash if necessary */
519 
520         /* @@@ToDo
521            use function ensure backslash
522         */
523         sal_uInt32 nLen = rtl_uString_getLength( pDirImpl->m_pDirectoryPath );
524         if ( nLen && pDirImpl->m_pDirectoryPath->buffer[nLen - 1] != L'\\' )
525         {
526             rtl_uString* pCurDir = 0;
527             rtl_uString* pBackSlash = 0;
528 
529             rtl_uString_assign( &pCurDir, pDirImpl->m_pDirectoryPath );
530             rtl_uString_newFromAscii( &pBackSlash, "\\" );
531             rtl_uString_newConcat( &pDirImpl->m_pDirectoryPath, pCurDir, pBackSlash );
532             rtl_uString_release( pBackSlash );
533             rtl_uString_release( pCurDir );
534         }
535 
536         pDirImpl->uType = DIRECTORYTYPE_LOCALROOT;
537         pDirImpl->hEnumDrives = OpenLogicalDrivesEnum();
538 
539         /* @@@ToDo
540            Use IsValidHandle(...)
541         */
542         if ( pDirImpl->hEnumDrives != INVALID_HANDLE_VALUE )
543         {
544             *pDirectory = (oslDirectory)pDirImpl;
545             error = osl_File_E_None;
546         }
547         else
548         {
549             if ( pDirImpl )
550             {
551                 if ( pDirImpl->m_pDirectoryPath )
552                 {
553                     rtl_uString_release( pDirImpl->m_pDirectoryPath );
554                     pDirImpl->m_pDirectoryPath = 0;
555                 }
556 
557                 rtl_freeMemory(pDirImpl);
558                 pDirImpl = 0;
559             }
560 
561             error = oslTranslateFileError( GetLastError() );
562         }
563 
564         rtl_uString_release( strSysPath );
565     }
566     return error;
567 }
568 
569 //#####################################################
osl_openFileDirectory(rtl_uString * strDirectoryPath,oslDirectory * pDirectory)570 static oslFileError SAL_CALL osl_openFileDirectory(
571 	rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
572 {
573 	oslFileError error = osl_File_E_None;
574 
575 	if ( !pDirectory )
576 		return osl_File_E_INVAL;
577 	*pDirectory = NULL;
578 
579 	Directory_Impl *pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
580     ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
581     rtl_uString_newFromString( &pDirImpl->m_pDirectoryPath, strDirectoryPath );
582 
583 	/* Append backslash if necessary */
584 
585 	/* @@@ToDo
586 	   use function ensure backslash
587 	*/
588     sal_uInt32 nLen = rtl_uString_getLength( pDirImpl->m_pDirectoryPath );
589     if ( nLen && pDirImpl->m_pDirectoryPath->buffer[nLen - 1] != L'\\' )
590     {
591         rtl_uString* pCurDir = 0;
592         rtl_uString* pBackSlash = 0;
593 
594         rtl_uString_assign( &pCurDir, pDirImpl->m_pDirectoryPath );
595         rtl_uString_newFromAscii( &pBackSlash, "\\" );
596         rtl_uString_newConcat( &pDirImpl->m_pDirectoryPath, pCurDir, pBackSlash );
597         rtl_uString_release( pBackSlash );
598         rtl_uString_release( pCurDir );
599     }
600 
601 
602 	pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM;
603 	pDirImpl->hDirectory = OpenDirectory( pDirImpl->m_pDirectoryPath );
604 
605 	if ( !pDirImpl->hDirectory )
606 	{
607 		error = oslTranslateFileError( GetLastError() );
608 
609         if ( pDirImpl->m_pDirectoryPath )
610         {
611             rtl_uString_release( pDirImpl->m_pDirectoryPath );
612             pDirImpl->m_pDirectoryPath = 0;
613         }
614 
615 		rtl_freeMemory(pDirImpl), pDirImpl = 0;
616 	}
617 
618 	*pDirectory = (oslDirectory)(pDirImpl);
619 	return error;
620 }
621 
622 //#####################################################
osl_openNetworkServer(rtl_uString * strSysDirPath,oslDirectory * pDirectory)623 static oslFileError SAL_CALL osl_openNetworkServer(
624 	rtl_uString *strSysDirPath, oslDirectory *pDirectory)
625 {
626 	NETRESOURCEW	aNetResource;
627 	HANDLE			hEnum;
628 	DWORD			dwError;
629 
630 	ZeroMemory( &aNetResource, sizeof(aNetResource) );
631 
632 	aNetResource.lpRemoteName = reinterpret_cast<LPWSTR>(strSysDirPath->buffer);
633 
634 	dwError = WNetOpenEnumW(
635 		RESOURCE_GLOBALNET,
636 		RESOURCETYPE_DISK,
637 		RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER,
638 		&aNetResource,
639 		&hEnum );
640 
641 	if ( ERROR_SUCCESS == dwError )
642 	{
643 		Directory_Impl	*pDirImpl;
644 
645 		pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
646         ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
647 		pDirImpl->uType = DIRECTORYTYPE_NETROOT;
648 		pDirImpl->hDirectory = hEnum;
649 		*pDirectory = (oslDirectory)pDirImpl;
650 	}
651 	return oslTranslateFileError( dwError );
652 }
653 
654 //#############################################
create_dir_with_callback(rtl_uString * dir_path,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)655 static DWORD create_dir_with_callback(
656     rtl_uString * dir_path,
657     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
658     void* pData)
659 {
660 	// Create the specified directory and call the
661 	// user specified callback function. On success
662 	// the function returns ERROR_SUCCESS else a Win32 error code.
663 
664     BOOL bCreated = FALSE;
665 
666     bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( dir_path )), NULL );
667 
668     if ( bCreated )
669     {
670         if (aDirectoryCreationCallbackFunc)
671         {
672             rtl::OUString url;
673             _osl_getFileURLFromSystemPath(dir_path, &(url.pData));
674             aDirectoryCreationCallbackFunc(pData, url.pData);
675         }
676         return ERROR_SUCCESS;
677     }
678     return GetLastError();
679 }
680 
681 //#############################################
path_make_parent(sal_Unicode * path)682 static int path_make_parent(sal_Unicode* path)
683 {
684     /*  Cut off the last part of the given path to
685     get the parent only, e.g. 'c:\dir\subdir' ->
686     'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
687     @return The position where the path has been cut
688     off (this is the posistion of the last backslash).
689     If there are no more parents 0 will be returned,
690     e.g. 'c:\' or '\\Share' have no more parents */
691 
692 	OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) == -1, "Path must not contain slashes");
693 	OSL_PRECOND(has_path_parent(path), "Path must have a parent");
694 
695 	sal_Unicode* pos_last_backslash = path + rtl_ustr_lastIndexOfChar(path, BACKSLASH);
696 	*pos_last_backslash = 0;
697 	return (pos_last_backslash - path);
698 }
699 
700 //#############################################
create_dir_recursively_(rtl_uString * dir_path,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)701 static DWORD create_dir_recursively_(
702     rtl_uString * dir_path,
703     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
704     void* pData)
705 {
706     OSL_PRECOND(
707 		rtl_ustr_lastIndexOfChar_WithLength(dir_path->buffer, dir_path->length, BACKSLASH) != dir_path->length,
708 		"Path must not end with a backslash");
709 
710     DWORD w32_error = create_dir_with_callback(
711         dir_path, aDirectoryCreationCallbackFunc, pData);
712     if (w32_error == ERROR_SUCCESS)
713         return ERROR_SUCCESS;
714 
715     if ((w32_error != ERROR_PATH_NOT_FOUND) || !has_path_parent(dir_path->buffer))
716         return w32_error;
717 
718     int pos = path_make_parent(dir_path->buffer); // dir_path->buffer[pos] = 0, restore below
719 
720     w32_error = create_dir_recursively_(
721         dir_path, aDirectoryCreationCallbackFunc, pData);
722 
723     dir_path->buffer[pos] = BACKSLASH; // restore
724 
725     if (ERROR_SUCCESS != w32_error)
726         return w32_error;
727 
728     return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
729 }
730 
731 //#############################################
osl_createDirectoryPath(rtl_uString * aDirectoryUrl,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)732 oslFileError SAL_CALL osl_createDirectoryPath(
733     rtl_uString* aDirectoryUrl,
734     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
735     void* pData)
736 {
737     if (aDirectoryUrl == NULL)
738         return osl_File_E_INVAL;
739 
740     rtl::OUString sys_path;
741     oslFileError osl_error =
742         _osl_getSystemPathFromFileURL(aDirectoryUrl, &sys_path.pData, sal_False);
743 
744     if (osl_error != osl_File_E_None)
745         return osl_error;
746 
747     osl::systemPathRemoveSeparator(sys_path);
748 
749     // const_cast because sys_path is a local copy
750     // which we want to modify inplace instead of
751     // coyp it into another buffer on the heap again
752     return oslTranslateFileError(create_dir_recursively_(
753         sys_path.pData, aDirectoryCreationCallbackFunc, pData));
754 }
755 
756 //#####################################################
osl_createDirectory(rtl_uString * strPath)757 oslFileError SAL_CALL osl_createDirectory(rtl_uString* strPath)
758 {
759 	rtl_uString	*strSysPath = NULL;
760 	oslFileError	error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
761 
762 	if ( osl_File_E_None == error )
763 	{
764         BOOL bCreated = FALSE;
765 
766         bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), NULL );
767 
768         if ( !bCreated )
769 		{
770             /*@@@ToDo
771               The following case is a hack because the ucb or the webtop had some
772               problems with the error code that CreateDirectory returns in
773               case the path is only a logical drive, should be removed!
774             */
775 
776 			const sal_Unicode	*pBuffer = rtl_uString_getStr( strSysPath );
777 			sal_Int32			nLen = rtl_uString_getLength( strSysPath );
778 
779 			if (
780 				( ( pBuffer[0] >= 'A' && pBuffer[0] <= 'Z' ) ||
781 				  ( pBuffer[0] >= 'a' && pBuffer[0] <= 'z' ) ) &&
782 				pBuffer[1] == ':' && ( nLen ==2 || ( nLen == 3 && pBuffer[2] == '\\' ) )
783 				)
784 				SetLastError( ERROR_ALREADY_EXISTS );
785 
786 			error = oslTranslateFileError( GetLastError() );
787 		}
788 
789 		rtl_uString_release( strSysPath );
790 	}
791 	return error;
792 }
793 
794 //#####################################################
osl_removeDirectory(rtl_uString * strPath)795 oslFileError SAL_CALL osl_removeDirectory(rtl_uString* strPath)
796 {
797 	rtl_uString	*strSysPath = NULL;
798 	oslFileError	error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
799 
800 	if ( osl_File_E_None == error )
801 	{
802 		if ( RemoveDirectory( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
803 			error = osl_File_E_None;
804 		else
805 			error = oslTranslateFileError( GetLastError() );
806 
807 		rtl_uString_release( strSysPath );
808 	}
809 	return error;
810 }
811 
812 //#####################################################
osl_openDirectory(rtl_uString * strDirectoryPath,oslDirectory * pDirectory)813 oslFileError SAL_CALL osl_openDirectory(rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
814 {
815 	oslFileError	error;
816 
817 	if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath->buffer, "file:///" ) )
818 		error = osl_openLocalRoot( strDirectoryPath, pDirectory );
819 	else
820 	{
821 		rtl_uString	*strSysDirectoryPath = NULL;
822 		DWORD		dwPathType;
823 
824 		error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysDirectoryPath, sal_False );
825 
826 		if ( osl_File_E_None != error )
827 				return error;
828 
829 		dwPathType = IsValidFilePath( strSysDirectoryPath, NULL, VALIDATEPATH_NORMAL, NULL );
830 
831 		if ( dwPathType & PATHTYPE_IS_SERVER )
832 		{
833 			error = osl_openNetworkServer( strSysDirectoryPath, pDirectory );
834 		}
835 		else
836 			error = osl_openFileDirectory( strSysDirectoryPath, pDirectory );
837 
838 		rtl_uString_release( strSysDirectoryPath );
839 	}
840 	return error;
841 }
842 
843 //#####################################################
osl_getNextNetResource(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)844 static oslFileError SAL_CALL osl_getNextNetResource(
845 	oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
846 {
847 	Directory_Impl		*pDirImpl = (Directory_Impl *)Directory;
848 	DirectoryItem_Impl	*pItemImpl = NULL;
849 	BYTE				buffer[16384];
850 	LPNETRESOURCEW		lpNetResource = (LPNETRESOURCEW)buffer;
851 	DWORD				dwError, dwCount, dwBufSize;
852 
853 	uHint = uHint; /* to get no warning */
854 
855 	if ( !pItem )
856 		return osl_File_E_INVAL;
857 	*pItem = NULL;
858 
859 	if ( !pDirImpl )
860 		return osl_File_E_INVAL;
861 
862 	dwCount = 1;
863 	dwBufSize = sizeof(buffer);
864 	dwError = WNetEnumResource( pDirImpl->hDirectory, &dwCount, lpNetResource, &dwBufSize );
865 
866 	switch ( dwError )
867 	{
868 	    case NO_ERROR:
869 	    case ERROR_MORE_DATA:
870 		{
871 			pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
872 			if ( !pItemImpl )
873 				return osl_File_E_NOMEM;
874 
875 			ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
876 			pItemImpl->uType = DIRECTORYITEM_DRIVE;
877 			osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
878 
879 			wcscpy( pItemImpl->cDriveString, lpNetResource->lpRemoteName );
880 
881 			*pItem = pItemImpl;
882 		}
883 		return osl_File_E_None;
884 	    case ERROR_NO_MORE_ITEMS:
885 		    return osl_File_E_NOENT;
886 	    default:
887 		    return oslTranslateFileError( dwError );
888 	}
889 }
890 
891 //#####################################################
osl_getNextDrive(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)892 static oslFileError SAL_CALL osl_getNextDrive(
893 	oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
894 {
895 	Directory_Impl		*pDirImpl = (Directory_Impl *)Directory;
896 	DirectoryItem_Impl	*pItemImpl = NULL;
897 	BOOL				fSuccess;
898 
899 	uHint = uHint; /* avoid warnings */
900 
901 	if ( !pItem )
902 		return osl_File_E_INVAL;
903 	*pItem = NULL;
904 
905 	if ( !pDirImpl )
906 		return osl_File_E_INVAL;
907 
908 	pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
909 	if ( !pItemImpl )
910 		return osl_File_E_NOMEM;
911 
912 	ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
913 	pItemImpl->uType = DIRECTORYITEM_DRIVE;
914 	osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
915 	fSuccess = EnumLogicalDrives( pDirImpl->hEnumDrives, pItemImpl->cDriveString );
916 
917 	if ( fSuccess )
918 	{
919 		*pItem = pItemImpl;
920 		return osl_File_E_None;
921 	}
922 	else
923 	{
924         if ( pItemImpl->m_pFullPath )
925         {
926             rtl_uString_release( pItemImpl->m_pFullPath );
927             pItemImpl->m_pFullPath = 0;
928         }
929 
930 		rtl_freeMemory( pItemImpl );
931 		return oslTranslateFileError( GetLastError() );
932 	}
933 }
934 
935 //#####################################################
osl_getNextFileItem(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)936 static oslFileError SAL_CALL osl_getNextFileItem(
937 	oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
938 {
939 	Directory_Impl		*pDirImpl = (Directory_Impl *)Directory;
940 	DirectoryItem_Impl	*pItemImpl = NULL;
941 	BOOL				fFound;
942 
943 	uHint = uHint; /* avoid warnings */
944 
945 	if ( !pItem )
946 		return osl_File_E_INVAL;
947 	*pItem = NULL;
948 
949 	if ( !pDirImpl )
950 		return osl_File_E_INVAL;
951 
952 	pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
953 	if ( !pItemImpl )
954 		return osl_File_E_NOMEM;
955 
956 	memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
957 	fFound = EnumDirectory( pDirImpl->hDirectory, &pItemImpl->FindData );
958 
959 	if ( fFound )
960 	{
961 		pItemImpl->uType = DIRECTORYITEM_FILE;
962 		pItemImpl->nRefCount = 1;
963 
964         rtl_uString* pTmpFileName = 0;
965         rtl_uString_newFromStr( &pTmpFileName,  reinterpret_cast<const sal_Unicode *>(pItemImpl->FindData.cFileName) );
966         rtl_uString_newConcat( &pItemImpl->m_pFullPath, pDirImpl->m_pDirectoryPath, pTmpFileName );
967         rtl_uString_release( pTmpFileName );
968 
969 		pItemImpl->bFullPathNormalized = FALSE;
970 		*pItem = (oslDirectoryItem)pItemImpl;
971 		return osl_File_E_None;
972 	}
973 	else
974 	{
975         if ( pItemImpl->m_pFullPath )
976         {
977             rtl_uString_release( pItemImpl->m_pFullPath );
978             pItemImpl->m_pFullPath = 0;
979         }
980 
981 		rtl_freeMemory( pItemImpl );
982 		return oslTranslateFileError( GetLastError() );
983 	}
984 }
985 
986 //#####################################################
osl_getNextDirectoryItem(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)987 oslFileError SAL_CALL osl_getNextDirectoryItem(
988 	oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
989 {
990 	Directory_Impl		*pDirImpl = (Directory_Impl *)Directory;
991 
992 	/* Assume failure */
993 
994 	if ( !pItem )
995 		return osl_File_E_INVAL;
996 	*pItem = NULL;
997 
998 	if ( !pDirImpl )
999 		return osl_File_E_INVAL;
1000 
1001 	switch ( pDirImpl->uType )
1002 	{
1003 	case DIRECTORYTYPE_LOCALROOT:
1004 		return osl_getNextDrive( Directory, pItem, uHint );
1005 	case DIRECTORYTYPE_NETROOT:
1006 		return osl_getNextNetResource( Directory, pItem, uHint );
1007 	case DIRECTORYTYPE_FILESYSTEM:
1008 		return osl_getNextFileItem( Directory, pItem, uHint );
1009 	default:
1010 		return osl_File_E_INVAL;
1011 	}
1012 }
1013 
1014 //#####################################################
osl_closeDirectory(oslDirectory Directory)1015 oslFileError SAL_CALL osl_closeDirectory(oslDirectory Directory)
1016 {
1017 	Directory_Impl	*pDirImpl = (Directory_Impl *)Directory;
1018 	oslFileError	eError = osl_File_E_INVAL;
1019 
1020 	if ( pDirImpl )
1021 	{
1022 		switch ( pDirImpl->uType )
1023 		{
1024 		case DIRECTORYTYPE_FILESYSTEM:
1025 			eError = CloseDirectory( pDirImpl->hDirectory ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
1026 			break;
1027 		case DIRECTORYTYPE_LOCALROOT:
1028 			eError = CloseLogicalDrivesEnum( pDirImpl->hEnumDrives ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
1029 			break;
1030 		case DIRECTORYTYPE_NETROOT:
1031 		    {
1032 		        DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
1033 			    eError = (err == NO_ERROR) ? osl_File_E_None : oslTranslateFileError(err);
1034 			}
1035 			break;
1036 		default:
1037 			OSL_ENSURE( 0, "Invalid directory type" );
1038 			break;
1039 		}
1040 
1041         if ( pDirImpl->m_pDirectoryPath )
1042         {
1043             rtl_uString_release( pDirImpl->m_pDirectoryPath );
1044             pDirImpl->m_pDirectoryPath = 0;
1045         }
1046 
1047 		rtl_freeMemory(pDirImpl);
1048 	}
1049 	return eError;
1050 }
1051 
1052 //#####################################################
1053 /* Different types of paths */
1054 typedef enum _PATHTYPE
1055 {
1056 	PATHTYPE_SYNTAXERROR = 0,
1057 	PATHTYPE_NETROOT,
1058 	PATHTYPE_NETSERVER,
1059 	PATHTYPE_VOLUME,
1060 	PATHTYPE_FILE
1061 } PATHTYPE;
1062 
osl_getDirectoryItem(rtl_uString * strFilePath,oslDirectoryItem * pItem)1063 oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString *strFilePath, oslDirectoryItem *pItem)
1064 {
1065 	oslFileError	error = osl_File_E_None;
1066 	rtl_uString*	strSysFilePath = NULL;
1067 	PATHTYPE		type = PATHTYPE_FILE;
1068 	DWORD			dwPathType;
1069 
1070 	/* Assume failure */
1071 
1072 	if ( !pItem )
1073 		return osl_File_E_INVAL;
1074 
1075 	*pItem = NULL;
1076 
1077 
1078 	error = _osl_getSystemPathFromFileURL( strFilePath, &strSysFilePath, sal_False );
1079 
1080 	if ( osl_File_E_None != error )
1081 			return error;
1082 
1083 	dwPathType = IsValidFilePath( strSysFilePath, NULL, VALIDATEPATH_NORMAL, NULL );
1084 
1085 	if ( dwPathType & PATHTYPE_IS_VOLUME )
1086 		type = PATHTYPE_VOLUME;
1087 	else if ( dwPathType & PATHTYPE_IS_SERVER )
1088 		type = PATHTYPE_NETSERVER;
1089 	else
1090 		type = PATHTYPE_FILE;
1091 
1092 	switch ( type )
1093 	{
1094 	case PATHTYPE_NETSERVER:
1095 		{
1096 			DirectoryItem_Impl*	pItemImpl =
1097 			    reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1098 
1099 			if ( !pItemImpl )
1100 				error = osl_File_E_NOMEM;
1101 
1102 			if ( osl_File_E_None == error )
1103 			{
1104 				ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1105 				pItemImpl->uType = DIRECTORYITEM_SERVER;
1106 
1107 				osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1108                 rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath );
1109 
1110 				// Assign a title anyway
1111 				{
1112 					int iSrc = 2;
1113 					int	iDst = 0;
1114 
1115 					while( iSrc < strSysFilePath->length && strSysFilePath->buffer[iSrc] && strSysFilePath->buffer[iSrc] != '\\' )
1116 					{
1117 						pItemImpl->FindData.cFileName[iDst++] = strSysFilePath->buffer[iSrc++];
1118 					}
1119 				}
1120 
1121 				*pItem = pItemImpl;
1122 			}
1123 		}
1124 		break;
1125 	case PATHTYPE_VOLUME:
1126 		{
1127 			DirectoryItem_Impl*	pItemImpl =
1128 			    reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1129 
1130 			if ( !pItemImpl )
1131 				error = osl_File_E_NOMEM;
1132 
1133 			if ( osl_File_E_None == error )
1134 			{
1135 				ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1136 				pItemImpl->uType = DIRECTORYITEM_DRIVE;
1137 
1138 				osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1139 
1140 				_tcscpy( pItemImpl->cDriveString, reinterpret_cast<LPCTSTR>(strSysFilePath->buffer) );
1141 				pItemImpl->cDriveString[0] = _toupper( pItemImpl->cDriveString[0] );
1142 
1143 				if ( pItemImpl->cDriveString[_tcslen(pItemImpl->cDriveString) - 1] != '\\' )
1144 					_tcscat( pItemImpl->cDriveString, TEXT( "\\" ) );
1145 
1146 				*pItem = pItemImpl;
1147 			}
1148 		}
1149 		break;
1150     case PATHTYPE_SYNTAXERROR:
1151     case PATHTYPE_NETROOT:
1152 	case PATHTYPE_FILE:
1153 		{
1154 			HANDLE				hFind;
1155 			WIN32_FIND_DATA		aFindData;
1156 
1157 			if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' )
1158 				rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 );
1159 
1160 			hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysFilePath)), &aFindData );
1161 
1162 			if ( hFind != INVALID_HANDLE_VALUE )
1163 			{
1164 				DirectoryItem_Impl	*pItemImpl =
1165 				    reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1166 
1167 				ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1168 				osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1169 
1170 				CopyMemory( &pItemImpl->FindData, &aFindData, sizeof(WIN32_FIND_DATA) );
1171                 rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath );
1172 
1173 				// MT: This costs 600ms startup time on fast v60x!
1174 				// GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
1175 
1176 				pItemImpl->uType = DIRECTORYITEM_FILE;
1177 				*pItem = pItemImpl;
1178 				FindClose( hFind );
1179 			}
1180 			else
1181 				error = oslTranslateFileError( GetLastError() );
1182 		}
1183 		break;
1184 	}
1185 
1186 	if ( strSysFilePath )
1187 		rtl_uString_release( strSysFilePath );
1188 
1189 	return error;
1190 }
1191 
1192 //#####################################################
osl_acquireDirectoryItem(oslDirectoryItem Item)1193 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
1194 {
1195 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
1196 
1197 	if ( !pItemImpl )
1198 		return osl_File_E_INVAL;
1199 
1200 	pItemImpl->nRefCount++;
1201 	return osl_File_E_None;
1202 }
1203 
1204 //#####################################################
osl_releaseDirectoryItem(oslDirectoryItem Item)1205 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
1206 {
1207 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
1208 
1209 	if ( !pItemImpl )
1210 		return osl_File_E_INVAL;
1211 
1212 	if ( ! --pItemImpl->nRefCount )
1213     {
1214         if ( pItemImpl->m_pFullPath )
1215         {
1216             rtl_uString_release( pItemImpl->m_pFullPath );
1217             pItemImpl->m_pFullPath = 0;
1218         }
1219 
1220 		rtl_freeMemory( pItemImpl );
1221     }
1222 
1223 	return osl_File_E_None;
1224 }
1225 
1226 //#####################################################
1227 // volume / file info handling functions
1228 //#####################################################
1229 
1230 //#####################################################
is_floppy_A_present()1231 static inline bool is_floppy_A_present()
1232 { return (GetLogicalDrives() & 1); }
1233 
1234 //#####################################################
is_floppy_B_present()1235 static inline bool is_floppy_B_present()
1236 { return (GetLogicalDrives() & 2); }
1237 
1238 //#####################################################
is_floppy_volume_mount_point(const rtl::OUString & path)1239 bool is_floppy_volume_mount_point(const rtl::OUString& path)
1240 {
1241     // determines if a volume mount point shows to a floppy
1242     // disk by comparing the unique volume names
1243     static const LPCWSTR FLOPPY_A = L"A:\\";
1244     static const LPCWSTR FLOPPY_B = L"B:\\";
1245 
1246 	rtl::OUString p(path);
1247 	osl::systemPathEnsureSeparator(p);
1248 
1249 	TCHAR vn[51];
1250 	if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1251 	{
1252 		TCHAR vnfloppy[51];
1253 		if (is_floppy_A_present() &&
1254 			GetVolumeNameForVolumeMountPoint(FLOPPY_A, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1255 			(0 == wcscmp(vn, vnfloppy)))
1256 			return true;
1257 
1258 		if (is_floppy_B_present() &&
1259 			GetVolumeNameForVolumeMountPoint(FLOPPY_B, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1260 			(0 == wcscmp(vn, vnfloppy)))
1261 			return true;
1262 	}
1263 	return false;
1264 }
1265 
1266 //################################################
is_floppy_drive(const rtl::OUString & path)1267 static bool is_floppy_drive(const rtl::OUString& path)
1268 {
1269 	static const LPCWSTR FLOPPY_DRV_LETTERS = TEXT("AaBb");
1270 
1271     // we must take into account that even a floppy
1272     // drive may be mounted to a directory so checking
1273     // for the drive letter alone is not sufficient
1274     // we must compare the unique volume name with
1275     // that of the available floppy disks
1276 
1277 	const sal_Unicode* pszPath = path.getStr();
1278 	return ((wcschr(FLOPPY_DRV_LETTERS, pszPath[0]) && (L':' == pszPath[1])) || is_floppy_volume_mount_point(path));
1279 }
1280 
1281 //#####################################################
is_volume_mount_point(const rtl::OUString & path)1282 static bool is_volume_mount_point(const rtl::OUString& path)
1283 {
1284 	rtl::OUString p(path);
1285 	osl::systemPathRemoveSeparator(p);
1286 
1287 	bool  is_volume_root = false;
1288 
1289 	if (!is_floppy_drive(p))
1290 	{
1291 		DWORD fattr = GetFileAttributes(reinterpret_cast<LPCTSTR>(p.getStr()));
1292 
1293 		if ((INVALID_FILE_ATTRIBUTES != fattr) &&
1294 			(FILE_ATTRIBUTE_REPARSE_POINT & fattr))
1295 		{
1296 			WIN32_FIND_DATA find_data;
1297 			HANDLE h_find = FindFirstFile(reinterpret_cast<LPCTSTR>(p.getStr()), &find_data);
1298 
1299 			if (IsValidHandle(h_find) &&
1300 				(FILE_ATTRIBUTE_REPARSE_POINT & find_data.dwFileAttributes) &&
1301 				(IO_REPARSE_TAG_MOUNT_POINT == find_data.dwReserved0))
1302 			{
1303 				is_volume_root = true;
1304 			}
1305 			if (IsValidHandle(h_find))
1306 				FindClose(h_find);
1307 		}
1308 	}
1309 	return is_volume_root;
1310 }
1311 
1312 //#############################################
get_volume_mount_point_drive_type(const rtl::OUString & path)1313 static UINT get_volume_mount_point_drive_type(const rtl::OUString& path)
1314 {
1315 	if (0 == path.getLength())
1316 		return GetDriveType(NULL);
1317 
1318 	rtl::OUString p(path);
1319 	osl::systemPathEnsureSeparator(p);
1320 
1321 	TCHAR vn[51];
1322 	if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1323 		return GetDriveType(vn);
1324 
1325 	return DRIVE_NO_ROOT_DIR;
1326 }
1327 
1328 //#############################################
is_drivetype_request(sal_uInt32 field_mask)1329 static inline bool is_drivetype_request(sal_uInt32 field_mask)
1330 {
1331 	return (field_mask & osl_VolumeInfo_Mask_Attributes);
1332 }
1333 
1334 //#############################################
osl_get_drive_type(const rtl::OUString & path,oslVolumeInfo * pInfo)1335 static oslFileError osl_get_drive_type(
1336 	const rtl::OUString& path, oslVolumeInfo* pInfo)
1337 {
1338 	// GetDriveType fails on empty volume mount points
1339 	// see Knowledge Base Q244089
1340 	UINT drive_type;
1341 	if (is_volume_mount_point(path))
1342 		drive_type = get_volume_mount_point_drive_type(path);
1343 	else
1344 		drive_type = GetDriveType(reinterpret_cast<LPCTSTR>(path.getStr()));
1345 
1346 	if (DRIVE_NO_ROOT_DIR == drive_type)
1347 		return oslTranslateFileError(ERROR_INVALID_DRIVE);
1348 
1349 	pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1350 
1351 	switch (drive_type)
1352 	{
1353 		case DRIVE_CDROM:
1354 			pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
1355 			break;
1356 		case DRIVE_REMOVABLE:
1357 			pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
1358 			if (is_floppy_drive(path))
1359 				pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
1360 			break;
1361 		case DRIVE_FIXED:
1362 			pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
1363 			break;
1364 		case DRIVE_RAMDISK:
1365 			pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
1366 			break;
1367 		case DRIVE_REMOTE:
1368 			pInfo->uAttributes |= osl_Volume_Attribute_Remote;
1369 			break;
1370 		case DRIVE_UNKNOWN:
1371 			pInfo->uAttributes = 0;
1372 			break;
1373 		default:
1374 			pInfo->uValidFields &= ~osl_VolumeInfo_Mask_Attributes;
1375 			pInfo->uAttributes = 0;
1376 			break;
1377 	}
1378 	return osl_File_E_None;
1379 }
1380 
1381 //#############################################
is_volume_space_info_request(sal_uInt32 field_mask)1382 static inline bool is_volume_space_info_request(sal_uInt32 field_mask)
1383 {
1384 	return (field_mask &
1385 			(osl_VolumeInfo_Mask_TotalSpace |
1386 			 osl_VolumeInfo_Mask_UsedSpace  |
1387 			 osl_VolumeInfo_Mask_FreeSpace));
1388 }
1389 
1390 //#############################################
get_volume_space_information(const rtl::OUString & path,oslVolumeInfo * pInfo)1391 static void get_volume_space_information(
1392 	const rtl::OUString& path, oslVolumeInfo *pInfo)
1393 {
1394 	BOOL ret = GetDiskFreeSpaceEx(
1395 		reinterpret_cast<LPCTSTR>(path.getStr()),
1396 		(PULARGE_INTEGER)&(pInfo->uFreeSpace),
1397 		(PULARGE_INTEGER)&(pInfo->uTotalSpace),
1398 		NULL);
1399 
1400 	if (ret)
1401 	{
1402 		pInfo->uUsedSpace    = pInfo->uTotalSpace - pInfo->uFreeSpace;
1403 		pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace |
1404 			osl_VolumeInfo_Mask_UsedSpace |
1405 			osl_VolumeInfo_Mask_FreeSpace;
1406 	}
1407 }
1408 
1409 //#############################################
is_filesystem_attributes_request(sal_uInt32 field_mask)1410 static inline bool is_filesystem_attributes_request(sal_uInt32 field_mask)
1411 {
1412 	return (field_mask &
1413 			(osl_VolumeInfo_Mask_MaxNameLength |
1414 			 osl_VolumeInfo_Mask_MaxPathLength |
1415 			 osl_VolumeInfo_Mask_FileSystemName |
1416 			 osl_VolumeInfo_Mask_FileSystemCaseHandling));
1417 }
1418 
1419 //#############################################
get_filesystem_attributes(const rtl::OUString & path,sal_uInt32 field_mask,oslVolumeInfo * pInfo)1420 static oslFileError get_filesystem_attributes(
1421 	const rtl::OUString& path, sal_uInt32 field_mask, oslVolumeInfo* pInfo)
1422 {
1423 	pInfo->uAttributes = 0;
1424 
1425 	// osl_get_drive_type must be called first because
1426 	// this function resets osl_VolumeInfo_Mask_Attributes
1427 	// on failure
1428 	if (is_drivetype_request(field_mask))
1429 	{
1430 		oslFileError osl_error = osl_get_drive_type(path, pInfo);
1431         if (osl_File_E_None != osl_error)
1432 			return osl_error;
1433 	}
1434 	if (is_filesystem_attributes_request(field_mask))
1435 	{
1436         /* the following two parameters can not be longer than MAX_PATH+1 */
1437 		WCHAR vn[MAX_PATH+1];
1438 		WCHAR fsn[MAX_PATH+1];
1439 
1440 		DWORD serial;
1441 		DWORD mcl;
1442 		DWORD flags;
1443 
1444 		LPCTSTR pszPath = reinterpret_cast<LPCTSTR>(path.getStr());
1445 		if (GetVolumeInformation(pszPath, vn, MAX_PATH+1, &serial, &mcl, &flags, fsn, MAX_PATH+1))
1446 		{
1447             // Currently sal does not use this value, instead MAX_PATH is used
1448 			pInfo->uValidFields   |= osl_VolumeInfo_Mask_MaxNameLength;
1449 			pInfo->uMaxNameLength  = mcl;
1450 
1451             // Should the uMaxPathLength be set to 32767, "\\?\" prefix allowes it
1452 			pInfo->uValidFields   |= osl_VolumeInfo_Mask_MaxPathLength;
1453 			pInfo->uMaxPathLength  = MAX_PATH;
1454 
1455 			pInfo->uValidFields   |= osl_VolumeInfo_Mask_FileSystemName;
1456 			rtl_uString_newFromStr(&pInfo->ustrFileSystemName, reinterpret_cast<const sal_Unicode*>(fsn));
1457 
1458 			// volumes (even NTFS) will always be considered case
1459 			// insensitive because the Win32 API is not able to
1460 			// deal with case sensitive volumes see M$ Knowledge Base
1461 			// article 100625 that's why we never set the attribute
1462 			// osl_Volume_Attribute_Case_Sensitive
1463 
1464 			if (flags & FS_CASE_IS_PRESERVED)
1465 				pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
1466 
1467 			pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1468 		}
1469 	}
1470 	return osl_File_E_None;
1471 }
1472 
1473 //#####################################################
path_get_parent(rtl::OUString & path)1474 static bool path_get_parent(rtl::OUString& path)
1475 {
1476 	OSL_PRECOND(path.lastIndexOf(SLASH) == -1, "Path must not have slashes");
1477 
1478 	if (!has_path_parent(path))
1479 	{
1480 		sal_Int32 i = path.lastIndexOf(BACKSLASH);
1481 		if (-1 < i)
1482 		{
1483 			path = rtl::OUString(path.getStr(), i);
1484 			return true;
1485 		}
1486 	}
1487 	return false;
1488 }
1489 
1490 //#####################################################
path_travel_to_volume_root(const rtl::OUString & system_path,rtl::OUString & volume_root)1491 static void path_travel_to_volume_root(const rtl::OUString& system_path, rtl::OUString& volume_root)
1492 {
1493 	rtl::OUString sys_path(system_path);
1494 
1495 	while(!is_volume_mount_point(sys_path) && path_get_parent(sys_path))
1496 		/**/;
1497 
1498 	volume_root = sys_path;
1499 	osl::systemPathEnsureSeparator(volume_root);
1500 }
1501 
1502 //#############################################
osl_getVolumeInformation(rtl_uString * ustrURL,oslVolumeInfo * pInfo,sal_uInt32 uFieldMask)1503 oslFileError SAL_CALL osl_getVolumeInformation(
1504     rtl_uString *ustrURL, oslVolumeInfo *pInfo, sal_uInt32 uFieldMask )
1505 {
1506 	if (!pInfo)
1507 		return osl_File_E_INVAL;
1508 
1509     rtl::OUString system_path;
1510 	oslFileError error = _osl_getSystemPathFromFileURL(ustrURL, &system_path.pData, sal_False);
1511 
1512     if (osl_File_E_None != error)
1513         return error;
1514 
1515     rtl::OUString volume_root;
1516     path_travel_to_volume_root(system_path, volume_root);
1517 
1518 	pInfo->uValidFields = 0;
1519 
1520     if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None)
1521         return error;
1522 
1523 	if (is_volume_space_info_request(uFieldMask))
1524 	    get_volume_space_information(volume_root, pInfo);
1525 
1526 	if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
1527 	{
1528 		pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
1529 		osl_getFileURLFromSystemPath(volume_root.pData, (rtl_uString**)&pInfo->pDeviceHandle);
1530 	}
1531 
1532 	return osl_File_E_None;
1533 }
1534 
1535 //#####################################################
osl_getDriveInfo(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)1536 static oslFileError SAL_CALL osl_getDriveInfo(
1537 	oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask)
1538 {
1539 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
1540 	TCHAR				cDrive[3] = TEXT("A:");
1541 	TCHAR				cRoot[4] = TEXT("A:\\");
1542 
1543 	if ( !pItemImpl )
1544 		return osl_File_E_INVAL;
1545 
1546 	pStatus->uValidFields = 0;
1547 
1548 	cDrive[0] = pItemImpl->cDriveString[0];
1549 	cRoot[0] = pItemImpl->cDriveString[0];
1550 
1551 	if ( uFieldMask & osl_FileStatus_Mask_FileName )
1552 	{
1553 		if ( pItemImpl->cDriveString[0] == '\\' && pItemImpl->cDriveString[1] == '\\' )
1554 		{
1555 			LPCWSTR	lpFirstBkSlash = wcschr( &pItemImpl->cDriveString[2], '\\' );
1556 
1557 			if ( lpFirstBkSlash && lpFirstBkSlash[1] )
1558 			{
1559 				LPCWSTR	lpLastBkSlash = wcschr( &lpFirstBkSlash[1], '\\' );
1560 
1561 				if ( lpLastBkSlash )
1562 					rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]), lpLastBkSlash - lpFirstBkSlash - 1 );
1563 				else
1564 					rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]) );
1565 				pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1566 			}
1567 		}
1568 		else switch ( GetDriveType( cRoot ) )
1569 		{
1570 		    case DRIVE_REMOTE:
1571 			{
1572 				TCHAR szBuffer[1024];
1573 				DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szBuffer);
1574 				DWORD dwBufsize = dwBufsizeConst;
1575 
1576 				DWORD dwResult = WNetGetConnection( cDrive, szBuffer, &dwBufsize );
1577 				if ( NO_ERROR == dwResult )
1578 				{
1579 					TCHAR szFileName[dwBufsizeConst + 16];
1580 
1581 					swprintf( szFileName, L"%s [%s]", cDrive, szBuffer );
1582 					rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
1583 				}
1584 				else
1585 					rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
1586 			}
1587 			pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1588 			break;
1589 		    case DRIVE_FIXED:
1590 			{
1591 				TCHAR szVolumeNameBuffer[1024];
1592 				DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szVolumeNameBuffer);
1593 
1594 				if ( GetVolumeInformation( cRoot, szVolumeNameBuffer, dwBufsizeConst, NULL, NULL, NULL, NULL, 0 ) )
1595 				{
1596 					TCHAR	szFileName[dwBufsizeConst + 16];
1597 
1598 					swprintf( szFileName, L"%s [%s]", cDrive, szVolumeNameBuffer );
1599 					rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
1600 				}
1601 				else
1602 					rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
1603 			}
1604 			pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1605 			break;
1606 		    case DRIVE_CDROM:
1607 		    case DRIVE_REMOVABLE:
1608 			    pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1609 			    rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cRoot) );
1610 			    break;
1611 		    case DRIVE_UNKNOWN:
1612 		    default:
1613 			    break;
1614 		}
1615 	}
1616 
1617 	pStatus->eType = osl_File_Type_Volume;
1618 	pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1619 
1620 	if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1621 	{
1622 		rtl_uString	*ustrSystemPath = NULL;
1623 
1624 		rtl_uString_newFromStr( &ustrSystemPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->cDriveString) );
1625 		osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
1626 		rtl_uString_release( ustrSystemPath );
1627 		pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1628 	}
1629 	return osl_File_E_None;
1630 }
1631 
1632 //#####################################################
osl_getServerInfo(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)1633 static oslFileError SAL_CALL osl_getServerInfo(
1634 	oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask )
1635 {
1636 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
1637 	if ( !pItemImpl )
1638 		return osl_File_E_INVAL;
1639 
1640 	pStatus->uValidFields = 0;
1641 
1642 	//	pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1643 
1644 	//	if ( _tcscmp( pItemImpl->FindData.cFileName, TEXT(".") ) == 0 )
1645 	//		rtl_uString_newFromAscii( &pStatus->ustrFileName, "/" );
1646 	//	else
1647 	//		rtl_uString_newFromStr( &pStatus->ustrFileName, pItemImpl->FindData.cFileName );
1648 
1649 	pStatus->eType = osl_File_Type_Directory;
1650 	pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1651 
1652 	if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1653 	{
1654 		osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrFileURL );
1655 		pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1656 	}
1657 	return osl_File_E_None;
1658 }
1659 
1660 //#############################################
osl_getFileStatus(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)1661 oslFileError SAL_CALL osl_getFileStatus(
1662     oslDirectoryItem Item,
1663     oslFileStatus *pStatus,
1664     sal_uInt32 uFieldMask )
1665 {
1666 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
1667 
1668 	if ( !pItemImpl )
1669 		return osl_File_E_INVAL;
1670 
1671 	switch ( pItemImpl->uType  )
1672 	{
1673 	case DIRECTORYITEM_DRIVE:
1674 		return osl_getDriveInfo( Item, pStatus, uFieldMask );
1675 	case DIRECTORYITEM_SERVER:
1676 		return osl_getServerInfo( Item, pStatus, uFieldMask );
1677 	default:
1678 		break;
1679 	}
1680 
1681 	if ( uFieldMask & osl_FileStatus_Mask_Validate )
1682 	{
1683 		HANDLE	hFind = FindFirstFile( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ), &pItemImpl->FindData );
1684 
1685 		if ( hFind != INVALID_HANDLE_VALUE )
1686 			FindClose( hFind );
1687 		else
1688 			return oslTranslateFileError( GetLastError() );
1689 
1690 		uFieldMask &= ~	osl_FileStatus_Mask_Validate;
1691 	}
1692 
1693 	/* If no fields to retrieve left ignore pStatus */
1694 	if ( !uFieldMask )
1695 		return osl_File_E_None;
1696 
1697 	/* Otherwise, this must be a valid pointer */
1698 	if ( !pStatus )
1699 		return osl_File_E_INVAL;
1700 
1701 	if ( pStatus->uStructSize != sizeof(oslFileStatus) )
1702 		return osl_File_E_INVAL;
1703 
1704 	pStatus->uValidFields = 0;
1705 
1706 	/* File time stamps */
1707 
1708 	if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime) &&
1709 		FileTimeToTimeValue( &pItemImpl->FindData.ftLastWriteTime, &pStatus->aModifyTime ) )
1710 		pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime;
1711 
1712 	if ( (uFieldMask & osl_FileStatus_Mask_AccessTime) &&
1713 		FileTimeToTimeValue( &pItemImpl->FindData.ftLastAccessTime, &pStatus->aAccessTime ) )
1714 		pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime;
1715 
1716 	if ( (uFieldMask & osl_FileStatus_Mask_CreationTime) &&
1717 		FileTimeToTimeValue( &pItemImpl->FindData.ftCreationTime, &pStatus->aCreationTime ) )
1718 		pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime;
1719 
1720 	/* Most of the fields are already set, regardless of requiered fields */
1721 
1722 	rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(pItemImpl->FindData.cFileName) );
1723 	pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1724 
1725     if ((FILE_ATTRIBUTE_REPARSE_POINT & pItemImpl->FindData.dwFileAttributes) &&
1726         (IO_REPARSE_TAG_MOUNT_POINT == pItemImpl->FindData.dwReserved0))
1727         pStatus->eType = osl_File_Type_Volume;
1728     else if (pItemImpl->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1729         pStatus->eType = osl_File_Type_Directory;
1730     else
1731 	    pStatus->eType = osl_File_Type_Regular;
1732 
1733 	pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1734 
1735 	pStatus->uAttributes = pItemImpl->FindData.dwFileAttributes;
1736 	pStatus->uValidFields |= osl_FileStatus_Mask_Attributes;
1737 
1738 	pStatus->uFileSize = (sal_uInt64)pItemImpl->FindData.nFileSizeLow + ((sal_uInt64)pItemImpl->FindData.nFileSizeHigh << 32);
1739 	pStatus->uValidFields |= osl_FileStatus_Mask_FileSize;
1740 
1741 	if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL )
1742 	{
1743 		osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrLinkTargetURL );
1744 
1745 		pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
1746 	}
1747 
1748 	if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1749 	{
1750 		if ( !pItemImpl->bFullPathNormalized )
1751 		{
1752             sal_uInt32 nLen = rtl_uString_getLength( pItemImpl->m_pFullPath );
1753             ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
1754             sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ),
1755                                                       ::osl::mingw_reinterpret_cast<LPTSTR>( aBuffer ),
1756                                                       aBuffer.getBufSizeInSymbols(),
1757                                                       sal_True );
1758 
1759             if ( nNewLen )
1760             {
1761                 rtl_uString_newFromStr( &pItemImpl->m_pFullPath, aBuffer );
1762                 pItemImpl->bFullPathNormalized = TRUE;
1763             }
1764 		}
1765 
1766 		osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrFileURL );
1767 		pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1768 	}
1769 
1770 	return osl_File_E_None;
1771 }
1772 
1773 //#####################################################
1774 // file attributes handling functions
1775 //#####################################################
1776 
1777 //#############################################
osl_setFileAttributes(rtl_uString * ustrFileURL,sal_uInt64 uAttributes)1778 oslFileError SAL_CALL osl_setFileAttributes(
1779     rtl_uString *ustrFileURL,
1780     sal_uInt64 uAttributes )
1781 {
1782 	oslFileError	error;
1783 	rtl_uString		*ustrSysPath = NULL;
1784 	DWORD			dwFileAttributes;
1785 	BOOL			fSuccess;
1786 
1787 	// Converts the normalized path into a systempath
1788 	error = _osl_getSystemPathFromFileURL( ustrFileURL, &ustrSysPath, sal_False );
1789 
1790 	if ( osl_File_E_None != error )
1791 		return error;
1792 
1793 	dwFileAttributes = GetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)) );
1794 
1795 	if ( (DWORD)-1 != dwFileAttributes )
1796 	{
1797 		dwFileAttributes &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN);
1798 
1799 		if ( uAttributes & osl_File_Attribute_ReadOnly )
1800 			dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
1801 
1802 		if ( uAttributes & osl_File_Attribute_Hidden )
1803 			dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1804 
1805 		fSuccess = SetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)), dwFileAttributes );
1806 	}
1807 	else
1808 		fSuccess = FALSE;
1809 
1810 	if ( !fSuccess )
1811 		error = oslTranslateFileError( GetLastError() );
1812 
1813 	rtl_uString_release( ustrSysPath );
1814 
1815 	return error;
1816 }
1817 
1818 //#####################################################
osl_setFileTime(rtl_uString * filePath,const TimeValue * aCreationTime,const TimeValue * aLastAccessTime,const TimeValue * aLastWriteTime)1819 oslFileError SAL_CALL osl_setFileTime(
1820     rtl_uString *filePath,
1821     const TimeValue *aCreationTime,
1822     const TimeValue *aLastAccessTime,
1823     const TimeValue *aLastWriteTime)
1824 {
1825 	oslFileError error;
1826 	rtl_uString *sysPath=NULL;
1827 	FILETIME *lpCreationTime=NULL;
1828 	FILETIME *lpLastAccessTime=NULL;
1829 	FILETIME *lpLastWriteTime=NULL;
1830 	FILETIME ftCreationTime;
1831 	FILETIME ftLastAccessTime;
1832 	FILETIME ftLastWriteTime;
1833 	HANDLE hFile;
1834 	BOOL fSuccess;
1835 
1836 
1837 	error=_osl_getSystemPathFromFileURL(filePath, &sysPath, sal_False);
1838 
1839 	if (error==osl_File_E_INVAL)
1840 		return error;
1841 
1842 	hFile=CreateFileW(reinterpret_cast<LPCWSTR>(rtl_uString_getStr(sysPath)), GENERIC_WRITE, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1843 	rtl_uString_release(sysPath);
1844 
1845 	if (hFile==INVALID_HANDLE_VALUE)
1846 		return osl_File_E_NOENT;
1847 
1848 	if (TimeValueToFileTime(aCreationTime, &ftCreationTime))
1849 		lpCreationTime=&ftCreationTime;
1850 
1851 	if (TimeValueToFileTime(aLastAccessTime, &ftLastAccessTime))
1852 		lpLastAccessTime=&ftLastAccessTime;
1853 
1854 	if (TimeValueToFileTime(aLastWriteTime, &ftLastWriteTime))
1855 		lpLastWriteTime=&ftLastWriteTime;
1856 
1857 	fSuccess=SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
1858 
1859 	CloseHandle(hFile);
1860 
1861 	if (!fSuccess)
1862 		return osl_File_E_INVAL;
1863 	else
1864 		return osl_File_E_None;
1865 }
1866