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.

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