1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #define UNICODE
25 #define _UNICODE
26 #define _WIN32_WINNT_0x0500
27 #include "systools/win32/uwinapi.h"
28
29 #include "osl/file.h"
30
31 #include "file_url.h"
32 #include "file_error.h"
33
34 #include "path_helper.hxx"
35
36 #include "osl/diagnose.h"
37 #include "osl/time.h"
38 #include "rtl/alloc.h"
39 #include "rtl/ustring.hxx"
40
41 #include <tchar.h>
42 #ifdef __MINGW32__
43 #include <ctype.h>
44 #endif
45
46 //#####################################################
47 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
48
49 static const wchar_t UNC_PREFIX[] = L"\\\\";
50 static const wchar_t BACKSLASH = '\\';
51 static const wchar_t SLASH = '/';
52
53 //#####################################################
TimeValueToFileTime(const TimeValue * cpTimeVal,FILETIME * pFTime)54 extern "C" BOOL TimeValueToFileTime(const TimeValue *cpTimeVal, FILETIME *pFTime)
55 {
56 SYSTEMTIME BaseSysTime;
57 FILETIME BaseFileTime;
58 FILETIME FTime;
59 __int64 localTime;
60 BOOL fSuccess = FALSE;
61
62 BaseSysTime.wYear = 1970;
63 BaseSysTime.wMonth = 1;
64 BaseSysTime.wDayOfWeek = 0;
65 BaseSysTime.wDay = 1;
66 BaseSysTime.wHour = 0;
67 BaseSysTime.wMinute = 0;
68 BaseSysTime.wSecond = 0;
69 BaseSysTime.wMilliseconds = 0;
70
71 if (cpTimeVal==NULL)
72 return fSuccess;
73
74 if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
75 {
76 __int64 timeValue;
77 localTime=cpTimeVal->Seconds*(__int64)10000000+cpTimeVal->Nanosec/100;
78 *(__int64 *)&FTime=localTime;
79 fSuccess = 0 <= (timeValue= *((__int64 *)&BaseFileTime) + *((__int64 *) &FTime));
80 if (fSuccess)
81 *(__int64 *)pFTime=timeValue;
82 }
83 return fSuccess;
84 }
85
86 //#####################################################
FileTimeToTimeValue(const FILETIME * cpFTime,TimeValue * pTimeVal)87 extern "C" BOOL FileTimeToTimeValue(const FILETIME *cpFTime, TimeValue *pTimeVal)
88 {
89 SYSTEMTIME BaseSysTime;
90 FILETIME BaseFileTime;
91 BOOL fSuccess = FALSE; /* Assume failure */
92
93 BaseSysTime.wYear = 1970;
94 BaseSysTime.wMonth = 1;
95 BaseSysTime.wDayOfWeek = 0;
96 BaseSysTime.wDay = 1;
97 BaseSysTime.wHour = 0;
98 BaseSysTime.wMinute = 0;
99 BaseSysTime.wSecond = 0;
100 BaseSysTime.wMilliseconds = 0;
101
102 if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
103 {
104 __int64 Value;
105
106 fSuccess = 0 <= (Value = *((__int64 *)cpFTime) - *((__int64 *)&BaseFileTime));
107
108 if ( fSuccess )
109 {
110 pTimeVal->Seconds = (unsigned long) (Value / 10000000L);
111 pTimeVal->Nanosec = (unsigned long)((Value % 10000000L) * 100);
112 }
113 }
114 return fSuccess;
115 }
116
117 //#####################################################
118 namespace /* private */
119 {
120 //#####################################################
121 struct Component
122 {
Component__anon1d5b1b750111::Component123 Component() :
124 begin_(0), end_(0)
125 {}
126
isPresent__anon1d5b1b750111::Component127 bool isPresent() const
128 { return (static_cast<sal_IntPtr>(end_ - begin_) > 0); }
129
130 const sal_Unicode* begin_;
131 const sal_Unicode* end_;
132 };
133
134 //#####################################################
135 struct UNCComponents
136 {
137 Component server_;
138 Component share_;
139 Component resource_;
140 };
141
142 //#####################################################
is_UNC_path(const sal_Unicode * path)143 inline bool is_UNC_path(const sal_Unicode* path)
144 { return (0 == wcsncmp(UNC_PREFIX, reinterpret_cast<LPCWSTR>(path), ELEMENTS_OF_ARRAY(UNC_PREFIX) - 1)); }
145
146 //#####################################################
is_UNC_path(const rtl::OUString & path)147 inline bool is_UNC_path(const rtl::OUString& path)
148 { return is_UNC_path(path.getStr()); }
149
150 //#####################################################
parse_UNC_path(const sal_Unicode * path,UNCComponents * puncc)151 void parse_UNC_path(const sal_Unicode* path, UNCComponents* puncc)
152 {
153 OSL_PRECOND(is_UNC_path(path), "Precondition violated: No UNC path");
154 OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) == -1, "Path must not contain slashes");
155
156 const sal_Unicode* pend = path + rtl_ustr_getLength(path);
157 const sal_Unicode* ppos = path + 2;
158
159 puncc->server_.begin_ = ppos;
160 while ((ppos < pend) && (*ppos != BACKSLASH))
161 ppos++;
162
163 puncc->server_.end_ = ppos;
164
165 if (BACKSLASH == *ppos)
166 {
167 puncc->share_.begin_ = ++ppos;
168 while ((ppos < pend) && (*ppos != BACKSLASH))
169 ppos++;
170
171 puncc->share_.end_ = ppos;
172
173 if (BACKSLASH == *ppos)
174 {
175 puncc->resource_.begin_ = ++ppos;
176 while (ppos < pend)
177 ppos++;
178
179 puncc->resource_.end_ = ppos;
180 }
181 }
182
183 OSL_POSTCOND(puncc->server_.isPresent() && puncc->share_.isPresent(), \
184 "Postcondition violated: Invalid UNC path detected");
185 }
186
187 //#####################################################
parse_UNC_path(const rtl::OUString & path,UNCComponents * puncc)188 void parse_UNC_path(const rtl::OUString& path, UNCComponents* puncc)
189 { parse_UNC_path(path.getStr(), puncc); }
190
191
192 //#####################################################
has_path_parent(const sal_Unicode * path)193 bool has_path_parent(const sal_Unicode* path)
194 {
195 // Has the given path a parent or are we already there,
196 // e.g. 'c:\' or '\\server\share\'?
197
198 bool has_parent = false;
199 if (is_UNC_path(path))
200 {
201 UNCComponents unc_comp;
202 parse_UNC_path(path, &unc_comp);
203 has_parent = unc_comp.resource_.isPresent();
204 }
205 else
206 {
207 has_parent = !osl::systemPathIsLogicalDrivePattern(path);
208 }
209 return has_parent;
210 }
211
212 //#####################################################
has_path_parent(const rtl::OUString & path)213 inline bool has_path_parent(const rtl::OUString& path)
214 { return has_path_parent(path.getStr()); }
215
216 } // end namespace private
217
218 //#####################################################
219 // volume handling functions
220 //#####################################################
221
222 //#####################################################
osl_unmountVolumeDevice(oslVolumeDeviceHandle Handle)223 oslFileError SAL_CALL osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
224 {
225 if ( Handle )
226 return osl_File_E_None;
227 else
228 return osl_File_E_INVAL;
229 }
230
231 //#####################################################
osl_automountVolumeDevice(oslVolumeDeviceHandle Handle)232 oslFileError SAL_CALL osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
233 {
234 if ( Handle )
235 return osl_File_E_None;
236 else
237 return osl_File_E_INVAL;
238 }
239
240 //#####################################################
osl_acquireVolumeDeviceHandle(oslVolumeDeviceHandle Handle)241 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
242 {
243 if ( Handle )
244 {
245 rtl_uString_acquire( (rtl_uString *)Handle );
246 return osl_File_E_None;
247 }
248 else
249 return osl_File_E_INVAL;
250 }
251
252 //#####################################################
osl_releaseVolumeDeviceHandle(oslVolumeDeviceHandle Handle)253 oslFileError SAL_CALL osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
254 {
255 if ( Handle )
256 {
257 rtl_uString_release( (rtl_uString *)Handle );
258 return osl_File_E_None;
259 }
260 else
261 return osl_File_E_INVAL;
262 }
263
264 //#####################################################
osl_getVolumeDeviceMountPath(oslVolumeDeviceHandle Handle,rtl_uString ** pstrPath)265 oslFileError SAL_CALL osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
266 {
267 if ( Handle && pstrPath )
268 {
269 rtl_uString_assign( pstrPath, (rtl_uString *)Handle );
270 return osl_File_E_None;
271 }
272 else
273 return osl_File_E_INVAL;
274 }
275
276 //##################################################################
277 // directory handling functions
278 //##################################################################
279
280 #define DIRECTORYITEM_DRIVE 0
281 #define DIRECTORYITEM_FILE 1
282 #define DIRECTORYITEM_SERVER 2
283
284 struct DirectoryItem_Impl
285 {
286 UINT uType;
287 union {
288 WIN32_FIND_DATA FindData;
289 TCHAR cDriveString[MAX_PATH];
290 };
291 rtl_uString* m_pFullPath;
292 BOOL bFullPathNormalized;
293 int nRefCount;
294 };
295
296 //#####################################################
297
298 #define DIRECTORYTYPE_LOCALROOT 0
299 #define DIRECTORYTYPE_NETROOT 1
300 #define DIRECTORYTYPE_NETRESORCE 2
301 #define DIRECTORYTYPE_FILESYSTEM 3
302
303 struct Directory_Impl
304 {
305 UINT uType;
306 union {
307 HANDLE hDirectory;
308 HANDLE hEnumDrives;
309 };
310 rtl_uString* m_pDirectoryPath;
311 };
312
313 //#####################################################
314
315 typedef struct tagDRIVEENUM
316 {
317 LPCTSTR lpIdent;
318 TCHAR cBuffer[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
319 LPCTSTR lpCurrent;
320 } DRIVEENUM, * PDRIVEENUM, FAR * LPDRIVEENUM;
321
322 //#####################################################
323
OpenLogicalDrivesEnum(void)324 static HANDLE WINAPI OpenLogicalDrivesEnum(void)
325 {
326 LPDRIVEENUM pEnum = (LPDRIVEENUM)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM) );
327 if ( pEnum )
328 {
329 DWORD dwNumCopied = GetLogicalDriveStrings( (sizeof(pEnum->cBuffer) - 1) / sizeof(TCHAR), pEnum->cBuffer );
330
331 if ( dwNumCopied && dwNumCopied < sizeof(pEnum->cBuffer) / sizeof(TCHAR) )
332 {
333 pEnum->lpCurrent = pEnum->cBuffer;
334 pEnum->lpIdent = L"tagDRIVEENUM";
335 }
336 else
337 {
338 HeapFree( GetProcessHeap(), 0, pEnum );
339 pEnum = NULL;
340 }
341 }
342 return pEnum ? (HANDLE)pEnum : INVALID_HANDLE_VALUE;
343 }
344
345 //#####################################################
EnumLogicalDrives(HANDLE hEnum,LPTSTR lpBuffer)346 static BOOL WINAPI EnumLogicalDrives(HANDLE hEnum, LPTSTR lpBuffer)
347 {
348 BOOL fSuccess = FALSE;
349 LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
350
351 if ( pEnum )
352 {
353 int nLen = _tcslen( pEnum->lpCurrent );
354
355 if ( nLen )
356 {
357 CopyMemory( lpBuffer, pEnum->lpCurrent, (nLen + 1) * sizeof(TCHAR) );
358 pEnum->lpCurrent += nLen + 1;
359 fSuccess = TRUE;
360 }
361 else
362 SetLastError( ERROR_NO_MORE_FILES );
363 }
364 else
365 SetLastError( ERROR_INVALID_HANDLE );
366
367 return fSuccess;
368 }
369
370 //#####################################################
CloseLogicalDrivesEnum(HANDLE hEnum)371 static BOOL WINAPI CloseLogicalDrivesEnum(HANDLE hEnum)
372 {
373 BOOL fSuccess = FALSE;
374 LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
375
376 if ( pEnum )
377 {
378 HeapFree( GetProcessHeap(), 0, pEnum );
379 fSuccess = TRUE;
380 }
381 else
382 SetLastError( ERROR_INVALID_HANDLE );
383
384 return fSuccess;
385 }
386
387 //#####################################################
388 typedef struct tagDIRECTORY
389 {
390 HANDLE hFind;
391 WIN32_FIND_DATA aFirstData;
392 } DIRECTORY, *PDIRECTORY, FAR *LPDIRECTORY;
393
394 //#####################################################
OpenDirectory(rtl_uString * pPath)395 static HANDLE WINAPI OpenDirectory( rtl_uString* pPath)
396 {
397 LPDIRECTORY pDirectory = NULL;
398
399 if ( pPath )
400 {
401 sal_uInt32 nLen = rtl_uString_getLength( pPath );
402 if ( nLen )
403 {
404 TCHAR* pSuffix = 0;
405 sal_uInt32 nSuffLen = 0;
406
407 if ( pPath->buffer[nLen - 1] != L'\\' )
408 {
409 pSuffix = L"\\*.*";
410 nSuffLen = 4;
411 }
412 else
413 {
414 pSuffix = L"*.*";
415 nSuffLen = 3;
416 }
417
418 TCHAR* szFileMask = reinterpret_cast< TCHAR* >( rtl_allocateMemory( sizeof( TCHAR ) * ( nLen + nSuffLen + 1 ) ) );
419
420 _tcscpy( szFileMask, reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pPath ) ) );
421 _tcscat( szFileMask, pSuffix );
422
423 pDirectory = (LPDIRECTORY)HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY));
424 pDirectory->hFind = FindFirstFile(szFileMask, &pDirectory->aFirstData);
425
426 if (!IsValidHandle(pDirectory->hFind))
427 {
428 if ( GetLastError() != ERROR_NO_MORE_FILES )
429 {
430 HeapFree(GetProcessHeap(), 0, pDirectory);
431 pDirectory = NULL;
432 }
433 }
434
435 rtl_freeMemory(szFileMask); // #119939#, memory leak
436 }
437 }
438
439 return (HANDLE)pDirectory;
440 }
441
442 //#####################################################
EnumDirectory(HANDLE hDirectory,LPWIN32_FIND_DATA pFindData)443 BOOL WINAPI EnumDirectory(HANDLE hDirectory, LPWIN32_FIND_DATA pFindData)
444 {
445 BOOL fSuccess = FALSE;
446 LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
447
448 if ( pDirectory )
449 {
450 BOOL fValid;
451
452 do
453 {
454 if ( pDirectory->aFirstData.cFileName[0] )
455 {
456 *pFindData = pDirectory->aFirstData;
457 fSuccess = TRUE;
458 pDirectory->aFirstData.cFileName[0] = 0;
459 }
460 else if ( IsValidHandle( pDirectory->hFind ) )
461 fSuccess = FindNextFile( pDirectory->hFind, pFindData );
462 else
463 {
464 fSuccess = FALSE;
465 SetLastError( ERROR_NO_MORE_FILES );
466 }
467
468 fValid = fSuccess && _tcscmp( TEXT("."), pFindData->cFileName ) != 0 && _tcscmp( TEXT(".."), pFindData->cFileName ) != 0;
469
470 } while( fSuccess && !fValid );
471 }
472 else
473 SetLastError( ERROR_INVALID_HANDLE );
474
475 return fSuccess;
476 }
477
478 //#####################################################
CloseDirectory(HANDLE hDirectory)479 static BOOL WINAPI CloseDirectory(HANDLE hDirectory)
480 {
481 BOOL fSuccess = FALSE;
482 LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
483
484 if (pDirectory)
485 {
486 if (IsValidHandle(pDirectory->hFind))
487 fSuccess = FindClose(pDirectory->hFind);
488
489 fSuccess = HeapFree(GetProcessHeap(), 0, pDirectory) && fSuccess;
490 }
491 else
492 SetLastError(ERROR_INVALID_HANDLE);
493
494 return fSuccess;
495 }
496
497 //#####################################################
osl_openLocalRoot(rtl_uString * strDirectoryPath,oslDirectory * pDirectory)498 static oslFileError osl_openLocalRoot(
499 rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
500 {
501 rtl_uString *strSysPath = NULL;
502 oslFileError error;
503
504 if ( !pDirectory )
505 return osl_File_E_INVAL;
506
507 *pDirectory = NULL;
508
509 error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysPath, sal_False );
510 if ( osl_File_E_None == error )
511 {
512 Directory_Impl *pDirImpl;
513
514 pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory( sizeof(Directory_Impl)));
515 ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
516 rtl_uString_newFromString( &pDirImpl->m_pDirectoryPath, strSysPath );
517
518 /* Append backslash if necessary */
519
520 /* @@@ToDo
521 use function ensure backslash
522 */
523 sal_uInt32 nLen = rtl_uString_getLength( pDirImpl->m_pDirectoryPath );
524 if ( nLen && pDirImpl->m_pDirectoryPath->buffer[nLen - 1] != L'\\' )
525 {
526 rtl_uString* pCurDir = 0;
527 rtl_uString* pBackSlash = 0;
528
529 rtl_uString_assign( &pCurDir, pDirImpl->m_pDirectoryPath );
530 rtl_uString_newFromAscii( &pBackSlash, "\\" );
531 rtl_uString_newConcat( &pDirImpl->m_pDirectoryPath, pCurDir, pBackSlash );
532 rtl_uString_release( pBackSlash );
533 rtl_uString_release( pCurDir );
534 }
535
536 pDirImpl->uType = DIRECTORYTYPE_LOCALROOT;
537 pDirImpl->hEnumDrives = OpenLogicalDrivesEnum();
538
539 /* @@@ToDo
540 Use IsValidHandle(...)
541 */
542 if ( pDirImpl->hEnumDrives != INVALID_HANDLE_VALUE )
543 {
544 *pDirectory = (oslDirectory)pDirImpl;
545 error = osl_File_E_None;
546 }
547 else
548 {
549 if ( pDirImpl )
550 {
551 if ( pDirImpl->m_pDirectoryPath )
552 {
553 rtl_uString_release( pDirImpl->m_pDirectoryPath );
554 pDirImpl->m_pDirectoryPath = 0;
555 }
556
557 rtl_freeMemory(pDirImpl);
558 pDirImpl = 0;
559 }
560
561 error = oslTranslateFileError( GetLastError() );
562 }
563
564 rtl_uString_release( strSysPath );
565 }
566 return error;
567 }
568
569 //#####################################################
osl_openFileDirectory(rtl_uString * strDirectoryPath,oslDirectory * pDirectory)570 static oslFileError SAL_CALL osl_openFileDirectory(
571 rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
572 {
573 oslFileError error = osl_File_E_None;
574
575 if ( !pDirectory )
576 return osl_File_E_INVAL;
577 *pDirectory = NULL;
578
579 Directory_Impl *pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
580 ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
581 rtl_uString_newFromString( &pDirImpl->m_pDirectoryPath, strDirectoryPath );
582
583 /* Append backslash if necessary */
584
585 /* @@@ToDo
586 use function ensure backslash
587 */
588 sal_uInt32 nLen = rtl_uString_getLength( pDirImpl->m_pDirectoryPath );
589 if ( nLen && pDirImpl->m_pDirectoryPath->buffer[nLen - 1] != L'\\' )
590 {
591 rtl_uString* pCurDir = 0;
592 rtl_uString* pBackSlash = 0;
593
594 rtl_uString_assign( &pCurDir, pDirImpl->m_pDirectoryPath );
595 rtl_uString_newFromAscii( &pBackSlash, "\\" );
596 rtl_uString_newConcat( &pDirImpl->m_pDirectoryPath, pCurDir, pBackSlash );
597 rtl_uString_release( pBackSlash );
598 rtl_uString_release( pCurDir );
599 }
600
601
602 pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM;
603 pDirImpl->hDirectory = OpenDirectory( pDirImpl->m_pDirectoryPath );
604
605 if ( !pDirImpl->hDirectory )
606 {
607 error = oslTranslateFileError( GetLastError() );
608
609 if ( pDirImpl->m_pDirectoryPath )
610 {
611 rtl_uString_release( pDirImpl->m_pDirectoryPath );
612 pDirImpl->m_pDirectoryPath = 0;
613 }
614
615 rtl_freeMemory(pDirImpl), pDirImpl = 0;
616 }
617
618 *pDirectory = (oslDirectory)(pDirImpl);
619 return error;
620 }
621
622 //#####################################################
osl_openNetworkServer(rtl_uString * strSysDirPath,oslDirectory * pDirectory)623 static oslFileError SAL_CALL osl_openNetworkServer(
624 rtl_uString *strSysDirPath, oslDirectory *pDirectory)
625 {
626 NETRESOURCEW aNetResource;
627 HANDLE hEnum;
628 DWORD dwError;
629
630 ZeroMemory( &aNetResource, sizeof(aNetResource) );
631
632 aNetResource.lpRemoteName = reinterpret_cast<LPWSTR>(strSysDirPath->buffer);
633
634 dwError = WNetOpenEnumW(
635 RESOURCE_GLOBALNET,
636 RESOURCETYPE_DISK,
637 RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER,
638 &aNetResource,
639 &hEnum );
640
641 if ( ERROR_SUCCESS == dwError )
642 {
643 Directory_Impl *pDirImpl;
644
645 pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
646 ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
647 pDirImpl->uType = DIRECTORYTYPE_NETROOT;
648 pDirImpl->hDirectory = hEnum;
649 *pDirectory = (oslDirectory)pDirImpl;
650 }
651 return oslTranslateFileError( dwError );
652 }
653
654 //#############################################
create_dir_with_callback(rtl_uString * dir_path,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)655 static DWORD create_dir_with_callback(
656 rtl_uString * dir_path,
657 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
658 void* pData)
659 {
660 // Create the specified directory and call the
661 // user specified callback function. On success
662 // the function returns ERROR_SUCCESS else a Win32 error code.
663
664 BOOL bCreated = FALSE;
665
666 bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( dir_path )), NULL );
667
668 if ( bCreated )
669 {
670 if (aDirectoryCreationCallbackFunc)
671 {
672 rtl::OUString url;
673 _osl_getFileURLFromSystemPath(dir_path, &(url.pData));
674 aDirectoryCreationCallbackFunc(pData, url.pData);
675 }
676 return ERROR_SUCCESS;
677 }
678 return GetLastError();
679 }
680
681 //#############################################
path_make_parent(sal_Unicode * path)682 static int path_make_parent(sal_Unicode* path)
683 {
684 /* Cut off the last part of the given path to
685 get the parent only, e.g. 'c:\dir\subdir' ->
686 'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
687 @return The position where the path has been cut
688 off (this is the posistion of the last backslash).
689 If there are no more parents 0 will be returned,
690 e.g. 'c:\' or '\\Share' have no more parents */
691
692 OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) == -1, "Path must not contain slashes");
693 OSL_PRECOND(has_path_parent(path), "Path must have a parent");
694
695 sal_Unicode* pos_last_backslash = path + rtl_ustr_lastIndexOfChar(path, BACKSLASH);
696 *pos_last_backslash = 0;
697 return (pos_last_backslash - path);
698 }
699
700 //#############################################
create_dir_recursively_(rtl_uString * dir_path,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)701 static DWORD create_dir_recursively_(
702 rtl_uString * dir_path,
703 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
704 void* pData)
705 {
706 OSL_PRECOND(
707 rtl_ustr_lastIndexOfChar_WithLength(dir_path->buffer, dir_path->length, BACKSLASH) != dir_path->length,
708 "Path must not end with a backslash");
709
710 DWORD w32_error = create_dir_with_callback(
711 dir_path, aDirectoryCreationCallbackFunc, pData);
712 if (w32_error == ERROR_SUCCESS)
713 return ERROR_SUCCESS;
714
715 if ((w32_error != ERROR_PATH_NOT_FOUND) || !has_path_parent(dir_path->buffer))
716 return w32_error;
717
718 int pos = path_make_parent(dir_path->buffer); // dir_path->buffer[pos] = 0, restore below
719
720 w32_error = create_dir_recursively_(
721 dir_path, aDirectoryCreationCallbackFunc, pData);
722
723 dir_path->buffer[pos] = BACKSLASH; // restore
724
725 if (ERROR_SUCCESS != w32_error)
726 return w32_error;
727
728 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
729 }
730
731 //#############################################
osl_createDirectoryPath(rtl_uString * aDirectoryUrl,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)732 oslFileError SAL_CALL osl_createDirectoryPath(
733 rtl_uString* aDirectoryUrl,
734 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
735 void* pData)
736 {
737 if (aDirectoryUrl == NULL)
738 return osl_File_E_INVAL;
739
740 rtl::OUString sys_path;
741 oslFileError osl_error =
742 _osl_getSystemPathFromFileURL(aDirectoryUrl, &sys_path.pData, sal_False);
743
744 if (osl_error != osl_File_E_None)
745 return osl_error;
746
747 osl::systemPathRemoveSeparator(sys_path);
748
749 // const_cast because sys_path is a local copy
750 // which we want to modify inplace instead of
751 // coyp it into another buffer on the heap again
752 return oslTranslateFileError(create_dir_recursively_(
753 sys_path.pData, aDirectoryCreationCallbackFunc, pData));
754 }
755
756 //#####################################################
osl_createDirectory(rtl_uString * strPath)757 oslFileError SAL_CALL osl_createDirectory(rtl_uString* strPath)
758 {
759 rtl_uString *strSysPath = NULL;
760 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
761
762 if ( osl_File_E_None == error )
763 {
764 BOOL bCreated = FALSE;
765
766 bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), NULL );
767
768 if ( !bCreated )
769 {
770 /*@@@ToDo
771 The following case is a hack because the ucb or the webtop had some
772 problems with the error code that CreateDirectory returns in
773 case the path is only a logical drive, should be removed!
774 */
775
776 const sal_Unicode *pBuffer = rtl_uString_getStr( strSysPath );
777 sal_Int32 nLen = rtl_uString_getLength( strSysPath );
778
779 if (
780 ( ( pBuffer[0] >= 'A' && pBuffer[0] <= 'Z' ) ||
781 ( pBuffer[0] >= 'a' && pBuffer[0] <= 'z' ) ) &&
782 pBuffer[1] == ':' && ( nLen ==2 || ( nLen == 3 && pBuffer[2] == '\\' ) )
783 )
784 SetLastError( ERROR_ALREADY_EXISTS );
785
786 error = oslTranslateFileError( GetLastError() );
787 }
788
789 rtl_uString_release( strSysPath );
790 }
791 return error;
792 }
793
794 //#####################################################
osl_removeDirectory(rtl_uString * strPath)795 oslFileError SAL_CALL osl_removeDirectory(rtl_uString* strPath)
796 {
797 rtl_uString *strSysPath = NULL;
798 oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
799
800 if ( osl_File_E_None == error )
801 {
802 if ( RemoveDirectory( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
803 error = osl_File_E_None;
804 else
805 error = oslTranslateFileError( GetLastError() );
806
807 rtl_uString_release( strSysPath );
808 }
809 return error;
810 }
811
812 //#####################################################
osl_openDirectory(rtl_uString * strDirectoryPath,oslDirectory * pDirectory)813 oslFileError SAL_CALL osl_openDirectory(rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
814 {
815 oslFileError error;
816
817 if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath->buffer, "file:///" ) )
818 error = osl_openLocalRoot( strDirectoryPath, pDirectory );
819 else
820 {
821 rtl_uString *strSysDirectoryPath = NULL;
822 DWORD dwPathType;
823
824 error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysDirectoryPath, sal_False );
825
826 if ( osl_File_E_None != error )
827 return error;
828
829 dwPathType = IsValidFilePath( strSysDirectoryPath, NULL, VALIDATEPATH_NORMAL, NULL );
830
831 if ( dwPathType & PATHTYPE_IS_SERVER )
832 {
833 error = osl_openNetworkServer( strSysDirectoryPath, pDirectory );
834 }
835 else
836 error = osl_openFileDirectory( strSysDirectoryPath, pDirectory );
837
838 rtl_uString_release( strSysDirectoryPath );
839 }
840 return error;
841 }
842
843 //#####################################################
osl_getNextNetResource(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)844 static oslFileError SAL_CALL osl_getNextNetResource(
845 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
846 {
847 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
848 DirectoryItem_Impl *pItemImpl = NULL;
849 BYTE buffer[16384];
850 LPNETRESOURCEW lpNetResource = (LPNETRESOURCEW)buffer;
851 DWORD dwError, dwCount, dwBufSize;
852
853 uHint = uHint; /* to get no warning */
854
855 if ( !pItem )
856 return osl_File_E_INVAL;
857 *pItem = NULL;
858
859 if ( !pDirImpl )
860 return osl_File_E_INVAL;
861
862 dwCount = 1;
863 dwBufSize = sizeof(buffer);
864 dwError = WNetEnumResource( pDirImpl->hDirectory, &dwCount, lpNetResource, &dwBufSize );
865
866 switch ( dwError )
867 {
868 case NO_ERROR:
869 case ERROR_MORE_DATA:
870 {
871 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
872 if ( !pItemImpl )
873 return osl_File_E_NOMEM;
874
875 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
876 pItemImpl->uType = DIRECTORYITEM_DRIVE;
877 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
878
879 wcscpy( pItemImpl->cDriveString, lpNetResource->lpRemoteName );
880
881 *pItem = pItemImpl;
882 }
883 return osl_File_E_None;
884 case ERROR_NO_MORE_ITEMS:
885 return osl_File_E_NOENT;
886 default:
887 return oslTranslateFileError( dwError );
888 }
889 }
890
891 //#####################################################
osl_getNextDrive(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)892 static oslFileError SAL_CALL osl_getNextDrive(
893 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
894 {
895 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
896 DirectoryItem_Impl *pItemImpl = NULL;
897 BOOL fSuccess;
898
899 uHint = uHint; /* avoid warnings */
900
901 if ( !pItem )
902 return osl_File_E_INVAL;
903 *pItem = NULL;
904
905 if ( !pDirImpl )
906 return osl_File_E_INVAL;
907
908 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
909 if ( !pItemImpl )
910 return osl_File_E_NOMEM;
911
912 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
913 pItemImpl->uType = DIRECTORYITEM_DRIVE;
914 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
915 fSuccess = EnumLogicalDrives( pDirImpl->hEnumDrives, pItemImpl->cDriveString );
916
917 if ( fSuccess )
918 {
919 *pItem = pItemImpl;
920 return osl_File_E_None;
921 }
922 else
923 {
924 if ( pItemImpl->m_pFullPath )
925 {
926 rtl_uString_release( pItemImpl->m_pFullPath );
927 pItemImpl->m_pFullPath = 0;
928 }
929
930 rtl_freeMemory( pItemImpl );
931 return oslTranslateFileError( GetLastError() );
932 }
933 }
934
935 //#####################################################
osl_getNextFileItem(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)936 static oslFileError SAL_CALL osl_getNextFileItem(
937 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
938 {
939 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
940 DirectoryItem_Impl *pItemImpl = NULL;
941 BOOL fFound;
942
943 uHint = uHint; /* avoid warnings */
944
945 if ( !pItem )
946 return osl_File_E_INVAL;
947 *pItem = NULL;
948
949 if ( !pDirImpl )
950 return osl_File_E_INVAL;
951
952 pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
953 if ( !pItemImpl )
954 return osl_File_E_NOMEM;
955
956 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
957 fFound = EnumDirectory( pDirImpl->hDirectory, &pItemImpl->FindData );
958
959 if ( fFound )
960 {
961 pItemImpl->uType = DIRECTORYITEM_FILE;
962 pItemImpl->nRefCount = 1;
963
964 rtl_uString* pTmpFileName = 0;
965 rtl_uString_newFromStr( &pTmpFileName, reinterpret_cast<const sal_Unicode *>(pItemImpl->FindData.cFileName) );
966 rtl_uString_newConcat( &pItemImpl->m_pFullPath, pDirImpl->m_pDirectoryPath, pTmpFileName );
967 rtl_uString_release( pTmpFileName );
968
969 pItemImpl->bFullPathNormalized = FALSE;
970 *pItem = (oslDirectoryItem)pItemImpl;
971 return osl_File_E_None;
972 }
973 else
974 {
975 if ( pItemImpl->m_pFullPath )
976 {
977 rtl_uString_release( pItemImpl->m_pFullPath );
978 pItemImpl->m_pFullPath = 0;
979 }
980
981 rtl_freeMemory( pItemImpl );
982 return oslTranslateFileError( GetLastError() );
983 }
984 }
985
986 //#####################################################
osl_getNextDirectoryItem(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)987 oslFileError SAL_CALL osl_getNextDirectoryItem(
988 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
989 {
990 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
991
992 /* Assume failure */
993
994 if ( !pItem )
995 return osl_File_E_INVAL;
996 *pItem = NULL;
997
998 if ( !pDirImpl )
999 return osl_File_E_INVAL;
1000
1001 switch ( pDirImpl->uType )
1002 {
1003 case DIRECTORYTYPE_LOCALROOT:
1004 return osl_getNextDrive( Directory, pItem, uHint );
1005 case DIRECTORYTYPE_NETROOT:
1006 return osl_getNextNetResource( Directory, pItem, uHint );
1007 case DIRECTORYTYPE_FILESYSTEM:
1008 return osl_getNextFileItem( Directory, pItem, uHint );
1009 default:
1010 return osl_File_E_INVAL;
1011 }
1012 }
1013
1014 //#####################################################
osl_closeDirectory(oslDirectory Directory)1015 oslFileError SAL_CALL osl_closeDirectory(oslDirectory Directory)
1016 {
1017 Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
1018 oslFileError eError = osl_File_E_INVAL;
1019
1020 if ( pDirImpl )
1021 {
1022 switch ( pDirImpl->uType )
1023 {
1024 case DIRECTORYTYPE_FILESYSTEM:
1025 eError = CloseDirectory( pDirImpl->hDirectory ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
1026 break;
1027 case DIRECTORYTYPE_LOCALROOT:
1028 eError = CloseLogicalDrivesEnum( pDirImpl->hEnumDrives ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
1029 break;
1030 case DIRECTORYTYPE_NETROOT:
1031 {
1032 DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
1033 eError = (err == NO_ERROR) ? osl_File_E_None : oslTranslateFileError(err);
1034 }
1035 break;
1036 default:
1037 OSL_ENSURE( 0, "Invalid directory type" );
1038 break;
1039 }
1040
1041 if ( pDirImpl->m_pDirectoryPath )
1042 {
1043 rtl_uString_release( pDirImpl->m_pDirectoryPath );
1044 pDirImpl->m_pDirectoryPath = 0;
1045 }
1046
1047 rtl_freeMemory(pDirImpl);
1048 }
1049 return eError;
1050 }
1051
1052 //#####################################################
1053 /* Different types of paths */
1054 typedef enum _PATHTYPE
1055 {
1056 PATHTYPE_SYNTAXERROR = 0,
1057 PATHTYPE_NETROOT,
1058 PATHTYPE_NETSERVER,
1059 PATHTYPE_VOLUME,
1060 PATHTYPE_FILE
1061 } PATHTYPE;
1062
osl_getDirectoryItem(rtl_uString * strFilePath,oslDirectoryItem * pItem)1063 oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString *strFilePath, oslDirectoryItem *pItem)
1064 {
1065 oslFileError error = osl_File_E_None;
1066 rtl_uString* strSysFilePath = NULL;
1067 PATHTYPE type = PATHTYPE_FILE;
1068 DWORD dwPathType;
1069
1070 /* Assume failure */
1071
1072 if ( !pItem )
1073 return osl_File_E_INVAL;
1074
1075 *pItem = NULL;
1076
1077
1078 error = _osl_getSystemPathFromFileURL( strFilePath, &strSysFilePath, sal_False );
1079
1080 if ( osl_File_E_None != error )
1081 return error;
1082
1083 dwPathType = IsValidFilePath( strSysFilePath, NULL, VALIDATEPATH_NORMAL, NULL );
1084
1085 if ( dwPathType & PATHTYPE_IS_VOLUME )
1086 type = PATHTYPE_VOLUME;
1087 else if ( dwPathType & PATHTYPE_IS_SERVER )
1088 type = PATHTYPE_NETSERVER;
1089 else
1090 type = PATHTYPE_FILE;
1091
1092 switch ( type )
1093 {
1094 case PATHTYPE_NETSERVER:
1095 {
1096 DirectoryItem_Impl* pItemImpl =
1097 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1098
1099 if ( !pItemImpl )
1100 error = osl_File_E_NOMEM;
1101
1102 if ( osl_File_E_None == error )
1103 {
1104 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1105 pItemImpl->uType = DIRECTORYITEM_SERVER;
1106
1107 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1108 rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath );
1109
1110 // Assign a title anyway
1111 {
1112 int iSrc = 2;
1113 int iDst = 0;
1114
1115 while( iSrc < strSysFilePath->length && strSysFilePath->buffer[iSrc] && strSysFilePath->buffer[iSrc] != '\\' )
1116 {
1117 pItemImpl->FindData.cFileName[iDst++] = strSysFilePath->buffer[iSrc++];
1118 }
1119 }
1120
1121 *pItem = pItemImpl;
1122 }
1123 }
1124 break;
1125 case PATHTYPE_VOLUME:
1126 {
1127 DirectoryItem_Impl* pItemImpl =
1128 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1129
1130 if ( !pItemImpl )
1131 error = osl_File_E_NOMEM;
1132
1133 if ( osl_File_E_None == error )
1134 {
1135 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1136 pItemImpl->uType = DIRECTORYITEM_DRIVE;
1137
1138 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1139
1140 _tcscpy( pItemImpl->cDriveString, reinterpret_cast<LPCTSTR>(strSysFilePath->buffer) );
1141 pItemImpl->cDriveString[0] = _toupper( pItemImpl->cDriveString[0] );
1142
1143 if ( pItemImpl->cDriveString[_tcslen(pItemImpl->cDriveString) - 1] != '\\' )
1144 _tcscat( pItemImpl->cDriveString, TEXT( "\\" ) );
1145
1146 *pItem = pItemImpl;
1147 }
1148 }
1149 break;
1150 case PATHTYPE_SYNTAXERROR:
1151 case PATHTYPE_NETROOT:
1152 case PATHTYPE_FILE:
1153 {
1154 HANDLE hFind;
1155 WIN32_FIND_DATA aFindData;
1156
1157 if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' )
1158 rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 );
1159
1160 hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysFilePath)), &aFindData );
1161
1162 if ( hFind != INVALID_HANDLE_VALUE )
1163 {
1164 DirectoryItem_Impl *pItemImpl =
1165 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
1166
1167 ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
1168 osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
1169
1170 CopyMemory( &pItemImpl->FindData, &aFindData, sizeof(WIN32_FIND_DATA) );
1171 rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath );
1172
1173 // MT: This costs 600ms startup time on fast v60x!
1174 // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
1175
1176 pItemImpl->uType = DIRECTORYITEM_FILE;
1177 *pItem = pItemImpl;
1178 FindClose( hFind );
1179 }
1180 else
1181 error = oslTranslateFileError( GetLastError() );
1182 }
1183 break;
1184 }
1185
1186 if ( strSysFilePath )
1187 rtl_uString_release( strSysFilePath );
1188
1189 return error;
1190 }
1191
1192 //#####################################################
osl_acquireDirectoryItem(oslDirectoryItem Item)1193 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
1194 {
1195 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1196
1197 if ( !pItemImpl )
1198 return osl_File_E_INVAL;
1199
1200 pItemImpl->nRefCount++;
1201 return osl_File_E_None;
1202 }
1203
1204 //#####################################################
osl_releaseDirectoryItem(oslDirectoryItem Item)1205 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
1206 {
1207 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1208
1209 if ( !pItemImpl )
1210 return osl_File_E_INVAL;
1211
1212 if ( ! --pItemImpl->nRefCount )
1213 {
1214 if ( pItemImpl->m_pFullPath )
1215 {
1216 rtl_uString_release( pItemImpl->m_pFullPath );
1217 pItemImpl->m_pFullPath = 0;
1218 }
1219
1220 rtl_freeMemory( pItemImpl );
1221 }
1222
1223 return osl_File_E_None;
1224 }
1225
1226 //#####################################################
1227 // volume / file info handling functions
1228 //#####################################################
1229
1230 //#####################################################
is_floppy_A_present()1231 static inline bool is_floppy_A_present()
1232 { return (GetLogicalDrives() & 1); }
1233
1234 //#####################################################
is_floppy_B_present()1235 static inline bool is_floppy_B_present()
1236 { return (GetLogicalDrives() & 2); }
1237
1238 //#####################################################
is_floppy_volume_mount_point(const rtl::OUString & path)1239 bool is_floppy_volume_mount_point(const rtl::OUString& path)
1240 {
1241 // determines if a volume mount point shows to a floppy
1242 // disk by comparing the unique volume names
1243 static const LPCWSTR FLOPPY_A = L"A:\\";
1244 static const LPCWSTR FLOPPY_B = L"B:\\";
1245
1246 rtl::OUString p(path);
1247 osl::systemPathEnsureSeparator(p);
1248
1249 TCHAR vn[51];
1250 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1251 {
1252 TCHAR vnfloppy[51];
1253 if (is_floppy_A_present() &&
1254 GetVolumeNameForVolumeMountPoint(FLOPPY_A, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1255 (0 == wcscmp(vn, vnfloppy)))
1256 return true;
1257
1258 if (is_floppy_B_present() &&
1259 GetVolumeNameForVolumeMountPoint(FLOPPY_B, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
1260 (0 == wcscmp(vn, vnfloppy)))
1261 return true;
1262 }
1263 return false;
1264 }
1265
1266 //################################################
is_floppy_drive(const rtl::OUString & path)1267 static bool is_floppy_drive(const rtl::OUString& path)
1268 {
1269 static const LPCWSTR FLOPPY_DRV_LETTERS = TEXT("AaBb");
1270
1271 // we must take into account that even a floppy
1272 // drive may be mounted to a directory so checking
1273 // for the drive letter alone is not sufficient
1274 // we must compare the unique volume name with
1275 // that of the available floppy disks
1276
1277 const sal_Unicode* pszPath = path.getStr();
1278 return ((wcschr(FLOPPY_DRV_LETTERS, pszPath[0]) && (L':' == pszPath[1])) || is_floppy_volume_mount_point(path));
1279 }
1280
1281 //#####################################################
is_volume_mount_point(const rtl::OUString & path)1282 static bool is_volume_mount_point(const rtl::OUString& path)
1283 {
1284 rtl::OUString p(path);
1285 osl::systemPathRemoveSeparator(p);
1286
1287 bool is_volume_root = false;
1288
1289 if (!is_floppy_drive(p))
1290 {
1291 DWORD fattr = GetFileAttributes(reinterpret_cast<LPCTSTR>(p.getStr()));
1292
1293 if ((INVALID_FILE_ATTRIBUTES != fattr) &&
1294 (FILE_ATTRIBUTE_REPARSE_POINT & fattr))
1295 {
1296 WIN32_FIND_DATA find_data;
1297 HANDLE h_find = FindFirstFile(reinterpret_cast<LPCTSTR>(p.getStr()), &find_data);
1298
1299 if (IsValidHandle(h_find) &&
1300 (FILE_ATTRIBUTE_REPARSE_POINT & find_data.dwFileAttributes) &&
1301 (IO_REPARSE_TAG_MOUNT_POINT == find_data.dwReserved0))
1302 {
1303 is_volume_root = true;
1304 }
1305 if (IsValidHandle(h_find))
1306 FindClose(h_find);
1307 }
1308 }
1309 return is_volume_root;
1310 }
1311
1312 //#############################################
get_volume_mount_point_drive_type(const rtl::OUString & path)1313 static UINT get_volume_mount_point_drive_type(const rtl::OUString& path)
1314 {
1315 if (0 == path.getLength())
1316 return GetDriveType(NULL);
1317
1318 rtl::OUString p(path);
1319 osl::systemPathEnsureSeparator(p);
1320
1321 TCHAR vn[51];
1322 if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
1323 return GetDriveType(vn);
1324
1325 return DRIVE_NO_ROOT_DIR;
1326 }
1327
1328 //#############################################
is_drivetype_request(sal_uInt32 field_mask)1329 static inline bool is_drivetype_request(sal_uInt32 field_mask)
1330 {
1331 return (field_mask & osl_VolumeInfo_Mask_Attributes);
1332 }
1333
1334 //#############################################
osl_get_drive_type(const rtl::OUString & path,oslVolumeInfo * pInfo)1335 static oslFileError osl_get_drive_type(
1336 const rtl::OUString& path, oslVolumeInfo* pInfo)
1337 {
1338 // GetDriveType fails on empty volume mount points
1339 // see Knowledge Base Q244089
1340 UINT drive_type;
1341 if (is_volume_mount_point(path))
1342 drive_type = get_volume_mount_point_drive_type(path);
1343 else
1344 drive_type = GetDriveType(reinterpret_cast<LPCTSTR>(path.getStr()));
1345
1346 if (DRIVE_NO_ROOT_DIR == drive_type)
1347 return oslTranslateFileError(ERROR_INVALID_DRIVE);
1348
1349 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1350
1351 switch (drive_type)
1352 {
1353 case DRIVE_CDROM:
1354 pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
1355 break;
1356 case DRIVE_REMOVABLE:
1357 pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
1358 if (is_floppy_drive(path))
1359 pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
1360 break;
1361 case DRIVE_FIXED:
1362 pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
1363 break;
1364 case DRIVE_RAMDISK:
1365 pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
1366 break;
1367 case DRIVE_REMOTE:
1368 pInfo->uAttributes |= osl_Volume_Attribute_Remote;
1369 break;
1370 case DRIVE_UNKNOWN:
1371 pInfo->uAttributes = 0;
1372 break;
1373 default:
1374 pInfo->uValidFields &= ~osl_VolumeInfo_Mask_Attributes;
1375 pInfo->uAttributes = 0;
1376 break;
1377 }
1378 return osl_File_E_None;
1379 }
1380
1381 //#############################################
is_volume_space_info_request(sal_uInt32 field_mask)1382 static inline bool is_volume_space_info_request(sal_uInt32 field_mask)
1383 {
1384 return (field_mask &
1385 (osl_VolumeInfo_Mask_TotalSpace |
1386 osl_VolumeInfo_Mask_UsedSpace |
1387 osl_VolumeInfo_Mask_FreeSpace));
1388 }
1389
1390 //#############################################
get_volume_space_information(const rtl::OUString & path,oslVolumeInfo * pInfo)1391 static void get_volume_space_information(
1392 const rtl::OUString& path, oslVolumeInfo *pInfo)
1393 {
1394 BOOL ret = GetDiskFreeSpaceEx(
1395 reinterpret_cast<LPCTSTR>(path.getStr()),
1396 (PULARGE_INTEGER)&(pInfo->uFreeSpace),
1397 (PULARGE_INTEGER)&(pInfo->uTotalSpace),
1398 NULL);
1399
1400 if (ret)
1401 {
1402 pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
1403 pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace |
1404 osl_VolumeInfo_Mask_UsedSpace |
1405 osl_VolumeInfo_Mask_FreeSpace;
1406 }
1407 }
1408
1409 //#############################################
is_filesystem_attributes_request(sal_uInt32 field_mask)1410 static inline bool is_filesystem_attributes_request(sal_uInt32 field_mask)
1411 {
1412 return (field_mask &
1413 (osl_VolumeInfo_Mask_MaxNameLength |
1414 osl_VolumeInfo_Mask_MaxPathLength |
1415 osl_VolumeInfo_Mask_FileSystemName |
1416 osl_VolumeInfo_Mask_FileSystemCaseHandling));
1417 }
1418
1419 //#############################################
get_filesystem_attributes(const rtl::OUString & path,sal_uInt32 field_mask,oslVolumeInfo * pInfo)1420 static oslFileError get_filesystem_attributes(
1421 const rtl::OUString& path, sal_uInt32 field_mask, oslVolumeInfo* pInfo)
1422 {
1423 pInfo->uAttributes = 0;
1424
1425 // osl_get_drive_type must be called first because
1426 // this function resets osl_VolumeInfo_Mask_Attributes
1427 // on failure
1428 if (is_drivetype_request(field_mask))
1429 {
1430 oslFileError osl_error = osl_get_drive_type(path, pInfo);
1431 if (osl_File_E_None != osl_error)
1432 return osl_error;
1433 }
1434 if (is_filesystem_attributes_request(field_mask))
1435 {
1436 /* the following two parameters can not be longer than MAX_PATH+1 */
1437 WCHAR vn[MAX_PATH+1];
1438 WCHAR fsn[MAX_PATH+1];
1439
1440 DWORD serial;
1441 DWORD mcl;
1442 DWORD flags;
1443
1444 LPCTSTR pszPath = reinterpret_cast<LPCTSTR>(path.getStr());
1445 if (GetVolumeInformation(pszPath, vn, MAX_PATH+1, &serial, &mcl, &flags, fsn, MAX_PATH+1))
1446 {
1447 // Currently sal does not use this value, instead MAX_PATH is used
1448 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
1449 pInfo->uMaxNameLength = mcl;
1450
1451 // Should the uMaxPathLength be set to 32767, "\\?\" prefix allowes it
1452 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
1453 pInfo->uMaxPathLength = MAX_PATH;
1454
1455 pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
1456 rtl_uString_newFromStr(&pInfo->ustrFileSystemName, reinterpret_cast<const sal_Unicode*>(fsn));
1457
1458 // volumes (even NTFS) will always be considered case
1459 // insensitive because the Win32 API is not able to
1460 // deal with case sensitive volumes see M$ Knowledge Base
1461 // article 100625 that's why we never set the attribute
1462 // osl_Volume_Attribute_Case_Sensitive
1463
1464 if (flags & FS_CASE_IS_PRESERVED)
1465 pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
1466
1467 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1468 }
1469 }
1470 return osl_File_E_None;
1471 }
1472
1473 //#####################################################
path_get_parent(rtl::OUString & path)1474 static bool path_get_parent(rtl::OUString& path)
1475 {
1476 OSL_PRECOND(path.lastIndexOf(SLASH) == -1, "Path must not have slashes");
1477
1478 if (!has_path_parent(path))
1479 {
1480 sal_Int32 i = path.lastIndexOf(BACKSLASH);
1481 if (-1 < i)
1482 {
1483 path = rtl::OUString(path.getStr(), i);
1484 return true;
1485 }
1486 }
1487 return false;
1488 }
1489
1490 //#####################################################
path_travel_to_volume_root(const rtl::OUString & system_path,rtl::OUString & volume_root)1491 static void path_travel_to_volume_root(const rtl::OUString& system_path, rtl::OUString& volume_root)
1492 {
1493 rtl::OUString sys_path(system_path);
1494
1495 while(!is_volume_mount_point(sys_path) && path_get_parent(sys_path))
1496 /**/;
1497
1498 volume_root = sys_path;
1499 osl::systemPathEnsureSeparator(volume_root);
1500 }
1501
1502 //#############################################
osl_getVolumeInformation(rtl_uString * ustrURL,oslVolumeInfo * pInfo,sal_uInt32 uFieldMask)1503 oslFileError SAL_CALL osl_getVolumeInformation(
1504 rtl_uString *ustrURL, oslVolumeInfo *pInfo, sal_uInt32 uFieldMask )
1505 {
1506 if (!pInfo)
1507 return osl_File_E_INVAL;
1508
1509 rtl::OUString system_path;
1510 oslFileError error = _osl_getSystemPathFromFileURL(ustrURL, &system_path.pData, sal_False);
1511
1512 if (osl_File_E_None != error)
1513 return error;
1514
1515 rtl::OUString volume_root;
1516 path_travel_to_volume_root(system_path, volume_root);
1517
1518 pInfo->uValidFields = 0;
1519
1520 if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None)
1521 return error;
1522
1523 if (is_volume_space_info_request(uFieldMask))
1524 get_volume_space_information(volume_root, pInfo);
1525
1526 if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
1527 {
1528 pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
1529 osl_getFileURLFromSystemPath(volume_root.pData, (rtl_uString**)&pInfo->pDeviceHandle);
1530 }
1531
1532 return osl_File_E_None;
1533 }
1534
1535 //#####################################################
osl_getDriveInfo(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)1536 static oslFileError SAL_CALL osl_getDriveInfo(
1537 oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask)
1538 {
1539 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1540 TCHAR cDrive[3] = TEXT("A:");
1541 TCHAR cRoot[4] = TEXT("A:\\");
1542
1543 if ( !pItemImpl )
1544 return osl_File_E_INVAL;
1545
1546 pStatus->uValidFields = 0;
1547
1548 cDrive[0] = pItemImpl->cDriveString[0];
1549 cRoot[0] = pItemImpl->cDriveString[0];
1550
1551 if ( uFieldMask & osl_FileStatus_Mask_FileName )
1552 {
1553 if ( pItemImpl->cDriveString[0] == '\\' && pItemImpl->cDriveString[1] == '\\' )
1554 {
1555 LPCWSTR lpFirstBkSlash = wcschr( &pItemImpl->cDriveString[2], '\\' );
1556
1557 if ( lpFirstBkSlash && lpFirstBkSlash[1] )
1558 {
1559 LPCWSTR lpLastBkSlash = wcschr( &lpFirstBkSlash[1], '\\' );
1560
1561 if ( lpLastBkSlash )
1562 rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]), lpLastBkSlash - lpFirstBkSlash - 1 );
1563 else
1564 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]) );
1565 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1566 }
1567 }
1568 else switch ( GetDriveType( cRoot ) )
1569 {
1570 case DRIVE_REMOTE:
1571 {
1572 TCHAR szBuffer[1024];
1573 DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szBuffer);
1574 DWORD dwBufsize = dwBufsizeConst;
1575
1576 DWORD dwResult = WNetGetConnection( cDrive, szBuffer, &dwBufsize );
1577 if ( NO_ERROR == dwResult )
1578 {
1579 TCHAR szFileName[dwBufsizeConst + 16];
1580
1581 swprintf( szFileName, L"%s [%s]", cDrive, szBuffer );
1582 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
1583 }
1584 else
1585 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
1586 }
1587 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1588 break;
1589 case DRIVE_FIXED:
1590 {
1591 TCHAR szVolumeNameBuffer[1024];
1592 DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szVolumeNameBuffer);
1593
1594 if ( GetVolumeInformation( cRoot, szVolumeNameBuffer, dwBufsizeConst, NULL, NULL, NULL, NULL, 0 ) )
1595 {
1596 TCHAR szFileName[dwBufsizeConst + 16];
1597
1598 swprintf( szFileName, L"%s [%s]", cDrive, szVolumeNameBuffer );
1599 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
1600 }
1601 else
1602 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
1603 }
1604 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1605 break;
1606 case DRIVE_CDROM:
1607 case DRIVE_REMOVABLE:
1608 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1609 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cRoot) );
1610 break;
1611 case DRIVE_UNKNOWN:
1612 default:
1613 break;
1614 }
1615 }
1616
1617 pStatus->eType = osl_File_Type_Volume;
1618 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1619
1620 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1621 {
1622 rtl_uString *ustrSystemPath = NULL;
1623
1624 rtl_uString_newFromStr( &ustrSystemPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->cDriveString) );
1625 osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
1626 rtl_uString_release( ustrSystemPath );
1627 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1628 }
1629 return osl_File_E_None;
1630 }
1631
1632 //#####################################################
osl_getServerInfo(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)1633 static oslFileError SAL_CALL osl_getServerInfo(
1634 oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask )
1635 {
1636 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1637 if ( !pItemImpl )
1638 return osl_File_E_INVAL;
1639
1640 pStatus->uValidFields = 0;
1641
1642 // pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1643
1644 // if ( _tcscmp( pItemImpl->FindData.cFileName, TEXT(".") ) == 0 )
1645 // rtl_uString_newFromAscii( &pStatus->ustrFileName, "/" );
1646 // else
1647 // rtl_uString_newFromStr( &pStatus->ustrFileName, pItemImpl->FindData.cFileName );
1648
1649 pStatus->eType = osl_File_Type_Directory;
1650 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1651
1652 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1653 {
1654 osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrFileURL );
1655 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1656 }
1657 return osl_File_E_None;
1658 }
1659
1660 //#############################################
osl_getFileStatus(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)1661 oslFileError SAL_CALL osl_getFileStatus(
1662 oslDirectoryItem Item,
1663 oslFileStatus *pStatus,
1664 sal_uInt32 uFieldMask )
1665 {
1666 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
1667
1668 if ( !pItemImpl )
1669 return osl_File_E_INVAL;
1670
1671 switch ( pItemImpl->uType )
1672 {
1673 case DIRECTORYITEM_DRIVE:
1674 return osl_getDriveInfo( Item, pStatus, uFieldMask );
1675 case DIRECTORYITEM_SERVER:
1676 return osl_getServerInfo( Item, pStatus, uFieldMask );
1677 default:
1678 break;
1679 }
1680
1681 if ( uFieldMask & osl_FileStatus_Mask_Validate )
1682 {
1683 HANDLE hFind = FindFirstFile( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ), &pItemImpl->FindData );
1684
1685 if ( hFind != INVALID_HANDLE_VALUE )
1686 FindClose( hFind );
1687 else
1688 return oslTranslateFileError( GetLastError() );
1689
1690 uFieldMask &= ~ osl_FileStatus_Mask_Validate;
1691 }
1692
1693 /* If no fields to retrieve left ignore pStatus */
1694 if ( !uFieldMask )
1695 return osl_File_E_None;
1696
1697 /* Otherwise, this must be a valid pointer */
1698 if ( !pStatus )
1699 return osl_File_E_INVAL;
1700
1701 if ( pStatus->uStructSize != sizeof(oslFileStatus) )
1702 return osl_File_E_INVAL;
1703
1704 pStatus->uValidFields = 0;
1705
1706 /* File time stamps */
1707
1708 if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime) &&
1709 FileTimeToTimeValue( &pItemImpl->FindData.ftLastWriteTime, &pStatus->aModifyTime ) )
1710 pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime;
1711
1712 if ( (uFieldMask & osl_FileStatus_Mask_AccessTime) &&
1713 FileTimeToTimeValue( &pItemImpl->FindData.ftLastAccessTime, &pStatus->aAccessTime ) )
1714 pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime;
1715
1716 if ( (uFieldMask & osl_FileStatus_Mask_CreationTime) &&
1717 FileTimeToTimeValue( &pItemImpl->FindData.ftCreationTime, &pStatus->aCreationTime ) )
1718 pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime;
1719
1720 /* Most of the fields are already set, regardless of requiered fields */
1721
1722 rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(pItemImpl->FindData.cFileName) );
1723 pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1724
1725 if ((FILE_ATTRIBUTE_REPARSE_POINT & pItemImpl->FindData.dwFileAttributes) &&
1726 (IO_REPARSE_TAG_MOUNT_POINT == pItemImpl->FindData.dwReserved0))
1727 pStatus->eType = osl_File_Type_Volume;
1728 else if (pItemImpl->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1729 pStatus->eType = osl_File_Type_Directory;
1730 else
1731 pStatus->eType = osl_File_Type_Regular;
1732
1733 pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1734
1735 pStatus->uAttributes = pItemImpl->FindData.dwFileAttributes;
1736 pStatus->uValidFields |= osl_FileStatus_Mask_Attributes;
1737
1738 pStatus->uFileSize = (sal_uInt64)pItemImpl->FindData.nFileSizeLow + ((sal_uInt64)pItemImpl->FindData.nFileSizeHigh << 32);
1739 pStatus->uValidFields |= osl_FileStatus_Mask_FileSize;
1740
1741 if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL )
1742 {
1743 osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrLinkTargetURL );
1744
1745 pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
1746 }
1747
1748 if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1749 {
1750 if ( !pItemImpl->bFullPathNormalized )
1751 {
1752 sal_uInt32 nLen = rtl_uString_getLength( pItemImpl->m_pFullPath );
1753 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
1754 sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ),
1755 ::osl::mingw_reinterpret_cast<LPTSTR>( aBuffer ),
1756 aBuffer.getBufSizeInSymbols(),
1757 sal_True );
1758
1759 if ( nNewLen )
1760 {
1761 rtl_uString_newFromStr( &pItemImpl->m_pFullPath, aBuffer );
1762 pItemImpl->bFullPathNormalized = TRUE;
1763 }
1764 }
1765
1766 osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrFileURL );
1767 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1768 }
1769
1770 return osl_File_E_None;
1771 }
1772
1773 //#####################################################
1774 // file attributes handling functions
1775 //#####################################################
1776
1777 //#############################################
osl_setFileAttributes(rtl_uString * ustrFileURL,sal_uInt64 uAttributes)1778 oslFileError SAL_CALL osl_setFileAttributes(
1779 rtl_uString *ustrFileURL,
1780 sal_uInt64 uAttributes )
1781 {
1782 oslFileError error;
1783 rtl_uString *ustrSysPath = NULL;
1784 DWORD dwFileAttributes;
1785 BOOL fSuccess;
1786
1787 // Converts the normalized path into a systempath
1788 error = _osl_getSystemPathFromFileURL( ustrFileURL, &ustrSysPath, sal_False );
1789
1790 if ( osl_File_E_None != error )
1791 return error;
1792
1793 dwFileAttributes = GetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)) );
1794
1795 if ( (DWORD)-1 != dwFileAttributes )
1796 {
1797 dwFileAttributes &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN);
1798
1799 if ( uAttributes & osl_File_Attribute_ReadOnly )
1800 dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
1801
1802 if ( uAttributes & osl_File_Attribute_Hidden )
1803 dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1804
1805 fSuccess = SetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)), dwFileAttributes );
1806 }
1807 else
1808 fSuccess = FALSE;
1809
1810 if ( !fSuccess )
1811 error = oslTranslateFileError( GetLastError() );
1812
1813 rtl_uString_release( ustrSysPath );
1814
1815 return error;
1816 }
1817
1818 //#####################################################
osl_setFileTime(rtl_uString * filePath,const TimeValue * aCreationTime,const TimeValue * aLastAccessTime,const TimeValue * aLastWriteTime)1819 oslFileError SAL_CALL osl_setFileTime(
1820 rtl_uString *filePath,
1821 const TimeValue *aCreationTime,
1822 const TimeValue *aLastAccessTime,
1823 const TimeValue *aLastWriteTime)
1824 {
1825 oslFileError error;
1826 rtl_uString *sysPath=NULL;
1827 FILETIME *lpCreationTime=NULL;
1828 FILETIME *lpLastAccessTime=NULL;
1829 FILETIME *lpLastWriteTime=NULL;
1830 FILETIME ftCreationTime;
1831 FILETIME ftLastAccessTime;
1832 FILETIME ftLastWriteTime;
1833 HANDLE hFile;
1834 BOOL fSuccess;
1835
1836
1837 error=_osl_getSystemPathFromFileURL(filePath, &sysPath, sal_False);
1838
1839 if (error==osl_File_E_INVAL)
1840 return error;
1841
1842 hFile=CreateFileW(reinterpret_cast<LPCWSTR>(rtl_uString_getStr(sysPath)), GENERIC_WRITE, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1843 rtl_uString_release(sysPath);
1844
1845 if (hFile==INVALID_HANDLE_VALUE)
1846 return osl_File_E_NOENT;
1847
1848 if (TimeValueToFileTime(aCreationTime, &ftCreationTime))
1849 lpCreationTime=&ftCreationTime;
1850
1851 if (TimeValueToFileTime(aLastAccessTime, &ftLastAccessTime))
1852 lpLastAccessTime=&ftLastAccessTime;
1853
1854 if (TimeValueToFileTime(aLastWriteTime, &ftLastWriteTime))
1855 lpLastWriteTime=&ftLastWriteTime;
1856
1857 fSuccess=SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
1858
1859 CloseHandle(hFile);
1860
1861 if (!fSuccess)
1862 return osl_File_E_INVAL;
1863 else
1864 return osl_File_E_None;
1865 }
1866