585 lines
15 KiB
C
585 lines
15 KiB
C
/*++
|
||
|
||
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 <windows.h> // IN, OUT, OPTIONAL, LPTSTR, etc.
|
||
#include <lmcons.h> // NET_API_STATUS, CNLEN, RMLEN, etc.
|
||
|
||
// These may be included in any order:
|
||
|
||
#include <debuglib.h> // IF_DEBUG().
|
||
#include <icanon.h> // ITYPE_ equates, NetpNameCanonicalize(), etc.
|
||
#include <names.h> // My prototypes, etc.
|
||
#include <netdebug.h> // NetpKdPrint(()).
|
||
#include <prefix.h> // PREFIX_ equates.
|
||
#include <tstring.h> // ISALPHA(), NetpAlloc routines, TCHAR_EOS, etc.
|
||
#include <winerror.h> // 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
|