windows-nt/Source/XPSP1/NT/ds/netapi/netlib/rpcfail.c

293 lines
9.7 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991-1993 Microsoft Corporation
Module Name:
RpcFail.c
Abstract:
This routine is a captive of the NET_REMOTE_RPC_FAILED macro in
netrpc.h. See that header file for more info.
Author:
John Rogers (JohnRo) 01-Nov-1991
Environment:
User Mode - Win32
Only runs under NT; has an NT-specific interface (with Win32 types).
Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
01-Nov-1991 JohnRo
Created this routine as part of fixing RAID 3414: allow explicit local
server name.
07-Nov-1991 JohnRo
RAID 4186: assert in RxNetShareAdd and other DLL stub problems.
12-Nov-1991 JohnRo
Return correct error code for server not started.
17-Jan-1992 JohnRo
Added NET_REMOTE_RPC_FAILED_W for UNICODE-only server names.
08-Apr-1992 JohnRo
Clarify that ServiceName parameter is OPTIONAL.
12-Jan-1993 JohnRo
RAID 1586: NetReplSetInfo fails after stop service. (Also fix error
code if remote RPC service is not started.)
Use PREFIX_ equates.
Use NetpKdPrint where possible.
30-Jun-1993 JohnRo
Perhaps we don't need to query if remote service is started.
Also handle RPC_S_SERVER_TOO_BUSY.
--*/
// These must be included first:
#include <nt.h> // IN, etc.
#include <windef.h> // LPVOID, etc.
#include <lmcons.h> // NET_API_STATUS, etc.
#include <rpc.h> // Needed by NetRpc.h
// These may be included in any order:
#include <debuglib.h> // IF_DEBUG().
#include <lmerr.h> // NERR_Success, etc.
#include <lmremutl.h> // NetpRemoteComputerSupports(), SUPPORTS_ stuff
#include <lmsname.h> // SERVICE_ equates.
#include <netdebug.h> // FORMAT_ equates, LPDEBUG_STRING, NetpKdPrint(), etc.
#include <netlib.h> // NetpIsServiceStarted().
#include <netrpc.h> // My prototypes, NET_REMOTE_FLAG_ equates.
#include <prefix.h> // PREFIX_ equates.
#include <rpcutil.h> // NetpRpcStatusToApiStatus().
#include <tstring.h> // NetpAlloc{type}From{type}(), TCHAR_EOS, STRICMP().
#define UnexpectedMsg( debugString ) \
{ \
NetpKdPrint(( PREFIX_NETAPI \
FORMAT_LPDEBUG_STRING ": unexpected situation... " \
debugString ", rpc status is " FORMAT_RPC_STATUS ".\n", \
DebugName, RpcStatus )); \
}
NET_API_STATUS
NetpHandleRpcFailure(
IN LPDEBUG_STRING DebugName, // Used by UnexpectedMsg().
IN RPC_STATUS RpcStatus, // Used by UnexpectedMsg().
IN LPTSTR ServerNameValue OPTIONAL,
IN LPTSTR ServiceName OPTIONAL,
IN DWORD Flags, // NET_REMOTE_FLAG_ stuff.
OUT LPBOOL TryDownlevel
)
{
NET_API_STATUS ApiStatus;
*TryDownlevel = FALSE; // Be pesimistic until we know for sure.
if (RpcStatus == RPC_S_OK) {
//
// Exception without error code? Don't try the downlevel call.
// In theory, this should never happen.
//
UnexpectedMsg( "exception with RPC_S_OK" );
return (NERR_InternalError);
} else if (RpcStatus == ERROR_ACCESS_DENIED) {
//
// Exception was access denied, so it does no good to go any further
//
return (RpcStatus);
}
else
{ // exception with error code
DWORD OptionsSupported = 0;
//
// Learn about the machine. This is fairly easy since the
// NetRemoteComputerSupports also handles the local machine (whether
// or not a server name is given).
//
ApiStatus = NetRemoteComputerSupports(
ServerNameValue,
SUPPORTS_RPC | SUPPORTS_LOCAL, // options wanted
&OptionsSupported);
if (ApiStatus != NERR_Success) {
// This is where machine not found gets handled.
return (ApiStatus);
}
if (OptionsSupported & SUPPORTS_LOCAL) {
//
// Local service not started?
//
if (RpcStatus == RPC_S_SERVER_UNAVAILABLE ||
RpcStatus == RPC_S_UNKNOWN_IF ) {
if ( (Flags & NET_REMOTE_FLAG_SVC_CTRL) == 0 ) {
NetpAssert( ServiceName != NULL );
NetpAssert( (*ServiceName) != TCHAR_EOS );
//
// This isn't a service controller API, so we can ask the
// service controller if the service is started.
//
if ( !NetpIsServiceStarted(ServiceName)) {
// Local service not started.
if (STRICMP( ServiceName,
(LPTSTR) SERVICE_WORKSTATION) == 0) {
return (NERR_WkstaNotStarted);
} else if (STRICMP( ServiceName,
(LPTSTR) SERVICE_SERVER) == 0) {
return (NERR_ServerNotStarted);
} else {
return (NERR_ServiceNotInstalled);
}
/*NOTREACHED*/
} else { // local service started
//
// In theory, this shouldn't be possible,
// but just in case...
//
UnexpectedMsg("local, can't connect, started");
return (NetpRpcStatusToApiStatus(RpcStatus));
}
/*NOTREACHED*/
} else { // local, can't connect, service controller API
//
// Perhaps service controller died? Bug in RPC?
// Service too busy?
// Or, may just be out of memory trying to connect...
//
UnexpectedMsg(
"local, can't connect, service controller API" );
return (NetpRpcStatusToApiStatus(RpcStatus));
}
/*NOTREACHED*/
} else {
// Local and something besides RPC_S_SERVER_UNAVAILABLE.
// Perhaps we just ran out of memory, or service too busy.
UnexpectedMsg( "local, not RPC_S_SERVER_UNAVAILABLE" );
return (NetpRpcStatusToApiStatus(RpcStatus));
}
/*NOTREACHED*/
} else { // remote machine
//
// Local workstation is not started? (It must be in order to
// remote downlevel APIs to the other system.)
//
if ( (RpcStatus == RPC_S_SERVER_UNAVAILABLE) &&
( !NetpIsServiceStarted( (LPTSTR) SERVICE_WORKSTATION))) {
return (NERR_WkstaNotStarted);
} else if (RpcStatus == RPC_S_SERVER_UNAVAILABLE) {
//
// Local wksta is started, assume remote service isn't...
// Remote RPC binding failed. Find out why.
//
IF_DEBUG(DLLSTUBS) {
NetpKdPrint(( PREFIX_NETAPI
FORMAT_LPDEBUG_STRING
": RPC binding failed.\n", DebugName));
}
//
// See if the machine supports RPC. If it does, we do not
// try the downlevel calls, but just return the error.
//
if (OptionsSupported & SUPPORTS_RPC) {
if ( (Flags & NET_REMOTE_FLAG_SVC_CTRL) == 0 ) {
NetpAssert( ServiceName != NULL );
NetpAssert( (*ServiceName) != TCHAR_EOS );
//
// This isn't a service controller API, so we can
// generate an error code based on the service name.
//
if (STRICMP( ServiceName,
(LPTSTR) SERVICE_WORKSTATION) == 0) {
return (NERR_WkstaNotStarted);
} else if (STRICMP( ServiceName,
(LPTSTR) SERVICE_SERVER) == 0) {
return (NERR_ServerNotStarted);
} else {
return (NERR_ServiceNotInstalled);
}
/*NOTREACHED*/
} else { // local, can't connect, service controller API
UnexpectedMsg( "remote svc ctrl: "
"machine supports RPC, or other error." );
return (NetpRpcStatusToApiStatus(RpcStatus));
}
/*NOTREACHED*/
} else { // need to call downlevel
// NetpKdPrint(( PREFIX_NETAPI
// FORMAT_LPDEBUG_STRING
// ": call downlevel.\n", DebugName ));
//
// Caller would insert a call to some RxNet routine
// after the NET_REMOTE_RPC_FAILED macro. This flag is how
// we tell the macro whether or not to fall into that call.
//
*TryDownlevel = TRUE;
return (ERROR_NOT_SUPPORTED); // any error code will do.
} // need to call downlevel
/*NOTREACHED*/
} else {
//
// Perhaps just out of memory somewhere, server too busy, etc.
//
UnexpectedMsg("remote, not RPC_S_SERVER_UNAVAILABLE");
return (NetpRpcStatusToApiStatus(RpcStatus));
}
/*NOTREACHED*/
} // remote machine
/*NOTREACHED*/
} // exception with error code
/*NOTREACHED*/
} // NetpHandleRpcFailure