Delphi Pascal - Using SetFilePointerEx and GetFileSizeEx, Getting Physical Media exact size when reading as a file
- by SuicideClutchX2
I am having trouble understanding how to delcare GetFileSizeEx and SetFilePointerEx in Delphi 2009 so that I can use them since they are not in the RTL or Windows.pas.
I was able to compile with the following:
function GetFileSizeEx(hFile: THandle; lpFileSizeHigh: Pointer): DWORD; external 'kernel32';
Then using GetFileSizeEx(PD, Pointer(DriveSize)); to get the size.
But could not get it to work, the disk handle I am using is valid and I have had no problem reading the data or working under the 2gb mark with the older API's. GetFileSize of course returns 4294967295. I have had greater trouble trying to use SetFilePointerEx with the data types it uses.
The overall project needs to read the data from a flash card, which is not a problem at all I can do this. My problem is that I can not find the length or size of the media I will be reading. I have code I have used in the past to do this with media under 2GB. But now that I need to read media over 2GB it is a problem. If you still dont understand I am dumping a card with all data including the boot record, etc.
This is the code I would normally use to read from the physical disk to grab say the boot record and dump it to file:
SetFilePointer(PD,0,nil,FILE_BEGIN);
SetLength(Buffer,512);
ReadFile(PD,Buffer[0],512,BytesReturned,nil);
I just need to figure out how to find the end of an 8gb card and so on as well as being able to set a file pointer beyond the 2gb barrier. I guess any help in the external declarations as well as understand the values that SetFilePointerEx uses (I do not understand the whole High Low thing) would be of great help.
var
Form1: TForm1;
function GetFileSizeEx(hFile: THandle; var FileSize: Int64): DWORD; stdcall; external 'kernel32';
implementation
{$R *.dfm}
function GetLD(Drive: Char): Cardinal;
var
Buffer : String;
begin
Buffer := Format('\\.\%s:',[Drive]);
Result := CreateFile(PChar(Buffer),GENERIC_READ Or GENERIC_WRITE,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
If Result = INVALID_HANDLE_VALUE Then
begin
Result := CreateFile(PChar(Buffer),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
end;
end;
function GetPD(Drive: Byte): Cardinal;
var
Buffer : String;
begin
If Drive = 0 Then
begin
Result := INVALID_HANDLE_VALUE;
Exit;
end;
Buffer := Format('\\.\PHYSICALDRIVE%d',[Drive]);
Result := CreateFile(PChar(Buffer),GENERIC_READ Or GENERIC_WRITE,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
If Result = INVALID_HANDLE_VALUE Then
begin
Result := CreateFile(PChar(Buffer),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
end;
end;
function GetPhysicalDiskNumber(Drive: Char): Byte;
var
LD : DWORD;
DiskExtents : PVolumeDiskExtents;
DiskExtent : TDiskExtent;
BytesReturned : Cardinal;
begin
Result := 0;
LD := GetLD(Drive);
If LD = INVALID_HANDLE_VALUE Then Exit;
Try
DiskExtents := AllocMem(Max_Path);
DeviceIOControl(LD,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,nil,0,DiskExtents,Max_Path,BytesReturned,nil);
If DiskExtents^.NumberOfDiskExtents > 0 Then
begin
DiskExtent := DiskExtents^.Extents[0];
Result := DiskExtent.DiskNumber;
end;
Finally
CloseHandle(LD);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
PD : DWORD;
BytesReturned : Cardinal;
Buffer : Array Of Byte;
myFile: File;
DriveSize: Int64;
begin
PD := GetPD(GetPhysicalDiskNumber(Edit1.Text[1]));
If PD = INVALID_HANDLE_VALUE Then Exit;
Try
GetFileSizeEx(PD, DriveSize);
//SetFilePointer(PD,0,nil,FILE_BEGIN);
//etLength(Buffer,512);
//ZeroMemory(@Buffer,SizeOf(Buffer));
//ReadFile(PD,Buffer[0],512,BytesReturned,nil);
//AssignFile(myFile, 'StickDump.bin');
//ReWrite(myFile, 512);
//BlockWrite(myFile, Buffer[0], 1);
//CloseFile(myFile);
Finally
CloseHandle(PD);
End;
end;