[INTRIN]
[reactos.git] / reactos / win32ss / base / scm / svchost / rpcsrv.c
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
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
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
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
83 RpcpAddInterface (
84 _In_ LPCWSTR 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", 10, endpointName, NULL);
102 if ((rpcStatus != RPC_S_OK) && (rpcStatus != RPC_S_DUPLICATE_ENDPOINT))
103 {
104 /* We couldn't create it, or it already existed... */
105 DbgPrint("RpcServerUseProtseqW failed! rpcstatus = %u\n", rpcStatus);
106 }
107 else
108 {
109 /* It worked, register an interface on this endpoint now*/
110 rpcStatus = RpcServerRegisterIf(IfSpec, 0, 0);
111 }
112
113 /* In both success and failure, free the name, and convert the status */
114 LocalFree(endpointName);
115 ntStatus = I_RpcMapWin32Status(rpcStatus);
116 }
117 else
118 {
119 /* No memory, bail out */
120 ntStatus = STATUS_NO_MEMORY;
121 }
122
123 /* Return back to the caller */
124 return ntStatus;
125 }
126
127 NTSTATUS
128 NTAPI
129 RpcpStartRpcServer (
130 _In_ LPCWSTR IfName,
131 _In_ RPC_IF_HANDLE IfSpec
132 )
133 {
134 NTSTATUS ntStatus;
135
136 /* Acquire the lock while we instantiate a new interface */
137 EnterCriticalSection(&RpcpCriticalSection);
138
139 /* Add this interface to the service */
140 ntStatus = RpcpAddInterface(IfName, IfSpec);
141 if (!ntStatus)
142 {
143 /* Increment the reference count to see if this was the first interface */
144 if (++RpcpNumInstances == 1)
145 {
146 /* It was, so put the server into listening mode now */
147 ntStatus = RpcServerListen(1, 12345, TRUE);
148 if (ntStatus == RPC_S_ALREADY_LISTENING) ntStatus = STATUS_SUCCESS;
149 }
150 }
151
152 /* Release the lock and return back the result to the caller */
153 LeaveCriticalSection(&RpcpCriticalSection);
154 return I_RpcMapWin32Status(ntStatus);
155 }
156