Reputation: 15
I've been working on a native Unity plugin that will allow a user to print something (text at the moment) to the default printer on Windows.
My (EDIT: OLD) code is as follows for printing text:
bool PrintText(const char* pText, int pTextWidth, int pTextHeight, const char* pPrinterName) {
LPCSTR szDriver = (LPCSTR)"WINSPOOL";
TCHAR szPrinter[256];
DWORD cchBuffer = 255;
HDC hdcPrint = NULL;
HDC hdcPrintImg = NULL;
HANDLE hPrinter = NULL;
PRINTER_INFO_2 *pPrinterData;
BYTE pdBuffer[16384];
BOOL bReturn = FALSE;
LPCSTR documentFilename = "PrintTest";
LPCSTR documentText = (LPCSTR)pText;
DWORD cbBuf = sizeof(pdBuffer);
DWORD cbNeeded = 0;
pPrinterData = (PRINTER_INFO_2 *)&pdBuffer[0];
bReturn = GetDefaultPrinter(szPrinter, &cchBuffer);
if (bReturn) {
bReturn = OpenPrinter((LPSTR)pPrinterName, &hPrinter, NULL);
}
if (bReturn) {
bReturn = GetPrinter(hPrinter, 2, &pdBuffer[0], cbBuf, &cbNeeded);
ClosePrinter(hPrinter);
}
if (bReturn) {
hdcPrint = CreateDC(szDriver, (LPSTR)pPrinterName, pPrinterData->pPortName, NULL);
}
if (hdcPrint) {
Escape(hdcPrint, STARTDOC, 8, documentFilename, NULL);
TextOut(hdcPrint, pTextWidth, pTextHeight, documentText, strlen((const char*)documentText));
Escape(hdcPrint, NEWFRAME, 0, NULL, NULL);
Escape(hdcPrint, ENDDOC, 0, NULL, NULL);
DeleteDC(hdcPrint);
}
return bReturn;
}
This will send the document to the print spooler and successfully print, however, I get a breakpoint triggered in VS saying that a heap has been corrupted.
I'm very new to C++ and unmanaged languages in general so any pointers (ha!) will be much appreciated :)
EDIT: A person at work helped pinpoint the problems. The bare minimum code to print text to a printer:
bool PrintText(char* inputText, int positionX, int positionY, char* printerName)
{
HDC printerDeviceContext = NULL;
HANDLE printerHandle = NULL;
BOOL bReturn = FALSE;
LPCSTR documentFilename = "PrintTest";
LPCSTR documentText = (LPCSTR)inputText;
DWORD buffer;
DWORD bytesRequired;
bReturn = OpenPrinter((LPSTR)printerName, &printerHandle, NULL);
GetPrinter(printerHandle, 2, NULL, 0, &buffer);
BYTE* printerBuffer = new BYTE[buffer]; //allocate buffer
bReturn = GetPrinter(printerHandle, 2, printerBuffer, buffer, &bytesRequired);
ClosePrinter(printerHandle);
printerDeviceContext = CreateDC(NULL, printerName, NULL, NULL);
if (printerDeviceContext)
{
Escape(printerDeviceContext, STARTDOC, 8, documentFilename, NULL);
TextOut(printerDeviceContext, positionX, positionY, documentText, strlen((char*)documentText));
Escape(printerDeviceContext, NEWFRAME, 0, NULL, NULL);
Escape(printerDeviceContext, ENDDOC, 0, NULL, NULL);
DeleteDC(printerDeviceContext);
}
delete[] printerBuffer; //free buffer
return bReturn;
}
Upvotes: 0
Views: 555
Reputation: 1051
I actually don't see any direct issues which could result in heap corruption.
However there are a couple of other issues in the code above:
BYTE pdBuffer[16384]
): Basically you should call GetPrinter() twice: once without providing a buffer. This call will fail, but it will return the size of the buffer which is actually required. Then allocate a buffer for that size and provide it to the second call.Edit: 4 should actually look somewhat like this:
GetPrinter(hPrinter, 2, NULL, 0, &cbNeeded);
BYTE* pBuffer = new BYTE[cbNeeded]; //allocate buffer
bReturn = GetPrinter(hPrinter, 2, pBuffer, cbNeeded, &cbActual);
// do something with pBuffer
delete[] pBuffer; //free buffer
Edit 2: Basically there are three things that can go wrong:
You try to free memory which has already been freed
delete pObject;
//some code
delete pObject;
You try to use memory which has already been freed
delete pObject;
pObject->use();
You have a buffer overflow on the heap somewhere
pBuffer = new BYTES[3]
memcpy(pBuffer, pSomeMemory, 100); //copy 100 bytes into a 3 byte buffer
delete[] pBuffer;
Chances are very high that the actual error is in some other part of your code.
Upvotes: 1