1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: file.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
33 #define _WIN32_WINNT_0x0500
34 #include "systools/win32/uwinapi.h"
39 #include "file_error.h"
40 #include "path_helper.hxx"
42 #include "osl/diagnose.h"
44 #include "rtl/alloc.h"
45 #include "rtl/ustring.hxx"
52 //#####################################################
53 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
55 static const wchar_t UNC_PREFIX
[] = L
"\\\\";
56 static const wchar_t BACKSLASH
= '\\';
57 static const wchar_t SLASH
= '/';
59 //#####################################################
60 extern "C" BOOL
TimeValueToFileTime(const TimeValue
*cpTimeVal
, FILETIME
*pFTime
)
62 SYSTEMTIME BaseSysTime
;
63 FILETIME BaseFileTime
;
66 BOOL fSuccess
= FALSE
;
68 BaseSysTime
.wYear
= 1970;
69 BaseSysTime
.wMonth
= 1;
70 BaseSysTime
.wDayOfWeek
= 0;
72 BaseSysTime
.wHour
= 0;
73 BaseSysTime
.wMinute
= 0;
74 BaseSysTime
.wSecond
= 0;
75 BaseSysTime
.wMilliseconds
= 0;
80 if ( SystemTimeToFileTime(&BaseSysTime
, &BaseFileTime
) )
83 localTime
=cpTimeVal
->Seconds
*(__int64
)10000000+cpTimeVal
->Nanosec
/100;
84 *(__int64
*)&FTime
=localTime
;
85 fSuccess
= 0 <= (timeValue
= *((__int64
*)&BaseFileTime
) + *((__int64
*) &FTime
));
87 *(__int64
*)pFTime
=timeValue
;
92 //#####################################################
93 extern "C" BOOL
FileTimeToTimeValue(const FILETIME
*cpFTime
, TimeValue
*pTimeVal
)
95 SYSTEMTIME BaseSysTime
;
96 FILETIME BaseFileTime
;
97 BOOL fSuccess
= FALSE
; /* Assume failure */
99 BaseSysTime
.wYear
= 1970;
100 BaseSysTime
.wMonth
= 1;
101 BaseSysTime
.wDayOfWeek
= 0;
102 BaseSysTime
.wDay
= 1;
103 BaseSysTime
.wHour
= 0;
104 BaseSysTime
.wMinute
= 0;
105 BaseSysTime
.wSecond
= 0;
106 BaseSysTime
.wMilliseconds
= 0;
108 if ( SystemTimeToFileTime(&BaseSysTime
, &BaseFileTime
) )
112 fSuccess
= 0 <= (Value
= *((__int64
*)cpFTime
) - *((__int64
*)&BaseFileTime
));
116 pTimeVal
->Seconds
= (unsigned long) (Value
/ 10000000L);
117 pTimeVal
->Nanosec
= (unsigned long)((Value
% 10000000L) * 100);
123 //#####################################################
124 namespace /* private */
126 //#####################################################
133 bool isPresent() const
134 { return (static_cast<sal_IntPtr
>(end_
- begin_
) > 0); }
136 const sal_Unicode
* begin_
;
137 const sal_Unicode
* end_
;
140 //#####################################################
148 //#####################################################
149 inline bool is_UNC_path(const sal_Unicode
* path
)
150 { return (0 == wcsncmp(UNC_PREFIX
, reinterpret_cast<LPCWSTR
>(path
), ELEMENTS_OF_ARRAY(UNC_PREFIX
) - 1)); }
152 //#####################################################
153 inline bool is_UNC_path(const rtl::OUString
& path
)
154 { return is_UNC_path(path
.getStr()); }
156 //#####################################################
157 void parse_UNC_path(const sal_Unicode
* path
, UNCComponents
* puncc
)
159 OSL_PRECOND(is_UNC_path(path
), "Precondition violated: No UNC path");
160 OSL_PRECOND(rtl_ustr_indexOfChar(path
, SLASH
) != -1, "Path must not contain slashes");
162 const sal_Unicode
* pend
= path
+ rtl_ustr_getLength(path
);
163 const sal_Unicode
* ppos
= path
+ 2;
165 puncc
->server_
.begin_
= ppos
;
166 while ((ppos
< pend
) && (*ppos
!= BACKSLASH
))
169 puncc
->server_
.end_
= ppos
;
171 if (BACKSLASH
== *ppos
)
173 puncc
->share_
.begin_
= ++ppos
;
174 while ((ppos
< pend
) && (*ppos
!= BACKSLASH
))
177 puncc
->share_
.end_
= ppos
;
179 if (BACKSLASH
== *ppos
)
181 puncc
->resource_
.begin_
= ++ppos
;
185 puncc
->resource_
.end_
= ppos
;
189 OSL_POSTCOND(puncc
->server_
.isPresent() && puncc
->share_
.isPresent(), \
190 "Postcondition violated: Invalid UNC path detected");
193 //#####################################################
194 void parse_UNC_path(const rtl::OUString
& path
, UNCComponents
* puncc
)
195 { parse_UNC_path(path
.getStr(), puncc
); }
198 //#####################################################
199 bool has_path_parent(const sal_Unicode
* path
)
201 // Has the given path a parent or are we already there,
202 // e.g. 'c:\' or '\\server\share\'?
204 bool has_parent
= false;
205 if (is_UNC_path(path
))
207 UNCComponents unc_comp
;
208 parse_UNC_path(path
, &unc_comp
);
209 has_parent
= unc_comp
.resource_
.isPresent();
213 has_parent
= !osl::systemPathIsLogicalDrivePattern(path
);
218 //#####################################################
219 inline bool has_path_parent(const rtl::OUString
& path
)
220 { return has_path_parent(path
.getStr()); }
222 } // end namespace private
224 //#####################################################
225 // volume handling functions
226 //#####################################################
228 //#####################################################
229 oslFileError SAL_CALL
osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle
)
232 return osl_File_E_None
;
234 return osl_File_E_INVAL
;
237 //#####################################################
238 oslFileError SAL_CALL
osl_automountVolumeDevice( oslVolumeDeviceHandle Handle
)
241 return osl_File_E_None
;
243 return osl_File_E_INVAL
;
246 //#####################################################
247 oslFileError SAL_CALL
osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle
)
251 rtl_uString_acquire( (rtl_uString
*)Handle
);
252 return osl_File_E_None
;
255 return osl_File_E_INVAL
;
258 //#####################################################
259 oslFileError SAL_CALL
osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle
)
263 rtl_uString_release( (rtl_uString
*)Handle
);
264 return osl_File_E_None
;
267 return osl_File_E_INVAL
;
270 //#####################################################
271 oslFileError SAL_CALL
osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle
, rtl_uString
**pstrPath
)
273 if ( Handle
&& pstrPath
)
275 rtl_uString_assign( pstrPath
, (rtl_uString
*)Handle
);
276 return osl_File_E_None
;
279 return osl_File_E_INVAL
;
282 //##################################################################
283 // directory handling functions
284 //##################################################################
286 #define DIRECTORYITEM_DRIVE 0
287 #define DIRECTORYITEM_FILE 1
288 #define DIRECTORYITEM_SERVER 2
290 struct DirectoryItem_Impl
294 WIN32_FIND_DATA FindData
;
295 TCHAR cDriveString
[MAX_PATH
];
297 TCHAR szFullPath
[MAX_PATH
];
298 BOOL bFullPathNormalized
;
302 //#####################################################
304 #define DIRECTORYTYPE_LOCALROOT 0
305 #define DIRECTORYTYPE_NETROOT 1
306 #define DIRECTORYTYPE_NETRESORCE 2
307 #define DIRECTORYTYPE_FILESYSTEM 3
309 struct Directory_Impl
316 TCHAR szDirectoryPath
[MAX_PATH
];
319 //#####################################################
321 typedef struct tagDRIVEENUM
324 TCHAR cBuffer
[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
326 } DRIVEENUM
, * PDRIVEENUM
, FAR
* LPDRIVEENUM
;
328 //#####################################################
330 static HANDLE WINAPI
OpenLogicalDrivesEnum(void)
332 LPDRIVEENUM pEnum
= (LPDRIVEENUM
)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM
) );
335 DWORD dwNumCopied
= GetLogicalDriveStrings( (sizeof(pEnum
->cBuffer
) - 1) / sizeof(TCHAR
), pEnum
->cBuffer
);
337 if ( dwNumCopied
&& dwNumCopied
< sizeof(pEnum
->cBuffer
) / sizeof(TCHAR
) )
339 pEnum
->lpCurrent
= pEnum
->cBuffer
;
340 pEnum
->lpIdent
= L
"tagDRIVEENUM";
344 HeapFree( GetProcessHeap(), 0, pEnum
);
348 return pEnum
? (HANDLE
)pEnum
: INVALID_HANDLE_VALUE
;
351 //#####################################################
352 static BOOL WINAPI
EnumLogicalDrives(HANDLE hEnum
, LPTSTR lpBuffer
)
354 BOOL fSuccess
= FALSE
;
355 LPDRIVEENUM pEnum
= (LPDRIVEENUM
)hEnum
;
359 int nLen
= _tcslen( pEnum
->lpCurrent
);
363 CopyMemory( lpBuffer
, pEnum
->lpCurrent
, (nLen
+ 1) * sizeof(TCHAR
) );
364 pEnum
->lpCurrent
+= nLen
+ 1;
368 SetLastError( ERROR_NO_MORE_FILES
);
371 SetLastError( ERROR_INVALID_HANDLE
);
376 //#####################################################
377 static BOOL WINAPI
CloseLogicalDrivesEnum(HANDLE hEnum
)
379 BOOL fSuccess
= FALSE
;
380 LPDRIVEENUM pEnum
= (LPDRIVEENUM
)hEnum
;
384 HeapFree( GetProcessHeap(), 0, pEnum
);
388 SetLastError( ERROR_INVALID_HANDLE
);
393 //#####################################################
394 typedef struct tagDIRECTORY
397 WIN32_FIND_DATA aFirstData
;
398 } DIRECTORY
, *PDIRECTORY
, FAR
*LPDIRECTORY
;
400 //#####################################################
401 static HANDLE WINAPI
OpenDirectory(LPCTSTR lpszPath
)
403 LPDIRECTORY pDirectory
= (LPDIRECTORY
)HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY
));
407 TCHAR szFileMask
[MAX_PATH
];
410 _tcscpy( szFileMask
, lpszPath
);
411 nLen
= _tcslen( szFileMask
);
413 if (nLen
&& szFileMask
[nLen
-1] != '\\')
414 _tcscat(szFileMask
, TEXT("\\*.*"));
416 _tcscat(szFileMask
, TEXT("*.*"));
418 pDirectory
->hFind
= FindFirstFile(szFileMask
, &pDirectory
->aFirstData
);
420 if (!IsValidHandle(pDirectory
->hFind
))
422 if ( GetLastError() != ERROR_NO_MORE_FILES
)
424 HeapFree(GetProcessHeap(), 0, pDirectory
);
429 return (HANDLE
)pDirectory
;
432 //#####################################################
433 BOOL WINAPI
EnumDirectory(HANDLE hDirectory
, LPWIN32_FIND_DATA pFindData
)
435 BOOL fSuccess
= FALSE
;
436 LPDIRECTORY pDirectory
= (LPDIRECTORY
)hDirectory
;
444 if ( pDirectory
->aFirstData
.cFileName
[0] )
446 *pFindData
= pDirectory
->aFirstData
;
448 pDirectory
->aFirstData
.cFileName
[0] = 0;
450 else if ( IsValidHandle( pDirectory
->hFind
) )
451 fSuccess
= FindNextFile( pDirectory
->hFind
, pFindData
);
455 SetLastError( ERROR_NO_MORE_FILES
);
458 fValid
= fSuccess
&& _tcscmp( TEXT("."), pFindData
->cFileName
) != 0 && _tcscmp( TEXT(".."), pFindData
->cFileName
) != 0;
460 } while( fSuccess
&& !fValid
);
463 SetLastError( ERROR_INVALID_HANDLE
);
468 //#####################################################
469 static BOOL WINAPI
CloseDirectory(HANDLE hDirectory
)
471 BOOL fSuccess
= FALSE
;
472 LPDIRECTORY pDirectory
= (LPDIRECTORY
)hDirectory
;
476 if (IsValidHandle(pDirectory
->hFind
))
477 fSuccess
= FindClose(pDirectory
->hFind
);
479 fSuccess
= HeapFree(GetProcessHeap(), 0, pDirectory
) && fSuccess
;
482 SetLastError(ERROR_INVALID_HANDLE
);
487 //#####################################################
488 static oslFileError
osl_openLocalRoot(
489 rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
491 rtl_uString
*strSysPath
= NULL
;
495 return osl_File_E_INVAL
;
499 error
= _osl_getSystemPathFromFileURL( strDirectoryPath
, &strSysPath
, sal_False
);
500 if ( osl_File_E_None
== error
)
502 Directory_Impl
*pDirImpl
;
504 pDirImpl
= reinterpret_cast<Directory_Impl
*>(rtl_allocateMemory( sizeof(Directory_Impl
)));
505 _tcscpy( pDirImpl
->szDirectoryPath
, reinterpret_cast<LPCTSTR
>(rtl_uString_getStr(strSysPath
)) );
507 /* Append backslash if neccessary */
510 use function ensure backslash
512 if ( pDirImpl
->szDirectoryPath
[_tcslen(pDirImpl
->szDirectoryPath
) - 1] != L
'\\' )
513 _tcscat( pDirImpl
->szDirectoryPath
, L
"\\" );
515 pDirImpl
->uType
= DIRECTORYTYPE_LOCALROOT
;
516 pDirImpl
->hEnumDrives
= OpenLogicalDrivesEnum();
519 Use IsValidHandle(...)
521 if ( pDirImpl
->hEnumDrives
!= INVALID_HANDLE_VALUE
)
523 *pDirectory
= (oslDirectory
)pDirImpl
;
524 error
= osl_File_E_None
;
529 rtl_freeMemory(pDirImpl
);
531 error
= oslTranslateFileError( GetLastError() );
534 rtl_uString_release( strSysPath
);
539 //#####################################################
540 static oslFileError SAL_CALL
osl_openFileDirectory(
541 rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
543 oslFileError error
= osl_File_E_None
;
546 return osl_File_E_INVAL
;
549 Directory_Impl
*pDirImpl
= reinterpret_cast<Directory_Impl
*>(rtl_allocateMemory(sizeof(Directory_Impl
)));
550 _tcscpy( pDirImpl
->szDirectoryPath
, reinterpret_cast<LPCTSTR
>(rtl_uString_getStr(strDirectoryPath
)) );
552 /* Append backslash if neccessary */
555 use function ensure backslash
557 if ( pDirImpl
->szDirectoryPath
[_tcslen(pDirImpl
->szDirectoryPath
) - 1] != L
'\\' )
558 _tcscat( pDirImpl
->szDirectoryPath
, L
"\\" );
560 pDirImpl
->uType
= DIRECTORYTYPE_FILESYSTEM
;
561 pDirImpl
->hDirectory
= OpenDirectory( pDirImpl
->szDirectoryPath
);
563 if ( !pDirImpl
->hDirectory
)
565 error
= oslTranslateFileError( GetLastError() );
567 rtl_freeMemory(pDirImpl
), pDirImpl
= 0;
570 *pDirectory
= (oslDirectory
)(pDirImpl
);
574 //#####################################################
575 static oslFileError SAL_CALL
osl_openNetworkServer(
576 rtl_uString
*strSysDirPath
, oslDirectory
*pDirectory
)
578 NETRESOURCEW aNetResource
;
582 ZeroMemory( &aNetResource
, sizeof(aNetResource
) );
584 aNetResource
.lpRemoteName
= reinterpret_cast<LPWSTR
>(strSysDirPath
->buffer
);
586 dwError
= WNetOpenEnumW(
589 RESOURCEUSAGE_CONNECTABLE
| RESOURCEUSAGE_CONTAINER
,
593 if ( ERROR_SUCCESS
== dwError
)
595 Directory_Impl
*pDirImpl
;
597 pDirImpl
= reinterpret_cast<Directory_Impl
*>(rtl_allocateMemory(sizeof(Directory_Impl
)));
598 pDirImpl
->uType
= DIRECTORYTYPE_NETROOT
;
599 pDirImpl
->hDirectory
= hEnum
;
600 *pDirectory
= (oslDirectory
)pDirImpl
;
602 return oslTranslateFileError( dwError
);
605 //#############################################
606 static DWORD
create_dir_with_callback(
607 rtl_uString
* dir_path
,
608 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
611 // Create the specified directory and call the
612 // user specified callback function. On success
613 // the function returns ERROR_SUCCESS else a Win32 error code.
615 if (CreateDirectory(reinterpret_cast<LPCTSTR
>(dir_path
->buffer
), NULL
))
617 if (aDirectoryCreationCallbackFunc
)
620 _osl_getFileURLFromSystemPath(dir_path
, &(url
.pData
));
621 aDirectoryCreationCallbackFunc(pData
, url
.pData
);
623 return ERROR_SUCCESS
;
625 return GetLastError();
628 //#############################################
629 static int path_make_parent(sal_Unicode
* path
)
631 /* Cut off the last part of the given path to
632 get the parent only, e.g. 'c:\dir\subdir' ->
633 'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
634 @return The position where the path has been cut
635 off (this is the posistion of the last backslash).
636 If there are no more parents 0 will be returned,
637 e.g. 'c:\' or '\\Share' have no more parents */
639 OSL_PRECOND(rtl_ustr_indexOfChar(path
, SLASH
) != -1, "Path must not contain slashes");
640 OSL_PRECOND(has_path_parent(path
), "Path must have a parent");
642 sal_Unicode
* pos_last_backslash
= path
+ rtl_ustr_lastIndexOfChar(path
, BACKSLASH
);
643 *pos_last_backslash
= 0;
644 return (pos_last_backslash
- path
);
647 //#############################################
648 static DWORD
create_dir_recursively_(
649 rtl_uString
* dir_path
,
650 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
654 rtl_ustr_lastIndexOfChar_WithLength(dir_path
->buffer
, dir_path
->length
, BACKSLASH
) != dir_path
->length
,
655 "Path must not end with a backslash");
657 DWORD w32_error
= create_dir_with_callback(
658 dir_path
, aDirectoryCreationCallbackFunc
, pData
);
659 if (w32_error
== ERROR_SUCCESS
)
660 return ERROR_SUCCESS
;
662 if ((w32_error
!= ERROR_PATH_NOT_FOUND
) || !has_path_parent(dir_path
->buffer
))
665 int pos
= path_make_parent(dir_path
->buffer
); // dir_path->buffer[pos] = 0, restore below
667 w32_error
= create_dir_recursively_(
668 dir_path
, aDirectoryCreationCallbackFunc
, pData
);
670 dir_path
->buffer
[pos
] = BACKSLASH
; // restore
672 if (ERROR_SUCCESS
!= w32_error
)
675 return create_dir_recursively_(dir_path
, aDirectoryCreationCallbackFunc
, pData
);
678 //#############################################
679 oslFileError SAL_CALL
osl_createDirectoryPath(
680 rtl_uString
* aDirectoryUrl
,
681 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc
,
684 if (aDirectoryUrl
== NULL
)
685 return osl_File_E_INVAL
;
687 rtl::OUString sys_path
;
688 oslFileError osl_error
=
689 _osl_getSystemPathFromFileURL(aDirectoryUrl
, &sys_path
.pData
, sal_False
);
691 if (osl_error
!= osl_File_E_None
)
694 osl::systemPathRemoveSeparator(sys_path
);
696 // const_cast because sys_path is a local copy
697 // which we want to modify inplace instead of
698 // coyp it into another buffer on the heap again
699 return oslTranslateFileError(create_dir_recursively_(
700 sys_path
.pData
, aDirectoryCreationCallbackFunc
, pData
));
703 //#####################################################
704 oslFileError SAL_CALL
osl_createDirectory(rtl_uString
* strPath
)
706 rtl_uString
*strSysPath
= NULL
;
707 oslFileError error
= _osl_getSystemPathFromFileURL( strPath
, &strSysPath
, sal_False
);
709 if ( osl_File_E_None
== error
)
711 if ( CreateDirectoryW( reinterpret_cast<LPCWSTR
>(rtl_uString_getStr( strSysPath
)), NULL
) )
712 error
= osl_File_E_None
;
714 The else case is a hack because the ucb or the webtop had some
715 problems with the error code that CreateDirectory returns in
716 case the path is only a logical drive, should be removed!
720 const sal_Unicode
*pBuffer
= rtl_uString_getStr( strSysPath
);
721 sal_Int32 nLen
= rtl_uString_getLength( strSysPath
);
724 ( ( pBuffer
[0] >= 'A' && pBuffer
[0] <= 'Z' ) ||
725 ( pBuffer
[0] >= 'a' && pBuffer
[0] <= 'z' ) ) &&
726 pBuffer
[1] == ':' && ( nLen
==2 || ( nLen
== 3 && pBuffer
[2] == '\\' ) )
728 SetLastError( ERROR_ALREADY_EXISTS
);
730 error
= oslTranslateFileError( GetLastError() );
733 rtl_uString_release( strSysPath
);
738 //#####################################################
739 oslFileError SAL_CALL
osl_removeDirectory(rtl_uString
* strPath
)
741 rtl_uString
*strSysPath
= NULL
;
742 oslFileError error
= _osl_getSystemPathFromFileURL( strPath
, &strSysPath
, sal_False
);
744 if ( osl_File_E_None
== error
)
746 if ( RemoveDirectory( reinterpret_cast<LPCTSTR
>(rtl_uString_getStr( strSysPath
)) ) )
747 error
= osl_File_E_None
;
749 error
= oslTranslateFileError( GetLastError() );
751 rtl_uString_release( strSysPath
);
756 //#####################################################
757 oslFileError SAL_CALL
osl_openDirectory(rtl_uString
*strDirectoryPath
, oslDirectory
*pDirectory
)
761 if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath
->buffer
, "file:///" ) )
762 error
= osl_openLocalRoot( strDirectoryPath
, pDirectory
);
765 rtl_uString
*strSysDirectoryPath
= NULL
;
768 error
= _osl_getSystemPathFromFileURL( strDirectoryPath
, &strSysDirectoryPath
, sal_False
);
770 if ( osl_File_E_None
!= error
)
773 dwPathType
= IsValidFilePath( strSysDirectoryPath
, NULL
, VALIDATEPATH_NORMAL
, NULL
);
775 if ( dwPathType
& PATHTYPE_IS_SERVER
)
777 error
= osl_openNetworkServer( strSysDirectoryPath
, pDirectory
);
780 error
= osl_openFileDirectory( strSysDirectoryPath
, pDirectory
);
782 rtl_uString_release( strSysDirectoryPath
);
787 //#####################################################
788 static oslFileError SAL_CALL
osl_getNextNetResource(
789 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32 uHint
)
791 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
792 DirectoryItem_Impl
*pItemImpl
= NULL
;
794 LPNETRESOURCEW lpNetResource
= (LPNETRESOURCEW
)buffer
;
795 DWORD dwError
, dwCount
, dwBufSize
;
797 uHint
= uHint
; /* to get no warning */
800 return osl_File_E_INVAL
;
804 return osl_File_E_INVAL
;
807 dwBufSize
= sizeof(buffer
);
808 dwError
= WNetEnumResource( pDirImpl
->hDirectory
, &dwCount
, lpNetResource
, &dwBufSize
);
813 case ERROR_MORE_DATA
:
815 pItemImpl
= reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
817 return osl_File_E_NOMEM
;
819 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
820 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
821 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
823 wcscpy( pItemImpl
->cDriveString
, lpNetResource
->lpRemoteName
);
827 return osl_File_E_None
;
828 case ERROR_NO_MORE_ITEMS
:
829 return osl_File_E_NOENT
;
831 return oslTranslateFileError( dwError
);
835 //#####################################################
836 static oslFileError SAL_CALL
osl_getNextDrive(
837 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32 uHint
)
839 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
840 DirectoryItem_Impl
*pItemImpl
= NULL
;
843 uHint
= uHint
; /* avoid warnings */
846 return osl_File_E_INVAL
;
850 return osl_File_E_INVAL
;
852 pItemImpl
= reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
854 return osl_File_E_NOMEM
;
856 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
857 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
858 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
859 fSuccess
= EnumLogicalDrives( pDirImpl
->hEnumDrives
, pItemImpl
->cDriveString
);
864 return osl_File_E_None
;
868 rtl_freeMemory( pItemImpl
);
869 return oslTranslateFileError( GetLastError() );
873 //#####################################################
874 static oslFileError SAL_CALL
osl_getNextFileItem(
875 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32 uHint
)
877 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
878 DirectoryItem_Impl
*pItemImpl
= NULL
;
881 uHint
= uHint
; /* avoid warnings */
884 return osl_File_E_INVAL
;
888 return osl_File_E_INVAL
;
890 pItemImpl
= reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
892 return osl_File_E_NOMEM
;
894 memset( pItemImpl
, 0, sizeof(DirectoryItem_Impl
) );
895 fFound
= EnumDirectory( pDirImpl
->hDirectory
, &pItemImpl
->FindData
);
899 pItemImpl
->uType
= DIRECTORYITEM_FILE
;
900 pItemImpl
->nRefCount
= 1;
901 _tcscpy( pItemImpl
->szFullPath
, pDirImpl
->szDirectoryPath
);
902 _tcscat( pItemImpl
->szFullPath
, pItemImpl
->FindData
.cFileName
);
903 pItemImpl
->bFullPathNormalized
= FALSE
;
904 *pItem
= (oslDirectoryItem
)pItemImpl
;
905 return osl_File_E_None
;
909 rtl_freeMemory( pItemImpl
);
910 return oslTranslateFileError( GetLastError() );
914 //#####################################################
915 oslFileError SAL_CALL
osl_getNextDirectoryItem(
916 oslDirectory Directory
, oslDirectoryItem
*pItem
, sal_uInt32 uHint
)
918 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
923 return osl_File_E_INVAL
;
927 return osl_File_E_INVAL
;
929 switch ( pDirImpl
->uType
)
931 case DIRECTORYTYPE_LOCALROOT
:
932 return osl_getNextDrive( Directory
, pItem
, uHint
);
933 case DIRECTORYTYPE_NETROOT
:
934 return osl_getNextNetResource( Directory
, pItem
, uHint
);
935 case DIRECTORYTYPE_FILESYSTEM
:
936 return osl_getNextFileItem( Directory
, pItem
, uHint
);
938 return osl_File_E_INVAL
;
942 //#####################################################
943 oslFileError SAL_CALL
osl_closeDirectory(oslDirectory Directory
)
945 Directory_Impl
*pDirImpl
= (Directory_Impl
*)Directory
;
946 oslFileError eError
= osl_File_E_INVAL
;
950 switch ( pDirImpl
->uType
)
952 case DIRECTORYTYPE_FILESYSTEM
:
953 eError
= CloseDirectory( pDirImpl
->hDirectory
) ? osl_File_E_None
: oslTranslateFileError( GetLastError() );
955 case DIRECTORYTYPE_LOCALROOT
:
956 eError
= CloseLogicalDrivesEnum( pDirImpl
->hEnumDrives
) ? osl_File_E_None
: oslTranslateFileError( GetLastError() );
958 case DIRECTORYTYPE_NETROOT
:
960 DWORD err
= WNetCloseEnum(pDirImpl
->hDirectory
);
961 eError
= (err
== NO_ERROR
) ? osl_File_E_None
: oslTranslateFileError(err
);
965 OSL_ENSURE( 0, "Invalid directory type" );
969 rtl_freeMemory(pDirImpl
);
974 //#####################################################
975 /* Different types of paths */
976 typedef enum _PATHTYPE
978 PATHTYPE_SYNTAXERROR
= 0,
985 oslFileError SAL_CALL
osl_getDirectoryItem(rtl_uString
*strFilePath
, oslDirectoryItem
*pItem
)
987 oslFileError error
= osl_File_E_None
;
988 rtl_uString
* strSysFilePath
= NULL
;
989 PATHTYPE type
= PATHTYPE_FILE
;
995 return osl_File_E_INVAL
;
1000 error
= _osl_getSystemPathFromFileURL( strFilePath
, &strSysFilePath
, sal_False
);
1002 if ( osl_File_E_None
!= error
)
1005 dwPathType
= IsValidFilePath( strSysFilePath
, NULL
, VALIDATEPATH_NORMAL
, NULL
);
1007 if ( dwPathType
& PATHTYPE_IS_VOLUME
)
1008 type
= PATHTYPE_VOLUME
;
1009 else if ( dwPathType
& PATHTYPE_IS_SERVER
)
1010 type
= PATHTYPE_NETSERVER
;
1012 type
= PATHTYPE_FILE
;
1016 case PATHTYPE_NETSERVER
:
1018 DirectoryItem_Impl
* pItemImpl
=
1019 reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
1022 error
= osl_File_E_NOMEM
;
1024 if ( osl_File_E_None
== error
)
1026 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
1027 pItemImpl
->uType
= DIRECTORYITEM_SERVER
;
1029 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
1031 _tcscpy( pItemImpl
->szFullPath
, reinterpret_cast<LPCTSTR
>(strSysFilePath
->buffer
) );
1033 // Assign a title anyway
1038 while( iSrc
< strSysFilePath
->length
&& strSysFilePath
->buffer
[iSrc
] && strSysFilePath
->buffer
[iSrc
] != '\\' )
1040 pItemImpl
->FindData
.cFileName
[iDst
++] = strSysFilePath
->buffer
[iSrc
++];
1048 case PATHTYPE_VOLUME
:
1050 DirectoryItem_Impl
* pItemImpl
=
1051 reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
1054 error
= osl_File_E_NOMEM
;
1056 if ( osl_File_E_None
== error
)
1058 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
1059 pItemImpl
->uType
= DIRECTORYITEM_DRIVE
;
1061 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
1063 _tcscpy( pItemImpl
->cDriveString
, reinterpret_cast<LPCTSTR
>(strSysFilePath
->buffer
) );
1064 pItemImpl
->cDriveString
[0] = _toupper( pItemImpl
->cDriveString
[0] );
1066 if ( pItemImpl
->cDriveString
[_tcslen(pItemImpl
->cDriveString
) - 1] != '\\' )
1067 _tcscat( pItemImpl
->cDriveString
, TEXT( "\\" ) );
1073 case PATHTYPE_SYNTAXERROR
:
1074 case PATHTYPE_NETROOT
:
1078 WIN32_FIND_DATA aFindData
;
1080 if ( strSysFilePath
->length
> 0 && strSysFilePath
->buffer
[strSysFilePath
->length
- 1] == '\\' )
1081 rtl_uString_newFromStr_WithLength( &strSysFilePath
, strSysFilePath
->buffer
, strSysFilePath
->length
- 1 );
1083 hFind
= FindFirstFile( reinterpret_cast<LPCTSTR
>(rtl_uString_getStr(strSysFilePath
)), &aFindData
);
1085 if ( hFind
!= INVALID_HANDLE_VALUE
)
1087 DirectoryItem_Impl
*pItemImpl
=
1088 reinterpret_cast<DirectoryItem_Impl
*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl
)));
1090 ZeroMemory( pItemImpl
, sizeof(DirectoryItem_Impl
) );
1091 osl_acquireDirectoryItem( (oslDirectoryItem
)pItemImpl
);
1093 CopyMemory( &pItemImpl
->FindData
, &aFindData
, sizeof(WIN32_FIND_DATA
) );
1094 _tcscpy( pItemImpl
->szFullPath
, reinterpret_cast<LPCTSTR
>(rtl_uString_getStr(strSysFilePath
)) );
1096 // MT: This costs 600ms startup time on fast v60x!
1097 // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
1099 pItemImpl
->uType
= DIRECTORYITEM_FILE
;
1104 error
= oslTranslateFileError( GetLastError() );
1109 if ( strSysFilePath
)
1110 rtl_uString_release( strSysFilePath
);
1115 //#####################################################
1116 oslFileError SAL_CALL
osl_acquireDirectoryItem( oslDirectoryItem Item
)
1118 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1121 return osl_File_E_INVAL
;
1123 pItemImpl
->nRefCount
++;
1124 return osl_File_E_None
;
1127 //#####################################################
1128 oslFileError SAL_CALL
osl_releaseDirectoryItem( oslDirectoryItem Item
)
1130 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1133 return osl_File_E_INVAL
;
1135 if ( ! --pItemImpl
->nRefCount
)
1136 rtl_freeMemory( pItemImpl
);
1137 return osl_File_E_None
;
1140 //#####################################################
1141 // volume / file info handling functions
1142 //#####################################################
1144 //#####################################################
1145 static inline bool is_floppy_A_present()
1146 { return (GetLogicalDrives() & 1); }
1148 //#####################################################
1149 static inline bool is_floppy_B_present()
1150 { return (GetLogicalDrives() & 2); }
1152 //#####################################################
1153 bool is_floppy_volume_mount_point(const rtl::OUString
& path
)
1155 // determines if a volume mount point shows to a floppy
1156 // disk by comparing the unique volume names
1157 static const LPCWSTR FLOPPY_A
= L
"A:\\";
1158 static const LPCWSTR FLOPPY_B
= L
"B:\\";
1160 rtl::OUString
p(path
);
1161 osl::systemPathEnsureSeparator(p
);
1164 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR
>(p
.getStr()), vn
, ELEMENTS_OF_ARRAY(vn
)))
1167 if (is_floppy_A_present() &&
1168 GetVolumeNameForVolumeMountPoint(FLOPPY_A
, vnfloppy
, ELEMENTS_OF_ARRAY(vnfloppy
)) &&
1169 (0 == wcscmp(vn
, vnfloppy
)))
1172 if (is_floppy_B_present() &&
1173 GetVolumeNameForVolumeMountPoint(FLOPPY_B
, vnfloppy
, ELEMENTS_OF_ARRAY(vnfloppy
)) &&
1174 (0 == wcscmp(vn
, vnfloppy
)))
1180 //################################################
1181 static bool is_floppy_drive(const rtl::OUString
& path
)
1183 static const LPCWSTR FLOPPY_DRV_LETTERS
= TEXT("AaBb");
1185 // we must take into account that even a floppy
1186 // drive may be mounted to a directory so checking
1187 // for the drive letter alone is not sufficient
1188 // we must compare the unique volume name with
1189 // that of the available floppy disks
1191 const sal_Unicode
* pszPath
= path
.getStr();
1192 return ((wcschr(FLOPPY_DRV_LETTERS
, pszPath
[0]) && (L
':' == pszPath
[1])) || is_floppy_volume_mount_point(path
));
1195 //#####################################################
1196 static bool is_volume_mount_point(const rtl::OUString
& path
)
1198 rtl::OUString
p(path
);
1199 osl::systemPathRemoveSeparator(p
);
1201 bool is_volume_root
= false;
1203 if (!is_floppy_drive(p
))
1205 DWORD fattr
= GetFileAttributes(reinterpret_cast<LPCTSTR
>(p
.getStr()));
1207 if ((INVALID_FILE_ATTRIBUTES
!= fattr
) &&
1208 (FILE_ATTRIBUTE_REPARSE_POINT
& fattr
))
1210 WIN32_FIND_DATA find_data
;
1211 HANDLE h_find
= FindFirstFile(reinterpret_cast<LPCTSTR
>(p
.getStr()), &find_data
);
1213 if (IsValidHandle(h_find
) &&
1214 (FILE_ATTRIBUTE_REPARSE_POINT
& find_data
.dwFileAttributes
) &&
1215 (IO_REPARSE_TAG_MOUNT_POINT
== find_data
.dwReserved0
))
1217 is_volume_root
= true;
1219 if (IsValidHandle(h_find
))
1223 return is_volume_root
;
1226 //#############################################
1227 static UINT
get_volume_mount_point_drive_type(const rtl::OUString
& path
)
1229 if (0 == path
.getLength())
1230 return GetDriveType(NULL
);
1232 rtl::OUString
p(path
);
1233 osl::systemPathEnsureSeparator(p
);
1236 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR
>(p
.getStr()), vn
, ELEMENTS_OF_ARRAY(vn
)))
1237 return GetDriveType(vn
);
1239 return DRIVE_NO_ROOT_DIR
;
1242 //#############################################
1243 static inline bool is_drivetype_request(sal_uInt32 field_mask
)
1245 return (field_mask
& osl_VolumeInfo_Mask_Attributes
);
1248 //#############################################
1249 static oslFileError
osl_get_drive_type(
1250 const rtl::OUString
& path
, oslVolumeInfo
* pInfo
)
1252 // GetDriveType fails on empty volume mount points
1253 // see Knowledge Base Q244089
1255 if (is_volume_mount_point(path
))
1256 drive_type
= get_volume_mount_point_drive_type(path
);
1258 drive_type
= GetDriveType(reinterpret_cast<LPCTSTR
>(path
.getStr()));
1260 if (DRIVE_NO_ROOT_DIR
== drive_type
)
1261 return oslTranslateFileError(ERROR_INVALID_DRIVE
);
1263 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_Attributes
;
1268 pInfo
->uAttributes
|= osl_Volume_Attribute_CompactDisc
| osl_Volume_Attribute_Removeable
;
1270 case DRIVE_REMOVABLE
:
1271 pInfo
->uAttributes
|= osl_Volume_Attribute_Removeable
;
1272 if (is_floppy_drive(path
))
1273 pInfo
->uAttributes
|= osl_Volume_Attribute_FloppyDisk
;
1276 pInfo
->uAttributes
|= osl_Volume_Attribute_FixedDisk
;
1279 pInfo
->uAttributes
|= osl_Volume_Attribute_RAMDisk
;
1282 pInfo
->uAttributes
|= osl_Volume_Attribute_Remote
;
1285 pInfo
->uAttributes
= 0;
1288 pInfo
->uValidFields
&= ~osl_VolumeInfo_Mask_Attributes
;
1289 pInfo
->uAttributes
= 0;
1292 return osl_File_E_None
;
1295 //#############################################
1296 static inline bool is_volume_space_info_request(sal_uInt32 field_mask
)
1298 return (field_mask
&
1299 (osl_VolumeInfo_Mask_TotalSpace
|
1300 osl_VolumeInfo_Mask_UsedSpace
|
1301 osl_VolumeInfo_Mask_FreeSpace
));
1304 //#############################################
1305 static void get_volume_space_information(
1306 const rtl::OUString
& path
, oslVolumeInfo
*pInfo
)
1308 BOOL ret
= GetDiskFreeSpaceEx(
1309 reinterpret_cast<LPCTSTR
>(path
.getStr()),
1310 (PULARGE_INTEGER
)&(pInfo
->uFreeSpace
),
1311 (PULARGE_INTEGER
)&(pInfo
->uTotalSpace
),
1316 pInfo
->uUsedSpace
= pInfo
->uTotalSpace
- pInfo
->uFreeSpace
;
1317 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_TotalSpace
|
1318 osl_VolumeInfo_Mask_UsedSpace
|
1319 osl_VolumeInfo_Mask_FreeSpace
;
1323 //#############################################
1324 static inline bool is_filesystem_attributes_request(sal_uInt32 field_mask
)
1326 return (field_mask
&
1327 (osl_VolumeInfo_Mask_MaxNameLength
|
1328 osl_VolumeInfo_Mask_MaxPathLength
|
1329 osl_VolumeInfo_Mask_FileSystemName
|
1330 osl_VolumeInfo_Mask_FileSystemCaseHandling
));
1333 //#############################################
1334 static oslFileError
get_filesystem_attributes(
1335 const rtl::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
))
1351 WCHAR fsn
[MAX_PATH
];
1356 LPCTSTR pszPath
= reinterpret_cast<LPCTSTR
>(path
.getStr());
1357 if (GetVolumeInformation(pszPath
, vn
, MAX_PATH
, &serial
, &mcl
, &flags
, fsn
, MAX_PATH
))
1359 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_MaxNameLength
;
1360 pInfo
->uMaxNameLength
= mcl
;
1362 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_MaxPathLength
;
1363 pInfo
->uMaxPathLength
= MAX_PATH
;
1365 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_FileSystemName
;
1366 rtl_uString_newFromStr(&pInfo
->ustrFileSystemName
, reinterpret_cast<const sal_Unicode
*>(fsn
));
1368 // volumes (even NTFS) will always be considered case
1369 // insensitive because the Win32 API is not able to
1370 // deal with case sensitive volumes see M$ Knowledge Base
1371 // article 100625 that's why we never set the attribute
1372 // osl_Volume_Attribute_Case_Sensitive
1374 if (flags
& FS_CASE_IS_PRESERVED
)
1375 pInfo
->uAttributes
|= osl_Volume_Attribute_Case_Is_Preserved
;
1377 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_Attributes
;
1380 return osl_File_E_None
;
1383 //#####################################################
1384 static bool path_get_parent(rtl::OUString
& path
)
1386 OSL_PRECOND(path
.lastIndexOf(SLASH
) == -1, "Path must not have slashes");
1388 if (!has_path_parent(path
))
1390 sal_Int32 i
= path
.lastIndexOf(BACKSLASH
);
1393 path
= rtl::OUString(path
.getStr(), i
);
1400 //#####################################################
1401 static void path_travel_to_volume_root(const rtl::OUString
& system_path
, rtl::OUString
& volume_root
)
1403 rtl::OUString
sys_path(system_path
);
1405 while(!is_volume_mount_point(sys_path
) && path_get_parent(sys_path
))
1408 volume_root
= sys_path
;
1409 osl::systemPathEnsureSeparator(volume_root
);
1412 //#############################################
1413 oslFileError SAL_CALL
osl_getVolumeInformation(
1414 rtl_uString
*ustrURL
, oslVolumeInfo
*pInfo
, sal_uInt32 uFieldMask
)
1417 return osl_File_E_INVAL
;
1419 rtl::OUString system_path
;
1420 oslFileError error
= _osl_getSystemPathFromFileURL(ustrURL
, &system_path
.pData
, sal_False
);
1422 if (osl_File_E_None
!= error
)
1425 rtl::OUString volume_root
;
1426 path_travel_to_volume_root(system_path
, volume_root
);
1428 pInfo
->uValidFields
= 0;
1430 if ((error
= get_filesystem_attributes(volume_root
, uFieldMask
, pInfo
)) != osl_File_E_None
)
1433 if (is_volume_space_info_request(uFieldMask
))
1434 get_volume_space_information(volume_root
, pInfo
);
1436 if (uFieldMask
& osl_VolumeInfo_Mask_DeviceHandle
)
1438 pInfo
->uValidFields
|= osl_VolumeInfo_Mask_DeviceHandle
;
1439 osl_getFileURLFromSystemPath(volume_root
.pData
, (rtl_uString
**)&pInfo
->pDeviceHandle
);
1442 return osl_File_E_None
;
1445 //#####################################################
1446 static oslFileError SAL_CALL
osl_getDriveInfo(
1447 oslDirectoryItem Item
, oslFileStatus
*pStatus
, sal_uInt32 uFieldMask
)
1449 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1450 TCHAR cDrive
[3] = TEXT("A:");
1451 TCHAR cRoot
[4] = TEXT("A:\\");
1454 return osl_File_E_INVAL
;
1456 pStatus
->uValidFields
= 0;
1458 cDrive
[0] = pItemImpl
->cDriveString
[0];
1459 cRoot
[0] = pItemImpl
->cDriveString
[0];
1461 if ( uFieldMask
& osl_FileStatus_Mask_FileName
)
1463 if ( pItemImpl
->cDriveString
[0] == '\\' && pItemImpl
->cDriveString
[1] == '\\' )
1465 LPCWSTR lpFirstBkSlash
= wcschr( &pItemImpl
->cDriveString
[2], '\\' );
1467 if ( lpFirstBkSlash
&& lpFirstBkSlash
[1] )
1469 LPCWSTR lpLastBkSlash
= wcschr( &lpFirstBkSlash
[1], '\\' );
1471 if ( lpLastBkSlash
)
1472 rtl_uString_newFromStr_WithLength( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(&lpFirstBkSlash
[1]), lpLastBkSlash
- lpFirstBkSlash
- 1 );
1474 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(&lpFirstBkSlash
[1]) );
1475 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1478 else switch ( GetDriveType( cRoot
) )
1482 TCHAR szBuffer
[1024];
1483 DWORD
const dwBufsizeConst
= ELEMENTS_OF_ARRAY(szBuffer
);
1484 DWORD dwBufsize
= dwBufsizeConst
;
1486 DWORD dwResult
= WNetGetConnection( cDrive
, szBuffer
, &dwBufsize
);
1487 if ( NO_ERROR
== dwResult
)
1489 TCHAR szFileName
[dwBufsizeConst
+ 16];
1491 swprintf( szFileName
, L
"%s [%s]", cDrive
, szBuffer
);
1492 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(szFileName
) );
1495 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(cDrive
) );
1497 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1501 TCHAR szVolumeNameBuffer
[1024];
1502 DWORD
const dwBufsizeConst
= ELEMENTS_OF_ARRAY(szVolumeNameBuffer
);
1504 if ( GetVolumeInformation( cRoot
, szVolumeNameBuffer
, dwBufsizeConst
, NULL
, NULL
, NULL
, NULL
, 0 ) )
1506 TCHAR szFileName
[dwBufsizeConst
+ 16];
1508 swprintf( szFileName
, L
"%s [%s]", cDrive
, szVolumeNameBuffer
);
1509 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(szFileName
) );
1512 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(cDrive
) );
1514 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1517 case DRIVE_REMOVABLE
:
1518 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1519 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(cRoot
) );
1527 pStatus
->eType
= osl_File_Type_Volume
;
1528 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1530 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1532 rtl_uString
*ustrSystemPath
= NULL
;
1534 rtl_uString_newFromStr( &ustrSystemPath
, reinterpret_cast<const sal_Unicode
*>(pItemImpl
->cDriveString
) );
1535 osl_getFileURLFromSystemPath( ustrSystemPath
, &pStatus
->ustrFileURL
);
1536 rtl_uString_release( ustrSystemPath
);
1537 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1539 return osl_File_E_None
;
1542 //#####################################################
1543 static oslFileError SAL_CALL
osl_getServerInfo(
1544 oslDirectoryItem Item
, oslFileStatus
*pStatus
, sal_uInt32 uFieldMask
)
1546 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1548 return osl_File_E_INVAL
;
1550 pStatus
->uValidFields
= 0;
1552 // pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1554 // if ( _tcscmp( pItemImpl->FindData.cFileName, TEXT(".") ) == 0 )
1555 // rtl_uString_newFromAscii( &pStatus->ustrFileName, "/" );
1557 // rtl_uString_newFromStr( &pStatus->ustrFileName, pItemImpl->FindData.cFileName );
1559 pStatus
->eType
= osl_File_Type_Directory
;
1560 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1562 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1564 rtl_uString
*ustrSystemPath
= NULL
;
1566 rtl_uString_newFromStr( &ustrSystemPath
, reinterpret_cast<const sal_Unicode
*>(pItemImpl
->szFullPath
) );
1567 osl_getFileURLFromSystemPath( ustrSystemPath
, &pStatus
->ustrFileURL
);
1568 rtl_uString_release( ustrSystemPath
);
1569 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1571 return osl_File_E_None
;
1574 //#############################################
1575 oslFileError SAL_CALL
osl_getFileStatus(
1576 oslDirectoryItem Item
,
1577 oslFileStatus
*pStatus
,
1578 sal_uInt32 uFieldMask
)
1580 DirectoryItem_Impl
*pItemImpl
= (DirectoryItem_Impl
*)Item
;
1583 return osl_File_E_INVAL
;
1585 switch ( pItemImpl
->uType
)
1587 case DIRECTORYITEM_DRIVE
:
1588 return osl_getDriveInfo( Item
, pStatus
, uFieldMask
);
1589 case DIRECTORYITEM_SERVER
:
1590 return osl_getServerInfo( Item
, pStatus
, uFieldMask
);
1595 if ( uFieldMask
& osl_FileStatus_Mask_Validate
)
1597 HANDLE hFind
= FindFirstFile( pItemImpl
->szFullPath
, &pItemImpl
->FindData
);
1599 if ( hFind
!= INVALID_HANDLE_VALUE
)
1602 return oslTranslateFileError( GetLastError() );
1604 uFieldMask
&= ~ osl_FileStatus_Mask_Validate
;
1607 /* If no fields to retrieve left ignore pStatus */
1609 return osl_File_E_None
;
1611 /* Otherwise, this must be a valid pointer */
1613 return osl_File_E_INVAL
;
1615 if ( pStatus
->uStructSize
!= sizeof(oslFileStatus
) )
1616 return osl_File_E_INVAL
;
1618 pStatus
->uValidFields
= 0;
1620 /* File time stamps */
1622 if ( (uFieldMask
& osl_FileStatus_Mask_ModifyTime
) &&
1623 FileTimeToTimeValue( &pItemImpl
->FindData
.ftLastWriteTime
, &pStatus
->aModifyTime
) )
1624 pStatus
->uValidFields
|= osl_FileStatus_Mask_ModifyTime
;
1626 if ( (uFieldMask
& osl_FileStatus_Mask_AccessTime
) &&
1627 FileTimeToTimeValue( &pItemImpl
->FindData
.ftLastAccessTime
, &pStatus
->aAccessTime
) )
1628 pStatus
->uValidFields
|= osl_FileStatus_Mask_AccessTime
;
1630 if ( (uFieldMask
& osl_FileStatus_Mask_CreationTime
) &&
1631 FileTimeToTimeValue( &pItemImpl
->FindData
.ftCreationTime
, &pStatus
->aCreationTime
) )
1632 pStatus
->uValidFields
|= osl_FileStatus_Mask_CreationTime
;
1634 /* Most of the fields are already set, regardless of requiered fields */
1636 rtl_uString_newFromStr( &pStatus
->ustrFileName
, reinterpret_cast<const sal_Unicode
*>(pItemImpl
->FindData
.cFileName
) );
1637 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileName
;
1639 if ((FILE_ATTRIBUTE_REPARSE_POINT
& pItemImpl
->FindData
.dwFileAttributes
) &&
1640 (IO_REPARSE_TAG_MOUNT_POINT
== pItemImpl
->FindData
.dwReserved0
))
1641 pStatus
->eType
= osl_File_Type_Volume
;
1642 else if (pItemImpl
->FindData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1643 pStatus
->eType
= osl_File_Type_Directory
;
1645 pStatus
->eType
= osl_File_Type_Regular
;
1647 pStatus
->uValidFields
|= osl_FileStatus_Mask_Type
;
1649 pStatus
->uAttributes
= pItemImpl
->FindData
.dwFileAttributes
;
1650 pStatus
->uValidFields
|= osl_FileStatus_Mask_Attributes
;
1652 pStatus
->uFileSize
= (sal_uInt64
)pItemImpl
->FindData
.nFileSizeLow
+ ((sal_uInt64
)pItemImpl
->FindData
.nFileSizeHigh
<< 32);
1653 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileSize
;
1655 if ( uFieldMask
& osl_FileStatus_Mask_LinkTargetURL
)
1657 rtl_uString
*ustrFullPath
= NULL
;
1659 rtl_uString_newFromStr( &ustrFullPath
, reinterpret_cast<const sal_Unicode
*>(pItemImpl
->szFullPath
) );
1660 osl_getFileURLFromSystemPath( ustrFullPath
, &pStatus
->ustrLinkTargetURL
);
1661 rtl_uString_release( ustrFullPath
);
1663 pStatus
->uValidFields
|= osl_FileStatus_Mask_LinkTargetURL
;
1666 if ( uFieldMask
& osl_FileStatus_Mask_FileURL
)
1668 rtl_uString
*ustrFullPath
= NULL
;
1671 if ( !pItemImpl
->bFullPathNormalized
)
1673 GetCaseCorrectPathName( pItemImpl
->szFullPath
, pItemImpl
->szFullPath
, sizeof(pItemImpl
->szFullPath
) );
1674 pItemImpl
->bFullPathNormalized
= TRUE
;
1676 rtl_uString_newFromStr( &ustrFullPath
, reinterpret_cast<const sal_Unicode
*>(pItemImpl
->szFullPath
) );
1677 osl_getFileURLFromSystemPath( ustrFullPath
, &pStatus
->ustrFileURL
);
1678 rtl_uString_release( ustrFullPath
);
1679 pStatus
->uValidFields
|= osl_FileStatus_Mask_FileURL
;
1682 return osl_File_E_None
;
1685 //#####################################################
1686 // file attributes handling functions
1687 //#####################################################
1689 //#############################################
1690 oslFileError SAL_CALL
osl_setFileAttributes(
1691 rtl_uString
*ustrFileURL
,
1692 sal_uInt64 uAttributes
)
1695 rtl_uString
*ustrSysPath
= NULL
;
1696 DWORD dwFileAttributes
;
1699 // Converts the normalized path into a systempath
1700 error
= _osl_getSystemPathFromFileURL( ustrFileURL
, &ustrSysPath
, sal_False
);
1702 if ( osl_File_E_None
!= error
)
1705 dwFileAttributes
= GetFileAttributes( reinterpret_cast<LPCTSTR
>(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
= SetFileAttributes( reinterpret_cast<LPCTSTR
>(rtl_uString_getStr(ustrSysPath
)), dwFileAttributes
);
1723 error
= oslTranslateFileError( GetLastError() );
1725 rtl_uString_release( ustrSysPath
);
1730 //#####################################################
1731 oslFileError SAL_CALL
osl_setFileTime(
1732 rtl_uString
*filePath
,
1733 const TimeValue
*aCreationTime
,
1734 const TimeValue
*aLastAccessTime
,
1735 const TimeValue
*aLastWriteTime
)
1738 rtl_uString
*sysPath
=NULL
;
1739 FILETIME
*lpCreationTime
=NULL
;
1740 FILETIME
*lpLastAccessTime
=NULL
;
1741 FILETIME
*lpLastWriteTime
=NULL
;
1742 FILETIME ftCreationTime
;
1743 FILETIME ftLastAccessTime
;
1744 FILETIME ftLastWriteTime
;
1749 error
=_osl_getSystemPathFromFileURL(filePath
, &sysPath
, sal_False
);
1751 if (error
==osl_File_E_INVAL
)
1754 hFile
=CreateFileW(reinterpret_cast<LPCWSTR
>(rtl_uString_getStr(sysPath
)), GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
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
;