337 lines
8.1 KiB
C
337 lines
8.1 KiB
C
/*++
|
||
|
||
Copyright (c) 1989-91 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
namecan.c
|
||
|
||
Abstract:
|
||
|
||
Net name canonicalization routines:
|
||
|
||
NetpwNameCanonicalize
|
||
|
||
Author:
|
||
|
||
Richard L Firth (rfirth) 06-Jan-1992
|
||
Chandana Surlu (chandans) 19-Dec-1979 Modified to use this util on WIN9x
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#ifdef WIN32_CHICAGO
|
||
// yes, this is strange, but all internal data for DsGetDcname are maintained
|
||
// in unicode but we don't define UNICODE globally. Therefore, this hack
|
||
// -ChandanS
|
||
#define UNICODE 1
|
||
#endif // WIN32_CHICAGO
|
||
#include "nticanon.h"
|
||
#include <netlibnt.h> // NetpNtStatusToApiStatus
|
||
|
||
|
||
//
|
||
// data
|
||
//
|
||
|
||
static TCHAR szShareTrailChars[] = TEXT(". ");
|
||
|
||
//
|
||
// functions
|
||
//
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpwNameCanonicalize(
|
||
IN LPTSTR Name,
|
||
OUT LPTSTR Outbuf,
|
||
IN DWORD OutbufLen,
|
||
IN DWORD NameType,
|
||
IN DWORD Flags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
NetpwNameCanonicalize converts a LANMAN object name to canonical
|
||
form. In the current implementation, that simply means converting
|
||
the name to upper case (except for passwords).
|
||
|
||
This function supports canonicalization in place because in the
|
||
current world, canonicalization just consists of convert a name to
|
||
upper case. If in the future canonicalization becomes more
|
||
sophisticated, this function will have to allocate a buffer
|
||
internally to allow it to do canonicalization.
|
||
|
||
Arguments:
|
||
|
||
Name - The name to canonicalize.
|
||
|
||
Outbuf - The place to store the canonicalized version of the name.
|
||
Note that if <Name> and <Outbuf> are the same it will
|
||
canonicalize the name in place.
|
||
|
||
OutbufLen - The size, in bytes, of <Outbuf>.
|
||
|
||
NameType - The type of the LANMAN object names. Valid values are
|
||
specified by NAMETYPE_* manifests in NET\H\ICANON.H.
|
||
|
||
Flags - Flags to determine operation. Currently defined values are:
|
||
|
||
CrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrL
|
||
|
||
where:
|
||
|
||
C = LM2.x compatible name canonicalization
|
||
|
||
r = Reserved. MBZ.
|
||
|
||
L = If set, the function requires the length of the output
|
||
buffer to be sufficient to hold any name of the specified
|
||
type (e.g. CNLEN+1 if the name type is NAMETYPE_COMPUTER).
|
||
Otherwise, the buffer length only needs to be large
|
||
enough to hold the canonicalized version of the input
|
||
name specified in this invocation of the function (e.g.
|
||
5, if the canonicalized name is "TEST").
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS
|
||
Success - NERR_Success
|
||
|
||
Failure - ERROR_INVALID_PARAMETER
|
||
Flags has a reserved bit on
|
||
|
||
ERROR_INVALID_NAME
|
||
Supplied name cannot be successfully canonicalized
|
||
|
||
NERR_BufTooSmall
|
||
Caller's output buffer not large enough to hold canonicalized
|
||
name, or maximum canonicalized name for type if L bit on in
|
||
Flags
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS RetVal = 0;
|
||
DWORD NameLen;
|
||
DWORD MaxNameLen;
|
||
BOOL UpperCase = FALSE; // default for NT names
|
||
|
||
|
||
#ifdef CANONDBG
|
||
DbgPrint("NetpwNameCanonicalize\n");
|
||
#endif
|
||
|
||
//
|
||
// Parameter validation
|
||
//
|
||
|
||
if (Flags & INNCA_FLAGS_RESERVED) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Compute the length of the string
|
||
//
|
||
// Note that share names need special handling, because trailing
|
||
// dots and spaces are not significant.
|
||
//
|
||
|
||
#ifndef WIN32_CHICAGO
|
||
|
||
if (NameType == NAMETYPE_SHARE) {
|
||
NameLen = (DWORD)(strtail(Name, szShareTrailChars) - Name);
|
||
} else {
|
||
NameLen = STRLEN(Name);
|
||
}
|
||
|
||
#else
|
||
|
||
NameLen = STRLEN(Name);
|
||
|
||
#endif // WIN32_CHICAGO
|
||
|
||
RetVal = NetpwNameValidate(Name, NameType, 0L);
|
||
if (RetVal) {
|
||
return RetVal;
|
||
}
|
||
|
||
//
|
||
// Determine the size of the buffer needed and whether or not to
|
||
// upper case the name.
|
||
//
|
||
|
||
switch (NameType) {
|
||
case NAMETYPE_USER:
|
||
if (Flags & LM2X_COMPATIBLE) {
|
||
MaxNameLen = LM20_UNLEN;
|
||
UpperCase = TRUE;
|
||
} else {
|
||
MaxNameLen = UNLEN;
|
||
}
|
||
break;
|
||
|
||
case NAMETYPE_GROUP:
|
||
if (Flags & LM2X_COMPATIBLE) {
|
||
MaxNameLen = LM20_GNLEN;
|
||
UpperCase = TRUE;
|
||
} else {
|
||
MaxNameLen = GNLEN;
|
||
}
|
||
break;
|
||
|
||
case NAMETYPE_COMPUTER:
|
||
if (Flags & LM2X_COMPATIBLE) {
|
||
MaxNameLen = LM20_CNLEN;
|
||
UpperCase = TRUE;
|
||
} else {
|
||
MaxNameLen = MAX_PATH-1; // allow for null
|
||
}
|
||
break;
|
||
|
||
case NAMETYPE_EVENT: // Used only by the Alerter service
|
||
MaxNameLen = EVLEN;
|
||
UpperCase = TRUE;
|
||
break;
|
||
|
||
case NAMETYPE_DOMAIN:
|
||
if (Flags & LM2X_COMPATIBLE) {
|
||
MaxNameLen = LM20_DNLEN;
|
||
UpperCase = TRUE;
|
||
} else {
|
||
MaxNameLen = DNLEN;
|
||
}
|
||
break;
|
||
|
||
case NAMETYPE_SERVICE:
|
||
if (Flags & LM2X_COMPATIBLE) {
|
||
MaxNameLen = LM20_SNLEN;
|
||
UpperCase = TRUE;
|
||
} else {
|
||
MaxNameLen = SNLEN;
|
||
}
|
||
break;
|
||
|
||
case NAMETYPE_NET:
|
||
//#if DBG
|
||
// DbgPrint("NAMETYPE_NET being used. Please notify rfirth. Hit 'i' to continue\n");
|
||
// ASSERT(FALSE);
|
||
//#endif
|
||
MaxNameLen = MAX_PATH - 1; // allow for NULL
|
||
UpperCase = TRUE;
|
||
break;
|
||
|
||
case NAMETYPE_SHARE:
|
||
if (Flags & LM2X_COMPATIBLE) {
|
||
MaxNameLen = LM20_NNLEN;
|
||
UpperCase = TRUE;
|
||
} else {
|
||
MaxNameLen = NNLEN;
|
||
}
|
||
break;
|
||
|
||
case NAMETYPE_PASSWORD:
|
||
if (Flags & LM2X_COMPATIBLE) {
|
||
MaxNameLen = LM20_PWLEN;
|
||
} else {
|
||
MaxNameLen = PWLEN;
|
||
}
|
||
break;
|
||
|
||
case NAMETYPE_SHAREPASSWORD:
|
||
MaxNameLen = SHPWLEN;
|
||
break;
|
||
|
||
case NAMETYPE_MESSAGE:
|
||
//#if DBG
|
||
// DbgPrint("NAMETYPE_MESSAGE being used. Please notify rfirth. Hit 'i' to continue\n");
|
||
// ASSERT(FALSE);
|
||
//#endif
|
||
MaxNameLen = (MAX_PATH - 1);
|
||
UpperCase = TRUE;
|
||
break;
|
||
|
||
case NAMETYPE_MESSAGEDEST:
|
||
MaxNameLen = MAX_PATH - 1; // allow for NULL
|
||
UpperCase = TRUE;
|
||
break;
|
||
|
||
case NAMETYPE_WORKGROUP:
|
||
if (Flags & LM2X_COMPATIBLE) {
|
||
MaxNameLen = LM20_DNLEN;
|
||
UpperCase = TRUE;
|
||
} else {
|
||
MaxNameLen = DNLEN;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
|
||
//
|
||
// The caller specified an invalid name type.
|
||
//
|
||
// NOTE: This should already have been caught by
|
||
// NetpwNameValidate(), so this code should
|
||
// never be reached.
|
||
//
|
||
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Check the buffer is large enough, abort if it isn't
|
||
//
|
||
|
||
if (Flags & INNCA_FLAGS_FULL_BUFLEN) {
|
||
NameLen = MaxNameLen;
|
||
}
|
||
if (OutbufLen < (NameLen + 1) * sizeof(TCHAR)) {
|
||
return NERR_BufTooSmall;
|
||
}
|
||
|
||
//
|
||
// If the input buffer and output buffer are not the same, copy
|
||
// the name to the output buffer.
|
||
//
|
||
|
||
if (Name != Outbuf) {
|
||
STRNCPY(Outbuf, Name, NameLen);
|
||
}
|
||
|
||
//
|
||
// Note that we copy in a terminating null even if the input and
|
||
// output buffer are the same. This is to handle the case of
|
||
// a share name from which trailing characters need to be stripped.
|
||
//
|
||
|
||
Outbuf[NameLen] = TCHAR_EOS;
|
||
|
||
#ifndef WIN32_CHICAGO
|
||
// We never set Uppercase anyway. -ChandanS
|
||
|
||
//
|
||
// Upper-case the name, if appropriate
|
||
//
|
||
|
||
if (UpperCase) {
|
||
|
||
NTSTATUS status;
|
||
UNICODE_STRING stringOut;
|
||
UNICODE_STRING stringIn;
|
||
|
||
RtlInitUnicodeString(&stringIn, Name);
|
||
stringOut.Buffer = Outbuf;
|
||
stringOut.Length = 0;
|
||
stringOut.MaximumLength = (USHORT)OutbufLen;
|
||
status = RtlUpcaseUnicodeString(&stringOut, &stringIn, FALSE);
|
||
if (!NT_SUCCESS(status)) {
|
||
return NetpNtStatusToApiStatus(status);
|
||
}
|
||
}
|
||
#endif // WIN32_CHICAGO
|
||
return NERR_Success;
|
||
}
|