Курсовая работа: Разработка вспомогательной системной программы в системе программирования Delphi с использованием средств WinApi
bpbList: TValueListEditor;
Label1: TLabel;
GroupBox2: TGroupBox;
Disks: TLabel;
BitBtn1: TBitBtn;
GroupBox3: TGroupBox;
Memo1: TMemo;
Grid2: TStringGrid;
Label2: TLabel;
Memo2: TMemo;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure DiscGeometryShow;
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormActivate(Sender: TObject); // Result = LoDWORD
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
hDrive,hMBRDrive: THandle;
DiscGeometry:TDiscGeometry;
typeOfDisc:string;
implementation
{$R *.dfm}
// определение версии ОС
function DetectWinVersion : TWinVersion;
var
OSVersionInfo : TOSVersionInfo;
begin
Result := wvUnknown; // Неизвестная версия ОС
OSVersionInfo.dwOSVersionInfoSize := sizeof(TOSVersionInfo);
if GetVersionEx(OSVersionInfo)
then
begin
case OSVersionInfo.DwMajorVersion of
3: Result := wvNT3; // Windows NT 3
4: case OSVersionInfo.DwMinorVersion of
0: if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT
then Result := wvNT4 // Windows NT 4
else Result := wv95; // Windows 95
10: Result := wv98; // Windows 98
90: Result := wvME; // Windows ME
end;
5: case OSVersionInfo.DwMinorVersion of
0: Result := wvW2K; // Windows 2000
1: Result := wvXP; // Windows XP
2: Result := wv2003; // Windows 2003
end;
6: case OSVersionInfo.DwMinorVersion of
0: Result := wvVista; // Windows Vista
1: Result := wv7; // Windows 7
end;
end;
end;
end;
// для вывода версии
function DetectWinVersionStr : string;
const
VersStr : array[TWinVersion] of string = (
'Unknown',
'Windows 95',
'Windows 98',
'Windows ME',
'Windows NT 3',
'Windows NT 4',
'Windows 2000',
'Windows XP',
'Windows 2003',
'Windows Vista',
'Windows Seven');
begin
Result := VersStr[DetectWinVersion];
end;
// для перемещения по диску
function __Mul(a,b: DWORD; var HiDWORD: DWORD):DWORD;
asm
mul edx
mov [ecx],edx
end;
// Чтение сектора жесткго диска(Вызыв когда работа с диском начата)
function ReadSectors(hDrive:Thandle; StartingSector, SectorCount: DWORD;
Buffer: Pointer; BytesPerSector: DWORD): DWORD;
var
br,TmpLo,TmpHi: DWORD;
begin
Result := 0;
TmpLo := __Mul(StartingSector,BytesPerSector,TmpHi);
if SetFilePointer(hDrive,TmpLo,@TmpHi,FILE_BEGIN) = TmpLo then
begin
SectorCount := SectorCount*BytesPerSector;
if ReadFile(hDrive,Buffer^,SectorCount,br,nil) then Result := br;
end;
end;
// вывод геометрии
procedure TForm3.DiscGeometryShow;
begin
Memo1.Clear;
Memo1.Text:='Вы просматриваете логический диск: '+DriveComboBox1.Drive+#13#10;
Memo1.Text:= memo1.Text + 'Количество цилиндров: '+inttoStr(DiscGeometry.Cylinders)+#13#10;
case DiscGeometry.MediaType of
12:typeOfDisc:=' жёсткий диск';
11:typeOfDisc:=' съёмный носитель';
end;
Memo1.Text:= memo1.Text + 'Тип носителя: '+typeOfDisc+#13#10;
Memo1.Text:= memo1.Text + 'Дорожек на цилиндре: '+intToStr(DiscGeometry.TracksPerCylinder)+#13#10;
Memo1.Text:= memo1.Text + 'Секторов на дорожке: '+intToStr(DiscGeometry.SectorsPerTrack)+#13#10;
Memo1.Text:= memo1.Text + 'Байт в секторе: '+intToStr(DiscGeometry.BytesPerSector)+#13#10;
end;
//создаем файл диска/выводим геомертию
//начинаем работу с жёстким диском
procedure TForm3.Button1Click(Sender: TObject);
var
discNameBPB,discNameMBR:string;
junk:Cardinal;
result:boolean;
begin
if hDrive <> 0 then CloseHandle(hDrive);
if hMBRDrive <> 0 then CloseHandle(hMBRDrive);
discNameBPB:='\\.\'+DriveComboBox1.Drive+':';
discNameMBR:='\\.\PHYSICALDRIVE'+intToStr(0);
hMBRDrive:= CreateFile(PChar(discNameMBR),GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
hDrive:= CreateFile(PChar(discNameBPB),GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
if (hDrive <> INVALID_HANDLE_VALUE) and (hMBRDrive <> INVALID_HANDLE_VALUE) then
begin
Result := DeviceIoControl(hDrive,IOCTL_DISK_GET_DRIVE_GEOMETRY,nil,0,
@DiscGeometry,SizeOf(TDiscGeometry),junk,nil) and (junk = SizeOf(TDiscGeometry));
DiscGeometryShow();
end
else
begin
ShowMessage('Не возможно создать дескрипторы носителя');
exit;
end;
end;
// Чтение и рашифровка BPB
procedure TForm3.Button2Click(Sender: TObject);
var
i,j,k:integer;
read:Cardinal;
s:string;
buffer: array[1..131072] of byte;
begin
if ReadSectors(hDrive,0,1,@buffer,DiscGeometry.BytesPerSector) = DiscGeometry.BytesPerSector then
begin
for i:= 1 to 16 do
Grid1.Cells[i,0]:=intToHex((i-1),1);
i:=1; j:=1; k:=1;
while k<=DiscGeometry.BytesPerSector do
begin
if i=1 then Grid1.Cells[0,j]:=IntToHex(((j-1)*16+(i-1)),3);
Grid1.Cells[i,j]:=IntToHex(Buffer[k],2);
inc(k);
inc(i);
if i>16 then
begin
i:=1;
j:=j+1;
Grid1.RowCount:= Grid1.RowCount+1;
end;
end;
// расшифровка данных BPB
for i:= 1 to 3 do
s:=s+ intToHex(buffer[i],2);
bpbList.Cells[1,1]:= s + 'h';
s:='';
// чтение имени ОС
for i:= 4 to 4 + 7 do
s:=s+ chr(buffer[i]);
bpbList.Cells[1,2]:= s;
s:='';
//--------------------------
bpbList.Cells[1,3]:=IntToStr(buffer[$C+1] shl 8 + buffer[$C]);
bpbList.Cells[1,4]:=IntToStr(buffer[$C + 2]);
bpbList.Cells[1,5]:=intToStr(buffer[$C + 4] shl 8 + buffer[$C+3]);
bpbList.Cells[1,6]:=intToStr(buffer[$C+5]);
bpbList.Cells[1,7]:=IntToStr(buffer[$F + 4] shl 8 + buffer[$F + 3]);
bpbList.Cells[1,8]:=intToStr(buffer[$F+6] shl 8 + buffer[$F + 5]);
bpbList.Cells[1,9]:=intToHex(buffer [22],2);
if bpbList.Cells[1,9] = 'F8' then bpbList.Cells[1,9]:='Системный носитель инФормации'
else if bpbList.Cells[1,9] = 'FDh' then bpbList.Cells[1,9]:=' накопитель - 2 стороны, 9 секторов'
else if bpbList.Cells[1,9] = 'F9h' then bpbList.Cells[1,9]:=' накопитель - 2 стороны, 9 секторов'
else if bpbList.Cells[1,9] = 'F0h' then bpbList.Cells[1,9]:=' накопитель - 2 стороны, 15 секторов';
bpbList.Cells[1,10]:=intToStr(buffer[$F+9] shl 8 + buffer[$F+8]);
bpbList.Cells[1,11]:=intToStr(buffer[$F+11] shl 8 + buffer[$F+10]);
bpbList.Cells[1,12]:=intToStr(buffer[$F+13] shl 8 + buffer[$F+12]);
bpbList.Cells[1,13]:=intToStr(buffer[$F+17] shl 32 + buffer[$f+16]+ buffer[$f+15]+buffer[$f+14]);
bpbList.Cells[1,14]:=intToStr(buffer[$F + 21] shl 24 + buffer[$F + 20] shl 16 + buffer[$F + 19] shl 8 + buffer[$F + 18]);
bpbList.Cells[1,15]:=intToStr(buffer[$C + 25]);
bpbList.Cells[1,16]:=intToStr(buffer[$F + 23]);
bpbList.Cells[1,17]:=intToStr(buffer[$F + 24]);
bpbList.Cells[1,18]:=intToHex((buffer[$F + 28] shl 24 + buffer[$F + 27] shl 16 + buffer[$F + 26] shl 8 + buffer[$F + 25]),8);
//-----------вывод метки -----------
s:='';
for i:=29 to 40 do
s:=s+chr(buffer[$F+i]);
bpbList.Cells[1,19]:= s;
s:='';
//----------------------------------
//-- чтение ID ОС-------------
for i:= 55 to 62 do
s:=s+ chr(buffer[i]);
bpbList.Cells[1,20]:= s;
s:='';
//----------------------------
end
else
ShowMessage('Не удалось считать блок параметров Bios');
end;
// чтение данных из структуры DriveInfo
procedure TForm3.Button3Click(Sender: TObject);
var
i,j,k:integer;
read:Cardinal;
s:string;
buffer: array[1..131072] of byte;
begin
Memo2.Clear;
if ReadSectors(hMBRDrive,0,1,@buffer,DiscGeometry.BytesPerSector) = DiscGeometry.BytesPerSector then
begin
for i:= 1 to 16 do
Grid2.Cells[i,0]:=intToHex((i-1),1);
i:=1; j:=1; k:=1;
while k<=DiscGeometry.BytesPerSector do
begin
if i=1 then Grid2.Cells[0,j]:=IntToHex(((j-1)*16+(i-1)),3);
Grid2.Cells[i,j]:=IntToHex(Buffer[k],2);
inc(k);
inc(i);
if i>16 then
begin
i:=1;
j:=j+1;
Grid2.RowCount:= Grid2.RowCount+1;
end;
end;
// Расшифровка PartitionTable
// первая часть
Memo2.Text:=Memo2.Text+'Первый элемент таблицы разделов системного диска: '+#13#10;
Memo2.Text:=Memo2.Text+'Признак загрузки: '+intToHex(buffer[$1bf],2)+#13#10;
Memo2.Text:=Memo2.Text+'Начало раздела диска{';
Memo2.Text:=Memo2.Text+'Головка: '+intToStr(buffer[448]);
Memo2.Text:=Memo2.Text+' Сектор: '+intToStr(buffer[449]);
Memo2.Text:=Memo2.Text+' Цилиндр: '+intToStr(buffer[450]);
Memo2.Text:=Memo2.Text+' }'+#13#10;
Memo2.Text:=Memo2.Text+'Тип раздела {';
Memo2.Text:=Memo2.Text+'Ос: '+intToStr(buffer[451]);
Memo2.Text:=Memo2.Text+' }'+#13#10;
Memo2.Text:=Memo2.Text+'Конец раздела диска{';
Memo2.Text:=Memo2.Text+'Головка: '+intToStr(buffer[$1c4]);
Memo2.Text:=Memo2.Text+' Сектор: '+intToStr(buffer[$1c5]);
Memo2.Text:=Memo2.Text+' Цилиндр: '+intToStr(buffer[$1c6]);
Memo2.Text:=Memo2.Text+' }'+#13#10;
Memo2.Text:=Memo2.Text+'Номер Сектора {';
Memo2.Text:=Memo2.Text+': '+intToStr(buffer[458]shl 32+buffer[457]+buffer[456]+buffer[455]);
Memo2.Text:=Memo2.Text+' }'+#13#10;
Memo2.Text:=Memo2.Text+'Размер раздела {';
Memo2.Text:=Memo2.Text+': '+intToStr(buffer[462]shl 24 +buffer[461] shl 16 +buffer[460]shl 8+buffer[459]);
Memo2.Text:=Memo2.Text+' }'+#13#10+#13#10+#13#10;
//вторая часть
Memo2.Text:=Memo2.Text+'Второй элемент таблицы разделов системного диска: '+#13#10;
Memo2.Text:=Memo2.Text+'Признак загрузки: '+intToHex(buffer[$1CF],2)+#13#10;
Memo2.Text:=Memo2.Text+'Начало раздела диска{';
Memo2.Text:=Memo2.Text+'Головка: '+intToStr(buffer[465]);
Memo2.Text:=Memo2.Text+' Сектор: '+intToStr(buffer[466]);
Memo2.Text:=Memo2.Text+' Цилиндр: '+intToStr(buffer[467]);
Memo2.Text:=Memo2.Text+' }'+#13#10;
Memo2.Text:=Memo2.Text+'Тип раздела {';
Memo2.Text:=Memo2.Text+'Ос: '+intToStr(buffer[468]);
Memo2.Text:=Memo2.Text+' }'+#13#10;
Memo2.Text:=Memo2.Text+'Конец раздела диска{';
Memo2.Text:=Memo2.Text+'Головка: '+intToStr(buffer[469]);
Memo2.Text:=Memo2.Text+' Сектор: '+intToStr(buffer[470]);
Memo2.Text:=Memo2.Text+' Цилиндр: '+intToStr(buffer[471]);
Memo2.Text:=Memo2.Text+' }'+#13#10;
Memo2.Text:=Memo2.Text+'Номер Сектора {';
Memo2.Text:=Memo2.Text+': '+intToStr(buffer[$1D7+3]shl 24+buffer[$1D7+2] shl 16+buffer[$1D7+1]shl 8 +buffer[$1D7]);
Memo2.Text:=Memo2.Text+' }'+#13#10;
Memo2.Text:=Memo2.Text+'Размер раздела {';
Memo2.Text:=Memo2.Text+': '+intToStr(buffer[$1db+3]shl 24 +buffer[$11db+2] shl 16 +buffer[$1db+1]shl 8+buffer[$1db]);
Memo2.Text:=Memo2.Text+' }'+#13#10+#13#10+#13#10;
end
else
ShowMessage('Не удалось считать PartitionTable');
end;
// получение инфо о нужных дисках
procedure TForm3.FormActivate(Sender: TObject);
var
S,SOut : String;
i:Integer;
VolumeName,FileSystemName,NewDiscNumber : String;
MaxComponentLength,FileSystemFlags:LongWord;
// от переменной VolumeSerialNo : DWord;
begin
S:=GetDisks(DiskHDD); {Получаем список Жёстких дисков (Параметр DiskHDD)}
s:=s+GetDisks(DiskFDD);
s:=s+GetDisks(DiskNet);
s:=s+GetDisks(DiskCDROM);
s:=s+GetDisks(DiskRAM);
SOut:='';
For i:=1 to Length(S) do {Получаем информацию о всех дисках и пишем в TLabel на форме}
begin
{Если диск существует/вставлен ...}
if GetHDDInfo(S[I], VolumeName, FileSystemName,NewDiscNumber,
MaxComponentLength, FileSystemFlags) then {... тогда собираем информацию}
SOut:=SOut+
'Диск: '+S[I]+#13#10+
'Метка: '+VolumeName+#13#10+
'Файловая система: '+FileSystemName+#13+#10+
'Серийный номер: '+NewDiscNumber+#13+#10+
'Макс. длина имени файла: '+IntToStr(MaxComponentLength)+#13+#10+
'Flags: '+IntToHex(FileSystemFlags,4)+#13#10+#13#10;
end;
Disks.Caption:=SOut; {Выводим в компонент TLabel полученные данные о дисках}
end;
end.
5) Модуль ThrdRcvr (модуль описывающий работу потока – приёмника сообщений):
unit ThrdRcvr; // принимающий поток
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,StdCtrls, Buttons, Menus, ComCtrls, ActnMan, ActnColorMaps;
type
TThreadReceiver = class(TThread)
private
PBaseAdress:PChar;
TextString:String;
nlineSize:integer;
protected
procedure Execute; override;
public
end;
implementation
uses
Unit1;
// Считываем соержимое из проекции файла в Memo1
procedure TThreadReceiver.Execute;
begin
while (not terminated) do
begin
WaitForSingleObject(Form1.HEvent, INFINITE);
ResetEvent(Form1.HEvent);
try
// резерв. память в потоке для этотой проекции
PBaseAdress:=MapViewOfFile(Form1.HFileSender, FILE_MAP_READ,0,0,65536);
if (PBaseAdress = nil) then
begin
CloseHandle(Form1.HFileSender);
st:='не удалось отобразить файл на адресное пространство';
Application.MessageBox(st,'Сообщение...',MB_OK);
form1.BitBtn2.Visible:=false;
form1.Button1.Visible:=false;
exit;
end;
nlineSize:=integer(PBaseAdress^);
SetLength(TextString,nlineSize);
CopyMemory(PChar(TextString),Pointer(Integer(PBaseAdress)+4),nlineSize);
Form1.Memo1.Text:=Form1.Memo1.Text+'---------'+#13#10;
Form1.Memo1.Text:=Form1.Memo1.Text+TextString+#13#10;
sendmessage(Form1.memo1.handle, em_linescroll, 0, Form1.memo1.lines.count-1);
UnmapViewOfFile(PBaseAdress);
finally
end;
end;
end;
end.
6) Модуль HDDInfo (модуль получающий информацию о жёстких дисках):
unit HDDInfo;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, FileCtrl, ExtCtrls, Grids, ValEdit;
const {Константы для TypeOfDisk функции GetDisks}DiskUnknown=0; {Неизвестные диски}
DiskNone=1; {Отсутствующие диски}
DiskFDD=DRIVE_REMOVABLE; {Съёмные диски, дискеты}
DiskHDD=DRIVE_FIXED; {Не съёиные диски, жёсткие диски}
DiskNet=DRIVE_REMOTE; {Сетевые диски}
DiskCDROM=DRIVE_CDROM; {CD ROM}
DiskRAM=DRIVE_RAMDISK; {Диски в ОЗУ}
function GetDisks(TypeOfDisk : Word) : String;
function GetHDDInfo(Disk : Char;Var VolumeName, FileSystemName,NewDiscNumber : String;
MaxComponentLength, FileSystemFlags:LongWord) : Boolean;
implementation
//получить имена доступных дисков
function GetDisks(TypeOfDisk : Word) : String;{Получить имена нужных дисков}
var
DriveArray : array[1..26] of Char;
i:integer;
beginDriveArray:='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for i:= 1 to 26 do
if GetDriveType(PChar(DriveArray[I]+':\')) = TypeOfDisk then
Result := Result+DriveArray[I];
end;
// определение правильного серийного номера диска
function GetReplaceCDNumber(num: String): String;
var
i, len: Integer;
begin
Result:= '';
len:= Length(num);
if len <> 8 then exit;
for i:= 1 to (len div 2) do begin
Dec(len);
Result:= Result + num[len];
Result:= Result + num[len+1];
Dec(len);
end;
end;
// получить инфо о дисках с нужными именами
function GetHDDInfo(Disk : Char;Var VolumeName, FileSystemName,NewDiscNumber : String;
MaxComponentLength, FileSystemFlags:LongWord) : Boolean;
var
_VolumeName,_FileSystemName:array [0..MAX_PATH-1] of Char;
_VolumeSerialNo,_MaxComponentLength,_FileSystemFlags:LongWord;
_NewDiscNumber:string;
begin
if GetVolumeInformation(PChar(Disk+':\'),_VolumeName,MAX_PATH,@_VolumeSerialNo,
_MaxComponentLength,_FileSystemFlags,_FileSystemName,MAX_PATH) then
begin
NewDiscNumber:=IntToHex(integer(_VolumeSerialNo),8);
NewDiscNumber:=GetReplaceCDNumber(NewDiscNumber);
VolumeName:=_VolumeName;
MaxComponentLength:=_MaxComponentLength;
FileSystemFlags:=_FileSystemFlags;
FileSystemName:=_FileSystemName;
Result:=True;
end
else
Result:=False;
end;
end.
Список литературы:
1) М. Фленов «Библия Delphi»
2) А. Танцер «Синхронизация процессов при работе с Windows»
3) Сайт CitForum > http://citforum.ru/programming/delphi/disk_editor/ </
4)Cайт Delphi-Faq > http://delphi-faq.zoxt.net/a79.htm <.
5) Cайт DelphiSource.