service.cpp revision 8b6d6a8ed111e707923b2f87e4e28304f89773cf
/** @file
*
* Shared Clipboard:
* Host service entry points.
*/
/*
* Copyright (C) 2006-2007 innotek GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include <iprt/critsect.h>
#include "VBoxClipboard.h"
#define VBOX_HGCM_PARM_COUNT(a) ((sizeof (a) - sizeof (((a *)0)->hdr)) / sizeof (HGCMFunctionParameter))
{
}
{
{
return VINF_SUCCESS;
}
return VERR_INVALID_PARAMETER;
}
#if 0
{
}
#endif
{
{
return VINF_SUCCESS;
}
return VERR_INVALID_PARAMETER;
}
static PVBOXHGCMSVCHELPERS g_pHelpers;
static RTCRITSECT critsect;
static PFNHGCMSVCEXT g_pfnExtension;
static void *g_pvExtension;
static VBOXCLIPBOARDCLIENTDATA *g_pClient;
static uint32_t vboxSvcClipboardMode (void)
{
return g_u32Mode;
}
{
switch (u32Mode)
{
break;
default:
}
}
bool vboxSvcClipboardLock (void)
{
}
void vboxSvcClipboardUnlock (void)
{
}
/* Set the HGCM parameters according to pending messages.
* Executed under the clipboard lock.
*/
{
/* Message priority is taken into account. */
{
LogFlow(("vboxSvcClipboardReturnMsg: Quit\n"));
}
else if (pClient->fMsgReadData)
{
pClient->fMsgReadData = false;
}
else if (pClient->fMsgFormats)
{
pClient->fMsgFormats = false;
}
else
{
/* No pending messages. */
LogFlow(("vboxSvcClipboardReturnMsg: no message\n"));
return false;
}
/* Message information assigned. */
return true;
}
void vboxSvcClipboardReportMsg (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats)
{
if (vboxSvcClipboardLock ())
{
switch (u32Msg)
{
{
LogFlow(("vboxSvcClipboardReportMsg: Quit\n"));
} break;
{
{
/* Skip the message. */
break;
}
pClient->fMsgReadData = true;
} break;
{
{
/* Skip the message. */
break;
}
pClient->fMsgFormats = true;
} break;
default:
{
/* Invalid message. */
} break;
}
{
/* The client waits for a responce. */
/* Make a copy of the handle. */
if (fMessageReturned)
{
/* There is a responce. */
}
if (fMessageReturned)
{
LogFlow(("vboxSvcClipboardReportMsg: CallComplete\n"));
}
}
else
{
}
}
}
static int svcInit (void)
{
return vboxClipboardInit ();
}
static DECLCALLBACK(int) svcUnload (void)
{
return VINF_SUCCESS;
}
{
/* Register the client. */
int rc = VINF_SUCCESS;
if (VBOX_SUCCESS (rc))
{
}
return rc;
}
{
return VINF_SUCCESS;
}
void *pvClient,
{
int rc = VINF_SUCCESS;
Log(("svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",
bool fAsynchronousProcessing = false;
#ifdef DEBUG
uint32_t i;
for (i = 0; i < cParms; i++)
{
/** @todo parameters other than 32 bit */
}
#endif
switch (u32Function)
{
{
/* The quest requests a host message. */
Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG\n"));
{
}
)
{
}
else
{
/* Atomically verify the client's state. */
if (vboxSvcClipboardLock ())
{
if (fMessageReturned)
{
/* Just return to the caller. */
}
else
{
/* No event available at the time. Process asynchronously. */
fAsynchronousProcessing = true;
Log(("svcCall: async.\n"));
}
}
else
{
}
}
} break;
{
/* The guest reports that some formats are available. */
Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_FORMATS\n"));
{
}
)
{
}
else
{
if (VBOX_SUCCESS (rc))
{
{
break;
}
if (g_pfnExtension)
{
}
else
{
}
}
}
} break;
{
/* The guest wants to read data in the given format. */
Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_READ_DATA\n"));
{
}
)
{
}
else
{
void *pv;
if (VBOX_SUCCESS (rc))
{
if (VBOX_SUCCESS (rc))
{
{
break;
}
if (g_pfnExtension)
{
if (VBOX_SUCCESS (rc))
{
}
}
else
{
}
if (VBOX_SUCCESS (rc))
{
}
}
}
}
} break;
{
/* The guest writes the requested data. */
Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA\n"));
{
}
)
{
}
else
{
void *pv;
if (VBOX_SUCCESS (rc))
{
if (VBOX_SUCCESS (rc))
{
{
break;
}
if (g_pfnExtension)
{
}
else
{
}
}
}
}
} break;
default:
{
}
}
if (!fAsynchronousProcessing)
{
}
}
/*
* We differentiate between a function handler for the guest and one for the host.
*/
{
int rc = VINF_SUCCESS;
Log(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n",
switch (u32Function)
{
{
Log(("svcCall: VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE\n"));
if (cParms != 1)
{
}
)
{
}
else
{
/* The setter takes care of invalid values. */
}
} break;
default:
break;
}
return rc;
}
{
/* If there are any pending requests, they must be completed here. Since
* the service is single threaded, there could be only requests
* which the service itself has postponed.
*
* HGCM knows that the state is being saved and that the pfnComplete
* calls are just clean ups. These requests are saved by the VMMDev.
*
* When the state will be restored, these requests will be reissued
* by VMMDev. The service therefore must save state as if there were no
* pending request.
*/
/* Save client structure length & contents */
{
g_pHelpers->pfnCallComplete (pClient->async.callHandle, VINF_SUCCESS /* error code is not important here. */);
}
return VINF_SUCCESS;
}
{
/* Existing client can not be in async state yet. */
/* Restore the client data. */
if (len != sizeof(VBOXCLIPBOARDCLIENTDATA))
{
}
/* Verify the loaded clients data and update the pClient. */
{
}
/* Actual host data are to be reported to guest (SYNC). */
return VINF_SUCCESS;
}
static DECLCALLBACK(int) extCallback (uint32_t u32Function, uint32_t u32Format, void *pvData, uint32_t cbData)
{
{
switch (u32Function)
{
{
} break;
{
} break;
default:
return VERR_NOT_SUPPORTED;
}
}
return VINF_SUCCESS;
}
{
if (pfnExtension)
{
/* Install extension. */
}
else
{
if (g_pfnExtension)
{
}
/* Uninstall extension. */
}
return VINF_SUCCESS;
}
{
int rc = VINF_SUCCESS;
if (!ptable)
{
}
else
{
Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
{
}
else
{
/* Service specific initialization. */
}
}
return rc;
}