mirror of https://github.com/lianthony/NT4.0
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.
5135 lines
124 KiB
5135 lines
124 KiB
/*++
|
|
|
|
Copyright (c) 1990-1995 Microsoft Corporation
|
|
All rights reserved
|
|
|
|
Module Name:
|
|
|
|
win32 provider (win32spl)
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
DaveSn
|
|
|
|
Environment:
|
|
|
|
User Mode -Win32
|
|
|
|
Revision History:
|
|
|
|
Matthew A Felton (Mattfe) July 16 1994
|
|
Added Caching for remote NT printers
|
|
MattFe Jan 1995 CleanUp DeletePrinterConnection ( for memory allocation errors )
|
|
SWilson May 1996 Added RemoteEnumPrinterData & RemoteDeletePrinterData
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <winspool.h>
|
|
#include <winsplp.h>
|
|
#include <winddiui.h>
|
|
#include <lm.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <rpc.h>
|
|
#include "winspl.h"
|
|
#include <drivinit.h>
|
|
#include <offsets.h>
|
|
#include <w32types.h>
|
|
#include <splcom.h>
|
|
#include <local.h>
|
|
#include <winerror.h>
|
|
#include <gdispool.h>
|
|
|
|
DWORD
|
|
RpcValidate(
|
|
);
|
|
|
|
BOOL
|
|
RemoteFindFirstPrinterChangeNotification(
|
|
HANDLE hPrinter,
|
|
DWORD fdwFlags,
|
|
DWORD fdwOptions,
|
|
HANDLE hNotify,
|
|
PDWORD pfdwStatus,
|
|
PVOID pvReserved0,
|
|
PVOID pvReserved1);
|
|
|
|
BOOL
|
|
RemoteFindClosePrinterChangeNotification(
|
|
HANDLE hPrinter);
|
|
|
|
BOOL
|
|
RemoteRefreshPrinterChangeNotification(
|
|
HANDLE hPrinter,
|
|
DWORD dwColor,
|
|
PVOID pPrinterNotifyRefresh,
|
|
PVOID* ppPrinterNotifyInfo);
|
|
|
|
|
|
HANDLE hInst; /* DLL instance handle, used for resources */
|
|
|
|
#define MAX_PRINTER_INFO2 1000
|
|
|
|
HANDLE hNetApi;
|
|
INT_FARPROC pfnNetServerEnum;
|
|
INT_FARPROC pfnNetShareEnum;
|
|
INT_FARPROC pfnNetWkstaUserGetInfo;
|
|
INT_FARPROC pfnNetWkstaGetInfo;
|
|
INT_FARPROC pfnNetServerGetInfo;
|
|
FARPROC pfnNetApiBufferFree;
|
|
|
|
WCHAR szPrintProvidorName[80];
|
|
WCHAR szPrintProvidorDescription[80];
|
|
WCHAR szPrintProvidorComment[80];
|
|
|
|
WCHAR *szLoggedOnDomain=L"Logged on Domain";
|
|
WCHAR *szRegistryConnections=L"Printers\\Connections";
|
|
WCHAR *szRegistryPath=NULL;
|
|
WCHAR *szRegistryPortNames=L"PortNames";
|
|
PWCHAR pszRemoteRegistryPrinters = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\\%ws\\PrinterDriverData";
|
|
WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+3];
|
|
|
|
WCHAR *szVersion=L"Version";
|
|
WCHAR *szName=L"Name";
|
|
WCHAR *szConfigurationFile=L"Configuration File";
|
|
WCHAR *szDataFile=L"Data File";
|
|
WCHAR *szDriver=L"Driver";
|
|
WCHAR *szDevices=L"Devices";
|
|
WCHAR *szPrinterPorts=L"PrinterPorts";
|
|
WCHAR *szPorts=L"Ports";
|
|
WCHAR *szComma = L",";
|
|
WCHAR *szRegistryRoot = L"System\\CurrentControlSet\\Control\\Print";
|
|
WCHAR *szMajorVersion = L"MajorVersion";
|
|
WCHAR *szMinorVersion = L"MinorVersion";
|
|
|
|
// kernel mode is 2.
|
|
DWORD cThisMajorVersion = 2;
|
|
|
|
DWORD cThisMinorVersion = 0;
|
|
|
|
SPLCLIENT_INFO_1 gSplClientInfo1;
|
|
DWORD gdwThisGetVersion;
|
|
|
|
#if defined(_MIPS_)
|
|
WCHAR *szEnvironment = L"Windows NT R4000";
|
|
#elif defined(_ALPHA_)
|
|
WCHAR *szEnvironment = L"Windows NT Alpha_AXP";
|
|
#elif defined(_PPC_)
|
|
WCHAR *szEnvironment = L"Windows NT PowerPC";
|
|
#else
|
|
WCHAR *szEnvironment = L"Windows NT x86";
|
|
#endif
|
|
|
|
CRITICAL_SECTION SpoolerSection;
|
|
|
|
//
|
|
// Note indented calls have some Cache Effect.
|
|
//
|
|
|
|
PRINTPROVIDOR PrintProvidor = { CacheOpenPrinter,
|
|
SetJob,
|
|
GetJob,
|
|
EnumJobs,
|
|
AddPrinter,
|
|
DeletePrinter,
|
|
SetPrinter,
|
|
CacheGetPrinter,
|
|
EnumPrinters,
|
|
RemoteAddPrinterDriver,
|
|
EnumPrinterDrivers,
|
|
CacheGetPrinterDriver,
|
|
RemoteGetPrinterDriverDirectory,
|
|
DeletePrinterDriver,
|
|
AddPrintProcessor,
|
|
EnumPrintProcessors,
|
|
GetPrintProcessorDirectory,
|
|
DeletePrintProcessor,
|
|
EnumPrintProcessorDatatypes,
|
|
StartDocPrinter,
|
|
StartPagePrinter,
|
|
WritePrinter,
|
|
EndPagePrinter,
|
|
AbortPrinter,
|
|
ReadPrinter,
|
|
RemoteEndDocPrinter,
|
|
AddJob,
|
|
ScheduleJob,
|
|
CacheGetPrinterData,
|
|
SetPrinterData,
|
|
WaitForPrinterChange,
|
|
CacheClosePrinter,
|
|
AddForm,
|
|
DeleteForm,
|
|
CacheGetForm,
|
|
SetForm,
|
|
CacheEnumForms,
|
|
EnumMonitors,
|
|
RemoteEnumPorts,
|
|
RemoteAddPort,
|
|
RemoteConfigurePort,
|
|
RemoteDeletePort,
|
|
CreatePrinterIC,
|
|
PlayGdiScriptOnPrinterIC,
|
|
DeletePrinterIC,
|
|
AddPrinterConnection,
|
|
DeletePrinterConnection,
|
|
PrinterMessageBox,
|
|
AddMonitor,
|
|
DeleteMonitor,
|
|
CacheResetPrinter,
|
|
NULL,
|
|
RemoteFindFirstPrinterChangeNotification,
|
|
RemoteFindClosePrinterChangeNotification,
|
|
RemoteAddPortEx,
|
|
NULL,
|
|
RemoteRefreshPrinterChangeNotification,
|
|
NULL,
|
|
NULL,
|
|
SetPort,
|
|
RemoteEnumPrinterData,
|
|
RemoteDeletePrinterData
|
|
};
|
|
|
|
BOOL
|
|
LibMain(
|
|
HANDLE hModule,
|
|
DWORD dwReason,
|
|
LPVOID lpRes
|
|
)
|
|
{
|
|
if (dwReason != DLL_PROCESS_ATTACH)
|
|
return TRUE;
|
|
|
|
hInst = hModule;
|
|
|
|
InitializeCriticalSection(&SpoolerSection);
|
|
DisableThreadLibraryCalls(hModule);
|
|
|
|
return TRUE;
|
|
|
|
UNREFERENCED_PARAMETER( lpRes );
|
|
}
|
|
|
|
PWCHAR gpSystemDir = NULL;
|
|
PWCHAR gpWin32SplDir = NULL;
|
|
|
|
|
|
BOOL
|
|
InitializePrintProvidor(
|
|
LPPRINTPROVIDOR pPrintProvidor,
|
|
DWORD cbPrintProvidor,
|
|
LPWSTR pFullRegistryPath
|
|
)
|
|
{
|
|
DWORD i;
|
|
WCHAR SystemDir[MAX_PATH];
|
|
DWORD ReturnValue = TRUE;
|
|
UINT Index;
|
|
OSVERSIONINFO OSVersionInfo;
|
|
SYSTEM_INFO SystemInfo;
|
|
|
|
|
|
if (!pFullRegistryPath || !*pFullRegistryPath) {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// DbgInit();
|
|
|
|
if ( !GetPrintSystemVersion() ) {
|
|
|
|
DBGMSG( DBG_WARNING, ("GetPrintSystemVersion ERROR %d\n", GetLastError() ));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(szRegistryPath = AllocSplStr(pFullRegistryPath)))
|
|
return FALSE;
|
|
|
|
szPrintProvidorName[0] = L'\0';
|
|
szPrintProvidorDescription[0] = L'\0';
|
|
szPrintProvidorComment[0] = L'\0';
|
|
|
|
if (!LoadString(hInst, IDS_WINDOWS_NT_REMOTE_PRINTERS,
|
|
szPrintProvidorName,
|
|
sizeof(szPrintProvidorName) / sizeof(*szPrintProvidorName)))
|
|
|
|
return FALSE;
|
|
|
|
if (!LoadString(hInst, IDS_MICROSOFT_WINDOWS_NETWORK,
|
|
szPrintProvidorDescription,
|
|
sizeof(szPrintProvidorDescription) / sizeof(*szPrintProvidorDescription)))
|
|
|
|
return FALSE;
|
|
|
|
if (!LoadString(hInst, IDS_REMOTE_PRINTERS,
|
|
szPrintProvidorComment,
|
|
sizeof(szPrintProvidorComment) / sizeof(*szPrintProvidorComment)))
|
|
|
|
return FALSE;
|
|
|
|
if ((hNetApi = LoadLibrary(L"netapi32.dll"))) {
|
|
|
|
pfnNetServerEnum = GetProcAddress(hNetApi, "NetServerEnum");
|
|
pfnNetShareEnum = GetProcAddress(hNetApi, "NetShareEnum");
|
|
pfnNetWkstaUserGetInfo = GetProcAddress(hNetApi, "NetWkstaUserGetInfo");
|
|
pfnNetWkstaGetInfo = GetProcAddress(hNetApi, "NetWkstaGetInfo");
|
|
pfnNetApiBufferFree = GetProcAddress(hNetApi, "NetApiBufferFree");
|
|
pfnNetServerGetInfo = GetProcAddress(hNetApi, "NetServerGetInfo");
|
|
|
|
if ( pfnNetServerEnum == NULL ||
|
|
pfnNetShareEnum == NULL ||
|
|
pfnNetWkstaUserGetInfo == NULL ||
|
|
pfnNetWkstaGetInfo == NULL ||
|
|
pfnNetApiBufferFree == NULL ||
|
|
pfnNetServerGetInfo == NULL ) {
|
|
|
|
DBGMSG( DBG_WARNING, ("Failed GetProcAddres on Net Api's %d\n", GetLastError() ));
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DBGMSG(DBG_WARNING,
|
|
("Failed LoadLibrary( netapi32.dll ) %d\n", GetLastError() ));
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
memcpy(pPrintProvidor, &PrintProvidor, min(sizeof(PRINTPROVIDOR),
|
|
cbPrintProvidor));
|
|
|
|
QueryTrustedDriverInformation();
|
|
|
|
szMachineName[0] = szMachineName[1] = L'\\';
|
|
|
|
i = MAX_COMPUTERNAME_LENGTH + 1;
|
|
|
|
gdwThisGetVersion = GetVersion();
|
|
GetSystemInfo(&SystemInfo);
|
|
OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
|
|
|
|
if (!GetComputerName(szMachineName+2, &i) ||
|
|
!GetVersionEx(&OSVersionInfo) ||
|
|
!(gSplClientInfo1.pMachineName = AllocSplStr(szMachineName)) )
|
|
return FALSE;
|
|
|
|
gSplClientInfo1.dwSize = sizeof(gSplClientInfo1);
|
|
gSplClientInfo1.dwBuildNum = OSVersionInfo.dwBuildNumber;
|
|
gSplClientInfo1.dwMajorVersion = cThisMajorVersion;
|
|
gSplClientInfo1.dwMinorVersion = cThisMinorVersion;
|
|
gSplClientInfo1.pUserName = NULL;
|
|
|
|
gSplClientInfo1.wProcessorArchitecture = SystemInfo.wProcessorArchitecture;
|
|
|
|
|
|
if ( InitializePortNames() != NO_ERROR )
|
|
return FALSE;
|
|
|
|
Index = GetSystemDirectory(SystemDir, sizeof(SystemDir));
|
|
|
|
if ( Index == 0 ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
gpSystemDir = AllocSplStr( SystemDir );
|
|
if ( gpSystemDir == NULL ) {
|
|
return FALSE;
|
|
}
|
|
|
|
wcscpy( &SystemDir[Index], szWin32SplDirectory );
|
|
|
|
gpWin32SplDir = AllocSplStr( SystemDir );
|
|
|
|
if ( gpWin32SplDir == NULL ) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
DWORD
|
|
InitializePortNames(
|
|
)
|
|
{
|
|
LONG Status;
|
|
HKEY hkeyPath;
|
|
HKEY hkeyPortNames;
|
|
WCHAR Buffer[MAX_PATH];
|
|
DWORD BufferSize;
|
|
DWORD i;
|
|
DWORD dwReturnValue;
|
|
|
|
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szRegistryPath, 0,
|
|
KEY_READ, &hkeyPath );
|
|
|
|
dwReturnValue = Status;
|
|
|
|
if( Status == NO_ERROR ) {
|
|
|
|
Status = RegOpenKeyEx( hkeyPath, szRegistryPortNames, 0,
|
|
KEY_READ, &hkeyPortNames );
|
|
|
|
if( Status == NO_ERROR ) {
|
|
|
|
i = 0;
|
|
|
|
while( Status == NO_ERROR ) {
|
|
|
|
BufferSize = sizeof Buffer;
|
|
|
|
Status = RegEnumValue( hkeyPortNames, i, Buffer, &BufferSize,
|
|
NULL, NULL, NULL, NULL );
|
|
|
|
if( Status == NO_ERROR )
|
|
CreatePortEntry( Buffer, &pIniFirstPort );
|
|
|
|
i++;
|
|
}
|
|
|
|
/* We expect RegEnumKeyEx to return ERROR_NO_MORE_ITEMS
|
|
* when it gets to the end of the keys, so reset the status:
|
|
*/
|
|
if( Status == ERROR_NO_MORE_ITEMS )
|
|
Status = NO_ERROR;
|
|
|
|
RegCloseKey( hkeyPortNames );
|
|
|
|
} else {
|
|
|
|
DBGMSG( DBG_INFO, ( "RegOpenKeyEx (%ws) failed: Error = %d\n",
|
|
szRegistryPortNames, Status ) );
|
|
}
|
|
|
|
RegCloseKey( hkeyPath );
|
|
|
|
} else {
|
|
|
|
DBGMSG( DBG_WARNING, ( "RegOpenKeyEx (%ws) failed: Error = %d\n",
|
|
szRegistryPath, Status ) );
|
|
}
|
|
|
|
if ( dwReturnValue != NO_ERROR ) {
|
|
SetLastError( dwReturnValue );
|
|
}
|
|
|
|
return dwReturnValue;
|
|
}
|
|
|
|
|
|
void
|
|
MarshallUpStructure(
|
|
LPBYTE lpStructure,
|
|
LPDWORD lpOffsets
|
|
)
|
|
{
|
|
register DWORD i=0;
|
|
|
|
while (lpOffsets[i] != -1) {
|
|
|
|
if ((*(LPBYTE *)(lpStructure+lpOffsets[i]))) {
|
|
(*(LPBYTE *)(lpStructure+lpOffsets[i]))+=(DWORD)lpStructure;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
EnumerateFavouritePrinters(
|
|
LPWSTR pDomain,
|
|
DWORD Level,
|
|
DWORD cbStruct,
|
|
LPDWORD pOffsets,
|
|
LPBYTE pPrinter,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
HKEY hClientKey = NULL;
|
|
HKEY hKey1=NULL;
|
|
DWORD cPrinters, cbData;
|
|
WCHAR PrinterName[ MAX_UNC_PRINTER_NAME ];
|
|
DWORD cReturned, TotalcbNeeded, cbNeeded, cTotalReturned;
|
|
DWORD Error=0;
|
|
DWORD BufferSize=cbBuf;
|
|
HANDLE hPrinter;
|
|
DWORD Status;
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateFavouritePrinters called\n"));
|
|
|
|
*pcbNeeded = 0;
|
|
*pcReturned = 0;
|
|
|
|
hClientKey = GetClientUserHandle(KEY_READ);
|
|
|
|
if ( hClientKey == NULL ) {
|
|
|
|
DBGMSG( DBG_WARNING, ("EnumerateFavouritePrinters GetClientUserHandle failed error %d", GetLastError() ));
|
|
return FALSE;
|
|
}
|
|
|
|
Status = RegOpenKeyEx(hClientKey, szRegistryConnections, 0,
|
|
KEY_READ, &hKey1);
|
|
|
|
if ( Status != ERROR_SUCCESS ) {
|
|
|
|
RegCloseKey(hClientKey);
|
|
SetLastError( Status );
|
|
DBGMSG( DBG_WARNING, ("EnumerateFavouritePrinters RegOpenKeyEx failed error %d", GetLastError() ));
|
|
return FALSE;
|
|
}
|
|
|
|
cPrinters=0;
|
|
|
|
cbData = sizeof(PrinterName);
|
|
|
|
TotalcbNeeded = cTotalReturned = 0;
|
|
|
|
cReturned = cbNeeded = 0;
|
|
|
|
while (RegEnumKeyEx(hKey1, cPrinters, PrinterName, &cbData,
|
|
NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
|
|
|
|
FormatRegistryKeyForPrinter(PrinterName, PrinterName);
|
|
|
|
// Do not fail if any of these calls fails, because we want
|
|
// to return whatever we can find.
|
|
|
|
if (CacheOpenPrinter(PrinterName, &hPrinter, NULL)) {
|
|
|
|
if (CacheGetPrinter(hPrinter, Level, pPrinter, BufferSize, &cbNeeded)) {
|
|
|
|
if (Level == 2) {
|
|
((PPRINTER_INFO_2)pPrinter)->Attributes |=
|
|
PRINTER_ATTRIBUTE_NETWORK;
|
|
((PPRINTER_INFO_2)pPrinter)->Attributes &=
|
|
~PRINTER_ATTRIBUTE_LOCAL;
|
|
}
|
|
|
|
cTotalReturned++;
|
|
|
|
pPrinter += cbStruct;
|
|
|
|
if (cbNeeded <= BufferSize)
|
|
BufferSize -= cbNeeded;
|
|
|
|
TotalcbNeeded += cbNeeded;
|
|
|
|
} else {
|
|
|
|
DWORD Error;
|
|
|
|
if ((Error = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) {
|
|
|
|
if (cbNeeded <= BufferSize)
|
|
BufferSize -= cbNeeded;
|
|
|
|
TotalcbNeeded += cbNeeded;
|
|
|
|
} else {
|
|
|
|
DBGMSG( DBG_WARNING, ( "GetPrinter( %ws ) failed: Error %d\n",
|
|
PrinterName, Error ) );
|
|
}
|
|
}
|
|
|
|
CacheClosePrinter(hPrinter);
|
|
|
|
} else {
|
|
|
|
DBGMSG( DBG_WARNING, ( "CacheOpenPrinter( %ws ) failed: Error %d\n",
|
|
PrinterName, GetLastError( ) ) );
|
|
}
|
|
|
|
cPrinters++;
|
|
|
|
cbData = sizeof(PrinterName);
|
|
}
|
|
|
|
RegCloseKey(hKey1);
|
|
|
|
if (hClientKey) {
|
|
RegCloseKey(hClientKey);
|
|
}
|
|
|
|
*pcbNeeded = TotalcbNeeded;
|
|
|
|
*pcReturned = cTotalReturned;
|
|
|
|
if (TotalcbNeeded > cbBuf) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateFavouritePrinters returns ERROR_INSUFFICIENT_BUFFER\n"));
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
EnumerateDomainPrinters(
|
|
LPWSTR pDomain,
|
|
DWORD Level,
|
|
DWORD cbStruct,
|
|
LPDWORD pOffsets,
|
|
LPBYTE pPrinter,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
DWORD i, j, NoReturned, Total, OuterLoopCount;
|
|
DWORD rc = 0;
|
|
PSERVER_INFO_101 pserver_info_101;
|
|
DWORD ReturnValue=FALSE;
|
|
WCHAR string[MAX_PATH];
|
|
PPRINTER_INFO_1 pPrinterInfo1;
|
|
DWORD cb=cbBuf;
|
|
LPWSTR SourceStrings[sizeof(PRINTER_INFO_1)/sizeof(LPWSTR)];
|
|
LPBYTE pEnd;
|
|
DWORD ServerType;
|
|
BOOL bServerFound = FALSE;
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters called\n"));
|
|
|
|
string[0] = string[1] = '\\';
|
|
|
|
*pcbNeeded = *pcReturned = 0;
|
|
|
|
if (!(*pfnNetServerEnum)(NULL, 101, (LPBYTE *)&pserver_info_101, -1,
|
|
&NoReturned, &Total,
|
|
SV_TYPE_PRINTQ_SERVER | SV_TYPE_WFW,
|
|
pDomain, NULL)) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters NetServerEnum returned %d\n", NoReturned));
|
|
|
|
//
|
|
// First Look try NT Servers, then if that Fails Look at the WorkStations
|
|
//
|
|
|
|
for ( ServerType = ( SV_TYPE_SERVER_NT | SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL ), OuterLoopCount = 0;
|
|
bServerFound == FALSE && OuterLoopCount < 2;
|
|
ServerType = SV_TYPE_NT, OuterLoopCount++ ) {
|
|
|
|
//
|
|
// Loop Through looking for a print server that will return a good browse list
|
|
//
|
|
|
|
for ( i = 0; i < NoReturned; i++ ) {
|
|
|
|
if ( pserver_info_101[i].sv101_type & ServerType ) {
|
|
|
|
wcscpy( &string[2], pserver_info_101[i].sv101_name );
|
|
|
|
RpcTryExcept {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters Trying %ws ENUM_NETWORK type %x\n", string, ServerType ));
|
|
|
|
if ( !(rc = RpcValidate()) &&
|
|
!(rc = RpcEnumPrinters(PRINTER_ENUM_NETWORK,
|
|
string,
|
|
1, pPrinter,
|
|
cbBuf, pcbNeeded,
|
|
pcReturned)) ) {
|
|
|
|
j = *pcReturned;
|
|
|
|
while (j--) {
|
|
|
|
MarshallUpStructure(pPrinter, PrinterInfo1Offsets);
|
|
|
|
pPrinter += cbStruct;
|
|
}
|
|
|
|
//
|
|
// Only return success if we found some data.
|
|
//
|
|
|
|
if ( *pcReturned != 0 ) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters %ws ENUM_NETWORK Success %d returned\n", string, *pcReturned ));
|
|
|
|
bServerFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
} else if (rc == ERROR_INSUFFICIENT_BUFFER) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters %ws ENUM_NETWORK ERROR_INSUFFICIENT_BUFFER\n", string ));
|
|
|
|
bServerFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
DBGMSG( DBG_TRACE,( "Failed to connect to Print Server%ws\n",
|
|
pserver_info_101[i].sv101_name ) );
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters %ws type %x not type %x\n", pserver_info_101[i].sv101_name, pserver_info_101[i].sv101_type, ServerType));
|
|
}
|
|
}
|
|
}
|
|
|
|
pPrinterInfo1 = (PPRINTER_INFO_1)pPrinter;
|
|
|
|
pEnd = (LPBYTE)pPrinterInfo1 + cb - *pcbNeeded;
|
|
|
|
for ( i = 0; i < NoReturned; i++ ) {
|
|
|
|
wcscpy( string, szPrintProvidorName );
|
|
wcscat( string, L"!" );
|
|
if ( pDomain )
|
|
wcscat( string, pDomain );
|
|
wcscat( string, L"!\\\\" );
|
|
wcscat( string, pserver_info_101[i].sv101_name );
|
|
|
|
cb = wcslen(pserver_info_101[i].sv101_name)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
wcslen(string)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
wcslen(szLoggedOnDomain)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
sizeof(PRINTER_INFO_1);
|
|
|
|
(*pcbNeeded) += cb;
|
|
|
|
if ( cbBuf >= *pcbNeeded ) {
|
|
|
|
(*pcReturned)++;
|
|
|
|
pPrinterInfo1->Flags = PRINTER_ENUM_CONTAINER | PRINTER_ENUM_ICON3;
|
|
|
|
SourceStrings[0] = pserver_info_101[i].sv101_name;
|
|
SourceStrings[1] = string;
|
|
SourceStrings[2] = szLoggedOnDomain;
|
|
|
|
pEnd = PackStrings( SourceStrings, (LPBYTE)pPrinterInfo1,
|
|
PrinterInfo1Strings, pEnd );
|
|
|
|
pPrinterInfo1++;
|
|
}
|
|
}
|
|
|
|
(*pfnNetApiBufferFree)((LPVOID)pserver_info_101);
|
|
|
|
if ( cbBuf < *pcbNeeded ) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters returns ERROR_INSUFFICIENT_BUFFER\n"));
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
EnumerateDomains(
|
|
PRINTER_INFO_1 *pPrinter,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
LPBYTE pEnd
|
|
)
|
|
{
|
|
DWORD i, NoReturned, Total;
|
|
DWORD cb;
|
|
SERVER_INFO_100 *pNames;
|
|
PWKSTA_INFO_100 pWkstaInfo = NULL;
|
|
LPWSTR SourceStrings[sizeof(PRINTER_INFO_1)/sizeof(LPWSTR)];
|
|
WCHAR string[MAX_PATH];
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomains pPrinter %x cbBuf %d pcbNeeded %x pcReturned %x pEnd %x\n",
|
|
pPrinter, cbBuf, pcbNeeded, pcReturned, pEnd ));
|
|
|
|
*pcReturned = 0;
|
|
*pcbNeeded = 0;
|
|
|
|
if (!(*pfnNetServerEnum)(NULL, 100, (LPBYTE *)&pNames, -1,
|
|
&NoReturned, &Total, SV_TYPE_DOMAIN_ENUM,
|
|
NULL, NULL)) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomains - NetServerEnum returned %d\n", NoReturned));
|
|
|
|
(*pfnNetWkstaGetInfo)(NULL, 100, (LPBYTE *)&pWkstaInfo);
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomains - NetWkstaGetInfo returned pWkstaInfo %x\n", pWkstaInfo));
|
|
|
|
for (i=0; i<NoReturned; i++) {
|
|
|
|
wcscpy(string, szPrintProvidorName);
|
|
wcscat(string, L"!");
|
|
wcscat(string, pNames[i].sv100_name);
|
|
|
|
cb = wcslen(pNames[i].sv100_name)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
wcslen(string)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
wcslen(szLoggedOnDomain)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
sizeof(PRINTER_INFO_1);
|
|
|
|
(*pcbNeeded)+=cb;
|
|
|
|
if (cbBuf >= *pcbNeeded) {
|
|
|
|
(*pcReturned)++;
|
|
|
|
pPrinter->Flags = PRINTER_ENUM_CONTAINER | PRINTER_ENUM_ICON2;
|
|
|
|
/* Set the PRINTER_ENUM_EXPAND flag for the user's logon domain
|
|
*/
|
|
if (!lstrcmpi(pNames[i].sv100_name,
|
|
pWkstaInfo->wki100_langroup))
|
|
pPrinter->Flags |= PRINTER_ENUM_EXPAND;
|
|
|
|
SourceStrings[0]=pNames[i].sv100_name;
|
|
SourceStrings[1]=string;
|
|
SourceStrings[2]=szLoggedOnDomain;
|
|
|
|
pEnd = PackStrings(SourceStrings, (LPBYTE)pPrinter,
|
|
PrinterInfo1Strings, pEnd);
|
|
|
|
pPrinter++;
|
|
}
|
|
}
|
|
|
|
(*pfnNetApiBufferFree)((LPVOID)pNames);
|
|
(*pfnNetApiBufferFree)((LPVOID)pWkstaInfo);
|
|
|
|
if (cbBuf < *pcbNeeded) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumerateDomains returns ERROR_INSUFFICIENT_BUFFER\n"));
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
EnumeratePrintShares(
|
|
LPWSTR pDomain,
|
|
LPWSTR pServer,
|
|
DWORD Level,
|
|
DWORD cbStruct,
|
|
LPDWORD pOffsets,
|
|
LPBYTE pPrinter,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
DWORD i, NoReturned, Total;
|
|
DWORD cb;
|
|
SHARE_INFO_1 *pNames;
|
|
LPWSTR SourceStrings[sizeof(PRINTER_INFO_1)/sizeof(LPWSTR)];
|
|
WCHAR string[MAX_PATH];
|
|
PRINTER_INFO_1 *pPrinterInfo1 = (PRINTER_INFO_1 *)pPrinter;
|
|
LPBYTE pEnd=pPrinter+cbBuf;
|
|
WCHAR FullName[MAX_PATH];
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumeratePrintShares\n"));
|
|
|
|
*pcReturned = 0;
|
|
*pcbNeeded = 0;
|
|
|
|
if (!(*pfnNetShareEnum)(pServer, 1, (LPBYTE *)&pNames, -1,
|
|
&NoReturned, &Total, NULL)) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumeratePrintShares NetShareEnum returned %d\n", NoReturned));
|
|
|
|
for (i=0; i<NoReturned; i++) {
|
|
|
|
if (pNames[i].shi1_type == STYPE_PRINTQ) {
|
|
|
|
wcscpy(string, pNames[i].shi1_netname);
|
|
wcscat(string, L",");
|
|
wcscat(string, pNames[i].shi1_remark);
|
|
|
|
wcscpy(FullName, pServer);
|
|
wcscat(FullName, L"\\");
|
|
wcscat(FullName, pNames[i].shi1_netname);
|
|
|
|
cb = wcslen(FullName)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
wcslen(string)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
wcslen(szLoggedOnDomain)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
sizeof(PRINTER_INFO_1);
|
|
|
|
(*pcbNeeded)+=cb;
|
|
|
|
if (cbBuf >= *pcbNeeded) {
|
|
|
|
(*pcReturned)++;
|
|
|
|
pPrinterInfo1->Flags = PRINTER_ENUM_ICON8;
|
|
|
|
SourceStrings[0]=string;
|
|
SourceStrings[1]=FullName;
|
|
SourceStrings[2]=szLoggedOnDomain;
|
|
|
|
pEnd = PackStrings(SourceStrings, (LPBYTE)pPrinterInfo1,
|
|
PrinterInfo1Strings, pEnd);
|
|
|
|
pPrinterInfo1++;
|
|
}
|
|
}
|
|
}
|
|
|
|
(*pfnNetApiBufferFree)((LPVOID)pNames);
|
|
|
|
if ( cbBuf < *pcbNeeded ) {
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumeratePrintShares returns ERROR_INSUFFICIENT_BUFFER\n"));
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
EnumPrinters(
|
|
DWORD Flags,
|
|
LPWSTR Name,
|
|
DWORD Level,
|
|
LPBYTE pPrinter,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
BOOL ReturnValue = FALSE;
|
|
DWORD cbStruct, cb;
|
|
DWORD *pOffsets;
|
|
DWORD NoReturned=0, i, rc;
|
|
LPBYTE pKeepPrinter = pPrinter;
|
|
BOOL OutOfMemory = FALSE;
|
|
PPRINTER_INFO_1 pPrinter1=(PPRINTER_INFO_1)pPrinter;
|
|
WCHAR FullName[MAX_PATH], *pDomain, *pServer;
|
|
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumPrinters Flags %x pName %x Level %d pPrinter %x cbBuf %d pcbNeeded %x pcReturned %x\n",
|
|
Flags, Name, Level, pPrinter, cbBuf, pcbNeeded, pcReturned ));
|
|
|
|
*pcReturned = 0;
|
|
*pcbNeeded = 0;
|
|
|
|
switch (Level) {
|
|
|
|
case STRESSINFOLEVEL:
|
|
pOffsets = PrinterInfoStressOffsets;
|
|
cbStruct = sizeof(PRINTER_INFO_STRESS);
|
|
break;
|
|
|
|
case 1:
|
|
pOffsets = PrinterInfo1Offsets;
|
|
cbStruct = sizeof(PRINTER_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pOffsets = PrinterInfo2Offsets;
|
|
cbStruct = sizeof(PRINTER_INFO_2);
|
|
break;
|
|
|
|
case 4:
|
|
|
|
//
|
|
// There are no local printers in win32spl, and connections
|
|
// are handled by the router.
|
|
//
|
|
return TRUE;
|
|
|
|
case 5:
|
|
pOffsets = PrinterInfo5Offsets;
|
|
cbStruct = sizeof(PRINTER_INFO_5);
|
|
break;
|
|
|
|
default:
|
|
SetLastError( ERROR_INVALID_LEVEL );
|
|
DBGMSG( DBG_TRACE, ("EnumPrinters failed ERROR_INVALID_LEVEL\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
if ( Flags & PRINTER_ENUM_NAME ) {
|
|
|
|
if (!Name && (Level == 1)) {
|
|
|
|
LPWSTR SourceStrings[sizeof(PRINTER_INFO_1)/sizeof(LPWSTR)];
|
|
LPWSTR *pSourceStrings=SourceStrings;
|
|
|
|
cb = wcslen(szPrintProvidorName)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
wcslen(szPrintProvidorDescription)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
wcslen(szPrintProvidorComment)*sizeof(WCHAR) + sizeof(WCHAR) +
|
|
sizeof(PRINTER_INFO_1);
|
|
|
|
*pcbNeeded=cb;
|
|
|
|
if ( cb > cbBuf ) {
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
DBGMSG( DBG_TRACE, ("EnumPrinters returns ERROR_INSUFFICIENT_BUFFER\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
*pcReturned = 1;
|
|
|
|
pPrinter1->Flags = PRINTER_ENUM_CONTAINER |
|
|
PRINTER_ENUM_ICON1 |
|
|
PRINTER_ENUM_EXPAND;
|
|
|
|
*pSourceStrings++=szPrintProvidorDescription;
|
|
*pSourceStrings++=szPrintProvidorName;
|
|
*pSourceStrings++=szPrintProvidorComment;
|
|
|
|
PackStrings( SourceStrings, pPrinter, PrinterInfo1Strings,
|
|
pPrinter+cbBuf );
|
|
|
|
DBGMSG( DBG_TRACE, ("EnumPrinters returns Success just Provider Info\n"));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if (Name && *Name && (Level == 1)) {
|
|
|
|
wcscpy(FullName, Name);
|
|
|
|
pServer = NULL;
|
|
|
|
pDomain = wcschr(FullName, L'!');
|
|
|
|
if (pDomain) {
|
|
|
|
*pDomain++=0;
|
|
|
|
pServer = wcschr(pDomain, L'!');
|
|
|
|
if (pServer)
|
|
*pServer++=0;
|
|
}
|
|
|
|
if (!lstrcmpi(FullName, szPrintProvidorName)) {
|
|
|
|
if (!pServer && !pDomain)
|
|
|
|
return EnumerateDomains((PRINTER_INFO_1 *)pPrinter,
|
|
cbBuf, pcbNeeded,
|
|
pcReturned, pPrinter+cbBuf);
|
|
else if (!pServer)
|
|
|
|
return EnumerateDomainPrinters(pDomain,
|
|
Level, cbStruct,
|
|
pOffsets, pPrinter, cbBuf,
|
|
pcbNeeded, pcReturned);
|
|
else
|
|
|
|
return EnumeratePrintShares(pDomain, pServer, Level,
|
|
cbStruct, pOffsets, pPrinter,
|
|
cbBuf, pcbNeeded, pcReturned);
|
|
}
|
|
}
|
|
|
|
if ( !VALIDATE_NAME(Name) || MyUNCName(Name)) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pPrinter)
|
|
memset(pPrinter, 0, cbBuf);
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (rc = RpcValidate()) ||
|
|
(rc = RpcEnumPrinters(Flags,
|
|
Name,
|
|
Level, pPrinter,
|
|
cbBuf, pcbNeeded,
|
|
pcReturned)) ) {
|
|
|
|
SetLastError(rc);
|
|
// ReturnValue = FALSE;
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
DBGMSG( DBG_TRACE, ( "Failed to connect to Print Server%ws\n", Name ) );
|
|
|
|
*pcbNeeded = 0;
|
|
*pcReturned = 0;
|
|
SetLastError(RpcExceptionCode());
|
|
// ReturnValue = FALSE;
|
|
return FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
i = *pcReturned;
|
|
|
|
|
|
while (i--) {
|
|
|
|
MarshallUpStructure(pPrinter, pOffsets);
|
|
|
|
if (Level == 2) {
|
|
((PPRINTER_INFO_2)pPrinter)->Attributes |=
|
|
PRINTER_ATTRIBUTE_NETWORK;
|
|
((PPRINTER_INFO_2)pPrinter)->Attributes &=
|
|
~PRINTER_ATTRIBUTE_LOCAL;
|
|
}
|
|
|
|
if (Level == 5) {
|
|
((PPRINTER_INFO_5)pPrinter)->Attributes |=
|
|
PRINTER_ATTRIBUTE_NETWORK;
|
|
((PPRINTER_INFO_5)pPrinter)->Attributes &=
|
|
~PRINTER_ATTRIBUTE_LOCAL;
|
|
}
|
|
pPrinter += cbStruct;
|
|
}
|
|
|
|
} else if (Flags & PRINTER_ENUM_REMOTE) {
|
|
|
|
if (Level != 1) {
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = EnumerateDomainPrinters(NULL, Level,
|
|
cbStruct, pOffsets,
|
|
pPrinter, cbBuf,
|
|
pcbNeeded, pcReturned);
|
|
}
|
|
|
|
} else if (Flags & PRINTER_ENUM_CONNECTIONS) {
|
|
|
|
ReturnValue = EnumerateFavouritePrinters(NULL, Level,
|
|
cbStruct, pOffsets,
|
|
pPrinter, cbBuf,
|
|
pcbNeeded, pcReturned);
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
RemoteOpenPrinter(
|
|
LPWSTR pPrinterName,
|
|
LPHANDLE phPrinter,
|
|
LPPRINTER_DEFAULTS pDefault,
|
|
BOOL CallLMOpenPrinter
|
|
)
|
|
{
|
|
DWORD RpcReturnValue;
|
|
BOOL ReturnValue = FALSE;
|
|
DEVMODE_CONTAINER DevModeContainer;
|
|
SPLCLIENT_CONTAINER SplClientContainer;
|
|
SPLCLIENT_INFO_1 SplClientInfo;
|
|
HANDLE hPrinter;
|
|
PWSPOOL pSpool;
|
|
DWORD Status = 0;
|
|
DWORD RpcError = 0;
|
|
DWORD dwIndex;
|
|
WCHAR UserName[MAX_PATH+1];
|
|
HANDLE hSplPrinter, hIniSpooler, hDevModeChgInfo;
|
|
|
|
if (!VALIDATE_NAME(pPrinterName)) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pDefault && pDefault->pDevMode) {
|
|
|
|
DevModeContainer.cbBuf = pDefault->pDevMode->dmSize +
|
|
pDefault->pDevMode->dmDriverExtra;
|
|
DevModeContainer.pDevMode = (LPBYTE)pDefault->pDevMode;
|
|
|
|
} else {
|
|
|
|
DevModeContainer.cbBuf = 0;
|
|
DevModeContainer.pDevMode = NULL;
|
|
}
|
|
|
|
|
|
if ( CallLMOpenPrinter ) {
|
|
|
|
//
|
|
// Now check if we have an entry in the
|
|
// downlevel cache. We don't want to hit the wire, search the whole net
|
|
// and fail if we know that the printer is LM. if the printer is LM
|
|
// try and succeed
|
|
//
|
|
|
|
EnterSplSem();
|
|
|
|
dwIndex = FindEntryinWin32LMCache(pPrinterName);
|
|
|
|
LeaveSplSem();
|
|
|
|
if (dwIndex != -1) {
|
|
ReturnValue = LMOpenPrinter(pPrinterName, phPrinter, pDefault);
|
|
if (ReturnValue) {
|
|
return TRUE ;
|
|
}
|
|
//
|
|
// Delete Entry in Cache
|
|
|
|
EnterSplSem();
|
|
DeleteEntryfromWin32LMCache(pPrinterName);
|
|
LeaveSplSem();
|
|
}
|
|
}
|
|
|
|
CopyMemory((LPBYTE)&SplClientInfo,
|
|
(LPBYTE)&gSplClientInfo1,
|
|
sizeof(SplClientInfo));
|
|
|
|
dwIndex = sizeof(UserName)/sizeof(UserName[0]) - 1;
|
|
if ( !GetUserName(UserName, &dwIndex) ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
SplClientInfo.pUserName = UserName;
|
|
SplClientContainer.ClientInfo.pClientInfo1 = &SplClientInfo;
|
|
SplClientContainer.Level = 1;
|
|
|
|
RpcTryExcept {
|
|
|
|
EnterSplSem();
|
|
pSpool = AllocWSpool();
|
|
LeaveSplSem();
|
|
|
|
if ( pSpool != NULL ) {
|
|
|
|
pSpool->pName = AllocSplStr( pPrinterName );
|
|
|
|
if ( pSpool->pName != NULL ) {
|
|
|
|
pSpool->Status = Status;
|
|
|
|
if ( CopypDefaultTopSpool( pSpool, pDefault ) ) {
|
|
|
|
|
|
RpcReturnValue = RpcValidate();
|
|
if ( RpcReturnValue == ERROR_SUCCESS )
|
|
RpcReturnValue = RpcOpenPrinterEx(
|
|
pPrinterName,
|
|
&hPrinter,
|
|
pDefault ? pDefault->pDatatype
|
|
: NULL,
|
|
&DevModeContainer,
|
|
pDefault ? pDefault->DesiredAccess
|
|
: 0,
|
|
&SplClientContainer);
|
|
|
|
if (RpcReturnValue) {
|
|
|
|
SetLastError(RpcReturnValue);
|
|
|
|
} else {
|
|
|
|
pSpool->RpcHandle = hPrinter;
|
|
*phPrinter = (HANDLE)pSpool;
|
|
ReturnValue = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
RpcError = RpcExceptionCode();
|
|
} RpcEndExcept;
|
|
|
|
if ( RpcError == RPC_S_PROCNUM_OUT_OF_RANGE ) {
|
|
|
|
RpcError = 0;
|
|
|
|
if ( pDefault && pDefault->pDevMode ) {
|
|
|
|
DevModeContainer.cbBuf = 0;
|
|
DevModeContainer.pDevMode = NULL;
|
|
|
|
if ( OpenCachePrinterOnly(pPrinterName, &hPrinter,
|
|
&hIniSpooler, NULL) ) {
|
|
|
|
hDevModeChgInfo = LoadDriverFiletoConvertDevmodeFromPSpool(hPrinter);
|
|
if ( hDevModeChgInfo ) {
|
|
|
|
(VOID)CallDrvDevModeConversion(hDevModeChgInfo,
|
|
pPrinterName,
|
|
(LPBYTE)pDefault->pDevMode,
|
|
&DevModeContainer.pDevMode,
|
|
&DevModeContainer.cbBuf,
|
|
CDM_CONVERT351,
|
|
TRUE);
|
|
|
|
UnloadDriverFile(hDevModeChgInfo);
|
|
}
|
|
|
|
CacheClosePrinter(hPrinter);
|
|
}
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
RpcReturnValue = RpcOpenPrinter(pPrinterName,
|
|
&hPrinter,
|
|
pDefault ? pDefault->pDatatype
|
|
: NULL,
|
|
&DevModeContainer,
|
|
pDefault ? pDefault->DesiredAccess
|
|
: 0);
|
|
|
|
if (RpcReturnValue) {
|
|
|
|
SetLastError(RpcReturnValue);
|
|
} else {
|
|
|
|
pSpool->RpcHandle = hPrinter;
|
|
pSpool->bNt3xServer = TRUE;
|
|
*phPrinter = (HANDLE)pSpool;
|
|
ReturnValue = TRUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
RpcError = RpcExceptionCode();
|
|
DBGMSG(DBG_WARNING,("RpcOpenPrinter exception %d\n", RpcError));
|
|
} RpcEndExcept;
|
|
}
|
|
|
|
if ( RpcError ) {
|
|
|
|
SetLastError(RpcError);
|
|
}
|
|
|
|
if ( ReturnValue == FALSE && pSpool != NULL ) {
|
|
|
|
EnterSplSem();
|
|
FreepSpool( pSpool );
|
|
LeaveSplSem();
|
|
}
|
|
|
|
if ( (RpcError == RPC_S_SERVER_UNAVAILABLE) && CallLMOpenPrinter ) {
|
|
|
|
ReturnValue = LMOpenPrinter(pPrinterName, phPrinter, pDefault);
|
|
|
|
if (ReturnValue) {
|
|
|
|
EnterSplSem();
|
|
AddEntrytoWin32LMCache(pPrinterName);
|
|
LeaveSplSem();
|
|
}
|
|
}
|
|
|
|
if ( !ReturnValue ) {
|
|
|
|
DBGMSG(DBG_TRACE,
|
|
("RemoteOpenPrinter %ws failed %d\n",
|
|
pPrinterName, GetLastError() ));
|
|
|
|
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( DevModeContainer.pDevMode &&
|
|
DevModeContainer.pDevMode != (LPBYTE)pDefault->pDevMode ) {
|
|
|
|
FreeSplMem(DevModeContainer.pDevMode);
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
|
|
BOOL PrinterConnectionExists(
|
|
LPWSTR pPrinterName
|
|
)
|
|
{
|
|
HKEY hClientKey = NULL;
|
|
HKEY hKeyConnections=NULL;
|
|
HKEY hKeyPrinter=NULL;
|
|
WCHAR PrinterConnection[ MAX_UNC_PRINTER_NAME ];
|
|
LPWSTR pKeyName;
|
|
BOOL ConnectionFound = FALSE;
|
|
DWORD Status;
|
|
|
|
hClientKey = GetClientUserHandle(KEY_READ);
|
|
|
|
if (hClientKey) {
|
|
|
|
Status = RegOpenKeyEx(hClientKey, szRegistryConnections, 0,
|
|
KEY_READ, &hKeyConnections);
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
|
|
pKeyName = FormatPrinterForRegistryKey( pPrinterName, PrinterConnection );
|
|
|
|
if ( RegOpenKeyEx(hKeyConnections, pKeyName,
|
|
REG_OPTION_RESERVED, KEY_READ, &hKeyPrinter)
|
|
== ERROR_SUCCESS) {
|
|
|
|
RegCloseKey(hKeyPrinter);
|
|
ConnectionFound = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hKeyConnections);
|
|
|
|
} else {
|
|
|
|
DBGMSG(DBG_WARNING, ("RegOpenKeyEx failed: %ws Error %d\n", szRegistryConnections ,Status));
|
|
}
|
|
|
|
RegCloseKey(hClientKey);
|
|
|
|
}
|
|
|
|
return ConnectionFound;
|
|
}
|
|
|
|
|
|
BOOL
|
|
RemoteResetPrinter(
|
|
HANDLE hPrinter,
|
|
LPPRINTER_DEFAULTS pDefault
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DEVMODE_CONTAINER DevModeContainer;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
DBGMSG(DBG_TRACE, ("ResetPrinter\n"));
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pDefault && pDefault->pDevMode)
|
|
{
|
|
DevModeContainer.cbBuf = pDefault->pDevMode->dmSize +
|
|
pDefault->pDevMode->dmDriverExtra;
|
|
DevModeContainer.pDevMode = (LPBYTE)pDefault->pDevMode;
|
|
}
|
|
else
|
|
{
|
|
DevModeContainer.cbBuf = 0;
|
|
DevModeContainer.pDevMode = NULL;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( ReturnValue = RpcResetPrinter(pSpool->RpcHandle,
|
|
pDefault ? pDefault->pDatatype : NULL,
|
|
&DevModeContainer) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
SetJob(
|
|
HANDLE hPrinter,
|
|
DWORD JobId,
|
|
DWORD Level,
|
|
LPBYTE pJob,
|
|
DWORD Command
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
GENERIC_CONTAINER GenericContainer;
|
|
GENERIC_CONTAINER *pGenericContainer;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (pJob) {
|
|
|
|
GenericContainer.Level = Level;
|
|
GenericContainer.pData = pJob;
|
|
pGenericContainer = &GenericContainer;
|
|
|
|
} else
|
|
|
|
pGenericContainer = NULL;
|
|
|
|
//
|
|
// JOB_CONTROL_DELETE was added in NT 4.0
|
|
//
|
|
if ( pSpool->bNt3xServer && Command == JOB_CONTROL_DELETE )
|
|
Command = JOB_CONTROL_CANCEL;
|
|
|
|
if ( ReturnValue = RpcSetJob(pSpool->RpcHandle, JobId,
|
|
(JOB_CONTAINER *)pGenericContainer,
|
|
Command) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMSetJob(hPrinter, JobId, Level, pJob, Command);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
GetJob(
|
|
HANDLE hPrinter,
|
|
DWORD JobId,
|
|
DWORD Level,
|
|
LPBYTE pJob,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD *pOffsets;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = JobInfo1Offsets;
|
|
break;
|
|
|
|
case 2:
|
|
pOffsets = JobInfo2Offsets;
|
|
break;
|
|
|
|
case 3:
|
|
pOffsets = JobInfo3Offsets;
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if (pJob)
|
|
memset(pJob, 0, cbBuf);
|
|
|
|
if ( ReturnValue = RpcGetJob(pSpool->RpcHandle, JobId, Level, pJob,
|
|
cbBuf, pcbNeeded) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
if (pJob)
|
|
MarshallUpStructure(pJob, pOffsets);
|
|
|
|
ReturnValue = TRUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
|
|
//
|
|
// This will be thrown by the server if a cbBuf > 1 Meg is
|
|
// passed across the wire.
|
|
//
|
|
SPLASSERT( GetLastError() != ERROR_INVALID_USER_BUFFER );
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMGetJob(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
EnumJobs(
|
|
HANDLE hPrinter,
|
|
DWORD FirstJob,
|
|
DWORD NoJobs,
|
|
DWORD Level,
|
|
LPBYTE pJob,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD i, cbStruct, *pOffsets;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = JobInfo1Offsets;
|
|
cbStruct = sizeof(JOB_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pOffsets = JobInfo2Offsets;
|
|
cbStruct = sizeof(JOB_INFO_2);
|
|
break;
|
|
|
|
case 3:
|
|
pOffsets = JobInfo3Offsets;
|
|
cbStruct = sizeof(JOB_INFO_3);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if (pJob)
|
|
memset(pJob, 0, cbBuf);
|
|
|
|
if (ReturnValue = RpcEnumJobs(pSpool->RpcHandle, FirstJob, NoJobs, Level, pJob,
|
|
cbBuf, pcbNeeded, pcReturned) ) {
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
i=*pcReturned;
|
|
|
|
while (i--) {
|
|
|
|
MarshallUpStructure(pJob, pOffsets);
|
|
pJob += cbStruct;;
|
|
}
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMEnumJobs(hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf,
|
|
pcbNeeded, pcReturned);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
HANDLE
|
|
AddPrinter(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
LPBYTE pPrinter
|
|
)
|
|
{
|
|
DWORD ReturnValue;
|
|
PRINTER_CONTAINER PrinterContainer;
|
|
DEVMODE_CONTAINER DevModeContainer;
|
|
SECURITY_CONTAINER SecurityContainer;
|
|
HANDLE hPrinter = INVALID_HANDLE_VALUE;
|
|
PWSPOOL pSpool = NULL;
|
|
PWSTR pScratchBuffer = NULL;
|
|
PWSTR pCopyPrinterName = NULL;
|
|
SPLCLIENT_CONTAINER SplClientContainer;
|
|
SPLCLIENT_INFO_1 SplClientInfo;
|
|
WCHAR UserName[MAX_PATH+1];
|
|
DWORD dwRpcError = 0;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
CopyMemory((LPBYTE)&SplClientInfo,
|
|
(LPBYTE)&gSplClientInfo1,
|
|
sizeof(SplClientInfo));
|
|
|
|
//
|
|
// Don't pass in user name for browsing level because this
|
|
// causes LSA to chew up a lot of CPU. This isn't needed anyway
|
|
// because an AddPrinter( LEVEL_1 ) call never returns a print
|
|
// handle.
|
|
//
|
|
if( Level == 1 ){
|
|
|
|
UserName[0] = 0;
|
|
|
|
} else {
|
|
|
|
DWORD dwSize = sizeof(UserName)/sizeof(UserName[0]) - 1;
|
|
|
|
if ( !GetUserName(UserName, &dwSize) ) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
PrinterContainer.Level = Level;
|
|
PrinterContainer.PrinterInfo.pPrinterInfo1 = (PPRINTER_INFO_1)pPrinter;
|
|
|
|
SplClientInfo.pUserName = UserName;
|
|
SplClientContainer.Level = 1;
|
|
SplClientContainer.ClientInfo.pClientInfo1 = &SplClientInfo;
|
|
|
|
if (Level == 2) {
|
|
|
|
PPRINTER_INFO_2 pPrinterInfo = (PPRINTER_INFO_2)pPrinter;
|
|
|
|
if (pPrinterInfo->pDevMode) {
|
|
|
|
DevModeContainer.cbBuf = pPrinterInfo->pDevMode->dmSize +
|
|
pPrinterInfo->pDevMode->dmDriverExtra;
|
|
DevModeContainer.pDevMode = (LPBYTE)pPrinterInfo->pDevMode;
|
|
|
|
} else {
|
|
|
|
DevModeContainer.cbBuf = 0;
|
|
DevModeContainer.pDevMode = NULL;
|
|
}
|
|
|
|
if (pPrinterInfo->pSecurityDescriptor) {
|
|
|
|
SecurityContainer.cbBuf = GetSecurityDescriptorLength(pPrinterInfo->pSecurityDescriptor);
|
|
SecurityContainer.pSecurity = pPrinterInfo->pSecurityDescriptor;
|
|
|
|
} else {
|
|
|
|
SecurityContainer.cbBuf = 0;
|
|
SecurityContainer.pSecurity = NULL;
|
|
}
|
|
|
|
if (!pPrinterInfo->pPrinterName) {
|
|
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
if ( pScratchBuffer = AllocSplMem( MAX_UNC_PRINTER_NAME )) {
|
|
|
|
wsprintf( pScratchBuffer, L"%ws\\%ws", pName, pPrinterInfo->pPrinterName );
|
|
pCopyPrinterName = AllocSplStr( pScratchBuffer );
|
|
FreeSplMem( pScratchBuffer );
|
|
}
|
|
|
|
} else {
|
|
|
|
DevModeContainer.cbBuf = 0;
|
|
DevModeContainer.pDevMode = NULL;
|
|
|
|
SecurityContainer.cbBuf = 0;
|
|
SecurityContainer.pSecurity = NULL;
|
|
}
|
|
|
|
EnterSplSem();
|
|
|
|
|
|
pSpool = AllocWSpool();
|
|
|
|
LeaveSplSem();
|
|
|
|
if ( pSpool != NULL ) {
|
|
|
|
pSpool->pName = pCopyPrinterName;
|
|
|
|
pCopyPrinterName = NULL;
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcAddPrinterEx(pName,
|
|
(PPRINTER_CONTAINER)&PrinterContainer,
|
|
(PDEVMODE_CONTAINER)&DevModeContainer,
|
|
(PSECURITY_CONTAINER)&SecurityContainer,
|
|
&SplClientContainer,
|
|
&hPrinter)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
hPrinter = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
dwRpcError = RpcExceptionCode();
|
|
|
|
} RpcEndExcept
|
|
|
|
if ( dwRpcError == RPC_S_PROCNUM_OUT_OF_RANGE ) {
|
|
|
|
dwRpcError = ERROR_SUCCESS;
|
|
RpcTryExcept {
|
|
|
|
if ( ReturnValue = RpcAddPrinter
|
|
(pName,
|
|
(PPRINTER_CONTAINER)&PrinterContainer,
|
|
(PDEVMODE_CONTAINER)&DevModeContainer,
|
|
(PSECURITY_CONTAINER)&SecurityContainer,
|
|
&hPrinter) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
hPrinter = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
dwRpcError = RpcExceptionCode();
|
|
|
|
} RpcEndExcept
|
|
|
|
}
|
|
|
|
if ( dwRpcError ) {
|
|
|
|
SetLastError(dwRpcError);
|
|
hPrinter = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
|
|
EnterSplSem();
|
|
|
|
if ( hPrinter != INVALID_HANDLE_VALUE ) {
|
|
|
|
pSpool->RpcHandle = hPrinter;
|
|
|
|
} else {
|
|
|
|
FreepSpool( pSpool );
|
|
pSpool = NULL;
|
|
|
|
}
|
|
|
|
LeaveSplSem();
|
|
|
|
|
|
} else {
|
|
|
|
// Failed to allocate Printer Handle
|
|
|
|
FreeSplStr( pCopyPrinterName );
|
|
}
|
|
|
|
SplOutSem();
|
|
|
|
return (HANDLE)pSpool;
|
|
}
|
|
|
|
BOOL
|
|
DeletePrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( ReturnValue = RpcDeletePrinter(pSpool->RpcHandle) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
ReturnValue = FALSE;
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
|
|
/* SavePrinterConnectionInRegistry
|
|
*
|
|
* Saves data in the registry for a printer connection.
|
|
* Creates a key under the current impersonation client's key
|
|
* in the registry under \Printers\Connections.
|
|
* The printer name is stripped of backslashes, since the registry
|
|
* API does not permit the creation of keys with backslashes.
|
|
* They are replaced by commas, which are invalid characters
|
|
* in printer names, so we should never get one passed in.
|
|
*
|
|
*
|
|
* *** WARNING ***
|
|
*
|
|
* IF YOU MAKE CHANGES TO THE LOCATION IN THE REGISTRY
|
|
* WHERE PRINTER CONNECTIONS ARE STORED, YOU MUST MAKE
|
|
* CORRESPONDING CHANGES IN USER\USERINIT\USERINIT.C.
|
|
*
|
|
*/
|
|
BOOL
|
|
SavePrinterConnectionInRegistry(
|
|
LPWSTR pRealName,
|
|
LPBYTE pDriverInfo,
|
|
DWORD dwLevel
|
|
)
|
|
{
|
|
TCHAR string[ MAX_UNC_PRINTER_NAME ];
|
|
HKEY hClientKey = NULL;
|
|
HKEY hConnectionsKey;
|
|
HKEY hPrinterKey;
|
|
LPWSTR pKeyName = NULL;
|
|
LPWSTR pData;
|
|
DWORD Status = NO_ERROR;
|
|
BOOL rc = TRUE;
|
|
LPDRIVER_INFO_2 pDriverInfo2 = (LPDRIVER_INFO_2) pDriverInfo;
|
|
LPDRIVER_INFO_3 pDriverInfo3 = (LPDRIVER_INFO_3) pDriverInfo;
|
|
|
|
hClientKey = GetClientUserHandle(KEY_READ);
|
|
|
|
if ( hClientKey == NULL ) {
|
|
|
|
DBGMSG( DBG_WARNING, ("SavePrinterConnectionInRegistry failed %d\n", GetLastError() ));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
Status = RegCreateKeyEx( hClientKey, szRegistryConnections,
|
|
REG_OPTION_RESERVED, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE, NULL, &hConnectionsKey, NULL );
|
|
|
|
if (Status == NO_ERROR) {
|
|
|
|
pKeyName = FormatPrinterForRegistryKey( pRealName, string );
|
|
|
|
Status = RegCreateKeyEx( hConnectionsKey, pKeyName, REG_OPTION_RESERVED,
|
|
NULL, 0, KEY_WRITE, NULL, &hPrinterKey, NULL);
|
|
|
|
if (Status == NO_ERROR) {
|
|
|
|
switch ( dwLevel ) {
|
|
|
|
case 2:
|
|
if (!SET_REG_VAL_DWORD(hPrinterKey, szVersion, pDriverInfo2->cVersion))
|
|
rc = FALSE;
|
|
|
|
if (!SET_REG_VAL_SZ(hPrinterKey, szName, pDriverInfo2->pName))
|
|
rc = FALSE;
|
|
|
|
// Note - None of the following values are required for NT 3.51 release or there after.
|
|
// We continue to write them incase someone has floating profiles and thus
|
|
// needs this stuff on 3.5 - 3.1 Daytona or before machine.
|
|
// Consider removing it in CAIRO ie assume that everyone has upgraded to 3.51 release
|
|
|
|
// Now write the driver files minus path:
|
|
|
|
if (!(pData = wcsrchr(pDriverInfo2->pConfigFile, '\\')))
|
|
pData = pDriverInfo2->pConfigFile;
|
|
else
|
|
pData++;
|
|
|
|
if (!SET_REG_VAL_SZ(hPrinterKey, szConfigurationFile, pData))
|
|
rc = FALSE;
|
|
|
|
if (!(pData = wcsrchr(pDriverInfo2->pDataFile, '\\')))
|
|
pData = pDriverInfo2->pDataFile;
|
|
else
|
|
pData++;
|
|
|
|
if (!SET_REG_VAL_SZ(hPrinterKey, szDataFile, pData))
|
|
rc = FALSE;
|
|
|
|
if (!(pData = wcsrchr(pDriverInfo2->pDriverPath, '\\')))
|
|
pData = pDriverInfo2->pDriverPath;
|
|
else
|
|
pData++;
|
|
|
|
if (!SET_REG_VAL_SZ(hPrinterKey, szDriver, pData))
|
|
rc = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
|
if (!SET_REG_VAL_DWORD(hPrinterKey, szVersion, pDriverInfo3->cVersion))
|
|
rc = FALSE;
|
|
|
|
if (!SET_REG_VAL_SZ(hPrinterKey, szName, pDriverInfo3->pName))
|
|
rc = FALSE;
|
|
|
|
// Note - None of the following values are required for NT 3.51 release or there after.
|
|
// We continue to write them incase someone has floating profiles and thus
|
|
// needs this stuff on 3.5 - 3.1 Daytona or before machine.
|
|
// Consider removing it in CAIRO ie assume that everyone has upgraded to 3.51 release
|
|
|
|
// Now write the driver files minus path:
|
|
|
|
if (!(pData = wcsrchr(pDriverInfo3->pConfigFile, '\\')))
|
|
pData = pDriverInfo3->pConfigFile;
|
|
else
|
|
pData++;
|
|
|
|
if (!SET_REG_VAL_SZ(hPrinterKey, szConfigurationFile, pData))
|
|
rc = FALSE;
|
|
|
|
if (!(pData = wcsrchr(pDriverInfo3->pDataFile, '\\')))
|
|
pData = pDriverInfo3->pDataFile;
|
|
else
|
|
pData++;
|
|
|
|
if (!SET_REG_VAL_SZ(hPrinterKey, szDataFile, pData))
|
|
rc = FALSE;
|
|
|
|
if (!(pData = wcsrchr(pDriverInfo3->pDriverPath, '\\')))
|
|
pData = pDriverInfo3->pDriverPath;
|
|
else
|
|
pData++;
|
|
|
|
if (!SET_REG_VAL_SZ(hPrinterKey, szDriver, pData))
|
|
rc = FALSE;
|
|
|
|
break;
|
|
|
|
default:
|
|
DBGMSG(DBG_ERROR, ("SavePrinterConnectionInRegistry: invalid level %d", dwLevel));
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
rc = FALSE;
|
|
}
|
|
|
|
RegCloseKey(hPrinterKey);
|
|
|
|
} else {
|
|
|
|
DBGMSG(DBG_WARNING, ("RegCreateKeyEx(%ws) failed: Error %d\n",
|
|
pKeyName, Status ));
|
|
SetLastError( Status );
|
|
rc = FALSE;
|
|
}
|
|
|
|
// Now close the hConnectionsKey, we are done with it
|
|
|
|
RegCloseKey( hConnectionsKey );
|
|
|
|
} else {
|
|
|
|
DBGMSG( DBG_WARNING, ("RegCreateKeyEx(%ws) failed: Error %d\n",
|
|
szRegistryConnections, Status ));
|
|
SetLastError( Status );
|
|
rc = FALSE;
|
|
}
|
|
|
|
|
|
if (!rc) {
|
|
|
|
DBGMSG( DBG_WARNING, ("Error updating registry: %d\n",
|
|
GetLastError())); // This may not be the error
|
|
|
|
if ( pKeyName )
|
|
RegDeleteKey( hClientKey, pKeyName );
|
|
}
|
|
|
|
RegCloseKey( hClientKey );
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
DeletePrinterConnection(
|
|
LPWSTR pName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a printer connection (printer name or share name) that
|
|
belongs to win32spl.dll.
|
|
|
|
Note: The Router takes care of updating win.ini and per user connections
|
|
section based on returning True / False.
|
|
|
|
Arguments:
|
|
|
|
pName - Either a printer or share name.
|
|
|
|
Return Value:
|
|
|
|
TRUE - success, FALSE - fail. LastError set.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL bReturnValue = FALSE;
|
|
HKEY hClientKey = NULL;
|
|
HKEY hPrinterConnectionsKey = NULL;
|
|
DWORD i;
|
|
WCHAR szBuffer[MAX_UNC_PRINTER_NAME + 30]; // space for szRegistryConnections
|
|
DWORD cbBuffer;
|
|
PWCACHEINIPRINTEREXTRA pExtraData;
|
|
HANDLE hSplPrinter = NULL;
|
|
HANDLE hIniSpooler = NULL;
|
|
DWORD cRef;
|
|
|
|
WCHAR PrinterInfo1[ MAX_PRINTER_INFO1 ];
|
|
LPPRINTER_INFO_1W pPrinter1 = (LPPRINTER_INFO_1W)&PrinterInfo1;
|
|
|
|
LPWSTR pConnectionName = pName;
|
|
|
|
#if DBG
|
|
SetLastError( 0 );
|
|
#endif
|
|
|
|
try {
|
|
|
|
if ( !VALIDATE_NAME( pName ) ) {
|
|
SetLastError( ERROR_INVALID_NAME );
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// If the Printer is in the Cache then Decrement its connection
|
|
// reference count.
|
|
//
|
|
|
|
if( !OpenCachePrinterOnly( pName, &hSplPrinter, &hIniSpooler, NULL )){
|
|
|
|
DWORD dwLastError;
|
|
|
|
hSplPrinter = NULL;
|
|
hIniSpooler = NULL;
|
|
|
|
dwLastError = GetLastError();
|
|
|
|
if (( dwLastError != ERROR_INVALID_PRINTER_NAME ) &&
|
|
( dwLastError != ERROR_INVALID_NAME )) {
|
|
|
|
DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed OpenCachePrinterOnly %ws error %d\n", pName, dwLastError ));
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// Printer Is NOT in Cache,
|
|
//
|
|
// Continue to remove from HKEY_CURRENT_USER
|
|
// Can happen with Floating Profiles
|
|
//
|
|
|
|
} else {
|
|
|
|
//
|
|
// Printer is in Cache
|
|
// Support for DeletetPrinterConnection( \\server\share );
|
|
//
|
|
|
|
if( !SplGetPrinter( hSplPrinter,
|
|
1,
|
|
(LPBYTE)pPrinter1,
|
|
sizeof( PrinterInfo1),
|
|
&cbBuffer )){
|
|
|
|
DBGMSG( DBG_WARNING, ("DeletePrinterConenction failed SplGetPrinter %d hSplPrinter %x\n", GetLastError(), hSplPrinter ));
|
|
SPLASSERT( pConnectionName == pName );
|
|
|
|
} else {
|
|
pConnectionName = pPrinter1->pName;
|
|
}
|
|
|
|
//
|
|
// Update Connection Reference Count
|
|
//
|
|
|
|
EnterSplSem();
|
|
|
|
if( !SplGetPrinterExtra( hSplPrinter, &(DWORD)pExtraData )){
|
|
|
|
DBGMSG( DBG_WARNING,
|
|
("DeletePrinterConnection SplGetPrinterExtra pSplPrinter %x error %d\n",
|
|
hSplPrinter, GetLastError() ));
|
|
|
|
pExtraData = NULL;
|
|
}
|
|
|
|
if (( pExtraData != NULL ) &&
|
|
( pExtraData->cRef != 0 )) {
|
|
|
|
SPLASSERT( pExtraData->signature == WCIP_SIGNATURE );
|
|
|
|
pExtraData->cRef--;
|
|
cRef = pExtraData->cRef;
|
|
|
|
} else {
|
|
|
|
cRef = 0;
|
|
}
|
|
|
|
|
|
LeaveSplSem();
|
|
|
|
|
|
if ( cRef == 0 ) {
|
|
|
|
//
|
|
// Allow the Driver to do Per Cache Connection Cleanup
|
|
//
|
|
|
|
SplDriverEvent( pConnectionName, PRINTER_EVENT_CACHE_DELETE, (LPARAM)NULL );
|
|
|
|
//
|
|
// Remove Cache for this printer
|
|
//
|
|
|
|
if ( !SplDeletePrinter( hSplPrinter )) {
|
|
|
|
DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed SplDeletePrinter %d\n", GetLastError() ));
|
|
leave;
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( !SplSetPrinterExtra( hSplPrinter, (LPBYTE)pExtraData ) ) {
|
|
|
|
DBGMSG( DBG_ERROR, ("DeletePrinterConnection SplSetPrinterExtra failed %x\n", GetLastError() ));
|
|
leave;
|
|
}
|
|
}
|
|
|
|
SplOutSem();
|
|
}
|
|
|
|
//
|
|
// Note pConnectionName will either be the name passed in
|
|
// or if the Printer was in the Cache, would be the printer
|
|
// name from the cache.
|
|
// This will allow somone to call DeleteprinterConnection
|
|
// with a UNC Share name.
|
|
//
|
|
|
|
hClientKey = GetClientUserHandle(KEY_READ);
|
|
|
|
if ( hClientKey == NULL ) {
|
|
|
|
DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed %d\n", GetLastError() ));
|
|
leave;
|
|
}
|
|
|
|
|
|
wcscpy( szBuffer, szRegistryConnections );
|
|
|
|
i = wcslen(szBuffer);
|
|
szBuffer[i++] = L'\\';
|
|
|
|
FormatPrinterForRegistryKey( pConnectionName, szBuffer + i );
|
|
|
|
if( ERROR_SUCCESS != RegOpenKeyEx( hClientKey,
|
|
szBuffer,
|
|
0,
|
|
KEY_READ,
|
|
&hPrinterConnectionsKey )){
|
|
|
|
if ( pConnectionName == pName ) {
|
|
|
|
SetLastError( ERROR_INVALID_PRINTER_NAME );
|
|
leave;
|
|
}
|
|
|
|
//
|
|
// If we have a printer on the server whose sharename is the same
|
|
// as a previously deleted printers printername then CacheOpenPrinter
|
|
// would have succeded but you are not going to find the share name in
|
|
// the registry
|
|
//
|
|
FormatPrinterForRegistryKey( pName, szBuffer + i );
|
|
|
|
if ( ERROR_SUCCESS != RegOpenKeyEx(hClientKey,
|
|
szBuffer,
|
|
0,
|
|
KEY_READ,
|
|
&hPrinterConnectionsKey) ) {
|
|
|
|
SetLastError( ERROR_INVALID_PRINTER_NAME );
|
|
leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Common case is success, so set the return value here.
|
|
// Only if we fail will we set it to FALSE now.
|
|
//
|
|
bReturnValue = TRUE;
|
|
|
|
cbBuffer = sizeof(szBuffer);
|
|
|
|
//
|
|
// If there is a Provider value, and it doesn't match win32spl.dll,
|
|
// then fail the call.
|
|
//
|
|
// If the provider value isn't there, succeed for backward
|
|
// compatibility.
|
|
//
|
|
if( ERROR_SUCCESS == RegQueryValueEx( hPrinterConnectionsKey,
|
|
L"Provider",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szBuffer,
|
|
&cbBuffer) &&
|
|
_wcsicmp( szBuffer, L"win32spl.dll" )){
|
|
|
|
bReturnValue = FALSE;
|
|
SetLastError( ERROR_INVALID_PRINTER_NAME );
|
|
}
|
|
|
|
RegCloseKey( hPrinterConnectionsKey );
|
|
|
|
} finally {
|
|
|
|
if( hClientKey ){
|
|
RegCloseKey( hClientKey );
|
|
}
|
|
|
|
if( hSplPrinter ){
|
|
if (!SplClosePrinter( hSplPrinter )){
|
|
DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed to close hSplPrinter %x error %d\n", hSplPrinter, GetLastError() ));
|
|
}
|
|
}
|
|
|
|
if( hIniSpooler ){
|
|
if( !SplCloseSpooler( hIniSpooler )){
|
|
DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed to close hSplSpooler %x error %d\n", hIniSpooler, GetLastError() ));
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !bReturnValue ){
|
|
SPLASSERT( GetLastError( ));
|
|
}
|
|
|
|
return bReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
SetPrinter(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pPrinter,
|
|
DWORD Command
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PRINTER_CONTAINER PrinterContainer;
|
|
DEVMODE_CONTAINER DevModeContainer;
|
|
SECURITY_CONTAINER SecurityContainer;
|
|
PPRINTER_INFO_2 pPrinterInfo2;
|
|
PPRINTER_INFO_3 pPrinterInfo3;
|
|
PPRINTER_INFO_5 pPrinterInfo5;
|
|
PPRINTER_INFO_6 pPrinterInfo6;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
BOOL bNeedToFreeDevMode = FALSE;
|
|
HANDLE hDevModeChgInfo = NULL;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
if (pSpool->Type != SJ_WIN32HANDLE) {
|
|
|
|
return LMSetPrinter(hPrinter, Level, pPrinter, Command);
|
|
|
|
}
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
PrinterContainer.Level = Level;
|
|
PrinterContainer.PrinterInfo.pPrinterInfo1 = (PPRINTER_INFO_1)pPrinter;
|
|
|
|
DevModeContainer.cbBuf = 0;
|
|
DevModeContainer.pDevMode = NULL;
|
|
|
|
SecurityContainer.cbBuf = 0;
|
|
SecurityContainer.pSecurity = NULL;
|
|
|
|
switch (Level) {
|
|
|
|
case 0:
|
|
case 1:
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
pPrinterInfo2 = (PPRINTER_INFO_2)pPrinter;
|
|
|
|
if (pPrinterInfo2->pDevMode) {
|
|
|
|
if ( pSpool->bNt3xServer ) {
|
|
|
|
//
|
|
// If Nt 3xserver we will set devmode only if we can convert
|
|
//
|
|
if ( pSpool->Status & WSPOOL_STATUS_USE_CACHE ) {
|
|
|
|
hDevModeChgInfo = LoadDriverFiletoConvertDevmodeFromPSpool(pSpool->hSplPrinter);
|
|
if ( hDevModeChgInfo ) {
|
|
|
|
SPLASSERT( pSpool->pName != NULL );
|
|
|
|
if ( ERROR_SUCCESS == CallDrvDevModeConversion(
|
|
hDevModeChgInfo,
|
|
pSpool->pName,
|
|
(LPBYTE)pPrinterInfo2->pDevMode,
|
|
(LPBYTE *)&DevModeContainer.pDevMode,
|
|
&DevModeContainer.cbBuf,
|
|
CDM_CONVERT351,
|
|
TRUE) ) {
|
|
|
|
bNeedToFreeDevMode = TRUE;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
|
|
DevModeContainer.cbBuf = pPrinterInfo2->pDevMode->dmSize +
|
|
pPrinterInfo2->pDevMode->dmDriverExtra;
|
|
DevModeContainer.pDevMode = (LPBYTE)pPrinterInfo2->pDevMode;
|
|
}
|
|
|
|
}
|
|
|
|
if (pPrinterInfo2->pSecurityDescriptor) {
|
|
|
|
SecurityContainer.cbBuf = GetSecurityDescriptorLength(pPrinterInfo2->pSecurityDescriptor);
|
|
SecurityContainer.pSecurity = pPrinterInfo2->pSecurityDescriptor;
|
|
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
|
|
pPrinterInfo3 = (PPRINTER_INFO_3)pPrinter;
|
|
|
|
//
|
|
// If this is NULL, should we even rpc out?
|
|
//
|
|
|
|
if (pPrinterInfo3->pSecurityDescriptor) {
|
|
|
|
SecurityContainer.cbBuf = GetSecurityDescriptorLength(pPrinterInfo3->pSecurityDescriptor);
|
|
SecurityContainer.pSecurity = pPrinterInfo3->pSecurityDescriptor;
|
|
}
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
pPrinterInfo5 = (PPRINTER_INFO_5)pPrinter;
|
|
break;
|
|
|
|
case 6:
|
|
|
|
pPrinterInfo6 = (PPRINTER_INFO_6)pPrinter;
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( ReturnValue = RpcSetPrinter(pSpool->RpcHandle,
|
|
(PPRINTER_CONTAINER)&PrinterContainer,
|
|
(PDEVMODE_CONTAINER)&DevModeContainer,
|
|
(PSECURITY_CONTAINER)&SecurityContainer,
|
|
Command) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
//
|
|
// Make sure Forms Cache is consistent
|
|
//
|
|
|
|
|
|
if ( ReturnValue ) {
|
|
|
|
ConsistencyCheckCache( pSpool );
|
|
}
|
|
|
|
if ( bNeedToFreeDevMode )
|
|
FreeSplMem(DevModeContainer.pDevMode);
|
|
|
|
if ( hDevModeChgInfo )
|
|
UnloadDriverFile(hDevModeChgInfo);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteGetPrinter(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pPrinter,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
{
|
|
BOOL ReturnValue=FALSE;
|
|
DWORD *pOffsets;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
LPBYTE pNewPrinter = NULL;
|
|
DWORD dwNewSize;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
switch (Level) {
|
|
|
|
case STRESSINFOLEVEL:
|
|
pOffsets = PrinterInfoStressOffsets;
|
|
break;
|
|
|
|
case 1:
|
|
pOffsets = PrinterInfo1Offsets;
|
|
break;
|
|
|
|
case 2:
|
|
pOffsets = PrinterInfo2Offsets;
|
|
break;
|
|
|
|
case 3:
|
|
pOffsets = PrinterInfo3Offsets;
|
|
break;
|
|
|
|
case 5:
|
|
pOffsets = PrinterInfo5Offsets;
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pPrinter)
|
|
memset(pPrinter, 0, cbBuf);
|
|
|
|
//
|
|
// If going to different version and we have localspl handle want
|
|
// to do devmode conversion
|
|
//
|
|
if ( Level == 2 &&
|
|
(pSpool->Status & WSPOOL_STATUS_USE_CACHE) ) {
|
|
|
|
dwNewSize = cbBuf + MAX_PRINTER_INFO2;
|
|
pNewPrinter = AllocSplMem(dwNewSize);
|
|
|
|
if ( !pNewPrinter )
|
|
goto Cleanup;
|
|
} else {
|
|
|
|
dwNewSize = cbBuf;
|
|
pNewPrinter = pPrinter;
|
|
}
|
|
|
|
do {
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( ReturnValue = RpcGetPrinter(pSpool->RpcHandle,
|
|
Level,
|
|
pNewPrinter,
|
|
dwNewSize,
|
|
pcbNeeded) ) {
|
|
|
|
if ( Level == 2 &&
|
|
pNewPrinter != pPrinter &&
|
|
ReturnValue == ERROR_INSUFFICIENT_BUFFER ) {
|
|
|
|
FreeSplMem(pNewPrinter);
|
|
|
|
dwNewSize = *pcbNeeded;
|
|
pNewPrinter = AllocSplMem(dwNewSize);
|
|
// do loop if pNewPrinter != NULL
|
|
} else {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
}
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
if (pNewPrinter) {
|
|
|
|
MarshallUpStructure(pNewPrinter, pOffsets);
|
|
|
|
if (Level == 2 ) {
|
|
|
|
//
|
|
// In the Cache && Different OS Level
|
|
//
|
|
|
|
if ( pNewPrinter != pPrinter ) {
|
|
|
|
SPLASSERT(pSpool->Status & WSPOOL_STATUS_USE_CACHE);
|
|
SPLASSERT(pSpool->pName != NULL );
|
|
|
|
ReturnValue = DoDevModeConversionAndBuildNewPrinterInfo2(
|
|
(LPPRINTER_INFO_2)pNewPrinter,
|
|
*pcbNeeded,
|
|
pPrinter,
|
|
cbBuf,
|
|
pcbNeeded,
|
|
pSpool);
|
|
}
|
|
|
|
if ( ReturnValue ) {
|
|
|
|
((PPRINTER_INFO_2)pPrinter)->Attributes |=
|
|
PRINTER_ATTRIBUTE_NETWORK;
|
|
((PPRINTER_INFO_2)pPrinter)->Attributes &=
|
|
~PRINTER_ATTRIBUTE_LOCAL;
|
|
}
|
|
}
|
|
|
|
if (Level == 5) {
|
|
((PPRINTER_INFO_5)pPrinter)->Attributes |=
|
|
PRINTER_ATTRIBUTE_NETWORK;
|
|
((PPRINTER_INFO_5)pPrinter)->Attributes &=
|
|
~PRINTER_ATTRIBUTE_LOCAL;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
|
|
//
|
|
// This will be thrown by the server if a cbBuf > 1 Meg is
|
|
// passed across the wire.
|
|
//
|
|
SPLASSERT( GetLastError() != ERROR_INVALID_USER_BUFFER );
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} while ( Level == 2 &&
|
|
ReturnValue == ERROR_INSUFFICIENT_BUFFER &&
|
|
pNewPrinter != pPrinter &&
|
|
pNewPrinter );
|
|
|
|
} else
|
|
|
|
return LMGetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
|
|
|
|
Cleanup:
|
|
|
|
if ( pNewPrinter != pPrinter )
|
|
FreeSplMem(pNewPrinter );
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteAddPrinterDriver(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
PBYTE pDriverInfo
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DRIVER_CONTAINER DriverContainer;
|
|
PDRIVER_INFO_2W pDriverInfo2 = (PDRIVER_INFO_2W) pDriverInfo;
|
|
PDRIVER_INFO_3W pDriverInfo3 = (PDRIVER_INFO_3W) pDriverInfo;
|
|
LPRPC_DRIVER_INFO_3W pRpcDriverInfo3 = NULL;
|
|
LPWSTR pStr;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// ClientSide should have set a default environment if one was not
|
|
// specified.
|
|
//
|
|
switch (Level) {
|
|
case 2:
|
|
SPLASSERT( ( pDriverInfo2->pEnvironment != NULL ) &&
|
|
(*pDriverInfo2->pEnvironment != L'\0') );
|
|
break;
|
|
|
|
case 3:
|
|
SPLASSERT( ( pDriverInfo3->pEnvironment != NULL ) &&
|
|
(*pDriverInfo3->pEnvironment != L'\0') );
|
|
break;
|
|
|
|
default:
|
|
DBGMSG(DBG_ERROR, ("RemoteAddPrinterDriver: invalid level %d", Level));
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
DriverContainer.Level = Level;
|
|
if ( Level == 2 ) {
|
|
|
|
DriverContainer.DriverInfo.Level2 = (DRIVER_INFO_2 *)pDriverInfo;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Level == 3
|
|
//
|
|
if( !( pRpcDriverInfo3 = AllocSplMem( sizeof( *pRpcDriverInfo3 )))) {
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
pRpcDriverInfo3->cVersion = pDriverInfo3->cVersion;
|
|
pRpcDriverInfo3->pName = pDriverInfo3->pName;
|
|
pRpcDriverInfo3->pEnvironment = pDriverInfo3->pEnvironment;
|
|
pRpcDriverInfo3->pDriverPath = pDriverInfo3->pDriverPath;
|
|
pRpcDriverInfo3->pDataFile = pDriverInfo3->pDataFile;
|
|
pRpcDriverInfo3->pConfigFile = pDriverInfo3->pConfigFile;
|
|
pRpcDriverInfo3->pHelpFile = pDriverInfo3->pHelpFile;
|
|
pRpcDriverInfo3->pDependentFiles = pDriverInfo3->pDependentFiles;
|
|
pRpcDriverInfo3->pMonitorName = pDriverInfo3->pMonitorName;
|
|
pRpcDriverInfo3->pDefaultDataType = pDriverInfo3->pDefaultDataType;
|
|
|
|
pStr = pRpcDriverInfo3->pDependentFiles;
|
|
if( pStr && *pStr ){
|
|
while ( *pStr ){
|
|
pStr += wcslen(pStr) + 1;
|
|
}
|
|
pRpcDriverInfo3->cchDependentFiles = pStr -
|
|
pDriverInfo3->pDependentFiles + 1;
|
|
} else {
|
|
pRpcDriverInfo3->cchDependentFiles = 0;
|
|
}
|
|
|
|
DriverContainer.DriverInfo.Level3 = pRpcDriverInfo3;
|
|
}
|
|
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcAddPrinterDriver(pName, &DriverContainer)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
if ( pRpcDriverInfo3 ) {
|
|
|
|
FreeSplMem(pRpcDriverInfo3);
|
|
}
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
EnumPrinterDrivers(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pDriverInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD i, cbStruct;
|
|
DWORD *pOffsets;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = DriverInfo1Offsets;
|
|
cbStruct = sizeof(DRIVER_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pOffsets = DriverInfo2Offsets;
|
|
cbStruct = sizeof(DRIVER_INFO_2);
|
|
break;
|
|
|
|
case 3:
|
|
pOffsets = DriverInfo3Offsets;
|
|
cbStruct = sizeof(DRIVER_INFO_3);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcEnumPrinterDrivers(pName, pEnvironment, Level,
|
|
pDriverInfo, cbBuf,
|
|
pcbNeeded, pcReturned)) ) {
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
if (pDriverInfo) {
|
|
|
|
i = *pcReturned;
|
|
|
|
while (i--) {
|
|
|
|
MarshallUpStructure(pDriverInfo, pOffsets);
|
|
|
|
pDriverInfo += cbStruct;
|
|
}
|
|
}
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteGetPrinterDriverDirectory(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pDriverDirectory,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcGetPrinterDriverDirectory(pName, pEnvironment,
|
|
Level,
|
|
pDriverDirectory,
|
|
cbBuf, pcbNeeded)) ) {
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
DeletePrinterDriver(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pDriverName
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcDeletePrinterDriver(pName,
|
|
pEnvironment,
|
|
pDriverName)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
AddPrintProcessor(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pPathName,
|
|
LPWSTR pPrintProcessorName
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcAddPrintProcessor(pName , pEnvironment,pPathName,
|
|
pPrintProcessorName)) ) {
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
EnumPrintProcessors(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pPrintProcessorInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD i, cbStruct;
|
|
DWORD *pOffsets;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = PrintProcessorInfo1Offsets;
|
|
cbStruct = sizeof(PRINTPROCESSOR_INFO_1);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcEnumPrintProcessors(pName, pEnvironment, Level,
|
|
pPrintProcessorInfo, cbBuf,
|
|
pcbNeeded, pcReturned)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
if (pPrintProcessorInfo) {
|
|
|
|
i = *pcReturned;
|
|
|
|
while (i--) {
|
|
|
|
MarshallUpStructure(pPrintProcessorInfo, pOffsets);
|
|
|
|
pPrintProcessorInfo += cbStruct;
|
|
}
|
|
}
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
EnumPrintProcessorDatatypes(
|
|
LPWSTR pName,
|
|
LPWSTR pPrintProcessorName,
|
|
DWORD Level,
|
|
LPBYTE pDatatypes,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD i, cbStruct;
|
|
DWORD *pOffsets;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = DatatypeInfo1Offsets;
|
|
cbStruct = sizeof(DATATYPES_INFO_1);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcEnumPrintProcessorDatatypes(pName,
|
|
pPrintProcessorName,
|
|
Level,
|
|
pDatatypes,
|
|
cbBuf,
|
|
pcbNeeded,
|
|
pcReturned)) ) {
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
if (pDatatypes) {
|
|
|
|
i = *pcReturned;
|
|
|
|
while (i--) {
|
|
|
|
MarshallUpStructure(pDatatypes, pOffsets);
|
|
|
|
pDatatypes += cbStruct;
|
|
}
|
|
}
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
GetPrintProcessorDirectory(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pPrintProcessorDirectory,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcGetPrintProcessorDirectory(pName, pEnvironment,
|
|
Level,
|
|
pPrintProcessorDirectory,
|
|
cbBuf, pcbNeeded)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
DWORD
|
|
StartDocPrinter(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pDocInfo
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
GENERIC_CONTAINER DocInfoContainer;
|
|
DWORD JobId;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
PDOC_INFO_1 pDocInfo1 = (PDOC_INFO_1)pDocInfo;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
|
|
if (Win32IsGoingToFile(pSpool, pDocInfo1->pOutputFile)) {
|
|
|
|
HANDLE hFile;
|
|
|
|
//
|
|
// !! BUGBUG / POLICY !!
|
|
//
|
|
// If no datatype is specified, and the default is non-raw,
|
|
// should we fail?
|
|
//
|
|
if( pDocInfo1 &&
|
|
pDocInfo1->pDatatype &&
|
|
!ValidRawDatatype( pDocInfo1->pDatatype )){
|
|
|
|
SetLastError( ERROR_INVALID_DATATYPE );
|
|
return FALSE;
|
|
}
|
|
|
|
pSpool->Status |= WSPOOL_STATUS_PRINT_FILE;
|
|
hFile = CreateFile( pDocInfo1->pOutputFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL );
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
return FALSE;
|
|
} else {
|
|
pSpool->hFile = hFile;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
DocInfoContainer.Level = Level;
|
|
DocInfoContainer.pData = pDocInfo;
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( ReturnValue = RpcStartDocPrinter(pSpool->RpcHandle,
|
|
(LPDOC_INFO_CONTAINER)&DocInfoContainer,
|
|
&JobId) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = JobId;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMStartDocPrinter(hPrinter, Level, pDocInfo);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
StartPagePrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
|
|
if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE) {
|
|
return TRUE;
|
|
}
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( ReturnValue = RpcStartPagePrinter(pSpool->RpcHandle) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMStartPagePrinter(hPrinter);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
WritePrinter(
|
|
HANDLE hPrinter,
|
|
LPVOID pBuf,
|
|
DWORD cbBuf,
|
|
LPDWORD pcWritten
|
|
)
|
|
{
|
|
BOOL ReturnValue=TRUE;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
*pcWritten = 0;
|
|
|
|
if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE) {
|
|
|
|
ReturnValue = WriteFile(pSpool->hFile, pBuf, cbBuf, pcWritten, NULL);
|
|
return ReturnValue;
|
|
|
|
}
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
// Note this code used chop the request into 4k chunks which were
|
|
// the prefered size for Rpc. However the client dll batches all
|
|
// data into 4k chunks so no need to duplcate that code here.
|
|
|
|
if (ReturnValue = RpcWritePrinter(pSpool->RpcHandle, pBuf, cbBuf, pcWritten)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
|
|
} else {
|
|
|
|
return LMWritePrinter(hPrinter, pBuf, cbBuf, pcWritten);
|
|
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
EndPagePrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE) {
|
|
return TRUE;
|
|
}
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcEndPagePrinter(pSpool->RpcHandle)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMEndPagePrinter(hPrinter);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
AbortPrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcAbortPrinter(pSpool->RpcHandle)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMAbortPrinter(hPrinter);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
ReadPrinter(
|
|
HANDLE hPrinter,
|
|
LPVOID pBuf,
|
|
DWORD cbBuf,
|
|
LPDWORD pNoBytesRead
|
|
)
|
|
{
|
|
BOOL ReturnValue=TRUE;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
|
|
if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE ) {
|
|
return FALSE;
|
|
}
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcReadPrinter(pSpool->RpcHandle, pBuf, cbBuf, pNoBytesRead)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMReadPrinter(hPrinter, pBuf, cbBuf, pNoBytesRead);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteEndDocPrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE) {
|
|
CloseHandle( pSpool->hFile );
|
|
pSpool->hFile = INVALID_HANDLE_VALUE;
|
|
pSpool->Status &= ~WSPOOL_STATUS_PRINT_FILE;
|
|
return TRUE;
|
|
}
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcEndDocPrinter(pSpool->RpcHandle)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMEndDocPrinter(hPrinter);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
AddJob(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pData,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcAddJob(pSpool->RpcHandle, Level, pData,
|
|
cbBuf, pcbNeeded)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
MarshallUpStructure(pData, AddJobOffsets);
|
|
ReturnValue = TRUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMAddJob(hPrinter, Level, pData, cbBuf, pcbNeeded);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
ScheduleJob(
|
|
HANDLE hPrinter,
|
|
DWORD JobId
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcScheduleJob(pSpool->RpcHandle, JobId)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else
|
|
|
|
return LMScheduleJob(hPrinter, JobId);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
DWORD
|
|
RemoteGetPrinterData(
|
|
HANDLE hPrinter,
|
|
LPWSTR pValueName,
|
|
LPDWORD pType,
|
|
LPBYTE pData,
|
|
DWORD nSize,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
{
|
|
DWORD ReturnValue = 0;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
ReturnValue = RpcGetPrinterData(pSpool->RpcHandle, pValueName, pType,
|
|
pData, nSize, pcbNeeded);
|
|
|
|
} RpcExcept(1) {
|
|
|
|
ReturnValue = RpcExceptionCode();
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
ReturnValue = ERROR_INVALID_FUNCTION;
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
|
|
DWORD
|
|
RemoteEnumPrinterData(
|
|
HANDLE hPrinter,
|
|
DWORD dwIndex,
|
|
LPWSTR pValueName,
|
|
DWORD cbValueName,
|
|
LPDWORD pcbValueName,
|
|
LPDWORD pType,
|
|
LPBYTE pData,
|
|
DWORD cbData,
|
|
LPDWORD pcbData
|
|
)
|
|
{
|
|
DWORD ReturnValue = 0;
|
|
DWORD ReturnType = 0;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
// Downlevel variables
|
|
LPWSTR pKeyName = NULL;
|
|
PWCHAR pPrinterName = NULL;
|
|
PWCHAR pScratch = NULL;
|
|
PWCHAR pBuffer = NULL;
|
|
LPPRINTER_INFO_1W pPrinter1 = NULL;
|
|
PWCHAR pMachineName = NULL;
|
|
HKEY hkMachine = INVALID_HANDLE_VALUE;
|
|
HKEY hkDownlevel = INVALID_HANDLE_VALUE;
|
|
DWORD dwNeeded;
|
|
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
//
|
|
// The user should be able to pass in NULL for buffer, and
|
|
// 0 for size. However, the RPC interface specifies a ref pointer,
|
|
// so we must pass in a valid pointer. Pass in a pointer to
|
|
// a dummy pointer.
|
|
//
|
|
|
|
if (!pValueName && !cbValueName)
|
|
pValueName = (LPWSTR) &ReturnValue;
|
|
|
|
if( !pData && !cbData )
|
|
pData = (PBYTE)&ReturnValue;
|
|
|
|
if (!pType)
|
|
pType = (PDWORD) &ReturnType;
|
|
|
|
|
|
RpcTryExcept {
|
|
|
|
ReturnValue = RpcEnumPrinterData( pSpool->RpcHandle,
|
|
dwIndex,
|
|
pValueName,
|
|
cbValueName,
|
|
pcbValueName,
|
|
pType,
|
|
pData,
|
|
cbData,
|
|
pcbData
|
|
);
|
|
|
|
} RpcExcept(1) {
|
|
|
|
ReturnValue = RpcExceptionCode();
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
ReturnValue = ERROR_INVALID_FUNCTION;
|
|
}
|
|
|
|
// If the remote spooler doesn't support EnumPrinterData, do it the old way
|
|
if (ReturnValue == RPC_S_PROCNUM_OUT_OF_RANGE) {
|
|
|
|
|
|
pBuffer = AllocSplMem((wcslen(pszRemoteRegistryPrinters) + MAX_UNC_PRINTER_NAME)*sizeof(WCHAR));
|
|
pScratch = AllocSplMem(MAX_UNC_PRINTER_NAME*sizeof(WCHAR));
|
|
pPrinter1 = AllocSplMem(MAX_PRINTER_INFO1);
|
|
|
|
if (pBuffer == NULL || pScratch == NULL || pPrinter1 == NULL) {
|
|
ReturnValue = GetLastError();
|
|
goto DownlevelDone;
|
|
}
|
|
|
|
SPLASSERT ( 0 == _wcsnicmp( pSpool->pName, L"\\\\", 2 ) ) ;
|
|
SPLASSERT ( pSpool->Status & WSPOOL_STATUS_USE_CACHE );
|
|
|
|
wcscpy( pBuffer, pSpool->pName);
|
|
pPrinterName = wcschr( pBuffer+2, L'\\' );
|
|
*pPrinterName = L'\0';
|
|
pMachineName = AllocSplStr( pBuffer );
|
|
|
|
if (pMachineName == NULL) {
|
|
ReturnValue = GetLastError();
|
|
goto DownlevelDone;
|
|
}
|
|
|
|
// We cannot use pSpool->pName since this might be the share name which will
|
|
// fail if we try to use it as a registry key on the remote machine
|
|
// Get the full friendly name from the cache
|
|
|
|
if ( !SplGetPrinter( pSpool->hSplPrinter, 1, (LPBYTE)pPrinter1, MAX_PRINTER_INFO1, &dwNeeded )) {
|
|
DBGMSG( DBG_ERROR, ("RemoteEnumPrinterData failed SplGetPrinter %d pSpool %x\n", GetLastError(), pSpool ));
|
|
ReturnValue = GetLastError();
|
|
goto DownlevelDone;
|
|
}
|
|
|
|
pPrinterName = wcschr( pPrinter1->pName+2, L'\\' );
|
|
|
|
if ( pPrinterName++ == NULL ) {
|
|
ReturnValue = ERROR_INVALID_PARAMETER;
|
|
goto DownlevelDone;
|
|
}
|
|
|
|
//
|
|
// Generate the Correct KeyName from the Printer Name
|
|
//
|
|
|
|
DBGMSG( DBG_TRACE,(" pSpool->pName %ws pPrinterName %ws\n", pSpool->pName, pPrinterName));
|
|
|
|
pKeyName = FormatPrinterForRegistryKey( pPrinterName, pScratch );
|
|
wsprintf( pBuffer, pszRemoteRegistryPrinters, pKeyName );
|
|
|
|
// Because there is no EnumPrinterData downlevel we are forced to open the remote registry
|
|
// for LocalSpl and use the registry RegEnumValue to read through the printer data
|
|
// values.
|
|
|
|
ReturnValue = RegConnectRegistry( pMachineName, HKEY_LOCAL_MACHINE, &hkMachine);
|
|
|
|
if (ReturnValue != ERROR_SUCCESS) {
|
|
DBGMSG( DBG_WARNING, ("RemoteEnumPrinterData RegConnectRegistry error %d\n",GetLastError()));
|
|
goto DownlevelDone;
|
|
}
|
|
|
|
ReturnValue = RegOpenKeyEx(hkMachine, pBuffer, 0, KEY_READ, &hkDownlevel);
|
|
|
|
if ( ReturnValue != ERROR_SUCCESS ) {
|
|
|
|
DBGMSG( DBG_WARNING, ("RemoteEnumPrinterData RegOpenKeyEx %ws error %d\n", pBuffer, ReturnValue ));
|
|
goto DownlevelDone;
|
|
}
|
|
|
|
// Get the max sizes
|
|
if (!cbValueName && !cbData) {
|
|
ReturnValue = RegQueryInfoKey( hkDownlevel, // Key
|
|
NULL, // lpClass
|
|
NULL, // lpcbClass
|
|
NULL, // lpReserved
|
|
NULL, // lpcSubKeys
|
|
NULL, // lpcbMaxSubKeyLen
|
|
NULL, // lpcbMaxClassLen
|
|
NULL, // lpcValues
|
|
pcbValueName, // lpcbMaxValueNameLen
|
|
pcbData, // lpcbMaxValueLen
|
|
NULL, // lpcbSecurityDescriptor
|
|
NULL // lpftLastWriteTime
|
|
);
|
|
|
|
*pcbValueName = (*pcbValueName + 1)*sizeof(WCHAR);
|
|
|
|
} else { // Do an enum
|
|
|
|
*pcbValueName = cbValueName/sizeof(WCHAR);
|
|
*pcbData = cbData;
|
|
ReturnValue = RegEnumValue( hkDownlevel,
|
|
dwIndex,
|
|
pValueName,
|
|
pcbValueName,
|
|
NULL,
|
|
pType,
|
|
pData,
|
|
pcbData
|
|
);
|
|
*pcbValueName = (*pcbValueName + 1)*sizeof(WCHAR);
|
|
}
|
|
|
|
DownlevelDone:
|
|
|
|
FreeSplMem(pBuffer);
|
|
FreeSplStr(pScratch);
|
|
FreeSplMem(pPrinter1);
|
|
FreeSplStr(pMachineName);
|
|
|
|
if (hkMachine != INVALID_HANDLE_VALUE)
|
|
RegCloseKey(hkMachine);
|
|
|
|
if (hkDownlevel != INVALID_HANDLE_VALUE)
|
|
RegCloseKey(hkDownlevel);
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
RemoteDeletePrinterData(
|
|
HANDLE hPrinter,
|
|
LPWSTR pValueName
|
|
)
|
|
{
|
|
DWORD ReturnValue = 0;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
ReturnValue = RpcDeletePrinterData(pSpool->RpcHandle, pValueName);
|
|
|
|
} RpcExcept(1) {
|
|
|
|
ReturnValue = RpcExceptionCode();
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
ReturnValue = ERROR_INVALID_FUNCTION;
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
SetPrinterData(
|
|
HANDLE hPrinter,
|
|
LPWSTR pValueName,
|
|
DWORD Type,
|
|
LPBYTE pData,
|
|
DWORD cbData
|
|
)
|
|
{
|
|
DWORD ReturnValue = 0;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
ReturnValue = RpcSetPrinterData(pSpool->RpcHandle, pValueName, Type,
|
|
pData, cbData);
|
|
|
|
} RpcExcept(1) {
|
|
|
|
ReturnValue = RpcExceptionCode();
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
ReturnValue = ERROR_INVALID_FUNCTION;
|
|
}
|
|
|
|
//
|
|
// Make sure Driver Data Cache is consistent
|
|
//
|
|
|
|
|
|
if ( ReturnValue == ERROR_SUCCESS ) {
|
|
|
|
ConsistencyCheckCache( pSpool );
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteClosePrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
if (pSpool->Status & WSPOOL_STATUS_OPEN_ERROR) {
|
|
|
|
DBGMSG(DBG_WARNING, ("Closing dummy handle to %ws\n", pSpool->pName));
|
|
|
|
EnterSplSem();
|
|
|
|
FreepSpool( pSpool );
|
|
|
|
LeaveSplSem();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcClosePrinter(&pSpool->RpcHandle)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
EnterSplSem();
|
|
|
|
pSpool->RpcHandle = INVALID_HANDLE_VALUE;
|
|
FreepSpool( pSpool );
|
|
|
|
LeaveSplSem();
|
|
|
|
} else
|
|
|
|
return LMClosePrinter(hPrinter);
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
DWORD
|
|
WaitForPrinterChange(
|
|
HANDLE hPrinter,
|
|
DWORD Flags
|
|
)
|
|
{
|
|
DWORD ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if( pSpool->Status & WSPOOL_STATUS_NOTIFY ){
|
|
DBGMSG( DBG_WARNING, ( "WPC: Already waiting.\n" ));
|
|
SetLastError( ERROR_ALREADY_WAITING );
|
|
return 0;
|
|
}
|
|
|
|
pSpool->Status |= WSPOOL_STATUS_NOTIFY;
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcWaitForPrinterChange(pSpool->RpcHandle, Flags, &Flags)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = Flags;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
ReturnValue = LMWaitForPrinterChange(hPrinter, Flags);
|
|
}
|
|
|
|
pSpool->Status &= ~WSPOOL_STATUS_NOTIFY;
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
AddForm(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pForm
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
GENERIC_CONTAINER FormContainer;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
FormContainer.Level = Level;
|
|
FormContainer.pData = pForm;
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcAddForm(pSpool->RpcHandle, (PFORM_CONTAINER)&FormContainer)) {
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
ReturnValue = FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure Forms Cache is consistent
|
|
//
|
|
|
|
|
|
if ( ReturnValue ) {
|
|
|
|
ConsistencyCheckCache( pSpool );
|
|
}
|
|
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
DeleteForm(
|
|
HANDLE hPrinter,
|
|
LPWSTR pFormName
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcDeleteForm(pSpool->RpcHandle, pFormName)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
ReturnValue = FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure Forms Cache is consistent
|
|
//
|
|
|
|
|
|
if ( ReturnValue ) {
|
|
|
|
ConsistencyCheckCache( pSpool );
|
|
}
|
|
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteGetForm(
|
|
HANDLE hPrinter,
|
|
LPWSTR pFormName,
|
|
DWORD Level,
|
|
LPBYTE pForm,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD *pOffsets;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = FormInfo1Offsets;
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pForm)
|
|
memset(pForm, 0, cbBuf);
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcGetForm(pSpool->RpcHandle, pFormName, Level, pForm, cbBuf,
|
|
pcbNeeded)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
if (pForm) {
|
|
|
|
MarshallUpStructure(pForm, pOffsets);
|
|
}
|
|
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
ReturnValue = FALSE;
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
SetForm(
|
|
HANDLE hPrinter,
|
|
LPWSTR pFormName,
|
|
DWORD Level,
|
|
LPBYTE pForm
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
GENERIC_CONTAINER FormContainer;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
FormContainer.Level = Level;
|
|
FormContainer.pData = pForm;
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcSetForm(pSpool->RpcHandle, pFormName,
|
|
(PFORM_CONTAINER)&FormContainer)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
ReturnValue = FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure Forms Cache is consistent
|
|
//
|
|
|
|
|
|
if ( ReturnValue ) {
|
|
|
|
ConsistencyCheckCache( pSpool );
|
|
}
|
|
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteEnumForms(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pForm,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD cbStruct;
|
|
DWORD *pOffsets;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = FormInfo1Offsets;
|
|
cbStruct = sizeof(FORM_INFO_1);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if (pForm)
|
|
memset(pForm, 0, cbBuf);
|
|
|
|
if (ReturnValue = RpcEnumForms(pSpool->RpcHandle, Level, pForm, cbBuf,
|
|
pcbNeeded, pcReturned)) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
if (pForm) {
|
|
|
|
DWORD i=*pcReturned;
|
|
|
|
while (i--) {
|
|
|
|
MarshallUpStructure(pForm, pOffsets);
|
|
|
|
pForm+=cbStruct;
|
|
}
|
|
}
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
ReturnValue = FALSE;
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteEnumPorts(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
LPBYTE pPort,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD cbStruct;
|
|
DWORD *pOffsets;
|
|
|
|
|
|
*pcReturned = 0;
|
|
*pcbNeeded = 0;
|
|
|
|
if (MyName(pName))
|
|
return LMEnumPorts(pName, Level, pPort, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
if (MyUNCName(pName)) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = PortInfo1Offsets;
|
|
cbStruct = sizeof(PORT_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pOffsets = PortInfo2Offsets;
|
|
cbStruct = sizeof(PORT_INFO_2);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if (pPort)
|
|
memset(pPort, 0, cbBuf);
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcEnumPorts(pName, Level, pPort, cbBuf,
|
|
pcbNeeded, pcReturned)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
if (pPort) {
|
|
|
|
DWORD i=*pcReturned;
|
|
|
|
while (i--) {
|
|
|
|
MarshallUpStructure(pPort, pOffsets);
|
|
|
|
pPort+=cbStruct;
|
|
}
|
|
}
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
EnumMonitors(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
LPBYTE pMonitor,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
DWORD cbStruct;
|
|
DWORD *pOffsets;
|
|
|
|
*pcReturned = 0;
|
|
*pcbNeeded = 0;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pOffsets = MonitorInfo1Offsets;
|
|
cbStruct = sizeof(MONITOR_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pOffsets = MonitorInfo2Offsets;
|
|
cbStruct = sizeof(MONITOR_INFO_2);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if (pMonitor)
|
|
memset(pMonitor, 0, cbBuf);
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcEnumMonitors(pName, Level, pMonitor, cbBuf,
|
|
pcbNeeded, pcReturned)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
if (pMonitor) {
|
|
|
|
DWORD i=*pcReturned;
|
|
|
|
while (i--) {
|
|
|
|
MarshallUpStructure(pMonitor, pOffsets);
|
|
|
|
pMonitor+=cbStruct;
|
|
}
|
|
}
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
|
|
}
|
|
|
|
BOOL
|
|
RemoteAddPort(
|
|
LPWSTR pName,
|
|
HWND hWnd,
|
|
LPWSTR pMonitorName
|
|
)
|
|
{
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
|
|
#ifdef OLDSTUFF
|
|
|
|
BOOL ReturnValue;
|
|
|
|
if (MyName(pName))
|
|
return LMAddPort(pName, hWnd, pMonitorName);
|
|
|
|
if (MyUNCName(pName)) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
#if REMOTE_PORT_ADMINISTRATION
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcAddPort(pName, (DWORD)hWnd, pMonitorName)) {
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
#else
|
|
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
ReturnValue = FALSE;
|
|
|
|
#endif /* REMOTE_PORT_ADMINISTRATION */
|
|
|
|
return ReturnValue;
|
|
|
|
#endif /* OLDSTUFF */
|
|
}
|
|
|
|
BOOL
|
|
RemoteConfigurePort(
|
|
LPWSTR pName,
|
|
HWND hWnd,
|
|
LPWSTR pPortName
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
|
|
if (MyName(pName))
|
|
return LMConfigurePort(pName, hWnd, pPortName);
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
#if REMOTE_PORT_ADMINISTRATION
|
|
|
|
RpcTryExcept {
|
|
|
|
if (ReturnValue = RpcConfigurePort(pName, (DWORD)hWnd, pPortName)) {
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
#else
|
|
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
ReturnValue = FALSE;
|
|
|
|
#endif /* REMOTE_PORT_ADMINISTRATION */
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
RemoteDeletePort(
|
|
LPWSTR pName,
|
|
HWND hWnd,
|
|
LPWSTR pPortName
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
if (MyName(pName))
|
|
return LMDeletePort(pName, hWnd, pPortName);
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcDeletePort(pName, (DWORD)hWnd, pPortName)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
HANDLE
|
|
CreatePrinterIC(
|
|
HANDLE hPrinter,
|
|
LPDEVMODE pDevMode
|
|
)
|
|
{
|
|
HANDLE ReturnValue;
|
|
DWORD Error;
|
|
DEVMODE_CONTAINER DevModeContainer;
|
|
HANDLE hGdi;
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
if (pDevMode)
|
|
|
|
DevModeContainer.cbBuf = pDevMode->dmSize + pDevMode->dmDriverExtra;
|
|
|
|
else
|
|
|
|
DevModeContainer.cbBuf = 0;
|
|
|
|
DevModeContainer.pDevMode = (LPBYTE)pDevMode;
|
|
|
|
RpcTryExcept {
|
|
|
|
if (Error = RpcCreatePrinterIC(pSpool->RpcHandle, &hGdi,
|
|
&DevModeContainer)) {
|
|
|
|
SetLastError(Error);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = hGdi;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
ReturnValue = FALSE;
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
PlayGdiScriptOnPrinterIC(
|
|
HANDLE hPrinterIC,
|
|
LPBYTE pIn,
|
|
DWORD cIn,
|
|
LPBYTE pOut,
|
|
DWORD cOut,
|
|
DWORD ul
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcPlayGdiScriptOnPrinterIC(hPrinterIC, pIn, cIn,
|
|
pOut, cOut, ul)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
DeletePrinterIC(
|
|
HANDLE hPrinterIC
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcDeletePrinterIC(&hPrinterIC)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
DWORD
|
|
PrinterMessageBox(
|
|
HANDLE hPrinter,
|
|
DWORD Error,
|
|
HWND hWnd,
|
|
LPWSTR pText,
|
|
LPWSTR pCaption,
|
|
DWORD dwType
|
|
)
|
|
{
|
|
PWSPOOL pSpool = (PWSPOOL)hPrinter;
|
|
|
|
VALIDATEW32HANDLE( pSpool );
|
|
|
|
SYNCRPCHANDLE( pSpool );
|
|
|
|
if (pSpool->Type == SJ_WIN32HANDLE) {
|
|
|
|
RpcTryExcept {
|
|
|
|
return RpcPrinterMessageBox(pSpool->RpcHandle, Error, (DWORD)hWnd, pText,
|
|
pCaption, dwType);
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
return 0;
|
|
|
|
} RpcEndExcept
|
|
|
|
} else {
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
AddMonitorW(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
LPBYTE pMonitorInfo
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
MONITOR_CONTAINER MonitorContainer;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (Level) {
|
|
|
|
case 2:
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
MonitorContainer.Level = Level;
|
|
MonitorContainer.MonitorInfo.pMonitorInfo2 = (MONITOR_INFO_2 *)pMonitorInfo;
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcAddMonitor(pName, &MonitorContainer)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
DeleteMonitorW(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pMonitorName
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcDeleteMonitor(pName,
|
|
pEnvironment,
|
|
pMonitorName)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
DeletePrintProcessorW(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pPrintProcessorName
|
|
)
|
|
{
|
|
BOOL ReturnValue;
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcDeletePrintProcessor(pName,
|
|
pEnvironment,
|
|
pPrintProcessorName)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
|
|
} else
|
|
|
|
ReturnValue = TRUE;
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
|
|
} RpcEndExcept
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
BOOL
|
|
GetPrintSystemVersion(
|
|
)
|
|
{
|
|
DWORD Status;
|
|
HKEY hKey;
|
|
DWORD cbData;
|
|
|
|
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegistryRoot, 0,
|
|
KEY_READ, &hKey);
|
|
if (Status != ERROR_SUCCESS) {
|
|
DBGMSG(DBG_ERROR, ("Cannot determine Print System Version Number\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (RegQueryValueEx(hKey, szMinorVersion, NULL, NULL,
|
|
(LPBYTE)&cThisMinorVersion, &cbData)
|
|
== ERROR_SUCCESS) {
|
|
DBGMSG(DBG_TRACE, ("This Minor Version - %d\n", cThisMinorVersion));
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
RemoteAddPortEx(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
LPBYTE lpBuffer,
|
|
LPWSTR lpMonitorName
|
|
)
|
|
{
|
|
DWORD ReturnValue;
|
|
PORT_CONTAINER PortContainer;
|
|
PORT_VAR_CONTAINER PortVarContainer;
|
|
PPORT_INFO_FF pPortInfoFF;
|
|
PPORT_INFO_1 pPortInfo1;
|
|
|
|
|
|
if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!lpBuffer) {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (Level) {
|
|
case (DWORD)-1:
|
|
pPortInfoFF = (PPORT_INFO_FF)lpBuffer;
|
|
PortContainer.Level = Level;
|
|
PortContainer.PortInfo.pPortInfoFF = (PPORT_INFO_FF)pPortInfoFF;
|
|
PortVarContainer.cbMonitorData = pPortInfoFF->cbMonitorData;
|
|
PortVarContainer.pMonitorData = pPortInfoFF->pMonitorData;
|
|
break;
|
|
|
|
case 1:
|
|
pPortInfo1 = (PPORT_INFO_1)lpBuffer;
|
|
PortContainer.Level = Level;
|
|
PortContainer.PortInfo.pPortInfo1 = (PPORT_INFO_1)pPortInfo1;
|
|
PortVarContainer.cbMonitorData = 0;
|
|
PortVarContainer.pMonitorData = NULL;
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcAddPortEx(pName, (LPPORT_CONTAINER)&PortContainer,
|
|
(LPPORT_VAR_CONTAINER)&PortVarContainer,
|
|
lpMonitorName)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
return FALSE;
|
|
} else {
|
|
return TRUE ;
|
|
}
|
|
} RpcExcept(1) {
|
|
SetLastError(RpcExceptionCode());
|
|
return FALSE;
|
|
|
|
} RpcEndExcept
|
|
}
|
|
|
|
|
|
BOOL
|
|
SetPort(
|
|
LPWSTR pszName,
|
|
LPWSTR pszPortName,
|
|
DWORD dwLevel,
|
|
LPBYTE pPortInfo
|
|
)
|
|
{
|
|
BOOL ReturnValue = FALSE;
|
|
PORT_CONTAINER PortContainer;
|
|
|
|
if ( !VALIDATE_NAME(pszName) || MyUNCName(pszName) ) {
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (dwLevel) {
|
|
|
|
case 3:
|
|
PortContainer.Level = dwLevel;
|
|
PortContainer.PortInfo.pPortInfo3 = (LPPORT_INFO_3W) pPortInfo;
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
goto Cleanup;
|
|
}
|
|
|
|
RpcTryExcept {
|
|
|
|
if ( (ReturnValue = RpcValidate()) ||
|
|
(ReturnValue = RpcSetPort(pszName, pszPortName, &PortContainer)) ) {
|
|
|
|
SetLastError(ReturnValue);
|
|
ReturnValue = FALSE;
|
|
} else {
|
|
|
|
ReturnValue = TRUE;
|
|
}
|
|
|
|
} RpcExcept(1) {
|
|
|
|
SetLastError(RpcExceptionCode());
|
|
ReturnValue = FALSE;
|
|
} RpcEndExcept
|
|
|
|
Cleanup:
|
|
return ReturnValue;
|
|
}
|