1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include "systools/win32/uwinapi.h"
27 #include <sal/macros.h>
28 #include "file_error.h"
30 #include "path_helper.hxx"
32 #include "osl/diagnose.h"
34 #include "rtl/alloc.h"
35 #include "rtl/ustring.hxx"
42 //#####################################################
43 static const wchar_t UNC_PREFIX
[] = L
"\\\\";
44 static const wchar_t BACKSLASH
= '\\';
45 static const wchar_t SLASH
= '/';
47 //#####################################################
48 extern "C" BOOL
TimeValueToFileTime(const TimeValue
*cpTimeVal
, FILETIME
*pFTime
)
50 SYSTEMTIME BaseSysTime
;
51 FILETIME BaseFileTime
;
53 BOOL fSuccess
= FALSE
;
55 BaseSysTime
.wYear
= 1970;
56 BaseSysTime
.wMonth
= 1;
57 BaseSysTime
.wDayOfWeek
= 0;
59 BaseSysTime
.wHour
= 0;
60 BaseSysTime
.wMinute
= 0;
61 BaseSysTime
.wSecond
= 0;
62 BaseSysTime
.wMilliseconds
= 0;
67 if ( SystemTimeToFileTime(&BaseSysTime
, &BaseFileTime
) )
71 __int64 localTime
= cpTimeVal
->Seconds
*(__int64
)10000000+cpTimeVal
->Nanosec
/100;
72 *(__int64
*)&FTime
=localTime
;
73 fSuccess
= 0 <= (timeValue
= *((__int64
*)&BaseFileTime
) + *((__int64
*) &FTime
));
75 *(__int64
*)pFTime
=timeValue
;
80 //#####################################################
81 extern "C" BOOL
FileTimeToTimeValue(const FILETIME
*cpFTime
, TimeValue
*pTimeVal
)
83 SYSTEMTIME BaseSysTime
;
84 FILETIME BaseFileTime
;
85 BOOL fSuccess
= FALSE
; /* Assume failure */
87 BaseSysTime
.wYear
= 1970;
88 BaseSysTime
.wMonth
= 1;
89 BaseSysTime
.wDayOfWeek
= 0;
91 BaseSysTime
.wHour
= 0;
92 BaseSysTime
.wMinute
= 0;
93 BaseSysTime
.wSecond
= 0;
94 BaseSysTime
.wMilliseconds
= 0;
96 if ( SystemTimeToFileTime(&BaseSysTime
, &BaseFileTime
) )
100 fSuccess
= 0 <= (Value
= *((__int64
*)cpFTime
) - *((__int64
*)&BaseFileTime
));
104 pTimeVal
->Seconds
= (unsigned long) (Value
/ 10000000L);
105 pTimeVal
->Nanosec
= (unsigned long)((Value
% 10000000L) * 100);
111 //#####################################################
112 namespace /* private */
114 //#####################################################
121 bool isPresent() const
122 { return (static_cast<sal_IntPtr
>(end_
- begin_
) > 0); }
124 const sal_Unicode
* begin_
;
125 const sal_Unicode
* end_
;
128 //#####################################################
136 //#####################################################
137 inline bool is_UNC_path(const sal_Unicode
* path
)
138 { return (0 == wcsncmp(UNC_PREFIX
, reinterpret_cast<LPCWSTR
>(path
), SAL_N_ELEMENTS(UNC_PREFIX
) - 1)); }
140 //#####################################################
141 inline bool is_UNC_path(const rtl::OUString
& path
)
142 { return is_UNC_path(path
.getStr()); }
144 //#####################################################
145 void parse_UNC_path(const sal_Unicode
* path
, UNCComponents
* puncc
)
147 OSL_PRECOND(is_UNC_path(path
), "Precondition violated: No UNC path");
148 OSL_PRECOND(rtl_ustr_indexOfChar(path
, SLASH
) == -1, "Path must not contain slashes");
150 const sal_Unicode
* pend
= path
+ rtl_ustr_getLength(path
);
151 const sal_Unicode
* ppos
= path
+ 2;
153 puncc
->server_
.begin_
= ppos
;
154 while ((ppos
< pend
) && (*ppos
!= BACKSLASH
))
157 puncc
->server_
.end_
= ppos
;
159 if (BACKSLASH
== *ppos
)
161 puncc
->share_
.begin_
= ++ppos
;
162 while ((ppos
< pend
) && (*ppos
!= BACKSLASH
))
165 puncc
->share_
.end_
= ppos
;
167 if (BACKSLASH
== *ppos
)
169 puncc
->resource_
.begin_
= ++ppos
;
173 puncc
->resource_
.end_
= ppos
;
177 OSL_POSTCOND(puncc
->server_
.isPresent() && puncc
->share_
.isPresent(), \
178 "Postcondition violated: Invalid UNC path detected");
181 //#####################################################
182 void parse_UNC_path(const rtl::OUString
& path
, UNCComponents
* puncc
)
183 { parse_UNC_path(path
.getStr(), puncc
); }
186 //#####################################################
187 bool has_path_parent(const sal_Unicode
* path
)
189 // Has the given path a parent or are we already there,
190 // e.g. 'c:\' or '\\server\share\'?
192 bool has_parent
= false;
193 if (is_UNC_path(path
))
195 UNCComponents unc_comp
;
196 parse_UNC_path(path
, &unc_comp
);
197 has_parent
= unc_comp
.resource_
.isPresent();
201 has_parent
= !osl::systemPathIsLogicalDrivePattern(path
);
206 //#####################################################
207 inline bool has_path_parent(const rtl::OUString
& path
)
208 { return has_path_parent(path
.getStr()); }
210 } // end namespace private
212 //#####################################################
213 // volume handling functions
214 //#####################################################
216 //#####################################################
217 oslFileError SAL_CALL
osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle
)
221 rtl_uString_acquire( (rtl_uString
*)Handle
);
222 return osl_File_E_None
;
225 return osl_File_E_INVAL
;
228 //#####################################################
229 oslFileError SAL_CALL
osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle
)
233 rtl_uString_release( (rtl_uString
*)Handle
);
234 return osl_File_E_None
;
237 return osl_File_E_INVAL
;
240 //#####################################################
241 oslFileError SAL_CALL
osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle
, rtl_uString
**pstrPath
)
243 if ( Handle
&& pstrPath
)
245 rtl_uString_assign( pstrPath
, (rtl_uString
*)Handle
);
246 return osl_File_E_None
;
249 return osl_File_E_INVAL
;
252 //##################################################################
253 // directory handling functions
254 //##################################################################
256 #define DIRECTORYITEM_DRIVE 0
257 #define DIRECTORYITEM_FILE 1
258 #define DIRECTORYITEM_SERVER 2
260 struct DirectoryItem_Impl
264 WIN32_FIND_DATA FindData
;
265 TCHAR cDriveString
[MAX_PATH
];
267 rtl_uString
* m_pFullPath
;
268 BOOL bFullPathNormalized
;
272 //#####################################################
274 #define DIRECTORYTYPE_LOCALROOT 0
275 #define DIRECTORYTYPE_NETROOT 1
276 #define DIRECTORYTYPE_FILESYSTEM 3
278 struct Directory_Impl
285 rtl_uString
* m_pDirectoryPath
;
288 //#####################################################
290 typedef struct tagDRIVEENUM
293 TCHAR cBuffer
[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
295 } DRIVEENUM
, * PDRIVEENUM
, FAR
* LPDRIVEENUM
;
297 //#####################################################
299 static HANDLE WINAPI
OpenLogicalDrivesEnum(void)
301 LPDRIVEENUM pEnum
= (LPDRIVEENUM
)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM
) );
304 DWORD dwNumCopied
= GetLogicalDriveStrings( (sizeof(pEnum
->cBuffer
) - 1) / sizeof(TCHAR
), pEnum
->cBuffer
);
306 if ( dwNumCopied
&& dwNumCopied
< sizeof(pEnum
->cBuffer
) / sizeof(TCHAR
) )
308 pEnum
->lpCurrent
= pEnum
->cBuffer
;
309 pEnum
->lpIdent
= L
"tagDRIVEENUM";
313 HeapFree( GetProcessHeap(), 0, pEnum
);
317 return pEnum
? (HANDLE
)pEnum
: INVALID_HANDLE_VALUE
;
320 //#####################################################
321 static BOOL WINAPI
EnumLogicalDrives(HANDLE hEnum
, LPTSTR lpBuffer
)
323 BOOL fSuccess
= FALSE
;
324 LPDRIVEENUM pEnum
= (LPDRIVEENUM
)hEnum
;
328 int nLen
= _tcslen( pEnum
->lpCurrent
);
332 CopyMemory( lpBuffer
, pEnum
->lpCurrent
, (nLen
+ 1) * sizeof(TCHAR
) );
333 pEnum
->lpCurrent
+= nLen
+ 1;
337 SetLastError( ERROR_NO_MORE_FILES
);
340 SetLastError( ERROR_INVALID_HANDLE
);
345 //#####################################################
346 static BOOL WINAPI
CloseLogicalDrivesEnum(HANDLE hEnum
)
348 BOOL fSuccess
= FALSE
;
349 LPDRIVEENUM pEnum
= (LPDRIVEENUM
)hEnum
;
353 HeapFree( GetProcessHeap(), 0, pEnum
);
357 SetLastError( ERROR_INVALID_HANDLE
);
362 //#####################################################
363 typedef struct tagDIRECTORY
366 WIN32_FIND_DATA aFirstData
;
367 } DIRECTORY
, *PDIRECTORY
, FAR
*LPDIRECTORY
;
369 //#####################################################
370 static HANDLE WINAPI
OpenDirectory( rtl_uString
* pPath
)
372 LPDIRECTORY pDirectory
= NULL
;
376 sal_uInt32 nLen
= rtl_uString_getLength( pPath
);
379 const TCHAR
* pSuffix
= 0;
380 sal_uInt32 nSuffLen
= 0;
382 if ( pPath
->buffer
[nLen
- 1] != L
'\\' )
393 TCHAR
* szFileMask
= reinterpret_cast< TCHAR
* >( rtl_allocateMemory( sizeof( TCHAR
) * ( nLen
+ nSuffLen
+ 1 ) ) );
395 _tcscpy( szFileMask
, reinterpret_cast<LPCTSTR
>( rtl_uString_getStr( pPath
) ) );
396 _tcscat( szFileMask
, pSuffix
);
398 pDirectory
= (LPDIRECTORY
)HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY
));
399 pDirectory
->hFind
= FindFirstFile(szFileMask
, &pDirectory
->aFirstData
);
401 if (!IsValidHandle(pDirectory
->hFind
))
403 if ( GetLastError() != ERROR_NO_MORE_FILES
)
405 HeapFree(GetProcessHeap(), 0, pDirectory
);
409 rtl_freeMemory(szFileMask
);
413 return (HANDLE
)pDirectory
;
416 //#####################################################
417 BOOL WINAPI
EnumDirectory(HANDLE hDirectory
, LPWIN32_FIND_DATA pFindData
)
419 BOOL fSuccess
= FALSE
;
420 LPDIRECTORY pDirectory
= (LPDIRECTORY
)hDirectory
;
428 if ( pDirectory
->aFirstData
.cFileName
[0] )
430 *pFindData
= pDirectory
->aFirstData
;
432 pDirectory
->aFirstData
.cFileName
[0] = 0;
434 else if ( IsValidHandle( pDirectory
->hFind
) )
435 fSuccess
= FindNextFile( pDirectory
->hFind
, pFindData
);
439 SetLastError( ERROR_NO_MORE_FILES
);
442 fValid
= fSuccess
&& _tcscmp( TEXT("."), pFindData
->cFileName
) != 0 && _tcscmp( TEXT(".."), pFindData
->cFileName
) != 0;
444 } while( fSuccess
&& !fValid
);
447 SetLastError( ERROR_INVALID_HANDLE
);
452 //#####################################################
453 static BOOL WINAPI
CloseDirectory(HANDLE hDirectory
)
455 BOOL fSuccess
= FALSE
;
456 LPDIRECTORY pDirectory
= (LPDIRECTORY
)hDirectory
;
460 if (IsValidHandle(pDirectory
->hFind
))
461 fSuccess
= FindClose(pDirectory
->hFind
);
463 fSuccess
= HeapFree(GetProcessHeap(), 0, pDirectory
) && fSuccess
;
466 SetLastError(ERROR_INVALID_HANDLE
);
471 //#####################################################
472 static oslFileError
osl_openLocalRoot(
473 rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
475 rtl_uString
*strSysPath
= NULL
;
479 return osl_File_E_INVAL
;
483 error
= _osl_getSystemPathFromFileURL( strDirectoryPath
, &strSysPath
, sal_False
);
484 if ( osl_File_E_None
== error
)
486 Directory_Impl
*pDirImpl
;
488 pDirImpl
= reinterpret_cast<Directory_Impl
*>(rtl_allocateMemory( sizeof(Directory_Impl
)));
489 ZeroMemory( pDirImpl
, sizeof(Directory_Impl
) );
490 rtl_uString_newFromString( &pDirImpl
->m_pDirectoryPath
, strSysPath
);
492 /* Append backslash if necessary */
495 use function ensure backslash
497 sal_uInt32 nLen
= rtl_uString_getLength( pDirImpl
->m_pDirectoryPath
);
498 if ( nLen
&& pDirImpl
->m_pDirectoryPath
->buffer
[nLen
- 1] != L
'\\' )
500 rtl_uString
* pCurDir
= 0;
501 rtl_uString
* pBackSlash
= 0;
503 rtl_uString_assign( &pCurDir
, pDirImpl
->m_pDirectoryPath
);
504 rtl_uString_newFromAscii( &pBackSlash
, "\\" );
505 rtl_uString_newConcat( &pDirImpl
->m_pDirectoryPath
, pCurDir
, pBackSlash
);
506 rtl_uString_release( pBackSlash
);
507 rtl_uString_release( pCurDir
);
510 pDirImpl
->uType
= DIRECTORYTYPE_LOCALROOT
;
511 pDirImpl
->hEnumDrives
= OpenLogicalDrivesEnum();
514 Use IsValidHandle(...)
516 if ( pDirImpl
->hEnumDrives
!= INVALID_HANDLE_VALUE
)
518 *pDirectory
= (oslDirectory
)pDirImpl
;
519 error
= osl_File_E_None
;
525 if ( pDirImpl
->m_pDirectoryPath
)
527 rtl_uString_release( pDirImpl
->m_pDirectoryPath
);
528 pDirImpl
->m_pDirectoryPath
= 0;
531 rtl_freeMemory(pDirImpl
);
535 error
= oslTranslateFileError( GetLastError() );
538 rtl_uString_release( strSysPath
);
543 //#####################################################
544 static oslFileError SAL_CALL
osl_openFileDirectory(
545 rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
547 oslFileError error
= osl_File_E_None
;
550 return osl_File_E_INVAL
;
553 Directory_Impl
*pDirImpl
= reinterpret_cast<Directory_Impl
*>(rtl_allocateMemory(sizeof(Directory_Impl
)));
554 ZeroMemory( pDirImpl
, sizeof(Directory_Impl
) );
555 rtl_uString_newFromString( &pDirImpl
->m_pDirectoryPath
, strDirectoryPath
);
557 /* Append backslash if necessary */
560 use function ensure backslash
562 sal_uInt32 nLen
= rtl_uString_getLength( pDirImpl
->m_pDirectoryPath
);
563 if ( nLen
&& pDirImpl
->m_pDirectoryPath
->buffer
[nLen
- 1] != L
'\\' )
565 rtl_uString
* pCurDir
= 0;
566 rtl_uString
* pBackSlash
= 0;
568 rtl_uString_assign( &pCurDir
, pDirImpl
->m_pDirectoryPath
);
569 rtl_uString_newFromAscii( &pBackSlash
, "\\" );
570 rtl_uString_newConcat( &pDirImpl
->m_pDirectoryPath
, pCurDir
, pBackSlash
);
571 rtl_uString_release( pBackSlash
);
572 rtl_uString_release( pCurDir
);
576 pDirImpl
->uType
= DIRECTORYTYPE_FILESYSTEM
;
577 pDirImpl
->hDirectory
= OpenDirectory( pDirImpl
->m_pDirectoryPath
);
579 if ( !pDirImpl
->hDirectory
)
581 error
= oslTranslateFileError( GetLastError() );
583 if ( pDirImpl
->m_pDirectoryPath
)
585 rtl_uString_release( pDirImpl
->m_pDirectoryPath
);
586 pDirImpl
->m_pDirectoryPath
= 0;
589 rtl_freeMemory(pDirImpl
), pDirImpl
= 0;
592 *pDirectory
= (oslDirectory
)(pDirImpl
);
596 //#####################################################
597 static oslFileError SAL_CALL
osl_openNetworkServer(
598 rtl_uString
*strSysDirPath
, oslDirectory
*pDirectory
)
600 NETRESOURCEW aNetResource
;
604 ZeroMemory( &aNetResource
, sizeof(aNetResource
) );
606 aNetResource
.lpRemoteName
= reinterpret_cast<LPWSTR
>(strSysDirPath
->buffer
);
608 dwError
= WNetOpenEnumW(
611 RESOURCEUSAGE_CONNECTABLE
| RESOURCEUSAGE_CONTAINER
,
615 if ( ERROR_SUCCESS
== dwError
)
617 Directory_Impl
*pDirImpl
;
619 pDirImpl
= reinterpret_cast<Directory_Impl
*>(rtl_allocateMemory(sizeof(Directory_Impl
)));
620 ZeroMemory( pDirImpl
, sizeof(Directory_Impl
) );
621 pDirImpl
->uType
= DIRECTORYTYPE_NETROOT
;
622 pDirImpl
->hDirectory
= hEnum
;
623 *pDirectory
= (oslDirectory
)pDirImpl
;
625 return oslTranslateFileError( dwError
);
628 //#############################################
629 static DWORD
create_dir_with_callback(
630 rtl_uString
* dir_path
,
631 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
634 // Create the specified directory and call the
635 // user specified callback function. On success
636 // the function returns ERROR_SUCCESS else a Win32 error code.
638 BOOL bCreated
= FALSE
;
640 bCreated
= CreateDirectoryW( reinterpret_cast<LPCWSTR
>(rtl_uString_getStr( dir_path
)), NULL
);
644 if (aDirectoryCreationCallbackFunc
)
647 _osl_getFileURLFromSystemPath(dir_path
, &(url
.pData
));
648 aDirectoryCreationCallbackFunc(pData
, url
.pData
);
650 return ERROR_SUCCESS
;
652 return GetLastError();
655 //#############################################
656 static int path_make_parent(sal_Unicode
* path
)
658 /* Cut off the last part of the given path to
659 get the parent only, e.g. 'c:\dir\subdir' ->
660 'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
661 @return The position where the path has been cut
662 off (this is the posistion of the last backslash).
663 If there are no more parents 0 will be returned,
664 e.g. 'c:\' or '\\Share' have no more parents */
666 OSL_PRECOND(rtl_ustr_indexOfChar(path
, SLASH
) == -1, "Path must not contain slashes");
667 OSL_PRECOND(has_path_parent(path
), "Path must have a parent");
669 sal_Unicode
* pos_last_backslash
= path
+ rtl_ustr_lastIndexOfChar(path
, BACKSLASH
);
670 *pos_last_backslash
= 0;
671 return (pos_last_backslash
- path
);
674 //#############################################
675 static DWORD
create_dir_recursively_(
676 rtl_uString
* dir_path
,
677 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
681 rtl_ustr_lastIndexOfChar_WithLength(dir_path
->buffer
, dir_path
->length
, BACKSLASH
) != dir_path
->length
,
682 "Path must not end with a backslash");
684 DWORD w32_error
= create_dir_with_callback(
685 dir_path
, aDirectoryCreationCallbackFunc
, pData
);
686 if (w32_error
== ERROR_SUCCESS
)
687 return ERROR_SUCCESS
;
689 if ((w32_error
!= ERROR_PATH_NOT_FOUND
) || !has_path_parent(dir_path
->buffer
))
692 int pos
= path_make_parent(dir_path
->buffer
); // dir_path->buffer[pos] = 0, restore below
694 w32_error
= create_dir_recursively_(
695 dir_path
, aDirectoryCreationCallbackFunc
, pData
);
697 dir_path
->buffer
[pos
] = BACKSLASH
; // restore
699 if (ERROR_SUCCESS
!= w32_error
)
702 return create_dir_recursively_(dir_path
, aDirectoryCreationCallbackFunc
, pData
);
705 //#############################################
706 oslFileError SAL_CALL
osl_createDirectoryPath(
707 rtl_uString
* aDirectoryUrl
,
708 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
711 if (aDirectoryUrl
== NULL
)
712 return osl_File_E_INVAL
;
714 rtl::OUString sys_path
;
715 oslFileError osl_error
=
716 _osl_getSystemPathFromFileURL(aDirectoryUrl
, &sys_path
.pData
, sal_False
);
718 if (osl_error
!= osl_File_E_None
)
721 osl::systemPathRemoveSeparator(sys_path
);
723 // const_cast because sys_path is a local copy
724 // which we want to modify inplace instead of
725 // coyp it into another buffer on the heap again
726 return oslTranslateFileError(create_dir_recursively_(
727 sys_path
.pData
, aDirectoryCreationCallbackFunc
, pData
));
730 //#####################################################
731 oslFileError SAL_CALL
osl_createDirectory(rtl_uString
* strPath
)
733 rtl_uString
*strSysPath
= NULL
;
734 oslFileError error
= _osl_getSystemPathFromFileURL( strPath
, &strSysPath
, sal_False
);
736 if ( osl_File_E_None
== error
)
738 BOOL bCreated
= FALSE
;
740 bCreated
= CreateDirectoryW( reinterpret_cast<LPCWSTR
>(rtl_uString_getStr( strSysPath
)), NULL
);
745 The following case is a hack because the ucb or the webtop had some
746 problems with the error code that CreateDirectory returns in
747 case the path is only a logical drive, should be removed!
750 const sal_Unicode
*pBuffer
= rtl_uString_getStr( strSysPath
);
751 sal_Int32 nLen
= rtl_uString_getLength( strSysPath
);
754 ( ( pBuffer
[0] >= 'A' && pBuffer
[0] <= 'Z' ) ||
755 ( pBuffer
[0] >= 'a' && pBuffer
[0] <= 'z' ) ) &&
756 pBuffer
[1] == ':' && ( nLen
==2 || ( nLen
== 3 && pBuffer
[2] == '\\' ) )
758 SetLastError( ERROR_ALREADY_EXISTS
);
760 error
= oslTranslateFileError( GetLastError() );
763 rtl_uString_release( strSysPath
);
768 //#####################################################
769 oslFileError SAL_CALL
osl_removeDirectory(rtl_uString
* strPath
)
771 rtl_uString
*strSysPath
= NULL
;
772 oslFileError error
= _osl_getSystemPathFromFileURL( strPath
, &strSysPath
, sal_False
);
774 if ( osl_File_E_None
== error
)
776 if ( RemoveDirectory( reinterpret_cast<LPCTSTR
>(rtl_uString_getStr( strSysPath
)) ) )
777 error
= osl_File_E_None
;
779 error
= oslTranslateFileError( GetLastError() );
781 rtl_uString_release( strSysPath
);
786 //#####################################################
787 oslFileError SAL_CALL
osl_openDirectory(rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
791 if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath
->buffer
, "file:///" ) )
792 error
= osl_openLocalRoot( strDirectoryPath
, pDirectory
);
795 rtl_uString
*strSysDirectoryPath
= NULL
;
798 error
= _osl_getSystemPathFromFileURL( strDirectoryPath
, &strSysDirectoryPath
, sal_False
);
800 if ( osl_File_E_None
!= error
)
803 dwPathType
= IsValidFilePath( strSysDirectoryPath
, NULL
, VALIDATEPATH_NORMAL
, NULL
);
805 if ( dwPathType
& PATHTYPE_IS_SERVER
)
807 error
= osl_openNetworkServer( strSysDirectoryPath
, pDirectory
);
810 error
= osl_openFileDirectory( strSysDirectoryPath
, pDirectory
);
812 rtl_uString_release( strSysDirectoryPath
);
817 //#####################################################
818 static oslFileError SAL_CALL
osl_getNextNetResource(
819 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32
/*uHint*/ )
821 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
822 DirectoryItem_Impl
*pItemImpl
= NULL
;
824 LPNETRESOURCEW lpNetResource
= (LPNETRESOURCEW
)buffer
;
825 DWORD dwError
, dwCount
, dwBufSize
;
828 return osl_File_E_INVAL
;
832 return osl_File_E_INVAL
;
835 dwBufSize
= sizeof(buffer
);
836 dwError
= WNetEnumResource( pDirImpl
->hDirectory
, &dwCount
, lpNetResource
, &dwBufSize
);
841 case ERROR_MORE_DATA
:
843 pItemImpl
= reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
845 return osl_File_E_NOMEM
;
847 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
848 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
849 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
851 wcscpy( pItemImpl
->cDriveString
, lpNetResource
->lpRemoteName
);
855 return osl_File_E_None
;
856 case ERROR_NO_MORE_ITEMS
:
857 return osl_File_E_NOENT
;
859 return oslTranslateFileError( dwError
);
863 //#####################################################
864 static oslFileError SAL_CALL
osl_getNextDrive(
865 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32
/*uHint*/ )
867 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
868 DirectoryItem_Impl
*pItemImpl
= NULL
;
872 return osl_File_E_INVAL
;
876 return osl_File_E_INVAL
;
878 pItemImpl
= reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
880 return osl_File_E_NOMEM
;
882 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
883 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
884 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
885 fSuccess
= EnumLogicalDrives( pDirImpl
->hEnumDrives
, pItemImpl
->cDriveString
);
890 return osl_File_E_None
;
894 if ( pItemImpl
->m_pFullPath
)
896 rtl_uString_release( pItemImpl
->m_pFullPath
);
897 pItemImpl
->m_pFullPath
= 0;
900 rtl_freeMemory( pItemImpl
);
901 return oslTranslateFileError( GetLastError() );
905 //#####################################################
906 static oslFileError SAL_CALL
osl_getNextFileItem(
907 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32
/*uHint*/)
909 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
910 DirectoryItem_Impl
*pItemImpl
= NULL
;
914 return osl_File_E_INVAL
;
918 return osl_File_E_INVAL
;
920 pItemImpl
= reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
922 return osl_File_E_NOMEM
;
924 memset( pItemImpl
, 0, sizeof(DirectoryItem_Impl
) );
925 fFound
= EnumDirectory( pDirImpl
->hDirectory
, &pItemImpl
->FindData
);
929 pItemImpl
->uType
= DIRECTORYITEM_FILE
;
930 pItemImpl
->nRefCount
= 1;
932 rtl_uString
* pTmpFileName
= 0;
933 rtl_uString_newFromStr( &pTmpFileName
, reinterpret_cast<const sal_Unicode
*>(pItemImpl
->FindData
.cFileName
) );
934 rtl_uString_newConcat( &pItemImpl
->m_pFullPath
, pDirImpl
->m_pDirectoryPath
, pTmpFileName
);
935 rtl_uString_release( pTmpFileName
);
937 pItemImpl
->bFullPathNormalized
= FALSE
;
938 *pItem
= (oslDirectoryItem
)pItemImpl
;
939 return osl_File_E_None
;
943 if ( pItemImpl
->m_pFullPath
)
945 rtl_uString_release( pItemImpl
->m_pFullPath
);
946 pItemImpl
->m_pFullPath
= 0;
949 rtl_freeMemory( pItemImpl
);
950 return oslTranslateFileError( GetLastError() );
954 //#####################################################
955 oslFileError SAL_CALL
osl_getNextDirectoryItem(
956 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32 uHint
)
958 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
963 return osl_File_E_INVAL
;
967 return osl_File_E_INVAL
;
969 switch ( pDirImpl
->uType
)
971 case DIRECTORYTYPE_LOCALROOT
:
972 return osl_getNextDrive( Directory
, pItem
, uHint
);
973 case DIRECTORYTYPE_NETROOT
:
974 return osl_getNextNetResource( Directory
, pItem
, uHint
);
975 case DIRECTORYTYPE_FILESYSTEM
:
976 return osl_getNextFileItem( Directory
, pItem
, uHint
);
978 return osl_File_E_INVAL
;
982 //#####################################################
983 oslFileError SAL_CALL
osl_closeDirectory(oslDirectory Directory
)
985 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
986 oslFileError eError
= osl_File_E_INVAL
;
990 switch ( pDirImpl
->uType
)
992 case DIRECTORYTYPE_FILESYSTEM
:
993 eError
= CloseDirectory( pDirImpl
->hDirectory
) ? osl_File_E_None
: oslTranslateFileError( GetLastError() );
995 case DIRECTORYTYPE_LOCALROOT
:
996 eError
= CloseLogicalDrivesEnum( pDirImpl
->hEnumDrives
) ? osl_File_E_None
: oslTranslateFileError( GetLastError() );
998 case DIRECTORYTYPE_NETROOT
:
1000 DWORD err
= WNetCloseEnum(pDirImpl
->hDirectory
);
1001 eError
= (err
== NO_ERROR
) ? osl_File_E_None
: oslTranslateFileError(err
);
1005 OSL_FAIL( "Invalid directory type" );
1009 if ( pDirImpl
->m_pDirectoryPath
)
1011 rtl_uString_release( pDirImpl
->m_pDirectoryPath
);
1012 pDirImpl
->m_pDirectoryPath
= 0;
1015 rtl_freeMemory(pDirImpl
);
1020 //#####################################################
1021 /* Different types of paths */
1022 typedef enum _PATHTYPE
1024 PATHTYPE_SYNTAXERROR
= 0,
1031 oslFileError SAL_CALL
osl_getDirectoryItem(rtl_uString
*strFilePath
, oslDirectoryItem
*pItem
)
1033 oslFileError error
= osl_File_E_None
;
1034 rtl_uString
* strSysFilePath
= NULL
;
1035 PATHTYPE type
= PATHTYPE_FILE
;
1038 /* Assume failure */
1041 return osl_File_E_INVAL
;
1046 error
= _osl_getSystemPathFromFileURL( strFilePath
, &strSysFilePath
, sal_False
);
1048 if ( osl_File_E_None
!= error
)
1051 dwPathType
= IsValidFilePath( strSysFilePath
, NULL
, VALIDATEPATH_NORMAL
, NULL
);
1053 if ( dwPathType
& PATHTYPE_IS_VOLUME
)
1054 type
= PATHTYPE_VOLUME
;
1055 else if ( dwPathType
& PATHTYPE_IS_SERVER
)
1056 type
= PATHTYPE_NETSERVER
;
1058 type
= PATHTYPE_FILE
;
1062 case PATHTYPE_NETSERVER
:
1064 DirectoryItem_Impl
* pItemImpl
=
1065 reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
1068 error
= osl_File_E_NOMEM
;
1070 if ( osl_File_E_None
== error
)
1072 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
1073 pItemImpl
->uType
= DIRECTORYITEM_SERVER
;
1075 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
1076 rtl_uString_newFromString( &pItemImpl
->m_pFullPath
, strSysFilePath
);
1078 // Assign a title anyway
1083 while( iSrc
< strSysFilePath
->length
&& strSysFilePath
->buffer
[iSrc
] && strSysFilePath
->buffer
[iSrc
] != '\\' )
1085 pItemImpl
->FindData
.cFileName
[iDst
++] = strSysFilePath
->buffer
[iSrc
++];
1093 case PATHTYPE_VOLUME
:
1095 DirectoryItem_Impl
* pItemImpl
=
1096 reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
1099 error
= osl_File_E_NOMEM
;
1101 if ( osl_File_E_None
== error
)
1103 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
1104 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
1106 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
1108 _tcscpy( pItemImpl
->cDriveString
, reinterpret_cast<LPCTSTR
>(strSysFilePath
->buffer
) );
1109 pItemImpl
->cDriveString
[0] = toupper( pItemImpl
->cDriveString
[0] );
1111 if ( pItemImpl
->cDriveString
[_tcslen(pItemImpl
->cDriveString
) - 1] != '\\' )
1112 _tcscat( pItemImpl
->cDriveString
, TEXT( "\\" ) );
1118 case PATHTYPE_SYNTAXERROR
:
1119 case PATHTYPE_NETROOT
:
1123 WIN32_FIND_DATA aFindData
;
1125 if ( strSysFilePath
->length
> 0 && strSysFilePath
->buffer
[strSysFilePath
->length
- 1] == '\\' )
1126 rtl_uString_newFromStr_WithLength( &strSysFilePath
, strSysFilePath
->buffer
, strSysFilePath
->length
- 1 );
1128 hFind
= FindFirstFile( reinterpret_cast<LPCTSTR
>(rtl_uString_getStr(strSysFilePath
)), &aFindData
);
1130 if ( hFind
!= INVALID_HANDLE_VALUE
)
1132 DirectoryItem_Impl
*pItemImpl
=
1133 reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
1135 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
1136 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
1138 CopyMemory( &pItemImpl
->FindData
, &aFindData
, sizeof(WIN32_FIND_DATA
) );
1139 rtl_uString_newFromString( &pItemImpl
->m_pFullPath
, strSysFilePath
);
1141 // MT: This costs 600ms startup time on fast v60x!
1142 // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
1144 pItemImpl
->uType
= DIRECTORYITEM_FILE
;
1149 error
= oslTranslateFileError( GetLastError() );
1154 if ( strSysFilePath
)
1155 rtl_uString_release( strSysFilePath
);
1160 //#####################################################
1161 oslFileError SAL_CALL
osl_acquireDirectoryItem( oslDirectoryItem Item
)
1163 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1166 return osl_File_E_INVAL
;
1168 pItemImpl
->nRefCount
++;
1169 return osl_File_E_None
;
1172 //#####################################################
1173 oslFileError SAL_CALL
osl_releaseDirectoryItem( oslDirectoryItem Item
)
1175 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1178 return osl_File_E_INVAL
;
1180 if ( ! --pItemImpl
->nRefCount
)
1182 if ( pItemImpl
->m_pFullPath
)
1184 rtl_uString_release( pItemImpl
->m_pFullPath
);
1185 pItemImpl
->m_pFullPath
= 0;
1188 rtl_freeMemory( pItemImpl
);
1191 return osl_File_E_None
;
1196 SAL_CALL
osl_identicalDirectoryItem( oslDirectoryItem a
, oslDirectoryItem b
)
1198 DirectoryItem_Impl
*pA
= (DirectoryItem_Impl
*) a
;
1199 DirectoryItem_Impl
*pB
= (DirectoryItem_Impl
*) b
;
1202 /* same name => same item, unless renaming / moving madness has occurred */
1203 if (rtl_ustr_compare_WithLength(
1204 pA
->m_pFullPath
->buffer
, pA
->m_pFullPath
->length
,
1205 pB
->m_pFullPath
->buffer
, pB
->m_pFullPath
->length
) == 0)
1208 // FIXME: as/when/if this is used in anger on Windows we could
1214 //#####################################################
1215 // volume / file info handling functions
1216 //#####################################################
1218 //#####################################################
1219 static inline bool is_floppy_A_present()
1220 { return (GetLogicalDrives() & 1); }
1222 //#####################################################
1223 static inline bool is_floppy_B_present()
1224 { return (GetLogicalDrives() & 2); }
1226 //#####################################################
1227 bool is_floppy_volume_mount_point(const rtl::OUString
& path
)
1229 // determines if a volume mount point shows to a floppy
1230 // disk by comparing the unique volume names
1231 static const LPCWSTR FLOPPY_A
= L
"A:\\";
1232 static const LPCWSTR FLOPPY_B
= L
"B:\\";
1234 rtl::OUString
p(path
);
1235 osl::systemPathEnsureSeparator(p
);
1238 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR
>(p
.getStr()), vn
, SAL_N_ELEMENTS(vn
)))
1241 if (is_floppy_A_present() &&
1242 GetVolumeNameForVolumeMountPoint(FLOPPY_A
, vnfloppy
, SAL_N_ELEMENTS(vnfloppy
)) &&
1243 (0 == wcscmp(vn
, vnfloppy
)))
1246 if (is_floppy_B_present() &&
1247 GetVolumeNameForVolumeMountPoint(FLOPPY_B
, vnfloppy
, SAL_N_ELEMENTS(vnfloppy
)) &&
1248 (0 == wcscmp(vn
, vnfloppy
)))
1254 //################################################
1255 static bool is_floppy_drive(const rtl::OUString
& path
)
1257 static const LPCWSTR FLOPPY_DRV_LETTERS
= TEXT("AaBb");
1259 // we must take into account that even a floppy
1260 // drive may be mounted to a directory so checking
1261 // for the drive letter alone is not sufficient
1262 // we must compare the unique volume name with
1263 // that of the available floppy disks
1265 const sal_Unicode
* pszPath
= path
.getStr();
1266 return ((wcschr(FLOPPY_DRV_LETTERS
, pszPath
[0]) && (L
':' == pszPath
[1])) || is_floppy_volume_mount_point(path
));
1269 //#####################################################
1270 static bool is_volume_mount_point(const rtl::OUString
& path
)
1272 rtl::OUString
p(path
);
1273 osl::systemPathRemoveSeparator(p
);
1275 bool is_volume_root
= false;
1277 if (!is_floppy_drive(p
))
1279 DWORD fattr
= GetFileAttributes(reinterpret_cast<LPCTSTR
>(p
.getStr()));
1281 if ((INVALID_FILE_ATTRIBUTES
!= fattr
) &&
1282 (FILE_ATTRIBUTE_REPARSE_POINT
& fattr
))
1284 WIN32_FIND_DATA find_data
;
1285 HANDLE h_find
= FindFirstFile(reinterpret_cast<LPCTSTR
>(p
.getStr()), &find_data
);
1287 if (IsValidHandle(h_find
) &&
1288 (FILE_ATTRIBUTE_REPARSE_POINT
& find_data
.dwFileAttributes
) &&
1289 (IO_REPARSE_TAG_MOUNT_POINT
== find_data
.dwReserved0
))
1291 is_volume_root
= true;
1293 if (IsValidHandle(h_find
))
1297 return is_volume_root
;
1300 //#############################################
1301 static UINT
get_volume_mount_point_drive_type(const rtl::OUString
& path
)
1303 if (0 == path
.getLength())
1304 return GetDriveType(NULL
);
1306 rtl::OUString
p(path
);
1307 osl::systemPathEnsureSeparator(p
);
1310 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR
>(p
.getStr()), vn
, SAL_N_ELEMENTS(vn
)))
1311 return GetDriveType(vn
);
1313 return DRIVE_NO_ROOT_DIR
;
1316 //#############################################
1317 static inline bool is_drivetype_request(sal_uInt32 field_mask
)
1319 return (field_mask
& osl_VolumeInfo_Mask_Attributes
);
1322 //#############################################
1323 static oslFileError
osl_get_drive_type(
1324 const rtl::OUString
& path
, oslVolumeInfo
* pInfo
)
1326 // GetDriveType fails on empty volume mount points
1327 // see Knowledge Base Q244089
1329 if (is_volume_mount_point(path
))
1330 drive_type
= get_volume_mount_point_drive_type(path
);
1332 drive_type
= GetDriveType(reinterpret_cast<LPCTSTR
>(path
.getStr()));
1334 if (DRIVE_NO_ROOT_DIR
== drive_type
)
1335 return oslTranslateFileError(ERROR_INVALID_DRIVE
);
1337 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_Attributes
;
1342 pInfo
->uAttributes
|= osl_Volume_Attribute_CompactDisc
| osl_Volume_Attribute_Removeable
;
1344 case DRIVE_REMOVABLE
:
1345 pInfo
->uAttributes
|= osl_Volume_Attribute_Removeable
;
1346 if (is_floppy_drive(path
))
1347 pInfo
->uAttributes
|= osl_Volume_Attribute_FloppyDisk
;
1350 pInfo
->uAttributes
|= osl_Volume_Attribute_FixedDisk
;
1353 pInfo
->uAttributes
|= osl_Volume_Attribute_RAMDisk
;
1356 pInfo
->uAttributes
|= osl_Volume_Attribute_Remote
;
1359 pInfo
->uAttributes
= 0;
1362 pInfo
->uValidFields
&= ~osl_VolumeInfo_Mask_Attributes
;
1363 pInfo
->uAttributes
= 0;
1366 return osl_File_E_None
;
1369 //#############################################
1370 static inline bool is_volume_space_info_request(sal_uInt32 field_mask
)
1372 return (field_mask
&
1373 (osl_VolumeInfo_Mask_TotalSpace
|
1374 osl_VolumeInfo_Mask_UsedSpace
|
1375 osl_VolumeInfo_Mask_FreeSpace
));
1378 //#############################################
1379 static void get_volume_space_information(
1380 const rtl::OUString
& path
, oslVolumeInfo
*pInfo
)
1382 BOOL ret
= GetDiskFreeSpaceEx(
1383 reinterpret_cast<LPCTSTR
>(path
.getStr()),
1384 (PULARGE_INTEGER
)&(pInfo
->uFreeSpace
),
1385 (PULARGE_INTEGER
)&(pInfo
->uTotalSpace
),
1390 pInfo
->uUsedSpace
= pInfo
->uTotalSpace
- pInfo
->uFreeSpace
;
1391 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_TotalSpace
|
1392 osl_VolumeInfo_Mask_UsedSpace
|
1393 osl_VolumeInfo_Mask_FreeSpace
;
1397 //#############################################
1398 static inline bool is_filesystem_attributes_request(sal_uInt32 field_mask
)
1400 return (field_mask
&
1401 (osl_VolumeInfo_Mask_MaxNameLength
|
1402 osl_VolumeInfo_Mask_MaxPathLength
|
1403 osl_VolumeInfo_Mask_FileSystemName
|
1404 osl_VolumeInfo_Mask_FileSystemCaseHandling
));
1407 //#############################################
1408 static oslFileError
get_filesystem_attributes(
1409 const rtl::OUString
& path
, sal_uInt32 field_mask
, oslVolumeInfo
* pInfo
)
1411 pInfo
->uAttributes
= 0;
1413 // osl_get_drive_type must be called first because
1414 // this function resets osl_VolumeInfo_Mask_Attributes
1416 if (is_drivetype_request(field_mask
))
1418 oslFileError osl_error
= osl_get_drive_type(path
, pInfo
);
1419 if (osl_File_E_None
!= osl_error
)
1422 if (is_filesystem_attributes_request(field_mask
))
1424 /* the following two parameters can not be longer than MAX_PATH+1 */
1425 WCHAR vn
[MAX_PATH
+1];
1426 WCHAR fsn
[MAX_PATH
+1];
1432 LPCTSTR pszPath
= reinterpret_cast<LPCTSTR
>(path
.getStr());
1433 if (GetVolumeInformation(pszPath
, vn
, MAX_PATH
+1, &serial
, &mcl
, &flags
, fsn
, MAX_PATH
+1))
1435 // Currently sal does not use this value, instead MAX_PATH is used
1436 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_MaxNameLength
;
1437 pInfo
->uMaxNameLength
= mcl
;
1439 // Should the uMaxPathLength be set to 32767, "\\?\" prefix allowes it
1440 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_MaxPathLength
;
1441 pInfo
->uMaxPathLength
= MAX_PATH
;
1443 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_FileSystemName
;
1444 rtl_uString_newFromStr(&pInfo
->ustrFileSystemName
, reinterpret_cast<const sal_Unicode
*>(fsn
));
1446 // volumes (even NTFS) will always be considered case
1447 // insensitive because the Win32 API is not able to
1448 // deal with case sensitive volumes see M$ Knowledge Base
1449 // article 100625 that's why we never set the attribute
1450 // osl_Volume_Attribute_Case_Sensitive
1452 if (flags
& FS_CASE_IS_PRESERVED
)
1453 pInfo
->uAttributes
|= osl_Volume_Attribute_Case_Is_Preserved
;
1455 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_Attributes
;
1458 return osl_File_E_None
;
1461 //#####################################################
1462 static bool path_get_parent(rtl::OUString
& path
)
1464 OSL_PRECOND(path
.lastIndexOf(SLASH
) == -1, "Path must not have slashes");
1466 if (!has_path_parent(path
))
1468 sal_Int32 i
= path
.lastIndexOf(BACKSLASH
);
1471 path
= rtl::OUString(path
.getStr(), i
);
1478 //#####################################################
1479 static void path_travel_to_volume_root(const rtl::OUString
& system_path
, rtl::OUString
& volume_root
)
1481 rtl::OUString
sys_path(system_path
);
1483 while(!is_volume_mount_point(sys_path
) && path_get_parent(sys_path
))
1486 volume_root
= sys_path
;
1487 osl::systemPathEnsureSeparator(volume_root
);
1490 //#############################################
1491 oslFileError SAL_CALL
osl_getVolumeInformation(
1492 rtl_uString
*ustrURL
, oslVolumeInfo
*pInfo
, sal_uInt32 uFieldMask
)
1495 return osl_File_E_INVAL
;
1497 rtl::OUString system_path
;
1498 oslFileError error
= _osl_getSystemPathFromFileURL(ustrURL
, &system_path
.pData
, sal_False
);
1500 if (osl_File_E_None
!= error
)
1503 rtl::OUString volume_root
;
1504 path_travel_to_volume_root(system_path
, volume_root
);
1506 pInfo
->uValidFields
= 0;
1508 if ((error
= get_filesystem_attributes(volume_root
, uFieldMask
, pInfo
)) != osl_File_E_None
)
1511 if (is_volume_space_info_request(uFieldMask
))
1512 get_volume_space_information(volume_root
, pInfo
);
1514 if (uFieldMask
& osl_VolumeInfo_Mask_DeviceHandle
)
1516 error
= osl_getFileURLFromSystemPath(volume_root
.pData
, (rtl_uString
**)&pInfo
->pDeviceHandle
);
1517 if (error
!= osl_File_E_None
)
1519 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_DeviceHandle
;
1522 return osl_File_E_None
;
1525 //#####################################################
1526 static oslFileError SAL_CALL
osl_getDriveInfo(
1527 oslDirectoryItem Item
, oslFileStatus
*pStatus
, sal_uInt32 uFieldMask
)
1529 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1530 TCHAR cDrive
[3] = TEXT("A:");
1531 TCHAR cRoot
[4] = TEXT("A:\\");
1534 return osl_File_E_INVAL
;
1536 pStatus
->uValidFields
= 0;
1538 cDrive
[0] = pItemImpl
->cDriveString
[0];
1539 cRoot
[0] = pItemImpl
->cDriveString
[0];
1541 if ( uFieldMask
& osl_FileStatus_Mask_FileName
)
1543 if ( pItemImpl
->cDriveString
[0] == '\\' && pItemImpl
->cDriveString
[1] == '\\' )
1545 LPCWSTR lpFirstBkSlash
= wcschr( &pItemImpl
->cDriveString
[2], '\\' );
1547 if ( lpFirstBkSlash
&& lpFirstBkSlash
[1] )
1549 LPCWSTR lpLastBkSlash
= wcschr( &lpFirstBkSlash
[1], '\\' );
1551 if ( lpLastBkSlash
)
1552 rtl_uString_newFromStr_WithLength( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(&lpFirstBkSlash
[1]), lpLastBkSlash
- lpFirstBkSlash
- 1 );
1554 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(&lpFirstBkSlash
[1]) );
1555 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1558 else switch ( GetDriveType( cRoot
) )
1562 TCHAR szBuffer
[1024];
1563 DWORD
const dwBufsizeConst
= SAL_N_ELEMENTS(szBuffer
);
1564 DWORD dwBufsize
= dwBufsizeConst
;
1566 DWORD dwResult
= WNetGetConnection( cDrive
, szBuffer
, &dwBufsize
);
1567 if ( NO_ERROR
== dwResult
)
1569 TCHAR szFileName
[dwBufsizeConst
+ 16];
1571 swprintf( szFileName
, L
"%s [%s]", cDrive
, szBuffer
);
1572 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(szFileName
) );
1575 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(cDrive
) );
1577 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1581 TCHAR szVolumeNameBuffer
[1024];
1582 DWORD
const dwBufsizeConst
= SAL_N_ELEMENTS(szVolumeNameBuffer
);
1584 if ( GetVolumeInformation( cRoot
, szVolumeNameBuffer
, dwBufsizeConst
, NULL
, NULL
, NULL
, NULL
, 0 ) )
1586 TCHAR szFileName
[dwBufsizeConst
+ 16];
1588 swprintf( szFileName
, L
"%s [%s]", cDrive
, szVolumeNameBuffer
);
1589 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(szFileName
) );
1592 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(cDrive
) );
1594 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1597 case DRIVE_REMOVABLE
:
1598 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1599 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(cRoot
) );
1607 pStatus
->eType
= osl_File_Type_Volume
;
1608 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1610 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1612 rtl_uString
*ustrSystemPath
= NULL
;
1614 rtl_uString_newFromStr( &ustrSystemPath
, reinterpret_cast<const sal_Unicode
*>(pItemImpl
->cDriveString
) );
1615 oslFileError error
= osl_getFileURLFromSystemPath( ustrSystemPath
, &pStatus
->ustrFileURL
);
1616 rtl_uString_release( ustrSystemPath
);
1617 if (error
!= osl_File_E_None
)
1619 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1621 return osl_File_E_None
;
1624 //#####################################################
1625 static oslFileError SAL_CALL
osl_getServerInfo(
1626 oslDirectoryItem Item
, oslFileStatus
*pStatus
, sal_uInt32 uFieldMask
)
1628 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1630 return osl_File_E_INVAL
;
1632 pStatus
->uValidFields
= 0;
1634 // pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1636 // if ( _tcscmp( pItemImpl->FindData.cFileName, TEXT(".") ) == 0 )
1637 // rtl_uString_newFromAscii( &pStatus->ustrFileName, "/" );
1639 // rtl_uString_newFromStr( &pStatus->ustrFileName, pItemImpl->FindData.cFileName );
1641 pStatus
->eType
= osl_File_Type_Directory
;
1642 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1644 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1646 oslFileError error
= osl_getFileURLFromSystemPath( pItemImpl
->m_pFullPath
, &pStatus
->ustrFileURL
);
1647 if (error
!= osl_File_E_None
)
1649 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1651 return osl_File_E_None
;
1654 //#############################################
1655 oslFileError SAL_CALL
osl_getFileStatus(
1656 oslDirectoryItem Item
,
1657 oslFileStatus
*pStatus
,
1658 sal_uInt32 uFieldMask
)
1660 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1663 return osl_File_E_INVAL
;
1665 switch ( pItemImpl
->uType
)
1667 case DIRECTORYITEM_DRIVE
:
1668 return osl_getDriveInfo( Item
, pStatus
, uFieldMask
);
1669 case DIRECTORYITEM_SERVER
:
1670 return osl_getServerInfo( Item
, pStatus
, uFieldMask
);
1675 if ( uFieldMask
& osl_FileStatus_Mask_Validate
)
1677 HANDLE hFind
= FindFirstFile( reinterpret_cast<LPCTSTR
>( rtl_uString_getStr( pItemImpl
->m_pFullPath
) ), &pItemImpl
->FindData
);
1679 if ( hFind
!= INVALID_HANDLE_VALUE
)
1682 return oslTranslateFileError( GetLastError() );
1684 uFieldMask
&= ~ osl_FileStatus_Mask_Validate
;
1687 /* If no fields to retrieve left ignore pStatus */
1689 return osl_File_E_None
;
1691 /* Otherwise, this must be a valid pointer */
1693 return osl_File_E_INVAL
;
1695 if ( pStatus
->uStructSize
!= sizeof(oslFileStatus
) )
1696 return osl_File_E_INVAL
;
1698 pStatus
->uValidFields
= 0;
1700 /* File time stamps */
1702 if ( (uFieldMask
& osl_FileStatus_Mask_ModifyTime
) &&
1703 FileTimeToTimeValue( &pItemImpl
->FindData
.ftLastWriteTime
, &pStatus
->aModifyTime
) )
1704 pStatus
->uValidFields
|= osl_FileStatus_Mask_ModifyTime
;
1706 if ( (uFieldMask
& osl_FileStatus_Mask_AccessTime
) &&
1707 FileTimeToTimeValue( &pItemImpl
->FindData
.ftLastAccessTime
, &pStatus
->aAccessTime
) )
1708 pStatus
->uValidFields
|= osl_FileStatus_Mask_AccessTime
;
1710 if ( (uFieldMask
& osl_FileStatus_Mask_CreationTime
) &&
1711 FileTimeToTimeValue( &pItemImpl
->FindData
.ftCreationTime
, &pStatus
->aCreationTime
) )
1712 pStatus
->uValidFields
|= osl_FileStatus_Mask_CreationTime
;
1714 /* Most of the fields are already set, regardless of requiered fields */
1716 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(pItemImpl
->FindData
.cFileName
) );
1717 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1719 if ((FILE_ATTRIBUTE_REPARSE_POINT
& pItemImpl
->FindData
.dwFileAttributes
) &&
1720 (IO_REPARSE_TAG_MOUNT_POINT
== pItemImpl
->FindData
.dwReserved0
))
1721 pStatus
->eType
= osl_File_Type_Volume
;
1722 else if (pItemImpl
->FindData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1723 pStatus
->eType
= osl_File_Type_Directory
;
1725 pStatus
->eType
= osl_File_Type_Regular
;
1727 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1729 pStatus
->uAttributes
= pItemImpl
->FindData
.dwFileAttributes
;
1730 pStatus
->uValidFields
|= osl_FileStatus_Mask_Attributes
;
1732 pStatus
->uFileSize
= (sal_uInt64
)pItemImpl
->FindData
.nFileSizeLow
+ ((sal_uInt64
)pItemImpl
->FindData
.nFileSizeHigh
<< 32);
1733 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileSize
;
1735 if ( uFieldMask
& osl_FileStatus_Mask_LinkTargetURL
)
1737 oslFileError error
= osl_getFileURLFromSystemPath( pItemImpl
->m_pFullPath
, &pStatus
->ustrLinkTargetURL
);
1738 if (error
!= osl_File_E_None
)
1741 pStatus
->uValidFields
|= osl_FileStatus_Mask_LinkTargetURL
;
1744 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1746 if ( !pItemImpl
->bFullPathNormalized
)
1748 ::osl::LongPathBuffer
< sal_Unicode
> aBuffer( MAX_LONG_PATH
);
1749 sal_uInt32 nNewLen
= GetCaseCorrectPathName( reinterpret_cast<LPCTSTR
>( rtl_uString_getStr( pItemImpl
->m_pFullPath
) ),
1750 ::osl::mingw_reinterpret_cast
<LPTSTR
>( aBuffer
),
1751 aBuffer
.getBufSizeInSymbols(),
1756 rtl_uString_newFromStr( &pItemImpl
->m_pFullPath
, aBuffer
);
1757 pItemImpl
->bFullPathNormalized
= TRUE
;
1761 oslFileError error
= osl_getFileURLFromSystemPath( pItemImpl
->m_pFullPath
, &pStatus
->ustrFileURL
);
1762 if (error
!= osl_File_E_None
)
1764 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1767 return osl_File_E_None
;
1770 //#####################################################
1771 // file attributes handling functions
1772 //#####################################################
1774 //#############################################
1775 oslFileError SAL_CALL
osl_setFileAttributes(
1776 rtl_uString
*ustrFileURL
,
1777 sal_uInt64 uAttributes
)
1780 rtl_uString
*ustrSysPath
= NULL
;
1781 DWORD dwFileAttributes
;
1784 // Converts the normalized path into a systempath
1785 error
= _osl_getSystemPathFromFileURL( ustrFileURL
, &ustrSysPath
, sal_False
);
1787 if ( osl_File_E_None
!= error
)
1790 dwFileAttributes
= GetFileAttributes( reinterpret_cast<LPCTSTR
>(rtl_uString_getStr(ustrSysPath
)) );
1792 if ( (DWORD
)-1 != dwFileAttributes
)
1794 dwFileAttributes
&= ~(FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
);
1796 if ( uAttributes
& osl_File_Attribute_ReadOnly
)
1797 dwFileAttributes
|= FILE_ATTRIBUTE_READONLY
;
1799 if ( uAttributes
& osl_File_Attribute_Hidden
)
1800 dwFileAttributes
|= FILE_ATTRIBUTE_HIDDEN
;
1802 fSuccess
= SetFileAttributes( reinterpret_cast<LPCTSTR
>(rtl_uString_getStr(ustrSysPath
)), dwFileAttributes
);
1808 error
= oslTranslateFileError( GetLastError() );
1810 rtl_uString_release( ustrSysPath
);
1815 //#####################################################
1816 oslFileError SAL_CALL
osl_setFileTime(
1817 rtl_uString
*filePath
,
1818 const TimeValue
*aCreationTime
,
1819 const TimeValue
*aLastAccessTime
,
1820 const TimeValue
*aLastWriteTime
)
1823 rtl_uString
*sysPath
=NULL
;
1824 FILETIME
*lpCreationTime
=NULL
;
1825 FILETIME
*lpLastAccessTime
=NULL
;
1826 FILETIME
*lpLastWriteTime
=NULL
;
1827 FILETIME ftCreationTime
;
1828 FILETIME ftLastAccessTime
;
1829 FILETIME ftLastWriteTime
;
1834 error
=_osl_getSystemPathFromFileURL(filePath
, &sysPath
, sal_False
);
1836 if (error
==osl_File_E_INVAL
)
1839 hFile
=CreateFileW(reinterpret_cast<LPCWSTR
>(rtl_uString_getStr(sysPath
)), GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1840 rtl_uString_release(sysPath
);
1842 if (hFile
==INVALID_HANDLE_VALUE
)
1843 return osl_File_E_NOENT
;
1845 if (TimeValueToFileTime(aCreationTime
, &ftCreationTime
))
1846 lpCreationTime
=&ftCreationTime
;
1848 if (TimeValueToFileTime(aLastAccessTime
, &ftLastAccessTime
))
1849 lpLastAccessTime
=&ftLastAccessTime
;
1851 if (TimeValueToFileTime(aLastWriteTime
, &ftLastWriteTime
))
1852 lpLastWriteTime
=&ftLastWriteTime
;
1854 fSuccess
=SetFileTime(hFile
, lpCreationTime
, lpLastAccessTime
, lpLastWriteTime
);
1859 return osl_File_E_INVAL
;
1861 return osl_File_E_None
;
1864 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */