diff options
Diffstat (limited to 'private/nw/svcdlls/nwwks/lib/misc.c')
-rw-r--r-- | private/nw/svcdlls/nwwks/lib/misc.c | 785 |
1 files changed, 785 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/lib/misc.c b/private/nw/svcdlls/nwwks/lib/misc.c new file mode 100644 index 000000000..e28db0a84 --- /dev/null +++ b/private/nw/svcdlls/nwwks/lib/misc.c @@ -0,0 +1,785 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + api.c + +Abstract: + + This module contains misc APIs that are used by the + NWC wksta. + +Author: + + ChuckC 2-Mar-94 Created + + +Revision History: + +--*/ + + +#include <stdlib.h> +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <windows.h> +#include <nwcons.h> +#include <nwmisc.h> +#include <nwapi32.h> +#include "nwstatus.h" +#include "nwevent.h" + +DWORD +NwMapStatus( + IN NTSTATUS NtStatus + ); + +DWORD +NwOpenPreferredServer( + PHANDLE ServerHandle + ); + +NTSTATUS +NwOpenHandle( + IN PUNICODE_STRING ObjectName, + IN BOOL ValidateFlag, + OUT PHANDLE ObjectHandle + ); + +NTSTATUS +NwCallNtOpenFile( + OUT PHANDLE ObjectHandle, + IN ACCESS_MASK DesiredAccess, + IN PUNICODE_STRING ObjectName, + IN ULONG OpenOptions + ); + + +// +// list of error mappings known for E3H calls. we do not have a single list +// because Netware reuses the numbers depending on call. +// + +typedef struct _ERROR_MAP_ENTRY +{ + UCHAR NetError; + NTSTATUS ResultingStatus; +} ERROR_MAP_ENTRY ; + +ERROR_MAP_ENTRY Error_Map_Bindery[] = +{ + + // + // NetWare specific error mappings. Specific to E3H. + // + { 1, STATUS_DISK_FULL }, + {128, STATUS_SHARING_VIOLATION }, + {129, STATUS_INSUFF_SERVER_RESOURCES }, + {130, STATUS_ACCESS_DENIED }, + {131, STATUS_DATA_ERROR }, + {132, STATUS_ACCESS_DENIED }, + {133, STATUS_ACCESS_DENIED }, + {134, STATUS_ACCESS_DENIED }, + {135, STATUS_OBJECT_NAME_INVALID }, + {136, STATUS_INVALID_HANDLE }, + {137, STATUS_ACCESS_DENIED }, + {138, STATUS_ACCESS_DENIED }, + {139, STATUS_ACCESS_DENIED }, + {140, STATUS_ACCESS_DENIED }, + {141, STATUS_SHARING_VIOLATION }, + {142, STATUS_SHARING_VIOLATION }, + {143, STATUS_ACCESS_DENIED }, + {144, STATUS_ACCESS_DENIED }, + {145, STATUS_OBJECT_NAME_COLLISION }, + {146, STATUS_OBJECT_NAME_COLLISION }, + {147, STATUS_ACCESS_DENIED }, + {148, STATUS_ACCESS_DENIED }, + {150, STATUS_INSUFF_SERVER_RESOURCES }, + {151, STATUS_NO_SPOOL_SPACE }, + {152, STATUS_NO_SUCH_DEVICE }, + {153, STATUS_DISK_FULL }, + {154, STATUS_NOT_SAME_DEVICE }, + {155, STATUS_INVALID_HANDLE }, + {156, STATUS_OBJECT_PATH_NOT_FOUND }, + {157, STATUS_INSUFF_SERVER_RESOURCES }, + {158, STATUS_OBJECT_PATH_INVALID }, + {159, STATUS_SHARING_VIOLATION }, + {160, STATUS_DIRECTORY_NOT_EMPTY }, + {161, STATUS_DATA_ERROR }, + {162, STATUS_SHARING_VIOLATION }, + {192, STATUS_ACCESS_DENIED }, + {198, STATUS_ACCESS_DENIED }, + {211, STATUS_ACCESS_DENIED }, + {212, STATUS_PRINT_QUEUE_FULL }, + {213, STATUS_PRINT_CANCELLED }, + {214, STATUS_ACCESS_DENIED }, + {215, STATUS_PASSWORD_RESTRICTION }, + {216, STATUS_PASSWORD_RESTRICTION }, + {220, STATUS_ACCOUNT_DISABLED }, + {222, STATUS_PASSWORD_EXPIRED }, + {223, STATUS_PASSWORD_EXPIRED }, + {239, STATUS_OBJECT_NAME_INVALID }, + {240, STATUS_OBJECT_NAME_INVALID }, + {251, STATUS_INVALID_PARAMETER }, + {252, STATUS_NO_MORE_ENTRIES }, + {253, STATUS_FILE_LOCK_CONFLICT }, + {254, STATUS_FILE_LOCK_CONFLICT }, + {255, STATUS_UNSUCCESSFUL} +}; + + +ERROR_MAP_ENTRY Error_Map_General[] = +{ + { 1, STATUS_DISK_FULL }, + {128, STATUS_SHARING_VIOLATION }, + {129, STATUS_INSUFF_SERVER_RESOURCES }, + {130, STATUS_ACCESS_DENIED }, + {131, STATUS_DATA_ERROR }, + {132, STATUS_ACCESS_DENIED }, + {133, STATUS_ACCESS_DENIED }, + {134, STATUS_ACCESS_DENIED }, + {135, STATUS_OBJECT_NAME_INVALID }, + {136, STATUS_INVALID_HANDLE }, + {137, STATUS_ACCESS_DENIED }, + {138, STATUS_ACCESS_DENIED }, + {139, STATUS_ACCESS_DENIED }, + {140, STATUS_ACCESS_DENIED }, + {141, STATUS_SHARING_VIOLATION }, + {142, STATUS_SHARING_VIOLATION }, + {143, STATUS_ACCESS_DENIED }, + {144, STATUS_ACCESS_DENIED }, + {145, STATUS_OBJECT_NAME_COLLISION }, + {146, STATUS_OBJECT_NAME_COLLISION }, + {147, STATUS_ACCESS_DENIED }, + {148, STATUS_ACCESS_DENIED }, + {150, STATUS_INSUFF_SERVER_RESOURCES }, + {151, STATUS_NO_SPOOL_SPACE }, + {152, STATUS_NO_SUCH_DEVICE }, + {153, STATUS_DISK_FULL }, + {154, STATUS_NOT_SAME_DEVICE }, + {155, STATUS_INVALID_HANDLE }, + {156, STATUS_OBJECT_PATH_NOT_FOUND }, + {157, STATUS_INSUFF_SERVER_RESOURCES }, + {158, STATUS_OBJECT_PATH_INVALID }, + {159, STATUS_SHARING_VIOLATION }, + {160, STATUS_DIRECTORY_NOT_EMPTY }, + {161, STATUS_DATA_ERROR }, + {162, STATUS_SHARING_VIOLATION }, + {192, STATUS_ACCESS_DENIED }, + {198, STATUS_ACCESS_DENIED }, + {211, STATUS_ACCESS_DENIED }, + {212, STATUS_PRINT_QUEUE_FULL }, + {213, STATUS_PRINT_CANCELLED }, + {214, STATUS_ACCESS_DENIED }, + {215, STATUS_DEVICE_BUSY }, + {216, STATUS_DEVICE_DOES_NOT_EXIST }, + {220, STATUS_ACCOUNT_DISABLED }, + {222, STATUS_PASSWORD_EXPIRED }, + {223, STATUS_PASSWORD_EXPIRED }, + {239, STATUS_OBJECT_NAME_INVALID }, + {240, STATUS_OBJECT_NAME_INVALID }, + {251, STATUS_INVALID_PARAMETER }, + {252, STATUS_NO_MORE_ENTRIES }, + {253, STATUS_FILE_LOCK_CONFLICT }, + {254, STATUS_FILE_LOCK_CONFLICT }, + {255, STATUS_UNSUCCESSFUL} +}; + +#define NUM_ERRORS(x) (sizeof(x)/sizeof(x[0])) + +DWORD +NwMapBinderyCompletionCode( + IN NTSTATUS NtStatus + ) +/*++ + +Routine Description: + + This function takes a bindery completion code embedded in an NT status + code and maps it to the appropriate Win32 error code. Used specifically + for E3H operations. + +Arguments: + + NtStatus - Supplies the NT status (that contains the code in low 16 bits) + +Return Value: + + Returns the appropriate Win32 error. + +--*/ +{ + DWORD i; UCHAR code ; + + // + // A small optimization for the most common case. + // + if (NtStatus == STATUS_SUCCESS) + return NO_ERROR; + + // + // Map connection errors specially. + // + + if ( ( (NtStatus & 0xFFFF0000) == 0xC0010000) && + ( (NtStatus & 0xFF00) != 0 ) ) + { + return ERROR_UNEXP_NET_ERR; + } + + // + // if facility code not set, assume it is NT Status + // + if ( (NtStatus & 0xFFFF0000) != 0xC0010000) + return RtlNtStatusToDosError(NtStatus); + + code = NtStatus & 0x000000FF ; + for (i = 0; i < NUM_ERRORS(Error_Map_Bindery); i++) + { + if (Error_Map_Bindery[i].NetError == code) + return( NwMapStatus(Error_Map_Bindery[i].ResultingStatus)); + } + + // + // if cannot find let NwMapStatus do its best + // + return NwMapStatus(NtStatus); +} + + + +DWORD +NwMapStatus( + IN NTSTATUS NtStatus + ) +/*++ + +Routine Description: + + This function takes an NT status code and maps it to the appropriate + Win32 error code. If facility code is set, assume it is NW specific + +Arguments: + + NtStatus - Supplies the NT status. + +Return Value: + + Returns the appropriate Win32 error. + +--*/ +{ + DWORD i; UCHAR code ; + + // + // A small optimization for the most common case. + // + if (NtStatus == STATUS_SUCCESS) + return NO_ERROR; + + // + // Map connection errors specially. + // + + if ( ( (NtStatus & 0xFFFF0000) == 0xC0010000) && + ( (NtStatus & 0xFF00) != 0 ) ) + { + return ERROR_UNEXP_NET_ERR; + } + + // + // if facility code set, assume it is NW Completion code + // + if ( (NtStatus & 0xFFFF0000) == 0xC0010000) + { + code = NtStatus & 0x000000FF ; + for (i = 0; i < NUM_ERRORS(Error_Map_General); i++) + { + if (Error_Map_General[i].NetError == code) + { + // + // map it to NTSTATUS and then drop thru to map to Win32 + // + NtStatus = Error_Map_General[i].ResultingStatus ; + break ; + } + } + } + + switch (NtStatus) { + case STATUS_OBJECT_NAME_COLLISION: + return ERROR_ALREADY_ASSIGNED; + + case STATUS_OBJECT_NAME_NOT_FOUND: + return ERROR_NOT_CONNECTED; + + case STATUS_IMAGE_ALREADY_LOADED: + case STATUS_REDIRECTOR_STARTED: + return ERROR_SERVICE_ALREADY_RUNNING; + + case STATUS_REDIRECTOR_HAS_OPEN_HANDLES: + return ERROR_REDIRECTOR_HAS_OPEN_HANDLES; + + case STATUS_NO_MORE_FILES: + case STATUS_NO_MORE_ENTRIES: + return WN_NO_MORE_ENTRIES; + + case STATUS_MORE_ENTRIES: + return WN_MORE_DATA; + + case STATUS_CONNECTION_IN_USE: + return ERROR_DEVICE_IN_USE; + + case NWRDR_PASSWORD_HAS_EXPIRED: + return NW_PASSWORD_HAS_EXPIRED; + + case STATUS_INVALID_DEVICE_REQUEST: + return ERROR_CONNECTION_INVALID; + + default: + return RtlNtStatusToDosError(NtStatus); + } +} + +DWORD +NwGetGraceLoginCount( + LPWSTR Server, + LPWSTR UserName, + LPDWORD lpResult + ) +/*++ + +Routine Description: + + Get the number grace logins for a user. + +Arguments: + + Server - the server to authenticate against + + UserName - the user account + +Return Value: + + Returns the appropriate Win32 error. + +--*/ +{ + DWORD status ; + HANDLE hConn ; + CHAR UserNameO[NW_MAX_USERNAME_LEN+1] ; + BYTE LoginControl[128] ; + BYTE MoreFlags, PropFlags ; + + // + // skip the backslashes if present + // + if (*Server == L'\\') + Server += 2 ; + + // + // attach to the NW server + // + if (status = NWAttachToFileServerW(Server, + 0, + &hConn)) + { + return status ; + } + + // + // convert unicode UserName to OEM, and then call the NCP + // + if ( !WideCharToMultiByte(CP_OEMCP, + 0, + UserName, + -1, + UserNameO, + sizeof(UserNameO), + NULL, + NULL)) + { + status = GetLastError() ; + } + else + { + status = NWReadPropertyValue( hConn, + UserNameO, + OT_USER, + "LOGIN_CONTROL", + 1, + LoginControl, + &MoreFlags, + &PropFlags) ; + } + + // + // dont need these anymore. if any error, bag out + // + (void) NWDetachFromFileServer(hConn) ; + + + if (status == NO_ERROR) + *lpResult = (DWORD) LoginControl[7] ; + + return status ; +} + + +WORD +NwParseNdsUncPath( + IN OUT LPWSTR * Result, + IN LPWSTR ContainerName, + IN ULONG flag +) +/*++ + +Routine Description: + + This function is used to extract either the tree name, fully distinguished + name path to an object, or object name, out of a complete NDS UNC path. + +Arguments: + + Result - parsed result buffer. + ContainerName - Complete NDS UNC path that is to be parsed. + flag - Flag indicating operation to be performed: + + PARSE_NDS_GET_TREE_NAME + PARSE_NDS_GET_PATH_NAME + PARSE_NDS_GET_OBJECT_NAME + + +Return Value: + + Length of string in result buffer. If error occured, 0 is returned. + +--*/ // NwParseNdsUncPath +{ + unsigned short length = 2; + unsigned short totalLength = wcslen( ContainerName ); + + if ( totalLength < 2 ) + return 0; + + // + // First get length to indicate the character in the string that indicates the + // "\" in between the tree name and the rest of the UNC path. + // + // Example: \\<tree name>\<path to object>[\|.]<object> + // ^ + // | + // + while ( length < totalLength && ContainerName[length] != L'\\' ) + { + length++; + } + + if ( flag == PARSE_NDS_GET_TREE_NAME ) + { + *Result = (LPWSTR) ( ContainerName + 2 ); + + return ( length - 2 ) * sizeof( WCHAR ); // Take off 2 for the two \\'s + } + + if ( flag == PARSE_NDS_GET_PATH_NAME && length == totalLength ) + { + *Result = ContainerName; + + return 0; + } + + if ( flag == PARSE_NDS_GET_PATH_NAME ) + { + *Result = ContainerName + length + 1; + + return ( totalLength - length - 1 ) * sizeof( WCHAR ); + } + + *Result = ContainerName + totalLength - 1; + length = 1; + + while ( **Result != L'\\' ) + { + *Result--; + length++; + } + + *Result++; + length--; + + return length * sizeof( WCHAR ); +} + + +DWORD +NwOpenAServer( + PWCHAR pwszServName, + PHANDLE ServerHandle, + BOOL fVerify + ) +/*++ + +Routine Description: + + This routine opens a handle to a server. + +Arguments: + + ServerHandle - Receives an opened handle to the preferred or + nearest server. + +Return Value: + + NO_ERROR or reason for failure. + +--*/ +{ + UNICODE_STRING AServer; + WCHAR wszName[sizeof(NW_RDR_NAME) + (48 * sizeof(WCHAR))]; + DWORD wLen; + + + if(!pwszServName) + { + pwszServName = NW_RDR_PREFERRED_SERVER; + RtlInitUnicodeString(&AServer, wszName); + } + else + { + wLen = wcslen(pwszServName); + if(wLen > 47) + { + return(WSAEFAULT); + } + wcscpy(wszName, NW_RDR_NAME); + wcscat(wszName, pwszServName); + RtlInitUnicodeString(&AServer, wszName); + } + + return RtlNtStatusToDosError( + NwOpenHandle(&AServer, fVerify, ServerHandle) + ); + +} + + +DWORD +NwOpenPreferredServer( + PHANDLE ServerHandle + ) +/*++ + +Routine Description: + + This routine opens a handle to the preferred server. If the + preferred server has not been specified, a handle to the + nearest server is opened instead. + +Arguments: + + ServerHandle - Receives an opened handle to the preferred or + nearest server. + +Return Value: + + NO_ERROR or reason for failure. + +--*/ +{ + UNICODE_STRING PreferredServer; + + + // + // The NetWare redirector recognizes "*" to mean the preferred + // or nearest server. + // + RtlInitUnicodeString(&PreferredServer, NW_RDR_PREFERRED_SERVER); + + return RtlNtStatusToDosError( + NwOpenHandle(&PreferredServer, FALSE, ServerHandle) + ); + +} + + +NTSTATUS +NwOpenHandle( + IN PUNICODE_STRING ObjectName, + IN BOOL ValidateFlag, + OUT PHANDLE ObjectHandle + ) +/*++ + +Routine Description: + + This function opens a handle to \Device\Nwrdr\<ObjectName>. + +Arguments: + + ObjectName - Supplies the name of the redirector object to open. + + ValidateFlag - Supplies a flag which if TRUE, opens the handle to + the object by validating the default user account. + + ObjectHandle - Receives a pointer to the opened object handle. + +Return Value: + + STATUS_SUCCESS or reason for failure. + +--*/ +{ + ACCESS_MASK DesiredAccess = SYNCHRONIZE; + + + if (ValidateFlag) { + + // + // The redirector only authenticates the default user credential + // if the remote resource is opened with write access. + // + DesiredAccess |= FILE_WRITE_DATA; + } + + + *ObjectHandle = NULL; + + return NwCallNtOpenFile( + ObjectHandle, + DesiredAccess, + ObjectName, + FILE_SYNCHRONOUS_IO_NONALERT + ); + +} + + +NTSTATUS +NwCallNtOpenFile( + OUT PHANDLE ObjectHandle, + IN ACCESS_MASK DesiredAccess, + IN PUNICODE_STRING ObjectName, + IN ULONG OpenOptions + ) +{ + + NTSTATUS ntstatus; + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + + + + InitializeObjectAttributes( + &ObjectAttributes, + ObjectName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + ntstatus = NtOpenFile( + ObjectHandle, + DesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_VALID_FLAGS, + OpenOptions + ); + + if (!NT_ERROR(ntstatus) && + !NT_INFORMATION(ntstatus) && + !NT_WARNING(ntstatus)) { + + ntstatus = IoStatusBlock.Status; + + } + + return ntstatus; +} + + +BOOL +NwConvertToUnicode( + OUT LPWSTR *UnicodeOut, + IN LPSTR OemIn + ) +/*++ + +Routine Description: + + This function converts the given OEM string to a Unicode string. + The Unicode string is returned in a buffer allocated by this + function and must be freed with LocalFree. + +Arguments: + + UnicodeOut - Receives a pointer to the Unicode string. + + OemIn - This is a pointer to an ansi string that is to be converted. + +Return Value: + + TRUE - The conversion was successful. + + FALSE - The conversion was unsuccessful. In this case a buffer for + the unicode string was not allocated. + +--*/ +{ + NTSTATUS ntstatus; + DWORD BufSize; + UNICODE_STRING UnicodeString; + OEM_STRING OemString; + + + // + // Allocate a buffer for the unicode string. + // + + BufSize = (strlen(OemIn) + 1) * sizeof(WCHAR); + + *UnicodeOut = LocalAlloc(LMEM_ZEROINIT, BufSize); + + if (*UnicodeOut == NULL) { + KdPrint(("NWWORKSTATION: NwConvertToUnicode:LocalAlloc failed %lu\n", + GetLastError())); + return FALSE; + } + + // + // Initialize the string structures + // + RtlInitAnsiString((PANSI_STRING) &OemString, OemIn); + + UnicodeString.Buffer = *UnicodeOut; + UnicodeString.MaximumLength = (USHORT) BufSize; + UnicodeString.Length = 0; + + // + // Call the conversion function. + // + ntstatus = RtlOemStringToUnicodeString( + &UnicodeString, // Destination + &OemString, // Source + FALSE // Allocate the destination + ); + + if (ntstatus != STATUS_SUCCESS) { + + KdPrint(("NWWORKSTATION: NwConvertToUnicode: RtlOemStringToUnicodeString failure x%08lx\n", + ntstatus)); + + (void) LocalFree((HLOCAL) *UnicodeOut); + *UnicodeOut = NULL; + return FALSE; + } + + *UnicodeOut = UnicodeString.Buffer; + + return TRUE; + +} |