Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

449 lines
9.0 KiB

/*++
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;
}