|
|
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
port.c
Abstract:
This module contains the code for port handling
Author:
Yi-Hsin Sung (yihsins) 15-May-1993
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <wingdi.h>
#include <winspool.h>
#include <splutil.h>
#include <nwspl.h>
//------------------------------------------------------------------
//
// Local Functions
//
//------------------------------------------------------------------
HMODULE hSpoolssDll = NULL; FARPROC pfnSpoolssEnumPorts = NULL;
HANDLE RevertToPrinterSelf( VOID );
BOOL ImpersonatePrinterClient( HANDLE hToken );
BOOL IsLocalMachine( LPWSTR pszName ) { if ( !pszName || !*pszName ) return TRUE;
if ( *pszName == L'\\' && *(pszName+1) == L'\\') if ( !lstrcmpi( pszName, szMachineName) ) return TRUE;
return FALSE;
}
BOOL PortExists( LPWSTR pPortName, LPDWORD pError ) /* PortExists
* * Calls EnumPorts to check whether the port name already exists. * This asks every monitor, rather than just this one. * The function will return TRUE if the specified port is in the list. * If an error occurs, the return is FALSE and the variable pointed * to by pError contains the return from GetLastError(). * The caller must therefore always check that *pError == NO_ERROR. */ { DWORD cbNeeded; DWORD cReturned; DWORD cbPorts; LPPORT_INFO_1W pPorts; DWORD i; BOOL Found = FALSE;
*pError = NO_ERROR;
if ( !hSpoolssDll ) { if ( hSpoolssDll = LoadLibrary( L"SPOOLSS.DLL" )) { pfnSpoolssEnumPorts = GetProcAddress(hSpoolssDll, "EnumPortsW"); if ( !pfnSpoolssEnumPorts ) { *pError = GetLastError(); FreeLibrary( hSpoolssDll ); hSpoolssDll = NULL; } } else { *pError = GetLastError(); } }
if ( !pfnSpoolssEnumPorts ) return FALSE;
if ( !(*pfnSpoolssEnumPorts)( NULL, 1, NULL, 0, &cbNeeded, &cReturned) ) { if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { cbPorts = cbNeeded;
EnterCriticalSection( &NwSplSem );
pPorts = AllocNwSplMem( LMEM_ZEROINIT, cbPorts ); if ( pPorts ) { if ( (*pfnSpoolssEnumPorts)( NULL, 1, (LPBYTE)pPorts, cbPorts, &cbNeeded, &cReturned)) { for ( i = 0; i < cReturned; i++) { if ( !lstrcmpi( pPorts[i].pName, pPortName) ) Found = TRUE; } } else { *pError = GetLastError(); }
FreeNwSplMem( pPorts, cbPorts ); } else { *pError = ERROR_NOT_ENOUGH_MEMORY; }
LeaveCriticalSection( &NwSplSem );
} else { *pError = GetLastError(); } }
return Found; }
BOOL PortKnown( LPWSTR pPortName ) { PNWPORT pNwPort;
EnterCriticalSection( &NwSplSem );
pNwPort = pNwFirstPort;
while ( pNwPort ) { if ( !lstrcmpi( pNwPort->pName, pPortName ) ) { LeaveCriticalSection( &NwSplSem ); return TRUE; }
pNwPort = pNwPort->pNext; }
LeaveCriticalSection( &NwSplSem ); return FALSE;
}
PNWPORT CreatePortEntry( LPWSTR pPortName ) { PNWPORT pNwPort, pPort; DWORD cb = sizeof(NWPORT) + (wcslen(pPortName) + 1) * sizeof(WCHAR);
if ( pNwPort = AllocNwSplMem( LMEM_ZEROINIT, cb)) { pNwPort->pName = wcscpy((LPWSTR)(pNwPort+1), pPortName); pNwPort->cb = cb; pNwPort->pNext = NULL;
EnterCriticalSection( &NwSplSem );
if ( pPort = pNwFirstPort ) { while ( pPort->pNext ) pPort = pPort->pNext;
pPort->pNext = pNwPort; } else { pNwFirstPort = pNwPort; }
LeaveCriticalSection( &NwSplSem ); }
return pNwPort; }
BOOL DeletePortEntry( LPWSTR pPortName ) /*
Return TRUE when the port name is found and deleted. FALSE otherwise. */ { BOOL fRetVal; PNWPORT pPort, pPrevPort;
EnterCriticalSection( &NwSplSem );
pPort = pNwFirstPort; while ( pPort && lstrcmpi(pPort->pName, pPortName)) { pPrevPort = pPort; pPort = pPort->pNext; }
if (pPort) { if (pPort == pNwFirstPort) { pNwFirstPort = pPort->pNext; } else { pPrevPort->pNext = pPort->pNext; }
FreeNwSplMem( pPort, pPort->cb ); fRetVal = TRUE; } else { fRetVal = FALSE; }
LeaveCriticalSection( &NwSplSem );
return fRetVal; }
VOID DeleteAllPortEntries( VOID ) { PNWPORT pPort, pNextPort;
for ( pPort = pNwFirstPort; pPort; pPort = pNextPort ) { pNextPort = pPort->pNext; FreeNwSplMem( pPort, pPort->cb ); } }
DWORD CreateRegistryEntry( LPWSTR pPortName ) { DWORD err; HANDLE hToken; HKEY hkeyPath; HKEY hkeyPortNames;
hToken = RevertToPrinterSelf();
err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, pszRegistryPath, 0, NULL, 0, KEY_WRITE, NULL, &hkeyPath, NULL );
if ( !err ) { err = RegCreateKeyEx( hkeyPath, pszRegistryPortNames, 0, NULL, 0, KEY_WRITE, NULL, &hkeyPortNames, NULL );
if ( !err ) { err = RegSetValueEx( hkeyPortNames, pPortName, 0, REG_SZ, (LPBYTE) L"", 0 );
RegCloseKey( hkeyPortNames ); } else { KdPrint(("RegCreateKeyEx (%ws) failed: Error = %d\n", pszRegistryPortNames, err ) ); }
RegCloseKey( hkeyPath ); } else { KdPrint(("RegCreateKeyEx (%ws) failed: Error = %d\n", pszRegistryPath, err ) ); }
if ( hToken ) (void)ImpersonatePrinterClient(hToken);
return err; }
DWORD DeleteRegistryEntry( LPWSTR pPortName ) { DWORD err; HANDLE hToken; HKEY hkeyPath; HKEY hkeyPortNames;
hToken = RevertToPrinterSelf();
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, pszRegistryPath, 0, KEY_WRITE, &hkeyPath );
if ( !err ) {
err = RegOpenKeyEx( hkeyPath, pszRegistryPortNames, 0, KEY_WRITE, &hkeyPortNames );
if ( !err ) { err = RegDeleteValue( hkeyPortNames, pPortName ); RegCloseKey( hkeyPortNames ); } else { KdPrint(("RegOpenKeyEx (%ws) failed: Error = %d\n", pszRegistryPortNames, err ) ); }
RegCloseKey( hkeyPath );
} else { KdPrint(("RegOpenKeyEx (%ws) failed: Error = %d\n", pszRegistryPath, err ) ); }
if ( hToken ) (void)ImpersonatePrinterClient(hToken);
return err; }
HANDLE RevertToPrinterSelf( VOID ) { HANDLE NewToken = NULL; HANDLE OldToken; NTSTATUS ntstatus;
ntstatus = NtOpenThreadToken( NtCurrentThread(), TOKEN_IMPERSONATE, TRUE, &OldToken );
if ( !NT_SUCCESS(ntstatus) ) { SetLastError(ntstatus); return FALSE; }
ntstatus = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, (PVOID)&NewToken, (ULONG)sizeof(HANDLE) );
if ( !NT_SUCCESS(ntstatus) ) { SetLastError(ntstatus); return FALSE; }
return OldToken; }
BOOL ImpersonatePrinterClient( HANDLE hToken ) { NTSTATUS ntstatus = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, (PVOID) &hToken, (ULONG) sizeof(HANDLE));
if ( !NT_SUCCESS(ntstatus) ) { SetLastError( ntstatus ); return FALSE; }
(VOID) NtClose(hToken);
return TRUE; }
|