xref: /aoo41x/main/tools/source/fsys/wntmsc.cxx (revision cdf0e10c)
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