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/list.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 static WCHAR rpcssW
[] = L
"RpcSs";
39 static HANDLE exit_event
;
40 static SERVICE_STATUS_HANDLE service_handle
;
42 struct registered_class
47 PMInterfacePointer object
;
48 unsigned int single_use
: 1;
51 static CRITICAL_SECTION registered_classes_cs
= { NULL
, -1, 0, 0, 0, 0 };
52 static struct list registered_classes
= LIST_INIT(registered_classes
);
54 HRESULT __cdecl
irpcss_server_register(handle_t h
, const GUID
*clsid
, unsigned int flags
,
55 PMInterfacePointer object
, unsigned int *cookie
)
57 struct registered_class
*entry
;
58 static LONG next_cookie
;
60 if (!(entry
= calloc(1, sizeof(*entry
))))
63 entry
->clsid
= *clsid
;
64 entry
->single_use
= !(flags
& (REGCLS_MULTIPLEUSE
| REGCLS_MULTI_SEPARATE
));
65 if (!(entry
->object
= malloc(FIELD_OFFSET(MInterfacePointer
, abData
[object
->ulCntData
]))))
70 entry
->object
->ulCntData
= object
->ulCntData
;
71 memcpy(&entry
->object
->abData
, object
->abData
, object
->ulCntData
);
72 *cookie
= entry
->cookie
= InterlockedIncrement(&next_cookie
);
74 EnterCriticalSection(®istered_classes_cs
);
75 list_add_tail(®istered_classes
, &entry
->entry
);
76 LeaveCriticalSection(®istered_classes_cs
);
81 static void scm_revoke_class(struct registered_class
*_class
)
83 list_remove(&_class
->entry
);
88 HRESULT __cdecl
irpcss_server_revoke(handle_t h
, unsigned int cookie
)
90 struct registered_class
*cur
;
92 EnterCriticalSection(®istered_classes_cs
);
94 LIST_FOR_EACH_ENTRY(cur
, ®istered_classes
, struct registered_class
, entry
)
96 if (cur
->cookie
== cookie
)
98 scm_revoke_class(cur
);
103 LeaveCriticalSection(®istered_classes_cs
);
108 HRESULT __cdecl
irpcss_get_class_object(handle_t h
, const GUID
*clsid
,
109 PMInterfacePointer
*object
)
111 struct registered_class
*cur
;
115 EnterCriticalSection(®istered_classes_cs
);
117 LIST_FOR_EACH_ENTRY(cur
, ®istered_classes
, struct registered_class
, entry
)
119 if (!memcmp(clsid
, &cur
->clsid
, sizeof(*clsid
)))
121 *object
= MIDL_user_allocate(FIELD_OFFSET(MInterfacePointer
, abData
[cur
->object
->ulCntData
]));
124 (*object
)->ulCntData
= cur
->object
->ulCntData
;
125 memcpy((*object
)->abData
, cur
->object
->abData
, cur
->object
->ulCntData
);
129 scm_revoke_class(cur
);
135 LeaveCriticalSection(®istered_classes_cs
);
137 return *object
? S_OK
: E_NOINTERFACE
;
140 HRESULT __cdecl
irpcss_get_thread_seq_id(handle_t h
, DWORD
*id
)
142 static LONG thread_seq_id
;
143 *id
= InterlockedIncrement(&thread_seq_id
);
147 static RPC_STATUS
RPCSS_Initialize(void)
149 static unsigned short irot_protseq
[] = IROT_PROTSEQ
;
150 static unsigned short irot_endpoint
[] = IROT_ENDPOINT
;
151 static unsigned short epm_protseq
[] = L
"ncacn_np";
152 static unsigned short epm_endpoint
[] = L
"\\pipe\\epmapper";
153 static unsigned short epm_protseq_lrpc
[] = L
"ncalrpc";
154 static unsigned short epm_endpoint_lrpc
[] = L
"epmapper";
155 static unsigned short irpcss_protseq
[] = IRPCSS_PROTSEQ
;
156 static unsigned short irpcss_endpoint
[] = IRPCSS_ENDPOINT
;
157 static const struct protseq_map
159 unsigned short *protseq
;
160 unsigned short *endpoint
;
163 { epm_protseq
, epm_endpoint
},
164 { epm_protseq_lrpc
, epm_endpoint_lrpc
},
165 { irot_protseq
, irot_endpoint
},
166 { irpcss_protseq
, irpcss_endpoint
},
168 RPC_IF_HANDLE ifspecs
[] =
172 Irpcss_v0_0_s_ifspec
,
179 for (i
= 0, j
= 0; i
< ARRAY_SIZE(ifspecs
); ++i
, j
= i
)
181 status
= RpcServerRegisterIf(ifspecs
[i
], NULL
, NULL
);
182 if (status
!= RPC_S_OK
)
186 for (i
= 0; i
< ARRAY_SIZE(protseqs
); ++i
)
188 status
= RpcServerUseProtseqEpW(protseqs
[i
].protseq
, RPC_C_PROTSEQ_MAX_REQS_DEFAULT
,
189 protseqs
[i
].endpoint
, NULL
);
190 if (status
!= RPC_S_OK
)
194 status
= RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT
, TRUE
);
195 if (status
!= RPC_S_OK
)
201 for (i
= 0; i
< j
; ++i
)
202 RpcServerUnregisterIf(ifspecs
[i
], NULL
, FALSE
);
207 static DWORD WINAPI
service_handler( DWORD ctrl
, DWORD event_type
, LPVOID event_data
, LPVOID context
)
209 SERVICE_STATUS status
;
211 status
.dwServiceType
= SERVICE_WIN32
;
212 status
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
;
213 status
.dwWin32ExitCode
= 0;
214 status
.dwServiceSpecificExitCode
= 0;
215 status
.dwCheckPoint
= 0;
216 status
.dwWaitHint
= 0;
220 case SERVICE_CONTROL_STOP
:
221 case SERVICE_CONTROL_SHUTDOWN
:
222 TRACE( "shutting down\n" );
223 RpcMgmtStopServerListening( NULL
);
224 RpcServerUnregisterIf( epm_v3_0_s_ifspec
, NULL
, TRUE
);
225 RpcServerUnregisterIf( Irot_v0_2_s_ifspec
, NULL
, TRUE
);
226 status
.dwCurrentState
= SERVICE_STOP_PENDING
;
227 status
.dwControlsAccepted
= 0;
228 SetServiceStatus( service_handle
, &status
);
229 SetEvent( exit_event
);
232 FIXME( "got service ctrl %lx\n", ctrl
);
233 status
.dwCurrentState
= SERVICE_RUNNING
;
234 SetServiceStatus( service_handle
, &status
);
239 static void WINAPI
ServiceMain( DWORD argc
, LPWSTR
*argv
)
241 SERVICE_STATUS status
;
244 TRACE( "starting service\n" );
246 if ((ret
= RPCSS_Initialize()))
248 WARN("Failed to initialize rpc interfaces, status %ld.\n", ret
);
252 exit_event
= CreateEventW( NULL
, TRUE
, FALSE
, NULL
);
254 service_handle
= RegisterServiceCtrlHandlerExW( rpcssW
, service_handler
, NULL
);
255 if (!service_handle
) return;
257 status
.dwServiceType
= SERVICE_WIN32
;
258 status
.dwCurrentState
= SERVICE_RUNNING
;
259 status
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
;
260 status
.dwWin32ExitCode
= 0;
261 status
.dwServiceSpecificExitCode
= 0;
262 status
.dwCheckPoint
= 0;
263 status
.dwWaitHint
= 10000;
264 SetServiceStatus( service_handle
, &status
);
266 WaitForSingleObject( exit_event
, INFINITE
);
268 status
.dwCurrentState
= SERVICE_STOPPED
;
269 status
.dwControlsAccepted
= 0;
270 SetServiceStatus( service_handle
, &status
);
271 TRACE( "service stopped\n" );
274 int __cdecl
wmain( int argc
, WCHAR
*argv
[] )
276 static const SERVICE_TABLE_ENTRYW service_table
[] =
278 { rpcssW
, ServiceMain
},
282 StartServiceCtrlDispatcherW( service_table
);