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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_tools.hxx" 30 31 #ifdef _MSC_VER 32 #pragma warning (push,1) 33 #endif 34 #include <stdio.h> 35 #include <ctype.h> 36 #include <limits.h> 37 #ifdef _MSC_VER 38 #pragma warning (pop) 39 #endif 40 41 #include "wntmsc.hxx" 42 #include <tools/errinf.hxx> 43 #include <tools/debug.hxx> 44 #include <tools/list.hxx> 45 #include <tools/wldcrd.hxx> 46 #include <tools/fsys.hxx> 47 #include <tools/bigint.hxx> 48 49 DECLARE_LIST( DirEntryList, DirEntry* ); 50 DECLARE_LIST( FSysSortList, FSysSort* ); 51 DECLARE_LIST( FileStatList, FileStat* ); 52 53 int Sys2SolarError_Impl( int nSysErr ); 54 55 static sal_Bool bLastCaseSensitive = sal_False; 56 57 //-------------------------------------------------------------------- 58 59 ByteString Upper_Impl( const ByteString &rStr ) 60 { 61 ByteString aRet( rStr.GetBuffer() ); // es muss ein neuer String entstehen! 62 CharUpperBuff( (char*) aRet.GetBuffer(), aRet.Len() ); 63 return aRet; 64 } 65 66 //-------------------------------------------------------------------- 67 68 DIR *opendir( const char* pPfad ) 69 { 70 DIR *pDir = new DIR; 71 if ( pDir ) 72 pDir->p = (char*) pPfad; 73 return pDir; 74 } 75 76 struct dirent *readdir( DIR *pDir ) 77 { 78 bool bOk = false; 79 if ( pDir->p ) 80 { 81 char *pBuf = new char[ strlen( pDir->p ) + 5 ]; 82 if ( pBuf ) 83 { 84 // *.* dahinter, ggf mit "\\" abtrennen (falls nicht schon da) 85 strcpy( pBuf, pDir->p ); 86 strcat( pBuf, "\\*.*" + ( *(pBuf + strlen( pBuf ) - 1 ) == '\\' ) ); 87 CharUpperBuff( pBuf, strlen(pBuf) ); 88 pDir->h = FindFirstFile( pBuf, &pDir->aDirEnt ); 89 bOk = pDir->h != INVALID_HANDLE_VALUE; 90 pDir->p = NULL; 91 delete [] pBuf; 92 } 93 else 94 pDir->h = INVALID_HANDLE_VALUE; 95 } 96 else 97 { 98 bOk = FindNextFile( pDir->h, &pDir->aDirEnt ); 99 } 100 101 return bOk ? &pDir->aDirEnt : NULL; 102 } 103 104 int closedir( DIR *pDir ) 105 { 106 sal_Bool bOk = sal_False; 107 if ( pDir ) 108 { 109 bOk = 0 != pDir->p || FindClose( pDir->h ); 110 delete pDir; 111 } 112 return bOk; 113 } 114 115 /************************************************************************* 116 |* 117 |* DirEntry::GetPathStyle() const 118 |* 119 |* Beschreibung 120 |* Ersterstellung MI 11.05.95 121 |* Letzte Aenderung MI 11.05.95 122 |* 123 *************************************************************************/ 124 125 ErrCode GetPathStyle_Impl( const String &rDevice, FSysPathStyle &rStyle ) 126 { 127 ByteString aRootDir(rDevice, osl_getThreadTextEncoding()); 128 if ( aRootDir.Len() && aRootDir.GetBuffer()[aRootDir.Len()-1] != '\\' ) 129 aRootDir += '\\'; 130 131 char sVolumeName[256]; 132 char sFileSysName[16]; 133 DWORD nSerial[2]; 134 DWORD nMaxCompLen[2]; 135 DWORD nFlags[2]; 136 137 // Windows95 hat VFAT, WindowsNT nicht 138 DWORD nVer = GetVersion(); 139 sal_Bool bW95 = ( nVer & 0xFF ) >= 4; 140 141 FSysFailOnErrorImpl(); 142 rStyle = FSYS_STYLE_UNKNOWN; 143 if ( GetVolumeInformation( 144 (char*) aRootDir.GetBuffer(), 145 sVolumeName, 256, (LPDWORD) &nSerial, (LPDWORD) &nMaxCompLen, 146 (LPDWORD) &nFlags, sFileSysName, 16 ) ) 147 { 148 // FAT/VFAT? 149 if ( 0 == strcmp( "FAT", sFileSysName ) ) 150 rStyle = bW95 ? FSYS_STYLE_VFAT : FSYS_STYLE_FAT; 151 152 // NTFS? 153 else if ( 0 == strcmp( "NTFS", sFileSysName ) ) 154 rStyle = FSYS_STYLE_NTFS; 155 156 // HPFS? 157 else if ( 0 == strcmp( "HPFS", sFileSysName ) ) 158 rStyle = FSYS_STYLE_HPFS; 159 160 // NWCOMPA/NWFS? 161 else if ( 0 == strncmp( "NW", sFileSysName, 2 ) ) 162 rStyle = FSYS_STYLE_NWFS; 163 164 return ERRCODE_NONE; 165 } 166 167 return ERRCODE_IO_INVALIDDEVICE; 168 } 169 170 FSysPathStyle DirEntry::GetPathStyle( const String &rDevice ) 171 { 172 173 FSysPathStyle eStyle; 174 GetPathStyle_Impl( rDevice, eStyle ); 175 return eStyle; 176 } 177 178 /************************************************************************* 179 |* 180 |* DirEntry::IsCaseSensitive() 181 |* 182 |* Beschreibung FSYS.SDW 183 |* Ersterstellung MI 10.06.93 184 |* Letzte Aenderung TPF 26.02.1999 185 |* 186 *************************************************************************/ 187 188 sal_Bool DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const 189 { 190 191 if (eFormatter==FSYS_STYLE_HOST) 192 { 193 /* 194 DirEntry aRoot(*this); 195 aRoot.ToAbs(); 196 aRoot = aRoot[Level()-1]; 197 String aRootDir = aRoot.GetFull(FSYS_STYLE_HOST, sal_True); 198 199 char sVolumeName[256]; 200 DWORD nVolumeSerial; 201 DWORD nMaxCompLen; 202 DWORD nFlags; 203 char sFileSysName[16]; 204 205 if ( GetVolumeInformation( (char*) aRootDir.GetStr(), 206 sVolumeName, 207 256, 208 (LPDWORD) &nVolumeSerial, 209 (LPDWORD) &nMaxCompLen, 210 (LPDWORD) &nFlags, 211 sFileSysName, 212 16 )) 213 { 214 return (nFlags & FS_CASE_SENSITIVE) ? sal_True : sal_False; 215 } 216 else 217 { 218 return sal_False; 219 } 220 */ 221 // 222 // guter versuch, aber FS_CASE_SENSITIVE ist D?nnsinn in T?ten: 223 // 224 // sFileSysName FS_CASE_SENSITIVE 225 // FAT sal_False 226 // NTFS sal_True !!! 227 // NWCompat sal_False 228 // Samba sal_False 229 // 230 // NT spricht auch NTFS lediglich case preserving an, also ist unter NT alles case insensitiv 231 // 232 233 return sal_False; 234 } 235 else 236 { 237 sal_Bool isCaseSensitive = sal_False; // ich bin unter win32, also ist der default case insensitiv 238 switch ( eFormatter ) 239 { 240 case FSYS_STYLE_MAC: 241 case FSYS_STYLE_FAT: 242 case FSYS_STYLE_VFAT: 243 case FSYS_STYLE_NTFS: 244 case FSYS_STYLE_NWFS: 245 case FSYS_STYLE_HPFS: 246 case FSYS_STYLE_DETECT: 247 { 248 isCaseSensitive = sal_False; 249 break; 250 } 251 case FSYS_STYLE_SYSV: 252 case FSYS_STYLE_BSD: 253 { 254 isCaseSensitive = sal_True; 255 break; 256 } 257 default: 258 { 259 isCaseSensitive = sal_False; // ich bin unter win32, also ist der default case insensitiv 260 break; 261 } 262 } 263 return isCaseSensitive; 264 } 265 } 266 267 /************************************************************************* 268 |* 269 |* DirEntry::ToAbs() 270 |* 271 |* Beschreibung FSYS.SDW 272 |* Ersterstellung MI 26.04.91 273 |* Letzte Aenderung MA 02.12.91 274 |* 275 *************************************************************************/ 276 277 sal_Bool DirEntry::ToAbs() 278 { 279 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 280 281 if ( FSYS_FLAG_VOLUME == eFlag ) 282 { 283 eFlag = FSYS_FLAG_ABSROOT; 284 return sal_True; 285 } 286 287 if ( IsAbs() ) 288 { 289 return sal_True; 290 } 291 292 293 char sBuf[256]; 294 char *pOld; 295 ByteString aFullName( GetFull(), osl_getThreadTextEncoding() ); 296 FSysFailOnErrorImpl(); 297 if ( GetFullPathName((char*)aFullName.GetBuffer(),256,sBuf,&pOld) > 511 ) 298 return sal_False; 299 300 *this = DirEntry( String(sBuf, osl_getThreadTextEncoding() )); 301 return sal_True; 302 } 303 304 305 /************************************************************************* 306 |* 307 |* DirEntry::GetVolume() 308 |* 309 |* Beschreibung FSYS.SDW 310 |* Ersterstellung MI 27.08.92 311 |* Letzte Aenderung MI 28.08.92 312 |* 313 *************************************************************************/ 314 315 String DirEntry::GetVolume() const 316 { 317 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 318 319 String aRet; 320 const DirEntry *pTop = ImpGetTopPtr(); 321 ByteString aName = ByteString( pTop->aName ).ToLowerAscii(); 322 323 if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT || 324 pTop->eFlag == FSYS_FLAG_RELROOT || 325 pTop->eFlag == FSYS_FLAG_VOLUME ) 326 && aName != "a:" && aName != "b:" && Exists() ) 327 { 328 char sFileSysName[256]; 329 char sVolumeName[256]; 330 DWORD nVolumeNameLen = 256; 331 DWORD nSerial[2]; 332 DWORD nMaxCompLen[2]; 333 DWORD nFlags[2]; 334 ByteString aRootDir = pTop->aName; 335 FSysFailOnErrorImpl(); 336 337 // Network-Device zuerst probieren wegen langsamer Samba-Drives 338 if ( !WNetGetConnection( (char*) aRootDir.GetBuffer(), 339 sVolumeName, &nVolumeNameLen ) ) 340 aRet = String( sVolumeName, osl_getThreadTextEncoding()); 341 342 // dann den VolumeNamen fuer lokale Drives 343 if ( aRet.Len() == 0 ) 344 { 345 aRootDir += "\\"; 346 if ( GetVolumeInformation( (char*) aRootDir.GetBuffer(), 347 sVolumeName, 256, 348 (LPDWORD) &nSerial, (LPDWORD) &nMaxCompLen, 349 (LPDWORD) &nFlags, sFileSysName, 256 ) ) 350 aRet = String( sVolumeName, osl_getThreadTextEncoding()); 351 } 352 } 353 354 return aRet; 355 } 356 357 /************************************************************************* 358 |* 359 |* DirEntry::SetCWD() 360 |* 361 |* Beschreibung FSYS.SDW 362 |* Ersterstellung MI 26.04.91 363 |* Letzte Aenderung MI 21.05.92 364 |* 365 *************************************************************************/ 366 367 sal_Bool DirEntry::SetCWD( sal_Bool bSloppy ) const 368 { 369 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry ); 370 371 FSysFailOnErrorImpl(); 372 373 if ( eFlag == FSYS_FLAG_CURRENT && !aName.Len() ) 374 return sal_True; 375 376 if ( SetCurrentDirectory(ByteString(GetFull(), osl_getThreadTextEncoding()).GetBuffer()) ) 377 { 378 return sal_True; 379 } 380 381 if ( bSloppy && pParent && 382 SetCurrentDirectory(ByteString(pParent->GetFull(), osl_getThreadTextEncoding()).GetBuffer()) ) 383 { 384 return sal_True; 385 } 386 387 return sal_False; 388 } 389 390 //------------------------------------------------------------------------- 391 392 USHORT DirReader_Impl::Init() 393 { 394 // Block-Devices auflisten? 395 if ( pDir->eAttrMask & FSYS_KIND_BLOCK ) 396 { 397 // CWD merken 398 DirEntry aCurrentDir; 399 aCurrentDir.ToAbs(); 400 401 // einzeln auf Existenz und Masken-konformit"at pr"ufen 402 USHORT nRead = 0; 403 char sDrive[3] = { '?', ':', 0 }; 404 char sRoot[4] = { '?', ':', '\\', 0 }; 405 for ( char c = 'a'; c <= 'z'; c++ ) 406 { 407 sDrive[0] = c; 408 sRoot[0] = c; 409 DirEntry* pDrive = new DirEntry( sDrive, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST ); 410 if ( pDir->aNameMask.Matches( String( ByteString(sDrive), osl_getThreadTextEncoding())) && GetDriveType( sRoot ) != 1 ) 411 { 412 if ( pDir->pStatLst ) //Status fuer Sort gewuenscht? 413 { 414 FileStat *pNewStat = new FileStat( *pDrive ); 415 pDir->ImpSortedInsert( pDrive, pNewStat ); 416 } 417 else 418 pDir->ImpSortedInsert( pDrive, NULL ); 419 ++nRead; 420 } 421 else 422 delete pDrive; 423 } 424 425 // CWD restaurieren 426 aCurrentDir.SetCWD(); 427 return nRead; 428 } 429 430 return 0; 431 } 432 433 //------------------------------------------------------------------------- 434 435 USHORT DirReader_Impl::Read() 436 { 437 // Directories und Files auflisten? 438 if ( ( pDir->eAttrMask & FSYS_KIND_DIR || 439 pDir->eAttrMask & FSYS_KIND_FILE ) && 440 ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) ) 441 { 442 // Gross/Kleinschreibung nicht beruecksichtigen 443 ByteString aLowerName = pDosEntry->d_name; 444 CharLowerBuff( (char*) aLowerName.GetBuffer(), aLowerName.Len() ); 445 446 // Flags pruefen 447 sal_Bool bIsDirAndWantsDir = 448 ( ( pDir->eAttrMask & FSYS_KIND_DIR ) && 449 #ifdef ICC 450 ( pDosEntry->d_type & ( strcmp(pDosEntry->d_name,".") || 451 strcmp(pDosEntry->d_name,"..")) ) ); 452 #else 453 ( pDosEntry->d_type & DOS_DIRECT ) ); 454 #endif 455 sal_Bool bIsFileAndWantsFile = 456 ( ( pDir->eAttrMask & FSYS_KIND_FILE ) && 457 #ifdef ICC 458 !( pDosEntry->d_type & ( strcmp(pDosEntry->d_name,".") || 459 strcmp(pDosEntry->d_name,"..")) ) && 460 #else 461 !( pDosEntry->d_type & DOS_DIRECT ) && 462 #endif 463 !( pDosEntry->d_type & DOS_VOLUMEID ) ); 464 sal_Bool bIsHidden = (pDosEntry->d_type & _A_HIDDEN) != 0; 465 sal_Bool bWantsHidden = 0 == ( pDir->eAttrMask & FSYS_KIND_VISIBLE ); 466 if ( ( bIsDirAndWantsDir || bIsFileAndWantsFile ) && 467 ( bWantsHidden || !bIsHidden ) && 468 pDir->aNameMask.Matches( String(aLowerName, osl_getThreadTextEncoding()) ) ) 469 { 470 #ifdef DBG_UTIL 471 DbgOutf( "%s %s flags:%x found", 472 pDosEntry->d_name, 473 bIsFileAndWantsFile ? "file" : "dir", 474 pDosEntry->d_type ); 475 #endif 476 DirEntryFlag eFlag = 477 0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT 478 : 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT 479 : FSYS_FLAG_NORMAL; 480 DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name), 481 eFlag, FSYS_STYLE_NTFS ); 482 #ifdef FEAT_FSYS_DOUBLESPEED 483 pTemp->ImpSetStat( new FileStat( (void*) pDosDir, (void*) 0 ) ); 484 #endif 485 if ( pParent ) 486 pTemp->ImpChangeParent( new DirEntry( *pParent ), sal_False ); 487 if ( pDir->pStatLst ) //Status fuer Sort gewuenscht? 488 { 489 FileStat *pNewStat = new FileStat( (void*) pDosDir, (void*) 0 ); 490 pDir->ImpSortedInsert( pTemp, pNewStat ); 491 } 492 else 493 pDir->ImpSortedInsert( pTemp, NULL ); 494 return 1; 495 } 496 #ifdef DBG_UTIL 497 else 498 DbgOutf( "%s flags:%x skipped", 499 pDosEntry->d_name, 500 pDosEntry->d_type ); 501 #endif 502 503 } 504 else 505 bReady = sal_True; 506 return 0; 507 } 508 509 /************************************************************************* 510 |* 511 |* InitFileStat() 512 |* 513 |* Beschreibung gemeinsamer Teil der Ctoren fuer FileStat 514 |* Ersterstellung MI 28.08.92 515 |* Letzte Aenderung MI 28.08.92 516 |* 517 *************************************************************************/ 518 519 void FileStat::ImpInit( void* p ) 520 { 521 _WIN32_FIND_DATAA *pDirEnt = (_WIN32_FIND_DATAA*) p; 522 523 nError = FSYS_ERR_OK; 524 nSize = pDirEnt->nFileSizeLow; 525 526 SYSTEMTIME aSysTime; 527 FILETIME aLocTime; 528 529 // use the last write date / time when the creation date / time isn't set 530 if ( ( pDirEnt->ftCreationTime.dwLowDateTime == 0 ) && 531 ( pDirEnt->ftCreationTime.dwHighDateTime == 0 ) ) 532 { 533 pDirEnt->ftCreationTime.dwLowDateTime = pDirEnt->ftLastWriteTime.dwLowDateTime; 534 pDirEnt->ftCreationTime.dwHighDateTime = pDirEnt->ftLastWriteTime.dwHighDateTime; 535 } 536 537 // use the last write date / time when the last accessed date / time isn't set 538 if ( ( pDirEnt->ftLastAccessTime.dwLowDateTime == 0 ) && 539 ( pDirEnt->ftLastAccessTime.dwHighDateTime == 0 ) ) 540 { 541 pDirEnt->ftLastAccessTime.dwLowDateTime = pDirEnt->ftLastWriteTime.dwLowDateTime; 542 pDirEnt->ftLastAccessTime.dwHighDateTime = pDirEnt->ftLastWriteTime.dwHighDateTime; 543 } 544 545 FileTimeToLocalFileTime( &pDirEnt->ftCreationTime, &aLocTime ); 546 FileTimeToSystemTime( &aLocTime, &aSysTime ); 547 aDateCreated = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear ); 548 aTimeCreated = Time( aSysTime.wHour, aSysTime.wMinute, 549 aSysTime.wSecond, 0 ); 550 551 FileTimeToLocalFileTime( &pDirEnt->ftLastWriteTime, &aLocTime ); 552 FileTimeToSystemTime( &aLocTime, &aSysTime ); 553 aDateModified = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear ); 554 aTimeModified = Time( aSysTime.wHour, aSysTime.wMinute, 555 aSysTime.wSecond, 0 ); 556 557 FileTimeToLocalFileTime( &pDirEnt->ftLastAccessTime, &aLocTime ); 558 FileTimeToSystemTime( &aLocTime, &aSysTime ); 559 aDateAccessed = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear ); 560 aTimeAccessed = Time( aSysTime.wHour, aSysTime.wMinute, 561 aSysTime.wSecond, 0 ); 562 563 nKindFlags = FSYS_KIND_FILE; 564 if ( pDirEnt->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) 565 nKindFlags = FSYS_KIND_DIR; 566 } 567 568 /************************************************************************* 569 |* 570 |* FileStat::FileStat() 571 |* 572 |* Beschreibung FSYS.SDW 573 |* Ersterstellung MI 27.08.92 574 |* Letzte Aenderung MI 28.08.92 575 |* 576 *************************************************************************/ 577 578 FileStat::FileStat( const void *pInfo, // struct dirent 579 const void * ): // dummy 580 aDateCreated(0), 581 aTimeCreated(0), 582 aDateModified(0), 583 aTimeModified(0), 584 aDateAccessed(0), 585 aTimeAccessed(0) 586 { 587 ImpInit( ( (dirent*) pInfo ) ); 588 } 589 590 /************************************************************************* 591 |* 592 |* FileStat::Update() 593 |* 594 |* Beschreibung FSYS.SDW 595 |* Ersterstellung MI 27.08.92 596 |* Letzte Aenderung MI 28.08.92 597 |* 598 *************************************************************************/ 599 600 #ifdef _MSC_VER 601 #pragma warning(push, 1) 602 #pragma warning(disable: 4917) 603 #endif 604 #include <shlobj.h> 605 #ifdef _MSC_VER 606 #pragma warning(pop) 607 #endif 608 609 #ifdef UNICODE 610 #define lstrchr wcschr 611 #define lstrncmp wcsncmp 612 #else 613 #define lstrchr strchr 614 #define lstrncmp strncmp 615 #endif 616 617 //--------------------------------------------------------------------------- 618 619 void SHFreeMem( void *p ) 620 { 621 LPMALLOC pMalloc = NULL; 622 623 if ( SUCCEEDED(SHGetMalloc(&pMalloc)) ) 624 { 625 pMalloc->Free( p ); 626 pMalloc->Release(); 627 } 628 } 629 630 //--------------------------------------------------------------------------- 631 632 HRESULT SHGetIDListFromPath( HWND hwndOwner, LPCTSTR pszPath, LPITEMIDLIST *ppidl ) 633 { 634 if ( IsBadWritePtr(ppidl, sizeof(LPITEMIDLIST)) ) 635 return E_INVALIDARG; 636 637 LPSHELLFOLDER pDesktopFolder = NULL; 638 639 HRESULT hResult = SHGetDesktopFolder( &pDesktopFolder ); 640 if ( FAILED(hResult) ) 641 return hResult; 642 643 ULONG chEaten = lstrlen( pszPath ); 644 DWORD dwAttributes = FILE_ATTRIBUTE_DIRECTORY; 645 646 #ifdef UNICODE 647 LPOLESTR wszPath = pszPath; 648 #else 649 WCHAR wszPath[MAX_PATH]; 650 MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszPath, -1, wszPath, MAX_PATH ); 651 #endif 652 653 hResult = pDesktopFolder->ParseDisplayName( hwndOwner, (LPBC)NULL, wszPath, &chEaten, ppidl, &dwAttributes ); 654 pDesktopFolder->Release(); 655 656 return hResult; 657 } 658 659 //--------------------------------------------------------------------------- 660 661 HRESULT SHGetFolderFromIDList( LPCITEMIDLIST pidl, LPSHELLFOLDER *ppFolder ) 662 { 663 if ( IsBadWritePtr(ppFolder, sizeof(LPSHELLFOLDER)) ) 664 return E_INVALIDARG; 665 666 *ppFolder = NULL; 667 668 LPSHELLFOLDER pDesktopFolder = NULL; 669 670 HRESULT hResult = SHGetDesktopFolder( &pDesktopFolder ); 671 if ( FAILED(hResult) ) 672 return hResult; 673 674 hResult = pDesktopFolder->BindToObject( pidl, (LPBC)NULL, IID_IShellFolder, (LPVOID *)ppFolder ); 675 pDesktopFolder->Release(); 676 677 return hResult; 678 } 679 680 //--------------------------------------------------------------------------- 681 682 HRESULT SHResolvePath( HWND hwndOwner, LPCTSTR pszPath, LPITEMIDLIST *ppidl ) 683 { 684 // If hwndOwner is NULL, use the desktop window, because dialogs need a parent 685 686 #ifdef BOOTSTRAP 687 return NO_ERROR; 688 #else 689 if ( !hwndOwner ) 690 hwndOwner = GetDesktopWindow(); 691 692 HRESULT hResult = NOERROR; 693 LPTSTR pszPathCopy; 694 LPTSTR pszTrailingPath; 695 TCHAR cBackup = 0; 696 697 // First make a copy of the path 698 699 pszPathCopy = new TCHAR[lstrlen(pszPath) + 1]; 700 if ( pszPathCopy ) 701 lstrcpy( pszPathCopy, pszPath ); 702 else 703 return E_OUTOFMEMORY; 704 705 // Determine the first token 706 707 if ( !lstrncmp( pszPathCopy, "\\\\", 2 ) ) 708 pszTrailingPath = lstrchr( pszPathCopy + 2, '\\' ); 709 else 710 pszTrailingPath = lstrchr( pszPathCopy, '\\' ); 711 712 // Now scan the path tokens 713 714 while ( SUCCEEDED(hResult) ) 715 { 716 if ( pszTrailingPath ) 717 { 718 cBackup = *(++pszTrailingPath); 719 *pszTrailingPath = 0; 720 } 721 722 LPITEMIDLIST pidl = NULL; 723 724 // Make item ID list from leading path 725 726 hResult = SHGetIDListFromPath( hwndOwner, pszPathCopy, &pidl ); 727 728 // if path exists try to open it as folder 729 730 if ( SUCCEEDED(hResult) ) 731 { 732 // Only open the folder if it was not the last token 733 734 if ( pszTrailingPath ) 735 { 736 LPSHELLFOLDER pFolder; 737 738 // Create a folder instance 739 hResult = SHGetFolderFromIDList( pidl, &pFolder); 740 741 // Is it a folder ? 742 if ( SUCCEEDED(hResult) ) 743 { 744 // No try to instantiate an enumerator. 745 // This should popup a login dialog if any 746 747 LPENUMIDLIST pEnum = NULL; 748 749 hResult = pFolder->EnumObjects( hwndOwner, 750 SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN, 751 &pEnum ); 752 753 // Release the enumerator interface 754 if ( SUCCEEDED(hResult) ) 755 pEnum->Release(); 756 757 // Release the folder interface 758 pFolder->Release(); 759 } 760 761 SHFreeMem( pidl ); 762 } 763 else // It was the last token 764 { 765 if ( ppidl ) 766 *ppidl = pidl; 767 else 768 SHFreeMem( pidl ); 769 } 770 } 771 772 773 // Forward to next token 774 775 if ( pszTrailingPath ) 776 { 777 *pszTrailingPath = cBackup; 778 pszTrailingPath = lstrchr( pszTrailingPath, '\\' ); 779 } 780 else 781 break; 782 } 783 784 // Free the working copy of the path 785 delete pszPathCopy; 786 787 // NOERROR or OLE error code 788 return hResult; 789 #endif 790 } 791 792 //--------------------------------------------------------------------------- 793 // The Wrapper 794 //--------------------------------------------------------------------------- 795 796 sal_Bool Exists_Impl( const ByteString & crPath ) 797 { 798 // We do not know if OLE was initialized for this thread 799 800 CoInitialize( NULL ); 801 802 sal_Bool bSuccess = SUCCEEDED( SHResolvePath(NULL, crPath.GetBuffer(), NULL) ); 803 804 CoUninitialize(); 805 806 return bSuccess; 807 } 808 809 //--------------------------------------------------------------------------- 810 811 sal_Bool FileStat::Update( const DirEntry& rDirEntry, sal_Bool bForceAccess ) 812 { 813 nSize = 0; 814 nKindFlags = 0; 815 aCreator.Erase(); 816 aType.Erase(); 817 aDateCreated = Date(0); 818 aTimeCreated = Time(0); 819 aDateModified = Date(0); 820 aTimeModified = Time(0); 821 aDateAccessed = Date(0); 822 aTimeAccessed = Time(0); 823 824 if ( !rDirEntry.IsValid() ) 825 { 826 nError = FSYS_ERR_UNKNOWN; 827 nKindFlags = 0; 828 return sal_False; 829 } 830 831 // Sonderbehandlung falls es sich um eine Root ohne Laufwerk handelt 832 833 if ( !rDirEntry.aName.Len() && rDirEntry.eFlag == FSYS_FLAG_ABSROOT ) 834 { 835 nKindFlags = FSYS_KIND_DIR; 836 nError = FSYS_ERR_OK; 837 return sal_True; 838 } 839 840 // keine Error-Boxen anzeigen 841 FSysFailOnErrorImpl(); 842 843 // Redirect 844 String aPath( rDirEntry.GetFull() ); 845 #ifndef BOOTSTRAP 846 FSysRedirector::DoRedirect( aPath ); 847 #endif 848 DirEntry aDirEntry( aPath ); 849 850 // ist ein Medium im Laufwerk? 851 HACK("wie?") 852 sal_Bool bAccess = sal_True; 853 const DirEntry *pTop = aDirEntry.ImpGetTopPtr(); 854 ByteString aName = ByteString(pTop->aName).ToLowerAscii(); 855 if ( !bForceAccess && 856 ( pTop->eFlag == FSYS_FLAG_ABSROOT || 857 pTop->eFlag == FSYS_FLAG_RELROOT || 858 pTop->eFlag == FSYS_FLAG_VOLUME ) ) 859 if ( aName == "a:" || aName == "b:" ) 860 bAccess = sal_False; 861 else 862 DBG_TRACE( "FSys: will access removable device!" ); 863 if ( bAccess && ( aName == "a:" || aName == "b:" ) ) { 864 DBG_WARNING( "floppy will clatter" ); 865 } 866 867 // Sonderbehandlung, falls es sich um ein Volume handelt 868 if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME || 869 aDirEntry.eFlag == FSYS_FLAG_ABSROOT ) 870 { 871 if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME ) 872 nKindFlags = FSYS_KIND_DEV | ( aDirEntry.aName.Len() == 2 873 ? FSYS_KIND_BLOCK 874 : FSYS_KIND_CHAR ); 875 else 876 nKindFlags = FSYS_KIND_DIR; 877 878 if ( !bAccess ) 879 { 880 if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME ) 881 nKindFlags |= FSYS_KIND_REMOVEABLE; 882 nError = FSYS_ERR_NOTEXISTS; 883 nKindFlags = 0; 884 return sal_False; 885 } 886 887 ByteString aRootDir = aDirEntry.aName; 888 aRootDir += ByteString( "\\" ); 889 UINT nType = GetDriveType( (char *) aRootDir.GetBuffer() ); //TPF: 2i 890 if ( nType == 1 || nType == 0 ) 891 { 892 nError = FSYS_ERR_NOTEXISTS; 893 nKindFlags = 0; 894 return sal_False; 895 } 896 897 if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME ) 898 nKindFlags = nKindFlags | 899 ( ( nType == DRIVE_REMOVABLE ) ? FSYS_KIND_REMOVEABLE : 0 ) | 900 ( ( nType == DRIVE_FIXED ) ? FSYS_KIND_FIXED : 0 ) | 901 ( ( nType == DRIVE_REMOTE ) ? FSYS_KIND_REMOTE : 0 ) | 902 ( ( nType == DRIVE_RAMDISK ) ? FSYS_KIND_RAM : 0 ) | 903 ( ( nType == DRIVE_CDROM ) ? FSYS_KIND_CDROM : 0 ) | 904 ( ( nType == 0 ) ? FSYS_KIND_UNKNOWN : 0 ); 905 906 nError = ERRCODE_NONE; 907 908 return sal_True; 909 } 910 911 // Statusinformation vom Betriebssystem holen 912 HANDLE h; //() 913 _WIN32_FIND_DATAA aEntry = {}; 914 DirEntry aAbsEntry( aDirEntry ); 915 if ( bAccess && aAbsEntry.ToAbs() ) 916 { 917 // im Namen k"onnen auch ';*?' als normale Zeichen vorkommen 918 ByteString aFilePath( aAbsEntry.GetFull(), osl_getThreadTextEncoding() ); 919 920 // MI: dann gehen Umlaute auf Novell-Servern nicht / wozu ueberhaupt 921 // CharUpperBuff( (char*) aFilePath.GetStr(), aFilePath.Len() ); 922 DBG_TRACE1( "FileStat: %s", aFilePath.GetBuffer() ); 923 h = aFilePath.Len() < 230 924 // die Win32-API ist hier sehr schwammig 925 ? FindFirstFile( (char *) aFilePath.GetBuffer(), &aEntry )//TPF: 2i 926 : INVALID_HANDLE_VALUE; 927 928 if ( INVALID_HANDLE_VALUE != h ) 929 { 930 if ( !( aEntry.dwFileAttributes & 0x40 ) ) // com1: etc. e.g. not encrypted (means normal) 931 { 932 ByteString aUpperName = Upper_Impl(ByteString(aAbsEntry.GetName(), osl_getThreadTextEncoding())); 933 934 // HRO: #74051# Compare also with short alternate filename 935 if ( aUpperName != Upper_Impl( aEntry.cFileName ) && aUpperName != Upper_Impl( aEntry.cAlternateFileName ) ) 936 h = INVALID_HANDLE_VALUE; 937 } 938 } 939 940 if ( INVALID_HANDLE_VALUE == h ) 941 { 942 DWORD dwError = GetLastError(); 943 944 if ( ERROR_BAD_NET_NAME == dwError ) 945 { 946 nKindFlags = FSYS_KIND_UNKNOWN; 947 nError = FSYS_ERR_NOTEXISTS; 948 return sal_False; 949 } 950 951 // UNC-Volume? 952 DirEntry *pTop = aAbsEntry.ImpGetTopPtr(); 953 if ( pTop->GetFlag() == FSYS_FLAG_ABSROOT && 954 ( pTop->aName.Len() > 1 && (pTop->aName.GetBuffer()[1] != ':' )) ) 955 { 956 if ( bForceAccess ) 957 { 958 if ( Exists_Impl( aFilePath ) ) 959 { 960 nKindFlags = FSYS_KIND_DIR|FSYS_KIND_REMOTE; 961 nError = FSYS_ERR_OK; 962 return sal_True; 963 } 964 else 965 { 966 nKindFlags = FSYS_KIND_UNKNOWN; 967 nError = FSYS_ERR_NOTEXISTS; 968 return sal_False; 969 } 970 } 971 } 972 } 973 } 974 else 975 h = INVALID_HANDLE_VALUE; 976 977 if ( h == INVALID_HANDLE_VALUE ) 978 { 979 // Sonderbehandlung falls es sich um eine Wildcard handelt 980 ByteString aTempName( aDirEntry.GetName(), osl_getThreadTextEncoding() ); 981 if ( strchr( aTempName.GetBuffer(), '?' ) || 982 strchr( aTempName.GetBuffer(), '*' ) || 983 strchr( aTempName.GetBuffer(), ';' ) ) 984 { 985 nKindFlags = FSYS_KIND_WILD; 986 nError = FSYS_ERR_OK; 987 return sal_True; 988 } 989 990 if ( bAccess ) 991 { 992 nError = FSYS_ERR_NOTEXISTS; 993 nKindFlags = FSYS_KIND_UNKNOWN; 994 } 995 else 996 nKindFlags = FSYS_KIND_REMOVEABLE; 997 } 998 else 999 { 1000 ImpInit( &aEntry ); 1001 FindClose( h ); 1002 } 1003 1004 if ( 0 != nError ) 1005 nKindFlags = 0; 1006 1007 return 0 == nError; 1008 1009 } 1010 1011 sal_Bool IsRedirectable_Impl( const ByteString &rPath ) 1012 { 1013 if ( rPath.Len() >= 3 && ':' == rPath.GetBuffer()[1] ) 1014 { 1015 ByteString aVolume = rPath.Copy( 0, 3 ); 1016 UINT nType = GetDriveType( (char *) aVolume.GetBuffer() ); 1017 SetLastError( ERROR_SUCCESS ); 1018 return DRIVE_FIXED != nType; 1019 } 1020 return sal_False; 1021 } 1022 1023 /************************************************************************* 1024 |* 1025 |* TempDirImpl() 1026 |* 1027 |* Beschreibung liefert den Namens des Directories fuer temporaere 1028 |* Dateien 1029 |* Ersterstellung MI 16.03.94 1030 |* Letzte Aenderung MI 16.03.94 1031 |* 1032 *************************************************************************/ 1033 1034 const char* TempDirImpl( char *pBuf ) 1035 { 1036 if ( !GetTempPath( MAX_PATH, pBuf ) && 1037 !GetWindowsDirectory( pBuf, MAX_PATH ) && 1038 !GetEnvironmentVariable( "HOMEPATH", pBuf, MAX_PATH ) ) 1039 return 0; 1040 1041 return pBuf; 1042 } 1043 1044 //======================================================================= 1045 1046 ErrCode FileStat::QueryDiskSpace( const String &rPath, 1047 BigInt &rFreeBytes, BigInt &rTotalBytes ) 1048 { 1049 DWORD nSectorsPerCluster; /* address of sectors per cluster */ 1050 DWORD nBytesPerSector; /* address of bytes per sector */ 1051 DWORD nFreeClusters; /* address of number of free clusters */ 1052 DWORD nClusters; /* address of total number of clusters */ 1053 1054 ByteString aVol( DirEntry(rPath).ImpGetTopPtr()->GetName(), osl_getThreadTextEncoding()); 1055 bool bOK = GetDiskFreeSpace( aVol.GetBuffer(), 1056 &nSectorsPerCluster, &nBytesPerSector, 1057 &nFreeClusters, &nClusters ); 1058 if ( !bOK ) 1059 return Sys2SolarError_Impl( GetLastError() ); 1060 1061 BigInt aBytesPerCluster( BigInt(nSectorsPerCluster) * 1062 BigInt(nBytesPerSector) ); 1063 rFreeBytes = aBytesPerCluster * BigInt(nFreeClusters); 1064 rTotalBytes = aBytesPerCluster * BigInt(nClusters); 1065 return 0; 1066 } 1067 1068 //========================================================================= 1069 1070 void FSysEnableSysErrorBox( sal_Bool bEnable ) 1071 { // Preserve other Bits!! 1072 sal_uInt32 nErrorMode = SetErrorMode( bEnable ? 0 : SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX ); 1073 if ( bEnable ) 1074 nErrorMode &= ~(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); 1075 else 1076 nErrorMode |= (SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); 1077 SetErrorMode( nErrorMode ); 1078 } 1079 1080 1081 1082