Fixed HeapRealloc typo.
[wine/wine64.git] / dlls / ole32 / rpc.c
blob43e823a412eaee98505e9d230070f8374e43bec9
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 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;
61 static wine_rpc_request **reqs = NULL;
62 static int nrofreqs = 0;
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;
70 int pending;
71 HANDLE hThread;
72 CRITICAL_SECTION crit;
73 } wine_pipe;
75 static wine_pipe *pipes = NULL;
76 static int nrofpipes = 0;
78 typedef struct _PipeBuf {
79 ICOM_VTABLE(IRpcChannelBuffer) *lpVtbl;
80 DWORD ref;
82 wine_marshal_id mid;
83 wine_pipe *pipe;
84 } PipeBuf;
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;
93 if (res!=size) {
94 FIXME("Read only %ld of %ld bytes from %p.\n",res,size,hf);
95 return E_FAIL;
97 return S_OK;
100 static void
101 drs(LPCSTR where) {
102 #if 0
103 static int nrofreaders = 0;
105 int i, states[10];
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]
121 #endif
123 return ;
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;
133 if (res!=size) {
134 FIXME("Wrote only %ld of %ld bytes to %p.\n",res,size,hf);
135 return E_FAIL;
137 return S_OK;
140 static DWORD WINAPI _StubReaderThread(LPVOID);
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;
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();
167 return S_OK;
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)
177 return pipes[i].hPipe;
178 return INVALID_HANDLE_VALUE;
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)
188 return pipes+i;
190 return NULL;
193 static HRESULT
194 RPC_GetRequest(wine_rpc_request **req) {
195 static int reqid = 0xdeadbeef;
196 int i;
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;
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)
216 else
217 reqs = (wine_rpc_request**)HeapAlloc(
218 GetProcessHeap(),
219 HEAP_ZERO_MEMORY,
220 sizeof(wine_rpc_request*)
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;
234 static void
235 RPC_FreeRequest(wine_rpc_request *req) {
236 req->state = REQSTATE_DONE; /* Just reuse slot. */
237 return;
240 static HRESULT WINAPI
241 PipeBuf_QueryInterface(
242 LPRPCCHANNELBUFFER iface,REFIID riid,LPVOID *ppv
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;
250 return E_NOINTERFACE;
253 static ULONG WINAPI
254 PipeBuf_AddRef(LPRPCCHANNELBUFFER iface) {
255 ICOM_THIS(PipeBuf,iface);
256 This->ref++;
257 return This->ref;
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;
271 static HRESULT WINAPI
272 PipeBuf_GetBuffer(
273 LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,REFIID riid
275 /*ICOM_THIS(PipeBuf,iface);*/
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;
284 static HRESULT
285 _invoke_onereq(wine_rpc_request *req) {
286 IRpcStubBuffer *stub;
287 RPCOLEMESSAGE msg;
288 HRESULT hres;
289 DWORD reqtype;
291 hres = MARSHAL_Find_Stub_Buffer(&(req->reqh.mid),&stub);
292 if (hres) {
293 ERR("Stub not found?\n");
294 return hres;
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;
315 static HRESULT _read_one(wine_pipe *xpipe);
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));
325 if (!xpipe) {
326 FIXME("no pipe found.\n");
327 return E_POINTER;
329 if (GetCurrentProcessId() == req->reqh.mid.processid) {
330 ERR("In current process?\n");
331 return E_FAIL;
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;
343 while (1) {
344 /*WaitForSingleObject(hRpcChanged,INFINITE);*/
345 hres = _read_one(xpipe);
346 if (hres) break;
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);
354 if (req->state == REQSTATE_RESP_GOT)
355 return S_OK;
357 return hres;
360 static HRESULT WINAPI
361 PipeBuf_SendReceive(
362 LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,ULONG *status
364 ICOM_THIS(PipeBuf,iface);
365 wine_rpc_request *req;
366 HRESULT hres;
368 TRACE("()\n");
370 if (This->mid.processid == GetCurrentProcessId()) {
371 ERR("Need to call directly!\n");
372 return E_FAIL;
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;
386 msg->cbBuffer = req->resph.cbBuffer;
387 msg->Buffer = req->Buffer;
388 *status = req->resph.retval;
389 RPC_FreeRequest(req);
390 return S_OK;
394 static HRESULT WINAPI
395 PipeBuf_FreeBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg) {
396 FIXME("(%p), stub!\n",msg);
397 return E_FAIL;
400 static HRESULT WINAPI
401 PipeBuf_GetDestCtx(
402 LPRPCCHANNELBUFFER iface,DWORD* pdwDestContext,void** ppvDestContext
404 FIXME("(%p,%p), stub!\n",pdwDestContext,ppvDestContext);
405 return E_FAIL;
408 static HRESULT WINAPI
409 PipeBuf_IsConnected(LPRPCCHANNELBUFFER iface) {
410 FIXME("(), stub!\n");
411 return S_OK;
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
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;
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,
442 NULL,
443 OPEN_EXISTING,
447 if (hPipe == INVALID_HANDLE_VALUE) {
448 FIXME("Could not open named pipe %s, le is %lx\n",pipefn,GetLastError());
449 return E_FAIL;
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;
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;
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;
479 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
481 sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
482 hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
484 if (hres != ERROR_SUCCESS)
485 return REGDB_E_READREGDB; /* Probably */
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;
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
511 strcpy(pipefn,PIPEPREF);
512 WINE_StringFromCLSID(rclsid,pipefn+strlen(PIPEPREF));
514 while (tries++<MAXTRIES) {
515 hPipe = CreateFileA(
516 pipefn,
517 GENERIC_READ|GENERIC_WRITE,
519 NULL,
520 OPEN_EXISTING,
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);
533 continue;
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;
541 CloseHandle(hPipe);
542 break;
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.s.LowPart = 0;seekto.s.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;
559 static void WINAPI
560 PIPE_StartRequestThread(HANDLE xhPipe) {
561 wine_marshal_id remoteid;
562 HRESULT hres;
564 hres = _xread(xhPipe,&remoteid,sizeof(remoteid));
565 if (hres) {
566 ERR("Failed to read remote mid!\n");
567 return;
569 PIPE_RegisterPipe(&remoteid,xhPipe, TRUE);
572 static HRESULT
573 _read_one(wine_pipe *xpipe) {
574 DWORD reqtype;
575 HRESULT hres = S_OK;
576 HANDLE xhPipe = xpipe->hPipe;
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);*/
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;
597 if (reqtype == REQTYPE_RESPONSE) {
598 wine_rpc_response_header resph;
599 int i;
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));
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);
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;
622 ERR("Did not find request for id %lx\n",resph.reqid);
623 hres = S_OK;
624 goto end;
626 ERR("Unknown reqtype %ld\n",reqtype);
627 hres = E_FAIL;
628 end:
629 LeaveCriticalSection(&(xpipe->crit));
630 return hres;
633 static DWORD WINAPI
634 _StubReaderThread(LPVOID param) {
635 wine_pipe *xpipe = (wine_pipe*)param;
636 HANDLE xhPipe = xpipe->hPipe;
637 HRESULT hres;
639 TRACE("STUB reader thread %lx\n",GetCurrentProcessId());
640 while (1) {
641 int i;
642 hres = _read_one(xpipe);
643 if (hres) break;
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);
652 FIXME("Failed with hres %lx\n",hres);
653 CloseHandle(xhPipe);
654 return 0;
657 static DWORD WINAPI
658 _StubMgrThread(LPVOID param) {
659 char pipefn[200];
660 HANDLE listenPipe;
662 sprintf(pipefn,OLESTUBMGR"_%08lx",GetCurrentProcessId());
663 TRACE("Stub Manager Thread starting on (%s)\n",pipefn);
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
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 */
680 if (!ConnectNamedPipe(listenPipe,NULL)) {
681 ERR("Failure during ConnectNamedPipe %lx!\n",GetLastError());
682 CloseHandle(listenPipe);
683 continue;
685 PIPE_StartRequestThread(listenPipe);
687 return 0;
690 void
691 STUBMGR_Start() {
692 static BOOL stubMgrRunning = FALSE;
693 DWORD tid;
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 */