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