Man kann ja dennoch das Array verwenden, aber dann eben nicht auf alle, sondern nur auf die richige Anzahl der Einträge zugreifen.
0 bis daswasdieapisagt-1
BOOL EnumPrinterDrivers(
_In_ LPTSTR pName,
_In_ LPTSTR pEnvironment,
_In_ DWORD Level,
_Out_ LPBYTE pDriverInfo,
_In_ DWORD cbBuf,
_Out_ LPDWORD pcbNeeded,
_Out_ LPDWORD pcReturned
);
Aber das Problem ist ja, dass
pcbNeeded
in Bytes angegeben ist und ausdrücklich
nicht pcReturned * SizeOf(DRIVER_INFO_2)
ist. Nichtmal ein Vielfaches von
SizeOf(DRIVER_INFO_2)
ist garantiert. Mit einem
Array of DRIVER_INFO_2
zu arbeiten, macht doch rein von der Logik her einfach keinen Sinn.
Kann man das so machen oder ist das zu gefährlich / dümmlich ?
Macht wenig Sinn. Der 3. Aufruf der
API wird fehlschlagen (bzw. noch schlimmer: zufälligen Speicher überschreiben), da dein Array nach wie vor die falsche Größe hat. Siehe oben:
pcbNeeded
ist kein Vielfaches von
SizeOf(DRIVER_INFO_2)
. Der Array Ansatz kann nicht funktionieren - du hast enweder zu wenig Platz = Buffer Overflow oder du reservierst zu viel = Logisch fragwürdig. Arrays sollte man wirklich nur dann verwenden, wenn man homogene Strukturen zusammenfassen will.
Delphi-Quellcode:
function EnumPrinterDriversW(pName: LPSTR; pEnvironment: LPSTR; Level: DWord; pDriverInfo: LPBYTE;
cbBuf: DWord; var pcbNeeded: DWord; var cbReturned: DWord): BOOL; stdcall;
external 'winspool.drv';
type
DRIVER_INFO_2 = packed record
cVersion: DWord;
pName: LPTSTR;
pEnvironment: LPTSTR;
pDriverPath: LPTSTR;
pDataFile: LPTSTR;
pConfigFile: LPTSTR;
end;
PDriverInfo2 = ^TDriverInfo2;
TDriverInfo2 = DRIVER_INFO_2;
procedure TForm6.FormCreate(Sender: TObject);
var
Buf: Pointer;
ErrorCode,
pcbNeeded,
cbReturned,
I: DWord;
Driver: PDriverInfo2;
begin
EnumPrinterDriversW(nil, nil, 2, nil, 0, pcbNeeded, cbReturned);
ErrorCode := GetLastError;
if (ErrorCode <> ERROR_INSUFFICIENT_BUFFER) then
begin
RaiseLastOsError(ErrorCode);
end;
GetMem(Buf, pcbNeeded);
try
if (not EnumPrinterDriversW(nil, nil, 2, Buf, pcbNeeded, pcbNeeded, cbReturned)) then
begin
RaiseLastOsError;
end;
Driver := Buf;
for I := 1 to cbReturned do
begin
ShowMessage(Driver^.pName);
Inc(Driver);
end;
finally
FreeMem(Buf);
end;
end;
Wenn der Zugriff umbedingt über ein Array erfolgen soll, dann geht auch folgende Variante:
Delphi-Quellcode:
procedure TForm6.FormCreate(Sender: TObject);
type
PDriverInfo2Array = ^TDriverInfo2Array;
TDriverInfo2Array = array[0..0] of TDriverInfo2;
var
Buf: Pointer;
...
I: DWord;
Drivers: PDriverInfo2Array;
begin
...
try
...
Drivers := Buf;
for I := 0 to cbReturned - 1 do
begin
ShowMessage(Drivers^[I].pName);
end;
finally
...
end;
end;