Source code of Windows XP (NT5)
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.

2887 lines
75 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. dcesvr.cxx
  5. Abstract:
  6. This routine implements the server side DCE runtime APIs. The
  7. routines in this file are used by server applications only.
  8. Author:
  9. Michael Montague (mikemon) 13-Nov-1991
  10. Revision History:
  11. --*/
  12. #include <precomp.hxx>
  13. #include <wincrypt.h>
  14. #include <rpcssl.h>
  15. #include <rpcobj.hxx>
  16. #include <rpcasync.h>
  17. #include <hndlsvr.hxx>
  18. #include <mgmt.h>
  19. #include <rpccfg.h>
  20. #include <CharConv.hxx>
  21. long GroupIdCounter;
  22. RPC_INTERFACE * GlobalManagementInterface;
  23. RPC_STATUS RPC_ENTRY
  24. RpcNetworkInqProtseqs (
  25. OUT RPC_PROTSEQ_VECTOR PAPI * PAPI * ProtseqVector
  26. )
  27. /*++
  28. Routine Description:
  29. A server application will call this routine to obtain a list of the
  30. rpc protocol sequences supported by this system configuration.
  31. Arguments:
  32. ProtseqVector - Returns a vector of the rpc protocol sequences
  33. supported by this system configuration.
  34. Return Value:
  35. RPC_S_OK - The operation completed successfully.
  36. RPC_S_NO_PROTSEQS - The current system configuration does not
  37. support any rpc protocol sequences.
  38. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to inquire
  39. the rpc protocol sequences supported by this system configuration.
  40. --*/
  41. {
  42. InitializeIfNecessary();
  43. return(RpcConfigInquireProtocolSequences(FALSE, ProtseqVector));
  44. }
  45. RPC_STATUS RPC_ENTRY
  46. RpcObjectInqType (
  47. IN UUID PAPI * ObjUuid,
  48. OUT UUID PAPI * TypeUuid OPTIONAL
  49. )
  50. /*++
  51. Routine Description:
  52. A server application will use this routine to obtain the type uuid
  53. for an object. This routine can also be used to determine whether
  54. a given object is register with the runtime or not. This is done
  55. by not specifying the optional type uuid argument.
  56. Arguments:
  57. ObjUuid - Supplies the object uuid for which we want look up the
  58. type uuid.
  59. TypeUuid - Optionally returns the type uuid of the specified object
  60. uuid.
  61. Return Value:
  62. RPC_S_OK - The operation completed successfully; the object uuid
  63. is registered with the runtime or the object inquiry function
  64. knows the object uuid.
  65. RPC_S_OBJECT_NOT_FOUND - The specified object uuid has not been
  66. registered with the runtime and the object inquiry function
  67. does not know about the object uuid.
  68. --*/
  69. {
  70. RPC_UUID OptionalTypeUuid;
  71. InitializeIfNecessary();
  72. if (ARGUMENT_PRESENT(TypeUuid))
  73. {
  74. return(ObjectInqType(
  75. (RPC_UUID PAPI *) ObjUuid, (RPC_UUID PAPI *) TypeUuid));
  76. }
  77. return(ObjectInqType(
  78. (RPC_UUID PAPI *) ObjUuid, &OptionalTypeUuid));
  79. }
  80. RPC_STATUS RPC_ENTRY
  81. RpcObjectSetInqFn (
  82. IN RPC_OBJECT_INQ_FN PAPI * InquiryFn
  83. )
  84. /*++
  85. Routine Description:
  86. A function to be used to determine an object's type is specified
  87. using this routine.
  88. Arguments:
  89. InquiryFn - Supplies a pointer to a function which will automatically
  90. be called when an inquiry is made for the type of object which
  91. has not yet been registered with the runtime.
  92. Return Value:
  93. RPC_S_OK - This value will always be returned.
  94. --*/
  95. {
  96. InitializeIfNecessary();
  97. return(ObjectSetInqFn(InquiryFn));
  98. }
  99. RPC_STATUS RPC_ENTRY
  100. RpcObjectSetType (
  101. IN UUID PAPI * ObjUuid,
  102. IN UUID PAPI * TypeUuid OPTIONAL
  103. )
  104. /*++
  105. Routine Description:
  106. An application will call this routine to register an object and its
  107. type with the runtime.
  108. Arguments:
  109. ObjUuid - Supplies the object uuid to be registered with the runtime.
  110. TypeUuid - Supplies the type of the object being registered. The type
  111. is registered with the object.
  112. Return Value:
  113. RPC_S_OK - The object uuid (and type uuid with it) were successfully
  114. registered with the runtime.
  115. RPC_S_ALREADY_REGISTERED - The object uuid specified has already
  116. been registered with the runtime.
  117. RPC_S_OUT_OF_MEMORY - There is insufficient memory available to
  118. register the object with the runtime.
  119. RPC_S_INVALID_OBJECT - The object uuid specified is the nil uuid.
  120. --*/
  121. {
  122. InitializeIfNecessary();
  123. return(ObjectSetType(
  124. (RPC_UUID PAPI *) ObjUuid, (RPC_UUID PAPI *) TypeUuid));
  125. }
  126. RPC_STATUS RPC_ENTRY
  127. RpcProtseqVectorFree (
  128. IN OUT RPC_PROTSEQ_VECTOR PAPI * PAPI * ProtseqVector
  129. )
  130. /*++
  131. Routine Description:
  132. The protocol sequence vector obtained by calling RpcNetworkInqProtseqs
  133. is freed using this routine. Each of the protocol sequences (they
  134. are represented as strings) and the vector itself are all freed.
  135. Arguments:
  136. ProtseqVector - Supplies the rpc protocol sequence vector to be freed,
  137. and returns zero in place of the pointer to the vector.
  138. Return Value:
  139. RPC_S_OK - This routine always completes successfully.
  140. --*/
  141. {
  142. unsigned int Index, Count;
  143. InitializeIfNecessary();
  144. if ( *ProtseqVector == 0 )
  145. {
  146. return(RPC_S_OK);
  147. }
  148. for (Index = 0, Count = (*ProtseqVector)->Count; Index < Count; Index++)
  149. {
  150. delete((*ProtseqVector)->Protseq[Index]);
  151. }
  152. delete(*ProtseqVector);
  153. *ProtseqVector = 0;
  154. return(RPC_S_OK);
  155. }
  156. RPC_STATUS RPC_ENTRY
  157. RpcServerInqBindings (
  158. OUT RPC_BINDING_VECTOR PAPI * PAPI * BindingVector
  159. )
  160. /*++
  161. Routine Description:
  162. A server application will call this routine to obtain a vector of
  163. binding handles. Each protocol sequence registered with the rpc
  164. server will be used to create one binding handle.
  165. Arguments:
  166. BindingVector - Returns the vector of binding handles.
  167. Return Value:
  168. RPC_S_OK - At least one rpc protocol sequence has been registered
  169. with the rpc server, and the operation completed successfully.
  170. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  171. the operation.
  172. RPC_S_NO_BINDINGS - No rpc protocol sequences have been successfully
  173. registered with the rpc server.
  174. --*/
  175. {
  176. InitializeIfNecessary();
  177. *BindingVector = 0L;
  178. return(GlobalRpcServer->InquireBindings(BindingVector));
  179. }
  180. RPC_STATUS RPC_ENTRY
  181. RpcServerInqIf (
  182. IN RPC_IF_HANDLE IfSpec,
  183. IN UUID PAPI * MgrTypeUuid, OPTIONAL
  184. OUT RPC_MGR_EPV PAPI * PAPI * MgrEpv
  185. )
  186. /*++
  187. Routine Description:
  188. A server application will call this routine to obtain the manager
  189. entry point vector for a given interface and a given type uuid.
  190. Arguments:
  191. IfSpec - Supplies a description of the interface.
  192. MgrTypeUuid - Optionally supplies the type uuid of the manager
  193. entry point vector we want returned. If no manager type uuid
  194. is specified, then the null uuid is assumed.
  195. MgrEpv - Returns the manager entry point vector.
  196. Return Value:
  197. RPC_S_OK - The manager entry point vector has successfully been
  198. returned.
  199. RPC_S_UNKNOWN_MGR_TYPE - The specified type uuid is not registered
  200. with the interface.
  201. RPC_S_UNKNOWN_IF - The specified interface is not registered with
  202. the rpc server.
  203. --*/
  204. {
  205. InitializeIfNecessary();
  206. return(GlobalRpcServer->InquireManagerEpv(
  207. (RPC_SERVER_INTERFACE PAPI *) IfSpec,
  208. (RPC_UUID PAPI *) MgrTypeUuid, MgrEpv));
  209. }
  210. RPC_STATUS RPC_ENTRY
  211. RpcServerListen (
  212. IN unsigned int MinimumCallThreads,
  213. IN unsigned int MaxCalls,
  214. IN unsigned int DontWait
  215. )
  216. /*++
  217. Routine Description:
  218. This routine gets called to start the rpc server listening for remote
  219. procedure calls. We do not return until RpcMgmtStopServerListening
  220. is called and all active remote procedure calls complete, or a fatal
  221. error occurs in the runtime.
  222. Arguments:
  223. MinimumCallThreads - Supplies the minimum number of threads which
  224. should be around to service remote procedure calls. A higher
  225. value for this number will give more responsive service at the
  226. cost of more threads.
  227. MaxCalls - Supplies the maximum number of concurrent calls the rpc
  228. server is willing to accept. This number must be greater than
  229. or equal to the largest MaxCalls value specified to the
  230. RpcServerUse* routines.
  231. DontWait - Supplies a flag indicating whether or not to wait until
  232. RpcMgmtStopServerListening has been called and all calls have
  233. completed. A non-zero value indicates not to wait.
  234. Return Value:
  235. RPC_S_OK - Everything worked as expected. All active remote procedure
  236. calls have completed. It is now safe to exit this process.
  237. RPC_S_ALREADY_LISTENING - Another thread has already called
  238. RpcServerListen and has not yet returned.
  239. RPC_S_NO_PROTSEQS_REGISTERED - No protocol sequences have been
  240. registered with the rpc server. As a consequence it is
  241. impossible for the rpc server to receive any remote procedure
  242. calls, hence, the error code.
  243. RPC_S_MAX_CALLS_TOO_SMALL - The supplied value for MaxCalls is smaller
  244. than the the supplied value for MinimumCallThreads, or the zero
  245. was supplied for MaxCalls.
  246. --*/
  247. {
  248. THREAD *Thread;
  249. InitializeIfNecessary();
  250. Thread = ThreadSelf();
  251. if (Thread)
  252. {
  253. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  254. }
  255. return(GlobalRpcServer->ServerListen(MinimumCallThreads, MaxCalls,
  256. DontWait));
  257. }
  258. RPC_STATUS RPC_ENTRY
  259. RpcServerRegisterIf (
  260. IN RPC_IF_HANDLE IfSpec,
  261. IN UUID PAPI * MgrTypeUuid OPTIONAL,
  262. IN RPC_MGR_EPV PAPI * MgrEpv OPTIONAL
  263. )
  264. /*++
  265. Routine Description:
  266. This routine is used by server application to register a manager
  267. entry point vector and optionally an interface. If the interface
  268. has not been registered, then it will be registered. If it has
  269. already been registered, the manager entry point vector will be
  270. added to it under the specified type uuid.
  271. Arguments:
  272. IfSpec - Supplies a description of the interface. This is actually
  273. a pointer to an opaque data structure which the runtime knows
  274. how to interpret.
  275. MgrTypeUuid - Optionally supplies the type uuid for the specified
  276. manager entry point vector. If no type uuid is supplied, then
  277. the null uuid will be used as the type uuid.
  278. MgrEpv - Optionally supplies a manager entry point vector corresponding
  279. to the type uuid. If a manager entry point vector is not supplied,
  280. then the manager entry point vector in the interface will be
  281. used.
  282. Return Value:
  283. RPC_S_OK - The specified rpc interface has been successfully
  284. registered with the rpc server. It is now ready to accept
  285. remote procedure calls.
  286. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to register
  287. the rpc interface with the rpc server.
  288. RPC_S_TYPE_ALREADY_REGISTERED - A manager entry point vector has
  289. already been registered for the supplied rpc interface and
  290. manager type UUID.
  291. --*/
  292. {
  293. InitializeIfNecessary();
  294. return(GlobalRpcServer->RegisterInterface(
  295. (RPC_SERVER_INTERFACE PAPI *) IfSpec,
  296. (RPC_UUID PAPI *) MgrTypeUuid, MgrEpv, 0,
  297. MAX_IF_CALLS, gMaxRpcSize, 0));
  298. }
  299. RPC_STATUS RPC_ENTRY
  300. RpcServerRegisterIfEx (
  301. IN RPC_IF_HANDLE IfSpec,
  302. IN UUID PAPI * MgrTypeUuid,
  303. IN RPC_MGR_EPV PAPI * MgrEpv,
  304. IN unsigned int Flags,
  305. IN unsigned int MaxCalls,
  306. IN RPC_IF_CALLBACK_FN PAPI *IfCallbackFn
  307. )
  308. /*++
  309. Routine Description:
  310. This routine is used by server application to register a manager
  311. entry point vector and an interface. If the interface
  312. has not been registered, then it will be registered. If it has
  313. already been registered, the manager entry point vector will be
  314. added to it under the specified type uuid. If the IF_AUTOLISTEN flag
  315. has been specified, then the registered interface will be treated as an
  316. auto-listen interface.
  317. Arguments:
  318. IfSpec - Supplies a description of the interface. This is actually
  319. a pointer to an opaque data structure which the runtime knows
  320. how to interpret.
  321. MgrTypeUuid - Optionally supplies the type uuid for the specified
  322. manager entry point vector. If no type uuid is supplied, then
  323. the null uuid will be used as the type uuid.
  324. MgrEpv - Optionally supplies a manager entry point vector corresponding
  325. to the type uuid. If a manager entry point vector is not supplied,
  326. then the manager entry point vector in the interface will be
  327. used.
  328. Flags -
  329. RPC_IF_OLE - the interface is an OLE interface. Calls need to be dispatched
  330. to procnum 0
  331. RPC_IF_AUTOLISTEN - the interface is an auto-listen inteface, calls may be
  332. dispatched on this inteface as soon as it is registered.
  333. MaxCalls -
  334. Maximum number of calls that can be simulaneously dispatched on this interface
  335. Return Value:
  336. RPC_S_OK - The specified rpc interface has been successfully
  337. registered with the rpc server. It is now ready to accept
  338. remote procedure calls.
  339. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to register
  340. the rpc interface with the rpc server.
  341. RPC_S_TYPE_ALREADY_REGISTERED - A manager entry point vector has
  342. already been registered for the supplied rpc interface and
  343. manager type UUID.
  344. --*/
  345. {
  346. InitializeIfNecessary();
  347. if (Flags & RPC_IF_OLE)
  348. {
  349. Flags |= RPC_IF_AUTOLISTEN ;
  350. }
  351. return(GlobalRpcServer->RegisterInterface(
  352. (RPC_SERVER_INTERFACE PAPI *) IfSpec,
  353. (RPC_UUID PAPI *) MgrTypeUuid, MgrEpv, Flags,
  354. MaxCalls, gMaxRpcSize, IfCallbackFn));
  355. }
  356. RPC_STATUS RPC_ENTRY
  357. RpcServerRegisterIf2 (
  358. IN RPC_IF_HANDLE IfSpec,
  359. IN UUID PAPI * MgrTypeUuid,
  360. IN RPC_MGR_EPV PAPI * MgrEpv,
  361. IN unsigned int Flags,
  362. IN unsigned int MaxCalls,
  363. IN unsigned int MaxRpcSize,
  364. IN RPC_IF_CALLBACK_FN PAPI *IfCallbackFn
  365. )
  366. {
  367. InitializeIfNecessary();
  368. if (Flags & RPC_IF_OLE)
  369. {
  370. Flags |= RPC_IF_AUTOLISTEN ;
  371. }
  372. return(GlobalRpcServer->RegisterInterface(
  373. (RPC_SERVER_INTERFACE PAPI *) IfSpec,
  374. (RPC_UUID PAPI *) MgrTypeUuid, MgrEpv, Flags,
  375. MaxCalls, MaxRpcSize, IfCallbackFn));
  376. }
  377. RPC_STATUS RPC_ENTRY
  378. RpcServerUnregisterIf (
  379. IN RPC_IF_HANDLE IfSpec,
  380. IN UUID PAPI * MgrTypeUuid, OPTIONAL
  381. IN unsigned int WaitForCallsToComplete
  382. )
  383. /*++
  384. Routine Description:
  385. A server application will use this routine to unregister an interface
  386. with the rpc server. Depending on what is specified for the manager
  387. type uuid one or all of the manager entry point vectors will be removed
  388. from the interface.
  389. Arguments:
  390. IfSpec - Supplies a description of the interface. This is actually
  391. a pointer to an opaque data structure which the runtime knows
  392. how to interpret.
  393. MgrTypeUuid - Optionally supplies the type uuid of the manager entry
  394. point vector to be removed. If this argument is not supplied,
  395. then all manager entry point vectors for this interface will
  396. be removed.
  397. WaitForCallsToComplete - Supplies a flag indicating whether or not
  398. this routine should wait for all calls to complete using the
  399. interface and manager being unregistered. A non-zero value
  400. indicates to wait.
  401. Return Value:
  402. RPC_S_OK - The manager entry point vector(s) are(were) successfully
  403. removed from the specified interface.
  404. RPC_S_UNKNOWN_MGR_TYPE - The specified type uuid is not registered
  405. with the interface.
  406. RPC_S_UNKNOWN_IF - The specified interface is not registered with
  407. the rpc server.
  408. --*/
  409. {
  410. InitializeIfNecessary();
  411. return(GlobalRpcServer->UnregisterIf(
  412. (RPC_SERVER_INTERFACE PAPI *) IfSpec,
  413. (RPC_UUID PAPI *) MgrTypeUuid, WaitForCallsToComplete));
  414. }
  415. RPC_STATUS RPC_ENTRY
  416. RpcServerUnregisterIfEx (
  417. IN RPC_IF_HANDLE IfSpec,
  418. IN UUID PAPI * MgrTypeUuid, OPTIONAL
  419. IN int RundownContextHandles
  420. )
  421. /*++
  422. Routine Description:
  423. Does the same as RpcServerUnregisterIf and in addition to that
  424. will cleanup all context handles registered by this interface
  425. provided that the interface is using strict_context_handles. If
  426. the interface does not use strict context handles, this API will
  427. return ERROR_INVALID_HANDLE, but the interface will be
  428. unregistered. Unlike RpcServerUnregisterIf, this API requires the
  429. IfSpec argument.
  430. Arguments:
  431. IfSpec - Supplies a description of the interface. This is actually
  432. a pointer to an opaque data structure which the runtime knows
  433. how to interpret.
  434. MgrTypeUuid - Optionally supplies the type uuid of the manager entry
  435. point vector to be removed. If this argument is not supplied,
  436. then all manager entry point vectors for this interface will
  437. be removed.
  438. RundownContextHandles - if TRUE, the context handles belonging to
  439. this interface will be rundown. If FALSE, only the runtime
  440. portion of the context handle will be cleaned up, and the
  441. server portion of the context handle will be left alone.
  442. Return Value:
  443. RPC_S_OK - The manager entry point vector(s) are(were) successfully
  444. removed from the specified interface.
  445. RPC_S_UNKNOWN_MGR_TYPE - The specified type uuid is not registered
  446. with the interface.
  447. RPC_S_UNKNOWN_IF - The specified interface is not registered with
  448. the rpc server.
  449. --*/
  450. {
  451. RPC_STATUS RpcStatus;
  452. DestroyContextHandleCallbackContext CallbackContext;
  453. InitializeIfNecessary();
  454. if (!ARGUMENT_PRESENT(IfSpec))
  455. return ERROR_INVALID_PARAMETER;
  456. RpcStatus = RpcServerUnregisterIf(IfSpec,
  457. MgrTypeUuid,
  458. TRUE // WaitForCallsToComplete
  459. );
  460. if (RpcStatus != RPC_S_OK)
  461. return RpcStatus;
  462. CallbackContext.RpcInterfaceInformation = (RPC_SERVER_INTERFACE *) IfSpec;
  463. CallbackContext.RundownContextHandles = RundownContextHandles;
  464. RpcStatus = GlobalRpcServer->EnumerateAndCallEachAddress(
  465. RPC_SERVER::actDestroyContextHandle,
  466. &CallbackContext);
  467. return RpcStatus;
  468. }
  469. RPC_STATUS RPC_ENTRY
  470. RpcServerUseAllProtseqsEx (
  471. IN unsigned int MaxCalls,
  472. IN void PAPI * SecurityDescriptor,
  473. IN PRPC_POLICY Policy
  474. )
  475. /*++
  476. Routine Description:
  477. A server application will use this routine to add all rpc protocol
  478. sequences supported by the current operating environment to the
  479. rpc server. An endpoint will be dynamically selected for each rpc
  480. protocol sequence. We will inquire the supported rpc protocol
  481. sequences, and then let the RPC_SERVER class take care of adding
  482. each one for us.
  483. Arguments:
  484. MaxCalls - Supplies a lower bound for the number of concurrent
  485. remote procedure calls the server must be able to handle.
  486. SecurityDescriptor - Optionally supplies a security descriptor to
  487. place on the rpc protocol sequence (address) we are adding to
  488. the rpc server.
  489. Return Value:
  490. RPC_S_OK - All supported rpc protocol sequences have been added to
  491. the rpc server.
  492. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add all of
  493. the supported rpc protocol sequences to the rpc server.
  494. RPC_S_NO_PROTSEQS - The current system configuration does not
  495. support any rpc protocol sequences.
  496. RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
  497. invalid.
  498. --*/
  499. {
  500. RPC_PROTSEQ_VECTOR * RpcProtseqVector;
  501. RPC_STATUS Status;
  502. unsigned int Index, ValidProtocolSequences = 0;
  503. THREAD *Thread;
  504. InitializeIfNecessary();
  505. if (Policy->Length < sizeof(RPC_POLICY))
  506. {
  507. return RPC_S_INVALID_BOUND ;
  508. }
  509. Thread = ThreadSelf();
  510. if (!Thread)
  511. return RPC_S_OUT_OF_MEMORY;
  512. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  513. Status = RpcConfigInquireProtocolSequences(TRUE, &RpcProtseqVector);
  514. if (Status != RPC_S_OK)
  515. {
  516. return(Status);
  517. }
  518. Policy->EndpointFlags |= RPC_C_DONT_FAIL;
  519. for (Index = 0; Index < RpcProtseqVector->Count; Index++)
  520. {
  521. //
  522. // Don't include nb protocols, ncadg_mq and ncacn_http
  523. // in RpcServerUseAllProtseqs().
  524. //
  525. if ( (RpcpStringNCompare(RPC_CONST_STRING("ncacn_nb_"),
  526. RpcProtseqVector->Protseq[Index],
  527. 9) == 0)
  528. ||(RpcpStringNCompare(RPC_CONST_STRING("ncadg_mq"),
  529. RpcProtseqVector->Protseq[Index],
  530. 8) == 0)
  531. #if !defined(APPLETALK_ON)
  532. ||(RpcpStringNCompare(RPC_CONST_STRING("ncacn_at_dsp"),
  533. RpcProtseqVector->Protseq[Index],
  534. 12) == 0)
  535. #endif
  536. ||(RpcpStringNCompare(RPC_CONST_STRING("ncacn_http"),
  537. RpcProtseqVector->Protseq[Index],
  538. 10) == 0) )
  539. {
  540. continue;
  541. }
  542. Status = GlobalRpcServer->UseRpcProtocolSequence(NULL,
  543. RpcProtseqVector->Protseq[Index], MaxCalls, 0,
  544. SecurityDescriptor, Policy->EndpointFlags, Policy->NICFlags);
  545. if ( Status == RPC_S_OK )
  546. {
  547. ValidProtocolSequences += 1;
  548. }
  549. else if ( ( Status == RPC_S_OUT_OF_MEMORY )
  550. || ( Status == RPC_S_INVALID_SECURITY_DESC )
  551. || ( Status == RPC_S_OUT_OF_RESOURCES ) )
  552. {
  553. RpcProtseqVectorFree(&RpcProtseqVector);
  554. return(Status);
  555. }
  556. }
  557. RpcProtseqVectorFree(&RpcProtseqVector);
  558. if ( ValidProtocolSequences == 0 )
  559. {
  560. return(Status);
  561. }
  562. return(RPC_S_OK);
  563. }
  564. RPC_STATUS RPC_ENTRY
  565. RpcServerUseAllProtseqs (
  566. IN unsigned int MaxCalls,
  567. IN void PAPI * SecurityDescriptor OPTIONAL
  568. )
  569. {
  570. RPC_POLICY Policy ;
  571. Policy.Length = sizeof(RPC_POLICY) ;
  572. Policy.EndpointFlags = 0;
  573. Policy.NICFlags = 0;
  574. return RpcServerUseAllProtseqsEx (MaxCalls, SecurityDescriptor, &Policy) ;
  575. }
  576. RPC_STATUS RPC_ENTRY
  577. RpcServerUseAllProtseqsIfEx (
  578. IN unsigned int MaxCalls,
  579. IN RPC_IF_HANDLE IfSpec,
  580. IN void PAPI * SecurityDescriptor,
  581. IN PRPC_POLICY Policy
  582. )
  583. /*++
  584. Routine Description:
  585. A server application will use this routine to add all protocol
  586. sequences and endpoints specified in the header of an IDL file.
  587. This information (from the IDL file) is specified by the interface
  588. specification argument.
  589. Arguments:
  590. MaxCalls - Supplies a lower bound for the number of concurrent
  591. remote procedure calls the server must be able to handle.
  592. IfSpec - Supplies the interface specification from which we
  593. should extract the rpc protocol sequence and end point
  594. information to be used.
  595. SecurityDescriptor - Optionally supplies a security descriptor to
  596. place on the rpc protocol sequence (address) we are adding to
  597. the rpc server.
  598. Return Value:
  599. RPC_S_OK - All of the support rpc protocol sequences (and their
  600. associated endpoints) have been added to the rpc server.
  601. RPC_S_NO_PROTSEQS - None of the specified rpc protocol sequences
  602. are supported by the rpc server, or no rpc protocol sequences
  603. were specified.
  604. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add the
  605. requested rpc protocol sequence to the rpc server.
  606. RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
  607. syntactically invalid.
  608. RPC_S_DUPLICATE_ENDPOINT - One of the supplied endpoints has already
  609. been added to this rpc server.
  610. RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
  611. invalid.
  612. --*/
  613. {
  614. RPC_SERVER_INTERFACE PAPI * RpcServerInfo;
  615. unsigned int SupportedProtseqCount = 0;
  616. unsigned int Index;
  617. RPC_STATUS Status;
  618. InitializeIfNecessary();
  619. if (Policy->Length < sizeof(RPC_POLICY))
  620. {
  621. return RPC_S_INVALID_BOUND ;
  622. }
  623. RpcServerInfo = (RPC_SERVER_INTERFACE PAPI *) IfSpec;
  624. if (RpcServerInfo->RpcProtseqEndpointCount == 0)
  625. {
  626. return(RPC_S_NO_PROTSEQS);
  627. }
  628. Policy->EndpointFlags |= RPC_C_DONT_FAIL;
  629. for (Index = 0; Index < RpcServerInfo->RpcProtseqEndpointCount;
  630. Index++)
  631. {
  632. Status = RpcServerUseProtseqEpExA(
  633. RpcServerInfo->RpcProtseqEndpoint[Index].RpcProtocolSequence,
  634. MaxCalls, RpcServerInfo->RpcProtseqEndpoint[Index].Endpoint,
  635. SecurityDescriptor, Policy);
  636. if ( Status == RPC_S_OK )
  637. {
  638. SupportedProtseqCount += 1;
  639. }
  640. else if ( ( Status == RPC_S_OUT_OF_MEMORY )
  641. || ( Status == RPC_S_INVALID_SECURITY_DESC )
  642. || ( Status == RPC_S_OUT_OF_RESOURCES ) )
  643. {
  644. return(Status);
  645. }
  646. }
  647. if ( SupportedProtseqCount == 0 )
  648. {
  649. if ( Status == RPC_S_PROTSEQ_NOT_SUPPORTED )
  650. {
  651. return(RPC_S_NO_PROTSEQS);
  652. }
  653. return(Status);
  654. }
  655. return(RPC_S_OK);
  656. }
  657. RPC_STATUS RPC_ENTRY
  658. RpcServerUseAllProtseqsIf (
  659. IN unsigned int MaxCalls,
  660. IN RPC_IF_HANDLE IfSpec,
  661. IN void PAPI * SecurityDescriptor OPTIONAL
  662. )
  663. {
  664. RPC_POLICY Policy ;
  665. Policy.Length = sizeof(RPC_POLICY) ;
  666. Policy.EndpointFlags = 0;
  667. Policy.NICFlags = 0;
  668. return RpcServerUseAllProtseqsIfEx ( MaxCalls, IfSpec, SecurityDescriptor, &Policy) ;
  669. }
  670. RPC_STATUS RPC_ENTRY
  671. I_RpcServerUseProtseq2 (
  672. IN unsigned short PAPI *NetworkAddress,
  673. IN unsigned short PAPI *Protseq,
  674. IN unsigned int MaxCalls,
  675. IN void PAPI *SecurityDescriptor,
  676. IN void *pPolicy
  677. )
  678. {
  679. PRPC_POLICY Policy = (PRPC_POLICY) pPolicy;
  680. THREAD *Thread;
  681. InitializeIfNecessary();
  682. Thread = ThreadSelf();
  683. if (!Thread)
  684. return RPC_S_OUT_OF_MEMORY;
  685. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  686. if (Policy->Length < sizeof(RPC_POLICY))
  687. {
  688. return RPC_S_INVALID_BOUND ;
  689. }
  690. return(GlobalRpcServer->UseRpcProtocolSequence(NetworkAddress, Protseq, MaxCalls, 0,
  691. SecurityDescriptor, Policy->EndpointFlags, Policy->NICFlags));
  692. }
  693. RPC_STATUS RPC_ENTRY
  694. RpcServerUseProtseqEx (
  695. IN unsigned short PAPI * Protseq,
  696. IN unsigned int MaxCalls,
  697. IN void PAPI * SecurityDescriptor,
  698. IN PRPC_POLICY Policy
  699. )
  700. /*++
  701. Routine Description:
  702. This routine is used by a server application to add an rpc protocol
  703. sequence to the rpc server. An endpoint will be dynamically selected
  704. for this rpc protocol sequence. What we do is to let the RPC_SERVER
  705. class take care of most of the work.
  706. Arguments:
  707. Protseq - Supplies the rpc protocol sequence we wish to add. An
  708. rpc protocol sequence contains two pieces of information we
  709. are interested in: the rpc protocol (connection, datagram, or
  710. shared memory) and the transport interface requested.
  711. MaxCalls - Supplies a lower bound for the number of concurrent
  712. remote procedure calls the server must be able to handle.
  713. SecurityDescriptor - Optionally supplies a security descriptor to
  714. place on the rpc protocol sequence (address) we are adding to
  715. the rpc server.
  716. Return Value:
  717. RPC_S_OK - The requested rpc protocol sequence has been added to
  718. the rpc server.
  719. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add the
  720. requested rpc protocol sequence to the rpc server.
  721. RPC_S_PROTSEQ_NOT_SUPPORTED - The specified rpc protocol sequence
  722. is not supported (but it appears to be valid).
  723. RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
  724. syntactically invalid.
  725. RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
  726. invalid.
  727. --*/
  728. {
  729. return I_RpcServerUseProtseq2(NULL, Protseq, MaxCalls, SecurityDescriptor, Policy);
  730. }
  731. RPC_STATUS RPC_ENTRY
  732. RpcServerUseProtseq (
  733. IN unsigned short PAPI * Protseq,
  734. IN unsigned int MaxCalls,
  735. IN void PAPI * SecurityDescriptor OPTIONAL
  736. )
  737. {
  738. RPC_POLICY Policy ;
  739. THREAD *Thread;
  740. InitializeIfNecessary();
  741. Policy.Length = sizeof(RPC_POLICY) ;
  742. Policy.EndpointFlags = 0;
  743. Policy.NICFlags = 0;
  744. Thread = ThreadSelf();
  745. if (!Thread)
  746. return RPC_S_OUT_OF_MEMORY;
  747. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  748. return RpcServerUseProtseqEx(Protseq, MaxCalls, SecurityDescriptor, &Policy) ;
  749. }
  750. RPC_STATUS RPC_ENTRY
  751. I_RpcServerUseProtseqEp2 (
  752. IN unsigned short PAPI * NetworkAddress,
  753. IN unsigned short PAPI * Protseq,
  754. IN unsigned int MaxCalls,
  755. IN RPC_CHAR PAPI * Endpoint,
  756. IN void PAPI * SecurityDescriptor,
  757. IN void *pPolicy
  758. )
  759. {
  760. PRPC_POLICY Policy = (PRPC_POLICY) pPolicy;
  761. InitializeIfNecessary();
  762. if (Policy->Length < sizeof(RPC_POLICY))
  763. {
  764. return RPC_S_INVALID_BOUND ;
  765. }
  766. return(GlobalRpcServer->UseRpcProtocolSequence(NetworkAddress, Protseq, MaxCalls,
  767. Endpoint, SecurityDescriptor,
  768. Policy->EndpointFlags, Policy->NICFlags));
  769. }
  770. RPC_STATUS RPC_ENTRY
  771. RpcServerUseProtseqEpEx (
  772. IN unsigned short PAPI * Protseq,
  773. IN unsigned int MaxCalls,
  774. IN unsigned short PAPI * Endpoint,
  775. IN void PAPI * SecurityDescriptor,
  776. IN PRPC_POLICY Policy
  777. )
  778. /*++
  779. Routine Description:
  780. This routine is used by a server application to add an rpc protocol
  781. sequence and an endpoint to the rpc server. What we do is to let
  782. the RPC_SERVER class take care of most of the work.
  783. Arguments:
  784. Protseq - Supplies the rpc protocol sequence we wish to add. An
  785. rpc protocol sequence contains two pieces of information we
  786. are interested in: the rpc protocol (connection, datagram, or
  787. shared memory) and the transport interface requested.
  788. MaxCalls - Supplies a lower bound for the number of concurrent
  789. remote procedure calls the server must be able to handle.
  790. Endpoint - Supplies the endpoint to use for this rpc protocol
  791. sequence.
  792. SecurityDescriptor - Optionally supplies a security descriptor to
  793. place on the rpc protocol sequence (address) we are adding to
  794. the rpc server.
  795. Return Value:
  796. RPC_S_OK - The requested rpc protocol sequence has been added to
  797. the rpc server.
  798. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add the
  799. requested rpc protocol sequence to the rpc server.
  800. RPC_S_PROTSEQ_NOT_SUPPORTED - The specified rpc protocol sequence
  801. is not supported (but it appears to be valid).
  802. RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
  803. syntactically invalid.
  804. RPC_S_INVALID_ENDPOINT_FORMAT -
  805. RPC_S_DUPLICATE_ENDPOINT - The supplied endpoint has already been
  806. added to this rpc server.
  807. RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
  808. invalid.
  809. --*/
  810. {
  811. return I_RpcServerUseProtseqEp2 (NULL, Protseq, MaxCalls, Endpoint,
  812. SecurityDescriptor, (void *) Policy);
  813. }
  814. RPC_STATUS RPC_ENTRY
  815. RpcServerUseProtseqEp (
  816. IN RPC_CHAR PAPI * Protseq,
  817. IN unsigned int MaxCalls,
  818. IN RPC_CHAR PAPI * Endpoint,
  819. IN void PAPI * SecurityDescriptor
  820. )
  821. {
  822. RPC_POLICY Policy ;
  823. Policy.Length = sizeof(RPC_POLICY) ;
  824. Policy.EndpointFlags = 0;
  825. Policy.NICFlags = 0;
  826. return RpcServerUseProtseqEpEx(Protseq, MaxCalls, Endpoint,
  827. SecurityDescriptor, &Policy) ;
  828. }
  829. RPC_STATUS RPC_ENTRY
  830. RpcServerUseProtseqIfEx (
  831. IN unsigned short PAPI * Protseq,
  832. IN unsigned int MaxCalls,
  833. IN RPC_IF_HANDLE IfSpec,
  834. IN void PAPI * SecurityDescriptor,
  835. IN PRPC_POLICY Policy
  836. )
  837. /*++
  838. Routine Description:
  839. A server application will use this routine to one of the protocol
  840. sequences (and its associated endpoint) specified in the header of
  841. an IDL file. This information (from the IDL file) is specified by
  842. the interface specification argument.
  843. Arguments:
  844. Protseq - Supplies the rpc protocol sequence to be added to
  845. the rpc server. The list of rpc protocol sequence -- endpoint
  846. pairs in the interface specification will be searched to find
  847. the corresponding endpoint.
  848. MaxCalls - Supplies a lower bound for the number of concurrent
  849. remote procedure calls the server must be able to handle.
  850. IfSpec - Supplies the interface specification from which we
  851. should extract the rpc protocol sequence and end point
  852. information to be used.
  853. SecurityDescriptor - Optionally supplies a security descriptor to
  854. place on the rpc protocol sequence (address) we are adding to
  855. the rpc server.
  856. Return Value:
  857. RPC_S_OK - The requested rpc protocol sequence (and its associated
  858. endpoint) has been added to the rpc server.
  859. RPC_S_PROTSEQ_NOT_SUPPORTED - The supplied rpc protocol sequence
  860. is not supported by the rpc server.
  861. RPC_S_PROTSEQ_NOT_SUPPORTED - The supplied rpc protocol sequence is not
  862. in the list of rpc protocol sequences in the interface specification.
  863. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add the
  864. requested rpc protocol sequence to the rpc server.
  865. RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
  866. syntactically invalid.
  867. RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
  868. invalid.
  869. --*/
  870. {
  871. RPC_SERVER_INTERFACE PAPI * RpcServerInfo;
  872. unsigned int Index, EndpointsRegistered = 0;
  873. RPC_STATUS RpcStatus;
  874. #ifdef UNICODE
  875. UNICODE_STRING UnicodeString;
  876. #endif // UNICODE
  877. InitializeIfNecessary();
  878. if (Policy->Length < sizeof(RPC_POLICY))
  879. {
  880. return RPC_S_INVALID_BOUND ;
  881. }
  882. RpcServerInfo = (RPC_SERVER_INTERFACE PAPI *) IfSpec;
  883. for (Index = 0; Index < RpcServerInfo->RpcProtseqEndpointCount;
  884. Index++)
  885. {
  886. #ifdef UNICODE
  887. RpcStatus = AnsiToUnicodeString(
  888. RpcServerInfo->RpcProtseqEndpoint[Index].RpcProtocolSequence,
  889. &UnicodeString);
  890. if (RpcStatus != RPC_S_OK)
  891. return(RpcStatus);
  892. if ( RpcpStringCompare(Protseq, UnicodeString.Buffer) == 0 )
  893. #else // UNICODE
  894. if ( RpcpStringCompare(Protseq,
  895. RpcServerInfo->RpcProtseqEndpoint[Index].RpcProtocolSequence)
  896. == 0 )
  897. #endif // UNICODE
  898. {
  899. #ifdef UNICODE
  900. RtlFreeUnicodeString(&UnicodeString);
  901. #endif
  902. RpcStatus = RpcServerUseProtseqEpExA(
  903. RpcServerInfo->RpcProtseqEndpoint[ Index].RpcProtocolSequence,
  904. MaxCalls, RpcServerInfo->RpcProtseqEndpoint[Index].Endpoint,
  905. SecurityDescriptor, Policy);
  906. if ( RpcStatus != RPC_S_OK )
  907. {
  908. return(RpcStatus);
  909. }
  910. EndpointsRegistered += 1;
  911. }
  912. #ifdef UNICODE
  913. else
  914. {
  915. RtlFreeUnicodeString(&UnicodeString);
  916. }
  917. #endif // UNICODE
  918. }
  919. if ( EndpointsRegistered == 0 )
  920. {
  921. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  922. }
  923. return(RPC_S_OK);
  924. }
  925. RPC_STATUS RPC_ENTRY
  926. RpcServerUseProtseqIf (
  927. IN unsigned short PAPI * Protseq,
  928. IN unsigned int MaxCalls,
  929. IN RPC_IF_HANDLE IfSpec,
  930. IN void PAPI * SecurityDescriptor
  931. )
  932. {
  933. RPC_POLICY Policy ;
  934. Policy.Length = sizeof(RPC_POLICY) ;
  935. Policy.EndpointFlags = 0;
  936. Policy.NICFlags = 0;
  937. return RpcServerUseProtseqIfEx (Protseq, MaxCalls, IfSpec,
  938. SecurityDescriptor, &Policy) ;
  939. }
  940. RPC_STATUS RPC_ENTRY
  941. RpcMgmtStatsVectorFree (
  942. IN OUT RPC_STATS_VECTOR ** StatsVector
  943. )
  944. /*++
  945. Routine Description:
  946. This routine is used to free the statistics vector obtained from
  947. RpcMgmtInqStats.
  948. Arguments:
  949. StatsVector - Supplies the statistics vector to be freed; on return,
  950. the pointer this pointer points to will be set to zero.
  951. Return Value:
  952. RPC_S_OK - The operation completed successfully.
  953. RPC_S_INVALID_ARG - The specified statistics vectors does not contain
  954. the address of a statistics vector.
  955. --*/
  956. {
  957. InitializeIfNecessary();
  958. if (StatsVector == 0)
  959. return(RPC_S_INVALID_ARG);
  960. RpcpFarFree(*StatsVector);
  961. *StatsVector = 0;
  962. return(RPC_S_OK);
  963. }
  964. #define MAX_STATISTICS 4
  965. RPC_STATUS RPC_ENTRY
  966. RpcMgmtInqStats (
  967. IN RPC_BINDING_HANDLE Binding,
  968. OUT RPC_STATS_VECTOR ** Statistics
  969. )
  970. /*++
  971. Routine Description:
  972. This routine is used to inquire statistics about the server. In
  973. particular, the statistics consist of the number of remote procedure
  974. calls received by this server, the number of remote procedure calls
  975. initiated by this server (callbacks), the number of network packets
  976. received, and the number of network packets sent.
  977. Arguments:
  978. Binding - Optionally supplies a binding handle to the server. If this
  979. argument is not supplied, the local application is queried.
  980. Statistics - Returns the statistics vector for this server.
  981. Return Value:
  982. RPC_S_OK - Everything worked just fine, and you now know the
  983. statistics for this server.
  984. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  985. the operation.
  986. RPC_S_INVALID_BINDING - The supplied binding is not zero.
  987. --*/
  988. {
  989. unsigned long Status = 0;
  990. unsigned long Count = MAX_STATISTICS;
  991. unsigned long StatsVector[MAX_STATISTICS];
  992. InitializeIfNecessary();
  993. if (Binding == 0)
  994. {
  995. *Statistics = (RPC_STATS_VECTOR *) RpcpFarAllocate(sizeof(RPC_STATS_VECTOR)
  996. + 3 * sizeof(unsigned long));
  997. if (*Statistics == 0)
  998. return(RPC_S_OUT_OF_MEMORY);
  999. (*Statistics)->Count = 4;
  1000. GlobalRpcServer->InquireStatistics(*Statistics);
  1001. return(RPC_S_OK);
  1002. }
  1003. _rpc_mgmt_inq_stats(Binding, &Count, StatsVector, &Status);
  1004. if ( Status == RPC_S_OK )
  1005. {
  1006. *Statistics = (RPC_STATS_VECTOR __RPC_FAR *) RpcpFarAllocate(
  1007. sizeof(RPC_STATS_VECTOR) + sizeof(unsigned long)
  1008. * (MAX_STATISTICS - 1));
  1009. if ( *Statistics == 0 )
  1010. {
  1011. return(RPC_S_OUT_OF_MEMORY);
  1012. }
  1013. for ((*Statistics)->Count = 0; (*Statistics)->Count < Count
  1014. && (*Statistics)->Count < MAX_STATISTICS;
  1015. (*Statistics)->Count++)
  1016. {
  1017. (*Statistics)->Stats[(*Statistics)->Count] =
  1018. StatsVector[(*Statistics)->Count];
  1019. }
  1020. }
  1021. return(Status);
  1022. }
  1023. RPC_STATUS RPC_ENTRY
  1024. RpcMgmtIsServerListening (
  1025. IN RPC_BINDING_HANDLE Binding
  1026. )
  1027. /*++
  1028. Routine Description:
  1029. An application will use this routine to determine whether or not
  1030. the server is listening.
  1031. Arguments:
  1032. Binding - Optionally supplies a binding handle to the server. If this
  1033. argument is not supplied, the local application is queried.
  1034. Return Value:
  1035. RPC_S_OK - The server is listening.
  1036. RPC_S_INVALID_BINDING - The supplied binding is not zero.
  1037. RPC_S_NOT_LISTENING - The server is not listening.
  1038. --*/
  1039. {
  1040. unsigned long Result;
  1041. unsigned long Status = 0;
  1042. InitializeIfNecessary();
  1043. if (Binding == 0)
  1044. {
  1045. if (GlobalRpcServer->IsServerListening() == 0)
  1046. return(RPC_S_NOT_LISTENING);
  1047. return(RPC_S_OK);
  1048. }
  1049. Result = _rpc_mgmt_is_server_listening(Binding, &Status);
  1050. if (Status == RPC_S_OK)
  1051. {
  1052. return((Result == 1) ? RPC_S_OK : RPC_S_NOT_LISTENING);
  1053. }
  1054. if ( (Status == RPC_S_SERVER_UNAVAILABLE)
  1055. || (Status == RPC_S_SERVER_TOO_BUSY) )
  1056. {
  1057. return (RPC_S_NOT_LISTENING);
  1058. }
  1059. return(Status);
  1060. }
  1061. RPC_STATUS RPC_ENTRY
  1062. RpcMgmtStopServerListening (
  1063. IN RPC_BINDING_HANDLE Binding
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. This routine is used by an application to stop the rpc server from
  1068. accepting any more remote procedure calls. Currently active remote
  1069. procedure calls are allowed to complete.
  1070. Arguments:
  1071. Binding - Optionally supplies a binding handle to the server. If this
  1072. argument is not supplied, the local server is stopped.
  1073. Return Value:
  1074. RPC_S_OK - The server has been successfully notified that it should
  1075. stop listening for remote procedure calls. No new remote procedure
  1076. calls will be accepted after this routine returns. RpcServerListen
  1077. will return after all active calls have completed.
  1078. RPC_S_NOT_LISTENING - A thread has not called RpcServerListen (and
  1079. not returned) yet.
  1080. --*/
  1081. {
  1082. RPC_STATUS Status;
  1083. InitializeIfNecessary();
  1084. if (Binding == 0)
  1085. {
  1086. return(GlobalRpcServer->StopServerListening());
  1087. }
  1088. _rpc_mgmt_stop_server_listening(Binding, (unsigned long *)&Status);
  1089. return(Status);
  1090. }
  1091. RPC_STATUS RPC_ENTRY
  1092. RpcMgmtWaitServerListen (
  1093. void
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. This routine performs the wait that RpcServerListen normally performs
  1098. when the DontWait flag is not set. An application must call this
  1099. routine only after RpcServerListen has been called with the DontWait
  1100. flag set. We do not return until RpcMgmtStopServerListening is called
  1101. and all active remote procedure calls complete, or a fatal error occurs
  1102. in the runtime.
  1103. Return Value:
  1104. RPC_S_OK - Everything worked as expected. All active remote procedure
  1105. calls have completed. It is now safe to exit this process.
  1106. RPC_S_ALREADY_LISTENING - Another thread has already called
  1107. RpcMgmtWaitServerListen and has not yet returned.
  1108. RPC_S_NOT_LISTENING - RpcServerListen has not yet been called.
  1109. --*/
  1110. {
  1111. InitializeIfNecessary();
  1112. return(GlobalRpcServer->WaitServerListen());
  1113. }
  1114. RPC_STATUS RPC_ENTRY
  1115. I_RpcBindingInqDynamicEndpointA (
  1116. IN RPC_BINDING_HANDLE Binding,
  1117. OUT unsigned char PAPI * PAPI * DynamicEndpoint
  1118. )
  1119. {
  1120. #ifdef UNICODE
  1121. return (RPC_S_CANNOT_SUPPORT);
  1122. #else
  1123. USES_CONVERSION;
  1124. CNlDelUnicodeAnsi thunkedDynamicEndpoint;
  1125. RPC_STATUS RpcStatus;
  1126. RpcStatus = I_RpcBindingInqDynamicEndpointW(Binding, thunkedDynamicEndpoint);
  1127. if (RpcStatus == RPC_S_OK)
  1128. {
  1129. ATTEMPT_CONVERT_W2A_OPTIONAL(thunkedDynamicEndpoint, DynamicEndpoint);
  1130. }
  1131. return RpcStatus;
  1132. #endif
  1133. }
  1134. RPC_STATUS RPC_ENTRY
  1135. I_RpcBindingInqDynamicEndpointW (
  1136. IN RPC_BINDING_HANDLE Binding,
  1137. OUT unsigned short PAPI * PAPI * DynamicEndpoint
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. This routine is used to inquire the dynamic endpoint from a binding
  1142. handle. The only binding handles which will have dynamic endpoints
  1143. are those which are create from rpc addresses which have dynamic
  1144. endpoints. This routine will be used for one purpose and one purpose
  1145. only: RpcEpRegister and RpcEpRegisterNoReplace need to know which
  1146. binding handles have dynamic endpoints; only binding handles with
  1147. dynamic endpoints get placed into the endpoint mapper database.
  1148. Arguments:
  1149. Binding - Supplies the binding handle from which we wish to obtain
  1150. the dynamic endpoint.
  1151. DynamicEndpoint - Returns a pointer to a string containing the dynamic
  1152. endpoint for this binding handle if it has one; otherwise, it
  1153. will be zero. If a string is return, it must be freed using
  1154. RpcStringFree.
  1155. Return Value:
  1156. RPC_S_OK - The operation completed successfully. This does not
  1157. indicate whether or not the binding handle has a dynamic endpoint.
  1158. To determine that, you must check whether *DynamicEndpoint is
  1159. equal to zero.
  1160. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to duplicate
  1161. the dynamic endpoint.
  1162. RPC_S_INVALID_BINDING - The binding argument does not specify a binding
  1163. handle.
  1164. --*/
  1165. {
  1166. BINDING_HANDLE * BindingHandle;
  1167. #ifndef UNICODE
  1168. USES_CONVERSION;
  1169. COutDelThunk thunkedDynamicEndpoint;
  1170. RPC_STATUS RpcStatus;
  1171. #endif
  1172. InitializeIfNecessary();
  1173. BindingHandle = (BINDING_HANDLE *) Binding;
  1174. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  1175. return(RPC_S_INVALID_BINDING);
  1176. #ifdef UNICODE
  1177. return (BindingHandle->InquireDynamicEndpoint(DynamicEndpoint));
  1178. #else
  1179. RpcStatus = BindingHandle->InquireDynamicEndpoint(thunkedDynamicEndpoint);
  1180. if (RpcStatus == RPC_S_OK)
  1181. {
  1182. ATTEMPT_OUT_THUNK_OPTIONAL(thunkedDynamicEndpoint, DynamicEndpoint);
  1183. }
  1184. return RpcStatus;
  1185. #endif
  1186. }
  1187. RPC_STATUS RPC_ENTRY
  1188. RpcServerRegisterAuthInfo (
  1189. IN unsigned short PAPI * ServerPrincName,
  1190. IN unsigned long AuthnSvc,
  1191. IN RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, OPTIONAL
  1192. IN void PAPI * Arg OPTIONAL
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. A server application will use this routine to indicate to the runtime
  1197. what authentication service to use for authenticating remote procedure
  1198. calls. This routine should be called once for each pair of authentication
  1199. service and principal name which the server wishes to use for
  1200. authentication. In order for an client to be able to talk with an
  1201. authenticated server, the authentication service specified by the client
  1202. must be one of the ones registered by the server. Attempting to
  1203. register the same authentication service and principal name will not
  1204. result in an error.
  1205. Arguments:
  1206. ServerPrincName - Supplies the principal name for the server.
  1207. AuthnSvc - Supplies an authentication service to use when the server
  1208. receives a remote procedure call.
  1209. GetKeyFn - Optionally supplies a routine to be used when the runtime
  1210. needs an encryption key.
  1211. Arg - Optionally supplies an argument to be passed to the routine used
  1212. to get keys each time it is called.
  1213. Return Value:
  1214. RPC_S_OK - The authentication service and server principal name have
  1215. been registered with the runtime.
  1216. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  1217. operation.
  1218. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  1219. not supported.
  1220. --*/
  1221. {
  1222. THREAD *Thread;
  1223. InitializeIfNecessary();
  1224. Thread = ThreadSelf();
  1225. if (Thread)
  1226. {
  1227. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  1228. }
  1229. return(GlobalRpcServer->RegisterAuthInformation(ServerPrincName,
  1230. AuthnSvc, GetKeyFn, Arg));
  1231. }
  1232. RPC_STATUS RPC_ENTRY
  1233. RpcBindingInqAuthClient (
  1234. IN RPC_BINDING_HANDLE ClientBinding, OPTIONAL
  1235. OUT RPC_AUTHZ_HANDLE PAPI * Privs,
  1236. OUT unsigned short PAPI * PAPI * PrincName, OPTIONAL
  1237. OUT unsigned long PAPI * AuthnLevel, OPTIONAL
  1238. OUT unsigned long PAPI * AuthnSvc, OPTIONAL
  1239. OUT unsigned long PAPI * AuthzSvc OPTIONAL
  1240. )
  1241. {
  1242. return RpcBindingInqAuthClientEx( ClientBinding,
  1243. Privs,
  1244. PrincName,
  1245. AuthnLevel,
  1246. AuthnSvc,
  1247. AuthzSvc,
  1248. 0
  1249. );
  1250. }
  1251. RPC_STATUS RPC_ENTRY
  1252. RpcBindingInqAuthClientEx (
  1253. IN RPC_BINDING_HANDLE ClientBinding, OPTIONAL
  1254. OUT RPC_AUTHZ_HANDLE PAPI * Privs,
  1255. OUT unsigned short PAPI * PAPI * ServerPrincName, OPTIONAL
  1256. OUT unsigned long PAPI * AuthnLevel, OPTIONAL
  1257. OUT unsigned long PAPI * AuthnSvc, OPTIONAL
  1258. OUT unsigned long PAPI * AuthzSvc, OPTIONAL
  1259. IN unsigned long Flags
  1260. )
  1261. /*++
  1262. Routine Description:
  1263. A server application will use this routine to obtain the authorization
  1264. information about a client making an authenticated remote procedure
  1265. call.
  1266. Arguments:
  1267. ClientBinding - Optionally supplies a binding handle on the server
  1268. side which indicates for which remote procedure call we wish to
  1269. obtain authorization information. If no binding handle is supplied,
  1270. then it is taken to be the remote procedure call currently being
  1271. handled by this server thread.
  1272. Privs - Returns a handle to the privileges information for the client
  1273. thread which made the remote procedure call.
  1274. ServerPrincName - Optionally returns the server principal name specified
  1275. by the client application.
  1276. AuthnLevel - Optionally returns the authentication level requested
  1277. by the client application.
  1278. AuthnSvc - Optionally returns the authentication service requested by
  1279. the client application.
  1280. AuthzSvc - Optionally returns the authorization service requested by
  1281. the client application.
  1282. Return Value:
  1283. RPC_S_OK - We successfully obtained the requested authentication and
  1284. authorization information.
  1285. RPC_S_INVALID_BINDING - The supplied binding handle (as the binding
  1286. argument) is not a valid binding handle.
  1287. RPC_S_WRONG_KIND_OF_BINDING - The binding handle is not a binding handle
  1288. on the server side.
  1289. RPC_S_BINDING_HAS_NO_AUTH - The remote procedure call is not
  1290. authenticated.
  1291. RPC_S_NO_CALL_ACTIVE - No binding handle was supplied and there is no
  1292. call active for this server thread.
  1293. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  1294. operation.
  1295. --*/
  1296. {
  1297. SCALL * SCall;
  1298. InitializeIfNecessary();
  1299. if (ARGUMENT_PRESENT(ClientBinding))
  1300. {
  1301. SCall = (SCALL *) ClientBinding;
  1302. if (SCall->InvalidHandle(SCALL_TYPE))
  1303. {
  1304. return(RPC_S_INVALID_BINDING);
  1305. }
  1306. }
  1307. else
  1308. {
  1309. SCall = (SCALL *) RpcpGetThreadContext();
  1310. if ( SCall == 0 )
  1311. {
  1312. return(RPC_S_NO_CALL_ACTIVE);
  1313. }
  1314. }
  1315. return SCall->InquireAuthClient(Privs,
  1316. ServerPrincName,
  1317. AuthnLevel,
  1318. AuthnSvc,
  1319. AuthzSvc,
  1320. Flags
  1321. );
  1322. }
  1323. RPCRTAPI
  1324. RPC_STATUS
  1325. RPC_ENTRY
  1326. RpcServerInqCallAttributesW (
  1327. IN RPC_BINDING_HANDLE ClientBinding, OPTIONAL
  1328. IN OUT void *RpcCallAttributes
  1329. )
  1330. /*++
  1331. Routine Description:
  1332. A server application will use this routine to obtain the security context
  1333. attributes for the calling client.
  1334. Arguments:
  1335. ClientBinding - Optionally supplies a binding handle on the server
  1336. side which indicates for which remote procedure call we wish to
  1337. obtain authorization information. If no binding handle is supplied,
  1338. then it is taken to be the remote procedure call currently being
  1339. handled by this server thread.
  1340. RpcCallAttributes - a pointer to
  1341. RPC_CALL_ATTRIBUTES_V1_W structure. The Version
  1342. member must be initialized.
  1343. Return Value:
  1344. RPC_S_OK for success of RPC_S_* /Win32 error code for error. EEInfo is
  1345. supplied. If the function fails, the contents of
  1346. RpcCallAttributes is undefined.
  1347. --*/
  1348. {
  1349. SCALL * SCall;
  1350. RPC_CALL_ATTRIBUTES_V1 *CallAttributes;
  1351. CallAttributes =
  1352. (RPC_CALL_ATTRIBUTES_V1 *)RpcCallAttributes;
  1353. if (CallAttributes->Version != 1)
  1354. return ERROR_INVALID_PARAMETER;
  1355. if (CallAttributes->Flags & RPC_QUERY_SERVER_PRINCIPAL_NAME)
  1356. {
  1357. if ((CallAttributes->ServerPrincipalName == NULL) &&
  1358. (CallAttributes->ServerPrincipalNameBufferLength != 0))
  1359. {
  1360. return ERROR_INVALID_PARAMETER;
  1361. }
  1362. }
  1363. if (CallAttributes->Flags & RPC_QUERY_CLIENT_PRINCIPAL_NAME)
  1364. {
  1365. if ((CallAttributes->ClientPrincipalName == NULL) &&
  1366. (CallAttributes->ClientPrincipalNameBufferLength != 0))
  1367. {
  1368. return ERROR_INVALID_PARAMETER;
  1369. }
  1370. }
  1371. InitializeIfNecessary();
  1372. if (ARGUMENT_PRESENT(ClientBinding))
  1373. {
  1374. SCall = (SCALL *) ClientBinding;
  1375. if (SCall->InvalidHandle(SCALL_TYPE))
  1376. {
  1377. return(RPC_S_INVALID_BINDING);
  1378. }
  1379. }
  1380. else
  1381. {
  1382. SCall = (SCALL *) RpcpGetThreadContext();
  1383. if ( SCall == 0 )
  1384. {
  1385. return(RPC_S_NO_CALL_ACTIVE);
  1386. }
  1387. }
  1388. return SCall->InquireCallAttributes(CallAttributes);
  1389. }
  1390. RPC_STATUS RPC_ENTRY
  1391. RpcImpersonateClient (
  1392. IN RPC_BINDING_HANDLE ClientBinding OPTIONAL
  1393. )
  1394. /*++
  1395. Routine Description:
  1396. Arguments:
  1397. Return Values:
  1398. --*/
  1399. {
  1400. SCALL * SCall;
  1401. THREAD *Thread;
  1402. InitializeIfNecessary();
  1403. ASSERT(!RpcpCheckHeap());
  1404. Thread = ThreadSelf();
  1405. if (!Thread)
  1406. return RPC_S_OUT_OF_MEMORY;
  1407. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  1408. if ( ClientBinding == 0 )
  1409. {
  1410. SCall = (SCALL *) RpcpGetThreadContext();
  1411. if (SCall == 0)
  1412. return(RPC_S_NO_CALL_ACTIVE);
  1413. }
  1414. else
  1415. {
  1416. SCall = (SCALL *) ClientBinding;
  1417. if (SCall->InvalidHandle(SCALL_TYPE))
  1418. return(RPC_S_INVALID_BINDING);
  1419. }
  1420. return(SCall->ImpersonateClient());
  1421. }
  1422. // the handle to the authz.dll. Protected by the global mutex. Once initialized,
  1423. // never uninitialized
  1424. HMODULE AuthzDllHandle = NULL;
  1425. // pointer to the AuthzInitializeContextFromToken function from authz.dll. Once
  1426. // initialized, never uninitialized
  1427. AuthzInitializeContextFromTokenFnType AuthzInitializeContextFromTokenFn = NULL;
  1428. // pointer to the AuthzInitializeContextFromSid function from authz.dll. Once
  1429. // initialized, never uninitialized
  1430. AuthzInitializeContextFromSidFnType AuthzInitializeContextFromSidFn = NULL;
  1431. // pointer to the AuthzInitializeContextFromContext function from authz.dll. Once
  1432. // initialized, never uninitialized
  1433. AuthzInitializeContextFromAuthzContextFnType AuthzInitializeContextFromAuthzContextFn = NULL;
  1434. // pointer to the AuthzInitializeContextFromToken function from authz.dll. Once
  1435. // initialized, never uninitialized
  1436. AuthzFreeContextFnType AuthzFreeContextFn = NULL;
  1437. // the dummy resource manager with NULL callbacks for everything. Protected
  1438. // by the global mutex. Once initialized, never uninitialized
  1439. AUTHZ_RESOURCE_MANAGER_HANDLE DummyResourceManager = NULL;
  1440. typedef struct tagProcLoadArgs
  1441. {
  1442. char *ProcName;
  1443. PVOID *ProcRoutine;
  1444. } ProcLoadArgs;
  1445. const ProcLoadArgs AuthzProcs[4] = {
  1446. {"AuthzInitializeContextFromToken", (PVOID *)&AuthzInitializeContextFromTokenFn},
  1447. {"AuthzInitializeContextFromAuthzContext", (PVOID *)&AuthzInitializeContextFromAuthzContextFn},
  1448. {"AuthzInitializeContextFromSid", (PVOID *)&AuthzInitializeContextFromSidFn},
  1449. {"AuthzFreeContext", (PVOID *) &AuthzFreeContextFn}
  1450. };
  1451. RPC_STATUS
  1452. InitializeAuthzSupportIfNecessary (
  1453. void
  1454. )
  1455. /*++
  1456. Routine Description:
  1457. Perform initialization required for Authz functions to work. Everybody
  1458. should call that before they use any Authz functionality.
  1459. Arguments:
  1460. Return Values:
  1461. RPC_S_OK for success and RPC_S_* for the rest
  1462. --*/
  1463. {
  1464. RPC_STATUS Status;
  1465. int i;
  1466. if (AuthzDllHandle)
  1467. return RPC_S_OK;
  1468. GlobalMutexRequest();
  1469. if (AuthzDllHandle)
  1470. {
  1471. GlobalMutexClear();
  1472. return RPC_S_OK;
  1473. }
  1474. AuthzDllHandle = LoadLibrary(L"Authz.dll");
  1475. if (AuthzDllHandle)
  1476. {
  1477. Status = RPC_S_OK;
  1478. for (i = 0; i < (sizeof(AuthzProcs) / sizeof(AuthzProcs[0])); i ++)
  1479. {
  1480. *(AuthzProcs[i].ProcRoutine) = GetProcAddress(AuthzDllHandle,
  1481. AuthzProcs[i].ProcName);
  1482. if (*(AuthzProcs[i].ProcRoutine) == NULL)
  1483. {
  1484. Status = GetLastError();
  1485. RpcpErrorAddRecord(EEInfoGCRuntime,
  1486. Status,
  1487. EEInfoDLInitializeAuthzSupportIfNecessary20,
  1488. AuthzProcs[i].ProcName);
  1489. FreeLibrary(AuthzDllHandle);
  1490. AuthzDllHandle = NULL;
  1491. break;
  1492. }
  1493. }
  1494. }
  1495. else
  1496. {
  1497. Status = GetLastError();
  1498. RpcpErrorAddRecord(EEInfoGCRuntime,
  1499. Status,
  1500. EEInfoDLInitializeAuthzSupportIfNecessary10,
  1501. L"Authz.dll");
  1502. }
  1503. GlobalMutexClear();
  1504. return Status;
  1505. }
  1506. typedef AUTHZAPI
  1507. BOOL
  1508. (WINAPI *AuthzInitializeResourceManagerFnType) (
  1509. IN DWORD AuthzFlags,
  1510. IN PFN_AUTHZ_DYNAMIC_ACCESS_CHECK pfnAccessCheck OPTIONAL,
  1511. IN PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS pfnComputeDynamicGroups OPTIONAL,
  1512. IN PFN_AUTHZ_FREE_DYNAMIC_GROUPS pfnFreeDynamicGroups OPTIONAL,
  1513. IN PCWSTR szResourceManagerName,
  1514. OUT PAUTHZ_RESOURCE_MANAGER_HANDLE pAuthzResourceManager
  1515. );
  1516. RPC_STATUS
  1517. CreateDummyResourceManagerIfNecessary (
  1518. void
  1519. )
  1520. /*++
  1521. Routine Description:
  1522. Perform initialization of the dummy resource manager. Any function that
  1523. uses the dummy resource manager must call this function beforehand.
  1524. This function must be called after InitializeAuthzSupportIfNecessary
  1525. Arguments:
  1526. Return Values:
  1527. RPC_S_OK for success and RPC_S_* for the rest
  1528. --*/
  1529. {
  1530. AuthzInitializeResourceManagerFnType AuthzInitializeResourceManagerFn;
  1531. RPC_STATUS Status;
  1532. BOOL Result;
  1533. // this function must be called after InitializeAuthzSupportIfNecessary
  1534. ASSERT(AuthzDllHandle);
  1535. if (DummyResourceManager)
  1536. return RPC_S_OK;
  1537. GlobalMutexRequest();
  1538. if (DummyResourceManager)
  1539. {
  1540. GlobalMutexClear();
  1541. return RPC_S_OK;
  1542. }
  1543. AuthzInitializeResourceManagerFn
  1544. = (AuthzInitializeResourceManagerFnType) GetProcAddress(AuthzDllHandle,
  1545. "AuthzInitializeResourceManager");
  1546. if (AuthzInitializeResourceManagerFn == NULL)
  1547. {
  1548. Status = GetLastError();
  1549. RpcpErrorAddRecord(EEInfoGCRuntime,
  1550. Status,
  1551. EEInfoDLCreateDummyResourceManagerIfNecessary10,
  1552. "AuthzInitializeResourceManager");
  1553. }
  1554. else
  1555. {
  1556. Result = AuthzInitializeResourceManagerFn(
  1557. 0, // Flags
  1558. NULL, // pfnAccessCheck
  1559. NULL, // pfnComputeDynamicGroups
  1560. NULL, // pfnFreeDynamicGroups
  1561. L"", // Name
  1562. &DummyResourceManager);
  1563. if (Result == FALSE)
  1564. {
  1565. Status = GetLastError();
  1566. RpcpErrorAddRecord(EEInfoGCAuthz,
  1567. Status,
  1568. EEInfoDLCreateDummyResourceManagerIfNecessary20);
  1569. }
  1570. else
  1571. Status = RPC_S_OK;
  1572. }
  1573. GlobalMutexClear();
  1574. return Status;
  1575. }
  1576. RPC_STATUS RPC_ENTRY
  1577. RpcGetAuthorizationContextForClient (
  1578. IN RPC_BINDING_HANDLE ClientBinding OPTIONAL,
  1579. IN BOOL ImpersonateOnReturn,
  1580. IN PVOID Reserved1,
  1581. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  1582. IN LUID Reserved2,
  1583. IN DWORD Reserved3,
  1584. IN PVOID Reserved4,
  1585. OUT PVOID *pAuthzClientContext
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. Gets an authorization context for the client that can be used
  1590. with Authz functions. The resulting context is owned by the caller
  1591. and must be freed by it.
  1592. Arguments:
  1593. ImpersonateOnReturn - if TRUE, when we return, we should be impersonating.
  1594. If the function fails, we're not impersonating
  1595. Reserved1 - the resource manager to use (passed to Authz). Must be
  1596. NULL for now
  1597. pExpirationTime - the expiration time to use (passed to Authz)
  1598. Reserved2 - the LUID (passed to Authz). Must be 0 for now.
  1599. Resevred3 - Flags (passed to Authz). Must be 0 for now.
  1600. Reserved4 - DynamicGroupArgs parameter required by Authz (passed to Authz)
  1601. pAuthzClientContext - the authorization context, returned on success.
  1602. Undefined on failure.
  1603. Return Values:
  1604. RPC_S_OK for success, ERROR_INVALID_PARAMETER for non-null values for
  1605. the Reserved parameters and RPC_S_* / Win32 errors for the rest
  1606. --*/
  1607. {
  1608. SCALL * SCall;
  1609. THREAD *Thread;
  1610. RPC_STATUS Status;
  1611. InitializeIfNecessary();
  1612. ASSERT(!RpcpCheckHeap());
  1613. Thread = ThreadSelf();
  1614. if (!Thread)
  1615. return RPC_S_OUT_OF_MEMORY;
  1616. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  1617. if ((Reserved1 != NULL)
  1618. || (Reserved2.HighPart != 0)
  1619. || (Reserved2.LowPart != 0)
  1620. || (Reserved3 != 0)
  1621. || (Reserved4 != NULL))
  1622. {
  1623. return ERROR_INVALID_PARAMETER;
  1624. }
  1625. Status = InitializeAuthzSupportIfNecessary();
  1626. if (Status != RPC_S_OK)
  1627. return Status;
  1628. Status = CreateDummyResourceManagerIfNecessary();
  1629. if (Status != RPC_S_OK)
  1630. return Status;
  1631. if ( ClientBinding == 0 )
  1632. {
  1633. SCall = (SCALL *) RpcpGetThreadContext();
  1634. if (SCall == 0)
  1635. return(RPC_S_NO_CALL_ACTIVE);
  1636. }
  1637. else
  1638. {
  1639. SCall = (SCALL *) ClientBinding;
  1640. if (SCall->InvalidHandle(SCALL_TYPE))
  1641. return(RPC_S_INVALID_BINDING);
  1642. }
  1643. return(SCall->GetAuthorizationContext(ImpersonateOnReturn,
  1644. DummyResourceManager,
  1645. pExpirationTime,
  1646. Reserved2,
  1647. Reserved3,
  1648. Reserved4,
  1649. (PAUTHZ_CLIENT_CONTEXT_HANDLE)pAuthzClientContext));
  1650. }
  1651. RPC_STATUS RPC_ENTRY
  1652. RpcFreeAuthorizationContext (
  1653. IN OUT PVOID *pAuthzClientContext
  1654. )
  1655. /*++
  1656. Routine Description:
  1657. Frees an authorization context obtained through
  1658. RpcGetAuthorizationContextForClient
  1659. Arguments:
  1660. pAuthzClientContext - a pointer to the authorization context to
  1661. be freed. The function will zero-out the freed authorization context
  1662. to prevent accidental re-use in the success case. The authorization
  1663. context won't be touched in case of failure.
  1664. Return Values:
  1665. RPC_S_OK for success, Win32 errors for the rest
  1666. --*/
  1667. {
  1668. BOOL Result;
  1669. Result = AuthzFreeContextFn((AUTHZ_CLIENT_CONTEXT_HANDLE)(*pAuthzClientContext));
  1670. if (Result == FALSE)
  1671. {
  1672. return GetLastError();
  1673. }
  1674. else
  1675. {
  1676. *pAuthzClientContext = NULL;
  1677. return RPC_S_OK;
  1678. }
  1679. }
  1680. RPC_STATUS RPC_ENTRY
  1681. RpcRevertToSelfEx (
  1682. IN RPC_BINDING_HANDLE ClientBinding OPTIONAL
  1683. )
  1684. /*++
  1685. Routine Description:
  1686. Return Value:
  1687. --*/
  1688. {
  1689. SCALL * SCall ;
  1690. InitializeIfNecessary();
  1691. ASSERT(!RpcpCheckHeap());
  1692. if ( ClientBinding == 0 )
  1693. {
  1694. SCall = (SCALL *) RpcpGetThreadContext();
  1695. if ( SCall == 0 )
  1696. return(RPC_S_NO_CALL_ACTIVE);
  1697. }
  1698. else
  1699. {
  1700. SCall = (SCALL *) ClientBinding;
  1701. if (SCall->InvalidHandle(SCALL_TYPE))
  1702. return(RPC_S_INVALID_BINDING);
  1703. }
  1704. return(SCall->RevertToSelf());
  1705. }
  1706. RPC_STATUS RPC_ENTRY
  1707. RpcRevertToSelf (
  1708. )
  1709. /*++
  1710. Routine Description:
  1711. Return Value:
  1712. --*/
  1713. {
  1714. return(RpcRevertToSelfEx((RPC_BINDING_HANDLE) 0));
  1715. }
  1716. RPC_STATUS RPC_ENTRY
  1717. RpcMgmtSetServerStackSize (
  1718. IN unsigned long ThreadStackSize
  1719. )
  1720. /*++
  1721. Routine Description:
  1722. An application will use this routine to specify the stack size for
  1723. each of the threads created by the server to handle remote procedure
  1724. calls.
  1725. Arguments:
  1726. ThreadStackSize - Supplies the thread stack size in bytes.
  1727. Return Value:
  1728. RPC_S_OK - Everybody is happy with the stack size.
  1729. RPC_S_INVALID_ARG - The stack size is either too small, or too large.
  1730. --*/
  1731. {
  1732. InitializeIfNecessary();
  1733. return(SetThreadStackSize(ThreadStackSize));
  1734. }
  1735. RPC_STATUS RPC_ENTRY
  1736. I_RpcBindingIsClientLocal (
  1737. IN RPC_BINDING_HANDLE BindingHandle OPTIONAL,
  1738. OUT unsigned int PAPI * ClientLocalFlag
  1739. )
  1740. /*++
  1741. Routine Description:
  1742. This routine exists for one reason: so that the security system can
  1743. tell if a client is local or remote. The client must be using named
  1744. pipes to talk to the server.
  1745. Arguments:
  1746. BindingHandle - Optionally supplies a client binding handle specifing
  1747. which client we want to know if it is local or remote. If this
  1748. parameter is not supplied, then we will determine local/remote for
  1749. the client which made call currently being handled by this server
  1750. thread.
  1751. ClientLocalFlag - Returns an indication of whether or not the client is
  1752. local (ie. on the same machine as the server). This field will be
  1753. set to a non-zero value to indicate that the client is local;
  1754. otherwise, the client is remote.
  1755. Return Value:
  1756. RPC_S_OK - We successfully determined whether or not the client is
  1757. local.
  1758. RPC_S_NO_CALL_ACTIVE - There is no call active for this server thread.
  1759. RPC_S_CANNOT_SUPPORT - Only the connection oriented protocol over named
  1760. pipes can support this operation. If the client is using something
  1761. else, other than the connection oriented protocol, this will be
  1762. returned.
  1763. RPC_S_INVALID_BINDING - The binding argument does not supply a client
  1764. binding handle.
  1765. --*/
  1766. {
  1767. SCALL *SCall;
  1768. InitializeIfNecessary();
  1769. if ( BindingHandle == 0 )
  1770. {
  1771. SCall = (SCALL *) RpcpGetThreadContext();
  1772. if ( SCall == 0 )
  1773. {
  1774. return(RPC_S_NO_CALL_ACTIVE);
  1775. }
  1776. }
  1777. else
  1778. {
  1779. SCall = (SCALL *) BindingHandle;
  1780. if ( SCall->InvalidHandle(SCALL_TYPE) )
  1781. {
  1782. return(RPC_S_INVALID_BINDING);
  1783. }
  1784. }
  1785. return(SCall->IsClientLocal(ClientLocalFlag));
  1786. }
  1787. RPC_STATUS RPC_ENTRY
  1788. RpcMgmtInqIfIds (
  1789. IN RPC_BINDING_HANDLE Binding,
  1790. OUT RPC_IF_ID_VECTOR __RPC_FAR * __RPC_FAR * IfIdVector
  1791. )
  1792. /*++
  1793. Routine Description:
  1794. This routine is used to obtain a vector of the interface identifiers of
  1795. the interfaces supported by a server.
  1796. Arguments:
  1797. Binding - Optionally supplies a binding handle to the server. If this
  1798. argument is not supplied, the local application is queried.
  1799. IfIdVector - Returns a vector of the interfaces supported by the server.
  1800. Return Value:
  1801. RPC_S_OK - Everything worked just fine, and you now know the interfaces
  1802. supported by this server.
  1803. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  1804. the operation.
  1805. RPC_S_INVALID_BINDING - The supplied binding is not zero.
  1806. --*/
  1807. {
  1808. RPC_STATUS Status;
  1809. InitializeIfNecessary();
  1810. if ( Binding == 0 )
  1811. {
  1812. return(GlobalRpcServer->InquireInterfaceIds(IfIdVector));
  1813. }
  1814. *IfIdVector = 0;
  1815. _rpc_mgmt_inq_if_ids(Binding, (rpc_if_id_vector_p_t *) IfIdVector,
  1816. (unsigned long *) &Status);
  1817. return(Status);
  1818. }
  1819. RPC_STATUS RPC_ENTRY
  1820. RpcIfIdVectorFree (
  1821. IN OUT RPC_IF_ID_VECTOR __RPC_FAR * __RPC_FAR * IfIdVector
  1822. )
  1823. /*++
  1824. Routine Description:
  1825. This routine is used to free an interface id vector.
  1826. Arguments:
  1827. IfIdVector - Supplies the interface id vector to be freed; on return
  1828. this will be set to zero.
  1829. Return Value:
  1830. RPC_S_OK - This will always be returned.
  1831. --*/
  1832. {
  1833. unsigned int Count;
  1834. InitializeIfNecessary();
  1835. if (!*IfIdVector)
  1836. {
  1837. return(RPC_S_OK);
  1838. }
  1839. for (Count = 0; Count < (*IfIdVector)->Count; Count++)
  1840. {
  1841. if ( (*IfIdVector)->IfId[Count] != 0 )
  1842. {
  1843. RpcpFarFree((*IfIdVector)->IfId[Count]);
  1844. }
  1845. }
  1846. RpcpFarFree(*IfIdVector);
  1847. *IfIdVector = 0;
  1848. return(RPC_S_OK);
  1849. }
  1850. // StringToUnicodeString lives in epmgmt.c
  1851. //
  1852. extern "C" RPC_CHAR *StringToWideCharString(unsigned char *, RPC_STATUS *);
  1853. #define SERVER_PRINC_NAME_SIZE 256
  1854. RPC_STATUS RPC_ENTRY
  1855. RpcMgmtInqServerPrincName (
  1856. IN RPC_BINDING_HANDLE Binding,
  1857. IN unsigned long AuthnSvc,
  1858. OUT unsigned short __RPC_FAR * __RPC_FAR * ServerPrincName
  1859. )
  1860. /*++
  1861. Routine Description:
  1862. Arguments:
  1863. Binding - Supplies
  1864. AuthnSvc - Supplies
  1865. ServerPrincName - Returns
  1866. Return Value:
  1867. RPC_S_OK - Everything worked just fine, and you now know the interfaces
  1868. supported by this server.
  1869. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  1870. the operation.
  1871. RPC_S_INVALID_BINDING - The supplied binding is not zero.
  1872. --*/
  1873. {
  1874. RPC_STATUS Status;
  1875. unsigned char *AnsiPrincName;
  1876. THREAD *Thread;
  1877. InitializeIfNecessary();
  1878. Thread = ThreadSelf();
  1879. if (Thread)
  1880. {
  1881. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  1882. }
  1883. if ( Binding == 0 )
  1884. {
  1885. return(GlobalRpcServer->InquirePrincipalName(AuthnSvc, ServerPrincName));
  1886. }
  1887. AnsiPrincName = new unsigned char[SERVER_PRINC_NAME_SIZE + 1];
  1888. if (AnsiPrincName == 0)
  1889. return(RPC_S_OUT_OF_MEMORY);
  1890. _rpc_mgmt_inq_princ_name(Binding, AuthnSvc, SERVER_PRINC_NAME_SIZE,
  1891. AnsiPrincName, (unsigned long *)&Status);
  1892. *ServerPrincName = 0;
  1893. if ( Status == RPC_S_OK )
  1894. {
  1895. Status = A2WAttachHelper((char *)AnsiPrincName, ServerPrincName);
  1896. if (Status != RPC_S_OK)
  1897. {
  1898. delete AnsiPrincName;
  1899. ASSERT(Status == RPC_S_OUT_OF_MEMORY);
  1900. return(RPC_S_OUT_OF_MEMORY);
  1901. }
  1902. }
  1903. delete AnsiPrincName;
  1904. return(Status);
  1905. }
  1906. RPC_STATUS RPC_ENTRY
  1907. RpcServerInqDefaultPrincName (
  1908. IN unsigned long AuthnSvc,
  1909. OUT unsigned short __RPC_FAR * __RPC_FAR * PrincName
  1910. )
  1911. /*++
  1912. Routine Description:
  1913. Arguments:
  1914. PrincName - Returns
  1915. Return Value:
  1916. RPC_S_OK - Everything worked just fine, and you now know the interfaces
  1917. supported by this server.
  1918. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  1919. the operation.
  1920. --*/
  1921. {
  1922. RPC_STATUS Status = RPC_S_OK;
  1923. SECURITY_CREDENTIALS *pCredentials;
  1924. SEC_CHAR * DefaultPrincName = NULL;
  1925. RPC_CHAR *CopyPrincName;
  1926. InitializeIfNecessary();
  1927. Status = FindServerCredentials(
  1928. NULL,
  1929. NULL,
  1930. AuthnSvc,
  1931. 0,
  1932. NULL,
  1933. &pCredentials
  1934. );
  1935. if (Status != RPC_S_OK) {
  1936. return (Status);
  1937. }
  1938. Status = pCredentials->InquireDefaultPrincName(&DefaultPrincName);
  1939. if (Status != RPC_S_OK) {
  1940. return (Status);
  1941. }
  1942. ASSERT(DefaultPrincName);
  1943. CopyPrincName = DuplicateString((RPC_CHAR *)DefaultPrincName);
  1944. if (CopyPrincName == 0)
  1945. return(RPC_S_OUT_OF_MEMORY);
  1946. *PrincName = CopyPrincName;
  1947. return (RPC_S_OK);
  1948. }
  1949. RPC_STATUS RPC_ENTRY
  1950. THUNK_FN(RpcServerInqDefaultPrincName) (
  1951. IN unsigned long AuthnSvc,
  1952. OUT THUNK_CHAR **PrincName
  1953. )
  1954. {
  1955. RPC_STATUS RpcStatus;
  1956. USES_CONVERSION;
  1957. COutDelThunk thunkedPrincName;
  1958. RpcStatus = RpcServerInqDefaultPrincName(AuthnSvc,
  1959. thunkedPrincName);
  1960. if (RpcStatus != RPC_S_OK)
  1961. {
  1962. return(RpcStatus);
  1963. }
  1964. ATTEMPT_OUT_THUNK(thunkedPrincName, PrincName);
  1965. return (RpcStatus);
  1966. }
  1967. RPC_STATUS RPC_ENTRY
  1968. RpcBindingServerFromClient (
  1969. IN RPC_BINDING_HANDLE ClientBinding,
  1970. OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
  1971. )
  1972. /*++
  1973. Routine Description:
  1974. This routine is used by a server application to convert a client binding
  1975. handle (server side binding handle) into a partially bound server binding
  1976. handle (client side binding handle).
  1977. Arguments:
  1978. ClientBinding - Supplies a client binding.
  1979. ServerBinding - Returns a partially bound server binding handle which
  1980. can be used to get back to the client.
  1981. Return Values:
  1982. RPC_S_OK - The client binding handle has been successfully converted into
  1983. a server binding handle.
  1984. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete this
  1985. operation.
  1986. RPC_S_CANNOT_SUPPORT - The requested operation can not be supported.
  1987. RPC_S_INVALID_BINDING - The supplied client binding is invalid.
  1988. RPC_S_WRONG_KIND_OF_BINDING - The supplied client binding is not a
  1989. client binding.
  1990. --*/
  1991. {
  1992. GENERIC_OBJECT * SCall;
  1993. THREAD *Thread;
  1994. InitializeIfNecessary();
  1995. Thread = ThreadSelf();
  1996. if (!Thread)
  1997. return RPC_S_OUT_OF_MEMORY;
  1998. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  1999. if (ARGUMENT_PRESENT(ClientBinding))
  2000. {
  2001. SCall = (GENERIC_OBJECT *) ClientBinding;
  2002. if (SCall->InvalidHandle(CALL_TYPE | BINDING_HANDLE_TYPE))
  2003. {
  2004. *ServerBinding = 0;
  2005. return(RPC_S_INVALID_BINDING);
  2006. }
  2007. if (SCall->InvalidHandle(SCALL_TYPE))
  2008. {
  2009. *ServerBinding = 0;
  2010. return(RPC_S_WRONG_KIND_OF_BINDING);
  2011. }
  2012. }
  2013. else
  2014. {
  2015. SCall = (GENERIC_OBJECT *) RpcpGetThreadContext();
  2016. if ( SCall == 0 )
  2017. {
  2018. *ServerBinding = 0;
  2019. return(RPC_S_NO_CALL_ACTIVE);
  2020. }
  2021. }
  2022. return(((SCALL *) SCall)->ConvertToServerBinding(ServerBinding));
  2023. }
  2024. RPC_STATUS RPC_ENTRY
  2025. I_RpcServerRegisterForwardFunction(
  2026. IN RPC_FORWARD_FUNCTION __RPC_FAR * pForwardFunction
  2027. )
  2028. /*++
  2029. Routine Description:
  2030. Allows Epmapper to register a function with the runtime
  2031. to allow the runtime to determine the 'forwarding' endpoint
  2032. (that is the local endpoint the server must forward the
  2033. currently received packet to).
  2034. Return Value:
  2035. --*/
  2036. {
  2037. InitializeIfNecessary();
  2038. GlobalRpcServer->RegisterRpcForwardFunction(pForwardFunction);
  2039. return RPC_S_OK;
  2040. }
  2041. RPC_ADDRESS_CHANGE_FN * gAddressChangeFn = 0;
  2042. RPC_ADDRESS_CHANGE_FN * RPC_ENTRY
  2043. I_RpcServerInqAddressChangeFn()
  2044. {
  2045. return gAddressChangeFn;
  2046. }
  2047. RPC_STATUS RPC_ENTRY
  2048. I_RpcServerSetAddressChangeFn(
  2049. IN RPC_ADDRESS_CHANGE_FN * pAddressChangeFn
  2050. )
  2051. {
  2052. gAddressChangeFn = pAddressChangeFn;
  2053. return RPC_S_OK;
  2054. }
  2055. RPC_STATUS
  2056. RPC_ENTRY
  2057. I_RpcServerInqLocalConnAddress (
  2058. IN RPC_BINDING_HANDLE Binding,
  2059. IN OUT void *Buffer,
  2060. IN OUT unsigned long *BufferSize,
  2061. OUT unsigned long *AddressFormat
  2062. )
  2063. /*++
  2064. Routine Description:
  2065. This routine is used by a server application to inquire about the local
  2066. address on which a call is made.
  2067. Arguments:
  2068. Binding - Supplies a valid server binding (SCALL).
  2069. Buffer - The buffer that will receive the output address
  2070. BufferSize - the size of the supplied Buffer on input. On output the
  2071. number of bytes written to the buffer. If the buffer is too small
  2072. to receive all the output data, ERROR_MORE_DATA is returned,
  2073. nothing is written to the buffer, and BufferSize is set to
  2074. the size of the buffer needed to return all the data.
  2075. AddressFormat - a constant indicating the format of the returned address.
  2076. Currently supported are RPC_P_ADDR_FORMAT_TCP_IPV4 and
  2077. RPC_P_ADDR_FORMAT_TCP_IPV6. Undefined on failure.
  2078. Return Values:
  2079. RPC_S_OK - success.
  2080. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete this
  2081. operation.
  2082. RPC_S_INVALID_BINDING - The supplied client binding is invalid.
  2083. RPC_S_CANNOT_SUPPORT - The local address was inquired for a protocol
  2084. sequence that doesn't support this type of functionality. Currently
  2085. only ncacn_ip_tcp supports it.
  2086. RPC_S_* or Win32 error for other errors
  2087. --*/
  2088. {
  2089. SCALL *SCall;
  2090. THREAD *Thread;
  2091. RPC_STATUS Status;
  2092. InitializeIfNecessary();
  2093. ASSERT(!RpcpCheckHeap());
  2094. Thread = ThreadSelf();
  2095. if (!Thread)
  2096. return RPC_S_OUT_OF_MEMORY;
  2097. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  2098. if ( Binding == 0 )
  2099. {
  2100. SCall = (SCALL *) RpcpGetThreadContext();
  2101. if (SCall == 0)
  2102. return(RPC_S_NO_CALL_ACTIVE);
  2103. }
  2104. else
  2105. {
  2106. SCall = (SCALL *) Binding;
  2107. if (SCall->InvalidHandle(SCALL_TYPE))
  2108. return(RPC_S_INVALID_BINDING);
  2109. }
  2110. return InqLocalConnAddress(
  2111. SCall,
  2112. Buffer,
  2113. BufferSize,
  2114. AddressFormat);
  2115. }
  2116. RPC_STATUS RPC_ENTRY
  2117. I_RpcServerUnregisterEndpoint (
  2118. IN RPC_CHAR * Protseq,
  2119. IN RPC_CHAR * Endpoint
  2120. )
  2121. {
  2122. InitializeIfNecessary();
  2123. return GlobalRpcServer->UnregisterEndpoint(Protseq, Endpoint);
  2124. }
  2125. int
  2126. InitializeRpcServer (
  2127. )
  2128. /*++
  2129. Routine Description:
  2130. This routine will be called once at DLL initialization time. We
  2131. have got to create and initialize the server. This will get it
  2132. all ready to hang protocol sequences (addresses) and interfaces
  2133. from.
  2134. Return Value:
  2135. Zero will be returned if everything is initialized correctly;
  2136. otherwise, non-zero will be returned.
  2137. --*/
  2138. {
  2139. RPC_STATUS RpcStatus = RPC_S_OK;
  2140. GlobalRpcServer = new RPC_SERVER(&RpcStatus);
  2141. if ( ( GlobalRpcServer == 0 )
  2142. || ( RpcStatus != RPC_S_OK ) )
  2143. {
  2144. return(1);
  2145. }
  2146. GroupIdCounter = GetTickCount();
  2147. // If we can't create the global management interface
  2148. // don't worry about it; it probably won't be used anyway.
  2149. // When it is used, it should be checked for NULL.
  2150. GlobalManagementInterface = new RPC_INTERFACE(
  2151. (RPC_SERVER_INTERFACE *)mgmt_ServerIfHandle,
  2152. GlobalRpcServer, 0, MAX_IF_CALLS, gMaxRpcSize, 0, &RpcStatus);
  2153. if (GlobalManagementInterface)
  2154. {
  2155. GlobalManagementInterface->RegisterTypeManager(0,
  2156. ((RPC_SERVER_INTERFACE *)mgmt_ServerIfHandle)->DefaultManagerEpv);
  2157. }
  2158. return(RpcStatus);
  2159. }