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 int ScanNTFSStreams(Entry
* entry
, HANDLE hFile
)
39 DWORD read
, seek_high
;
40 Entry
** pnext
= &entry
->_down
;
44 struct NTFS_StreamHdr
: public WIN32_STREAM_ID
{
45 WCHAR name_padding
[_MAX_FNAME
]; // room for reading stream name
48 if (!BackupRead(hFile
, (LPBYTE
)&hdr
, (LPBYTE
)&hdr
.cStreamName
-(LPBYTE
)&hdr
, &read
, FALSE
, FALSE
, &ctx
) ||
49 (long)read
!=(LPBYTE
)&hdr
.cStreamName
-(LPBYTE
)&hdr
)
52 if (hdr
.dwStreamId
== BACKUP_ALTERNATE_DATA
) {
53 if (hdr
.dwStreamNameSize
&&
54 BackupRead(hFile
, (LPBYTE
)hdr
.cStreamName
, hdr
.dwStreamNameSize
, &read
, FALSE
, FALSE
, &ctx
) &&
55 read
==hdr
.dwStreamNameSize
)
59 int l
= hdr
.dwStreamNameSize
/ sizeof(WCHAR
);
60 LPCWSTR p
= hdr
.cStreamName
;
61 LPCWSTR e
= hdr
.cStreamName
+ l
;
74 Entry
* stream_entry
= new WinEntry(entry
);
76 memcpy(&stream_entry
->_data
, &entry
->_data
, sizeof(WIN32_FIND_DATA
));
77 lstrcpy(stream_entry
->_data
.cFileName
, String(p
, l
));
79 stream_entry
->_down
= NULL
;
80 stream_entry
->_expanded
= false;
81 stream_entry
->_scanned
= false;
82 stream_entry
->_level
= entry
->_level
+ 1;
84 *pnext
= stream_entry
;
85 pnext
= &stream_entry
->_next
;
89 // jump to the next stream header
90 if (!BackupSeek(hFile
, ~0, ~0, &read
, &seek_high
, &ctx
)) {
91 DWORD error
= GetLastError();
93 if (error
!= ERROR_SEEK
) {
94 BackupRead(hFile
, 0, 0, &read
, TRUE
, FALSE
, &ctx
); // terminate BackupRead() loop
95 THROW_EXCEPTION(error
);
99 hdr
.Size
.QuadPart
-= read
;
100 hdr
.Size
.HighPart
-= seek_high
;
104 while(hdr
.Size
.QuadPart
> 0) {
105 if (!BackupRead(hFile
, buffer
, sizeof(buffer
), &read
, FALSE
, FALSE
, &ctx
) || read
!=sizeof(buffer
))
108 hdr
.Size
.QuadPart
-= read
;
114 if (!BackupRead(hFile
, 0, 0, &read
, TRUE
, FALSE
, &ctx
)) // terminate BackupRead() loop
115 THROW_EXCEPTION(GetLastError());
121 void WinDirectory::read_directory(int scan_flags
)
123 CONTEXT("WinDirectory::read_directory()");
125 int level
= _level
+ 1;
127 Entry
* first_entry
= NULL
;
131 LPCTSTR path
= (LPCTSTR
)_path
;
132 TCHAR buffer
[MAX_PATH
], *pname
;
133 for(pname
=buffer
; *path
; )
136 lstrcpy(pname
, TEXT("\\*"));
138 WIN32_FIND_DATA w32fd
;
139 HANDLE hFind
= FindFirstFile(buffer
, &w32fd
);
141 if (hFind
!= INVALID_HANDLE_VALUE
) {
143 lstrcpy(pname
+1, w32fd
.cFileName
);
145 if (w32fd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
146 entry
= new WinDirectory(this, buffer
);
148 entry
= new WinEntry(this);
156 memcpy(&entry
->_data
, &w32fd
, sizeof(WIN32_FIND_DATA
));
157 entry
->_level
= level
;
159 // display file type names, but don't hide file extensions
160 g_Globals
._ftype_mgr
.set_type(entry
, true);
162 if (!(scan_flags
& SCAN_DONT_ACCESS
)) {
163 HANDLE hFile
= CreateFile(buffer
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
164 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
166 if (hFile
!= INVALID_HANDLE_VALUE
) {
167 if (GetFileInformationByHandle(hFile
, &entry
->_bhfi
))
168 entry
->_bhfi_valid
= true;
170 if (ScanNTFSStreams(entry
, hFile
))
171 entry
->_scanned
= true; // There exist named NTFS sub-streams in this file.
177 last
= entry
; // There is always at least one entry, because FindFirstFile() succeeded and we don't filter the file entries.
178 } while(FindNextFile(hFind
, &w32fd
));
191 const void* WinDirectory::get_next_path_component(const void* p
) const
193 LPCTSTR s
= (LPCTSTR
) p
;
195 while(*s
&& *s
!=TEXT('\\') && *s
!=TEXT('/'))
198 while(*s
==TEXT('\\') || *s
==TEXT('/'))
208 Entry
* WinDirectory::find_entry(const void* p
)
210 LPCTSTR name
= (LPCTSTR
)p
;
212 for(Entry
*entry
=_down
; entry
; entry
=entry
->_next
) {
214 LPCTSTR q
= entry
->_data
.cFileName
;
217 if (!*p
|| *p
==TEXT('\\') || *p
==TEXT('/'))
219 } while(tolower(*p
++) == tolower(*q
++));
222 q
= entry
->_data
.cAlternateFileName
;
225 if (!*p
|| *p
==TEXT('\\') || *p
==TEXT('/'))
227 } while(tolower(*p
++) == tolower(*q
++));
234 // get full path of specified directory entry
235 bool WinEntry::get_path(PTSTR path
, size_t path_count
) const
237 return get_path_base(path
, path_count
, ET_WINDOWS
);
240 ShellPath
WinEntry::create_absolute_pidl() const
242 CONTEXT("WinEntry::create_absolute_pidl()");
244 TCHAR path
[MAX_PATH
];
246 if (get_path(path
, COUNTOF(path
)))
247 return ShellPath(path
);