wineoss: Fix missing break statement.
[wine.git] / programs / rpcss / rpcss_main.c
blob2fef34d1171a812b5d8632ddbbecb18bc92b0874
1 /*
2 * Copyright 2001, Ove Kåven, TransGaming Technologies Inc.
3 * Copyright 2002 Greg Turner
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <limits.h>
23 #include <assert.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnt.h"
28 #include "winsvc.h"
29 #include "irot.h"
30 #include "epm.h"
31 #include "irpcss.h"
33 #include "wine/debug.h"
34 #include "wine/heap.h"
35 #include "wine/list.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 static WCHAR rpcssW[] = L"RpcSs";
40 static HANDLE exit_event;
41 static SERVICE_STATUS_HANDLE service_handle;
43 struct registered_class
45 struct list entry;
46 GUID clsid;
47 unsigned int cookie;
48 PMInterfacePointer object;
49 unsigned int single_use : 1;
52 static CRITICAL_SECTION registered_classes_cs = { NULL, -1, 0, 0, 0, 0 };
53 static struct list registered_classes = LIST_INIT(registered_classes);
55 HRESULT __cdecl irpcss_server_register(handle_t h, const GUID *clsid, unsigned int flags,
56 PMInterfacePointer object, unsigned int *cookie)
58 struct registered_class *entry;
59 static LONG next_cookie;
61 if (!(entry = heap_alloc_zero(sizeof(*entry))))
62 return E_OUTOFMEMORY;
64 entry->clsid = *clsid;
65 entry->single_use = !(flags & (REGCLS_MULTIPLEUSE | REGCLS_MULTI_SEPARATE));
66 if (!(entry->object = heap_alloc(FIELD_OFFSET(MInterfacePointer, abData[object->ulCntData]))))
68 heap_free(entry);
69 return E_OUTOFMEMORY;
71 entry->object->ulCntData = object->ulCntData;
72 memcpy(&entry->object->abData, object->abData, object->ulCntData);
73 *cookie = entry->cookie = InterlockedIncrement(&next_cookie);
75 EnterCriticalSection(&registered_classes_cs);
76 list_add_tail(&registered_classes, &entry->entry);
77 LeaveCriticalSection(&registered_classes_cs);
79 return S_OK;
82 static void scm_revoke_class(struct registered_class *_class)
84 list_remove(&_class->entry);
85 heap_free(_class->object);
86 heap_free(_class);
89 HRESULT __cdecl irpcss_server_revoke(handle_t h, unsigned int cookie)
91 struct registered_class *cur;
93 EnterCriticalSection(&registered_classes_cs);
95 LIST_FOR_EACH_ENTRY(cur, &registered_classes, struct registered_class, entry)
97 if (cur->cookie == cookie)
99 scm_revoke_class(cur);
100 break;
104 LeaveCriticalSection(&registered_classes_cs);
106 return S_OK;
109 HRESULT __cdecl irpcss_get_class_object(handle_t h, const GUID *clsid,
110 PMInterfacePointer *object)
112 struct registered_class *cur;
114 *object = NULL;
116 EnterCriticalSection(&registered_classes_cs);
118 LIST_FOR_EACH_ENTRY(cur, &registered_classes, struct registered_class, entry)
120 if (!memcmp(clsid, &cur->clsid, sizeof(*clsid)))
122 *object = MIDL_user_allocate(FIELD_OFFSET(MInterfacePointer, abData[cur->object->ulCntData]));
123 if (*object)
125 (*object)->ulCntData = cur->object->ulCntData;
126 memcpy((*object)->abData, cur->object->abData, cur->object->ulCntData);
129 if (cur->single_use)
130 scm_revoke_class(cur);
132 break;
136 LeaveCriticalSection(&registered_classes_cs);
138 return *object ? S_OK : E_NOINTERFACE;
141 HRESULT __cdecl irpcss_get_thread_seq_id(handle_t h, DWORD *id)
143 static LONG thread_seq_id;
144 *id = InterlockedIncrement(&thread_seq_id);
145 return S_OK;
148 static RPC_STATUS RPCSS_Initialize(void)
150 static unsigned short irot_protseq[] = IROT_PROTSEQ;
151 static unsigned short irot_endpoint[] = IROT_ENDPOINT;
152 static unsigned short epm_protseq[] = L"ncacn_np";
153 static unsigned short epm_endpoint[] = L"\\pipe\\epmapper";
154 static unsigned short epm_protseq_lrpc[] = L"ncalrpc";
155 static unsigned short epm_endpoint_lrpc[] = L"epmapper";
156 static unsigned short irpcss_protseq[] = IRPCSS_PROTSEQ;
157 static unsigned short irpcss_endpoint[] = IRPCSS_ENDPOINT;
158 static const struct protseq_map
160 unsigned short *protseq;
161 unsigned short *endpoint;
162 } protseqs[] =
164 { epm_protseq, epm_endpoint },
165 { epm_protseq_lrpc, epm_endpoint_lrpc },
166 { irot_protseq, irot_endpoint },
167 { irpcss_protseq, irpcss_endpoint },
169 RPC_IF_HANDLE ifspecs[] =
171 epm_v3_0_s_ifspec,
172 Irot_v0_2_s_ifspec,
173 Irpcss_v0_0_s_ifspec,
175 RPC_STATUS status;
176 int i, j;
178 WINE_TRACE("\n");
180 for (i = 0, j = 0; i < ARRAY_SIZE(ifspecs); ++i, j = i)
182 status = RpcServerRegisterIf(ifspecs[i], NULL, NULL);
183 if (status != RPC_S_OK)
184 goto fail;
187 for (i = 0; i < ARRAY_SIZE(protseqs); ++i)
189 status = RpcServerUseProtseqEpW(protseqs[i].protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
190 protseqs[i].endpoint, NULL);
191 if (status != RPC_S_OK)
192 goto fail;
195 status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
196 if (status != RPC_S_OK)
197 goto fail;
199 return RPC_S_OK;
201 fail:
202 for (i = 0; i < j; ++i)
203 RpcServerUnregisterIf(ifspecs[i], NULL, FALSE);
205 return status;
208 static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )
210 SERVICE_STATUS status;
212 status.dwServiceType = SERVICE_WIN32;
213 status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
214 status.dwWin32ExitCode = 0;
215 status.dwServiceSpecificExitCode = 0;
216 status.dwCheckPoint = 0;
217 status.dwWaitHint = 0;
219 switch (ctrl)
221 case SERVICE_CONTROL_STOP:
222 case SERVICE_CONTROL_SHUTDOWN:
223 TRACE( "shutting down\n" );
224 RpcMgmtStopServerListening( NULL );
225 RpcServerUnregisterIf( epm_v3_0_s_ifspec, NULL, TRUE );
226 RpcServerUnregisterIf( Irot_v0_2_s_ifspec, NULL, TRUE );
227 status.dwCurrentState = SERVICE_STOP_PENDING;
228 status.dwControlsAccepted = 0;
229 SetServiceStatus( service_handle, &status );
230 SetEvent( exit_event );
231 return NO_ERROR;
232 default:
233 FIXME( "got service ctrl %lx\n", ctrl );
234 status.dwCurrentState = SERVICE_RUNNING;
235 SetServiceStatus( service_handle, &status );
236 return NO_ERROR;
240 static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv )
242 SERVICE_STATUS status;
243 RPC_STATUS ret;
245 TRACE( "starting service\n" );
247 if ((ret = RPCSS_Initialize()))
249 WARN("Failed to initialize rpc interfaces, status %ld.\n", ret);
250 return;
253 exit_event = CreateEventW( NULL, TRUE, FALSE, NULL );
255 service_handle = RegisterServiceCtrlHandlerExW( rpcssW, service_handler, NULL );
256 if (!service_handle) return;
258 status.dwServiceType = SERVICE_WIN32;
259 status.dwCurrentState = SERVICE_RUNNING;
260 status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
261 status.dwWin32ExitCode = 0;
262 status.dwServiceSpecificExitCode = 0;
263 status.dwCheckPoint = 0;
264 status.dwWaitHint = 10000;
265 SetServiceStatus( service_handle, &status );
267 WaitForSingleObject( exit_event, INFINITE );
269 status.dwCurrentState = SERVICE_STOPPED;
270 status.dwControlsAccepted = 0;
271 SetServiceStatus( service_handle, &status );
272 TRACE( "service stopped\n" );
275 int __cdecl wmain( int argc, WCHAR *argv[] )
277 static const SERVICE_TABLE_ENTRYW service_table[] =
279 { rpcssW, ServiceMain },
280 { NULL, NULL }
283 StartServiceCtrlDispatcherW( service_table );
284 return 0;