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
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
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
))))
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
]))))
71 entry
->object
->ulCntData
= object
->ulCntData
;
72 memcpy(&entry
->object
->abData
, object
->abData
, object
->ulCntData
);
73 *cookie
= entry
->cookie
= InterlockedIncrement(&next_cookie
);
75 EnterCriticalSection(®istered_classes_cs
);
76 list_add_tail(®istered_classes
, &entry
->entry
);
77 LeaveCriticalSection(®istered_classes_cs
);
82 static void scm_revoke_class(struct registered_class
*_class
)
84 list_remove(&_class
->entry
);
85 heap_free(_class
->object
);
89 HRESULT __cdecl
irpcss_server_revoke(handle_t h
, unsigned int cookie
)
91 struct registered_class
*cur
;
93 EnterCriticalSection(®istered_classes_cs
);
95 LIST_FOR_EACH_ENTRY(cur
, ®istered_classes
, struct registered_class
, entry
)
97 if (cur
->cookie
== cookie
)
99 scm_revoke_class(cur
);
104 LeaveCriticalSection(®istered_classes_cs
);
109 HRESULT __cdecl
irpcss_get_class_object(handle_t h
, const GUID
*clsid
,
110 PMInterfacePointer
*object
)
112 struct registered_class
*cur
;
116 EnterCriticalSection(®istered_classes_cs
);
118 LIST_FOR_EACH_ENTRY(cur
, ®istered_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
]));
125 (*object
)->ulCntData
= cur
->object
->ulCntData
;
126 memcpy((*object
)->abData
, cur
->object
->abData
, cur
->object
->ulCntData
);
130 scm_revoke_class(cur
);
136 LeaveCriticalSection(®istered_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
);
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
;
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
[] =
173 Irpcss_v0_0_s_ifspec
,
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
)
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
)
195 status
= RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT
, TRUE
);
196 if (status
!= RPC_S_OK
)
202 for (i
= 0; i
< j
; ++i
)
203 RpcServerUnregisterIf(ifspecs
[i
], NULL
, FALSE
);
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;
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
);
233 FIXME( "got service ctrl %lx\n", ctrl
);
234 status
.dwCurrentState
= SERVICE_RUNNING
;
235 SetServiceStatus( service_handle
, &status
);
240 static void WINAPI
ServiceMain( DWORD argc
, LPWSTR
*argv
)
242 SERVICE_STATUS status
;
245 TRACE( "starting service\n" );
247 if ((ret
= RPCSS_Initialize()))
249 WARN("Failed to initialize rpc interfaces, status %ld.\n", ret
);
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
},
283 StartServiceCtrlDispatcherW( service_table
);