VirtualBox

source: vbox/trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp@ 25985

Last change on this file since 25985 was 25985, checked in by vboxsync, 15 years ago

pdmifs.h: the final batch of refactored interface ID code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.8 KB
Line 
1/* $Id: DrvNamedPipe.cpp 25985 2010-01-23 00:51:04Z vboxsync $ */
2/** @file
3 * VBox stream drivers: Named pipe stream
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DRV_NAMEDPIPE
27#include <VBox/pdmdrv.h>
28#include <iprt/assert.h>
29#include <iprt/file.h>
30#include <iprt/stream.h>
31#include <iprt/alloc.h>
32#include <iprt/string.h>
33#include <iprt/semaphore.h>
34#include <iprt/uuid.h>
35
36#include "Builtins.h"
37
38#ifdef RT_OS_WINDOWS
39# include <windows.h>
40#else /* !RT_OS_WINDOWS */
41# include <errno.h>
42# include <unistd.h>
43# include <sys/types.h>
44# include <sys/socket.h>
45# include <sys/un.h>
46#endif /* !RT_OS_WINDOWS */
47
48
49/*******************************************************************************
50* Defined Constants And Macros *
51*******************************************************************************/
52/** Converts a pointer to DRVNAMEDPIPE::IMedia to a PDRVNAMEDPIPE. */
53#define PDMISTREAM_2_DRVNAMEDPIPE(pInterface) ( (PDRVNAMEDPIPE)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAMEDPIPE, IStream)) )
54
55/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
56#define PDMIBASE_2_DRVINS(pInterface) ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
57
58
59/*******************************************************************************
60* Structures and Typedefs *
61*******************************************************************************/
62/**
63 * Named pipe driver instance data.
64 *
65 * @implements PDMISTREAM
66 */
67typedef struct DRVNAMEDPIPE
68{
69 /** The stream interface. */
70 PDMISTREAM IStream;
71 /** Pointer to the driver instance. */
72 PPDMDRVINS pDrvIns;
73 /** Pointer to the named pipe file name. (Freed by MM) */
74 char *pszLocation;
75 /** Flag whether VirtualBox represents the server or client side. */
76 bool fIsServer;
77#ifdef RT_OS_WINDOWS
78 /* File handle of the named pipe. */
79 HANDLE NamedPipe;
80 /* Overlapped structure for writes. */
81 OVERLAPPED OverlappedWrite;
82 /* Overlapped structure for reads. */
83 OVERLAPPED OverlappedRead;
84 /* Listen thread wakeup semaphore */
85 RTSEMEVENT ListenSem;
86#else /* !RT_OS_WINDOWS */
87 /** Socket handle of the local socket for server. */
88 RTSOCKET LocalSocketServer;
89 /** Socket handle of the local socket. */
90 RTSOCKET LocalSocket;
91#endif /* !RT_OS_WINDOWS */
92 /** Thread for listening for new connections. */
93 RTTHREAD ListenThread;
94 /** Flag to signal listening thread to shut down. */
95 bool fShutdown;
96} DRVNAMEDPIPE, *PDRVNAMEDPIPE;
97
98
99/*******************************************************************************
100* Internal Functions *
101*******************************************************************************/
102
103
104/** @copydoc PDMISTREAM::pfnRead */
105static DECLCALLBACK(int) drvNamedPipeRead(PPDMISTREAM pInterface, void *pvBuf, size_t *pcbRead)
106{
107 int rc = VINF_SUCCESS;
108 PDRVNAMEDPIPE pThis = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
109 LogFlow(("%s: pvBuf=%p *pcbRead=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbRead, pThis->pszLocation));
110
111 Assert(pvBuf);
112#ifdef RT_OS_WINDOWS
113 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
114 {
115 DWORD cbReallyRead;
116 pThis->OverlappedRead.Offset = 0;
117 pThis->OverlappedRead.OffsetHigh = 0;
118 if (!ReadFile(pThis->NamedPipe, pvBuf, (DWORD)*pcbRead, &cbReallyRead, &pThis->OverlappedRead))
119 {
120 DWORD uError = GetLastError();
121
122 if ( uError == ERROR_PIPE_LISTENING
123 || uError == ERROR_PIPE_NOT_CONNECTED)
124 {
125 /* No connection yet/anymore */
126 cbReallyRead = 0;
127
128 /* wait a bit or else we'll be called right back. */
129 RTThreadSleep(100);
130 }
131 else
132 {
133 if (uError == ERROR_IO_PENDING)
134 {
135 uError = 0;
136
137 /* Wait for incoming bytes. */
138 if (GetOverlappedResult(pThis->NamedPipe, &pThis->OverlappedRead, &cbReallyRead, TRUE) == FALSE)
139 uError = GetLastError();
140 }
141
142 rc = RTErrConvertFromWin32(uError);
143 Log(("drvNamedPipeRead: ReadFile returned %d (%Rrc)\n", uError, rc));
144 }
145 }
146
147 if (RT_FAILURE(rc))
148 {
149 Log(("drvNamedPipeRead: FileRead returned %Rrc fShutdown=%d\n", rc, pThis->fShutdown));
150 if ( !pThis->fShutdown
151 && ( rc == VERR_EOF
152 || rc == VERR_BROKEN_PIPE
153 )
154 )
155
156 {
157 FlushFileBuffers(pThis->NamedPipe);
158 DisconnectNamedPipe(pThis->NamedPipe);
159 if (!pThis->fIsServer)
160 {
161 CloseHandle(pThis->NamedPipe);
162 pThis->NamedPipe = INVALID_HANDLE_VALUE;
163 }
164 /* pretend success */
165 rc = VINF_SUCCESS;
166 }
167 cbReallyRead = 0;
168 }
169 *pcbRead = (size_t)cbReallyRead;
170 }
171#else /* !RT_OS_WINDOWS */
172 if (pThis->LocalSocket != NIL_RTSOCKET)
173 {
174 ssize_t cbReallyRead;
175 cbReallyRead = recv(pThis->LocalSocket, pvBuf, *pcbRead, 0);
176 if (cbReallyRead == 0)
177 {
178 RTSOCKET tmp = pThis->LocalSocket;
179 pThis->LocalSocket = NIL_RTSOCKET;
180 close(tmp);
181 }
182 else if (cbReallyRead == -1)
183 {
184 cbReallyRead = 0;
185 rc = RTErrConvertFromErrno(errno);
186 }
187 *pcbRead = cbReallyRead;
188 }
189#endif /* !RT_OS_WINDOWS */
190 else
191 {
192 RTThreadSleep(100);
193 *pcbRead = 0;
194 }
195
196 LogFlow(("%s: *pcbRead=%zu returns %Rrc\n", __FUNCTION__, *pcbRead, rc));
197 return rc;
198}
199
200
201/** @copydoc PDMISTREAM::pfnWrite */
202static DECLCALLBACK(int) drvNamedPipeWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
203{
204 int rc = VINF_SUCCESS;
205 PDRVNAMEDPIPE pThis = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
206 LogFlow(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbWrite, pThis->pszLocation));
207
208 Assert(pvBuf);
209#ifdef RT_OS_WINDOWS
210 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
211 {
212 DWORD cbWritten = (DWORD)*pcbWrite;
213 pThis->OverlappedWrite.Offset = 0;
214 pThis->OverlappedWrite.OffsetHigh = 0;
215 if (!WriteFile(pThis->NamedPipe, pvBuf, cbWritten, NULL, &pThis->OverlappedWrite))
216 {
217 DWORD uError = GetLastError();
218
219 if ( uError == ERROR_PIPE_LISTENING
220 || uError == ERROR_PIPE_NOT_CONNECTED)
221 {
222 /* No connection yet/anymore; just discard the write (pretening everything was written). */;
223 }
224 else if (uError != ERROR_IO_PENDING)
225 {
226 rc = RTErrConvertFromWin32(uError);
227 Log(("drvNamedPipeWrite: WriteFile returned %d (%Rrc)\n", uError, rc));
228 cbWritten = 0;
229 }
230 else
231 {
232 /* Wait for the write to complete. */
233 if (GetOverlappedResult(pThis->NamedPipe, &pThis->OverlappedWrite, &cbWritten, TRUE /*bWait*/) == FALSE)
234 rc = RTErrConvertFromWin32(uError = GetLastError());
235 }
236 }
237
238 if (RT_FAILURE(rc))
239 {
240 if ( rc == VERR_EOF
241 || rc == VERR_BROKEN_PIPE)
242 {
243 FlushFileBuffers(pThis->NamedPipe);
244 DisconnectNamedPipe(pThis->NamedPipe);
245 if (!pThis->fIsServer)
246 {
247 CloseHandle(pThis->NamedPipe);
248 pThis->NamedPipe = INVALID_HANDLE_VALUE;
249 }
250 /* pretend success */
251 rc = VINF_SUCCESS;
252 }
253 cbWritten = 0;
254 }
255 *pcbWrite = cbWritten;
256 }
257#else /* !RT_OS_WINDOWS */
258 if (pThis->LocalSocket != NIL_RTSOCKET)
259 {
260 ssize_t cbWritten;
261 cbWritten = send(pThis->LocalSocket, pvBuf, *pcbWrite, 0);
262 if (cbWritten == 0)
263 {
264 RTSOCKET tmp = pThis->LocalSocket;
265 pThis->LocalSocket = NIL_RTSOCKET;
266 close(tmp);
267 }
268 else if (cbWritten == -1)
269 {
270 cbWritten = 0;
271 rc = RTErrConvertFromErrno(errno);
272 }
273 *pcbWrite = cbWritten;
274 }
275#endif /* !RT_OS_WINDOWS */
276
277 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
278 return rc;
279}
280
281
282/**
283 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
284 */
285static DECLCALLBACK(void *) drvNamedPipeQueryInterface(PPDMIBASE pInterface, const char *pszIID)
286{
287 PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
288 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
289 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
290 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISTREAM, &pThis->IStream);
291 return NULL;
292}
293
294
295/* -=-=-=-=- listen thread -=-=-=-=- */
296
297/**
298 * Receive thread loop.
299 *
300 * @returns 0 on success.
301 * @param ThreadSelf Thread handle to this thread.
302 * @param pvUser User argument.
303 */
304static DECLCALLBACK(int) drvNamedPipeListenLoop(RTTHREAD ThreadSelf, void *pvUser)
305{
306 PDRVNAMEDPIPE pThis = (PDRVNAMEDPIPE)pvUser;
307 int rc = VINF_SUCCESS;
308#ifdef RT_OS_WINDOWS
309 HANDLE NamedPipe = pThis->NamedPipe;
310 HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, 0);
311#endif
312
313 while (RT_LIKELY(!pThis->fShutdown))
314 {
315#ifdef RT_OS_WINDOWS
316 OVERLAPPED overlapped;
317
318 memset(&overlapped, 0, sizeof(overlapped));
319 overlapped.hEvent = hEvent;
320
321 BOOL fConnected = ConnectNamedPipe(NamedPipe, &overlapped);
322 if ( !fConnected
323 && !pThis->fShutdown)
324 {
325 DWORD hrc = GetLastError();
326
327 if (hrc == ERROR_IO_PENDING)
328 {
329 DWORD dummy;
330
331 hrc = 0;
332 if (GetOverlappedResult(pThis->NamedPipe, &overlapped, &dummy, TRUE) == FALSE)
333 hrc = GetLastError();
334
335 }
336
337 if (pThis->fShutdown)
338 break;
339
340 if (hrc == ERROR_PIPE_CONNECTED)
341 {
342 RTSemEventWait(pThis->ListenSem, 250);
343 }
344 else if (hrc != ERROR_SUCCESS)
345 {
346 rc = RTErrConvertFromWin32(hrc);
347 LogRel(("NamedPipe%d: ConnectNamedPipe failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
348 break;
349 }
350 }
351#else /* !RT_OS_WINDOWS */
352 if (listen(pThis->LocalSocketServer, 0) == -1)
353 {
354 rc = RTErrConvertFromErrno(errno);
355 LogRel(("NamedPipe%d: listen failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
356 break;
357 }
358 int s = accept(pThis->LocalSocketServer, NULL, NULL);
359 if (s == -1)
360 {
361 rc = RTErrConvertFromErrno(errno);
362 LogRel(("NamedPipe%d: accept failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
363 break;
364 }
365 else
366 {
367 if (pThis->LocalSocket != NIL_RTSOCKET)
368 {
369 LogRel(("NamedPipe%d: only single connection supported\n", pThis->pDrvIns->iInstance));
370 close(s);
371 }
372 else
373 pThis->LocalSocket = s;
374 }
375#endif /* !RT_OS_WINDOWS */
376 }
377
378#ifdef RT_OS_WINDOWS
379 CloseHandle(hEvent);
380#endif
381 pThis->ListenThread = NIL_RTTHREAD;
382 return VINF_SUCCESS;
383}
384
385
386/**
387 * Construct a named pipe stream driver instance.
388 *
389 * @copydoc FNPDMDRVCONSTRUCT
390 */
391static DECLCALLBACK(int) drvNamedPipeConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
392{
393 int rc;
394 char *pszLocation = NULL;
395 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
396
397 /*
398 * Init the static parts.
399 */
400 pThis->pDrvIns = pDrvIns;
401 pThis->pszLocation = NULL;
402 pThis->fIsServer = false;
403#ifdef RT_OS_WINDOWS
404 pThis->NamedPipe = INVALID_HANDLE_VALUE;
405#else /* !RT_OS_WINDOWS */
406 pThis->LocalSocketServer = NIL_RTSOCKET;
407 pThis->LocalSocket = NIL_RTSOCKET;
408#endif /* !RT_OS_WINDOWS */
409 pThis->ListenThread = NIL_RTTHREAD;
410 pThis->fShutdown = false;
411 /* IBase */
412 pDrvIns->IBase.pfnQueryInterface = drvNamedPipeQueryInterface;
413 /* IStream */
414 pThis->IStream.pfnRead = drvNamedPipeRead;
415 pThis->IStream.pfnWrite = drvNamedPipeWrite;
416
417 /*
418 * Read the configuration.
419 */
420 if (!CFGMR3AreValuesValid(pCfgHandle, "Location\0IsServer\0"))
421 {
422 rc = VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
423 goto out;
424 }
425
426 rc = CFGMR3QueryStringAlloc(pCfgHandle, "Location", &pszLocation);
427 if (RT_FAILURE(rc))
428 {
429 AssertMsgFailed(("Configuration error: query \"Location\" resulted in %Rrc.\n", rc));
430 goto out;
431 }
432 pThis->pszLocation = pszLocation;
433
434 bool fIsServer;
435 rc = CFGMR3QueryBool(pCfgHandle, "IsServer", &fIsServer);
436 if (RT_FAILURE(rc))
437 {
438 AssertMsgFailed(("Configuration error: query \"IsServer\" resulted in %Rrc.\n", rc));
439 goto out;
440 }
441 pThis->fIsServer = fIsServer;
442
443#ifdef RT_OS_WINDOWS
444 if (fIsServer)
445 {
446 HANDLE hPipe = CreateNamedPipe(pThis->pszLocation, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 32, 32, 10000, NULL);
447 if (hPipe == INVALID_HANDLE_VALUE)
448 {
449 rc = RTErrConvertFromWin32(GetLastError());
450 LogRel(("NamedPipe%d: CreateNamedPipe failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
451 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create named pipe %s"), pDrvIns->iInstance, pszLocation);
452 }
453 pThis->NamedPipe = hPipe;
454
455 rc = RTSemEventCreate(&pThis->ListenSem);
456 AssertRC(rc);
457
458 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe");
459 if RT_FAILURE(rc)
460 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance);
461
462 }
463 else
464 {
465 /* Connect to the named pipe. */
466 HANDLE hPipe = CreateFile(pThis->pszLocation, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
467 if (hPipe == INVALID_HANDLE_VALUE)
468 {
469 rc = RTErrConvertFromWin32(GetLastError());
470 LogRel(("NamedPipe%d: CreateFile failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
471 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to connect to named pipe %s"), pDrvIns->iInstance, pszLocation);
472 }
473 pThis->NamedPipe = hPipe;
474 }
475
476 memset(&pThis->OverlappedWrite, 0, sizeof(pThis->OverlappedWrite));
477 memset(&pThis->OverlappedRead, 0, sizeof(pThis->OverlappedRead));
478 pThis->OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
479 pThis->OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
480#else /* !RT_OS_WINDOWS */
481 int s;
482 struct sockaddr_un addr;
483
484 if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
485 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to create local socket"), pDrvIns->iInstance);
486
487 memset(&addr, 0, sizeof(addr));
488 addr.sun_family = AF_UNIX;
489 strncpy(addr.sun_path, pszLocation, sizeof(addr.sun_path)-1);
490
491 if (fIsServer)
492 {
493 /* Bind address to the local socket. */
494 RTFileDelete(pszLocation);
495 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
496 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to bind to local socket %s"), pDrvIns->iInstance, pszLocation);
497 pThis->LocalSocketServer = s;
498 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe");
499 if RT_FAILURE(rc)
500 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance);
501 }
502 else
503 {
504 /* Connect to the local socket. */
505 if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
506 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to connect to local socket %s"), pDrvIns->iInstance, pszLocation);
507 pThis->LocalSocket = s;
508 }
509#endif /* !RT_OS_WINDOWS */
510
511out:
512 if (RT_FAILURE(rc))
513 {
514 if (pszLocation)
515 MMR3HeapFree(pszLocation);
516 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to initialize"), pDrvIns->iInstance);
517 }
518
519 LogFlow(("drvNamedPipeConstruct: location %s isServer %d\n", pszLocation, fIsServer));
520 LogRel(("NamedPipe: location %s, %s\n", pszLocation, fIsServer ? "server" : "client"));
521 return VINF_SUCCESS;
522}
523
524
525/**
526 * Destruct a named pipe stream driver instance.
527 *
528 * Most VM resources are freed by the VM. This callback is provided so that
529 * any non-VM resources can be freed correctly.
530 *
531 * @param pDrvIns The driver instance data.
532 */
533static DECLCALLBACK(void) drvNamedPipeDestruct(PPDMDRVINS pDrvIns)
534{
535 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
536 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
537
538 if (pThis->ListenThread)
539 {
540 RTThreadWait(pThis->ListenThread, 250, NULL);
541 if (pThis->ListenThread != NIL_RTTHREAD)
542 LogRel(("NamedPipe%d: listen thread did not terminate\n", pDrvIns->iInstance));
543 }
544
545 if (pThis->pszLocation)
546 MMR3HeapFree(pThis->pszLocation);
547}
548
549
550/**
551 * Power off a named pipe stream driver instance.
552 *
553 * This does most of the destruction work, to avoid ordering dependencies.
554 *
555 * @param pDrvIns The driver instance data.
556 */
557static DECLCALLBACK(void) drvNamedPipePowerOff(PPDMDRVINS pDrvIns)
558{
559 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
560 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
561
562 pThis->fShutdown = true;
563
564#ifdef RT_OS_WINDOWS
565 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
566 {
567 if (pThis->fIsServer)
568 {
569 FlushFileBuffers(pThis->NamedPipe);
570 DisconnectNamedPipe(pThis->NamedPipe);
571 }
572
573 CloseHandle(pThis->NamedPipe);
574 pThis->NamedPipe = INVALID_HANDLE_VALUE;
575 CloseHandle(pThis->OverlappedRead.hEvent);
576 CloseHandle(pThis->OverlappedWrite.hEvent);
577 }
578 if (pThis->fIsServer)
579 {
580 /* Wake up listen thread */
581 RTSemEventSignal(pThis->ListenSem);
582 RTSemEventDestroy(pThis->ListenSem);
583 }
584#else /* !RT_OS_WINDOWS */
585 if (pThis->fIsServer)
586 {
587 if (pThis->LocalSocketServer != NIL_RTSOCKET)
588 close(pThis->LocalSocketServer);
589 if (pThis->pszLocation)
590 RTFileDelete(pThis->pszLocation);
591 }
592 else
593 {
594 if (pThis->LocalSocket != NIL_RTSOCKET)
595 close(pThis->LocalSocket);
596 }
597#endif /* !RT_OS_WINDOWS */
598}
599
600
601/**
602 * Named pipe driver registration record.
603 */
604const PDMDRVREG g_DrvNamedPipe =
605{
606 /* u32Version */
607 PDM_DRVREG_VERSION,
608 /* szDriverName */
609 "NamedPipe",
610 /* szRCMod */
611 "",
612 /* szR0Mod */
613 "",
614 /* pszDescription */
615 "Named Pipe stream driver.",
616 /* fFlags */
617 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
618 /* fClass. */
619 PDM_DRVREG_CLASS_STREAM,
620 /* cMaxInstances */
621 ~0,
622 /* cbInstance */
623 sizeof(DRVNAMEDPIPE),
624 /* pfnConstruct */
625 drvNamedPipeConstruct,
626 /* pfnDestruct */
627 drvNamedPipeDestruct,
628 /* pfnRelocate */
629 NULL,
630 /* pfnIOCtl */
631 NULL,
632 /* pfnPowerOn */
633 NULL,
634 /* pfnReset */
635 NULL,
636 /* pfnSuspend */
637 NULL,
638 /* pfnResume */
639 NULL,
640 /* pfnAttach */
641 NULL,
642 /* pfnDetach */
643 NULL,
644 /* pfnPowerOff */
645 drvNamedPipePowerOff,
646 /* pfnSoftReset */
647 NULL,
648 /* u32EndVersion */
649 PDM_DRVREG_VERSION
650};
651
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette