3213 lines
70 KiB
C
3213 lines
70 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1993 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
nwspl.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the Netware print provider.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Yi-Hsin Sung (yihsins) 15-Apr-1993
|
|||
|
|
|||
|
Revision History:
|
|||
|
Yi-Hsin Sung (yihsins) 15-May-1993
|
|||
|
Moved most of the functionality to the server side
|
|||
|
|
|||
|
Ram Viswanathan (ramv) 09-Aug-1995
|
|||
|
Added functionality to Add and Delete Printer.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
|
|||
|
#include <nwclient.h>
|
|||
|
#include <winspool.h>
|
|||
|
#include <winsplp.h>
|
|||
|
#include <ntlsa.h>
|
|||
|
|
|||
|
#include <nwpkstr.h>
|
|||
|
#include <splutil.h>
|
|||
|
#include <nwreg.h>
|
|||
|
#include <nwspl.h>
|
|||
|
#include <nwmisc.h>
|
|||
|
#include <winsta.h>
|
|||
|
//------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Local Functions
|
|||
|
//
|
|||
|
//------------------------------------------------------------------
|
|||
|
// now all SKUs have TerminalServer flag. If App Server is enabled, SingleUserTS flag is cleared
|
|||
|
#define IsTerminalServer() (BOOLEAN)(!(USER_SHARED_DATA->SuiteMask & (1 << SingleUserTS))) //user mode
|
|||
|
DWORD
|
|||
|
InitializePortNames(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
NwpGetUserInfo(
|
|||
|
LPWSTR *ppszUser,
|
|||
|
BOOL *pfGateway
|
|||
|
);
|
|||
|
|
|||
|
DWORD
|
|||
|
NwpGetThreadUserInfo(
|
|||
|
LPWSTR *ppszUser,
|
|||
|
LPWSTR *ppszUserSid
|
|||
|
);
|
|||
|
|
|||
|
DWORD
|
|||
|
NwpGetUserNameFromSid(
|
|||
|
PSID pUserSid,
|
|||
|
LPWSTR *ppszUserName
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
NwpGetLogonUserInfo(
|
|||
|
LPWSTR *ppszUserSid
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
ThreadIsInteractive(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
pFreeAllContexts();
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Global Variables
|
|||
|
//
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
HMODULE hmodNW = NULL;
|
|||
|
BOOL fIsWinnt = FALSE ;
|
|||
|
WCHAR *pszRegistryPath = NULL;
|
|||
|
WCHAR *pszRegistryPortNames=L"PortNames";
|
|||
|
WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH + 3];
|
|||
|
PNWPORT pNwFirstPort = NULL;
|
|||
|
CRITICAL_SECTION NwSplSem;
|
|||
|
CRITICAL_SECTION NwServiceListCriticalSection; // Used to protect linked
|
|||
|
// list of registered services
|
|||
|
HANDLE NwServiceListDoneEvent = NULL;// Used to stop local advertise
|
|||
|
// threads.
|
|||
|
STATIC HANDLE handleDummy; // This is a dummy handle used to
|
|||
|
// return to the clients if we have previously
|
|||
|
// opened the given printer successfully
|
|||
|
// and the netware workstation service is not
|
|||
|
// currently available.
|
|||
|
|
|||
|
STATIC
|
|||
|
PRINTPROVIDOR PrintProvidor = { OpenPrinter,
|
|||
|
SetJob,
|
|||
|
GetJob,
|
|||
|
EnumJobs,
|
|||
|
AddPrinter, // NOT SUPPORTED
|
|||
|
DeletePrinter, // NOT SUPPORTED
|
|||
|
SetPrinter,
|
|||
|
GetPrinter,
|
|||
|
EnumPrinters,
|
|||
|
AddPrinterDriver, // NOT SUPPORTED
|
|||
|
EnumPrinterDrivers, // NOT SUPPORTED
|
|||
|
GetPrinterDriverW, // NOT SUPPORTED
|
|||
|
GetPrinterDriverDirectory, // NOT SUPPORTED
|
|||
|
DeletePrinterDriver, // NOT SUPPORTED
|
|||
|
AddPrintProcessor, // NOT SUPPORTED
|
|||
|
EnumPrintProcessors, // NOT SUPPORTED
|
|||
|
GetPrintProcessorDirectory, // NOT SUPPORTED
|
|||
|
DeletePrintProcessor, // NOT SUPPORTED
|
|||
|
EnumPrintProcessorDatatypes,// NOT SUPPORTED
|
|||
|
StartDocPrinter,
|
|||
|
StartPagePrinter, // NOT SUPPORTED
|
|||
|
WritePrinter,
|
|||
|
EndPagePrinter, // NOT SUPPORTED
|
|||
|
AbortPrinter,
|
|||
|
ReadPrinter, // NOT SUPPORTED
|
|||
|
EndDocPrinter,
|
|||
|
AddJob,
|
|||
|
ScheduleJob,
|
|||
|
GetPrinterData, // NOT SUPPORTED
|
|||
|
SetPrinterData, // NOT SUPPORTED
|
|||
|
WaitForPrinterChange,
|
|||
|
ClosePrinter,
|
|||
|
AddForm, // NOT SUPPORTED
|
|||
|
DeleteForm, // NOT SUPPORTED
|
|||
|
GetForm, // NOT SUPPORTED
|
|||
|
SetForm, // NOT SUPPORTED
|
|||
|
EnumForms, // NOT SUPPORTED
|
|||
|
EnumMonitors, // NOT SUPPORTED
|
|||
|
EnumPorts,
|
|||
|
AddPort, // NOT SUPPORTED
|
|||
|
ConfigurePort,
|
|||
|
DeletePort,
|
|||
|
CreatePrinterIC, // NOT SUPPORTED
|
|||
|
PlayGdiScriptOnPrinterIC, // NOT SUPPORTED
|
|||
|
DeletePrinterIC, // NOT SUPPORTED
|
|||
|
AddPrinterConnection, // NOT SUPPORTED
|
|||
|
DeletePrinterConnection, // NOT SUPPORTED
|
|||
|
PrinterMessageBox, // NOT SUPPORTED
|
|||
|
AddMonitor, // NOT SUPPORTED
|
|||
|
DeleteMonitor // NOT SUPPORTED
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Initialization Functions
|
|||
|
//
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
BOOL InitializeDll(
|
|||
|
HINSTANCE hdll,
|
|||
|
DWORD dwReason,
|
|||
|
LPVOID lpReserved
|
|||
|
)
|
|||
|
{
|
|||
|
NT_PRODUCT_TYPE ProductType ;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( lpReserved );
|
|||
|
|
|||
|
if ( dwReason == DLL_PROCESS_ATTACH )
|
|||
|
{
|
|||
|
DisableThreadLibraryCalls( hdll );
|
|||
|
|
|||
|
hmodNW = hdll;
|
|||
|
|
|||
|
//
|
|||
|
// are we a winnt machine?
|
|||
|
//
|
|||
|
fIsWinnt = RtlGetNtProductType(&ProductType) ?
|
|||
|
(ProductType == NtProductWinNt) :
|
|||
|
FALSE ;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the critical section for maintaining the registered
|
|||
|
// service list
|
|||
|
//
|
|||
|
InitializeCriticalSection( &NwServiceListCriticalSection );
|
|||
|
NwServiceListDoneEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
|
|||
|
}
|
|||
|
else if ( dwReason == DLL_PROCESS_DETACH )
|
|||
|
{
|
|||
|
//
|
|||
|
// Free up memories used by the port link list
|
|||
|
//
|
|||
|
DeleteAllPortEntries();
|
|||
|
|
|||
|
//
|
|||
|
// Get rid of Service List and Shutdown SAP library
|
|||
|
//
|
|||
|
NwTerminateServiceProvider();
|
|||
|
|
|||
|
#ifndef NT1057
|
|||
|
//
|
|||
|
// Clean up shell extensions
|
|||
|
//
|
|||
|
NwCleanupShellExtensions();
|
|||
|
#endif
|
|||
|
pFreeAllContexts(); // clean up RNR stuff
|
|||
|
DeleteCriticalSection( &NwServiceListCriticalSection );
|
|||
|
if ( NwServiceListDoneEvent )
|
|||
|
{
|
|||
|
CloseHandle( NwServiceListDoneEvent );
|
|||
|
NwServiceListDoneEvent = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
InitializePortNames(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is called by the InitializePrintProvidor to initialize the ports
|
|||
|
names used in this providor.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns NO_ERROR or the error that occurred.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
HKEY hkeyPath;
|
|||
|
HKEY hkeyPortNames;
|
|||
|
|
|||
|
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|||
|
pszRegistryPath,
|
|||
|
0,
|
|||
|
KEY_READ,
|
|||
|
&hkeyPath );
|
|||
|
|
|||
|
if ( !err )
|
|||
|
{
|
|||
|
err = RegOpenKeyEx( hkeyPath,
|
|||
|
pszRegistryPortNames,
|
|||
|
0,
|
|||
|
KEY_READ,
|
|||
|
&hkeyPortNames );
|
|||
|
|
|||
|
if ( !err )
|
|||
|
{
|
|||
|
DWORD i = 0;
|
|||
|
WCHAR Buffer[MAX_PATH];
|
|||
|
DWORD BufferSize;
|
|||
|
|
|||
|
while ( !err )
|
|||
|
{
|
|||
|
BufferSize = sizeof(Buffer) / sizeof(WCHAR);
|
|||
|
|
|||
|
err = RegEnumValue( hkeyPortNames,
|
|||
|
i,
|
|||
|
Buffer,
|
|||
|
&BufferSize,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL );
|
|||
|
|
|||
|
if ( !err )
|
|||
|
CreatePortEntry( Buffer );
|
|||
|
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
/* We expect RegEnumKeyEx to return ERROR_NO_MORE_ITEMS
|
|||
|
* when it gets to the end of the keys, so reset the status:
|
|||
|
*/
|
|||
|
if( err == ERROR_NO_MORE_ITEMS )
|
|||
|
err = NO_ERROR;
|
|||
|
|
|||
|
RegCloseKey( hkeyPortNames );
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
else
|
|||
|
{
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [RegOpenKeyEx] (%ws) failed: Error = %d\n",
|
|||
|
pszRegistryPortNames, err ));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
RegCloseKey( hkeyPath );
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
else
|
|||
|
{
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [RegOpenKeyEx] (%ws) failed: Error = %d\n",
|
|||
|
pszRegistryPath, err ));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Print Provider Functions supported by NetWare provider
|
|||
|
//
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
InitializePrintProvidor(
|
|||
|
LPPRINTPROVIDOR pPrintProvidor,
|
|||
|
DWORD cbPrintProvidor,
|
|||
|
LPWSTR pszFullRegistryPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is called by the spooler subsystem to initialize the print
|
|||
|
providor.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pPrintProvidor - Pointer to the print providor structure to be
|
|||
|
filled in by this function
|
|||
|
cbPrintProvidor - Count of bytes of the print providor structure
|
|||
|
pszFullRegistryPath - Full path to the registry key of this print providor
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Always TRUE.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// dfergus 20 Apr 2001 #323700
|
|||
|
// Prevent Multiple CS Initialization
|
|||
|
//
|
|||
|
static int iCSInit = 0;
|
|||
|
|
|||
|
DWORD dwLen;
|
|||
|
|
|||
|
if ( !pPrintProvidor || !pszFullRegistryPath || !*pszFullRegistryPath )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
memcpy( pPrintProvidor,
|
|||
|
&PrintProvidor,
|
|||
|
min( sizeof(PRINTPROVIDOR), cbPrintProvidor) );
|
|||
|
|
|||
|
//
|
|||
|
// Store the registry path for this print providor
|
|||
|
//
|
|||
|
if ( !(pszRegistryPath = AllocNwSplStr(pszFullRegistryPath)) )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Store the local machine name
|
|||
|
//
|
|||
|
szMachineName[0] = szMachineName[1] = L'\\';
|
|||
|
dwLen = MAX_COMPUTERNAME_LENGTH;
|
|||
|
GetComputerName( szMachineName + 2, &dwLen );
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
{
|
|||
|
KdPrint(("NWSPL [InitializePrintProvidor] "));
|
|||
|
KdPrint(("RegistryPath = %ws, ComputerName = %ws\n",
|
|||
|
pszRegistryPath, szMachineName ));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// dfergus 20 Apr 2001 #323700
|
|||
|
// Prevent Multiple CS Initialization
|
|||
|
//
|
|||
|
if( !iCSInit )
|
|||
|
{
|
|||
|
InitializeCriticalSection( &NwSplSem );
|
|||
|
iCSInit = 1;
|
|||
|
}
|
|||
|
//
|
|||
|
// Ignore the error returned from InitializePortNames.
|
|||
|
// The provider can still function if we cannot get all the port
|
|||
|
// names.
|
|||
|
//
|
|||
|
InitializePortNames();
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
OpenPrinterW(
|
|||
|
LPWSTR pszPrinterName,
|
|||
|
LPHANDLE phPrinter,
|
|||
|
LPPRINTER_DEFAULTS pDefault
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves a handle identifying the specified printer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pszPrinterName - Name of the printer
|
|||
|
phPrinter - Receives the handle that identifies the given printer
|
|||
|
pDefault - Points to a PRINTER_DEFAULTS structure. Can be NULL.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise. Use GetLastError() for
|
|||
|
extended error information.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [OpenPrinter] Name = %ws\n", pszPrinterName ));
|
|||
|
#endif
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( pDefault );
|
|||
|
|
|||
|
if ( !pszPrinterName )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrOpenPrinter( NULL,
|
|||
|
pszPrinterName,
|
|||
|
PortKnown( pszPrinterName ),
|
|||
|
(LPNWWKSTA_PRINTER_CONTEXT) phPrinter );
|
|||
|
|
|||
|
//
|
|||
|
// Make sure there is a port of this name so that
|
|||
|
// EnumPorts will return it.
|
|||
|
//
|
|||
|
|
|||
|
if ( !err )
|
|||
|
{
|
|||
|
|
|||
|
if ( !PortExists( pszPrinterName, &err ) && !err )
|
|||
|
{
|
|||
|
//
|
|||
|
// We will ignore the errors since it is
|
|||
|
// still OK if we can't add the port.
|
|||
|
// Cannot delete once created, don't create
|
|||
|
// We should not create port entry and registry entry
|
|||
|
|
|||
|
if ( CreatePortEntry( pszPrinterName ) )
|
|||
|
CreateRegistryEntry( pszPrinterName );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
{
|
|||
|
if ( PortKnown( pszPrinterName ))
|
|||
|
{
|
|||
|
*phPrinter = &handleDummy;
|
|||
|
err = NO_ERROR;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
err = ERROR_INVALID_NAME;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
{
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [OpenPrinter] err = %d\n", err));
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
return ( err == NO_ERROR );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ClosePrinter(
|
|||
|
HANDLE hPrinter
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine closes the given printer object.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer object
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise. Use GetLastError() for
|
|||
|
extended error information.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [ClosePrinter]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Just return success if the handle is a dummy one
|
|||
|
//
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
return TRUE;
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrClosePrinter( (LPNWWKSTA_PRINTER_CONTEXT) &hPrinter );
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
GetPrinter(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbPrinter,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The routine retrieves information about the given printer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer
|
|||
|
dwLevel - Specifies the level of the structure to which pbPrinter points.
|
|||
|
pbPrinter - Points to a buffer that receives the PRINTER_INFO object.
|
|||
|
cbBuf - Size, in bytes of the array pbPrinter points to.
|
|||
|
pcbNeeded - Points to a value which specifies the number of bytes copied
|
|||
|
if the function succeeds or the number of bytes required if
|
|||
|
cbBuf was too small.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds and FALSE otherwise. GetLastError() can be
|
|||
|
used to retrieve extended error information.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [GetPrinter] Level = %d\n", dwLevel ));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( ( dwLevel != 1 ) && ( dwLevel != 2 ) && (dwLevel != 3 ))
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_LEVEL );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrGetPrinter( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
dwLevel,
|
|||
|
pbPrinter,
|
|||
|
cbBuf,
|
|||
|
pcbNeeded );
|
|||
|
|
|||
|
if ( !err )
|
|||
|
{
|
|||
|
if ( dwLevel == 1 )
|
|||
|
MarshallUpStructure( pbPrinter, PrinterInfo1Offsets, pbPrinter);
|
|||
|
else
|
|||
|
MarshallUpStructure( pbPrinter, PrinterInfo2Offsets, pbPrinter);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
SetPrinter(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbPrinter,
|
|||
|
DWORD dwCommand
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The routine sets the specified by pausing printing, resuming printing, or
|
|||
|
clearing all print jobs.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer
|
|||
|
dwLevel - Specifies the level of the structure to which pbPrinter points.
|
|||
|
pbPrinter - Points to a buffer that supplies the PRINTER_INFO object.
|
|||
|
dwCommand - Specifies the new printer state.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds and FALSE otherwise. GetLastError() can be
|
|||
|
used to retrieve extended error information.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err = NO_ERROR;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( pbPrinter );
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
{
|
|||
|
KdPrint(( "NWSPL [SetPrinter] Level = %d Command = %d\n",
|
|||
|
dwLevel, dwCommand ));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
switch ( dwLevel )
|
|||
|
{
|
|||
|
case 0:
|
|||
|
case 1:
|
|||
|
case 2:
|
|||
|
case 3:
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
SetLastError( ERROR_INVALID_LEVEL );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrSetPrinter( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
dwCommand );
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumPrintersW(
|
|||
|
DWORD dwFlags,
|
|||
|
LPWSTR pszName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbPrinter,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded,
|
|||
|
LPDWORD pcReturned
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine enumerates the available providers, servers, printers
|
|||
|
depending on the given pszName.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwFlags - Printer type requested
|
|||
|
pszName - The name of the container object
|
|||
|
dwLevel - The structure level requested
|
|||
|
pbPrinter - Points to the array to receive the PRINTER_INFO objects
|
|||
|
cbBuf - Size, in bytes of pbPrinter
|
|||
|
pcbNeeded - Count of bytes needed
|
|||
|
pcReturned - Count of PRINTER_INFO objects
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err = NO_ERROR;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
{
|
|||
|
KdPrint(("NWSPL [EnumPrinters] Flags = %d Level = %d",dwFlags,dwLevel));
|
|||
|
if ( pszName )
|
|||
|
KdPrint((" PrinterName = %ws\n", pszName ));
|
|||
|
else
|
|||
|
KdPrint(("\n"));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if ( (dwLevel != 1) && (dwLevel != 2) )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_NAME ); // should be level, but winspool
|
|||
|
// is silly.
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( !pcbNeeded || !pcReturned )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
*pcReturned = 0;
|
|||
|
*pcbNeeded = 0;
|
|||
|
|
|||
|
if ( ( dwFlags & PRINTER_ENUM_NAME )
|
|||
|
&& ( dwLevel == 1 )
|
|||
|
)
|
|||
|
{
|
|||
|
err = NwrEnumPrinters( NULL,
|
|||
|
pszName,
|
|||
|
pbPrinter,
|
|||
|
cbBuf,
|
|||
|
pcbNeeded,
|
|||
|
pcReturned );
|
|||
|
|
|||
|
if ( !err )
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
for ( i = 0; i < *pcReturned; i++ )
|
|||
|
MarshallUpStructure( pbPrinter + i*sizeof(PRINTER_INFO_1W),
|
|||
|
PrinterInfo1Offsets,
|
|||
|
pbPrinter );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
err = ERROR_INVALID_NAME;
|
|||
|
}
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_NAME;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Handle structure
|
|||
|
// This structure was copied from \nw\svcdlls\nwwks\server\spool.c
|
|||
|
// to fix NT bug # 366632.
|
|||
|
//
|
|||
|
typedef struct _NWSPOOL {
|
|||
|
DWORD nSignature; // Signature
|
|||
|
DWORD errOpenPrinter; // OpenPrinter API will always return
|
|||
|
// success on known printers. This will
|
|||
|
// contain the error that we get
|
|||
|
// if something went wrong in the API.
|
|||
|
PVOID pPrinter; // Points to the corresponding printer
|
|||
|
HANDLE hServer; // Opened handle to the server
|
|||
|
struct _NWSPOOL *pNextSpool; // Points to the next handle
|
|||
|
DWORD nStatus; // Status
|
|||
|
DWORD nJobNumber; // StartDocPrinter/AddJob: Job Number
|
|||
|
HANDLE hChangeEvent; // WaitForPrinterChange: event to wait on
|
|||
|
DWORD nWaitFlags; // WaitForPrinterChange: flags to wait on
|
|||
|
DWORD nChangeFlags; // Changes that occurred to the printer
|
|||
|
} NWSPOOL, *PNWSPOOL;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
StartDocPrinter(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE lpbDocInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine informs the print spooler that a document is to be spooled
|
|||
|
for printing.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer
|
|||
|
dwLevel - Level of the structure pointed to by lpbDocInfo. Must be 1.
|
|||
|
lpbDocInfo - Points to the DOC_INFO_1 object
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise. The extended error
|
|||
|
can be retrieved through GetLastError().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
DOC_INFO_1 *pDocInfo1 = (DOC_INFO_1 *) lpbDocInfo;
|
|||
|
LPWSTR pszUser = NULL;
|
|||
|
BOOL fGateway = FALSE;
|
|||
|
|
|||
|
DWORD PrintOption = NW_GATEWAY_PRINT_OPTION_DEFAULT;
|
|||
|
LPWSTR pszPreferredSrv = NULL;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
{
|
|||
|
KdPrint(( "NWSPL [StartDocPrinter] " ));
|
|||
|
if ( pDocInfo1 )
|
|||
|
{
|
|||
|
if ( pDocInfo1->pDocName )
|
|||
|
KdPrint(("Document %ws", pDocInfo1->pDocName ));
|
|||
|
if ( pDocInfo1->pOutputFile )
|
|||
|
KdPrint(("OutputFile %ws", pDocInfo1->pOutputFile ));
|
|||
|
if ( pDocInfo1->pDatatype )
|
|||
|
KdPrint(("Datatype %ws", pDocInfo1->pDatatype ));
|
|||
|
}
|
|||
|
KdPrint(("\n"));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( dwLevel != 1 )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// ignore the error, just use default value
|
|||
|
NwpGetUserInfo( &pszUser, &fGateway );
|
|||
|
if ( !fGateway ) {
|
|||
|
NwQueryInfo( &PrintOption, &pszPreferredSrv );
|
|||
|
if (pszPreferredSrv) {
|
|||
|
LocalFree( pszPreferredSrv );
|
|||
|
}
|
|||
|
}
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrStartDocPrinter( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
pDocInfo1? pDocInfo1->pDocName : NULL,
|
|||
|
pszUser,
|
|||
|
PrintOption,
|
|||
|
fGateway );
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
LocalFree( pszUser );
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
//
|
|||
|
// Can't do this, seems to break GSWN printing on multi-homed machines
|
|||
|
// Commenting out code change that tries to return the job id.
|
|||
|
//
|
|||
|
// else
|
|||
|
// return ((PNWSPOOL) hPrinter)->nJobNumber;
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
WritePrinter(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPVOID pBuf,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbWritten
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine informs the print spooler that the specified data should be
|
|||
|
written to the given printer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer object
|
|||
|
pBuf - Address of array that contains printer data
|
|||
|
cbBuf - Size, in bytes of pBuf
|
|||
|
pcbWritten - Receives the number of bytes actually written to the printer
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if it succeeds, FALSE otherwise. Use GetLastError() to get extended
|
|||
|
error.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [WritePrinter]\n"));
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrWritePrinter( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
pBuf,
|
|||
|
cbBuf,
|
|||
|
pcbWritten );
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
AbortPrinter(
|
|||
|
HANDLE hPrinter
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine deletes a printer's spool file if the printer is configured
|
|||
|
for spooling.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer object
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [AbortPrinter]\n"));
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrAbortPrinter( (NWWKSTA_PRINTER_CONTEXT) hPrinter );
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
EndDocPrinter(
|
|||
|
HANDLE hPrinter
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine ends the print job for the given printer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer object
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [EndDocPrinter]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrEndDocPrinter( (NWWKSTA_PRINTER_CONTEXT) hPrinter );
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
GetJob(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwJobId,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbJob,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves print-job data for the given printer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer
|
|||
|
dwJobId - Job identifition number
|
|||
|
dwLevel - Data structure level of pbJob
|
|||
|
pbJob - Address of data-structure array
|
|||
|
cbBuf - Count of bytes in array
|
|||
|
pcbNeeded - Count of bytes retrieved or required
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [GetJob] JobId = %d Level = %d\n", dwJobId, dwLevel));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if (( dwLevel != 1 ) && ( dwLevel != 2 ))
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_LEVEL );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrGetJob( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
dwJobId,
|
|||
|
dwLevel,
|
|||
|
pbJob,
|
|||
|
cbBuf,
|
|||
|
pcbNeeded );
|
|||
|
|
|||
|
if ( !err )
|
|||
|
{
|
|||
|
if ( dwLevel == 1 )
|
|||
|
MarshallUpStructure( pbJob, JobInfo1Offsets, pbJob );
|
|||
|
else
|
|||
|
MarshallUpStructure( pbJob, JobInfo2Offsets, pbJob );
|
|||
|
}
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumJobs(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwFirstJob,
|
|||
|
DWORD dwNoJobs,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbJob,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded,
|
|||
|
LPDWORD pcReturned
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the array of JOB_INFO_1 or JOB_INFO_2 structures
|
|||
|
with data describing the specified print jobs for the given printer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer
|
|||
|
dwFirstJob - Location of first job in the printer
|
|||
|
dwNoJobs - Number of jobs to enumerate
|
|||
|
dwLevel - Data structure level
|
|||
|
pbJob - Address of structure array
|
|||
|
cbBuf - Size of pbJob, in bytes
|
|||
|
pcbNeeded - Receives the number of bytes copied or required
|
|||
|
pcReturned - Receives the number of jobs copied
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [EnumJobs] Level = %d FirstJob = %d NoJobs = %d\n",
|
|||
|
dwLevel, dwFirstJob, dwNoJobs));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( ( dwLevel != 1 ) && ( dwLevel != 2 ) )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_LEVEL );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
*pcReturned = 0;
|
|||
|
*pcbNeeded = 0;
|
|||
|
|
|||
|
err = NwrEnumJobs( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
dwFirstJob,
|
|||
|
dwNoJobs,
|
|||
|
dwLevel,
|
|||
|
pbJob,
|
|||
|
cbBuf,
|
|||
|
pcbNeeded,
|
|||
|
pcReturned );
|
|||
|
|
|||
|
if ( !err )
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
DWORD cbStruct;
|
|||
|
DWORD_PTR *pOffsets;
|
|||
|
|
|||
|
if ( dwLevel == 1 )
|
|||
|
{
|
|||
|
cbStruct = sizeof( JOB_INFO_1W );
|
|||
|
pOffsets = JobInfo1Offsets;
|
|||
|
}
|
|||
|
else // dwLevel == 2
|
|||
|
{
|
|||
|
cbStruct = sizeof( JOB_INFO_2W );
|
|||
|
pOffsets = JobInfo2Offsets;
|
|||
|
}
|
|||
|
|
|||
|
for ( i = 0; i < *pcReturned; i++ )
|
|||
|
MarshallUpStructure( pbJob + i * cbStruct, pOffsets, pbJob );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
SetJob(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwJobId,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbJob,
|
|||
|
DWORD dwCommand
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine pauses, cancels, resumes, restarts the specified print job
|
|||
|
in the given printer. The function can also be used to set print job
|
|||
|
parameters such as job position, and so on.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer
|
|||
|
dwJobId - Job indentification number
|
|||
|
dwLevel - Data structure level
|
|||
|
pbJob - Address of data structure
|
|||
|
dwCommand - Specify the operation to be performed
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
{
|
|||
|
KdPrint(("NWSPL [SetJob] Level = %d JobId = %d Command = %d\n",
|
|||
|
dwLevel, dwJobId, dwCommand));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( ( dwLevel != 0 ) && ( dwLevel != 1 ) && ( dwLevel != 2 ) )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_LEVEL );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( ( dwLevel == 0 ) && ( pbJob != NULL ) )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
NW_JOB_INFO NwJobInfo;
|
|||
|
|
|||
|
if ( dwLevel == 1 )
|
|||
|
{
|
|||
|
NwJobInfo.nPosition = ((LPJOB_INFO_1W) pbJob)->Position;
|
|||
|
NwJobInfo.pUserName = ((LPJOB_INFO_1W) pbJob)->pUserName;
|
|||
|
NwJobInfo.pDocument = ((LPJOB_INFO_1W) pbJob)->pDocument;
|
|||
|
}
|
|||
|
else if ( dwLevel == 2 )
|
|||
|
{
|
|||
|
NwJobInfo.nPosition = ((LPJOB_INFO_2W) pbJob)->Position;
|
|||
|
NwJobInfo.pUserName = ((LPJOB_INFO_2W) pbJob)->pUserName;
|
|||
|
NwJobInfo.pDocument = ((LPJOB_INFO_2W) pbJob)->pDocument;
|
|||
|
}
|
|||
|
|
|||
|
err = NwrSetJob( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
dwJobId,
|
|||
|
dwLevel,
|
|||
|
dwLevel == 0 ? NULL : &NwJobInfo,
|
|||
|
dwCommand );
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
AddJob(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbAddJob,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine returns a full path and filename of a file that can be used
|
|||
|
to store a print job.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer
|
|||
|
dwLevel - Data structure level
|
|||
|
pbAddJob - Points to a ADD_INFO_1 structure
|
|||
|
cbBuf - Size of pbAddJob, in bytes
|
|||
|
pcbNeeded - Receives the bytes copied or required
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
ADDJOB_INFO_1W TempBuffer;
|
|||
|
PADDJOB_INFO_1W OutputBuffer;
|
|||
|
DWORD OutputBufferSize;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [AddJob]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( dwLevel != 1 )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The output buffer size must be at least the size of the fixed
|
|||
|
// portion of the structure marshalled by RPC or RPC will not
|
|||
|
// call the server-side to get the pcbNeeded. Use our own temporary
|
|||
|
// buffer to force RPC to call the server-side if output buffer
|
|||
|
// specified by the caller is too small.
|
|||
|
//
|
|||
|
if (cbBuf < sizeof(ADDJOB_INFO_1W)) {
|
|||
|
OutputBuffer = &TempBuffer;
|
|||
|
OutputBufferSize = sizeof(ADDJOB_INFO_1W);
|
|||
|
}
|
|||
|
else {
|
|||
|
OutputBuffer = (LPADDJOB_INFO_1W) pbAddJob;
|
|||
|
OutputBufferSize = cbBuf;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrAddJob( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
OutputBuffer,
|
|||
|
OutputBufferSize,
|
|||
|
pcbNeeded );
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ScheduleJob(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwJobId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine informs the print spooler that the specified job can be
|
|||
|
scheduled for spooling.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer
|
|||
|
dwJobId - Job number that can be scheduled
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [ScheduleJob] JobId = %d\n", dwJobId ));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrScheduleJob( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
dwJobId );
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
WaitForPrinterChange(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwFlags
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns when one or more requested changes occur on a
|
|||
|
print server or if the function times out.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hPrinter - Handle of the printer to wait on
|
|||
|
dwFlags - A bitmask that specifies the changes that the application
|
|||
|
wishes to be notified of.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Return a bitmask that indicates the changes that occurred.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [WaitForPrinterChange] Flags = %d\n", dwFlags));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NO_NETWORK );
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrWaitForPrinterChange( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
|
|||
|
&dwFlags );
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if ( err )
|
|||
|
{
|
|||
|
SetLastError( err );
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
return dwFlags;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumPortsW(
|
|||
|
LPWSTR pszName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbPort,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded,
|
|||
|
LPDWORD pcReturned
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function enumerates the ports available for printing on a
|
|||
|
specified server.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pszName - Name of the server to enumerate on
|
|||
|
dwLevel - Structure level
|
|||
|
pbPort - Address of array to receive the port information
|
|||
|
cbBuf - Size, in bytes, of pbPort
|
|||
|
pcbNeeded - Address to store the number of bytes needed or copied
|
|||
|
pcReturned - Address to store the number of entries copied
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err = NO_ERROR;
|
|||
|
DWORD cb = 0;
|
|||
|
PNWPORT pNwPort;
|
|||
|
LPPORT_INFO_1W pPortInfo1;
|
|||
|
LPBYTE pEnd = pbPort + cbBuf;
|
|||
|
LPBYTE pFixedDataEnd = pbPort;
|
|||
|
BOOL FitInBuffer;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [EnumPorts]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( dwLevel != 1 )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( !IsLocalMachine( pszName ) )
|
|||
|
{
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
EnterCriticalSection( &NwSplSem );
|
|||
|
|
|||
|
pNwPort = pNwFirstPort;
|
|||
|
while ( pNwPort )
|
|||
|
{
|
|||
|
cb += sizeof(PORT_INFO_1W) + ( wcslen( pNwPort->pName)+1)*sizeof(WCHAR);
|
|||
|
pNwPort = pNwPort->pNext;
|
|||
|
}
|
|||
|
|
|||
|
*pcbNeeded = cb;
|
|||
|
*pcReturned = 0;
|
|||
|
|
|||
|
if ( cb <= cbBuf )
|
|||
|
{
|
|||
|
pEnd = pbPort + cbBuf;
|
|||
|
|
|||
|
pNwPort = pNwFirstPort;
|
|||
|
while ( pNwPort )
|
|||
|
{
|
|||
|
pPortInfo1 = (LPPORT_INFO_1W) pFixedDataEnd;
|
|||
|
pFixedDataEnd += sizeof( PORT_INFO_1W );
|
|||
|
|
|||
|
FitInBuffer = NwlibCopyStringToBuffer( pNwPort->pName,
|
|||
|
wcslen( pNwPort->pName),
|
|||
|
(LPCWSTR) pFixedDataEnd,
|
|||
|
(LPWSTR *) &pEnd,
|
|||
|
&pPortInfo1->pName );
|
|||
|
ASSERT( FitInBuffer );
|
|||
|
|
|||
|
pNwPort = pNwPort->pNext;
|
|||
|
(*pcReturned)++;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
err = ERROR_INSUFFICIENT_BUFFER;
|
|||
|
}
|
|||
|
|
|||
|
LeaveCriticalSection( &NwSplSem );
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
DeletePortW(
|
|||
|
LPWSTR pszName,
|
|||
|
HWND hWnd,
|
|||
|
LPWSTR pszPortName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine deletes the port given on the server. A dialog can
|
|||
|
be displayed if needed.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pszName - Name of the server for which the port should be deleted
|
|||
|
hWnd - Parent window
|
|||
|
pszPortName - The name of the port to delete
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
BOOL fPortDeleted;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeletePort]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( !IsLocalMachine( pszName ) )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
fPortDeleted = DeletePortEntry( pszPortName );
|
|||
|
|
|||
|
if ( fPortDeleted )
|
|||
|
{
|
|||
|
err = DeleteRegistryEntry( pszPortName );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
err = ERROR_UNKNOWN_PORT;
|
|||
|
}
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ConfigurePortW(
|
|||
|
LPWSTR pszName,
|
|||
|
HWND hWnd,
|
|||
|
LPWSTR pszPortName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine displays the port configuration dialog box
|
|||
|
for the given port on the given server.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pszName - Name of the server on which the given port exist
|
|||
|
hWnd - Parent window
|
|||
|
pszPortName - The name of the port to be configured
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the function succeeds, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD nCurrentThreadId;
|
|||
|
DWORD nWindowThreadId;
|
|||
|
WCHAR szCaption[MAX_PATH];
|
|||
|
WCHAR szMessage[MAX_PATH];
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [ConfigurePort] PortName = %ws\n", pszPortName));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( !IsLocalMachine( pszName ) )
|
|||
|
{
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else if ( !PortKnown( pszPortName ) )
|
|||
|
{
|
|||
|
SetLastError( ERROR_UNKNOWN_PORT );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
nCurrentThreadId = GetCurrentThreadId();
|
|||
|
nWindowThreadId = GetWindowThreadProcessId( hWnd, NULL );
|
|||
|
|
|||
|
if ( !AttachThreadInput( nCurrentThreadId, nWindowThreadId, TRUE ))
|
|||
|
KdPrint(("[NWSPL] AttachThreadInput failed with %d.\n",GetLastError()));
|
|||
|
|
|||
|
if ( LoadStringW( hmodNW,
|
|||
|
IDS_NETWARE_PRINT_CAPTION,
|
|||
|
szCaption,
|
|||
|
sizeof( szCaption ) / sizeof( WCHAR )))
|
|||
|
{
|
|||
|
if ( LoadStringW( hmodNW,
|
|||
|
IDS_NOTHING_TO_CONFIGURE,
|
|||
|
szMessage,
|
|||
|
sizeof( szMessage ) / sizeof( WCHAR )))
|
|||
|
{
|
|||
|
MessageBox( hWnd, szMessage, szCaption,
|
|||
|
MB_OK | MB_ICONINFORMATION );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
KdPrint(("[NWSPL] LoadString failed with %d.\n",GetLastError()));
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
KdPrint(("[NWSPL] LoadString failed with %d.\n",GetLastError()));
|
|||
|
}
|
|||
|
|
|||
|
if ( !AttachThreadInput( nCurrentThreadId, nWindowThreadId, FALSE ))
|
|||
|
KdPrint(("[NWSPL] DetachThreadInput failed with %d.\n",GetLastError()));
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Print Provider Functions not supported by NetWare provider
|
|||
|
//
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
BOOL
|
|||
|
AddPrinterConnectionW(
|
|||
|
LPWSTR pszPrinterName
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
{
|
|||
|
KdPrint(("NWSPL [AddPrinterConnection] PrinterName = %ws\n",
|
|||
|
pszPrinterName));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumMonitorsW(
|
|||
|
LPWSTR pszName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbMonitor,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded,
|
|||
|
LPDWORD pcReturned
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [EnumMonitors]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
AddPortW(
|
|||
|
LPWSTR pszName,
|
|||
|
HWND hWnd,
|
|||
|
LPWSTR pszMonitorName
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [AddPort]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HANDLE
|
|||
|
AddPrinterW(
|
|||
|
LPWSTR pszName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbPrinter
|
|||
|
)
|
|||
|
|
|||
|
// Creates a print queue on the netware server and returns a handle to it
|
|||
|
{
|
|||
|
#ifdef NOT_USED
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [AddPrinterW]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|||
|
return FALSE;
|
|||
|
#else
|
|||
|
|
|||
|
LPTSTR pszPrinterName = NULL;
|
|||
|
LPTSTR pszPServer = NULL;
|
|||
|
LPTSTR pszQueue = NULL;
|
|||
|
HANDLE hPrinter = NULL;
|
|||
|
DWORD err;
|
|||
|
PPRINTER_INFO_2 pPrinterInfo;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [AddPrinterW]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
pPrinterInfo = (PPRINTER_INFO_2)pbPrinter;
|
|||
|
|
|||
|
|
|||
|
if (dwLevel != 2)
|
|||
|
{
|
|||
|
err = ERROR_INVALID_PARAMETER;
|
|||
|
goto ErrorExit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (!(pszPrinterName = (LPTSTR)LocalAlloc(LPTR, (wcslen(((PRINTER_INFO_2 *)pbPrinter)->pPrinterName)+1)* sizeof(WCHAR))))
|
|||
|
{
|
|||
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto ErrorExit;
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(pszPrinterName,pPrinterInfo->pPrinterName);
|
|||
|
|
|||
|
// PrinterName is the name represented as \\server\share
|
|||
|
//The pszPServer parameter could have multiple fields separated by semicolons
|
|||
|
|
|||
|
|
|||
|
if ( ( !ValidateUNCName( pszPrinterName ) )
|
|||
|
|| ( (pszQueue = wcschr( pszPrinterName + 2, L'\\')) == NULL )
|
|||
|
|| ( pszQueue == (pszPrinterName + 2) )
|
|||
|
|| ( *(pszQueue + 1) == L'\0' )
|
|||
|
)
|
|||
|
{
|
|||
|
err = ERROR_INVALID_NAME;
|
|||
|
goto ErrorExit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [AddPrinter] Name = %ws\n",pszPServer));
|
|||
|
#endif
|
|||
|
|
|||
|
if ( pszPrinterName == NULL )
|
|||
|
//PrinterName is a mandatory field but not the list of PServers
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [AddPrinter] Printername not supplied\n" ));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
goto ErrorExit;
|
|||
|
}
|
|||
|
|
|||
|
//Check to see if there is a port of the same name
|
|||
|
// If so, abort the addprinter operation.
|
|||
|
// This code was commented earlier
|
|||
|
|
|||
|
if (PortExists(pszPrinterName, &err ) && !err )
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [AddPrinter], = %ws; Port exists with same name\n", pszPrinterName ));
|
|||
|
#endif
|
|||
|
SetLastError(ERROR_ALREADY_ASSIGNED);
|
|||
|
goto ErrorExit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Put all the relevant information into the PRINTER_INFO_2 structure
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
err = NwrAddPrinter ( NULL,
|
|||
|
(LPPRINTER_INFO_2W) pPrinterInfo,
|
|||
|
(LPNWWKSTA_PRINTER_CONTEXT) &hPrinter
|
|||
|
);
|
|||
|
if (!err)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(( "NWSPL [AddPrinter] Name = %ws\n", pszPrinterName ));
|
|||
|
#endif
|
|||
|
goto ErrorExit;
|
|||
|
}
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
goto ErrorExit;
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
if ( !pszPrinterName)
|
|||
|
(void) LocalFree((HLOCAL)pszPrinterName);
|
|||
|
|
|||
|
return hPrinter;
|
|||
|
|
|||
|
ErrorExit:
|
|||
|
if ( !pszPrinterName)
|
|||
|
(void) LocalFree((HLOCAL)pszPrinterName);
|
|||
|
|
|||
|
SetLastError( err);
|
|||
|
return (HANDLE)0x0;
|
|||
|
|
|||
|
#endif // #ifdef NOT_USED
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
DeletePrinter(
|
|||
|
HANDLE hPrinter
|
|||
|
)
|
|||
|
{
|
|||
|
#ifdef NOT_USED
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeletePrinter]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|||
|
return FALSE;
|
|||
|
#else
|
|||
|
LPWSTR pszPrinterName = NULL ; // Used to delete entry from registry
|
|||
|
DWORD err = NO_ERROR;
|
|||
|
DWORD DoesPortExist;
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeletePrinter]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
pszPrinterName = (LPWSTR)LocalAlloc(LPTR,sizeof(WCHAR)*MAX_PATH);
|
|||
|
|
|||
|
if(pszPrinterName == NULL)
|
|||
|
{
|
|||
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
//
|
|||
|
// Just return success if the handle is a dummy one
|
|||
|
//
|
|||
|
if ( hPrinter == &handleDummy )
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeletePrinter] Dummy handle \n"));
|
|||
|
#endif
|
|||
|
SetLastError(ERROR_NO_NETWORK);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
|
|||
|
|
|||
|
err = NwrDeletePrinter( NULL,
|
|||
|
// pszPrinterName,
|
|||
|
(LPNWWKSTA_PRINTER_CONTEXT) &hPrinter );
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
DWORD code = RpcExceptionCode();
|
|||
|
|
|||
|
if ( code == RPC_S_SERVER_UNAVAILABLE )
|
|||
|
err = ERROR_INVALID_HANDLE;
|
|||
|
else
|
|||
|
err = NwpMapRpcError( code );
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if (!err && PortExists(pszPrinterName, &DoesPortExist) && DoesPortExist)
|
|||
|
{
|
|||
|
|
|||
|
if ( DeleteRegistryEntry (pszPrinterName))
|
|||
|
(void) DeletePortEntry(pszPrinterName);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if ( err )
|
|||
|
SetLastError( err );
|
|||
|
|
|||
|
return err == NO_ERROR;
|
|||
|
|
|||
|
#endif // #ifdef NOT_USED
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
DeletePrinterConnectionW(
|
|||
|
LPWSTR pszName
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeletePrinterConnection]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
AddPrinterDriverW(
|
|||
|
LPWSTR pszName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbPrinter
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [AddPrinterDriver]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumPrinterDriversW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbDriverInfo,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded,
|
|||
|
LPDWORD pcReturned
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [EnumPrinterDrivers]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
GetPrinterDriverW(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbDriverInfo,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [GetPrinterDriver]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
GetPrinterDriverDirectoryW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbDriverDirectory,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [GetPrinterDriverDirectory]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
DeletePrinterDriverW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
LPWSTR pszDriverName
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeletePrinterDriver]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
AddPrintProcessorW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
LPWSTR pszPathName,
|
|||
|
LPWSTR pszPrintProcessorName
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [AddPrintProcessor]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumPrintProcessorsW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbPrintProcessorInfo,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded,
|
|||
|
LPDWORD pcReturned
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [EnumPrintProcessors]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumPrintProcessorDatatypesW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszPrintProcessorName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbDatatypes,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded,
|
|||
|
LPDWORD pcReturned
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [EnumPrintProcessorDatatypes]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
GetPrintProcessorDirectoryW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbPrintProcessorDirectory,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [GetPrintProcessorDirectory]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
StartPagePrinter(
|
|||
|
HANDLE hPrinter
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [StartPagePrinter]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
EndPagePrinter(
|
|||
|
HANDLE hPrinter
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [EndPagePrinter]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
ReadPrinter(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPVOID pBuf,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbRead
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [ReadPrinter]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
GetPrinterDataW(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPWSTR pszValueName,
|
|||
|
LPDWORD pdwType,
|
|||
|
LPBYTE pbData,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [GetPrinterData]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
SetPrinterDataW(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPWSTR pszValueName,
|
|||
|
DWORD dwType,
|
|||
|
LPBYTE pbData,
|
|||
|
DWORD cbData
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [SetPrinterData]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
AddForm(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbForm
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [AddForm]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
DeleteFormW(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPWSTR pszFormName
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeleteForm]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
GetFormW(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPWSTR pszFormName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbForm,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [GetForm]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
SetFormW(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPWSTR pszFormName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbForm
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [SetForm]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumForms(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbForm,
|
|||
|
DWORD cbBuf,
|
|||
|
LPDWORD pcbNeeded,
|
|||
|
LPDWORD pcReturned
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [EnumForms]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HANDLE
|
|||
|
CreatePrinterIC(
|
|||
|
HANDLE hPrinter,
|
|||
|
LPDEVMODE pDevMode
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [CreatePrinterIC]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
PlayGdiScriptOnPrinterIC(
|
|||
|
HANDLE hPrinterIC,
|
|||
|
LPBYTE pbIn,
|
|||
|
DWORD cbIn,
|
|||
|
LPBYTE pbOut,
|
|||
|
DWORD cbOut,
|
|||
|
DWORD ul
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [PlayGdiScriptOnPrinterIC]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
DeletePrinterIC(
|
|||
|
HANDLE hPrinterIC
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeletePrinterIC]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PrinterMessageBoxW(
|
|||
|
HANDLE hPrinter,
|
|||
|
DWORD dwError,
|
|||
|
HWND hWnd,
|
|||
|
LPWSTR pszText,
|
|||
|
LPWSTR pszCaption,
|
|||
|
DWORD dwType
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [PrinterMessageBox]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
AddMonitorW(
|
|||
|
LPWSTR pszName,
|
|||
|
DWORD dwLevel,
|
|||
|
LPBYTE pbMonitorInfo
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [AddMonitor]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
DeleteMonitorW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
LPWSTR pszMonitorName
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeleteMonitor]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
DeletePrintProcessorW(
|
|||
|
LPWSTR pszName,
|
|||
|
LPWSTR pszEnvironment,
|
|||
|
LPWSTR pszPrintProcessorName
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NWSPL [DeletePrintProcessor]\n"));
|
|||
|
#endif
|
|||
|
|
|||
|
SetLastError( ERROR_INVALID_NAME );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Print Provider Miscellaneous Functions
|
|||
|
//
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
VOID
|
|||
|
NwpGetUserInfo(
|
|||
|
LPWSTR *ppszUser,
|
|||
|
BOOL *pfGateway
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Get the user information of the impersonating client.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppszUser - A pointer to buffer to store the Unicode string if
|
|||
|
the impersonated client's user name can be looked up
|
|||
|
successfully. If the conversion was unsuccessful, it points
|
|||
|
to NULL.
|
|||
|
|
|||
|
pfGateway - A pointer to a boolean to store whether the user is
|
|||
|
printing through a gateway or not. We assume that
|
|||
|
if the user sid and the current logon user sid is not
|
|||
|
the same, then the user is printing through gateway.
|
|||
|
Else the user is printing locally.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
LPWSTR pszUserSid = NULL;
|
|||
|
// LPWSTR pszLogonUserSid = NULL; //Removed for Multi-user code merge
|
|||
|
//Terminal Server doesn't user this varible
|
|||
|
//There is no single "Logon User" in Terminal Server
|
|||
|
|
|||
|
//
|
|||
|
// If any error occurs while trying to get the username, just
|
|||
|
// assume no user name and not gateway printing.
|
|||
|
//
|
|||
|
*pfGateway = TRUE;
|
|||
|
*ppszUser = NULL;
|
|||
|
|
|||
|
if ( ((err = NwpGetThreadUserInfo( ppszUser, &pszUserSid )) == NO_ERROR)
|
|||
|
// && ((err = NwpGetLogonUserInfo( &pszLogonUserSid ))) == NO_ERROR) //Removed from Multi-user code merge
|
|||
|
) {
|
|||
|
if ( ThreadIsInteractive() ) {
|
|||
|
*pfGateway = FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
*pfGateway = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NwpGetUserInfo: Thread User= %ws, Thread SID = %ws,\nfGateway = %d\n",
|
|||
|
*ppszUser, pszUserSid, *pfGateway ));
|
|||
|
#endif
|
|||
|
|
|||
|
// } else {
|
|||
|
// if ( _wcsicmp( pszUserSid, pszLogonUserSid ) == 0 ) {
|
|||
|
// *pfGateway = FALSE;
|
|||
|
// }
|
|||
|
|
|||
|
//#if DBG
|
|||
|
// IF_DEBUG(PRINT)
|
|||
|
// KdPrint(("NwpGetUserInfo: Thread User= %ws, Thread SID = %ws,\nCurrent SID = %ws fGateway = %d\n",
|
|||
|
// *ppszUser, pszUserSid, pszLogonUserSid, *pfGateway ));
|
|||
|
//#endif
|
|||
|
// }
|
|||
|
|
|||
|
LocalFree( pszUserSid );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#define SIZE_OF_TOKEN_INFORMATION \
|
|||
|
sizeof( TOKEN_USER ) \
|
|||
|
+ sizeof( SID ) \
|
|||
|
+ sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES
|
|||
|
|
|||
|
DWORD
|
|||
|
NwpGetThreadUserInfo(
|
|||
|
LPWSTR *ppszUser,
|
|||
|
LPWSTR *ppszUserSid
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Get the user name and user sid string of the impersonating client.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppszUser - A pointer to buffer to store the Unicode string
|
|||
|
if the impersonated client's can be looked up. If the
|
|||
|
lookup was unsuccessful, it points to NULL.
|
|||
|
|
|||
|
ppszUserSid - A pointer to buffer to store the string if the impersonated
|
|||
|
client's SID can be expanded successfully into unicode string.
|
|||
|
If the conversion was unsuccessful, it points to NULL.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The error code.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
HANDLE TokenHandle;
|
|||
|
UCHAR TokenInformation[ SIZE_OF_TOKEN_INFORMATION ];
|
|||
|
ULONG ReturnLength;
|
|||
|
|
|||
|
*ppszUser = NULL;
|
|||
|
*ppszUserSid = NULL;
|
|||
|
|
|||
|
// We can use OpenThreadToken because this server thread
|
|||
|
// is impersonating a client
|
|||
|
|
|||
|
if ( !OpenThreadToken( GetCurrentThread(),
|
|||
|
TOKEN_READ,
|
|||
|
TRUE, /* Open as self */
|
|||
|
&TokenHandle ))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NwpGetThreadUserInfo: OpenThreadToken failed: Error %d\n",
|
|||
|
GetLastError()));
|
|||
|
#endif
|
|||
|
return(GetLastError());
|
|||
|
}
|
|||
|
|
|||
|
// notice that we've allocated enough space for the
|
|||
|
// TokenInformation structure. so if we fail, we
|
|||
|
// return a NULL pointer indicating failure
|
|||
|
|
|||
|
|
|||
|
if ( !GetTokenInformation( TokenHandle,
|
|||
|
TokenUser,
|
|||
|
TokenInformation,
|
|||
|
sizeof( TokenInformation ),
|
|||
|
&ReturnLength ))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NwpGetThreadUserInfo: GetTokenInformation failed: Error %d\n",
|
|||
|
GetLastError()));
|
|||
|
#endif
|
|||
|
return(GetLastError());
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle( TokenHandle );
|
|||
|
|
|||
|
// convert the Sid (pointed to by pSid) to its
|
|||
|
// equivalent Unicode string representation.
|
|||
|
|
|||
|
err = NwpGetUserNameFromSid( ((PTOKEN_USER)TokenInformation)->User.Sid,
|
|||
|
ppszUser );
|
|||
|
err = err? err : NwpConvertSid( ((PTOKEN_USER)TokenInformation)->User.Sid,
|
|||
|
ppszUserSid );
|
|||
|
|
|||
|
if ( err )
|
|||
|
{
|
|||
|
if ( *ppszUser )
|
|||
|
LocalFree( *ppszUser );
|
|||
|
|
|||
|
if ( *ppszUserSid )
|
|||
|
LocalFree( *ppszUserSid );
|
|||
|
}
|
|||
|
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
NwpGetUserNameFromSid(
|
|||
|
PSID pUserSid,
|
|||
|
LPWSTR *ppszUserName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Lookup the user name given the user SID.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pUserSid - Points to the user sid to be looked up
|
|||
|
|
|||
|
ppszUserName - A pointer to buffer to store the string if the impersonated
|
|||
|
client's SID can be expanded successfully into unicode string.
|
|||
|
If the conversion was unsuccessful, it points to NULL.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The error code.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS ntstatus;
|
|||
|
|
|||
|
LSA_HANDLE hlsa;
|
|||
|
OBJECT_ATTRIBUTES oa;
|
|||
|
SECURITY_QUALITY_OF_SERVICE sqos;
|
|||
|
PLSA_REFERENCED_DOMAIN_LIST plsardl = NULL;
|
|||
|
PLSA_TRANSLATED_NAME plsatn = NULL;
|
|||
|
|
|||
|
sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|||
|
sqos.ImpersonationLevel = SecurityImpersonation;
|
|||
|
sqos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
|||
|
sqos.EffectiveOnly = FALSE;
|
|||
|
InitializeObjectAttributes( &oa, NULL, 0L, NULL, NULL );
|
|||
|
oa.SecurityQualityOfService = &sqos;
|
|||
|
|
|||
|
ntstatus = LsaOpenPolicy( NULL,
|
|||
|
&oa,
|
|||
|
POLICY_LOOKUP_NAMES,
|
|||
|
&hlsa );
|
|||
|
|
|||
|
if ( NT_SUCCESS( ntstatus ))
|
|||
|
{
|
|||
|
ntstatus = LsaLookupSids( hlsa,
|
|||
|
1,
|
|||
|
&pUserSid,
|
|||
|
&plsardl,
|
|||
|
&plsatn );
|
|||
|
|
|||
|
if ( NT_SUCCESS( ntstatus ))
|
|||
|
{
|
|||
|
UNICODE_STRING *pUnicodeStr = &((*plsatn).Name);
|
|||
|
|
|||
|
*ppszUserName = LocalAlloc( LMEM_ZEROINIT,
|
|||
|
pUnicodeStr->Length+sizeof(WCHAR));
|
|||
|
|
|||
|
if ( *ppszUserName != NULL )
|
|||
|
{
|
|||
|
memcpy( *ppszUserName, pUnicodeStr->Buffer, pUnicodeStr->Length );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ntstatus = STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
LsaFreeMemory( plsardl );
|
|||
|
LsaFreeMemory( plsatn );
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
else
|
|||
|
{
|
|||
|
KdPrint(("NwpGetUserNameFromSid: LsaLookupSids failed: Error = %d\n",
|
|||
|
GetLastError()));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
LsaClose( hlsa );
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
else
|
|||
|
{
|
|||
|
KdPrint(("NwpGetUserNameFromSid: LsaOpenPolicy failed: Error = %d\n",
|
|||
|
GetLastError()));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
return RtlNtStatusToDosError( ntstatus );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
NwpGetLogonUserInfo(
|
|||
|
LPWSTR *ppszUserSid
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Get the logon user sid string from the registry.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppszUserSid - On return, this points to the current logon user
|
|||
|
sid string.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The error code.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
HKEY WkstaKey;
|
|||
|
|
|||
|
LPWSTR CurrentUser = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
|||
|
// \NWCWorkstation\Parameters to get the sid of the CurrentUser
|
|||
|
//
|
|||
|
err = RegOpenKeyExW(
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
NW_WORKSTATION_REGKEY,
|
|||
|
REG_OPTION_NON_VOLATILE,
|
|||
|
KEY_READ,
|
|||
|
&WkstaKey
|
|||
|
);
|
|||
|
|
|||
|
if ( err == NO_ERROR) {
|
|||
|
|
|||
|
//
|
|||
|
// Read the current user SID string so that we
|
|||
|
// know which key is the current user key to open.
|
|||
|
//
|
|||
|
err = NwReadRegValue(
|
|||
|
WkstaKey,
|
|||
|
NW_CURRENTUSER_VALUENAME,
|
|||
|
&CurrentUser
|
|||
|
);
|
|||
|
|
|||
|
RegCloseKey( WkstaKey );
|
|||
|
|
|||
|
if ( err == NO_ERROR) {
|
|||
|
*ppszUserSid = CurrentUser;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return(err);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#define SIZE_OF_STATISTICS_TOKEN_INFORMATION \
|
|||
|
sizeof( TOKEN_STATISTICS )
|
|||
|
|
|||
|
DWORD
|
|||
|
ThreadIsInteractive(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determines if this is an "Interactive" logon thread
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - Thread is interactive
|
|||
|
FALSE - Thread is not interactive
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HANDLE TokenHandle;
|
|||
|
UCHAR TokenInformation[ SIZE_OF_STATISTICS_TOKEN_INFORMATION ];
|
|||
|
WCHAR LogonIdKeyName[NW_MAX_LOGON_ID_LEN];
|
|||
|
|
|||
|
ULONG ReturnLength;
|
|||
|
LUID LogonId;
|
|||
|
LONG RegError;
|
|||
|
HKEY InteractiveLogonKey;
|
|||
|
HKEY OneLogonKey;
|
|||
|
|
|||
|
|
|||
|
// We can use OpenThreadToken because this server thread
|
|||
|
// is impersonating a client
|
|||
|
|
|||
|
if ( !OpenThreadToken( GetCurrentThread(),
|
|||
|
TOKEN_READ,
|
|||
|
TRUE, /* Open as self */
|
|||
|
&TokenHandle ))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("ThreadIsInteractive: OpenThreadToken failed: Error %d\n",
|
|||
|
GetLastError()));
|
|||
|
#endif
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// notice that we've allocated enough space for the
|
|||
|
// TokenInformation structure. so if we fail, we
|
|||
|
// return a NULL pointer indicating failure
|
|||
|
|
|||
|
|
|||
|
if ( !GetTokenInformation( TokenHandle,
|
|||
|
TokenStatistics,
|
|||
|
TokenInformation,
|
|||
|
sizeof( TokenInformation ),
|
|||
|
&ReturnLength ))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("ThreadIsInteractive: GetTokenInformation failed: Error %d\n",
|
|||
|
GetLastError()));
|
|||
|
#endif
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle( TokenHandle );
|
|||
|
|
|||
|
LogonId = ((PTOKEN_STATISTICS)TokenInformation)->AuthenticationId;
|
|||
|
|
|||
|
RegError = RegOpenKeyExW(
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
NW_INTERACTIVE_LOGON_REGKEY,
|
|||
|
REG_OPTION_NON_VOLATILE,
|
|||
|
KEY_READ,
|
|||
|
&InteractiveLogonKey
|
|||
|
);
|
|||
|
|
|||
|
if (RegError != ERROR_SUCCESS) {
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("ThreadIsInteractive: RegOpenKeyExW failed: Error %d\n",
|
|||
|
GetLastError()));
|
|||
|
#endif
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
NwLuidToWStr(&LogonId, LogonIdKeyName);
|
|||
|
|
|||
|
//
|
|||
|
// Open the <LogonIdKeyName> key under Logon
|
|||
|
//
|
|||
|
RegError = RegOpenKeyExW(
|
|||
|
InteractiveLogonKey,
|
|||
|
LogonIdKeyName,
|
|||
|
REG_OPTION_NON_VOLATILE,
|
|||
|
KEY_READ,
|
|||
|
&OneLogonKey
|
|||
|
);
|
|||
|
|
|||
|
if ( RegError == ERROR_SUCCESS ) {
|
|||
|
(void) RegCloseKey(OneLogonKey);
|
|||
|
(void) RegCloseKey(InteractiveLogonKey);
|
|||
|
return TRUE; /* We found it */
|
|||
|
}
|
|||
|
else {
|
|||
|
(void) RegCloseKey(InteractiveLogonKey);
|
|||
|
return FALSE; /* We did not find it */
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
NwpCitrixGetUserInfo(
|
|||
|
LPWSTR *ppszUserSid
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Get the user sid string of the client.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppszUserSid - A pointer to buffer to store the string.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The error code.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
HANDLE TokenHandle;
|
|||
|
UCHAR TokenInformation[ SIZE_OF_TOKEN_INFORMATION ];
|
|||
|
ULONG ReturnLength;
|
|||
|
|
|||
|
*ppszUserSid = NULL;
|
|||
|
|
|||
|
// We can use OpenThreadToken because this server thread
|
|||
|
// is impersonating a client
|
|||
|
|
|||
|
if ( !OpenThreadToken( GetCurrentThread(),
|
|||
|
TOKEN_READ,
|
|||
|
TRUE, /* Open as self */
|
|||
|
&TokenHandle ))
|
|||
|
{
|
|||
|
err = GetLastError();
|
|||
|
if ( err == ERROR_NO_TOKEN ) {
|
|||
|
if ( !OpenProcessToken( GetCurrentProcess(),
|
|||
|
TOKEN_READ,
|
|||
|
&TokenHandle )) {
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NwpGetThreadUserInfo: OpenThreadToken failed: Error %d\n",
|
|||
|
GetLastError()));
|
|||
|
#endif
|
|||
|
|
|||
|
return(GetLastError());
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
return( err );
|
|||
|
}
|
|||
|
|
|||
|
// notice that we've allocated enough space for the
|
|||
|
// TokenInformation structure. so if we fail, we
|
|||
|
// return a NULL pointer indicating failure
|
|||
|
|
|||
|
|
|||
|
if ( !GetTokenInformation( TokenHandle,
|
|||
|
TokenUser,
|
|||
|
TokenInformation,
|
|||
|
sizeof( TokenInformation ),
|
|||
|
&ReturnLength ))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
IF_DEBUG(PRINT)
|
|||
|
KdPrint(("NwpGetThreadUserInfo: GetTokenInformation failed: Error %d\n",
|
|||
|
GetLastError()));
|
|||
|
#endif
|
|||
|
return(GetLastError());
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle( TokenHandle );
|
|||
|
|
|||
|
// convert the Sid (pointed to by pSid) to its
|
|||
|
// equivalent Unicode string representation.
|
|||
|
|
|||
|
err = NwpConvertSid( ((PTOKEN_USER)TokenInformation)->User.Sid,
|
|||
|
ppszUserSid );
|
|||
|
|
|||
|
if ( err )
|
|||
|
{
|
|||
|
if ( *ppszUserSid )
|
|||
|
LocalFree( *ppszUserSid );
|
|||
|
}
|
|||
|
|
|||
|
return err;
|
|||
|
}
|