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 |