|
|
|
date: Wed, 02 Jul 2008 20:20:41 -0400,
group: microsoft.public.win32.programmer.gdi
back
XcvData broken on Vista
I have a print driver/port monitor pair that use XcvData and XcvDataPort
to communicate. When the printer is being used as a network printer and
connected to by a client, the driver on the client calls XcvData with a
custom string in pszDataName. My XcvDataPort function in the port
monitor recognizes this string and responds with the requested data. It's
very simple, fully supported according to the documentation, and works
flawlessly between XP boxes.
But throw Vista into the mix and it's completely broken. If the server is
XP and the client is Vista, XcvData returns error 2 (file not found). The
port monitor on the server is *not* called.
Conversely, if the server is Vista and the client is XP, XcvData returns
error 122 (insufficient buffer). And again, the port monitor on the
server is not called. However, despite the fact that XcvDataPort was
never called, XcvData gives me back error 2 as XcvDataPort's return code.
The actual printing works flawlessly in both cases, so I know it's not a
fundamental permissions or network issue. It's purely a problem with
XcvData.
I strongly suspect it's a security issue since most things Vista are, but
even if I turn off the firewall, UAC, print as admin, set permissions on
the printer to full control for everyone, etc, I get the same results.
It's as if Vista is simply refusing to allow XcvData to communicate with
the port monitor.
Any clues? Simplified code follows to give you an idea....
On the client I do this:
// open the port on the print server
HANDLE hServer;
if (!OpenPrinterW(L"MyServer\\,XcvPort DIRPS:", &hServer, NULL))
return false;
// request the data
char *pBuff = new char[dataSize];
if (!XcvData(hServer, L"GetConfigData", 0, 0, (PBYTE)pBuff, dataSize, &dataSize, &status) || status != ERROR_SUCCESS)
return false;
On the server, the port monitor does this:
DWORD WINAPI XcvDataPort(HANDLE hXcv,
LPCWSTR pszDataName,
PBYTE pInputData,
DWORD cbInputData,
PBYTE pOutputData,
DWORD cbOutputData,
PDWORD pcbOutputNeeded)
{
if (pszDataName && !wcscmp(pszDataName, L"GetConfigData"))
{
*pcbOutputNeeded = dataSize;
if (cbOutputData < dataSize)
return ERROR_INSUFFICIENT_BUFFER;
*pOutputData = myData;
return ERROR_SUCCESS;
}
return ERROR_SUCCESS;
}
date: Wed, 02 Jul 2008 20:20:41 -0400
author: Carey Gregory
Re: XcvData broken on Vista
A little additional info on this (and to bump the thread ;-)).....
Carey Gregory wrote:
>Conversely, if the server is Vista and the client is XP, XcvData returns
>error 122 (insufficient buffer). And again, the port monitor on the
>server is not called. However, despite the fact that XcvDataPort was
>never called, XcvData gives me back error 2 as XcvDataPort's return code.
This was pilot error on my part. XcvData *does* work when printing from
an XP client to a Vista host.
>But throw Vista into the mix and it's completely broken. If the server is
>XP and the client is Vista, XcvData returns error 2 (file not found). The
>port monitor on the server is *not* called.
This is confirmed. XcvData does *not* work when printing from a Vista
client to an XP host (or Server 2003).
I ran a packet sniffer on my LAN, and the RPC call from Vista to XP is
never even made, so the problem isn't on the XP side (which I figured
since XP <--> XP printing works fine). The problem is on Vista.
Since Vista clients printing to printers on XP and Server 2003 hosts is
going to be a common setup for years to come, this pretty much means
XcvData is now completely broken and useless.
date: Sat, 05 Jul 2008 18:12:48 -0400
author: Carey Gregory
Re: XcvData broken on Vista
Never mind. It's an astonishingly subtle bug in Vista involving the
OpenPrinter function. For the next victim who encounters this bug, here's
how you fix it:
Vista apparently caches printer handles, and does a less than stellar job
of it. The solution is the OpenPrinter2 function (new to Vista) and the
PRINTER_OPTION_NO_CACHE option (also new). For example, this fixes the
problem:
PRINTER_OPTIONSW po;
po.cbSize = sizeof(po);
po.dwFlags = PRINTER_OPTION_NO_CACHE;
OpenPrinter2(L"\\\\myServer\\,XvcPort myPort", &hServer, 0, &po);
Note that OpenPrinter2 is found only on Vista, so you'll have to
dynamically load it at runtime if you need to support XP, etc.
I presume what's happening is that on Vista, OpenPrinter is making the
mistake of thinking it can use a cached handle to the printer itself
instead of opening a new handle to the port monitor. But the semantics of
including the "XvcPort" string in the call to OpenPrinter demands a call
to XvcOpenPort. Vista is not doing that, which of course causes XcvData
to fail mysteriously. That requirement is clearly spelled out in the
documentation, so this is definitely a bug.
date: Mon, 07 Jul 2008 11:42:15 -0400
author: Carey Gregory
|
|