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