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