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