Uses of the different forms of the gdiPlaySpoolStream and ReadPrinter functions are shown in the following pseudo code version of the WinprintPrintDocumentOnPrintProcessor function.
The WinprintPrintDocumentOnPrintProcessor function is supplied two parameters:
The WinprintPrintDocumentOnPrintProcessor function uses two data structures: PRINTPROCESSORDOCUMENTDATA, a pointer to which is given as a parameter, and the global PRINTPROCESSORDATA structure.
typedef struct _PRINTPROCESSORDOCUMENTDATA { LPDEVMODE pDevMode; // printer device init and status info LPTSTR pDatatype; // datatype of document LPTSTR pParameters; // print processor parameters LPTSTR pDocumentName; // DWORD JobId; // print job assoc w/ document LPTSTR pOutputFile; // document spool file LPTSTR pSpoolFileName; // full path to document spool file LPTSTR pSepFile; // file printed between jobs }PRINTPROCESSORDOCUMENTDATA
The global PRINTPROCESSORDATA structure is defined below:
typedef struct _PRINTPROCESSORDATA { DWORD signature; DWORD cb; struct _PRINTPROCESSORDATA FAR *pNext; DWORD fsStatus; HANDLE semPaused; DWORD uDatatype; HANDLE hPrinter; LPTSTR pPrinterName; } PRINTPROCESSORDATA, *PPRINTPROCESSORDATA;
The logic of the WinprintPrintDocumentOnPrintProcessor function is shown in the following pseudo code. Notice that the ReadPrinter function is used to read the spool file, rather than reading status data from the printer. When the WinprintPrintDocumentOnPrintProcessor function is called, the print processor already has a printer associated with it (has a handle to a printer). However, this handle, which was established in a prior OpenPrintProcessor function call, is used to write to printer.
if not called with a handle this print processor has open then set last error to ERROR_INVALID_HANDLE return FALSE endif if capable of using document datatype passed in move datatype into PRINTPROCESSORDATA structure endif if capable of using separator file type passed in print out the banner that separates this job from previous job endif move information about the document from PPRINTPROCESSORDATA structure to local DOC_INFO_2 structure, specifically: (1) document name (2) spool file filename (3) spool file data type (4) print job ID call local print provider OpenPrinter function to open the printer that is already associated with the print processor for reading (the spool file). call local print provider StartDocPrinter function with DI_READ_SPOOL_JOB flag set in JOB_INFO_2 structure to initiate reading of spool file. if the spool file datatype is raw then call the local print processor StartDocPrinter with DI_CHANNEL_WRITE flag set in JOB_INFO_2 structure to enable sending spool file contents directly to printer through the local print provider. (If the spool file datatype is EMF, the print processor will send the spool file data through GDI32.) endif /* start of loop: while there is still data to be read in the spool file, call the local print provider ReadPrinter function to read a block of data from the spool file. if the spool file data type is raw, the block of data is then sent directly to the printer by this print processor code; if the spool file data type is EMF, then this print processor code will use the gdiPlaySpoolStream function call to get GDI32 to manage the rendering and sending of the print data to the printer. */ while there is still data to be read in the spool file, call the local print provider ReadPrinter function to read a block of data from the spool file. trap special case of Print Processor paused between print out of pages (one page = one EMF file) and wait until unpaused trap special case of Print Processor aborted and document datatype is EMF and call GDI32 gdiPlaySpoolStream function to delete metafiles and DC /* Note the parameter list for this gdiPlaySpoolStream function call. This parameter list structure instructs gdiPlaySpoolStream to delete the spool file(s) and close the printer DC, etc. gdiPlaySpoolStream( NULL, NULL, lpDoc->pSpoolFileName, 0, 0, hDC); break; */ if document datatype is raw, call the print provider WritePrinter function to send the spool file data directly to the printer. if document datatype is EMF then call GDI32 gdiPlaySpoolStream function to playback the EMF file. /* Note the structure of the parameter list in the gdiPlaySpoolStream function call used to actually render and send data to the printer from the EMF spool file. The hDC parameter is NULL the first time this function is called. hDC = gdiPlaySpoolStream( pData->pPrinterName, lpDoc->pOutputFile, Buffer, lpDoc->JobId, &NoRead, hDC ); */ if gdiPlaySpoolStream does not return a DC handle and process the first block of spool file data OK, then call the GDI32 gdiPlaySpoolStream function to delete metafiles. /* end of loop */ if spool file data type is raw, call the local print provider EndDocPrinter function to end the document printing session.