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