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.

652 lines
18 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. dcecmmn.cxx
  5. Abstract:
  6. This module contains the code implementing the Binding Object DCE RPC
  7. runtime APIs which are common to both the client and server runtimes.
  8. Two different versions of each of the common APIs live in this file;
  9. one contains the code for both the client and server runtimes, the
  10. other contains the code for just the client runtime. The files
  11. dcecsvr.cxx (client and server) and dcecclnt.cxx (client) include
  12. this file. The client side only, dcecclnt.cxx, will define
  13. RPC_CLIENT_SIDE_ONLY.
  14. Author:
  15. Michael Montague (mikemon) 04-Nov-1991
  16. Revision History:
  17. --*/
  18. // This file is always included into file which include precomp.hxx
  19. #include <precomp.hxx>
  20. #include <rpcdce.h>
  21. #ifndef RPC_CLIENT_SIDE_ONLY
  22. #include <rpccfg.h>
  23. #endif
  24. #ifndef RPC_CLIENT_SIDE_ONLY
  25. #include <hndlsvr.hxx>
  26. #endif // RPC_CLIENT_SIDE_ONLY
  27. RPC_STATUS RPC_ENTRY
  28. RpcBindingInqObject (
  29. IN RPC_BINDING_HANDLE Binding,
  30. OUT UUID PAPI * ObjectUuid
  31. )
  32. /*++
  33. Routine Description:
  34. RpcBindingInqObject returns the object UUID from the binding handle.
  35. Arguments:
  36. Binding - Supplies a binding handle from which the object UUID will
  37. be returned.
  38. ObjectUuid - Returns the object UUID contained in the binding handle.
  39. Return Value:
  40. The status of the operation is returned.
  41. --*/
  42. {
  43. BINDING_HANDLE *BindingHandle;
  44. InitializeIfNecessary();
  45. BindingHandle = (BINDING_HANDLE *) Binding;
  46. #ifdef RPC_CLIENT_SIDE_ONLY
  47. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  48. return(RPC_S_INVALID_BINDING);
  49. BindingHandle->InquireObjectUuid((RPC_UUID PAPI *) ObjectUuid);
  50. #else // ! RPC_CLIENT_SIDE_ONLY
  51. if ( BindingHandle == 0 )
  52. {
  53. BindingHandle = (BINDING_HANDLE *) RpcpGetThreadContext();
  54. if ( BindingHandle == 0 )
  55. {
  56. return(RPC_S_NO_CALL_ACTIVE);
  57. }
  58. }
  59. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE | SCALL_TYPE))
  60. return(RPC_S_INVALID_BINDING);
  61. if (BindingHandle->Type(BINDING_HANDLE_TYPE))
  62. BindingHandle->InquireObjectUuid((RPC_UUID PAPI *) ObjectUuid);
  63. else
  64. ((SCALL *) BindingHandle)->InquireObjectUuid(
  65. (RPC_UUID PAPI *) ObjectUuid);
  66. #endif // RPC_CLIENT_SIDE_ONLY
  67. return(RPC_S_OK);
  68. }
  69. RPC_STATUS RPC_ENTRY
  70. RpcBindingToStringBinding (
  71. IN RPC_BINDING_HANDLE Binding,
  72. OUT unsigned short PAPI * PAPI * StringBinding
  73. )
  74. /*++
  75. Routine Description:
  76. RpcBindingToStringBinding returns a string representation of a binding
  77. handle.
  78. Arguments:
  79. Binding - Supplies a binding handle for which the string representation
  80. will be returned.
  81. StringBinding - Returns the string representation of the binding handle.
  82. Return Value:
  83. The status of the operation will be returned.
  84. --*/
  85. {
  86. #ifdef RPC_CLIENT_SIDE_ONLY
  87. BINDING_HANDLE * BindingHandle;
  88. InitializeIfNecessary();
  89. BindingHandle = (BINDING_HANDLE *) Binding;
  90. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  91. return(RPC_S_INVALID_BINDING);
  92. return(BindingHandle->ToStringBinding(StringBinding));
  93. #else // RPC_CLIENT_SIDE_ONLY
  94. BINDING_HANDLE * BindingHandle;
  95. InitializeIfNecessary();
  96. BindingHandle = (BINDING_HANDLE *) Binding;
  97. if (((GENERIC_OBJECT *) Binding)->InvalidHandle(BINDING_HANDLE_TYPE
  98. | SCALL_TYPE))
  99. return(RPC_S_INVALID_BINDING);
  100. if (((GENERIC_OBJECT *) Binding)->Type(BINDING_HANDLE_TYPE))
  101. return(((BINDING_HANDLE *) Binding)->ToStringBinding(
  102. StringBinding));
  103. else
  104. return(((SCALL *) Binding)->ToStringBinding(StringBinding));
  105. #endif // RPC_CLIENT_SIDE_ONLY
  106. }
  107. RPC_STATUS RPC_ENTRY
  108. I_RpcBindingToStaticStringBindingW (
  109. IN RPC_BINDING_HANDLE Binding,
  110. OUT unsigned short PAPI * PAPI * StringBinding
  111. )
  112. /*++
  113. Routine Description:
  114. RpcBindingToStringBinding returns a string representation of a binding
  115. handle.
  116. Arguments:
  117. Binding - Supplies a binding handle for which the string representation
  118. will be returned.
  119. StringBinding - Returns the string representation of the binding handle.
  120. Return Value:
  121. The status of the operation will be returned.
  122. --*/
  123. {
  124. RPC_STATUS Status;
  125. InitializeIfNecessary();
  126. if (((GENERIC_OBJECT *) Binding)->InvalidHandle(BINDING_HANDLE_TYPE))
  127. return(RPC_S_INVALID_BINDING);
  128. if (((GENERIC_OBJECT *) Binding)->InvalidHandle(SVR_BINDING_HANDLE_TYPE))
  129. {
  130. return (((BINDING_HANDLE *) Binding)->ToStringBinding(StringBinding));
  131. }
  132. return (((SVR_BINDING_HANDLE *) Binding)->ToStaticStringBinding(StringBinding));
  133. }
  134. RPC_STATUS RPC_ENTRY
  135. RpcMgmtInqDefaultProtectLevel(
  136. IN unsigned long AuthnSvc,
  137. OUT unsigned long PAPI *AuthnLevel
  138. )
  139. /*++
  140. Routine Description:
  141. Returns the default protect level for the specified authentication service.
  142. For Nt 3.5, all packaged except the DECs krb package must support
  143. connect level as their default.
  144. Arguments:
  145. AuthnSvc - Specified Authentication Service
  146. AuthnLevel - Default protection level supported.
  147. Return Value:
  148. RPC_S_OK - We successfully determined whether or not the client is
  149. local.
  150. --*/
  151. {
  152. RPC_CHAR DllName[255+1];
  153. #ifndef RPC_CLIENT_SIDE_ONLY
  154. RPC_CHAR *Dll = &DllName[0];
  155. #endif
  156. unsigned long Count;
  157. RPC_STATUS Status;
  158. InitializeIfNecessary();
  159. #ifndef RPC_CLIENT_SIDE_ONLY
  160. Status = RpcGetSecurityProviderInfo(
  161. AuthnSvc,
  162. &Dll,
  163. &Count);
  164. if (Status != RPC_S_OK)
  165. {
  166. ASSERT(Status == RPC_S_UNKNOWN_AUTHN_SERVICE);
  167. return (Status);
  168. }
  169. #endif
  170. //Authn Service is installed
  171. if (AuthnSvc == RPC_C_AUTHN_DCE_PRIVATE)
  172. {
  173. *AuthnLevel = RPC_C_PROTECT_LEVEL_PKT_INTEGRITY;
  174. }
  175. else
  176. {
  177. *AuthnLevel = RPC_C_PROTECT_LEVEL_CONNECT;
  178. }
  179. return (RPC_S_OK);
  180. }
  181. RPC_STATUS RPC_ENTRY
  182. RpcBindingSetOption( IN RPC_BINDING_HANDLE hBinding,
  183. IN unsigned long option,
  184. IN ULONG_PTR optionValue )
  185. /*++
  186. Routine Description:
  187. An RPC client calls this routine to set transport specific
  188. options for a binding handle.
  189. Arguments:
  190. hBinding - The binding handle in question. This must be of
  191. type BINDING_HANDLE_TYPE.
  192. option - Which transport specific option to set.
  193. optionValue - The new value for the transport option.
  194. Return Value: RPC_S_OK
  195. RPC_S_INVALID_BINDING
  196. RPC_S_CANNOT_SUPPORT
  197. --*/
  198. {
  199. RPC_STATUS Status;
  200. InitializeIfNecessary();
  201. if ((option == RPC_C_OPT_DONT_LINGER) && (optionValue == FALSE))
  202. return RPC_S_INVALID_ARG;
  203. if ( ((GENERIC_OBJECT*)hBinding)->InvalidHandle(BINDING_HANDLE_TYPE) )
  204. {
  205. Status = RpcSsGetContextBinding(hBinding, &hBinding);
  206. if (Status != RPC_S_OK)
  207. return RPC_S_INVALID_BINDING;
  208. return RpcBindingSetOption(hBinding, option, optionValue);
  209. }
  210. else
  211. return ((BINDING_HANDLE*)hBinding)->SetTransportOption(
  212. option,
  213. optionValue );
  214. }
  215. RPC_STATUS RPC_ENTRY
  216. RpcBindingInqOption( IN RPC_BINDING_HANDLE hBinding,
  217. IN unsigned long option,
  218. OUT ULONG_PTR *pOptionValue )
  219. /*++
  220. Routine Description:
  221. An RPC client calls this routine to get the value of a
  222. transport specific option for a binding handle.
  223. Arguments:
  224. hBinding - The binding handle in question. This must be of
  225. type BINDING_HANDLE_TYPE.
  226. option - Which transport specific option to set.
  227. pOptionValue- The current value for the transport option is
  228. returned here.
  229. Return Value: RPC_S_OK
  230. RPC_S_INVALID_BINDING
  231. RPC_S_CANNOT_SUPPORT
  232. --*/
  233. {
  234. InitializeIfNecessary();
  235. if ( ((GENERIC_OBJECT*)hBinding)->InvalidHandle(BINDING_HANDLE_TYPE) )
  236. return RPC_S_INVALID_BINDING;
  237. else
  238. {
  239. if (option > RPC_C_OPT_MAX_OPTIONS)
  240. {
  241. return RPC_S_INVALID_ARG;
  242. }
  243. return ((BINDING_HANDLE*)hBinding)->InqTransportOption(
  244. option,
  245. pOptionValue );
  246. }
  247. }
  248. RPC_STATUS RPC_ENTRY
  249. I_RpcBindingInqConnId (
  250. IN RPC_BINDING_HANDLE Binding,
  251. OUT void **ConnId,
  252. OUT BOOL *pfFirstCall
  253. )
  254. /*++
  255. Routine Description:
  256. Used to get the connection id corresponding to the binding handle.
  257. Arguments:
  258. Binding - Supplies the binding handle from which we wish to obtain
  259. the connection id.
  260. ConnId - If the call suceeds, *ConnId will contain the connection Id
  261. pfFirstCall - If the call succeeds,
  262. *pfFirstCall - 1 - This is the first time
  263. - 0 - This is not the first time
  264. Return Value:
  265. RPC_S_OK - The operation completed successfully.
  266. RPC_S_INVALID_BINDING - When the argument is not a binding handle.
  267. --*/
  268. {
  269. BINDING_HANDLE * BindingHandle;
  270. BindingHandle = (BINDING_HANDLE *) Binding;
  271. if (BindingHandle->InvalidHandle(SCALL_TYPE))
  272. return(RPC_S_INVALID_BINDING);
  273. return ((SCALL *) Binding)->InqConnection(ConnId, pfFirstCall);
  274. }
  275. RPC_STATUS RPC_ENTRY
  276. I_RpcBindingInqTransportType(
  277. IN RPC_BINDING_HANDLE Binding,
  278. OUT unsigned int __RPC_FAR * Type
  279. )
  280. /*++
  281. Routine Description:
  282. Determines what kind of transport this binding handle uses.
  283. Arguments:
  284. Binding - Supplies the binding handle from which we wish to obtain
  285. the information.
  286. Type - Points to the type of binding if the functions succeeds.
  287. One of:
  288. TRANSPORT_TYPE_CN
  289. TRANSPORT_TYPE_DG
  290. TRANSPORT_TYPE_LPC
  291. Return Value:
  292. RPC_S_OK - The operation completed successfully.
  293. RPC_S_INVALID_BINDING - When the argument is not a binding handle.
  294. --*/
  295. {
  296. BINDING_HANDLE * BindingHandle;
  297. InitializeIfNecessary();
  298. BindingHandle = (BINDING_HANDLE *) Binding;
  299. #ifndef RPC_CLIENT_SIDE_ONLY
  300. if ( BindingHandle == 0 )
  301. {
  302. BindingHandle = (BINDING_HANDLE *) RpcpGetThreadContext();
  303. if ( BindingHandle == 0 )
  304. {
  305. return(RPC_S_NO_CALL_ACTIVE);
  306. }
  307. }
  308. #endif
  309. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE|SCALL_TYPE))
  310. return(RPC_S_INVALID_BINDING);
  311. #ifndef RPC_CLIENT_SIDE_ONLY
  312. if (BindingHandle->Type(SCALL_TYPE))
  313. {
  314. return(((SCALL *)BindingHandle)->InqTransportType(Type));
  315. }
  316. else
  317. #endif
  318. return(BindingHandle->InquireTransportType(Type));
  319. }
  320. //
  321. // Map of RPC (local system) error codes to well known NCA error codes
  322. // so that the receiver can correctly convert these well known errors
  323. // into system specific errors.
  324. //
  325. const long RpcToNcaMap[] =
  326. {
  327. RPC_S_UNKNOWN_IF, NCA_STATUS_UNK_IF,
  328. RPC_S_NOT_LISTENING, NCA_STATUS_SERVER_TOO_BUSY,
  329. RPC_S_SERVER_TOO_BUSY, NCA_STATUS_SERVER_TOO_BUSY,
  330. RPC_S_PROTOCOL_ERROR, NCA_STATUS_PROTO_ERROR,
  331. RPC_S_PROCNUM_OUT_OF_RANGE, NCA_STATUS_OP_RNG_ERROR,
  332. RPC_S_UNSUPPORTED_TYPE, NCA_STATUS_UNSUPPORTED_TYPE,
  333. RPC_X_SS_CONTEXT_MISMATCH, NCA_STATUS_CONTEXT_MISMATCH,
  334. RPC_X_INVALID_BOUND, NCA_STATUS_INVALID_BOUND,
  335. RPC_X_SS_HANDLES_MISMATCH, NCA_STATUS_CONTEXT_MISMATCH,
  336. RPC_S_INVALID_TAG, NCA_STATUS_INVALID_TAG,
  337. RPC_S_OUT_OF_MEMORY, NCA_STATUS_REMOTE_OUT_OF_MEMORY,
  338. RPC_S_CALL_FAILED_DNE, NCA_STATUS_CALL_DNE,
  339. RPC_S_CALL_FAILED, NCA_STATUS_FAULT_UNSPEC,
  340. RPC_S_CALL_CANCELLED, NCA_STATUS_FAULT_CANCEL,
  341. RPC_S_COMM_FAILURE, NCA_STATUS_COMM_FAILURE,
  342. RPC_X_PIPE_EMPTY, NCA_STATUS_FAULT_PIPE_EMPTY,
  343. RPC_X_PIPE_CLOSED, NCA_STATUS_FAULT_PIPE_CLOSED,
  344. RPC_X_WRONG_PIPE_ORDER, NCA_STATUS_FAULT_PIPE_ORDER,
  345. RPC_X_PIPE_DISCIPLINE_ERROR,NCA_STATUS_FAULT_PIPE_DISCIPLINE,
  346. // Currently not used
  347. // NCA_STATUS_BAD_ACTID
  348. // NCA_STATUS_WHO_ARE_YOU_FAILED
  349. // NCA_STATUS_WRONG_BOOT_TIME
  350. // NCA_STATUS_YOU_CRASHED
  351. STATUS_INTEGER_DIVIDE_BY_ZERO, NCA_STATUS_ZERO_DIVIDE,
  352. STATUS_FLOAT_DIVIDE_BY_ZERO, NCA_STATUS_FP_DIV_ZERO,
  353. STATUS_FLOAT_UNDERFLOW, NCA_STATUS_FP_UNDERFLOW,
  354. STATUS_FLOAT_OVERFLOW, NCA_STATUS_FP_OVERFLOW,
  355. STATUS_FLOAT_INVALID_OPERATION, NCA_STATUS_FP_ERROR,
  356. STATUS_INTEGER_OVERFLOW, NCA_STATUS_OVERFLOW,
  357. // Note: these exceptions are not caught by our code.
  358. // STATUS_ACCESS_VIOLATION, NCA_STATUS_ADDRESS_ERROR,
  359. // STATUS_PRIVILEGED_INSTRUCTION, NCA_STATUS_ILLEGAL_INSTRUCTION,
  360. // STATUS_ILLEGAL_INSTRUCTION, NCA_STATUS_ILLEGAL_INSTRUCTION,
  361. };
  362. //
  363. // Map of NCA error codes to RPC (local system) error codes. These
  364. // errors usually arrive in fault packets and may have come from an
  365. // NT, Mac or OSF machine.
  366. //
  367. const long NcaToRpcMap[] =
  368. {
  369. NCA_STATUS_COMM_FAILURE, RPC_S_COMM_FAILURE,
  370. NCA_STATUS_OP_RNG_ERROR, RPC_S_PROCNUM_OUT_OF_RANGE,
  371. NCA_STATUS_UNK_IF, RPC_S_UNKNOWN_IF,
  372. NCA_STATUS_PROTO_ERROR, RPC_S_PROTOCOL_ERROR,
  373. NCA_STATUS_OUT_ARGS_TOO_BIG, RPC_S_SERVER_OUT_OF_MEMORY,
  374. NCA_STATUS_REMOTE_OUT_OF_MEMORY, RPC_S_SERVER_OUT_OF_MEMORY,
  375. NCA_STATUS_SERVER_TOO_BUSY, RPC_S_SERVER_TOO_BUSY,
  376. NCA_STATUS_UNSUPPORTED_TYPE, RPC_S_UNSUPPORTED_TYPE,
  377. NCA_STATUS_ILLEGAL_INSTRUCTION, RPC_S_ADDRESS_ERROR,
  378. NCA_STATUS_ADDRESS_ERROR, RPC_S_ADDRESS_ERROR,
  379. NCA_STATUS_OVERFLOW, RPC_S_ADDRESS_ERROR,
  380. NCA_STATUS_ZERO_DIVIDE, RPC_S_ZERO_DIVIDE,
  381. NCA_STATUS_FP_DIV_ZERO, RPC_S_FP_DIV_ZERO,
  382. NCA_STATUS_FP_UNDERFLOW, RPC_S_FP_UNDERFLOW,
  383. NCA_STATUS_FP_OVERFLOW, RPC_S_FP_OVERFLOW,
  384. NCA_STATUS_FP_ERROR, RPC_S_FP_OVERFLOW,
  385. NCA_STATUS_INVALID_TAG, RPC_S_INVALID_TAG,
  386. NCA_STATUS_INVALID_BOUND, RPC_S_INVALID_BOUND,
  387. NCA_STATUS_CONTEXT_MISMATCH, RPC_X_SS_CONTEXT_MISMATCH,
  388. NCA_STATUS_FAULT_CANCEL, RPC_S_CALL_CANCELLED,
  389. NCA_STATUS_WHO_ARE_YOU_FAILED, RPC_S_CALL_FAILED,
  390. NCA_STATUS_YOU_CRASHED, RPC_S_CALL_FAILED,
  391. NCA_STATUS_FAULT_UNSPEC, RPC_S_CALL_FAILED,
  392. NCA_STATUS_VERSION_MISMATCH, RPC_S_PROTOCOL_ERROR,
  393. NCA_STATUS_INVALID_PRES_CXT_ID, RPC_S_PROTOCOL_ERROR,
  394. NCA_STATUS_FAULT_PIPE_EMPTY, RPC_X_PIPE_EMPTY,
  395. NCA_STATUS_FAULT_PIPE_CLOSED, RPC_X_PIPE_CLOSED,
  396. NCA_STATUS_FAULT_PIPE_ORDER, RPC_X_WRONG_PIPE_ORDER,
  397. NCA_STATUS_FAULT_PIPE_MEMORY, RPC_S_OUT_OF_MEMORY,
  398. NCA_STATUS_FAULT_PIPE_DISCIPLINE, RPC_X_PIPE_DISCIPLINE_ERROR,
  399. NCA_STATUS_FAULT_PIPE_COMM_ERROR, RPC_S_COMM_FAILURE,
  400. NCA_STATUS_INVALID_CHECKSUM, RPC_S_CALL_FAILED_DNE,
  401. NCA_STATUS_INVALID_CRC, RPC_S_CALL_FAILED_DNE,
  402. NCA_STATUS_UNSPEC_REJECT, RPC_S_CALL_FAILED_DNE,
  403. NCA_STATUS_BAD_ACTID, RPC_S_CALL_FAILED_DNE,
  404. NCA_STATUS_CALL_DNE, RPC_S_CALL_FAILED_DNE,
  405. NCA_STATUS_UNSUPPORTED_AUTHN_LEVEL, RPC_S_UNSUPPORTED_AUTHN_LEVEL,
  406. // Catch all for OSF interop
  407. 0, RPC_S_CALL_FAILED
  408. };
  409. long
  410. MapStatusCode(
  411. IN long StatusToMap,
  412. IN const long aErrorMap[],
  413. IN unsigned MapSize
  414. )
  415. /*++
  416. Routine Description:
  417. Maps a status value from one type of error to another.
  418. Arguments:
  419. StatusToMap - The status code to map
  420. aErrorMap - An array of status codes of the format <original error><mapped error>
  421. MapSize - The number of <original error>'s in the array.
  422. Return Value:
  423. If a mapping is found it will be returned, otherwise the original error is returned.
  424. --*/
  425. {
  426. for (unsigned i = 0; i < MapSize; i++)
  427. {
  428. if (aErrorMap[i * 2] == StatusToMap)
  429. return(aErrorMap[i * 2 + 1]);
  430. }
  431. return(StatusToMap);
  432. }
  433. unsigned long
  434. MapToNcaStatusCode (
  435. IN RPC_STATUS RpcStatus
  436. )
  437. /*++
  438. Routine Description:
  439. This routine maps a local RPC status code to an NCA status code to
  440. be sent across the wire.
  441. Arguments:
  442. RpcStatus - Supplies the RPC status code to be mapped into an NCA
  443. status code.
  444. Return Value:
  445. The NCA status code will be returned. If the RPC status code could
  446. not be mapped, it will be returned unchanged.
  447. --*/
  448. {
  449. return((unsigned long) MapStatusCode(
  450. RpcStatus,
  451. RpcToNcaMap,
  452. sizeof(RpcToNcaMap)/(2*sizeof(long))
  453. )
  454. );
  455. }
  456. RPC_STATUS
  457. MapFromNcaStatusCode (
  458. IN unsigned long NcaStatus
  459. )
  460. /*++
  461. Routine Description:
  462. This routine is used to map an NCA status code (typically one received
  463. off of the wire) into a local RPC status code. If the NCA status code
  464. can not be mapped, it will be returned unchanged.
  465. Arguments:
  466. NcaStatus - Supplies the NCA status code to be mapped into an RPC status
  467. code.
  468. Return Value:
  469. An RPC status code will be returned.
  470. --*/
  471. {
  472. return((RPC_STATUS) MapStatusCode(NcaStatus,
  473. NcaToRpcMap,
  474. sizeof(NcaToRpcMap)/(2*sizeof(long))
  475. )
  476. );
  477. }