mirror of
https://github.com/reactos/reactos.git
synced 2025-04-21 12:40:33 +00:00
[LOCALSPL]
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
This commit is contained in:
parent
03a88ff715
commit
309215ece6
3 changed files with 258 additions and 60 deletions
|
@ -48,37 +48,48 @@ typedef BOOL (WINAPI *PPrintDocumentOnPrintProcessor)(HANDLE, LPWSTR);
|
||||||
typedef LPMONITOREX(WINAPI *PInitializePrintMonitor)(PWSTR);
|
typedef LPMONITOREX(WINAPI *PInitializePrintMonitor)(PWSTR);
|
||||||
typedef LPMONITOR2(WINAPI *PInitializePrintMonitor2)(PMONITORINIT, PHANDLE);
|
typedef LPMONITOR2(WINAPI *PInitializePrintMonitor2)(PMONITORINIT, PHANDLE);
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
typedef struct _LOCAL_HANDLE LOCAL_HANDLE, *PLOCAL_HANDLE;
|
||||||
|
typedef struct _LOCAL_JOB LOCAL_JOB, *PLOCAL_JOB;
|
||||||
|
typedef struct _LOCAL_PORT LOCAL_PORT, *PLOCAL_PORT;
|
||||||
|
typedef struct _LOCAL_PORT_HANDLE LOCAL_PORT_HANDLE, *PLOCAL_PORT_HANDLE;
|
||||||
|
typedef struct _LOCAL_PRINT_MONITOR LOCAL_PRINT_MONITOR, *PLOCAL_PRINT_MONITOR;
|
||||||
|
typedef struct _LOCAL_PRINT_PROCESSOR LOCAL_PRINT_PROCESSOR, *PLOCAL_PRINT_PROCESSOR;
|
||||||
|
typedef struct _LOCAL_PRINTER LOCAL_PRINTER, *PLOCAL_PRINTER;
|
||||||
|
typedef struct _LOCAL_PRINTER_HANDLE LOCAL_PRINTER_HANDLE, *PLOCAL_PRINTER_HANDLE;
|
||||||
|
typedef struct _LOCAL_XCV_HANDLE LOCAL_XCV_HANDLE, *PLOCAL_XCV_HANDLE;
|
||||||
|
typedef struct _SHD_HEADER SHD_HEADER, *PSHD_HEADER;
|
||||||
|
|
||||||
// Structures
|
// Structures
|
||||||
/**
|
/**
|
||||||
* Describes a Print Monitor.
|
* Describes a Print Monitor.
|
||||||
*/
|
*/
|
||||||
typedef struct _LOCAL_PRINT_MONITOR
|
struct _LOCAL_PRINT_MONITOR
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry;
|
||||||
PWSTR pwszName; /** Name of the Print Monitor as read from the registry. */
|
PWSTR pwszName; /** Name of the Print Monitor as read from the registry. */
|
||||||
PWSTR pwszFileName; /** DLL File Name of the Print Monitor. */
|
PWSTR pwszFileName; /** DLL File Name of the Print Monitor. */
|
||||||
BOOL bIsLevel2; /** Whether this Print Monitor supplies an InitializePrintMonitor2 API (preferred) instead of InitializePrintMonitor. */
|
BOOL bIsLevel2; /** Whether this Print Monitor supplies an InitializePrintMonitor2 API (preferred) instead of InitializePrintMonitor. */
|
||||||
PVOID pMonitor; /** For bIsLevel2 == TRUE: LPMONITOR2 pointer returned by InitializePrintMonitor2.
|
PVOID pMonitor; /** For bIsLevel2 == TRUE: LPMONITOR2 pointer returned by InitializePrintMonitor2.
|
||||||
For bIsLevel2 == FALSE: LPMONITOREX pointer returned by InitializePrintMonitor. */
|
For bIsLevel2 == FALSE: LPMONITOREX pointer returned by InitializePrintMonitor. */
|
||||||
HANDLE hMonitor; /** Only used when bIsLevel2 == TRUE: Handle returned by InitializePrintMonitor2. */
|
HANDLE hMonitor; /** Only used when bIsLevel2 == TRUE: Handle returned by InitializePrintMonitor2. */
|
||||||
}
|
};
|
||||||
LOCAL_PRINT_MONITOR, *PLOCAL_PRINT_MONITOR;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a Port handled by a Print Monitor.
|
* Describes a Port handled by a Print Monitor.
|
||||||
*/
|
*/
|
||||||
typedef struct _LOCAL_PORT
|
struct _LOCAL_PORT
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry;
|
||||||
PWSTR pwszName; /** The name of the port (including the trailing colon). */
|
PWSTR pwszName; /** The name of the port (including the trailing colon). */
|
||||||
PLOCAL_PRINT_MONITOR pPrintMonitor; /** The Print Monitor handling this port. */
|
PLOCAL_PRINT_MONITOR pPrintMonitor; /** The Print Monitor handling this port. */
|
||||||
}
|
PLOCAL_JOB pNextJobToProcess; /** The Print Job that will be processed by the next created Port handle. */
|
||||||
LOCAL_PORT, *PLOCAL_PORT;
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a Print Processor.
|
* Describes a Print Processor.
|
||||||
*/
|
*/
|
||||||
typedef struct _LOCAL_PRINT_PROCESSOR
|
struct _LOCAL_PRINT_PROCESSOR
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry;
|
||||||
PWSTR pwszName;
|
PWSTR pwszName;
|
||||||
|
@ -90,14 +101,13 @@ typedef struct _LOCAL_PRINT_PROCESSOR
|
||||||
PGetPrintProcessorCapabilities pfnGetPrintProcessorCapabilities;
|
PGetPrintProcessorCapabilities pfnGetPrintProcessorCapabilities;
|
||||||
POpenPrintProcessor pfnOpenPrintProcessor;
|
POpenPrintProcessor pfnOpenPrintProcessor;
|
||||||
PPrintDocumentOnPrintProcessor pfnPrintDocumentOnPrintProcessor;
|
PPrintDocumentOnPrintProcessor pfnPrintDocumentOnPrintProcessor;
|
||||||
}
|
};
|
||||||
LOCAL_PRINT_PROCESSOR, *PLOCAL_PRINT_PROCESSOR;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a printer and manages its print jobs.
|
* Describes a printer and manages its print jobs.
|
||||||
* Created once for every printer at startup.
|
* Created once for every printer at startup.
|
||||||
*/
|
*/
|
||||||
typedef struct _LOCAL_PRINTER
|
struct _LOCAL_PRINTER
|
||||||
{
|
{
|
||||||
// This sort key must be the first element for LookupElementSkiplist to work!
|
// This sort key must be the first element for LookupElementSkiplist to work!
|
||||||
PWSTR pwszPrinterName;
|
PWSTR pwszPrinterName;
|
||||||
|
@ -111,14 +121,13 @@ typedef struct _LOCAL_PRINTER
|
||||||
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
|
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
|
||||||
PLOCAL_PORT pPort;
|
PLOCAL_PORT pPort;
|
||||||
SKIPLIST JobList;
|
SKIPLIST JobList;
|
||||||
}
|
};
|
||||||
LOCAL_PRINTER, *PLOCAL_PRINTER;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes an entire print job associated to a specific printer through the Printer member.
|
* Describes an entire print job associated to a specific printer through the Printer member.
|
||||||
* Created with every valid call to LocalStartDocPrinter.
|
* Created with every valid call to LocalStartDocPrinter.
|
||||||
*/
|
*/
|
||||||
typedef struct _LOCAL_JOB
|
struct _LOCAL_JOB
|
||||||
{
|
{
|
||||||
// This sort key must be the first element for LookupElementSkiplist to work!
|
// This sort key must be the first element for LookupElementSkiplist to work!
|
||||||
DWORD dwJobID; /** Internal and external ID of this Job */
|
DWORD dwJobID; /** Internal and external ID of this Job */
|
||||||
|
@ -143,49 +152,60 @@ typedef struct _LOCAL_JOB
|
||||||
DWORD dwStatus; /** JOB_STATUS_* flags of the Job */
|
DWORD dwStatus; /** JOB_STATUS_* flags of the Job */
|
||||||
PWSTR pwszMachineName; /** Name of the machine that submitted the Job (prepended with two backslashes) */
|
PWSTR pwszMachineName; /** Name of the machine that submitted the Job (prepended with two backslashes) */
|
||||||
PDEVMODEW pDevMode; /** Associated Device Mode to this Job */
|
PDEVMODEW pDevMode; /** Associated Device Mode to this Job */
|
||||||
}
|
};
|
||||||
LOCAL_JOB, *PLOCAL_JOB;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a template for new print jobs for a specific printer.
|
* Specific handle returned by LocalOpenPrinter for every valid call that opens a Printer or Print Job.
|
||||||
* Created with every valid call to LocalOpenPrinter.
|
|
||||||
*
|
|
||||||
* This is needed, because you can supply defaults in a LocalOpenPrinter call, which affect all subsequent print jobs
|
|
||||||
* started with the same handle and a call to LocalStartDocPrinter.
|
|
||||||
*/
|
*/
|
||||||
typedef struct _LOCAL_PRINTER_HANDLE
|
struct _LOCAL_PRINTER_HANDLE
|
||||||
{
|
{
|
||||||
BOOL bStartedDoc : 1; /** Whether StartDocPrinter has already been called. */
|
BOOL bStartedDoc : 1; /** Whether StartDocPrinter has already been called. */
|
||||||
HANDLE hSPLFile; /** Handle to an opened SPL file for Printer Job handles. */
|
HANDLE hSPLFile; /** Handle to an opened SPL file for Printer Job handles. */
|
||||||
PLOCAL_PRINTER pPrinter;
|
PLOCAL_PRINTER pPrinter; /** Printer associated with this handle. */
|
||||||
PLOCAL_JOB pJob;
|
PLOCAL_JOB pJob; /** Print Job associated with this handle. This can be the specified Job if this is a Print Job handle or the started job through LocalStartDocPrinter. */
|
||||||
PWSTR pwszDatatype;
|
PWSTR pwszDatatype; /** Datatype used for newly started jobs. */
|
||||||
PDEVMODEW pDevMode;
|
PDEVMODEW pDevMode; /** DevMode used for newly started jobs. */
|
||||||
}
|
};
|
||||||
LOCAL_PRINTER_HANDLE, *PLOCAL_PRINTER_HANDLE;
|
|
||||||
|
/**
|
||||||
|
* Specific handle returned by LocalOpenPrinter for every valid call that opens a Port.
|
||||||
|
*/
|
||||||
|
struct _LOCAL_PORT_HANDLE
|
||||||
|
{
|
||||||
|
HANDLE hPort; /** Handle returned by pfnOpenPort. */
|
||||||
|
PLOCAL_PORT pPort; /** Port associated with this handle. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific handle returned by LocalOpenPrinter for every valid call that opens an XcvMonitor or XcvPort.
|
||||||
|
*/
|
||||||
|
struct _LOCAL_XCV_HANDLE
|
||||||
|
{
|
||||||
|
HANDLE hXcv; /** Handle returned by pfnXcvOpenPort. */
|
||||||
|
PLOCAL_PRINT_MONITOR pPrintMonitor; /** Print Monitor associated with this handle. */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a handle returned by LocalOpenPrinter.
|
* Describes a handle returned by LocalOpenPrinter.
|
||||||
* Suitable for all things that can be opened through LocalOpenPrinter.
|
* Suitable for all things that can be opened through LocalOpenPrinter.
|
||||||
*/
|
*/
|
||||||
typedef struct _LOCAL_HANDLE
|
struct _LOCAL_HANDLE
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
HandleType_Port,
|
HandleType_Port, /** pSpecificHandle is a PLOCAL_PORT_HANDLE. */
|
||||||
HandleType_Printer,
|
HandleType_Printer, /** pSpecificHandle is a PLOCAL_PRINTER_HANDLE. */
|
||||||
HandleType_Xcv
|
HandleType_Xcv /** pSpecificHandle is a PLOCAL_XCV_HANDLE. */
|
||||||
}
|
}
|
||||||
HandleType;
|
HandleType;
|
||||||
PVOID pSpecificHandle;
|
PVOID pSpecificHandle;
|
||||||
}
|
};
|
||||||
LOCAL_HANDLE, *PLOCAL_HANDLE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the header of a print job serialized into a shadow file (.SHD)
|
* Describes the header of a print job serialized into a shadow file (.SHD)
|
||||||
* Documented in http://www.undocprint.org/formats/winspool/shd
|
* Documented in http://www.undocprint.org/formats/winspool/shd
|
||||||
* Compatible with Windows Server 2003
|
* Compatible with Windows Server 2003
|
||||||
*/
|
*/
|
||||||
typedef struct _SHD_HEADER
|
struct _SHD_HEADER
|
||||||
{
|
{
|
||||||
DWORD dwSignature;
|
DWORD dwSignature;
|
||||||
DWORD cbHeader;
|
DWORD cbHeader;
|
||||||
|
@ -215,8 +235,7 @@ typedef struct _SHD_HEADER
|
||||||
DWORD dwUnknown5;
|
DWORD dwUnknown5;
|
||||||
DWORD offMachineName;
|
DWORD offMachineName;
|
||||||
DWORD dwSPLSize;
|
DWORD dwSPLSize;
|
||||||
}
|
};
|
||||||
SHD_HEADER, *PSHD_HEADER;
|
|
||||||
|
|
||||||
// jobs.c
|
// jobs.c
|
||||||
extern SKIPLIST GlobalJobList;
|
extern SKIPLIST GlobalJobList;
|
||||||
|
|
|
@ -505,9 +505,11 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
PLOCAL_JOB pJob;
|
PLOCAL_JOB pJob;
|
||||||
PLOCAL_HANDLE pHandle = NULL;
|
PLOCAL_HANDLE pHandle = NULL;
|
||||||
PLOCAL_PORT pPort;
|
PLOCAL_PORT pPort;
|
||||||
|
PLOCAL_PORT_HANDLE pPortHandle = NULL;
|
||||||
PLOCAL_PRINT_MONITOR pPrintMonitor;
|
PLOCAL_PRINT_MONITOR pPrintMonitor;
|
||||||
PLOCAL_PRINTER pPrinter;
|
PLOCAL_PRINTER pPrinter;
|
||||||
PLOCAL_PRINTER_HANDLE pPrinterHandle = NULL;
|
PLOCAL_PRINTER_HANDLE pPrinterHandle = NULL;
|
||||||
|
PLOCAL_XCV_HANDLE pXcvHandle = NULL;
|
||||||
WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
|
WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
|
||||||
WCHAR wszFullPath[MAX_PATH];
|
WCHAR wszFullPath[MAX_PATH];
|
||||||
|
|
||||||
|
@ -635,9 +637,21 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new LOCAL_PORT_HANDLE.
|
||||||
|
pPortHandle = DllAllocSplMem(sizeof(LOCAL_PORT_HANDLE));
|
||||||
|
if (!pPortHandle)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
pPortHandle->hPort = hExternalHandle;
|
||||||
|
pPortHandle->pPort = pPort;
|
||||||
|
|
||||||
// Return the Port handle through our general handle.
|
// Return the Port handle through our general handle.
|
||||||
pHandle->HandleType = HandleType_Port;
|
pHandle->HandleType = HandleType_Port;
|
||||||
pHandle->pSpecificHandle = hExternalHandle;
|
pHandle->pSpecificHandle = pPortHandle;
|
||||||
}
|
}
|
||||||
else if (!pwszFirstParameter && pwszSecondParameter && wcsncmp(pwszSecondParameter, L"Xcv", 3) == 0)
|
else if (!pwszFirstParameter && pwszSecondParameter && wcsncmp(pwszSecondParameter, L"Xcv", 3) == 0)
|
||||||
{
|
{
|
||||||
|
@ -700,9 +714,21 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new LOCAL_XCV_HANDLE.
|
||||||
|
pXcvHandle = DllAllocSplMem(sizeof(LOCAL_XCV_HANDLE));
|
||||||
|
if (!pXcvHandle)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
pXcvHandle->hXcv = hExternalHandle;
|
||||||
|
pXcvHandle->pPrintMonitor = pPrintMonitor;
|
||||||
|
|
||||||
// Return the Xcv handle through our general handle.
|
// Return the Xcv handle through our general handle.
|
||||||
pHandle->HandleType = HandleType_Xcv;
|
pHandle->HandleType = HandleType_Xcv;
|
||||||
pHandle->pSpecificHandle = hExternalHandle;
|
pHandle->pSpecificHandle = pXcvHandle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -721,7 +747,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new printer handle.
|
// Create a new LOCAL_PRINTER_HANDLE.
|
||||||
pPrinterHandle = DllAllocSplMem(sizeof(LOCAL_PRINTER_HANDLE));
|
pPrinterHandle = DllAllocSplMem(sizeof(LOCAL_PRINTER_HANDLE));
|
||||||
if (!pPrinterHandle)
|
if (!pPrinterHandle)
|
||||||
{
|
{
|
||||||
|
@ -845,12 +871,44 @@ Cleanup:
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
|
LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
|
||||||
{
|
{
|
||||||
|
BOOL bReturnValue;
|
||||||
DWORD dwErrorCode;
|
DWORD dwErrorCode;
|
||||||
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
|
PLOCAL_PORT_HANDLE pPortHandle;
|
||||||
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||||
|
|
||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
if (!pHandle || pHandle->HandleType != HandleType_Printer)
|
if (!pHandle)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port handles are an entirely different thing.
|
||||||
|
if (pHandle->HandleType == HandleType_Port)
|
||||||
|
{
|
||||||
|
pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
|
||||||
|
|
||||||
|
// Call the monitor's ReadPort function.
|
||||||
|
if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
|
||||||
|
bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnReadPort(pPortHandle->hPort, pBuf, cbBuf, pNoBytesRead);
|
||||||
|
else
|
||||||
|
bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnReadPort(pPortHandle->hPort, pBuf, cbBuf, pNoBytesRead);
|
||||||
|
|
||||||
|
if (!bReturnValue)
|
||||||
|
{
|
||||||
|
// The ReadPort function failed. Return its last error.
|
||||||
|
dwErrorCode = GetLastError();
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We were successful!
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The remaining function deals with Printer handles only.
|
||||||
|
if (pHandle->HandleType != HandleType_Printer)
|
||||||
{
|
{
|
||||||
dwErrorCode = ERROR_INVALID_HANDLE;
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -884,25 +942,65 @@ Cleanup:
|
||||||
DWORD WINAPI
|
DWORD WINAPI
|
||||||
LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
|
LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
|
||||||
{
|
{
|
||||||
|
BOOL bReturnValue;
|
||||||
DWORD dwErrorCode;
|
DWORD dwErrorCode;
|
||||||
DWORD dwReturnValue = 0;
|
DWORD dwReturnValue = 0;
|
||||||
PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo;
|
PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo;
|
||||||
|
PLOCAL_JOB pJob;
|
||||||
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
|
PLOCAL_PORT_HANDLE pPortHandle;
|
||||||
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||||
|
|
||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
if (!pDocInfo1)
|
if (!pHandle)
|
||||||
{
|
{
|
||||||
dwErrorCode = ERROR_INVALID_PARAMETER;
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pHandle || pHandle->HandleType != HandleType_Printer)
|
// Port handles are an entirely different thing.
|
||||||
|
if (pHandle->HandleType == HandleType_Port)
|
||||||
|
{
|
||||||
|
pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
|
||||||
|
|
||||||
|
// This call should come from a Print Processor and the job this port is going to print was assigned to us before opening the Print Processor.
|
||||||
|
// Claim it exclusively for this port handle.
|
||||||
|
pJob = pPortHandle->pPort->pNextJobToProcess;
|
||||||
|
pPortHandle->pPort->pNextJobToProcess = NULL;
|
||||||
|
ASSERT(pJob);
|
||||||
|
|
||||||
|
// Call the monitor's StartDocPort function.
|
||||||
|
if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
|
||||||
|
bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnStartDocPort(pPortHandle->hPort, pJob->pPrinter->pwszPrinterName, pJob->dwJobID, Level, pDocInfo);
|
||||||
|
else
|
||||||
|
bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnStartDocPort(pPortHandle->hPort, pJob->pPrinter->pwszPrinterName, pJob->dwJobID, Level, pDocInfo);
|
||||||
|
|
||||||
|
if (!bReturnValue)
|
||||||
|
{
|
||||||
|
// The StartDocPort function failed. Return its last error.
|
||||||
|
dwErrorCode = GetLastError();
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We were successful!
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
dwReturnValue = pJob->dwJobID;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The remaining function deals with Printer handles only.
|
||||||
|
if (pHandle->HandleType != HandleType_Printer)
|
||||||
{
|
{
|
||||||
dwErrorCode = ERROR_INVALID_HANDLE;
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pDocInfo1)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
|
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
|
||||||
|
|
||||||
// pJob may already be occupied if this is a Print Job handle. In this case, StartDocPrinter has to fail.
|
// pJob may already be occupied if this is a Print Job handle. In this case, StartDocPrinter has to fail.
|
||||||
|
@ -989,14 +1087,46 @@ Cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalWritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten)
|
LocalWritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
|
||||||
{
|
{
|
||||||
|
BOOL bReturnValue;
|
||||||
DWORD dwErrorCode;
|
DWORD dwErrorCode;
|
||||||
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
|
PLOCAL_PORT_HANDLE pPortHandle;
|
||||||
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||||
|
|
||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
if (!pHandle || pHandle->HandleType != HandleType_Printer)
|
if (!pHandle)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port handles are an entirely different thing.
|
||||||
|
if (pHandle->HandleType == HandleType_Port)
|
||||||
|
{
|
||||||
|
pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
|
||||||
|
|
||||||
|
// Call the monitor's WritePort function.
|
||||||
|
if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
|
||||||
|
bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnWritePort(pPortHandle->hPort, pBuf, cbBuf, pcWritten);
|
||||||
|
else
|
||||||
|
bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnWritePort(pPortHandle->hPort, pBuf, cbBuf, pcWritten);
|
||||||
|
|
||||||
|
if (!bReturnValue)
|
||||||
|
{
|
||||||
|
// The WritePort function failed. Return its last error.
|
||||||
|
dwErrorCode = GetLastError();
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We were successful!
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The remaining function deals with Printer handles only.
|
||||||
|
if (pHandle->HandleType != HandleType_Printer)
|
||||||
{
|
{
|
||||||
dwErrorCode = ERROR_INVALID_HANDLE;
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -1054,12 +1184,44 @@ Cleanup:
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalEndDocPrinter(HANDLE hPrinter)
|
LocalEndDocPrinter(HANDLE hPrinter)
|
||||||
{
|
{
|
||||||
|
BOOL bReturnValue;
|
||||||
DWORD dwErrorCode;
|
DWORD dwErrorCode;
|
||||||
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
|
PLOCAL_PORT_HANDLE pPortHandle;
|
||||||
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||||
|
|
||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
if (!pHandle || pHandle->HandleType != HandleType_Printer)
|
if (!pHandle)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port handles are an entirely different thing.
|
||||||
|
if (pHandle->HandleType == HandleType_Port)
|
||||||
|
{
|
||||||
|
pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
|
||||||
|
|
||||||
|
// Call the monitor's EndDocPort function.
|
||||||
|
if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
|
||||||
|
bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnEndDocPort(pPortHandle->hPort);
|
||||||
|
else
|
||||||
|
bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnEndDocPort(pPortHandle->hPort);
|
||||||
|
|
||||||
|
if (!bReturnValue)
|
||||||
|
{
|
||||||
|
// The EndDocPort function failed. Return its last error.
|
||||||
|
dwErrorCode = GetLastError();
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We were successful!
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The remaining function deals with Printer handles only.
|
||||||
|
if (pHandle->HandleType != HandleType_Printer)
|
||||||
{
|
{
|
||||||
dwErrorCode = ERROR_INVALID_HANDLE;
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -1090,7 +1252,9 @@ BOOL WINAPI
|
||||||
LocalClosePrinter(HANDLE hPrinter)
|
LocalClosePrinter(HANDLE hPrinter)
|
||||||
{
|
{
|
||||||
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
|
PLOCAL_PORT_HANDLE pPortHandle;
|
||||||
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||||
|
PLOCAL_XCV_HANDLE pXcvHandle;
|
||||||
|
|
||||||
if (!pHandle)
|
if (!pHandle)
|
||||||
{
|
{
|
||||||
|
@ -1100,7 +1264,13 @@ LocalClosePrinter(HANDLE hPrinter)
|
||||||
|
|
||||||
if (pHandle->HandleType == HandleType_Port)
|
if (pHandle->HandleType == HandleType_Port)
|
||||||
{
|
{
|
||||||
// TODO
|
pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle;
|
||||||
|
|
||||||
|
// Call the monitor's ClosePort function.
|
||||||
|
if (pPortHandle->pPort->pPrintMonitor->bIsLevel2)
|
||||||
|
((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnClosePort(pPortHandle->hPort);
|
||||||
|
else
|
||||||
|
((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnClosePort(pPortHandle->hPort);
|
||||||
}
|
}
|
||||||
else if (pHandle->HandleType == HandleType_Printer)
|
else if (pHandle->HandleType == HandleType_Printer)
|
||||||
{
|
{
|
||||||
|
@ -1113,16 +1283,20 @@ LocalClosePrinter(HANDLE hPrinter)
|
||||||
// Free memory for the fields.
|
// Free memory for the fields.
|
||||||
DllFreeSplMem(pPrinterHandle->pDevMode);
|
DllFreeSplMem(pPrinterHandle->pDevMode);
|
||||||
DllFreeSplStr(pPrinterHandle->pwszDatatype);
|
DllFreeSplStr(pPrinterHandle->pwszDatatype);
|
||||||
|
|
||||||
// Free memory for the printer handle itself.
|
|
||||||
DllFreeSplMem(pPrinterHandle);
|
|
||||||
}
|
}
|
||||||
else if (pHandle->HandleType == HandleType_Xcv)
|
else if (pHandle->HandleType == HandleType_Xcv)
|
||||||
{
|
{
|
||||||
// TODO
|
pXcvHandle = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle;
|
||||||
|
|
||||||
|
// Call the monitor's XcvClosePort function.
|
||||||
|
if (pXcvHandle->pPrintMonitor->bIsLevel2)
|
||||||
|
((PMONITOR2)pXcvHandle->pPrintMonitor->pMonitor)->pfnXcvClosePort(pXcvHandle->hXcv);
|
||||||
|
else
|
||||||
|
((LPMONITOREX)pXcvHandle->pPrintMonitor->pMonitor)->Monitor.pfnXcvClosePort(pXcvHandle->hXcv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free memory for the handle itself.
|
// Free memory for the handle and the specific handle.
|
||||||
|
DllFreeSplMem(pHandle->pSpecificHandle);
|
||||||
DllFreeSplMem(pHandle);
|
DllFreeSplMem(pHandle);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -48,6 +48,11 @@ PrintingThreadProc(PLOCAL_JOB pJob)
|
||||||
OpenData.pParameters = pJob->pwszPrintProcessorParameters;
|
OpenData.pParameters = pJob->pwszPrintProcessorParameters;
|
||||||
OpenData.pPrinterName = pJob->pPrinter->pwszPrinterName;
|
OpenData.pPrinterName = pJob->pPrinter->pwszPrinterName;
|
||||||
|
|
||||||
|
// Associate our job to the port. The next port handle created through LocalOpenPrinter will pick this up.
|
||||||
|
// LocalStartDocPrinter needs this information to call StartDocPort of the Print Monitor, but as the parameters
|
||||||
|
// for LocalOpenPrinter and LocalStartDocPrinter are fixed, we can only pass over the information this way.
|
||||||
|
pJob->pPrinter->pPort->pNextJobToProcess = pJob;
|
||||||
|
|
||||||
// Open a handle to the Print Processor.
|
// Open a handle to the Print Processor.
|
||||||
hPrintProcessor = pPrintProcessor->pfnOpenPrintProcessor(pwszPrinterPort, &OpenData);
|
hPrintProcessor = pPrintProcessor->pfnOpenPrintProcessor(pwszPrinterPort, &OpenData);
|
||||||
if (!hPrintProcessor)
|
if (!hPrintProcessor)
|
||||||
|
|
Loading…
Reference in a new issue