NT4/private/windows/spooler/localspl/prtproc.c
2020-09-30 17:12:29 +02:00

711 lines
16 KiB
C

/*++
Copyright (c) 1990 - 1995 Microsoft Corporation
Module Name:
prtproc.c
Abstract:
This module provides all the public exported APIs relating to the
PrintProcessor based Spooler Apis for the Local Print Providor
LocalAddPrintProcessor
LocalEnumPrintProcessors
LocalDeletePrintProcessor
LocalGetPrintProcessorDirectory
LocalEnumPrintProcessorDatatypes
Support Functions in prtproc.c - (Warning! Do Not Add to this list!!)
AddPrintProcessorIni
DeletePrintProcessorIni
CopyIniPrintProcToPrintProcInfo
GetPrintProcessorInfoSize
Author:
Dave Snipp (DaveSn) 15-Mar-1991
Revision History:
Matthew A Felton ( MattFe ) 27 June 1994
pIniSpooler
--*/
#define NOMINMAX
#include <precomp.h>
#include <offsets.h>
//
// Private Declarations
//
extern WCHAR *szPrintProcKey;
//
// Support Function Prototypes
//
DWORD
GetPrintProcessorInfoSize(
PINIPRINTPROC pIniPrintProc,
DWORD Level,
LPWSTR pEnvironment
);
LPBYTE
CopyIniPrintProcToPrintProcInfo(
LPWSTR pEnvironment,
PINIPRINTPROC pIniPrintProc,
DWORD Level,
LPBYTE pPrintProcessorInfo,
LPBYTE pEnd
);
BOOL
AddPrintProcessorIni(
PINIPRINTPROC pIniPrintProc,
PINIENVIRONMENT pIniEnvironment,
PINISPOOLER pIniSpooler
);
BOOL
DeletePrintProcessorIni(
PINIPRINTPROC pIniPrintProc,
PINIENVIRONMENT pIniEnvironment,
PINISPOOLER pIniSpooler
);
BOOL
LocalAddPrintProcessor(
LPWSTR pName,
LPWSTR pEnvironment,
LPWSTR pPathName,
LPWSTR pPrintProcessorName
)
{
return ( SplAddPrintProcessor( pName, pEnvironment, pPathName,
pPrintProcessorName, pLocalIniSpooler));
}
BOOL
SplAddPrintProcessor(
LPWSTR pName,
LPWSTR pEnvironment,
LPWSTR pPathName,
LPWSTR pPrintProcessorName,
PINISPOOLER pIniSpooler
)
{
PINIPRINTPROC pIniPrintProc;
PINIENVIRONMENT pIniEnvironment;
DWORD LastError=0;
if (!MyName( pName, pIniSpooler )) {
return FALSE;
}
EnterSplSem();
if ( ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL, pIniSpooler )) {
if ((pIniEnvironment = FindEnvironment(pEnvironment)) && (pIniEnvironment == pThisEnvironment)) {
if (!FindPrintProc(pPrintProcessorName, pIniEnvironment)) {
pIniPrintProc = InitializePrintProcessor(pIniEnvironment,
pPrintProcessorName,
pPathName,
pIniSpooler);
if (!pIniPrintProc || !AddPrintProcessorIni(pIniPrintProc,
pIniEnvironment,
pIniSpooler))
LastError = GetLastError();
} else
LastError = ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED;
} else
LastError = ERROR_INVALID_ENVIRONMENT;
} else
LastError = GetLastError();
if (!LastError)
SetPrinterChange(NULL,
NULL,
NULL,
PRINTER_CHANGE_ADD_PRINT_PROCESSOR,
pIniSpooler);
LeaveSplSem();
SplOutSem();
if (LastError) {
SetLastError(LastError);
return FALSE;
}
return TRUE;
}
BOOL
LocalDeletePrintProcessor(
LPWSTR pName,
LPWSTR pEnvironment,
LPWSTR pPrintProcessorName
)
{
return ( SplDeletePrintProcessor( pName,
pEnvironment,
pPrintProcessorName,
pLocalIniSpooler ));
}
BOOL
SplDeletePrintProcessor(
LPWSTR pName,
LPWSTR pEnvironment,
LPWSTR pPrintProcessorName,
PINISPOOLER pIniSpooler
)
{
PINIENVIRONMENT pIniEnvironment;
PINIPRINTPROC pIniPrintProc;
BOOL Remote=FALSE;
if (pName && *pName) {
if (!MyName( pName, pIniSpooler )) {
return FALSE;
} else {
Remote = TRUE;
}
}
if ( !ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL, pIniSpooler )) {
return FALSE;
}
EnterSplSem();
pIniEnvironment = FindEnvironment(pEnvironment);
if (!pIniEnvironment || (pIniEnvironment != pThisEnvironment)) {
LeaveSplSem();
SetLastError(ERROR_INVALID_ENVIRONMENT);
return FALSE;
}
if (!(pIniPrintProc=(PINIPRINTPROC)FindIniKey(
(PINIENTRY)pIniEnvironment->pIniPrintProc,
pPrintProcessorName)) || pIniPrintProc->cRef) {
SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
LeaveSplSem();
return FALSE;
}
RemoveFromList((PINIENTRY *)&pIniEnvironment->pIniPrintProc,
(PINIENTRY)pIniPrintProc);
DeletePrintProcessorIni(pIniPrintProc, pIniEnvironment, pIniSpooler);
if (!FreeLibrary(pIniPrintProc->hLibrary)) {
DBGMSG(DBG_TRACE, ("DeletePrintProcessor: FreeLibrary failed\n"));
}
FreeSplMem(pIniPrintProc->pDatatypes);
SPLASSERT(pIniPrintProc->InCriticalSection == 0);
DeleteCriticalSection(&pIniPrintProc->CriticalSection);
FreeSplMem(pIniPrintProc);
SetPrinterChange(NULL,
NULL,
NULL,
PRINTER_CHANGE_DELETE_PRINT_PROCESSOR,
pIniSpooler);
LeaveSplSem();
return TRUE;
}
BOOL
LocalEnumPrintProcessors(
LPWSTR pName,
LPWSTR pEnvironment,
DWORD Level,
LPBYTE pPrintProcessorInfo,
DWORD cbBuf,
LPDWORD pcbNeeded,
LPDWORD pcReturned
)
{
return ( SplEnumPrintProcessors( pName,
pEnvironment,
Level,
pPrintProcessorInfo,
cbBuf,
pcbNeeded,
pcReturned,
pLocalIniSpooler ));
}
BOOL
SplEnumPrintProcessors(
LPWSTR pName,
LPWSTR pEnvironment,
DWORD Level,
LPBYTE pPrintProcessorInfo,
DWORD cbBuf,
LPDWORD pcbNeeded,
LPDWORD pcReturned,
PINISPOOLER pIniSpooler
)
{
PINIPRINTPROC pIniPrintProc;
PINIENVIRONMENT pIniEnvironment;
DWORD cb, cbStruct;
LPBYTE pEnd;
DWORD LastError=0;
if (!MyName( pName, pIniSpooler )) {
return FALSE;
}
if ( !ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
SERVER_ACCESS_ENUMERATE,
NULL, pIniSpooler )) {
return FALSE;
}
EnterSplSem();
// Ignore the environment.
// Otherwise, when a client with a different environment calls us
// to create a printer remotely, we will fail.
pIniEnvironment = pThisEnvironment;
LeaveSplSem();
switch (Level) {
case 1:
cbStruct = sizeof(PRINTPROCESSOR_INFO_1);
break;
}
*pcReturned=0;
cb=0;
EnterSplSem();
pIniPrintProc=pIniEnvironment->pIniPrintProc;
while (pIniPrintProc) {
cb+=GetPrintProcessorInfoSize(pIniPrintProc, Level, pEnvironment);
pIniPrintProc=pIniPrintProc->pNext;
}
*pcbNeeded=cb;
if (cb <= cbBuf) {
pIniPrintProc=pIniEnvironment->pIniPrintProc;
pEnd=pPrintProcessorInfo+cbBuf;
while (pEnd && pIniPrintProc) {
pEnd = CopyIniPrintProcToPrintProcInfo(pEnvironment,
pIniPrintProc,
Level,
pPrintProcessorInfo,
pEnd);
pPrintProcessorInfo+=cbStruct;
(*pcReturned)++;
pIniPrintProc=pIniPrintProc->pNext;
}
if (!pEnd)
LastError = ERROR_OUTOFMEMORY;
} else
LastError = ERROR_INSUFFICIENT_BUFFER;
LeaveSplSem();
SplOutSem();
if (LastError) {
SetLastError(LastError);
return FALSE;
}
return TRUE;
}
BOOL
LocalGetPrintProcessorDirectory(
LPWSTR pName,
LPWSTR pEnvironment,
DWORD Level,
LPBYTE pPrintProcessorInfo,
DWORD cbBuf,
LPDWORD pcbNeeded
)
{
return (SplGetPrintProcessorDirectory( pName,
pEnvironment,
Level,
pPrintProcessorInfo,
cbBuf,
pcbNeeded,
pLocalIniSpooler ) );
}
BOOL
SplGetPrintProcessorDirectory(
LPWSTR pName,
LPWSTR pEnvironment,
DWORD Level,
LPBYTE pPrintProcessorInfo,
DWORD cbBuf,
LPDWORD pcbNeeded,
PINISPOOLER pIniSpooler
)
{
PINIENVIRONMENT pIniEnvironment;
DWORD cb;
WCHAR string[MAX_PATH];
BOOL rc = FALSE;
if (!MyName( pName, pIniSpooler )) {
return FALSE;
}
if ( !ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
SERVER_ACCESS_ENUMERATE,
NULL, pIniSpooler )) {
return FALSE;
}
EnterSplSem();
pIniEnvironment = FindEnvironment(pEnvironment);
if (pIniEnvironment) {
cb = GetProcessorDirectory( string, pIniEnvironment->pDirectory, pIniSpooler )
* sizeof(WCHAR) + sizeof(WCHAR);
*pcbNeeded = cb;
if (cb > cbBuf) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
LeaveSplSem();
return FALSE;
}
wcscpy((LPWSTR)pPrintProcessorInfo, string);
// Make sure the directory exists:
CreatePrintProcDirectory( pIniEnvironment->pDirectory, pIniSpooler );
rc = TRUE;
} else
SetLastError(ERROR_INVALID_ENVIRONMENT);
LeaveSplSem();
return rc;
}
BOOL
LocalEnumPrintProcessorDatatypes(
LPWSTR pName,
LPWSTR pPrintProcessorName,
DWORD Level,
LPBYTE pDatatypes,
DWORD cbBuf,
LPDWORD pcbNeeded,
LPDWORD pcReturned
)
{
return ( SplEnumPrintProcessorDatatypes( pName,
pPrintProcessorName,
Level,
pDatatypes,
cbBuf,
pcbNeeded,
pcReturned,
pLocalIniSpooler ));
}
BOOL
SplEnumPrintProcessorDatatypes(
LPWSTR pName,
LPWSTR pPrintProcessorName,
DWORD Level,
LPBYTE pDatatypes,
DWORD cbBuf,
LPDWORD pcbNeeded,
LPDWORD pcReturned,
PINISPOOLER pIniSpooler
)
{
PINIPRINTPROC pIniPrintProc;
if (!MyName( pName, pIniSpooler )) {
return FALSE;
}
if ( !ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
SERVER_ACCESS_ENUMERATE,
NULL, pIniSpooler )) {
return FALSE;
}
EnterSplSem();
pIniPrintProc=FindPrintProc(pPrintProcessorName, pThisEnvironment);
LeaveSplSem();
if (pIniPrintProc)
return (*pIniPrintProc->EnumDatatypes)(pName, pPrintProcessorName,
Level, pDatatypes, cbBuf,
pcbNeeded, pcReturned);
else {
SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
return FALSE;
}
}
DWORD
GetPrintProcessorInfoSize(
PINIPRINTPROC pIniPrintProc,
DWORD Level,
LPWSTR pEnvironment
)
{
DWORD cb=0;
switch (Level) {
case 1:
cb=sizeof(PRINTPROCESSOR_INFO_1) +
wcslen(pIniPrintProc->pName)*sizeof(WCHAR) + sizeof(WCHAR);
break;
default:
cb = 0;
break;
}
return cb;
}
LPBYTE
CopyIniPrintProcToPrintProcInfo(
LPWSTR pEnvironment,
PINIPRINTPROC pIniPrintProc,
DWORD Level,
LPBYTE pPrintProcessorInfo,
LPBYTE pEnd
)
{
LPWSTR *pSourceStrings, *SourceStrings;
PPRINTPROCESSOR_INFO_1 pDriver1 = (PPRINTPROCESSOR_INFO_1)pPrintProcessorInfo;
DWORD j;
DWORD *pOffsets;
switch (Level) {
case 1:
pOffsets = PrintProcessorInfo1Strings;
break;
default:
return pEnd;
}
for (j=0; pOffsets[j] != -1; j++) {
}
SourceStrings = pSourceStrings = AllocSplMem(j * sizeof(LPWSTR));
if (!pSourceStrings) {
DBGMSG(DBG_WARNING, ("Could not allocate %d bytes for print proc source strings.\n",
(j * sizeof(LPWSTR))));
return pEnd;
}
switch (Level) {
case 1:
*pSourceStrings++=pIniPrintProc->pName;
pEnd = PackStrings(SourceStrings, (LPBYTE)pPrintProcessorInfo, pOffsets, pEnd);
break;
}
FreeSplMem(SourceStrings);
return pEnd;
}
BOOL
AddPrintProcessorIni(
PINIPRINTPROC pIniPrintProc,
PINIENVIRONMENT pIniEnvironment,
PINISPOOLER pIniSpooler
)
{
HKEY hEnvironmentsRootKey, hEnvironmentKey, hPrintProcsKey, hPrintProcKey;
HANDLE hToken;
BOOL ReturnValue = FALSE;
hToken = RevertToPrinterSelf();
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, pIniSpooler->pszRegistryEnvironments, 0,
NULL, 0, KEY_WRITE, NULL, &hEnvironmentsRootKey, NULL)
== ERROR_SUCCESS) {
if (RegOpenKeyEx(hEnvironmentsRootKey, pIniEnvironment->pName, 0,
KEY_WRITE, &hEnvironmentKey)
== ERROR_SUCCESS) {
if (RegOpenKeyEx(hEnvironmentKey, szPrintProcKey, 0,
KEY_WRITE, &hPrintProcsKey)
== ERROR_SUCCESS) {
if (RegCreateKeyEx(hPrintProcsKey, pIniPrintProc->pName, 0,
NULL, 0, KEY_WRITE, NULL,
&hPrintProcKey, NULL)
== ERROR_SUCCESS) {
if (RegSetValueEx(hPrintProcKey, szDriverFile, 0,
REG_SZ, (LPBYTE)pIniPrintProc->pDLLName,
(wcslen(pIniPrintProc->pDLLName) + 1)*sizeof(WCHAR))
== ERROR_SUCCESS)
ReturnValue = TRUE;
RegCloseKey(hPrintProcKey);
}
RegCloseKey(hPrintProcsKey);
}
RegCloseKey(hEnvironmentKey);
}
RegCloseKey(hEnvironmentsRootKey);
}
ImpersonatePrinterClient(hToken);
return ReturnValue;
}
BOOL
DeletePrintProcessorIni(
PINIPRINTPROC pIniPrintProc,
PINIENVIRONMENT pIniEnvironment,
PINISPOOLER pIniSpooler
)
{
HKEY hEnvironmentsRootKey, hEnvironmentKey, hPrintProcsKey;
HANDLE hToken;
hToken = RevertToPrinterSelf();
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, pIniSpooler->pszRegistryEnvironments, 0,
NULL, 0, KEY_WRITE, NULL, &hEnvironmentsRootKey, NULL)
== ERROR_SUCCESS) {
if (RegOpenKeyEx(hEnvironmentsRootKey, pIniEnvironment->pName, 0,
KEY_WRITE, &hEnvironmentKey)
== ERROR_SUCCESS) {
if (RegOpenKeyEx(hEnvironmentKey, szPrintProcKey, 0,
KEY_WRITE, &hPrintProcsKey)
== ERROR_SUCCESS) {
RegDeleteKey(hPrintProcsKey, pIniPrintProc->pName);
RegCloseKey(hPrintProcsKey);
}
RegCloseKey(hEnvironmentKey);
}
RegCloseKey(hEnvironmentsRootKey);
}
ImpersonatePrinterClient(hToken);
return TRUE;
}