/************************************************************************* * * 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 #include #include #include #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); }