winfs.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2003, 2004, 2005 Martin Fuchs
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 
00020  //
00021  // Explorer clone
00022  //
00023  // winfs.cpp
00024  //
00025  // Martin Fuchs, 23.07.2003
00026  //
00027 
00028 
00029 #include <precomp.h>
00030 
00031 #ifndef _NO_WIN_FS
00032 
00033 //#include "winfs.h"
00034 
00035 
00036 int ScanNTFSStreams(Entry* entry, HANDLE hFile)
00037 {
00038     PVOID ctx = 0;
00039     DWORD read, seek_high;
00040     Entry** pnext = &entry->_down;
00041     int cnt = 0;
00042 
00043     for(;;) {
00044         struct NTFS_StreamHdr : public WIN32_STREAM_ID {
00045             WCHAR name_padding[_MAX_FNAME]; // room for reading stream name
00046         } hdr;
00047 
00048         if (!BackupRead(hFile, (LPBYTE)&hdr, (LPBYTE)&hdr.cStreamName-(LPBYTE)&hdr, &read, FALSE, FALSE, &ctx) ||
00049             (long)read!=(LPBYTE)&hdr.cStreamName-(LPBYTE)&hdr)
00050             break;
00051 
00052         if (hdr.dwStreamId == BACKUP_ALTERNATE_DATA) {
00053             if (hdr.dwStreamNameSize &&
00054                 BackupRead(hFile, (LPBYTE)hdr.cStreamName, hdr.dwStreamNameSize, &read, FALSE, FALSE, &ctx) &&
00055                 read==hdr.dwStreamNameSize)
00056             {
00057                 ++cnt;
00058 
00059                 int l = hdr.dwStreamNameSize / sizeof(WCHAR);
00060                 LPCWSTR p = hdr.cStreamName;
00061                 LPCWSTR e = hdr.cStreamName + l;
00062 
00063                 if (l>0 && *p==':') {
00064                     ++p, --l;
00065 
00066                     e = p;
00067 
00068                     while(l>0 && *e!=':')
00069                         ++e, --l;
00070 
00071                     l = e - p;
00072                 }
00073 
00074                 Entry* stream_entry = new WinEntry(entry);
00075 
00076                 memcpy(&stream_entry->_data, &entry->_data, sizeof(WIN32_FIND_DATA));
00077                 lstrcpy(stream_entry->_data.cFileName, String(p, l));
00078 
00079                 stream_entry->_down = NULL;
00080                 stream_entry->_expanded = false;
00081                 stream_entry->_scanned = false;
00082                 stream_entry->_level = entry->_level + 1;
00083 
00084                 *pnext = stream_entry;
00085                 pnext = &stream_entry->_next;
00086             }
00087         }
00088 
00089          // jump to the next stream header
00090         if (!BackupSeek(hFile, ~0, ~0, &read, &seek_high, &ctx)) {
00091             DWORD error = GetLastError();
00092 
00093             if (error != ERROR_SEEK) {
00094                 BackupRead(hFile, 0, 0, &read, TRUE, FALSE, &ctx);  // terminate BackupRead() loop
00095                 THROW_EXCEPTION(error);
00096                 //break;
00097             }
00098 
00099             hdr.Size.QuadPart -= read;
00100             hdr.Size.HighPart -= seek_high;
00101 
00102             BYTE buffer[4096];
00103 
00104             while(hdr.Size.QuadPart > 0) {
00105                 if (!BackupRead(hFile, buffer, sizeof(buffer), &read, FALSE, FALSE, &ctx) || read!=sizeof(buffer))
00106                     break;
00107 
00108                 hdr.Size.QuadPart -= read;
00109             }
00110         }
00111     }
00112 
00113     if (ctx)
00114         if (!BackupRead(hFile, 0, 0, &read, TRUE, FALSE, &ctx)) // terminate BackupRead() loop
00115             THROW_EXCEPTION(GetLastError());
00116 
00117     return cnt;
00118 }
00119 
00120 
00121 void WinDirectory::read_directory(int scan_flags)
00122 {
00123     CONTEXT("WinDirectory::read_directory()");
00124 
00125     int level = _level + 1;
00126 
00127     Entry* first_entry = NULL;
00128     Entry* last = NULL;
00129     Entry* entry;
00130 
00131     LPCTSTR path = (LPCTSTR)_path;
00132     TCHAR buffer[MAX_PATH], *pname;
00133     for(pname=buffer; *path; )
00134         *pname++ = *path++;
00135 
00136     lstrcpy(pname, TEXT("\\*"));
00137 
00138     WIN32_FIND_DATA w32fd;
00139     HANDLE hFind = FindFirstFile(buffer, &w32fd);
00140 
00141     if (hFind != INVALID_HANDLE_VALUE) {
00142         do {
00143             lstrcpy(pname+1, w32fd.cFileName);
00144 
00145             if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
00146                 entry = new WinDirectory(this, buffer);
00147             else
00148                 entry = new WinEntry(this);
00149 
00150             if (!first_entry)
00151                 first_entry = entry;
00152 
00153             if (last)
00154                 last->_next = entry;
00155 
00156             memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
00157             entry->_level = level;
00158 
00159              // display file type names, but don't hide file extensions
00160             g_Globals._ftype_mgr.set_type(entry, true);
00161 
00162             if (!(scan_flags & SCAN_DONT_ACCESS)) {
00163                 HANDLE hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
00164                                             0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
00165 
00166                 if (hFile != INVALID_HANDLE_VALUE) {
00167                     if (GetFileInformationByHandle(hFile, &entry->_bhfi))
00168                         entry->_bhfi_valid = true;
00169 
00170                     if (ScanNTFSStreams(entry, hFile))
00171                         entry->_scanned = true; // There exist named NTFS sub-streams in this file.
00172 
00173                     CloseHandle(hFile);
00174                 }
00175             }
00176 
00177             last = entry;   // There is always at least one entry, because FindFirstFile() succeeded and we don't filter the file entries.
00178         } while(FindNextFile(hFind, &w32fd));
00179 
00180         if (last)
00181             last->_next = NULL;
00182 
00183         FindClose(hFind);
00184     }
00185 
00186     _down = first_entry;
00187     _scanned = true;
00188 }
00189 
00190 
00191 const void* WinDirectory::get_next_path_component(const void* p) const
00192 {
00193     LPCTSTR s = (LPCTSTR) p;
00194 
00195     while(*s && *s!=TEXT('\\') && *s!=TEXT('/'))
00196         ++s;
00197 
00198     while(*s==TEXT('\\') || *s==TEXT('/'))
00199         ++s;
00200 
00201     if (!*s)
00202         return NULL;
00203 
00204     return s;
00205 }
00206 
00207 
00208 Entry* WinDirectory::find_entry(const void* p)
00209 {
00210     LPCTSTR name = (LPCTSTR)p;
00211 
00212     for(Entry*entry=_down; entry; entry=entry->_next) {
00213         LPCTSTR p = name;
00214         LPCTSTR q = entry->_data.cFileName;
00215 
00216         do {
00217             if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
00218                 return entry;
00219         } while(tolower(*p++) == tolower(*q++));
00220 
00221         p = name;
00222         q = entry->_data.cAlternateFileName;
00223 
00224         do {
00225             if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
00226                 return entry;
00227         } while(tolower(*p++) == tolower(*q++));
00228     }
00229 
00230     return NULL;
00231 }
00232 
00233 
00234  // get full path of specified directory entry
00235 bool WinEntry::get_path(PTSTR path, size_t path_count) const
00236 {
00237     return get_path_base(path, path_count, ET_WINDOWS);
00238 }
00239 
00240 ShellPath WinEntry::create_absolute_pidl() const
00241 {
00242     CONTEXT("WinEntry::create_absolute_pidl()");
00243 
00244     TCHAR path[MAX_PATH];
00245 
00246     if (get_path(path, COUNTOF(path)))
00247         return ShellPath(path);
00248 
00249     return ShellPath();
00250 }
00251 
00252 #endif // _NO_WIN_FS

ROS Explorer Source Code Documentation
generated on 02.01.2013 by doxygen

ROS Explorer Homepage