Зсув
|
Розмір, байт
|
Опис
|
Ім’я
|
0
|
1
|
Номер порції імені
|
fn
|
1
|
10
|
5 символів імені об’єкту
|
FiveSymb
|
11
|
1
|
Байт атрибутів, дорівнює 0Fh
|
attr
|
12
|
1
|
Завжди дорівнює 0
|
reserv
|
13
|
1
|
Контрольна сума короткого ім’я
|
CRC
|
14
|
12
|
6 символів імені об’єкту
|
SixSymb
|
26
|
2
|
Резерв
|
reserv2
|
28
|
4
|
2 символа імені об’єкту
|
TwoSymb
|
Ім’я в останній порції довгого імені може бути меншим за 13 символів. У
такому випадку значима частина імені завершується нулем. усі інші поля імені
заповнюються FFFF.
2.4
Програмні структури
Всі необхідні програмні структури представлені в header-
файлах. Ціль їхнього створення - організація даних, прочитаних з носіїв.
Наприклад, кожний жорсткий диск буде представлений структурою
typedef struct _HARDINFO
{
char nHard; //номер
жорсткого диску
void* hDrive; //хендл жорсткого диску
UINT dwSectorSize; //розмір сектора
UINT bitsPerSector; //кількість розрядів для адресації всередині сектора
UINT dwExtendedAddr; //адреса розширеного
розділу
PLOGICAL_DISC disklist;
}
HARDINFO, *PHARDINFO;
Інформація
про розділи організується в список структур, по одному списку на кожний
жорсткий диск:
typedef struct _LOGICAL_DISC
{
void* next;
char nHard;
char nDisc;
char active;
UINT abs_addr;
UINT secLength;
UINT id;
char* cpFS;
UINT SN4;
UINT gbLength;
UINT mbLength;
void* disc_info;
UINT
prcfree;
} LOGICAL_DISC, *PLOGICAL_DISC, **PPLOGICAL_DISC;
Після
того, як FAT32-розділ був відкритий для читання, інформація про
нього записується в таку структуру
typedef struct _DISC_INFO {
char Disc; //логічний диск
UINT beginFAT; //адреса
початку FAT-таблиці у секторах
UINT nBytePerSector; //розмір сектора у
байтах
void* hDrive; //хендл відкритого розділу
char SectPerCluster; //розмір
кластера в секторах
UINT BytesPerCluster; //розмір кластера в байтах
UINT sizeFAT; //розмір FAT-таблиці
в секторах
UINT*
pFAT; //адреса образу FAT-таблиці у ОЗУ
UINT
sizeFATbytes; //розмір FAT-таблиці в байтах
USHORT
nFATCopy; //кількість копій FAT
USHORT
sizeReserved; //розмір зарезервованої області в секторах
UINT
bitsPerSector; //кількість розрядів для адресації всередині сектора
UINT
RootCluster; //номер першого
кластера корневой директории
UINT
dwRootDirSize; //кількість
кластерів для кореневої директорії
HDIR
hRootDir; //хендл кореневої
директориії
UINT prcfree;
BOOL bFAT16;
UINT RootSector;
UINT nRootElements;
}
DISC_INFO, *PDISC_INFO;
Список
прочитаних файлів організується в структуру:
typedef struct _FILES {
char* ansiname;
UINT attrib;
UINT firstcluster;
__int64 filesize;
void* next;
} FILES, *PFILES;
Якщо необхідно вивести на екран уміст файлу, спочатку його вміст буде відображено в таку структуру:
typedef struct _FILEBUF {
char* pBuf;
char* ansiname;
UINT dwLen;
} FILEBUF, *PFILEBUF;
3 ОПИС АЛГОРИТМІВ ПЗ ФМ
У цьому пункті розглядаються послідовно алгоритми пошуку та іменування
дисків, доступу до об’єктів файлової системи, визначення зайнятого місця для
файлової системи FAT32, FAT16.
3.1 Алгоритм пошуку дисків й іменування дисків
Алгоритм іменування логічних дисків засновано на звіренні серійного
номера, отриманого логічного диска із серійним номером, збереженим системою.
Рисунок
3.1 – Пошук та найменування дисків
3.2 Алгоритм доступу к об’єктам файлової системи
Основна концепція файлової системи FAT полягає в тім, що кожному файлу й
каталогу виділяється структура даних, називана дескриптором. У цій структурі
зберігається ім'я файлу, його розмір, початкова адреса вмісту файлу й інші
метадані. Данні файлів і каталогів зберігається в блоках даних, називаних
кластерами. Якщо файлу або каталогу виділяється більш одного кластера, інші
кластери знаходять за допомогою структури даних, називаної FAT(File Allocation
Table). Структура FAT використовується як для ідентифікації наступних кластерів
у файлах, так і для визначення стану кластерів. Існує три версії FAT: FAT12,
FAT16 і FAT32. Вони відрізняються друг від друга насамперед розміром запису у
структурі FAT. Зв'язки між структурами даних показано на рис.
3.4.
Рисунок 3.4 – Зв’язки між структурами даних
Файлова система FAT ділиться на три фізичні області для FAT32, та на чотири для FAT12/16.
Перша область називається
зарезервованою; в FAT12 і FAT16 зарезервована область займає всього 1 сектор,
але формально її розмір визначається в завантажувальному секторі. Друга область
FAT - містить основні й резервні структури FAT. Вона починається в секторі,
котрий розташовано за зарезервованою областю, а її розмір визначається
кількістю й розміром структур FAT. Третя – кореневий каталог, для FAT12/16
починається за областю FAT, а у FAT32 має
повільне положення у області даних. Область даних - містить кластери, виділені
для зберігання файлів і вмісту каталогів.
Доступ до файлових об’єктів виконується з припущення, що відома адреса
першого кластеру об’єкту.
У даній реалізації алгоритм доступу до об’єктів містить дві частини –
алгоритм пошуку шляху до поточної директорії та алгоритм пошуку об’єктів у
завантаженій директорії.
Алгоритм
пошуку об’єктів в каталогі наведено на рис. 3.2
Алгоритм
пошуку поточного шляху - рис.3.3
Рисунок 3.2 – Алгоритм пошуку об’єктів
в каталогі
Рисунок 3.3 – Алгоритм пошуку
поточного шляху
3.3 Алгоритм визначення зайнятого місця на розділі
Визначення зайнятого місця на розділі реалізується шляхом аналізу таблиці
FAT. Виконується перевірка усіх елементів таблиці FAT. Рахується кількість елементів, що містять 0. Ці елементи в файловій системі
ідентифікують незайняте місце.
Отже, після повного перегляду FAT таблиці відома
кількість елементів FAT таблиці та кількість елементів незайнятого
місця. Знаходиться відсоткове співвідношення. Через нього обчислюється зайняте
місце в байтах.
Алгоритм визначення на рис. 3.4.
Рисунок 3.4 – Алгоритм визначення зайнятого місця
3.4 Алгоритм зрівняння директорій
Рисунок 3.5 – Алгоритм зрівняння директорій
4 ОПИС
ПРОГРАМНИХ МОДУЛІВ
Точка входу знаходиться у модулі з назвою manager.cpp. Після автоматичної ініціалізації графічного інтерфейсу (все це
відбувається за рахунок VCL), виконується пошук і іменування всіх
логічних дисків. Код, відповідальний за це, знаходиться в модулі mbrmodule.cpp. Далі, якщо знайдено завантажувальний розділ
і, якщо файлова система на ньому є однією з підтримуваних, виконується пошук
усіх файлів у кореневому каталозі. Якщо файлова система розділу - FAT або FAT32 то
робиться це за допомогою модуля fat32.cpp. Якщо файлова система – NTFS, то пошук виконується невеликими функціями,
описаними, безпосередньо, у головному модулі (manager.cpp, на таку структуру вже наголошувалося раніше). Інші файлові системи не
підтримуються.
Короткий опис ключових функцій:
PHARDINFO Init(char n);
Функція виконує всі попередні дії, необхідні для подальшої роботи з
жорстким диском(виклик CreateFіle(), визначення розміру сектора й т.д.). У
випадку невдачі повертає NULL.
BOOL WalkOnMBR(PHARDINFO inf, PPLOGICAL_DISC first);
Функція проходить по ланцюжку MBR жорсткого диска, попередньо відкритого
функцією Іnіt
void DeInit(PHARDINFO inf);
Звільняє зайняту структурами пам'ять і закриває дескриптор жорсткого
диска
PDISC_INFO Fat32Init(char disc);
Виконує всі необхідні попередні дії для роботи з логічним диском, файлова
система котрого FAT або FAT32 (зчитування таблиці FAT, визначення кластера
кореневого каталогу та ін.)
UINT GotoDir(PDISC_INFO info, char* cpPath);
Повертає номер кластера виходячи зі шляху до директорії
UINT ListDirectory(PDISC_INFO info, HDIR hDir,UINT dwDirSize,char*
cpObjectName, PFILES* ppfiles);
Виконує побудова списку файлів у директорії або пошук елемента каталогу в
ній.
PFILES PrintRootDirectory(PDISC_INFO info);
Пошук всіх файлів у кореневому каталозі
HDIR LoadDirectory(PDISC_INFO info, UINT cluster, UINT* dirsize);
Завантажує вміст зазначеного ланцюжка кластерів на згадку
char* Fat32ReadFile(PDISC_INFO info, UINT FirstCluster, UINT*
dwFileSize);
Читає вміст файлу, перший кластер котрого відомий
void Fat32DeInit(PDISC_INFO info);
Звільняє зайняту пам'ять і закриває дескриптори.
void AnalyzeError(char* comment, int iErr);
Виконує аналіз помилки, що відбулася, результати виводить в MessageBox головного вікна
void createFolder(PDISC_INFO info,AnsiString
newDirName)
Виконує додаткове завдання КП. Створення директорії в FAT16/32. Приймає у якості параметрів структуру
інформації про поточний розділ та назву нової директорії. Функція отримує інші
необхідні дані та інтерфейс до роботи з раніше створених функцій та глобальних
змінних (ознака кореневої директорії, поточний шлях, тип ФС та ін.).
5 МЕТОДИКИ РОБОТИ
Для навігації серед елементів каталогу та серед списку логічних дисків
використовуються дії миші. Для порівняння директорії – окрема кнопка «Сравнение папок». Для вибору поточного диску – випадаючий список з усіма літерами
наявних дисків.
Після натискання на кнопку порівняння директорій, замість данних про
поточний логічний диск, з’являється
інформація щодо відкритих директорій в панелях менеджеру..
При зміні поточного диску відбувається оновлення інформації про диск у
правій частині вікна, та якщо зміна диска була у правому вікні, то й там є
відновлення. та оновлюється гістограма зайнятого/вільного простору.
6
ДОСЛІДЖЕННЯ РЕЗУЛЬТАТІВ
Відразу після запуску формується інтерфейс користувача й виводиться вміст
кореневого каталогу активного розділу. Виводиться наступна інформація про
файли: ім'я файлу, розмір, атрибути.
Також у праві1 частині вікна виводиться деяка інформація про логічний
диск.
На гістограмі відображено співвідношення зайнятого й вільного простору
логічного диску (рис. 6.1).
Рисунок
6.1 – Список файлів активного каталогу.
Перехід в іншу директорію здійснюється за допомогою мишки (подвійне
натискання) або ж натисканням клавіші ENTER (перед цим потрібна директорія
повинна бути виділена, цього можна домогтися нажатим клавіш "Нагору"
або "Униз" або ж одинарним натисканням лівої клавіші миші, рис.6.2).
Рисунок
6.2 – Список файлів в некореневому каталогі.
Зрівняння ми побачимо, нажавши кнопку «Сравнение папок». Праворуч від
панелей буде кількісна інформація щодо кожної панелі. (рис. 6.4).
Рисунок 6.4 – відображення вмісту кількісного зрівняння папок.
ВИСНОВОК
У
ході виконання курсового проекту
була створена програма для ОС Windows. Також були покращені навички роботи з
накопичувачем на жорсткому магнітному диску. Був розібраний низький рівень
існування інформації на жорсткому диску.
Так як основна увага приділялася роботі з ФС FAT,
були здобуті вичерпні знання про структуру цієї ФС та навички роботи з нею на
низькому рівні.
ДОДАТОК А.
ВИХІДНІ ТЕКCТИ ПРОГРАМИ
MANAGER.CPP
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "manager.h"
#include <string.h>
#include <vector>
#include <math.h>
#include "mbrmodule.h"
#include "fat32.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CGAUGES"
#pragma resource "*.dfm"
PHARDINFO hdd[256];
PFILES files, files2;
PLOGICAL_DISC currpld, currpld2;
char DisplayName[]="#Commander from Hell#";
char path[65536],
path2[65536], pat[256], pat2[256], nulpat[256];
//pat,pat2 переменные для копирования имени которое будет
удалятся из пути
HANDLE hlistbox,hwnd,hComboBox;
UINT iSelected, iSelected2;
PFILES mfile;
char buf[64];
char pathcpy[1024];
PLOGICAL_DISC pld;
PFILEBUF pfb;
int fil1, fil2, dir1, dir2; // счетчики файлов и папок
int fl=0;
void AnalyzeError(char* comment, int iErr)
{
char locBuf[1024];
char s[1024];
int len;
len = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
0, iErr, 0, locBuf, sizeof(locBuf), 0
);
if(len>=2)
if(locBuf[len-2]==0x0D)locBuf[len-2]=0;
wsprintf(s,"%s (%u)
%s",comment?comment:"", iErr, locBuf);
MessageBox(hwnd,s,DisplayName,MB_OK);
}
/*******************************************************************************
*
Очистка списка файлов, необходима перед началом работы со списком. *
*
Если забыть про очистку, то файлы на экране не очистятся, а новые добавятся *
* в конец *
******************************************************************************
*/
void FreeFilesList()
{
PFILES pfiles, ppred;
fil1=0;
dir1=0;
pfiles = files;
while(pfiles)
{
free(pfiles->ansiname);
ppred = pfiles;
pfiles =(_FILES*) pfiles->next;
free(ppred);
}
files = NULL;
}
void FreeFilesList2()
{
PFILES pfiles, ppred;
fil2=0;
dir2=0;
pfiles = files2;
while(pfiles)
{
free(pfiles->ansiname);
ppred = pfiles;
pfiles =(_FILES*) pfiles->next;
free(ppred);
files2
= NULL;
}
/*******************************************************************************
*
Конкретная функция для чтения директории в NTFS-томе *
*******************************************************************************
*/
int NTFSReadDir(PLOGICAL_DISC pld, char* pPath)
{
char pFullPath[1024];
HANDLE hFind;
WIN32_FIND_DATA fd;
PFILES pfirst = NULL, pfiles, ppred = NULL;
if(!pld)return 0;
pFullPath[0] = pld->nDisc;
pFullPath[1] = ':';
pFullPath[2] = '\\';
pFullPath[3] = 0;
if(pPath && pPath[0]!=0)wsprintf(pFullPath+3,pPath);
strcat(pFullPath,"*");
if((hFind =
FindFirstFile(pFullPath,&fd))==INVALID_HANDLE_VALUE)return
0;
if(files)FreeFilesList();
while(1)
{
pfiles =(_FILES*)
malloc(sizeof(FILES));
if(!pfirst)pfirst = pfiles;
pfiles->attrib =
fd.dwFileAttributes;
pfiles->filesize =
fd.nFileSizeLow;
pfiles->ansiname =(char*)
malloc(strlen((const char*)&fd.cFileName)+1);
if(ppred)ppred->next = pfiles;
wsprintf(pfiles->ansiname,(const
char*)&fd.cFileName);
ppred = pfiles;
if(!FindNextFile(hFind, &fd))
if(GetLastError() ==
ERROR_NO_MORE_FILES)
break;
}
pfiles->next = NULL;
FindClose(hFind);
files = pfirst;
Form1->APrintFileListExecute(0);
return 1;
}
int NTFSReadDir2(PLOGICAL_DISC pld, char* pPath)
{
char pFullPath[1024];
HANDLE hFind;
WIN32_FIND_DATA fd;
PFILES pfirst = NULL, pfiles, ppred = NULL;
if(!pld)return 0;
pFullPath[0] = pld->nDisc;
pFullPath[1] = ':';
pFullPath[2] = '\\';
pFullPath[3] = 0;
if(pPath &&
pPath[0]!=0)wsprintf(pFullPath+3,pPath);
strcat(pFullPath,"*");
if((hFind =
FindFirstFile(pFullPath,&fd))==INVALID_HANDLE_VALUE)return
0;
if(files2)FreeFilesList2();
while(1)
{
pfiles =(_FILES*)
malloc(sizeof(FILES));
if(!pfirst)pfirst = pfiles;
pfiles->attrib =
fd.dwFileAttributes;
pfiles->filesize =
fd.nFileSizeLow;
pfiles->ansiname =(char*)
malloc(strlen((const char*)&fd.cFileName)+1);
if(ppred)ppred->next = pfiles;
wsprintf(pfiles->ansiname,(const
char*)&fd.cFileName);
ppred = pfiles;
if(!FindNextFile(hFind, &fd))
if(GetLastError() ==
ERROR_NO_MORE_FILES)
break;
}
pfiles->next = NULL;
FindClose(hFind);
files2 = pfirst;
Form1->APrintFileListExecute2(0);
return 1;
}
/****************************************************************************
*
Получение свободного места в МБ свободного тома, если он в NTFS
**************************************************************************
*/
UINT GetNtfsFreeSpace(PLOGICAL_DISC pld)
{
__int64 i64FreeBytesToCaller, i64TotalBytes,
i64FreeBytes;
char szdisk[3];
szdisk[0] = pld->nDisc;
szdisk[1] = ':';
szdisk[2] = 0;
if(Sysutils::GetDiskFreeSpaceEx (szdisk,
i64FreeBytesToCaller,
i64TotalBytes,
&i64FreeBytes))
{
//Application->MessageBoxA(IntToStr(i64FreeBytes/(1024*1024)).c_str(),IntToStr(i64FreeBytes/(1024*1024)).c_str(),MB_OK);
return (i64FreeBytes/(1024*1024));
}
return
0;
}
/*******************************************************************************
*
Чтение заданной директории, определение того, какие ф-ции для этого надо *
* использовать *
*******************************************************************************
*/
int ReadDir(PLOGICAL_DISC pld, char* pPath)
{
ULONG dwDirSize; //размер директории в кластерах
HDIR hDir; //ccылка на
директорию
UINT DirCluster; //номер кластера директории
PDISC_INFO info;
PFILES pfirst, pfiles, ppred;
char disc;
char filename[1024];
char *ptr;
char pathh[65356];
//strcpy(pathh,path);
if(!pld)return 0;
info =(_DISC_INFO*) pld->disc_info;
disc = pld->nDisc;
if(!info)
{
if((pld->id ==
0x07)||(pld->id == 0x17))
{
if(!pld->prcfree)pld->prcfree
= GetNtfsFreeSpace(pld);
return
NTFSReadDir(pld,pPath);
}
if(!(info =(_DISC_INFO*)
pld->disc_info = Fat32Init(disc)))
return 0;
pld->prcfree =
((PDISC_INFO)(pld->disc_info))->prcfree;
}
if(pPath && pPath[0]!=0)
{
DirCluster=GotoDir(info, pPath+1);
if(DirCluster)
{
hDir=LoadDirectory(info,
DirCluster, &dwDirSize);
ListDirectory(info, hDir,
dwDirSize, NULL, &pfirst);
free(hDir);
}
}
else pfirst=PrintRootDirectory(info);
if(strlen(path)>1)
{
wsprintf(pathh,path);
pathh[strlen(pathh)-1]='\0';
ptr= strrchr(pathh,'\\')+1;
if (strcmp(ptr,"..")==0)
{
pathh[(strrchr(pathh,'\\')-pathh)]='\0';
if (strrchr(pathh,'\\')==pathh)
{
pfirst=PrintRootDirectory(info);
while(strlen(path)>1)
strncpy(path+strlen(path)-1,nulpat,1);
}
else
if(pfirst)
{
if(files)FreeFilesList();
files = pfirst;
Form1->APrintFileListExecute(0);
return 1;
}
}
else
if(pfirst)
{
if(files)FreeFilesList();
files = pfirst;
Form1->APrintFileListExecute(0);
return 1;
}
}
else
if(pfirst)
{
if(files)FreeFilesList();
files = pfirst;
Form1->APrintFileListExecute(0);
return 1;
}
return 0;
}
int ReadDir2(PLOGICAL_DISC pld, char* pPath)
{
ULONG dwDirSize; //размер директории в кластерах
HDIR hDir; //ccылка на
директорию
UINT DirCluster; //номер кластера директории
PDISC_INFO info;
PFILES pfirst, pfiles, ppred;
char disc;
char filename[1024];
char pathh[65356];
char *ptr;
//strcpy(pathh,path);
if(!pld)return 0;
info =(_DISC_INFO*) pld->disc_info;
disc = pld->nDisc;
if(!info)
{
if((pld->id ==
0x07)||(pld->id == 0x17))
{
if(!pld->prcfree)pld->prcfree
= GetNtfsFreeSpace(pld);
return
NTFSReadDir2(pld,pPath);
}
if(!(info =(_DISC_INFO*)
pld->disc_info = Fat32Init(disc)))
return 0;
pld->prcfree =
((PDISC_INFO)(pld->disc_info))->prcfree;
}
if(pPath && pPath[0]!=0)
{
DirCluster=GotoDir(info, pPath+1);
if(DirCluster)
{
hDir=LoadDirectory(info,
DirCluster, &dwDirSize);
ListDirectory(info, hDir,
dwDirSize, NULL, &pfirst);
free(hDir);
}
}
else pfirst=PrintRootDirectory(info);
if(strlen(path2)>1)
{
wsprintf(pathh,path2);
pathh[strlen(pathh)-1]='\0';
ptr= strrchr(pathh,'\\')+1;
if (strcmp(ptr,"..")==0)
{
pathh[(strrchr(pathh,'\\')-pathh)]='\0';
if (strrchr(pathh,'\\')==pathh)
{
pfirst=PrintRootDirectory(info);
while(strlen(path2)>1)
strncpy(path2+strlen(path2)-1,nulpat,1);
}
else
if(pfirst)
{
if(files2)FreeFilesList();
files2 = pfirst;
Form1->APrintFileListExecute2(0);
return 1;
}
}
else
if(pfirst)
{
if(files2)FreeFilesList();
files2 = pfirst;
Form1->APrintFileListExecute2(0);
return 1;
}
}
else
if(pfirst)
{
if(files2)FreeFilesList();
files2 = pfirst;
Form1->APrintFileListExecute2(0);
return 1;
}
return 0;
}
/*-----------------------------------------------------------------------------*/
/*******************************************************************************
* Инициализация списка разделов *
*******************************************************************************
*/
void InitPartitionList()
{
int i, iRetVal, nActive = 0;
char combobuf[64];
PHARDINFO inf;
PLOGICAL_DISC pld;
UCHAR nHDD=0;
while(inf = hdd[nHDD] = Init(nHDD))
{
pld = inf->disklist;
while(pld)
{
combobuf[0] =
pld->nDisc;
combobuf[1] = ':';
combobuf[2] = 0;
iRetVal = Form1->CBDiskName->ItemIndex;
iRetVal = Form1->CBDiskName2->ItemIndex;
if(pld->active=='+')
{
nActive =
iRetVal;
currpld = pld;
}
pld =(_LOGICAL_DISC*)
pld->next;
}
nHDD++;
}
ReadDir(currpld,NULL);
ReadDir2(currpld2,NULL);
}
/*-----------------------------------------------------------------------------*/
/*******************************************************************************
*
Поиск диска по его имени *
*******************************************************************************
*/
PLOGICAL_DISC FindDiskByChar(char disk)
{
int i = 0;
PHARDINFO inf;
PLOGICAL_DISC pld;
while(inf=hdd[i++])
{
pld = inf->disklist;
while(pld)
{
if(pld->nDisc ==
disk)return pld;
pld =(_LOGICAL_DISC*)
pld->next;
}
}
return NULL;
}
/*-----------------------------------------------------------------------------*/
/*******************************************************************************
*Поиск
диска по его индексу, вызывается, когда происходит смена текущего диска*
*******************************************************************************
*/
PLOGICAL_DISC FindDiskByIndex(char index)
{
int i = 0, j = 0;
PHARDINFO inf;
PLOGICAL_DISC pld;
while(inf=hdd[i++])
{
pld = inf->disklist;
while(pld)
{
if(j == index)return pld;
pld =(_LOGICAL_DISC*)
pld->next;
j++;
}
}
return NULL;
}
/*******************************************************************************
*
Поиск файла в заранее сформированном списке по его индексу *
*******************************************************************************
*/
PFILES FindFileByIndex(int index)
{
int i = 0;
PFILES pfiles;
pfiles = files;
while(pfiles)
{
pfiles =(_FILES*) pfiles->next;
i++;
}
return NULL;
}
PFILES FindFileByIndex2(int index)
{
int i = 0;
PFILES pfiles;
pfiles = files2;
while(pfiles)
{
if(i == index)return pfiles;
pfiles =(_FILES*) pfiles->next;
i++;
}
return NULL;
}
/*******************************************************************************
*
Ложимся спать и освобождаем все, что загадили. *
*******************************************************************************
*/
void DeInitialize()
{
int i = 0;
PHARDINFO inf;
PLOGICAL_DISC pld, pred;
while(inf=hdd[i++])
{
pld = inf->disklist;
while(pld)
{
if(pld->disc_info)Fat32DeInit((_DISC_INFO*)pld->disc_info);
pred = pld;
pld =(_LOGICAL_DISC*)
pld->next;
free(pred);
}
DeInit(inf);
}
}
/*****************************************************************************/
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
/*******************************************************************************
*
Функция списка действий, обновление списка дисков. Выполняет полное *
*
полное обновление, аналогично, как и при запуске программы. *
*******************************************************************************
*/
void __fastcall TForm1::ARefreshListExecute(TObject
*Sender)
{
int i, iRetVal, nActive = 0;
char combobuf[64];
PHARDINFO inf;
PLOGICAL_DISC pld;
UCHAR nHDD=0;
CBDiskName->Items->Clear();
CBDiskName2->Items->Clear();
while(inf = hdd[nHDD] = Init(nHDD))
{
pld = inf->disklist;
while(pld)
{
if(pld->nDisc=='?')
goto figoviyDisk;
combobuf[0] =
pld->nDisc;
combobuf[1] = ':';
combobuf[2] = 0;
iRetVal =
CBDiskName->ItemIndex;
iRetVal = CBDiskName2->ItemIndex;
CBDiskName->Items->Add(combobuf);
CBDiskName2->Items->Add(combobuf);
if(pld->active=='+')
{
nActive =
iRetVal;
currpld = pld;
currpld2 = pld;
}
figoviyDisk:
pld =(_LOGICAL_DISC*)
pld->next;
}
nHDD++;
}
//ReadDir(currpld,NULL);
//ReadDir2(currpld,NULL);
}
/*******************************************************************************
*
При первом показе формы устанавливает текущий диск как индекс значения в *
*
списке дисков, это значение всегда используется для получения номера диска. *
*******************************************************************************
*/
void __fastcall TForm1::FormShow(TObject *Sender)
{
CBDiskName2->ItemIndex=0;
Form1->CBDiskName2->OnChange(0);
CBDiskName->ItemIndex=0;
Form1->CBDiskName->OnChange(0);
wsprintf(path,"\\");
wsprintf(path2,"\\");
}
/*******************************************************************************
*
Вывод файлов на панель, функция списка действий *
*******************************************************************************
*/
void __fastcall TForm1::APrintFileListExecute(TObject
*Sender)
{
PFILES pfiles;
char sz[128];
char s[2048];
int maxx=0;
pfiles = files;
Form1->Label11->Caption=currpld->cpFS;
Form1->Label12->Caption=currpld->mbLength;
Form1->Label13->Caption=currpld->abs_addr;
Form1->Label14->Caption=currpld->prcfree;
Form1->LBFileList->Items->Clear();
//Form1->LBFileList->Items->SetText("");
while(pfiles)
{
if(pfiles->attrib==8)
{
pfiles =(_FILES*) pfiles->next;
fl=1;
continue;
}
if(pfiles->attrib &
FILE_ATTRIBUTE_DIRECTORY){wsprintf(sz,"<DIR>"); dir1++;}
else
{wsprintf(sz,"%u",pfiles->filesize); fil1++;}
//if (!strstr("..",pfiles->ansiname ))
dir1-=2;
if(pfiles->attrib & FILE_ATTRIBUTE_DIRECTORY)
wsprintf(s,"[%-18s] %#10s %02X",pfiles->ansiname,sz,pfiles->attrib);
else
wsprintf(s,"%-20s %#10s %02X",pfiles->ansiname,sz,pfiles->attrib);
Form1->LBFileList->Items->Add(AnsiString(s));
pfiles =(_FILES*) pfiles->next;
if (strlen(s)>maxx) maxx=strlen(s);
}
Form1->LBFileList->ScrollWidth=maxx*8+10;
Form1->Edit1->Text =
Form1->CBDiskName->Text+'\\';
//if (strlen(path) > 1) dir1 -= 2;
Form1->Label22->Caption=dir1;
Form1->Label25->Caption=fil1;
}
void __fastcall TForm1::APrintFileListExecute2(TObject
*Sender)
{
PFILES pfiles;
char sz[128];
char s[2048];
int maxx=0;
pfiles = files2;
Form1->LBFileList2->Items->Clear();
while(pfiles)
{
if(pfiles->attrib==8)
{
pfiles =(_FILES*) pfiles->next;
continue;
}
if(pfiles->attrib &
FILE_ATTRIBUTE_DIRECTORY){wsprintf(sz,"<DIR>"); dir2++;}
else
{wsprintf(sz,"%u",pfiles->filesize);/*ltoa((ULONG)pfiles->filesize,sz,10);
*/fil2++;}
if(pfiles->attrib & FILE_ATTRIBUTE_DIRECTORY)
wsprintf(s,"[%-18s] %#10s %02X",pfiles->ansiname,sz,pfiles->attrib);
else
wsprintf(s,"%-20s %#10s %02X",pfiles->ansiname,sz,pfiles->attrib);
Form1->LBFileList2->Items->Add(AnsiString(s));
pfiles =(_FILES*) pfiles->next;
if (strlen(s)>maxx) maxx=strlen(s);
}
Form1->LBFileList2->ScrollWidth=maxx*8+10;
Form1->Edit2->Text =
Form1->CBDiskName2->Text+'\\';
//if (strlen(path2) > 1) dir2 -= 2;
Form1->Label27->Caption=dir2;
Form1->Label29->Caption=fil2;
}
*******************************************************************************
*
Обработчик изменения имени диска в выпадающем списке вверху. Обновляются все*
*
необходимые данные. *
*******************************************************************************
*/
void __fastcall TForm1::CBDiskNameChange(TObject *Sender)
{
LBFileList->Items->Clear();
currpld=FindDiskByChar(*(CBDiskName->Text.SubString(0,1).c_str()));
if(currpld == NULL) return;
ReadDir(currpld,NULL);
wsprintf(path,"\\");
CGauge1->Progress=100-currpld->prcfree/(currpld->mbLength/100);
}
void __fastcall TForm1::CBDiskName2Change(TObject
*Sender)
{
LBFileList2->Items->Clear();
currpld2=FindDiskByChar(*(CBDiskName2->Text.SubString(0,1).c_str()));
if(currpld2 == NULL) return;
ReadDir2(currpld2,NULL);
wsprintf(path2,"\\");
}
/*******************************************************************************
*
Обработчик двойного щелчка на области панели с файлами, обрабатываем только *
* бегание по директориям. *
*******************************************************************************
*/
void __fastcall TForm1::LBFileListDblClick(TObject
*Sender)
{
int i;
iSelected = LBFileList->ItemIndex;
char *ptr;
char bufferstr[65356];
char buffpath[2048];
PFILES pfirst, pfiles;
if(iSelected == -1)return;
mfile = FindFileByIndex(iSelected);
/*Реагируем
только на вход в директорию и на выход из нее */
if((mfile->attrib & 0x10))
if((strlen(path)==1) ||
((strlen(path)>1)&&(iSelected>0)))
{
if((strlen(mfile->ansiname)+strlen(path)+3)>sizeof(path))return;
strcat(path, mfile->ansiname);
wsprintf(bufferstr,mfile->ansiname);
strcat(path, "\\");
//ReadDir(currpld,path);
if(!ReadDir(currpld,path))
if (strcmp(bufferstr,"..")!=0)
{
ptr = strrchr(path,'\\');
while((ptr - path) < strlen(path))
strncpy(ptr,nulpat,strlen(path));
ptr = strrchr(path,'\\')+1;
while((ptr - path) < strlen(path))
strncpy(ptr,nulpat,strlen(path));
}
if(strlen(path) == 0) strcat(path, "\\");
else if(strlen(path) != 1)
{
if (strcmp(bufferstr,"..")==0)
{
ptr = strrchr(path,'\\');
while((ptr - path) < strlen(path))
strncpy(ptr,nulpat,strlen(path));
ptr = strrchr(path,'\\');
while((ptr - path) < strlen(path))
strncpy(ptr,nulpat,strlen(path));
ptr = strrchr(path,'\\')+1;
while((ptr - path) < strlen(path))
strncpy(ptr,nulpat,strlen(path));
LBFileList->Items->Clear();
ReadDir(currpld,path);
}
}
else
{
LBFileList->Items->Clear();
ReadDir(currpld,NULL);
wsprintf(path,"\\");
}
if (strcmp(bufferstr,".")==0)
{
ptr = strrchr(path,'\\')-1;
strncpy(ptr,nulpat,strlen(path));
}
Form1->Edit1->Text =
Form1->CBDiskName->Text+path;
if (strlen(path) > 1) dir1 -= 2;
// (buffpath,IntToStr(dir1));
Form1->Label22->Caption=dir1;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LBFileList2DblClick(TObject
*Sender)
{
int i;
iSelected2 = LBFileList2->ItemIndex;
char *ptr;
char bufferstr[65356];
char buffpath2[2048];
PFILES pfirst, pfiles;
if(iSelected2 == -1)return;
mfile = FindFileByIndex2(iSelected2);
/*Реагируем
только на вход в директорию и на выход из нее */
if((mfile->attrib & 0x10))
if((strlen(path2)==1) ||
((strlen(path2)>1)&&(iSelected2>0)))
{
if((strlen(mfile->ansiname)+strlen(path2)+3)>sizeof(path2))return;
strcat(path2, mfile->ansiname);
wsprintf(bufferstr,mfile->ansiname);
strcat(path2, "\\");
//ReadDir2(currpld2,path2);
if(!ReadDir2(currpld2,path2))
if (strcmp(bufferstr,"..")!=0)
{
ptr = strrchr(path2,'\\');
while((ptr - path2) < strlen(path2))
strncpy(ptr,nulpat,strlen(path2));
ptr = strrchr(path2,'\\')+1;
while((ptr - path2) < strlen(path2))
strncpy(ptr,nulpat,strlen(path2));
}
if(strlen(path2) == 0) strcat(path2, "\\");
else if(strlen(path2) != 1)
{
if (strcmp(bufferstr,"..")==0)
{
ptr = strrchr(path2,'\\');
while((ptr - path2) < strlen(path2))
strncpy(ptr,nulpat,strlen(path2));
ptr = strrchr(path2,'\\');
while((ptr - path2) < strlen(path2))
strncpy(ptr,nulpat,strlen(path2));
ptr = strrchr(path2,'\\')+1;
while((ptr - path2) < strlen(path2))
strncpy(ptr,nulpat,strlen(path2));
LBFileList2->Items->Clear();
ReadDir2(currpld2,path2);
}
}
else
{
LBFileList2->Items->Clear();
ReadDir2(currpld2,NULL);
wsprintf(path2,"\\");
}
if (strcmp(bufferstr,".")==0)
{
ptr = strrchr(path2,'\\')-1;
strncpy(ptr,nulpat,strlen(path2));
}
Form1->Edit2->Text =
Form1->CBDiskName2->Text+path2;
if (strlen(path2) > 1) dir2 -= 2;
// (buffpath,IntToStr(dir1));
Form1->Label27->Caption=dir2;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Compare->Visible = false;
Button2->Visible = true;
Button2->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Compare->Visible = true;
Button2->Visible = false;
Button1->SetFocus();
}
//---------------------------------------------------------------------------
FAT32.CPP
#include <windows.h>
//#include "fat32.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Чтение данных раздела
BOOL Fat32DataRead(PDISC_INFO info, char* buf, UINT
bufsize)
{
int nRead;
BOOL bRetValue=ReadFile(info->hDrive, buf,
bufsize,(unsigned long*) &nRead, NULL);
if(!bRetValue)AnalyzeError("# Error at
ReadFile: ",GetLastError());
return bRetValue;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//сдвинуть указатель внутри раздела
UINT Fat32DataMovePointer(PDISC_INFO info, UINT
secpointer)
{
UINT iErr;
UINT
HiPointer=secpointer>>(32-info->bitsPerSector);
UINT
LoPointer=secpointer<<(info->bitsPerSector);
UINT
bRetValue=SetFilePointer(info->hDrive,LoPointer,(long*)&HiPointer,FILE_BEGIN);
if(bRetValue==-1)
{
iErr=GetLastError();
if(iErr!=NO_ERROR)AnalyzeError("#
Error at SetFilePointer: ",iErr);
}
return bRetValue;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//найти следующий элемент цепочки кластеров
UINT GetNextFileCluster(PDISC_INFO info, UINT
nCurrCluster)
{
UINT nextcluster;
if(info->bFAT16)nextcluster =
((USHORT*)(info->pFAT))[nCurrCluster];
else nextcluster =
info->pFAT[nCurrCluster];
return nextcluster;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
UINT Cluster2Sector(PDISC_INFO info, UINT cluster)
{
UINT retval;
if(info->bFAT16)
retval = info->sizeReserved+
(info->nFATCopy)*(info->sizeFAT)+
cluster*(info->SectPerCluster);
else
retval = info->sizeReserved+
(info->nFATCopy)*(info->sizeFAT)+
(cluster-2)*(info->SectPerCluster);
return retval;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
char* Fat32ReadFile(PDISC_INFO info, UINT
FirstCluster, ULONG* dwFileSize)
{
char* retval = LoadDirectory(info,
FirstCluster, dwFileSize);
if(dwFileSize)*dwFileSize =
(*dwFileSize)*(info->BytesPerCluster);
return retval;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//пройтись по цепочке кластеров
UINT WalkOnFATTable(PDISC_INFO info, UINT
FirstCluster, UINT* LastCluster, UINT* nClusters)
{
UINT fragments=1;
UINT predCluster, n=0;
UINT currCluster=FirstCluster;
while(1)
{
predCluster=currCluster; n++;
currCluster=GetNextFileCluster(info,
currCluster);
if(currCluster==0)return 0;
if(currCluster>=0x0FFFFFF8)break;
if(info->bFAT16 &&
(currCluster>=0xfff8))break;
if(currCluster!=(predCluster+1))fragments++;
}
if(LastCluster)*LastCluster=predCluster;
if(nClusters)*nClusters=n;
return fragments;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Загружает директорию в память
HDIR LoadDirectory(PDISC_INFO info, UINT cluster,
ULONG* dirsize)
{
UINT sector,currCluster;
UINT i;
UINT nClusters,dwSize;
HDIR hDir;
char b[1024];
currCluster=cluster;
if(info->bFAT16 && (0 == cluster))
{
nClusters = 1 +
(info->nRootElements * 32) / info->BytesPerCluster;
dwSize = nClusters *
info->BytesPerCluster;
//MessageBox(0,"zzz","",MB_OK);
}else{
WalkOnFATTable(info,cluster,NULL,&nClusters);
dwSize=(info->BytesPerCluster)*nClusters;
}
hDir=(HDIR)malloc(dwSize);
for(i=0;i<nClusters;i++)
{
if(info->bFAT16 && (0 ==
cluster))
{
sector =
info->RootSector;
}else
sector = Cluster2Sector(info,
currCluster);
if(Fat32DataMovePointer(info,sector)==-1)
{
free(hDir);
return NULL;
}
if(!Fat32DataRead(info,hDir+i*(info->BytesPerCluster),info->BytesPerCluster))
{
free(hDir);
return NULL;
}
if(info->bFAT16 && (0 ==
cluster))
{currCluster++;}
else
{
currCluster =
GetNextFileCluster(info,currCluster);
if(currCluster==0)
{
free(hDir);
return NULL;
}
}
if(currCluster>=0x0FFFFFF8)break;
}
//MessageBox(0,"zzz2","",MB_OK);
if(dirsize)*dirsize=nClusters;
return hDir;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Загружает таблицу FAT в память
BOOL LoadFAT(PDISC_INFO info)
{
UINT
dwSize=(info->sizeFAT)*(info->nBytePerSector);
if(Fat32DataMovePointer(info,info->beginFAT)==-1)return
0;
info->pFAT=(unsigned int*)malloc(dwSize);
if(info->pFAT==NULL)return FALSE;
if(!Fat32DataRead(info,(char*)(info->pFAT),dwSize))
{
free(info->pFAT);
return FALSE;
}
info->sizeFATbytes=dwSize;
return TRUE;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//если pObjectName==NULL то печатает содержимое
директории, находящейся в памяти
//если
pObjectName!=NULL ищет в директории директорию с именем pObjectName
UINT ListDirectory(PDISC_INFO info, HDIR hDir,UINT
dwDirSize,char* cpObjectName, PFILES* ppfiles)
{
UCHAR attrib;
UCHAR* p;
UCHAR* t;
USHORT firstclusterLo,firstclusterHi;
UINT i,j,h,firstcluster,filesize;
char ansiname[1024];
unsigned char uname[1024];
BOOL IsTheLong=FALSE;
PFILES pfiles, pfirst=NULL, ppred=NULL;
if(hDir==NULL)return 0;
p=hDir; ansiname[11]=0;
for(i=0;i<(dwDirSize*(info->BytesPerCluster))/32;i++)
{
if((p[0]==0xE5) || (p[0] == 0x8F)
|| (p[11]) == '\b')
{
p=p+32;
continue;
}
if(p[0]==0)break;
attrib=p[11];
if(attrib!=0x0F)
{
firstclusterLo=(*(USHORT*)&p[26]);
firstclusterHi=(*(USHORT*)&p[20]);
firstcluster=firstclusterHi;
firstcluster=(firstcluster<<16)+firstclusterLo;
if(!cpObjectName)
{
filesize=*(UINT*)&p[28];
pfiles
=(_FILES*) malloc(sizeof(FILES));
pfiles->attrib
= attrib;
pfiles->firstcluster
= firstcluster;
pfiles->filesize
= filesize;
if(!pfirst)pfirst
= pfiles;
if(ppred)ppred->next
= pfiles;
}
for(int g=10;g>1;g--)
if(p[g]==' ') p[g]='\0';
memcpy(ansiname,p,11);
for(j=10;j>1;j--)
if(ansiname[j]!=0x20)
{
ansiname[j+1]=0;
break;
}
if(IsTheLong)
{
WideCharToMultiByte(CP_ACP,0,(LPCWSTR)uname,-1,ansiname,sizeof(ansiname),NULL,NULL);
IsTheLong=FALSE;
}
if(cpObjectName)
if((!strcmpi(cpObjectName,ansiname))
&&
((attrib&0x10)!=0))
return
firstcluster;
if(!cpObjectName)
{
pfiles->ansiname
=(char*)
malloc(strlen(ansiname)+1);
strcpy(pfiles->ansiname,
ansiname);
pfiles->next
= NULL;
ppred = pfiles;
}
}
else if((p[0]==1)||(p[0]&0x40))
{
if(p!=(hDir+dwDirSize))
if((p[0]&0x40)&&((p+32)[11]==0x0F))
{
p+=32;
continue;
}
t=p; h=0;
memset(uname,0,sizeof(uname));
while(1)
{
j=t[0];
memcpy(uname+h+00,t+1,10);
memcpy(uname+h+10,t+14,12);
memcpy(uname+h+22,t+28,4);
if(j&0x40)
{
IsTheLong=TRUE;
break;
}
t-=32; h+=26;
if(t<hDir)break;
if(t[11]!=0x0F)break;
}
}
p+=32;
}
if(ppfiles)
*ppfiles = pfirst;
return 0;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
double GetFreeSpaceEx(PDISC_INFO info)//
{
unsigned long i;
double RET;
double freeclusters = 0;
double clusters = info->sizeFATbytes / 4;
if (clusters == 0) return 0;
for(i=0;i<clusters;i++)
if(!info->pFAT[i])freeclusters++;
RET=(freeclusters * info->BytesPerCluster);
RET /= (1024*1024);
return RET;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//инициализирует структуру DISC_INFO
PDISC_INFO Fat32Init(char disc)
{
char LogicalDiskName[]="\\\\.\\X:";
char RootDir[]="X:";
UCHAR buf[2048];
UCHAR signature1; //66
USHORT signature2; //510
UCHAR signature3; //38
UINT i,n;
PDISC_INFO
info=(_DISC_INFO*)malloc(sizeof(DISC_INFO));
info->Disc=disc;
LogicalDiskName[4]=disc;
RootDir[0]=disc;
info->hDrive=CreateFile(
LogicalDiskName,
GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0,
NULL);
if(info->hDrive==INVALID_HANDLE_VALUE)
{
AnalyzeError("# Error at
CreateFile: ",GetLastError());
free(info);
return NULL;
}
GetDiskFreeSpace(RootDir,NULL,(unsigned
long*)&(info->nBytePerSector),NULL,NULL);
if(!Fat32DataRead(info, buf,
info->nBytePerSector))
{
CloseHandle(info->hDrive);
free(info);
return NULL;
}
//bFAT16
signature3=*(UCHAR*)&buf[38];
signature1=*(UCHAR*)&buf[66];
signature2=*(USHORT*)&buf[510];
if(signature2!=0xAA55)
{
//printf("# 55AA sig
n'found");
CloseHandle(info->hDrive);
free(info);
return NULL;
}
if((signature3==0x29) && (signature1!=0x29))
{
//printf("YAAHO!!
FAT16!!!!!!!!!");
info->bFAT16 = TRUE;
info->sizeFAT =
*(short*)&buf[22];
info->nRootElements =
*(short*)&buf[17];
}else{
if(signature1 != 0x29)
{
//printf("# unknown
FS");
free(info);
return NULL;
}
info->bFAT16 = FALSE;
info->sizeFAT=*(short*)&buf[36];
}
info->nFATCopy=*(short*)&buf[16];
info->sizeReserved=*(short*)&buf[14];
info->SectPerCluster=*(char*)&buf[13];
info->BytesPerCluster=(info->SectPerCluster)*(info->nBytePerSector);
info->beginFAT=info->sizeReserved;
i=info->nBytePerSector; n=0;
while(i=i/2)n++;
info->bitsPerSector=n;
if(!LoadFAT(info))
{
CloseHandle(info->hDrive);
free(info);
return NULL;
}
if(info->bFAT16)
{
info->RootSector =
info->beginFAT + info->nFATCopy * info->sizeFAT;
info->RootCluster = 0;
}
else
info->RootCluster=*(int*)&buf[44];
info->RootSector = 0;
}
info->hRootDir=LoadDirectory(info,
info->RootCluster,&(info->dwRootDirSize));
info->prcfree = GetFreeSpaceEx(info);
return info;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//возвращает кластер директории расположенной по пути
cpPath
UINT GotoDir(PDISC_INFO info, char* cpPath)
{
UINT i,dwLen=strlen(cpPath);
char* pStr=(char*)malloc(dwLen+2);
char* cpDirName=pStr;
UINT DirCluster; ULONG dwDirSize;
HDIR hDir;
hDir=info->hRootDir;
dwDirSize=info->dwRootDirSize;
strcpy(pStr,cpPath);
if(pStr[dwLen-1]!='\\')
{
strcat(pStr,"\\");
dwLen++;
}
for(i=0;i<dwLen;i++)
{
if(pStr[i]=='\\')
{
pStr[i]=0;
DirCluster=ListDirectory(info,
hDir,dwDirSize,cpDirName, NULL);
if(hDir!=info->hRootDir)free(hDir);
if(!DirCluster)
{
//printf("#
error directory %s not found",cpDirName);
free(pStr);
return 0;
}
if(i==(dwLen-1))
{
free(pStr);
return
DirCluster;
}
hDir=LoadDirectory(info,
DirCluster, &dwDirSize);
cpDirName=pStr+i+1;
}
}
free(pStr);
return 0;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void Fat32DeInit(PDISC_INFO info)
{
free(info->pFAT);
free(info->hRootDir);
CloseHandle(info->hDrive);
free(info);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
PFILES PrintRootDirectory(PDISC_INFO info)
{
PFILES pfirst = NULL;
ListDirectory(info, info->hRootDir,
info->dwRootDirSize, NULL, &pfirst);
return pfirst;
}
MBRMODULE.CPP
#include <windows.h>
//#include "mbrmodule.h"
#include "err.h"
char FAT[]="\x01\x04\x06\x0D\x0E";
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Узнать диск по серийному номеру
char GetDiscBySN(UINT SN)
{
UINT VolumeSerialNumber;
char Drive[4]="X:\\";
int i;
for(i=2;i<25;i++)
if((GetLogicalDrives()&(1<<i))!=0)
{
Drive[0] = 'A'+i;
switch(GetDriveType(Drive))
{
case
DRIVE_CDROM:
break;
default:
GetVolumeInformation(Drive,
NULL,0,
(unsigned long*)&VolumeSerialNumber,
NULL,0,NULL,0
);
if(VolumeSerialNumber==SN)
return
Drive[0];
}
}
return 0;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Узнать файловую систему диска по коду файловой
системы
char* GetFileSystem(unsigned char code)
{
int i;
if((code==0x07)||(code==0x17))
return "NTFS ";
if(code==0x82)
return "ext2 ";
if(code==0x83)
return "ext3 ";
if((code==0x0B)||(code==0x0C))
return "FAT32 ";
for(i=0;i<sizeof(FAT);i++)
if(code==FAT[i])
return "FAT ";
return "? ";
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//сдвинуть указатель
int MovePointer(PHARDINFO inf, UINT secpointer)
{
UINT iErr;
UINT
HiPointer=secpointer>>(32-inf->bitsPerSector);
UINT LoPointer=secpointer<<(inf->bitsPerSector);
UINT
bRetValue=SetFilePointer(inf->hDrive,LoPointer,(long*)&HiPointer,FILE_BEGIN);
if(bRetValue==-1)
{
iErr=GetLastError();
if(iErr!=NO_ERROR)
{
//printf("# error at
SetFilePointer: ");
AnalyzeError(NULL,iErr);
}
}
return bRetValue;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Читать один сектор с жесткого диска
void* RawRead(PHARDINFO inf)
{
UINT iErr, SectorSize, nRead, i, n;
void* buf;
SectorSize=inf->dwSectorSize;
if(!SectorSize)SectorSize=0x200;
buf=malloc(SectorSize);
while(!ReadFile(inf->hDrive, buf,
SectorSize, (unsigned long*)&nRead, NULL))
{
iErr=GetLastError();
free(buf);
if((iErr==ERROR_INVALID_PARAMETER)&&(SectorSize<0x8000))
{
SectorSize=SectorSize*2;
buf=malloc(SectorSize);
continue;
}
//printf("# error at ReadFile:
");
AnalyzeError(NULL,iErr);
return NULL;
};
if(inf->dwSectorSize!=SectorSize)
{
i=SectorSize; n=0;
while(i=i/2)n++;
inf->bitsPerSector=n;
inf->dwSectorSize=SectorSize;
}
return buf;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*Изъять серийный номер для FAT или NTFS
abs_addr -
адрес начала логического диска в секторах
Serial -
адрес 8-байтного буфера для серийного номера
id -
идентификатор файловой системы
*/
BOOL GetDiscSerial(PHARDINFO inf, UINT abs_addr,
UCHAR* Serial, UCHAR id)
{
char* buf;
int i;
if(MovePointer(inf,abs_addr)==-1)return
FALSE;
if((buf=(char*)RawRead(inf))==NULL)return
FALSE;
switch(id)
{
case 0x07: //NTFS
memcpy(Serial,buf+72,8);
break;
case 0x0E:
case 0x0C:
case 0x0B: //FAT32
memcpy(Serial,buf+67,4);
break;
default:
for(i=0;i<sizeof(FAT);i++)
if(id==FAT[i])
{
memcpy(Serial,buf+39,4);
free(buf);
return TRUE;
}
return FALSE;
}
free(buf);
return TRUE;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void DeInit(PHARDINFO inf)
{
CloseHandle(inf->hDrive);
free(inf);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Вывести список разделов из Partition Table в MBR
PLOGICAL_DISC ListMBR(PHARDINFO inf, UCHAR* pMBR, UINT
dwMBRAddr, UINT* pExtended, PPLOGICAL_DISC last)
{
UCHAR* pPart;
UCHAR id,active;
UINT
ext=0,secBegin,secLength,mbLength=0,gbLength=0;
PLOGICAL_DISC first=NULL, pld=NULL,
pred=NULL;
UINT SectorSize,abs_addr,SN4;
UCHAR SN[8];
char* cpFS;
int i;
SectorSize=inf->dwSectorSize;
pPart=pMBR+0x01BE;
for(i=0;i<4;i++)
{
id=pPart[4];
if(!id)
{
pPart+=0x10;
continue;
}
secBegin=*(UINT*)&pPart[8];
secLength=*(UINT*)&pPart[12];
active=pPart[0];
if(active)active='+';
else active='-';
pPart+=0x10;
mbLength=secLength/(2*1024)*SectorSize/512;
gbLength=mbLength/1024;
abs_addr=dwMBRAddr+secBegin;
cpFS=GetFileSystem(id);
if((id==0x0F)||(id==0x05))
{
ext=secBegin;
continue;
}
memset(SN,0,sizeof(SN));
GetDiscSerial(inf,abs_addr,SN,id);
memcpy(&SN4,SN,4);
pred = pld;
pld =(_LOGICAL_DISC*)
malloc(sizeof(LOGICAL_DISC));
memset(pld, 0,
sizeof(LOGICAL_DISC));
if(pred!=NULL)
pred->next = pld;
else first = pld;
pld->nHard = inf->nHard;
pld->nDisc =
SN4?GetDiscBySN(SN4):'?';
pld->active = active;
pld->abs_addr = abs_addr;
pld->secLength = secLength;
pld->id = id;
pld->cpFS = cpFS;
pld->SN4 = SN4;
pld->gbLength = gbLength;
pld->mbLength = mbLength;
pld->next = NULL;
}
*pExtended = ext;
*last = pld;
return first;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Печатать заголовок
void PrintHead()
{
//printf("HDD Disc Boot Addr Size FS SN mb/gb\n");
//printf("------------------------------------------------------------------------\n");
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Проверить сигнатуру
BOOL CheckMBR(UCHAR* pMBR)
{
BOOL bRetValue=*(USHORT*)(pMBR+0x01FE)==0xAA55;
// if(!bRetValue)printf("# not valid
MBR\n");
return bRetValue;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Пройтись по цепочке MBR
BOOL WalkOnMBR(PHARDINFO inf, PPLOGICAL_DISC first)
{
PLOGICAL_DISC pred=NULL, last=NULL;
UINT ext,dwNextMBRAddr;
void* pMBR;
*first = NULL;
if((pMBR=RawRead(inf))==NULL)return FALSE;
if(!CheckMBR((unsigned char*)pMBR))
{
free(pMBR);
return FALSE;
}
if((*first=ListMBR(inf,(unsigned
char*)pMBR,0,&ext,&last))&&ext)
{
inf->dwExtendedAddr=ext;
ext=0;
while(1)
{
free(pMBR);
dwNextMBRAddr=ext+inf->dwExtendedAddr;
if(MovePointer(inf,dwNextMBRAddr)==-1)return
FALSE;
if((pMBR=RawRead(inf))==NULL)return
FALSE;
if(!CheckMBR((unsigned
char*)pMBR))
{
free(pMBR);
return FALSE;
}
pred = last;
pred->next =
ListMBR(inf,(unsigned char*)pMBR,dwNextMBRAddr,&ext,&last);
if(!ext)break;
}
}
free(pMBR);
return TRUE;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
PHARDINFO Init(char n)
{
char
HardDiskName[]="\\\\.\\PHYSICALDRIVE0";
void* hDrive;
UINT iErr, dwSectorSize;
PHARDINFO inf;
HardDiskName[sizeof(HardDiskName)-2]=n+'0';
hDrive=CreateFile(
HardDiskName,
GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL
if(hDrive==INVALID_HANDLE_VALUE)
{
iErr=GetLastError();
if(iErr==ERROR_FILE_NOT_FOUND)return
NULL;
AnalyzeError("# Error at
CreateFile: ",iErr);
return NULL;
}
inf=(_HARDINFO*)malloc(sizeof(HARDINFO));
inf->hDrive=hDrive;
inf->nHard=n;
inf->dwSectorSize=0;
WalkOnMBR(inf, &inf->disklist);
return inf;}