>I am trying to get details on all the partitions on a physical drive, but I
am getting an access denied message with the call to DeviceIOControl.
hDevice := CreateFile(PChar(Drive),0, FILE_SHARE_READ Or
FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
try asking for read permission
hDevice := CreateFile(PChar(Drive), GENERIC_READ, FILE_SHARE_READ Or
FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
If that fails, which I doubt, try
GENERIC_READ | GENERIC_WRITE
and/or FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
and/or FILE_ATTRIBUTE_NORMAL (I’ve always found the docs on that parameter
confusing, it sounds like FILE_ATTRIBUTE_NORMAL is required, if nothing
else, yet people seem to get away with 0.)
You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com
>From: xxxxx@cornell.edu [mailto:xxxxx@cornell.edu]
Subject: : Getting all partitions on a Drive using DeviceIoControl
>I am trying to get details on all the partitions on a physical drive, but
I
>am getting an access denied message with the call to DeviceIOControl.
> hDevice := CreateFile(PChar(Drive),0, FILE_SHARE_READ Or
>FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
try asking for read permission
> hDevice := CreateFile(PChar(Drive), GENERIC_READ, FILE_SHARE_READ Or
>FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
If that fails, which I doubt, try
GENERIC_READ | GENERIC_WRITE
and/or FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
and/or FILE_ATTRIBUTE_NORMAL (I’ve always found the docs on that parameter
confusing, it sounds like FILE_ATTRIBUTE_NORMAL is required, if nothing
else, yet people seem to get away with 0.)
- Jay
-----Original Message-----
From: Chris Crowe
>Subject: RE: : Getting all partitions on a Drive using DeviceIoControl
>Hi Jay,
>
>Thanks for the info there. I tried the GENERIC_READ and got a different
>error message which was 122.
>
>“The data area passed to a system call is too small.”
>
>So it means my data structure is wrong…
>
>A couple of questions:
>
>1) Am I suppose to use
>
>Drive := ‘\.\PHYSICALDRIVE0’; // This is what I am using!!!
>or
>Drive := ‘\.\c:’;
>
>2) From the docs I have I am suppose to send a DRIVE_LAYOUT_INFORMATION
>structure, but I do not understand how a structure with an array of 1 can
be
>variable sized.
>
>This is what I have written :
>
>Type DRIVE_LAYOUT_INFORMATION = Record
> PartitionCount : DWORD;
> Signature : DWORD;
> Partitioninfo: array[0…1] of PARTITION_INFORMATION;
> end;
>
>This is what the docs say:
>
>typedef struct _DRIVE_LAYOUT_INFORMATION
>
> DWORD PartitionCount;
> DWORD Signature;
> PARTITION_INFORMATION PartitionEntry[1];
>} DRIVE_LAYOUT_INFORMATION;
>
>Any way I do not get a valid partition count back ever.
>
>So I have ended up with this code at the moment.
>
>Var // Declare Variables
> RetBytes : DWORD;
> hDevice : Longint;
> Status : Longbool;
> Drive : String;
> PartitionInfo : DRIVE_LAYOUT_INFORMATION;
>begin
> Drive := ‘\.\PHYSICALDRIVE’ + inttostr(DriveNum);
> hDevice := CreateFile(PChar(Drive),GENERIC_READ, FILE_SHARE_READ Or
>FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
> If hDevice <> INVALID_HANDLE_VALUE Then
> begin
> Status := DeviceIoControl (hDevice, IOCTL_DISK_GET_DRIVE_LAYOUT,
>nil, 0, @PartitionInfo,
> Sizeof(DRIVE_LAYOUT_INFORMATION), RetBytes, nil);
> if (status = false) then
> showmessage(‘Read Partitions Failed :
’+inttostr(getLastError()));
> CloseHandle(hDevice);
> end;
>End;
>
>Your help would be most appreciated, the RetBytes returns a value of
1244448
>when the status = false, and the error code is 122 which is “The data area
>passed to a system call is too small.” (when using my original structure
>above)
>
>if I change the structure to the following
>
>Type DRIVE_LAYOUT_INFORMATION = Record
> PartitionCount : DWORD;
> Signature : DWORD;
> Partitioninfo: array[0…100] of PARTITION_INFORMATION;
> end;
>
>so that I can have 100 partitions I do not get an error but I get a count
of
>8 partitions, but I only have 1 physical hard drive, and 2 partitions.
>
>The retBytes drops to 264 bytes, but from what I can see each
>PARTITION_INFORMATION structure is only 32 bytes long.
>
>So from this It looks like the DRIVE_LAYOUT_INFORMATION is correct (sort
of)
>
>4 bytes for the PartitionCount, 4 bytes for the Signature, and 8 x
>PARTITION_INFORMATION structures @ 32 bytes each which equates to 264
bytes.
>
>Please help…
>
>Chris
Chris, You’d /really/ be better off using C or C++ and the Microsoft
headers, or even Microsoft Java, C#, or script, IF IF they provide
declarations for these things (I doubt they do, if only they were in winnt.h
instead of winioctl.h…). How do you even know if you get the right
“packing/alignment” of these structs/records correct? Maybe that’s a
relatively solved issue in Delphi. I don’t think I’ve seen any Pascal/Delphi
on this list before.
Whatever the language arguments, the “library binding” argument very very
strongly favors C/C++ imho.
It’s a somewhat common practise to have structs end in variably sized
arrays, 0 or 1 or unstated, where only 1 is really allowed by the C
standard, and the general practise isn’t theoretically portable, but is
practically portable.
struct FooElement
{
int blah;
char blahblah;
};
struct Foo
{
int count;
FooElement foos[1];
// aka FooElement foos[0]; but I think this is much less portable, not
even accepted by Visual C++
// aka FooElement foos; but I think this is much less portable as well,
not even accepted by Visual C++
// aka FooElement foos[]; at least for Midl, as seen in winnt.h
// notice in winnt.h: #define ANYSIZE_ARRAY 1, and look for its uses, mostly
arrays at the ends of structs
};
char buffer[sizeof(Foo) + 100sizeof(FooElement)];
Foo* pfoo = (Foo*)&buffer;
for (i = 0 ; i < pfoo->count ; ++i)
{
pfoo->foos[i] …;
}
It is a bit dubious from a strongly typed point of view, but it is
efficient. It’s a bit too bad there’s no portable safe way to do this…one
that would pass a C/C++ compiler/codegen that did array range checking…
(some do, at least optionally).
DeviceIoControl(&pfoo, sizeof(buffer), …);
I think you want PhysicalDrive0.
Be sure to get winobj.exe from http://www.sysinternals.com and look around
under ?? and \Device\Harddisk* to get another measure of the count of
partitions (and notice the differences between NT4 and Win2k). I think
there’s always the zeroeth partition that includes the whole drive. It is
interesting in general to browse the NT namespace.
>PARTITION_INFORMATION structure is only 32 bytes long.
Seems about right. 28 bytes, then padded/aligned.
Send questions to the mailing list, not to me directly. Thanks.
- Jay
—
You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com