Reimplement several RpcServer.* methods in rpc_server.c.
[wine/testsucceed.git] / dlls / rpcrt4 / rpc_server.c
blobaf7c80bc77940f650dde81c40e86f84beab495be
1 /*
2 * RPC server API
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * TODO:
21 * - a whole lot
24 #include <stdio.h>
25 #include <string.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winreg.h"
32 #include "rpc.h"
34 #include "wine/debug.h"
36 #include "rpc_server.h"
37 #include "rpc_defs.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41 static RpcServerProtseq* protseqs;
42 static RpcServerInterface* ifs;
44 static CRITICAL_SECTION server_cs = CRITICAL_SECTION_INIT("RpcServer");
45 static BOOL std_listen;
46 static LONG listen_count = -1;
47 static HANDLE mgr_event, server_thread;
49 static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
51 UUID* MgrType = NULL;
52 RpcServerInterface* cif = NULL;
53 RPC_STATUS status;
55 /* FIXME: object -> MgrType */
56 EnterCriticalSection(&server_cs);
57 cif = ifs;
58 while (cif) {
59 if (UuidEqual(if_id, &cif->If->InterfaceId.SyntaxGUID, &status) &&
60 UuidEqual(MgrType, &cif->MgrTypeUuid, &status) &&
61 (std_listen || (cif->Flags & RPC_IF_AUTOLISTEN))) break;
62 cif = cif->Next;
64 LeaveCriticalSection(&server_cs);
65 return cif;
68 static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
70 RpcBinding* bind = (RpcBinding*)the_arg;
71 RpcPktHdr hdr;
72 DWORD dwRead;
73 RPC_MESSAGE msg;
74 RpcServerInterface* sif;
75 RPC_DISPATCH_FUNCTION func;
77 memset(&msg, 0, sizeof(msg));
78 msg.Handle = (RPC_BINDING_HANDLE)bind;
80 for (;;) {
81 /* read packet header */
82 #ifdef OVERLAPPED_WORKS
83 if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) {
84 DWORD err = GetLastError();
85 if (err != ERROR_IO_PENDING) {
86 TRACE("connection lost, error=%08lx\n", err);
87 break;
89 if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break;
91 #else
92 if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
93 TRACE("connection lost, error=%08lx\n", GetLastError());
94 break;
96 #endif
97 if (dwRead != sizeof(hdr)) {
98 TRACE("protocol error\n");
99 break;
102 /* read packet body */
103 msg.BufferLength = hdr.len;
104 msg.Buffer = HeapAlloc(GetProcessHeap(), 0, msg.BufferLength);
105 #ifdef OVERLAPPED_WORKS
106 if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, &bind->ovl)) {
107 DWORD err = GetLastError();
108 if (err != ERROR_IO_PENDING) {
109 TRACE("connection lost, error=%08lx\n", err);
110 break;
112 if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break;
114 #else
115 if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, NULL)) {
116 TRACE("connection lost, error=%08lx\n", GetLastError());
117 break;
119 #endif
120 if (dwRead != hdr.len) {
121 TRACE("protocol error\n");
122 break;
125 sif = RPCRT4_find_interface(&hdr.object, &hdr.if_id);
126 if (sif) {
127 msg.RpcInterfaceInformation = sif->If;
128 /* associate object with binding (this is a bit of a hack...
129 * a new binding should probably be created for each object) */
130 RPCRT4_SetBindingObject(bind, &hdr.object);
131 /* process packet*/
132 switch (hdr.ptype) {
133 case PKT_REQUEST:
134 /* find dispatch function */
135 msg.ProcNum = hdr.opnum;
136 if (sif->Flags & RPC_IF_OLE) {
137 /* native ole32 always gives us a dispatch table with a single entry
138 * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
139 func = *sif->If->DispatchTable->DispatchTable;
140 } else {
141 if (msg.ProcNum >= sif->If->DispatchTable->DispatchTableCount) {
142 ERR("invalid procnum\n");
143 func = NULL;
145 func = sif->If->DispatchTable->DispatchTable[msg.ProcNum];
148 /* dispatch */
149 if (func) func(&msg);
151 /* prepare response packet */
152 hdr.ptype = PKT_RESPONSE;
153 break;
154 default:
155 ERR("unknown packet type\n");
156 goto no_reply;
159 /* write reply packet */
160 hdr.len = msg.BufferLength;
161 WriteFile(bind->conn, &hdr, sizeof(hdr), NULL, NULL);
162 WriteFile(bind->conn, msg.Buffer, msg.BufferLength, NULL, NULL);
164 no_reply:
165 /* un-associate object */
166 RPCRT4_SetBindingObject(bind, NULL);
167 msg.RpcInterfaceInformation = NULL;
169 else {
170 ERR("got RPC packet to unregistered interface %s\n", debugstr_guid(&hdr.if_id));
173 /* clean up */
174 HeapFree(GetProcessHeap(), 0, msg.Buffer);
175 msg.Buffer = NULL;
177 if (msg.Buffer) HeapFree(GetProcessHeap(), 0, msg.Buffer);
178 RPCRT4_DestroyBinding(bind);
179 return 0;
182 static void RPCRT4_new_client(RpcBinding* bind)
184 bind->thread = CreateThread(NULL, 0, RPCRT4_io_thread, bind, 0, NULL);
187 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
189 HANDLE m_event = mgr_event, b_handle;
190 HANDLE *objs = NULL;
191 DWORD count, res;
192 RpcServerProtseq* cps;
193 RpcBinding* bind;
194 RpcBinding* cbind;
196 for (;;) {
197 EnterCriticalSection(&server_cs);
198 /* open and count bindings */
199 count = 1;
200 cps = protseqs;
201 while (cps) {
202 bind = cps->bind;
203 while (bind) {
204 RPCRT4_OpenBinding(bind);
205 if (bind->ovl.hEvent) count++;
206 bind = bind->Next;
208 cps = cps->Next;
210 /* make array of bindings */
211 objs = HeapReAlloc(GetProcessHeap(), 0, objs, count*sizeof(HANDLE));
212 objs[0] = m_event;
213 count = 1;
214 cps = protseqs;
215 while (cps) {
216 bind = cps->bind;
217 while (bind) {
218 if (bind->ovl.hEvent) objs[count++] = bind->ovl.hEvent;
219 bind = bind->Next;
221 cps = cps->Next;
223 LeaveCriticalSection(&server_cs);
225 /* start waiting */
226 res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
227 if (res == WAIT_OBJECT_0) {
228 if (listen_count == -1) break;
230 else if (res == WAIT_FAILED) {
231 ERR("wait failed\n");
233 else {
234 b_handle = objs[res - WAIT_OBJECT_0];
235 /* find which binding got a RPC */
236 EnterCriticalSection(&server_cs);
237 bind = NULL;
238 cps = protseqs;
239 while (cps) {
240 bind = cps->bind;
241 while (bind) {
242 if (bind->ovl.hEvent == b_handle) break;
243 bind = bind->Next;
245 if (bind) break;
246 cps = cps->Next;
248 cbind = NULL;
249 if (bind) RPCRT4_SpawnBinding(&cbind, bind);
250 LeaveCriticalSection(&server_cs);
251 if (!bind) {
252 ERR("failed to locate binding for handle %d\n", b_handle);
254 if (cbind) RPCRT4_new_client(cbind);
257 HeapFree(GetProcessHeap(), 0, objs);
258 EnterCriticalSection(&server_cs);
259 /* close bindings */
260 cps = protseqs;
261 while (cps) {
262 bind = cps->bind;
263 while (bind) {
264 RPCRT4_CloseBinding(bind);
265 bind = bind->Next;
267 cps = cps->Next;
269 LeaveCriticalSection(&server_cs);
270 return 0;
273 static void RPCRT4_start_listen(void)
275 if (!InterlockedIncrement(&listen_count)) {
276 mgr_event = CreateEventA(NULL, FALSE, FALSE, NULL);
277 server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);
279 else SetEvent(mgr_event);
282 /* not used (WTF?) ---------------------------
284 static void RPCRT4_stop_listen(void)
286 HANDLE m_event = mgr_event;
287 if (InterlockedDecrement(&listen_count) < 0)
288 SetEvent(m_event);
291 --------------------- */
293 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)
295 RPCRT4_CreateBindingA(&ps->bind, TRUE, ps->Protseq);
296 RPCRT4_CompleteBindingA(ps->bind, NULL, ps->Endpoint, NULL);
298 EnterCriticalSection(&server_cs);
299 ps->Next = protseqs;
300 protseqs = ps;
301 LeaveCriticalSection(&server_cs);
303 if (listen_count >= 0) SetEvent(mgr_event);
305 return RPC_S_OK;
308 /***********************************************************************
309 * RpcServerInqBindings (RPCRT4.@)
311 RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
313 RPC_STATUS status;
314 DWORD count;
315 RpcServerProtseq* ps;
316 RpcBinding* bind;
318 EnterCriticalSection(&server_cs);
319 /* count bindings */
320 count = 0;
321 ps = protseqs;
322 while (ps) {
323 bind = ps->bind;
324 while (bind) {
325 count++;
326 bind = bind->Next;
328 ps = ps->Next;
330 if (count) {
331 /* export bindings */
332 *BindingVector = HeapAlloc(GetProcessHeap(), 0,
333 sizeof(RPC_BINDING_VECTOR) +
334 sizeof(RPC_BINDING_HANDLE)*(count-1));
335 (*BindingVector)->Count = count;
336 count = 0;
337 ps = protseqs;
338 while (ps) {
339 bind = ps->bind;
340 while (bind) {
341 RPCRT4_ExportBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
342 bind);
343 count++;
344 bind = bind->Next;
346 ps = ps->Next;
348 status = RPC_S_OK;
349 } else {
350 *BindingVector = NULL;
351 status = RPC_S_NO_BINDINGS;
353 LeaveCriticalSection(&server_cs);
354 return status;
357 /***********************************************************************
358 * RpcServerUseProtseqEpA (RPCRT4.@)
360 RPC_STATUS WINAPI RpcServerUseProtseqEpA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor )
362 RPC_POLICY policy;
364 TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor );
366 /* This should provide the default behaviour */
367 policy.Length = sizeof( policy );
368 policy.EndpointFlags = 0;
369 policy.NICFlags = 0;
371 return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
374 /***********************************************************************
375 * RpcServerUseProtseqEpW (RPCRT4.@)
377 RPC_STATUS WINAPI RpcServerUseProtseqEpW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor )
379 RPC_POLICY policy;
381 TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor );
383 /* This should provide the default behaviour */
384 policy.Length = sizeof( policy );
385 policy.EndpointFlags = 0;
386 policy.NICFlags = 0;
388 return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
391 /***********************************************************************
392 * RpcServerUseProtseqEpExA (RPCRT4.@)
394 RPC_STATUS WINAPI RpcServerUseProtseqEpExA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor,
395 PRPC_POLICY lpPolicy )
397 RpcServerProtseq* ps;
399 TRACE("(%s,%u,%s,%p,{%u,%lu,%lu}): stub\n", debugstr_a( Protseq ), MaxCalls,
400 debugstr_a( Endpoint ), SecurityDescriptor,
401 lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
403 ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
404 ps->MaxCalls = MaxCalls;
405 ps->Protseq = RPCRT4_strdupA(Protseq);
406 ps->Endpoint = RPCRT4_strdupA(Endpoint);
408 return RPCRT4_use_protseq(ps);
411 /***********************************************************************
412 * RpcServerUseProtseqEpExW (RPCRT4.@)
414 RPC_STATUS WINAPI RpcServerUseProtseqEpExW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor,
415 PRPC_POLICY lpPolicy )
417 RpcServerProtseq* ps;
419 TRACE("(%s,%u,%s,%p,{%u,%lu,%lu}): stub\n", debugstr_w( Protseq ), MaxCalls,
420 debugstr_w( Endpoint ), SecurityDescriptor,
421 lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
423 ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
424 ps->MaxCalls = MaxCalls;
425 /* FIXME: Did Ove have these next two as RPCRT4_strdupW for a reason? */
426 ps->Protseq = RPCRT4_strdupWtoA(Protseq);
427 ps->Endpoint = RPCRT4_strdupWtoA(Endpoint);
429 return RPCRT4_use_protseq(ps);
432 /***********************************************************************
433 * RpcServerRegisterIf (RPCRT4.@)
435 RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )
437 TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv);
438 return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );
441 /***********************************************************************
442 * RpcServerRegisterIfEx (RPCRT4.@)
444 RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
445 UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn )
447 TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn);
448 return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );
451 /***********************************************************************
452 * RpcServerRegisterIf2 (RPCRT4.@)
454 RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
455 UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
457 PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
458 RpcServerInterface* sif;
459 int i;
461 TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls,
462 MaxRpcSize, IfCallbackFn);
463 TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
464 If->InterfaceId.SyntaxVersion.MajorVersion,
465 If->InterfaceId.SyntaxVersion.MinorVersion);
466 TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
467 If->InterfaceId.SyntaxVersion.MajorVersion,
468 If->InterfaceId.SyntaxVersion.MinorVersion);
469 TRACE(" dispatch table: %p\n", If->DispatchTable);
470 if (If->DispatchTable) {
471 TRACE(" dispatch table count: %d\n", If->DispatchTable->DispatchTableCount);
472 for (i=0; i<If->DispatchTable->DispatchTableCount; i++) {
473 TRACE(" entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]);
475 TRACE(" reserved: %ld\n", If->DispatchTable->Reserved);
477 TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount);
478 TRACE(" default manager epv: %p\n", If->DefaultManagerEpv);
479 TRACE(" interpreter info: %p\n", If->InterpreterInfo);
480 TRACE(" flags: %08x\n", If->Flags);
482 sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));
483 sif->If = If;
484 if (MgrTypeUuid)
485 memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID));
486 else
487 memset(&sif->MgrTypeUuid, 0, sizeof(UUID));
488 sif->MgrEpv = MgrEpv;
489 sif->Flags = Flags;
490 sif->MaxCalls = MaxCalls;
491 sif->MaxRpcSize = MaxRpcSize;
492 sif->IfCallbackFn = IfCallbackFn;
494 EnterCriticalSection(&server_cs);
495 sif->Next = ifs;
496 ifs = sif;
497 LeaveCriticalSection(&server_cs);
499 if (sif->Flags & RPC_IF_AUTOLISTEN) {
500 /* well, start listening, I think... */
501 RPCRT4_start_listen();
504 return RPC_S_OK;
507 /***********************************************************************
508 * RpcServerRegisterAuthInfoA (RPCRT4.@)
510 RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
511 LPVOID Arg )
513 FIXME( "(%s,%lu,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );
515 return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
518 /***********************************************************************
519 * RpcServerRegisterAuthInfoW (RPCRT4.@)
521 RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( LPWSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
522 LPVOID Arg )
524 FIXME( "(%s,%lu,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg );
526 return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
529 /***********************************************************************
530 * RpcServerListen (RPCRT4.@)
532 RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
534 TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait);
536 if (std_listen)
537 return RPC_S_ALREADY_LISTENING;
539 if (!protseqs)
540 return RPC_S_NO_PROTSEQS_REGISTERED;
542 std_listen = TRUE;
543 RPCRT4_start_listen();
545 if (DontWait) return RPC_S_OK;
547 /* RpcMgmtWaitServerListen(); */
548 FIXME("can't wait yet\n");
549 return RPC_S_OK;
552 /***********************************************************************
553 * I_RpcServerStartListening (RPCRT4.@)
555 RPC_STATUS WINAPI I_RpcServerStartListening( void* hWnd )
557 FIXME( "(%p): stub\n", hWnd );
559 return RPC_S_OK;
562 /***********************************************************************
563 * I_RpcServerStopListening (RPCRT4.@)
565 RPC_STATUS WINAPI I_RpcServerStopListening( void )
567 FIXME( "(): stub\n" );
569 return RPC_S_OK;
572 /***********************************************************************
573 * I_RpcWindowProc (RPCRT4.@)
575 UINT WINAPI I_RpcWindowProc( void* hWnd, UINT Message, UINT wParam, ULONG lParam )
577 FIXME( "(%p,%08x,%08x,%08lx): stub\n", hWnd, Message, wParam, lParam );
579 return 0;