Additional tests show that IsValidDevmodeA/W actually does a lot more than I previously thought.
Implement the missing known features and test this little function to death in winspool_apitest to cover each and every possible call.
They pass on ReactOS, Windows Server 2003 and Windows 8.1.
Credits and many thanks go to Mark Jansen for the additional tests!
svn path=/branches/colins-printing-for-freedom/; revision=70595
- Implement StartDocPrinterA.
- Fix an uninitialized access in StartDocPrinterW.
- Make OpenPrinterA and StartDocPrinterA consistent.
svn path=/branches/colins-printing-for-freedom/; revision=70505
Add and fully implement IsValidDevmodeA and IsValidDevmodeW.
[WINSPOOL_APITEST]
Add tests for IsValidDevmodeA and IsValidDevmodeW covering the entire functions.
svn path=/branches/colins-printing-for-freedom/; revision=70503
Add a missing dependency to psdk for the skiplist code.
Work in this branch continues as long as Trunk still serves a purpose for the 0.4.0 release.
svn path=/branches/colins-printing-for-freedom/; revision=70502
The Park-Miller Lehmer Random Number Generator only outputs 31 uniformly distributed random bits. Bit 32 is always zero.
Fix the code accordingly.
This limits the maximum number of Skiplist levels to 31, but we only use 16 anyway so far.
svn path=/branches/colins-printing-for-freedom/; revision=68991
Make winspool_print print a file to the "Dummy Printer On LPT1".
We're now able to print RAW data through the native Win32 Spooler APIs.
https://youtu.be/cNzePucTOLY
svn path=/branches/colins-printing-for-freedom/; revision=68567
This is where things get dirty. StartDocPort of the Print Monitor needs the Printer Name and Job ID of the job to print on this port.
But StartDocPort is called by LocalStartDocPrinter, whose parameters are fixed and don't include this information.
Therefore, I have no way to pass these parameters to a port handle directly. Instead, I need to store a pointer to the job in the port structure itself and let the next port handle pick up this information in LocalStartDocPrinter.
Surprisingly, Windows doesn't seem to do any better here. For testing, I stalled execution inside my own Print Processor and called StartDocPrinter from another thread.
It then picked up and "stole" the stored job information. When the Print Processor resumed execution, the job information wasn't present anymore and its StartDocPrinter call crashed. So even Windows definitely stores this information only for a single StartDocPrinter call.
Having solved this, I could finally implement OpenPrinter, StartDocPrinter, ReadPrinter, WritePrinter and ClosePrinter for Port handles as well as OpenPrinter and ClosePrinter for Xcv handles.
svn path=/branches/colins-printing-for-freedom/; revision=68550
Stalling execution of the Print Processor under Windows reveals that the status flag JOB_STATUS_PRINTING is only set right before calling PrintDocumentOnPrintProcessor.
svn path=/branches/colins-printing-for-freedom/; revision=68549
Fix a nasty stack corruption due to a *ppwsz[cch] vs. (*ppwsz)[cch] case.
But actually, we don't even need this line for null-terminating the string at all, because we operate on zero-initialized buffers. Remove it in another location as well.
svn path=/branches/colins-printing-for-freedom/; revision=68510
Rewrite RevertToPrinterSelf and ImpersonatePrinterClient.
In contrast to what I first thought, they shall also work when the thread has no impersonation token. This occurs for example when spooler functions are called from a thread that doesn't originate from a RPC request.
The rewritten functions also provide proper error codes.
The native behaviour of these functions was verified through API Monitoring under Windows.
svn path=/branches/colins-printing-for-freedom/; revision=68472
[LOCALSPL]
- A Print Job has more optional fields than I thought. Only do a wcslen on them if they are not NULL.
- Make the code for checking changed fields more robust. Add checks for NULL to the Find and Compare functions.
- Fix some wrong parameters given to CopyMemory.
- Set the pPort field of a LOCAL_PRINTER structure.
[WINSPOOL]
Only pass the datatype from the DOC_INFO_1W structure of StartDocPrinterW to SetJobW if it's not NULL.
For StartDocPrinterW, this means that the datatype shall not be changed while SetJobW would return ERROR_INVALID_DATATYPE if none was passed.
svn path=/branches/colins-printing-for-freedom/; revision=68471
Bugfix: winspool.drv shall only do local connections for now.
Even if wszName may include a computer name that needs to be extracted in the future, it must in no way be directly passed as the NetworkAddr parameter.
Fixes problems when using the spooler components with the "ncacn_np" protocol or with Windows' rpcrt4.dll.
svn path=/branches/colins-printing-for-freedom/; revision=68417
Bugfix: hPrinter is a PSPOOLER_HANDLE for all winspool functions. The hPrinter member of a SPOOLER_HANDLE is only passed to RPC calls.
svn path=/branches/colins-printing-for-freedom/; revision=68414
The pDevModeContainer parameter of _RpcOpenPrinter is not optional, but its contents may be null.
You can see this in the IDL file (pDevModeContainer is not marked with the "unique" attribute) or refer to https://msdn.microsoft.com/en-us/library/cc244808.aspx
svn path=/branches/colins-printing-for-freedom/; revision=68412
Add registry entries for all developed printing components along with a dummy printer on LPT1.
These entries are enough to boot up the spooler.
svn path=/branches/colins-printing-for-freedom/; revision=68411
- Bugfix: A cb value includes the terminating null-character, a cch value does not. Fix the conversion.
- Bugfix: Properly calculate the required buffer size in LocalGetPrintProcessorDirectory and properly copy the string.
svn path=/branches/colins-printing-for-freedom/; revision=68410
- Add RPC calls, proper marshalling and exports for all implemented functions.
- Move the spoolsv stubs into categories, so that future implementations in winspool, spoolsv, spoolss and localspl can follow a consistent naming scheme.
svn path=/branches/colins-printing-for-freedom/; revision=68408
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
- Bugfix: Unset bStartedDoc in LocalmonEndDocPort so that new documents can be started again.
- Bugfix: Use CREATE_ALWAYS instead of OPEN_ALWAYS for CreateFileW to truncate any existing output file before writing a new document into it.
svn path=/branches/colins-printing-for-freedom/; revision=68403
My idea to just care about COM, FILE: and LPT ports was too short-sighted.
Apart from selecting a FILE: port that prompts for the output filename at printing, you can also add a port "C:\bla.txt" to always output into that particular file.
Even shared network printers can be added as a local port "\\COMPUTERNAME\PrinterName" (and Windows even does that when auto-adding printers found on the network). Note that this is the exception though, shared network printers are normally handled by a different component.
Our localmon now handles all valid ports found in the registry.
Port name checks were modified to be extra-picky and not let any false positives happen (e.g. trying to print into a file starting with "LPT" shouldn't be treated as printing to an LPT port)
svn path=/branches/colins-printing-for-freedom/; revision=68402
Bugfix: The Printer Name with Port is given through the parameter pPrinterName, not the pPrinterName field of the pPrintProcessorOpenData structure.
svn path=/branches/colins-printing-for-freedom/; revision=68401
- Rewrite LocalOpenPrinter to also properly support opening Port and Xcv handles.
- Manage a list of Ports and their associated Print Monitors.
- const-ify some parameters.
svn path=/branches/colins-printing-for-freedom/; revision=68397
- Initialize all Print Monitors on startup and keep a list of them.
- Implement LocalEnumMonitors and LocalEnumPorts.
- Check the result of the initialization functions.
[SPOOLSS]
- Implement support for multiple Print Providers.
Initialize them on startup and keep a list here as well.
- Implement all functions that had simple stubs in the C code. This still needs to be done for the remaining functions stubbed in the .spec file.
But generally spoken, this always boils down to 3 cases:
* Forward the call to the Local Spooler (for general functions like GetPrintProcessorDirectory).
* Forward the call to the Print Provider we used for OpenPrinter (for functions like SetJob).
* Forward the call to all Print Providers and collect the results (for functions like EnumPrinters).
svn path=/branches/colins-printing-for-freedom/; revision=68375
- Bugfix: LocalmonClosePort must only free the memory for virtual file ports. Other port entries are reused.
- Bugfix: Set the port type to PortType_OtherLPT in all conditions that ít's not a physical LPT port.
- Synchronize access to the port lists.
- Keep a list of open Xcv handles as well to properly close them on shutdown.
- Add traces to all monitor functions for easier debugging. (requires DEBUGCHANNEL=+localmon environment variable)
svn path=/branches/colins-printing-for-freedom/; revision=68364
Implement a Local Port Monitor for COM, FILE: and LPT ports, usable as a drop-in replacement for the Windows original.
Fully implements opening, enumerating and closing ports, starting and ending documents as well as reading and writing to ports along with Xcv data transfer between Port Monitor and Port Monitor UI.
Does not support IrDA printers unlike the Windows original, sorry guys :-P
The Windows Local Port Monitor is partly documented in an ancient DDK sample.
Additional information was gathered through API monitoring.
TODO:
- AddPort, DeletePort and PortIsValid Xcv functions need to be implemented.
- A real privilege check needs to be added to LocalmonXcvOpenPort.
- TESTING TESTING TESTING (under Windows) and fixing bugs.
To test it under Windows:
- Copy the compiled "localmon.dll" to the system32 directory.
- Open regedit.exe and move to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors\Local Port.
- Replace "localspl.dll" by "localmon.dll" for the "Driver" value.
[SPOOLSS]
- Properly stub EnumPortsW to let localmon compile.
svn path=/branches/colins-printing-for-freedom/; revision=68356
Source our winspool.h from MinGW-w64.
Our current version was still based on MinGW w32api from 2005 and missing lots of definitions added ages ago.
svn path=/branches/colins-printing-for-freedom/; revision=68355
Bugfix: All functions returning multiple elements must only set *pcReturned to the element count on success!
Currently, this was also done when querying the needed buffer size. But for this case, *pcReturned just has to be zeroed.
svn path=/branches/colins-printing-for-freedom/; revision=68335
Bugfix: The RegEnum* functions take the buffer size _including_ the terminating null character as input and only return the actual data length _without_ the terminating null character as output.
svn path=/branches/colins-printing-for-freedom/; revision=68324
Bugfix: I want to dereference the pointer and then increment its value, not increment the pointer address.
svn path=/branches/colins-printing-for-freedom/; revision=68323
Bugfix: The last entry in a doubly linked list (LIST_ENTRY structure) is actually the head element again, not NULL!
svn path=/branches/colins-printing-for-freedom/; revision=68322
- Partly implement LocalScheduleJob.
- Set the default status to JOB_STATUS_SPOOLING in LocalAddJob.
- Fix file sharing flags in ReadJobShadowFile and WriteJobShadowFile.
[SPOOLSS, SPOOLSV, WINSPOOL]
- Forward the newly implemented ScheduleJob call all the way down to localspl.dll.
- Stub ReadPrinter.
[WINPRINT]
Implement a very simple RAW Print Processor that just takes the input and forwards it to the Print Monitor. This one doesn't even do pausing or multiple copies yet.
The implementation includes:
- Implemented ClosePrintProcessor, OpenPrintProcessor and PrintDocumentOnPrintProcessor (apart from the previously implemented EnumPrintProcessorDatatypesW).
- Stubbed ControlPrintProcessor and GetPrintProcessorCapabilities.
svn path=/branches/colins-printing-for-freedom/; revision=68304
- Write the shadow file after changing job details.
- dwUnknown2 in the shadow file header is actually the offset of the Print Processor Parameters.
- Process all known fields of the shadow file in ReadJobShadowFile and WriteJobShadowFile.
svn path=/branches/colins-printing-for-freedom/; revision=68292
Connect AddJobW, EnumJobsW, GetJobW and SetJobW from winspool.drv over spoolsv.exe and spoolss.dll to the implemented functions in localspl.dll (including marshalling the involved structures down and up).
I decided to not use my recently implemented MarshallDownStructure API here and rather do the pointer math in place as this is simpler and faster.
svn path=/branches/colins-printing-for-freedom/; revision=68288
Implement LocalEnumJobs the easy way by using the new Skiplist function LookupNodeByIndexSkiplist and calling _LocalGetJobLevelX for each job.
This required changes in _LocalGetJobLevelX, so that the strings are now copied in reverse to the end of the buffer while the structure is copied to the start. By preserving the pointers after each call, the function can be called multiple times.
svn path=/branches/colins-printing-for-freedom/; revision=68264
- Add a LookupNodeByIndexSkiplist function and a small test for it in skiplist_test.
- Remove a redundant double-set in LookupElementSkiplist.
Yes, we now have one lookup function that accepts search criteria and returns an element and another one that accepts an index and returns a SKIPLIST_NODE.
It's simply because I have exactly these two cases :)
You're free to implement the two missing functions or refactor this code another way.
svn path=/branches/colins-printing-for-freedom/; revision=68262
- Implement LocalSetJob for Level 1 and 2.
- Add pPrintProcessor, pwszPrintProcessorParameters and pwszStatus members to the LOCAL_JOB structure and use them in LocalAddJob, LocalGetJob and LocalSetJob.
- Fix naming of some LOCAL_JOB members.
svn path=/branches/colins-printing-for-freedom/; revision=68259
Halfplement and document the undocumented but exported MarshallDownStructure API.
Information about this API was exclusively gained by writing a custom XML file for rohitab.com's API Monitor and monitoring calls under Windows.
I could figure out the parameters passed to the function, but don't really know what most of them are for.
For me, the function does what it should and what I will soon need it for, but without making use of cbSize, cbPerElementSize, cbStructureSize and bSomeBoolean.
A Code Review and additional hints are highly appreciated! My XML file for the API Monitor is available on request.
svn path=/branches/colins-printing-for-freedom/; revision=68253
Local Communication between winspool.drv and spoolsv.exe happens using the ncalrpc protocol. The ncacn_np endpoint is only available when sharing a printer. It's then used for receiving a remote call from win32spl.dll.
Reference: http://www.hsc.fr/ressources/articles/win_net_srv/msrpc_spoolss.html
This fixes e.g. testing a _RpcOpenPrinter call from our winspool.drv to a local printer under Windows.
svn path=/branches/colins-printing-for-freedom/; revision=68248
Don't rely on pure magic to transmit the error code of the RPC call to the calling application. Instead use SetLastError on the return value of the call (this is what all these DWORD return values are for!)
[SPOOLSV]
For every RPC function, return the error code of the called Spooler Router function instead of the error code of RpcRevertToSelf.
[LOCALSPL, WINPRINT]
- Change the code structure in every function called from the Spooler Router to always set an error code, especially ERROR_SUCCESS on success.
- Store Attributes and Status values for a local printer.
- Fail in LocalAddJob if an invalid handle has been supplied or the printer is set to do direct printing.
svn path=/branches/colins-printing-for-freedom/; revision=68247