reading of FAT image files (work in progress)

svn path=/trunk/; revision=8005
This commit is contained in:
Martin Fuchs 2004-02-02 23:18:07 +00:00
parent 2f3d748c1d
commit 51612d040b
23 changed files with 1019 additions and 52 deletions

View file

@ -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

View file

@ -82,6 +82,7 @@ OBJECTS = \
shellfs.o \
ntobjfs.o \
regfs.o \
fatfs.o \
mainframe.o \
filechild.o \
pane.o \

View file

@ -56,6 +56,7 @@ OBJECTS = \
shellfs.o \
ntobjfs.o \
regfs.o \
fatfs.o \
mainframe.o \
filechild.o \
pane.o \

View file

@ -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 \

View file

@ -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

View file

@ -3,7 +3,7 @@
<tr>
<td><address style="align: right;"><small>
ROS Explorer Source Code Documentation
<br>generated on 01.02.2004 by <a href="http://www.doxygen.org/index.html">
<br>generated on 03.02.2004 by <a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0>
</small></address>
</td>

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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; i<anz; i++) {
_CacheSec[i] = sec++;
_CacheCnt[i] = C;
_CacheDty[i] = 0;
}
_CacheCnt[0] = _CacheCount;
return read_sector(_CacheSec[0], *bufptr=(Buffer*) &_FATCache[0], anz);
}
else
{
_CacheDty[i] = 0;
_CacheCnt[i] = _CacheCount;
return read_sector(_CacheSec[i]=sec, *bufptr=(Buffer*) &_FATCache[i], 1);
}
}
int FATDrive::get_cache_buffer() // search for free cache buffer
{
int i, j, minCnt;
for(i=0; i<_Caches; i++)
if (_CacheSec[i])
break;
_cache_empty = i==_Caches? true: false;
for(i=0; _CacheSec[i] && i<_Caches; )
++i;
if (i < _Caches)
j = i;
else
{
minCnt = 0; // search for least used buffer
for(j=i=0; i<_Caches; i++)
if (minCnt < _CacheCnt[i]) {
minCnt = _CacheCnt[i];
j = i;
}
/**@todo enable write back
if (CacheDty[j]) // Dirty-Flag gesetzt?
if (writesec(_CacheSec[j], (Buffer*) &_FATCache[j], 1))
FPara = _CacheSec[j], Frag(SecWriteErr);
*/
}
return j;
}

View file

@ -0,0 +1,258 @@
/*
* 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.h
//
// Martin Fuchs, 01.02.2004
//
/// FAT file system file-entry
struct FATEntry : public Entry
{
FATEntry(Entry* parent, unsigned cluster) : Entry(parent, ET_FAT), _cluster(cluster) {}
protected:
FATEntry() : Entry(ET_FAT) {}
virtual bool get_path(PTSTR path) const;
DWORD _cluster;
};
struct FATDrive;
/// FAT file system directory-entry
struct FATDirectory : public FATEntry, public Directory
{
FATDirectory(FATDrive& drive, LPCTSTR root_path);
FATDirectory(FATDrive& drive, Entry* parent, LPCTSTR path, unsigned cluster);
~FATDirectory();
virtual void read_directory(int scan_flags=SCAN_ALL);
virtual Entry* find_entry(const void*);
protected:
FATDrive& _drive;
struct dirsecz* _secarr;
int _cur_bufs;
int _ents;
struct dirent* _dir;
struct Kette* _alloc;
bool read_dir();
};
#pragma pack(push, 1)
struct BootSector {
BYTE jmp[3];
char OEM[8];
WORD BytesPerSector; // dpb.bsec
BYTE SectorsPerCluster; // dpb.sclus + 1
WORD ReservedSectors; // dpb.ffatsec
BYTE NumberFATs;
WORD RootEntries; // dpb.ndir
WORD Sectors16;
BYTE MediaDescr;
WORD SectorsPerFAT;
WORD SectorsPerTrack;
WORD Heads;
DWORD HiddenSectors;
DWORD Sectors32;
BYTE DriveUnit;
WORD ExtBootFlag;
DWORD SerialNr;
char Label[11];
char FileSystem[8];
BYTE BootCode[448];
BYTE BootSignature[2];
};
struct BootSector32 {
BYTE jmp[3];
char OEM[8];
WORD BytesPerSector;
BYTE SectorsPerCluster;
WORD ReservedSectors;
BYTE NumberFATs;
WORD reserved1; // immer 0 für FAT32
WORD Sectors16;
BYTE MediaDescr;
WORD reserved2; // immer 0 für FAT32
WORD SectorsPerTrack;
WORD Heads;
DWORD HiddenSectors;
DWORD Sectors32;
DWORD SectorsPerFAT32;
DWORD unknown1;
DWORD RootSectors; // correct?
char unknown2[6];
char FileSystem[8];
BYTE BootCode[448];
BYTE BootSignature[2];
};
struct ftime {
WORD sec2 : 5;
WORD min : 6;
WORD hour : 5;
};
struct fdate {
WORD day : 5;
WORD month : 4;
WORD year : 7;
};
typedef struct {
unsigned readonly : 1;
unsigned hidden : 1;
unsigned system : 1;
unsigned volume : 1;
unsigned directory : 1;
unsigned archived : 1;
unsigned deleted : 1;
} fattr;
typedef union {
char b;
fattr a;
} FAT_attribute;
struct DEntry_E {
char name[8];
char ext[3];
char attr;
char rsrvd[10];
struct ftime time;
struct fdate date;
WORD fclus;
DWORD size;
};
union DEntry {
DEntry_E E;
BYTE B[8+3+1+10+sizeof(struct ftime)+sizeof(struct fdate)+sizeof(WORD)+sizeof(DWORD)];
};
#pragma pack(pop)
#define BufLen 512
struct Buffer {
BYTE dat[BufLen];
};
struct Cache {
BYTE dat[BufLen];
};
struct dskrwblk {
DWORD sec;
WORD anz;
struct buffer far *buf;
};
#define RONLY 0x01
#define HIDDEN 0x02
#define SYSTEM 0x04
#define VOLUME 0x08
#define DIRENT 0x10
#define ARCHIVE 0x20
#define _A_DELETED 0x40
#define _A_ILLEGAL 0x80
#define IS_LNAME(a) ((a&0xFF)==0x0F) // "& 0xFF" correct?
#define FAT_DEL_CHAR (char)0xe5
#define AddP(p,s) {(int&)p += s;}
struct dirent {
union DEntry ent[1];
};
struct dirsecz {
DWORD s[32]; // 32 only as placeholder
};
struct Kette {
struct Kette* Vorw;
struct Kette* Rueck;
union DEntry* Ent;
};
#define MK_P(ofs) ((void*) ((size_t)(ofs)))
#define MK_LONG(l,h) ((DWORD)WORD(l)|((DWORD)WORD(h)<<16))
#define spoke(ofs,w) (*((BYTE*)MK_P(ofs)) = (BYTE)(w))
#define wpoke(ofs,w) (*((WORD*)MK_P(ofs)) = (WORD)(w))
#define dpoke(ofs,w) (*((DWORD*)MK_P(ofs)) = (DWORD)(w))
#define speek(ofs) (*((BYTE*)MK_P(ofs)))
#define wpeek(ofs) (*((WORD*)MK_P(ofs)))
#define dpeek(p) (*((DWORD*)MK_P(p)))
/// FAT drive root entry
struct FATDrive : public FATDirectory
{
FATDrive(LPCTSTR path);
/*
FATDrive(Entry* parent, LPCTSTR path)
: FATEntry(parent)
{
_path = _tcsdup(path);
}
*/
~FATDrive();
HANDLE _hDrive;
BootSector _boot_sector;
int _bufl;
int _bufents;
int _SClus;
#define CACHE_SIZE_LOW 32
Cache* _FATCache;
int _CacheCount;
DWORD* _CacheSec; // numbers of buffered cache sectors
int* _CacheCnt; // counters for cache usage
bool* _CacheDty; // dirty flags for cache
int _Caches;
bool _cache_empty;
int _read_ahead;
bool read_sector(DWORD sec, Buffer* buf, int len);
DWORD read_FAT(DWORD Clus, bool& ok);
void small_cache();
void reset_cache();
bool read_cache(DWORD sec, Buffer** bufptr);
int get_cache_buffer();
};

View file

@ -32,6 +32,7 @@
#include "../globals.h"
#include "ntobjfs.h"
#include "regfs.h"
#include "fatfs.h"
#include "../explorer_intres.h"
@ -82,6 +83,13 @@ RegistryChildWndInfo::RegistryChildWndInfo(LPCTSTR path)
}
FATChildWndInfo::FATChildWndInfo(LPCTSTR path)
: FileChildWndInfo(path)
{
_etype = ET_FAT;
}
FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
: ChildWindow(hwnd)
{
@ -143,6 +151,18 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
_root._entry = new RegistryRoot();
entry = _root._entry->read_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:

View file

@ -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

View file

@ -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];

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -217,6 +217,12 @@ void ShellBrowserChild::Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPO
LPCITEMIDLIST pidl = static_cast<ShellEntry*>(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));
}
}
}

View file

@ -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;

View file

@ -104,7 +104,6 @@ void UnixDirectory::read_directory()
entry->_bhfi_valid = FALSE;
}
entry->_down = NULL;
entry->_up = this;
entry->_expanded = FALSE;
entry->_scanned = FALSE;

View file

@ -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

View file

@ -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);
}