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