xref: /reactos/base/services/svchost/rpcsrv.c (revision 84344399)
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_ 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
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