2000-04-25 18:04:06 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-04-25 18:04:06 +04:00
client error handling routines
Copyright ( C ) Andrew Tridgell 1994 - 1998
2003-04-15 18:42:06 +04:00
Copyright ( C ) Jelmer Vernooij 2003
2006-02-24 08:05:09 +03:00
Copyright ( C ) Jeremy Allison 2006
2000-04-25 18:04:06 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
/*****************************************************
RAP error codes - a small start but will be extended .
2002-01-22 08:11:28 +03:00
XXX : Perhaps these should move into a common function because they ' re
duplicated in clirap2 . c
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-24 08:05:09 +03:00
static const struct {
int err ;
const char * message ;
} rap_errmap [ ] = {
{ 5 , " RAP5: User has insufficient privilege " } ,
{ 50 , " RAP50: Not supported by server " } ,
{ 65 , " RAP65: Access denied " } ,
{ 86 , " RAP86: The specified password is invalid " } ,
{ 2220 , " RAP2220: Group does not exist " } ,
{ 2221 , " RAP2221: User does not exist " } ,
{ 2226 , " RAP2226: Operation only permitted on a Primary Domain Controller " } ,
{ 2237 , " RAP2237: User is not in group " } ,
{ 2242 , " RAP2242: The password of this user has expired. " } ,
{ 2243 , " RAP2243: The password of this user cannot change. " } ,
{ 2244 , " RAP2244: This password cannot be used now (password history conflict). " } ,
{ 2245 , " RAP2245: The password is shorter than required. " } ,
{ 2246 , " RAP2246: The password of this user is too recent to change. " } ,
/* these really shouldn't be here ... */
{ 0x80 , " Not listening on called name " } ,
{ 0x81 , " Not listening for calling name " } ,
{ 0x82 , " Called name not present " } ,
{ 0x83 , " Called name present, but insufficient resources " } ,
{ 0 , NULL }
2000-04-25 18:04:06 +04:00
} ;
/****************************************************************************
2006-02-24 08:05:09 +03:00
Return a description of an SMB error .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-24 08:05:09 +03:00
2003-01-03 11:28:12 +03:00
static const char * cli_smb_errstr ( struct cli_state * cli )
2000-04-25 18:04:06 +04:00
{
2001-09-05 15:32:59 +04:00
return smb_dos_errstr ( cli - > inbuf ) ;
2000-04-25 18:04:06 +04:00
}
2006-02-24 08:05:09 +03:00
/****************************************************************************
Convert a socket error into an NTSTATUS .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS cli_smb_rw_error_to_ntstatus ( struct cli_state * cli )
{
switch ( cli - > smb_rw_error ) {
case READ_TIMEOUT :
return NT_STATUS_IO_TIMEOUT ;
case READ_EOF :
return NT_STATUS_END_OF_FILE ;
/* What we shoud really do for read/write errors is convert from errno. */
/* FIXME. JRA. */
case READ_ERROR :
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
case WRITE_ERROR :
return NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
case READ_BAD_SIG :
return NT_STATUS_INVALID_PARAMETER ;
default :
break ;
}
return NT_STATUS_UNSUCCESSFUL ;
}
2001-08-10 10:00:33 +04:00
/***************************************************************************
Return an error message - either an NT error , SMB error or a RAP error .
Note some of the NT errors are actually warnings or " informational " errors
in which case they can be safely ignored .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-24 08:05:09 +03:00
2003-01-03 11:28:12 +03:00
const char * cli_errstr ( struct cli_state * cli )
2000-04-25 18:04:06 +04:00
{
2001-11-26 10:53:33 +03:00
static fstring cli_error_message ;
2001-08-10 10:00:33 +04:00
uint32 flgs2 = SVAL ( cli - > inbuf , smb_flg2 ) , errnum ;
2001-12-10 22:48:43 +03:00
uint8 errclass ;
int i ;
2002-02-13 19:44:49 +03:00
if ( ! cli - > initialised ) {
fstrcpy ( cli_error_message , " [Programmer's error] cli_errstr called on unitialized cli_stat struct! \n " ) ;
return cli_error_message ;
}
2002-10-01 10:50:38 +04:00
/* Was it server socket error ? */
if ( cli - > fd = = - 1 & & cli - > smb_rw_error ) {
switch ( cli - > smb_rw_error ) {
case READ_TIMEOUT :
slprintf ( cli_error_message , sizeof ( cli_error_message ) - 1 ,
" Call timed out: server did not respond after %d milliseconds " ,
cli - > timeout ) ;
break ;
case READ_EOF :
slprintf ( cli_error_message , sizeof ( cli_error_message ) - 1 ,
2003-04-21 17:00:39 +04:00
" Call returned zero bytes (EOF) " ) ;
2002-10-01 10:50:38 +04:00
break ;
case READ_ERROR :
slprintf ( cli_error_message , sizeof ( cli_error_message ) - 1 ,
2003-04-21 17:00:39 +04:00
" Read error: %s " , strerror ( errno ) ) ;
2002-10-01 10:50:38 +04:00
break ;
case WRITE_ERROR :
slprintf ( cli_error_message , sizeof ( cli_error_message ) - 1 ,
2003-04-21 17:00:39 +04:00
" Write error: %s " , strerror ( errno ) ) ;
2002-10-01 10:50:38 +04:00
break ;
2003-04-21 17:00:39 +04:00
case READ_BAD_SIG :
slprintf ( cli_error_message , sizeof ( cli_error_message ) - 1 ,
2003-07-16 09:51:10 +04:00
" Server packet had invalid SMB signature! " ) ;
2003-04-21 17:00:39 +04:00
break ;
default :
2002-10-01 10:50:38 +04:00
slprintf ( cli_error_message , sizeof ( cli_error_message ) - 1 ,
" Unknown error code %d \n " , cli - > smb_rw_error ) ;
break ;
}
2002-10-01 05:41:20 +04:00
return cli_error_message ;
}
2001-12-10 22:48:43 +03:00
/* Case #1: RAP error */
if ( cli - > rap_error ) {
for ( i = 0 ; rap_errmap [ i ] . message ! = NULL ; i + + ) {
if ( rap_errmap [ i ] . err = = cli - > rap_error ) {
return rap_errmap [ i ] . message ;
}
2001-12-10 22:18:56 +03:00
}
2001-12-10 22:48:43 +03:00
slprintf ( cli_error_message , sizeof ( cli_error_message ) - 1 , " RAP code %d " ,
cli - > rap_error ) ;
2000-04-25 18:04:06 +04:00
2001-12-10 22:48:43 +03:00
return cli_error_message ;
}
2000-04-25 18:04:06 +04:00
2001-12-10 22:48:43 +03:00
/* Case #2: 32-bit NT errors */
if ( flgs2 & FLAGS2_32_BIT_ERROR_CODES ) {
NTSTATUS status = NT_STATUS ( IVAL ( cli - > inbuf , smb_rcls ) ) ;
2001-08-10 10:00:33 +04:00
2002-03-17 07:36:35 +03:00
return nt_errstr ( status ) ;
2001-12-10 22:48:43 +03:00
}
2000-04-25 18:04:06 +04:00
2001-12-10 22:48:43 +03:00
cli_dos_error ( cli , & errclass , & errnum ) ;
2000-04-25 18:04:06 +04:00
2001-12-10 22:48:43 +03:00
/* Case #3: SMB error */
2001-08-10 10:00:33 +04:00
2001-12-10 22:48:43 +03:00
return cli_smb_errstr ( cli ) ;
2000-04-25 18:04:06 +04:00
}
2006-02-24 08:05:09 +03:00
/****************************************************************************
Return the 32 - bit NT status code from the last packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 21:52:23 +04:00
NTSTATUS cli_nt_error ( struct cli_state * cli )
2001-08-10 10:00:33 +04:00
{
int flgs2 = SVAL ( cli - > inbuf , smb_flg2 ) ;
2000-04-25 18:04:06 +04:00
2006-02-24 08:05:09 +03:00
/* Deal with socket errors first. */
if ( cli - > fd = = - 1 & & cli - > smb_rw_error ) {
return cli_smb_rw_error_to_ntstatus ( cli ) ;
}
2001-08-10 10:00:33 +04:00
if ( ! ( flgs2 & FLAGS2_32_BIT_ERROR_CODES ) ) {
2005-06-25 00:25:18 +04:00
int e_class = CVAL ( cli - > inbuf , smb_rcls ) ;
2001-08-27 12:19:43 +04:00
int code = SVAL ( cli - > inbuf , smb_err ) ;
2005-06-25 00:25:18 +04:00
return dos_to_ntstatus ( e_class , code ) ;
2001-08-10 10:00:33 +04:00
}
2001-08-27 21:52:23 +04:00
return NT_STATUS ( IVAL ( cli - > inbuf , smb_rcls ) ) ;
2001-08-10 10:00:33 +04:00
}
2001-08-27 12:19:43 +04:00
2006-02-24 08:05:09 +03:00
/****************************************************************************
Return the DOS error from the last packet - an error class and an error
code .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 12:19:43 +04:00
void cli_dos_error ( struct cli_state * cli , uint8 * eclass , uint32 * ecode )
2000-04-25 18:04:06 +04:00
{
int flgs2 ;
2006-02-24 08:05:09 +03:00
if ( ! cli - > initialised ) {
return ;
}
/* Deal with socket errors first. */
if ( cli - > fd = = - 1 & & cli - > smb_rw_error ) {
NTSTATUS status = cli_smb_rw_error_to_ntstatus ( cli ) ;
ntstatus_to_dos ( status , eclass , ecode ) ;
return ;
}
2000-04-25 18:04:06 +04:00
flgs2 = SVAL ( cli - > inbuf , smb_flg2 ) ;
if ( flgs2 & FLAGS2_32_BIT_ERROR_CODES ) {
2001-08-27 21:52:23 +04:00
NTSTATUS ntstatus = NT_STATUS ( IVAL ( cli - > inbuf , smb_rcls ) ) ;
2001-08-27 12:19:43 +04:00
ntstatus_to_dos ( ntstatus , eclass , ecode ) ;
2001-08-10 10:00:33 +04:00
return ;
}
2000-04-25 18:04:06 +04:00
2006-08-28 05:56:17 +04:00
* eclass = CVAL ( cli - > inbuf , smb_rcls ) ;
* ecode = SVAL ( cli - > inbuf , smb_err ) ;
2001-08-10 10:00:33 +04:00
}
2000-04-25 18:04:06 +04:00
2001-08-10 10:00:33 +04:00
/* Return a UNIX errno from a NT status code */
2006-09-24 01:41:41 +04:00
struct {
2001-08-27 21:52:23 +04:00
NTSTATUS status ;
int error ;
} nt_errno_map [ ] = {
{ NT_STATUS_ACCESS_VIOLATION , EACCES } ,
{ NT_STATUS_INVALID_HANDLE , EBADF } ,
{ NT_STATUS_ACCESS_DENIED , EACCES } ,
{ NT_STATUS_OBJECT_NAME_NOT_FOUND , ENOENT } ,
{ NT_STATUS_SHARING_VIOLATION , EBUSY } ,
{ NT_STATUS_OBJECT_PATH_INVALID , ENOTDIR } ,
{ NT_STATUS_OBJECT_NAME_COLLISION , EEXIST } ,
{ NT_STATUS_PATH_NOT_COVERED , ENOENT } ,
2003-04-15 18:42:06 +04:00
{ NT_STATUS_UNSUCCESSFUL , EINVAL } ,
{ NT_STATUS_NOT_IMPLEMENTED , ENOSYS } ,
{ NT_STATUS_IN_PAGE_ERROR , EFAULT } ,
{ NT_STATUS_BAD_NETWORK_NAME , ENOENT } ,
# ifdef EDQUOT
{ NT_STATUS_PAGEFILE_QUOTA , EDQUOT } ,
{ NT_STATUS_QUOTA_EXCEEDED , EDQUOT } ,
{ NT_STATUS_REGISTRY_QUOTA_LIMIT , EDQUOT } ,
{ NT_STATUS_LICENSE_QUOTA_EXCEEDED , EDQUOT } ,
# endif
# ifdef ETIME
{ NT_STATUS_TIMER_NOT_CANCELED , ETIME } ,
# endif
{ NT_STATUS_INVALID_PARAMETER , EINVAL } ,
{ NT_STATUS_NO_SUCH_DEVICE , ENODEV } ,
{ NT_STATUS_NO_SUCH_FILE , ENOENT } ,
# ifdef ENODATA
{ NT_STATUS_END_OF_FILE , ENODATA } ,
# endif
# ifdef ENOMEDIUM
{ NT_STATUS_NO_MEDIA_IN_DEVICE , ENOMEDIUM } ,
{ NT_STATUS_NO_MEDIA , ENOMEDIUM } ,
# endif
{ NT_STATUS_NONEXISTENT_SECTOR , ESPIPE } ,
{ NT_STATUS_NO_MEMORY , ENOMEM } ,
{ NT_STATUS_CONFLICTING_ADDRESSES , EADDRINUSE } ,
{ NT_STATUS_NOT_MAPPED_VIEW , EINVAL } ,
{ NT_STATUS_UNABLE_TO_FREE_VM , EADDRINUSE } ,
{ NT_STATUS_ACCESS_DENIED , EACCES } ,
{ NT_STATUS_BUFFER_TOO_SMALL , ENOBUFS } ,
{ NT_STATUS_WRONG_PASSWORD , EACCES } ,
{ NT_STATUS_LOGON_FAILURE , EACCES } ,
{ NT_STATUS_INVALID_WORKSTATION , EACCES } ,
{ NT_STATUS_INVALID_LOGON_HOURS , EACCES } ,
{ NT_STATUS_PASSWORD_EXPIRED , EACCES } ,
{ NT_STATUS_ACCOUNT_DISABLED , EACCES } ,
{ NT_STATUS_DISK_FULL , ENOSPC } ,
{ NT_STATUS_INVALID_PIPE_STATE , EPIPE } ,
{ NT_STATUS_PIPE_BUSY , EPIPE } ,
{ NT_STATUS_PIPE_DISCONNECTED , EPIPE } ,
{ NT_STATUS_PIPE_NOT_AVAILABLE , ENOSYS } ,
{ NT_STATUS_FILE_IS_A_DIRECTORY , EISDIR } ,
{ NT_STATUS_NOT_SUPPORTED , ENOSYS } ,
{ NT_STATUS_NOT_A_DIRECTORY , ENOTDIR } ,
{ NT_STATUS_DIRECTORY_NOT_EMPTY , ENOTEMPTY } ,
{ NT_STATUS_NETWORK_UNREACHABLE , ENETUNREACH } ,
{ NT_STATUS_HOST_UNREACHABLE , EHOSTUNREACH } ,
{ NT_STATUS_CONNECTION_ABORTED , ECONNABORTED } ,
{ NT_STATUS_CONNECTION_REFUSED , ECONNREFUSED } ,
{ NT_STATUS_TOO_MANY_LINKS , EMLINK } ,
{ NT_STATUS_NETWORK_BUSY , EBUSY } ,
{ NT_STATUS_DEVICE_DOES_NOT_EXIST , ENODEV } ,
# ifdef ELIBACC
{ NT_STATUS_DLL_NOT_FOUND , ELIBACC } ,
# endif
{ NT_STATUS_PIPE_BROKEN , EPIPE } ,
{ NT_STATUS_REMOTE_NOT_LISTENING , ECONNREFUSED } ,
{ NT_STATUS_NETWORK_ACCESS_DENIED , EACCES } ,
{ NT_STATUS_TOO_MANY_OPENED_FILES , EMFILE } ,
# ifdef EPROTO
{ NT_STATUS_DEVICE_PROTOCOL_ERROR , EPROTO } ,
# endif
{ NT_STATUS_FLOAT_OVERFLOW , ERANGE } ,
{ NT_STATUS_FLOAT_UNDERFLOW , ERANGE } ,
{ NT_STATUS_INTEGER_OVERFLOW , ERANGE } ,
{ NT_STATUS_MEDIA_WRITE_PROTECTED , EROFS } ,
{ NT_STATUS_PIPE_CONNECTED , EISCONN } ,
{ NT_STATUS_MEMORY_NOT_ALLOCATED , EFAULT } ,
{ NT_STATUS_FLOAT_INEXACT_RESULT , ERANGE } ,
{ NT_STATUS_ILL_FORMED_PASSWORD , EACCES } ,
{ NT_STATUS_PASSWORD_RESTRICTION , EACCES } ,
{ NT_STATUS_ACCOUNT_RESTRICTION , EACCES } ,
{ NT_STATUS_PORT_CONNECTION_REFUSED , ECONNREFUSED } ,
{ NT_STATUS_NAME_TOO_LONG , ENAMETOOLONG } ,
{ NT_STATUS_REMOTE_DISCONNECT , ESHUTDOWN } ,
{ NT_STATUS_CONNECTION_DISCONNECTED , ECONNABORTED } ,
{ NT_STATUS_CONNECTION_RESET , ENETRESET } ,
# ifdef ENOTUNIQ
{ NT_STATUS_IP_ADDRESS_CONFLICT1 , ENOTUNIQ } ,
{ NT_STATUS_IP_ADDRESS_CONFLICT2 , ENOTUNIQ } ,
# endif
{ NT_STATUS_PORT_MESSAGE_TOO_LONG , EMSGSIZE } ,
{ NT_STATUS_PROTOCOL_UNREACHABLE , ENOPROTOOPT } ,
{ NT_STATUS_ADDRESS_ALREADY_EXISTS , EADDRINUSE } ,
{ NT_STATUS_PORT_UNREACHABLE , EHOSTUNREACH } ,
{ NT_STATUS_IO_TIMEOUT , ETIMEDOUT } ,
{ NT_STATUS_RETRY , EAGAIN } ,
2004-05-07 13:50:43 +04:00
# ifdef ENOTUNIQ
{ NT_STATUS_DUPLICATE_NAME , ENOTUNIQ } ,
# endif
2003-04-15 18:42:06 +04:00
# ifdef ECOMM
{ NT_STATUS_NET_WRITE_FAULT , ECOMM } ,
# endif
2001-08-27 21:52:23 +04:00
{ NT_STATUS ( 0 ) , 0 }
} ;
2006-02-24 08:05:09 +03:00
/****************************************************************************
The following mappings need tidying up and moving into libsmb / errormap . c . . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
static int cli_errno_from_nt ( NTSTATUS status )
2001-08-10 10:00:33 +04:00
{
2001-08-27 21:52:23 +04:00
int i ;
DEBUG ( 10 , ( " cli_errno_from_nt: 32 bit codes: code=%08x \n " , NT_STATUS_V ( status ) ) ) ;
2001-08-10 10:00:33 +04:00
/* Status codes without this bit set are not errors */
2006-02-24 08:05:09 +03:00
if ( ! ( NT_STATUS_V ( status ) & 0xc0000000 ) ) {
2001-08-10 10:00:33 +04:00
return 0 ;
2006-02-24 08:05:09 +03:00
}
2001-08-10 10:00:33 +04:00
2001-08-27 21:52:23 +04:00
for ( i = 0 ; nt_errno_map [ i ] . error ; i + + ) {
if ( NT_STATUS_V ( nt_errno_map [ i ] . status ) = =
NT_STATUS_V ( status ) ) return nt_errno_map [ i ] . error ;
}
2001-08-10 10:00:33 +04:00
/* for all other cases - a default code */
return EINVAL ;
}
/* Return a UNIX errno appropriate for the error received in the last
packet . */
int cli_errno ( struct cli_state * cli )
{
2006-02-24 08:47:19 +03:00
NTSTATUS status ;
2006-02-24 08:05:09 +03:00
if ( cli_is_nt_error ( cli ) ) {
2006-02-24 08:47:19 +03:00
status = cli_nt_error ( cli ) ;
return cli_errno_from_nt ( status ) ;
2006-02-24 08:05:09 +03:00
}
2001-08-10 10:00:33 +04:00
2001-08-28 05:28:01 +04:00
if ( cli_is_dos_error ( cli ) ) {
2001-08-10 10:00:33 +04:00
uint8 eclass ;
uint32 ecode ;
cli_dos_error ( cli , & eclass , & ecode ) ;
2006-02-24 08:47:19 +03:00
status = dos_to_ntstatus ( eclass , ecode ) ;
return cli_errno_from_nt ( status ) ;
2001-08-10 10:00:33 +04:00
}
2006-02-24 08:05:09 +03:00
/* for other cases */
return EINVAL ;
2001-08-10 10:00:33 +04:00
}
/* Return true if the last packet was in error */
BOOL cli_is_error ( struct cli_state * cli )
{
uint32 flgs2 = SVAL ( cli - > inbuf , smb_flg2 ) , rcls = 0 ;
2006-02-24 08:05:09 +03:00
/* A socket error is always an error. */
if ( cli - > fd = = - 1 & & cli - > smb_rw_error ! = 0 ) {
2003-07-30 22:57:37 +04:00
return True ;
2006-02-24 08:05:09 +03:00
}
2003-07-30 22:57:37 +04:00
2001-08-21 07:04:41 +04:00
if ( flgs2 & FLAGS2_32_BIT_ERROR_CODES ) {
/* Return error is error bits are set */
2001-08-10 10:00:33 +04:00
rcls = IVAL ( cli - > inbuf , smb_rcls ) ;
2001-08-21 07:04:41 +04:00
return ( rcls & 0xF0000000 ) = = 0xC0000000 ;
}
/* Return error if error class in non-zero */
2001-08-10 10:00:33 +04:00
2001-08-21 07:04:41 +04:00
rcls = CVAL ( cli - > inbuf , smb_rcls ) ;
return rcls ! = 0 ;
2001-08-10 10:00:33 +04:00
}
/* Return true if the last error was an NT error */
BOOL cli_is_nt_error ( struct cli_state * cli )
{
uint32 flgs2 = SVAL ( cli - > inbuf , smb_flg2 ) ;
2006-02-24 08:05:09 +03:00
/* A socket error is always an NT error. */
if ( cli - > fd = = - 1 & & cli - > smb_rw_error ! = 0 ) {
return True ;
}
2001-08-10 10:00:33 +04:00
return cli_is_error ( cli ) & & ( flgs2 & FLAGS2_32_BIT_ERROR_CODES ) ;
}
/* Return true if the last error was a DOS error */
BOOL cli_is_dos_error ( struct cli_state * cli )
{
uint32 flgs2 = SVAL ( cli - > inbuf , smb_flg2 ) ;
2006-02-24 08:05:09 +03:00
/* A socket error is always a DOS error. */
if ( cli - > fd = = - 1 & & cli - > smb_rw_error ! = 0 ) {
return True ;
}
2001-08-10 10:00:33 +04:00
return cli_is_error ( cli ) & & ! ( flgs2 & FLAGS2_32_BIT_ERROR_CODES ) ;
}
2005-09-30 21:13:37 +04:00
/* Return the last error always as an NTSTATUS. */
NTSTATUS cli_get_nt_error ( struct cli_state * cli )
{
if ( cli_is_nt_error ( cli ) ) {
return cli_nt_error ( cli ) ;
} else if ( cli_is_dos_error ( cli ) ) {
uint32 ecode ;
uint8 eclass ;
cli_dos_error ( cli , & eclass , & ecode ) ;
return dos_to_ntstatus ( eclass , ecode ) ;
} else {
/* Something went wrong, we don't know what. */
return NT_STATUS_UNSUCCESSFUL ;
}
}