Разработка программы "Формирование и проверка контрольной суммы кластеров"

ВВЕДЕНИЕ



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

Персональный компьютер, как известно, является универсальным устройством для обработки информации. Персональные компьютеры могут выполнять практически любые действия по обработке информации. Для этого необходимо составить для компьютера на понятном ему языке точную и подробную последовательность инструкций (программу), как надо обрабатывать информацию.

Абсолютное большинство всех персональных компьютеров мира работают под операционной системой Windows разных версий. Поэтому и большинство программ, которые создаются, созданы для использования именно под ОС Windows. Несложно понять потенциальную применимость любой программы, ведь работа нескольких профессиональных программистов может помочь миллионам пользователей в их работе, разнообразить их досуг, облегчить общение и многое другое. 

В современных условиях разработки программного обеспечения сложно придумать что-нибудь новое, поэтому практически в каждом направлении разработки прикладных программ ведется ожесточенная борьба «за пользователя». Если раньше программа должна была всего лишь выполнять определенные функции, то теперь она должна обладать еще и рядом дополнительных свойств: удобным интерфейсом, простотой использования, гармоничностью дизайна. 

			
ОБЩИЕ СВЕДЕНИЯ В ОБЛАСТИ ФОРМИРОВАНИЯ КОНТРОЛЬНОЙ СУММЫ И ПРОВЕРКИ КЛАСТЕРОВ 



Целью данного курсового проекта является разработка программного обеспечения под названием «Подсчет и проверка контрольной суммы кластеров». Очевидно, что для выполнения задания в приложении должны быть реализованы функции просмотра параметров жесткого диска указанной операционной системы и анализа его структуры, также подсчета контрольной суммы. Следует отметить, что для понимания программных возможностей разрабатываемой программы необходимы конкретные знания о предметах исследования – стуктура файловых систем Windows и контрольная сумма.



			Основные элементы в файловой системе Windows и их взаимодействие



Файловая система (англ. file system) — регламент, определяющий способ организации, хранения и именования данных на носителях информации. Она определяет формат физического хранения информации, которую принято группировать в виде файлов. Конкретная файловая система определяет размер имени файла (папки), максимальный возможный размер файла и раздела, набор атрибутов файла. Некоторые файловые системы предоставляют сервисные возможности, например, разграничение доступа или шифрование файлов.

Файловая система связывает носитель информации с одной стороны и API для доступа к файлам — с другой. Когда прикладная программа обращается к файлу, она не имеет никакого представления о том, каким образом расположена информация в конкретном файле, так же, как и на каком физическом типе носителя (CD, жёстком диске, магнитной ленте или блоке флеш-памяти) он записан. Всё, что знает программа — это имя файла, его размер и атрибуты. Эти данные она получает от драйвера файловой системы. Именно файловая система устанавливает, где и как будет записан файл на физическом носителе (например, жёстком диске).

С точки зрения операционной системы, весь диск представляет собой набор кластеров размером от 512 байт и выше. Драйверы файловой системы организуют кластеры в файлы и каталоги (реально являющиеся файлами, содержащими список файлов в этом каталоге). Эти же драйверы отслеживают, какие из кластеров в настоящее время используются, какие свободны, какие помечены как неисправные.

Кластер (англ. cluster) — в некоторых типах файловых систем логическая единица хранения данных в таблице размещения файлов, объединяющая группу секторов. Например, на дисках с размером секторов в 512 байт, 512-байтный кластер содержит один сектор, тогда как 4-килобайтный кластер содержит восемь секторов.

Как правило, это наименьшее место на диске, которое может быть выделено для хранения файла.

Понятие кластер используется в файловых системах FAT и NTFS. Другие файловые системы оперируют схожими понятиями (зоны в Minix, блоки в Unix). 

	


Рисунок 1.1 – Структура диска

На рисунку 1.1 показаны основные элементы структуры диска:

Дорожка.

Геометрический сектор.

Сектор дорожки.

Кластер.



 Понятие контрольной суммы, ее предназначение



Контрольная сумма — некоторое значение, рассчитанное из последовательности данных путём применения определённого алгоритма, используемое для проверки правильности передачи данных (для исключения влияния каких-либо помех при передаче).

С точки зрения математики контрольная сумма является хеш-функцией, используемой для вычисления контрольного кода — небольшого количества бит внутри большого блока данных, например, сетевого пакета или блока компьютерного файла, применяемого для обнаружения ошибок при передаче или хранении информации. Значение контрольной суммы добавляется в конец блока данных непосредственно перед началом передачи или записи данных на какой-либо носитель информации. Впоследствии оно проверяется для подтверждения целостности данных.

Популярность использования контрольных сумм для проверки целостности данных обусловлена тем, что подобная проверка просто реализуема в двоичном цифровом оборудовании, легко анализируется и хорошо подходит для обнаружения общих ошибок, вызванных наличием шума в каналах передачи данных.

Одним из методов подсчета контрольной суммы является циклический избыточный код (в частности, CRC32), применяется для проверки целостности передачи данных. Программы-архиваторы включают CRC исходных данных в созданный архив для того, чтобы получающий мог удостовериться в корректности полученных данных. Такая контрольная сумма проста в реализации и обеспечивает низкую вероятность возникновения коллизий.

Алгоритм вычисления контрольной суммы (англ. Cyclic redundancy code, CRC — циклический избыточный код) — способ цифровой идентификации некоторой последовательности данных, который заключается в вычислении контрольного значения её циклического избыточного кода.

Алгоритм CRC базируется на свойствах деления с остатком двоичных многочленов, то есть многочленов над конечным полем GF(2). Значение CRC является по сути остатком от деления многочлена, соответствующего входным данным, на некий фиксированный порождающий многочлен.

Каждой конечной последовательности битов  взаимно-однозначно сопоставляется двоичный многочлен , последовательность коэффициентов которого представляет собой исходную последовательность. Например, последовательность битов 1011010 соответствует многочлену:






Нетрудно видеть, что количество различных многочленов степени меньшей N равно 2N, что совпадает с числом всех двоичных последовательностей длины N.

Значение CRC с порождающим многочленом G(x) степени N определяется как битовая последовательность длины N, представляющая многочлен R(x), получившийся в остатке при делении многочлена P(x), представляющего входной поток бит, на многочлен G(x):







где:

R(x) — многочлен, представляющий значение CRC.

P(x) — многочлен, коэффициенты которого представляют входные данные.

G(x) — порождающий многочлен.

 — степень порождающего многочлена.

Умножение xN осуществляется приписыванием N нулевых битов к входной последовательности, что улучшает качество хеширования для коротких входных последовательностей.

При делении с остатком степень многочлена-остатка строго меньше степени многочлена-делителя, то есть при делении на многочлен G(x) степени N можно получить 2N различных остатков от деления. При «правильном» выборе порождающего многочлена G(x), остатки от деления на него будут обладать нужными свойствами хеширования — хорошей перемешиваемостью и быстрым алгоритмом вычисления. Второе обеспечивается тем, что степень порождающего многочлена обычно пропорциональна длине байта или машинного слова (например 8, 16 или 32).

Операция деления на примитивный полином также эквивалентна следующей схеме:

Пусть выбран примитивный полином, задающий цикл де Брейна 0010111001011100… и блок данных 0111110, построена таблица, верхняя строка заполнена блоком данных, а нижние строки — смещения на 0,1,2 бит цикла де Брейна







Тогда контрольная сумма будет равна операции XOR тех столбцов, над которыми в верхней строке расположена 1. В этом случае, 010 xor 101 xor 011 xor 111 xor 110 = 101 (CRC).

Алгоритм CRC32, используемый данным проектом, основан на примитивном полиноме 0xEDB88320 (зеркальное отображение полинома 0x04C11DB7) и является одним из самых распространенных методов подсчета контрольной суммы.

Еще используется криптографический алгоритм MD5.

MD5 (англ. Message Digest 5) — 128-битный алгоритм хеширования, разработанный профессором Рональдом Л. Ривестом из Массачусетского технологического института (Massachusetts Institute of Technology, MIT) в 1991 году. Предназначен для создания «отпечатков» или «дайджестов» сообщений произвольной длины. Является улучшенной в плане безопасности версией MD4.[1] Зная MD5-образ (называемый также MD5-хеш или MD5-дайджест), невозможно восстановить входное сообщение, так как одному MD5-образу могут соответствовать разные сообщения. Используется для проверки подлинности опубликованных сообщений путём сравнения дайджеста сообщения с опубликованным. Эту операцию называют «проверка хеша» (hashcheck).

На вход алгоритма поступает входной поток данных, хеш которого необходимо найти. Длина сообщения может быть любой (в том числе нулевой). Запишем длину сообщения в L. Это число целое и неотрицательное. Кратность каким-либо числам необязательна. После поступления данных идёт процесс подготовки потока к вычислениям.

Ниже приведены 5 шагов алгоритма:

Шаг 1. Выравнивание потока.

Шаг 2. Добавление длины сообщения.

Шаг 3. Инициализация буфера.

Шаг 4. Вычисление в цикле.

Шаг 5. Результат вычислений.



Выбор платформы и языка разработки приложения



Перед началом разработки был произведен анализ требований к программному обеспечению, результаты которого были преобразованы в требования к платформе разработки:

простота организации и программирования пользовательского интерфейса;

возможность работать на компьютерах с версией ОС Windows ХР и выше;

возможность работы с файловой системой Windows;

возможность работы с математическими операциями.

В результате было принято решение разрабатывать приложение на основе технологии .NET, т.к. она является «родной» для операционных систем семейства Windows и позволяет работать с файловой системой. .NET Framework — программная технология от компании Microsoft, платформа для создания и развертывания приложений. Она предоставляет высокопроизводительную, основанную на стандартах, многоязыковую среду, которая позволяет интегрировать существующие приложения с приложениями и сервисами следующего поколения, а также решать задачи развертывания и использования интернет-приложений. .NET Framework состоит из трех основных частей - общеязыковой среды выполнения, иерархического множества унифицированных библиотек классов и компонентной версии ASP, называемой ASP.NET. Т.к. при работе с платформой . NET существует возможность работать с несколькими языками программирования выбор был сделан в пользу языка C#, как наиболее распространенного и развитого языка разработки приложений. 

Необходимо упомянуть также о возможности визуальной разработки программного обеспечения, которую предоставляет платформа .NET. Очевидно, что упрощение создания пользовательского интерфейса позволит уделить больше внимания функциональной полноте разрабатываемой программы. 



			Функциональные возможности разрабатываемого программного обеспечения



Основываясь на правиле, что для программного обеспечения первичным является выполнение им необходимых функций, выделим основные действия, которые должна выполнять разрабатываемая программа:

отображение носителей информации подключенных к ОС;

отображение параметров нужного носителя информации;

формирование и вывод контрольной суммы кластеров;

проверку контрольной суммы кластеров.

Таким образом, каждая из вышеперечисленных функций должна быть реализована для выполнения задания к курсовому проекту. Очевидно, что описанные функции являются каркасом приложения, которое также должно отвечать следующим требованиям: минимальные аппаратные требования, интуитивность пользовательского интерфейса и удобство работы с ним, корректность работы в исключительных ситуациях.

			
РАЗРАБОТКА СТРУКТУРЫ И АЛГОРИТМОВ ПРОГРАММЫ

		

			Логическая структура интерфейса пользователя



Для построения приложения, которое реализовывает предполагаемый функционал и приспособлено к работе с конечным пользователем было принято решения о распределении логически-функциональной нагрузки между несколькими окнами приложения. Это обусловлено тем, что нагромождение всех возможных настроек, функций и информационных блоков в одном окне приводит перегрузке интерфейса и неудобству работы с приложением.

Для организации интерфейса разработана следующая структура окон программы:

1. Основное окно программы – список для вывода подключенных устройств памяти, а также выбора между ними, текстовое поле выводящее информацию о выбранном устройстве, кнопка анализа, текстовое поле хранящее информацию не зависимо от выбора, для сравнения, кнопка проверки алгоритмов.

2. Окно проверки алгоритмов – имеет 2 кнопки для запуска нужного алгоритма, 2 текстовых поля для вывода результатов подсчета, по одному на каждый алгоритм и по одному поля для ввода информации.

Навигация между окнами производиться стандартными средствами Windows, а также кнопки проверки алгоритмов.



			 Программная организация отображения информации об устройствах памяти и контрольных сумм



Учитывая тот факт, что файловая система ОС Windows является иерархической базой данных, объем которой достаточно велик, необходимо использовать промежуточные программные средства для хранения и отображения пользователю информации о ней.

Для этой цели в рамках разрабатываемого приложения был создан класс HardDrive. Данный класс упрощает как хранение информации, так и отображение ее на экране в виде, удобном для пользователя. Условно класс HardDrive хранит структуру объектов, каждый из которых может иметь неограниченное число дочерних узлов. Также стоит указать, что для изменения атрибутов файла в программе использовался класс File из библиотеки .NET.



				 Структурная декомпозиция функций разрабатываемого программного обеспечения



Для реализации функциональных возможностей приложения, описанных в пункте 1.3 были описан набор программных функций, реализуемых приложением. Большинство из этих функций были описаны в классе основного окна приложения. Далее приведены декларации этих функций с описанием действий, которые они выполняют:

	private void Form1_Load(object sender, EventArgs e) – функция вызывающаяся при загрузки программы, вызывает окно спрашивающие, действительно ли пользователь хочет считать информация и запускает функции взятия информации и добавления ее в список.

	private void GetHardDiskInfo() – функция считывания информации о запоминающем устройстве.

	private void AddHDDItemToListview() – функция добавляющая в список подключенные запоминающие устройства.

	private void AddItemToListview(ListViewGroup GroupName, int IndexNumber, string ItemName, int ImageIndex, string ItemTAG) – функция добавляющая информацию в структуру HardDrive.

	private void WriteHDDText() – функция добавляющая информацию о запоминающем устройстве в текстовое поле.

	private void listView1_SelectedIndexChanged(object sender, EventArgs e) – функция определяющая какое устройство пользователь выбрал в списке.

	private void button1_Click(object sender, EventArgs e) – функция определяющая действие при нажатии кнопки «Анализ».

	private void button2_Click(object sender, EventArgs e) – функция определяющая действие при нажатии кнопки «Проверить алгоритм».

	private void button1_Click(object sender, EventArgs e) – функция определяющая действие при нажатии кнопки «CRC32».

	public static uint CalculateCRC(System.IO.Stream stream) – функция запускающая формирование контрольной суммы CRC32.

	private void button2_Click(object sender, EventArgs e) – функция определяющая действие при нажатии кнопки «MD5».

	Также созданы функции по формированию контрольной суммы MD5, перечисленные ниже:

	private static void FF(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)

	private static void GG(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)

	private static void HH(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)

	private static void II(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)

	private static void MD5_Init()

Описанные выше декларации функций отображают внутреннюю организацию приложения на уровне конкретных действий. Вызов этих функций в приложении не будет прямым, а будет производиться в функциях-обработчиках событий от конкретных компонентов пользовательского интерфейса. Это обусловлено тем, что пользователь напрямую не работает с файловой системой, а обращается к информации дерева класса HardDrive. 


3. РЕАЛИЗАЦИЯ ПРОГРАММЫ



Приложение, которое является результатом курсового проектирования было реализовано на языке С# платформы .NET. При написании программы был использован объектно-ориентированный подход: были созданы и описаны два класса, каждый из которых включает в себя поведение одного из окон программы – Form1, Form2, а также диалоговое окно MessageBox спрашивающее разрешение пользователя на доступ программы к данным.

MessageBox реализует отображение окна с подтвеждением, на здоступ приложением к информации. Вид окна представлен на рисунке 3.1.





Рисунок 3.1 – Вид диалогового окна подтверждения



MessageBox имеют очень простую программную реализацию, которая не предполагает дополнительных объяснений, поэтому его код не описывается в пояснительной записке.



 Программная реализация класса Form1



Класс Form1 описывает поведение основного окна приложения, внешний вид которого представлен на рисунке 3.2.

Как видно на рисунке 3.2, основное окно разработанного приложения Контрольная сумма включает в себя следующие элементы:

	список подключенных устройств хранения данных, реализуемый объектом HDDGroup. С помощью списка производится выбор устройства;

	текстовое поле отображения информации, реализуемое объектом richTextBox1;

	текстовое поле отображения информации для проверки и сравнения, реализуемое объектом richTextBox2; 

	кнопку для анализа (Анализ);

	кнопку запуска и проверки алгоритмов (Проверить алгоритм);

	стандартные элементы управления окном в ОС семейств Windows.

	



Рисунок 3.2 – Внешний вид главного окна приложения



Конструктор, обработчики событий и члены класса Form1

Инициализация объектов-членов класса Form1 осуществляется в конструкторе класса. Ниже приведен код конструктора с комментариями:

public Form1() {

//инициализация компонента – необходима для создания окна

 InitializeComponent();

}

Также несколько методов класса Form1, код которого приведен в приложении являются обработчиками событий: нажатие кнопки, работа с информацией.

Программная реализация функции private void AddHDDItemToListview()

Данная функция добавляет в список подключенные запоминающие устройства. Ниже приведен код функции.

 private void AddHDDItemToListview()

 {

 //Makes the Search group:::......

 ListViewGroup HDDGroup = new ListViewGroup();

 HDDGroup.Header = "HardDrive(s) :";

 HDDGroup.HeaderAlignment = HorizontalAlignment.Left;

 HDDGroup.Name = "HardDrive(s)";

 //Adds the search group...

 listView1.Groups.Add(HDDGroup);

 int i = 0;

 foreach (HardDrive x in hdCollection)

 { AddItemToListview(HDDGroup, i, x.Model.ToString(), 0, "1");

 i++; }

 HDDGroup = null; }

Программная реализация функции private void AddItemToListview(ListViewGroup GroupName, int IndexNumber, string ItemName, int ImageIndex, string ItemTAG)

Данная функция добавляет информацию в структуру HardDrive. Ниже приведен код функции.

private void AddItemToListview(ListViewGroup GroupName, int IndexNumber, string ItemName, int ImageIndex, string ItemTAG)

 { ListViewItem NewItem = new ListViewItem();

 ListViewItem.ListViewSubItem NewSubItem = new ListViewItem.ListViewSubItem();

 NewSubItem.Text = IndexNumber.ToString();

 NewSubItem.Name = "Subitem1";

 NewItem.SubItems.Add(NewSubItem);

 NewItem.SubItems.Add(NewSubItem);

 NewItem.Name = ItemName;

 NewItem.Text = ItemName;

 NewItem.Group = GroupName;

 NewItem.ImageIndex = ImageIndex;

 NewItem.Tag = ItemTAG;

 listView1.Items.Add(NewItem);

 NewItem = null;

 NewSubItem = null;

 // Group = null; }

Программная реализация функции private void private void listView1_SelectedIndexChanged(object sender, EventArgs e)

Данная функция определяет какое устройство пользователь выбрал в списке. Ниже приведен код функции.

private void listView1_SelectedIndexChanged(object sender, EventArgs e)

 { int selected_index;

 try {

 //MessageBox.Show(listView1.SelectedItems[0].Tag.ToString());

 selected_index = listView1.SelectedItems[0].Index;

 switch (listView1.SelectedItems[0].Tag.ToString())

 { case "1":

 WriteHDDText();

 break; } }

 catch (Exception)

 { //Do nothing } }


2.5 Программная реализация класса Form2

программа контрольная сумма кластер

Класс Form2 описывает поведение дополнительного окна приложения, внешний вид которого представлен на рисунке 3.3.





Рисунок 3.3 – Внешний вид дополнительного окна приложения



Как видно на рисунке 3.3, дополнителное окно разработанного приложения Контрольная сумма включает в себя следующие элементы:

	четыре текстовых поля для ввода и вывода информации проверки алгоритмов формирования контрольной суммы кластеров, реализованные объектами textBox1, textBox2, textBox3, textBox4 ;

	кнопку для запуска проверки алгоритма CRC32(проверить CRC32);

	кнопку для запуска проверки алгоритма MD5 (проверить MD5);

	стандартные элементы управления окном в ОС семейств Windows.

Конструктор, обработчики событий и члены класса Form2

Инициализация объектов-членов класса Form2 осуществляется в конструкторе класса. Ниже приведен код конструктора с комментариями:

public Form2() {

//инициализация компонента – необходима для создания окна

 InitializeComponent();

}

Также несколько методов класса Form2, код которого приведен в приложении являются обработчиками событий: нажатие кнопки, работа с информацией.

Программная реализация обработчика сообщений private void button1_Click(object sender, EventArgs e)

Определяет действие при нажатии кнопки «CRC32». Код обработчика приведен ниже.

private void button1_Click(object sender, EventArgs e)

 { // Читаем 

 System.IO.FileStream stream1 = System.IO.File.OpenRead(textBox1.Text.ToString());

 textBox3.Text=(string.Format("{0:X}", CalculateCRC(stream1))).ToString();}

Программная реализация функции public static uint CalculateCRC(System.IO.Stream stream)

Данная функция реализует алгоритм формирования контрольной суммы CRC32. Код функции приведен ниже с комментариями.

public static uint CalculateCRC(System.IO.Stream stream) 

		{ 	const int buffer_size = 1024; 

			const uint POLYNOMIAL = 0xEDB88320; 

 			uint result = 0xFFFFFFFF; 

			uint Crc32; 

			byte[] buffer = new byte[buffer_size]; 

			uint[] table_CRC32 = new uint[256]; 

			unchecked 

			{ 	// Инициалиазация таблицы

				for (int i = 0; i < 256; i++) 

				{ 	Crc32 = (uint)i; 

 					for (int j = 8; j > 0; j--) 

					{ if ((Crc32 & 1)==1) 

					Crc32 = (Crc32 >> 1) ^ POLYNOMIAL; 

					else 

					Crc32 >>= 1; } 

 					table_CRC32[i] = Crc32; } 

 				// Чтение из буфера

				int count = stream.Read(buffer, 0, buffer_size); 

				// Вычисление CRC

				while (count > 0) 

				{ for (int i = 0; i < count; i++) 

					{ result = ((result) >> 8) 

						^ table_CRC32[(buffer[i]) 

						^ ((result) & 0x000000FF)]; 	} 

 					count = stream.Read(buffer, 0, buffer_size); } } 

 			return ~result; }

Программная реализация обработчика сообщений private void button2_Click(object sender, EventArgs e)

Определяет действие при нажатии кнопки «проверка MD5». Также мостит в себе алгоритм формирования контрольной суммы MD5 и все прилагающие функции. Код из-за большого объема не описывается, его можно просмотреть в общем коде программы в Приложении Б. 


3. ТЕСТИРОВАНИЕ ПРОГРАММЫ И РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ



3.1 Тестирование программы



В ходе выполнения задания курсового проектирования было проведено тестирование результирующего программного продукта.

В результате тестирования программы были установлены как недостатки разработанных алгоритмов, так и несовершенство их программной реализации, как-то:

	зависимость от прав администратора;

	невозможность изменения кластера с помощью прямого доступа, а сложности при проверке;

	проблемы с прямым доступом, связанные с новыми введенными ограничениями в ОС Windows 7.

Обнаруженные недостатки были исправлены как на уровне алгоритма (если требовалось), так и на уровне программной реализации.

Также во время тестирования программы были определены минимальные требования к оборудованию и программному обеспечению для использования данного продукта:

ОС Windows XP, процессор Pentium IV 1 ГГц, ОЗУ 128 Мб, 100 KB свободного места на жестком диске, библиотека .NET Framework 4.0 и выше.



3.2 Руководство пользователя



После запуска программы на экране отображается окно со следующими элементами:

	список подключенных устройств хранения данных. С помощью списка производится выбор устройства, для которого пользователь хочет применить нужные операции;

	текстовое поле отображения информации об устройстве и контрольная сумма кластеров;

	текстовое поле отображения информации для проверки и сравнения; 

	кнопка для анализа (Анализ), активирует второе текстовое поле;

	кнопка запуска и проверки алгоритмов (Проверить алгоритм);

	четыре текстовых поля для ввода и вывода информации проверки алгоритмов формирования контрольной суммы кластеров;

	кнопка для запуска проверки алгоритма CRC32(проверить CRC32);

	кнопка для запуска проверки алгоритма MD5 (проверить MD5);




ВЫВОДЫ



Во время выполнения задания были закреплены навыки использования функций библиотеки .NET Framework, углублены знания в языке C# и написании программ под ОС семейства Windows.

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

В частности, были решены задачи корректной работы приложения, правильного выведения необходимой информации на экран. Также были решены задачи выборки нужной информации о файловой системе и ее параметрах в ОС Windows, преобразование полученной информации к форме, удобной для пользователя.

В результате выполнения курсового проекта было разработано приложение с использованием библиотеки .NET Framework – программа Формирования и проверки контрольной суммы клатеров.

Можно сказать, что поставленное при курсовом проектировании задание было реализовано полностью. 

Недостатками результирующего программного средства являются:

	недостаточная гармоничность и привлекательность графической составляющей проекта;

	небольшие задержки при выполнении приложения на компьютерах с малым объемом оперативной памяти;

	требования к предустановленном ПО (в частности .NET Framework 4.0)

Данные недостатки могли бы быть исправлены при наличии более широких знаний и навыков решения задач подобного рода.


СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ



1. CLR via C#. Программирование на платформе Microsoft .NET Framework 2.0 на языке C#. Мастер-класс./ Пер. с англ. – М.: Издательство «Русская редакция»; СПб.: Питер, 2007. – 656 с.

2. С# в подлиннике: Пер. с англ./ Дейтел Х., Дейтел П., Листфиолд Дж., Нието Т., Йегер Ш., Златкина М. – СПб.Ж БХВ-Петербург, 2006. – 1056 с.

3. http://msdn.microsoft.com/

4. http://intuit.ru/

5. http://windxp.ru/

6. ДСТУ 3008-95 "ЗВІТИ У СФЕРІ НАУКИ І ТЕХНІКИ. Структура та правила оформлення".






ПРИЛОЖЕНИЕ А



Пример выполнения программы «Формирование и проверка контрольной суммы кластеров»





Рисунок 1 – Внишний вид диологового окна перед запуском сомой программы





Рисунок 2 – Внешний вид гланого окна программы






Рисунок 3 – Пример выполнения программы





Рисунок 4 – Пример выполнения проверки 




ПРИЛОЖЕНИЕ Б



Код приложения «Формирование и проверка контрольной суммы кластеров»

//Form1.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;



using System.Collections;

using System.Management;

using Microsoft.Win32;



namespace kurs_pogulyat

{

 public partial class Form1 : Form

 {

 public Form1()

 {

 InitializeComponent();

 }

 ArrayList hdCollection = new ArrayList();

 int Num_Hdd = 0;

 double TotalSize = 0;

 double TotalSpaceLeft = 0;

 bool analiz = false;

 bool OSXP = false;



 private void Form1_Load(object sender, EventArgs e)

 {

 if (MessageBox.Show("Start getting info ?\nThis may take a while, so please stand by.", "Notice", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.No)

 {

 this.Close();

 }

 else

 {

 //AddGeneralinfoTolistview();



 GetHardDiskInfo();

 AddHDDItemToListview();



 }



 }

 

 private void GetHardDiskInfo()

 {

 #region HDD_Collction of Infomation



 hdCollection.Clear();

 Num_Hdd = 0;

 TotalSize = 0;

 TotalSpaceLeft = 0;

 ManagementObjectSearcher searcher = new

 ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");



 foreach (ManagementObject wmi_HD in searcher.Get())

 {

 HardDrive hd = new HardDrive();



 #region hd.Model

 try

 {

 hd.Model = wmi_HD["Model"].ToString();

 }

 catch (Exception)

 {

 hd.Model = "Unknown";

 }

 #endregion



 #region hd.Type

 try

 {

 hd.Type = wmi_HD["InterfaceType"].ToString();

 }

 catch (Exception)

 {

 hd.Type = "Unknown";

 }

 #endregion



 #region hd.BytesPerSector

 try

 {

 hd.BytesPerSector = wmi_HD["BytesPerSector"].ToString();

 }

 catch (Exception)

 {

 hd.BytesPerSector = "Unknown";

 }

 #endregion



 #region hd.MediaType

 try

 {

 hd.MediaType = wmi_HD["MediaType"].ToString();

 }

 catch (Exception)

 {

 hd.MediaType = "Unknown";

 }

 #endregion



 #region hd.Partitions

 try

 {

 hd.Partitions = wmi_HD["Partitions"].ToString();

 }

 catch (Exception)

 {

 hd.Partitions = "Unknown";

 }

 #endregion



 #region hd.SectorsPerTrack

 try

 {

 hd.SectorsPerTrack = wmi_HD["SectorsPerTrack"].ToString();

 }

 catch (Exception)

 {

 hd.SectorsPerTrack = "Unknown";

 }

 #endregion



 #region hd.Signature

 try

 {

 hd.Signature = wmi_HD["Signature"].ToString();

 }

 catch (Exception)

 {

 hd.Signature = "Unknown";

 }

 #endregion



 #region hd.size

 try

 {

 hd.Size = wmi_HD["Size"].ToString();

 }

 catch (Exception)

 {

 hd.Size = "0";

 }

 #endregion



 #region hd.Status

 try

 {

 hd.Status = wmi_HD["Status"].ToString();

 }

 catch (Exception)

 {

 hd.Status = "Unknown";

 }

 #endregion



 #region hd.TotalCylonders

 try

 {

 hd.TotalCylinders = wmi_HD["TotalCylinders"].ToString();

 }

 catch (Exception)

 {

 hd.TotalCylinders = "Unknown";

 }

 #endregion



 #region hd.TotalHeads

 try

 {

 hd.TotalHeads = wmi_HD["TotalHeads"].ToString();

 }

 catch (Exception)

 {

 hd.TotalHeads = "Unknown";

 }

 #endregion



 #region hd.TotalSectors

 try

 {

 hd.TotalSectors = wmi_HD["TotalSectors"].ToString();

 }

 catch (Exception)

 {

 hd.TotalSectors = "Unknown"; }

 #endregion



 #region hd.TotalTracks

 try

 {

 hd.TotalTracks = wmi_HD["TotalTracks"].ToString(); }

 catch (Exception)

 {

 hd.TotalTracks = "Unknown"; }

 #endregion



 #region hd.TracksPerCylinder

 try

 {

 hd.TracksPerCylinder = wmi_HD["TracksPerCylinder"].ToString(); }

 catch (Exception)

 {

 hd.TracksPerCylinder = "Unknown"; }

 #endregion



 #region hd.SeralNo



 if (OSXP != true)

 {

 try

 {

 hd.SerialNo = wmi_HD["SerialNumber"].ToString(); }

 catch (Exception)

 {

 hd.SerialNo = "Unknown";

 } }

 else

 { }

 #endregion



 #region hd.FirmwareRevision

 try

 {

 hd.FirmwareRevision = wmi_HD["FirmwareRevision"].ToString(); }

 catch (Exception)

 {

 hd.FirmwareRevision = " "; }

 #endregion



 hdCollection.Add(hd);

 hd = null;

 Num_Hdd = Num_Hdd + 1;

 TotalSize = TotalSize + double.Parse(wmi_HD["Size"].ToString());



 }



 #region //Getting HDD's serial under XP

 if (OSXP == true)

 {

 searcher = new

 ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");



 int i = 0;

 foreach (ManagementObject wmi_HD in searcher.Get())

 {

 // get the hard drive from collection

 // using index

 HardDrive hd = (HardDrive)hdCollection[i];



 // get the hardware serial no.

 if (wmi_HD["SerialNumber"] == null)

 hd.SerialNo = "None";

 else

 hd.SerialNo = wmi_HD["SerialNumber"].ToString();



 ++i;

 }

 }

 #endregion

 searcher = new

 ManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk");



 foreach (ManagementObject wmi_HD in searcher.Get())

 {



 // get how much Freespace the HDD have left...

 if (wmi_HD["FreeSpace"] == null)

 {

 //do nothing

 }

 else

 {

 if (wmi_HD["DriveType"].ToString() == "3")

 {

 TotalSpaceLeft += double.Parse(wmi_HD["FreeSpace"].ToString());

 }

 }

 }



 // HDD_info_Done = true;

 searcher = null;



 #endregion

 }



 private void AddHDDItemToListview()

 {



 //Makes the Search group:::......

 ListViewGroup HDDGroup = new ListViewGroup();

 HDDGroup.Header = "HardDrive(s) :";

 HDDGroup.HeaderAlignment = HorizontalAlignment.Left;

 HDDGroup.Name = "HardDrive(s)";

 //Adds the search group...

 listView1.Groups.Add(HDDGroup);

 int i = 0;

 foreach (HardDrive x in hdCollection)

 {

 AddItemToListview(HDDGroup, i, x.Model.ToString(), 0, "1");

 i++; }

 HDDGroup = null; }



 private void AddItemToListview(ListViewGroup GroupName, int IndexNumber, string ItemName, int ImageIndex, string ItemTAG)

 {

 ListViewItem NewItem = new ListViewItem();

 ListViewItem.ListViewSubItem NewSubItem = new ListViewItem.ListViewSubItem();

 NewSubItem.Text = IndexNumber.ToString();

 NewSubItem.Name = "Subitem1";

 NewItem.SubItems.Add(NewSubItem);

 NewItem.SubItems.Add(NewSubItem);

 NewItem.Name = ItemName;

 NewItem.Text = ItemName;

 NewItem.Group = GroupName;

 NewItem.ImageIndex = ImageIndex;

 NewItem.Tag = ItemTAG;



 listView1.Items.Add(NewItem);

 NewItem = null;

 NewSubItem = null;

 // Group = null; }



 private void WriteHDDText()

 {

 HardDrive Hd = null;

 bool fail = false;



 try

 {

 Hd = (HardDrive)hdCollection[int.Parse(listView1.SelectedItems[0].SubItems[1].Text)]; }

 catch (Exception)

 {

 Hd = null;

 fail = true; }



 if (fail != true)

 {

 Hd = (HardDrive)hdCollection[int.Parse(listView1.SelectedItems[0].SubItems[1].Text)];



 double size_temp = double.Parse(Hd.Size);

 if (analiz == false)

 {

 richTextBox1.Clear();

 richTextBox1.Text = ("\n" +

 "Model:\n" +

 "--------------------------------------------------------\n" +

 "Model : " + Hd.Model.ToString() + "\n" +

 "Type : " + Hd.Type.ToString() + "\n" +

 "Serial No. : " + Hd.SerialNo.ToString() + "\n" +

 "Firmware Revision : " + Hd.FirmwareRevision.ToString() + "\n" +

 "\n" +

 "Characteristics:\n" +

 "--------------------------------------------------------\n" +

 "Media Type : " + Hd.MediaType.ToString() + "\n" +

 "Partitions : " + Hd.Partitions.ToString() + "\n" +

 "Signature : " + Hd.Signature.ToString() + "\n" +

 "Size : " + Hd.Size.ToString() + " Byte (" + Math.Round((((size_temp / 1024) / 1024) / 1024), 2) + " GB)" + "\n" +

 "\n" +

 "Status : " + Hd.Status.ToString() + "\n" +

 "\n" +

 "Tracks:\n" +

 "--------------------------------------------------------\n" +

 "Total Cylinders : " + Hd.TotalCylinders.ToString() + "\n" +

 "Total Heads : " + Hd.TotalHeads.ToString() + "\n" +

 "Total Sectors : " + Hd.TotalSectors.ToString() + "\n" +

 "Total Tracks : " + Hd.TotalTracks.ToString() + "\n" +

 "Bytes Pr. Sector : " + Hd.BytesPerSector.ToString() + "\n" +

 "Sector Pr. Tracks : " + Hd.SectorsPerTrack.ToString() + "\n" +

 "Tracks Pr. Cylinder : " + Hd.TracksPerCylinder.ToString() + "\n"



 ); }

 else

 {

 richTextBox2.Clear();

 richTextBox2.Text = ("\n" +

 "Model:\n" +

 "--------------------------------------------------------\n" +

 "Model : " + Hd.Model.ToString() + "\n" +

 "Type : " + Hd.Type.ToString() + "\n" +

 "Serial No. : " + Hd.SerialNo.ToString() + "\n" +

 "Firmware Revision : " + Hd.FirmwareRevision.ToString() + "\n" +

 "\n" +

 "Characteristics:\n" +

 "--------------------------------------------------------\n" +

 "Media Type : " + Hd.MediaType.ToString() + "\n" +

 "Partitions : " + Hd.Partitions.ToString() + "\n" +

 "Signature : " + Hd.Signature.ToString() + "\n" +

 "Size : " + Hd.Size.ToString() + " Byte (" + Math.Round((((size_temp / 1024) / 1024) / 1024), 2) + " GB)" + "\n" +

 "\n" +

 "Status : " + Hd.Status.ToString() + "\n" +

 "\n" +

 "Tracks:\n" +

 "--------------------------------------------------------\n" +

 "Total Cylinders : " + Hd.TotalCylinders.ToString() + "\n" +

 "Total Heads : " + Hd.TotalHeads.ToString() + "\n" +

 "Total Sectors : " + Hd.TotalSectors.ToString() + "\n" +

 "Total Tracks : " + Hd.TotalTracks.ToString() + "\n" +

 "Bytes Pr. Sector : " + Hd.BytesPerSector.ToString() + "\n" +

 "Sector Pr. Tracks : " + Hd.SectorsPerTrack.ToString() + "\n" +

 "Tracks Pr. Cylinder : " + Hd.TracksPerCylinder.ToString() + "\n"

 ); }

 size_temp = 0;

 }

 Hd = null;

 }

 private void listView1_SelectedIndexChanged(object sender, EventArgs e)

 {

 int selected_index;

 try

 {

 //MessageBox.Show(listView1.SelectedItems[0].Tag.ToString());

 selected_index = listView1.SelectedItems[0].Index;

 switch (listView1.SelectedItems[0].Tag.ToString())

 {

 case "1":

 WriteHDDText();

 break; 

 } }

 catch (Exception)

 {

 //Do nothing

 } }



 private void button1_Click(object sender, EventArgs e)

 {

 if (analiz == false)

 analiz = true;

 else

 analiz = false;

 GetHardDiskInfo();

 WriteHDDText();



 }

 private void button2_Click(object sender, EventArgs e)

 {

 Form2 f2 = new Form2();

 f2.Show();

 }



 }

}



//Form2.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.IO;

using System.Collections;



namespace kurs_pogulyat

{

 public partial class Form2 : Form

 {

 public Form2()

 {

 InitializeComponent();

 }



 //CRC 32

 private void button1_Click(object sender, EventArgs e)

 {

 

 // Читаем файл test.txt

 System.IO.FileStream stream1 = System.IO.File.OpenRead(textBox1.Text.ToString());

			

 textBox3.Text=(string.Format("{0:X}", CalculateCRC(stream1))).ToString();

 }

		/// <summary>

		/// Вычисление CRC32

		/// </summary>

		/// <param name="stream"></param>

		/// <returns></returns>

		public static uint CalculateCRC(System.IO.Stream stream) 

		{ 

			const int buffer_size = 1024; 

			const uint POLYNOMIAL = 0xEDB88320; 

 

			uint result = 0xFFFFFFFF; 

			uint Crc32; 



			byte[] buffer = new byte[buffer_size]; 

			uint[] table_CRC32 = new uint[256]; 



			unchecked 

			{ 

				// Инициалиазация таблицы

				for (int i = 0; i < 256; i++) 

				{ 

					Crc32 = (uint)i; 

 

					for (int j = 8; j > 0; j--) 

					{ 

						if ((Crc32 & 1)==1) 

							Crc32 = (Crc32 >> 1) ^ POLYNOMIAL; 

						else 

							Crc32 >>= 1; 

					} 

 					table_CRC32[i] = Crc32; 

				} 

 /

				// Чтение из буфера

				int count = stream.Read(buffer, 0, buffer_size); 

				// Вычисление CRC

				while (count > 0) 

				{ 

					for (int i = 0; i < count; i++) 

					{ 

						result = ((result) >> 8) 

							^ table_CRC32[(buffer[i]) 

							^ ((result) & 0x000000FF)]; 

					} 

 					count = stream.Read(buffer, 0, buffer_size); 

				} 

			} 

 

			return ~result; 

		}

 //MD5

 private void button2_Click(object sender, EventArgs e)

 {

 textBox4.Text = MD5File(textBox2.Text.ToString()).ToString();

 } 

 //статические переменные

 private static UInt32 A;

 private static UInt32 B;

 private static UInt32 C;

 private static UInt32 D;

 

 //номер бита сдвиг

 private const int S11 = 7;

 private const int S12 = 12;

 private const int S13 = 17;

 private const int S14 = 22;

 private const int S21 = 5;

 private const int S22 = 9;

 private const int S23 = 14;

 private const int S24 = 20;

 private const int S31 = 4;

 private const int S32 = 11;

 private const int S33 = 16;

 private const int S34 = 23;

 private const int S41 = 6;

 private const int S42 = 10;

 private const int S43 = 15;

 private const int S44 = 21;

 /* сдвиги

 r[ 0..15] := {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22} 

 r[16..31] := {5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20}

 r[32..47] := {4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23}

 r[48..63] := {6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}*/

 /* F, G, H и I основные функции алгоритма вычисления MD5

 F(X,Y,Z) =(X&Y)|((~X)&Z)

 G(X,Y,Z) =(X&Z)|(Y&(~Z))

 H(X,Y,Z) =X^Y^Z

 I(X,Y,Z)=Y^(X|(~Z))

 */

 private static UInt32 F(UInt32 x, UInt32 y, UInt32 z)

 {

 return (x & y) | ((~x) & z); 

 }

 private static UInt32 G(UInt32 x, UInt32 y, UInt32 z)

 {

 return (x & z) | (y & (~z));

 }

 private static UInt32 H(UInt32 x, UInt32 y, UInt32 z)

 {

 return x ^ y ^ z;

 }

 private static UInt32 I(UInt32 x, UInt32 y, UInt32 z)

 {

 return y ^ (x | (~z));

 }

 

 // FF, GG, HH, и II преобразоания для раундов 1, 2, 3, и 4.

 

 private static void FF(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)

 {

 a = a + F(b, c, d) + mj + ti;

 a = a << s | a >> (32 - s); 

 a += b;

 }

 private static void GG(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)

 {

 a = a + G(b, c, d) + mj + ti;

 a = a << s | a >> (32 - s);

 a += b;

 }

 private static void HH(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)

 {

 a = a + H(b, c, d) + mj + ti;

 a = a << s | a >> (32 - s);

 a += b;

 }

 private static void II(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)

 {

 a = a + I(b, c, d) + mj + ti;

 a = a << s | a >> (32 - s);

 a += b;

 }

 

 private static void MD5_Init() 

 {

 A = 0x67452301; //в памяти 0x01234567

 B = 0xefcdab89; //в памяти, 0x89abcdef

 C = 0x98badcfe; //в памяти, 0xfedcba98

 D = 0x10325476; //в памяти, 0x76543210

 }

 

 private static UInt32[] MD5_Append(byte[] input)

 {

 int zeros = 0;

 int ones = 1;

 int size = 0;

 int n = input.Length;

 int m = n % 64; //остаток от деления

 if (m < 56)

 {

 zeros = 55 - m;

 size = n - m + 64;

 }

 else

 {

 zeros = 63 - m + 56;

 size = n + 64 - m + 64;

 }

 

 ArrayList bs = new ArrayList(input);

 if (ones == 1)

 {

 bs.Add((byte)0x80); // 0x80 = $10000000

 }

 for (int i = 0; i < zeros; i++)

 {

 bs.Add((byte)0);

 }

 

 UInt64 N = (UInt64)n * 8;

 byte h1 = (byte)(N & 0xFF);

 byte h2 = (byte)((N >> 8) & 0xFF);

 byte h3 = (byte)((N >> 16) & 0xFF);

 byte h4 = (byte)((N >> 24) & 0xFF);

 byte h5 = (byte)((N >> 32) & 0xFF);

 byte h6 = (byte)((N >> 40) & 0xFF);

 byte h7 = (byte)((N >> 48) & 0xFF);

 byte h8 = (byte)(N >> 56);

 bs.Add(h1);

 bs.Add(h2);

 bs.Add(h3);

 bs.Add(h4);

 bs.Add(h5);

 bs.Add(h6);

 bs.Add(h7);

 bs.Add(h8);

 byte[] ts = (byte[])bs.ToArray(typeof(byte));

 

 // Декодинг input (byte[]) в output (UInt32[])

 

 UInt32[] output = new UInt32[size / 4];

 for (Int64 i = 0, j = 0; i < size; j++, i += 4)

 {

 output[j] = (UInt32)(ts[i] | ts[i + 1] << 8 | ts[i + 2] << 16 | ts[i + 3] << 24);

 }

 return output;

 }

 

 private static UInt32[] MD5_Trasform(UInt32[] x)

 {

 

 UInt32 a, b, c, d;

 

 for (int k = 0; k < x.Length; k += 16)

 {

 a = A;

 b = B;

 c = C;

 d = D;

 

 /* Раунд1 */

 FF(ref a, b, c, d, x[k + 0], S11, 0xd76aa478); /* 1 */

 FF(ref d, a, b, c, x[k + 1], S12, 0xe8c7b756); /* 2 */

 FF(ref c, d, a, b, x[k + 2], S13, 0x242070db); /* 3 */

 FF(ref b, c, d, a, x[k + 3], S14, 0xc1bdceee); /* 4 */

 FF(ref a, b, c, d, x[k + 4], S11, 0xf57c0faf); /* 5 */

 FF(ref d, a, b, c, x[k + 5], S12, 0x4787c62a); /* 6 */

 FF(ref c, d, a, b, x[k + 6], S13, 0xa8304613); /* 7 */

 FF(ref b, c, d, a, x[k + 7], S14, 0xfd469501); /* 8 */

 FF(ref a, b, c, d, x[k + 8], S11, 0x698098d8); /* 9 */

 FF(ref d, a, b, c, x[k + 9], S12, 0x8b44f7af); /* 10 */

 FF(ref c, d, a, b, x[k + 10], S13, 0xffff5bb1); /* 11 */

 FF(ref b, c, d, a, x[k + 11], S14, 0x895cd7be); /* 12 */

 FF(ref a, b, c, d, x[k + 12], S11, 0x6b901122); /* 13 */

 FF(ref d, a, b, c, x[k + 13], S12, 0xfd987193); /* 14 */

 FF(ref c, d, a, b, x[k + 14], S13, 0xa679438e); /* 15 */

 FF(ref b, c, d, a, x[k + 15], S14, 0x49b40821); /* 16 */

 

 /* Раунд2 */

 GG(ref a, b, c, d, x[k + 1], S21, 0xf61e2562); /* 17 */

 GG(ref d, a, b, c, x[k + 6], S22, 0xc040b340); /* 18 */

 GG(ref c, d, a, b, x[k + 11], S23, 0x265e5a51); /* 19 */

 GG(ref b, c, d, a, x[k + 0], S24, 0xe9b6c7aa); /* 20 */

 GG(ref a, b, c, d, x[k + 5], S21, 0xd62f105d); /* 21 */

 GG(ref d, a, b, c, x[k + 10], S22, 0x2441453); /* 22 */

 GG(ref c, d, a, b, x[k + 15], S23, 0xd8a1e681); /* 23 */

 GG(ref b, c, d, a, x[k + 4], S24, 0xe7d3fbc8); /* 24 */

 GG(ref a, b, c, d, x[k + 9], S21, 0x21e1cde6); /* 25 */

 GG(ref d, a, b, c, x[k + 14], S22, 0xc33707d6); /* 26 */

 GG(ref c, d, a, b, x[k + 3], S23, 0xf4d50d87); /* 27 */

 GG(ref b, c, d, a, x[k + 8], S24, 0x455a14ed); /* 28 */

 GG(ref a, b, c, d, x[k + 13], S21, 0xa9e3e905); /* 29 */

 GG(ref d, a, b, c, x[k + 2], S22, 0xfcefa3f8); /* 30 */

 GG(ref c, d, a, b, x[k + 7], S23, 0x676f02d9); /* 31 */

 GG(ref b, c, d, a, x[k + 12], S24, 0x8d2a4c8a); /* 32 */

 

 /* Раунд3 */

 HH(ref a, b, c, d, x[k + 5], S31, 0xfffa3942); /* 33 */

 HH(ref d, a, b, c, x[k + 8], S32, 0x8771f681); /* 34 */

 HH(ref c, d, a, b, x[k + 11], S33, 0x6d9d6122); /* 35 */

 HH(ref b, c, d, a, x[k + 14], S34, 0xfde5380c); /* 36 */

 HH(ref a, b, c, d, x[k + 1], S31, 0xa4beea44); /* 37 */

 HH(ref d, a, b, c, x[k + 4], S32, 0x4bdecfa9); /* 38 */

 HH(ref c, d, a, b, x[k + 7], S33, 0xf6bb4b60); /* 39 */

 HH(ref b, c, d, a, x[k + 10], S34, 0xbebfbc70); /* 40 */

 HH(ref a, b, c, d, x[k + 13], S31, 0x289b7ec6); /* 41 */

 HH(ref d, a, b, c, x[k + 0], S32, 0xeaa127fa); /* 42 */

 HH(ref c, d, a, b, x[k + 3], S33, 0xd4ef3085); /* 43 */

 HH(ref b, c, d, a, x[k + 6], S34, 0x4881d05); /* 44 */

 HH(ref a, b, c, d, x[k + 9], S31, 0xd9d4d039); /* 45 */

 HH(ref d, a, b, c, x[k + 12], S32, 0xe6db99e5); /* 46 */

 HH(ref c, d, a, b, x[k + 15], S33, 0x1fa27cf8); /* 47 */

 HH(ref b, c, d, a, x[k + 2], S34, 0xc4ac5665); /* 48 */

 

 /* Раунд4 */

 II(ref a, b, c, d, x[k + 0], S41, 0xf4292244); /* 49 */

 II(ref d, a, b, c, x[k + 7], S42, 0x432aff97); /* 50 */

 II(ref c, d, a, b, x[k + 14], S43, 0xab9423a7); /* 51 */

 II(ref b, c, d, a, x[k + 5], S44, 0xfc93a039); /* 52 */

 II(ref a, b, c, d, x[k + 12], S41, 0x655b59c3); /* 53 */

 II(ref d, a, b, c, x[k + 3], S42, 0x8f0ccc92); /* 54 */

 II(ref c, d, a, b, x[k + 10], S43, 0xffeff47d); /* 55 */

 II(ref b, c, d, a, x[k + 1], S44, 0x85845dd1); /* 56 */

 II(ref a, b, c, d, x[k + 8], S41, 0x6fa87e4f); /* 57 */

 II(ref d, a, b, c, x[k + 15], S42, 0xfe2ce6e0); /* 58 */

 II(ref c, d, a, b, x[k + 6], S43, 0xa3014314); /* 59 */

 II(ref b, c, d, a, x[k + 13], S44, 0x4e0811a1); /* 60 */

 II(ref a, b, c, d, x[k + 4], S41, 0xf7537e82); /* 61 */

 II(ref d, a, b, c, x[k + 11], S42, 0xbd3af235); /* 62 */

 II(ref c, d, a, b, x[k + 2], S43, 0x2ad7d2bb); /* 63 */

 II(ref b, c, d, a, x[k + 9], S44, 0xeb86d391); /* 64 */

 

 A += a;

 B += b;

 C += c;

 D += d;

 }

 return new UInt32[] { A, B, C, D };

 }

 private static byte[] MD5Array(byte[] input)

 {

 MD5_Init();

 UInt32[] block = MD5_Append(input);

 UInt32[] bits = MD5_Trasform(block);

 

 // Кодирует bits (UInt32[]) в output (byte[]). 

 byte[] output = new byte[bits.Length * 4];

 for (int i = 0, j = 0; i < bits.Length; i++, j += 4)

 {

 output[j] = (byte)(bits[i] & 0xff);

 output[j + 1] = (byte)((bits[i] >> 8) & 0xff);

 output[j + 2] = (byte)((bits[i] >> 16) & 0xff);

 output[j + 3] = (byte)((bits[i] >> 24) & 0xff);

 }

 return output;

 }



 private static string ArrayToHexString(byte[] array, bool uppercase) 

 {

 string hexString = "";

 string format = "x2";

 if (uppercase)

 {

 format = "X2";

 }

 foreach (byte b in array)

 {

 hexString += b.ToString(format);

 }

 return hexString;

 }



 private static string MD5File(string fileName) 

 {

 FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read);

 byte[] array = new byte[fs.Length]; 

 fs.Read(array, 0, (int)fs.Length); 

 byte[] digest = MD5Array(array);

 fs.Close();

 return ArrayToHexString(digest, false);

 }

 }

}



//HardDrive.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;



namespace kurs_pogulyat

{

 class HardDrive

 {

 private string model = "";

 private string type = "";

 private string serialNo = "";

 private string bytesPerSector = "";

 private string mediaType = "";

 private string partitions = "";

 private string sectorsPerTrack = "";

 private string signature = "";

 private string size = "";

 private string freespace = "";

 private string status = "";

 private string totalCylinders = "";

 private string totalHeads = "";

 private string totalSectors = "";

 private string totalTracks = "";

 private string tracksPerCylinder = "";

 private string firmwareRevision = "";



 public string Model

 {

 get { return model; }

 set { model = value; }

 }



 public string Type

 {

 get { return type; }

 set { type = value; }

 }



 public string SerialNo

 {

 get { return serialNo; }

 set { serialNo = value; }

 }



 public string BytesPerSector

 {

 get { return bytesPerSector; }

 set { bytesPerSector = value; }

 }



 public string MediaType

 {

 get { return mediaType; }

 set { mediaType = value; }

 }



 public string Partitions

 {

 get { return partitions; }

 set { partitions = value; }

 }



 public string SectorsPerTrack

 {

 get { return sectorsPerTrack; }

 set { sectorsPerTrack = value; }

 }



 public string Signature

 {

 get { return signature; }

 set { signature = value; }

 }



 public string Size

 {

 get { return size; }

 set { size = value; }

 }



 public string FreeSpace

 {

 get { return freespace; }

 set { freespace = value; }

 }



 public string Status

 {

 get { return status; }

 set { status = value; }

 }



 public string TotalCylinders

 {

 get { return totalCylinders; }

 set { totalCylinders = value; }

 }



 public string TotalHeads

 {

 get { return totalHeads; }

 set { totalHeads = value; }

 }



 public string TotalSectors

 {

 get { return totalSectors; }

 set { totalSectors = value; }

 }



 public string TotalTracks

 {

 get { return totalTracks; }

 set { totalTracks = value; }

 }



 public string TracksPerCylinder

 {

 get { return tracksPerCylinder; }

 set { tracksPerCylinder = value; }

 }



 public string FirmwareRevision

 {

 get { return firmwareRevision; }

 set { firmwareRevision = value; }

 } }

}

//Program.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows.Forms;



namespace kurs_pogulyat

{

 static class Program

 {

 [STAThread]

 static void Main()

 {

 Application.EnableVisualStyles();

 Application.SetCompatibleTextRenderingDefault(false);

 Application.Run(new Form1());

 }

 }

}