IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
#1
Posted 25 March 2010 - 03:29 PM
That will use steve6375's RMPARTUSB.exe to format an USB flash drive in a nativeEx script.
But currently, following Billy the Door's documentation, I get drive numbers which are random in the range of thousands.
I use the MSDN published definition (Delphi adapted):
TDiskExtent = packed record
DiskNumber: DWORD;
StartingOffset: LARGE_INTEGER;
ExtentLength: LARGE_INTEGER;
end;
If I look into the debugger there seems to be one additional DWORD in the structure.
And if I use
TDiskExtent = packed record
Unknown: DWORD;
DiskNumber: DWORD;
StartingOffset: LARGE_INTEGER;
ExtentLength: LARGE_INTEGER;
end;
everything works fine.
I ask the experts to explain and perhaps tell me links where this behaviour is documented.
Thanks
Peter
#2
Posted 25 March 2010 - 03:45 PM
Item #1:
http://www.911cd.net...o...22273&st=27
Item #2:
http://www.boot-land...?showtopic=8219
Wonko
#3
Posted 25 March 2010 - 04:00 PM
The reason is simply:
It is the only app having a command line input.
It is the most "universal" of the known alternities.
I e.g. already e-mailed to the author of Pe2USB about command line input (before I got to know rmprepusb): Result "no answer since some weeks".BTW: For a long time I did not recognize the RMPrepUSB package by steve6375. Today I found when searching for some help for the nativeEx CreateUSB.Script
For me that seems to be the "Only This One" package!
BTW: Thanks for the precise and useful answer to my question!
Peter
#4
Posted 25 March 2010 - 04:18 PM
typedef struct _VOLUME_DISK_EXTENTS { DWORD NumberOfDiskExtents; DISK_EXTENT Extents[ANYSIZE_ARRAY]; } VOLUME_DISK_EXTENTS, *PVOLUME_DISK_EXTENTS;
typedef struct _DISK_EXTENT { DWORD DiskNumber; LARGE_INTEGER StartingOffset; LARGE_INTEGER ExtentLength; } DISK_EXTENT, *PDISK_EXTENT;
DISK_EXTENT is just a member of the VOLUME_DISK_EXTENTS structure.
So the unknown DWORD that you see is NumberOfDiskExtents.
Also please note that the DISK_EXTENT member is an array as a volume can span multiple disks.
#5
Posted 25 March 2010 - 04:21 PM
TDiskExtent = packed record
Unknown: DWORD;
DiskNumber: DWORD;
StartingOffset: LARGE_INTEGER;
ExtentLength: LARGE_INTEGER;
end;
It is probably necessary to specify so:?
TDiskExtent = record
#6
Posted 25 March 2010 - 04:22 PM
I have the feeling that you do not like either steve6735 or his app.
Well, you have a completely WRONG feeling (as often happens to you lately), JFYI, my opinion on RMPREPUSB:
- I find it the best thing around
- I recommend it any time
- I contributed (a very small bit) to it's development
- I contributed (a very small bit) in having ilko_t to adopt it in WinsetupfromUSB
Guess part of the reasons (a very small bit) why RMPREPUSB has a new feature?
http://www.911cd.net...o...=23696&st=0
Guess who originally helped (a very small bit) Codebeetle with PEtoUSB?
http://www.911cd.net...o...13784&st=44
I guess you are the only programmer around I haven't hassled with making a good USB formatting app ....
... and it seems, judging from the way with which you react to advice and help given to you, like I did the right thing.
I am sorry, I don't know how that stupid API works, I gave you two distinct workarounds, BOTH working and tested, you are of course free to not use any of them, but a basic form of politeness would ask you to at least acknowledge the attempt to help you I made without using sarcasm.
No problem, everyone makes his own mistakes, mine - and not for the first time - was to try helping you, it won't happen again.
Wonko
#7
Posted 25 March 2010 - 05:04 PM
Thanks for suggestions, but both of you could not help me.
Maybe I'm currently stupid / blind and do not see something essential.
Therefore here the complete code (after removing 'packed' as suggested by olegpov):
[codebox]function DosDevices(const drive: string): byte; const IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = $560000; type TDiskExtent = record Unknown: DWORD; DiskNumber: DWORD; StartingOffset: LARGE_INTEGER; ExtentLength: LARGE_INTEGER; end; PDiskExtent = ^TDiskExtent; type TVolumeDiskExtents = record NumberOfDiskExtents: DWORD; Extents: array [0 .. 1] of TDiskExtent; end; PVolumeDiskExtents = ^TVolumeDiskExtents; var sVolumeName: string; bIOResult: Boolean; cBytesReturned: Cardinal; hVolumeHandle: THandle; pvde: PVolumeDiskExtents; begin sVolumeName := '\\.\' + drive; hVolumeHandle := CreateFile(PChar(sVolumeName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if hVolumeHandle = INVALID_HANDLE_VALUE then begin Result := 255; CloseHandle(hVolumeHandle); Exit; end; GetMem(pVde, 64); ZeroMemory(pVde, 64); bIOResult := DeviceIoControl(hVolumeHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, nil, 0, pVde, 64, cBytesReturned, nil); if bIOResult then Result := pvde.Extents[0].DiskNumber else Result := GetLastError(); CloseHandle(hVolumeHandle);
FreeMem(pvde);
end;
[/codebox]
When I have the 'Unknown' line, results are correct. When I omit it results are -as described in first post- random numbers.
cBytesReturned is 32, so the hardcoded 64 is ok (I'll change later).
Peter
#8
Posted 25 March 2010 - 05:34 PM
Peter Probably I am not right but in old records source codes still since then when I was popular Delphi5 has found such record:
type TDiskExtent = record DiskNumber: DWORD; StartingOffset: LARGE_INTEGER; ExtentLength: LARGE_INTEGER; end; PDiskExtent = ^TDiskExtent; type TVolumeDiskExtents = record NumberOfDiskExtents: DWORD; Extents: array[0..1] of TDiskExtent; end; PVolumeDiskExtents = ^TVolumeDiskExtents;
#9
Posted 25 March 2010 - 05:49 PM
If I use the "good old" definition > failure.
If I insert my "unknown" > ok for all my defined drives between c: and z:
Peter
#10
Posted 25 March 2010 - 06:14 PM
I just tried again to find my failure, but no success.
Maybe I did not understand what you intended to explain me. Some friends tell me that I'm becoming old and sometimes I do not recognize the reality on the first view.
Do you have suggestions to change the code that it works with "Billy the Door's documentation"?
Peter
#11
Posted 25 March 2010 - 06:43 PM
I thought you passed in a DISK_EXTENT instead of a VOLUME_DISK_EXTENTS structure because you only mentioned DISK_EXTENT in your fist post. But that's not the problem.Maybe I did not understand what you intended to explain me. Some friends tell me that I'm becoming old and sometimes I do not recognize the reality on the first view.
Your problem seems to be data structure alignment.
That means that the structure has a 8 byte alignment in memory. SizeOf(DISK_EXTENT) returns 24 in c/c++ instead of 20 (1 DWORD + 2*LARGE_INTEGER = 20 bytes).
So I think it's ok to use the unknown DWORD in the structure if there's no other way to get 8-byte alignment in delphi.
(Sorry, I'm just a VB programmer ).
#12
Posted 25 March 2010 - 06:50 PM
Thanks!I thought you passed in a DISK_EXTENT instead of a VOLUME_DISK_EXTENTS structure because you only mentioned DISK_EXTENT in your fist post. But that's not the problem.
Your problem seems to be data structure alignment.
That means that the structure has a 8 byte alignment in memory. SizeOf(DISK_EXTENT) returns 24 in c/c++ instead of 20 (1 DWORD + 2*LARGE_INTEGER = 20 bytes).
So I think it's ok to use the unknown DWORD in the structure if there's no other way to get 8-byte alignment in delphi.
(Sorry, I'm just a VB programmer ).
I'll look to try to find a Delphi way to align correctly!
BTW: Do not tell other people: I'm primarily also a convinced VB programmer, but sometimes real life demands something ...
Peter
#13
Posted 25 March 2010 - 07:01 PM
There has been an "align structure" option in my Delphi IDE, which was at "1 byte". I changed to "8 bytes", and now everything is working well.
To all who now may get concerns: ONLY for this project! Not for all WB apps at all!
But nobody knows why
[german] Danke! [/german]
Peter
#14
Posted 25 March 2010 - 07:11 PM
[german] Gern geschehen! [/german]
#15
Posted 25 March 2010 - 07:23 PM
My working code :
function GetVolumeExtent(DriverLetter: Char):TDiskExtent; stdcall;
var
hVolume: THandle;
DiskExtents: PVolumeDiskExtents;
dwOutBytes: Cardinal;
begin
with Result do
begin
DiskNumber := 0;
StartingOffset.QuadPart := 0;
ExtentLength.QuadPart := 0;
end;
hVolume := CreateFile(PChar('\\.\' + DriverLetter + ':'), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hVolume < 1 then Exit;
DiskExtents := AllocMem(Max_Path);
if DeviceIoControl(hVolume,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nil, 0,
DiskExtents, Max_Path,
dwOutBytes, nil) then
begin
if DiskExtents^.NumberOfDiskExtents > 0 then
Result := DiskExtents^.Extents[0];
end;
FreeMem(DiskExtents);
CloseHandle(hVolume);
end;
and the type from jwawinioctl
type
PDISK_EXTENT = ^DISK_EXTENT;
_DISK_EXTENT = record
DiskNumber: DWORD;
StartingOffset: LARGE_INTEGER;
ExtentLength: LARGE_INTEGER;
end;
DISK_EXTENT = _DISK_EXTENT;
TDiskExtent = DISK_EXTENT;
PDiskExtent = PDISK_EXTENT;
PVOLUME_DISK_EXTENTS = ^VOLUME_DISK_EXTENTS;
_VOLUME_DISK_EXTENTS = record
NumberOfDiskExtents: DWORD;
Extents: array [0..0] of DISK_EXTENT;
end;
VOLUME_DISK_EXTENTS = _VOLUME_DISK_EXTENTS;
TVolumeDiskExtents = VOLUME_DISK_EXTENTS;
PVolumeDiskExtents = PVOLUME_DISK_EXTENTS;
Regards,
Erwan.
#16
Posted 27 March 2010 - 09:37 PM
D:\RMPREPUSB_2.0.734_DEV\RMPrepUSB Beta 2.0.734>rmpartusb find
SET DRIVE=1
SET DRIVEDESC=Single Flash Reader USB Device
SET DRIVESIZE=4075290112
SET DRIVELETTER=G:
so just output this to a .CMD file and call the .CMD file to get these as environment variables.
There is also a LIST command
RMPARTUSB v2.0.732 ©2008-10 RM Education plc [SSi]
====================================================
*DRIVE 1 - 3.8GiB Single Flash Reader USB Device G:
DRIVE 2 - 3.8GiB HP v135w USB Device F:
the * denotes which drive will be returned by the FIND command.
cheers
Steve
#17
Posted 28 March 2010 - 06:39 PM
The issue has been solved completelly by TheK's hint about structure alignment.
(I'm feeling a bit stupid not to have seen this ...).
Due to RMPARTUSB: I'm working on including it into my "nativeEx barebone" and "nativeEx Win7" projects as "CreateUSBStick.script".
When I've more time during the upcoming week, you'll get a PM asking about 'License conditions'.
Currently I'm fighting with cleaning imagex.exe mount issues in Win7 (maybe Vista) projects.
WimCaptEx.exe gets addidional "Verify" and "Clean" tasks.
Right now it looks well. No more errors when trying to mount a (used / orphaned / forgotten etc. WIM)
Peter
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users