WindowsXP-SP1/ds/nw/nwlib/canon.c

481 lines
11 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}