Fixed some issues found by winapi_check.
[wine/dcerpc.git] / dlls / ole32 / rpc.c
blob5411e6c93de1401744a00453cafbe5c337842c41
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/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"
48 #include "compobj_private.h"
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(ole);
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;
62 static wine_rpc_request **reqs = NULL;
63 static int nrofreqs = 0;
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;
71 int pending;
72 HANDLE hThread;
73 CRITICAL_SECTION crit;
74 } wine_pipe;
76 static wine_pipe *pipes = NULL;
77 static int nrofpipes = 0;
79 typedef struct _PipeBuf {
80 ICOM_VTABLE(IRpcChannelBuffer) *lpVtbl;
81 DWORD ref;
83 wine_marshal_id mid;
84 wine_pipe *pipe;
85 } PipeBuf;
87 static int nrofreaders = 0;
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 %x, le is %lx\n",hf,GetLastError());
94 return E_FAIL;
96 if (res!=size) {
97 FIXME("Read only %ld of %ld bytes.\n",res,size);
98 return E_FAIL;
100 return S_OK;
103 static void
104 drs(LPCSTR where) {
105 int i, states[10];
107 return ;
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]
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 %x, le is %lx\n",hf,GetLastError());
130 return E_FAIL;
132 if (res!=size) {
133 FIXME("Wrote only %ld of %ld bytes.\n",res,size);
134 return E_FAIL;
136 return S_OK;
139 static DWORD WINAPI _StubReaderThread(LPVOID);
141 static HRESULT
142 PIPE_RegisterPipe(wine_marshal_id *mid, HANDLE hPipe, BOOL startreader) {
143 int i;
144 char pipefn[100];
146 for (i=0;i<nrofpipes;i++)
147 if (pipes[i].mid.processid==mid->processid)
148 return S_OK;
149 if (pipes)
150 pipes=(wine_pipe*)HeapReAlloc(GetProcessHeap(),0,pipes,sizeof(pipes[0])*(nrofpipes+1));
151 else
152 pipes=(wine_pipe*)HeapAlloc(GetProcessHeap(),0,sizeof(pipes[0]));
153 if (!pipes) return E_OUTOFMEMORY;
154 sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid);
155 memcpy(&(pipes[nrofpipes].mid),mid,sizeof(*mid));
156 pipes[nrofpipes].hPipe = hPipe;
157 InitializeCriticalSection(&(pipes[nrofpipes].crit));
158 nrofpipes++;
159 if (startreader) {
160 pipes[nrofpipes-1].hThread = CreateThread(NULL,0,_StubReaderThread,(LPVOID)pipes+(nrofpipes-1),0,&(pipes[nrofpipes-1].tid));
161 } else {
162 pipes[nrofpipes-1].tid = GetCurrentThreadId();
164 return S_OK;
167 static HANDLE
168 PIPE_FindByMID(wine_marshal_id *mid) {
169 int i;
170 for (i=0;i<nrofpipes;i++)
171 if ((pipes[i].mid.processid==mid->processid) &&
172 (GetCurrentThreadId()==pipes[i].tid)
174 return pipes[i].hPipe;
175 return INVALID_HANDLE_VALUE;
178 static wine_pipe*
179 PIPE_GetFromMID(wine_marshal_id *mid) {
180 int i;
181 for (i=0;i<nrofpipes;i++) {
182 if ((pipes[i].mid.processid==mid->processid) &&
183 (GetCurrentThreadId()==pipes[i].tid)
185 return pipes+i;
187 return NULL;
190 static HRESULT
191 RPC_GetRequest(wine_rpc_request **req) {
192 static int reqid = 0xdeadbeef;
193 int i;
195 for (i=0;i<nrofreqs;i++) { /* try to reuse */
196 if (reqs[i]->state == REQSTATE_DONE) {
197 reqs[i]->reqh.reqid = reqid++;
198 reqs[i]->resph.reqid = reqs[i]->reqh.reqid;
199 reqs[i]->hPipe = INVALID_HANDLE_VALUE;
200 *req = reqs[i];
201 reqs[i]->state = REQSTATE_START;
202 return S_OK;
205 /* create new */
206 if (reqs)
207 reqs = (wine_rpc_request**)HeapReAlloc(
208 GetProcessHeap(),
209 HEAP_ZERO_MEMORY,
210 reqs,
211 sizeof(wine_rpc_request*)*(nrofreqs+1)
213 else
214 reqs = (wine_rpc_request**)HeapAlloc(
215 GetProcessHeap(),
216 HEAP_ZERO_MEMORY,
217 sizeof(wine_rpc_request*)
219 if (!reqs)
220 return E_OUTOFMEMORY;
221 reqs[nrofreqs] = (wine_rpc_request*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(wine_rpc_request));
222 reqs[nrofreqs]->reqh.reqid = reqid++;
223 reqs[nrofreqs]->resph.reqid = reqs[nrofreqs]->reqh.reqid;
224 reqs[nrofreqs]->hPipe = INVALID_HANDLE_VALUE;
225 *req = reqs[nrofreqs];
226 reqs[nrofreqs]->state = REQSTATE_START;
227 nrofreqs++;
228 return S_OK;
231 static void
232 RPC_FreeRequest(wine_rpc_request *req) {
233 req->state = REQSTATE_DONE; /* Just reuse slot. */
234 return;
237 static HRESULT WINAPI
238 PipeBuf_QueryInterface(
239 LPRPCCHANNELBUFFER iface,REFIID riid,LPVOID *ppv
241 *ppv = NULL;
242 if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) {
243 *ppv = (LPVOID)iface;
244 IUnknown_AddRef(iface);
245 return S_OK;
247 return E_NOINTERFACE;
250 static ULONG WINAPI
251 PipeBuf_AddRef(LPRPCCHANNELBUFFER iface) {
252 ICOM_THIS(PipeBuf,iface);
253 This->ref++;
254 return This->ref;
257 static ULONG WINAPI
258 PipeBuf_Release(LPRPCCHANNELBUFFER iface) {
259 ICOM_THIS(PipeBuf,iface);
260 This->ref--;
261 if (This->ref)
262 return This->ref;
263 ERR("Free all stuff.\n");
264 HeapFree(GetProcessHeap(),0,This);
265 return 0;
268 static HRESULT WINAPI
269 PipeBuf_GetBuffer(
270 LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,REFIID riid
272 /*ICOM_THIS(PipeBuf,iface);*/
274 TRACE("(%p,%s), slightly wrong.\n",msg,debugstr_guid(riid));
275 /* probably reuses IID in real. */
276 if (msg->cbBuffer && (msg->Buffer == NULL))
277 msg->Buffer = HeapAlloc(GetProcessHeap(),0,msg->cbBuffer);
278 return S_OK;
281 static HRESULT
282 _invoke_onereq(wine_rpc_request *req) {
283 IRpcStubBuffer *stub;
284 RPCOLEMESSAGE msg;
285 HRESULT hres;
286 DWORD reqtype;
288 hres = MARSHAL_Find_Stub_Buffer(&(req->reqh.mid),&stub);
289 if (hres) {
290 ERR("Stub not found?\n");
291 return hres;
293 msg.Buffer = req->Buffer;
294 msg.iMethod = req->reqh.iMethod;
295 msg.cbBuffer = req->reqh.cbBuffer;
296 req->state = REQSTATE_INVOKING;
297 req->resph.retval = IRpcStubBuffer_Invoke(stub,&msg,NULL);
298 req->Buffer = msg.Buffer;
299 req->resph.cbBuffer = msg.cbBuffer;
300 reqtype = REQTYPE_RESPONSE;
301 hres = _xwrite(req->hPipe,&reqtype,sizeof(reqtype));
302 if (hres) return hres;
303 hres = _xwrite(req->hPipe,&(req->resph),sizeof(req->resph));
304 if (hres) return hres;
305 hres = _xwrite(req->hPipe,req->Buffer,req->resph.cbBuffer);
306 if (hres) return hres;
307 req->state = REQSTATE_DONE;
308 drs("invoke");
309 return S_OK;
312 static HRESULT _read_one(wine_pipe *xpipe);
314 static HRESULT
315 RPC_QueueRequestAndWait(wine_rpc_request *req) {
316 int i;
317 wine_rpc_request *xreq;
318 HRESULT hres;
319 DWORD reqtype;
320 wine_pipe *xpipe = PIPE_GetFromMID(&(req->reqh.mid));
322 if (!xpipe) {
323 FIXME("no pipe found.\n");
324 return E_POINTER;
326 if (GetCurrentProcessId() == req->reqh.mid.processid) {
327 ERR("In current process?\n");
328 return E_FAIL;
330 req->hPipe = xpipe->hPipe;
331 req->state = REQSTATE_REQ_WAITING_FOR_REPLY;
332 reqtype = REQTYPE_REQUEST;
333 hres = _xwrite(req->hPipe,&reqtype,sizeof(reqtype));
334 if (hres) return hres;
335 hres = _xwrite(req->hPipe,&(req->reqh),sizeof(req->reqh));
336 if (hres) return hres;
337 hres = _xwrite(req->hPipe,req->Buffer,req->reqh.cbBuffer);
338 if (hres) return hres;
340 while (1) {
341 /*WaitForSingleObject(hRpcChanged,INFINITE);*/
342 hres = _read_one(xpipe);
343 if (hres) break;
345 for (i=0;i<nrofreqs;i++) {
346 xreq = reqs[i];
347 if ((xreq->state==REQSTATE_REQ_GOT) && (xreq->hPipe==req->hPipe)) {
348 _invoke_onereq(xreq);
351 if (req->state == REQSTATE_RESP_GOT)
352 return S_OK;
354 return hres;
357 static HRESULT WINAPI
358 PipeBuf_SendReceive(
359 LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,ULONG *status
361 ICOM_THIS(PipeBuf,iface);
362 wine_rpc_request *req;
363 HRESULT hres;
365 TRACE("()\n");
367 if (This->mid.processid == GetCurrentProcessId()) {
368 ERR("Need to call directly!\n");
369 return E_FAIL;
372 hres = RPC_GetRequest(&req);
373 if (hres) return hres;
374 req->reqh.iMethod = msg->iMethod;
375 req->reqh.cbBuffer = msg->cbBuffer;
376 memcpy(&(req->reqh.mid),&(This->mid),sizeof(This->mid));
377 req->Buffer = msg->Buffer;
378 hres = RPC_QueueRequestAndWait(req);
379 if (hres) {
380 RPC_FreeRequest(req);
381 return hres;
383 msg->cbBuffer = req->resph.cbBuffer;
384 msg->Buffer = req->Buffer;
385 *status = req->resph.retval;
386 RPC_FreeRequest(req);
387 return S_OK;
391 static HRESULT WINAPI
392 PipeBuf_FreeBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg) {
393 FIXME("(%p), stub!\n",msg);
394 return E_FAIL;
397 static HRESULT WINAPI
398 PipeBuf_GetDestCtx(
399 LPRPCCHANNELBUFFER iface,DWORD* pdwDestContext,void** ppvDestContext
401 FIXME("(%p,%p), stub!\n",pdwDestContext,ppvDestContext);
402 return E_FAIL;
405 static HRESULT WINAPI
406 PipeBuf_IsConnected(LPRPCCHANNELBUFFER iface) {
407 FIXME("(), stub!\n");
408 return S_OK;
411 static ICOM_VTABLE(IRpcChannelBuffer) pipebufvt = {
412 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
413 PipeBuf_QueryInterface,
414 PipeBuf_AddRef,
415 PipeBuf_Release,
416 PipeBuf_GetBuffer,
417 PipeBuf_SendReceive,
418 PipeBuf_FreeBuffer,
419 PipeBuf_GetDestCtx,
420 PipeBuf_IsConnected
423 HRESULT
424 PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) {
425 wine_marshal_id ourid;
426 DWORD res;
427 HANDLE hPipe;
428 HRESULT hres;
429 PipeBuf *pbuf;
431 hPipe = PIPE_FindByMID(mid);
432 if (hPipe == INVALID_HANDLE_VALUE) {
433 char pipefn[200];
434 sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid);
435 hPipe = CreateFileA(
436 pipefn,
437 GENERIC_READ|GENERIC_WRITE,
439 NULL,
440 OPEN_EXISTING,
444 if (hPipe == INVALID_HANDLE_VALUE) {
445 FIXME("Could not open named pipe %s, le is %lx\n",pipefn,GetLastError());
446 return E_FAIL;
448 hres = PIPE_RegisterPipe(mid, hPipe, FALSE);
449 if (hres) return hres;
450 memset(&ourid,0,sizeof(ourid));
451 ourid.processid = GetCurrentProcessId();
452 if (!WriteFile(hPipe,&ourid,sizeof(ourid),&res,NULL)||(res!=sizeof(ourid))) {
453 ERR("Failed writing startup mid!\n");
454 return E_FAIL;
457 pbuf = (PipeBuf*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PipeBuf));
458 pbuf->lpVtbl = &pipebufvt;
459 pbuf->ref = 1;
460 memcpy(&(pbuf->mid),mid,sizeof(*mid));
461 *pipebuf = (IRpcChannelBuffer*)pbuf;
462 return S_OK;
465 static HRESULT
466 create_server(REFCLSID rclsid) {
467 HKEY key;
468 char buf[200];
469 HRESULT hres = E_UNEXPECTED;
470 char xclsid[80];
471 WCHAR dllName[MAX_PATH+1];
472 DWORD dllNameLen = sizeof(dllName);
473 STARTUPINFOW sinfo;
474 PROCESS_INFORMATION pinfo;
476 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
478 sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
479 hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
481 if (hres != ERROR_SUCCESS)
482 return REGDB_E_CLASSNOTREG;
484 memset(dllName,0,sizeof(dllName));
485 hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen);
486 if (hres)
487 return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
488 RegCloseKey(key);
489 memset(&sinfo,0,sizeof(sinfo));
490 sinfo.cb = sizeof(sinfo);
491 if (!CreateProcessW(NULL,dllName,NULL,NULL,FALSE,0,NULL,NULL,&sinfo,&pinfo))
492 return E_FAIL;
493 return S_OK;
495 /* http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, Figure 4 */
496 HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) {
497 HRESULT hres;
498 HANDLE hPipe;
499 char pipefn[200];
500 DWORD res,bufferlen;
501 char marshalbuffer[200];
502 IStream *pStm;
503 LARGE_INTEGER seekto;
504 ULARGE_INTEGER newpos;
505 int tries = 0;
506 #define MAXTRIES 10000
508 strcpy(pipefn,PIPEPREF);
509 WINE_StringFromCLSID(rclsid,pipefn+strlen(PIPEPREF));
511 while (tries++<MAXTRIES) {
512 hPipe = CreateFileA(
513 pipefn,
514 GENERIC_READ|GENERIC_WRITE,
516 NULL,
517 OPEN_EXISTING,
521 if (hPipe == INVALID_HANDLE_VALUE) {
522 if (tries == 1) {
523 if ((hres = create_server(rclsid)))
524 return hres;
525 Sleep(1000);
526 } else {
527 WARN("Could not open named pipe to broker %s, le is %lx\n",pipefn,GetLastError());
528 Sleep(1000);
530 continue;
532 bufferlen = 0;
533 if (!ReadFile(hPipe,marshalbuffer,sizeof(marshalbuffer),&bufferlen,NULL)) {
534 FIXME("Failed to read marshal id from classfactory of %s.\n",debugstr_guid(rclsid));
535 Sleep(1000);
536 continue;
538 CloseHandle(hPipe);
539 break;
541 if (tries>=MAXTRIES)
542 return E_NOINTERFACE;
543 hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
544 if (hres) return hres;
545 hres = IStream_Write(pStm,marshalbuffer,bufferlen,&res);
546 if (hres) goto out;
547 seekto.s.LowPart = 0;seekto.s.HighPart = 0;
548 hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
549 hres = CoUnmarshalInterface(pStm,&IID_IClassFactory,ppv);
550 out:
551 IStream_Release(pStm);
552 return hres;
556 static void WINAPI
557 PIPE_StartRequestThread(HANDLE xhPipe) {
558 wine_marshal_id remoteid;
559 HRESULT hres;
561 hres = _xread(xhPipe,&remoteid,sizeof(remoteid));
562 if (hres) {
563 ERR("Failed to read remote mid!\n");
564 return;
566 PIPE_RegisterPipe(&remoteid,xhPipe, TRUE);
569 static HRESULT
570 _read_one(wine_pipe *xpipe) {
571 DWORD reqtype;
572 HRESULT hres = S_OK;
573 HANDLE xhPipe = xpipe->hPipe;
575 /*FIXME("%lx %d reading reqtype\n",GetCurrentProcessId(),xhPipe);*/
576 hres = _xread(xhPipe,&reqtype,sizeof(reqtype));
577 if (hres) goto end;
578 EnterCriticalSection(&(xpipe->crit));
579 /*FIXME("%lx got reqtype %ld\n",GetCurrentProcessId(),reqtype);*/
581 if (reqtype == REQTYPE_REQUEST) {
582 wine_rpc_request *xreq;
583 RPC_GetRequest(&xreq);
584 xreq->hPipe = xhPipe;
585 hres = _xread(xhPipe,&(xreq->reqh),sizeof(xreq->reqh));
586 if (hres) goto end;
587 xreq->resph.reqid = xreq->reqh.reqid;
588 xreq->Buffer = HeapAlloc(GetProcessHeap(),0, xreq->reqh.cbBuffer);
589 hres = _xread(xhPipe,xreq->Buffer,xreq->reqh.cbBuffer);
590 if (hres) goto end;
591 xreq->state = REQSTATE_REQ_GOT;
592 goto end;
594 if (reqtype == REQTYPE_RESPONSE) {
595 wine_rpc_response_header resph;
596 int i;
598 hres = _xread(xhPipe,&resph,sizeof(resph));
599 if (hres) goto end;
600 for (i=nrofreqs;i--;) {
601 wine_rpc_request *xreq = reqs[i];
602 if (xreq->state != REQSTATE_REQ_WAITING_FOR_REPLY)
603 continue;
604 if (xreq->reqh.reqid == resph.reqid) {
605 memcpy(&(xreq->resph),&resph,sizeof(resph));
606 xreq->Buffer = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,xreq->Buffer,xreq->resph.cbBuffer);
607 hres = _xread(xhPipe,xreq->Buffer,xreq->resph.cbBuffer);
608 if (hres) goto end;
609 xreq->state = REQSTATE_RESP_GOT;
610 /*PulseEvent(hRpcChanged);*/
611 goto end;
614 ERR("Did not find request for id %lx\n",resph.reqid);
615 hres = S_OK;
616 goto end;
618 ERR("Unknown reqtype %ld\n",reqtype);
619 hres = E_FAIL;
620 end:
621 LeaveCriticalSection(&(xpipe->crit));
622 return hres;
625 static DWORD WINAPI
626 _StubReaderThread(LPVOID param) {
627 wine_pipe *xpipe = (wine_pipe*)param;
628 HANDLE xhPipe = xpipe->hPipe;
629 HRESULT hres;
631 TRACE("STUB reader thread %lx\n",GetCurrentProcessId());
632 while (1) {
633 int i;
634 hres = _read_one(xpipe);
635 if (hres) break;
637 for (i=nrofreqs;i--;) {
638 wine_rpc_request *xreq = reqs[i];
639 if ((xreq->state == REQSTATE_REQ_GOT) && (xreq->hPipe == xhPipe)) {
640 _invoke_onereq(xreq);
644 FIXME("Failed with hres %lx\n",hres);
645 CloseHandle(xhPipe);
646 return 0;
649 static DWORD WINAPI
650 _StubMgrThread(LPVOID param) {
651 char pipefn[200];
652 HANDLE listenPipe;
654 sprintf(pipefn,OLESTUBMGR"_%08lx",GetCurrentProcessId());
655 TRACE("Stub Manager Thread starting on (%s)\n",pipefn);
657 listenPipe = CreateNamedPipeA(
658 pipefn,
659 PIPE_ACCESS_DUPLEX,
660 PIPE_TYPE_BYTE|PIPE_WAIT,
661 PIPE_UNLIMITED_INSTANCES,
662 4096,
663 4096,
664 NMPWAIT_USE_DEFAULT_WAIT,
665 NULL
667 if (listenPipe == INVALID_HANDLE_VALUE) {
668 FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError());
669 return 1; /* permanent failure, so quit stubmgr thread */
672 while (1) {
673 if (!ConnectNamedPipe(listenPipe,NULL)) {
674 ERR("Failure during ConnectNamedPipe %lx!\n",GetLastError());
675 CloseHandle(listenPipe);
676 continue;
678 PIPE_StartRequestThread(listenPipe);
679 listenPipe = CreateNamedPipeA(
680 pipefn,
681 PIPE_ACCESS_DUPLEX,
682 PIPE_TYPE_BYTE|PIPE_WAIT,
683 PIPE_UNLIMITED_INSTANCES,
684 4096,
685 4096,
686 NMPWAIT_USE_DEFAULT_WAIT,
687 NULL
689 if (listenPipe == INVALID_HANDLE_VALUE) {
690 FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError());
691 return 1; /* permanent failure, so quit stubmgr thread */
694 return 0;
697 void
698 STUBMGR_Start() {
699 static BOOL stubMgrRunning = FALSE;
700 DWORD tid;
702 if (!stubMgrRunning) {
703 stubMgrRunning = TRUE;
704 CreateThread(NULL,0,_StubMgrThread,NULL,0,&tid);
705 Sleep(2000); /* actually we just try opening the pipe until it succeeds */