481 lines
10 KiB
C
481 lines
10 KiB
C
/*++
|
||
|
||
Copyright (c) 1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
canon.c
|
||
|
||
Abstract:
|
||
|
||
Contains canonicalization routines for NetWare names.
|
||
|
||
Author:
|
||
|
||
Rita Wong (ritaw) 19-Feb-1993
|
||
|
||
Environment:
|
||
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
|
||
#include <procs.h>
|
||
|
||
|
||
DWORD
|
||
NwLibValidateLocalName(
|
||
IN LPWSTR LocalName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine checks to see if the supplied name is a valid
|
||
DOS device name.
|
||
|
||
Arguments:
|
||
|
||
LocalName - Supplies a local device name. It can be any of
|
||
the following:
|
||
|
||
X:
|
||
LPTn or LPTn:
|
||
COMn or COMn:
|
||
PRN or PRN:
|
||
AUX or AUX:
|
||
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR - LocalName is valid.
|
||
|
||
WN_BAD_NETNAME - LocalName is invalid.
|
||
|
||
--*/
|
||
{
|
||
DWORD LocalNameLength;
|
||
|
||
|
||
//
|
||
// Cannot be a NULL or empty string
|
||
//
|
||
if (LocalName == NULL || *LocalName == 0) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
LocalNameLength = wcslen(LocalName);
|
||
|
||
if (LocalNameLength == 1) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
if (LocalName[LocalNameLength - 1] == L':') {
|
||
if (! IS_VALID_TOKEN(LocalName, LocalNameLength - 1)) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
}
|
||
else {
|
||
if (! IS_VALID_TOKEN(LocalName, LocalNameLength)) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
}
|
||
|
||
if (LocalNameLength == 2) {
|
||
//
|
||
// Must be in the form of X:
|
||
//
|
||
if (! iswalpha(*LocalName)) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
if (LocalName[1] != L':') {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
if (RtlIsDosDeviceName_U(LocalName) == 0) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
//
|
||
// Valid DOS device name but invalid redirection name
|
||
//
|
||
if (_wcsnicmp(LocalName, L"NUL", 3) == 0) {
|
||
return WN_BAD_NETNAME;
|
||
|
||
}
|
||
return NO_ERROR;
|
||
}
|
||
|
||
|
||
DWORD
|
||
NwLibCanonLocalName(
|
||
IN LPWSTR LocalName,
|
||
OUT LPWSTR *OutputBuffer,
|
||
OUT LPDWORD OutputBufferLength OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine canonicalizes the local name by uppercasing the string
|
||
and converting the following:
|
||
|
||
x: -> X:
|
||
LPTn: -> LPTn
|
||
COMn: -> COMn
|
||
PRN or PRN: -> LPT1
|
||
AUX or AUX: -> COM1
|
||
|
||
Arguments:
|
||
|
||
LocalName - Supplies a local device name.
|
||
|
||
OutputBuffer - Receives a pointer to the canonicalized LocalName.
|
||
|
||
OutputBufferLength - Receives the length of the canonicalized name
|
||
in number of characters, if specified.
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR - Successfully canonicalized the local name.
|
||
|
||
WN_BAD_NETNAME - LocalName is invalid.
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY - Could not allocate output buffer.
|
||
|
||
--*/
|
||
{
|
||
DWORD status;
|
||
DWORD LocalNameLength;
|
||
|
||
|
||
status = NwLibValidateLocalName(LocalName);
|
||
|
||
if (status != NO_ERROR) {
|
||
return status;
|
||
}
|
||
|
||
LocalNameLength = wcslen(LocalName);
|
||
|
||
//
|
||
// Allocate output buffer. Should be the size of the LocalName
|
||
// plus 1 for the special case of PRN -> LPT1 or AUX -> COM1.
|
||
//
|
||
*OutputBuffer = (PVOID) LocalAlloc(
|
||
LMEM_ZEROINIT,
|
||
(LocalNameLength + 2) * sizeof(WCHAR)
|
||
);
|
||
|
||
if (*OutputBuffer == NULL) {
|
||
KdPrint(("NWLIB: NwLibCanonLocalName LocalAlloc failed %lu\n",
|
||
GetLastError()));
|
||
return ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
wcscpy(*OutputBuffer, LocalName);
|
||
|
||
if (LocalNameLength > 2) {
|
||
|
||
if (_wcsnicmp(*OutputBuffer, L"PRN", 3) == 0) {
|
||
|
||
//
|
||
// Convert PRN or PRN: to LPT1
|
||
//
|
||
wcscpy(*OutputBuffer, L"LPT1");
|
||
LocalNameLength = 4;
|
||
|
||
}
|
||
else if (_wcsnicmp(*OutputBuffer, L"AUX", 3) == 0) {
|
||
|
||
//
|
||
// Convert AUX or AUX: to COM1
|
||
//
|
||
wcscpy(*OutputBuffer, L"COM1");
|
||
LocalNameLength = 4;
|
||
}
|
||
|
||
//
|
||
// Remove trailing colon, if there is one, and decrement the length
|
||
// of DOS device name.
|
||
//
|
||
if ((*OutputBuffer)[LocalNameLength - 1] == L':') {
|
||
(*OutputBuffer)[--LocalNameLength] = 0;
|
||
}
|
||
}
|
||
|
||
//
|
||
// LocalName is always in uppercase.
|
||
//
|
||
_wcsupr(*OutputBuffer);
|
||
|
||
if (ARGUMENT_PRESENT(OutputBufferLength)) {
|
||
*OutputBufferLength = LocalNameLength;
|
||
}
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
|
||
DWORD
|
||
NwLibCanonRemoteName(
|
||
IN LPWSTR LocalName OPTIONAL,
|
||
IN LPWSTR RemoteName,
|
||
OUT LPWSTR *OutputBuffer,
|
||
OUT LPDWORD OutputBufferLength OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine validates and canonicalizes the supplied
|
||
NetWare UNC name. It can be of any length in the form of:
|
||
|
||
\\Server\Volume\Directory\Subdirectory
|
||
|
||
Arguments:
|
||
|
||
LocalName - Supplies the local device name. If it is NULL, then
|
||
\\Server is an acceptable format for the UNC name.
|
||
|
||
RemoteName - Supplies the UNC name.
|
||
|
||
OutputBuffer - Receives a pointer to the canonicalized RemoteName.
|
||
|
||
OutputBufferLength - Receives the length of the canonicalized name
|
||
in number of characters, if specified.
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR - RemoteName is valid.
|
||
|
||
WN_BAD_NETNAME - RemoteName is invalid.
|
||
|
||
--*/
|
||
{
|
||
DWORD RemoteNameLength;
|
||
DWORD i;
|
||
DWORD TokenLength;
|
||
LPWSTR TokenPtr;
|
||
BOOL fFirstToken = TRUE;
|
||
|
||
|
||
//
|
||
// Cannot be a NULL or empty string
|
||
//
|
||
if (RemoteName == NULL || *RemoteName == 0) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
RemoteNameLength = wcslen(RemoteName);
|
||
|
||
//
|
||
// Must be at least \\x\y if local device name is specified.
|
||
// Otherwise it must be at least \\x.
|
||
//
|
||
if ((RemoteNameLength < 5 && ARGUMENT_PRESENT(LocalName)) ||
|
||
(RemoteNameLength < 3)) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
//
|
||
// First two characters must be "\\"
|
||
//
|
||
if (*RemoteName != L'\\' || RemoteName[1] != L'\\') {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
if (! ARGUMENT_PRESENT(LocalName) &&
|
||
(IS_VALID_TOKEN(&RemoteName[2], RemoteNameLength - 2))) {
|
||
|
||
//
|
||
// Return success for \\Server case.
|
||
//
|
||
|
||
*OutputBuffer = (PVOID) LocalAlloc(
|
||
LMEM_ZEROINIT,
|
||
(RemoteNameLength + 1) * sizeof(WCHAR)
|
||
);
|
||
|
||
if (*OutputBuffer == NULL) {
|
||
KdPrint(("NWLIB: NwLibCanonRemoteName LocalAlloc failed %lu\n",
|
||
GetLastError()));
|
||
return ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
wcscpy(*OutputBuffer, RemoteName);
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
//
|
||
// Must have at least one more backslash after the third character
|
||
//
|
||
if (wcschr(&RemoteName[3], L'\\') == NULL) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
//
|
||
// Last character cannot a backward slash
|
||
//
|
||
if (RemoteName[RemoteNameLength - 1] == L'\\') {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
//
|
||
// Allocate output buffer. Should be the size of the RemoteName
|
||
// and space for an extra character to simplify parsing code below.
|
||
//
|
||
*OutputBuffer = (PVOID) LocalAlloc(
|
||
LMEM_ZEROINIT,
|
||
(RemoteNameLength + 2) * sizeof(WCHAR)
|
||
);
|
||
|
||
|
||
if (*OutputBuffer == NULL) {
|
||
KdPrint(("NWLIB: NwLibCanonRemoteName LocalAlloc failed %lu\n",
|
||
GetLastError()));
|
||
return ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
wcscpy(*OutputBuffer, RemoteName);
|
||
|
||
//
|
||
// Convert all backslashes to NULL terminator, skipping first 2 chars.
|
||
//
|
||
for (i = 2; i < RemoteNameLength; i++) {
|
||
if ((*OutputBuffer)[i] == L'\\') {
|
||
|
||
(*OutputBuffer)[i] = 0;
|
||
|
||
//
|
||
// Two consecutive forward or backslashes is bad.
|
||
//
|
||
if ((i + 1 < RemoteNameLength) &&
|
||
((*OutputBuffer)[i + 1] == L'\\')) {
|
||
|
||
(void) LocalFree((HLOCAL) *OutputBuffer);
|
||
*OutputBuffer = NULL;
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Validate each token of the RemoteName, separated by NULL terminator.
|
||
//
|
||
TokenPtr = *OutputBuffer + 2; // Skip first 2 chars
|
||
|
||
while (*TokenPtr != 0) {
|
||
|
||
TokenLength = wcslen(TokenPtr);
|
||
|
||
if ( ( fFirstToken && !IS_VALID_SERVER_TOKEN(TokenPtr, TokenLength))
|
||
|| ( !fFirstToken && !IS_VALID_TOKEN(TokenPtr, TokenLength))
|
||
)
|
||
{
|
||
(void) LocalFree((HLOCAL) *OutputBuffer);
|
||
*OutputBuffer = NULL;
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
fFirstToken = FALSE;
|
||
TokenPtr += TokenLength + 1;
|
||
}
|
||
|
||
//
|
||
// Convert NULL separators to backslashes
|
||
//
|
||
for (i = 0; i < RemoteNameLength; i++) {
|
||
if ((*OutputBuffer)[i] == 0) {
|
||
(*OutputBuffer)[i] = L'\\';
|
||
}
|
||
}
|
||
|
||
if (ARGUMENT_PRESENT(OutputBufferLength)) {
|
||
*OutputBufferLength = RemoteNameLength;
|
||
}
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
|
||
DWORD
|
||
NwLibCanonUserName(
|
||
IN LPWSTR UserName,
|
||
OUT LPWSTR *OutputBuffer,
|
||
OUT LPDWORD OutputBufferLength OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine canonicalizes the user name by checking to see
|
||
if the name contains any illegal characters.
|
||
|
||
|
||
Arguments:
|
||
|
||
UserName - Supplies a username.
|
||
|
||
OutputBuffer - Receives a pointer to the canonicalized UserName.
|
||
|
||
OutputBufferLength - Receives the length of the canonicalized name
|
||
in number of characters, if specified.
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR - Successfully canonicalized the username.
|
||
|
||
WN_BAD_NETNAME - UserName is invalid.
|
||
|
||
ERROR_NOT_ENOUGH_MEMORY - Could not allocate output buffer.
|
||
|
||
--*/
|
||
{
|
||
DWORD UserNameLength;
|
||
|
||
|
||
//
|
||
// Cannot be a NULL or empty string
|
||
//
|
||
if (UserName == NULL) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
UserNameLength = wcslen(UserName);
|
||
|
||
if (! IS_VALID_TOKEN(UserName, UserNameLength)) {
|
||
return WN_BAD_NETNAME;
|
||
}
|
||
|
||
//
|
||
// Allocate output buffer. Should be the size of the UserName
|
||
// plus 1 for the special case of PRN -> LPT1 or AUX -> COM1.
|
||
//
|
||
*OutputBuffer = (PVOID) LocalAlloc(
|
||
LMEM_ZEROINIT,
|
||
(UserNameLength + 1) * sizeof(WCHAR)
|
||
);
|
||
|
||
if (*OutputBuffer == NULL) {
|
||
KdPrint(("NWLIB: NwLibCanonUserName LocalAlloc failed %lu\n",
|
||
GetLastError()));
|
||
return ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
wcscpy(*OutputBuffer, UserName);
|
||
|
||
if (ARGUMENT_PRESENT(OutputBufferLength)) {
|
||
*OutputBufferLength = UserNameLength;
|
||
}
|
||
|
||
return NO_ERROR;
|
||
}
|