Leider knallt es beim Auslesen der PPRinterInfo2 -Struktur
( FPrinterListName.Add(PPrinter^.pPrinterName); // Zeile 528 in GetPrinterListName)
Was kann das sein? (Auf einem XP-Rechner funktioniert es!)
Da ist wohl ein Bug in folgender Methode (und auch anderen Methoden)
Erklärung:
Es wird ein neuer Record von PPrinterInfo2 im Speicher angelegt,
dann werden alle Daten aus dem Speicherblock
Buffer übertragen
und dann wird der Record an die Liste
FAllInfos angehängt.
Das ist die Idee hinter dem Code.
In Wirklichkeit werden hier aber keine Daten kopiert, sondern hauptsächlich Zeiger.
Und die Zeiger zeigen direkt in den
Buffer hinein.
Mit dem letzten Befehl FreeMem(Buffer); wird der Puffer allerdings freigegeben
und die Zeiger verweisen auf freigegebenen Speicher.
Es hängt vom Zufall ab, wie lange es dauert bis es eine Zugriffsverletzung gibt.
Delphi-Quellcode:
procedure TPrinterCustom.GetAllPrinterInfos;
var
pcbNeeded : DWORD;
pcReturned : DWORD;
Buffer : PChar;
PrinterInfo: PChar;
I : Integer;
PPrinter : PPrinterInfo2;
Flags : DWORD;
Level : Byte;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
Flags := PRINTER_ENUM_CONNECTIONS or PRINTER_ENUM_LOCAL;
Level := 2;
end
else
begin
Flags := PRINTER_ENUM_LOCAL;
Level := 2;
end;
EnumPrinters(Flags, nil, Level, nil, 0, pcbNeeded, pcReturned);
GetMem(Buffer, pcbNeeded);
EnumPrinters(Flags, nil, Level, PByte(Buffer), pcbNeeded, pcbNeeded, pcReturned);
PrinterInfo := Buffer;
for I := 0 to pcReturned - 1 do
begin
New(PPrinter);
with PPrinterInfo2(PrinterInfo)^ do
begin
PPrinter^.pServerName := pServerName; // kopiere PChar-Zeiger
PPrinter^.pPrinterName := pPrinterName; // dito
PPrinter^.pShareName := pShareName; // ...
PPrinter^.pPortName := pPortName;
PPrinter^.pDriverName := pDriverName;
PPrinter^.pComment := pComment;
PPrinter^.pLocation := pLocation;
PPrinter^.pSepFile := pSepFile;
PPrinter^.pPrintProcessor := pPrintProcessor;
PPrinter^.pDatatype := pDatatype;
PPrinter^.pParameters := pParameters;
PPrinter^.Attributes := Attributes;
PPrinter^.Priority := Priority;
PPrinter^.DefaultPriority := DefaultPriority;
PPrinter^.StartTime := StartTime;
PPrinter^.UntilTime := UntilTime;
PPrinter^.Status := Status;
PPrinter^.cJobs := cJobs;
PPrinter^.AveragePPM := AveragePPM;
FAllInfos.Add(Pointer(PPrinter));
Inc(PrinterInfo, SizeOf(TPrinterInfo2));
end;
end;
FreeMem(Buffer);
end;