2 * Copyright 2003, 2004, 2005 Martin Fuchs
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 // Martin Fuchs, 23.07.2003
36 #ifdef BACKUP_READ_IMPLEMENTED
37 int ScanNTFSStreams(Entry
* entry
, HANDLE hFile
)
40 DWORD read
, seek_high
;
41 Entry
** pnext
= &entry
->_down
;
45 struct NTFS_StreamHdr
: public WIN32_STREAM_ID
{
46 WCHAR name_padding
[_MAX_FNAME
]; // room for reading stream name
49 if (!BackupRead(hFile
, (LPBYTE
)&hdr
, (LPBYTE
)&hdr
.cStreamName
-(LPBYTE
)&hdr
, &read
, FALSE
, FALSE
, &ctx
) ||
50 (long)read
!=(LPBYTE
)&hdr
.cStreamName
-(LPBYTE
)&hdr
)
53 if (hdr
.dwStreamId
== BACKUP_ALTERNATE_DATA
) {
54 if (hdr
.dwStreamNameSize
&&
55 BackupRead(hFile
, (LPBYTE
)hdr
.cStreamName
, hdr
.dwStreamNameSize
, &read
, FALSE
, FALSE
, &ctx
) &&
56 read
==hdr
.dwStreamNameSize
)
60 int l
= hdr
.dwStreamNameSize
/ sizeof(WCHAR
);
61 LPCWSTR p
= hdr
.cStreamName
;
62 LPCWSTR e
= hdr
.cStreamName
+ l
;
75 Entry
* stream_entry
= new WinEntry(entry
);
77 memcpy(&stream_entry
->_data
, &entry
->_data
, sizeof(WIN32_FIND_DATA
));
78 lstrcpy(stream_entry
->_data
.cFileName
, String(p
, l
));
80 stream_entry
->_down
= NULL
;
81 stream_entry
->_expanded
= false;
82 stream_entry
->_scanned
= false;
83 stream_entry
->_level
= entry
->_level
+ 1;
85 *pnext
= stream_entry
;
86 pnext
= &stream_entry
->_next
;
90 // jump to the next stream header
91 if (!BackupSeek(hFile
, ~0, ~0, &read
, &seek_high
, &ctx
)) {
92 DWORD error
= GetLastError();
94 if (error
!= ERROR_SEEK
) {
95 BackupRead(hFile
, 0, 0, &read
, TRUE
, FALSE
, &ctx
); // terminate BackupRead() loop
96 THROW_EXCEPTION(error
);
100 hdr
.Size
.QuadPart
-= read
;
101 hdr
.Size
.HighPart
-= seek_high
;
105 while(hdr
.Size
.QuadPart
> 0) {
106 if (!BackupRead(hFile
, buffer
, sizeof(buffer
), &read
, FALSE
, FALSE
, &ctx
) || read
!=sizeof(buffer
))
109 hdr
.Size
.QuadPart
-= read
;
115 if (!BackupRead(hFile
, 0, 0, &read
, TRUE
, FALSE
, &ctx
)) // terminate BackupRead() loop
116 THROW_EXCEPTION(GetLastError());
123 void WinDirectory::read_directory(int scan_flags
)
125 CONTEXT("WinDirectory::read_directory()");
127 int level
= _level
+ 1;
129 Entry
* first_entry
= NULL
;
133 LPCTSTR path
= (LPCTSTR
)_path
;
134 TCHAR buffer
[MAX_PATH
], *pname
;
135 for(pname
=buffer
; *path
; )
138 lstrcpy(pname
, TEXT("\\*"));
140 WIN32_FIND_DATA w32fd
;
141 HANDLE hFind
= FindFirstFile(buffer
, &w32fd
);
143 if (hFind
!= INVALID_HANDLE_VALUE
) {
145 lstrcpy(pname
+1, w32fd
.cFileName
);
147 if (w32fd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
148 entry
= new WinDirectory(this, buffer
);
150 entry
= new WinEntry(this);
158 memcpy(&entry
->_data
, &w32fd
, sizeof(WIN32_FIND_DATA
));
159 entry
->_level
= level
;
161 // display file type names, but don't hide file extensions
162 g_Globals
._ftype_mgr
.set_type(entry
, true);
164 if (!(scan_flags
& SCAN_DONT_ACCESS
)) {
165 HANDLE hFile
= CreateFile(buffer
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
166 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
168 if (hFile
!= INVALID_HANDLE_VALUE
) {
169 if (GetFileInformationByHandle(hFile
, &entry
->_bhfi
))
170 entry
->_bhfi_valid
= true;
172 #ifdef BACKUP_READ_IMPLEMENTED
173 if (ScanNTFSStreams(entry
, hFile
))
174 entry
->_scanned
= true; // There exist named NTFS sub-streams in this file.
181 last
= entry
; // There is always at least one entry, because FindFirstFile() succeeded and we don't filter the file entries.
182 } while(FindNextFile(hFind
, &w32fd
));
195 const void* WinDirectory::get_next_path_component(const void* p
) const
197 LPCTSTR s
= (LPCTSTR
) p
;
199 while(*s
&& *s
!=TEXT('\\') && *s
!=TEXT('/'))
202 while(*s
==TEXT('\\') || *s
==TEXT('/'))
212 Entry
* WinDirectory::find_entry(const void* p
)
214 LPCTSTR name
= (LPCTSTR
)p
;
216 for(Entry
*entry
=_down
; entry
; entry
=entry
->_next
) {
218 LPCTSTR q
= entry
->_data
.cFileName
;
221 if (!*p
|| *p
==TEXT('\\') || *p
==TEXT('/'))
223 } while(tolower(*p
++) == tolower(*q
++));
226 q
= entry
->_data
.cAlternateFileName
;
229 if (!*p
|| *p
==TEXT('\\') || *p
==TEXT('/'))
231 } while(tolower(*p
++) == tolower(*q
++));
238 // get full path of specified directory entry
239 bool WinEntry::get_path(PTSTR path
, size_t path_count
) const
241 return get_path_base(path
, path_count
, ET_WINDOWS
);
244 ShellPath
WinEntry::create_absolute_pidl() const
246 CONTEXT("WinEntry::create_absolute_pidl()");
248 TCHAR path
[MAX_PATH
];
250 if (get_path(path
, COUNTOF(path
)))
251 return ShellPath(path
);