Файловый джихад

Часто по долгу службы (или по семейным обстоятельствам) мы вынуждены делить свой (или не свой:() компьютер с кем-либо другим. Этот момент порождает массу неприятностей ("Нет, ну какое безобразие! Накачали тут, видишь ли, всякой ерунды из Интернета, так она теперь драгоценное место занимает! Все удалю к чертовой бабушке!"). Простейшим способом борьбы за свои файлы (и за компьютер) было бы установить supervisor password, user password, да еще пароль на операционную систему. Но ввиду щепетильности обстоятельств этот способ — отнюдь не лучший выход (если начнутся разборки с участием начальника, неприятностей на вашу бедную голову свалится еще больше).

Так как компьютер отобрать мы не имеем права, то единственный способ защиты своих файлов заключается в том, чтобы прибегнуть к некоторым фокусам, которые, будем надеяться, помогут без особых конфликтов спасти нашу информацию от неправедного гнева оппонентов. Сами-то, небось, тоже вовсю юзают Интернет "за счет фирмы" и обзаводятся всякими совершенно бесполезными рюшечками, используя многострадальные ресурсы общей машины. Мешать им мы не собираемся, а вот качать собственные права будем по полной программе и используя насильственные методы. Чтобы не было разночтений, поясню: насильственные по отношению к компьютеру8-).

И еще кое-что. Даже если вы используете Windows NT/2000/XP/Server, то следует осознавать, что разграничение пользователей еще не дает полной независимости. Описанный конфликт вполне может произойти и между пользователями вышеозначенных OS. Но если у вас ограниченная запись, а ваш оппонент — админ компьютера (или всей сети, или пользуется поддержкой оного), то лучше попытаться разрешить вопрос мирно. В принципе, более- менее знающему человеку (уровня advanced user), добраться-таки до ваших файлов — дело минутное (исключая, конечно, PGP-диски, но их можно просто удалить). А коль скоро полноценный админ, по идее, владеет компьютером повыше опытного пользователя, то единственное, на что можно рассчитывать — это взять его неожиданностью и/или… разозлить. Последнего советую избегать всеми правдами и неправдами. Тем не менее, избавление от назойливости домашних и не особенно выдающихся познаниями в области информационных технологий коллег вам гарантировано. Ну-с, с теологическим аспектом мы закончили. Теперь — к делу.

Способ первый. Для неандертальцев. Сразу предупреждаю: способ вряд ли "прокатит" с людьми, хоть сколько-нибудь приобщившимися к достижениям современной цивилизации, но если вы своего противника к этой категории не относите, то можете попробовать. Только не вините меня, если окажется, что недооцененный вами оппонент обнаружит эту уловку уровня третьего класса начальной школы (где информатику еще и не изучают) и, ткнув в вас пальцем, публично обвинит в ламерстве. Выделяем в "Проводнике" вашу папку с файлами, вызываем контекстное меню и выбираем оттуда Свойства (Properties) или просто жмем Alt — Enter. В появившемся окне устанавливаем флажок напротив атрибута Скрытый (Hidden) и жмем OK. На вопрос о том, стоит ли применять эти атрибуты ко всем вложенным папкам и файлам, если таковой будет задан, советую ответить отрицательно. Сначала наша директория становится полупрозрачной. Теперь жмем F5 (Обновить). Если папка не исчезла, а администратор не обделил нас правами, открываем пункт Свойства папки меню Сервис, переходим к вкладке Вид и в подгруппе Скрытые файлы и папки выбираем Не показывать скрытые файлы и папки. Жмем OK. Папка исчезла. Главное — помнить ее имя и местоположение. Еще раз предупреждаю: обнаружить устроенное нами очень легко. Достаточно просто вернуть назад режим отображения скрытых данных, а иногда и вообще посмотреть на строку состояния.

Способ второй. Для гурманов. Есть такая замечательная программка — TailGrower. Есть еще и десяток ей подобных, но разница в том, что она совершенно простая, бесплатная (точнее, распространяется по принципу donationware: хочешь — плати, не хочешь — как хочешь) и весит всего лишь 85 килобайт. Особенно мощной ее не назовешь, но нам этого и не надо. Качать отсюдова: сайт . Суть такая: это детище софтовой индустрии предназначено для "приращивания" в конец файлов нескольких форматов каких-либо других файлов, которые оттуда потом можно вытащить. Короче, пакуем "секретные" данные в архив, запускаем TailGrower, выбираем исходным файлом какой-нибудь видеофайл, установщик или чего еще покрупнее (поддерживаются форматы EXE, DLL, BMP, JPG, AVI, MG, WMV, RAR, ZIP, DOC) и присобачиваем наш архив в конец файла. При необходимости — оттуда достаем. Остается, правда, вопрос, куда девать саму программу. Можно просто записать исполняемый файл софтины (а ничего другого для работы ей и не надо), скажем, куда-нибудь в F:\Program Files\Common Files, где ее вряд ли будут искать.

Способ третий. Для конспираторов. В чистом виде непригоден для сохранения файлов, но конфиденциальность обеспечивает на 110%, а в комбинации с другими способами позволяет добиться впечатляющих успехов в "бронировании" собственной инфы. Речь идет об использовании мощнейшего средства шифрования — программы под названием PGP. В принципе, эта софтина изначально не предназначена для сугубо бытового использования, равно как не была ориентирована и на хакерскую аудиторию, которая, впрочем, программу полюбила и стала ее интенсивно эксплуатировать. Итак, отправляемся сюда: сайт и качаем. Здесь лежит бесплатная версия с ограниченной функциональностью, но на сайте разработчика можно приобрести и шароварный релиз, более мощный. С другой стороны, если за вами не охотится КГБ, в переходе на "продвинутую" версию резона немного. В противном случае — вы пришли не по адресу:-(.

Способ четвертый. Для извергов (поклонники переводного творчества господина Роберта Линна Асприна, думается, меня поймут:)). Не знаю, какими словами можно охарактеризовать эту идею. Поэтому и не буду пытаться. Просто объясняю концепцию: какой файл, по-вашему, нельзя открыть, изменить и удалить? Тот, который занят другой программой, не правда ли? Вот мы с вами и напишем небольшую программку, которая открывала бы наши файлы, не давая другим приложениям share-доступа, и освобождала их по нашему требованию. От глаз посторонних мы ее спрячем и вызывать будем по заданному сочетанию клавиш. Таким образом, когда озлобленный супостат бросится удалять ваши данные, его ждет приятный сюрприз: он попросту не сможет этого сделать. Прятать нашу программу от Task Manager мы не будем (ибо, скажем, в Окнах ХР это сделать весьма непросто), а просто попытаемся ее замаскировать. Если вы делите с кем-то компьютер с девяносто восьмыми "Окнами", то отсылаю вас к статье Fireangel в КГ №7, где прятанье от менеджера задач не-NT-систем описано довольно подробно.

Теперь об инструментах. Я лично простоты ради писал "заниматель" в Borland C++ Builder, и код приведу, соответственно, для него же. В принципе, портировать его в тот же Delphi можно буквально на ходу. Особых трудностей не должно возникнуть и с MS Visual C++ или Visual Basic. Итак, сначала создаем новую форму. Ее Name оставим в покое, а вот компоненты в дальнейшем я буду именовать ради простоты и чтобы не путаться в многочисленных номерах компонентов одного класса. Как все это будет выглядеть в вашей версии — ваше дело. Как говорится, хозяин — барин. Для начала перетаскиваем на форму компонент CheckListBox (вкладка Additional) и сразу переименовываем его в FList. Теперь тащим на форму (я лично предварительно создал наименованную панельку Standard -> GroupBox) две простые кнопки (Standard -> Button) — для начала. Одну из них именуем Add, а вторую — Remove. Еще один компонент, который потребуется нам сразу же — это OpenDialog с вкладки Dialogs. Его мы назовем FileAdd. Теперь находим где-то в начале кода следующий текст:

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}

И вписываем туда (пояснение для отчаянно начинающих — "туда" суть "между фигурных скобок") такую инструкцию:

FList-> Items-> Clear();

Каждый раз, когда мы очищаем список Items этого компонента, там всегда остается по крайней мере один пункт. Его программа удалит сама при запуске. Затем, еще раньше, чем приведенный выше код, находим декларацию нашей формы (TForm1 *Form1;) и пишем следующей строкой (на самом деле то, где мы пишем, не суть важно, просто лучше держать все объявления переменных в одном и том же месте):

struct _file
{AnsiString name;
HANDLE handle;
} opened[256];
int a, b, x;
AnsiString fn;

Мы объявили структуру _file, которая пригодится нам позднее, когда возникнет необходимость ставить в соответствие открытый программой файл и его название, дабы его можно было безболезненно убрать как из списка, так и из памяти. Здесь же мы создали массив opened, который будет включать в себя информацию об открытых нами файлах, храня ее максимум в 256 структурах _file — больше вряд ли потребуется. Ну и, наконец, целочисленные a, b и x и строка fn типа AnsiString — просто служебные переменные, которые понадобятся нам в коде. Теперь дважды кликаем на добавленной нами кнопке Add и пишем:

void __fastcall TForm1::AddClick(TObject *Sender)
{
FileAdd-> Execute();
fn=FileAdd-> FileName;
opened[x].handle=CreateFile(fn.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0);
opened[x].name=fn;
FList-> Items-> Add(fn);
x++;
}

В этом фрагменте кода имя открытого посредством нашего диалогового окна файла добавляет одноименный Item в список файлов и используется в функции CreateFile, которая открывает файл, делая его недоступным для других приложений. Обратите внимание, что, если файла с заданным именем просто не существует, функция не сработает (не создаст пустой файл), поскольку вызвана с аргументом OPEN_EXISTING. Если вы захотите, чтобы добавленные в список файлы открывались с возможностью последующего просмотра, блокируя, однако, попытки редактирования и/или удаления, замените третий аргумент (в приведенном выше коде равный нулю) на FILE_SHARE_READ. За более подробным описанием функции CreateFile, если кому оно понадобится, отсылаю вас к Windows SDK Help.

Ну-с, с загрузочной частью мы закончили. Хорошо бы научить программу еще и удалять файлы из списка. Здесь как раз нам и понадобится описанная нами структура _file, ведь нужно не только убирать элементы ChechkListBox, но и закрывать соответствующие файлы, а для этого нам нужны их handle. С учетом того, что файлы из списка могут удаляться выборочно, одного массива целых чисел недостаточно: скажем, удалили второй элемент строки — тогда бывший третий элемент станет вторым, бывший четвертый — третьим и т.д. А если удалят еще файл? И еще?.. Или добавят еще один в конец поредевшего списка? В результате все окажется в таком хаосе, что одних только номеров будет недостаточно для определения handle файлов. Все это напоминает пресловутую историю о том, как одному мальчику захотелось яблока с самого низа высокой кучки — несчастный ребенок был погребен яблочной лавиной (история литературная, так что можете не особенно за него беспокоиться:)). Что делать? Можно, конечно, вносить изменения в числовой массив по мере удаления и добавления файлов — но мы пойдем другим путем;-). Вернее говоря, мы уже выбрали эту дорогу, когда создали структуру _file, где handle файла ставится в соответствие не его номер в списке, а его имя, являющее собой уникальное значение. Затем при удалении handle файла будет определяться путем нахождения одинаковых значений name одного из элементов структуры и строки в нашем списке. Жмем кнопку удаления Remove и набираем:

void __fastcall TForm1::RemoveClick(TObject *Sender)
{
for(b=0; b Items-> Count; b++)
{
if(FList-> Checked[b]==true) {
for(a=0; a<256; a++) {if(opened[a].name==flist-> Items-> Strings[b]) CloseHandle(opened[a].handle);}
FList-> Items-> Delete(b); }
}
}

Главная часть программы готова. За исключением механизма скрытия/показа по горячей клавише, о котором мы поговорим в следующий раз, в наше детище осталось вписать буквально пару рюшечек, которые немного упрощают работу. Сначала добавим кнопку инвертирования выделения (в моем случае ее Name — Invert). Вешаем на нее нехитрый код:

void __fastcall TForm1::InvertClick(TObject *Sender)
{
for(b=0; b Items-> Count; b++)
{
if(FList-> Checked[b]==false) FList-> Checked[b]=true;
else if(FList-> Checked[b]==true) FList-> Checked[b]=false;
}
}

Здесь, думаю, все понятно. Теперь создадим еще один OpenDialog и один SaveDialog и назовем их LoadListDialog и SaveListDialog
соответственно. Как сохранить список — вопрос наивный:

SaveListDialog-> Execute();
FList-> Items-> SaveToFile(SaveListDialog-> FileName);

Загрузка несколько более проблемна, ведь грузить нужно не только список, но и соответствующие файлы; а сначала нелишним было бы очистить список и закрыть все ранее открытые файлы. Итак:

void __fastcall TForm1::LoadListClick(TObject *Sender)
{
for(a=0; a<256; a++) {if(!opened[a].handle) closehandle(opened[a].handle);}
LoadListDialog-> Execute();
FList-> Items-> LoadFromFile(LoadListDialog-> FileName);
for(b=0; b Items-> Count; b++)
{
opened[b].name=FList-> Items-> Strings[b];
opened[b].handle=CreateFile(FList-> Items-> Strings[b].c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0);
}
}

В сущности, все это — дубляж уже использованного кода, так что, полагаю, пояснения не нужны. Напоследок, для пущей солидности, "повесим" на форму кнопку выхода, назовем ее Quit и назначим ей соответствовать своему названию:

void __fastcall TForm1::QuitClick(TObject *Sender)
{
Close();
}

Однако, как и всякому себя уважающему приложению, нашей программе потребуется запросить у пользователя подтверждение выхода, причем вне зависимости от того, использует он для этого созданную нами кнопку или знаменитый "крестик в правом верхнем углу". Для этого выбираем объект Form1 в Object Inspector, открываем вкладку Events, жмем напротив события OnClose и вводим такой код:

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if(MessageBox(Handle, "Вы правда хотите выйти?", "Здесь могла бы быть ваша реклама", MB_YESNO)==ID_YES) Action = caFree;
else Action = caNone;
}

Если при вызове сообщения с кнопками Yes и No пользователь утвердительно ответит на вопрос о своем желании покинуть программу (нажмет Yes), то форма будет закрыта. В противном случае действие будет отменено.

Вот и все на сегодня. В следующий раз мы с вами поговорим о том, как скрыть нашу форму "с глаз долой" и вызывать ее назад по горячей клавише, и заодно обсудим прием сообщений, направляемых нашей программе Windows. Ну и, естественно, ждите еще пару шизофренических способов спасения собственных файлов:). Свои идеи при желании можете отмыливать мне — все они будут по крайней мере рассмотрены. До новых встреч!

Михаил Федотов AlsoKnownAs $ky$pe@R, skyspear@tut.by, Минск, 2005


Компьютерная газета. Статья была опубликована в номере 15 за 2005 год в рубрике soft :: файлы

©1997-2024 Компьютерная газета