Jump to content











Photo
- - - - -

IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS


  • Please log in to reply
16 replies to this topic

#1 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 25 March 2010 - 03:29 PM

I'm using IOCTL API to find the physical drive number corresponding to a drive letter.

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 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 16066 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 25 March 2010 - 03:45 PM

If you are using an external app (rmprepusb.exe) why cannot you use another external app?

Item #1:
http://www.911cd.net...o...22273&st=27

Item #2:
http://www.boot-land...?showtopic=8219


:)
Wonko

#3 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 25 March 2010 - 04:00 PM

I have the feeling that you do not like either steve6735 or his app.

The reason is simply:
It is the only app having a command line input.
It is the most "universal" of the known alternities.

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! :)

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: Thanks for the precise and useful answer to my question! :)

Peter

#4 TheK

TheK

    Frequent Member

  • Advanced user
  • 141 posts
  • Location:Germany (BW)
  •  
    Germany

Posted 25 March 2010 - 04:18 PM

The problem seems to be that you pass a DISK_EXTENT structure to the function instead of a VOLUME_DISK_EXTENTS structure.

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 olegpov

olegpov

    Frequent Member

  • .script developer
  • 309 posts
  • Location:Orel
  • Interests:BSD systems

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 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 16066 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

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 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 25 March 2010 - 05:04 PM

@Olegpov, @TheK:

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 olegpov

olegpov

    Frequent Member

  • .script developer
  • 309 posts
  • Location:Orel
  • Interests:BSD systems

Posted 25 March 2010 - 05:34 PM

@psc
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 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 25 March 2010 - 05:49 PM

That's exactly my issue.

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 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 25 March 2010 - 06:14 PM

@TheK:
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 TheK

TheK

    Frequent Member

  • Advanced user
  • 141 posts
  • Location:Germany (BW)
  •  
    Germany

Posted 25 March 2010 - 06:43 PM

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.

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 :) ).

#12 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 25 March 2010 - 06:50 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.

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 :) ).

Thanks! :)
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 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 25 March 2010 - 07:01 PM

Thanks again to TheK:
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 TheK

TheK

    Frequent Member

  • Advanced user
  • 141 posts
  • Location:Germany (BW)
  •  
    Germany

Posted 25 March 2010 - 07:11 PM

My pleasure! :)
[german] Gern geschehen! [/german]

:)

#15 erwan.l

erwan.l

    Platinum Member

  • Developer
  • 3041 posts
  • Location:Nantes - France
  •  
    France

Posted 25 March 2010 - 07:23 PM

Hi,

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 steve6375

steve6375

    Platinum Member

  • Developer
  • 7566 posts
  • Location:UK
  • Interests:computers, programming (masm,vb6,C,vbs), photography,TV,films
  •  
    United Kingdom

Posted 27 March 2010 - 09:37 PM

Just seen this post! RMPARTUSB has a FIND command, this has output like

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 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 28 March 2010 - 06:39 PM

Thanks Steve! :)

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