/*++ Copyright (c) 1991-1993 Microsoft Corporation Module Name: Names.c Abstract: This module contains routines for dealing with network-related names. Author: John Rogers (JohnRo) 25-Feb-1991 Environment: Portable to more or less any environment. (Uses Win32 typedefs.) Requires ANSI C extensions: slash-slash comments long external names _stricmp(), _strnicmp() Revision History: 25-Feb-1991 JohnRo Created 15-Mar-1991 JohnRo Fixed bug in NetpIsRemoteNameValid(). Some minor style changes. 20-Mar-1991 RitaW Added NetpCanonRemoteName(). 09-Apr-1991 JohnRo ANSI-ize (use _stricmp instead of _stricmp). Deleted tabs. 19-Aug-1991 JohnRo Allow UNICODE use. 30-Sep-1991 JohnRo More work toward UNICODE. 20-Oct-1992 JohnRo RAID 9020: setup: PortUas fails ("prompt on conflicts" version). Do full syntax checks on computer name. 26-Jan-1993 JohnRo RAID 8683: PortUAS should set primary group from Mac parms. Made changes suggested by PC-LINT 5.0 08-Feb-1993 JohnRo RAID 10299: portuas: generate assert in netlib/names.c 15-Apr-1993 JohnRo RAID 6167: avoid _access violation or assert with WFW print server. --*/ // These must be included first: #include // IN, OUT, OPTIONAL, LPTSTR, etc. #include // NET_API_STATUS, CNLEN, RMLEN, etc. // These may be included in any order: #include // IF_DEBUG(). #include // ITYPE_ equates, NetpNameCanonicalize(), etc. #include // My prototypes, etc. #include // NetpKdPrint(()). #include // PREFIX_ equates. #include // ISALPHA(), NetpAlloc routines, TCHAR_EOS, etc. #include // NO_ERROR. // // Canon routines don't have a print Q support, so we (like everyone else) // have to treat them as share names. // #if (QNLEN != NNLEN) # error QNLEN and NNLEN are not equal #endif #ifndef NAMETYPE_PRINTQ #define NAMETYPE_PRINTQ NAMETYPE_SHARE #endif // This extracts a group name from "mGroup:" format. // Note that other chars may appear after the colon; they are ignored. NET_API_STATUS NetpGetPrimaryGroupFromMacField( IN LPCTSTR MacPrimaryField, // name in "mGroup:" format. OUT LPCTSTR * GroupNamePtr // alloc and set ptr. ) { LPTSTR ColonPtr; DWORD GroupLen; // Length of group (in characters). TCHAR GroupName[LM20_GNLEN+1]; LPTSTR GroupNameCopy; DWORD StringLen; // Avoid confusing caller's cleanup code. if (GroupNamePtr == NULL) { return (ERROR_INVALID_PARAMETER); } *GroupNamePtr = NULL; // Check for other caller errors. if (MacPrimaryField==NULL) { return (ERROR_INVALID_PARAMETER); // Empty field is not valid. } else if ( (*MacPrimaryField) != TEXT('m') ) { return (ERROR_INVALID_PARAMETER); // Must start with lower case 'm'. } StringLen = STRLEN( MacPrimaryField ); if (StringLen <= 2) { // Must be room for 'm', group, ':' (at least 3). return (ERROR_INVALID_PARAMETER); } ColonPtr = STRCHR( MacPrimaryField, TCHAR_COLON ); if (ColonPtr == NULL) { return (ERROR_INVALID_PARAMETER); // No, not valid (must have colon). } // Compute group length in characters, without 'm' or ':'. GroupLen = (DWORD) ((ColonPtr - MacPrimaryField) - 1); if (GroupLen == 0) { return (ERROR_INVALID_PARAMETER); // No, not valid (missing group). } if (GroupLen > LM20_GNLEN) { return (ERROR_INVALID_PARAMETER); // No, not valid (too long). } (VOID) STRNCPY( GroupName, // dest &MacPrimaryField[1], // src (after 'm') GroupLen ); // char count GroupName[ GroupLen ] = TCHAR_EOS; if ( !NetpIsGroupNameValid( GroupName ) ) { return (ERROR_INVALID_PARAMETER); } GroupNameCopy = NetpAllocWStrFromWStr( GroupName ); if (GroupNameCopy == NULL) { return (ERROR_NOT_ENOUGH_MEMORY); } *GroupNamePtr = GroupNameCopy; return (NO_ERROR); } // NetpGetPrimaryGroupFromMacField BOOL NetpIsComputerNameValid( IN LPTSTR ComputerName ) /*++ Routine Description: NetpIsComputerNameValid checks for "server" (not "\\server") format. The name is only checked syntactically; no attempt is made to determine whether or not a server with that name actually exists. Arguments: ComputerName - Supplies an alleged computer (server) name. Return Value: BOOL - TRUE if name is syntactically valid, FALSE otherwise. --*/ { NET_API_STATUS ApiStatus; TCHAR CanonBuf[MAX_PATH]; if (ComputerName == (LPTSTR) NULL) { return (FALSE); } if ( (*ComputerName) == TCHAR_EOS ) { return (FALSE); } ApiStatus = NetpNameCanonicalize( NULL, // no server name ComputerName, // name to validate CanonBuf, // output buffer sizeof( CanonBuf ), // output buffer size NAMETYPE_COMPUTER, // type 0 ); // flags: none IF_DEBUG( NAMES ) { if (ApiStatus != NO_ERROR) { NetpKdPrint(( PREFIX_NETLIB "NetpIsComputerNameValid: err " FORMAT_API_STATUS " after canon of '" FORMAT_LPTSTR "'.\n", ApiStatus, ComputerName )); } } return (ApiStatus == NO_ERROR); } // NetpIsComputerNameValid BOOL NetpIsDomainNameValid( IN LPTSTR DomainName ) /*++ Routine Description: NetpIsDomainNameValid checks for "domain" format. The name is only checked syntactically; no attempt is made to determine whether or not a domain with that name actually exists. Arguments: DomainName - Supplies an alleged Domain name. Return Value: BOOL - TRUE if name is syntactically valid, FALSE otherwise. --*/ { NET_API_STATUS ApiStatus; TCHAR CanonBuf[DNLEN+1]; if (DomainName == (LPTSTR) NULL) { return (FALSE); } if ( (*DomainName) == TCHAR_EOS ) { return (FALSE); } ApiStatus = NetpNameCanonicalize( NULL, // no server name DomainName, // name to validate CanonBuf, // output buffer (DNLEN+1) * sizeof(TCHAR), // output buffer size NAMETYPE_DOMAIN, // type 0 ); // flags: none IF_DEBUG( NAMES ) { if (ApiStatus != NO_ERROR) { NetpKdPrint(( PREFIX_NETLIB "NetpIsDomainNameValid: err " FORMAT_API_STATUS " after canon of '" FORMAT_LPTSTR "'.\n", ApiStatus, DomainName )); } } return (ApiStatus == NO_ERROR); } // NetpIsDomainNameValid BOOL NetpIsShareNameValid( IN LPTSTR ShareName ) /*++ Routine Description: NetpIsShareNameValid checks for "share" format. The name is only checked syntactically; no attempt is made to determine whether or not a share with that name actually exists. Arguments: ShareName - Supplies an alleged Share name. Return Value: BOOL - TRUE if name is syntactically valid, FALSE otherwise. --*/ { NET_API_STATUS ApiStatus; TCHAR CanonBuf[SNLEN+1]; if (ShareName == (LPTSTR) NULL) { return (FALSE); } if ( (*ShareName) == TCHAR_EOS ) { return (FALSE); } ApiStatus = NetpNameCanonicalize( NULL, // no server name ShareName, // name to validate CanonBuf, // output buffer (SNLEN+1) * sizeof(TCHAR), // output buffer size NAMETYPE_SHARE, // type 0 ); // flags: none IF_DEBUG( NAMES ) { if (ApiStatus != NO_ERROR) { NetpKdPrint(( PREFIX_NETLIB "NetpIsShareNameValid: err " FORMAT_API_STATUS " after canon of '" FORMAT_LPTSTR "'.\n", ApiStatus, ShareName )); } } return (ApiStatus == NO_ERROR); } // NetpIsShareNameValid BOOL NetpIsGroupNameValid( IN LPTSTR GroupName ) { NET_API_STATUS ApiStatus; TCHAR CanonBuf[UNLEN+1]; if (GroupName == (LPTSTR) NULL) { return (FALSE); } if ( (*GroupName) == TCHAR_EOS ) { return (FALSE); } ApiStatus = NetpNameCanonicalize( NULL, // no server name GroupName, // name to validate CanonBuf, // output buffer (UNLEN+1) * sizeof(TCHAR), // output buffer size NAMETYPE_GROUP, // type 0 ); // flags: none IF_DEBUG( NAMES ) { if (ApiStatus != NO_ERROR) { NetpKdPrint(( PREFIX_NETLIB "NetpIsGroupNameValid: err " FORMAT_API_STATUS " after canon of '" FORMAT_LPTSTR "'.\n", ApiStatus, GroupName )); } } return (ApiStatus == NO_ERROR); } // NetpIsGroupNameValid // This checks for "mGroup:" format. // Note that other chars may appear after the colon; they are ignored. BOOL NetpIsMacPrimaryGroupFieldValid( IN LPCTSTR MacPrimaryField ) { LPTSTR ColonPtr; DWORD GroupLen; // Length of group (in characters). TCHAR GroupName[LM20_GNLEN+1]; DWORD StringLen; if (MacPrimaryField==NULL) { return (FALSE); // Empty field is not valid. } else if ( (*MacPrimaryField) != TEXT('m') ) { return (FALSE); // Must start with lower case 'm'. } StringLen = STRLEN( MacPrimaryField ); if (StringLen <= 2) { // Must be room for 'm', group, ':' (at least 3). return (FALSE); } ColonPtr = STRCHR( MacPrimaryField, TCHAR_COLON ); if (ColonPtr == NULL) { return (FALSE); // No, not valid (must have colon). } // Compute group length in characters, without 'm' or ':'. GroupLen = (DWORD) ((ColonPtr - MacPrimaryField) - 1); if (GroupLen == 0) { return (FALSE); // No, not valid (missing group). } if (GroupLen > LM20_GNLEN) { return (FALSE); // No, not valid (too long). } (VOID) STRNCPY( GroupName, // dest &MacPrimaryField[1], // src (after 'm') GroupLen ); // char count GroupName[ GroupLen ] = TCHAR_EOS; return (NetpIsGroupNameValid( GroupName )); } // NetpIsMacPrimaryGroupFieldValid BOOL NetpIsPrintQueueNameValid( IN LPCTSTR QueueName ) { NET_API_STATUS ApiStatus; TCHAR CanonBuf[ MAX_PATH ]; if (QueueName == NULL) { return (FALSE); } if ( (*QueueName) == TCHAR_EOS ) { return (FALSE); } ApiStatus = NetpNameCanonicalize( NULL, // no server name (LPTSTR) QueueName, // name to validate CanonBuf, // output buffer sizeof( CanonBuf ), // output buffer size NAMETYPE_PRINTQ, // type 0 ); // flags: none IF_DEBUG( NAMES ) { if (ApiStatus != NO_ERROR) { NetpKdPrint(( PREFIX_NETLIB "NetpIsPrintQueuNameValid: err " FORMAT_API_STATUS " after canon of '" FORMAT_LPTSTR "'.\n", ApiStatus, QueueName )); } } return (ApiStatus == NO_ERROR); } // NetpIsPrintQueueNameValid BOOL NetpIsRemoteNameValid( IN LPTSTR RemoteName ) /*++ Routine Description: NetpIsRemoteNameValid checks for "\\server\share" format. The name is only checked syntactically; no attempt is made to determine whether or not a server or share with that name actually exists. Forward slashes are acceptable. Arguments: RemoteName - Supplies an alleged remote name. Return Value: BOOL - TRUE if name is syntactically valid, FALSE otherwise. --*/ { if (RemoteName == (LPTSTR) NULL) { return (FALSE); } // // Shortest is \\x\y (5). // if ((STRLEN(RemoteName) < 5) || (STRLEN(RemoteName) > MAX_PATH )) { return (FALSE); } // // First two characters must be slashes. // if (((RemoteName[0] != '\\') && (RemoteName[0] != '/')) || ((RemoteName[1] != '\\') && (RemoteName[1] != '/'))) { return (FALSE); } // // Three leading \ or / is illegal. // if ((RemoteName[2] == '\\') || (RemoteName[2] == '/')) { return (FALSE); } // // Must have a least 1 \ or / inside. // if ((STRCHR(&RemoteName[2], '\\') == NULL) && (STRCHR(&RemoteName[2], '/') == NULL)) { return (FALSE); } return (TRUE); } // NetpIsRemoteNameValid BOOL NetpIsUncComputerNameValid( IN LPTSTR ComputerName ) /*++ Routine Description: NetpIsUncComputerNameValid checks for "\\server" format. The name is only checked syntactically; no attempt is made to determine whether or not a server with that name actually exists. Arguments: ComputerName - Supplies an alleged computer (server) name. Return Value: BOOL - TRUE if name is syntactically valid, FALSE otherwise. --*/ { if (ComputerName == (LPTSTR) NULL) { return (FALSE); } if ( ! IS_PATH_SEPARATOR( ComputerName[0] ) ) { return (FALSE); } if ( ! IS_PATH_SEPARATOR( ComputerName[1] ) ) { return (FALSE); } return (NetpIsComputerNameValid( &ComputerName[2]) ); } // NetpIsUncComputerNameValid BOOL NetpIsUserNameValid( IN LPTSTR UserName ) { NET_API_STATUS ApiStatus; TCHAR CanonBuf[UNLEN+1]; if (UserName == (LPTSTR) NULL) { return (FALSE); } if ( (*UserName) == TCHAR_EOS ) { return (FALSE); } ApiStatus = NetpNameCanonicalize( NULL, // no server name UserName, // name to validate CanonBuf, // output buffer (UNLEN+1) * sizeof(TCHAR), // output buffer size NAMETYPE_USER, // type 0 ); // flags: none IF_DEBUG( NAMES ) { if (ApiStatus != NO_ERROR) { NetpKdPrint(( PREFIX_NETLIB "NetpIsUserNameValid: err " FORMAT_API_STATUS " after canon of '" FORMAT_LPTSTR "'.\n", ApiStatus, UserName )); } } return (ApiStatus == NO_ERROR); } // NetpIsUserNameValid