Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

530 lines
11 KiB

/*++
Copyright (c) 1990-1994 Microsoft Corporation
Module Name:
local.c
Abstract:
This module provides all the public exported APIs relating to Printer
and Job management for the Local Print Providor
Author:
Dave Snipp (DaveSn) 15-Mar-1991
Revision History:
16-Jun-1992 JohnRo net print vs. UNICODE.
July 1994 MattFe Caching
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntddrdr.h>
#include <windows.h>
#include <winspool.h>
#include <lm.h>
#include <w32types.h>
#include <local.h>
#include <winsplp.h>
#include <splcom.h> // DBGMSG
#include <winerror.h>
#include <string.h>
#define NOTIFY_TIMEOUT 10000
DWORD
LMStartDocPrinter(
HANDLE hPrinter,
DWORD Level,
LPBYTE pDocInfo
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
WCHAR szFileName[MAX_PATH];
PDOC_INFO_1 pDocInfo1=(PDOC_INFO_1)pDocInfo;
QUERY_PRINT_JOB_INFO JobInfo;
IO_STATUS_BLOCK Iosb;
VALIDATEW32HANDLE( pSpool );
if (pSpool->Status) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pSpool->Status |= WSPOOL_STATUS_STARTDOC;
if(StrNCatBuff(szFileName,
COUNTOF(szFileName),
pSpool->pServer,
L"\\",
pSpool->pShare,
NULL) != ERROR_SUCCESS)
{
return FALSE;
}
pSpool->hFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (pSpool->hFile == INVALID_HANDLE_VALUE) {
EnterSplSem();
DeleteEntryfromLMCache(pSpool->pServer, pSpool->pShare);
LeaveSplSem();
DBGMSG( DBG_WARNING, ("Failed to open %ws\n", szFileName));
pSpool->Status &= ~WSPOOL_STATUS_STARTDOC;
SetLastError(ERROR_INVALID_NAME);
return FALSE;
}
if (pDocInfo1 && pDocInfo1->pDocName && (wcslen(pDocInfo1->pDocName) < MAX_PATH)) {
if (NtFsControlFile(pSpool->hFile,
NULL,
NULL,
NULL,
&Iosb,
FSCTL_GET_PRINT_ID,
NULL, 0,
&JobInfo, sizeof(JobInfo)) == ERROR_SUCCESS){
RxPrintJobSetInfo(pSpool->pServer,
JobInfo.JobId,
3,
(LPBYTE)pDocInfo1->pDocName,
wcslen(pDocInfo1->pDocName)*sizeof(WCHAR) + sizeof(WCHAR),
PRJ_COMMENT_PARMNUM);
}
else
{
DBGMSG( DBG_WARN, ("NtFsControlFile failed %ws\n", szFileName));
}
}
return TRUE;
}
BOOL
LMStartPagePrinter(
HANDLE hPrinter
)
{
PWSPOOL pSpool = (PWSPOOL)hPrinter;
VALIDATEW32HANDLE( pSpool );
return FALSE;
}
BOOL
LMWritePrinter(
HANDLE hPrinter,
LPVOID pBuf,
DWORD cbBuf,
LPDWORD pcWritten
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
DWORD cWritten, cTotal;
DWORD rc;
LPBYTE pByte=pBuf;
VALIDATEW32HANDLE( pSpool );
if (!(pSpool->Status & WSPOOL_STATUS_STARTDOC)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (pSpool->hFile == INVALID_HANDLE_VALUE) {
*pcWritten = 0;
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
cWritten = cTotal = 0;
while (cbBuf) {
rc = WriteFile(pSpool->hFile, pByte, cbBuf, &cWritten, NULL);
if (!rc) {
rc = GetLastError();
DBGMSG(DBG_WARNING, ("Win32 Spooler: Error writing to server, Error %d\n", rc));
cTotal+=cWritten;
*pcWritten=cTotal;
return FALSE;
} else if (!cWritten) {
DBGMSG(DBG_ERROR, ("Spooler: Amount written is zero !!!\n"));
}
cTotal+=cWritten;
cbBuf-=cWritten;
pByte+=cWritten;
}
*pcWritten = cTotal;
return TRUE;
}
BOOL
LMEndPagePrinter(
HANDLE hPrinter
)
{
PWSPOOL pSpool = (PWSPOOL)hPrinter;
VALIDATEW32HANDLE( pSpool );
return FALSE;
}
BOOL
LMAbortPrinter(
HANDLE hPrinter
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
VALIDATEW32HANDLE( pSpool );
// Abort Printer remoteley won't work until we maintain state information
// on a per handle basis. For PDK, this is good enough
#ifdef LATER
WORD parm = 0;
PRIDINFO PridInfo;
DosDevIOCtl(&PridInfo, (LPSTR)&parm, SPOOL_LMGetPrintId, SPOOL_LMCAT,
hSpooler);
RxPrintJobDel(NULL, PridInfo.uJobId);
#endif
return TRUE;
}
BOOL
LMReadPrinter(
HANDLE hPrinter,
LPVOID pBuf,
DWORD cbBuf,
LPDWORD pNoBytesRead
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
VALIDATEW32HANDLE( pSpool );
return 0;
UNREFERENCED_PARAMETER(pBuf);
UNREFERENCED_PARAMETER(pNoBytesRead);
}
BOOL
LMEndDocPrinter(
HANDLE hPrinter
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
VALIDATEW32HANDLE( pSpool );
if (!(pSpool->Status & WSPOOL_STATUS_STARTDOC)) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
pSpool->Status &= ~WSPOOL_STATUS_STARTDOC;
if (pSpool->hFile != INVALID_HANDLE_VALUE) {
CloseHandle(pSpool->hFile);
pSpool->hFile = INVALID_HANDLE_VALUE;
}
return TRUE;
}
BOOL
LMAddJob(
HANDLE hPrinter,
DWORD Level,
LPBYTE pData,
DWORD cbBuf,
LPDWORD pcbNeeded
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
DWORD cb;
WCHAR szFileName[MAX_PATH];
LPBYTE pEnd;
LPADDJOB_INFO_1 pAddJob=(LPADDJOB_INFO_1)pData;
VALIDATEW32HANDLE( pSpool );
if(StrNCatBuff(szFileName,
COUNTOF(szFileName),
pSpool->pServer,
L"\\",
pSpool->pShare,
NULL) != ERROR_SUCCESS)
{
return(FALSE);
}
cb = wcslen(szFileName)*sizeof(WCHAR) + sizeof(WCHAR) + sizeof(ADDJOB_INFO_1);
if (cb > cbBuf) {
*pcbNeeded=cb;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return(FALSE);
}
pEnd = (LPBYTE)pAddJob+cbBuf;
pEnd -= wcslen(szFileName)*sizeof(WCHAR)+sizeof(WCHAR);
pAddJob->Path = wcscpy((LPWSTR)pEnd, szFileName);
pAddJob->JobId = (DWORD)-1;
return TRUE;
}
BOOL
LMScheduleJob(
HANDLE hPrinter,
DWORD JobId
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
VALIDATEW32HANDLE( pSpool );
JobId = JobId;
return TRUE;
}
DWORD
LMGetPrinterData(
HANDLE hPrinter,
LPTSTR pValueName,
LPDWORD pType,
LPBYTE pData,
DWORD nSize,
LPDWORD pcbNeeded
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
VALIDATEW32HANDLE( pSpool );
return FALSE;
}
DWORD
LMSetPrinterData(
HANDLE hPrinter,
LPTSTR pValueName,
DWORD Type,
LPBYTE pData,
DWORD cbData
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
VALIDATEW32HANDLE( pSpool );
return FALSE;
}
BOOL
LMClosePrinter(
HANDLE hPrinter
)
{
PWSPOOL pSpool=(PWSPOOL)hPrinter;
PLMNOTIFY pLMNotify = &pSpool->LMNotify;
BOOL bReturnValue = FALSE;
VALIDATEW32HANDLE( pSpool );
EnterSplSem();
if (pSpool->Status & WSPOOL_STATUS_STARTDOC)
EndDocPrinter(hPrinter);
if (pLMNotify->ChangeEvent) {
if (pLMNotify->ChangeEvent != INVALID_HANDLE_VALUE) {
CloseHandle(pLMNotify->ChangeEvent);
} else {
LMFindClosePrinterChangeNotification(hPrinter);
}
}
FreepSpool( pSpool );
bReturnValue = TRUE;
LeaveSplSem();
return bReturnValue;
}
DWORD
LMWaitForPrinterChange(
HANDLE hPrinter,
DWORD Flags
)
{
PWSPOOL pSpool = (PWSPOOL)hPrinter;
PLMNOTIFY pLMNotify = &pSpool->LMNotify;
HANDLE ChangeEvent;
DWORD bReturnValue = FALSE;
EnterSplSem();
//
// !! LATER !!
//
// We have no synchronization code in win32spl. This opens us
// up to AVs if same handle is used (ResetPrinter validates;
// Close closes; ResetPrinter tries to use handle boom.)
// Here's one more case:
//
if (pLMNotify->ChangeEvent) {
SetLastError(ERROR_ALREADY_WAITING);
goto Error;
}
// Allocate memory for ChangeEvent for LanMan Printers
// This event is pulsed by LMSetJob and any othe LM
// function that modifies the printer/job status
// LMWaitForPrinterChange waits on this event
// being pulsed.
ChangeEvent = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
if (!ChangeEvent) {
DBGMSG(DBG_WARNING, ("CreateEvent( ChangeEvent ) failed: Error %d\n",
GetLastError()));
goto Error;
}
pLMNotify->ChangeEvent = ChangeEvent;
LeaveSplSem();
WaitForSingleObject(pLMNotify->ChangeEvent, NOTIFY_TIMEOUT);
CloseHandle(ChangeEvent);
//
// !! LATER !!
//
// We shouldn't return that everything changed; we should
// return what did.
//
return Flags;
Error:
LeaveSplSem();
return 0;
}
BOOL
LMFindFirstPrinterChangeNotification(
HANDLE hPrinter,
DWORD fdwFlags,
DWORD fdwOptions,
HANDLE hNotify,
PDWORD pfdwStatus)
{
PWSPOOL pSpool = (PWSPOOL)hPrinter;
PLMNOTIFY pLMNotify = &pSpool->LMNotify;
EnterSplSem();
pLMNotify->hNotify = hNotify;
pLMNotify->fdwChangeFlags = fdwFlags;
pLMNotify->ChangeEvent = INVALID_HANDLE_VALUE;
*pfdwStatus = PRINTER_NOTIFY_STATUS_ENDPOINT | PRINTER_NOTIFY_STATUS_POLL;
LeaveSplSem();
return TRUE;
}
BOOL
LMFindClosePrinterChangeNotification(
HANDLE hPrinter)
{
PWSPOOL pSpool = (PWSPOOL)hPrinter;
PLMNOTIFY pLMNotify = &pSpool->LMNotify;
SplInSem();
if (pLMNotify->ChangeEvent != INVALID_HANDLE_VALUE) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
pLMNotify->hNotify = NULL;
pLMNotify->ChangeEvent = NULL;
return TRUE;
}
VOID
LMSetSpoolChange(
PWSPOOL pSpool)
{
PLMNOTIFY pLMNotify;
pLMNotify = &pSpool->LMNotify;
EnterSplSem();
if (pLMNotify->ChangeEvent) {
if (pLMNotify->ChangeEvent == INVALID_HANDLE_VALUE) {
//
// FindFirstPrinterChangeNotification used.
//
ReplyPrinterChangeNotification(pLMNotify->hNotify,
pLMNotify->fdwChangeFlags,
NULL,
NULL);
} else {
SetEvent(pLMNotify->ChangeEvent);
}
}
LeaveSplSem();
}