Opened 3 years ago

Closed 3 years ago

#14154 closed defect (invalid)

Printing fails when selecting a printer device whose (descriptive) name is longer than 32 characters (common for network printers)

Reported by: mmacleod Owned by:
Priority: normal Milestone:
Component: wxMSW Version: 2.9.3
Keywords: print printing network Cc:
Blocked By: Blocking:
Patch: no

Description

When trying to print on wxMSW printing seems to fail when selecting printers that have long names in the printing dialog. I first noticed this on a network printer as these tend to have long names but can also replicate this just by giving a normal printer a long name.

I have traced this down to the fact that wxPrintNativeData::InitializeDevMode(...) uses the DocumentProperties(...) function (http://msdn.microsoft.com/en-us/library/windows/desktop/dd183576%28v=vs.85%29.aspx) to fill in a DEVMODE (http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565%28v=vs.85%29.aspx) structure, however the DEVMODE structure truncates device names to 32 characters.
Later on the code passes the name to CreateDC(...) inside wxGetPrinterDC(...) however CreateDC(...) expects the full printer device name and therefore fails.

It appears that the printer name would have to be obtained by some other means in order to avoid truncation, although it is not clear to me how. It looks like GetPrinter(...) and PRINTER_INFO_4 might be capable of doing this but I don't know if it is; or if there is perhaps some better way?

Change History (5)

comment:1 Changed 3 years ago by vadz

I think using GetPrinter() is indeed the correct idea because we must provide the full name to ::CreateDC() and this looks the simplest way to do it.

Looking at the code I don't understand something though: what is printerName argument passed to wxWindowsPrintNativeData::InitializeDevMode()? Shouldn't it already contain the full name of the printer? IOW how do we get this printer in the first place?

comment:2 Changed 3 years ago by mmacleod

Okay, it looks like I slightly misreported that in my haste. The problem is actually looking closer in more then one place.

DocumentProperties() doesn't actually get called, as the name string is empty at that point; At some point further on this function does get called with a non empty name string (which is already truncated at this point) however the DocumentProperties() function still doesn't get called then as m_devMode is not NULL. It is not clear to me when, if ever, m_devMode will be NULL and a name passed in. So its possible DocumentProperties never gets called? (Presumably there is some case where it does, or is this actually dead code?)
In the case where m_devMode is NULL and the name string passed in is also NULL (the case I am actually running into) the DEVMODE structure gets filled in via other means and not DocumentProperties. However the same problem applies, as it is the DEVMODE structure itself that truncates the name string.

So essentially from what I can tell (I do not know much about printing APIs).
1) Everywhere where the DEVMODE structure is filled in we will have to manually stash the name in a separate variable) and then everywhere where the DEVMODE structure is used the name from this seperate variable should be used instead and not the name from the DEDEVMODE structure.
2) Iff the code that calls DocumentProperties() is actually unreachable then it should obviously be removed entirely. Trying briefly with a break point and inspecting the code I can't spot an obvious situation in which it could be reached, however it would take a lot more analysis to be sure on this part.

comment:3 Changed 3 years ago by vadz

Unfortunately I don't understand the logic of this code neither (it doesn't help that it's very, very old). The best we can do is to fix the bug you're seeing (probably by doing (1) as I don't see what else can we do) and the first step would be to describe what exactly needs to be done in order to reproduce it? I.e. how is the printer selected in the first place -- from the print dialog? Can this be seen in the printing sample?

comment:4 Changed 3 years ago by mmacleod

Hmm, it looks like it isn't as clear cut as I thought.

After doing a rebuild of wxWidgets and trying again with the sample I have discovered that the code overwrites the "printer name" slightly further on via m_devnames with the line "wxString printerName = (LPTSTR)lpDevNames + lpDevNames->wDeviceOffset;" and that unlike the names in the other cases this name is not truncated.
This then allows ::CreateDC() to work correctly as it has the full non-truncated name.

I can't seem to get it to reach ::CreateDC with a truncated name anymore, not sure what has changed. Either it was something specific to my printer configuration that has now changed. Or something was wrong with my wx build? Not sure...

Anyway maybe close this as invalid for now, I can play around some more with various configurations and if it happens again I will re-open it.

Thanks.

comment:5 Changed 3 years ago by vadz

  • Resolution set to invalid
  • Status changed from new to closed

Hmm, ok, please reopen if you do manage to find a way to reproduce the bug.

Note: See TracTickets for help on using tickets.