Einzelnen Beitrag anzeigen

Andreas2k

Registriert seit: 2. Jan 2003
108 Beiträge
 
Delphi XE5 Professional
 
#22

AW: EnumPrinterDrivers = Zugriffsverletzung (Anfängerfrage)

  Alt 14. Mär 2017, 10:45
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;
Vielen Dank,
ich glaube langsam verstehe ich die Problematik und es macht jetzt auch Sinn das ein Element von DriverInfo2 immer 24 Byte groß ist und somit das Array nicht funktioniert.

Ich werde es jetzt nach deinem Beispiel machen was für mich jetzt endlich Sinn ergibt
Andreas
  Mit Zitat antworten Zitat