Open JackTrapper opened 5 years ago
In order to figure out the size of memory that needs to be allocated for a subsequent call to DocumentProperties, the SetPrinter method calls:
Vcl.Printers.pas:
DocumentProperties(0, FPrinterHandle, ADevice, nil, nil, 0);
MSDN documents that DocumentProperties will return the number of bytes required when you pass fMode as 0:
If the fMode parameter is zero, the return value is the size of the buffer required to contain the printer driver initialization data. If the function fails, the return value is less than zero.
If the fMode parameter is zero, the return value is the size of the buffer required to contain the printer driver initialization data.
If the function fails, the return value is less than zero.
But rather than checking if the function failed, it immediately tries to allocate a negative amount of bytes:
DeviceMode := Marshal.AllocHGlobal(DocumentProperties(0, FPrinterHandle, ADevice, DeviceMode, DeviceMode, 0));
This is then also invalid, and is a chain of uncaught failures.
Check the function return value:
Vcl.Printers.Pas:
procedure TPrinter.SetPrinter(ADevice, ADriver, APort: PChar; ADeviceMode: THandle); var nBytesRequired: Longint; nBytesRequired := DocumentProperties(0, FPrinterHandle, ADevice, nil, nil, 0); if (nBytesRequired >= 0) then DeviceMode := GlobalAlloc(GHND, nBytesRequired) else DeviceMode := 0;
Tested
Background
In order to figure out the size of memory that needs to be allocated for a subsequent call to DocumentProperties, the SetPrinter method calls:
Vcl.Printers.pas:
MSDN documents that DocumentProperties will return the number of bytes required when you pass fMode as 0:
But rather than checking if the function failed, it immediately tries to allocate a negative amount of bytes:
This is then also invalid, and is a chain of uncaught failures.
Write correct code
Check the function return value:
Vcl.Printers.Pas: