Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

292 lines
10 KiB

  1. /*++
  2. Copyright (c) 1991-1993 Microsoft Corporation
  3. Module Name:
  4. RpcFail.c
  5. Abstract:
  6. This routine is a captive of the NET_REMOTE_RPC_FAILED macro in
  7. netrpc.h. See that header file for more info.
  8. Author:
  9. John Rogers (JohnRo) 01-Nov-1991
  10. Environment:
  11. User Mode - Win32
  12. Only runs under NT; has an NT-specific interface (with Win32 types).
  13. Requires ANSI C extensions: slash-slash comments, long external names.
  14. Revision History:
  15. 01-Nov-1991 JohnRo
  16. Created this routine as part of fixing RAID 3414: allow explicit local
  17. server name.
  18. 07-Nov-1991 JohnRo
  19. RAID 4186: assert in RxNetShareAdd and other DLL stub problems.
  20. 12-Nov-1991 JohnRo
  21. Return correct error code for server not started.
  22. 17-Jan-1992 JohnRo
  23. Added NET_REMOTE_RPC_FAILED_W for UNICODE-only server names.
  24. 08-Apr-1992 JohnRo
  25. Clarify that ServiceName parameter is OPTIONAL.
  26. 12-Jan-1993 JohnRo
  27. RAID 1586: NetReplSetInfo fails after stop service. (Also fix error
  28. code if remote RPC service is not started.)
  29. Use PREFIX_ equates.
  30. Use NetpKdPrint where possible.
  31. 30-Jun-1993 JohnRo
  32. Perhaps we don't need to query if remote service is started.
  33. Also handle RPC_S_SERVER_TOO_BUSY.
  34. --*/
  35. // These must be included first:
  36. #include <nt.h> // IN, etc.
  37. #include <windef.h> // LPVOID, etc.
  38. #include <lmcons.h> // NET_API_STATUS, etc.
  39. #include <rpc.h> // Needed by NetRpc.h
  40. // These may be included in any order:
  41. #include <debuglib.h> // IF_DEBUG().
  42. #include <lmerr.h> // NERR_Success, etc.
  43. #include <lmremutl.h> // NetpRemoteComputerSupports(), SUPPORTS_ stuff
  44. #include <lmsname.h> // SERVICE_ equates.
  45. #include <netdebug.h> // FORMAT_ equates, LPDEBUG_STRING, NetpKdPrint(), etc.
  46. #include <netlib.h> // NetpIsServiceStarted().
  47. #include <netrpc.h> // My prototypes, NET_REMOTE_FLAG_ equates.
  48. #include <prefix.h> // PREFIX_ equates.
  49. #include <rpcutil.h> // NetpRpcStatusToApiStatus().
  50. #include <tstring.h> // NetpAlloc{type}From{type}(), TCHAR_EOS, STRICMP().
  51. #define UnexpectedMsg( debugString ) \
  52. { \
  53. NetpKdPrint(( PREFIX_NETAPI \
  54. FORMAT_LPDEBUG_STRING ": unexpected situation... " \
  55. debugString ", rpc status is " FORMAT_RPC_STATUS ".\n", \
  56. DebugName, RpcStatus )); \
  57. }
  58. NET_API_STATUS
  59. NetpHandleRpcFailure(
  60. IN LPDEBUG_STRING DebugName, // Used by UnexpectedMsg().
  61. IN RPC_STATUS RpcStatus, // Used by UnexpectedMsg().
  62. IN LPTSTR ServerNameValue OPTIONAL,
  63. IN LPTSTR ServiceName OPTIONAL,
  64. IN DWORD Flags, // NET_REMOTE_FLAG_ stuff.
  65. OUT LPBOOL TryDownlevel
  66. )
  67. {
  68. NET_API_STATUS ApiStatus;
  69. *TryDownlevel = FALSE; // Be pesimistic until we know for sure.
  70. if (RpcStatus == RPC_S_OK) {
  71. //
  72. // Exception without error code? Don't try the downlevel call.
  73. // In theory, this should never happen.
  74. //
  75. UnexpectedMsg( "exception with RPC_S_OK" );
  76. return (NERR_InternalError);
  77. } else if (RpcStatus == ERROR_ACCESS_DENIED) {
  78. //
  79. // Exception was access denied, so it does no good to go any further
  80. //
  81. return (RpcStatus);
  82. }
  83. else
  84. { // exception with error code
  85. DWORD OptionsSupported = 0;
  86. //
  87. // Learn about the machine. This is fairly easy since the
  88. // NetRemoteComputerSupports also handles the local machine (whether
  89. // or not a server name is given).
  90. //
  91. ApiStatus = NetRemoteComputerSupports(
  92. ServerNameValue,
  93. SUPPORTS_RPC | SUPPORTS_LOCAL, // options wanted
  94. &OptionsSupported);
  95. if (ApiStatus != NERR_Success) {
  96. // This is where machine not found gets handled.
  97. return (ApiStatus);
  98. }
  99. if (OptionsSupported & SUPPORTS_LOCAL) {
  100. //
  101. // Local service not started?
  102. //
  103. if (RpcStatus == RPC_S_SERVER_UNAVAILABLE ||
  104. RpcStatus == RPC_S_UNKNOWN_IF ) {
  105. if ( (Flags & NET_REMOTE_FLAG_SVC_CTRL) == 0 ) {
  106. NetpAssert( ServiceName != NULL );
  107. NetpAssert( (*ServiceName) != TCHAR_EOS );
  108. //
  109. // This isn't a service controller API, so we can ask the
  110. // service controller if the service is started.
  111. //
  112. if ( !NetpIsServiceStarted(ServiceName)) {
  113. // Local service not started.
  114. if (STRICMP( ServiceName,
  115. (LPTSTR) SERVICE_WORKSTATION) == 0) {
  116. return (NERR_WkstaNotStarted);
  117. } else if (STRICMP( ServiceName,
  118. (LPTSTR) SERVICE_SERVER) == 0) {
  119. return (NERR_ServerNotStarted);
  120. } else {
  121. return (NERR_ServiceNotInstalled);
  122. }
  123. /*NOTREACHED*/
  124. } else { // local service started
  125. //
  126. // In theory, this shouldn't be possible,
  127. // but just in case...
  128. //
  129. UnexpectedMsg("local, can't connect, started");
  130. return (NetpRpcStatusToApiStatus(RpcStatus));
  131. }
  132. /*NOTREACHED*/
  133. } else { // local, can't connect, service controller API
  134. //
  135. // Perhaps service controller died? Bug in RPC?
  136. // Service too busy?
  137. // Or, may just be out of memory trying to connect...
  138. //
  139. UnexpectedMsg(
  140. "local, can't connect, service controller API" );
  141. return (NetpRpcStatusToApiStatus(RpcStatus));
  142. }
  143. /*NOTREACHED*/
  144. } else {
  145. // Local and something besides RPC_S_SERVER_UNAVAILABLE.
  146. // Perhaps we just ran out of memory, or service too busy.
  147. UnexpectedMsg( "local, not RPC_S_SERVER_UNAVAILABLE" );
  148. return (NetpRpcStatusToApiStatus(RpcStatus));
  149. }
  150. /*NOTREACHED*/
  151. } else { // remote machine
  152. //
  153. // Local workstation is not started? (It must be in order to
  154. // remote downlevel APIs to the other system.)
  155. //
  156. if ( (RpcStatus == RPC_S_SERVER_UNAVAILABLE) &&
  157. ( !NetpIsServiceStarted( (LPTSTR) SERVICE_WORKSTATION))) {
  158. return (NERR_WkstaNotStarted);
  159. } else if (RpcStatus == RPC_S_SERVER_UNAVAILABLE) {
  160. //
  161. // Local wksta is started, assume remote service isn't...
  162. // Remote RPC binding failed. Find out why.
  163. //
  164. IF_DEBUG(DLLSTUBS) {
  165. NetpKdPrint(( PREFIX_NETAPI
  166. FORMAT_LPDEBUG_STRING
  167. ": RPC binding failed.\n", DebugName));
  168. }
  169. //
  170. // See if the machine supports RPC. If it does, we do not
  171. // try the downlevel calls, but just return the error.
  172. //
  173. if (OptionsSupported & SUPPORTS_RPC) {
  174. if ( (Flags & NET_REMOTE_FLAG_SVC_CTRL) == 0 ) {
  175. NetpAssert( ServiceName != NULL );
  176. NetpAssert( (*ServiceName) != TCHAR_EOS );
  177. //
  178. // This isn't a service controller API, so we can
  179. // generate an error code based on the service name.
  180. //
  181. if (STRICMP( ServiceName,
  182. (LPTSTR) SERVICE_WORKSTATION) == 0) {
  183. return (NERR_WkstaNotStarted);
  184. } else if (STRICMP( ServiceName,
  185. (LPTSTR) SERVICE_SERVER) == 0) {
  186. return (NERR_ServerNotStarted);
  187. } else {
  188. return (NERR_ServiceNotInstalled);
  189. }
  190. /*NOTREACHED*/
  191. } else { // local, can't connect, service controller API
  192. UnexpectedMsg( "remote svc ctrl: "
  193. "machine supports RPC, or other error." );
  194. return (NetpRpcStatusToApiStatus(RpcStatus));
  195. }
  196. /*NOTREACHED*/
  197. } else { // need to call downlevel
  198. // NetpKdPrint(( PREFIX_NETAPI
  199. // FORMAT_LPDEBUG_STRING
  200. // ": call downlevel.\n", DebugName ));
  201. //
  202. // Caller would insert a call to some RxNet routine
  203. // after the NET_REMOTE_RPC_FAILED macro. This flag is how
  204. // we tell the macro whether or not to fall into that call.
  205. //
  206. *TryDownlevel = TRUE;
  207. return (ERROR_NOT_SUPPORTED); // any error code will do.
  208. } // need to call downlevel
  209. /*NOTREACHED*/
  210. } else {
  211. //
  212. // Perhaps just out of memory somewhere, server too busy, etc.
  213. //
  214. UnexpectedMsg("remote, not RPC_S_SERVER_UNAVAILABLE");
  215. return (NetpRpcStatusToApiStatus(RpcStatus));
  216. }
  217. /*NOTREACHED*/
  218. } // remote machine
  219. /*NOTREACHED*/
  220. } // exception with error code
  221. /*NOTREACHED*/
  222. } // NetpHandleRpcFailure