winapiwdkprint-spooler-api

How to detect printing app when splwow64.exe is involved?


We have a print driver that captures the name of the printing exe within the driver's UI module. It does this by using the GetModuleFileName function. This works well until a 32-bit prints on a 64-bit machine. In that scenario Windows invokes splwow64.exe to print on behalf of the 32-bit application, and so GetModuleFileName returns "splwow64.exe" as the printing app rather than the one that is actually doing the printing.

We attempted to solve this by capturing splwow64.exe's parent process with the Toolhelp32 API, but this is not reliable since splwow64 remains loaded once the first app finishes printing in order to service other apps. This means that the parent process may or may not be the process that's actually printing. So far, we have been unable find any files or named pipes or other IPC objects that connect splwow64 and the printing application.

Microsoft released a hot fix (KB2815716) that causes splwow64 to terminate after a user-specified timeout period, but that doesn't solve the problem because splwow64.exe remains in memory indefinitely as long as the first printing app that invoked it remains loaded. It completely ignores the timeout the hot fix provides. (I would consider this a Windows bug.)

My question is this:

We need a method of reliably determining which application is printing when it happens to be 32-bit and splwow64.exe is being used.

The solution can reside in a print driver or in a user-mode application -- either is fine. We would strongly prefer not to use techniques involving API hooking or code injection since those actions tend to be flagged by anti-virus software.


Solution

  • I'm assuming from the referenced hotfix that you're targeting machines after Vista.

    The GetPrintExecutionData function looks to provide the information you want. It does assume you're running in the context of the spooler, but from the question, that doesn't seem to be a problem. The function returns a PRINT_EXECUTION_DATA structure with a member

    [...]clientAppPID [which] identifies the client application on whose behalf the splwow64.exe process loaded the printer driver.

    The issue referenced in KB2815716 may still affect this. I am assuming that the KB install has been verified and that the timeout is the default (2min) or non-zero. The KB is a little ambiguous about whether it's the process requesting printing that must terminate, or whether it's the print job that has to terminate. Also, if terminal services is involved in any way with the printing, as in KB2513330, then you may need to set the Sysprocs key.