Preliminary implementation of ICreateTypeInfo2_fnAddFuncDesc() and
[wine] / dlls / ole32 / rpc.c
1 /*
2  *      (Local) RPC Stuff
3  *
4  *  Copyright 2002  Marcus Meissner
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
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "objbase.h"
35 #include "ole2.h"
36 #include "ole2ver.h"
37 #include "rpc.h"
38 #include "winerror.h"
39 #include "winreg.h"
40 #include "wownt32.h"
41 #include "wtypes.h"
42 #include "wine/unicode.h"
43 #include "wine/winbase16.h"
44 #include "compobj_private.h"
45 #include "ifs.h"
46
47 #include "compobj_private.h"
48
49 #include "wine/debug.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL(ole);
52
53 typedef struct _wine_rpc_request {
54     int                         state;
55     HANDLE                      hPipe;  /* temp copy of handle */
56     wine_rpc_request_header     reqh;
57     wine_rpc_response_header    resph;
58     LPBYTE                      Buffer;
59 } wine_rpc_request;
60
61 static wine_rpc_request **reqs = NULL;
62 static int nrofreqs = 0;
63
64 /* This pipe is _thread_ based */
65 typedef struct _wine_pipe {
66     wine_marshal_id     mid;    /* target mid */
67     DWORD               tid;    /* thread in which we execute */
68     HANDLE              hPipe;
69
70     int                 pending;
71     HANDLE              hThread;
72     CRITICAL_SECTION    crit;
73 } wine_pipe;
74
75 static wine_pipe *pipes = NULL;
76 static int nrofpipes = 0;
77
78 typedef struct _PipeBuf {
79     ICOM_VTABLE(IRpcChannelBuffer)      *lpVtbl;
80     DWORD                               ref;
81
82     wine_marshal_id                     mid;
83     wine_pipe                           *pipe;
84 } PipeBuf;
85
86 static HRESULT WINAPI
87 _xread(HANDLE hf, LPVOID ptr, DWORD size) {
88     DWORD res;
89     if (!ReadFile(hf,ptr,size,&res,NULL)) {
90         FIXME("Failed to read from %p, le is %lx\n",hf,GetLastError());
91         return E_FAIL;
92     }
93     if (res!=size) {
94         FIXME("Read only %ld of %ld bytes from %p.\n",res,size,hf);
95         return E_FAIL;
96     }
97     return S_OK;
98 }
99
100 static void
101 drs(LPCSTR where) {
102 #if 0
103     static int nrofreaders = 0;
104
105     int i, states[10];
106
107     memset(states,0,sizeof(states));
108     for (i=nrofreqs;i--;)
109         states[reqs[i]->state]++;
110     FIXME("%lx/%s/%d: rq %d, w %d, rg %d, rsq %d, rsg %d, d %d\n",
111             GetCurrentProcessId(),
112             where,
113             nrofreaders,
114             states[REQSTATE_REQ_QUEUED],
115             states[REQSTATE_REQ_WAITING_FOR_REPLY],
116             states[REQSTATE_REQ_GOT],
117             states[REQSTATE_RESP_QUEUED],
118             states[REQSTATE_RESP_GOT],
119             states[REQSTATE_DONE]
120     );
121 #endif
122
123     return ;
124 }
125
126 static HRESULT WINAPI
127 _xwrite(HANDLE hf, LPVOID ptr, DWORD size) {
128     DWORD res;
129     if (!WriteFile(hf,ptr,size,&res,NULL)) {
130         FIXME("Failed to write to %p, le is %lx\n",hf,GetLastError());
131         return E_FAIL;
132     }
133     if (res!=size) {
134         FIXME("Wrote only %ld of %ld bytes to %p.\n",res,size,hf);
135         return E_FAIL;
136     }
137     return S_OK;
138 }
139
140 static DWORD WINAPI _StubReaderThread(LPVOID);
141
142 static HRESULT
143 PIPE_RegisterPipe(wine_marshal_id *mid, HANDLE hPipe, BOOL startreader) {
144   int   i;
145   char  pipefn[100];
146   wine_pipe *new_pipes;
147
148   for (i=0;i<nrofpipes;i++)
149     if (pipes[i].mid.processid==mid->processid)
150       return S_OK;
151   if (pipes)
152     new_pipes=(wine_pipe*)HeapReAlloc(GetProcessHeap(),0,pipes,sizeof(pipes[0])*(nrofpipes+1));
153   else
154     new_pipes=(wine_pipe*)HeapAlloc(GetProcessHeap(),0,sizeof(pipes[0]));
155   if (!new_pipes) return E_OUTOFMEMORY;
156   pipes = new_pipes;
157   sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid);
158   memcpy(&(pipes[nrofpipes].mid),mid,sizeof(*mid));
159   pipes[nrofpipes].hPipe        = hPipe;
160   InitializeCriticalSection(&(pipes[nrofpipes].crit));
161   nrofpipes++;
162   if (startreader) {
163       pipes[nrofpipes-1].hThread = CreateThread(NULL,0,_StubReaderThread,(LPVOID)(pipes+(nrofpipes-1)),0,&(pipes[nrofpipes-1].tid));
164   } else {
165       pipes[nrofpipes-1].tid     = GetCurrentThreadId();
166   }
167   return S_OK;
168 }
169
170 static HANDLE
171 PIPE_FindByMID(wine_marshal_id *mid) {
172   int i;
173   for (i=0;i<nrofpipes;i++)
174     if ((pipes[i].mid.processid==mid->processid) &&
175         (GetCurrentThreadId()==pipes[i].tid)
176     )
177       return pipes[i].hPipe;
178   return INVALID_HANDLE_VALUE;
179 }
180
181 static wine_pipe*
182 PIPE_GetFromMID(wine_marshal_id *mid) {
183   int i;
184   for (i=0;i<nrofpipes;i++) {
185     if ((pipes[i].mid.processid==mid->processid) &&
186         (GetCurrentThreadId()==pipes[i].tid)
187     )
188       return pipes+i;
189   }
190   return NULL;
191 }
192
193 static HRESULT
194 RPC_GetRequest(wine_rpc_request **req) {
195     static int reqid = 0xdeadbeef;
196     int i;
197
198     for (i=0;i<nrofreqs;i++) { /* try to reuse */
199         if (reqs[i]->state == REQSTATE_DONE) {
200             reqs[i]->reqh.reqid = reqid++;
201             reqs[i]->resph.reqid = reqs[i]->reqh.reqid;
202             reqs[i]->hPipe = INVALID_HANDLE_VALUE;
203             *req = reqs[i];
204             reqs[i]->state = REQSTATE_START;
205             return S_OK;
206         }
207     }
208     /* create new */
209     if (reqs)
210         reqs = (wine_rpc_request**)HeapReAlloc(
211                         GetProcessHeap(),
212                         HEAP_ZERO_MEMORY,
213                         reqs,
214                         sizeof(wine_rpc_request*)*(nrofreqs+1)
215                 );
216     else
217         reqs = (wine_rpc_request**)HeapAlloc(
218                         GetProcessHeap(),
219                         HEAP_ZERO_MEMORY,
220                         sizeof(wine_rpc_request*)
221                 );
222     if (!reqs)
223         return E_OUTOFMEMORY;
224     reqs[nrofreqs] = (wine_rpc_request*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(wine_rpc_request));
225     reqs[nrofreqs]->reqh.reqid = reqid++;
226     reqs[nrofreqs]->resph.reqid = reqs[nrofreqs]->reqh.reqid;
227     reqs[nrofreqs]->hPipe = INVALID_HANDLE_VALUE;
228     *req = reqs[nrofreqs];
229     reqs[nrofreqs]->state = REQSTATE_START;
230     nrofreqs++;
231     return S_OK;
232 }
233
234 static void
235 RPC_FreeRequest(wine_rpc_request *req) {
236     req->state = REQSTATE_DONE; /* Just reuse slot. */
237     return;
238 }
239
240 static HRESULT WINAPI
241 PipeBuf_QueryInterface(
242     LPRPCCHANNELBUFFER iface,REFIID riid,LPVOID *ppv
243 ) {
244     *ppv = NULL;
245     if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) {
246         *ppv = (LPVOID)iface;
247         IUnknown_AddRef(iface);
248         return S_OK;
249     }
250     return E_NOINTERFACE;
251 }
252
253 static ULONG WINAPI
254 PipeBuf_AddRef(LPRPCCHANNELBUFFER iface) {
255     ICOM_THIS(PipeBuf,iface);
256     This->ref++;
257     return This->ref;
258 }
259
260 static ULONG WINAPI
261 PipeBuf_Release(LPRPCCHANNELBUFFER iface) {
262     ICOM_THIS(PipeBuf,iface);
263     This->ref--;
264     if (This->ref)
265         return This->ref;
266     ERR("Free all stuff.\n");
267     HeapFree(GetProcessHeap(),0,This);
268     return 0;
269 }
270
271 static HRESULT WINAPI
272 PipeBuf_GetBuffer(
273     LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,REFIID riid
274 ) {
275     /*ICOM_THIS(PipeBuf,iface);*/
276
277     TRACE("(%p,%s), slightly wrong.\n",msg,debugstr_guid(riid));
278     /* probably reuses IID in real. */
279     if (msg->cbBuffer && (msg->Buffer == NULL))
280         msg->Buffer = HeapAlloc(GetProcessHeap(),0,msg->cbBuffer);
281     return S_OK;
282 }
283
284 static HRESULT
285 _invoke_onereq(wine_rpc_request *req) {
286     IRpcStubBuffer      *stub;
287     RPCOLEMESSAGE       msg;
288     HRESULT             hres;
289     DWORD               reqtype;
290
291     hres = MARSHAL_Find_Stub_Buffer(&(req->reqh.mid),&stub);
292     if (hres) {
293         ERR("Stub not found?\n");
294         return hres;
295     }
296     msg.Buffer          = req->Buffer;
297     msg.iMethod         = req->reqh.iMethod;
298     msg.cbBuffer        = req->reqh.cbBuffer;
299     req->state          = REQSTATE_INVOKING;
300     req->resph.retval   = IRpcStubBuffer_Invoke(stub,&msg,NULL);
301     req->Buffer         = msg.Buffer;
302     req->resph.cbBuffer = msg.cbBuffer;
303     reqtype             = REQTYPE_RESPONSE;
304     hres = _xwrite(req->hPipe,&reqtype,sizeof(reqtype));
305     if (hres) return hres;
306     hres = _xwrite(req->hPipe,&(req->resph),sizeof(req->resph));
307     if (hres) return hres;
308     hres = _xwrite(req->hPipe,req->Buffer,req->resph.cbBuffer);
309     if (hres) return hres;
310     req->state = REQSTATE_DONE;
311     drs("invoke");
312     return S_OK;
313 }
314
315 static HRESULT _read_one(wine_pipe *xpipe);
316
317 static HRESULT
318 RPC_QueueRequestAndWait(wine_rpc_request *req) {
319     int                 i;
320     wine_rpc_request    *xreq;
321     HRESULT             hres;
322     DWORD               reqtype;
323     wine_pipe           *xpipe = PIPE_GetFromMID(&(req->reqh.mid));
324
325     if (!xpipe) {
326         FIXME("no pipe found.\n");
327         return E_POINTER;
328     }
329     if (GetCurrentProcessId() == req->reqh.mid.processid) {
330         ERR("In current process?\n");
331         return E_FAIL;
332     }
333     req->hPipe = xpipe->hPipe;
334     req->state = REQSTATE_REQ_WAITING_FOR_REPLY;
335     reqtype = REQTYPE_REQUEST;
336     hres = _xwrite(req->hPipe,&reqtype,sizeof(reqtype));
337     if (hres) return hres;
338     hres = _xwrite(req->hPipe,&(req->reqh),sizeof(req->reqh));
339     if (hres) return hres;
340     hres = _xwrite(req->hPipe,req->Buffer,req->reqh.cbBuffer);
341     if (hres) return hres;
342
343     while (1) {
344         /*WaitForSingleObject(hRpcChanged,INFINITE);*/
345         hres = _read_one(xpipe);
346         if (hres) break;
347
348         for (i=0;i<nrofreqs;i++) {
349             xreq = reqs[i];
350             if ((xreq->state==REQSTATE_REQ_GOT) && (xreq->hPipe==req->hPipe)) {
351                 _invoke_onereq(xreq);
352             }
353         }
354         if (req->state == REQSTATE_RESP_GOT)
355             return S_OK;
356     }
357     return hres;
358 }
359
360 static HRESULT WINAPI
361 PipeBuf_SendReceive(
362     LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,ULONG *status
363 ) {
364     ICOM_THIS(PipeBuf,iface);
365     wine_rpc_request    *req;
366     HRESULT             hres;
367
368     TRACE("()\n");
369
370     if (This->mid.processid == GetCurrentProcessId()) {
371         ERR("Need to call directly!\n");
372         return E_FAIL;
373     }
374
375     hres = RPC_GetRequest(&req);
376     if (hres) return hres;
377     req->reqh.iMethod   = msg->iMethod;
378     req->reqh.cbBuffer  = msg->cbBuffer;
379     memcpy(&(req->reqh.mid),&(This->mid),sizeof(This->mid));
380     req->Buffer = msg->Buffer;
381     hres = RPC_QueueRequestAndWait(req);
382     if (hres) {
383         RPC_FreeRequest(req);
384         return hres;
385     }
386     msg->cbBuffer       = req->resph.cbBuffer;
387     msg->Buffer         = req->Buffer;
388     *status             = req->resph.retval;
389     RPC_FreeRequest(req);
390     return S_OK;
391 }
392
393
394 static HRESULT WINAPI
395 PipeBuf_FreeBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg) {
396     FIXME("(%p), stub!\n",msg);
397     return E_FAIL;
398 }
399
400 static HRESULT WINAPI
401 PipeBuf_GetDestCtx(
402     LPRPCCHANNELBUFFER iface,DWORD* pdwDestContext,void** ppvDestContext
403 ) {
404     FIXME("(%p,%p), stub!\n",pdwDestContext,ppvDestContext);
405     return E_FAIL;
406 }
407
408 static HRESULT WINAPI
409 PipeBuf_IsConnected(LPRPCCHANNELBUFFER iface) {
410     FIXME("(), stub!\n");
411     return S_OK;
412 }
413
414 static ICOM_VTABLE(IRpcChannelBuffer) pipebufvt = {
415     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
416     PipeBuf_QueryInterface,
417     PipeBuf_AddRef,
418     PipeBuf_Release,
419     PipeBuf_GetBuffer,
420     PipeBuf_SendReceive,
421     PipeBuf_FreeBuffer,
422     PipeBuf_GetDestCtx,
423     PipeBuf_IsConnected
424 };
425
426 HRESULT
427 PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) {
428   wine_marshal_id       ourid;
429   DWORD                 res;
430   HANDLE                hPipe;
431   HRESULT               hres;
432   PipeBuf               *pbuf;
433
434   hPipe = PIPE_FindByMID(mid);
435   if (hPipe == INVALID_HANDLE_VALUE) {
436       char                      pipefn[200];
437       sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid);
438       hPipe = CreateFileA(
439               pipefn,
440               GENERIC_READ|GENERIC_WRITE,
441               0,
442               NULL,
443               OPEN_EXISTING,
444               0,
445               0
446       );
447       if (hPipe == INVALID_HANDLE_VALUE) {
448           FIXME("Could not open named pipe %s, le is %lx\n",pipefn,GetLastError());
449           return E_FAIL;
450       }
451       hres = PIPE_RegisterPipe(mid, hPipe, FALSE);
452       if (hres) return hres;
453       memset(&ourid,0,sizeof(ourid));
454       ourid.processid = GetCurrentProcessId();
455       if (!WriteFile(hPipe,&ourid,sizeof(ourid),&res,NULL)||(res!=sizeof(ourid))) {
456           ERR("Failed writing startup mid!\n");
457           return E_FAIL;
458       }
459   }
460   pbuf = (PipeBuf*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PipeBuf));
461   pbuf->lpVtbl  = &pipebufvt;
462   pbuf->ref     = 1;
463   memcpy(&(pbuf->mid),mid,sizeof(*mid));
464   *pipebuf = (IRpcChannelBuffer*)pbuf;
465   return S_OK;
466 }
467
468 static HRESULT
469 create_server(REFCLSID rclsid) {
470   HKEY          key;
471   char          buf[200];
472   HRESULT       hres = E_UNEXPECTED;
473   char          xclsid[80];
474   WCHAR         dllName[MAX_PATH+1];
475   DWORD         dllNameLen = sizeof(dllName);
476   STARTUPINFOW  sinfo;
477   PROCESS_INFORMATION   pinfo;
478
479   WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
480
481   sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
482   hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
483
484   if (hres != ERROR_SUCCESS)
485       return REGDB_E_READREGDB; /* Probably */
486
487   memset(dllName,0,sizeof(dllName));
488   hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen);
489   RegCloseKey(key);
490   if (hres)
491           return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
492   memset(&sinfo,0,sizeof(sinfo));
493   sinfo.cb = sizeof(sinfo);
494   if (!CreateProcessW(NULL,dllName,NULL,NULL,FALSE,0,NULL,NULL,&sinfo,&pinfo))
495       return E_FAIL;
496   return S_OK;
497 }
498 /* http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, Figure 4 */
499 HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) {
500   HRESULT       hres;
501   HANDLE        hPipe;
502   char          pipefn[200];
503   DWORD         res,bufferlen;
504   char          marshalbuffer[200];
505   IStream       *pStm;
506   LARGE_INTEGER seekto;
507   ULARGE_INTEGER newpos;
508   int           tries = 0;
509 #define MAXTRIES 10000
510
511   strcpy(pipefn,PIPEPREF);
512   WINE_StringFromCLSID(rclsid,pipefn+strlen(PIPEPREF));
513
514   while (tries++<MAXTRIES) {
515       hPipe     = CreateFileA(
516               pipefn,
517               GENERIC_READ|GENERIC_WRITE,
518               0,
519               NULL,
520               OPEN_EXISTING,
521               0,
522               0
523       );
524       if (hPipe == INVALID_HANDLE_VALUE) {
525           if (tries == 1) {
526               if ((hres = create_server(rclsid)))
527                   return hres;
528               Sleep(1000);
529           } else {
530               WARN("Could not open named pipe to broker %s, le is %lx\n",pipefn,GetLastError());
531               Sleep(1000);
532           }
533           continue;
534       }
535       bufferlen = 0;
536       if (!ReadFile(hPipe,marshalbuffer,sizeof(marshalbuffer),&bufferlen,NULL)) {
537           FIXME("Failed to read marshal id from classfactory of %s.\n",debugstr_guid(rclsid));
538           Sleep(1000);
539           continue;
540       }
541       CloseHandle(hPipe);
542       break;
543   }
544   if (tries>=MAXTRIES)
545       return E_NOINTERFACE;
546   hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
547   if (hres) return hres;
548   hres = IStream_Write(pStm,marshalbuffer,bufferlen,&res);
549   if (hres) goto out;
550   seekto.u.LowPart = 0;seekto.u.HighPart = 0;
551   hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
552   hres = CoUnmarshalInterface(pStm,&IID_IClassFactory,ppv);
553 out:
554   IStream_Release(pStm);
555   return hres;
556 }
557
558
559 static void WINAPI
560 PIPE_StartRequestThread(HANDLE xhPipe) {
561     wine_marshal_id     remoteid;
562     HRESULT             hres;
563
564     hres = _xread(xhPipe,&remoteid,sizeof(remoteid));
565     if (hres) {
566         ERR("Failed to read remote mid!\n");
567         return;
568     }
569     PIPE_RegisterPipe(&remoteid,xhPipe, TRUE);
570 }
571
572 static HRESULT
573 _read_one(wine_pipe *xpipe) {
574     DWORD       reqtype;
575     HRESULT     hres = S_OK;
576     HANDLE      xhPipe = xpipe->hPipe;
577
578     /*FIXME("%lx %d reading reqtype\n",GetCurrentProcessId(),xhPipe);*/
579     hres = _xread(xhPipe,&reqtype,sizeof(reqtype));
580     if (hres) goto end;
581     EnterCriticalSection(&(xpipe->crit));
582     /*FIXME("%lx got reqtype %ld\n",GetCurrentProcessId(),reqtype);*/
583
584     if (reqtype == REQTYPE_REQUEST) {
585         wine_rpc_request        *xreq;
586         RPC_GetRequest(&xreq);
587         xreq->hPipe = xhPipe;
588         hres = _xread(xhPipe,&(xreq->reqh),sizeof(xreq->reqh));
589         if (hres) goto end;
590         xreq->resph.reqid = xreq->reqh.reqid;
591         xreq->Buffer = HeapAlloc(GetProcessHeap(),0, xreq->reqh.cbBuffer);
592         hres = _xread(xhPipe,xreq->Buffer,xreq->reqh.cbBuffer);
593         if (hres) goto end;
594         xreq->state = REQSTATE_REQ_GOT;
595         goto end;
596     }
597     if (reqtype == REQTYPE_RESPONSE) {
598         wine_rpc_response_header        resph;
599         int i;
600
601         hres = _xread(xhPipe,&resph,sizeof(resph));
602         if (hres) goto end;
603         for (i=nrofreqs;i--;) {
604             wine_rpc_request *xreq = reqs[i];
605             if (xreq->state != REQSTATE_REQ_WAITING_FOR_REPLY)
606                 continue;
607             if (xreq->reqh.reqid == resph.reqid) {
608                 memcpy(&(xreq->resph),&resph,sizeof(resph));
609
610                 if (xreq->Buffer)
611                     xreq->Buffer = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,xreq->Buffer,xreq->resph.cbBuffer);
612                 else
613                     xreq->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,xreq->resph.cbBuffer);
614
615                 hres = _xread(xhPipe,xreq->Buffer,xreq->resph.cbBuffer);
616                 if (hres) goto end;
617                 xreq->state = REQSTATE_RESP_GOT;
618                 /*PulseEvent(hRpcChanged);*/
619                 goto end;
620             }
621         }
622         ERR("Did not find request for id %lx\n",resph.reqid);
623         hres = S_OK;
624         goto end;
625     }
626     ERR("Unknown reqtype %ld\n",reqtype);
627     hres = E_FAIL;
628 end:
629     LeaveCriticalSection(&(xpipe->crit));
630     return hres;
631 }
632
633 static DWORD WINAPI
634 _StubReaderThread(LPVOID param) {
635     wine_pipe           *xpipe = (wine_pipe*)param;
636     HANDLE              xhPipe = xpipe->hPipe;
637     HRESULT             hres;
638
639     TRACE("STUB reader thread %lx\n",GetCurrentProcessId());
640     while (1) {
641         int i;
642         hres = _read_one(xpipe);
643         if (hres) break;
644
645         for (i=nrofreqs;i--;) {
646             wine_rpc_request *xreq = reqs[i];
647             if ((xreq->state == REQSTATE_REQ_GOT) && (xreq->hPipe == xhPipe)) {
648                 _invoke_onereq(xreq);
649             }
650         }
651     }
652     FIXME("Failed with hres %lx\n",hres);
653     CloseHandle(xhPipe);
654     return 0;
655 }
656
657 static DWORD WINAPI
658 _StubMgrThread(LPVOID param) {
659     char                pipefn[200];
660     HANDLE              listenPipe;
661
662     sprintf(pipefn,OLESTUBMGR"_%08lx",GetCurrentProcessId());
663     TRACE("Stub Manager Thread starting on (%s)\n",pipefn);
664
665     while (1) {
666         listenPipe = CreateNamedPipeA(
667             pipefn,
668             PIPE_ACCESS_DUPLEX,
669             PIPE_TYPE_BYTE|PIPE_WAIT,
670             PIPE_UNLIMITED_INSTANCES,
671             4096,
672             4096,
673             NMPWAIT_USE_DEFAULT_WAIT,
674             NULL
675         );
676         if (listenPipe == INVALID_HANDLE_VALUE) {
677             FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError());
678             return 1; /* permanent failure, so quit stubmgr thread */
679         }
680         if (!ConnectNamedPipe(listenPipe,NULL)) {
681             ERR("Failure during ConnectNamedPipe %lx!\n",GetLastError());
682             CloseHandle(listenPipe);
683             continue;
684         }
685         PIPE_StartRequestThread(listenPipe);
686     }
687     return 0;
688 }
689
690 void
691 STUBMGR_Start() {
692   static BOOL stubMgrRunning = FALSE;
693   DWORD tid;
694
695   if (!stubMgrRunning) {
696       stubMgrRunning = TRUE;
697       CreateThread(NULL,0,_StubMgrThread,NULL,0,&tid);
698       Sleep(2000); /* actually we just try opening the pipe until it succeeds */
699   }
700 }