diff --git a/reactos/subsys/system/explorer/Jamfile b/reactos/subsys/system/explorer/Jamfile
index 189954029c7..e8f2fcf9b28 100644
--- a/reactos/subsys/system/explorer/Jamfile
+++ b/reactos/subsys/system/explorer/Jamfile
@@ -23,6 +23,7 @@ exe explorer :
shell/winfs.cpp
shell/ntobjfs.cpp
shell/regfs.cpp
+ shell/fatfs.cpp
shell/startup.c
taskbar/desktopbar.cpp
taskbar/quicklaunch.cpp
diff --git a/reactos/subsys/system/explorer/Makefile b/reactos/subsys/system/explorer/Makefile
index 21d1a9d5475..990cf3a35e1 100644
--- a/reactos/subsys/system/explorer/Makefile
+++ b/reactos/subsys/system/explorer/Makefile
@@ -82,6 +82,7 @@ OBJECTS = \
shellfs.o \
ntobjfs.o \
regfs.o \
+ fatfs.o \
mainframe.o \
filechild.o \
pane.o \
diff --git a/reactos/subsys/system/explorer/Makefile.MinGW b/reactos/subsys/system/explorer/Makefile.MinGW
index b0d61afb299..5d35b4edc43 100644
--- a/reactos/subsys/system/explorer/Makefile.MinGW
+++ b/reactos/subsys/system/explorer/Makefile.MinGW
@@ -56,6 +56,7 @@ OBJECTS = \
shellfs.o \
ntobjfs.o \
regfs.o \
+ fatfs.o \
mainframe.o \
filechild.o \
pane.o \
diff --git a/reactos/subsys/system/explorer/Makefile.Wine b/reactos/subsys/system/explorer/Makefile.Wine
index 6a73833d169..f84158f92aa 100644
--- a/reactos/subsys/system/explorer/Makefile.Wine
+++ b/reactos/subsys/system/explorer/Makefile.Wine
@@ -30,6 +30,7 @@ CPP_SRCS = \
shell/pane.cpp \
shell/shellbrowser.cpp \
shell/ntobjfs.cpp \
+ shell/fatfs.cpp \
shell/regfs.cpp \
taskbar/desktopbar.cpp \
taskbar/taskbar.cpp \
diff --git a/reactos/subsys/system/explorer/doc/changes.txt b/reactos/subsys/system/explorer/doc/changes.txt
index 9c1aae589a0..c8573e4a55d 100644
--- a/reactos/subsys/system/explorer/doc/changes.txt
+++ b/reactos/subsys/system/explorer/doc/changes.txt
@@ -59,3 +59,4 @@ If you search for more information, look into the CVS repository.
18.01.2004 m. fuchs explorer/desktop settings property sheet
31.01.2004 m. fuchs included NT Object namespace as virtual file system
31.01.2004 m. fuchs included Registry as virtual file system
+02.02.2004 m. fuchs reading of FAT image files
diff --git a/reactos/subsys/system/explorer/doxy-footer.html b/reactos/subsys/system/explorer/doxy-footer.html
index 32c0449b746..a64ab65e893 100644
--- a/reactos/subsys/system/explorer/doxy-footer.html
+++ b/reactos/subsys/system/explorer/doxy-footer.html
@@ -3,7 +3,7 @@
ROS Explorer Source Code Documentation
- generated on 01.02.2004 by
+ generated on 03.02.2004 by
|
diff --git a/reactos/subsys/system/explorer/explorer.dsp b/reactos/subsys/system/explorer/explorer.dsp
index b50ba704bf1..a33392fb841 100644
--- a/reactos/subsys/system/explorer/explorer.dsp
+++ b/reactos/subsys/system/explorer/explorer.dsp
@@ -728,6 +728,14 @@ SOURCE=.\shell\entries.h
# End Source File
# Begin Source File
+SOURCE=.\shell\fatfs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\shell\fatfs.h
+# End Source File
+# Begin Source File
+
SOURCE=.\shell\filechild.cpp
# End Source File
# Begin Source File
diff --git a/reactos/subsys/system/explorer/explorer_intres.h b/reactos/subsys/system/explorer/explorer_intres.h
index 0d70dc01904..b049da16af4 100644
--- a/reactos/subsys/system/explorer/explorer_intres.h
+++ b/reactos/subsys/system/explorer/explorer_intres.h
@@ -120,7 +120,8 @@
#define ID_DRIVE_UNIX_FS 0x9002
#define ID_DRIVE_NTOBJ_NS 0x9003
#define ID_DRIVE_REGISTRY 0x9004
-#define ID_DRIVE_FIRST 0x9005
+#define ID_DRIVE_FAT 0x9005
+#define ID_DRIVE_FIRST 0x9006
#define ID_ABOUT_WINDOWS 40002
#define ID_ABOUT_EXPLORER 40003
#define ID_DESKTOPBAR_SETTINGS 40005
diff --git a/reactos/subsys/system/explorer/explorer_intres.rc b/reactos/subsys/system/explorer/explorer_intres.rc
index 7a1fcab119d..dda2bd8378d 100644
--- a/reactos/subsys/system/explorer/explorer_intres.rc
+++ b/reactos/subsys/system/explorer/explorer_intres.rc
@@ -353,7 +353,7 @@ CAPTION "About ReactOS Explorer"
FONT 10, "MS Sans Serif"
BEGIN
LTEXT "ReactOS Explorer",IDC_ROS_EXPLORER,91,29,90,11
- LTEXT "(c) 2003 Martin Fuchs",IDC_STATIC,90,50,70,8
+ LTEXT "(c) 2003/2004 Martin Fuchs",IDC_STATIC,90,50,79,8
LTEXT "http://www.sky.franken.de/explorer/",IDC_WWW,21,84,104,
8
CONTROL "&OK",IDOK,"Button",BS_OWNERDRAW | BS_FLAT | WS_GROUP,
diff --git a/reactos/subsys/system/explorer/shell/entries.h b/reactos/subsys/system/explorer/shell/entries.h
index acf146e111b..7050c55828b 100644
--- a/reactos/subsys/system/explorer/shell/entries.h
+++ b/reactos/subsys/system/explorer/shell/entries.h
@@ -33,7 +33,8 @@ enum ENTRY_TYPE {
#endif
ET_SHELL,
ET_NTOBJS,
- ET_REGISTRY
+ ET_REGISTRY,
+ ET_FAT
};
enum SORT_ORDER {
@@ -54,6 +55,9 @@ enum SCAN_FLAGS {
};
#ifndef ATTRIBUTE_SYMBOLIC_LINK
+#define ATTRIBUTE_LONGNAME 0x08000000
+#define ATTRIBUTE_VOLNAME 0x10000000
+#define ATTRIBUTE_ERASED 0x20000000
#define ATTRIBUTE_SYMBOLIC_LINK 0x40000000
#define ATTRIBUTE_EXECUTABLE 0x80000000
#endif
diff --git a/reactos/subsys/system/explorer/shell/fatfs.cpp b/reactos/subsys/system/explorer/shell/fatfs.cpp
new file mode 100644
index 00000000000..1dbe4c8bd1b
--- /dev/null
+++ b/reactos/subsys/system/explorer/shell/fatfs.cpp
@@ -0,0 +1,661 @@
+/*
+ * Copyright 2003 Martin Fuchs
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+ //
+ // Explorer clone
+ //
+ // fatfs.cpp
+ //
+ // Martin Fuchs, 01.02.2004
+ //
+
+
+#include "../utility/utility.h"
+#include "../utility/shellclasses.h"
+#include "../globals.h"
+
+#include "entries.h"
+#include "fatfs.h"
+
+
+static union DEntry* link_dir_entries(struct dirent* dir, struct Kette* K, int cnt)
+{
+ union DEntry* Ent = (union DEntry*) dir;
+ struct Kette* L = NULL;
+
+ for(; cnt; cnt--) {
+ K->Rueck = L;
+ (L=K)->Ent = Ent;
+ AddP(K, sizeof(struct Kette));
+ L->Vorw = K;
+ AddP(Ent, sizeof(union DEntry));
+ }
+
+ L->Vorw = NULL;
+
+ return Ent;
+}
+
+void FATDirectory::read_directory(int scan_flags)
+{
+ CONTEXT("FATDirectory::read_directory()");
+
+ read_dir();
+
+ union DEntry* p = (union DEntry*) _dir;
+ int i = 0;
+
+ do {
+/* if (!IS_LNAME(p->E.attr) && p->E.name[0]!=FAT_DEL_CHAR)
+ gesBytes += p->E.size;
+*/
+
+ AddP(p, sizeof(union DEntry));
+ } while(++i<_ents && p->E.name[0]);
+
+ _alloc = (struct Kette*) malloc((size_t)((_ents=i)+8)*sizeof(struct Kette));
+ if (!_alloc)
+ return;
+
+ link_dir_entries(_dir, _alloc, i);
+
+ Entry* first_entry = NULL;
+ int level = _level + 1;
+
+ Entry* last = NULL;
+
+ WIN32_FIND_DATA w32fd;
+ FAT_attribute attr;
+ String long_name;
+
+ TCHAR buffer[MAX_PATH];
+
+ _tcscpy(buffer, (LPCTSTR)_path);
+ LPTSTR pname = buffer + _tcslen(buffer);
+
+ *pname++ = '\\';
+
+ for(Kette*p=_alloc; p; p=p->Vorw) {
+ memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
+
+ DEntry_E& e = p->Ent->E;
+
+ // get file/directory attributes
+ attr.b = e.attr;
+
+ if (attr.b & (_A_DELETED | _A_ILLEGAL))
+ attr.b |= _A_ILLEGAL;
+
+ const char* s = e.name;
+ LPTSTR d = w32fd.cFileName;
+
+ if (!IS_LNAME(attr.b) || e.name[0]==FAT_DEL_CHAR) {
+ if (e.name[0] == FAT_DEL_CHAR)
+ w32fd.dwFileAttributes |= ATTRIBUTE_ERASED;
+ else if (IS_LNAME(attr.b))
+ w32fd.dwFileAttributes |= ATTRIBUTE_LONGNAME;
+ else if (attr.a.directory)
+ w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+ else if (attr.a.volume)
+ w32fd.dwFileAttributes |= ATTRIBUTE_VOLNAME; //@@ -> in Volume-Name der Root kopieren
+
+ // get file name
+ *d++ = *s==FAT_DEL_CHAR? '?': *s;
+ ++s;
+
+ for(i=0; i<7; ++i)
+ *d++ = *s++;
+
+ while(d>w32fd.cFileName && d[-1]==' ')
+ --d;
+
+ *d++ = '.';
+
+ for(; i<10; ++i)
+ *d++ = *s++;
+
+ while(d>w32fd.cFileName && d[-1]==' ')
+ --d;
+
+ if (d>w32fd.cFileName && d[-1]=='.')
+ --d;
+
+ *d = '\0';
+ } else {
+ // read long file name
+ TCHAR lname[] = {s[1], s[3], s[5], s[7], s[9], s[14], s[16], s[18], s[20], s[22], s[24], s[28], s[30]};
+
+ long_name = String(lname, 13) + long_name;
+ }
+
+ if (!IS_LNAME(attr.b) && !attr.a.volume) {
+ // get file size
+ w32fd.nFileSizeLow = e.size;
+
+ // convert date/time attribute into FILETIME
+ const fdate& date = e.date;
+ const ftime& time = e.time;
+ SYSTEMTIME stime;
+ FILETIME ftime;
+
+ stime.wYear = date.year + 1980;
+ stime.wMonth = date.month;
+ stime.wDayOfWeek = (WORD)-1;
+ stime.wDay = date.day;
+ stime.wHour = time.hour;
+ stime.wMinute = time.min;
+ stime.wSecond = time.sec2 * 2;
+ stime.wMilliseconds = 0;
+
+ if (SystemTimeToFileTime(&stime, &ftime))
+ LocalFileTimeToFileTime(&ftime, &w32fd.ftLastWriteTime);
+
+ if (!(w32fd.dwFileAttributes & ATTRIBUTE_ERASED)) { //@@
+ Entry* entry;
+
+ if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ _tcscpy(pname, w32fd.cFileName);
+ entry = new FATDirectory(_drive, this, buffer, e.fclus);
+ } else
+ entry = new FATEntry(this, e.fclus);
+
+ memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
+
+ if (!long_name.empty()) {
+ entry->_content = _tcsdup(long_name);
+ long_name.erase();
+ }
+
+ if (!first_entry)
+ first_entry = entry;
+
+ if (last)
+ last->_next = entry;
+
+ entry->_level = level;
+
+ last = entry;
+ }
+ }
+ }
+
+ if (last)
+ last->_next = NULL;
+
+ _down = first_entry;
+ _scanned = true;
+}
+
+
+Entry* FATDirectory::find_entry(const void* p)
+{
+ LPCTSTR name = (LPCTSTR)p;
+
+ for(Entry*entry=_down; entry; entry=entry->_next) {
+ LPCTSTR p = name;
+ LPCTSTR q = entry->_data.cFileName;
+
+ do {
+ if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
+ return entry;
+ } while(tolower(*p++) == tolower(*q++));
+
+ p = name;
+ q = entry->_data.cAlternateFileName;
+
+ do {
+ if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
+ return entry;
+ } while(tolower(*p++) == tolower(*q++));
+ }
+
+ return NULL;
+}
+
+
+ // get full path of specified directory entry
+bool FATEntry::get_path(PTSTR path) const
+{
+ int level = 0;
+ int len = 0;
+ int l = 0;
+ LPCTSTR name = NULL;
+ TCHAR buffer[MAX_PATH];
+
+ const Entry* entry;
+ for(entry=this; entry; level++) {
+ l = 0;
+
+ if (entry->_etype == ET_FAT) {
+ name = entry->_data.cFileName;
+
+ for(LPCTSTR s=name; *s && *s!=TEXT('/') && *s!=TEXT('\\'); s++)
+ ++l;
+
+ if (!entry->_up)
+ break;
+ } else {
+ if (entry->get_path(buffer)) {
+ l = _tcslen(buffer);
+ name = buffer;
+
+ /* special handling of drive names */
+ if (l>0 && buffer[l-1]=='\\' && path[0]=='\\')
+ --l;
+
+ memmove(path+l, path, len*sizeof(TCHAR));
+ memcpy(path, name, l*sizeof(TCHAR));
+ len += l;
+ }
+
+ entry = NULL;
+ break;
+ }
+
+ if (l > 0) {
+ memmove(path+l+1, path, len*sizeof(TCHAR));
+ memcpy(path+1, name, l*sizeof(TCHAR));
+ len += l+1;
+
+ path[0] = TEXT('\\');
+ }
+
+ entry = entry->_up;
+ }
+
+ if (entry) {
+ memmove(path+l, path, len*sizeof(TCHAR));
+ memcpy(path, name, l*sizeof(TCHAR));
+ len += l;
+ }
+
+ if (!level)
+ path[len++] = TEXT('\\');
+
+ path[len] = TEXT('\0');
+
+ return true;
+}
+
+
+FATDirectory::FATDirectory(FATDrive& drive, LPCTSTR root_path)
+ : FATEntry(),
+ _drive(drive)
+{
+ _path = _tcsdup(root_path);
+
+ _secarr = NULL;
+ _cur_bufs = 0;
+ _ents = 0;
+ _dir = NULL;
+ _cluster = 0;
+}
+
+FATDirectory::FATDirectory(FATDrive& drive, Entry* parent, LPCTSTR path, unsigned cluster)
+ : FATEntry(parent, cluster),
+ _drive(drive)
+{
+ _path = _tcsdup(path);
+
+ _secarr = NULL;
+ _cur_bufs = 0;
+ _ents = 0;
+ _dir = NULL;
+}
+
+FATDirectory::~FATDirectory()
+{
+ free(_path);
+ _path = NULL;
+}
+
+bool FATDirectory::read_dir()
+{
+ int i;
+
+ if (_cluster == 0) {
+ if (!_drive._boot_sector.SectorsPerFAT) { // FAT32? [boot_sector32->reserved0==0]
+ BootSector32* boot_sector32 = (BootSector32*) &_drive._boot_sector;
+ DWORD sect = _drive._boot_sector.ReservedSectors + _drive._boot_sector.NumberFATs*boot_sector32->SectorsPerFAT32; // lese Root-Directory ein
+ int RootEntries = boot_sector32->RootSectors * 32; //@@
+
+ _secarr = (struct dirsecz*)malloc(sizeof(DWORD) * (_cur_bufs = (int)((_ents=RootEntries)/_drive._bufents)));
+
+ for(i=0; i<_cur_bufs; i++)
+ _secarr->s[i] = sect+i;
+
+ _dir = (struct dirent*)malloc((size_t)(_ents+16)*sizeof(union DEntry));
+ if (!_dir)
+ return false;
+
+ if (!(_drive.read_sector(*_secarr->s,(Buffer*)_dir,_cur_bufs)))
+ return false;
+ } else {
+ DWORD sect = _drive._boot_sector.ReservedSectors + _drive._boot_sector.NumberFATs*_drive._boot_sector.SectorsPerFAT; // read in root directory
+
+ _secarr = (struct dirsecz*)malloc(sizeof(DWORD) * (_cur_bufs = (int)((_ents=_drive._boot_sector.RootEntries)/_drive._bufents)));
+
+ for(i=0; i<_cur_bufs; i++)
+ _secarr->s[i] = sect+i;
+
+ _dir = (struct dirent*)malloc((size_t)(_ents+16)*sizeof(union DEntry));
+ if (!_dir)
+ return false;
+
+ if (!_drive.read_sector(*_secarr->s,(Buffer*)_dir,_cur_bufs))
+ return false;
+ }
+ } else {
+ Buffer* buf;
+ bool ok;
+
+ DWORD h = _cluster;
+
+ _cur_bufs = 0;
+
+ do {
+ h = _drive.read_FAT(h, ok);
+
+ if (!ok)
+ return false;
+
+ _cur_bufs++;
+ } while (h<0x0ffffff0 && h);
+
+ _secarr = (struct dirsecz*) malloc(sizeof(DWORD) * _cur_bufs);
+
+ if (!_secarr)
+ return false;
+
+ _ents = _drive._bufents * (size_t)_cur_bufs * _drive._SClus;
+
+ if ((buf=(Buffer*)(_dir=(struct dirent*)malloc((size_t) (_ents+16)*sizeof(union DEntry)))) == NULL)
+ return false;
+
+ h = _cluster;
+
+ DWORD fdatsec;
+
+ if (!_drive._boot_sector.SectorsPerFAT) { // FAT32 ?
+ BootSector32* boot_sector32 = (BootSector32*) &_drive._boot_sector;
+ //int RootEntries = boot_sector32->RootSectors * 32; //@@
+ //fdatsec = _drive._boot_sector.ReservedSectors + _drive._boot_sector.NumberFATs*boot_sector32->SectorsPerFAT32 + RootEntries*sizeof(DEntry)/_drive._boot_sector.BytesPerSector; // dpb.fdirsec
+ fdatsec = _drive._boot_sector.ReservedSectors +
+ _drive._boot_sector.NumberFATs*boot_sector32->SectorsPerFAT32 + boot_sector32->RootSectors;
+ } else
+ fdatsec = _drive._boot_sector.ReservedSectors +
+ _drive._boot_sector.NumberFATs*_drive._boot_sector.SectorsPerFAT +
+ _drive._boot_sector.RootEntries*sizeof(DEntry)/_drive._boot_sector.BytesPerSector; // dpb.fdirsec
+
+ for(i=0; i<_cur_bufs; i++) {
+ _secarr->s[i] = fdatsec + (DWORD)_drive._SClus*(h-2);
+
+ h = _drive.read_FAT(h, ok);
+
+ if (!ok)
+ return false;
+ }
+
+ for(i=0; i<_cur_bufs; i++) {
+ if ((ok = (_drive.read_sector(_secarr->s[i], buf, _drive._SClus))) == true)
+ AddP(buf, _drive._bufl*_drive._SClus)
+ else {
+ //@@FPara = _secarr->s[i];
+ return false;
+ }
+ }
+
+ buf->dat[0] = 0; // Endekennzeichen für Rekurs setzen
+ }
+
+ return true;
+}
+
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4355)
+#endif
+
+FATDrive::FATDrive(LPCTSTR path)
+ : FATDirectory(*this, TEXT("\\"))
+{
+ _bufl = 0;
+ _bufents = 0;
+ _SClus = 0;
+ _FATCache = NULL;
+ _CacheCount = 0;
+ _CacheSec = NULL;
+ _CacheCnt = NULL;
+ _CacheDty = NULL;
+ _Caches = 0;
+
+ _hDrive = CreateFile(path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+
+ if (_hDrive != INVALID_HANDLE_VALUE) {
+ _boot_sector.BytesPerSector = 512;
+
+ if (read_sector(0, (Buffer*)&_boot_sector, 1)) {
+ _bufl = _boot_sector.BytesPerSector;
+ _SClus = _boot_sector.SectorsPerCluster;
+ _bufents = _bufl / sizeof(union DEntry);
+ }
+
+ small_cache();
+ }
+}
+
+FATDrive::~FATDrive()
+{
+ if (_hDrive != INVALID_HANDLE_VALUE)
+ CloseHandle(_hDrive);
+
+ free(_path);
+ _path = NULL;
+}
+
+void FATDrive::small_cache()
+{
+ if (_FATCache)
+ free(_FATCache);
+
+ if (_CacheSec) {
+ free(_CacheSec), _CacheSec = NULL;
+ free(_CacheCnt);
+ free(_CacheDty);
+ }
+
+ _Caches = CACHE_SIZE_LOW;
+ _FATCache = (struct Cache *) malloc((_Caches+1) * _drive._bufl);
+
+ reset_cache();
+}
+
+void FATDrive::reset_cache() // mark cache as empty
+{
+ int i;
+
+ if (!_CacheSec) {
+ _CacheSec = (DWORD*) malloc(_Caches * sizeof(DWORD));
+ _CacheCnt = (int*) malloc(_Caches * sizeof(int));
+ _CacheDty = (bool*) malloc(_Caches * sizeof(bool));
+ } else {
+ _CacheSec = (DWORD*) realloc(_CacheSec, _Caches * sizeof(DWORD));
+ _CacheCnt = (int*) realloc(_CacheCnt, _Caches * sizeof(int));
+ _CacheDty = (bool*) realloc(_CacheDty, _Caches * sizeof(bool));
+ }
+
+ for(i=0; i<_Caches; i++)
+ _CacheSec[i] = 0;
+
+ _read_ahead = (_Caches+1) / 2;
+}
+
+bool FATDrive::read_sector(DWORD sec, Buffer* buf, int len)
+{
+ sec += 63; //@@ jump to first partition
+
+ if (SetFilePointer(_hDrive, sec*_drive._boot_sector.BytesPerSector, 0, 0) == INVALID_SET_FILE_POINTER)
+ return false;
+
+ DWORD read;
+
+ if (!ReadFile(_hDrive, buf, len*_drive._boot_sector.BytesPerSector, &read, 0))
+ return false;
+
+ return true;
+}
+
+DWORD FATDrive::read_FAT(DWORD cluster, bool& ok) //@@ use exception handling
+{
+ DWORD nClus;
+ Buffer* FATBuf;
+
+ DWORD nclus = (_boot_sector.Sectors32? _boot_sector.Sectors32: _boot_sector.Sectors16) / _boot_sector.SectorsPerCluster; ///@todo cache result
+
+ if (cluster > nclus) {
+ ok = false;
+ return (DWORD)-1;
+ }
+
+ if (nclus >= 65536) { // FAT32
+ DWORD FATsec = cluster / (_boot_sector.BytesPerSector/4);
+ DWORD z = (cluster - _boot_sector.BytesPerSector/4 * FATsec)*4;
+ FATsec += _boot_sector.ReservedSectors;
+ if (!read_cache(FATsec, &FATBuf))
+ ok = false;
+ nClus = dpeek(&FATBuf->dat[z]);
+ } else if (nclus >= 4096) { // 16 Bit-FAT
+ DWORD FATsec = cluster / (_boot_sector.BytesPerSector/2);
+ DWORD z = (cluster - _boot_sector.BytesPerSector/2 * FATsec)*2;
+ FATsec += _boot_sector.ReservedSectors;
+ if (!read_cache(FATsec, &FATBuf))
+ ok = false;
+ nClus = wpeek(&FATBuf->dat[z]);
+
+ if (nClus >= 0xfff0)
+ nClus |= 0x0fff0000;
+ } else { // 12 Bit-FAT
+ DWORD FATsec = cluster*3 / (_boot_sector.BytesPerSector*2);
+ DWORD z = (cluster*3 - _boot_sector.BytesPerSector*2*FATsec)/2;
+ FATsec += _boot_sector.ReservedSectors;
+ if (!read_cache(FATsec,&FATBuf))
+ ok = false;
+ BYTE a = FATBuf->dat[z++];
+
+ if (z >= _boot_sector.BytesPerSector)
+ if (!read_cache(FATsec+1,&FATBuf))
+ ok = false;
+ z = 0;
+
+ BYTE b = FATBuf->dat[z];
+
+ if (cluster & 1)
+ nClus = (a>>4) | (b<<4);
+ else
+ nClus = a | ((b & 0xf)<<8);
+
+ if (nClus >= 0xff0)
+ nClus |= 0x0ffff000;
+ }
+
+ return nClus;
+}
+
+bool FATDrive::read_cache(DWORD sec, Buffer** bufptr)
+{
+ int i, C, anz;
+
+ if (_boot_sector.BytesPerSector != BufLen) // no standard sector size?
+ return read_sector(sec, *bufptr=(Buffer*)&_FATCache[0], 1);
+
+ _CacheCount++;
+
+ for(i=0; _CacheSec[i]!=sec && i<_Caches; )
+ ++i;
+
+ if (i < _Caches)
+ {
+ *bufptr = (Buffer*) &_FATCache[i]; // FAT-Sektor schon gepuffert
+ _CacheCnt[i]++;
+ return true;
+ }
+
+ i = get_cache_buffer();
+
+ if (_cache_empty) // von get_cache_buffer() gesetzt
+ {
+ C = _CacheCount-1;
+ anz = _boot_sector.SectorsPerFAT*_boot_sector.NumberFATs - sec;
+
+ if (anz > _read_ahead)
+ anz = _read_ahead;
+
+ for(i=0; iread_tree(info._path, SORT_NONE);
}
+ else if (info._etype == ET_FAT)
+ {
+ _root._drive_type = DRIVE_UNKNOWN;
+
+ _tsplitpath(info._path, drv, NULL, NULL, NULL);
+ lstrcat(drv, TEXT("\\"));
+ lstrcpy(_root._volname, TEXT("FAT XXX")); //@@
+ lstrcpy(_root._fs, TEXT("FAT"));
+ lstrcpy(_root._path, drv);
+ _root._entry = new FATDrive(TEXT("c:/reactos-bochs/cdrv.img")); //TEXT("\\\\.\\F:")); //@@
+ entry = _root._entry->read_tree(info._path, SORT_NONE);
+ }
else //if (info._etype == ET_WINDOWS)
{
_root._drive_type = GetDriveType(info._path);
@@ -422,12 +442,15 @@ LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
// now create the popup menu using shell namespace and IContextMenu
Pane* pane = GetFocus()==_left_hwnd? _left: _right;
int idx = ListBox_GetCurSel(*pane);
- Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx);
+ if (idx != -1) {
+ Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx);
- ShellPath shell_path = entry->create_absolute_pidl();
- LPCITEMIDLIST pidl = shell_path;
+ ShellPath shell_path = entry->create_absolute_pidl();
+ LPCITEMIDLIST pidl = shell_path;
- CHECKERROR(ShellFolderContextMenu(Desktop(), _hwnd, 1, &pidl, pos.x, pos.y));
+ ///@todo use parent folder instead of desktop -> correct "Properties" dialog, ...
+ CHECKERROR(ShellFolderContextMenu(Desktop(), _hwnd, 1, &pidl, pos.x, pos.y));
+ }
break;}
default: def:
diff --git a/reactos/subsys/system/explorer/shell/filechild.h b/reactos/subsys/system/explorer/shell/filechild.h
index 1b50eaa480b..9375a2340a9 100644
--- a/reactos/subsys/system/explorer/shell/filechild.h
+++ b/reactos/subsys/system/explorer/shell/filechild.h
@@ -59,6 +59,12 @@ struct RegistryChildWndInfo : public FileChildWndInfo
RegistryChildWndInfo(LPCTSTR path);
};
+ /// information structure for creation of FileChildWindow for the Registry
+struct FATChildWndInfo : public FileChildWndInfo
+{
+ FATChildWndInfo(LPCTSTR path);
+};
+
/// MDI child window displaying file lists
struct FileChildWindow : public ChildWindow
diff --git a/reactos/subsys/system/explorer/shell/mainframe.cpp b/reactos/subsys/system/explorer/shell/mainframe.cpp
index 2954e58bfcd..2a99eb5cb01 100644
--- a/reactos/subsys/system/explorer/shell/mainframe.cpp
+++ b/reactos/subsys/system/explorer/shell/mainframe.cpp
@@ -129,6 +129,13 @@ MainFrame::MainFrame(HWND hwnd)
drivebarBtn.idCommand = ID_DRIVE_REGISTRY;
SendMessage(_hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
+ ++drivebarBtn.iString;
+
+ // insert FAT direct file system access button
+ SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)TEXT("FAT\0"));
+
+ drivebarBtn.idCommand = ID_DRIVE_FAT;
+ SendMessage(_hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
++drivebarBtn.iString;
// register windows drive root strings
@@ -551,6 +558,20 @@ int MainFrame::Command(int id, int code)
#endif
break;}
+ case ID_DRIVE_FAT: {
+
+ ///@todo prompt for image file
+
+ if (activate_child_window(TEXT("FAT")))
+ break;
+
+#ifndef _NO_MDI
+ FileChildWindow::create(_hmdiclient, FATChildWndInfo(TEXT("FAT Image"))); //@@
+#else
+ ///@todo SDI implementation
+#endif
+ break;}
+
case ID_DRIVE_DESKTOP: {
TCHAR path[MAX_PATH];
diff --git a/reactos/subsys/system/explorer/shell/ntobjfs.cpp b/reactos/subsys/system/explorer/shell/ntobjfs.cpp
index 4bc41a09650..5b8336cc54e 100644
--- a/reactos/subsys/system/explorer/shell/ntobjfs.cpp
+++ b/reactos/subsys/system/explorer/shell/ntobjfs.cpp
@@ -329,9 +329,6 @@ void NtObjDirectory::read_directory(int scan_flags)
if (last)
last->_next = entry;
- entry->_down = NULL;
- entry->_expanded = false;
- entry->_scanned = false;
entry->_level = level;
last = entry;
diff --git a/reactos/subsys/system/explorer/shell/pane.cpp b/reactos/subsys/system/explorer/shell/pane.cpp
index 6ccc7f660c5..68704d086f2 100644
--- a/reactos/subsys/system/explorer/shell/pane.cpp
+++ b/reactos/subsys/system/explorer/shell/pane.cpp
@@ -69,7 +69,7 @@ static const int g_pos_align[] = {
HDF_LEFT, /* ADate */
HDF_LEFT, /* MDate */
HDF_LEFT, /* Index */
- HDF_CENTER, /* Links */
+ HDF_RIGHT, /* Links */
HDF_CENTER, /* Attributes */
HDF_LEFT, /* Security */
HDF_LEFT /* Content / Description */
@@ -484,7 +484,6 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
_out_wrkr.output_text(dis, _positions, col, entry->_display_name, 0);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, entry->_display_name);
-
++col;
// output type/class name
@@ -494,7 +493,6 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, entry->_type_name);
}
-
++col;
// display file size
@@ -507,9 +505,8 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
_out_wrkr.output_number(dis, _positions, col, buffer);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer); ///@todo not in every case time enough
-
- ++col;
}
+ ++col;
// display file date
if (visible_cols & (COL_DATE|COL_TIME)) {
@@ -533,7 +530,8 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer);
++col;
- }
+ } else
+ col += 3;
if (entry->_bhfi_valid) {
ULONGLONG index = ((ULONGLONG)entry->_bhfi.nFileIndexHigh << 32) | entry->_bhfi.nFileIndexLow;
@@ -550,7 +548,7 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
if (visible_cols & COL_LINKS) {
wsprintf(buffer, TEXT("%d"), entry->_bhfi.nNumberOfLinks);
if (calcWidthCol == -1)
- _out_wrkr.output_text(dis, _positions, col, buffer, DT_CENTER);
+ _out_wrkr.output_text(dis, _positions, col, buffer, DT_RIGHT);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer);
++col;
@@ -584,9 +582,8 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
_out_wrkr.output_tabbed_text(dis, _positions, col, buffer);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_tabbed_width(dis, col, buffer);
-
- ++col;
}
+ ++col;
/*TODO
if (flags.security) {
@@ -615,10 +612,9 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
output_text(dis, col++, buffer, 0, psize);
}
*/
-
++col;
- // output content / symbolic link target
+ // output content / symbolic link target / comment
if (visible_cols & COL_CONTENT) {
if (calcWidthCol == -1)
_out_wrkr.output_text(dis, _positions, col, entry->_content, 0);
diff --git a/reactos/subsys/system/explorer/shell/regfs.cpp b/reactos/subsys/system/explorer/shell/regfs.cpp
index a9eb9fbbf47..aa09ab2788d 100644
--- a/reactos/subsys/system/explorer/shell/regfs.cpp
+++ b/reactos/subsys/system/explorer/shell/regfs.cpp
@@ -43,13 +43,13 @@ void RegDirectory::read_directory(int scan_flags)
TCHAR buffer[MAX_PATH];
_tcscpy(buffer, (LPCTSTR)_path);
- LPTSTR p = buffer + _tcslen(buffer);
+ LPTSTR pname = buffer + _tcslen(buffer);
HKEY hKey;
if (!RegOpenKeyEx(_hKeyRoot, *buffer=='\\'?buffer+1:buffer, 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &hKey)) {
- if (p[-1] != '\\')
- *p++ = '\\';
+ if (pname[-1] != '\\')
+ *pname++ = '\\';
TCHAR name[MAX_PATH], class_name[MAX_PATH];
WIN32_FIND_DATA w32fd;
@@ -68,7 +68,7 @@ void RegDirectory::read_directory(int scan_flags)
w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
lstrcpy(w32fd.cFileName, name);
- _tcscpy(p, name);
+ _tcscpy(pname, name);
entry = new RegDirectory(this, buffer, _hKeyRoot);
memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
@@ -82,9 +82,6 @@ void RegDirectory::read_directory(int scan_flags)
if (last)
last->_next = entry;
- entry->_down = NULL;
- entry->_expanded = false;
- entry->_scanned = false;
entry->_level = level;
last = entry;
@@ -110,9 +107,6 @@ void RegDirectory::read_directory(int scan_flags)
if (last)
last->_next = entry;
- entry->_down = NULL;
- entry->_expanded = false;
- entry->_scanned = false;
entry->_level = level;
last = entry;
@@ -171,9 +165,6 @@ void RegDirectory::read_directory(int scan_flags)
if (last)
last->_next = entry;
- entry->_down = NULL;
- entry->_expanded = false;
- entry->_scanned = false;
entry->_level = level;
last = entry;
diff --git a/reactos/subsys/system/explorer/shell/shellbrowser.cpp b/reactos/subsys/system/explorer/shell/shellbrowser.cpp
index 2465d915ec4..2ae6f4e2863 100644
--- a/reactos/subsys/system/explorer/shell/shellbrowser.cpp
+++ b/reactos/subsys/system/explorer/shell/shellbrowser.cpp
@@ -217,6 +217,12 @@ void ShellBrowserChild::Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPO
LPCITEMIDLIST pidl = static_cast(entry)->_pidl;
CHECKERROR(ShellFolderContextMenu(folder, ::GetParent(hwndTreeView), 1, &pidl, pptScreen->x, pptScreen->y));
+ } else {
+ ShellPath shell_path = entry->create_absolute_pidl();
+ LPCITEMIDLIST pidl = shell_path;
+
+ ///@todo use parent folder instead of desktop
+ CHECKERROR(ShellFolderContextMenu(Desktop(), _hwnd, 1, &pidl, pptScreen->x, pptScreen->y));
}
}
}
diff --git a/reactos/subsys/system/explorer/shell/shellfs.cpp b/reactos/subsys/system/explorer/shell/shellfs.cpp
index 719d2da38f4..f3c6c943a36 100644
--- a/reactos/subsys/system/explorer/shell/shellfs.cpp
+++ b/reactos/subsys/system/explorer/shell/shellfs.cpp
@@ -261,11 +261,7 @@ void ShellDirectory::read_directory(int scan_flags)
memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
- entry->_down = NULL;
- entry->_expanded = false;
- entry->_scanned = false;
entry->_level = level;
- entry->_bhfi_valid = false;
if (scan_flags & SCAN_DO_ACCESS) {
HANDLE hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
@@ -400,9 +396,6 @@ void ShellDirectory::read_directory(int scan_flags)
if (attribs & SFGAO_LINK)
w32fd.dwFileAttributes |= ATTRIBUTE_SYMBOLIC_LINK;
- entry->_down = NULL;
- entry->_expanded = false;
- entry->_scanned = false;
entry->_level = level;
entry->_shell_attribs = attribs;
entry->_bhfi_valid = bhfi_valid;
diff --git a/reactos/subsys/system/explorer/shell/unixfs.cpp b/reactos/subsys/system/explorer/shell/unixfs.cpp
index a8e9a65e560..ee3b47c1a79 100644
--- a/reactos/subsys/system/explorer/shell/unixfs.cpp
+++ b/reactos/subsys/system/explorer/shell/unixfs.cpp
@@ -104,7 +104,6 @@ void UnixDirectory::read_directory()
entry->_bhfi_valid = FALSE;
}
- entry->_down = NULL;
entry->_up = this;
entry->_expanded = FALSE;
entry->_scanned = FALSE;
diff --git a/reactos/subsys/system/explorer/shell/winfs.cpp b/reactos/subsys/system/explorer/shell/winfs.cpp
index 4737fccb614..7a13156fa64 100644
--- a/reactos/subsys/system/explorer/shell/winfs.cpp
+++ b/reactos/subsys/system/explorer/shell/winfs.cpp
@@ -130,18 +130,18 @@ void WinDirectory::read_directory(int scan_flags)
Entry* entry;
LPCTSTR path = (LPCTSTR)_path;
- TCHAR buffer[MAX_PATH], *p;
- for(p=buffer; *path; )
- *p++ = *path++;
+ TCHAR buffer[MAX_PATH], *pname;
+ for(pname=buffer; *path; )
+ *pname++ = *path++;
- lstrcpy(p, TEXT("\\*"));
+ lstrcpy(pname, TEXT("\\*"));
WIN32_FIND_DATA w32fd;
HANDLE hFind = FindFirstFile(buffer, &w32fd);
if (hFind != INVALID_HANDLE_VALUE) {
do {
- lstrcpy(p+1, w32fd.cFileName);
+ lstrcpy(pname+1, w32fd.cFileName);
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
entry = new WinDirectory(this, buffer);
@@ -155,9 +155,6 @@ void WinDirectory::read_directory(int scan_flags)
last->_next = entry;
memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
- entry->_down = NULL;
- entry->_expanded = false;
- entry->_scanned = false;
entry->_level = level;
// display file type names, but don't hide file extensions
diff --git a/reactos/subsys/system/explorer/utility/utility.cpp b/reactos/subsys/system/explorer/utility/utility.cpp
index f1ef438a9ad..453de9825bc 100644
--- a/reactos/subsys/system/explorer/utility/utility.cpp
+++ b/reactos/subsys/system/explorer/utility/utility.cpp
@@ -165,11 +165,12 @@ BOOL time_to_filetime(const time_t* t, FILETIME* ftime)
stime.wYear = tm->tm_year+1900;
stime.wMonth = tm->tm_mon+1;
- /* stime.wDayOfWeek */
+ stime.wDayOfWeek = (WORD)-1;
stime.wDay = tm->tm_mday;
stime.wHour = tm->tm_hour;
stime.wMinute = tm->tm_min;
stime.wSecond = tm->tm_sec;
+ stime.wMilliseconds = 0;
return SystemTimeToFileTime(&stime, ftime);
}