733 lines
18 KiB
C
733 lines
18 KiB
C
/*++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Convert.c
|
|
|
|
Abstract:
|
|
|
|
This module implements conversion routine to map NT formats to
|
|
Netware and vice versa.
|
|
|
|
Author:
|
|
|
|
Manny Weiser [MannyW] 3-Mar-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "Procs.h"
|
|
|
|
typedef union _NCP_DATE {
|
|
USHORT Ushort;
|
|
struct {
|
|
USHORT Day : 5;
|
|
USHORT Month : 4;
|
|
USHORT Year : 7;
|
|
} Struct;
|
|
} NCP_DATE;
|
|
|
|
typedef union _NCP_TIME {
|
|
USHORT Ushort;
|
|
struct {
|
|
USHORT TwoSeconds : 5;
|
|
USHORT Minutes : 6;
|
|
USHORT Hours : 5;
|
|
} Struct;
|
|
} NCP_TIME;
|
|
|
|
#define BASE_DOS_ERROR ((NTSTATUS )0xC0010000L)
|
|
|
|
|
|
struct {
|
|
UCHAR NetError;
|
|
NTSTATUS ResultingStatus;
|
|
} Error_Map[] = {
|
|
// NetWare specific error mappings
|
|
{ 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_OBJECT_NAME_COLLISION },
|
|
{134, STATUS_OBJECT_NAME_COLLISION },
|
|
{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 },
|
|
{149, 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_FILE_LOCK_CONFLICT },
|
|
{165, STATUS_OBJECT_NAME_NOT_FOUND },
|
|
{191, STATUS_OBJECT_NAME_INVALID }, // Name space not loaded
|
|
{192, STATUS_ACCESS_DENIED},
|
|
{193, STATUS_ACCOUNT_RESTRICTION },
|
|
{194, STATUS_ACCOUNT_RESTRICTION },
|
|
{195, STATUS_ACCOUNT_DISABLED},
|
|
{197, STATUS_ACCOUNT_DISABLED },
|
|
{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 },
|
|
#ifdef QFE_BUILD
|
|
{217, STATUS_ACCOUNT_RESTRICTION },
|
|
{218, STATUS_ACCOUNT_RESTRICTION },
|
|
{219, STATUS_ACCOUNT_RESTRICTION },
|
|
#else
|
|
{217, STATUS_CONNECTION_COUNT_LIMIT },
|
|
{218, STATUS_LOGIN_TIME_RESTRICTION },
|
|
{219, STATUS_LOGIN_WKSTA_RESTRICTION },
|
|
#endif
|
|
{220, STATUS_ACCOUNT_DISABLED },
|
|
{222, STATUS_PASSWORD_EXPIRED },
|
|
{223, NWRDR_PASSWORD_HAS_EXPIRED },
|
|
{231, STATUS_REMOTE_SESSION_LIMIT },
|
|
{236, STATUS_UNEXPECTED_NETWORK_ERROR },
|
|
{251, STATUS_INVALID_PARAMETER },
|
|
{252, STATUS_NO_MORE_ENTRIES },
|
|
{253, STATUS_FILE_LOCK_CONFLICT },
|
|
{254, STATUS_FILE_LOCK_CONFLICT },
|
|
{255, STATUS_UNSUCCESSFUL},
|
|
|
|
// DOS error mappings
|
|
//{ ERROR_INVALID_FUNCTION, STATUS_NOT_IMPLEMENTED },
|
|
{ ERROR_FILE_NOT_FOUND, STATUS_NO_SUCH_FILE },
|
|
{ ERROR_PATH_NOT_FOUND, STATUS_OBJECT_PATH_NOT_FOUND },
|
|
{ ERROR_TOO_MANY_OPEN_FILES, STATUS_TOO_MANY_OPENED_FILES },
|
|
{ ERROR_ACCESS_DENIED, STATUS_ACCESS_DENIED },
|
|
{ ERROR_INVALID_HANDLE, STATUS_INVALID_HANDLE },
|
|
{ ERROR_NOT_ENOUGH_MEMORY, STATUS_INSUFFICIENT_RESOURCES },
|
|
{ ERROR_INVALID_ACCESS, STATUS_ACCESS_DENIED },
|
|
{ ERROR_INVALID_DATA, STATUS_DATA_ERROR },
|
|
|
|
{ ERROR_CURRENT_DIRECTORY, STATUS_DIRECTORY_NOT_EMPTY },
|
|
{ ERROR_NOT_SAME_DEVICE, STATUS_NOT_SAME_DEVICE },
|
|
{ ERROR_NO_MORE_FILES, STATUS_NO_MORE_FILES },
|
|
/* */
|
|
/* These are the universal int 24 mappings for the old INT 24 set of errors */
|
|
/* */
|
|
{ ERROR_WRITE_PROTECT, STATUS_MEDIA_WRITE_PROTECTED},
|
|
{ ERROR_BAD_UNIT, STATUS_UNSUCCESSFUL}, // ***
|
|
{ ERROR_NOT_READY, STATUS_DEVICE_NOT_READY },
|
|
{ ERROR_BAD_COMMAND, STATUS_UNSUCCESSFUL}, // ***
|
|
{ ERROR_CRC, STATUS_CRC_ERROR },
|
|
{ ERROR_BAD_LENGTH, STATUS_DATA_ERROR },
|
|
{ ERROR_SEEK, STATUS_UNSUCCESSFUL },// ***
|
|
{ ERROR_NOT_DOS_DISK, STATUS_DISK_CORRUPT_ERROR }, //***
|
|
{ ERROR_SECTOR_NOT_FOUND, STATUS_NONEXISTENT_SECTOR },
|
|
{ ERROR_OUT_OF_PAPER, STATUS_DEVICE_PAPER_EMPTY},
|
|
{ ERROR_WRITE_FAULT, STATUS_UNSUCCESSFUL}, // ***
|
|
{ ERROR_READ_FAULT, STATUS_UNSUCCESSFUL}, // ***
|
|
{ ERROR_GEN_FAILURE, STATUS_UNSUCCESSFUL }, // ***
|
|
/* */
|
|
/* These are the new 3.0 error codes reported through INT 24 */
|
|
/* */
|
|
{ ERROR_SHARING_VIOLATION, STATUS_SHARING_VIOLATION },
|
|
{ ERROR_LOCK_VIOLATION, STATUS_FILE_LOCK_CONFLICT },
|
|
{ ERROR_WRONG_DISK, STATUS_WRONG_VOLUME },
|
|
// { ERROR_FCB_UNAVAILABLE, },
|
|
// { ERROR_SHARING_BUFFER_EXCEEDED, },
|
|
/* */
|
|
/* New OEM network-related errors are 50-79 */
|
|
/* */
|
|
{ ERROR_NOT_SUPPORTED, STATUS_NOT_SUPPORTED },
|
|
{ ERROR_REM_NOT_LIST, STATUS_REMOTE_NOT_LISTENING },
|
|
{ ERROR_DUP_NAME, STATUS_DUPLICATE_NAME },
|
|
{ ERROR_BAD_NETPATH, STATUS_BAD_NETWORK_PATH },
|
|
{ ERROR_NETWORK_BUSY, STATUS_NETWORK_BUSY },
|
|
{ ERROR_DEV_NOT_EXIST, STATUS_DEVICE_DOES_NOT_EXIST },
|
|
{ ERROR_TOO_MANY_CMDS, STATUS_TOO_MANY_COMMANDS },
|
|
{ ERROR_ADAP_HDW_ERR, STATUS_ADAPTER_HARDWARE_ERROR },
|
|
{ ERROR_BAD_NET_RESP, STATUS_INVALID_NETWORK_RESPONSE },
|
|
{ ERROR_UNEXP_NET_ERR, STATUS_UNEXPECTED_NETWORK_ERROR },
|
|
{ ERROR_BAD_REM_ADAP, STATUS_BAD_REMOTE_ADAPTER },
|
|
{ ERROR_PRINTQ_FULL, STATUS_PRINT_QUEUE_FULL },
|
|
{ ERROR_NO_SPOOL_SPACE, STATUS_NO_SPOOL_SPACE },
|
|
{ ERROR_PRINT_CANCELLED, STATUS_PRINT_CANCELLED },
|
|
{ ERROR_NETNAME_DELETED, STATUS_NETWORK_NAME_DELETED },
|
|
{ ERROR_NETWORK_ACCESS_DENIED, STATUS_NETWORK_ACCESS_DENIED },
|
|
{ ERROR_BAD_DEV_TYPE, STATUS_BAD_DEVICE_TYPE },
|
|
{ ERROR_BAD_NET_NAME, STATUS_BAD_NETWORK_NAME },
|
|
{ ERROR_TOO_MANY_NAMES, STATUS_TOO_MANY_NAMES },
|
|
{ ERROR_TOO_MANY_SESS, STATUS_REMOTE_SESSION_LIMIT },
|
|
{ ERROR_SHARING_PAUSED, STATUS_SHARING_PAUSED },
|
|
{ ERROR_REQ_NOT_ACCEP, STATUS_REQUEST_NOT_ACCEPTED },
|
|
{ ERROR_REDIR_PAUSED, STATUS_REDIRECTOR_PAUSED },
|
|
/* */
|
|
/* End of INT 24 reportable errors */
|
|
/* */
|
|
{ ERROR_FILE_EXISTS, STATUS_OBJECT_NAME_COLLISION },
|
|
// { ERROR_DUP_FCB, },
|
|
// { ERROR_CANNOT_MAKE, },
|
|
// { ERROR_FAIL_I24, },
|
|
/* */
|
|
/* New 3.0 network related error codes */
|
|
/* */
|
|
// { ERROR_OUT_OF_STRUCTURES, },
|
|
// { ERROR_ALREADY_ASSIGNED, },
|
|
{ ERROR_INVALID_PASSWORD, STATUS_WRONG_PASSWORD },
|
|
{ ERROR_INVALID_PARAMETER, STATUS_INVALID_PARAMETER },
|
|
{ ERROR_NET_WRITE_FAULT, STATUS_NET_WRITE_FAULT },
|
|
/* */
|
|
/* New error codes for 4.0 */
|
|
/* */
|
|
// { ERROR_NO_PROC_SLOTS, },
|
|
// { ERROR_NOT_FROZEN, },
|
|
// { ERR_TSTOVFL, },
|
|
// { ERR_TSTDUP, },
|
|
// { ERROR_NO_ITEMS, },
|
|
// { ERROR_INTERRUPT, },
|
|
|
|
// { ERROR_TOO_MANY_SEMAPHORES, },
|
|
// { ERROR_EXCL_SEM_ALREADY_OWNED, },
|
|
// { ERROR_SEM_IS_SET, },
|
|
// { ERROR_TOO_MANY_SEM_REQUESTS, },
|
|
// { ERROR_INVALID_AT_INTERRUPT_TIME, },
|
|
|
|
// { ERROR_SEM_OWNER_DIED, },
|
|
// { ERROR_SEM_USER_LIMIT, },
|
|
// { ERROR_DISK_CHANGE, },
|
|
// { ERROR_DRIVE_LOCKED, },
|
|
{ ERROR_BROKEN_PIPE, STATUS_PIPE_BROKEN },
|
|
/* */
|
|
/* New error codes for 5.0 */
|
|
/* */
|
|
//
|
|
// NOTE: ERROR_OPEN_FAILED is handled specially.
|
|
//
|
|
|
|
//
|
|
// The mapping of ERROR_OPEN_FAILED is context sensitive. If the
|
|
// disposition requested in the Open_AndX SMB is FILE_CREATE, this
|
|
// error means that the file already existed. If the disposition
|
|
// is FILE_OPEN, it means that the file does NOT exist!
|
|
//
|
|
|
|
{ ERROR_OPEN_FAILED, STATUS_OPEN_FAILED },
|
|
// { ERROR_BUFFER_OVERFLOW, },
|
|
{ ERROR_DISK_FULL, STATUS_DISK_FULL },
|
|
// { ERROR_NO_MORE_SEARCH_HANDLES, },
|
|
// { ERROR_INVALID_TARGET_HANDLE, },
|
|
// { ERROR_PROTECTION_VIOLATION, STATUS_ACCESS_VIOLATION },
|
|
// { ERROR_VIOKBD_REQUEST, },
|
|
// { ERROR_INVALID_CATEGORY, },
|
|
// { ERROR_INVALID_VERIFY_SWITCH, },
|
|
// { ERROR_BAD_DRIVER_LEVEL, },
|
|
// { ERROR_CALL_NOT_IMPLEMENTED, },
|
|
{ ERROR_SEM_TIMEOUT, STATUS_IO_TIMEOUT },
|
|
{ ERROR_INSUFFICIENT_BUFFER, STATUS_BUFFER_TOO_SMALL },
|
|
{ ERROR_INVALID_NAME, STATUS_OBJECT_NAME_INVALID },
|
|
{ ERROR_INVALID_LEVEL, STATUS_INVALID_LEVEL },
|
|
// { ERROR_NO_VOLUME_LABEL, },
|
|
|
|
/* NOTE: DosQFSInfo no longer returns the above error; it is still here for */
|
|
/* api\d_qfsinf.asm. */
|
|
|
|
// { ERROR_MOD_NOT_FOUND, },
|
|
// { ERROR_PROC_NOT_FOUND, },
|
|
|
|
// { ERROR_WAIT_NO_CHILDREN, },
|
|
|
|
// { ERROR_CHILD_NOT_COMPLETE, },
|
|
|
|
// { ERROR_DIRECT_ACCESS_HANDLE, },
|
|
/* for direct disk access */
|
|
/* handles */
|
|
// { ERROR_NEGATIVE_SEEK, },
|
|
/* with negitive offset */
|
|
// { ERROR_SEEK_ON_DEVICE, },
|
|
/* on device or pipe */
|
|
{ ERROR_BAD_PATHNAME, STATUS_OBJECT_PATH_INVALID }, //*
|
|
|
|
/*
|
|
* Error codes 230 - 249 are reserved for MS Networks
|
|
*/
|
|
{ ERROR_BAD_PIPE, STATUS_INVALID_PARAMETER },
|
|
{ ERROR_PIPE_BUSY, STATUS_PIPE_NOT_AVAILABLE },
|
|
{ ERROR_NO_DATA, STATUS_PIPE_EMPTY },
|
|
{ ERROR_PIPE_NOT_CONNECTED, STATUS_PIPE_DISCONNECTED },
|
|
{ ERROR_MORE_DATA, STATUS_BUFFER_OVERFLOW },
|
|
|
|
{ ERROR_VC_DISCONNECTED, STATUS_VIRTUAL_CIRCUIT_CLOSED },
|
|
};
|
|
|
|
#define NUM_ERRORS sizeof(Error_Map) / sizeof(Error_Map[0])
|
|
|
|
//
|
|
// The debug trace level
|
|
//
|
|
|
|
#define Dbg (DEBUG_TRACE_CONVERT)
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text( PAGE, NtToNwShareFlags )
|
|
#pragma alloc_text( PAGE, NtAttributesToNwAttributes )
|
|
|
|
#ifndef QFE_BUILD
|
|
#pragma alloc_text( PAGE1, pNwErrorToNtStatus )
|
|
#pragma alloc_text( PAGE1, NwBurstResultToNtStatus )
|
|
#pragma alloc_text( PAGE1, NwConnectionStatusToNtStatus )
|
|
#pragma alloc_text( PAGE1, NwDateTimeToNtTime )
|
|
#pragma alloc_text( PAGE1, NwNtTimeToNwDateTime )
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#if 0 // Not pageable
|
|
|
|
// see ifndef QFE_BUILD above
|
|
|
|
#endif
|
|
|
|
UCHAR
|
|
NtToNwShareFlags(
|
|
ULONG DesiredAccess,
|
|
ULONG NtShareFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine maps a NT desired/share access to Netware share flag bits.
|
|
|
|
Arguments:
|
|
|
|
DesiredAccess - Desired access for open as specified in the read IRP.
|
|
NtShareFlags - The NT share flags from the create IRP.
|
|
|
|
Return Value:
|
|
|
|
Netware share mode.
|
|
|
|
--*/
|
|
{
|
|
UCHAR NwShareFlags = 0;
|
|
ULONG lDesiredAccess;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Ignore share delete, since we can't do anything with it.
|
|
//
|
|
|
|
switch ( NtShareFlags & (FILE_SHARE_READ | FILE_SHARE_WRITE) ) {
|
|
|
|
case 0:
|
|
NwShareFlags = NW_OPEN_EXCLUSIVE;
|
|
break;
|
|
|
|
case FILE_SHARE_READ:
|
|
NwShareFlags = NW_DENY_WRITE;
|
|
break;
|
|
|
|
case FILE_SHARE_WRITE:
|
|
NwShareFlags = NW_DENY_READ;
|
|
break;
|
|
|
|
case FILE_SHARE_WRITE | FILE_SHARE_READ:
|
|
NwShareFlags = 0;
|
|
|
|
}
|
|
|
|
//
|
|
// Treat append the same as write.
|
|
//
|
|
|
|
if ( DesiredAccess & FILE_APPEND_DATA) {
|
|
|
|
lDesiredAccess = DesiredAccess | FILE_WRITE_DATA;
|
|
|
|
} else {
|
|
|
|
lDesiredAccess = DesiredAccess;
|
|
|
|
}
|
|
|
|
switch ( lDesiredAccess & (FILE_EXECUTE | FILE_WRITE_DATA | FILE_READ_DATA) ) {
|
|
|
|
case (FILE_EXECUTE | FILE_WRITE_DATA | FILE_READ_DATA):
|
|
case (FILE_EXECUTE | FILE_WRITE_DATA):
|
|
NwShareFlags |= NW_OPEN_EXCLUSIVE | NW_OPEN_FOR_WRITE | NW_OPEN_FOR_READ;
|
|
break;
|
|
|
|
case (FILE_EXECUTE | FILE_READ_DATA):
|
|
case (FILE_EXECUTE):
|
|
NwShareFlags |= NW_OPEN_EXCLUSIVE | NW_OPEN_FOR_READ;
|
|
break;
|
|
|
|
case (FILE_WRITE_DATA | FILE_READ_DATA):
|
|
NwShareFlags |= NW_OPEN_FOR_WRITE | NW_OPEN_FOR_READ;
|
|
break;
|
|
|
|
case (FILE_WRITE_DATA):
|
|
NwShareFlags |= NW_OPEN_FOR_WRITE;
|
|
break;
|
|
|
|
default:
|
|
NwShareFlags |= NW_OPEN_FOR_READ;
|
|
break;
|
|
}
|
|
|
|
if (NwShareFlags & NW_OPEN_EXCLUSIVE) {
|
|
|
|
//
|
|
// Remove the NW_DENY_* flags if exclusive is already specified since
|
|
// this interferes with the shareable flag.
|
|
//
|
|
|
|
return( NwShareFlags & ~(NW_DENY_READ | NW_DENY_WRITE) );
|
|
}
|
|
|
|
return( NwShareFlags );
|
|
}
|
|
|
|
|
|
UCHAR
|
|
NtAttributesToNwAttributes(
|
|
ULONG FileAttributes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine maps a NT attributes mask to a Netware mask.
|
|
|
|
Arguments:
|
|
|
|
DesiredAccess - Desired access for open as specified in the read IRP.
|
|
|
|
Return Value:
|
|
|
|
Netware share mode.
|
|
|
|
--*/
|
|
{
|
|
return( (UCHAR)FileAttributes & 0x3F );
|
|
}
|
|
|
|
NTSTATUS
|
|
pNwErrorToNtStatus(
|
|
UCHAR NwError
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts a Netware error code to an NT status code.
|
|
|
|
Arguments:
|
|
|
|
NwError - The netware error.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The converted status.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
|
|
ASSERT(NwError != 0);
|
|
|
|
//
|
|
// Errors 2 through 127 are mapped as DOS errors.
|
|
//
|
|
|
|
if ( NwError > 1 && NwError < 128 ) {
|
|
return( BASE_DOS_ERROR + NwError );
|
|
}
|
|
|
|
//
|
|
// For other errors, search the table for the matching error number.
|
|
//
|
|
|
|
for ( i = 0; i < NUM_ERRORS; i++ ) {
|
|
if ( Error_Map[i].NetError == NwError ) {
|
|
return( Error_Map[i].ResultingStatus );
|
|
}
|
|
}
|
|
|
|
DebugTrace( 0, 0, "No error mapping for error %d\n", NwError );
|
|
|
|
#ifdef NWDBG
|
|
Error( EVENT_NWRDR_NETWORK_ERROR, (NTSTATUS)0xC0010000 | NwError, NULL, 0, 0 );
|
|
#endif
|
|
|
|
return( (NTSTATUS)0xC0010000 | NwError );
|
|
}
|
|
|
|
NTSTATUS
|
|
NwBurstResultToNtStatus(
|
|
ULONG Result
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts a Netware burst result code to an NT status code.
|
|
|
|
Arguments:
|
|
|
|
Result - The netware burst result.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The converted status.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// the 3 high order bits should not be set. but if they are,
|
|
// we return an error.
|
|
//
|
|
if (Result & 0xFFFFFF00)
|
|
return( STATUS_UNEXPECTED_NETWORK_ERROR );
|
|
|
|
switch ( Result ) {
|
|
|
|
case 0:
|
|
case 3: // No data
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case 1:
|
|
Status = STATUS_DISK_FULL;
|
|
break;
|
|
|
|
case 2: // I/O error
|
|
Status = STATUS_UNEXPECTED_IO_ERROR;
|
|
break;
|
|
|
|
default:
|
|
Status = NwErrorToNtStatus( (UCHAR)Result );
|
|
break;
|
|
}
|
|
|
|
return( Status );
|
|
}
|
|
|
|
NTSTATUS
|
|
NwConnectionStatusToNtStatus(
|
|
UCHAR NwStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts a Netware connection status code to an NT
|
|
status code.
|
|
|
|
Arguments:
|
|
|
|
NwStatus - The netware connection status.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The converted status.
|
|
|
|
--*/
|
|
|
|
{
|
|
if ( (NwStatus & 1) == 0 ) {
|
|
return STATUS_SUCCESS;
|
|
} else {
|
|
return STATUS_REMOTE_DISCONNECT;
|
|
}
|
|
}
|
|
|
|
LARGE_INTEGER
|
|
NwDateTimeToNtTime (
|
|
IN USHORT UDate,
|
|
IN USHORT UTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts an NCP time to an NT time structure.
|
|
|
|
Arguments:
|
|
|
|
Time - Supplies the time of day to convert
|
|
Date - Supplies the day of the year to convert
|
|
|
|
Return Value:
|
|
|
|
LARGE_INTEGER - Time structure describing input time.
|
|
|
|
--*/
|
|
|
|
{
|
|
TIME_FIELDS TimeFields;
|
|
LARGE_INTEGER OutputTime;
|
|
NCP_DATE Date = *(NCP_DATE *)&UDate;
|
|
NCP_TIME Time = *(NCP_TIME *)&UTime;
|
|
|
|
if ( Date.Ushort == 0 && Time.Ushort == 0 ) {
|
|
|
|
//
|
|
// The file time stamp is zero. Do not return a file time of
|
|
// zero, since this will be biased to a negative time (due to
|
|
// time zone fixup), and no one will be able to display it
|
|
// correctly. Instead, we "randomly" pick Jan 01, 1980 @ 12:00am
|
|
// as the file time.
|
|
//
|
|
// We assume that the netware server is in our time zone.
|
|
|
|
RtlSecondsSince1980ToTime(0, &OutputTime);
|
|
|
|
} else {
|
|
|
|
TimeFields.Year = Date.Struct.Year + (USHORT )1980;
|
|
TimeFields.Month = Date.Struct.Month;
|
|
TimeFields.Day = Date.Struct.Day;
|
|
|
|
TimeFields.Hour = Time.Struct.Hours;
|
|
TimeFields.Minute = Time.Struct.Minutes;
|
|
TimeFields.Second = Time.Struct.TwoSeconds*(USHORT )2;
|
|
TimeFields.Milliseconds = 0;
|
|
|
|
//
|
|
// Make sure that the times specified in the packet are reasonable
|
|
// before converting them.
|
|
//
|
|
|
|
if (TimeFields.Year < 1601) {
|
|
TimeFields.Year = 1601;
|
|
}
|
|
|
|
if (TimeFields.Month > 12) {
|
|
TimeFields.Month = 12;
|
|
}
|
|
|
|
if (TimeFields.Hour >= 24) {
|
|
TimeFields.Hour = 23;
|
|
}
|
|
|
|
if (TimeFields.Minute >= 60) {
|
|
TimeFields.Minute = 59;
|
|
}
|
|
|
|
if (TimeFields.Second >= 60) {
|
|
TimeFields.Second = 59;
|
|
}
|
|
|
|
if (!RtlTimeFieldsToTime(&TimeFields, &OutputTime)) {
|
|
|
|
OutputTime.QuadPart = 0;
|
|
return OutputTime;
|
|
}
|
|
|
|
}
|
|
|
|
// Convert to UTC for the system.
|
|
ExLocalTimeToSystemTime(&OutputTime, &OutputTime);
|
|
return OutputTime;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
NwNtTimeToNwDateTime (
|
|
IN LARGE_INTEGER NtTime,
|
|
IN PUSHORT NwDate,
|
|
IN PUSHORT NwTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts an NT time structure to an NCP time.
|
|
|
|
Arguments:
|
|
|
|
NtTime - Supplies to NT Time to convert.
|
|
|
|
NwDate - Returns the Netware format date.
|
|
|
|
NwTime - Returns the Netware format time.
|
|
|
|
Return Value:
|
|
|
|
The status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
TIME_FIELDS TimeFields;
|
|
NCP_DATE Date;
|
|
NCP_TIME Time;
|
|
|
|
if (NtTime.QuadPart == 0) {
|
|
|
|
Time.Ushort = Date.Ushort = 0;
|
|
|
|
} else {
|
|
|
|
LARGE_INTEGER LocalTime;
|
|
|
|
// We assume that the netware server is in our time zone.
|
|
|
|
ExSystemTimeToLocalTime( &NtTime, &LocalTime );
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
if (TimeFields.Year < 1980 || TimeFields.Year > (1980 + 127) ) {
|
|
return( STATUS_INVALID_PARAMETER );
|
|
}
|
|
|
|
Date.Struct.Year = (USHORT )(TimeFields.Year - 1980);
|
|
Date.Struct.Month = TimeFields.Month;
|
|
Date.Struct.Day = TimeFields.Day;
|
|
|
|
Time.Struct.Hours = TimeFields.Hour;
|
|
Time.Struct.Minutes = TimeFields.Minute;
|
|
|
|
//
|
|
// When converting from a higher granularity time to a lesser
|
|
// granularity time (seconds to 2 seconds), always round up
|
|
// the time, don't round down.
|
|
//
|
|
|
|
Time.Struct.TwoSeconds = TimeFields.Second / 2;
|
|
|
|
}
|
|
|
|
*NwDate = *( USHORT *)&Date;
|
|
*NwTime = *( USHORT *)&Time;
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
|