update for HEAD-2003091401
[reactos.git] / subsys / system / explorer / shell / winfs.cpp
1 /*
2  * Copyright 2003 Martin Fuchs
3  *
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.
8  *
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.
13  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20  //
21  // Explorer clone
22  //
23  // winfs.cpp
24  //
25  // Martin Fuchs, 23.07.2003
26  //
27
28
29 #include "../utility/utility.h"
30 #include "../utility/shellclasses.h"
31
32 #include "entries.h"
33 #include "winfs.h"
34
35
36 void WinDirectory::read_directory()
37 {
38         Entry* first_entry = NULL;
39         Entry* last = NULL;
40         Entry* entry;
41
42         int level = _level + 1;
43
44         LPCTSTR path = (LPCTSTR)_path;
45         TCHAR buffer[MAX_PATH], *p;
46         for(p=buffer; *path; )
47                 *p++ = *path++;
48
49         lstrcpy(p, TEXT("\\*"));
50
51         WIN32_FIND_DATA w32fd;
52         HANDLE hFind = FindFirstFile(buffer, &w32fd);
53
54         if (hFind != INVALID_HANDLE_VALUE) {
55                 do {
56                         lstrcpy(p+1, w32fd.cFileName);
57
58                         if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
59                                 entry = new WinDirectory(this, buffer);
60                         else
61                                 entry = new WinEntry(this);
62
63                         if (!first_entry)
64                                 first_entry = entry;
65
66                         if (last)
67                                 last->_next = entry;
68
69                         memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
70                         entry->_down = NULL;
71                         entry->_expanded = false;
72                         entry->_scanned = false;
73                         entry->_level = level;
74                         entry->_bhfi_valid = false;
75
76                         HANDLE hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
77                                                                                 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
78
79                         if (hFile != INVALID_HANDLE_VALUE) {
80                                 if (GetFileInformationByHandle(hFile, &entry->_bhfi))
81                                         entry->_bhfi_valid = true;
82
83                                 CloseHandle(hFile);
84                         }
85
86                         last = entry;
87                 } while(FindNextFile(hFind, &w32fd));
88
89                 last->_next = NULL;
90
91                 FindClose(hFind);
92         }
93
94         _down = first_entry;
95         _scanned = true;
96 }
97
98
99 const void* WinDirectory::get_next_path_component(const void* p)
100 {
101         LPCTSTR s = (LPCTSTR) p;
102
103         while(*s && *s!=TEXT('\\') && *s!=TEXT('/'))
104                 ++s;
105
106         while(*s==TEXT('\\') || *s==TEXT('/'))
107                 ++s;
108
109         if (!*s)
110                 return NULL;
111
112         return s;
113 }
114
115
116 Entry* WinDirectory::find_entry(const void* p)
117 {
118         LPCTSTR name = (LPCTSTR)p;
119
120         for(Entry*entry=_down; entry; entry=entry->_next) {
121                 LPCTSTR p = name;
122                 LPCTSTR q = entry->_data.cFileName;
123
124                 do {
125                         if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
126                                 return entry;
127                 } while(tolower(*p++) == tolower(*q++));
128
129                 p = name;
130                 q = entry->_data.cAlternateFileName;
131
132                 do {
133                         if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
134                                 return entry;
135                 } while(tolower(*p++) == tolower(*q++));
136         }
137
138         return NULL;
139 }
140
141
142  // get full path of specified directory entry
143 void WinEntry::get_path(PTSTR path) const
144 {
145         int level = 0;
146         int len = 0;
147
148         for(const Entry* entry=this; entry; level++) {
149                 LPCTSTR name = entry->_data.cFileName;
150                 int l = 0;
151
152                 for(LPCTSTR s=name; *s && *s!=TEXT('/') && *s!=TEXT('\\'); s++)
153                         ++l;
154
155                 if (entry->_up) {
156                         if (l > 0) {
157                                 memmove(path+l+1, path, len*sizeof(TCHAR));
158                                 memcpy(path+1, name, l*sizeof(TCHAR));
159                                 len += l+1;
160
161                                 path[0] = TEXT('\\');
162                         }
163
164                         entry = entry->_up;
165                 } else {
166                         memmove(path+l, path, len*sizeof(TCHAR));
167                         memcpy(path, name, l*sizeof(TCHAR));
168                         len += l;
169                         break;
170                 }
171         }
172
173         if (!level)
174                 path[len++] = TEXT('\\');
175
176         path[len] = TEXT('\0');
177 }