summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/client/port.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/client/port.c')
-rw-r--r--private/nw/svcdlls/nwwks/client/port.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/port.c b/private/nw/svcdlls/nwwks/client/port.c
new file mode 100644
index 000000000..4cd287e5c
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/client/port.c
@@ -0,0 +1,449 @@
+/*++
+
+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 )
+ 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 )
+ 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;
+}