Я рад слышать, что вы делаете это на C ++. Кажется, никто больше не считает C ++ «необходимым». Это все C # this и ASP.NET, которые ... Даже я работаю в C # house, когда я поклялся, я бы никогда не переключился, поскольку C ++ делает все, что мне когда-либо нужно, а затем , Я достаточно взрослый, чтобы очистить свою память! хех .. В любом случае, вернемся к вопросу ...
DefineDOSDevice()
- это метод, который используется для назначения букв дисков, имен портов (LPT1, COM1 и т. Д.). Вы передаете ему имя, некоторые флаги и «путь», который обрабатывает это устройство. Но не позволяйте этому обмануть вас. Это не путь к файловой системе, это путь к объекту NT. Я уверен, что вы видели их как «\ Device \ HardDisk0» и т. Д. Вы можете использовать WinObj.exe из sysinternals, чтобы понять, что я имею в виду. В любом случае вы можете создать драйвер устройства, а затем указать на него символическую ссылку MSDOS, и все готово. Но при условии, что это кажется большой работой для первоначальной проблемы.
Сколько этих мегабайтовых файлов находится в обычном каталоге? Лучше всего просто прикрепить все файлы внутри одного гигантского файла и сохранить рядом с ним индексный файл (или заголовок каждого файла), который указывает на следующий «Файл» внутри вашего файла «виртуальной файловой системы».
Хорошим примером может быть просмотр формата Microsoft MSN Archive. Я перевернул этот формат архива, когда работал в AV-компании, и он на самом деле довольно креативный, но ОЧЕНЬ простой. Все это может быть сделано в одном файле, и если вы хотите стать модным, вы COULD сохраните данные в 3 файлах в конфигурации типа RAID 5, поэтому, если какой-либо из этих 3 файлов будет скрыт, вы МОЖЕТ восстановить другие. Кроме того, пользователи просто увидят 3 ОЧЕНЬ больших файлов в каталоге и не смогут получить доступ к отдельным (внутренним) файлам.
Я предоставил вам код, который распаковывает один из этих форматов MSN Archive. У меня нет кода, который СОЗДАЕТ один, но из исходного кода вы сможете создать / написать без проблем. Если файлы удаляются и / или часто переименовываются, это может привести к проблеме с используемым пространством в файле, которое необходимо время от времени обрезать.
Этот формат даже поддерживает поля CRC, поэтому вы можете проверить, правильно ли вы получили файл. Мне никогда не удавалось полностью изменить алгоритм, который Microsoft использовал для CRC-данных, но у меня есть довольно хорошая идея.
Вы не сможете сохранить текущие процедуры ввода-вывода, а это означает, что CreateFile () не просто сможет открыть какой-либо файл в архиве, однако, благодаря сверхскорости C ++, вы можете переопределить CreateFile. позвоните, чтобы реализовать формат вашего архива.
Если вам нужна помощь с ним, и это достаточно большая проблема, возможно, мы могли бы поговорить в автономном режиме и найти решение для вас.
Я не против написания вам FileSystemDriver, но для этого нам нужно начать говорить о компенсации. Я был бы более чем счастлив дать вам направление и идеи бесплатно, как я делаю сейчас.
Я не уверен, что для меня кошерно давать вам свой адрес электронной почты здесь, я не уверен в политике SO по этому вопросу, так как мы могли бы говорить о потенциальной работе / привлечении, но это не мое единственное намерение , Я бы лучше сначала помог вам найти ваши собственные решения.
Прежде чем заглянуть в драйвер устройства, скачайте WinDDK. На нем есть образцы драйверов.
Если вы удивляетесь, почему меня так волнует это, это потому, что я много лет писал на своем планшете драйвер, похожий на этот, который должен был быть совместимым с Windows И OSX, что позволит пользователям защищать тома дисков (USB-ключи, съемные тома) БЕЗ установки каких-либо драйверов или сложного (и громоздкого, иногда раздражающего) программного обеспечения. В последние годы многие производители оборудования делали аналогичные вещи, но я не думаю, что безопасность - это все, что безопасно. Я смотрю на использование RSA и AES, точно так же, как работают GPG и PGP. Первоначально со мной связались по поводу того, что (я верю, но у меня нет доказательств) собирались использовать для защиты файлов MP3. Поскольку они будут храниться в зашифрованном формате, они просто не будут работать без правильной парольной фразы. Но я видел и другие варианты использования. (Это было тогда, когда стоимость USB-ключа на 16 мегабайт (да, MEG) превышала 100 долларов или около того).
Этот проект также осуществлялся вместе с моей системой безопасности ПК для нефтяной и газовой промышленности, в которой использовалось что-то похожее на смарт-карты, просто намного проще в использовании, повторном использовании / повторном выпуске, невозможно (читай: ОЧЕНЬ сложно и маловероятно) взломать, и я мог бы использовать его на моих собственных детей дома! (Поскольку всегда идет борьба за то, кто получает время на компьютере, а кто получил больше всего, и так далее, и так далее, и ...)
Фуф ... Я думаю, что у меня тут не по теме. В любом случае, вот пример формата архива Microsoft MSN. Посмотрите, сможете ли вы использовать что-то подобное, зная, что вы всегда можете «пропустить» право на файл, следуя смещениям в файле, когда вы анализируете / ищите запрошенный файл в мастер-файле; или в предварительно проанализированных данных, хранящихся в памяти. А поскольку вы не будете загружать необработанные данные двоичных файлов в память, вашим единственным ограничением, вероятно, будет ограничение в 4 ГБ на 32-разрядных компьютерах.
Формат MARC (Microsoft MSN Archive) выложен (приблизительно) следующим образом:
- 12-байтовый заголовок (только один)
- Файл Magic
- MARC версия
- Количество файлов (в следующей таблице)
- 68 заголовков таблицы файлов байтов (от 1 до Header.NumFiles из них)
- Имя файла
- Размер файла
- Контрольная сумма
- смещение к необработанным данным файла
Теперь в 12-байтовых записях таблицы файлов 32 бита используются для длины файла и смещения. Для ваших ОЧЕНЬ больших файлов может потребоваться до 48 или 64-битных целых чисел.
Вот код, который я написал, чтобы справиться с этим.
#define MARC_FILE_MAGIC 0x4352414D // In Little Endian
#define MARC_FILENAME_LEN 56 //(You'll notice this is rather small)
#define MARC_HEADER_SIZE 12
#define MARC_FILE_ENT_SIZE 68
#define MARC_DATA_SIZE 1024 * 128 // 128k Read Buffer should be enough.
#define MARC_ERR_OK 0 // No error
#define MARC_ERR_OOD 314 // Out of data error
#define MARC_ERR_OS 315 // Error returned by the OS
#define MARC_ERR_CRC 316 // CRC error
struct marc_file_hdr
{
ULONG h_magic;
ULONG h_version;
ULONG h_files;
int h_fd;
struct marc_dir *h_dir;
};
struct marc_file
{
char f_filename[MARC_FILENAME_LEN];
long f_filesize;
unsigned long f_checksum;
long f_offset;
};
struct marc_dir
{
struct marc_file *dir_file;
ULONG dir_filenum;
struct marc_dir *dir_next;
};
Это дает вам представление о заголовках, которые я написал для них, и вот функция open. Да, ему не хватает всех звонков в службу поддержки, ошибочных процедур и т. Д., Но вы поняли идею. Пожалуйста, извините смесь стилей кода C и C ++. Наш сканер представлял собой совокупность множества различных проблем, подобных этой ... Я использовал античные вызовы, такие как open (), fopen (), чтобы соответствовать стандартам остальной части кода.
struct marc_file_hdr *marc_open(char *filename)
{
struct marc_file_hdr *fhdr = (struct marc_file_hdr*)malloc(sizeof(marc_file_hdr));
fhdr->h_dir = NULL;
#if defined(_sopen_s)
int errno = _sopen_s(fhdr->h_fd, filename, _O_BINARY | _O_RDONLY, _SH_DENYWR, _S_IREAD | _S_IWRITE);
#else
fhdr->h_fd = open(filename, _O_BINARY | _O_RDONLY);
#endif
if(fhdr->h_fd < 0)
{
marc_close(fhdr);
return NULL;
}
//Once we have the file open, read all the file headers, and populate our main headers linked list.
if(read(fhdr->h_fd, fhdr, MARC_HEADER_SIZE) != MARC_HEADER_SIZE)
{
errmsg("MARC: Could not read MARC header from file %s.\n", filename);
marc_close(fhdr);
return NULL;
}
// Verify the file magic
if(fhdr->h_magic != MARC_FILE_MAGIC)
{
errmsg("MARC: Incorrect file magic %x found in MARC file.", fhdr->h_magic);
marc_close(fhdr);
return NULL;
}
if(fhdr->h_files <= 0)
{
errmsg("MARC: No files found in archive.\n");
marc_close(fhdr);
return NULL;
}
// Get all the file headers from this archive, and link them to the main header.
struct marc_dir *lastdir = NULL, *curdir = NULL;
curdir = (struct marc_dir*)malloc(sizeof(marc_dir));
fhdr->h_dir = curdir;
for(int x = 0;x < fhdr->h_files;x++)
{
if(lastdir)
{
lastdir->dir_next = (struct marc_dir*)malloc(sizeof(marc_dir));
lastdir->dir_next->dir_next = NULL;
curdir = lastdir->dir_next;
}
curdir->dir_file = (struct marc_file*)malloc(sizeof(marc_file));
curdir->dir_filenum = x + 1;
if(read(fhdr->h_fd, curdir->dir_file, MARC_FILE_ENT_SIZE) != MARC_FILE_ENT_SIZE)
{
errmsg("MARC: Could not read file header for file %d\n", x);
marc_close(fhdr);
return NULL;
}
// LEF: Just a little extra insurance...
curdir->dir_file->f_filename[MARC_FILENAME_LEN] = NULL;
lastdir = curdir;
}
lastdir->dir_next = NULL;
return fhdr;
}
Тогда у вас есть простой метод извлечения. Имейте в виду, что это было строго для сканирования на вирусы, так что здесь нет никаких процедур поиска и т. Д. Это было разработано, чтобы просто выгружать файл, сканировать его и двигаться дальше. Ниже приведена процедура кода CRC, которую, как я полагаю, использовала Microsoft, но я не уверен, ЧТО именно они CRC '. Это может включать данные заголовка + данные файла и т. Д. Я просто не заботился о том, чтобы вернуться назад и попытаться изменить его. В любом случае, как вы можете видеть, в этом формате архива нет сжатия, но его легко добавить ОЧЕНЬ . Полный источник может быть предоставлен, если вы хотите. (Я думаю, что осталось только подпрограмма close (), код, который вызывает и извлекает каждый файл и т. Д. !!)
bool marc_extract(struct marc_file_hdr *marc, struct marc_file *marcfile, char *file, int &err)
{
// Create the file from marcfile, in *file's location, return any errors.
int ofd = 0;
#if defined(_sopen_s)
err = _sopen_s(ofd, filename, _O_CREAT | _O_SHORT_LIVED | _O_BINARY | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
#else
ofd = open(file, _O_CREAT | _O_SHORT_LIVED | _O_BINARY | _O_RDWR);
#endif
// Seek to the offset of the file to extract
if(lseek(marc->h_fd, marcfile->f_offset, SEEK_SET) != marcfile->f_offset)
{
errmsg("MARC: Could not seek to offset 0x%04x for file %s.\n", marcfile->f_offset, marcfile->f_filename);
close(ofd);
err = MARC_ERR_OS; // Get the last error from the OS.
return false;
}
unsigned char *buffer = (unsigned char*)malloc(MARC_DATA_SIZE);
long bytesleft = marcfile->f_filesize;
long readsize = MARC_DATA_SIZE >= marcfile->f_filesize ? marcfile->f_filesize : MARC_DATA_SIZE;
unsigned long crc = 0;
while(bytesleft)
{
if(read(marc->h_fd, buffer, readsize) != readsize)
{
errmsg("MARC: Failed to extract data from MARC archive.\n");
free(buffer);
close(ofd);
err = MARC_ERR_OOD;
return false;
}
crc = marc_checksum(buffer, readsize, crc);
if(write(ofd, buffer, readsize) != readsize)
{
errmsg("MARC: Failed to write data to file.\n");
free(buffer);
close(ofd);
err = MARC_ERR_OS; // Get the last error from the OS.
return false;
}
bytesleft -= readsize;
readsize = MARC_DATA_SIZE >= bytesleft ? bytesleft : MARC_DATA_SIZE;
}
// LEF: I can't quite figure out how the checksum is computed, but I think it has to do with the file header, PLUS the data in the file, or it's checked on the data in the file
// minus any BOM's at the start... So, we'll just rem out this code for now, but I wrote it anyways.
//if(crc != marcfile->f_checksum)
//{
// warningmsg("MARC: File CRC does not match. File could be corrupt, or altered. CRC=0x%08X, expected 0x%08X\n", crc, marcfile->f_checksum);
// err = MARC_ERR_CRC;
//}
free(buffer);
close(ofd);
return true;
}
Вот моя предполагаемая процедура CRC (возможно, я украл ее у Стюарта Кея и libmspack , я не могу вспомнить):
static unsigned long marc_checksum(void *pv, UINT cb, unsigned long seed)
{
int count = cb / 4;
unsigned long csum = seed;
BYTE *p = (BYTE*)pv;
unsigned long ul;
while(count-- > 0)
{
ul = *p++;
ul |= (((unsigned long)(*p++)) << 8);
ul |= (((unsigned long)(*p++)) << 16);
ul |= (((unsigned long)(*p++)) << 24);
csum ^= ul;
}
ul = 0;
switch(cb % 4)
{
case 3: ul |= (((unsigned long)(*p++)) << 16);
case 2: ul |= (((unsigned long)(*p++)) << 8);
case 1: ul |= *p++;
default: break;
}
csum ^= ul;
return csum;
}
Ну, я думаю, что этот пост достаточно длинный ... Свяжитесь со мной, если вам нужна помощь или у вас есть вопросы.