RE: Calling GetPrinterDataEx from OpenPortEx in Language Monitor i by Joe
Joe
Wed Mar 23 00:45:01 CST 2005
"Debabrata Sarma[MSFT]" wrote:
> We have not seen this behavior with XP Service Pack 2.
>
Okay, steps to reproduce: -
1) Either insert the following lines at the start of a langaunge monitor's
OpenPortEx call:
DWORD size;
HANDLE hPrinter;
PRINTER_DEFAULTS PrinterDef = { NULL, NULL, PRINTER_ALL_ACCESS };
OpenPrinter(pszPrinterName, &hPrinter, &PrinterDef);
GetPrinterDataExW(hPrinter, L"PrinterDriverData", L"test", 0, 0, 0,
&size);
ClosePrinter(hPrinter);
And build and install a debug version of the driver.
OR
At the end of the post is a bunch of files defining a minimal languange
monitor. Create these files in a single directory. Run the Windows Server
2003 DDK build utility for checked builds in this directory. This will create
a file mypjlmon.dll. Copy this file to your windows\system32 directory. Then
in regedit go to
HKLM\System\CurrentControlSet\Control\Print\Environments\Windows NT
x86\Drivers and find a driver that has a non-empty "Monitor" field". Then go
to HKLM\System\CurrentControlSet\Control\Print\Monitors and find this monitor
and change its "Driver" entry to be mypjlmon.dll.
2) Restart the spooler.
3) Attach a debugger to it.
4) Breakpoint on the GetPrinterDataExW() line above.
5) Load a printer dialog to force OpenPortEx() to be called.
6) When the breakpoint happens step over the line.
Now observe. On XP Sp1 and prior the call will fail straight away
immediately due to their being no such key defined. On XP Sp2 you will get
stuck in an infinite recursive loop with this breakpoint being called each
time, until stack overflow occurs (this is actually slightly different
behaviour to what I originally described - when I used VC7.1 as the compiler
it just locked up rather than infinite looping).
Files for step 1 follow.
Joe Hindmarsh
-----------------------------------------------------------
File: makefile
!INCLUDE $(NTMAKEENV)\makefile.def
-----------------------------------------------------------
File: mypjlmon.def
LIBRARY MYPJLMON
EXPORTS
InitializePrintMonitor2
-----------------------------------------------------------
File: mypjlmon.prf
-----------------------------------------------------------
File: sources
NTPROFILEINPUT=yes
C_DEFINES=-DUNICODE -DNO_STRICT
!IFNDEF MSC_WARNING_LEVEL
MSC_WARNING_LEVEL=/W3
!ENDIF
MSC_WARNING_LEVEL=$(MSC_WARNING_LEVEL) /WX
TARGETNAME=mypjlmon
TARGETPATH=obj
TARGETTYPE=DYNLINK
TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \
$(SDK_LIB_PATH)\advapi32.lib \
$(SDK_LIB_PATH)\user32.lib \
$(SDK_LIB_PATH)\spoolss.lib
DLLENTRY=_DllMainCRTStartup
USE_MSVCRT=1
SOURCES=pjlmon.c \
pjlmon.rc
----------------------------------------------------------
File: pjlmon.rc
#include <windows.h>
#define VER_FILETYPE VFT_DLL
#define VER_FILESUBTYPE VFT2_UNKNOWN
#define VER_FILEDESCRIPTION_STR "PJL Language monitor"
#define VER_INTERNALNAME_STR "MYPJLMON.DLL"
#define VER_ORIGINALFILENAME_STR "MYPJLMON.DLL"
----------------------------------------------------------
File: pjlmon.c
#include <windows.h>
#include <winspool.h>
#include <winddi.h>
#include <winsplp.h>
BOOL DllMain(
IN HANDLE hModule,
IN DWORD dwReason,
IN LPVOID lpRes)
{
UNREFERENCED_PARAMETER(lpRes);
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
break;
default:
;
}
return TRUE;
}
BOOL WINAPI PJLMonOpenPortEx(
IN HANDLE hMonitor,
IN HANDLE hMonitorForPort,
IN LPTSTR pszPortName,
IN LPTSTR pszPrinterName,
IN OUT LPHANDLE pHandle,
IN OUT MONITOR2 *pMonitor)
{
DWORD size;
HANDLE hPrinter;
PRINTER_DEFAULTS PrinterDef = { NULL, NULL, PRINTER_ALL_ACCESS };
OpenPrinter(pszPrinterName, &hPrinter, &PrinterDef);
GetPrinterDataExW(hPrinter, L"PrinterDriverData", L"test", 0, 0, 0,
&size);
ClosePrinter(hPrinter);
return TRUE;
}
BOOL WINAPI PJLMonStartDocPort(
IN HANDLE hPort,
IN LPTSTR pszPrinterName,
IN DWORD dwJobId,
IN DWORD dwLevel,
IN LPBYTE pDocInfo)
{
return TRUE;
}
BOOL WINAPI PJLMonReadPort(
IN HANDLE hPort,
OUT LPBYTE pBuffer,
IN DWORD cbBuf,
OUT LPDWORD pcbRead)
{
return FALSE;
}
BOOL WINAPI PJLMonWritePort(
IN HANDLE hPort,
IN LPBYTE pBuffer,
IN DWORD cbBuf,
IN LPDWORD pcbWritten)
{
return FALSE;
}
BOOL WINAPI PJLMonEndDocPort(
HANDLE hPort)
{
return TRUE;
}
BOOL WINAPI PJLMonClosePort( HANDLE hPort)
{
return FALSE;
}
BOOL WINAPI PJLMonGetPrinterDataFromPort(
HANDLE hPort,
DWORD ControlID,
LPTSTR pValueName,
LPTSTR lpInBuffer,
DWORD cbInBuffer,
LPTSTR lpOutBuffer,
DWORD cbOutBuffer,
LPDWORD lpcbReturned)
{
return FALSE;
}
void WINAPI PJLMonShutdown(
HANDLE hMonitor)
{
}
MONITOR2 gMonitor2 =
{
sizeof(MONITOR2),
NULL, // EnumPort not supported
NULL, // OpenPort not supported
PJLMonOpenPortEx,
PJLMonStartDocPort,
PJLMonWritePort,
PJLMonReadPort,
PJLMonEndDocPort,
PJLMonClosePort,
NULL, // AddPort not supported
NULL, // AddPortEx not supported
NULL, // ConfigurePort not supported
NULL, // DeletePort not supported
PJLMonGetPrinterDataFromPort,
NULL, // SetPortTimeOuts not supported
0,
0,
0,
PJLMonShutdown,
NULL, // SendRecvBidiDataFromPort not supported
};
LPMONITOR2 WINAPI InitializePrintMonitor2(
PMONITORINIT pMonitorInit,
PHANDLE phMonitor
)
{
return &gMonitor2;
}