VirtualBox

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

Last change on this file since 11136 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

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

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