Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. rpcutil.c
  5. Abstract:
  6. This module contains high level rpc wrapper apis.
  7. This code is here because the code in the rpcutil
  8. project uses NT apis and the WINFAX dll but load
  9. and run on win95.
  10. Author:
  11. Wesley Witt (wesw) 13-Aug-1997
  12. Revision History:
  13. --*/
  14. #include "faxapi.h"
  15. #pragma hdrstop
  16. #define NT_PIPE_PREFIX_W L"\\PIPE\\"
  17. #define WCSSIZE(s) ((wcslen(s)+1) * sizeof(WCHAR))
  18. static CRITICAL_SECTION RpcpCriticalSection;
  19. static DWORD RpcpNumInstances;
  20. DWORD
  21. RpcpInitRpcServer(
  22. VOID
  23. )
  24. /*++
  25. Routine Description:
  26. This function initializes the critical section used to protect the
  27. global server handle and instance count.
  28. Arguments:
  29. none
  30. Return Value:
  31. none
  32. --*/
  33. {
  34. InitializeCriticalSection(&RpcpCriticalSection);
  35. RpcpNumInstances = 0;
  36. return(0);
  37. }
  38. DWORD
  39. RpcpAddInterface(
  40. IN LPWSTR InterfaceName,
  41. IN RPC_IF_HANDLE InterfaceSpecification
  42. )
  43. /*++
  44. Routine Description:
  45. Starts an RPC Server, adds the address (or port/pipe), and adds the
  46. interface (dispatch table).
  47. Arguments:
  48. InterfaceName - points to the name of the interface.
  49. InterfaceSpecification - Supplies the interface handle for the
  50. interface which we wish to add.
  51. Return Value:
  52. NT_SUCCESS - Indicates the server was successfully started.
  53. STATUS_NO_MEMORY - An attempt to allocate memory has failed.
  54. Other - Status values that may be returned by:
  55. RpcServerRegisterIf()
  56. RpcServerUseProtseqEp()
  57. , or any RPC error codes, or any windows error codes that
  58. can be returned by LocalAlloc.
  59. --*/
  60. {
  61. RPC_STATUS RpcStatus;
  62. LPWSTR Endpoint = NULL;
  63. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  64. // We need to concatenate \pipe\ to the front of the interface name.
  65. Endpoint = (LPWSTR)LocalAlloc(LMEM_FIXED, sizeof(NT_PIPE_PREFIX_W) + WCSSIZE(InterfaceName));
  66. if (Endpoint == 0) {
  67. return(STATUS_NO_MEMORY);
  68. }
  69. wcscpy(Endpoint, NT_PIPE_PREFIX_W );
  70. wcscat(Endpoint,InterfaceName);
  71. // Ignore the second argument for now.
  72. RpcStatus = RpcServerUseProtseqEpW(L"ncacn_np", 10, Endpoint, SecurityDescriptor);
  73. // If RpcpStartRpcServer and then RpcpStopRpcServer have already
  74. // been called, the endpoint will have already been added but not
  75. // removed (because there is no way to do it). If the endpoint is
  76. // already there, it is ok.
  77. if ((RpcStatus != RPC_S_OK) && (RpcStatus != RPC_S_DUPLICATE_ENDPOINT)) {
  78. goto CleanExit;
  79. }
  80. RpcStatus = RpcServerRegisterIf(InterfaceSpecification, 0, 0);
  81. CleanExit:
  82. if ( Endpoint != NULL ) {
  83. LocalFree(Endpoint);
  84. }
  85. if ( SecurityDescriptor != NULL) {
  86. LocalFree(SecurityDescriptor);
  87. }
  88. return( I_RpcMapWin32Status(RpcStatus) );
  89. }
  90. DWORD
  91. RpcpStartRpcServer(
  92. IN LPWSTR InterfaceName,
  93. IN RPC_IF_HANDLE InterfaceSpecification
  94. )
  95. /*++
  96. Routine Description:
  97. Starts an RPC Server, adds the address (or port/pipe), and adds the
  98. interface (dispatch table).
  99. Arguments:
  100. InterfaceName - points to the name of the interface.
  101. InterfaceSpecification - Supplies the interface handle for the
  102. interface which we wish to add.
  103. Return Value:
  104. NT_SUCCESS - Indicates the server was successfully started.
  105. STATUS_NO_MEMORY - An attempt to allocate memory has failed.
  106. Other - Status values that may be returned by:
  107. RpcServerRegisterIf()
  108. RpcServerUseProtseqEp()
  109. , or any RPC error codes, or any windows error codes that
  110. can be returned by LocalAlloc.
  111. --*/
  112. {
  113. RPC_STATUS RpcStatus;
  114. EnterCriticalSection(&RpcpCriticalSection);
  115. RpcStatus = RpcpAddInterface( InterfaceName,
  116. InterfaceSpecification );
  117. if ( RpcStatus != RPC_S_OK ) {
  118. LeaveCriticalSection(&RpcpCriticalSection);
  119. return( I_RpcMapWin32Status(RpcStatus) );
  120. }
  121. RpcpNumInstances++;
  122. if (RpcpNumInstances == 1) {
  123. // The first argument specifies the minimum number of threads to
  124. // be created to handle calls; the second argument specifies the
  125. // maximum number of concurrent calls allowed. The last argument
  126. // indicates not to wait.
  127. RpcStatus = RpcServerListen(1,12345, 1);
  128. if ( RpcStatus == RPC_S_ALREADY_LISTENING ) {
  129. RpcStatus = RPC_S_OK;
  130. }
  131. }
  132. LeaveCriticalSection(&RpcpCriticalSection);
  133. return( I_RpcMapWin32Status(RpcStatus) );
  134. }
  135. DWORD
  136. RpcpStopRpcServer(
  137. IN RPC_IF_HANDLE InterfaceSpecification
  138. )
  139. /*++
  140. Routine Description:
  141. Deletes the interface. This is likely
  142. to be caused by an invalid handle. If an attempt to add the same
  143. interface or address again, then an error will be generated at that
  144. time.
  145. Arguments:
  146. InterfaceSpecification - A handle for the interface that is to be removed.
  147. Return Value:
  148. NERR_Success, or any RPC error codes that can be returned from
  149. RpcServerUnregisterIf.
  150. --*/
  151. {
  152. RPC_STATUS RpcStatus;
  153. RpcStatus = RpcServerUnregisterIf(InterfaceSpecification, 0, 1);
  154. EnterCriticalSection(&RpcpCriticalSection);
  155. RpcpNumInstances--;
  156. if (RpcpNumInstances == 0) {
  157. RpcMgmtStopServerListening(0);
  158. RpcMgmtWaitServerListen();
  159. }
  160. LeaveCriticalSection(&RpcpCriticalSection);
  161. return( I_RpcMapWin32Status(RpcStatus) );
  162. }
  163. DWORD
  164. RpcpBindRpc(
  165. IN LPCWSTR ServerName,
  166. IN LPCWSTR ServiceName,
  167. IN LPCWSTR NetworkOptions,
  168. OUT RPC_BINDING_HANDLE * pBindingHandle
  169. )
  170. /*++
  171. Routine Description:
  172. Binds to the RPC server if possible.
  173. Arguments:
  174. ServerName - Name of server to bind with.
  175. ServiceName - Name of service to bind with.
  176. pBindingHandle - Location where binding handle is to be placed
  177. Return Value:
  178. STATUS_SUCCESS - The binding has been successfully completed.
  179. STATUS_INVALID_COMPUTER_NAME - The ServerName syntax is invalid.
  180. STATUS_NO_MEMORY - There is not sufficient memory available to the
  181. caller to perform the binding.
  182. --*/
  183. {
  184. RPC_STATUS RpcStatus;
  185. LPWSTR StringBinding;
  186. LPWSTR Endpoint;
  187. WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  188. LPWSTR NewServerName = NULL;
  189. DWORD bufLen = MAX_COMPUTERNAME_LENGTH + 1;
  190. *pBindingHandle = NULL;
  191. if (ServerName != NULL) {
  192. if (GetComputerNameW(ComputerName,&bufLen)) {
  193. if ((_wcsicmp(ComputerName,ServerName) == 0) ||
  194. ((ServerName[0] == '\\') &&
  195. (ServerName[1] == '\\') &&
  196. (_wcsicmp(ComputerName,&(ServerName[2]))==0))) {
  197. NewServerName = NULL;
  198. }
  199. else {
  200. NewServerName = (LPWSTR)ServerName;
  201. }
  202. } else {
  203. NewServerName = (LPWSTR)ServerName;
  204. }
  205. }
  206. // We need to concatenate \pipe\ to the front of the service
  207. // name.
  208. Endpoint = (LPWSTR)LocalAlloc(
  209. 0,
  210. sizeof(NT_PIPE_PREFIX_W) + WCSSIZE(ServiceName));
  211. if (Endpoint == 0) {
  212. return(STATUS_NO_MEMORY);
  213. }
  214. wcscpy(Endpoint,NT_PIPE_PREFIX_W);
  215. wcscat(Endpoint,ServiceName);
  216. RpcStatus = RpcStringBindingComposeW(0, L"ncacn_np", NewServerName,
  217. Endpoint, (LPWSTR)NetworkOptions, &StringBinding);
  218. LocalFree(Endpoint);
  219. if ( RpcStatus != RPC_S_OK ) {
  220. return( STATUS_NO_MEMORY );
  221. }
  222. RpcStatus = RpcBindingFromStringBindingW(StringBinding, pBindingHandle);
  223. RpcStringFreeW(&StringBinding);
  224. if ( RpcStatus != RPC_S_OK ) {
  225. *pBindingHandle = NULL;
  226. if ( (RpcStatus == RPC_S_INVALID_ENDPOINT_FORMAT)
  227. || (RpcStatus == RPC_S_INVALID_NET_ADDR) ) {
  228. return( ERROR_INVALID_COMPUTERNAME );
  229. }
  230. return(STATUS_NO_MEMORY);
  231. }
  232. return(ERROR_SUCCESS);
  233. }
  234. DWORD
  235. RpcpUnbindRpc(
  236. IN RPC_BINDING_HANDLE BindingHandle
  237. )
  238. /*++
  239. Routine Description:
  240. Unbinds from the RPC interface.
  241. If we decide to cache bindings, this routine will do something more
  242. interesting.
  243. Arguments:
  244. BindingHandle - This points to the binding handle that is to be closed.
  245. Return Value:
  246. STATUS_SUCCESS - the unbinding was successful.
  247. --*/
  248. {
  249. RPC_STATUS RpcStatus;
  250. if (BindingHandle != NULL) {
  251. RpcStatus = RpcBindingFree(&BindingHandle);
  252. }
  253. return(ERROR_SUCCESS);
  254. }