Update ooo320-m1
[ooovba.git] / sal / osl / w32 / file_dirvol.cxx
blob441a571ed8fe333f026a3e232adee897f478a353
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: file.cxx,v $
10 * $Revision: 1.19 $
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 ************************************************************************/
31 #define UNICODE
32 #define _UNICODE
33 #define _WIN32_WINNT_0x0500
34 #include "systools/win32/uwinapi.h"
36 #include "osl/file.h"
38 #include "file_url.h"
39 #include "file_error.h"
40 #include "path_helper.hxx"
42 #include "osl/diagnose.h"
43 #include "osl/time.h"
44 #include "rtl/alloc.h"
45 #include "rtl/ustring.hxx"
47 #include <tchar.h>
48 #ifdef __MINGW32__
49 #include <ctype.h>
50 #endif
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;
64 FILETIME FTime;
65 __int64 localTime;
66 BOOL fSuccess = FALSE;
68 BaseSysTime.wYear = 1970;
69 BaseSysTime.wMonth = 1;
70 BaseSysTime.wDayOfWeek = 0;
71 BaseSysTime.wDay = 1;
72 BaseSysTime.wHour = 0;
73 BaseSysTime.wMinute = 0;
74 BaseSysTime.wSecond = 0;
75 BaseSysTime.wMilliseconds = 0;
77 if (cpTimeVal==NULL)
78 return fSuccess;
80 if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
82 __int64 timeValue;
83 localTime=cpTimeVal->Seconds*(__int64)10000000+cpTimeVal->Nanosec/100;
84 *(__int64 *)&FTime=localTime;
85 fSuccess = 0 <= (timeValue= *((__int64 *)&BaseFileTime) + *((__int64 *) &FTime));
86 if (fSuccess)
87 *(__int64 *)pFTime=timeValue;
89 return fSuccess;
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) )
110 __int64 Value;
112 fSuccess = 0 <= (Value = *((__int64 *)cpFTime) - *((__int64 *)&BaseFileTime));
114 if ( fSuccess )
116 pTimeVal->Seconds = (unsigned long) (Value / 10000000L);
117 pTimeVal->Nanosec = (unsigned long)((Value % 10000000L) * 100);
120 return fSuccess;
123 //#####################################################
124 namespace /* private */
126 //#####################################################
127 struct Component
129 Component() :
130 begin_(0), end_(0)
133 bool isPresent() const
134 { return (static_cast<sal_IntPtr>(end_ - begin_) > 0); }
136 const sal_Unicode* begin_;
137 const sal_Unicode* end_;
140 //#####################################################
141 struct UNCComponents
143 Component server_;
144 Component share_;
145 Component resource_;
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))
167 ppos++;
169 puncc->server_.end_ = ppos;
171 if (BACKSLASH == *ppos)
173 puncc->share_.begin_ = ++ppos;
174 while ((ppos < pend) && (*ppos != BACKSLASH))
175 ppos++;
177 puncc->share_.end_ = ppos;
179 if (BACKSLASH == *ppos)
181 puncc->resource_.begin_ = ++ppos;
182 while (ppos < pend)
183 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();
211 else
213 has_parent = !osl::systemPathIsLogicalDrivePattern(path);
215 return has_parent;
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 )
231 if ( Handle )
232 return osl_File_E_None;
233 else
234 return osl_File_E_INVAL;
237 //#####################################################
238 oslFileError SAL_CALL osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
240 if ( Handle )
241 return osl_File_E_None;
242 else
243 return osl_File_E_INVAL;
246 //#####################################################
247 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
249 if ( Handle )
251 rtl_uString_acquire( (rtl_uString *)Handle );
252 return osl_File_E_None;
254 else
255 return osl_File_E_INVAL;
258 //#####################################################
259 oslFileError SAL_CALL osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
261 if ( Handle )
263 rtl_uString_release( (rtl_uString *)Handle );
264 return osl_File_E_None;
266 else
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;
278 else
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
292 UINT uType;
293 union {
294 WIN32_FIND_DATA FindData;
295 TCHAR cDriveString[MAX_PATH];
297 TCHAR szFullPath[MAX_PATH];
298 BOOL bFullPathNormalized;
299 int nRefCount;
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
311 UINT uType;
312 union {
313 HANDLE hDirectory;
314 HANDLE hEnumDrives;
316 TCHAR szDirectoryPath[MAX_PATH];
319 //#####################################################
321 typedef struct tagDRIVEENUM
323 LPCTSTR lpIdent;
324 TCHAR cBuffer[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
325 LPCTSTR lpCurrent;
326 } DRIVEENUM, * PDRIVEENUM, FAR * LPDRIVEENUM;
328 //#####################################################
330 static HANDLE WINAPI OpenLogicalDrivesEnum(void)
332 LPDRIVEENUM pEnum = (LPDRIVEENUM)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM) );
333 if ( pEnum )
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";
342 else
344 HeapFree( GetProcessHeap(), 0, pEnum );
345 pEnum = NULL;
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;
357 if ( pEnum )
359 int nLen = _tcslen( pEnum->lpCurrent );
361 if ( nLen )
363 CopyMemory( lpBuffer, pEnum->lpCurrent, (nLen + 1) * sizeof(TCHAR) );
364 pEnum->lpCurrent += nLen + 1;
365 fSuccess = TRUE;
367 else
368 SetLastError( ERROR_NO_MORE_FILES );
370 else
371 SetLastError( ERROR_INVALID_HANDLE );
373 return fSuccess;
376 //#####################################################
377 static BOOL WINAPI CloseLogicalDrivesEnum(HANDLE hEnum)
379 BOOL fSuccess = FALSE;
380 LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
382 if ( pEnum )
384 HeapFree( GetProcessHeap(), 0, pEnum );
385 fSuccess = TRUE;
387 else
388 SetLastError( ERROR_INVALID_HANDLE );
390 return fSuccess;
393 //#####################################################
394 typedef struct tagDIRECTORY
396 HANDLE hFind;
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));
405 if (pDirectory)
407 TCHAR szFileMask[MAX_PATH];
408 int nLen;
410 _tcscpy( szFileMask, lpszPath );
411 nLen = _tcslen( szFileMask );
413 if (nLen && szFileMask[nLen-1] != '\\')
414 _tcscat(szFileMask, TEXT("\\*.*"));
415 else
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);
425 pDirectory = NULL;
429 return (HANDLE)pDirectory;
432 //#####################################################
433 BOOL WINAPI EnumDirectory(HANDLE hDirectory, LPWIN32_FIND_DATA pFindData)
435 BOOL fSuccess = FALSE;
436 LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
438 if ( pDirectory )
440 BOOL fValid;
444 if ( pDirectory->aFirstData.cFileName[0] )
446 *pFindData = pDirectory->aFirstData;
447 fSuccess = TRUE;
448 pDirectory->aFirstData.cFileName[0] = 0;
450 else if ( IsValidHandle( pDirectory->hFind ) )
451 fSuccess = FindNextFile( pDirectory->hFind, pFindData );
452 else
454 fSuccess = FALSE;
455 SetLastError( ERROR_NO_MORE_FILES );
458 fValid = fSuccess && _tcscmp( TEXT("."), pFindData->cFileName ) != 0 && _tcscmp( TEXT(".."), pFindData->cFileName ) != 0;
460 } while( fSuccess && !fValid );
462 else
463 SetLastError( ERROR_INVALID_HANDLE );
465 return fSuccess;
468 //#####################################################
469 static BOOL WINAPI CloseDirectory(HANDLE hDirectory)
471 BOOL fSuccess = FALSE;
472 LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
474 if (pDirectory)
476 if (IsValidHandle(pDirectory->hFind))
477 fSuccess = FindClose(pDirectory->hFind);
479 fSuccess = HeapFree(GetProcessHeap(), 0, pDirectory) && fSuccess;
481 else
482 SetLastError(ERROR_INVALID_HANDLE);
484 return fSuccess;
487 //#####################################################
488 static oslFileError osl_openLocalRoot(
489 rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
491 rtl_uString *strSysPath = NULL;
492 oslFileError error;
494 if ( !pDirectory )
495 return osl_File_E_INVAL;
497 *pDirectory = NULL;
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 */
509 /* @@@ToDo
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();
518 /* @@@ToDo
519 Use IsValidHandle(...)
521 if ( pDirImpl->hEnumDrives != INVALID_HANDLE_VALUE )
523 *pDirectory = (oslDirectory)pDirImpl;
524 error = osl_File_E_None;
526 else
528 if ( pDirImpl )
529 rtl_freeMemory(pDirImpl);
531 error = oslTranslateFileError( GetLastError() );
534 rtl_uString_release( strSysPath );
536 return error;
539 //#####################################################
540 static oslFileError SAL_CALL osl_openFileDirectory(
541 rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
543 oslFileError error = osl_File_E_None;
545 if ( !pDirectory )
546 return osl_File_E_INVAL;
547 *pDirectory = NULL;
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 */
554 /* @@@ToDo
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);
571 return error;
574 //#####################################################
575 static oslFileError SAL_CALL osl_openNetworkServer(
576 rtl_uString *strSysDirPath, oslDirectory *pDirectory)
578 NETRESOURCEW aNetResource;
579 HANDLE hEnum;
580 DWORD dwError;
582 ZeroMemory( &aNetResource, sizeof(aNetResource) );
584 aNetResource.lpRemoteName = reinterpret_cast<LPWSTR>(strSysDirPath->buffer);
586 dwError = WNetOpenEnumW(
587 RESOURCE_GLOBALNET,
588 RESOURCETYPE_DISK,
589 RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER,
590 &aNetResource,
591 &hEnum );
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,
609 void* pData)
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)
619 rtl::OUString url;
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,
651 void* pData)
653 OSL_PRECOND(
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))
663 return w32_error;
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)
673 return 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,
682 void* pData)
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)
692 return osl_error;
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;
713 /*@@@ToDo
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!
718 else
720 const sal_Unicode *pBuffer = rtl_uString_getStr( strSysPath );
721 sal_Int32 nLen = rtl_uString_getLength( strSysPath );
723 if (
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 );
735 return error;
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;
748 else
749 error = oslTranslateFileError( GetLastError() );
751 rtl_uString_release( strSysPath );
753 return error;
756 //#####################################################
757 oslFileError SAL_CALL osl_openDirectory(rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
759 oslFileError error;
761 if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath->buffer, "file:///" ) )
762 error = osl_openLocalRoot( strDirectoryPath, pDirectory );
763 else
765 rtl_uString *strSysDirectoryPath = NULL;
766 DWORD dwPathType;
768 error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysDirectoryPath, sal_False );
770 if ( osl_File_E_None != error )
771 return error;
773 dwPathType = IsValidFilePath( strSysDirectoryPath, NULL, VALIDATEPATH_NORMAL, NULL );
775 if ( dwPathType & PATHTYPE_IS_SERVER )
777 error = osl_openNetworkServer( strSysDirectoryPath, pDirectory );
779 else
780 error = osl_openFileDirectory( strSysDirectoryPath, pDirectory );
782 rtl_uString_release( strSysDirectoryPath );
784 return error;
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;
793 BYTE buffer[16384];
794 LPNETRESOURCEW lpNetResource = (LPNETRESOURCEW)buffer;
795 DWORD dwError, dwCount, dwBufSize;
797 uHint = uHint; /* to get no warning */
799 if ( !pItem )
800 return osl_File_E_INVAL;
801 *pItem = NULL;
803 if ( !pDirImpl )
804 return osl_File_E_INVAL;
806 dwCount = 1;
807 dwBufSize = sizeof(buffer);
808 dwError = WNetEnumResource( pDirImpl->hDirectory, &dwCount, lpNetResource, &dwBufSize );
810 switch ( dwError )
812 case NO_ERROR:
813 case ERROR_MORE_DATA:
815 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
816 if ( !pItemImpl )
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 );
825 *pItem = pItemImpl;
827 return osl_File_E_None;
828 case ERROR_NO_MORE_ITEMS:
829 return osl_File_E_NOENT;
830 default:
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;
841 BOOL fSuccess;
843 uHint = uHint; /* avoid warnings */
845 if ( !pItem )
846 return osl_File_E_INVAL;
847 *pItem = NULL;
849 if ( !pDirImpl )
850 return osl_File_E_INVAL;
852 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
853 if ( !pItemImpl )
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 );
861 if ( fSuccess )
863 *pItem = pItemImpl;
864 return osl_File_E_None;
866 else
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;
879 BOOL fFound;
881 uHint = uHint; /* avoid warnings */
883 if ( !pItem )
884 return osl_File_E_INVAL;
885 *pItem = NULL;
887 if ( !pDirImpl )
888 return osl_File_E_INVAL;
890 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
891 if ( !pItemImpl )
892 return osl_File_E_NOMEM;
894 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
895 fFound = EnumDirectory( pDirImpl->hDirectory, &pItemImpl->FindData );
897 if ( fFound )
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;
907 else
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;
920 /* Assume failure */
922 if ( !pItem )
923 return osl_File_E_INVAL;
924 *pItem = NULL;
926 if ( !pDirImpl )
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 );
937 default:
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;
948 if ( pDirImpl )
950 switch ( pDirImpl->uType )
952 case DIRECTORYTYPE_FILESYSTEM:
953 eError = CloseDirectory( pDirImpl->hDirectory ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
954 break;
955 case DIRECTORYTYPE_LOCALROOT:
956 eError = CloseLogicalDrivesEnum( pDirImpl->hEnumDrives ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
957 break;
958 case DIRECTORYTYPE_NETROOT:
960 DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
961 eError = (err == NO_ERROR) ? osl_File_E_None : oslTranslateFileError(err);
963 break;
964 default:
965 OSL_ENSURE( 0, "Invalid directory type" );
966 break;
969 rtl_freeMemory(pDirImpl);
971 return eError;
974 //#####################################################
975 /* Different types of paths */
976 typedef enum _PATHTYPE
978 PATHTYPE_SYNTAXERROR = 0,
979 PATHTYPE_NETROOT,
980 PATHTYPE_NETSERVER,
981 PATHTYPE_VOLUME,
982 PATHTYPE_FILE
983 } PATHTYPE;
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;
990 DWORD dwPathType;
992 /* Assume failure */
994 if ( !pItem )
995 return osl_File_E_INVAL;
997 *pItem = NULL;
1000 error = _osl_getSystemPathFromFileURL( strFilePath, &strSysFilePath, sal_False );
1002 if ( osl_File_E_None != error )
1003 return 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;
1011 else
1012 type = PATHTYPE_FILE;
1014 switch ( type )
1016 case PATHTYPE_NETSERVER:
1018 DirectoryItem_Impl* pItemImpl =
1019 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1021 if ( !pItemImpl )
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
1035 int iSrc = 2;
1036 int iDst = 0;
1038 while( iSrc < strSysFilePath->length && strSysFilePath->buffer[iSrc] && strSysFilePath->buffer[iSrc] != '\\' )
1040 pItemImpl->FindData.cFileName[iDst++] = strSysFilePath->buffer[iSrc++];
1044 *pItem = pItemImpl;
1047 break;
1048 case PATHTYPE_VOLUME:
1050 DirectoryItem_Impl* pItemImpl =
1051 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1053 if ( !pItemImpl )
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( "\\" ) );
1069 *pItem = pItemImpl;
1072 break;
1073 case PATHTYPE_SYNTAXERROR:
1074 case PATHTYPE_NETROOT:
1075 case PATHTYPE_FILE:
1077 HANDLE hFind;
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;
1100 *pItem = pItemImpl;
1101 FindClose( hFind );
1103 else
1104 error = oslTranslateFileError( GetLastError() );
1106 break;
1109 if ( strSysFilePath )
1110 rtl_uString_release( strSysFilePath );
1112 return error;
1115 //#####################################################
1116 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
1118 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1120 if ( !pItemImpl )
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;
1132 if ( !pItemImpl )
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);
1163 TCHAR vn[51];
1164 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1166 TCHAR vnfloppy[51];
1167 if (is_floppy_A_present() &&
1168 GetVolumeNameForVolumeMountPoint(FLOPPY_A, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1169 (0 == wcscmp(vn, vnfloppy)))
1170 return true;
1172 if (is_floppy_B_present() &&
1173 GetVolumeNameForVolumeMountPoint(FLOPPY_B, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1174 (0 == wcscmp(vn, vnfloppy)))
1175 return true;
1177 return false;
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))
1220 FindClose(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);
1235 TCHAR vn[51];
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
1254 UINT drive_type;
1255 if (is_volume_mount_point(path))
1256 drive_type = get_volume_mount_point_drive_type(path);
1257 else
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;
1265 switch (drive_type)
1267 case DRIVE_CDROM:
1268 pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
1269 break;
1270 case DRIVE_REMOVABLE:
1271 pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
1272 if (is_floppy_drive(path))
1273 pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
1274 break;
1275 case DRIVE_FIXED:
1276 pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
1277 break;
1278 case DRIVE_RAMDISK:
1279 pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
1280 break;
1281 case DRIVE_REMOTE:
1282 pInfo->uAttributes |= osl_Volume_Attribute_Remote;
1283 break;
1284 case DRIVE_UNKNOWN:
1285 pInfo->uAttributes = 0;
1286 break;
1287 default:
1288 pInfo->uValidFields &= ~osl_VolumeInfo_Mask_Attributes;
1289 pInfo->uAttributes = 0;
1290 break;
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),
1312 NULL);
1314 if (ret)
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
1341 // on failure
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)
1346 return osl_error;
1348 if (is_filesystem_attributes_request(field_mask))
1350 WCHAR vn[MAX_PATH];
1351 WCHAR fsn[MAX_PATH];
1352 DWORD serial;
1353 DWORD mcl;
1354 DWORD flags;
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);
1391 if (-1 < i)
1393 path = rtl::OUString(path.getStr(), i);
1394 return true;
1397 return false;
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))
1406 /**/;
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 )
1416 if (!pInfo)
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)
1423 return 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)
1431 return error;
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:\\");
1453 if ( !pItemImpl )
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 );
1473 else
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 ) )
1480 case DRIVE_REMOTE:
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) );
1494 else
1495 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
1497 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1498 break;
1499 case DRIVE_FIXED:
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) );
1511 else
1512 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
1514 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1515 break;
1516 case DRIVE_CDROM:
1517 case DRIVE_REMOVABLE:
1518 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1519 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cRoot) );
1520 break;
1521 case DRIVE_UNKNOWN:
1522 default:
1523 break;
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;
1547 if ( !pItemImpl )
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, "/" );
1556 // else
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;
1582 if ( !pItemImpl )
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 );
1591 default:
1592 break;
1595 if ( uFieldMask & osl_FileStatus_Mask_Validate )
1597 HANDLE hFind = FindFirstFile( pItemImpl->szFullPath, &pItemImpl->FindData );
1599 if ( hFind != INVALID_HANDLE_VALUE )
1600 FindClose( hFind );
1601 else
1602 return oslTranslateFileError( GetLastError() );
1604 uFieldMask &= ~ osl_FileStatus_Mask_Validate;
1607 /* If no fields to retrieve left ignore pStatus */
1608 if ( !uFieldMask )
1609 return osl_File_E_None;
1611 /* Otherwise, this must be a valid pointer */
1612 if ( !pStatus )
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;
1644 else
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 )
1694 oslFileError error;
1695 rtl_uString *ustrSysPath = NULL;
1696 DWORD dwFileAttributes;
1697 BOOL fSuccess;
1699 // Converts the normalized path into a systempath
1700 error = _osl_getSystemPathFromFileURL( ustrFileURL, &ustrSysPath, sal_False );
1702 if ( osl_File_E_None != error )
1703 return 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 );
1719 else
1720 fSuccess = FALSE;
1722 if ( !fSuccess )
1723 error = oslTranslateFileError( GetLastError() );
1725 rtl_uString_release( ustrSysPath );
1727 return error;
1730 //#####################################################
1731 oslFileError SAL_CALL osl_setFileTime(
1732 rtl_uString *filePath,
1733 const TimeValue *aCreationTime,
1734 const TimeValue *aLastAccessTime,
1735 const TimeValue *aLastWriteTime)
1737 oslFileError error;
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;
1745 HANDLE hFile;
1746 BOOL fSuccess;
1749 error=_osl_getSystemPathFromFileURL(filePath, &sysPath, sal_False);
1751 if (error==osl_File_E_INVAL)
1752 return error;
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);
1771 CloseHandle(hFile);
1773 if (!fSuccess)
1774 return osl_File_E_INVAL;
1775 else
1776 return osl_File_E_None;