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 .
20 #include <systools/win32/uwinapi.h>
22 #include "file_url.hxx"
23 #include "filetime.hxx"
24 #include "file_error.hxx"
26 #include "path_helper.hxx"
28 #include <rtl/alloc.h>
29 #include <rtl/ustring.hxx>
30 #include <rtl/character.hxx>
31 #include <sal/log.hxx>
32 #include <o3tl/char16_t2wchar_t.hxx>
34 static const wchar_t UNC_PREFIX
[] = L
"\\\\";
35 static const wchar_t BACKSLASH
= '\\';
36 static const wchar_t SLASH
= '/';
38 BOOL
TimeValueToFileTime(const TimeValue
*cpTimeVal
, FILETIME
*pFTime
)
40 SYSTEMTIME BaseSysTime
;
41 FILETIME BaseFileTime
;
43 BOOL fSuccess
= FALSE
;
45 BaseSysTime
.wYear
= 1970;
46 BaseSysTime
.wMonth
= 1;
47 BaseSysTime
.wDayOfWeek
= 0;
49 BaseSysTime
.wHour
= 0;
50 BaseSysTime
.wMinute
= 0;
51 BaseSysTime
.wSecond
= 0;
52 BaseSysTime
.wMilliseconds
= 0;
54 if (cpTimeVal
==nullptr)
57 if ( SystemTimeToFileTime(&BaseSysTime
, &BaseFileTime
) )
61 __int64 localTime
= cpTimeVal
->Seconds
*__int64(10000000)+cpTimeVal
->Nanosec
/100;
62 osl::detail::setFiletime(FTime
, localTime
);
63 fSuccess
= 0 <= (timeValue
= osl::detail::getFiletime(BaseFileTime
) + osl::detail::getFiletime(FTime
));
65 osl::detail::setFiletime(*pFTime
, timeValue
);
70 BOOL
FileTimeToTimeValue(const FILETIME
*cpFTime
, TimeValue
*pTimeVal
)
72 SYSTEMTIME BaseSysTime
;
73 FILETIME BaseFileTime
;
74 BOOL fSuccess
= FALSE
; /* Assume failure */
76 BaseSysTime
.wYear
= 1970;
77 BaseSysTime
.wMonth
= 1;
78 BaseSysTime
.wDayOfWeek
= 0;
80 BaseSysTime
.wHour
= 0;
81 BaseSysTime
.wMinute
= 0;
82 BaseSysTime
.wSecond
= 0;
83 BaseSysTime
.wMilliseconds
= 0;
85 if ( SystemTimeToFileTime(&BaseSysTime
, &BaseFileTime
) )
89 fSuccess
= 0 <= (Value
= osl::detail::getFiletime(*cpFTime
) - osl::detail::getFiletime(BaseFileTime
));
93 pTimeVal
->Seconds
= static_cast<unsigned long>(Value
/ 10000000L);
94 pTimeVal
->Nanosec
= static_cast<unsigned long>((Value
% 10000000L) * 100);
106 begin_(nullptr), end_(nullptr)
109 bool isPresent() const
110 { return (static_cast<sal_IntPtr
>(end_
- begin_
) > 0); }
112 const sal_Unicode
* begin_
;
113 const sal_Unicode
* end_
;
123 bool is_UNC_path(const sal_Unicode
* path
)
124 { return (0 == wcsncmp(UNC_PREFIX
, o3tl::toW(path
), SAL_N_ELEMENTS(UNC_PREFIX
) - 1)); }
126 void parse_UNC_path(const sal_Unicode
* path
, UNCComponents
* puncc
)
128 OSL_PRECOND(is_UNC_path(path
), "Precondition violated: No UNC path");
129 OSL_PRECOND(rtl_ustr_indexOfChar(path
, SLASH
) == -1, "Path must not contain slashes");
131 const sal_Unicode
* pend
= path
+ rtl_ustr_getLength(path
);
132 const sal_Unicode
* ppos
= path
+ 2;
134 puncc
->server_
.begin_
= ppos
;
135 while ((ppos
< pend
) && (*ppos
!= BACKSLASH
))
138 puncc
->server_
.end_
= ppos
;
140 if (BACKSLASH
== *ppos
)
142 puncc
->share_
.begin_
= ++ppos
;
143 while ((ppos
< pend
) && (*ppos
!= BACKSLASH
))
146 puncc
->share_
.end_
= ppos
;
148 if (BACKSLASH
== *ppos
)
150 puncc
->resource_
.begin_
= ++ppos
;
154 puncc
->resource_
.end_
= ppos
;
158 SAL_WARN_IF(!puncc
->server_
.isPresent() || !puncc
->share_
.isPresent(),
160 "Postcondition violated: Invalid UNC path detected");
163 bool has_path_parent(const sal_Unicode
* path
)
165 // Has the given path a parent or are we already there,
166 // e.g. 'c:\' or '\\server\share\'?
168 bool has_parent
= false;
169 if (is_UNC_path(path
))
171 UNCComponents unc_comp
;
172 parse_UNC_path(path
, &unc_comp
);
173 has_parent
= unc_comp
.resource_
.isPresent();
177 has_parent
= !osl::systemPathIsLogicalDrivePattern(path
);
182 bool has_path_parent(const OUString
& path
)
183 { return has_path_parent(path
.getStr()); }
187 oslFileError SAL_CALL
osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle
)
191 rtl_uString_acquire( static_cast<rtl_uString
*>(Handle
) );
192 return osl_File_E_None
;
195 return osl_File_E_INVAL
;
198 oslFileError SAL_CALL
osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle
)
202 rtl_uString_release( static_cast<rtl_uString
*>(Handle
) );
203 return osl_File_E_None
;
206 return osl_File_E_INVAL
;
209 oslFileError SAL_CALL
osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle
, rtl_uString
**pstrPath
)
211 if ( Handle
&& pstrPath
)
213 rtl_uString_assign( pstrPath
, static_cast<rtl_uString
*>(Handle
) );
214 return osl_File_E_None
;
217 return osl_File_E_INVAL
;
220 #define DIRECTORYITEM_DRIVE 0
221 #define DIRECTORYITEM_FILE 1
222 #define DIRECTORYITEM_SERVER 2
224 struct DirectoryItem_Impl
228 WIN32_FIND_DATAW FindData
;
229 WCHAR cDriveString
[MAX_PATH
];
231 rtl_uString
* m_pFullPath
;
232 BOOL bFullPathNormalized
;
236 #define DIRECTORYTYPE_LOCALROOT 0
237 #define DIRECTORYTYPE_NETROOT 1
238 #define DIRECTORYTYPE_FILESYSTEM 3
240 struct Directory_Impl
247 rtl_uString
* m_pDirectoryPath
;
250 typedef struct tagDRIVEENUM
253 WCHAR cBuffer
[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
255 } DRIVEENUM
, * PDRIVEENUM
, FAR
* LPDRIVEENUM
;
257 static HANDLE WINAPI
OpenLogicalDrivesEnum()
259 LPDRIVEENUM pEnum
= static_cast<LPDRIVEENUM
>(HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM
) ));
262 DWORD dwNumCopied
= GetLogicalDriveStringsW( SAL_N_ELEMENTS(pEnum
->cBuffer
) - 1, pEnum
->cBuffer
);
264 if ( dwNumCopied
&& dwNumCopied
< SAL_N_ELEMENTS(pEnum
->cBuffer
) )
266 pEnum
->lpCurrent
= pEnum
->cBuffer
;
267 pEnum
->lpIdent
= L
"tagDRIVEENUM";
271 HeapFree( GetProcessHeap(), 0, pEnum
);
275 return pEnum
? static_cast<HANDLE
>(pEnum
) : INVALID_HANDLE_VALUE
;
278 static BOOL WINAPI
EnumLogicalDrives(HANDLE hEnum
, LPWSTR lpBuffer
)
280 BOOL fSuccess
= FALSE
;
281 LPDRIVEENUM pEnum
= static_cast<LPDRIVEENUM
>(hEnum
);
285 int nLen
= wcslen( pEnum
->lpCurrent
);
289 CopyMemory( lpBuffer
, pEnum
->lpCurrent
, (nLen
+ 1) * sizeof(WCHAR
) );
290 pEnum
->lpCurrent
+= nLen
+ 1;
294 SetLastError( ERROR_NO_MORE_FILES
);
297 SetLastError( ERROR_INVALID_HANDLE
);
302 static BOOL WINAPI
CloseLogicalDrivesEnum(HANDLE hEnum
)
304 BOOL fSuccess
= FALSE
;
305 LPDRIVEENUM pEnum
= static_cast<LPDRIVEENUM
>(hEnum
);
309 HeapFree( GetProcessHeap(), 0, pEnum
);
313 SetLastError( ERROR_INVALID_HANDLE
);
318 typedef struct tagDIRECTORY
321 WIN32_FIND_DATAW aFirstData
;
322 } DIRECTORY
, *PDIRECTORY
, FAR
*LPDIRECTORY
;
324 static HANDLE WINAPI
OpenDirectory( rtl_uString
* pPath
)
326 LPDIRECTORY pDirectory
= nullptr;
330 sal_uInt32 nLen
= rtl_uString_getLength( pPath
);
333 const WCHAR
* pSuffix
= nullptr;
334 sal_uInt32 nSuffLen
= 0;
336 if ( pPath
->buffer
[nLen
- 1] != L
'\\' )
347 WCHAR
* szFileMask
= static_cast< WCHAR
* >( malloc( sizeof( WCHAR
) * ( nLen
+ nSuffLen
+ 1 ) ) );
348 assert(szFileMask
); // Don't handle OOM conditions
349 wcscpy( szFileMask
, o3tl::toW(rtl_uString_getStr( pPath
)) );
350 wcscat( szFileMask
, pSuffix
);
352 pDirectory
= static_cast<LPDIRECTORY
>(HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY
)));
353 assert(pDirectory
); // Don't handle OOM conditions
354 pDirectory
->hFind
= FindFirstFileW(szFileMask
, &pDirectory
->aFirstData
);
356 if (!IsValidHandle(pDirectory
->hFind
))
358 if ( GetLastError() != ERROR_NO_MORE_FILES
)
360 HeapFree(GetProcessHeap(), 0, pDirectory
);
361 pDirectory
= nullptr;
368 return static_cast<HANDLE
>(pDirectory
);
371 static BOOL WINAPI
EnumDirectory(HANDLE hDirectory
, LPWIN32_FIND_DATAW pFindData
)
373 BOOL fSuccess
= FALSE
;
374 LPDIRECTORY pDirectory
= static_cast<LPDIRECTORY
>(hDirectory
);
382 if ( pDirectory
->aFirstData
.cFileName
[0] )
384 *pFindData
= pDirectory
->aFirstData
;
386 pDirectory
->aFirstData
.cFileName
[0] = 0;
388 else if ( IsValidHandle( pDirectory
->hFind
) )
389 fSuccess
= FindNextFileW( pDirectory
->hFind
, pFindData
);
393 SetLastError( ERROR_NO_MORE_FILES
);
396 fValid
= fSuccess
&& wcscmp( L
".", pFindData
->cFileName
) != 0 && wcscmp( L
"..", pFindData
->cFileName
) != 0;
398 } while( fSuccess
&& !fValid
);
401 SetLastError( ERROR_INVALID_HANDLE
);
406 static BOOL WINAPI
CloseDirectory(HANDLE hDirectory
)
408 BOOL fSuccess
= FALSE
;
409 LPDIRECTORY pDirectory
= static_cast<LPDIRECTORY
>(hDirectory
);
413 if (IsValidHandle(pDirectory
->hFind
))
414 fSuccess
= FindClose(pDirectory
->hFind
);
416 fSuccess
= HeapFree(GetProcessHeap(), 0, pDirectory
) && fSuccess
;
419 SetLastError(ERROR_INVALID_HANDLE
);
424 static oslFileError
osl_openLocalRoot(
425 rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
427 rtl_uString
*strSysPath
= nullptr;
431 return osl_File_E_INVAL
;
433 *pDirectory
= nullptr;
435 error
= osl_getSystemPathFromFileURL_( strDirectoryPath
, &strSysPath
, false );
436 if ( osl_File_E_None
== error
)
438 Directory_Impl
*pDirImpl
;
440 pDirImpl
= static_cast<Directory_Impl
*>(malloc( sizeof(Directory_Impl
)));
441 assert(pDirImpl
); // Don't handle OOM conditions
442 ZeroMemory( pDirImpl
, sizeof(Directory_Impl
) );
443 rtl_uString_newFromString( &pDirImpl
->m_pDirectoryPath
, strSysPath
);
445 /* Append backslash if necessary */
448 use function ensure backslash
450 sal_uInt32 nLen
= rtl_uString_getLength( pDirImpl
->m_pDirectoryPath
);
451 if ( nLen
&& pDirImpl
->m_pDirectoryPath
->buffer
[nLen
- 1] != L
'\\' )
453 rtl_uString
* pCurDir
= nullptr;
454 rtl_uString
* pBackSlash
= nullptr;
456 rtl_uString_assign( &pCurDir
, pDirImpl
->m_pDirectoryPath
);
457 rtl_uString_newFromAscii( &pBackSlash
, "\\" );
458 rtl_uString_newConcat( &pDirImpl
->m_pDirectoryPath
, pCurDir
, pBackSlash
);
459 rtl_uString_release( pBackSlash
);
460 rtl_uString_release( pCurDir
);
463 pDirImpl
->uType
= DIRECTORYTYPE_LOCALROOT
;
464 pDirImpl
->hEnumDrives
= OpenLogicalDrivesEnum();
467 Use IsValidHandle(...)
469 if ( pDirImpl
->hEnumDrives
!= INVALID_HANDLE_VALUE
)
471 *pDirectory
= static_cast<oslDirectory
>(pDirImpl
);
472 error
= osl_File_E_None
;
478 if ( pDirImpl
->m_pDirectoryPath
)
480 rtl_uString_release( pDirImpl
->m_pDirectoryPath
);
481 pDirImpl
->m_pDirectoryPath
= nullptr;
488 error
= oslTranslateFileError( GetLastError() );
491 rtl_uString_release( strSysPath
);
496 static oslFileError
osl_openFileDirectory(
497 rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
499 oslFileError error
= osl_File_E_None
;
502 return osl_File_E_INVAL
;
503 *pDirectory
= nullptr;
505 Directory_Impl
*pDirImpl
= static_cast<Directory_Impl
*>(malloc(sizeof(Directory_Impl
)));
506 assert(pDirImpl
); // Don't handle OOM conditions
507 ZeroMemory( pDirImpl
, sizeof(Directory_Impl
) );
508 rtl_uString_newFromString( &pDirImpl
->m_pDirectoryPath
, strDirectoryPath
);
510 /* Append backslash if necessary */
513 use function ensure backslash
515 sal_uInt32 nLen
= rtl_uString_getLength( pDirImpl
->m_pDirectoryPath
);
516 if ( nLen
&& pDirImpl
->m_pDirectoryPath
->buffer
[nLen
- 1] != L
'\\' )
518 rtl_uString
* pCurDir
= nullptr;
519 rtl_uString
* pBackSlash
= nullptr;
521 rtl_uString_assign( &pCurDir
, pDirImpl
->m_pDirectoryPath
);
522 rtl_uString_newFromAscii( &pBackSlash
, "\\" );
523 rtl_uString_newConcat( &pDirImpl
->m_pDirectoryPath
, pCurDir
, pBackSlash
);
524 rtl_uString_release( pBackSlash
);
525 rtl_uString_release( pCurDir
);
528 pDirImpl
->uType
= DIRECTORYTYPE_FILESYSTEM
;
529 pDirImpl
->hDirectory
= OpenDirectory( pDirImpl
->m_pDirectoryPath
);
531 if ( !pDirImpl
->hDirectory
)
533 error
= oslTranslateFileError( GetLastError() );
535 if ( pDirImpl
->m_pDirectoryPath
)
537 rtl_uString_release( pDirImpl
->m_pDirectoryPath
);
538 pDirImpl
->m_pDirectoryPath
= nullptr;
545 *pDirectory
= static_cast<oslDirectory
>(pDirImpl
);
549 static oslFileError
osl_openNetworkServer(
550 rtl_uString
*strSysDirPath
, oslDirectory
*pDirectory
)
552 NETRESOURCEW aNetResource
;
556 ZeroMemory( &aNetResource
, sizeof(aNetResource
) );
558 aNetResource
.lpRemoteName
= o3tl::toW(strSysDirPath
->buffer
);
560 dwError
= WNetOpenEnumW(
563 RESOURCEUSAGE_CONNECTABLE
| RESOURCEUSAGE_CONTAINER
,
567 if ( ERROR_SUCCESS
== dwError
)
569 Directory_Impl
*pDirImpl
;
571 pDirImpl
= static_cast<Directory_Impl
*>(malloc(sizeof(Directory_Impl
)));
572 assert(pDirImpl
); // Don't handle OOM conditions
573 ZeroMemory( pDirImpl
, sizeof(Directory_Impl
) );
574 pDirImpl
->uType
= DIRECTORYTYPE_NETROOT
;
575 pDirImpl
->hDirectory
= hEnum
;
576 *pDirectory
= static_cast<oslDirectory
>(pDirImpl
);
578 return oslTranslateFileError( dwError
);
581 static DWORD
create_dir_with_callback(
582 rtl_uString
* dir_path
,
583 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
586 // Create the specified directory and call the
587 // user specified callback function. On success
588 // the function returns ERROR_SUCCESS else a Win32 error code.
590 BOOL bCreated
= CreateDirectoryW( o3tl::toW(rtl_uString_getStr( dir_path
)), nullptr );
594 if (aDirectoryCreationCallbackFunc
)
597 osl_getFileURLFromSystemPath(dir_path
, &(url
.pData
));
598 aDirectoryCreationCallbackFunc(pData
, url
.pData
);
600 return ERROR_SUCCESS
;
602 return GetLastError();
605 static int path_make_parent(sal_Unicode
* path
)
607 /* Cut off the last part of the given path to
608 get the parent only, e.g. 'c:\dir\subdir' ->
609 'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
610 @return The position where the path has been cut
611 off (this is the position of the last backslash).
612 If there are no more parents 0 will be returned,
613 e.g. 'c:\' or '\\Share' have no more parents */
615 OSL_PRECOND(rtl_ustr_indexOfChar(path
, SLASH
) == -1, "Path must not contain slashes");
616 OSL_PRECOND(has_path_parent(path
), "Path must have a parent");
618 sal_Unicode
* pos_last_backslash
= path
+ rtl_ustr_lastIndexOfChar(path
, BACKSLASH
);
619 *pos_last_backslash
= 0;
620 return (pos_last_backslash
- path
);
623 static DWORD
create_dir_recursively_(
624 rtl_uString
* dir_path
,
625 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
629 rtl_ustr_lastIndexOfChar_WithLength(dir_path
->buffer
, dir_path
->length
, BACKSLASH
) != dir_path
->length
,
630 "Path must not end with a backslash");
632 DWORD w32_error
= create_dir_with_callback(
633 dir_path
, aDirectoryCreationCallbackFunc
, pData
);
634 if (w32_error
== ERROR_SUCCESS
)
635 return ERROR_SUCCESS
;
637 if ((w32_error
!= ERROR_PATH_NOT_FOUND
) || !has_path_parent(dir_path
->buffer
))
640 int pos
= path_make_parent(dir_path
->buffer
); // dir_path->buffer[pos] = 0, restore below
642 w32_error
= create_dir_recursively_(
643 dir_path
, aDirectoryCreationCallbackFunc
, pData
);
645 dir_path
->buffer
[pos
] = BACKSLASH
; // restore
647 if (ERROR_SUCCESS
!= w32_error
&& ERROR_ALREADY_EXISTS
!= w32_error
)
650 return create_dir_recursively_(dir_path
, aDirectoryCreationCallbackFunc
, pData
);
653 oslFileError SAL_CALL
osl_createDirectoryPath(
654 rtl_uString
* aDirectoryUrl
,
655 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
658 if (aDirectoryUrl
== nullptr)
659 return osl_File_E_INVAL
;
662 oslFileError osl_error
=
663 osl_getSystemPathFromFileURL_(aDirectoryUrl
, &sys_path
.pData
, false);
665 if (osl_error
!= osl_File_E_None
)
668 osl::systemPathRemoveSeparator(sys_path
);
670 // const_cast because sys_path is a local copy
671 // which we want to modify inplace instead of
672 // copy it into another buffer on the heap again
673 return oslTranslateFileError(create_dir_recursively_(
674 sys_path
.pData
, aDirectoryCreationCallbackFunc
, pData
));
677 oslFileError SAL_CALL
osl_createDirectory(rtl_uString
* strPath
)
679 return osl_createDirectoryWithFlags(
680 strPath
, osl_File_OpenFlag_Read
| osl_File_OpenFlag_Write
);
683 oslFileError
osl_createDirectoryWithFlags(rtl_uString
* strPath
, sal_uInt32
)
685 rtl_uString
*strSysPath
= nullptr;
686 oslFileError error
= osl_getSystemPathFromFileURL_( strPath
, &strSysPath
, false );
688 if ( osl_File_E_None
== error
)
690 BOOL bCreated
= CreateDirectoryW( o3tl::toW(rtl_uString_getStr( strSysPath
)), nullptr );
695 The following case is a hack because the ucb or the webtop had some
696 problems with the error code that CreateDirectory returns in
697 case the path is only a logical drive, should be removed!
700 const sal_Unicode
*pBuffer
= rtl_uString_getStr( strSysPath
);
701 sal_Int32 nLen
= rtl_uString_getLength( strSysPath
);
704 ( ( pBuffer
[0] >= 'A' && pBuffer
[0] <= 'Z' ) ||
705 ( pBuffer
[0] >= 'a' && pBuffer
[0] <= 'z' ) ) &&
706 pBuffer
[1] == ':' && ( nLen
==2 || ( nLen
== 3 && pBuffer
[2] == '\\' ) )
708 SetLastError( ERROR_ALREADY_EXISTS
);
710 error
= oslTranslateFileError( GetLastError() );
713 rtl_uString_release( strSysPath
);
718 oslFileError SAL_CALL
osl_removeDirectory(rtl_uString
* strPath
)
720 rtl_uString
*strSysPath
= nullptr;
721 oslFileError error
= osl_getSystemPathFromFileURL_( strPath
, &strSysPath
, false );
723 if ( osl_File_E_None
== error
)
725 if ( RemoveDirectoryW( o3tl::toW(rtl_uString_getStr( strSysPath
) )) )
726 error
= osl_File_E_None
;
728 error
= oslTranslateFileError( GetLastError() );
730 rtl_uString_release( strSysPath
);
735 oslFileError SAL_CALL
osl_openDirectory(rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
739 if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath
->buffer
, "file:///" ) )
740 error
= osl_openLocalRoot( strDirectoryPath
, pDirectory
);
743 rtl_uString
*strSysDirectoryPath
= nullptr;
746 error
= osl_getSystemPathFromFileURL_( strDirectoryPath
, &strSysDirectoryPath
, false );
748 if ( osl_File_E_None
!= error
)
751 dwPathType
= IsValidFilePath( strSysDirectoryPath
, VALIDATEPATH_NORMAL
, nullptr );
753 if ( dwPathType
& PATHTYPE_IS_SERVER
)
755 error
= osl_openNetworkServer( strSysDirectoryPath
, pDirectory
);
758 error
= osl_openFileDirectory( strSysDirectoryPath
, pDirectory
);
760 rtl_uString_release( strSysDirectoryPath
);
765 static oslFileError
osl_getNextNetResource(
766 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32
/*uHint*/ )
768 Directory_Impl
*pDirImpl
= static_cast<Directory_Impl
*>(Directory
);
769 DirectoryItem_Impl
*pItemImpl
= nullptr;
771 LPNETRESOURCEW lpNetResource
= reinterpret_cast<LPNETRESOURCEW
>(buffer
);
772 DWORD dwError
, dwCount
, dwBufSize
;
775 return osl_File_E_INVAL
;
779 return osl_File_E_INVAL
;
782 dwBufSize
= sizeof(buffer
);
783 dwError
= WNetEnumResourceW( pDirImpl
->hDirectory
, &dwCount
, lpNetResource
, &dwBufSize
);
788 case ERROR_MORE_DATA
:
790 pItemImpl
= static_cast<DirectoryItem_Impl
*>(malloc(sizeof(DirectoryItem_Impl
)));
792 return osl_File_E_NOMEM
;
794 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
795 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
796 osl_acquireDirectoryItem( static_cast<oslDirectoryItem
>(pItemImpl
) );
798 wcscpy( pItemImpl
->cDriveString
, lpNetResource
->lpRemoteName
);
802 return osl_File_E_None
;
803 case ERROR_NO_MORE_ITEMS
:
804 return osl_File_E_NOENT
;
806 return oslTranslateFileError( dwError
);
810 static oslFileError
osl_getNextDrive(
811 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32
/*uHint*/ )
813 Directory_Impl
*pDirImpl
= static_cast<Directory_Impl
*>(Directory
);
814 DirectoryItem_Impl
*pItemImpl
= nullptr;
818 return osl_File_E_INVAL
;
822 return osl_File_E_INVAL
;
824 pItemImpl
= static_cast<DirectoryItem_Impl
*>(malloc(sizeof(DirectoryItem_Impl
)));
826 return osl_File_E_NOMEM
;
828 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
829 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
830 osl_acquireDirectoryItem( static_cast<oslDirectoryItem
>(pItemImpl
) );
831 fSuccess
= EnumLogicalDrives( pDirImpl
->hEnumDrives
, pItemImpl
->cDriveString
);
836 return osl_File_E_None
;
840 if ( pItemImpl
->m_pFullPath
)
842 rtl_uString_release( pItemImpl
->m_pFullPath
);
843 pItemImpl
->m_pFullPath
= nullptr;
847 return oslTranslateFileError( GetLastError() );
851 static oslFileError
osl_getNextFileItem(
852 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32
/*uHint*/)
854 Directory_Impl
*pDirImpl
= static_cast<Directory_Impl
*>(Directory
);
855 DirectoryItem_Impl
*pItemImpl
= nullptr;
859 return osl_File_E_INVAL
;
863 return osl_File_E_INVAL
;
865 pItemImpl
= static_cast<DirectoryItem_Impl
*>(malloc(sizeof(DirectoryItem_Impl
)));
867 return osl_File_E_NOMEM
;
869 memset( pItemImpl
, 0, sizeof(DirectoryItem_Impl
) );
870 fFound
= EnumDirectory( pDirImpl
->hDirectory
, &pItemImpl
->FindData
);
874 pItemImpl
->uType
= DIRECTORYITEM_FILE
;
875 pItemImpl
->nRefCount
= 1;
877 rtl_uString
* pTmpFileName
= nullptr;
878 rtl_uString_newFromStr( &pTmpFileName
, o3tl::toU(pItemImpl
->FindData
.cFileName
) );
879 rtl_uString_newConcat( &pItemImpl
->m_pFullPath
, pDirImpl
->m_pDirectoryPath
, pTmpFileName
);
880 rtl_uString_release( pTmpFileName
);
882 pItemImpl
->bFullPathNormalized
= FALSE
;
883 *pItem
= static_cast<oslDirectoryItem
>(pItemImpl
);
884 return osl_File_E_None
;
888 if ( pItemImpl
->m_pFullPath
)
890 rtl_uString_release( pItemImpl
->m_pFullPath
);
891 pItemImpl
->m_pFullPath
= nullptr;
895 return oslTranslateFileError( GetLastError() );
899 oslFileError SAL_CALL
osl_getNextDirectoryItem(
900 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32 uHint
)
902 Directory_Impl
*pDirImpl
= static_cast<Directory_Impl
*>(Directory
);
907 return osl_File_E_INVAL
;
911 return osl_File_E_INVAL
;
913 switch ( pDirImpl
->uType
)
915 case DIRECTORYTYPE_LOCALROOT
:
916 return osl_getNextDrive( Directory
, pItem
, uHint
);
917 case DIRECTORYTYPE_NETROOT
:
918 return osl_getNextNetResource( Directory
, pItem
, uHint
);
919 case DIRECTORYTYPE_FILESYSTEM
:
920 return osl_getNextFileItem( Directory
, pItem
, uHint
);
922 return osl_File_E_INVAL
;
926 oslFileError SAL_CALL
osl_closeDirectory(oslDirectory Directory
)
928 Directory_Impl
*pDirImpl
= static_cast<Directory_Impl
*>(Directory
);
929 oslFileError eError
= osl_File_E_INVAL
;
933 switch ( pDirImpl
->uType
)
935 case DIRECTORYTYPE_FILESYSTEM
:
936 eError
= CloseDirectory( pDirImpl
->hDirectory
) ? osl_File_E_None
: oslTranslateFileError( GetLastError() );
938 case DIRECTORYTYPE_LOCALROOT
:
939 eError
= CloseLogicalDrivesEnum( pDirImpl
->hEnumDrives
) ? osl_File_E_None
: oslTranslateFileError( GetLastError() );
941 case DIRECTORYTYPE_NETROOT
:
943 DWORD err
= WNetCloseEnum(pDirImpl
->hDirectory
);
944 eError
= (err
== NO_ERROR
) ? osl_File_E_None
: oslTranslateFileError(err
);
948 OSL_FAIL( "Invalid directory type" );
952 if ( pDirImpl
->m_pDirectoryPath
)
954 rtl_uString_release( pDirImpl
->m_pDirectoryPath
);
955 pDirImpl
->m_pDirectoryPath
= nullptr;
963 /* Different types of paths */
966 PATHTYPE_SYNTAXERROR
= 0,
973 oslFileError SAL_CALL
osl_getDirectoryItem(rtl_uString
*strFilePath
, oslDirectoryItem
*pItem
)
975 oslFileError error
= osl_File_E_None
;
976 rtl_uString
* strSysFilePath
= nullptr;
977 PATHTYPE type
= PATHTYPE_FILE
;
983 return osl_File_E_INVAL
;
987 error
= osl_getSystemPathFromFileURL_( strFilePath
, &strSysFilePath
, false );
989 if ( osl_File_E_None
!= error
)
992 dwPathType
= IsValidFilePath( strSysFilePath
, VALIDATEPATH_NORMAL
, nullptr );
994 if ( dwPathType
& PATHTYPE_IS_VOLUME
)
995 type
= PATHTYPE_VOLUME
;
996 else if ( dwPathType
& PATHTYPE_IS_SERVER
)
997 type
= PATHTYPE_NETSERVER
;
999 type
= PATHTYPE_FILE
;
1003 case PATHTYPE_NETSERVER
:
1005 DirectoryItem_Impl
* pItemImpl
=
1006 static_cast<DirectoryItem_Impl
*>(malloc(sizeof(DirectoryItem_Impl
)));
1009 error
= osl_File_E_NOMEM
;
1011 if ( osl_File_E_None
== error
)
1013 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
1014 pItemImpl
->uType
= DIRECTORYITEM_SERVER
;
1016 osl_acquireDirectoryItem( static_cast<oslDirectoryItem
>(pItemImpl
) );
1017 rtl_uString_newFromString( &pItemImpl
->m_pFullPath
, strSysFilePath
);
1019 // Assign a title anyway
1024 while( iSrc
< strSysFilePath
->length
&& strSysFilePath
->buffer
[iSrc
] && strSysFilePath
->buffer
[iSrc
] != '\\' )
1026 pItemImpl
->FindData
.cFileName
[iDst
++] = strSysFilePath
->buffer
[iSrc
++];
1034 case PATHTYPE_VOLUME
:
1036 DirectoryItem_Impl
* pItemImpl
=
1037 static_cast<DirectoryItem_Impl
*>(malloc(sizeof(DirectoryItem_Impl
)));
1040 error
= osl_File_E_NOMEM
;
1042 if ( osl_File_E_None
== error
)
1044 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
1045 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
1047 osl_acquireDirectoryItem( static_cast<oslDirectoryItem
>(pItemImpl
) );
1049 wcscpy( pItemImpl
->cDriveString
, o3tl::toW(strSysFilePath
->buffer
) );
1050 pItemImpl
->cDriveString
[0] = rtl::toAsciiUpperCase( pItemImpl
->cDriveString
[0] );
1052 if ( pItemImpl
->cDriveString
[wcslen(pItemImpl
->cDriveString
) - 1] != '\\' )
1053 wcscat( pItemImpl
->cDriveString
, L
"\\" );
1059 case PATHTYPE_SYNTAXERROR
:
1060 case PATHTYPE_NETROOT
:
1064 WIN32_FIND_DATAW aFindData
;
1066 if ( strSysFilePath
->length
> 0 && strSysFilePath
->buffer
[strSysFilePath
->length
- 1] == '\\' )
1067 rtl_uString_newFromStr_WithLength( &strSysFilePath
, strSysFilePath
->buffer
, strSysFilePath
->length
- 1 );
1069 hFind
= FindFirstFileW( o3tl::toW(rtl_uString_getStr(strSysFilePath
)), &aFindData
);
1071 if ( hFind
!= INVALID_HANDLE_VALUE
)
1073 DirectoryItem_Impl
*pItemImpl
=
1074 static_cast<DirectoryItem_Impl
*>(malloc(sizeof(DirectoryItem_Impl
)));
1076 error
= osl_File_E_NOMEM
;
1078 if (osl_File_E_None
== error
)
1080 ZeroMemory(pItemImpl
, sizeof(DirectoryItem_Impl
));
1081 osl_acquireDirectoryItem(static_cast<oslDirectoryItem
>(pItemImpl
));
1083 CopyMemory(&pItemImpl
->FindData
, &aFindData
, sizeof(WIN32_FIND_DATAW
));
1084 rtl_uString_newFromString(&pItemImpl
->m_pFullPath
, strSysFilePath
);
1086 // MT: This costs 600ms startup time on fast v60x!
1087 // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
1089 pItemImpl
->uType
= DIRECTORYITEM_FILE
;
1096 error
= oslTranslateFileError( GetLastError() );
1101 if ( strSysFilePath
)
1102 rtl_uString_release( strSysFilePath
);
1107 oslFileError SAL_CALL
osl_acquireDirectoryItem( oslDirectoryItem Item
)
1109 DirectoryItem_Impl
*pItemImpl
= static_cast<DirectoryItem_Impl
*>(Item
);
1112 return osl_File_E_INVAL
;
1114 pItemImpl
->nRefCount
++;
1115 return osl_File_E_None
;
1118 oslFileError SAL_CALL
osl_releaseDirectoryItem( oslDirectoryItem Item
)
1120 DirectoryItem_Impl
*pItemImpl
= static_cast<DirectoryItem_Impl
*>(Item
);
1123 return osl_File_E_INVAL
;
1125 if ( ! --pItemImpl
->nRefCount
)
1127 if ( pItemImpl
->m_pFullPath
)
1129 rtl_uString_release( pItemImpl
->m_pFullPath
);
1130 pItemImpl
->m_pFullPath
= nullptr;
1136 return osl_File_E_None
;
1140 SAL_CALL
osl_identicalDirectoryItem( oslDirectoryItem a
, oslDirectoryItem b
)
1142 DirectoryItem_Impl
*pA
= static_cast<DirectoryItem_Impl
*>(a
);
1143 DirectoryItem_Impl
*pB
= static_cast<DirectoryItem_Impl
*>(b
);
1146 /* same name => same item, unless renaming / moving madness has occurred */
1147 if (pA
->m_pFullPath
== pB
->m_pFullPath
)
1150 // FIXME: as/when/if this is used in anger on Windows we could
1156 static bool is_floppy_A_present()
1157 { return (GetLogicalDrives() & 1); }
1159 static bool is_floppy_B_present()
1160 { return (GetLogicalDrives() & 2); }
1162 static bool is_floppy_volume_mount_point(const OUString
& path
)
1164 // determines if a volume mount point shows to a floppy
1165 // disk by comparing the unique volume names
1166 static const LPCWSTR FLOPPY_A
= L
"A:\\";
1167 static const LPCWSTR FLOPPY_B
= L
"B:\\";
1170 osl::systemPathEnsureSeparator(p
);
1173 if (GetVolumeNameForVolumeMountPointW(o3tl::toW(p
.getStr()), vn
, SAL_N_ELEMENTS(vn
)))
1176 if (is_floppy_A_present() &&
1177 GetVolumeNameForVolumeMountPointW(FLOPPY_A
, vnfloppy
, SAL_N_ELEMENTS(vnfloppy
)) &&
1178 (0 == wcscmp(vn
, vnfloppy
)))
1181 if (is_floppy_B_present() &&
1182 GetVolumeNameForVolumeMountPointW(FLOPPY_B
, vnfloppy
, SAL_N_ELEMENTS(vnfloppy
)) &&
1183 (0 == wcscmp(vn
, vnfloppy
)))
1189 static bool is_floppy_drive(const OUString
& path
)
1191 static const LPCWSTR FLOPPY_DRV_LETTERS
= L
"AaBb";
1193 // we must take into account that even a floppy
1194 // drive may be mounted to a directory so checking
1195 // for the drive letter alone is not sufficient
1196 // we must compare the unique volume name with
1197 // that of the available floppy disks
1199 const sal_Unicode
* pszPath
= path
.getStr();
1200 return ((wcschr(FLOPPY_DRV_LETTERS
, pszPath
[0]) && (L
':' == pszPath
[1])) || is_floppy_volume_mount_point(path
));
1203 static bool is_volume_mount_point(const OUString
& path
)
1206 osl::systemPathRemoveSeparator(p
);
1208 bool is_volume_root
= false;
1210 if (!is_floppy_drive(p
))
1212 DWORD fattr
= GetFileAttributesW(o3tl::toW(p
.getStr()));
1214 if ((INVALID_FILE_ATTRIBUTES
!= fattr
) &&
1215 (FILE_ATTRIBUTE_REPARSE_POINT
& fattr
))
1217 WIN32_FIND_DATAW find_data
;
1218 HANDLE h_find
= FindFirstFileW(o3tl::toW(p
.getStr()), &find_data
);
1220 if (IsValidHandle(h_find
) &&
1221 (FILE_ATTRIBUTE_REPARSE_POINT
& find_data
.dwFileAttributes
) &&
1222 (IO_REPARSE_TAG_MOUNT_POINT
== find_data
.dwReserved0
))
1224 is_volume_root
= true;
1226 if (IsValidHandle(h_find
))
1230 return is_volume_root
;
1233 static UINT
get_volume_mount_point_drive_type(const OUString
& path
)
1235 if (0 == path
.getLength())
1236 return GetDriveTypeW(nullptr);
1239 osl::systemPathEnsureSeparator(p
);
1242 if (GetVolumeNameForVolumeMountPointW(o3tl::toW(p
.getStr()), vn
, SAL_N_ELEMENTS(vn
)))
1243 return GetDriveTypeW(vn
);
1245 return DRIVE_NO_ROOT_DIR
;
1248 static bool is_drivetype_request(sal_uInt32 field_mask
)
1250 return (field_mask
& osl_VolumeInfo_Mask_Attributes
);
1253 static oslFileError
osl_get_drive_type(
1254 const OUString
& path
, oslVolumeInfo
* pInfo
)
1256 // GetDriveType fails on empty volume mount points
1257 // see Knowledge Base Q244089
1259 if (is_volume_mount_point(path
))
1260 drive_type
= get_volume_mount_point_drive_type(path
);
1262 drive_type
= GetDriveTypeW(o3tl::toW(path
.getStr()));
1264 if (DRIVE_NO_ROOT_DIR
== drive_type
)
1265 return oslTranslateFileError(ERROR_INVALID_DRIVE
);
1267 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_Attributes
;
1272 pInfo
->uAttributes
|= osl_Volume_Attribute_CompactDisc
| osl_Volume_Attribute_Removeable
;
1274 case DRIVE_REMOVABLE
:
1275 pInfo
->uAttributes
|= osl_Volume_Attribute_Removeable
;
1276 if (is_floppy_drive(path
))
1277 pInfo
->uAttributes
|= osl_Volume_Attribute_FloppyDisk
;
1280 pInfo
->uAttributes
|= osl_Volume_Attribute_FixedDisk
;
1283 pInfo
->uAttributes
|= osl_Volume_Attribute_RAMDisk
;
1286 pInfo
->uAttributes
|= osl_Volume_Attribute_Remote
;
1289 pInfo
->uAttributes
= 0;
1292 pInfo
->uValidFields
&= ~osl_VolumeInfo_Mask_Attributes
;
1293 pInfo
->uAttributes
= 0;
1296 return osl_File_E_None
;
1299 static bool is_volume_space_info_request(sal_uInt32 field_mask
)
1301 return (field_mask
&
1302 (osl_VolumeInfo_Mask_TotalSpace
|
1303 osl_VolumeInfo_Mask_UsedSpace
|
1304 osl_VolumeInfo_Mask_FreeSpace
));
1307 static void get_volume_space_information(
1308 const OUString
& path
, oslVolumeInfo
*pInfo
)
1310 BOOL ret
= GetDiskFreeSpaceExW(
1311 o3tl::toW(path
.getStr()),
1312 reinterpret_cast<PULARGE_INTEGER
>(&pInfo
->uFreeSpace
),
1313 reinterpret_cast<PULARGE_INTEGER
>(&pInfo
->uTotalSpace
),
1318 pInfo
->uUsedSpace
= pInfo
->uTotalSpace
- pInfo
->uFreeSpace
;
1319 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_TotalSpace
|
1320 osl_VolumeInfo_Mask_UsedSpace
|
1321 osl_VolumeInfo_Mask_FreeSpace
;
1325 static bool is_filesystem_attributes_request(sal_uInt32 field_mask
)
1327 return (field_mask
&
1328 (osl_VolumeInfo_Mask_MaxNameLength
|
1329 osl_VolumeInfo_Mask_MaxPathLength
|
1330 osl_VolumeInfo_Mask_FileSystemName
|
1331 osl_VolumeInfo_Mask_FileSystemCaseHandling
));
1334 static oslFileError
get_filesystem_attributes(
1335 const OUString
& path
, sal_uInt32 field_mask
, oslVolumeInfo
* pInfo
)
1337 pInfo
->uAttributes
= 0;
1339 // osl_get_drive_type must be called first because
1340 // this function resets osl_VolumeInfo_Mask_Attributes
1342 if (is_drivetype_request(field_mask
))
1344 oslFileError osl_error
= osl_get_drive_type(path
, pInfo
);
1345 if (osl_File_E_None
!= osl_error
)
1348 if (is_filesystem_attributes_request(field_mask
))
1350 /* the following two parameters can not be longer than MAX_PATH+1 */
1351 WCHAR vn
[MAX_PATH
+1];
1352 WCHAR fsn
[MAX_PATH
+1];
1358 LPCWSTR pszPath
= o3tl::toW(path
.getStr());
1359 if (GetVolumeInformationW(pszPath
, vn
, MAX_PATH
+1, &serial
, &mcl
, &flags
, fsn
, MAX_PATH
+1))
1361 // Currently sal does not use this value, instead MAX_PATH is used
1362 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_MaxNameLength
;
1363 pInfo
->uMaxNameLength
= mcl
;
1365 // Should the uMaxPathLength be set to 32767, "\\?\" prefix allowes it
1366 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_MaxPathLength
;
1367 pInfo
->uMaxPathLength
= MAX_PATH
;
1369 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_FileSystemName
;
1370 rtl_uString_newFromStr(&pInfo
->ustrFileSystemName
, o3tl::toU(fsn
));
1372 // volumes (even NTFS) will always be considered case
1373 // insensitive because the Win32 API is not able to
1374 // deal with case sensitive volumes see M$ Knowledge Base
1375 // article 100625 that's why we never set the attribute
1376 // osl_Volume_Attribute_Case_Sensitive
1378 if (flags
& FS_CASE_IS_PRESERVED
)
1379 pInfo
->uAttributes
|= osl_Volume_Attribute_Case_Is_Preserved
;
1381 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_Attributes
;
1384 return osl_File_E_None
;
1387 static bool path_get_parent(OUString
& path
)
1389 OSL_PRECOND(path
.lastIndexOf(SLASH
) == -1, "Path must not have slashes");
1391 if (!has_path_parent(path
))
1393 sal_Int32 i
= path
.lastIndexOf(BACKSLASH
);
1396 path
= OUString(path
.getStr(), i
);
1403 static void path_travel_to_volume_root(const OUString
& system_path
, OUString
& volume_root
)
1405 OUString
sys_path(system_path
);
1407 while(!is_volume_mount_point(sys_path
) && path_get_parent(sys_path
))
1410 volume_root
= sys_path
;
1411 osl::systemPathEnsureSeparator(volume_root
);
1414 oslFileError SAL_CALL
osl_getVolumeInformation(
1415 rtl_uString
*ustrURL
, oslVolumeInfo
*pInfo
, sal_uInt32 uFieldMask
)
1418 return osl_File_E_INVAL
;
1420 OUString system_path
;
1421 oslFileError error
= osl_getSystemPathFromFileURL_(ustrURL
, &system_path
.pData
, false);
1423 if (osl_File_E_None
!= error
)
1426 OUString volume_root
;
1427 path_travel_to_volume_root(system_path
, volume_root
);
1429 pInfo
->uValidFields
= 0;
1431 if ((error
= get_filesystem_attributes(volume_root
, uFieldMask
, pInfo
)) != osl_File_E_None
)
1434 if (is_volume_space_info_request(uFieldMask
))
1435 get_volume_space_information(volume_root
, pInfo
);
1437 if (uFieldMask
& osl_VolumeInfo_Mask_DeviceHandle
)
1439 error
= osl_getFileURLFromSystemPath(volume_root
.pData
, reinterpret_cast<rtl_uString
**>(&pInfo
->pDeviceHandle
));
1440 if (error
!= osl_File_E_None
)
1442 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_DeviceHandle
;
1445 return osl_File_E_None
;
1448 static oslFileError
osl_getDriveInfo(
1449 oslDirectoryItem Item
, oslFileStatus
*pStatus
, sal_uInt32 uFieldMask
)
1451 DirectoryItem_Impl
*pItemImpl
= static_cast<DirectoryItem_Impl
*>(Item
);
1452 WCHAR cDrive
[3] = L
"A:";
1453 WCHAR cRoot
[4] = L
"A:\\";
1456 return osl_File_E_INVAL
;
1458 pStatus
->uValidFields
= 0;
1460 cDrive
[0] = pItemImpl
->cDriveString
[0];
1461 cRoot
[0] = pItemImpl
->cDriveString
[0];
1463 if ( uFieldMask
& osl_FileStatus_Mask_FileName
)
1465 if ( pItemImpl
->cDriveString
[0] == '\\' && pItemImpl
->cDriveString
[1] == '\\' )
1467 LPCWSTR lpFirstBkSlash
= wcschr( &pItemImpl
->cDriveString
[2], '\\' );
1469 if ( lpFirstBkSlash
&& lpFirstBkSlash
[1] )
1471 LPCWSTR lpLastBkSlash
= wcschr( &lpFirstBkSlash
[1], '\\' );
1473 if ( lpLastBkSlash
)
1474 rtl_uString_newFromStr_WithLength( &pStatus
->ustrFileName
, o3tl::toU(&lpFirstBkSlash
[1]), lpLastBkSlash
- lpFirstBkSlash
- 1 );
1476 rtl_uString_newFromStr( &pStatus
->ustrFileName
, o3tl::toU(&lpFirstBkSlash
[1]) );
1477 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1480 else switch ( GetDriveTypeW( cRoot
) )
1484 WCHAR szBuffer
[1024];
1485 DWORD
const dwBufsizeConst
= SAL_N_ELEMENTS(szBuffer
);
1486 DWORD dwBufsize
= dwBufsizeConst
;
1488 DWORD dwResult
= WNetGetConnectionW( cDrive
, szBuffer
, &dwBufsize
);
1489 if ( NO_ERROR
== dwResult
)
1491 WCHAR szFileName
[dwBufsizeConst
+ 16];
1493 swprintf( szFileName
, L
"%s [%s]", cDrive
, szBuffer
);
1494 rtl_uString_newFromStr( &pStatus
->ustrFileName
, o3tl::toU(szFileName
) );
1497 rtl_uString_newFromStr( &pStatus
->ustrFileName
, o3tl::toU(cDrive
) );
1499 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1503 WCHAR szVolumeNameBuffer
[1024];
1504 DWORD
const dwBufsizeConst
= SAL_N_ELEMENTS(szVolumeNameBuffer
);
1506 if ( GetVolumeInformationW( cRoot
, szVolumeNameBuffer
, dwBufsizeConst
, nullptr, nullptr, nullptr, nullptr, 0 ) )
1508 WCHAR szFileName
[dwBufsizeConst
+ 16];
1510 swprintf( szFileName
, L
"%s [%s]", cDrive
, szVolumeNameBuffer
);
1511 rtl_uString_newFromStr( &pStatus
->ustrFileName
, o3tl::toU(szFileName
) );
1514 rtl_uString_newFromStr( &pStatus
->ustrFileName
, o3tl::toU(cDrive
) );
1516 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1519 case DRIVE_REMOVABLE
:
1520 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1521 rtl_uString_newFromStr( &pStatus
->ustrFileName
, o3tl::toU(cRoot
) );
1529 pStatus
->eType
= osl_File_Type_Volume
;
1530 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1532 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1534 rtl_uString
*ustrSystemPath
= nullptr;
1536 rtl_uString_newFromStr( &ustrSystemPath
, o3tl::toU(pItemImpl
->cDriveString
) );
1537 oslFileError error
= osl_getFileURLFromSystemPath( ustrSystemPath
, &pStatus
->ustrFileURL
);
1538 rtl_uString_release( ustrSystemPath
);
1539 if (error
!= osl_File_E_None
)
1541 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1543 return osl_File_E_None
;
1546 static oslFileError
osl_getServerInfo(
1547 oslDirectoryItem Item
, oslFileStatus
*pStatus
, sal_uInt32 uFieldMask
)
1549 DirectoryItem_Impl
*pItemImpl
= static_cast<DirectoryItem_Impl
*>(Item
);
1551 return osl_File_E_INVAL
;
1553 pStatus
->uValidFields
= 0;
1554 pStatus
->eType
= osl_File_Type_Directory
;
1555 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1557 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1559 oslFileError error
= osl_getFileURLFromSystemPath( pItemImpl
->m_pFullPath
, &pStatus
->ustrFileURL
);
1560 if (error
!= osl_File_E_None
)
1562 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1564 return osl_File_E_None
;
1567 oslFileError SAL_CALL
osl_getFileStatus(
1568 oslDirectoryItem Item
,
1569 oslFileStatus
*pStatus
,
1570 sal_uInt32 uFieldMask
)
1572 DirectoryItem_Impl
*pItemImpl
= static_cast<DirectoryItem_Impl
*>(Item
);
1575 return osl_File_E_INVAL
;
1577 switch ( pItemImpl
->uType
)
1579 case DIRECTORYITEM_DRIVE
:
1580 return osl_getDriveInfo( Item
, pStatus
, uFieldMask
);
1581 case DIRECTORYITEM_SERVER
:
1582 return osl_getServerInfo( Item
, pStatus
, uFieldMask
);
1587 OUString
sFullPath(pItemImpl
->m_pFullPath
);
1589 // Prefix long paths, windows API calls expect this prefix
1590 // (only local paths starting with something like C: or D:)
1591 if (sFullPath
.getLength() >= MAX_PATH
&& isalpha(sFullPath
[0]) && sFullPath
[1] == ':')
1592 sFullPath
= "\\\\?\\" + sFullPath
;
1594 if ( uFieldMask
& osl_FileStatus_Mask_Validate
)
1596 HANDLE hFind
= FindFirstFileW( o3tl::toW(sFullPath
.getStr() ), &pItemImpl
->FindData
);
1598 if ( hFind
!= INVALID_HANDLE_VALUE
)
1601 return oslTranslateFileError( GetLastError() );
1603 uFieldMask
&= ~ osl_FileStatus_Mask_Validate
;
1606 /* If no fields to retrieve left ignore pStatus */
1608 return osl_File_E_None
;
1610 /* Otherwise, this must be a valid pointer */
1612 return osl_File_E_INVAL
;
1614 if ( pStatus
->uStructSize
!= sizeof(oslFileStatus
) )
1615 return osl_File_E_INVAL
;
1617 pStatus
->uValidFields
= 0;
1619 /* File time stamps */
1621 if ( (uFieldMask
& osl_FileStatus_Mask_ModifyTime
) &&
1622 FileTimeToTimeValue( &pItemImpl
->FindData
.ftLastWriteTime
, &pStatus
->aModifyTime
) )
1623 pStatus
->uValidFields
|= osl_FileStatus_Mask_ModifyTime
;
1625 if ( (uFieldMask
& osl_FileStatus_Mask_AccessTime
) &&
1626 FileTimeToTimeValue( &pItemImpl
->FindData
.ftLastAccessTime
, &pStatus
->aAccessTime
) )
1627 pStatus
->uValidFields
|= osl_FileStatus_Mask_AccessTime
;
1629 if ( (uFieldMask
& osl_FileStatus_Mask_CreationTime
) &&
1630 FileTimeToTimeValue( &pItemImpl
->FindData
.ftCreationTime
, &pStatus
->aCreationTime
) )
1631 pStatus
->uValidFields
|= osl_FileStatus_Mask_CreationTime
;
1633 /* Most of the fields are already set, regardless of required fields */
1635 rtl_uString_newFromStr( &pStatus
->ustrFileName
, o3tl::toU(pItemImpl
->FindData
.cFileName
) );
1636 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1638 if ((FILE_ATTRIBUTE_REPARSE_POINT
& pItemImpl
->FindData
.dwFileAttributes
) &&
1639 (IO_REPARSE_TAG_MOUNT_POINT
== pItemImpl
->FindData
.dwReserved0
))
1640 pStatus
->eType
= osl_File_Type_Volume
;
1641 else if (pItemImpl
->FindData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1642 pStatus
->eType
= osl_File_Type_Directory
;
1644 pStatus
->eType
= osl_File_Type_Regular
;
1646 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1648 pStatus
->uAttributes
= pItemImpl
->FindData
.dwFileAttributes
;
1649 pStatus
->uValidFields
|= osl_FileStatus_Mask_Attributes
;
1651 pStatus
->uFileSize
= static_cast<sal_uInt64
>(pItemImpl
->FindData
.nFileSizeLow
) + (static_cast<sal_uInt64
>(pItemImpl
->FindData
.nFileSizeHigh
) << 32);
1652 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileSize
;
1654 if ( uFieldMask
& osl_FileStatus_Mask_LinkTargetURL
)
1656 oslFileError error
= osl_getFileURLFromSystemPath( sFullPath
.pData
, &pStatus
->ustrLinkTargetURL
);
1657 if (error
!= osl_File_E_None
)
1660 pStatus
->uValidFields
|= osl_FileStatus_Mask_LinkTargetURL
;
1663 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1665 if ( !pItemImpl
->bFullPathNormalized
)
1667 ::osl::LongPathBuffer
< sal_Unicode
> aBuffer( MAX_LONG_PATH
);
1668 sal_uInt32 nNewLen
= GetCaseCorrectPathName( o3tl::toW( sFullPath
.getStr() ),
1669 o3tl::toW( aBuffer
),
1670 aBuffer
.getBufSizeInSymbols(),
1675 rtl_uString_newFromStr( &pItemImpl
->m_pFullPath
, aBuffer
);
1676 sFullPath
= OUString( pItemImpl
->m_pFullPath
);
1677 pItemImpl
->bFullPathNormalized
= TRUE
;
1681 oslFileError error
= osl_getFileURLFromSystemPath( sFullPath
.pData
, &pStatus
->ustrFileURL
);
1682 if (error
!= osl_File_E_None
)
1684 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1687 return osl_File_E_None
;
1690 oslFileError SAL_CALL
osl_setFileAttributes(
1691 rtl_uString
*ustrFileURL
,
1692 sal_uInt64 uAttributes
)
1695 rtl_uString
*ustrSysPath
= nullptr;
1696 DWORD dwFileAttributes
;
1699 // Converts the normalized path into a systempath
1700 error
= osl_getSystemPathFromFileURL_( ustrFileURL
, &ustrSysPath
, false );
1702 if ( osl_File_E_None
!= error
)
1705 dwFileAttributes
= GetFileAttributesW( o3tl::toW(rtl_uString_getStr(ustrSysPath
)) );
1707 if ( DWORD(-1) != dwFileAttributes
)
1709 dwFileAttributes
&= ~(FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
);
1711 if ( uAttributes
& osl_File_Attribute_ReadOnly
)
1712 dwFileAttributes
|= FILE_ATTRIBUTE_READONLY
;
1714 if ( uAttributes
& osl_File_Attribute_Hidden
)
1715 dwFileAttributes
|= FILE_ATTRIBUTE_HIDDEN
;
1717 fSuccess
= SetFileAttributesW( o3tl::toW(rtl_uString_getStr(ustrSysPath
)), dwFileAttributes
);
1725 error
= oslTranslateFileError( GetLastError() );
1727 rtl_uString_release( ustrSysPath
);
1732 oslFileError SAL_CALL
osl_setFileTime(
1733 rtl_uString
*filePath
,
1734 const TimeValue
*aCreationTime
,
1735 const TimeValue
*aLastAccessTime
,
1736 const TimeValue
*aLastWriteTime
)
1739 rtl_uString
*sysPath
=nullptr;
1740 FILETIME
*lpCreationTime
=nullptr;
1741 FILETIME
*lpLastAccessTime
=nullptr;
1742 FILETIME
*lpLastWriteTime
=nullptr;
1743 FILETIME ftCreationTime
;
1744 FILETIME ftLastAccessTime
;
1745 FILETIME ftLastWriteTime
;
1749 error
=osl_getSystemPathFromFileURL_(filePath
, &sysPath
, false);
1751 if (error
==osl_File_E_INVAL
)
1754 hFile
=CreateFileW(o3tl::toW(rtl_uString_getStr(sysPath
)), GENERIC_WRITE
, 0, nullptr , OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, nullptr);
1755 rtl_uString_release(sysPath
);
1757 if (hFile
==INVALID_HANDLE_VALUE
)
1758 return osl_File_E_NOENT
;
1760 if (TimeValueToFileTime(aCreationTime
, &ftCreationTime
))
1761 lpCreationTime
=&ftCreationTime
;
1763 if (TimeValueToFileTime(aLastAccessTime
, &ftLastAccessTime
))
1764 lpLastAccessTime
=&ftLastAccessTime
;
1766 if (TimeValueToFileTime(aLastWriteTime
, &ftLastWriteTime
))
1767 lpLastWriteTime
=&ftLastWriteTime
;
1769 fSuccess
=SetFileTime(hFile
, lpCreationTime
, lpLastAccessTime
, lpLastWriteTime
);
1774 return osl_File_E_INVAL
;
1776 return osl_File_E_None
;
1779 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */