Keep track of per-column information inside the listview.
[wine] / dlls / rpcrt4 / rpc_server.c
1 /*
2  * RPC server API
3  *
4  * Copyright 2001 Ove Kåven, TransGaming Technologies
5  *
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.
10  *
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.
15  *
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
19  *
20  * TODO:
21  *  - a whole lot
22  */
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winreg.h"
31
32 #include "rpc.h"
33
34 #include "wine/debug.h"
35
36 #include "rpc_server.h"
37 #include "rpc_defs.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40
41 static RpcServerProtseq* protseqs;
42 static RpcServerInterface* ifs;
43
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;
48
49 static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
50 {
51   UUID* MgrType = NULL;
52   RpcServerInterface* cif = NULL;
53   RPC_STATUS status;
54
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;
63   }
64   LeaveCriticalSection(&server_cs);
65   return cif;
66 }
67
68 static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
69 {
70   RpcBinding* bind = (RpcBinding*)the_arg;
71   RpcPktHdr hdr;
72   DWORD dwRead;
73   RPC_MESSAGE msg;
74   RpcServerInterface* sif;
75   RPC_DISPATCH_FUNCTION func;
76
77   memset(&msg, 0, sizeof(msg));
78   msg.Handle = (RPC_BINDING_HANDLE)bind;
79
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;
88       }
89       if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break;
90     }
91 #else
92     if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
93       TRACE("connection lost, error=%08lx\n", GetLastError());
94       break;
95     }
96 #endif
97     if (dwRead != sizeof(hdr)) {
98       TRACE("protocol error\n");
99       break;
100     }
101
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;
111       }
112       if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break;
113     }
114 #else
115     if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, NULL)) {
116       TRACE("connection lost, error=%08lx\n", GetLastError());
117       break;
118     }
119 #endif
120     if (dwRead != hdr.len) {
121       TRACE("protocol error\n");
122       break;
123     }
124
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;
144          }
145          func = sif->If->DispatchTable->DispatchTable[msg.ProcNum];
146        }
147
148        /* dispatch */
149        if (func) func(&msg);
150
151        /* prepare response packet */
152        hdr.ptype = PKT_RESPONSE;
153        break;
154       default:
155        ERR("unknown packet type\n");
156        goto no_reply;
157       }
158
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);
163
164     no_reply:
165       /* un-associate object */
166       RPCRT4_SetBindingObject(bind, NULL);
167       msg.RpcInterfaceInformation = NULL;
168     }
169     else {
170       ERR("got RPC packet to unregistered interface %s\n", debugstr_guid(&hdr.if_id));
171     }
172
173     /* clean up */
174     HeapFree(GetProcessHeap(), 0, msg.Buffer);
175     msg.Buffer = NULL;
176   }
177   if (msg.Buffer) HeapFree(GetProcessHeap(), 0, msg.Buffer);
178   RPCRT4_DestroyBinding(bind);
179   return 0;
180 }
181
182 static void RPCRT4_new_client(RpcBinding* bind)
183 {
184   bind->thread = CreateThread(NULL, 0, RPCRT4_io_thread, bind, 0, NULL);
185 }
186
187 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
188 {
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;
195
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;
207       }
208       cps = cps->Next;
209     }
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;
220       }
221       cps = cps->Next;
222     }
223     LeaveCriticalSection(&server_cs);
224
225     /* start waiting */
226     res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
227     if (res == WAIT_OBJECT_0) {
228       if (listen_count == -1) break;
229     }
230     else if (res == WAIT_FAILED) {
231       ERR("wait failed\n");
232     }
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;
244         }
245         if (bind) break;
246         cps = cps->Next;
247       }
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 %p\n", b_handle);
253       }
254       if (cbind) RPCRT4_new_client(cbind);
255     }
256   }
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;
266     }
267     cps = cps->Next;
268   }
269   LeaveCriticalSection(&server_cs);
270   return 0;
271 }
272
273 static void RPCRT4_start_listen(void)
274 {
275   TRACE("\n");
276   if (!InterlockedIncrement(&listen_count)) {
277     mgr_event = CreateEventA(NULL, FALSE, FALSE, NULL);
278     server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);
279   }
280   else SetEvent(mgr_event);
281 }
282
283 /* not used (WTF?) ---------------------------
284
285 static void RPCRT4_stop_listen(void)
286 {
287   HANDLE m_event = mgr_event;
288   if (InterlockedDecrement(&listen_count) < 0)
289     SetEvent(m_event);
290 }
291
292 --------------------- */
293
294 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)
295 {
296   RPCRT4_CreateBindingA(&ps->bind, TRUE, ps->Protseq);
297   RPCRT4_CompleteBindingA(ps->bind, NULL, ps->Endpoint, NULL);
298
299   EnterCriticalSection(&server_cs);
300   ps->Next = protseqs;
301   protseqs = ps;
302   LeaveCriticalSection(&server_cs);
303
304   if (listen_count >= 0) SetEvent(mgr_event);
305
306   return RPC_S_OK;
307 }
308
309 /***********************************************************************
310  *             RpcServerInqBindings (RPCRT4.@)
311  */
312 RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
313 {
314   RPC_STATUS status;
315   DWORD count;
316   RpcServerProtseq* ps;
317   RpcBinding* bind;
318
319   if (BindingVector)
320     TRACE("(*BindingVector == ^%p)\n", *BindingVector);
321   else
322     ERR("(BindingVector == ^null!!?)\n");
323
324   EnterCriticalSection(&server_cs);
325   /* count bindings */
326   count = 0;
327   ps = protseqs;
328   while (ps) {
329     bind = ps->bind;
330     while (bind) {
331       count++;
332       bind = bind->Next;
333     }
334     ps = ps->Next;
335   }
336   if (count) {
337     /* export bindings */
338     *BindingVector = HeapAlloc(GetProcessHeap(), 0,
339                               sizeof(RPC_BINDING_VECTOR) +
340                               sizeof(RPC_BINDING_HANDLE)*(count-1));
341     (*BindingVector)->Count = count;
342     count = 0;
343     ps = protseqs;
344     while (ps) {
345       bind = ps->bind;
346       while (bind) {
347        RPCRT4_ExportBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
348                             bind);
349        count++;
350        bind = bind->Next;
351       }
352       ps = ps->Next;
353     }
354     status = RPC_S_OK;
355   } else {
356     *BindingVector = NULL;
357     status = RPC_S_NO_BINDINGS;
358   }
359   LeaveCriticalSection(&server_cs);
360   return status;
361 }
362
363 /***********************************************************************
364  *             RpcServerUseProtseqEpA (RPCRT4.@)
365  */
366 RPC_STATUS WINAPI RpcServerUseProtseqEpA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor )
367 {
368   RPC_POLICY policy;
369   
370   TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor );
371   
372   /* This should provide the default behaviour */
373   policy.Length        = sizeof( policy );
374   policy.EndpointFlags = 0;
375   policy.NICFlags      = 0;
376   
377   return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
378 }
379
380 /***********************************************************************
381  *             RpcServerUseProtseqEpW (RPCRT4.@)
382  */
383 RPC_STATUS WINAPI RpcServerUseProtseqEpW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor )
384 {
385   RPC_POLICY policy;
386   
387   TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor );
388   
389   /* This should provide the default behaviour */
390   policy.Length        = sizeof( policy );
391   policy.EndpointFlags = 0;
392   policy.NICFlags      = 0;
393   
394   return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
395 }
396
397 /***********************************************************************
398  *             RpcServerUseProtseqEpExA (RPCRT4.@)
399  */
400 RPC_STATUS WINAPI RpcServerUseProtseqEpExA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor,
401                                             PRPC_POLICY lpPolicy )
402 {
403   RpcServerProtseq* ps;
404
405   TRACE("(%s,%u,%s,%p,{%u,%lu,%lu}): stub\n", debugstr_a( Protseq ), MaxCalls,
406        debugstr_a( Endpoint ), SecurityDescriptor,
407        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
408
409   ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
410   ps->MaxCalls = MaxCalls;
411   ps->Protseq = RPCRT4_strdupA(Protseq);
412   ps->Endpoint = RPCRT4_strdupA(Endpoint);
413
414   return RPCRT4_use_protseq(ps);
415 }
416
417 /***********************************************************************
418  *             RpcServerUseProtseqEpExW (RPCRT4.@)
419  */
420 RPC_STATUS WINAPI RpcServerUseProtseqEpExW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor,
421                                             PRPC_POLICY lpPolicy )
422 {
423   RpcServerProtseq* ps;
424
425   TRACE("(%s,%u,%s,%p,{%u,%lu,%lu}): stub\n", debugstr_w( Protseq ), MaxCalls,
426        debugstr_w( Endpoint ), SecurityDescriptor,
427        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
428
429   ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
430   ps->MaxCalls = MaxCalls;
431   /* FIXME: Did Ove have these next two as RPCRT4_strdupW for a reason? */
432   ps->Protseq = RPCRT4_strdupWtoA(Protseq);
433   ps->Endpoint = RPCRT4_strdupWtoA(Endpoint);
434
435   return RPCRT4_use_protseq(ps);
436 }
437
438 /***********************************************************************
439  *             RpcServerRegisterIf (RPCRT4.@)
440  */
441 RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )
442 {
443   TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv);
444   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );
445 }
446
447 /***********************************************************************
448  *             RpcServerRegisterIfEx (RPCRT4.@)
449  */
450 RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
451                        UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn )
452 {
453   TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn);
454   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );
455 }
456
457 /***********************************************************************
458  *             RpcServerRegisterIf2 (RPCRT4.@)
459  */
460 RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
461                       UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
462 {
463   PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
464   RpcServerInterface* sif;
465   int i;
466
467   TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls,
468          MaxRpcSize, IfCallbackFn);
469   TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
470                                      If->InterfaceId.SyntaxVersion.MajorVersion,
471                                      If->InterfaceId.SyntaxVersion.MinorVersion);
472   TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
473                                         If->InterfaceId.SyntaxVersion.MajorVersion,
474                                         If->InterfaceId.SyntaxVersion.MinorVersion);
475   TRACE(" dispatch table: %p\n", If->DispatchTable);
476   if (If->DispatchTable) {
477     TRACE("  dispatch table count: %d\n", If->DispatchTable->DispatchTableCount);
478     for (i=0; i<If->DispatchTable->DispatchTableCount; i++) {
479       TRACE("   entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]);
480     }
481     TRACE("  reserved: %ld\n", If->DispatchTable->Reserved);
482   }
483   TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount);
484   TRACE(" default manager epv: %p\n", If->DefaultManagerEpv);
485   TRACE(" interpreter info: %p\n", If->InterpreterInfo);
486   TRACE(" flags: %08x\n", If->Flags);
487
488   sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));
489   sif->If           = If;
490   if (MgrTypeUuid)
491     memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID));
492   else
493     memset(&sif->MgrTypeUuid, 0, sizeof(UUID));
494   sif->MgrEpv       = MgrEpv;
495   sif->Flags        = Flags;
496   sif->MaxCalls     = MaxCalls;
497   sif->MaxRpcSize   = MaxRpcSize;
498   sif->IfCallbackFn = IfCallbackFn;
499
500   EnterCriticalSection(&server_cs);
501   sif->Next = ifs;
502   ifs = sif;
503   LeaveCriticalSection(&server_cs);
504
505   if (sif->Flags & RPC_IF_AUTOLISTEN) {
506     /* well, start listening, I think... */
507     RPCRT4_start_listen();
508   }
509
510   return RPC_S_OK;
511 }
512
513 /***********************************************************************
514  *             RpcServerRegisterAuthInfoA (RPCRT4.@)
515  */
516 RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
517                             LPVOID Arg )
518 {
519   FIXME( "(%s,%lu,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );
520   
521   return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
522 }
523
524 /***********************************************************************
525  *             RpcServerRegisterAuthInfoW (RPCRT4.@)
526  */
527 RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( LPWSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
528                             LPVOID Arg )
529 {
530   FIXME( "(%s,%lu,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg );
531   
532   return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
533 }
534
535 /***********************************************************************
536  *             RpcServerListen (RPCRT4.@)
537  */
538 RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
539 {
540   TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait);
541
542   if (std_listen)
543     return RPC_S_ALREADY_LISTENING;
544
545   if (!protseqs)
546     return RPC_S_NO_PROTSEQS_REGISTERED;
547
548   std_listen = TRUE;
549   RPCRT4_start_listen();
550
551   if (DontWait) return RPC_S_OK;
552
553   return RpcMgmtWaitServerListen();
554 }
555
556 /***********************************************************************
557  *             RpcMgmtServerWaitListen (RPCRT4.@)
558  */
559 RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
560 {
561   TRACE("\n");
562
563   RPCRT4_start_listen();
564   while (listen_count > -1) {
565     WaitForSingleObject(mgr_event, 1000);
566   }
567
568   return RPC_S_OK;
569 }
570
571 /***********************************************************************
572  *             I_RpcServerStartListening (RPCRT4.@)
573  */
574 RPC_STATUS WINAPI I_RpcServerStartListening( void* hWnd )
575 {
576   FIXME( "(%p): stub\n", hWnd );
577
578   return RPC_S_OK;
579 }
580
581 /***********************************************************************
582  *             I_RpcServerStopListening (RPCRT4.@)
583  */
584 RPC_STATUS WINAPI I_RpcServerStopListening( void )
585 {
586   FIXME( "(): stub\n" );
587
588   return RPC_S_OK;
589 }
590
591 /***********************************************************************
592  *             I_RpcWindowProc (RPCRT4.@)
593  */
594 UINT WINAPI I_RpcWindowProc( void* hWnd, UINT Message, UINT wParam, ULONG lParam )
595 {
596   FIXME( "(%p,%08x,%08x,%08lx): stub\n", hWnd, Message, wParam, lParam );
597
598   return 0;
599 }