WindowsXP-SP1/termsrv/syslib/cpmutil.c

470 lines
11 KiB
C

/*************************************************************************
*
* cpmutil.c
*
* System Library Client Printer functions
*
* These functions tend to be includes in the spooler, printman,
* and various port monitor DLL's. So they are here for common code.
*
* Copyright Microsoft, 1998
*
*
*
*
*************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include "winsta.h"
#include "syslib.h"
#if DBG
#define DBGPRINT(x) DbgPrint x
#if DBGTRACE
#define TRACE0(x) DbgPrint x
#define TRACE1(x) DbgPrint x
#else
#define TRACE0(x)
#define TRACE1(x)
#endif
#else
#define DBGPRINT(x)
#define TRACE0(x)
#define TRACE1(x)
#endif
/*****************************************************************************
*
* IsClientPrinterPort
*
* Return whether the name is a client printer port
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
BOOL
IsClientPrinterPort(
PWCHAR pName
)
{
BOOL Result;
PORTNAMETYPE Type;
//
// This just does a brute force compare
//
if( pName == NULL ) {
return( FALSE );
}
if( _wcsicmp( L"Client\\LPT1:", pName ) == 0 ) {
return( TRUE );
}
if( _wcsicmp( L"Client\\LPT2:", pName ) == 0 ) {
return( TRUE );
}
if( _wcsicmp( L"Client\\LPT3:", pName ) == 0 ) {
return( TRUE );
}
if( _wcsicmp( L"Client\\LPT4:", pName ) == 0 ) {
return( TRUE );
}
if( _wcsicmp( L"Client\\COM1:", pName ) == 0 ) {
return( TRUE );
}
if( _wcsicmp( L"Client\\COM2:", pName ) == 0 ) {
return( TRUE );
}
if( _wcsicmp( L"Client\\COM3:", pName ) == 0 ) {
return( TRUE );
}
if( _wcsicmp( L"Client\\COM4:", pName ) == 0 ) {
return( TRUE );
}
//
// See if its a specific port
//
Result = ParseDynamicPortName(
pName,
NULL,
NULL,
&Type
);
if( Type != PortNameUnknown ) {
return( TRUE );
}
return( FALSE );
}
/*****************************************************************************
*
* ExtractDosNamePtr
*
* Extract the DOS name from a client port string.
*
* Returns a pointer to the DOS name which is contained within
* the argument string.
*
* Does not modify the argument string.
*
* ENTRY:
* pName (input)
* Input name string
*
* EXIT:
* NULL: No DOS name
* !=NULL Pointer to DOS name
*
****************************************************************************/
PWCHAR
ExtractDosNamePtr(
PWCHAR pName
)
{
PWCHAR this, prev;
LPWSTR Ptr;
ULONG Len, i, Count;
WCHAR NameBuf[USERNAME_LENGTH+9];
if( pName == NULL ) {
return NULL;
}
// Make sure it starts with "Client\"
if( _wcsnicmp( pName, L"Client\\", 7 ) != 0 ) {
return NULL;
}
// Count the '\'s
prev = pName;
Count = 0;
while( 1 ) {
this = wcschr( prev, L'\\' );
if( this == NULL ) {
break;
}
// Now we must skip over the '\' character
this++;
Count++;
prev = this;
}
if( Count == 0 ) {
DBGPRINT(("ExtractDosNamePtr: Bad Dynamic name format No separators :%ws:\n",pName));
return NULL;
}
//
// Might be Client\LPTx:
//
// NOTE: Windows printers currently do not support
// a generic name.
//
if( Count == 1 ) {
Len = wcslen( pName );
if( Len < 11 ) {
DBGPRINT(("ExtractDosNamePtr: Bad Dynamic name format Len < 11 :%ws:\n",pName));
return NULL;
}
// Skip over "Client\"
Ptr = pName + 7;
return( Ptr );
}
// Skip over "Client\"
Ptr = pName + 7;
//
// Here we must skip over the ICAName# or WinStationName
//
while( *Ptr ) {
if( *Ptr == '\\' ) {
break;
}
Ptr++;
}
//
// Ptr now points to the '\\' after the
// WinStation or ICA name. After this slash,
// is the rest of the printer or port name.
//
Ptr++;
return( Ptr );
}
/*****************************************************************************
*
* ExtractDosName
*
* Extract the DOS name from a client port string.
*
* Returns the DOS name which is in a newly allocated string.
*
* Does not modify the argument string.
*
* ENTRY:
* pName (input)
* Input name string
*
* EXIT:
* NULL: No DOS name
* !=NULL Pointer to DOS name
*
****************************************************************************/
PWCHAR
ExtractDosName(
PWCHAR pName
)
{
PWCHAR Ptr;
PWCHAR pNewName = NULL;
Ptr = ExtractDosNamePtr( pName );
if( Ptr == NULL ) return NULL;
pNewName = RtlAllocateHeap( RtlProcessHeap(), 0, (wcslen( Ptr )+1)*sizeof(WCHAR) );
if( pNewName == NULL ) return NULL;
wcscpy( pNewName, Ptr );
return( pNewName );
}
/*****************************************************************************
*
* ParseDynamicPortName
*
* Parse a dynamic port name into its components.
* (NOTE: This is also in \nt\private\windows\spooler\localspl\citrix\cpmsup.c)
*
* A dynamic port name is of the form:
*
* Client\WinStationName\LPTx:, where WinStationName is the hardwire name
* Client\ICAName#\LPTx:, where ICAName is the ICA configured client name
* Client\LPTx:
* Client\IcaName#\Windows_Printer_Name
* where Windows_Printer_Name is
* the remote windows client print
* manager printer name.
*
* Client\IcaName#\\\ntbuild\print1
* where Windows_Printer_Name is
* the remote windows client print
* manager printer name.
*
* ENTRY:
* pName (input)
* Name to be parsed
*
* EXIT:
* TRUE - Name parsed successfully
* FALSE - Name is incorrect.
*
****************************************************************************/
BOOL
ParseDynamicPortName(
LPWSTR pName,
LPWSTR pUser,
LPWSTR pDosPort,
PORTNAMETYPE *pType
)
{
PWCHAR this, prev;
LPWSTR Ptr;
ULONG Len, i, Count;
WCHAR NameBuf[USERNAME_LENGTH+9];
if( pName == NULL ) {
*pType = PortNameUnknown;
return(FALSE);
}
// Make sure it starts with "Client\"
if( _wcsnicmp( pName, L"Client\\", 7 ) != 0 ) {
*pType = PortNameUnknown;
return(FALSE);
}
// Count the '\'s
prev = pName;
Count = 0;
while( 1 ) {
this = wcschr( prev, L'\\' );
if( this == NULL ) {
break;
}
// Now we must skip over the '\' character
this++;
Count++;
prev = this;
}
if( Count == 0 ) {
DBGPRINT(("ParseDynamicName: Bad Dynamic name format No separators :%ws:\n",pName));
*pType = PortNameUnknown;
return(FALSE);
}
//
// Might be Client\LPTx:
//
// NOTE: Windows printers currently do not support
// a generic name.
//
if( Count == 1 ) {
Len = wcslen( pName );
if( Len < 11 ) {
*pType = PortNameUnknown;
DBGPRINT(("ParseDynamicName: Bad Dynamic name format Len < 11 :%ws:\n",pName));
return(FALSE);
}
// Skip over "Client\"
Ptr = pName + 7;
if( !((_wcsnicmp( Ptr, L"LPT", 3 ) == 0)
||
(_wcsnicmp( Ptr, L"COM", 3 ) == 0)
||
(_wcsnicmp( Ptr, L"AUX", 3 ) == 0)) ) {
*pType = PortNameUnknown;
DBGPRINT(("ParseDynamicName: Bad Dynamic name format Not LPT!COM!AUX :%ws:\n",pName));
return(FALSE);
}
// Range check the number
if( (Ptr[3] < L'1') || (Ptr[3] > L'4') ) {
*pType = PortNameUnknown;
DBGPRINT(("ParseDynamicName: Bad Dynamic name format Number Range:%ws:\n",pName));
return(FALSE);
}
Ptr = ExtractDosNamePtr( pName );
if( Ptr == NULL ) {
// Bad Dos component
*pType = PortNameUnknown;
DBGPRINT(("ParseDynamicName: Bad Dynamic name format DosName :%ws:\n",pName));
return(FALSE);
}
// Copy out the Dos name
if( pDosPort )
wcscpy( pDosPort, Ptr );
// Set the rest of the flags
if( pUser )
pUser[0] = 0;
*pType = PortNameGeneric;
return(TRUE);
}
#ifdef notdef
//
// The rest of the formats have two '\'s
//
if( Count != 2 ) {
DBGPRINT(("ParseDynamicName: Bad Dynamic name format Must be 2 :%ws:\n",pName));
*pType = PortNameUnknown;
return(FALSE);
}
// Get the Dos Name, which could also be a Windows printer name
Ptr = ExtractDosNamePtr( pName );
if( Ptr == NULL ) {
// Bad Dos component
*pType = PortNameUnknown;
return(FALSE);
}
// Copy out the Dos name
if( pDosPort )
wcscpy( pDosPort, Ptr );
#endif
// Skip over "Client\"
Ptr = pName + 7;
//
// Now copy the ICAName#, or WinStationName to a local
// buffer for further processing
i = 0;
NameBuf[i] = 0;
while( *Ptr ) {
if( *Ptr == '\\' ) {
NameBuf[i] = 0;
break;
}
NameBuf[i] = *Ptr;
Ptr++;
i++;
}
//
// Ptr now points to the '\\' after the
// WinStation or ICA name. After this slash,
// is the rest of the printer or port name.
//
Ptr++;
// Copy out the Dos name
if( pDosPort )
wcscpy( pDosPort, Ptr );
//
// See if this is an ICA name, or a WinStation name
//
Ptr = wcschr( NameBuf, L'#' );
if( Ptr != NULL ) {
// NULL terminate the ICAName and copy it out
*Ptr = (WCHAR)NULL;
if( pUser )
wcscpy( pUser, NameBuf );
// Set the type to an ICA named roving WinStation
*pType = PortNameICA;
}
else {
//
// The name will be treated as a WinStation name
//
if( pUser )
wcscpy( pUser, NameBuf );
*pType = PortNameHardWire;
}
return(TRUE);
}