Stroh108
Stroh108

Reputation: 13

How to use OpenPrinter for a network printer?

I'm trying to establish a connection between a Windows 10 machine and a network printer via OpenPrinter API.

At the moment, OpenPrinter does not return with a valid handle and GetLastError() returns with Error 1801: "The printer name is invalid".

If I use a local printer connected to the machine, it does not occur and it works fine.

I've tried several versions of the name: The printer name used by Windows Control Panel, device name, IP, etc.,... but no success.

Within the registry only the local device is available. I use the network printer in several programs and I can ping it. So, from the network side it is ok.

But, the more I read about the Windows printer API, the more I get confused:

My basic understanding of this API is that I use an UNC name and post it to OpenPrinter(). Then OpenPrinter gives me a valid handle for the printer.

From my point of view anything else, like a socket connection, would be done by the API. Maybe I'm completely wrong and somebody can enlighten me.

Basically, the posted code snipped is an example provided by MSDN.

The variable LPWSTR printer = L"\\\\gisrv44.wekal.de\\wkkp04"; is given to LPTSTR szPrinterName.

BOOL RawDataToPrinter(LPTSTR szPrinterName, LPBYTE lpData, DWORD dwCount)
{

BOOL     bStatus = FALSE;
HANDLE     hPrinter = NULL;
DOC_INFO_1 DocInfo;
DWORD      dwJob = 0L;
DWORD      dwBytesWritten = 0L;
DWORD dwError = 0;

PRINTER_DEFAULTSA *pDefault = new PRINTER_DEFAULTSA();
pDefault->DesiredAccess = PRINTER_ACCESS_ADMINISTER;
PRINTER_OPTIONSA   *pOptions = new PRINTER_OPTIONSA();
pOptions->dwFlags = PRINTER_OPTION_NO_CACHE;

// Open a handle to the printer. 
bStatus = OpenPrinter(szPrinterName, &hPrinter, pDefault);
if (!bStatus)
{
    dwError = GetLastError();
    cout << dwError << endl;

}
    .....etc
}

Upvotes: 1

Views: 4412

Answers (1)

Elijan9
Elijan9

Reputation: 1304

I think this is your problem:

The variable LPWSTR printer = L"\\gisrv44.wekal.de\wkkp04"; is given to LPTSTR szPrinterName.

In C/C++ the character \ has a special purpose in string literals and can be used to express string that otherwise can't be expressed, such as \0, \n, \x48 and so on. This means that if you want to include a \ in your code, you will need to enter it twice, so you'll need to enter:

LPWSTR printer = L"\\\\gisrv44.wekal.de\\wkkp04";

If you want the string literal to become \\gisrv44.wekal.de\wkkp04

Alternatively, you can use the C++11 raw string literal syntax like:

LPWSTR printer = LR"(\\gisrv44.wekal.de\wkkp04)";

See here for more on C string literals


Furthermore, the usage of LPWSTR printer = ... for your printer url would suggest you are using the Unicode version of OpenPrinter (so OpenPrinterW) while PRINTER_DEFAULTSA would suggest you are using the ASCII version. Both should either use the ASCII (LPCSTR and PRINTER_DEFAULTSA) or the Unicode (LPWSTR and PRINTER_DEFAULTSW) variant, depending on the actual OpenPrinter define.

I would recommend to use OpenPrinterA or OpenPrinterW to make all WINAPI types and functions explicitly use ASCII or Unicode.

For example:

LPCSTR printer = R"(\\gisrv44.wekal.de\wkkp04)";

PRINTER_DEFAULTSA pDefault;
pDefault.DesiredAccess = PRINTER_ACCESS_ADMINISTER;

// Open a handle to the printer. 
bStatus = OpenPrinterA(szPrinterName, &hPrinter, &pDefault);

Upvotes: 2

Related Questions