update dev300-m58
[ooovba.git] / sal / osl / w32 / file_dirvol.cxx
blob15cade63eaf3d6a2d70565c8c697ae96a35d935a
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>
49 //#####################################################
50 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
52 static const wchar_t UNC_PREFIX[] = L"\\\\";
53 static const wchar_t BACKSLASH = '\\';
54 static const wchar_t SLASH = '/';
56 //#####################################################
57 extern "C" BOOL TimeValueToFileTime(const TimeValue *cpTimeVal, FILETIME *pFTime)
59 SYSTEMTIME BaseSysTime;
60 FILETIME BaseFileTime;
61 FILETIME FTime;
62 __int64 localTime;
63 BOOL fSuccess = FALSE;
65 BaseSysTime.wYear = 1970;
66 BaseSysTime.wMonth = 1;
67 BaseSysTime.wDayOfWeek = 0;
68 BaseSysTime.wDay = 1;
69 BaseSysTime.wHour = 0;
70 BaseSysTime.wMinute = 0;
71 BaseSysTime.wSecond = 0;
72 BaseSysTime.wMilliseconds = 0;
74 if (cpTimeVal==NULL)
75 return fSuccess;
77 if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
79 __int64 timeValue;
80 localTime=cpTimeVal->Seconds*(__int64)10000000+cpTimeVal->Nanosec/100;
81 *(__int64 *)&FTime=localTime;
82 fSuccess = 0 <= (timeValue= *((__int64 *)&BaseFileTime) + *((__int64 *) &FTime));
83 if (fSuccess)
84 *(__int64 *)pFTime=timeValue;
86 return fSuccess;
89 //#####################################################
90 extern "C" BOOL FileTimeToTimeValue(const FILETIME *cpFTime, TimeValue *pTimeVal)
92 SYSTEMTIME BaseSysTime;
93 FILETIME BaseFileTime;
94 BOOL fSuccess = FALSE; /* Assume failure */
96 BaseSysTime.wYear = 1970;
97 BaseSysTime.wMonth = 1;
98 BaseSysTime.wDayOfWeek = 0;
99 BaseSysTime.wDay = 1;
100 BaseSysTime.wHour = 0;
101 BaseSysTime.wMinute = 0;
102 BaseSysTime.wSecond = 0;
103 BaseSysTime.wMilliseconds = 0;
105 if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
107 __int64 Value;
109 fSuccess = 0 <= (Value = *((__int64 *)cpFTime) - *((__int64 *)&BaseFileTime));
111 if ( fSuccess )
113 pTimeVal->Seconds = (unsigned long) (Value / 10000000L);
114 pTimeVal->Nanosec = (unsigned long)((Value % 10000000L) * 100);
117 return fSuccess;
120 //#####################################################
121 namespace /* private */
123 //#####################################################
124 struct Component
126 Component() :
127 begin_(0), end_(0)
130 bool isPresent() const
131 { return (static_cast<sal_IntPtr>(end_ - begin_) > 0); }
133 const sal_Unicode* begin_;
134 const sal_Unicode* end_;
137 //#####################################################
138 struct UNCComponents
140 Component server_;
141 Component share_;
142 Component resource_;
145 //#####################################################
146 inline bool is_UNC_path(const sal_Unicode* path)
147 { return (0 == wcsncmp(UNC_PREFIX, reinterpret_cast<LPCWSTR>(path), ELEMENTS_OF_ARRAY(UNC_PREFIX) - 1)); }
149 //#####################################################
150 inline bool is_UNC_path(const rtl::OUString& path)
151 { return is_UNC_path(path.getStr()); }
153 //#####################################################
154 void parse_UNC_path(const sal_Unicode* path, UNCComponents* puncc)
156 OSL_PRECOND(is_UNC_path(path), "Precondition violated: No UNC path");
157 OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) != -1, "Path must not contain slashes");
159 const sal_Unicode* pend = path + rtl_ustr_getLength(path);
160 const sal_Unicode* ppos = path + 2;
162 puncc->server_.begin_ = ppos;
163 while ((ppos < pend) && (*ppos != BACKSLASH))
164 ppos++;
166 puncc->server_.end_ = ppos;
168 if (BACKSLASH == *ppos)
170 puncc->share_.begin_ = ++ppos;
171 while ((ppos < pend) && (*ppos != BACKSLASH))
172 ppos++;
174 puncc->share_.end_ = ppos;
176 if (BACKSLASH == *ppos)
178 puncc->resource_.begin_ = ++ppos;
179 while (ppos < pend)
180 ppos++;
182 puncc->resource_.end_ = ppos;
186 OSL_POSTCOND(puncc->server_.isPresent() && puncc->share_.isPresent(), \
187 "Postcondition violated: Invalid UNC path detected");
190 //#####################################################
191 void parse_UNC_path(const rtl::OUString& path, UNCComponents* puncc)
192 { parse_UNC_path(path.getStr(), puncc); }
195 //#####################################################
196 bool has_path_parent(const sal_Unicode* path)
198 // Has the given path a parent or are we already there,
199 // e.g. 'c:\' or '\\server\share\'?
201 bool has_parent = false;
202 if (is_UNC_path(path))
204 UNCComponents unc_comp;
205 parse_UNC_path(path, &unc_comp);
206 has_parent = unc_comp.resource_.isPresent();
208 else
210 has_parent = !osl::systemPathIsLogicalDrivePattern(path);
212 return has_parent;
215 //#####################################################
216 inline bool has_path_parent(const rtl::OUString& path)
217 { return has_path_parent(path.getStr()); }
219 } // end namespace private
221 //#####################################################
222 // volume handling functions
223 //#####################################################
225 //#####################################################
226 oslFileError SAL_CALL osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
228 if ( Handle )
229 return osl_File_E_None;
230 else
231 return osl_File_E_INVAL;
234 //#####################################################
235 oslFileError SAL_CALL osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
237 if ( Handle )
238 return osl_File_E_None;
239 else
240 return osl_File_E_INVAL;
243 //#####################################################
244 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
246 if ( Handle )
248 rtl_uString_acquire( (rtl_uString *)Handle );
249 return osl_File_E_None;
251 else
252 return osl_File_E_INVAL;
255 //#####################################################
256 oslFileError SAL_CALL osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
258 if ( Handle )
260 rtl_uString_release( (rtl_uString *)Handle );
261 return osl_File_E_None;
263 else
264 return osl_File_E_INVAL;
267 //#####################################################
268 oslFileError SAL_CALL osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
270 if ( Handle && pstrPath )
272 rtl_uString_assign( pstrPath, (rtl_uString *)Handle );
273 return osl_File_E_None;
275 else
276 return osl_File_E_INVAL;
279 //##################################################################
280 // directory handling functions
281 //##################################################################
283 #define DIRECTORYITEM_DRIVE 0
284 #define DIRECTORYITEM_FILE 1
285 #define DIRECTORYITEM_SERVER 2
287 struct DirectoryItem_Impl
289 UINT uType;
290 union {
291 WIN32_FIND_DATA FindData;
292 TCHAR cDriveString[MAX_PATH];
294 TCHAR szFullPath[MAX_PATH];
295 BOOL bFullPathNormalized;
296 int nRefCount;
299 //#####################################################
301 #define DIRECTORYTYPE_LOCALROOT 0
302 #define DIRECTORYTYPE_NETROOT 1
303 #define DIRECTORYTYPE_NETRESORCE 2
304 #define DIRECTORYTYPE_FILESYSTEM 3
306 struct Directory_Impl
308 UINT uType;
309 union {
310 HANDLE hDirectory;
311 HANDLE hEnumDrives;
313 TCHAR szDirectoryPath[MAX_PATH];
316 //#####################################################
318 typedef struct tagDRIVEENUM
320 LPCTSTR lpIdent;
321 TCHAR cBuffer[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
322 LPCTSTR lpCurrent;
323 } DRIVEENUM, * PDRIVEENUM, FAR * LPDRIVEENUM;
325 //#####################################################
327 static HANDLE WINAPI OpenLogicalDrivesEnum(void)
329 LPDRIVEENUM pEnum = (LPDRIVEENUM)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM) );
330 if ( pEnum )
332 DWORD dwNumCopied = GetLogicalDriveStrings( (sizeof(pEnum->cBuffer) - 1) / sizeof(TCHAR), pEnum->cBuffer );
334 if ( dwNumCopied && dwNumCopied < sizeof(pEnum->cBuffer) / sizeof(TCHAR) )
336 pEnum->lpCurrent = pEnum->cBuffer;
337 pEnum->lpIdent = L"tagDRIVEENUM";
339 else
341 HeapFree( GetProcessHeap(), 0, pEnum );
342 pEnum = NULL;
345 return pEnum ? (HANDLE)pEnum : INVALID_HANDLE_VALUE;
348 //#####################################################
349 static BOOL WINAPI EnumLogicalDrives(HANDLE hEnum, LPTSTR lpBuffer)
351 BOOL fSuccess = FALSE;
352 LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
354 if ( pEnum )
356 int nLen = _tcslen( pEnum->lpCurrent );
358 if ( nLen )
360 CopyMemory( lpBuffer, pEnum->lpCurrent, (nLen + 1) * sizeof(TCHAR) );
361 pEnum->lpCurrent += nLen + 1;
362 fSuccess = TRUE;
364 else
365 SetLastError( ERROR_NO_MORE_FILES );
367 else
368 SetLastError( ERROR_INVALID_HANDLE );
370 return fSuccess;
373 //#####################################################
374 static BOOL WINAPI CloseLogicalDrivesEnum(HANDLE hEnum)
376 BOOL fSuccess = FALSE;
377 LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
379 if ( pEnum )
381 HeapFree( GetProcessHeap(), 0, pEnum );
382 fSuccess = TRUE;
384 else
385 SetLastError( ERROR_INVALID_HANDLE );
387 return fSuccess;
390 //#####################################################
391 typedef struct tagDIRECTORY
393 HANDLE hFind;
394 WIN32_FIND_DATA aFirstData;
395 } DIRECTORY, *PDIRECTORY, FAR *LPDIRECTORY;
397 //#####################################################
398 static HANDLE WINAPI OpenDirectory(LPCTSTR lpszPath)
400 LPDIRECTORY pDirectory = (LPDIRECTORY)HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY));
402 if (pDirectory)
404 TCHAR szFileMask[MAX_PATH];
405 int nLen;
407 _tcscpy( szFileMask, lpszPath );
408 nLen = _tcslen( szFileMask );
410 if (nLen && szFileMask[nLen-1] != '\\')
411 _tcscat(szFileMask, TEXT("\\*.*"));
412 else
413 _tcscat(szFileMask, TEXT("*.*"));
415 pDirectory->hFind = FindFirstFile(szFileMask, &pDirectory->aFirstData);
417 if (!IsValidHandle(pDirectory->hFind))
419 if ( GetLastError() != ERROR_NO_MORE_FILES )
421 HeapFree(GetProcessHeap(), 0, pDirectory);
422 pDirectory = NULL;
426 return (HANDLE)pDirectory;
429 //#####################################################
430 BOOL WINAPI EnumDirectory(HANDLE hDirectory, LPWIN32_FIND_DATA pFindData)
432 BOOL fSuccess = FALSE;
433 LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
435 if ( pDirectory )
437 BOOL fValid;
441 if ( pDirectory->aFirstData.cFileName[0] )
443 *pFindData = pDirectory->aFirstData;
444 fSuccess = TRUE;
445 pDirectory->aFirstData.cFileName[0] = 0;
447 else if ( IsValidHandle( pDirectory->hFind ) )
448 fSuccess = FindNextFile( pDirectory->hFind, pFindData );
449 else
451 fSuccess = FALSE;
452 SetLastError( ERROR_NO_MORE_FILES );
455 fValid = fSuccess && _tcscmp( TEXT("."), pFindData->cFileName ) != 0 && _tcscmp( TEXT(".."), pFindData->cFileName ) != 0;
457 } while( fSuccess && !fValid );
459 else
460 SetLastError( ERROR_INVALID_HANDLE );
462 return fSuccess;
465 //#####################################################
466 static BOOL WINAPI CloseDirectory(HANDLE hDirectory)
468 BOOL fSuccess = FALSE;
469 LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
471 if (pDirectory)
473 if (IsValidHandle(pDirectory->hFind))
474 fSuccess = FindClose(pDirectory->hFind);
476 fSuccess = HeapFree(GetProcessHeap(), 0, pDirectory) && fSuccess;
478 else
479 SetLastError(ERROR_INVALID_HANDLE);
481 return fSuccess;
484 //#####################################################
485 static oslFileError osl_openLocalRoot(
486 rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
488 rtl_uString *strSysPath = NULL;
489 oslFileError error;
491 if ( !pDirectory )
492 return osl_File_E_INVAL;
494 *pDirectory = NULL;
496 error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysPath, sal_False );
497 if ( osl_File_E_None == error )
499 Directory_Impl *pDirImpl;
501 pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory( sizeof(Directory_Impl)));
502 _tcscpy( pDirImpl->szDirectoryPath, reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysPath)) );
504 /* Append backslash if neccessary */
506 /* @@@ToDo
507 use function ensure backslash
509 if ( pDirImpl->szDirectoryPath[_tcslen(pDirImpl->szDirectoryPath) - 1] != L'\\' )
510 _tcscat( pDirImpl->szDirectoryPath, L"\\" );
512 pDirImpl->uType = DIRECTORYTYPE_LOCALROOT;
513 pDirImpl->hEnumDrives = OpenLogicalDrivesEnum();
515 /* @@@ToDo
516 Use IsValidHandle(...)
518 if ( pDirImpl->hEnumDrives != INVALID_HANDLE_VALUE )
520 *pDirectory = (oslDirectory)pDirImpl;
521 error = osl_File_E_None;
523 else
525 if ( pDirImpl )
526 rtl_freeMemory(pDirImpl);
528 error = oslTranslateFileError( GetLastError() );
531 rtl_uString_release( strSysPath );
533 return error;
536 //#####################################################
537 static oslFileError SAL_CALL osl_openFileDirectory(
538 rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
540 oslFileError error = osl_File_E_None;
542 if ( !pDirectory )
543 return osl_File_E_INVAL;
544 *pDirectory = NULL;
546 Directory_Impl *pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
547 _tcscpy( pDirImpl->szDirectoryPath, reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strDirectoryPath)) );
549 /* Append backslash if neccessary */
551 /* @@@ToDo
552 use function ensure backslash
554 if ( pDirImpl->szDirectoryPath[_tcslen(pDirImpl->szDirectoryPath) - 1] != L'\\' )
555 _tcscat( pDirImpl->szDirectoryPath, L"\\" );
557 pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM;
558 pDirImpl->hDirectory = OpenDirectory( pDirImpl->szDirectoryPath );
560 if ( !pDirImpl->hDirectory )
562 error = oslTranslateFileError( GetLastError() );
564 rtl_freeMemory(pDirImpl), pDirImpl = 0;
567 *pDirectory = (oslDirectory)(pDirImpl);
568 return error;
571 //#####################################################
572 static oslFileError SAL_CALL osl_openNetworkServer(
573 rtl_uString *strSysDirPath, oslDirectory *pDirectory)
575 NETRESOURCEW aNetResource;
576 HANDLE hEnum;
577 DWORD dwError;
579 ZeroMemory( &aNetResource, sizeof(aNetResource) );
581 aNetResource.lpRemoteName = reinterpret_cast<LPWSTR>(strSysDirPath->buffer);
583 dwError = WNetOpenEnumW(
584 RESOURCE_GLOBALNET,
585 RESOURCETYPE_DISK,
586 RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER,
587 &aNetResource,
588 &hEnum );
590 if ( ERROR_SUCCESS == dwError )
592 Directory_Impl *pDirImpl;
594 pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
595 pDirImpl->uType = DIRECTORYTYPE_NETROOT;
596 pDirImpl->hDirectory = hEnum;
597 *pDirectory = (oslDirectory)pDirImpl;
599 return oslTranslateFileError( dwError );
602 //#############################################
603 static DWORD create_dir_with_callback(
604 rtl_uString * dir_path,
605 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
606 void* pData)
608 // Create the specified directory and call the
609 // user specified callback function. On success
610 // the function returns ERROR_SUCCESS else a Win32 error code.
612 if (CreateDirectory(reinterpret_cast<LPCTSTR>(dir_path->buffer), NULL))
614 if (aDirectoryCreationCallbackFunc)
616 rtl::OUString url;
617 _osl_getFileURLFromSystemPath(dir_path, &(url.pData));
618 aDirectoryCreationCallbackFunc(pData, url.pData);
620 return ERROR_SUCCESS;
622 return GetLastError();
625 //#############################################
626 static int path_make_parent(sal_Unicode* path)
628 /* Cut off the last part of the given path to
629 get the parent only, e.g. 'c:\dir\subdir' ->
630 'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
631 @return The position where the path has been cut
632 off (this is the posistion of the last backslash).
633 If there are no more parents 0 will be returned,
634 e.g. 'c:\' or '\\Share' have no more parents */
636 OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) != -1, "Path must not contain slashes");
637 OSL_PRECOND(has_path_parent(path), "Path must have a parent");
639 sal_Unicode* pos_last_backslash = path + rtl_ustr_lastIndexOfChar(path, BACKSLASH);
640 *pos_last_backslash = 0;
641 return (pos_last_backslash - path);
644 //#############################################
645 static DWORD create_dir_recursively_(
646 rtl_uString * dir_path,
647 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
648 void* pData)
650 OSL_PRECOND(
651 rtl_ustr_lastIndexOfChar_WithLength(dir_path->buffer, dir_path->length, BACKSLASH) != dir_path->length,
652 "Path must not end with a backslash");
654 DWORD w32_error = create_dir_with_callback(
655 dir_path, aDirectoryCreationCallbackFunc, pData);
656 if (w32_error == ERROR_SUCCESS)
657 return ERROR_SUCCESS;
659 if ((w32_error != ERROR_PATH_NOT_FOUND) || !has_path_parent(dir_path->buffer))
660 return w32_error;
662 int pos = path_make_parent(dir_path->buffer); // dir_path->buffer[pos] = 0, restore below
664 w32_error = create_dir_recursively_(
665 dir_path, aDirectoryCreationCallbackFunc, pData);
667 dir_path->buffer[pos] = BACKSLASH; // restore
669 if (ERROR_SUCCESS != w32_error)
670 return w32_error;
672 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
675 //#############################################
676 oslFileError SAL_CALL osl_createDirectoryPath(
677 rtl_uString* aDirectoryUrl,
678 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
679 void* pData)
681 if (aDirectoryUrl == NULL)
682 return osl_File_E_INVAL;
684 rtl::OUString sys_path;
685 oslFileError osl_error =
686 _osl_getSystemPathFromFileURL(aDirectoryUrl, &sys_path.pData, sal_False);
688 if (osl_error != osl_File_E_None)
689 return osl_error;
691 osl::systemPathRemoveSeparator(sys_path);
693 // const_cast because sys_path is a local copy
694 // which we want to modify inplace instead of
695 // coyp it into another buffer on the heap again
696 return oslTranslateFileError(create_dir_recursively_(
697 sys_path.pData, aDirectoryCreationCallbackFunc, pData));
700 //#####################################################
701 oslFileError SAL_CALL osl_createDirectory(rtl_uString* strPath)
703 rtl_uString *strSysPath = NULL;
704 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
706 if ( osl_File_E_None == error )
708 if ( CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), NULL ) )
709 error = osl_File_E_None;
710 /*@@@ToDo
711 The else case is a hack because the ucb or the webtop had some
712 problems with the error code that CreateDirectory returns in
713 case the path is only a logical drive, should be removed!
715 else
717 const sal_Unicode *pBuffer = rtl_uString_getStr( strSysPath );
718 sal_Int32 nLen = rtl_uString_getLength( strSysPath );
720 if (
721 ( pBuffer[0] >= 'A' && pBuffer[0] <= 'Z' ||
722 pBuffer[0] >= 'a' && pBuffer[0] <= 'z' ) &&
723 pBuffer[1] == ':' && ( nLen ==2 || nLen == 3 && pBuffer[2] == '\\' )
725 SetLastError( ERROR_ALREADY_EXISTS );
727 error = oslTranslateFileError( GetLastError() );
730 rtl_uString_release( strSysPath );
732 return error;
735 //#####################################################
736 oslFileError SAL_CALL osl_removeDirectory(rtl_uString* strPath)
738 rtl_uString *strSysPath = NULL;
739 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
741 if ( osl_File_E_None == error )
743 if ( RemoveDirectory( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
744 error = osl_File_E_None;
745 else
746 error = oslTranslateFileError( GetLastError() );
748 rtl_uString_release( strSysPath );
750 return error;
753 //#####################################################
754 oslFileError SAL_CALL osl_openDirectory(rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
756 oslFileError error;
758 if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath->buffer, "file:///" ) )
759 error = osl_openLocalRoot( strDirectoryPath, pDirectory );
760 else
762 rtl_uString *strSysDirectoryPath = NULL;
763 DWORD dwPathType;
765 error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysDirectoryPath, sal_False );
767 if ( osl_File_E_None != error )
768 return error;
770 dwPathType = IsValidFilePath( strSysDirectoryPath, NULL, VALIDATEPATH_NORMAL, NULL );
772 if ( dwPathType & PATHTYPE_IS_SERVER )
774 error = osl_openNetworkServer( strSysDirectoryPath, pDirectory );
776 else
777 error = osl_openFileDirectory( strSysDirectoryPath, pDirectory );
779 rtl_uString_release( strSysDirectoryPath );
781 return error;
784 //#####################################################
785 static oslFileError SAL_CALL osl_getNextNetResource(
786 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
788 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
789 DirectoryItem_Impl *pItemImpl = NULL;
790 BYTE buffer[16384];
791 LPNETRESOURCEW lpNetResource = (LPNETRESOURCEW)buffer;
792 DWORD dwError, dwCount, dwBufSize;
794 uHint = uHint; /* to get no warning */
796 if ( !pItem )
797 return osl_File_E_INVAL;
798 *pItem = NULL;
800 if ( !pDirImpl )
801 return osl_File_E_INVAL;
803 dwCount = 1;
804 dwBufSize = sizeof(buffer);
805 dwError = WNetEnumResource( pDirImpl->hDirectory, &dwCount, lpNetResource, &dwBufSize );
807 switch ( dwError )
809 case NO_ERROR:
810 case ERROR_MORE_DATA:
812 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
813 if ( !pItemImpl )
814 return osl_File_E_NOMEM;
816 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
817 pItemImpl->uType = DIRECTORYITEM_DRIVE;
818 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
820 wcscpy( pItemImpl->cDriveString, lpNetResource->lpRemoteName );
822 *pItem = pItemImpl;
824 return osl_File_E_None;
825 case ERROR_NO_MORE_ITEMS:
826 return osl_File_E_NOENT;
827 default:
828 return oslTranslateFileError( dwError );
832 //#####################################################
833 static oslFileError SAL_CALL osl_getNextDrive(
834 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
836 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
837 DirectoryItem_Impl *pItemImpl = NULL;
838 BOOL fSuccess;
840 uHint = uHint; /* avoid warnings */
842 if ( !pItem )
843 return osl_File_E_INVAL;
844 *pItem = NULL;
846 if ( !pDirImpl )
847 return osl_File_E_INVAL;
849 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
850 if ( !pItemImpl )
851 return osl_File_E_NOMEM;
853 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
854 pItemImpl->uType = DIRECTORYITEM_DRIVE;
855 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
856 fSuccess = EnumLogicalDrives( pDirImpl->hEnumDrives, pItemImpl->cDriveString );
858 if ( fSuccess )
860 *pItem = pItemImpl;
861 return osl_File_E_None;
863 else
865 rtl_freeMemory( pItemImpl );
866 return oslTranslateFileError( GetLastError() );
870 //#####################################################
871 static oslFileError SAL_CALL osl_getNextFileItem(
872 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
874 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
875 DirectoryItem_Impl *pItemImpl = NULL;
876 BOOL fFound;
878 uHint = uHint; /* avoid warnings */
880 if ( !pItem )
881 return osl_File_E_INVAL;
882 *pItem = NULL;
884 if ( !pDirImpl )
885 return osl_File_E_INVAL;
887 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
888 if ( !pItemImpl )
889 return osl_File_E_NOMEM;
891 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
892 fFound = EnumDirectory( pDirImpl->hDirectory, &pItemImpl->FindData );
894 if ( fFound )
896 pItemImpl->uType = DIRECTORYITEM_FILE;
897 pItemImpl->nRefCount = 1;
898 _tcscpy( pItemImpl->szFullPath, pDirImpl->szDirectoryPath );
899 _tcscat( pItemImpl->szFullPath, pItemImpl->FindData.cFileName );
900 pItemImpl->bFullPathNormalized = FALSE;
901 *pItem = (oslDirectoryItem)pItemImpl;
902 return osl_File_E_None;
904 else
906 rtl_freeMemory( pItemImpl );
907 return oslTranslateFileError( GetLastError() );
911 //#####################################################
912 oslFileError SAL_CALL osl_getNextDirectoryItem(
913 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
915 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
917 /* Assume failure */
919 if ( !pItem )
920 return osl_File_E_INVAL;
921 *pItem = NULL;
923 if ( !pDirImpl )
924 return osl_File_E_INVAL;
926 switch ( pDirImpl->uType )
928 case DIRECTORYTYPE_LOCALROOT:
929 return osl_getNextDrive( Directory, pItem, uHint );
930 case DIRECTORYTYPE_NETROOT:
931 return osl_getNextNetResource( Directory, pItem, uHint );
932 case DIRECTORYTYPE_FILESYSTEM:
933 return osl_getNextFileItem( Directory, pItem, uHint );
934 default:
935 return osl_File_E_INVAL;
939 //#####################################################
940 oslFileError SAL_CALL osl_closeDirectory(oslDirectory Directory)
942 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
943 oslFileError eError = osl_File_E_INVAL;
945 if ( pDirImpl )
947 switch ( pDirImpl->uType )
949 case DIRECTORYTYPE_FILESYSTEM:
950 eError = CloseDirectory( pDirImpl->hDirectory ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
951 break;
952 case DIRECTORYTYPE_LOCALROOT:
953 eError = CloseLogicalDrivesEnum( pDirImpl->hEnumDrives ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
954 break;
955 case DIRECTORYTYPE_NETROOT:
957 DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
958 eError = (err == NO_ERROR) ? osl_File_E_None : oslTranslateFileError(err);
960 break;
961 default:
962 OSL_ENSURE( 0, "Invalid directory type" );
963 break;
966 rtl_freeMemory(pDirImpl);
968 return eError;
971 //#####################################################
972 /* Different types of paths */
973 typedef enum _PATHTYPE
975 PATHTYPE_SYNTAXERROR = 0,
976 PATHTYPE_NETROOT,
977 PATHTYPE_NETSERVER,
978 PATHTYPE_VOLUME,
979 PATHTYPE_FILE
980 } PATHTYPE;
982 oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString *strFilePath, oslDirectoryItem *pItem)
984 oslFileError error = osl_File_E_None;
985 rtl_uString* strSysFilePath = NULL;
986 PATHTYPE type = PATHTYPE_FILE;
987 DWORD dwPathType;
989 /* Assume failure */
991 if ( !pItem )
992 return osl_File_E_INVAL;
994 *pItem = NULL;
997 error = _osl_getSystemPathFromFileURL( strFilePath, &strSysFilePath, sal_False );
999 if ( osl_File_E_None != error )
1000 return error;
1002 dwPathType = IsValidFilePath( strSysFilePath, NULL, VALIDATEPATH_NORMAL, NULL );
1004 if ( dwPathType & PATHTYPE_IS_VOLUME )
1005 type = PATHTYPE_VOLUME;
1006 else if ( dwPathType & PATHTYPE_IS_SERVER )
1007 type = PATHTYPE_NETSERVER;
1008 else
1009 type = PATHTYPE_FILE;
1011 switch ( type )
1013 case PATHTYPE_NETSERVER:
1015 DirectoryItem_Impl* pItemImpl =
1016 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1018 if ( !pItemImpl )
1019 error = osl_File_E_NOMEM;
1021 if ( osl_File_E_None == error )
1023 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1024 pItemImpl->uType = DIRECTORYITEM_SERVER;
1026 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1028 _tcscpy( pItemImpl->szFullPath, reinterpret_cast<LPCTSTR>(strSysFilePath->buffer) );
1030 // Assign a title anyway
1032 int iSrc = 2;
1033 int iDst = 0;
1035 while( iSrc < strSysFilePath->length && strSysFilePath->buffer[iSrc] && strSysFilePath->buffer[iSrc] != '\\' )
1037 pItemImpl->FindData.cFileName[iDst++] = strSysFilePath->buffer[iSrc++];
1041 *pItem = pItemImpl;
1044 break;
1045 case PATHTYPE_VOLUME:
1047 DirectoryItem_Impl* pItemImpl =
1048 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1050 if ( !pItemImpl )
1051 error = osl_File_E_NOMEM;
1053 if ( osl_File_E_None == error )
1055 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1056 pItemImpl->uType = DIRECTORYITEM_DRIVE;
1058 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1060 _tcscpy( pItemImpl->cDriveString, reinterpret_cast<LPCTSTR>(strSysFilePath->buffer) );
1061 pItemImpl->cDriveString[0] = _toupper( pItemImpl->cDriveString[0] );
1063 if ( pItemImpl->cDriveString[_tcslen(pItemImpl->cDriveString) - 1] != '\\' )
1064 _tcscat( pItemImpl->cDriveString, TEXT( "\\" ) );
1066 *pItem = pItemImpl;
1069 break;
1070 case PATHTYPE_SYNTAXERROR:
1071 case PATHTYPE_NETROOT:
1072 case PATHTYPE_FILE:
1074 HANDLE hFind;
1075 WIN32_FIND_DATA aFindData;
1077 if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' )
1078 rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 );
1080 hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysFilePath)), &aFindData );
1082 if ( hFind != INVALID_HANDLE_VALUE )
1084 DirectoryItem_Impl *pItemImpl =
1085 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1087 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1088 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1090 CopyMemory( &pItemImpl->FindData, &aFindData, sizeof(WIN32_FIND_DATA) );
1091 _tcscpy( pItemImpl->szFullPath, reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysFilePath)) );
1093 // MT: This costs 600ms startup time on fast v60x!
1094 // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
1096 pItemImpl->uType = DIRECTORYITEM_FILE;
1097 *pItem = pItemImpl;
1098 FindClose( hFind );
1100 else
1101 error = oslTranslateFileError( GetLastError() );
1103 break;
1106 if ( strSysFilePath )
1107 rtl_uString_release( strSysFilePath );
1109 return error;
1112 //#####################################################
1113 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
1115 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1117 if ( !pItemImpl )
1118 return osl_File_E_INVAL;
1120 pItemImpl->nRefCount++;
1121 return osl_File_E_None;
1124 //#####################################################
1125 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
1127 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1129 if ( !pItemImpl )
1130 return osl_File_E_INVAL;
1132 if ( ! --pItemImpl->nRefCount )
1133 rtl_freeMemory( pItemImpl );
1134 return osl_File_E_None;
1137 //#####################################################
1138 // volume / file info handling functions
1139 //#####################################################
1141 //#####################################################
1142 static inline bool is_floppy_A_present()
1143 { return (GetLogicalDrives() & 1); }
1145 //#####################################################
1146 static inline bool is_floppy_B_present()
1147 { return (GetLogicalDrives() & 2); }
1149 //#####################################################
1150 bool is_floppy_volume_mount_point(const rtl::OUString& path)
1152 // determines if a volume mount point shows to a floppy
1153 // disk by comparing the unique volume names
1154 static const LPWSTR FLOPPY_A = L"A:\\";
1155 static const LPWSTR FLOPPY_B = L"B:\\";
1157 rtl::OUString p(path);
1158 osl::systemPathEnsureSeparator(p);
1160 TCHAR vn[51];
1161 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1163 TCHAR vnfloppy[51];
1164 if (is_floppy_A_present() &&
1165 GetVolumeNameForVolumeMountPoint(FLOPPY_A, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1166 (0 == wcscmp(vn, vnfloppy)))
1167 return true;
1169 if (is_floppy_B_present() &&
1170 GetVolumeNameForVolumeMountPoint(FLOPPY_B, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1171 (0 == wcscmp(vn, vnfloppy)))
1172 return true;
1174 return false;
1177 //################################################
1178 static bool is_floppy_drive(const rtl::OUString& path)
1180 static const LPWSTR FLOPPY_DRV_LETTERS = TEXT("AaBb");
1182 // we must take into account that even a floppy
1183 // drive may be mounted to a directory so checking
1184 // for the drive letter alone is not sufficient
1185 // we must compare the unique volume name with
1186 // that of the available floppy disks
1188 const sal_Unicode* pszPath = path.getStr();
1189 return ((wcschr(FLOPPY_DRV_LETTERS, pszPath[0]) && (L':' == pszPath[1])) || is_floppy_volume_mount_point(path));
1192 //#####################################################
1193 static bool is_volume_mount_point(const rtl::OUString& path)
1195 rtl::OUString p(path);
1196 osl::systemPathRemoveSeparator(p);
1198 bool is_volume_root = false;
1200 if (!is_floppy_drive(p))
1202 DWORD fattr = GetFileAttributes(reinterpret_cast<LPCTSTR>(p.getStr()));
1204 if ((INVALID_FILE_ATTRIBUTES != fattr) &&
1205 (FILE_ATTRIBUTE_REPARSE_POINT & fattr))
1207 WIN32_FIND_DATA find_data;
1208 HANDLE h_find = FindFirstFile(reinterpret_cast<LPCTSTR>(p.getStr()), &find_data);
1210 if (IsValidHandle(h_find) &&
1211 (FILE_ATTRIBUTE_REPARSE_POINT & find_data.dwFileAttributes) &&
1212 (IO_REPARSE_TAG_MOUNT_POINT == find_data.dwReserved0))
1214 is_volume_root = true;
1216 if (IsValidHandle(h_find))
1217 FindClose(h_find);
1220 return is_volume_root;
1223 //#############################################
1224 static UINT get_volume_mount_point_drive_type(const rtl::OUString& path)
1226 if (0 == path.getLength())
1227 return GetDriveType(NULL);
1229 rtl::OUString p(path);
1230 osl::systemPathEnsureSeparator(p);
1232 TCHAR vn[51];
1233 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1234 return GetDriveType(vn);
1236 return DRIVE_NO_ROOT_DIR;
1239 //#############################################
1240 static inline bool is_drivetype_request(sal_uInt32 field_mask)
1242 return (field_mask & osl_VolumeInfo_Mask_Attributes);
1245 //#############################################
1246 static oslFileError osl_get_drive_type(
1247 const rtl::OUString& path, oslVolumeInfo* pInfo)
1249 // GetDriveType fails on empty volume mount points
1250 // see Knowledge Base Q244089
1251 UINT drive_type;
1252 if (is_volume_mount_point(path))
1253 drive_type = get_volume_mount_point_drive_type(path);
1254 else
1255 drive_type = GetDriveType(reinterpret_cast<LPCTSTR>(path.getStr()));
1257 if (DRIVE_NO_ROOT_DIR == drive_type)
1258 return oslTranslateFileError(ERROR_INVALID_DRIVE);
1260 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1262 switch (drive_type)
1264 case DRIVE_CDROM:
1265 pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
1266 break;
1267 case DRIVE_REMOVABLE:
1268 pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
1269 if (is_floppy_drive(path))
1270 pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
1271 break;
1272 case DRIVE_FIXED:
1273 pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
1274 break;
1275 case DRIVE_RAMDISK:
1276 pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
1277 break;
1278 case DRIVE_REMOTE:
1279 pInfo->uAttributes |= osl_Volume_Attribute_Remote;
1280 break;
1281 case DRIVE_UNKNOWN:
1282 pInfo->uAttributes = 0;
1283 break;
1284 default:
1285 pInfo->uValidFields &= ~osl_VolumeInfo_Mask_Attributes;
1286 pInfo->uAttributes = 0;
1287 break;
1289 return osl_File_E_None;
1292 //#############################################
1293 static inline bool is_volume_space_info_request(sal_uInt32 field_mask)
1295 return (field_mask &
1296 (osl_VolumeInfo_Mask_TotalSpace |
1297 osl_VolumeInfo_Mask_UsedSpace |
1298 osl_VolumeInfo_Mask_FreeSpace));
1301 //#############################################
1302 static void get_volume_space_information(
1303 const rtl::OUString& path, oslVolumeInfo *pInfo)
1305 BOOL ret = GetDiskFreeSpaceEx(
1306 reinterpret_cast<LPCTSTR>(path.getStr()),
1307 (PULARGE_INTEGER)&(pInfo->uFreeSpace),
1308 (PULARGE_INTEGER)&(pInfo->uTotalSpace),
1309 NULL);
1311 if (ret)
1313 pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
1314 pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace |
1315 osl_VolumeInfo_Mask_UsedSpace |
1316 osl_VolumeInfo_Mask_FreeSpace;
1320 //#############################################
1321 static inline bool is_filesystem_attributes_request(sal_uInt32 field_mask)
1323 return (field_mask &
1324 (osl_VolumeInfo_Mask_MaxNameLength |
1325 osl_VolumeInfo_Mask_MaxPathLength |
1326 osl_VolumeInfo_Mask_FileSystemName |
1327 osl_VolumeInfo_Mask_FileSystemCaseHandling));
1330 //#############################################
1331 static oslFileError get_filesystem_attributes(
1332 const rtl::OUString& path, sal_uInt32 field_mask, oslVolumeInfo* pInfo)
1334 pInfo->uAttributes = 0;
1336 // osl_get_drive_type must be called first because
1337 // this function resets osl_VolumeInfo_Mask_Attributes
1338 // on failure
1339 if (is_drivetype_request(field_mask))
1341 oslFileError osl_error = osl_get_drive_type(path, pInfo);
1342 if (osl_File_E_None != osl_error)
1343 return osl_error;
1345 if (is_filesystem_attributes_request(field_mask))
1347 WCHAR vn[MAX_PATH];
1348 WCHAR fsn[MAX_PATH];
1349 DWORD serial;
1350 DWORD mcl;
1351 DWORD flags;
1353 LPCTSTR pszPath = reinterpret_cast<LPCTSTR>(path.getStr());
1354 if (GetVolumeInformation(pszPath, vn, MAX_PATH, &serial, &mcl, &flags, fsn, MAX_PATH))
1356 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
1357 pInfo->uMaxNameLength = mcl;
1359 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
1360 pInfo->uMaxPathLength = MAX_PATH;
1362 pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
1363 rtl_uString_newFromStr(&pInfo->ustrFileSystemName, reinterpret_cast<const sal_Unicode*>(fsn));
1365 // volumes (even NTFS) will always be considered case
1366 // insensitive because the Win32 API is not able to
1367 // deal with case sensitive volumes see M$ Knowledge Base
1368 // article 100625 that's why we never set the attribute
1369 // osl_Volume_Attribute_Case_Sensitive
1371 if (flags & FS_CASE_IS_PRESERVED)
1372 pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
1374 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1377 return osl_File_E_None;
1380 //#####################################################
1381 static bool path_get_parent(rtl::OUString& path)
1383 OSL_PRECOND(path.lastIndexOf(SLASH) == -1, "Path must not have slashes");
1385 if (!has_path_parent(path))
1387 sal_Int32 i = path.lastIndexOf(BACKSLASH);
1388 if (-1 < i)
1390 path = rtl::OUString(path.getStr(), i);
1391 return true;
1394 return false;
1397 //#####################################################
1398 static void path_travel_to_volume_root(const rtl::OUString& system_path, rtl::OUString& volume_root)
1400 rtl::OUString sys_path(system_path);
1402 while(!is_volume_mount_point(sys_path) && path_get_parent(sys_path))
1403 /**/;
1405 volume_root = sys_path;
1406 osl::systemPathEnsureSeparator(volume_root);
1409 //#############################################
1410 oslFileError SAL_CALL osl_getVolumeInformation(
1411 rtl_uString *ustrURL, oslVolumeInfo *pInfo, sal_uInt32 uFieldMask )
1413 if (!pInfo)
1414 return osl_File_E_INVAL;
1416 rtl::OUString system_path;
1417 oslFileError error = _osl_getSystemPathFromFileURL(ustrURL, &system_path.pData, sal_False);
1419 if (osl_File_E_None != error)
1420 return error;
1422 rtl::OUString volume_root;
1423 path_travel_to_volume_root(system_path, volume_root);
1425 pInfo->uValidFields = 0;
1427 if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None)
1428 return error;
1430 if (is_volume_space_info_request(uFieldMask))
1431 get_volume_space_information(volume_root, pInfo);
1433 if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
1435 pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
1436 osl_getFileURLFromSystemPath(volume_root.pData, (rtl_uString**)&pInfo->pDeviceHandle);
1439 return osl_File_E_None;
1442 //#####################################################
1443 static oslFileError SAL_CALL osl_getDriveInfo(
1444 oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask)
1446 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1447 TCHAR cDrive[3] = TEXT("A:");
1448 TCHAR cRoot[4] = TEXT("A:\\");
1450 if ( !pItemImpl )
1451 return osl_File_E_INVAL;
1453 pStatus->uValidFields = 0;
1455 cDrive[0] = pItemImpl->cDriveString[0];
1456 cRoot[0] = pItemImpl->cDriveString[0];
1458 if ( uFieldMask & osl_FileStatus_Mask_FileName )
1460 if ( pItemImpl->cDriveString[0] == '\\' && pItemImpl->cDriveString[1] == '\\' )
1462 LPCWSTR lpFirstBkSlash = wcschr( &pItemImpl->cDriveString[2], '\\' );
1464 if ( lpFirstBkSlash && lpFirstBkSlash[1] )
1466 LPCWSTR lpLastBkSlash = wcschr( &lpFirstBkSlash[1], '\\' );
1468 if ( lpLastBkSlash )
1469 rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]), lpLastBkSlash - lpFirstBkSlash - 1 );
1470 else
1471 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]) );
1472 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1475 else switch ( GetDriveType( cRoot ) )
1477 case DRIVE_REMOTE:
1479 TCHAR szBuffer[1024];
1480 DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szBuffer);
1481 DWORD dwBufsize = dwBufsizeConst;
1483 DWORD dwResult = WNetGetConnection( cDrive, szBuffer, &dwBufsize );
1484 if ( NO_ERROR == dwResult )
1486 TCHAR szFileName[dwBufsizeConst + 16];
1488 swprintf( szFileName, L"%s [%s]", cDrive, szBuffer );
1489 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
1491 else
1492 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
1494 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1495 break;
1496 case DRIVE_FIXED:
1498 TCHAR szVolumeNameBuffer[1024];
1499 DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szVolumeNameBuffer);
1501 if ( GetVolumeInformation( cRoot, szVolumeNameBuffer, dwBufsizeConst, NULL, NULL, NULL, NULL, 0 ) )
1503 TCHAR szFileName[dwBufsizeConst + 16];
1505 swprintf( szFileName, L"%s [%s]", cDrive, szVolumeNameBuffer );
1506 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
1508 else
1509 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
1511 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1512 break;
1513 case DRIVE_CDROM:
1514 case DRIVE_REMOVABLE:
1515 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1516 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cRoot) );
1517 break;
1518 case DRIVE_UNKNOWN:
1519 default:
1520 break;
1524 pStatus->eType = osl_File_Type_Volume;
1525 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1527 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1529 rtl_uString *ustrSystemPath = NULL;
1531 rtl_uString_newFromStr( &ustrSystemPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->cDriveString) );
1532 osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
1533 rtl_uString_release( ustrSystemPath );
1534 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1536 return osl_File_E_None;
1539 //#####################################################
1540 static oslFileError SAL_CALL osl_getServerInfo(
1541 oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask )
1543 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1544 if ( !pItemImpl )
1545 return osl_File_E_INVAL;
1547 pStatus->uValidFields = 0;
1549 // pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1551 // if ( _tcscmp( pItemImpl->FindData.cFileName, TEXT(".") ) == 0 )
1552 // rtl_uString_newFromAscii( &pStatus->ustrFileName, "/" );
1553 // else
1554 // rtl_uString_newFromStr( &pStatus->ustrFileName, pItemImpl->FindData.cFileName );
1556 pStatus->eType = osl_File_Type_Directory;
1557 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1559 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1561 rtl_uString *ustrSystemPath = NULL;
1563 rtl_uString_newFromStr( &ustrSystemPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->szFullPath) );
1564 osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
1565 rtl_uString_release( ustrSystemPath );
1566 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1568 return osl_File_E_None;
1571 //#############################################
1572 oslFileError SAL_CALL osl_getFileStatus(
1573 oslDirectoryItem Item,
1574 oslFileStatus *pStatus,
1575 sal_uInt32 uFieldMask )
1577 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1579 if ( !pItemImpl )
1580 return osl_File_E_INVAL;
1582 switch ( pItemImpl->uType )
1584 case DIRECTORYITEM_DRIVE:
1585 return osl_getDriveInfo( Item, pStatus, uFieldMask );
1586 case DIRECTORYITEM_SERVER:
1587 return osl_getServerInfo( Item, pStatus, uFieldMask );
1588 default:
1589 break;
1592 if ( uFieldMask & osl_FileStatus_Mask_Validate )
1594 HANDLE hFind = FindFirstFile( pItemImpl->szFullPath, &pItemImpl->FindData );
1596 if ( hFind != INVALID_HANDLE_VALUE )
1597 FindClose( hFind );
1598 else
1599 return oslTranslateFileError( GetLastError() );
1601 uFieldMask &= ~ osl_FileStatus_Mask_Validate;
1604 /* If no fields to retrieve left ignore pStatus */
1605 if ( !uFieldMask )
1606 return osl_File_E_None;
1608 /* Otherwise, this must be a valid pointer */
1609 if ( !pStatus )
1610 return osl_File_E_INVAL;
1612 if ( pStatus->uStructSize != sizeof(oslFileStatus) )
1613 return osl_File_E_INVAL;
1615 pStatus->uValidFields = 0;
1617 /* File time stamps */
1619 if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime) &&
1620 FileTimeToTimeValue( &pItemImpl->FindData.ftLastWriteTime, &pStatus->aModifyTime ) )
1621 pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime;
1623 if ( (uFieldMask & osl_FileStatus_Mask_AccessTime) &&
1624 FileTimeToTimeValue( &pItemImpl->FindData.ftLastAccessTime, &pStatus->aAccessTime ) )
1625 pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime;
1627 if ( (uFieldMask & osl_FileStatus_Mask_CreationTime) &&
1628 FileTimeToTimeValue( &pItemImpl->FindData.ftCreationTime, &pStatus->aCreationTime ) )
1629 pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime;
1631 /* Most of the fields are already set, regardless of requiered fields */
1633 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(pItemImpl->FindData.cFileName) );
1634 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1636 if ((FILE_ATTRIBUTE_REPARSE_POINT & pItemImpl->FindData.dwFileAttributes) &&
1637 (IO_REPARSE_TAG_MOUNT_POINT == pItemImpl->FindData.dwReserved0))
1638 pStatus->eType = osl_File_Type_Volume;
1639 else if (pItemImpl->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1640 pStatus->eType = osl_File_Type_Directory;
1641 else
1642 pStatus->eType = osl_File_Type_Regular;
1644 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1646 pStatus->uAttributes = pItemImpl->FindData.dwFileAttributes;
1647 pStatus->uValidFields |= osl_FileStatus_Mask_Attributes;
1649 pStatus->uFileSize = (sal_uInt64)pItemImpl->FindData.nFileSizeLow + ((sal_uInt64)pItemImpl->FindData.nFileSizeHigh << 32);
1650 pStatus->uValidFields |= osl_FileStatus_Mask_FileSize;
1652 if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL )
1654 rtl_uString *ustrFullPath = NULL;
1656 rtl_uString_newFromStr( &ustrFullPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->szFullPath) );
1657 osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrLinkTargetURL );
1658 rtl_uString_release( ustrFullPath );
1660 pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
1663 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1665 rtl_uString *ustrFullPath = NULL;
1668 if ( !pItemImpl->bFullPathNormalized )
1670 GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
1671 pItemImpl->bFullPathNormalized = TRUE;
1673 rtl_uString_newFromStr( &ustrFullPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->szFullPath) );
1674 osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrFileURL );
1675 rtl_uString_release( ustrFullPath );
1676 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1679 return osl_File_E_None;
1682 //#####################################################
1683 // file attributes handling functions
1684 //#####################################################
1686 //#############################################
1687 oslFileError SAL_CALL osl_setFileAttributes(
1688 rtl_uString *ustrFileURL,
1689 sal_uInt64 uAttributes )
1691 oslFileError error;
1692 rtl_uString *ustrSysPath = NULL;
1693 DWORD dwFileAttributes;
1694 BOOL fSuccess;
1696 // Converts the normalized path into a systempath
1697 error = _osl_getSystemPathFromFileURL( ustrFileURL, &ustrSysPath, sal_False );
1699 if ( osl_File_E_None != error )
1700 return error;
1702 dwFileAttributes = GetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)) );
1704 if ( (DWORD)-1 != dwFileAttributes )
1706 dwFileAttributes &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN);
1708 if ( uAttributes & osl_File_Attribute_ReadOnly )
1709 dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
1711 if ( uAttributes & osl_File_Attribute_Hidden )
1712 dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1714 fSuccess = SetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)), dwFileAttributes );
1716 else
1717 fSuccess = FALSE;
1719 if ( !fSuccess )
1720 error = oslTranslateFileError( GetLastError() );
1722 rtl_uString_release( ustrSysPath );
1724 return error;
1727 //#####################################################
1728 oslFileError SAL_CALL osl_setFileTime(
1729 rtl_uString *filePath,
1730 const TimeValue *aCreationTime,
1731 const TimeValue *aLastAccessTime,
1732 const TimeValue *aLastWriteTime)
1734 oslFileError error;
1735 rtl_uString *sysPath=NULL;
1736 FILETIME *lpCreationTime=NULL;
1737 FILETIME *lpLastAccessTime=NULL;
1738 FILETIME *lpLastWriteTime=NULL;
1739 FILETIME ftCreationTime;
1740 FILETIME ftLastAccessTime;
1741 FILETIME ftLastWriteTime;
1742 HANDLE hFile;
1743 BOOL fSuccess;
1746 error=_osl_getSystemPathFromFileURL(filePath, &sysPath, sal_False);
1748 if (error==osl_File_E_INVAL)
1749 return error;
1751 hFile=CreateFileW(reinterpret_cast<LPCWSTR>(rtl_uString_getStr(sysPath)), GENERIC_WRITE, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1752 rtl_uString_release(sysPath);
1754 if (hFile==INVALID_HANDLE_VALUE)
1755 return osl_File_E_NOENT;
1757 if (TimeValueToFileTime(aCreationTime, &ftCreationTime))
1758 lpCreationTime=&ftCreationTime;
1760 if (TimeValueToFileTime(aLastAccessTime, &ftLastAccessTime))
1761 lpLastAccessTime=&ftLastAccessTime;
1763 if (TimeValueToFileTime(aLastWriteTime, &ftLastWriteTime))
1764 lpLastWriteTime=&ftLastWriteTime;
1766 fSuccess=SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
1768 CloseHandle(hFile);
1770 if (!fSuccess)
1771 return osl_File_E_INVAL;
1772 else
1773 return osl_File_E_None;