- 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
- Add RPC calls in winspool, Router calls in spoolsv and Local Spooler calls in spoolss for most of the APIs I've implemented in localspl.
This is still Work-In-Progress and missing some sanity checks, but a first step into something usable from the documented Spooler API side.
- Separate APIs into individual source files just like I did for localspl.
svn path=/branches/colins-printing-for-freedom/; revision=68237
- Get rid of the Generic Tables entirely and make use of the new Skiplist for the Global Job List, the Printer's Job List and the Printer List.
Use a doubly linked-list for the Print Processors (there won't be many) and just save the information returned from the Print Processor's EnumPrintProcessorDatatypesW instead of putting it in another structure.
- Implement LocalAddJob and LocalGetJob (with full JOB_INFO_1W and JOB_INFO_2W support)
This makes use of the element index in the new Skiplist implementation to retrieve the position of the job in the list.
- Do some changes to LocalStartDocPrinter, though this will make use of LocalAddJob in the future.
- Make some global variables static again.
svn path=/branches/colins-printing-for-freedom/; revision=68195
Put the calls that eventually give us the function pointers to localspl into a separate procedure GetLocalsplFuncs to enable further tests easily.
svn path=/branches/colins-printing-for-freedom/; revision=68194
Add a lazy stub for RpcBindingServerFromClient to get my upcoming localspl changes to compile.
This needs further attention later.
svn path=/branches/colins-printing-for-freedom/; revision=68193
Verify that SKIPLIST_LEVELS is in the required range using C_ASSERTs (thanks to Thomas for the hint!)
svn path=/branches/colins-printing-for-freedom/; revision=68192
Add my implementation of an efficient Skiplist. A Skiplist can do insertion, deletion and lookups in O(log N) on average just like balanced trees.
It features simpler algorithms though due to purely relying on probabilistic balancing at insertion and not on rebalancing with every modification.
This simple structure allowed me to implement some additions on top of the standard algorithms:
* Storing distances between elements on each level to efficiently return the index of the element in the Skiplist when doing a lookup.
* InsertTailElementSkiplist to explicitly insert an element at the end of the Skiplist.
This needs no comparisons and is useful when you can be sure that the new element would be inserted at the end (e.g. for a new print job in the queue with default priority).
More features are easily possible, but for now I limited features on those needed for my Local Spooler work.
Some references on Skiplists:
* ftp://ftp.cs.umd.edu/pub/skipLists/skiplists.pdf
* http://drum.lib.umd.edu/bitstream/1903/544/2/CS-TR-2286.1.pdf
svn path=/branches/colins-printing-for-freedom/; revision=68191
It's only the second disabled test, which is causing trouble for us, so reactivate the first one.
This also confirms that the problem is not related to SEH.
svn path=/branches/colins-printing-for-freedom/; revision=68104
- Add more tests for fpEnumPrinters.
For some reason, using SEH here works only once. We experience a hang in the testing process when you run the test again for a second time without restarting spoolsv. Needs more investigation.
- Ensure that the spooler service is running before starting any testing.
- Do proper cleanup in every case.
[LOCALSPL]
- Implement LocalEnumPrinters level 1 based on the API-Tests.
- Use DllAllocSplMem/DllFreeSplMem instead of HeapAlloc/HeapFree.
- Use AllocSplStr with DllFreeSplStr now that DuplicateStringW is gone.
- Use _countof where applicable.
[SPOOLSS]
- Found out that I was not the only one needing a wcsdup equivalent. My DuplicateStringW from localspl is actually exported as AllocSplStr in spoolss.
This is actually part of a range of undocumented memory functions in spoolss, so implement and document AllocSplStr, DllAllocSplMem, DllFreeSplMem, DllFreeSplStr, ReallocSplMem and ReallocSplStr.
Information about some of them was gathered through black box testing and DDK samples (down to Win95 DDK), which at least contained prototypes of them.
- Implement SplInitializeWinSpoolDrv based on the API-Test and simply return FALSE for SplIsUpgrade.
[SPOOLSS_APITEST]
- Add a test for ReallocSplStr, which was actually the most undocumented function of spoolss' memory functions.
[WINSPOOL]
SplInitializeWinSpoolDrv shows that we can't just auto-assign an ordinal to all winspool.drv functions. We even need to export some nameless functions by ordinal only.
Redo the whole .spec file based on the ordinals found in Windows Server 2003's winspool.drv. Trust WINE for the nameless stubs.
svn path=/branches/colins-printing-for-freedom/; revision=68089
Write an API-Test for localspl.dll. As the original localspl.dll from Windows Server 2003 relies on proper initialization inside spoolsv.exe, we cannot test it standalone as usual.
To make testing possible anyway, this program basically does four things:
- Injecting our testing code into spoolsv.exe.
- Registering and running us as a service in the SYSTEM security context like spoolsv.exe, so that injection is possible at all.
- Sending the test name and receiving the console output over named pipes.
- Redirecting the received console output to stdout again, so it looks and feels like a standard API-Test.
Nevertheless, the testing code in fpEnumPrinters.c is still written like a usual test. The known ok(), skip(), etc. macros can be used as usual, their output is just redirected through the named pipes.
Thanks to Thomas for giving me the tip about injecting code into spoolsv! :)
svn path=/branches/colins-printing-for-freedom/; revision=68080
Add a test for SplInitializeWinSpoolDrv verifying that Wine's XP-compatible implementation of this function also works for 2003 (and that we're going to need some nameless exports by ordinals in winspool.drv...)
svn path=/branches/colins-printing-for-freedom/; revision=68035
Add an include directory for all printing components containing definitions not found in the public headers.
For now, that's just PackStrings in spoolss.h.
[SPOOLSS_APITEST]
Use the new spoolss.h header.
[WINPRINT_APITEST]
Add an API-Test for the winprint Print Processor, so far for its EnumPrintProcessorDatatypesW function. Tests succeed in Windows Server 2003.
winspool.drv also provides functions that go into winprint.dll, but as these tests show, they behave slightly different in terms of error codes due to the involved RPC and routing.
Windows Server 2003 has winprint functions in localspl.dll, so you have to copy its localspl.dll to winprint.dll for testing.
[WINPRINT]
- Use PackStrings to simplify the code.
- Fix test failures.
svn path=/branches/colins-printing-for-freedom/; revision=68025
In an attempt to simplify the code for further functions that return information structures, implement and document the undocumented PackStrings function.
Hints were taken from an XP DDK sample and own testing.
[SPOOLSS_APITEST]
Add some tests for PackStrings that succeed under Windows Server 2003.
svn path=/branches/colins-printing-for-freedom/; revision=68023
[LOCALSPL]
- Begin work on the Local Spooler. Return a structure with function pointers in InitializePrintProvidor.
- Design and document internal structures for managing LocalSpl Handles, Printer Handles, Printers, Print Jobs and Print Processors.
Manage Printers and Print Processors in Generic Tables, with one Job Queue per Printer managed as a Doubly Linked List.
- Implement LocalOpenPrinter, LocalEnumPrintProcessorDatatypes, LocalEnumPrintProcessors, LocalGetPrintProcessorDirectory, with focus on catching all corner cases.
Currently working on LocalStartDocPrinter.
- Build upon the documentation at http://www.undocprint.org/formats/winspool/shd to read and write .SHD files.
[WINPRINT]
Begin work on the Standard Print Processor. Implement EnumPrintProcessorDatatypesW.
[WINSPOOL_APITEST]
Add an API Test for winspool.drv, currently testing some corner cases of ClosePrinter, EnumPrintProcessorDatatypesW, GetPrintProcessorDirectoryW, OpenPrinterW, StartDocPrinterW.
TODO: Find a way to actually test the localspl.dll functions instead of only winspool.drv. This DLL doesn't like to be tested standalone under Windows, e.g. without being used through spoolsv/spoolss.
[SPOOLSS]
Implement InitializeRouter by calling the InitializePrintProvidor function of localspl there.
This function should later also initialize further Print Providers.
[SPOOLSV]
Call InitializeRouter when starting up the service.
[WINSPOOL]
Add dummy functions for EnumPrintProcessorDatatypesA/EnumPrintProcessorDatatypesW.
[All modules]
Fix printf format specifiers for errors (%lu) and statuses (%ld).
svn path=/branches/colins-printing-for-freedom/; revision=67847
- Use GdiConvertToDevmodeW instead of duplicating code.
- Fix the spec2def call here as well.
svn path=/branches/colins-printing-for-freedom/; revision=67816
This serves as an example to show how I expect most spooler functions to work.
- Implement the publicly exported and fundamental RevertToPrinterSelf and ImpersonatePrinterClient spoolss.dll functions.
- Fix WINSPOOL_HANDLE_bind.
- Fix build with GCC.
svn path=/branches/colins-printing-for-freedom/; revision=67693
Another reference: http://www.hsc.fr/ressources/articles/win_net_srv/msrpc_spoolss.html
- Put this file in the public domain as it's just collected interface information from various sources without any real code.
svn path=/branches/colins-printing-for-freedom/; revision=67662
References:
- https://git.samba.org/?p=samba.git;a=blob;f=librpc/idl/spoolss.idl;hb=618af83d1bd07b12a9acc88b0d2111cab7a8bb2b
- https://msdn.microsoft.com/en-us/library/cc244649.aspx
- Replace our stubbed spoolsv by a new basic implementation that already creates a thread to serve RPC requests.
- Add stubbed versions of localmon, localspl, spoolss, winprint, winspool matching the exports of the Windows Server 2003 DLLs.
localmon and winprint are part of localspl in Windows Server 2003. I took the freedom of putting these distinct components into separate DLLs (as it's done for localmon in NT4 and for winprint in Win7).
- Implement some stubs myself to fix the build (e.g. comdlg32 uses some functions).
- Implement OpenPrinterA and OpenPrinterW in winspool. This is just ANSI-to-Unicode conversion and a RPC call.
- Remove the Wine-imported ntprint, this one also needs a complete rewrite once we're at this point.
svn path=/branches/colins-printing-for-freedom/; revision=67576
This line will arrive as RAW data in the printing stack, so it doesn't need any processing through GDI and serves as a good test for the very basic printing components.
svn path=/branches/colins-printing-for-freedom/; revision=67544
- Remove some Wine-imported components which are either entirely not usable for us or only implement so few functions that it's easier to completely reimplement them.
- Move "localui" (Wine-imported) and "spoolsv" (ReactOS stub) to the new directories.
svn path=/branches/colins-printing-for-freedom/; revision=67543