1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxDir implementation for Win32 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "dir.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  37 #include "wx/filefn.h"          // for wxPathExists() 
  40     #include "wx/msw/private.h" 
  43 // ---------------------------------------------------------------------------- 
  44 // define the types and functions used for file searching 
  45 // ---------------------------------------------------------------------------- 
  47 typedef WIN32_FIND_DATA FIND_STRUCT
; 
  48 typedef HANDLE FIND_DATA
; 
  49 typedef DWORD FIND_ATTR
; 
  51 static inline FIND_DATA 
InitFindData() { return INVALID_HANDLE_VALUE
; } 
  53 static inline bool IsFindDataOk(FIND_DATA fd
) 
  55         return fd 
!= INVALID_HANDLE_VALUE
; 
  58 static inline void FreeFindData(FIND_DATA fd
) 
  60         if ( !::FindClose(fd
) ) 
  62             wxLogLastError(_T("FindClose")); 
  66 static inline FIND_DATA 
FindFirst(const wxString
& spec
, 
  67                                       FIND_STRUCT 
*finddata
) 
  69         return ::FindFirstFile(spec
, finddata
); 
  72 static inline bool FindNext(FIND_DATA fd
, FIND_STRUCT 
*finddata
) 
  74         return ::FindNextFile(fd
, finddata
) != 0; 
  77 static const wxChar 
*GetNameFromFindData(FIND_STRUCT 
*finddata
) 
  79         return finddata
->cFileName
; 
  82 static const FIND_ATTR 
GetAttrFromFindData(FIND_STRUCT 
*finddata
) 
  84         return finddata
->dwFileAttributes
; 
  87 static inline bool IsDir(FIND_ATTR attr
) 
  89         return (attr 
& FILE_ATTRIBUTE_DIRECTORY
) != 0; 
  92 static inline bool IsHidden(FIND_ATTR attr
) 
  94         return (attr 
& (FILE_ATTRIBUTE_HIDDEN 
| FILE_ATTRIBUTE_SYSTEM
)) != 0; 
  97 // ---------------------------------------------------------------------------- 
  99 // ---------------------------------------------------------------------------- 
 102     #define MAX_PATH 260        // from VC++ headers 
 105 // ---------------------------------------------------------------------------- 
 107 // ---------------------------------------------------------------------------- 
 109 #define M_DIR       ((wxDirData *)m_data) 
 111 // ---------------------------------------------------------------------------- 
 113 // ---------------------------------------------------------------------------- 
 115 // this class stores everything we need to enumerate the files 
 119     wxDirData(const wxString
& dirname
); 
 122     void SetFileSpec(const wxString
& filespec
) { m_filespec 
= filespec
; } 
 123     void SetFlags(int flags
) { m_flags 
= flags
; } 
 127     bool Read(wxString 
*filename
); 
 129     const wxString
& GetName() const { return m_dirname
; } 
 132     FIND_DATA m_finddata
; 
 139     DECLARE_NO_COPY_CLASS(wxDirData
) 
 142 // ============================================================================ 
 144 // ============================================================================ 
 146 // ---------------------------------------------------------------------------- 
 148 // ---------------------------------------------------------------------------- 
 150 wxDirData::wxDirData(const wxString
& dirname
) 
 153     m_finddata 
= InitFindData(); 
 156 wxDirData::~wxDirData() 
 161 void wxDirData::Close() 
 163     if ( IsFindDataOk(m_finddata
) ) 
 165         FreeFindData(m_finddata
); 
 167         m_finddata 
= InitFindData(); 
 171 void wxDirData::Rewind() 
 176 bool wxDirData::Read(wxString 
*filename
) 
 180     WIN32_FIND_DATA finddata
; 
 181     #define PTR_TO_FINDDATA (&finddata) 
 183     if ( !IsFindDataOk(m_finddata
) ) 
 186         wxString filespec 
= m_dirname
; 
 187         if ( !wxEndsWithPathSeparator(filespec
) ) 
 189             filespec 
+= _T('\\'); 
 191         filespec 
+= (!m_filespec 
? _T("*.*") : m_filespec
.c_str()); 
 193         m_finddata 
= FindFirst(filespec
, PTR_TO_FINDDATA
); 
 198     if ( !IsFindDataOk(m_finddata
) ) 
 201         DWORD err 
= ::GetLastError(); 
 203         if ( err 
!= ERROR_FILE_NOT_FOUND 
) 
 205             wxLogSysError(err
, _("Can not enumerate files in directory '%s'"), 
 209         //else: not an error, just no (such) files 
 225             if ( !FindNext(m_finddata
, PTR_TO_FINDDATA
) ) 
 228                 DWORD err 
= ::GetLastError(); 
 230                 if ( err 
!= ERROR_NO_MORE_FILES 
) 
 232                     wxLogLastError(_T("FindNext")); 
 235                 //else: not an error, just no more (such) files 
 241         name 
= GetNameFromFindData(PTR_TO_FINDDATA
); 
 242         attr 
= GetAttrFromFindData(PTR_TO_FINDDATA
); 
 244         // don't return "." and ".." unless asked for 
 245         if ( name
[0] == _T('.') && 
 246              ((name
[1] == _T('.') && name
[2] == _T('\0')) || 
 247               (name
[1] == _T('\0'))) ) 
 249             if ( !(m_flags 
& wxDIR_DOTDOT
) ) 
 253         // check the type now 
 254         if ( !(m_flags 
& wxDIR_FILES
) && !IsDir(attr
) ) 
 256             // it's a file, but we don't want them 
 259         else if ( !(m_flags 
& wxDIR_DIRS
) && IsDir(attr
) ) 
 261             // it's a dir, and we don't want it 
 265         // finally, check whether it's a hidden file 
 266         if ( !(m_flags 
& wxDIR_HIDDEN
) ) 
 268             if ( IsHidden(attr
) ) 
 270                 // it's a hidden file, skip it 
 283 // ---------------------------------------------------------------------------- 
 285 // ---------------------------------------------------------------------------- 
 288 bool wxDir::Exists(const wxString
& dir
) 
 290     return wxPathExists(dir
); 
 293 // ---------------------------------------------------------------------------- 
 294 // wxDir construction/destruction 
 295 // ---------------------------------------------------------------------------- 
 297 wxDir::wxDir(const wxString
& dirname
) 
 304 bool wxDir::Open(const wxString
& dirname
) 
 307     m_data 
= new wxDirData(dirname
); 
 312 bool wxDir::IsOpened() const 
 314     return m_data 
!= NULL
; 
 317 wxString 
wxDir::GetName() const 
 322         name 
= M_DIR
->GetName(); 
 325             // bring to canonical Windows form 
 326             name
.Replace(_T("/"), _T("\\")); 
 328             if ( name
.Last() == _T('\\') ) 
 330                 // chop off the last (back)slash 
 331                 name
.Truncate(name
.length() - 1); 
 344 // ---------------------------------------------------------------------------- 
 346 // ---------------------------------------------------------------------------- 
 348 bool wxDir::GetFirst(wxString 
*filename
, 
 349                      const wxString
& filespec
, 
 352     wxCHECK_MSG( IsOpened(), FALSE
, _T("must wxDir::Open() first") ); 
 356     M_DIR
->SetFileSpec(filespec
); 
 357     M_DIR
->SetFlags(flags
); 
 359     return GetNext(filename
); 
 362 bool wxDir::GetNext(wxString 
*filename
) const 
 364     wxCHECK_MSG( IsOpened(), FALSE
, _T("must wxDir::Open() first") ); 
 366     wxCHECK_MSG( filename
, FALSE
, _T("bad pointer in wxDir::GetNext()") ); 
 368     return M_DIR
->Read(filename
); 
 371 // ---------------------------------------------------------------------------- 
 372 // wxGetDirectoryTimes: used by wxFileName::GetTimes() 
 373 // ---------------------------------------------------------------------------- 
 378 wxGetDirectoryTimes(const wxString
& dirname
, 
 379                     FILETIME 
*ftAccess
, FILETIME 
*ftCreate
, FILETIME 
*ftMod
) 
 381     // FindFirst() is going to fail 
 382     wxASSERT_MSG( !dirname
.empty() && dirname
.Last() != _T('\\'), 
 383                   _T("incorrect directory name format in wxGetDirectoryTimes") ); 
 386     FIND_DATA fd 
= FindFirst(dirname
, &fs
); 
 387     if ( !IsFindDataOk(fd
) ) 
 392     *ftAccess 
= fs
.ftLastAccessTime
; 
 393     *ftCreate 
= fs
.ftCreationTime
; 
 394     *ftMod 
= fs
.ftLastWriteTime
;