Windows Printer Spooler API get print data - winapi

Is it possible to extract RAW/Plain Text or any useful data from a Print Job using the Windows Printer Spooler API?
I am trying to build a separate App on a windows machine that listens to a Print Job and extracts "usable" data from it (plain text, etc.).
Say I print a "Hello Word" text from notepad, a separate application using the Win32 Spooler API would "catch" this job, get the plain text, then store it in a File/Database while the Printer prints it.
I'm looking up the Win32 APIs, printMon and before inpout32 (for port listening).
If someone can give me some guidance, help or what more to look into or even shed some light if this is possible it would be very helpful.
Thanks!

Probably the information from my old answer and another one could help you. I developed print monitor some year ago so I could answer on your additional questions. Perhaps you can solve your problem like I describe in old answer without usage of WDK (DDK). You can reduce the problem to the monitoring for files with respect of ReadDirectoryChangesW or FindNextChangeNotification / FindFirstChangeNotification API.

Related

netsh.exe message translations

Where can I find all messages translated into different languages for netsh.exe?
My problem is that I run netsh.exe to handle a Wi-Fi hotspot in my application and read/parse the output to see what happened. Now the problem is, that I cannot really parse the output, because it is different in every language version of Windows.
I am looking for a site that could have all the localized messages from the netsh.exe. Is there any? Another solution would be to somehow force the messages to another language (English), but I haven’t seen a good way to do that.
I went with alternative solution: .NET and P/Invoke
Solution on GitHub.

Change Display Resolution from Windows Service (Windows 7)

( Hi, everyone. I'm very new to Windows programming, so I apologize in advance if this has already been asked and I just didn't know what to search for, but this problem has been driving me crazy and I know someone could probably answer this really easily. )
My company has an application that runs as a service in Windows 7. I have been tasked with writing code to change display settings, but I apparently cannot do this from a system service. I created a small executable that changes the color depth to 8bpp in about 5-10 lines of code, but when I place this code in my application, it returns success yet does not actually succeed (nothing changes).
Without a commanding knowledge of how Windows programming works, I have managed to try a MILLION different things to get it to work but with no avail. Can somebody PLEASE help me find what I need to do to make this code function?
On Vista and upwards services run in a different session (session 0) and are isolated from the interactive desktop(s). This means that code that you run from the service is simply unable to make the changes you want. The obvious conclusion is that you need to run code in the interactive desktop.
Now you can do this, but it's not exactly easy to achieve. What you will need to do is arrange for your service to launch an process that runs on the interactive desktop: Launching an interactive process from Windows Service in Windows Vista and later. That process, rather than the service, is what will have to make the changes.
Whilst it is possible to achieve what you want, I think you should regard the difficulties involved as a signal to review whether or not your proposed approach is the best solution to whatever your underlying problem is.

Creating Windows Print Driver

I'm looking to create a print driver that will monitor jobs sent to a particular printer and add in a small amount of text to each page. I have downloaded the WDK and have the bitmap example working, but the monitor examples are complicated. The WDK documentation seems to be lacking any explanation of the samples. I also don't see any Visual Studio templates for Windows Drivers (not sure if they are supposed to be installed as part of the WDK or not).
I think what I'm struggling the most with is seeing the overall approach. Since this is printing to a printer (not file), I'm assuming I still need to use the printer's driver somehow. So does that make what I'm trying to do a "Filter Driver"? As you can tell, this is not something I've done before, so any help or direction would be greatly appreciated.
Thanks,
Ryan
What exactly do you need to add in? You can use the Mini Driver in the WinDDK and just hijack one of the commands.
If you need to add in something more you'll probably want a port monitor like Redmon (or we are about to release one) that can take your job and route it to some application that modifies the data and then routes to the final printer.
If you just need to insert some items at the very start (inject some PCL or something) then you can use the Windows separator page and insert the data at the start of the stream.
If you give some more detail about what exactly you need to modify or insert I can probably help a little more.

How to read some data from a Windows application memory?

I have an application, which displays me some data. I need to attach to this app's process, find the data I need in memory (one single number, actually), and save it somewhere. This application doesn't seem to use standard windows controls, so things aren't going to be as simple as reading controls data using AutoIt or something similar.
Currently I'm a self-learner database guy and have quite shallow knowledge about windows apps debugging. Not even sure if I asked my question correctly enough.
So, can you give me some starter guidelines about, say, what should I read first, and general directions I should work on?
Thanks.
To read memory of other application you need to open the process with respect of OpenProcess with at least PROCESS_VM_READ access rights and then use ReadProcessMemory to read any memory address from the process. If you are an administrator or have debug privilege you will be able to open any process with maximal access rights, you need only to enable SeDebugPrivilege before (see for example http://support.microsoft.com/kb/131065).
If you don't know a much about the memory of the destination process you can just enumerate the memory blocks with respect of VirtualQueryEx (see How does one use VirtualAllocEx do make room for a code cave? as an example where I examine the program code. The program data you can examine in the same way).
The most practical problem which I see is that you ask your question in too general way. If you explain more what kind of the data you are looking for I could probably suggest you a better way. For example if you could see the data somewhere you could examine the corresponding windows and controls with respect of Spy++ (a part of Visual Studio Tools). The most important are the class of windows (or controls) and the messages which will be send at the moment when the most interesting window are displayed. You can also use Process Monitor to trace all file and registry access at the time when the windows with the interesting information will be displayed. At least at the beginning you should examine the memory of the process with ReadProcessMemory at the moment when the data which you are looking for are displayed on the window.
If you will have no success in your investigations I'd recommend you to insert in your question more information.
My primary advice is: try to find any other method of integration than this. Even if you succeed, you'll be hostage to any kinds of changes in the target process, and possibly in the Windows O/S. What you are describing is behaviour most virus scanners should flag and hinder: if not now, then in the future.
That said, you can take a look at DLL injection. However, it sounds as if you're going to have to debug the heck out of the target process at the disassembly level: otherwise, how are you going to know what memory address to read?
I used to know the windows debugging API but it's long lost memory. How about using ollydbg:
http://www.ollydbg.de/
And controlling that with both ollydbg script and autoit?
Sounds interesting... but very difficult. Since you say this is a 'one-off', what about something like this instead?
Take a screenshot of this application.
Run the screenshot through an OCR program
If you are able to read the text you are looking for in a predictable way, you're halfway there!
So now if you can read a OCR'd screenshot of your application, it is a simple matter of writing a program that does the following:
Scripts the steps to get the data on the screen
Creates a screenshot of the data in question
Runs it through an OCR program like Microsoft Office Document Imaging
Extracts the relevant text and does 'whatever' with it.
I have done something like this before with pretty good results, but I would say it is a fragile solution. If the application changes, it stops working. If the OCR can't read the text, it stops working. If the OCR reads the wrong text, it might do worse things than stop working...
As the other posters have said, reaching into memory and pulling out data is a pretty advanced topic... kudos to you if you can figure out a way to do that!
I know this may not be a popular answer, due to the nature of what this software is used for, but programs like CheatEngine and ArtMoney allow you to search through all the memory reserved by a process for a given value, then refine the results till you find the address of the value you're looking for.
I learned this initially while trying to learn how to better protect my games after coming across a trainer for one of them, but have found the technique occasionally useful when debugging.
Here is an example of the technique described above in use: https://www.youtube.com/watch?v=Nv04gYx2jMw&t=265

How do you control printer tray selection for printer in Windows

We need to be able to change the default selected print tray of a given printer. Does anyone have VC++/win32 code for doing this?
In case it matters, I believe we have to change the default setting for the printer. Our print jobs are executed by an application other than ours, so we can't make these kinds of changes in the context of a print operation originating from inside our application. Unless there is some way to modify the default print settings in a different application, I think we are stuck changing the user's defaults for the printer, initiating our print job, then setting the defaults back to the original values.
We'd really prefer to have the defaults change for the current user only, and not require any special UAC elevation, etc...
I suspect that it will use something similar to what is shown in this MSDN article, and involve setting fields in the DEVMODE structure (either dmDefaultSource or dmFormName or both).
Any takers? Or does anyone have any gotchas they'd like to share?
EDIT: Here is a link for DEVMODE documentation DEVMODE documentation
EDIT: I should also point out that we are looking for a general solution - not something specific to a particular printer (we deploy in many, many environments)
FYI - the solution we wound up using was to capture the DEVMODE structure. We have a small win32 app that presents the printer settings dialog (via DocumentProperties with fMode set to DM_IN_PROMPT). The resultant DEVMODE is then saved to disk. When we do our printing, we capture the current DEVMODE, set the stored DEVMODE, initiate the print, then restore the original DEVMODE.
This actually works quite well. Occasionally, the print drivers will update and cause the stored DEVMODE to break, but that doesn't happen very often and it's easy enough for users to fix.
As an extra bonus, this approach allows us to capture ALL of the printer settings (not just the output tray) - so we were able to support advanced settings like stapling, collating, etc...
Tip: If you try this, be sure to write to disk as a binary output stream. In my initial evaluation of this approach, I accidentally set the output stream up as a text output stream. Things would work fine for many cases, then suddenly break for some printers (that used high order bytes in their DEVMODE private data). A dumb, but easy, mistake to make - and one that took a very nice solution off the table for awhile.
Setting features like this can be tricky, especially if the driver doesn't follow Microsoft's print guidelines. That being said, we've had some success with System.Drawing.Printing.PrinterSettings. You can set PaperSource but I'm not sure you can set the defaults.
If you haven't seen this example you may want to look further at it. It describes a method to store and reload printer settings. One of my guys pointed it to me:
PrinterSettings - Changing, Storing and Loading Printer Settings
Another method, that could work but might not work for you, is to determine your the handful of setups you need. Install a printer with each of these (ie: Tray 1, Tray 2) setups. Then simply switch the default printer on print. Not what you are looking for but it may help.
What we typically do in these situations is have the 3rd party app write the data to a folder that we are monitoring, we then pick up the file and parse the Postscript or PCL ourselves and change the paper tray and then send onto the destination device. A lot simpler then it may sound.
dmDefaultSource controls the tray. Unfortunately the values you'll want to set this to differs depending on your driver as this is a bin number and not necessarily the same number as the tray# printed on your printer.
The following link provides some VB6 code for gathering information about your printers tray/bin assignments. You can use that information to programatically assign dmDefaultSource to the appropriate bin # for a tray. You basically need to use DeviceCapabilities to return information about your printers and then search for a string (like "Tray 1") to get the associated bin number.
http://support.microsoft.com/kb/194789
I had to do something very similar recently on a specific printer driver and it required a vendor specific SDK. The tray doesn't seem to appear in DEVMODE or any of the other PRINTINFO_* structures so I guess I'd drop an email to the printer vendor.
As a last resort, I can think of two possible hacks. One is to automate the driver at GUI level using a scripted tool such as AutoIT. Second is to dump the registry to file, change the driver setting, dump the registry again, and compare the differences (may or may not work).
As far as I know, printers are controlled by the printer driver by sending them SNMP or PJL commands. But not all printers implement completely these sets of commands.
For HP printers I found at: http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?lang=en&cc=us&objectID=bpl07282&jumpid=reg_R1002_USEN some PJL commands (there are some related to the tray too).
I'm not sure this help, but take it as a hint for future searches...

Resources