update dev300-m57
[ooovba.git] / sal / osl / w32 / file.cxx
blob4e7994c52cb1911581dc7c9d6d33398b47520208
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 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sal.hxx"
34 #define UNICODE
35 #define _UNICODE
36 #define _WIN32_WINNT 0x0500
37 #include "systools\win32\uwinapi.h"
39 #include "path_helper.hxx"
41 #include "sal/types.h"
43 #include "osl/file.hxx"
44 #include "osl/diagnose.h"
45 #include "rtl/ustring.hxx"
46 #include "rtl/alloc.h"
47 #include "rtl/tencinfo.h"
48 #include "osl/thread.h"
49 #include "osl/mutex.h"
50 #include "rtl/byteseq.h"
51 #include "osl/time.h"
52 //#include <rtl/logfile.h>
53 #include <stdio.h>
55 #define WIN32_LEAN_AND_MEAN
56 #include <windows.h>
57 #include <tchar.h>
59 #ifdef __MINGW32__
60 #include <wchar.h>
61 #include <ctype.h>
62 #endif
64 #include <malloc.h>
65 #include <algorithm>
66 #include <limits>
68 #ifdef max /* conflict w/ std::numeric_limits<T>::max() */
69 #undef max
70 #endif
72 //#####################################################
73 // BEGIN global
74 //#####################################################
76 extern "C" oslMutex g_CurrentDirectoryMutex; /* Initialized in dllentry.c */
77 oslMutex g_CurrentDirectoryMutex;
79 //#####################################################
80 extern "C" BOOL TimeValueToFileTime(const TimeValue *cpTimeVal, FILETIME *pFTime)
82 SYSTEMTIME BaseSysTime;
83 FILETIME BaseFileTime;
84 FILETIME FTime;
85 __int64 localTime;
86 BOOL fSuccess = FALSE;
88 BaseSysTime.wYear = 1970;
89 BaseSysTime.wMonth = 1;
90 BaseSysTime.wDayOfWeek = 0;
91 BaseSysTime.wDay = 1;
92 BaseSysTime.wHour = 0;
93 BaseSysTime.wMinute = 0;
94 BaseSysTime.wSecond = 0;
95 BaseSysTime.wMilliseconds = 0;
97 if (cpTimeVal==NULL)
98 return fSuccess;
100 if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
102 __int64 timeValue;
103 localTime=cpTimeVal->Seconds*(__int64)10000000+cpTimeVal->Nanosec/100;
104 *(__int64 *)&FTime=localTime;
105 fSuccess = 0 <= (timeValue= *((__int64 *)&BaseFileTime) + *((__int64 *) &FTime));
106 if (fSuccess)
107 *(__int64 *)pFTime=timeValue;
109 return fSuccess;
112 //#####################################################
113 extern "C" BOOL FileTimeToTimeValue(const FILETIME *cpFTime, TimeValue *pTimeVal)
115 SYSTEMTIME BaseSysTime;
116 FILETIME BaseFileTime;
117 BOOL fSuccess = FALSE; /* Assume failure */
119 BaseSysTime.wYear = 1970;
120 BaseSysTime.wMonth = 1;
121 BaseSysTime.wDayOfWeek = 0;
122 BaseSysTime.wDay = 1;
123 BaseSysTime.wHour = 0;
124 BaseSysTime.wMinute = 0;
125 BaseSysTime.wSecond = 0;
126 BaseSysTime.wMilliseconds = 0;
128 if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
130 __int64 Value;
132 fSuccess = 0 <= (Value = *((__int64 *)cpFTime) - *((__int64 *)&BaseFileTime));
134 if ( fSuccess )
136 pTimeVal->Seconds = (unsigned long) (Value / 10000000L);
137 pTimeVal->Nanosec = (unsigned long)((Value % 10000000L) * 100);
140 return fSuccess;
143 //#####################################################
144 extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle(HANDLE hFile)
146 if ( IsValidHandle(hFile) )
147 return (oslFileHandle)hFile;
148 else
149 return NULL;
152 //#####################################################
153 // End global
154 //#####################################################
157 using namespace osl;
159 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
161 // Allocate n number of t's on the stack return a pointer to it in p
162 #ifdef __MINGW32__
163 #define STACK_ALLOC(p, t, n) (p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));
164 #else
165 #define STACK_ALLOC(p, t, n) __try {(p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));} \
166 __except(EXCEPTION_EXECUTE_HANDLER) {(p) = NULL;}
167 #endif
169 #if OSL_DEBUG_LEVEL > 0
170 #define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ? (void)0 : _osl_warnFile( msg, file ) )
171 #else
172 #define OSL_ENSURE_FILE( cond, msg, file ) ((void)0)
173 #endif
175 #define PATHTYPE_ERROR 0
176 #define PATHTYPE_RELATIVE 1
177 #define PATHTYPE_ABSOLUTE_UNC 2
178 #define PATHTYPE_ABSOLUTE_LOCAL 3
179 #define PATHTYPE_MASK_TYPE 0xFF
180 #define PATHTYPE_IS_VOLUME 0x0100
181 #define PATHTYPE_IS_SERVER 0x0200
183 #define VALIDATEPATH_NORMAL 0x0000
184 #define VALIDATEPATH_ALLOW_WILDCARDS 0x0001
185 #define VALIDATEPATH_ALLOW_ELLIPSE 0x0002
186 #define VALIDATEPATH_ALLOW_RELATIVE 0x0004
187 #define VALIDATEPATH_ALLOW_UNC 0x0008
188 #define VALIDATEPATH_ALLOW_INVALID_SPACE_AND_PERIOD 0x0010
190 #define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\"
192 typedef struct {
193 UINT uType;
195 union {
196 WIN32_FIND_DATA FindData;
197 TCHAR cDriveString[MAX_PATH];
199 TCHAR szFullPath[MAX_PATH];
200 BOOL bFullPathNormalized;
201 int nRefCount;
202 }DirectoryItem_Impl;
204 #define DIRECTORYTYPE_LOCALROOT 0
205 #define DIRECTORYTYPE_NETROOT 1
206 #define DIRECTORYTYPE_NETRESORCE 2
207 #define DIRECTORYTYPE_FILESYSTEM 3
209 #define DIRECTORYITEM_DRIVE 0
210 #define DIRECTORYITEM_FILE 1
211 #define DIRECTORYITEM_SERVER 2
213 typedef struct {
214 UINT uType;
215 union {
216 HANDLE hDirectory;
217 HANDLE hEnumDrives;
219 TCHAR szDirectoryPath[MAX_PATH];
220 } Directory_Impl;
222 /* Different types of paths */
223 typedef enum _PATHTYPE
225 PATHTYPE_SYNTAXERROR = 0,
226 PATHTYPE_NETROOT,
227 PATHTYPE_NETSERVER,
228 PATHTYPE_VOLUME,
229 PATHTYPE_FILE
230 } PATHTYPE;
233 namespace /* private */
235 // forward
236 void _osl_warnFile(const char*, rtl_uString*);
237 oslFileError SAL_CALL _osl_getFileURLFromSystemPath(rtl_uString* , rtl_uString**);
238 DWORD WINAPI IsValidFilePath(rtl_uString*, LPCTSTR*, DWORD, rtl_uString**);
239 HANDLE WINAPI OpenLogicalDrivesEnum(void);
240 BOOL WINAPI EnumLogicalDrives(HANDLE, LPTSTR);
241 BOOL WINAPI CloseLogicalDrivesEnum(HANDLE);
242 HANDLE WINAPI OpenDirectory(LPCTSTR);
243 BOOL WINAPI CloseDirectory(HANDLE);
244 BOOL WINAPI EnumDirectory(HANDLE, LPWIN32_FIND_DATA);
245 DWORD WINAPI GetCaseCorrectPathName(LPCTSTR, LPTSTR, DWORD);
246 oslFileError SAL_CALL _osl_getSystemPathFromFileURL(rtl_uString*, rtl_uString**, sal_Bool);
248 /* OS error to errno values mapping table */
249 struct errentry {
250 unsigned long oscode; /* OS return value */
251 int errnocode; /* System V error code */
254 struct errentry errtable[] = {
255 { ERROR_SUCCESS, osl_File_E_None }, /* 0 */
256 { ERROR_INVALID_FUNCTION, osl_File_E_INVAL }, /* 1 */
257 { ERROR_FILE_NOT_FOUND, osl_File_E_NOENT }, /* 2 */
258 { ERROR_PATH_NOT_FOUND, osl_File_E_NOENT }, /* 3 */
259 { ERROR_TOO_MANY_OPEN_FILES, osl_File_E_MFILE }, /* 4 */
260 { ERROR_ACCESS_DENIED, osl_File_E_ACCES }, /* 5 */
261 { ERROR_INVALID_HANDLE, osl_File_E_BADF }, /* 6 */
262 { ERROR_ARENA_TRASHED, osl_File_E_NOMEM }, /* 7 */
263 { ERROR_NOT_ENOUGH_MEMORY, osl_File_E_NOMEM }, /* 8 */
264 { ERROR_INVALID_BLOCK, osl_File_E_NOMEM }, /* 9 */
265 { ERROR_BAD_ENVIRONMENT, osl_File_E_2BIG }, /* 10 */
266 { ERROR_BAD_FORMAT, osl_File_E_NOEXEC }, /* 11 */
267 { ERROR_INVALID_ACCESS, osl_File_E_INVAL }, /* 12 */
268 { ERROR_INVALID_DATA, osl_File_E_INVAL }, /* 13 */
269 { ERROR_INVALID_DRIVE, osl_File_E_NOENT }, /* 15 */
270 { ERROR_CURRENT_DIRECTORY, osl_File_E_ACCES }, /* 16 */
271 { ERROR_NOT_SAME_DEVICE, osl_File_E_XDEV }, /* 17 */
272 { ERROR_NO_MORE_FILES, osl_File_E_NOENT }, /* 18 */
273 { ERROR_NOT_READY, osl_File_E_NOTREADY }, /* 21 */
274 { ERROR_LOCK_VIOLATION, osl_File_E_ACCES }, /* 33 */
275 { ERROR_BAD_NETPATH, osl_File_E_NOENT }, /* 53 */
276 { ERROR_NETWORK_ACCESS_DENIED, osl_File_E_ACCES }, /* 65 */
277 { ERROR_BAD_NET_NAME, osl_File_E_NOENT }, /* 67 */
278 { ERROR_FILE_EXISTS, osl_File_E_EXIST }, /* 80 */
279 { ERROR_CANNOT_MAKE, osl_File_E_ACCES }, /* 82 */
280 { ERROR_FAIL_I24, osl_File_E_ACCES }, /* 83 */
281 { ERROR_INVALID_PARAMETER, osl_File_E_INVAL }, /* 87 */
282 { ERROR_NO_PROC_SLOTS, osl_File_E_AGAIN }, /* 89 */
283 { ERROR_DRIVE_LOCKED, osl_File_E_ACCES }, /* 108 */
284 { ERROR_BROKEN_PIPE, osl_File_E_PIPE }, /* 109 */
285 { ERROR_DISK_FULL, osl_File_E_NOSPC }, /* 112 */
286 { ERROR_INVALID_TARGET_HANDLE, osl_File_E_BADF }, /* 114 */
287 { ERROR_INVALID_HANDLE, osl_File_E_INVAL }, /* 124 */
288 { ERROR_WAIT_NO_CHILDREN, osl_File_E_CHILD }, /* 128 */
289 { ERROR_CHILD_NOT_COMPLETE, osl_File_E_CHILD }, /* 129 */
290 { ERROR_DIRECT_ACCESS_HANDLE, osl_File_E_BADF }, /* 130 */
291 { ERROR_NEGATIVE_SEEK, osl_File_E_INVAL }, /* 131 */
292 { ERROR_SEEK_ON_DEVICE, osl_File_E_ACCES }, /* 132 */
293 { ERROR_DIR_NOT_EMPTY, osl_File_E_NOTEMPTY }, /* 145 */
294 { ERROR_NOT_LOCKED, osl_File_E_ACCES }, /* 158 */
295 { ERROR_BAD_PATHNAME, osl_File_E_NOENT }, /* 161 */
296 { ERROR_MAX_THRDS_REACHED, osl_File_E_AGAIN }, /* 164 */
297 { ERROR_LOCK_FAILED, osl_File_E_ACCES }, /* 167 */
298 { ERROR_ALREADY_EXISTS, osl_File_E_EXIST }, /* 183 */
299 { ERROR_FILENAME_EXCED_RANGE, osl_File_E_NOENT }, /* 206 */
300 { ERROR_NESTING_NOT_ALLOWED, osl_File_E_AGAIN }, /* 215 */
301 { ERROR_DIRECTORY, osl_File_E_NOENT }, /* 267 */
302 { ERROR_NOT_ENOUGH_QUOTA, osl_File_E_NOMEM }, /* 1816 */
303 { ERROR_UNEXP_NET_ERR, osl_File_E_NETWORK } /* 59 */
306 /* The following two constants must be the minimum and maximum
307 values in the (contiguous) range of osl_File_E_xec Failure errors. */
308 #define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
309 #define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
311 /* These are the low and high value in the range of errors that are
312 access violations */
313 #define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
314 #define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
316 //#####################################################
317 oslFileError MapError(DWORD dwError)
319 for (int i = 0; i < ELEMENTS_OF_ARRAY(errtable); ++i )
321 if (dwError == errtable[i].oscode)
322 return static_cast<oslFileError>(errtable[i].errnocode);
325 /* The error code wasn't in the table. We check for a range of
326 osl_File_E_ACCES errors or exec failure errors (ENOEXEC).
327 Otherwise osl_File_E_INVAL is returned. */
328 if ( dwError >= MIN_EACCES_RANGE && dwError <= MAX_EACCES_RANGE)
329 return osl_File_E_ACCES;
330 else if ( dwError >= MIN_EXEC_ERROR && dwError <= MAX_EXEC_ERROR)
331 return osl_File_E_NOEXEC;
332 else
333 return osl_File_E_INVAL;
336 //#####################################################
337 oslFileError SAL_CALL osl_openLocalRoot(
338 rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
340 rtl_uString *strSysPath = NULL;
341 oslFileError error;
343 if ( !pDirectory )
344 return osl_File_E_INVAL;
346 *pDirectory = NULL;
348 error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysPath, sal_False );
350 if ( osl_File_E_None == error )
352 Directory_Impl *pDirImpl;
354 pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory( sizeof(Directory_Impl)));
355 _tcscpy( pDirImpl->szDirectoryPath, reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysPath)) );
357 /* Append backslash if neccessary */
359 /* @@@ToDo
360 use function ensure backslash
362 if ( pDirImpl->szDirectoryPath[_tcslen(pDirImpl->szDirectoryPath) - 1] != L'\\' )
363 _tcscat( pDirImpl->szDirectoryPath, L"\\" );
365 pDirImpl->uType = DIRECTORYTYPE_LOCALROOT;
366 pDirImpl->hEnumDrives = OpenLogicalDrivesEnum();
368 /* @@@ToDo
369 Use IsValidHandle(...)
371 if ( pDirImpl->hEnumDrives != INVALID_HANDLE_VALUE )
373 *pDirectory = (oslDirectory)pDirImpl;
374 error = osl_File_E_None;
376 else
378 if ( pDirImpl )
379 rtl_freeMemory(pDirImpl);
381 error = MapError( GetLastError() );
384 rtl_uString_release( strSysPath );
386 return error;
389 //#####################################################
390 oslFileError SAL_CALL osl_openFileDirectory(
391 rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
393 // MT: Done in osl_openDirectory!
394 // rtl_uString *strSysPath = NULL;
395 oslFileError error;
397 //MT: Not done in osl_openNetworkServer, why here?
398 if ( !pDirectory )
399 return osl_File_E_INVAL;
401 *pDirectory = NULL;
403 // MT: Done in osl_openDirectory!
404 // error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysPath, sal_False );
405 // if ( osl_File_E_None == error )
407 Directory_Impl *pDirImpl;
409 pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
410 _tcscpy( pDirImpl->szDirectoryPath, reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strDirectoryPath)) );
412 /* Append backslash if neccessary */
414 /* @@@ToDo
415 use function ensure backslash
417 if ( pDirImpl->szDirectoryPath[_tcslen(pDirImpl->szDirectoryPath) - 1] != L'\\' )
418 _tcscat( pDirImpl->szDirectoryPath, L"\\" );
419 // MT: ???
420 // GetCaseCorrectPathName( pDirImpl->szDirectoryPath, pDirImpl->szDirectoryPath, sizeof(pDirImpl->szDirectoryPath) );
422 pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM;
423 pDirImpl->hDirectory = OpenDirectory( pDirImpl->szDirectoryPath );
425 if ( pDirImpl->hDirectory )
427 *pDirectory = (oslDirectory)pDirImpl;
428 error = osl_File_E_None;
430 else
432 if ( pDirImpl )
433 rtl_freeMemory(pDirImpl);
435 error = MapError( GetLastError() );
438 // rtl_uString_release( strSysPath );
440 return error;
443 typedef struct tagDIRECTORY
445 HANDLE hFind;
446 WIN32_FIND_DATA aFirstData;
447 } DIRECTORY, *PDIRECTORY, FAR *LPDIRECTORY;
449 //#####################################################
450 HANDLE WINAPI OpenDirectory(LPCTSTR lpszPath)
452 LPDIRECTORY pDirectory = (LPDIRECTORY)HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY));
454 if (pDirectory)
456 TCHAR szFileMask[MAX_PATH];
457 int nLen;
459 _tcscpy( szFileMask, lpszPath );
460 nLen = _tcslen( szFileMask );
462 if (nLen && szFileMask[nLen-1] != '\\')
463 _tcscat(szFileMask, TEXT("\\*.*"));
464 else
465 _tcscat(szFileMask, TEXT("*.*"));
467 pDirectory->hFind = FindFirstFile(szFileMask, &pDirectory->aFirstData);
469 if (!IsValidHandle(pDirectory->hFind))
471 if ( GetLastError() != ERROR_NO_MORE_FILES )
473 HeapFree(GetProcessHeap(), 0, pDirectory);
474 pDirectory = NULL;
478 return (HANDLE)pDirectory;
481 //#####################################################
482 BOOL WINAPI CloseDirectory(HANDLE hDirectory)
484 BOOL fSuccess = FALSE;
485 LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
487 if (pDirectory)
489 if (IsValidHandle(pDirectory->hFind))
490 fSuccess = FindClose(pDirectory->hFind);
492 fSuccess = HeapFree(GetProcessHeap(), 0, pDirectory) && fSuccess;
494 else
495 SetLastError(ERROR_INVALID_HANDLE);
497 return fSuccess;
500 //#####################################################
501 BOOL WINAPI EnumDirectory(HANDLE hDirectory, LPWIN32_FIND_DATA pFindData)
503 BOOL fSuccess = FALSE;
504 LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
506 if ( pDirectory )
508 BOOL fValid;
512 if ( pDirectory->aFirstData.cFileName[0] )
514 *pFindData = pDirectory->aFirstData;
515 fSuccess = TRUE;
516 pDirectory->aFirstData.cFileName[0] = 0;
518 else if ( IsValidHandle( pDirectory->hFind ) )
519 fSuccess = FindNextFile( pDirectory->hFind, pFindData );
520 else
522 fSuccess = FALSE;
523 SetLastError( ERROR_NO_MORE_FILES );
526 fValid = fSuccess && _tcscmp( TEXT("."), pFindData->cFileName ) != 0 && _tcscmp( TEXT(".."), pFindData->cFileName ) != 0;
528 } while( fSuccess && !fValid );
530 else
531 SetLastError( ERROR_INVALID_HANDLE );
533 return fSuccess;
536 //#####################################################
537 oslFileError SAL_CALL osl_openNetworkServer(rtl_uString *strSysDirPath, oslDirectory *pDirectory)
539 NETRESOURCEW aNetResource;
540 HANDLE hEnum;
541 DWORD dwError;
543 ZeroMemory( &aNetResource, sizeof(aNetResource) );
545 aNetResource.lpRemoteName = reinterpret_cast<LPWSTR>(strSysDirPath->buffer);
547 dwError = WNetOpenEnumW(
548 RESOURCE_GLOBALNET,
549 RESOURCETYPE_DISK,
550 RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER,
551 &aNetResource,
552 &hEnum );
554 if ( ERROR_SUCCESS == dwError )
556 Directory_Impl *pDirImpl;
558 pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
559 pDirImpl->uType = DIRECTORYTYPE_NETROOT;
560 pDirImpl->hDirectory = hEnum;
561 *pDirectory = (oslDirectory)pDirImpl;
563 return MapError( dwError );
566 //#####################################################
567 oslFileError SAL_CALL osl_getNextNetResource(
568 oslDirectory Directory,
569 oslDirectoryItem *pItem,
570 sal_uInt32 uHint )
572 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
573 DirectoryItem_Impl *pItemImpl = NULL;
574 BYTE buffer[16384];
575 LPNETRESOURCEW lpNetResource = (LPNETRESOURCEW)buffer;
576 DWORD dwError, dwCount, dwBufSize;
578 uHint = uHint; /* to get no warning */
580 if ( !pItem )
581 return osl_File_E_INVAL;
583 *pItem = NULL;
585 if ( !pDirImpl )
586 return osl_File_E_INVAL;
588 dwCount = 1;
589 dwBufSize = sizeof(buffer);
590 dwError = WNetEnumResource( pDirImpl->hDirectory, &dwCount, lpNetResource, &dwBufSize );
592 switch ( dwError )
594 case NO_ERROR:
595 case ERROR_MORE_DATA:
597 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
598 if ( !pItemImpl )
599 return osl_File_E_NOMEM;
601 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
602 pItemImpl->uType = DIRECTORYITEM_DRIVE;
603 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
605 wcscpy( pItemImpl->cDriveString, lpNetResource->lpRemoteName );
607 *pItem = pItemImpl;
609 return osl_File_E_None;
610 case ERROR_NO_MORE_ITEMS:
611 return osl_File_E_NOENT;
612 default:
613 return MapError( dwError );
617 //#####################################################
618 oslFileError SAL_CALL osl_getNextDrive(
619 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
621 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
622 DirectoryItem_Impl *pItemImpl = NULL;
623 BOOL fSuccess;
625 uHint = uHint; /* avoid warnings */
627 if ( !pItem )
628 return osl_File_E_INVAL;
630 *pItem = NULL;
632 if ( !pDirImpl )
633 return osl_File_E_INVAL;
635 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
636 if ( !pItemImpl )
637 return osl_File_E_NOMEM;
640 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
641 pItemImpl->uType = DIRECTORYITEM_DRIVE;
642 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
643 fSuccess = EnumLogicalDrives( pDirImpl->hEnumDrives, pItemImpl->cDriveString );
645 if ( fSuccess )
647 *pItem = pItemImpl;
648 return osl_File_E_None;
650 else
652 rtl_freeMemory( pItemImpl );
653 return MapError( GetLastError() );
657 //#####################################################
658 oslFileError SAL_CALL osl_getNextFileItem(
659 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
661 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
662 DirectoryItem_Impl *pItemImpl = NULL;
663 BOOL fFound;
665 uHint = uHint; /* avoid warnings */
667 if ( !pItem )
668 return osl_File_E_INVAL;
670 *pItem = NULL;
672 if ( !pDirImpl )
673 return osl_File_E_INVAL;
675 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
676 if ( !pItemImpl )
677 return osl_File_E_NOMEM;
679 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
680 fFound = EnumDirectory( pDirImpl->hDirectory, &pItemImpl->FindData );
682 if ( fFound )
684 pItemImpl->uType = DIRECTORYITEM_FILE;
685 pItemImpl->nRefCount = 1;
686 _tcscpy( pItemImpl->szFullPath, pDirImpl->szDirectoryPath );
687 _tcscat( pItemImpl->szFullPath, pItemImpl->FindData.cFileName );
688 pItemImpl->bFullPathNormalized = FALSE;
689 *pItem = (oslDirectoryItem)pItemImpl;
690 return osl_File_E_None;
692 else
694 rtl_freeMemory( pItemImpl );
695 return MapError( GetLastError() );
699 //#####################################################
700 oslFileError SAL_CALL osl_getDriveInfo(
701 oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask)
703 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
704 TCHAR cDrive[3] = TEXT("A:");
705 TCHAR cRoot[4] = TEXT("A:\\");
707 if ( !pItemImpl )
708 return osl_File_E_INVAL;
710 pStatus->uValidFields = 0;
712 cDrive[0] = pItemImpl->cDriveString[0];
713 cRoot[0] = pItemImpl->cDriveString[0];
715 if ( uFieldMask & osl_FileStatus_Mask_FileName )
717 if ( pItemImpl->cDriveString[0] == '\\' &&
718 pItemImpl->cDriveString[1] == '\\' )
720 LPCWSTR lpFirstBkSlash = wcschr( &pItemImpl->cDriveString[2], '\\' );
722 if ( lpFirstBkSlash && lpFirstBkSlash[1] )
724 LPCWSTR lpLastBkSlash = wcschr( &lpFirstBkSlash[1], '\\' );
726 if ( lpLastBkSlash )
727 rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]), lpLastBkSlash - lpFirstBkSlash - 1 );
728 else
729 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]) );
730 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
733 else switch ( GetDriveType( cRoot ) )
735 case DRIVE_REMOTE:
737 TCHAR szBuffer[1024];
738 DWORD dwBufsize = ELEMENTS_OF_ARRAY(szBuffer);
739 DWORD dwResult = WNetGetConnection( cDrive, szBuffer, &dwBufsize );
741 if ( NO_ERROR == dwResult )
743 TCHAR szFileName[ELEMENTS_OF_ARRAY(szBuffer) + 16];
745 swprintf( szFileName, L"%s [%s]", cDrive, szBuffer );
746 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
748 else
749 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
751 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
752 break;
753 case DRIVE_FIXED:
755 TCHAR szVolumeNameBuffer[1024];
757 if ( GetVolumeInformation( cRoot, szVolumeNameBuffer, ELEMENTS_OF_ARRAY(szVolumeNameBuffer), NULL, NULL, NULL, NULL, 0 ) )
759 TCHAR szFileName[ELEMENTS_OF_ARRAY(szVolumeNameBuffer) + 16];
761 swprintf( szFileName, L"%s [%s]", cDrive, szVolumeNameBuffer );
762 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
764 else
765 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
767 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
768 break;
769 case DRIVE_CDROM:
770 case DRIVE_REMOVABLE:
771 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
772 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cRoot) );
773 break;
774 case DRIVE_UNKNOWN:
775 default:
776 break;
780 pStatus->eType = osl_File_Type_Volume;
781 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
783 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
785 rtl_uString *ustrSystemPath = NULL;
787 rtl_uString_newFromStr( &ustrSystemPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->cDriveString) );
788 osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
789 rtl_uString_release( ustrSystemPath );
790 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
792 return osl_File_E_None;
795 //#####################################################
796 oslFileError SAL_CALL osl_getServerInfo(
797 oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask )
799 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
801 if ( !pItemImpl )
802 return osl_File_E_INVAL;
804 pStatus->uValidFields = 0;
806 // pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
808 // if ( _tcscmp( pItemImpl->FindData.cFileName, TEXT(".") ) == 0 )
809 // rtl_uString_newFromAscii( &pStatus->ustrFileName, "/" );
810 // else
811 // rtl_uString_newFromStr( &pStatus->ustrFileName, pItemImpl->FindData.cFileName );
813 pStatus->eType = osl_File_Type_Directory;
814 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
816 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
818 rtl_uString *ustrSystemPath = NULL;
820 rtl_uString_newFromStr( &ustrSystemPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->szFullPath) );
821 osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
822 rtl_uString_release( ustrSystemPath );
823 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
825 return osl_File_E_None;
828 typedef struct tagDRIVEENUM {
829 LPCTSTR lpIdent;
830 TCHAR cBuffer[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
831 LPCTSTR lpCurrent;
832 } DRIVEENUM, * PDRIVEENUM, FAR * LPDRIVEENUM;
834 //#####################################################
835 HANDLE WINAPI OpenLogicalDrivesEnum(void)
837 LPDRIVEENUM pEnum = NULL;
839 pEnum = (LPDRIVEENUM)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM) );
841 if ( pEnum )
843 DWORD dwNumCopied = GetLogicalDriveStrings( (sizeof(pEnum->cBuffer) - 1) / sizeof(TCHAR), pEnum->cBuffer );
845 if ( dwNumCopied && dwNumCopied < sizeof(pEnum->cBuffer) / sizeof(TCHAR) )
847 pEnum->lpCurrent = pEnum->cBuffer;
848 pEnum->lpIdent = L"tagDRIVEENUM";
850 else
852 HeapFree( GetProcessHeap(), 0, pEnum );
853 pEnum = NULL;
856 return pEnum ? (HANDLE)pEnum : INVALID_HANDLE_VALUE;
859 //#####################################################
860 BOOL WINAPI EnumLogicalDrives(HANDLE hEnum, LPTSTR lpBuffer)
862 BOOL fSuccess = FALSE;
863 LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
865 if ( pEnum )
867 int nLen = _tcslen( pEnum->lpCurrent );
869 if ( nLen )
871 CopyMemory( lpBuffer, pEnum->lpCurrent, (nLen + 1) * sizeof(TCHAR) );
872 pEnum->lpCurrent += nLen + 1;
873 fSuccess = TRUE;
875 else
876 SetLastError( ERROR_NO_MORE_FILES );
878 else
879 SetLastError( ERROR_INVALID_HANDLE );
881 return fSuccess;
884 //#####################################################
885 BOOL WINAPI CloseLogicalDrivesEnum(HANDLE hEnum)
887 BOOL fSuccess = FALSE;
888 LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
890 if ( pEnum )
892 HeapFree( GetProcessHeap(), 0, pEnum );
893 fSuccess = TRUE;
895 else
896 SetLastError( ERROR_INVALID_HANDLE );
898 return fSuccess;
901 //#####################################################
902 //Undocumented in SHELL32.DLL ordinal 35
903 BOOL WINAPI PathRemoveFileSpec(LPTSTR lpPath)
905 BOOL fSuccess = FALSE; // Assume failure
906 LPTSTR lpLastBkSlash = _tcsrchr( lpPath, '\\' );
907 LPTSTR lpLastSlash = _tcsrchr( lpPath, '/' );
908 LPTSTR lpLastDelimiter = lpLastSlash > lpLastBkSlash ? lpLastSlash : lpLastBkSlash;
910 if ( lpLastDelimiter )
912 if ( 0 == *(lpLastDelimiter + 1) )
914 if ( lpLastDelimiter > lpPath && *(lpLastDelimiter - 1) != ':' )
916 *lpLastDelimiter = 0;
917 fSuccess = TRUE;
920 else
922 *(++lpLastDelimiter) = 0;
923 fSuccess = TRUE;
926 return fSuccess;
929 //#####################################################
930 // Undocumented in SHELL32.DLL ordinal 32
931 LPTSTR WINAPI PathAddBackslash(LPTSTR lpPath)
933 LPTSTR lpEndPath = NULL;
935 if ( lpPath )
937 int nLen = _tcslen(lpPath);
939 if ( !nLen || lpPath[nLen-1] != '\\' && lpPath[nLen-1] != '/' && nLen < MAX_PATH - 1 )
941 lpEndPath = lpPath + nLen;
942 *lpEndPath++ = '\\';
943 *lpEndPath = 0;
946 return lpEndPath;
949 #if 1
950 //#####################################################
951 // Same as GetLongPathName but also 95/NT4
952 DWORD WINAPI GetCaseCorrectPathNameEx(
953 LPCTSTR lpszShortPath, // file name
954 LPTSTR lpszLongPath, // path buffer
955 DWORD cchBuffer, // size of path buffer
956 DWORD nSkipLevels
959 // log file doesn't work, because initialization of rtl log init() calls this method...
960 // RTL_LOGFILE_TRACE1( "SAL: GetCaseCorrectPathNameEx: %s (Skip:%n)", lpszShortPath,nSkipLevels );
962 TCHAR szPath[MAX_PATH];
963 BOOL fSuccess;
965 cchBuffer = cchBuffer; /* avoid warnings */
967 _tcscpy( szPath, lpszShortPath );
969 fSuccess = PathRemoveFileSpec( szPath );
971 if ( fSuccess )
973 int nLen = _tcslen( szPath );
974 LPCTSTR lpszFileSpec = lpszShortPath + nLen;
975 BOOL bSkipThis;
977 if ( 0 == _tcscmp( lpszFileSpec, TEXT("..") ) )
979 bSkipThis = TRUE;
980 nSkipLevels += 1;
982 else if (
983 0 == _tcscmp( lpszFileSpec, TEXT(".") ) ||
984 0 == _tcscmp( lpszFileSpec, TEXT("\\") ) ||
985 0 == _tcscmp( lpszFileSpec, TEXT("/") )
988 bSkipThis = TRUE;
990 else if ( nSkipLevels )
992 bSkipThis = TRUE;
993 nSkipLevels--;
995 else
996 bSkipThis = FALSE;
998 GetCaseCorrectPathNameEx( szPath, szPath, MAX_PATH, nSkipLevels );
1000 PathAddBackslash( szPath );
1002 /* Analyze parent if not only a trailing backslash was cutted but a real file spec */
1003 if ( !bSkipThis )
1005 WIN32_FIND_DATA aFindFileData;
1006 HANDLE hFind = FindFirstFile( lpszShortPath, &aFindFileData );
1008 if ( IsValidHandle(hFind) )
1010 _tcscat( szPath, aFindFileData.cFileName[0] ? aFindFileData.cFileName : aFindFileData.cAlternateFileName );
1012 FindClose( hFind );
1014 else
1015 return 0;
1018 else
1020 /* File specification can't be removed therefore the short path is either a drive
1021 or a network share. If still levels to skip are left, the path specification
1022 tries to travel below the file system root */
1023 if ( nSkipLevels )
1024 return 0;
1026 _tcsupr( szPath );
1029 _tcscpy( lpszLongPath, szPath );
1031 return _tcslen( lpszLongPath );
1033 #endif
1035 #if 0
1036 inline size_t wcstoupper( LPWSTR lpStr )
1038 size_t nLen = wcslen( lpStr );
1040 for ( LPWSTR p = lpStr; p < lpStr + nLen; p++ )
1042 *p = towupper(*p);
1045 return nLen;
1048 #endif
1050 //#####################################################
1051 DWORD WINAPI GetCaseCorrectPathName(
1052 LPCTSTR lpszShortPath, // file name
1053 LPTSTR lpszLongPath, // path buffer
1054 DWORD cchBuffer // size of path buffer
1056 #if 0
1058 /* Special handling for "\\.\" as system root */
1059 if ( lpszShortPath && 0 == wcscmp( lpszShortPath, WSTR_SYSTEM_ROOT_PATH ) )
1061 if ( cchBuffer >= ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) )
1063 wcscpy( lpszLongPath, WSTR_SYSTEM_ROOT_PATH );
1064 return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
1066 else
1067 return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH);
1069 else
1071 DWORD nSrcLen = wcslen( lpszShortPath );
1073 if ( cchBuffer > nSrcLen )
1075 wcscpy( lpszLongPath, lpszShortPath );
1076 wcstoupper( lpszLongPath );
1078 else
1079 nSrcLen++;
1081 return nSrcLen;
1084 #else
1086 /* Special handling for "\\.\" as system root */
1087 if ( lpszShortPath && 0 == wcscmp( lpszShortPath, WSTR_SYSTEM_ROOT_PATH ) )
1089 if ( cchBuffer >= ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) )
1091 wcscpy( lpszLongPath, WSTR_SYSTEM_ROOT_PATH );
1092 return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
1094 else
1095 return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
1097 else
1098 return GetCaseCorrectPathNameEx( lpszShortPath, lpszLongPath, cchBuffer, 0 );
1101 #endif
1103 //#####################################################
1104 #define CHARSET_SEPARATOR TEXT("\\/")
1106 BOOL WINAPI IsValidFilePathComponent(
1107 LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags)
1109 LPCTSTR lpComponentEnd = NULL;
1110 LPCTSTR lpCurrent = lpComponent;
1111 BOOL fValid = TRUE; /* Assume success */
1112 TCHAR cLast = 0;
1114 /* Path component length must not exceed MAX_PATH */
1116 while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < MAX_PATH )
1118 switch ( *lpCurrent )
1120 /* Both backslash and slash determine the end of a path component */
1121 case '\0':
1122 case '/':
1123 case '\\':
1124 switch ( cLast )
1126 /* Component must not end with '.' or blank and can't be empty */
1128 case '.':
1129 if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE )
1131 if ( (dwFlags & VALIDATEPATH_ALLOW_INVALID_SPACE_AND_PERIOD) ||
1132 1 == lpCurrent - lpComponent )
1134 /* Either do allow periods anywhere, or current directory */
1135 lpComponentEnd = lpCurrent;
1136 break;
1138 else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent )
1140 /* Parent directory is O.K. */
1141 lpComponentEnd = lpCurrent;
1142 break;
1145 case 0:
1146 case ' ':
1147 if ( dwFlags & VALIDATEPATH_ALLOW_INVALID_SPACE_AND_PERIOD )
1148 lpComponentEnd = lpCurrent;
1149 else
1151 lpComponentEnd = lpCurrent - 1;
1152 fValid = FALSE;
1154 break;
1155 default:
1156 lpComponentEnd = lpCurrent;
1157 break;
1159 break;
1160 /* '?' and '*' are valid wildcards but not valid file name characters */
1161 case '?':
1162 case '*':
1163 if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS )
1164 break;
1165 /* The following characters are reserved */
1166 case '<':
1167 case '>':
1168 case '\"':
1169 case '|':
1170 case ':':
1171 lpComponentEnd = lpCurrent;
1172 fValid = FALSE;
1173 break;
1174 default:
1175 /* Characters below ASCII 32 are not allowed */
1176 if ( *lpCurrent < ' ' )
1178 lpComponentEnd = lpCurrent;
1179 fValid = FALSE;
1181 break;
1183 cLast = *lpCurrent++;
1186 /* If we don't reached the end of the component the length of the component was to long
1187 ( See condition of while loop ) */
1188 if ( !lpComponentEnd )
1190 fValid = FALSE;
1191 lpComponentEnd = lpCurrent;
1194 /* Test wether the component specifies a device name what is not allowed */
1196 // MT: PERFORMANCE:
1197 // This is very expensive. A lot of calls to _tcsicmp.
1198 // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp!
1199 // Possible optimizations
1200 // - Array should be const static
1201 // - Sorted array, use binary search
1202 // - More intelligent check for com1-9, lpt1-9
1203 // Maybe make szComponent upper case, don't search case intensitive
1204 // Talked to HRO: Could be removed. Shouldn't be used in OOo, and if used for something like a filename, it will lead to an error anyway.
1206 if ( fValid )
1208 LPCTSTR alpDeviceNames[] =
1210 TEXT("CON"),
1211 TEXT("PRN"),
1212 TEXT("AUX"),
1213 TEXT("CLOCK$"),
1214 TEXT("NUL"),
1215 TEXT("LPT1"),
1216 TEXT("LPT2"),
1217 TEXT("LPT3"),
1218 TEXT("LPT4"),
1219 TEXT("LPT5"),
1220 TEXT("LPT6"),
1221 TEXT("LPT7"),
1222 TEXT("LPT8"),
1223 TEXT("LPT9"),
1224 TEXT("COM1"),
1225 TEXT("COM2"),
1226 TEXT("COM3"),
1227 TEXT("COM4"),
1228 TEXT("COM5"),
1229 TEXT("COM6"),
1230 TEXT("COM7"),
1231 TEXT("COM8"),
1232 TEXT("COM9")
1235 TCHAR szComponent[MAX_PATH];
1236 int nComponentLength;
1237 LPCTSTR lpDot;
1238 int i;
1240 // A device name with an extension is also invalid
1241 lpDot = _tcschr( lpComponent, '.' );
1243 if ( !lpDot || lpDot > lpComponentEnd )
1244 nComponentLength = lpComponentEnd - lpComponent;
1245 else
1246 nComponentLength = lpDot - lpComponent;
1248 _tcsncpy( szComponent, lpComponent, nComponentLength );
1249 szComponent[nComponentLength] = 0;
1251 for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ )
1253 if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) )
1255 lpComponentEnd = lpComponent;
1256 fValid = FALSE;
1257 break;
1263 if ( fValid )
1265 // Empty components are not allowed
1266 if ( lpComponentEnd - lpComponent < 1 )
1267 fValid = FALSE;
1269 // If we reached the end of the string NULL is returned
1270 else if ( !*lpComponentEnd )
1271 lpComponentEnd = NULL;
1275 if ( lppComponentEnd )
1276 *lppComponentEnd = lpComponentEnd;
1278 return fValid;
1281 //#####################################################
1282 DWORD WINAPI IsValidFilePath(rtl_uString *path, LPCTSTR *lppError, DWORD dwFlags, rtl_uString **corrected)
1284 LPCTSTR lpszPath = reinterpret_cast< LPCTSTR >(path->buffer);
1285 LPCTSTR lpComponent;
1286 BOOL fValid = TRUE;
1287 DWORD dwPathType = PATHTYPE_ERROR;
1289 if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
1290 dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE;
1292 if ( !lpszPath )
1294 fValid = FALSE;
1295 lpComponent = lpszPath;
1298 /* Test for UNC path notation */
1299 if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) )
1301 /* Place the pointer behind the leading to backslashes */
1303 lpComponent = lpszPath + 2;
1305 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE );
1307 /* So far we have a valid servername. Now let's see if we also have a network resource */
1309 dwPathType = PATHTYPE_ABSOLUTE_UNC;
1311 if ( fValid )
1313 if ( lpComponent && !*++lpComponent )
1314 lpComponent = NULL;
1316 if ( !lpComponent )
1318 #if 0
1319 /* We only have a Server specification what is invalid */
1321 lpComponent = lpszPath;
1322 fValid = FALSE;
1323 #else
1324 dwPathType |= PATHTYPE_IS_SERVER;
1325 #endif
1327 else
1329 /* Now test the network resource */
1331 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 );
1333 /* If we now reached the end of the path, everything is O.K. */
1336 if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) )
1338 lpComponent = NULL;
1339 dwPathType |= PATHTYPE_IS_VOLUME;
1345 /* Local path verification. Must start with <drive>: */
1346 else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] )
1348 /* Place pointer behind correct drive specification */
1350 lpComponent = lpszPath + 2;
1352 if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
1353 lpComponent++;
1354 else if ( *lpComponent )
1355 fValid = FALSE;
1357 dwPathType = PATHTYPE_ABSOLUTE_LOCAL;
1359 /* Now we are behind the backslash or it was a simple drive without backslash */
1361 if ( fValid && !*lpComponent )
1363 lpComponent = NULL;
1364 dwPathType |= PATHTYPE_IS_VOLUME;
1368 /* Can be a relative path */
1369 else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
1371 lpComponent = lpszPath;
1373 /* Relative path can start with a backslash */
1375 if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
1377 lpComponent++;
1378 if ( !*lpComponent )
1379 lpComponent = NULL;
1382 dwPathType = PATHTYPE_RELATIVE;
1385 /* Anything else is an error */
1386 else
1388 fValid = FALSE;
1389 lpComponent = lpszPath;
1392 /* Now validate each component of the path */
1393 while ( fValid && lpComponent )
1395 // Correct path by merging consecutive slashes:
1396 if (*lpComponent == '\\' && corrected != NULL) {
1397 sal_Int32 i = lpComponent - lpszPath;
1398 rtl_uString_newReplaceStrAt(corrected, path, i, 1, NULL);
1399 //TODO: handle out-of-memory
1400 lpszPath = reinterpret_cast< LPCTSTR >((*corrected)->buffer);
1401 lpComponent = lpszPath + i;
1404 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags | VALIDATEPATH_ALLOW_INVALID_SPACE_AND_PERIOD);
1406 if ( fValid && lpComponent )
1408 lpComponent++;
1410 /* If the string behind the backslash is empty, we've done */
1412 if ( !*lpComponent )
1413 lpComponent = NULL;
1417 if ( fValid && _tcslen( lpszPath ) >= MAX_PATH )
1419 fValid = FALSE;
1420 lpComponent = lpszPath + MAX_PATH;
1423 if ( lppError )
1424 *lppError = lpComponent;
1426 return fValid ? dwPathType : PATHTYPE_ERROR;
1429 //#####################################################
1430 bool is_floppy_drive(const rtl::OUString& path);
1432 //#####################################################
1433 struct Component
1435 Component() :
1436 begin_(0), end_(0)
1439 bool isPresent() const
1440 { return (static_cast<sal_Int32>(end_ - begin_) > 0); }
1442 const sal_Unicode* begin_;
1443 const sal_Unicode* end_;
1446 //#####################################################
1447 struct UNCComponents
1449 Component server_;
1450 Component share_;
1451 Component resource_;
1454 //#####################################################
1455 const wchar_t UNC_PREFIX[] = L"\\\\";
1456 const wchar_t BACKSLASH = '\\';
1457 const wchar_t SLASH = '/';
1459 bool is_UNC_path(const sal_Unicode* path)
1460 { return (0 == wcsncmp(UNC_PREFIX, reinterpret_cast<LPCWSTR>(path), ELEMENTS_OF_ARRAY(UNC_PREFIX) - 1)); }
1462 //#####################################################
1463 bool is_UNC_path(const rtl::OUString& path)
1464 { return is_UNC_path(path.getStr()); }
1466 //#####################################################
1467 void parse_UNC_path(const sal_Unicode* path, UNCComponents* puncc)
1469 OSL_PRECOND(is_UNC_path(path), "Precondition violated: No UNC path");
1470 OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) != -1, "Path must not contain slashes");
1472 const sal_Unicode* pend = path + rtl_ustr_getLength(path);
1473 const sal_Unicode* ppos = path + 2;
1475 puncc->server_.begin_ = ppos;
1476 while ((ppos < pend) && (*ppos != BACKSLASH))
1477 ppos++;
1479 puncc->server_.end_ = ppos;
1481 if (BACKSLASH == *ppos)
1483 puncc->share_.begin_ = ++ppos;
1484 while ((ppos < pend) && (*ppos != BACKSLASH))
1485 ppos++;
1487 puncc->share_.end_ = ppos;
1489 if (BACKSLASH == *ppos)
1491 puncc->resource_.begin_ = ++ppos;
1492 while (ppos < pend)
1493 ppos++;
1495 puncc->resource_.end_ = ppos;
1499 OSL_POSTCOND(puncc->server_.isPresent() && puncc->share_.isPresent(), \
1500 "Postcondition violated: Invalid UNC path detected");
1503 //#####################################################
1504 void parse_UNC_path(const rtl::OUString& path, UNCComponents* puncc)
1505 { parse_UNC_path(path.getStr(), puncc); }
1507 //#####################################################
1508 bool is_volume_mount_point(const rtl::OUString& path)
1510 rtl::OUString p(path);
1511 osl::systemPathRemoveSeparator(p);
1513 bool is_volume_root = false;
1515 if (!is_floppy_drive(p))
1517 DWORD fattr = GetFileAttributes(reinterpret_cast<LPCTSTR>(p.getStr()));
1519 if ((INVALID_FILE_ATTRIBUTES != fattr) &&
1520 (FILE_ATTRIBUTE_REPARSE_POINT & fattr))
1522 WIN32_FIND_DATA find_data;
1523 HANDLE h_find = FindFirstFile(reinterpret_cast<LPCTSTR>(p.getStr()), &find_data);
1525 if (IsValidHandle(h_find) &&
1526 (FILE_ATTRIBUTE_REPARSE_POINT & find_data.dwFileAttributes) &&
1527 (IO_REPARSE_TAG_MOUNT_POINT == find_data.dwReserved0))
1529 is_volume_root = true;
1531 if (IsValidHandle(h_find))
1532 FindClose(h_find);
1535 return is_volume_root;
1538 //#####################################################
1539 // Has the given path a parent or are we already there,
1540 // e.g. 'c:\' or '\\server\share\'?
1541 bool has_path_parent(const sal_Unicode* path)
1543 bool has_parent = false;
1545 if (is_UNC_path(path))
1547 UNCComponents unc_comp;
1548 parse_UNC_path(path, &unc_comp);
1549 has_parent = unc_comp.resource_.isPresent();
1551 else
1553 has_parent = !osl::systemPathIsLogicalDrivePattern(path);
1555 return has_parent;
1558 //#####################################################
1559 // @see bool has_path_parent(const sal_Unicode* path)
1560 bool has_path_parent(const rtl::OUString& path)
1561 { return has_path_parent(path.getStr()); }
1563 //#####################################################
1564 bool path_get_parent(rtl::OUString& path)
1566 OSL_PRECOND(path.lastIndexOf(SLASH) == -1, "Path must not have slashes");
1568 if (!has_path_parent(path))
1570 sal_Int32 i = path.lastIndexOf(BACKSLASH);
1571 if (-1 < i)
1573 path = rtl::OUString(path.getStr(), i);
1574 return true;
1577 return false;
1580 //#############################################
1581 /* Cut off the last part of the given path to
1582 get the parent only, e.g. 'c:\dir\subdir' ->
1583 'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
1584 @return The position where the path has been cut
1585 off (this is the posistion of the last backslash).
1586 If there are no more parents 0 will be returned,
1587 e.g. 'c:\' or '\\Share' have no more parents */
1588 int path_make_parent(sal_Unicode* path)
1590 OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) != -1, "Path must not contain slashes");
1591 OSL_PRECOND(has_path_parent(path), "Path must have a parent");
1593 sal_Unicode* pos_last_backslash = path + rtl_ustr_lastIndexOfChar(path, BACKSLASH);
1594 *pos_last_backslash = 0;
1595 return (pos_last_backslash - path);
1598 //#####################################################
1599 void path_travel_to_volume_root(const rtl::OUString& system_path, rtl::OUString& volume_root)
1601 rtl::OUString sys_path(system_path);
1603 while(!is_volume_mount_point(sys_path) && path_get_parent(sys_path))
1604 /**/;
1606 volume_root = sys_path;
1607 osl_systemPathEnsureSeparator(&volume_root.pData);
1610 //#####################################################
1611 inline bool is_floppy_A_present()
1612 { return (GetLogicalDrives() & 1); }
1614 //#####################################################
1615 inline bool is_floppy_B_present()
1616 { return (GetLogicalDrives() & 2); }
1618 //#####################################################
1619 // determines if a volume mount point shows to a floppy
1620 // disk by comparing the unique volume names
1621 const LPWSTR FLOPPY_A = L"A:\\";
1622 const LPWSTR FLOPPY_B = L"B:\\";
1624 bool is_floppy_volume_mount_point(const rtl::OUString& path)
1626 rtl::OUString p(path);
1627 osl_systemPathEnsureSeparator(&p.pData);
1629 TCHAR vn[51];
1630 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1632 TCHAR vnfloppy[51];
1633 if (is_floppy_A_present() &&
1634 GetVolumeNameForVolumeMountPoint(FLOPPY_A, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1635 (0 == wcscmp(vn, vnfloppy)))
1636 return true;
1638 if (is_floppy_B_present() &&
1639 GetVolumeNameForVolumeMountPoint(FLOPPY_B, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1640 (0 == wcscmp(vn, vnfloppy)))
1641 return true;
1643 return false;
1646 //################################################
1647 // we must take into account that even a floppy
1648 // drive may be mounted to a directory so checking
1649 // for the drive letter alone is not sufficient
1650 // we must compare the unique volume name with
1651 // that of the available floppy disks
1652 LPCWSTR FLOPPY_DRV_LETTERS = TEXT("AaBb");
1654 bool is_floppy_drive(const rtl::OUString& path)
1656 const sal_Unicode* pf = path.getStr();
1657 const sal_Unicode* ps = path.getStr() + 1;
1658 return ((wcschr(FLOPPY_DRV_LETTERS, *pf) && (L':' == *ps)) ||
1659 is_floppy_volume_mount_point(path));
1662 //#############################################
1663 UINT get_volume_mount_point_drive_type(const rtl::OUString& path)
1665 if (0 == path.getLength())
1666 return GetDriveType(NULL);
1668 rtl::OUString p(path);
1669 osl_systemPathEnsureSeparator(&p.pData);
1671 TCHAR vn[51];
1672 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1673 return GetDriveType(vn);
1675 return DRIVE_NO_ROOT_DIR;
1678 //#############################################
1679 oslFileError osl_get_drive_type(const rtl::OUString& path, oslVolumeInfo* pInfo)
1681 // GetDriveType fails on empty volume mount points
1682 // see Knowledge Base Q244089
1683 UINT drive_type;
1684 if (is_volume_mount_point(path))
1685 drive_type = get_volume_mount_point_drive_type(path);
1686 else
1687 drive_type = GetDriveType(reinterpret_cast<LPCTSTR>(path.getStr()));
1689 if (DRIVE_NO_ROOT_DIR == drive_type)
1690 return MapError(ERROR_INVALID_DRIVE);
1692 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1694 switch (drive_type)
1696 case DRIVE_CDROM:
1697 pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
1698 break;
1699 case DRIVE_REMOVABLE:
1700 pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
1701 if (is_floppy_drive(path))
1702 pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
1703 break;
1704 case DRIVE_FIXED:
1705 pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
1706 break;
1707 case DRIVE_RAMDISK:
1708 pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
1709 break;
1710 case DRIVE_REMOTE:
1711 pInfo->uAttributes |= osl_Volume_Attribute_Remote;
1712 break;
1713 case DRIVE_UNKNOWN:
1714 pInfo->uAttributes = 0;
1715 break;
1716 default:
1717 pInfo->uValidFields &= ~osl_VolumeInfo_Mask_Attributes;
1718 pInfo->uAttributes = 0;
1719 break;
1721 return osl_File_E_None;
1724 //#############################################
1725 inline bool is_volume_space_info_request(sal_uInt32 field_mask)
1727 return (field_mask &
1728 (osl_VolumeInfo_Mask_TotalSpace |
1729 osl_VolumeInfo_Mask_UsedSpace |
1730 osl_VolumeInfo_Mask_FreeSpace));
1733 //#############################################
1734 void get_volume_space_information(const rtl::OUString& path, oslVolumeInfo *pInfo)
1736 BOOL ret = GetDiskFreeSpaceEx(
1737 reinterpret_cast<LPCTSTR>(path.getStr()),
1738 (PULARGE_INTEGER)&pInfo->uFreeSpace,
1739 (PULARGE_INTEGER)&pInfo->uTotalSpace,
1740 NULL);
1742 if (ret)
1744 pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
1745 pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace |
1746 osl_VolumeInfo_Mask_UsedSpace |
1747 osl_VolumeInfo_Mask_FreeSpace;
1751 //#############################################
1752 inline bool is_filesystem_attributes_request(sal_uInt32 field_mask)
1754 return (field_mask &
1755 (osl_VolumeInfo_Mask_MaxNameLength |
1756 osl_VolumeInfo_Mask_MaxPathLength |
1757 osl_VolumeInfo_Mask_FileSystemName |
1758 osl_VolumeInfo_Mask_FileSystemCaseHandling));
1761 //#############################################
1762 inline bool is_drivetype_request(sal_uInt32 field_mask)
1764 return (field_mask & osl_VolumeInfo_Mask_Attributes);
1767 //#############################################
1768 oslFileError get_filesystem_attributes(const rtl::OUString& path, sal_uInt32 field_mask, oslVolumeInfo* pInfo)
1770 pInfo->uAttributes = 0;
1772 oslFileError osl_error = osl_File_E_None;
1774 // osl_get_drive_type must be called first because
1775 // this function resets osl_VolumeInfo_Mask_Attributes
1776 // on failure
1777 if (is_drivetype_request(field_mask))
1778 osl_error = osl_get_drive_type(path, pInfo);
1780 if ((osl_File_E_None == osl_error) && is_filesystem_attributes_request(field_mask))
1782 WCHAR vn[MAX_PATH];
1783 WCHAR fsn[MAX_PATH];
1784 DWORD serial;
1785 DWORD mcl;
1786 DWORD flags;
1788 if (GetVolumeInformation(reinterpret_cast<LPCTSTR>(path.getStr()), vn, MAX_PATH, &serial, &mcl, &flags, fsn, MAX_PATH))
1790 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
1791 pInfo->uMaxNameLength = mcl;
1793 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
1794 pInfo->uMaxPathLength = MAX_PATH;
1796 pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
1797 rtl_uString_newFromStr(&pInfo->ustrFileSystemName, reinterpret_cast<const sal_Unicode*>(fsn));
1799 // volumes (even NTFS) will always be considered case
1800 // insensitive because the Win32 API is not able to
1801 // deal with case sensitive volumes see M$ Knowledge Base
1802 // article 100625 that's why we never set the attribute
1803 // osl_Volume_Attribute_Case_Sensitive
1805 if (flags & FS_CASE_IS_PRESERVED)
1806 pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
1808 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1811 return osl_error;
1814 //#############################################
1815 // Create the specified directory and call the
1816 // user specified callback function. On success
1817 // the function returns ERROR_SUCCESS else a
1818 // Win32 error code.
1819 DWORD create_dir_with_callback(
1820 sal_Unicode* dir_path,
1821 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
1822 void* pData)
1824 if (CreateDirectory(reinterpret_cast<LPCTSTR>(dir_path), NULL))
1826 if (aDirectoryCreationCallbackFunc)
1828 rtl::OUString url;
1829 FileBase::getFileURLFromSystemPath(dir_path, url);
1830 aDirectoryCreationCallbackFunc(pData, url.pData);
1832 return ERROR_SUCCESS;
1834 return GetLastError();
1837 //#############################################
1838 DWORD create_dir_recursively_(
1839 sal_Unicode* dir_path,
1840 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
1841 void* pData)
1843 OSL_PRECOND(rtl_ustr_getLength(dir_path) > 0 && (rtl_ustr_lastIndexOfChar(dir_path, BACKSLASH) != rtl_ustr_getLength(dir_path) - 1), \
1844 "Path must not end with a backslash");
1846 DWORD w32_error = create_dir_with_callback(
1847 dir_path, aDirectoryCreationCallbackFunc, pData);
1849 if (w32_error == ERROR_SUCCESS)
1850 return ERROR_SUCCESS;
1852 if ((w32_error != ERROR_PATH_NOT_FOUND) || !has_path_parent(dir_path))
1853 return w32_error;
1855 int pos = path_make_parent(dir_path);
1857 w32_error = create_dir_recursively_(
1858 dir_path, aDirectoryCreationCallbackFunc, pData);
1860 if (ERROR_SUCCESS != w32_error)
1861 return w32_error;
1863 dir_path[pos] = BACKSLASH;
1865 return create_dir_recursively_(
1866 dir_path, aDirectoryCreationCallbackFunc, pData);
1869 //#####################################################
1870 // Temp file
1871 //#####################################################
1874 //#####################################################
1875 oslFileError osl_setup_base_directory_impl_(
1876 rtl_uString* pustrDirectoryURL,
1877 rtl_uString** ppustr_base_dir)
1879 rtl_uString* dir_url = 0;
1880 rtl_uString* dir = 0;
1881 oslFileError error = osl_File_E_None;
1883 if (pustrDirectoryURL)
1884 rtl_uString_assign(&dir_url, pustrDirectoryURL);
1885 else
1886 error = osl_getTempDirURL(&dir_url);
1888 if (osl_File_E_None == error)
1890 error = _osl_getSystemPathFromFileURL(dir_url, &dir, sal_False);
1891 rtl_uString_release(dir_url);
1894 if (osl_File_E_None == error )
1896 rtl_uString_assign(ppustr_base_dir, dir);
1897 rtl_uString_release(dir);
1900 return error;
1903 //#####################################################
1904 oslFileError osl_setup_createTempFile_impl_(
1905 rtl_uString* pustrDirectoryURL,
1906 oslFileHandle* pHandle,
1907 rtl_uString** ppustrTempFileURL,
1908 rtl_uString** ppustr_base_dir,
1909 sal_Bool* b_delete_on_close)
1911 oslFileError osl_error;
1913 OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
1915 if ((0 == pHandle) && (0 == ppustrTempFileURL))
1917 osl_error = osl_File_E_INVAL;
1919 else
1921 osl_error = osl_setup_base_directory_impl_(
1922 pustrDirectoryURL, ppustr_base_dir);
1924 *b_delete_on_close = (sal_Bool)(0 == ppustrTempFileURL);
1927 return osl_error;
1930 //#####################################################
1931 oslFileError osl_win32_GetTempFileName_impl_(
1932 rtl_uString* base_directory, LPWSTR temp_file_name)
1934 oslFileError osl_error = osl_File_E_None;
1936 if (0 == GetTempFileNameW(
1937 reinterpret_cast<LPCWSTR>(rtl_uString_getStr(base_directory)),
1938 L"",
1940 temp_file_name))
1942 osl_error = MapError(GetLastError());
1945 return osl_error;
1948 //#####################################################
1949 sal_Bool osl_win32_CreateFile_impl_(
1950 LPCWSTR file_name, sal_Bool b_delete_on_close, oslFileHandle* p_handle)
1952 DWORD flags = FILE_ATTRIBUTE_NORMAL;
1953 HANDLE hFile;
1955 OSL_ASSERT(p_handle);
1957 if (b_delete_on_close)
1958 flags |= FILE_FLAG_DELETE_ON_CLOSE;
1960 hFile = CreateFileW(
1961 file_name,
1962 GENERIC_READ | GENERIC_WRITE,
1964 NULL,
1965 TRUNCATE_EXISTING,
1966 flags,
1967 NULL);
1969 if (IsValidHandle(hFile))
1970 *p_handle = (oslFileHandle)hFile;
1972 return (sal_Bool)IsValidHandle(hFile);
1975 //#############################################
1976 oslFileError osl_createTempFile_impl_(
1977 rtl_uString* base_directory,
1978 LPWSTR tmp_name,
1979 sal_Bool b_delete_on_close,
1980 oslFileHandle* pHandle,
1981 rtl_uString** ppustrTempFileURL)
1983 oslFileError osl_error;
1987 osl_error = osl_win32_GetTempFileName_impl_(base_directory, tmp_name);
1989 /* if file could not be opened try again */
1991 if ((osl_File_E_None != osl_error) || (0 == pHandle) ||
1992 osl_win32_CreateFile_impl_(tmp_name, b_delete_on_close, pHandle))
1993 break;
1995 } while(1); // try until success
1997 if ((osl_File_E_None == osl_error) && !b_delete_on_close)
1999 rtl_uString* pustr = 0;
2000 rtl_uString_newFromStr(&pustr, reinterpret_cast<const sal_Unicode*>(tmp_name));
2001 osl_getFileURLFromSystemPath(pustr, ppustrTempFileURL);
2002 rtl_uString_release(pustr);
2005 return osl_error;
2008 //#####################################################
2009 // End Temp file
2010 //#####################################################
2013 //#############################################
2014 sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL )
2016 sal_Char *pBuffer;
2017 const sal_Char *pSrcEnd;
2018 const sal_Char *pSrc;
2019 sal_Char *pDest;
2020 sal_Int32 nSrcLen;
2021 sal_Bool bValidEncoded = sal_True; /* Assume success */
2023 /* The resulting decoded string length is shorter or equal to the source length */
2025 nSrcLen = rtl_string_getLength(strUTF8);
2026 pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1));
2028 pDest = pBuffer;
2029 pSrc = rtl_string_getStr(strUTF8);
2030 pSrcEnd = pSrc + nSrcLen;
2032 /* Now decode the URL what should result in an UTF8 string */
2033 while ( bValidEncoded && pSrc < pSrcEnd )
2035 switch ( *pSrc )
2037 case '%':
2039 sal_Char aToken[3];
2040 sal_Char aChar;
2042 pSrc++;
2043 aToken[0] = *pSrc++;
2044 aToken[1] = *pSrc++;
2045 aToken[2] = 0;
2047 aChar = (sal_Char)strtoul( aToken, NULL, 16 );
2049 /* The chars are path delimiters and must not be encoded */
2051 if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar )
2052 bValidEncoded = sal_False;
2053 else
2054 *pDest++ = aChar;
2056 break;
2057 default:
2058 *pDest++ = *pSrc++;
2059 break;
2063 *pDest++ = 0;
2065 if ( bValidEncoded ) {
2066 rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
2067 OSL_ASSERT(*pstrDecodedURL != 0);
2070 rtl_freeMemory( pBuffer );
2072 return bValidEncoded;
2075 //#############################################
2076 void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL )
2078 /* Encode non ascii characters within the URL */
2080 rtl_String *strUTF8 = NULL;
2081 sal_Char *pszEncodedURL;
2082 const sal_Char *pURLScan;
2083 sal_Char *pURLDest;
2084 sal_Int32 nURLScanLen;
2085 sal_Int32 nURLScanCount;
2087 rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
2089 pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) );
2091 pURLDest = pszEncodedURL;
2092 pURLScan = rtl_string_getStr( strUTF8 );
2093 nURLScanLen = rtl_string_getLength( strUTF8 );
2094 nURLScanCount = 0;
2096 while ( nURLScanCount < nURLScanLen )
2098 sal_Char cCurrent = *pURLScan;
2100 switch ( cCurrent )
2102 default:
2103 if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) )
2105 sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent );
2106 pURLDest += 3;
2107 break;
2109 case '!':
2110 case '\'':
2111 case '(':
2112 case ')':
2113 case '*':
2114 case '-':
2115 case '.':
2116 case '_':
2117 case '~':
2118 case '$':
2119 case '&':
2120 case '+':
2121 case ',':
2122 case '=':
2123 case '@':
2124 case ':':
2125 case '/':
2126 case '\\':
2127 case '|':
2128 *pURLDest++ = cCurrent;
2129 break;
2130 case 0:
2131 break;
2134 pURLScan++;
2135 nURLScanCount++;
2139 *pURLDest = 0;
2141 rtl_string_release( strUTF8 );
2142 rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL );
2143 rtl_freeMemory( pszEncodedURL );
2146 //#############################################
2147 oslFileError SAL_CALL _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative )
2149 rtl_String *strUTF8 = NULL;
2150 rtl_uString *strDecodedURL = NULL;
2151 rtl_uString *strTempPath = NULL;
2152 const sal_Unicode *pDecodedURL;
2153 sal_uInt32 nDecodedLen;
2154 sal_Bool bValidEncoded;
2155 oslFileError nError = osl_File_E_INVAL; /* Assume failure */
2157 /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from
2158 having a mixed encoded URL later */
2160 rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
2162 /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */
2164 OSL_ENSURE_FILE(
2165 strUTF8->length == strURL->length ||
2166 0 != rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 )
2167 ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL );
2169 bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL );
2171 /* Release the encoded UTF8 string */
2173 rtl_string_release( strUTF8 );
2176 if ( bValidEncoded )
2178 /* Replace backslashes and pipes */
2180 rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' );
2181 rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' );
2183 pDecodedURL = rtl_uString_getStr( strDecodedURL );
2184 nDecodedLen = rtl_uString_getLength( strDecodedURL );
2186 /* Must start with "file://" */
2188 if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) )
2190 sal_uInt32 nSkip;
2192 if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) )
2193 nSkip = 8;
2194 else if (
2195 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) ||
2196 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 )
2198 nSkip = 17;
2199 else
2200 nSkip = 5;
2202 /* Indicates local root */
2203 if ( nDecodedLen == nSkip )
2204 rtl_uString_newFromStr_WithLength( &strTempPath, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 );
2205 else
2206 rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip );
2208 if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) )
2209 nError = osl_File_E_None;
2211 else if ( bAllowRelative ) /* This maybe a relative file URL */
2213 rtl_uString_assign( &strTempPath, strDecodedURL );
2215 if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) )
2216 nError = osl_File_E_None;
2219 else
2220 OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL );
2225 if ( strDecodedURL )
2226 rtl_uString_release( strDecodedURL );
2228 if ( osl_File_E_None == nError )
2229 rtl_uString_assign( pustrPath, strTempPath );
2231 if ( strTempPath )
2232 rtl_uString_release( strTempPath );
2235 OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL );
2238 return nError;
2241 //#############################################
2242 oslFileError SAL_CALL _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL )
2244 oslFileError nError = osl_File_E_INVAL; /* Assume failure */
2245 rtl_uString *strTempURL = NULL;
2246 DWORD dwPathType = PATHTYPE_ERROR;
2248 if (strPath)
2249 dwPathType = IsValidFilePath(strPath, NULL, VALIDATEPATH_ALLOW_RELATIVE, NULL);
2251 if (dwPathType)
2253 rtl_uString *strTempPath = NULL;
2255 /* Replace backslashes */
2257 rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
2259 switch ( dwPathType & PATHTYPE_MASK_TYPE )
2261 case PATHTYPE_RELATIVE:
2262 rtl_uString_assign( &strTempURL, strTempPath );
2263 nError = osl_File_E_None;
2264 break;
2265 case PATHTYPE_ABSOLUTE_UNC:
2266 rtl_uString_newFromAscii( &strTempURL, "file:" );
2267 rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
2268 nError = osl_File_E_None;
2269 break;
2270 case PATHTYPE_ABSOLUTE_LOCAL:
2271 rtl_uString_newFromAscii( &strTempURL, "file:///" );
2272 rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
2273 nError = osl_File_E_None;
2274 break;
2275 default:
2276 break;
2279 /* Release temp path */
2281 rtl_uString_release( strTempPath );
2284 if ( osl_File_E_None == nError )
2286 rtl_String *strEncodedURL = NULL;
2288 /* Encode the URL */
2290 _osl_encodeURL( strTempURL, &strEncodedURL );
2292 /* Provide URL via unicode string */
2294 rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
2295 OSL_ASSERT(*pstrURL != 0);
2296 rtl_string_release( strEncodedURL );
2299 /* Release temp URL */
2301 if ( strTempURL )
2302 rtl_uString_release( strTempURL );
2305 OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath );
2308 return nError;
2311 #if OSL_DEBUG_LEVEL > 0
2313 //#####################################################
2314 void _osl_warnFile( const char *message, rtl_uString *ustrFile )
2316 char szBuffer[2048];
2318 if (ustrFile)
2320 rtl_String *strFile = NULL;
2322 rtl_uString2String( &strFile, rtl_uString_getStr( ustrFile ), rtl_uString_getLength( ustrFile ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
2323 snprintf( szBuffer, sizeof(szBuffer), message, strFile->buffer );
2324 rtl_string_release( strFile );
2326 message = szBuffer;
2328 OSL_ENSURE( 0, message );
2331 #endif // OSL_DEBUG_LEVEL > 0
2333 } // end namespace private
2336 //#####################################################
2337 // Exported OSL API
2338 //#####################################################
2341 //#############################################
2342 oslFileError SAL_CALL osl_getVolumeInformation(
2343 rtl_uString *ustrURL, oslVolumeInfo *pInfo, sal_uInt32 uFieldMask )
2345 if (!pInfo)
2346 return osl_File_E_INVAL;
2348 rtl::OUString system_path;
2349 oslFileError error = _osl_getSystemPathFromFileURL(ustrURL, &system_path.pData, sal_False);
2351 if (osl_File_E_None != error)
2352 return error;
2354 rtl::OUString volume_root;
2355 path_travel_to_volume_root(system_path, volume_root);
2357 pInfo->uValidFields = 0;
2359 if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None)
2360 return error;
2362 if (is_volume_space_info_request(uFieldMask))
2363 get_volume_space_information(volume_root, pInfo);
2365 if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
2367 pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
2368 osl_getFileURLFromSystemPath(volume_root.pData, (rtl_uString**)&pInfo->pDeviceHandle);
2371 return osl_File_E_None;
2375 //#############################################
2376 oslFileError SAL_CALL osl_createDirectoryPath(
2377 rtl_uString* aDirectoryUrl,
2378 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
2379 void* pData)
2381 if (aDirectoryUrl == NULL)
2382 return osl_File_E_INVAL;
2384 rtl::OUString sys_path;
2385 oslFileError osl_error =
2386 _osl_getSystemPathFromFileURL(aDirectoryUrl, &sys_path.pData, sal_False);
2388 if (osl_error != osl_File_E_None)
2389 return osl_error;
2391 systemPathRemoveSeparator(sys_path);
2393 // const_cast because sys_path is a local copy
2394 // which we want to modify inplace instead of
2395 // coyp it into another buffer on the heap again
2396 return MapError(create_dir_recursively_(
2397 sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData));
2400 //#############################################
2401 oslFileError SAL_CALL osl_createTempFile(
2402 rtl_uString* pustrDirectoryURL,
2403 oslFileHandle* pHandle,
2404 rtl_uString** ppustrTempFileURL)
2406 rtl_uString* base_directory = 0;
2407 LPWSTR tmp_name;
2408 sal_Bool b_delete_on_close;
2409 oslFileError osl_error;
2411 osl_error = osl_setup_createTempFile_impl_(
2412 pustrDirectoryURL,
2413 pHandle,
2414 ppustrTempFileURL,
2415 &base_directory,
2416 &b_delete_on_close);
2418 if (osl_File_E_None != osl_error)
2419 return osl_error;
2421 /* allocate enough space on the stack */
2422 STACK_ALLOC(tmp_name, WCHAR, (rtl_uString_getLength(base_directory) + MAX_PATH));
2424 if (tmp_name)
2426 osl_createTempFile_impl_(
2427 base_directory,
2428 tmp_name,
2429 b_delete_on_close,
2430 pHandle,
2431 ppustrTempFileURL);
2433 else // stack alloc failed
2435 osl_error = osl_File_E_NOMEM;
2438 if (base_directory)
2439 rtl_uString_release(base_directory);
2441 return osl_error;
2444 //#############################################
2445 oslFileError SAL_CALL osl_getTempDirURL(rtl_uString** pustrTempDir)
2447 WCHAR szBuffer[MAX_PATH];
2448 LPWSTR lpBuffer = szBuffer;
2449 DWORD nBufferLength = ELEMENTS_OF_ARRAY(szBuffer) - 1;
2451 DWORD nLength;
2452 oslFileError error;
2456 nLength = GetTempPathW( ELEMENTS_OF_ARRAY(szBuffer), lpBuffer );
2457 if ( nLength > nBufferLength )
2459 nLength++;
2460 lpBuffer = reinterpret_cast<WCHAR*>(alloca( sizeof(WCHAR) * nLength ));
2461 nBufferLength = nLength - 1;
2463 } while ( nLength > nBufferLength );
2465 if ( nLength )
2467 rtl_uString *ustrTempPath = NULL;
2469 if ( '\\' == lpBuffer[nLength-1] )
2470 lpBuffer[nLength-1] = 0;
2472 rtl_uString_newFromStr( &ustrTempPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) );
2474 error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
2476 rtl_uString_release( ustrTempPath );
2478 else
2479 error = MapError( GetLastError() );
2481 return error;
2484 //##################################################################
2485 // File handling functions
2486 //##################################################################
2489 //#############################################
2490 oslFileError SAL_CALL osl_openFile(
2491 rtl_uString *strPath, oslFileHandle *pHandle, sal_uInt32 uFlags )
2493 rtl_uString *strSysPath = NULL;
2494 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
2496 if ( osl_File_E_None == error )
2498 DWORD dwAccess = 0, dwShare = FILE_SHARE_READ, dwCreation = 0, dwAttributes = 0;
2499 HANDLE hFile;
2501 if ( uFlags & osl_File_OpenFlag_Read )
2502 dwAccess |= GENERIC_READ;
2504 if ( uFlags & osl_File_OpenFlag_Write )
2505 dwAccess |= GENERIC_WRITE;
2506 else
2507 dwShare |= FILE_SHARE_WRITE;
2509 if ( uFlags & osl_File_OpenFlag_NoLock )
2510 dwShare |= FILE_SHARE_WRITE;
2512 if ( uFlags & osl_File_OpenFlag_Create )
2513 dwCreation |= CREATE_NEW;
2514 else
2515 dwCreation |= OPEN_EXISTING;
2517 hFile = CreateFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), dwAccess, dwShare, NULL, dwCreation, dwAttributes, NULL );
2519 *pHandle = osl_createFileHandleFromOSHandle( hFile );
2521 if ( !IsValidHandle( hFile ) )
2522 error = MapError( GetLastError() );
2524 rtl_uString_release( strSysPath );
2527 return error;
2530 //#############################################
2531 oslFileError SAL_CALL osl_syncFile(oslFileHandle Handle)
2533 if (!IsValidHandle((HANDLE)Handle))
2534 return osl_File_E_INVAL;
2536 if (!FlushFileBuffers((HANDLE)Handle))
2537 return MapError(GetLastError());
2539 return osl_File_E_None;
2542 //#############################################
2543 oslFileError SAL_CALL osl_closeFile(oslFileHandle Handle)
2545 oslFileError error;
2546 HANDLE hFile = (HANDLE)Handle;
2548 if ( IsValidHandle(hFile) )
2549 error = CloseHandle( hFile ) ? osl_File_E_None : MapError( GetLastError() );
2550 else
2551 error = osl_File_E_INVAL;
2553 return error;
2556 //#############################################
2557 oslFileError SAL_CALL osl_isEndOfFile(oslFileHandle Handle, sal_Bool *pIsEOF)
2559 oslFileError error = osl_File_E_INVAL;
2560 HANDLE hFile = (HANDLE)Handle;
2562 if ( IsValidHandle(hFile) )
2564 LONG lDistanceToMove, lDistanceToMoveHigh;
2565 sal_uInt64 nCurPos;
2567 /* Return value INVALID_SET_FILE_POINTER is no error indication and LastError could
2568 be set from previous IO call */
2570 SetLastError( NOERROR );
2572 lDistanceToMoveHigh = 0;
2573 lDistanceToMove = SetFilePointer( hFile, 0, &lDistanceToMoveHigh, FILE_CURRENT );
2575 error = MapError( GetLastError() );
2577 if ( osl_File_E_None == error )
2579 nCurPos = (sal_uInt64)lDistanceToMove + ((sal_uInt64)lDistanceToMoveHigh << 32);
2581 lDistanceToMoveHigh = 0;
2582 lDistanceToMove = SetFilePointer( hFile, 0, &lDistanceToMoveHigh, FILE_END );
2584 error = MapError( GetLastError() );
2586 if ( osl_File_E_None == error )
2588 sal_uInt64 nEndPos = (sal_uInt64)lDistanceToMove + ((sal_uInt64)lDistanceToMoveHigh << 32);
2590 *pIsEOF = (sal_Bool)(nEndPos == nCurPos);
2592 lDistanceToMoveHigh = (LONG)(nCurPos >> 32);
2593 SetFilePointer( hFile, (LONG)(nCurPos & 0xFFFFFFFF), &lDistanceToMoveHigh, FILE_BEGIN );
2595 error = MapError( GetLastError() );
2599 return error;
2602 //#############################################
2603 oslFileError SAL_CALL osl_setFilePos(oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uPos)
2605 HANDLE hFile = (HANDLE)Handle;
2606 if (!IsValidHandle(hFile))
2607 return osl_File_E_INVAL;
2609 DWORD dwMoveMethod = 0;
2610 switch ( uHow )
2612 case osl_Pos_Current:
2613 dwMoveMethod = FILE_CURRENT;
2614 break;
2615 case osl_Pos_End:
2616 dwMoveMethod = FILE_END;
2617 break;
2618 case osl_Pos_Absolut:
2619 default:
2620 dwMoveMethod = FILE_BEGIN;
2621 break;
2624 LONG nOffsetLo = sal::static_int_cast<LONG>(uPos & 0xFFFFFFFF);
2625 LONG nOffsetHi = sal::static_int_cast<LONG>(uPos >> 32);
2627 SetLastError(0);
2628 DWORD dwPosLo = SetFilePointer( hFile, nOffsetLo, &nOffsetHi, dwMoveMethod );
2629 if (INVALID_SET_FILE_POINTER == dwPosLo)
2631 DWORD dwError = GetLastError();
2632 if (NO_ERROR != dwError)
2633 return MapError( dwError );
2635 return osl_File_E_None;
2638 //#############################################
2639 oslFileError SAL_CALL osl_getFilePos(oslFileHandle Handle, sal_uInt64 *pPos)
2641 oslFileError error;
2642 HANDLE hFile = (HANDLE)Handle;
2644 if ( IsValidHandle(hFile) )
2646 LONG lDistanceToMove, lDistanceToMoveHigh;
2648 /* Return value INVALID_SET_FILE_POINTER is no error indication and LastError could
2649 be set from previous IO call */
2651 SetLastError( NOERROR );
2653 lDistanceToMoveHigh = 0;
2654 lDistanceToMove = SetFilePointer( hFile, 0, &lDistanceToMoveHigh, FILE_CURRENT );
2656 error = MapError( GetLastError() );
2658 if ( osl_File_E_None == error )
2659 *pPos = (sal_uInt64)lDistanceToMove + ((sal_uInt64)lDistanceToMoveHigh << 32);
2661 else
2662 error = osl_File_E_INVAL;
2664 return error;
2667 //#############################################
2668 oslFileError SAL_CALL osl_getFileSize(oslFileHandle Handle, sal_uInt64 *pSize)
2670 HANDLE hFile = (HANDLE)Handle;
2671 if ( !IsValidHandle(hFile) )
2672 return osl_File_E_INVAL;
2674 DWORD nSize = GetFileSize(hFile, NULL);
2675 if (nSize == INVALID_FILE_SIZE)
2677 DWORD nError = GetLastError();
2678 if (nError != NO_ERROR)
2679 return MapError(nError);
2682 *pSize = (sal_uInt64)(nSize);
2683 return osl_File_E_None;
2686 oslFileError SAL_CALL osl_setFileSize(oslFileHandle Handle, sal_uInt64 uSize)
2688 oslFileError error = osl_setFilePos( Handle, osl_Pos_Absolut, uSize );
2689 if ( osl_File_E_None == error )
2691 if ( !SetEndOfFile( (HANDLE)Handle ) )
2692 error = MapError( osl_File_E_None );
2695 return error;
2698 //#############################################
2699 oslFileError SAL_CALL osl_mapFile(
2700 oslFileHandle Handle,
2701 void** ppAddr,
2702 sal_uInt64 uLength,
2703 sal_uInt64 uOffset,
2704 sal_uInt32 uFlags)
2706 struct FileMapping
2708 HANDLE m_handle;
2710 explicit FileMapping (HANDLE hMap)
2711 : m_handle (hMap)
2714 ~FileMapping()
2716 (void)::CloseHandle(m_handle);
2720 HANDLE hFile = (HANDLE)(Handle);
2721 if (!IsValidHandle(hFile) || (0 == ppAddr))
2722 return osl_File_E_INVAL;
2723 *ppAddr = 0;
2725 static SIZE_T const nLimit = std::numeric_limits< SIZE_T >::max();
2726 if (uLength > nLimit)
2727 return osl_File_E_OVERFLOW;
2728 SIZE_T const nLength = sal::static_int_cast< SIZE_T >(uLength);
2730 OSVERSIONINFO osinfo;
2731 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
2732 (void)::GetVersionEx(&osinfo);
2734 if (VER_PLATFORM_WIN32_NT != osinfo.dwPlatformId)
2735 return osl_File_E_NOSYS; // Unsupported
2737 FileMapping aMap( ::CreateFileMapping (hFile, NULL, SEC_COMMIT | PAGE_READONLY, 0, 0, NULL) );
2738 if (!IsValidHandle(aMap.m_handle))
2739 return MapError( GetLastError() );
2741 DWORD const dwOffsetHi = sal::static_int_cast<DWORD>(uOffset >> 32);
2742 DWORD const dwOffsetLo = sal::static_int_cast<DWORD>(uOffset & 0xFFFFFFFF);
2744 *ppAddr = ::MapViewOfFile( aMap.m_handle, FILE_MAP_READ, dwOffsetHi, dwOffsetLo, nLength );
2745 if (0 == *ppAddr)
2746 return MapError( GetLastError() );
2748 if (uFlags & osl_File_MapFlag_RandomAccess)
2750 // Determine memory pagesize.
2751 SYSTEM_INFO info;
2752 ::GetSystemInfo( &info );
2753 DWORD const dwPageSize = info.dwPageSize;
2756 * Pagein, touching first byte of each memory page.
2757 * Note: volatile disables optimizing the loop away.
2759 BYTE * pData (reinterpret_cast<BYTE*>(*ppAddr));
2760 SIZE_T nSize (nLength);
2762 volatile BYTE c = 0;
2763 while (nSize > dwPageSize)
2765 c ^= pData[0];
2766 pData += dwPageSize;
2767 nSize -= dwPageSize;
2769 if (nSize > 0)
2771 c ^= pData[0];
2772 pData += nSize;
2773 nSize -= nSize;
2776 return osl_File_E_None;
2779 //#############################################
2780 oslFileError SAL_CALL osl_unmapFile(void* pAddr, sal_uInt64 /* uLength */)
2782 if (0 == pAddr)
2783 return osl_File_E_INVAL;
2785 if (!::UnmapViewOfFile (pAddr))
2786 return MapError( GetLastError() );
2788 return osl_File_E_None;
2791 //#############################################
2792 oslFileError SAL_CALL osl_readFile(
2793 oslFileHandle Handle,
2794 void *pBuffer,
2795 sal_uInt64 uBytesRequested,
2796 sal_uInt64 *pBytesRead )
2798 oslFileError error;
2799 HANDLE hFile = (HANDLE)Handle;
2801 if ( IsValidHandle(hFile) )
2803 DWORD dwBytesToRead = (DWORD)uBytesRequested;
2804 DWORD dwBytesRead;
2806 if ( ReadFile( hFile, pBuffer, dwBytesToRead, &dwBytesRead, NULL ) )
2808 *pBytesRead = (sal_uInt64)dwBytesRead;
2809 error = osl_File_E_None;
2811 else
2812 error = MapError( GetLastError() );
2814 else
2815 error = osl_File_E_INVAL;
2817 return error;
2820 //#############################################
2821 oslFileError SAL_CALL osl_writeFile(
2822 oslFileHandle Handle,
2823 const void *pBuffer,
2824 sal_uInt64 uBytesToWrite,
2825 sal_uInt64 *pBytesWritten )
2827 oslFileError error;
2828 HANDLE hFile = (HANDLE)Handle;
2830 if ( IsValidHandle(hFile) )
2832 DWORD dwBytesToWrite = (DWORD)uBytesToWrite;
2833 DWORD dwBytesWritten;
2835 if ( WriteFile( hFile, pBuffer, dwBytesToWrite, &dwBytesWritten, NULL ) )
2837 *pBytesWritten = (sal_uInt64)dwBytesWritten;
2838 error = osl_File_E_None;
2840 else
2841 error = MapError( GetLastError() );
2843 else
2844 error = osl_File_E_INVAL;
2846 return error;
2849 //#############################################
2850 oslFileError SAL_CALL osl_readFileAt(
2851 oslFileHandle Handle,
2852 sal_uInt64 uOffset,
2853 void* pBuffer,
2854 sal_uInt64 uBytesRequested,
2855 sal_uInt64* pBytesRead)
2857 HANDLE hFile = (HANDLE)(Handle);
2858 if (!IsValidHandle(hFile) || (0 == pBuffer))
2859 return osl_File_E_INVAL;
2861 static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
2862 if (g_limit_dword < uBytesRequested)
2863 return osl_File_E_OVERFLOW;
2864 DWORD const dwBytes = sal::static_int_cast< DWORD >(uBytesRequested);
2866 if (0 == pBytesRead)
2867 return osl_File_E_INVAL;
2868 *pBytesRead = 0;
2870 oslFileError error = osl_setFilePos(Handle, osl_Pos_Absolut, uOffset);
2871 if (osl_File_E_None != error)
2872 return error;
2874 DWORD dwDone = 0;
2875 if (!::ReadFile(hFile, pBuffer, dwBytes, &dwDone, NULL))
2876 return MapError( GetLastError() );
2878 *pBytesRead = dwDone;
2879 return osl_File_E_None;
2882 //#############################################
2883 oslFileError SAL_CALL osl_writeFileAt(
2884 oslFileHandle Handle,
2885 sal_uInt64 uOffset,
2886 const void* pBuffer,
2887 sal_uInt64 uBytesToWrite,
2888 sal_uInt64* pBytesWritten)
2890 HANDLE hFile = (HANDLE)(Handle);
2891 if (!IsValidHandle(hFile) || (0 == pBuffer))
2892 return osl_File_E_INVAL;
2894 static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
2895 if (g_limit_dword < uBytesToWrite)
2896 return osl_File_E_OVERFLOW;
2897 DWORD const dwBytes = sal::static_int_cast< DWORD >(uBytesToWrite);
2899 if (0 == pBytesWritten)
2900 return osl_File_E_INVAL;
2901 *pBytesWritten = 0;
2903 oslFileError error = osl_setFilePos(Handle, osl_Pos_Absolut, uOffset);
2904 if (osl_File_E_None != error)
2905 return error;
2907 DWORD dwDone = 0;
2908 if (!::WriteFile(hFile, pBuffer, dwBytes, &dwDone, NULL))
2909 return MapError( GetLastError() );
2911 *pBytesWritten = dwDone;
2912 return osl_File_E_None;
2915 //#############################################
2916 oslFileError SAL_CALL osl_removeFile( rtl_uString* strPath )
2918 rtl_uString *strSysPath = NULL;
2919 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
2921 if ( osl_File_E_None == error )
2923 if ( DeleteFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
2924 error = osl_File_E_None;
2925 else
2926 error = MapError( GetLastError() );
2928 rtl_uString_release( strSysPath );
2930 return error;
2933 //#############################################
2934 #define osl_File_CopyRecursive 0x0001
2935 #define osl_File_CopyOverwrite 0x0002
2937 oslFileError SAL_CALL osl_copyFile( rtl_uString* strPath, rtl_uString *strDestPath )
2939 rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
2940 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
2942 if ( osl_File_E_None == error )
2943 error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
2945 if ( osl_File_E_None == error )
2947 if ( CopyFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )), reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath )), FALSE ) )
2948 error = osl_File_E_None;
2949 else
2950 error = MapError( GetLastError() );
2953 if ( strSysPath )
2954 rtl_uString_release( strSysPath );
2955 if ( strSysDestPath )
2956 rtl_uString_release( strSysDestPath );
2958 return error;
2961 //#############################################
2962 oslFileError SAL_CALL osl_moveFile( rtl_uString* strPath, rtl_uString *strDestPath )
2964 rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
2965 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
2967 if ( osl_File_E_None == error )
2968 error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
2970 if ( osl_File_E_None == error )
2972 if ( MoveFileEx( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )), reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING ) )
2973 error = osl_File_E_None;
2974 else
2975 error = MapError( GetLastError() );
2978 if ( strSysPath )
2979 rtl_uString_release( strSysPath );
2980 if ( strSysDestPath )
2981 rtl_uString_release( strSysDestPath );
2983 return error;
2986 //#############################################
2987 oslFileError SAL_CALL osl_setFileAttributes(
2988 rtl_uString *ustrFileURL,
2989 sal_uInt64 uAttributes )
2991 oslFileError error;
2992 rtl_uString *ustrSysPath = NULL;
2993 DWORD dwFileAttributes;
2994 BOOL fSuccess;
2996 // Converts the normalized path into a systempath
2997 error = _osl_getSystemPathFromFileURL( ustrFileURL, &ustrSysPath, sal_False );
2999 if ( osl_File_E_None != error )
3000 return error;
3002 dwFileAttributes = GetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)) );
3004 if ( (DWORD)-1 != dwFileAttributes )
3006 dwFileAttributes &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN);
3008 if ( uAttributes & osl_File_Attribute_ReadOnly )
3009 dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
3011 if ( uAttributes & osl_File_Attribute_Hidden )
3012 dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
3014 fSuccess = SetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)), dwFileAttributes );
3016 else
3017 fSuccess = FALSE;
3019 if ( !fSuccess )
3020 error = MapError( GetLastError() );
3022 rtl_uString_release( ustrSysPath );
3024 return error;
3027 //#####################################################
3028 oslFileError SAL_CALL osl_setFileTime(
3029 rtl_uString *filePath,
3030 const TimeValue *aCreationTime,
3031 const TimeValue *aLastAccessTime,
3032 const TimeValue *aLastWriteTime)
3034 oslFileError error;
3035 rtl_uString *sysPath=NULL;
3036 FILETIME *lpCreationTime=NULL;
3037 FILETIME *lpLastAccessTime=NULL;
3038 FILETIME *lpLastWriteTime=NULL;
3039 FILETIME ftCreationTime;
3040 FILETIME ftLastAccessTime;
3041 FILETIME ftLastWriteTime;
3042 HANDLE hFile;
3043 BOOL fSuccess;
3046 error=_osl_getSystemPathFromFileURL(filePath, &sysPath, sal_False);
3048 if (error==osl_File_E_INVAL)
3049 return error;
3051 hFile=CreateFileW(reinterpret_cast<LPCWSTR>(rtl_uString_getStr(sysPath)), GENERIC_WRITE, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3052 rtl_uString_release(sysPath);
3054 if (hFile==INVALID_HANDLE_VALUE)
3055 return osl_File_E_NOENT;
3057 if (TimeValueToFileTime(aCreationTime, &ftCreationTime))
3058 lpCreationTime=&ftCreationTime;
3060 if (TimeValueToFileTime(aLastAccessTime, &ftLastAccessTime))
3061 lpLastAccessTime=&ftLastAccessTime;
3063 if (TimeValueToFileTime(aLastWriteTime, &ftLastWriteTime))
3064 lpLastWriteTime=&ftLastWriteTime;
3066 fSuccess=SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
3068 CloseHandle(hFile);
3070 if (!fSuccess)
3071 return osl_File_E_INVAL;
3072 else
3073 return osl_File_E_None;
3076 //#####################################################
3077 oslFileError SAL_CALL osl_getFileStatus(
3078 oslDirectoryItem Item,
3079 oslFileStatus *pStatus,
3080 sal_uInt32 uFieldMask )
3082 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
3084 if ( !pItemImpl )
3085 return osl_File_E_INVAL;
3087 switch ( pItemImpl->uType )
3089 case DIRECTORYITEM_DRIVE:
3090 return osl_getDriveInfo( Item, pStatus, uFieldMask );
3091 case DIRECTORYITEM_SERVER:
3092 return osl_getServerInfo( Item, pStatus, uFieldMask );
3093 default:
3094 break;
3097 if ( uFieldMask & osl_FileStatus_Mask_Validate )
3099 HANDLE hFind = FindFirstFile( pItemImpl->szFullPath, &pItemImpl->FindData );
3101 if ( hFind != INVALID_HANDLE_VALUE )
3102 FindClose( hFind );
3103 else
3104 return MapError( GetLastError() );
3106 uFieldMask &= ~ osl_FileStatus_Mask_Validate;
3109 /* If no fields to retrieve left ignore pStatus */
3110 if ( !uFieldMask )
3111 return osl_File_E_None;
3113 /* Otherwise, this must be a valid pointer */
3114 if ( !pStatus )
3115 return osl_File_E_INVAL;
3117 if ( pStatus->uStructSize != sizeof(oslFileStatus) )
3118 return osl_File_E_INVAL;
3120 pStatus->uValidFields = 0;
3122 /* File time stamps */
3124 if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime) &&
3125 FileTimeToTimeValue( &pItemImpl->FindData.ftLastWriteTime, &pStatus->aModifyTime ) )
3126 pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime;
3128 if ( (uFieldMask & osl_FileStatus_Mask_AccessTime) &&
3129 FileTimeToTimeValue( &pItemImpl->FindData.ftLastAccessTime, &pStatus->aAccessTime ) )
3130 pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime;
3132 if ( (uFieldMask & osl_FileStatus_Mask_CreationTime) &&
3133 FileTimeToTimeValue( &pItemImpl->FindData.ftCreationTime, &pStatus->aCreationTime ) )
3134 pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime;
3136 /* Most of the fields are already set, regardless of requiered fields */
3138 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(pItemImpl->FindData.cFileName) );
3139 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
3141 if ((FILE_ATTRIBUTE_REPARSE_POINT & pItemImpl->FindData.dwFileAttributes) &&
3142 (IO_REPARSE_TAG_MOUNT_POINT == pItemImpl->FindData.dwReserved0))
3143 pStatus->eType = osl_File_Type_Volume;
3144 else if (pItemImpl->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
3145 pStatus->eType = osl_File_Type_Directory;
3146 else
3147 pStatus->eType = osl_File_Type_Regular;
3149 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
3151 pStatus->uAttributes = pItemImpl->FindData.dwFileAttributes;
3152 pStatus->uValidFields |= osl_FileStatus_Mask_Attributes;
3154 pStatus->uFileSize = (sal_uInt64)pItemImpl->FindData.nFileSizeLow + ((sal_uInt64)pItemImpl->FindData.nFileSizeHigh << 32);
3155 pStatus->uValidFields |= osl_FileStatus_Mask_FileSize;
3157 if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL )
3159 rtl_uString *ustrFullPath = NULL;
3161 rtl_uString_newFromStr( &ustrFullPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->szFullPath) );
3162 osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrLinkTargetURL );
3163 rtl_uString_release( ustrFullPath );
3165 pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
3168 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
3170 rtl_uString *ustrFullPath = NULL;
3173 if ( !pItemImpl->bFullPathNormalized )
3175 GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
3176 pItemImpl->bFullPathNormalized = TRUE;
3178 rtl_uString_newFromStr( &ustrFullPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->szFullPath) );
3179 osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrFileURL );
3180 rtl_uString_release( ustrFullPath );
3181 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
3184 return osl_File_E_None;
3187 //##################################################################
3188 // directory handling functions
3189 //##################################################################
3192 //#####################################################
3193 oslFileError SAL_CALL osl_createDirectory(rtl_uString* strPath)
3195 rtl_uString *strSysPath = NULL;
3196 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
3198 if ( osl_File_E_None == error )
3200 if ( CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), NULL ) )
3201 error = osl_File_E_None;
3202 /*@@@ToDo
3203 The else case is a hack because the ucb or the webtop had some
3204 problems with the error code that CreateDirectory returns in
3205 case the path is only a logical drive, should be removed!
3207 else
3209 const sal_Unicode *pBuffer = rtl_uString_getStr( strSysPath );
3210 sal_Int32 nLen = rtl_uString_getLength( strSysPath );
3212 if (
3213 ( pBuffer[0] >= 'A' && pBuffer[0] <= 'Z' ||
3214 pBuffer[0] >= 'a' && pBuffer[0] <= 'z' ) &&
3215 pBuffer[1] == ':' && ( nLen ==2 || nLen == 3 && pBuffer[2] == '\\' )
3217 SetLastError( ERROR_ALREADY_EXISTS );
3219 error = MapError( GetLastError() );
3222 rtl_uString_release( strSysPath );
3224 return error;
3227 //#####################################################
3228 oslFileError SAL_CALL osl_removeDirectory(rtl_uString* strPath)
3230 rtl_uString *strSysPath = NULL;
3231 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
3233 if ( osl_File_E_None == error )
3235 if ( RemoveDirectory( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
3236 error = osl_File_E_None;
3237 else
3238 error = MapError( GetLastError() );
3240 rtl_uString_release( strSysPath );
3242 return error;
3245 //#####################################################
3246 oslFileError SAL_CALL osl_openDirectory(rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
3248 oslFileError error;
3250 if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath->buffer, "file:///" ) )
3251 error = osl_openLocalRoot( strDirectoryPath, pDirectory );
3252 else
3254 rtl_uString *strSysDirectoryPath = NULL;
3255 // WCHAR szCorrectedPathName[MAX_PATH];
3256 DWORD dwPathType;
3258 error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysDirectoryPath, sal_False );
3260 if ( osl_File_E_None != error )
3261 return error;
3263 // MT Perform05
3265 if ( GetCaseCorrectPathName( strSysDirectoryPath->buffer, szCorrectedPathName, MAX_PATH ) )
3267 rtl_uString_newFromStr( &strSysDirectoryPath, szCorrectedPathName );
3271 dwPathType = IsValidFilePath( strSysDirectoryPath, NULL, VALIDATEPATH_NORMAL, NULL );
3273 if ( dwPathType & PATHTYPE_IS_SERVER )
3275 error = osl_openNetworkServer( strSysDirectoryPath, pDirectory );
3277 else
3278 error = osl_openFileDirectory( strSysDirectoryPath, pDirectory );
3280 rtl_uString_release( strSysDirectoryPath );
3282 return error;
3285 //#####################################################
3286 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
3288 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
3290 /* Assume failure */
3292 if ( !pItem )
3293 return osl_File_E_INVAL;
3295 *pItem = NULL;
3297 if ( !pDirImpl )
3298 return osl_File_E_INVAL;
3300 switch ( pDirImpl->uType )
3302 case DIRECTORYTYPE_LOCALROOT:
3303 return osl_getNextDrive( Directory, pItem, uHint );
3304 case DIRECTORYTYPE_NETROOT:
3305 return osl_getNextNetResource( Directory, pItem, uHint );
3306 case DIRECTORYTYPE_FILESYSTEM:
3307 return osl_getNextFileItem( Directory, pItem, uHint );
3308 default:
3309 return osl_File_E_INVAL;
3313 //#####################################################
3314 oslFileError SAL_CALL osl_closeDirectory(oslDirectory Directory)
3316 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
3317 oslFileError eError = osl_File_E_INVAL;
3319 if ( pDirImpl )
3321 switch ( pDirImpl->uType )
3323 case DIRECTORYTYPE_FILESYSTEM:
3324 eError = CloseDirectory( pDirImpl->hDirectory ) ? osl_File_E_None : MapError( GetLastError() );
3325 break;
3326 case DIRECTORYTYPE_LOCALROOT:
3327 eError = CloseLogicalDrivesEnum( pDirImpl->hEnumDrives ) ? osl_File_E_None : MapError( GetLastError() );
3328 break;
3329 case DIRECTORYTYPE_NETROOT:
3331 DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
3332 eError = (err == NO_ERROR) ? osl_File_E_None : MapError(err);
3334 break;
3335 default:
3336 OSL_ENSURE( 0, "Invalid directory type" );
3337 break;
3340 rtl_freeMemory(pDirImpl);
3342 return eError;
3345 //#####################################################
3346 oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString *strFilePath, oslDirectoryItem *pItem)
3348 oslFileError error = osl_File_E_None;
3349 rtl_uString* strSysFilePath = NULL;
3350 PATHTYPE type = PATHTYPE_FILE;
3351 DWORD dwPathType;
3352 // TCHAR szCorrectedPathName[MAX_PATH];
3354 /* Assume failure */
3356 if ( !pItem )
3357 return osl_File_E_INVAL;
3359 *pItem = NULL;
3362 error = _osl_getSystemPathFromFileURL( strFilePath, &strSysFilePath, sal_False );
3364 if ( osl_File_E_None != error )
3365 return error;
3367 // MT: I can't imagine a case where this is good for!
3369 if ( GetCaseCorrectPathName( strSysFilePath->buffer, szCorrectedPathName, MAX_PATH ) )
3371 rtl_uString_newFromStr( &strSysFilePath, szCorrectedPathName );
3375 dwPathType = IsValidFilePath( strSysFilePath, NULL, VALIDATEPATH_NORMAL, NULL );
3377 if ( dwPathType & PATHTYPE_IS_VOLUME )
3378 type = PATHTYPE_VOLUME;
3379 else if ( dwPathType & PATHTYPE_IS_SERVER )
3380 type = PATHTYPE_NETSERVER;
3381 else
3382 type = PATHTYPE_FILE;
3384 switch ( type )
3386 case PATHTYPE_NETSERVER:
3388 DirectoryItem_Impl* pItemImpl =
3389 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
3391 if ( !pItemImpl )
3392 error = osl_File_E_NOMEM;
3394 if ( osl_File_E_None == error )
3396 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
3397 pItemImpl->uType = DIRECTORYITEM_SERVER;
3399 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
3401 _tcscpy( pItemImpl->szFullPath, reinterpret_cast<LPCTSTR>(strSysFilePath->buffer) );
3403 // Assign a title anyway
3405 int iSrc = 2;
3406 int iDst = 0;
3408 while( iSrc < strSysFilePath->length && strSysFilePath->buffer[iSrc] && strSysFilePath->buffer[iSrc] != '\\' )
3410 pItemImpl->FindData.cFileName[iDst++] = strSysFilePath->buffer[iSrc++];
3414 *pItem = pItemImpl;
3417 break;
3418 case PATHTYPE_VOLUME:
3420 DirectoryItem_Impl* pItemImpl =
3421 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
3423 if ( !pItemImpl )
3424 error = osl_File_E_NOMEM;
3426 if ( osl_File_E_None == error )
3428 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
3429 pItemImpl->uType = DIRECTORYITEM_DRIVE;
3431 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
3433 _tcscpy( pItemImpl->cDriveString, reinterpret_cast<LPCTSTR>(strSysFilePath->buffer) );
3434 pItemImpl->cDriveString[0] = _toupper( pItemImpl->cDriveString[0] );
3436 if ( pItemImpl->cDriveString[_tcslen(pItemImpl->cDriveString) - 1] != '\\' )
3437 _tcscat( pItemImpl->cDriveString, TEXT( "\\" ) );
3439 *pItem = pItemImpl;
3442 break;
3443 case PATHTYPE_SYNTAXERROR:
3444 case PATHTYPE_NETROOT:
3445 case PATHTYPE_FILE:
3447 HANDLE hFind;
3448 WIN32_FIND_DATA aFindData;
3450 if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' )
3451 rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 );
3453 hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysFilePath)), &aFindData );
3455 if ( hFind != INVALID_HANDLE_VALUE )
3457 DirectoryItem_Impl *pItemImpl =
3458 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
3460 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
3461 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
3463 CopyMemory( &pItemImpl->FindData, &aFindData, sizeof(WIN32_FIND_DATA) );
3464 _tcscpy( pItemImpl->szFullPath, reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysFilePath)) );
3466 // MT: This costs 600ms startup time on fast v60x!
3467 // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
3469 pItemImpl->uType = DIRECTORYITEM_FILE;
3470 *pItem = pItemImpl;
3471 FindClose( hFind );
3473 else
3474 error = MapError( GetLastError() );
3476 break;
3479 if ( strSysFilePath )
3480 rtl_uString_release( strSysFilePath );
3482 return error;
3485 //#####################################################
3486 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
3488 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
3490 if ( !pItemImpl )
3491 return osl_File_E_INVAL;
3493 pItemImpl->nRefCount++;
3494 return osl_File_E_None;
3497 //#####################################################
3498 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
3500 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
3502 if ( !pItemImpl )
3503 return osl_File_E_INVAL;
3505 if ( ! --pItemImpl->nRefCount )
3506 rtl_freeMemory( pItemImpl );
3507 return osl_File_E_None;
3510 //#####################################################
3511 oslFileError SAL_CALL osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
3513 if ( Handle )
3514 return osl_File_E_None;
3515 else
3516 return osl_File_E_INVAL;
3519 //#####################################################
3520 oslFileError SAL_CALL osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
3522 if ( Handle )
3523 return osl_File_E_None;
3524 else
3525 return osl_File_E_INVAL;
3528 //#####################################################
3529 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
3531 if ( Handle )
3533 rtl_uString_acquire( (rtl_uString *)Handle );
3534 return osl_File_E_None;
3536 else
3537 return osl_File_E_INVAL;
3540 //#####################################################
3541 oslFileError SAL_CALL osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
3543 if ( Handle )
3545 rtl_uString_release( (rtl_uString *)Handle );
3546 return osl_File_E_None;
3548 else
3549 return osl_File_E_INVAL;
3552 //#####################################################
3553 oslFileError SAL_CALL osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
3555 if ( Handle && pstrPath )
3557 rtl_uString_assign( pstrPath, (rtl_uString *)Handle );
3558 return osl_File_E_None;
3560 else
3561 return osl_File_E_INVAL;
3565 //##################################################################
3566 // FileURL functions
3567 //##################################################################
3570 //#####################################################
3571 oslFileError SAL_CALL osl_getFileURLFromSystemPath(
3572 rtl_uString* ustrPath, rtl_uString** pustrURL )
3574 return _osl_getFileURLFromSystemPath( ustrPath, pustrURL );
3577 //#####################################################
3578 oslFileError SAL_CALL osl_getSystemPathFromFileURL(
3579 rtl_uString *ustrURL, rtl_uString **pustrPath)
3581 return _osl_getSystemPathFromFileURL( ustrURL, pustrPath, sal_True );
3584 //#####################################################
3585 oslFileError SAL_CALL osl_searchFileURL(
3586 rtl_uString *ustrFileName,
3587 rtl_uString *ustrSystemSearchPath,
3588 rtl_uString **pustrPath)
3590 rtl_uString *ustrUNCPath = NULL;
3591 rtl_uString *ustrSysPath = NULL;
3592 oslFileError error;
3594 /* First try to interpret the file name as an URL even a relative one */
3595 error = _osl_getSystemPathFromFileURL( ustrFileName, &ustrUNCPath, sal_True );
3597 /* So far we either have an UNC path or something invalid
3598 Now create a system path */
3599 if ( osl_File_E_None == error )
3600 error = _osl_getSystemPathFromFileURL( ustrUNCPath, &ustrSysPath, sal_True );
3602 if ( osl_File_E_None == error )
3604 DWORD nBufferLength;
3605 DWORD dwResult;
3606 LPTSTR lpBuffer = NULL;
3607 LPTSTR lpszFilePart;
3609 /* Repeat calling SearchPath ...
3610 Start with MAX_PATH for the buffer. In most cases this
3611 will be enough and does not force the loop to runtwice */
3612 dwResult = MAX_PATH;
3616 /* If search path is empty use a NULL pointer instead according to MSDN documentation of SearchPath */
3617 LPCTSTR lpszSearchPath = ustrSystemSearchPath && ustrSystemSearchPath->length ? reinterpret_cast<LPCTSTR>(ustrSystemSearchPath->buffer) : NULL;
3618 LPCTSTR lpszSearchFile = reinterpret_cast<LPCTSTR>(ustrSysPath->buffer);
3620 /* Allocate space for buffer according to previous returned count of required chars */
3621 /* +1 is not neccessary if we follow MSDN documentation but for robustness we do so */
3622 nBufferLength = dwResult + 1;
3623 lpBuffer = lpBuffer ?
3624 reinterpret_cast<LPTSTR>(rtl_reallocateMemory(lpBuffer, nBufferLength * sizeof(TCHAR))) :
3625 reinterpret_cast<LPTSTR>(rtl_allocateMemory(nBufferLength * sizeof(TCHAR)));
3627 dwResult = SearchPath( lpszSearchPath, lpszSearchFile, NULL, nBufferLength, lpBuffer, &lpszFilePart );
3628 } while ( dwResult && dwResult >= nBufferLength );
3630 /* ... until an error occures or buffer is large enough.
3631 dwResult == nBufferLength can not happen according to documentation but lets be robust ;-) */
3633 if ( dwResult )
3635 rtl_uString_newFromStr( &ustrSysPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) );
3636 error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath );
3638 else
3640 WIN32_FIND_DATA aFindFileData;
3641 HANDLE hFind;
3643 /* Somthing went wrong, perhaps the path was absolute */
3644 error = MapError( GetLastError() );
3646 hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(ustrSysPath->buffer), &aFindFileData );
3648 if ( IsValidHandle(hFind) )
3650 error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath );
3651 FindClose( hFind );
3655 rtl_freeMemory( lpBuffer );
3658 if ( ustrSysPath )
3659 rtl_uString_release( ustrSysPath );
3661 if ( ustrUNCPath )
3662 rtl_uString_release( ustrUNCPath );
3664 return error;
3667 //#####################################################
3669 oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL )
3671 oslFileError eError;
3672 rtl_uString *ustrRelSysPath = NULL;
3673 rtl_uString *ustrBaseSysPath = NULL;
3675 if ( ustrBaseURL && ustrBaseURL->length )
3677 eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False );
3678 OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" );
3680 eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True );
3682 else
3684 eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False );
3685 OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" );
3688 if ( !eError )
3690 TCHAR szBuffer[MAX_PATH];
3691 TCHAR szCurrentDir[MAX_PATH];
3692 LPTSTR lpFilePart = NULL;
3693 DWORD dwResult;
3695 /*@@@ToDo
3696 Bad, bad hack, this only works if the base path
3697 really exists which is not necessary according
3698 to RFC2396
3699 The whole FileURL implementation should be merged
3700 with the rtl/uri class.
3702 if ( ustrBaseSysPath )
3704 osl_acquireMutex( g_CurrentDirectoryMutex );
3706 GetCurrentDirectory( MAX_PATH, szCurrentDir );
3707 SetCurrentDirectory( reinterpret_cast<LPCTSTR>(ustrBaseSysPath->buffer) );
3710 dwResult = GetFullPathName( reinterpret_cast<LPCTSTR>(ustrRelSysPath->buffer), MAX_PATH, szBuffer, &lpFilePart );
3712 if ( ustrBaseSysPath )
3714 SetCurrentDirectory( szCurrentDir );
3716 osl_releaseMutex( g_CurrentDirectoryMutex );
3719 if ( dwResult )
3721 if ( dwResult >= MAX_PATH )
3722 eError = osl_File_E_INVAL;
3723 else
3725 rtl_uString *ustrAbsSysPath = NULL;
3727 rtl_uString_newFromStr( &ustrAbsSysPath, reinterpret_cast<const sal_Unicode*>(szBuffer) );
3729 eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL );
3731 if ( ustrAbsSysPath )
3732 rtl_uString_release( ustrAbsSysPath );
3735 else
3736 eError = MapError( GetLastError() );
3739 if ( ustrBaseSysPath )
3740 rtl_uString_release( ustrBaseSysPath );
3742 if ( ustrRelSysPath )
3743 rtl_uString_release( ustrRelSysPath );
3745 return eError;
3748 //#####################################################
3749 oslFileError SAL_CALL osl_getCanonicalName( rtl_uString *strRequested, rtl_uString **strValid )
3751 rtl_uString_newFromString(strValid, strRequested);
3752 return osl_File_E_None;