Autor Beitrag
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2162
Erhaltene Danke: 399

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Mo 13.02.17 10:37 
Hallo Forum

Problemstellung:
Beim Ermitteln von Laufwerk-Informationen mit STORAGE_DEVICE_DESCRIPTOR, bekomme ich den Fehler:

ausblenden Quelltext
1:
2:
Exception-Klasse EOSError mit Meldung 'System Error.  Code: 24.
Das Programm hat einen Befehl ausgegeben, aber die Befehlslänge ist falsch'.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
procedure TForm1.Button2Click(Sender: TObject);
const
  IOCTL_STORAGE_QUERY_PROPERTY = $002D1400;
var
  h: THandle;
  PropertyQuery: STORAGE_PROPERTY_QUERY;
  DeviceDescriptor: STORAGE_DEVICE_DESCRIPTOR;
  returnedBytes: UInt;
  InfoReceived: Boolean;
begin
  h := CreateFile(PChar('\\.\C:'), GENERIC_READ or GENERIC_WRITE,
                  FILE_SHARE_READ or FILE_SHARE_WRITE,
                  nil, OPEN_EXISTING, 00);
  if h = INVALID_HANDLE_VALUE then
  begin
    RaiseLastOSError;
    Exit;
  end;

  PropertyQuery.PropertyId := StorageDeviceProperty;
  PropertyQuery.QueryType  := PropertyStandardQuery;

  InfoReceived := DeviceIoControl(h, IOCTL_STORAGE_QUERY_PROPERTY,  // Fehler
                                  @PropertyQuery, SizeOf(PropertyQuery),
                                  @DeviceDescriptor, 
                                  SizeOf(DeviceDescriptor),
                                  returnedBytes, nil);
  if not InfoReceived then
  begin
    RaiseLastOSError;
    Exit;
  end;

  // Infos aus DeviceDescriptor auslesen
end;

Der Fehler tritt auch nur dann auf, wenn für den eigens definierten STORAGE_PROPERTY_QUERY Typ, jene Eigenschaften deklariert werden:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
type
  PStoragePropertyQuery = ^TStoragePropertyQuery;
  _STORAGE_PROPERTY_QUERY = record
    PropertyId: STORAGE_PROPERTY_ID//TStoragePropertyID;
    QueryType: STORAGE_QUERY_TYPE;  //TStorageQueryType;
    //AdditionalParameters: array[0..0] of Byte;
    AdditionalParameters: array[0..3of Byte;
  end;
  {$EXTERNALSYM _STORAGE_PROPERTY_QUERY}
  TStoragePropertyQuery  = _STORAGE_PROPERTY_QUERY;
  STORAGE_PROPERTY_QUERY = _STORAGE_PROPERTY_QUERY;
  {$EXTERNALSYM STORAGE_PROPERTY_QUERY}

Verwende ich stattdessen die Typen TStoragePropertyID und TStorageQueryType die als Cardinal hinterlegt wurden, habe ich das Problem nicht:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
type
  PStoragePropertyID = ^TStoragePropertyID;
  PSTORAGE_PROPERTY_ID = ^STORAGE_PROPERTY_ID;
  _STORAGE_PROPERTY_ID = (
    StorageDeviceProperty = 0,
    StorageAdapterProperty,
    StorageDeviceIdProperty,
    StorageDeviceUniqueIdProperty,  // Minimum support Vista/Server 2008
    StorageDeviceWriteCacheProperty,  // Minimum support Vista/Server 2008
    StorageMiniportProperty,
    StorageAccessAlignmentProperty,  // Minimum support Vista/Server 2008
    StorageDeviceSeekPenaltyProperty,  // Minimum support Win7/Server 2008 R2
    StorageDeviceTrimProperty,  // Minimum support Win7/Server 2008 R2
    StorageDeviceWriteAggregationProperty,
    StorageDeviceDeviceTelemetryProperty,
    StorageDeviceLBProvisioningProperty,  // Minimum support Win8/Server 2012
    StorageDevicePowerProperty,  // Minimum support Win8/Server 2012
    StorageDeviceCopyOffloadProperty,
    StorageDeviceResiliencyProperty,
    StorageDeviceMediumProductType,
    StorageDeviceIoCapabilityProperty = 48,
    StorageAdapterProtocolSpecificProperty,
    StorageDeviceProtocolSpecificProperty,
    StorageAdapterTemperatureProperty,
    StorageDeviceTemperatureProperty,
    StorageAdapterPhysicalTopologyProperty,
    StorageDevicePhysicalTopologyProperty,
    StorageDeviceAttributesProperty
  );
  {$EXTERNALSYM _STORAGE_PROPERTY_ID}
  {$NODEFINE TStoragePropertyID}
  TStoragePropertyID  = Cardinal;
  STORAGE_PROPERTY_ID = _STORAGE_PROPERTY_ID;
  {$EXTERNALSYM STORAGE_PROPERTY_ID}

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
type
  PStorageQueryType = ^TStorageQueryType;
  PSTORAGE_QUERY_TYPE = ^STORAGE_QUERY_TYPE;
  _STORAGE_QUERY_TYPE = (
    PropertyStandardQuery    = 0,
    PropertyExistsQuery      = 1,
    PropertyMaskQuery        = 2,
    PropertyQueryMaxDefined  = 3
  );
  {$EXTERNALSYM _STORAGE_QUERY_TYPE}
  {$NODEFINE TStorageQueryType}
  TStorageQueryType  = Cardinal;
  STORAGE_QUERY_TYPE = _STORAGE_QUERY_TYPE;
  {$EXTERNALSYM STORAGE_QUERY_TYPE}


Die Frage ist, wieso es mit den enumerischen Typen nicht geht, aber mit "festen" Typen schon. :gruebel:

Links zu:
- STORAGE_DEVICE_DESCRIPTOR (struct)
- STORAGE_PROPERTY_ID (enum)
- STORAGE_PROPERTY_QUERY (struct)
- STORAGE_QUERY_TYPE (enum)

Nachtrag:
Das Array AdditionalParameters in der _STORAGE_PROPERTY_QUERY war zu klein. Es muss in dem Fall auf 0..9 gesetzt werden.

Das Thema hat sich erledigt !!!

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)