在DELPHI程序中如何判断一个分区是否为活动分区及如何更改引导类型?(100分)

  • 主题发起人 主题发起人 宋阳
  • 开始时间 开始时间

宋阳

Unregistered / Unconfirmed
GUEST, unregistred user!
1、在DELPHI程序中如何判断一个分区是否为活动分区?
2、如何利用DELPHI程序代码(不是调用外部的如: bootsect /nt52 c: 适合xp引导,bootsect /nt60 c: 适合vista引导 )更改引导类型,是用DELPHI代码,不是调用bootsect.EXE,但要求达到 bootsect /nt52 c:及bootsect /nt60 c: 相同功能。
据说是打开一个路径为“//./PhysicalDrive0"的文件,然后修改这个文件里的数据,最后关闭文件。
 
毛了,用磁盘的i/o 或者 int13h 才能实现吧
 
可以参考一下 delphi里直接读取物理硬盘的相关代码
 
可惜,都是C的天下。而C又看不懂。
 
//./PhysicalDrive0就是访问物理硬盘
可以访问所有扇区
你需要熟悉硬盘分区结构的
 
这里有一个函数好象是读分区信息的,但我不会把它改为DELPHI的代码。
void CGghostDlg::LoadAllDrive4()
{

int i;
int z;
int k;

char c[256];
::GetModuleFileName(0,c,256);
CString str;
str=Getdir(c)+"//debug.log";
::DeleteFile(str);

//
// Getting a handle to 1st Hard Disk via CreateFile() function.
// Open the 1st HD using "////.//PhysicalDrive0"
// Open drive C: using "////.//C:"
//
CString hd;
int drivenum=0;


//while(1)
int pbuffer=32;
for(drivenum=0;drivenum<20;drivenum++)
{
start:
/*if(bRemovable(drivenum))
{

// drivenum++;
continue;
}
else
{

}
*/
HANDLE hDevice = NULL;
DWORD nBytesRead = 0;
DWORD nBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) + sizeof(PARTITION_INFORMATION) * pbuffer;
PDRIVE_LAYOUT_INFORMATION lpPartsInfo = (PDRIVE_LAYOUT_INFORMATION)malloc(nBufferSize);

if(lpPartsInfo == NULL)
{
return ;
}
memset(lpPartsInfo, 0, nBufferSize);






hd.Format("////.//PhysicalDrive%d",drivenum);
hDevice = CreateFile(
hd,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);

if(hDevice == INVALID_HANDLE_VALUE)
{

// return ;
continue;
}

if(DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_LAYOUT,NULL,0,lpPartsInfo,nBufferSize,&nBytesRead,NULL))
{
::CloseHandle(hDevice);


}
else
{
::CloseHandle(hDevice);
free(lpPartsInfo);
DWORD err=::GetLastError();
if(err==122)
{

pbuffer*=2;

goto start;
}
else continue;

}




sortpi(lpPartsInfo,pbuffer);
i=0;z=0;k=0;
while(1)
{

PARTITION_INFORMATION* pi;
pi=&(lpPartsInfo->PartitionEntry);
i++;

if(i==(pbuffer+1))break;
if(pi->PartitionLength.QuadPart==0)continue;
k++;

{

CString str,str2,str3;

int i=m_drive.GetItemCount();
int img=0;
str=Getlogdrv(pi,drivenum);
img=this->insertimg(str);
i=m_drive.InsertItem( i,str,img);

ULONGLONG ull;
ull=pi->PartitionLength.QuadPart;
ull=ull/1024/1024;
double db;
__int64 ll;
ll=ull;
db=(double)ll/1024;

str2.Format("%08.2f GB",db);

for(int j=0;j<str2.GetLength();j++)
{ if(str2.GetAt(j+1)=='.')break;
if(str2.GetAt(j)=='0')str2.SetAt(j,' ');
else break;
}

m_drive.SetItemText(i,4,str2);
if(pi->BootIndicator)m_drive.SetItemText(i,2,"是");
str.Format("%d:%d",drivenum+1,k);
m_drive.SetItemText(i,1,str);
m_drive.SetItemText(i,3,GetVol(m_drive.GetItemText(i,0)));

m_drive.SetItemText(i,5,Getbustype(drivenum));

if(m_drive.GetItemText(i,5)=="USB"||m_drive.GetItemText(i,5)=="1394")
{
m_drive.SetItemTextColor(i,-1,RGB(150,150,150));
m_drive.SetItemTextColor(i,5,RGB(255,0,0));
}
else
{


}



}
}

//CloseHandle(hDevice);
// memset(lpPartsInfo, 0, nBufferSize);

// drivenum++;
free(lpPartsInfo);
}
if(m_drive.GetItemCount()==0)this->MessageBox( "没有找到分区,可能没有以管理员身份运行本程序。",0,MB_ICONERROR);


}
 
不愿写了,COPY一段代码给你吧,可以参考一下^_^
TBPB = packed record
JMPCode: array[0..2] of BYTE; // * 引导跳转代码
System_ID: array[0..7] of CHAR; // * 厂商标志和版本号
SectorBytes: WORD; // * 每扇区字节数
SectorsPerCluster: BYTE; // * 每簇扇区数
ReservedSectors: WORD; // * 保留扇区数
NbrFat: BYTE; // * FAT的个数
RootEntry: WORD; // * 根目录项数
TotalSectors: WORD; // * 分区总扇区数(分区小于32M时)
Media: BYTE; // * 分区介质标识
SectorsPerFAT: WORD; // * 每个FAT占的扇区数
SectorsPerTrack: WORD; // * 每道扇区数
Heads: WORD; // * 磁头数
HiddenSectors: DWORD; // * 隐含扇区数
BigTotalSectors: DWORD; // * 分区总扇区数(分区大于32M时) * //*end of 23 Bytes*/
Drive: BYTE; // * 驱动器号
Head: BYTE; // * 磁头号
boot_rec_sig: BYTE; // * 含义未知
Vol_Serial_NoL: WORD; // * 磁盘序列号
Vol_Serial_NoH: WORD;
vlabel: array[0..10] of CHAR; // * 磁盘卷标号
FileSys_ID: array[0..7] of CHAR; // * 文件系统标识号
BootCode: array[0..449] of BYTE; // * 启动代码
end;

TParRec = packed record
bootid: byte;
beginh: byte;
beginsc: word;
filetype: byte;
endh: byte;
endsc: word;
forwsnum: DWORD;
totolsnum: DWORD;
end;

TDisk0 = packed record
Bootrecord: array[0..445] of byte;
ParRec: array[0..3] of TParRec;
AA55: WORD;
end;

TFileItem = packed record
index: integer;
startpos: int64;
nextpos: int64;
ParRec: array[0..3] of TParRec;
end;

TSDiskFile = packed record
Magic: DWORD; //$FFFF0001
FItem: array[0..17] of TFileItem;
EndFlag: DWORD; //$FFFF0001
end;
function SundyWriteFile(hFile: THANDLE; lpBuffer: Pointer; nNumberOfBytesToWrite: DWORD; lpNumberOfBytesWritten: PDWORD; lpOverlapped: Pointer): boolean; stdcall; external kernel32 name 'WriteFile';
Tcallbackfunc = procedure(var param: TDisk0; index: integer; Driveindex: int64);


function SundyFileWrite(Handle: Integer; Buffer: Pointer; Count: LongWord): Integer;
var
return: DWORD;
begin
return := Count;
if not SundyWriteFile(THandle(Handle), Buffer, Count, PDWORD(@return), nil) then
Result := -1
else
result := return;
end;

function _subfunc(hwnd: THandle; pos, rvpos: int64; callbackfunc: pointer; isc: boolean): boolean;
var
hpos, lpos: DWORD;
jpos, ipos, bpbpos: int64;
ptbuf: TDisk0;
bpb: TBpb;
i, j: integer;
begin
jpos := pos;
hpos := jpos div $FFFFFFFF;
lpos := jpos mod $FFFFFFFF;
ZeroMemory(@ptbuf, sizeof(TDisk0));
if SetFilePointer(hwnd, lpos, @hpos, 0) < lpos then
raise exception.Create('Partition Pointer Set Error.');
if FileRead(hwnd, ptbuf, sizeof(TDisk0)) = 0 then
raise exception.Create('Partition Read Error.');
if ptbuf.AA55 <> $AA55 then
raise exception.Create('Invalid Partition Format.');
i := 0;
while true do
begin
if ptbuf.ParRec.forwsnum = 0 then
break;
if (ptbuf.ParRec.filetype = $B) or
(ptbuf.ParRec.filetype = $C) or
(ptbuf.ParRec.filetype = $6) or
(ptbuf.ParRec.filetype = $E) then
begin
{bpbpos := ptbuf.ParRec.forwsnum;
bpbpos := bpbpos * 512;
bpbpos := jpos + bpbpos;
hpos := bpbpos div $FFFFFFFF;
lpos := bpbpos mod $FFFFFFFF;
ZeroMemory(@bpb, sizeof(bpb));
if SetFilePointer(hwnd, lpos, @hpos, 0) < lpos then
raise exception.Create('BPB Pointer Set Error.');
if FileRead(hwnd, bpb, sizeof(TBpb)) = 0 then
raise exception.Create('BPB Read Error.'); }
j := 0;
//j := bpb.Drive;
if assigned(callbackfunc) then
Tcallbackfunc(callbackfunc)(ptbuf, i, jpos);
end
else if (ptbuf.ParRec.filetype = $5) or
(ptbuf.ParRec.filetype = $F) then
begin
ipos := ptbuf.parRec.forwsnum;
ipos := ipos * sizeof(TDisk0);
if isc then
result := _subfunc(hwnd, ipos, rvpos, callbackfunc, false)
else
result := _subfunc(hwnd, ipos + rvpos, rvpos, callbackfunc, false);
end
else
begin
{bpbpos := ptbuf.ParRec.forwsnum;
bpbpos := bpbpos * 512;
bpbpos := jpos + bpbpos;
hpos := bpbpos div $FFFFFFFF;
lpos := bpbpos mod $FFFFFFFF;
ZeroMemory(@bpb, sizeof(bpb));
if SetFilePointer(hwnd, lpos, @hpos, 0) < lpos then
raise exception.Create('BPB Pointer Set Error.');
if FileRead(hwnd, bpb, sizeof(TBpb)) = 0 then
raise exception.Create('BPB Read Error.'); }
j := 0;
//showmessage(inttostr(sizeof(bpb)));
//j := bpb.Drive;
if assigned(callbackfunc) then
Tcallbackfunc(callbackfunc)(ptbuf, i, jpos);
end;
inc(i);
if i > 3 then break;
end;
result := true;
end;

function EnumPartition(callfunc: pointer): boolean;
var
hfile: THandle;
lagpos, rva: int64;
ptbuf: TDisk0;
begin
result := false;
hfile := CreateFile(pchar('//./PHYSICALDRIVE0'), GENERIC_ALL,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hfile = INVALID_HANDLE_VALUE then
raise Exception.Create('Partiton Information Read Error.');
lagpos := 0;
FileSeek(hfile, 0, 0);
ZeroMemory(@ptbuf, sizeof(TDisk0));
FileRead(hfile, ptbuf, sizeof(TDisk0));
rva := ptbuf.ParRec[1].forwsnum;
rva := rva * sizeof(TDisk0);
result := _subfunc(hfile, lagpos, rva, callfunc, true);
CloseHandle(hfile);
end;

var
partitonnum: integer = 0;
partinfo: array[0..17] of TParRec;
SysMenu: HMenu;
diskfile: TSDiskFile;

procedure callback(var param: TDisk0; index: integer; Driveindex: int64);
var
stype: string;
begin
stype := '未知类型';
case Param.ParRec[index].filetype of
$1, $4, $6, $E: stype := 'FAT16';
$B, $C: stype := 'FAT32';
$7: stype := 'NTFS';
$82: stype := 'Linux';
$83: stype := 'Linux Swap';
end;
SetForms.Memo1.Lines.Add('分区:' + inttostr(partitonnum + 1));
SetForms.Memo1.Lines.Add('启动标志: 0x' + inttohex(Param.ParRec[index].bootid, 2));
SetForms.Memo1.Lines.Add('格式类型: ' + stype);
SetForms.Memo1.Lines.Add('磁盘大小: ' + format('%0.2f', [param.ParRec[index].totolsnum / 2 / 1024 / 1024]) + ' G byte');
if not fExists then
begin
CopyMemory(Pointer(@diskfile.FItem[partitonnum].ParRec[0]), Pointer(@Param.ParRec[0].bootid), 4 * sizeof(TParRec));
diskfile.FItem[partitonnum].index := partitonnum;
diskfile.FItem[partitonnum].startpos := Driveindex;
diskfile.FItem[partitonnum].nextpos := 0;
end;
CopyMemory(pointer(@partinfo[partitonnum].bootid), Pointer(@Param.ParRec[index].bootid), sizeof(TParRec));
inc(partitonnum);
end;
 
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
hDeviceHandle: Thandle;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
const
BytesPerSector=512;
SectorCount=1;
SectorStart=0;
drive='//./C:';
var
str:string;
p:pchar;
i:Cardinal;
begin
hDeviceHandle := CreateFile(drive, GENERIC_ALL, //如果只是读扇区,可以用GENERIC_READ
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,0, 0);
if (hDeviceHandle <> INVALID_HANDLE_VALUE) then
begin
p:=allocmem(SectorCount*BytesPerSector);

FileSeek(hDevicehandle,SectorStart*BytesPerSector,0);
if FileRead(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then
raise exception.create('Read错误');

str:='';
for i:=0 to 512-1 do
begin
str:=str+format('%.2x',[integer(p)]);
if i mod 16=15 then str:=str+#13;
end;
showmessage(str);

FileSeek(hDevicehandle,SectorStart*BytesPerSector,0);
if FileWrite(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then
raise exception.create('Write错误%d');

freemem(p,SectorCount*BytesPerSector);
closehandle(hDeviceHandle);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
const
BytesPerSector=512;
SectorCount=1;
SectorStart=0;
drive='//./PHYSICALDRIVE0';
var
str:string;
p:pchar;
i:Cardinal;
begin
hDeviceHandle := CreateFile(drive, GENERIC_ALL, //如果只是读扇区,可以用GENERIC_READ
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,0, 0);
if (hDeviceHandle <> INVALID_HANDLE_VALUE) then
begin
p:=allocmem(SectorCount*BytesPerSector);

FileSeek(hDevicehandle,SectorStart*BytesPerSector,0);
if FileRead(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then
raise exception.create('Read错误');

str:='';
for i:=0 to 512-1 do
begin
str:=str+format('%.2x',[integer(p)]);
if i mod 16=15 then str:=str+#13;
end;
showmessage(str);

FileSeek(hDevicehandle,SectorStart*BytesPerSector,0);
if FileWrite(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then
raise exception.create('Write错误%d');

freemem(p,SectorCount*BytesPerSector);
closehandle(hDeviceHandle);
end;
end;

end.
 
如何才能实现上面-题目的要求呢?
 
高人,崇拜ing
 
晶晶:你好!
如何调用procedure callback(var param: TDisk0; index: integer; Driveindex: int64);函数?
 
在DELPHI里面这个问题真的很难实现么?
 
问题还没有解决,等待高手来解决。
 
建议楼主去仔细阅读一下上面高人贴的代码。
 
如果有一定基础的话,晶晶的代码就足够了。才那点分,懒得写。
 
如果200分的太少的话,只要问题完美解决了,就再开题送200分。
 
晶晶:你在线吗?
procedure callback(var param: TDisk0; index: integer; Driveindex: int64);
函数当中的条件语句 if not fExists then 里的 fExists 是从什么地方来的布尔变量?
你COPY过来的函数当中要调用的第一个函数是function EnumPartition(callfunc: pointer): boolean;吧?如何调用它呢?callfunc是无类型指针,如何赋值呢?
 
不知这样判断活动分区是否对
procedure TForm1.Button2Click(Sender: TObject);
const
BytesPerSector=512;
SectorCount=1;
SectorStart=0;
drive='//./PHYSICALDRIVE0';
var
str:string;
p:pchar;
i:Cardinal;
begin
hDeviceHandle := CreateFile(drive, GENERIC_ALL, //如果只是读扇区,可以用GENERIC_READ
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,0, 0);
if (hDeviceHandle <> INVALID_HANDLE_VALUE) then
begin
p:=allocmem(SectorCount*BytesPerSector);

FileSeek(hDevicehandle,SectorStart*BytesPerSector,0);
if FileRead(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then
raise exception.create('Read错误');

str:='';
for i:=0 to 512-1 do
begin
str:=str+format('%.2x',[integer(p)]);
if i mod 16=15 then str:=str+#13;
end;
showmessage(str);

FileSeek(hDevicehandle,SectorStart*BytesPerSector,0);
if FileWrite(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then
raise exception.create('Write错误%d');

freemem(p,SectorCount*BytesPerSector);
closehandle(hDeviceHandle);
end;
end;
读取str的第447个字节开始的每16个字节为一组看看每组的第一字符是否为80,如果是即为活动分区;如果存在隐藏分区如何确定分区符呢?
 
不回答问题
给楼主提个建议
看不懂C/C++可不行,会delphi的人不说精通C/C++
至少看懂能翻译才行
不然没法做,尤其是windowsSDk之类的
 
后退
顶部