1 /*
2 * PROJECT: ReactOS Service Host
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: base/services/svchost/rpcsrv.c
5 * PURPOSE: RPC Service Support
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "svchost.h"
12
13 /* GLOBALS *******************************************************************/
14
15 LONG RpcpNumInstances;
16 CRITICAL_SECTION RpcpCriticalSection;
17
18 /* FUNCTIONS *****************************************************************/
19
20 NTSTATUS
21 NTAPI
RpcpInitRpcServer(VOID)22 RpcpInitRpcServer (
23 VOID
24 )
25 {
26 /* Clear the reference count and initialize the critical section */
27 RpcpNumInstances = 0;
28 return RtlInitializeCriticalSection((PVOID)&RpcpCriticalSection);
29 }
30
31 NTSTATUS
32 NTAPI
RpcpStopRpcServer(_In_ RPC_IF_HANDLE IfSpec)33 RpcpStopRpcServer (
34 _In_ RPC_IF_HANDLE IfSpec
35 )
36 {
37 RPC_STATUS rpcStatus;
38
39 /* Unregister the interface */
40 rpcStatus = RpcServerUnregisterIf(IfSpec, NULL, TRUE);
41
42 /* Acquire the lock while we dereference the RPC services */
43 EnterCriticalSection(&RpcpCriticalSection);
44 if (--RpcpNumInstances == 0)
45 {
46 /* All RPC services stopped, rundown the server */
47 RpcMgmtStopServerListening(NULL);
48 RpcMgmtWaitServerListen();
49 }
50
51 /* Release the lock and return the unregister result */
52 LeaveCriticalSection(&RpcpCriticalSection);
53 return I_RpcMapWin32Status(rpcStatus);
54 }
55
56 NTSTATUS
57 NTAPI
RpcpStopRpcServerEx(_In_ RPC_IF_HANDLE IfSpec)58 RpcpStopRpcServerEx (
59 _In_ RPC_IF_HANDLE IfSpec
60 )
61 {
62 RPC_STATUS rpcStatus;
63
64 /* Unregister the interface */
65 rpcStatus = RpcServerUnregisterIfEx(IfSpec, NULL, TRUE);
66
67 /* Acquire the lock while we dereference the RPC services */
68 EnterCriticalSection(&RpcpCriticalSection);
69 if (--RpcpNumInstances == 0)
70 {
71 /* All RPC services stopped, rundown the server */
72 RpcMgmtStopServerListening(NULL);
73 RpcMgmtWaitServerListen();
74 }
75
76 /* Release the lock and return the unregister result */
77 LeaveCriticalSection(&RpcpCriticalSection);
78 return I_RpcMapWin32Status(rpcStatus);
79 }
80
81 NTSTATUS
82 NTAPI
RpcpAddInterface(_In_ PCWSTR IfName,_In_ RPC_IF_HANDLE IfSpec)83 RpcpAddInterface (
84 _In_ PCWSTR IfName,
85 _In_ RPC_IF_HANDLE IfSpec
86 )
87 {
88 PWCHAR endpointName;
89 NTSTATUS ntStatus;
90 RPC_STATUS rpcStatus;
91
92 /* Allocate space for the interface name and the \\PIPE\\ prefix */
93 endpointName = LocalAlloc(0, sizeof(WCHAR) * wcslen(IfName) + 16);
94 if (endpointName)
95 {
96 /* Copy the prefix, and then the interface name */
97 wcscpy(endpointName, L"\\PIPE\\");
98 wcscat(endpointName, IfName);
99
100 /* Create a named pipe endpoint with this name */
101 rpcStatus = RpcServerUseProtseqEpW(L"ncacn_np",
102 RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
103 endpointName, NULL);
104 if ((rpcStatus != RPC_S_OK) && (rpcStatus != RPC_S_DUPLICATE_ENDPOINT))
105 {
106 /* We couldn't create it, or it already existed... */
107 DbgPrint("RpcServerUseProtseqW failed! rpcstatus = %u\n", rpcStatus);
108 }
109 else
110 {
111 /* It worked, register an interface on this endpoint now */
112 rpcStatus = RpcServerRegisterIf(IfSpec, 0, 0);
113 }
114
115 /* In both success and failure, free the name, and convert the status */
116 LocalFree(endpointName);
117 ntStatus = I_RpcMapWin32Status(rpcStatus);
118 }
119 else
120 {
121 /* No memory, bail out */
122 ntStatus = STATUS_NO_MEMORY;
123 }
124
125 /* Return back to the caller */
126 return ntStatus;
127 }
128
129 NTSTATUS
130 NTAPI
RpcpStartRpcServer(_In_ PCWSTR IfName,_In_ RPC_IF_HANDLE IfSpec)131 RpcpStartRpcServer (
132 _In_ PCWSTR IfName,
133 _In_ RPC_IF_HANDLE IfSpec
134 )
135 {
136 NTSTATUS ntStatus;
137
138 /* Acquire the lock while we instantiate a new interface */
139 EnterCriticalSection(&RpcpCriticalSection);
140
141 /* Add this interface to the service */
142 ntStatus = RpcpAddInterface(IfName, IfSpec);
143 if (!ntStatus)
144 {
145 /* Increment the reference count to see if this was the first interface */
146 if (++RpcpNumInstances == 1)
147 {
148 /* It was, so put the server into listening mode now */
149 ntStatus = RpcServerListen(1, 12345, TRUE);
150 if (ntStatus == RPC_S_ALREADY_LISTENING) ntStatus = STATUS_SUCCESS;
151 }
152 }
153
154 /* Release the lock and return back the result to the caller */
155 LeaveCriticalSection(&RpcpCriticalSection);
156 return I_RpcMapWin32Status(ntStatus);
157 }
158
159