dies ist mein erster Post hier. Ich habe einige Jahre lang nur in AutoIt programmiert. Aber úmzusetzende Projekte sind immer komplexer geworden. Das lässt sich zwar auch meistens in AutoIt umsetzen, aber Performanceprobleme haben mich nach einer anderen Programmiersprache schauen lassen. Und nach langen hin und her habe ich mich für PureBasic entschieden. Es macht so einen Spaß damit zu programmieren. Es ist ähnlich wie AutoIt, aber wesentlich mächtiger. Nun sind seit den ersten Schritten zwei Wochen vergangen und ich habe nun ein Problem bezüglich eines DeviceIoControl aufrufes. Ich erhalte nicht die Informationen, die mir die Struktur eigentlich liefern sollte. Ich gehe schwer davon aus, dass ich ein Problem mit der Definition der Strukturen habe. Integer,Long oder doch quad oder sogar LARGE_INTEGER?

Und dann muss ich aufpassen ob ich den x86 Compiler unter 32 oder 64Bit ausführe. Puhhh.
Also hier mal mein Problem, in der Hoffnung das auch andere von einer Lösung profitieren können.
Hier nun ein Testprogramm. Es sollte das Laufwerk C: auslesen bzw. sagen auf welcher Platte die Partition liegt, welchen OffSet und welche Größe sie hat.
Code: Alles auswählen
OpenConsole()
#IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS=$560000
Structure t_DISK_EXTENT
DiskNumber.l
StartingOffset.q
ExtentLength.q
EndStructure
Structure t_VOLUME_DISK_EXTENTS
NumberOfDiskExtents.l
Extents.t_DISK_EXTENT[32] ; 32 just for having enough space.
EndStructure
; prototypes and procedure pre-definitions
; ----------------------------------------
Prototype GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint, lpszVolumeName, cchBufferLength)
Declare.s _getVolumeNameForVolumeMountPoint(lpszVolumeMountPoint$)
Declare _DeviceIoControl_IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS(sVolumeName.s, *VolumeDiskExtents.t_VOLUME_DISK_EXTENTS)
Declare.s GetLastErrorMessage(Error.i = $ABCDEF)
Define DriveLetter.s = "d:\"
; get VolumeName of driveletter c:
Define VolumeName.s = _getVolumeNameForVolumeMountPoint(DriveLetter)
If VolumeName = ""
PrintN( "No VolumeName for driveletter '" + DriveLetter + "' found" )
; Input()
End
Else
PrintN( "Volumename of drive '" + DriveLetter + "' is '" + VolumeName + "'" )
EndIf
Define VDE.t_VOLUME_DISK_EXTENTS
_DeviceIoControl_IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS(VolumeName, @VDE)
PrintN( "Number of diskextents : " + VDE\NumberOfDiskExtents )
PrintN( "Disk : " + Str(VDE\Extents[0]\DiskNumber) )
PrintN( "Offset : " + Str(VDE\Extents[0]\StartingOffset) )
PrintN( "Length : " + Str(VDE\Extents[0]\ExtentLength) )
; Input()
Procedure _DeviceIoControl_IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS(VolumeName.s, *VolumeDiskExtents.t_VOLUME_DISK_EXTENTS)
Protected iBytesReturned.i
Protected Result.i, LastError.i
Protected VDext.t_VOLUME_DISK_EXTENTS
Protected *DE.t_DISK_EXTENT
If Right(VolumeName,1) = "\" : VolumeName = RTrim(VolumeName,"\") : EndIf
Protected hDevice = CreateFile_(VolumeName, #GENERIC_READ, #FILE_SHARE_READ|#FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0, 0)
PrintN( "Volumehandle: " + hDevice + " (" + GetLastErrorMessage() + ")" )
If hDevice > 0
Result = DeviceIoControl_( hDevice,
#IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
#Null,
0,
@VDext,
SizeOf(VDext),
@iBytesReturned,
#Null)
LastError = GetLastError_()
PrintN( "Result of DeviceIoControl call: " + Result )
If Not Result : PrintN( "LastError: " + GetLastErrorMessage(LastError) ) : PrintN( "" ) : EndIf
CloseHandle_(hDevice)
If LastError = #ERROR_INSUFFICIENT_BUFFER
PrintN( "Insufficient buffer." )
PrintN( "Nothing returned." ) : PrintN( "" )
ElseIf LastError = 0
PrintN( "Error calling DeviceIoControl!" ) : PrintN( "" )
Else
PrintN( Str(iBytesReturned) + " bytes returned." )
EndIf
*DE = @VDext\Extents[0]
With *VolumeDiskExtents
\NumberOfDiskExtents = VDext\NumberOfDiskExtents
\Extents[0]\DiskNumber = *DE\DiskNumber
\Extents[0]\StartingOffset = *DE\StartingOffset
\Extents[0]\ExtentLength = *DE\ExtentLength
EndWith
EndIf
EndProcedure
Procedure.s GetLastErrorMessage(Error.i = $ABCDEF)
Protected *MemoryID,e$,Length
If Error = $ABCDEF : Error = GetLastError_() : EndIf
If Error
*MemoryID = AllocateMemory(255)
If *MemoryID
Length = FormatMessage_ (#FORMAT_MESSAGE_FROM_SYSTEM, #Null, Error, 0, *MemoryID, 255, #Null)
If Length > 1 ; Some error messages are "" + Chr (13) + Chr (10)... stoopid M$... :(
e$ = PeekS(*MemoryID, Length - 2)
Else
e$ = "Unknown error!"
EndIf
FreeMemory(*MemoryID)
ProcedureReturn e$
Else
ProcedureReturn "Error while decoding Error("+Str(Error)+")"
EndIf
Else
ProcedureReturn "No error has occurred!"
EndIf
EndProcedure
Procedure.s _getVolumeNameForVolumeMountPoint(lpszVolumeMountPoint$)
Protected lpszVolumeName$ = Space(255)
Protected hLib
hLib = OpenLibrary(#PB_Any, "Kernel32.dll")
If hLib
;Prototype GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint, lpszVolumeName, cchBufferLength)
Define GetVolumeNameForVolumeMountPoint.GetVolumeNameForVolumeMountPoint = GetFunction(hLib,"GetVolumeNameForVolumeMountPointW")
If GetVolumeNameForVolumeMountPoint.GetVolumeNameForVolumeMountPoint = 0
Debug ("Can't find GetVolumeNameForVolumeMountPointW")
CloseLibrary(hLib)
ProcedureReturn ""
EndIf
CloseLibrary(hLib)
Else
ProcedureReturn ""
EndIf
GetVolumeNameForVolumeMountPoint(@lpszVolumeMountPoint$, @lpszVolumeName$, 255)
ProcedureReturn lpszVolumeName$
EndProcedure
Hier mal ein Auszug aus den entsprechenden Teilen in der MSDN:
Code: Alles auswählen
typedef struct _VOLUME_DISK_EXTENTS {
DWORD NumberOfDiskExtents;
DISK_EXTENT Extents[ANYSIZE_ARRAY];
} VOLUME_DISK_EXTENTS, *PVOLUME_DISK_EXTENTS;
Code: Alles auswählen
typedef struct _DISK_EXTENT {
DWORD DiskNumber;
LARGE_INTEGER StartingOffset;
LARGE_INTEGER ExtentLength;
} DISK_EXTENT, *PDISK_EXTENT;
und hier der DeviceIoControl Aufruf:
Code: Alles auswählen
BOOL
WINAPI
DeviceIoControl( (HANDLE) hDevice, // handle to device
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
(LPVOID) lpOutBuffer, // output buffer
(DWORD) nOutBufferSize, // size of output buffer
(LPDWORD) lpBytesReturned, // number of bytes returned
(LPOVERLAPPED) lpOverlapped // OVERLAPPED structure
);
Ich bin mir halt nicht sicher ob ich LARGE_INTEGER nehmen soll. Dann müsste ich mich unter einer 32Bit Umgebung doch mit den entsprechenden High/Low Werten befassen, oder?
So. Ich hoffe das ich alles verständlich erklärt habe. Falls ich was vergessen habe, bitte melden. Ich versuche immer erst ein Problem selber auf die Reihe zu bekommen, aber nach nun drei Tagen und ca. 20 Stunden vor dem Rechner bin ich etwas Ratlos....

Viele Grüße
Sundance