summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/client/nwspl.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/client/nwspl.c')
-rw-r--r--private/nw/svcdlls/nwwks/client/nwspl.c2924
1 files changed, 2924 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/nwspl.c b/private/nw/svcdlls/nwwks/client/nwspl.c
new file mode 100644
index 000000000..e92ad0f5e
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/client/nwspl.c
@@ -0,0 +1,2924 @@
+/*++
+
+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>
+
+//------------------------------------------------------------------
+//
+// Local Functions
+//
+//------------------------------------------------------------------
+
+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
+);
+
+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
+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 );
+ }
+ 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 );
+ }
+
+ 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;
+
+ 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.
+
+--*/
+{
+ 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
+
+ InitializeCriticalSection( &NwSplSem );
+
+ //
+ // 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.
+ // BUG BUG :: Cannot delete once created,dont 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;
+}
+
+
+
+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;
+
+#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 );
+
+ RpcTryExcept
+ {
+ err = NwrStartDocPrinter( (NWWKSTA_PRINTER_CONTEXT) hPrinter,
+ pDocInfo1? pDocInfo1->pDocName : NULL,
+ pszUser,
+ 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 );
+
+ 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 *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;
+ }
+ //FIXFIX Should you delete the registry and port entries
+ //
+ // 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;
+
+ //
+ // 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)
+ )
+ {
+ 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 );
+ LocalFree( pszLogonUserSid );
+ }
+
+}
+
+#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);
+}