summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/lib/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/lib/misc.c')
-rw-r--r--private/nw/svcdlls/nwwks/lib/misc.c785
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;
+
+}