2
votes

I am currently facing a problem of the HANDLE returns NULL from network located printers.

//NOTE:szDriver is the driver location
//my device name  = "\\somelocation\HP Color LaserJet CP3505 PCL 6",
HANDLE hDC;
hDC = CreateDC(szDriver,(char*)pDevMode->dmDeviceName,NULL,pDevMode);

hDC will return NULL even I have double checked my printer and did my test print.

i put a GetLastError() call, which returns me error 1801 which means Printer Name is Invalid.

Then I had another look on pDevMode->dmDeviceName which seems like truncated. It ONLY shows part of my actual printer name.

2

2 Answers

5
votes

Later on I have found the MSDN reference of DEVMODE:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx

It stated: " dmDeviceName A zero-terminated character array that specifies the "friendly" name of the printer or display; for example, "PCL/HP LaserJet" in the case of PCL/HP LaserJet. This string is unique among device drivers. Note that this name may be truncated to fit in the dmDeviceName array."

It seems to have a limitation on 35 characters, anything over it will be truncated. That was pretty bad, because nowadays, lots of network printer has LONG names.

Then I copied the LONG name printer into a LOCAL VARIABLE (before I have assigned the value into dmDeviceName) and pass it through (instead of directly using dmDeviceName), then it works fine for me.

Here is how i did it:

//NOTE:szDriver is the driver location
//my device name  = "\\somelocation\HP Color LaserJet CP3505 PCL 6",
HANDLE hDC;

//use local variable
char    szPrinterName [255];
//NOTE:strcpysz is our own function copies a string into its destination with 0 terminator
//You can do it differently
strcpysz (szPrinterName,sizeof(szPrinterName), "\\somelocation\HP Color LaserJet CP3505 PCL 6");

//in this case 
//(char*)pDevMode->dmDeviceName will be "\\somelocation\HP Color Laser" <-TRUNCATED
hDC = CreateDC(szDriver,szPrinterName,NULL,pDevMode);

Then I can get my handle....

Hope this helps!

0
votes

You need to do something a bit more elaborate to get the full printer name, not truncated to 32 chars:

PG_PRINTDLGW pd;
PrintDlgW(&pd)
LPDEVNAMES dvn;
dvn = (LPDEVNAMES) GlobalLock(pd.hDevNames) ; 
// full name will be at:
(wchar_t *)dvn + dvn->wDeviceOffset;