VirtualBox

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

Last change on this file since 19167 was 18443, checked in by vboxsync, 16 years ago

DrvNamedPipe: Fixed (?) undefined variable in odd error case in drvNamedPipeWrite on windows. Some size_t warnings and hungarian spelling mistakes.

  • 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 *pcbRead)
103{
104 int rc = VINF_SUCCESS;
105 PDRVNAMEDPIPE pThis = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
106 LogFlow(("%s: pvBuf=%p *pcbRead=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbRead, pThis->pszLocation));
107
108 Assert(pvBuf);
109#ifdef RT_OS_WINDOWS
110 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
111 {
112 DWORD cbReallyRead;
113 pThis->OverlappedRead.Offset = 0;
114 pThis->OverlappedRead.OffsetHigh = 0;
115 if (!ReadFile(pThis->NamedPipe, pvBuf, (DWORD)*pcbRead, &cbReallyRead, &pThis->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(pThis->NamedPipe, &pThis->OverlappedRead, &cbReallyRead, TRUE) == FALSE)
136 uError = GetLastError();
137 }
138
139 rc = RTErrConvertFromWin32(uError);
140 Log(("drvNamedPipeRead: ReadFile returned %d (%Rrc)\n", uError, rc));
141 }
142 }
143
144 if (RT_FAILURE(rc))
145 {
146 Log(("drvNamedPipeRead: FileRead returned %Rrc fShutdown=%d\n", rc, pThis->fShutdown));
147 if ( !pThis->fShutdown
148 && ( rc == VERR_EOF
149 || rc == VERR_BROKEN_PIPE
150 )
151 )
152
153 {
154 FlushFileBuffers(pThis->NamedPipe);
155 DisconnectNamedPipe(pThis->NamedPipe);
156 if (!pThis->fIsServer)
157 {
158 CloseHandle(pThis->NamedPipe);
159 pThis->NamedPipe = INVALID_HANDLE_VALUE;
160 }
161 /* pretend success */
162 rc = VINF_SUCCESS;
163 }
164 cbReallyRead = 0;
165 }
166 *pcbRead = (size_t)cbReallyRead;
167 }
168#else /* !RT_OS_WINDOWS */
169 if (pThis->LocalSocket != NIL_RTSOCKET)
170 {
171 ssize_t cbReallyRead;
172 cbReallyRead = recv(pThis->LocalSocket, pvBuf, *pcbRead, 0);
173 if (cbReallyRead == 0)
174 {
175 RTSOCKET tmp = pThis->LocalSocket;
176 pThis->LocalSocket = NIL_RTSOCKET;
177 close(tmp);
178 }
179 else if (cbReallyRead == -1)
180 {
181 cbReallyRead = 0;
182 rc = RTErrConvertFromErrno(errno);
183 }
184 *pcbRead = cbReallyRead;
185 }
186#endif /* !RT_OS_WINDOWS */
187 else
188 {
189 RTThreadSleep(100);
190 *pcbRead = 0;
191 }
192
193 LogFlow(("%s: *pcbRead=%zu returns %Rrc\n", __FUNCTION__, *pcbRead, rc));
194 return rc;
195}
196
197
198/** @copydoc PDMISTREAM::pfnWrite */
199static DECLCALLBACK(int) drvNamedPipeWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
200{
201 int rc = VINF_SUCCESS;
202 PDRVNAMEDPIPE pThis = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
203 LogFlow(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbWrite, pThis->pszLocation));
204
205 Assert(pvBuf);
206#ifdef RT_OS_WINDOWS
207 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
208 {
209 DWORD cbWritten = (DWORD)*pcbWrite;
210 pThis->OverlappedWrite.Offset = 0;
211 pThis->OverlappedWrite.OffsetHigh = 0;
212 if (!WriteFile(pThis->NamedPipe, pvBuf, cbWritten, NULL, &pThis->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 (pretening everything was written). */;
220 }
221 else if (uError != ERROR_IO_PENDING)
222 {
223 rc = RTErrConvertFromWin32(uError);
224 Log(("drvNamedPipeWrite: WriteFile returned %d (%Rrc)\n", uError, rc));
225 cbWritten = 0;
226 }
227 else
228 {
229 /* Wait for the write to complete. */
230 if (GetOverlappedResult(pThis->NamedPipe, &pThis->OverlappedWrite, &cbWritten, TRUE /*bWait*/) == FALSE)
231 rc = RTErrConvertFromWin32(uError = GetLastError());
232 }
233 }
234
235 if (RT_FAILURE(rc))
236 {
237 if ( rc == VERR_EOF
238 || rc == VERR_BROKEN_PIPE)
239 {
240 FlushFileBuffers(pThis->NamedPipe);
241 DisconnectNamedPipe(pThis->NamedPipe);
242 if (!pThis->fIsServer)
243 {
244 CloseHandle(pThis->NamedPipe);
245 pThis->NamedPipe = INVALID_HANDLE_VALUE;
246 }
247 /* pretend success */
248 rc = VINF_SUCCESS;
249 }
250 cbWritten = 0;
251 }
252 *pcbWrite = cbWritten;
253 }
254#else /* !RT_OS_WINDOWS */
255 if (pThis->LocalSocket != NIL_RTSOCKET)
256 {
257 ssize_t cbWritten;
258 cbWritten = send(pThis->LocalSocket, pvBuf, *pcbWrite, 0);
259 if (cbWritten == 0)
260 {
261 RTSOCKET tmp = pThis->LocalSocket;
262 pThis->LocalSocket = NIL_RTSOCKET;
263 close(tmp);
264 }
265 else if (cbWritten == -1)
266 {
267 cbWritten = 0;
268 rc = RTErrConvertFromErrno(errno);
269 }
270 *pcbWrite = cbWritten;
271 }
272#endif /* !RT_OS_WINDOWS */
273
274 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
275 return rc;
276}
277
278
279/**
280 * Queries an interface to the driver.
281 *
282 * @returns Pointer to interface.
283 * @returns NULL if the interface was not supported by the driver.
284 * @param pInterface Pointer to this interface structure.
285 * @param enmInterface The requested interface identification.
286 * @thread Any thread.
287 */
288static DECLCALLBACK(void *) drvNamedPipeQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
289{
290 PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
291 PDRVNAMEDPIPE pDrv = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
292 switch (enmInterface)
293 {
294 case PDMINTERFACE_BASE:
295 return &pDrvIns->IBase;
296 case PDMINTERFACE_STREAM:
297 return &pDrv->IStream;
298 default:
299 return NULL;
300 }
301}
302
303
304/* -=-=-=-=- listen thread -=-=-=-=- */
305
306/**
307 * Receive thread loop.
308 *
309 * @returns 0 on success.
310 * @param ThreadSelf Thread handle to this thread.
311 * @param pvUser User argument.
312 */
313static DECLCALLBACK(int) drvNamedPipeListenLoop(RTTHREAD ThreadSelf, void *pvUser)
314{
315 PDRVNAMEDPIPE pThis = (PDRVNAMEDPIPE)pvUser;
316 int rc = VINF_SUCCESS;
317#ifdef RT_OS_WINDOWS
318 HANDLE NamedPipe = pThis->NamedPipe;
319 HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, 0);
320#endif
321
322 while (RT_LIKELY(!pThis->fShutdown))
323 {
324#ifdef RT_OS_WINDOWS
325 OVERLAPPED overlapped;
326
327 memset(&overlapped, 0, sizeof(overlapped));
328 overlapped.hEvent = hEvent;
329
330 BOOL fConnected = ConnectNamedPipe(NamedPipe, &overlapped);
331 if ( !fConnected
332 && !pThis->fShutdown)
333 {
334 DWORD hrc = GetLastError();
335
336 if (hrc == ERROR_IO_PENDING)
337 {
338 DWORD dummy;
339
340 hrc = 0;
341 if (GetOverlappedResult(pThis->NamedPipe, &overlapped, &dummy, TRUE) == FALSE)
342 hrc = GetLastError();
343
344 }
345
346 if (pThis->fShutdown)
347 break;
348
349 if (hrc == ERROR_PIPE_CONNECTED)
350 {
351 RTSemEventWait(pThis->ListenSem, 250);
352 }
353 else if (hrc != ERROR_SUCCESS)
354 {
355 rc = RTErrConvertFromWin32(hrc);
356 LogRel(("NamedPipe%d: ConnectNamedPipe failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
357 break;
358 }
359 }
360#else /* !RT_OS_WINDOWS */
361 if (listen(pThis->LocalSocketServer, 0) == -1)
362 {
363 rc = RTErrConvertFromErrno(errno);
364 LogRel(("NamedPipe%d: listen failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
365 break;
366 }
367 int s = accept(pThis->LocalSocketServer, NULL, NULL);
368 if (s == -1)
369 {
370 rc = RTErrConvertFromErrno(errno);
371 LogRel(("NamedPipe%d: accept failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
372 break;
373 }
374 else
375 {
376 if (pThis->LocalSocket != NIL_RTSOCKET)
377 {
378 LogRel(("NamedPipe%d: only single connection supported\n", pThis->pDrvIns->iInstance));
379 close(s);
380 }
381 else
382 pThis->LocalSocket = s;
383 }
384#endif /* !RT_OS_WINDOWS */
385 }
386
387#ifdef RT_OS_WINDOWS
388 CloseHandle(hEvent);
389#endif
390 pThis->ListenThread = NIL_RTTHREAD;
391 return VINF_SUCCESS;
392}
393
394
395/**
396 * Construct a named pipe stream driver instance.
397 *
398 * @returns VBox status.
399 * @param pDrvIns The driver instance data.
400 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
401 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
402 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
403 * iInstance it's expected to be used a bit in this function.
404 */
405static DECLCALLBACK(int) drvNamedPipeConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
406{
407 int rc;
408 char *pszLocation = NULL;
409 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
410
411 /*
412 * Init the static parts.
413 */
414 pThis->pDrvIns = pDrvIns;
415 pThis->pszLocation = NULL;
416 pThis->fIsServer = false;
417#ifdef RT_OS_WINDOWS
418 pThis->NamedPipe = INVALID_HANDLE_VALUE;
419#else /* !RT_OS_WINDOWS */
420 pThis->LocalSocketServer = NIL_RTSOCKET;
421 pThis->LocalSocket = NIL_RTSOCKET;
422#endif /* !RT_OS_WINDOWS */
423 pThis->ListenThread = NIL_RTTHREAD;
424 pThis->fShutdown = false;
425 /* IBase */
426 pDrvIns->IBase.pfnQueryInterface = drvNamedPipeQueryInterface;
427 /* IStream */
428 pThis->IStream.pfnRead = drvNamedPipeRead;
429 pThis->IStream.pfnWrite = drvNamedPipeWrite;
430
431 /*
432 * Read the configuration.
433 */
434 if (!CFGMR3AreValuesValid(pCfgHandle, "Location\0IsServer\0"))
435 {
436 rc = VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
437 goto out;
438 }
439
440 rc = CFGMR3QueryStringAlloc(pCfgHandle, "Location", &pszLocation);
441 if (RT_FAILURE(rc))
442 {
443 AssertMsgFailed(("Configuration error: query \"Location\" resulted in %Rrc.\n", rc));
444 goto out;
445 }
446 pThis->pszLocation = pszLocation;
447
448 bool fIsServer;
449 rc = CFGMR3QueryBool(pCfgHandle, "IsServer", &fIsServer);
450 if (RT_FAILURE(rc))
451 {
452 AssertMsgFailed(("Configuration error: query \"IsServer\" resulted in %Rrc.\n", rc));
453 goto out;
454 }
455 pThis->fIsServer = fIsServer;
456
457#ifdef RT_OS_WINDOWS
458 if (fIsServer)
459 {
460 HANDLE hPipe = CreateNamedPipe(pThis->pszLocation, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 32, 32, 10000, NULL);
461 if (hPipe == INVALID_HANDLE_VALUE)
462 {
463 rc = RTErrConvertFromWin32(GetLastError());
464 LogRel(("NamedPipe%d: CreateNamedPipe failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
465 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create named pipe %s"), pDrvIns->iInstance, pszLocation);
466 }
467 pThis->NamedPipe = hPipe;
468
469 rc = RTSemEventCreate(&pThis->ListenSem);
470 AssertRC(rc);
471
472 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe");
473 if RT_FAILURE(rc)
474 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance);
475
476 }
477 else
478 {
479 /* Connect to the named pipe. */
480 HANDLE hPipe = CreateFile(pThis->pszLocation, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
481 if (hPipe == INVALID_HANDLE_VALUE)
482 {
483 rc = RTErrConvertFromWin32(GetLastError());
484 LogRel(("NamedPipe%d: CreateFile failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
485 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to connect to named pipe %s"), pDrvIns->iInstance, pszLocation);
486 }
487 pThis->NamedPipe = hPipe;
488 }
489
490 memset(&pThis->OverlappedWrite, 0, sizeof(pThis->OverlappedWrite));
491 memset(&pThis->OverlappedRead, 0, sizeof(pThis->OverlappedRead));
492 pThis->OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
493 pThis->OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
494#else /* !RT_OS_WINDOWS */
495 int s;
496 struct sockaddr_un addr;
497
498 if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
499 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to create local socket"), pDrvIns->iInstance);
500
501 memset(&addr, 0, sizeof(addr));
502 addr.sun_family = AF_UNIX;
503 strncpy(addr.sun_path, pszLocation, sizeof(addr.sun_path)-1);
504
505 if (fIsServer)
506 {
507 /* Bind address to the local socket. */
508 RTFileDelete(pszLocation);
509 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
510 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to bind to local socket %s"), pDrvIns->iInstance, pszLocation);
511 pThis->LocalSocketServer = s;
512 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe");
513 if RT_FAILURE(rc)
514 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance);
515 }
516 else
517 {
518 /* Connect to the local socket. */
519 if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
520 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to connect to local socket %s"), pDrvIns->iInstance, pszLocation);
521 pThis->LocalSocket = s;
522 }
523#endif /* !RT_OS_WINDOWS */
524
525out:
526 if (RT_FAILURE(rc))
527 {
528 if (pszLocation)
529 MMR3HeapFree(pszLocation);
530 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to initialize"), pDrvIns->iInstance);
531 }
532
533 LogFlow(("drvNamedPipeConstruct: location %s isServer %d\n", pszLocation, fIsServer));
534 LogRel(("NamedPipe: location %s, %s\n", pszLocation, fIsServer ? "server" : "client"));
535 return VINF_SUCCESS;
536}
537
538
539/**
540 * Destruct a named pipe stream driver instance.
541 *
542 * Most VM resources are freed by the VM. This callback is provided so that
543 * any non-VM resources can be freed correctly.
544 *
545 * @param pDrvIns The driver instance data.
546 */
547static DECLCALLBACK(void) drvNamedPipeDestruct(PPDMDRVINS pDrvIns)
548{
549 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
550 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
551
552 if (pThis->ListenThread)
553 {
554 RTThreadWait(pThis->ListenThread, 250, NULL);
555 if (pThis->ListenThread != NIL_RTTHREAD)
556 LogRel(("NamedPipe%d: listen thread did not terminate\n", pDrvIns->iInstance));
557 }
558
559 if (pThis->pszLocation)
560 MMR3HeapFree(pThis->pszLocation);
561}
562
563
564/**
565 * Power off a named pipe stream driver instance.
566 *
567 * This does most of the destruction work, to avoid ordering dependencies.
568 *
569 * @param pDrvIns The driver instance data.
570 */
571static DECLCALLBACK(void) drvNamedPipePowerOff(PPDMDRVINS pDrvIns)
572{
573 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
574 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
575
576 pThis->fShutdown = true;
577
578#ifdef RT_OS_WINDOWS
579 if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
580 {
581 if (pThis->fIsServer)
582 {
583 FlushFileBuffers(pThis->NamedPipe);
584 DisconnectNamedPipe(pThis->NamedPipe);
585 }
586
587 CloseHandle(pThis->NamedPipe);
588 pThis->NamedPipe = INVALID_HANDLE_VALUE;
589 CloseHandle(pThis->OverlappedRead.hEvent);
590 CloseHandle(pThis->OverlappedWrite.hEvent);
591 }
592 if (pThis->fIsServer)
593 {
594 /* Wake up listen thread */
595 RTSemEventSignal(pThis->ListenSem);
596 RTSemEventDestroy(pThis->ListenSem);
597 }
598#else /* !RT_OS_WINDOWS */
599 if (pThis->fIsServer)
600 {
601 if (pThis->LocalSocketServer != NIL_RTSOCKET)
602 close(pThis->LocalSocketServer);
603 if (pThis->pszLocation)
604 RTFileDelete(pThis->pszLocation);
605 }
606 else
607 {
608 if (pThis->LocalSocket != NIL_RTSOCKET)
609 close(pThis->LocalSocket);
610 }
611#endif /* !RT_OS_WINDOWS */
612}
613
614
615/**
616 * Named pipe driver registration record.
617 */
618const PDMDRVREG g_DrvNamedPipe =
619{
620 /* u32Version */
621 PDM_DRVREG_VERSION,
622 /* szDriverName */
623 "NamedPipe",
624 /* pszDescription */
625 "Named Pipe stream driver.",
626 /* fFlags */
627 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
628 /* fClass. */
629 PDM_DRVREG_CLASS_STREAM,
630 /* cMaxInstances */
631 ~0,
632 /* cbInstance */
633 sizeof(DRVNAMEDPIPE),
634 /* pfnConstruct */
635 drvNamedPipeConstruct,
636 /* pfnDestruct */
637 drvNamedPipeDestruct,
638 /* pfnIOCtl */
639 NULL,
640 /* pfnPowerOn */
641 NULL,
642 /* pfnReset */
643 NULL,
644 /* pfnSuspend */
645 NULL,
646 /* pfnResume */
647 NULL,
648 /* pfnDetach */
649 NULL,
650 /* pfnPowerOff */
651 drvNamedPipePowerOff,
652};
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