721
/** This structure corresponds to the original layout of the
722
* VBOXCLIPBOARDCLIENTDATA structure. As the structure was saved as a whole
723
* when saving state, we need to remember it forever in order to preserve
725
* @todo the first person who needs to make an incompatible change to the
726
* saved state should switch to saving individual data members. So far,
727
* there are only three we care about anyway! */
728
typedef struct _CLIPSAVEDSTATEDATA
722
* SSM descriptor table for the VBOXCLIPBOARDCLIENTDATA structure.
724
static SSMFIELD const g_aClipboardClientDataFields[] =
730
struct _CLIPSAVEDSTATEDATA *pNext;
731
struct _CLIPSAVEDSTATEDATA *pPrev;
733
VBOXCLIPBOARDCONTEXT *pCtx;
735
uint32_t u32ClientID;
737
bool fAsync: 1; /* Guest is waiting for a message. */
740
bool fMsgReadData: 1;
744
VBOXHGCMCALLHANDLE callHandle;
745
VBOXHGCMSVCPARM *paParms;
754
uint32_t u32AvailableFormats;
755
uint32_t u32RequestedFormat;
757
} CLIPSAVEDSTATEDATA;
726
SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32ClientID), /* for validation purposes */
727
SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgQuit),
728
SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgReadData),
729
SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgFormats),
730
SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32RequestedFormat),
731
SSMFIELD_ENTRY_TERM()
759
734
static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
769
744
* by VMMDev. The service therefore must save state as if there were no
770
745
* pending request.
772
LogRel2(("svcSaveState: u32ClientID = %d\n", u32ClientID));
747
LogRel2 (("svcSaveState: u32ClientID = %d\n", u32ClientID));
774
749
VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
776
CLIPSAVEDSTATEDATA savedState = { 0 };
777
/* Save client structure length & contents */
778
int rc = SSMR3PutU32(pSSM, sizeof(savedState));
779
AssertRCReturn(rc, rc);
781
savedState.u32ClientID = pClient->u32ClientID;
782
savedState.fMsgQuit = pClient->fMsgQuit;
783
savedState.fMsgReadData = pClient->fMsgReadData;
784
savedState.fMsgFormats = pClient->fMsgFormats;
785
savedState.u32RequestedFormat = pClient->u32RequestedFormat;
786
rc = SSMR3PutMem(pSSM, &savedState, sizeof(savedState));
787
AssertRCReturn(rc, rc);
751
/* This field used to be the length. We're using it as a version field
752
with the high bit set. */
753
SSMR3PutU32 (pSSM, UINT32_C (0x80000002));
754
int rc = SSMR3PutStructEx (pSSM, pClient, sizeof(*pClient), 0 /*fFlags*/, &g_aClipboardClientDataFields[0], NULL);
755
AssertRCReturn (rc, rc);
789
757
if (pClient->fAsync)
792
760
pClient->fAsync = false;
795
vboxSvcClipboardCompleteReadData(pClient, VINF_SUCCESS, 0);
763
vboxSvcClipboardCompleteReadData (pClient, VINF_SUCCESS, 0);
797
765
return VINF_SUCCESS;
800
768
static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
802
LogRel2(("svcLoadState: u32ClientID = %d\n", u32ClientID));
770
LogRel2 (("svcLoadState: u32ClientID = %d\n", u32ClientID));
804
772
VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
806
774
/* Existing client can not be in async state yet. */
807
Assert(!pClient->fAsync);
775
Assert (!pClient->fAsync);
777
/* Save the client ID for data validation. */
778
/** @todo isn't this the same as u32ClientID? Playing safe for now... */
779
uint32_t const u32ClientIDOld = pClient->u32ClientID;
809
781
/* Restore the client data. */
811
int rc = SSMR3GetU32(pSSM, &len);
812
AssertRCReturn(rc, rc);
814
if (len != sizeof(CLIPSAVEDSTATEDATA))
816
LogRel2(("Client data size mismatch: expected %d, got %d\n", sizeof (CLIPSAVEDSTATEDATA), len));
817
return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
820
CLIPSAVEDSTATEDATA savedState;
821
rc = SSMR3GetMem(pSSM, &savedState, sizeof(savedState));
822
AssertRCReturn(rc, rc);
824
/* Verify the loaded clients data and update the pClient. */
825
if (pClient->u32ClientID != savedState.u32ClientID)
827
LogRel2(("Client ID mismatch: expected %d, got %d\n", pClient->u32ClientID, savedState.u32ClientID));
828
return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
831
pClient->fMsgQuit = savedState.fMsgQuit;
832
pClient->fMsgReadData = savedState.fMsgReadData;
833
pClient->fMsgFormats = savedState.fMsgFormats;
834
pClient->u32RequestedFormat = savedState.u32RequestedFormat;
783
int rc = SSMR3GetU32 (pSSM, &lenOrVer);
784
AssertRCReturn (rc, rc);
785
if (lenOrVer == UINT32_C (0x80000002))
787
rc = SSMR3GetStructEx (pSSM, pClient, sizeof(*pClient), 0 /*fFlags*/, &g_aClipboardClientDataFields[0], NULL);
788
AssertRCReturn (rc, rc);
790
else if (lenOrVer == (SSMR3HandleHostBits (pSSM) == 64 ? 72 : 48))
793
* This structure corresponds to the original layout of the
794
* VBOXCLIPBOARDCLIENTDATA structure. As the structure was saved as a whole
795
* when saving state, we need to remember it forever in order to preserve
798
* (Starting with 3.1 this is no longer used.)
800
typedef struct _CLIPSAVEDSTATEDATA
802
struct _CLIPSAVEDSTATEDATA *pNext;
803
struct _CLIPSAVEDSTATEDATA *pPrev;
805
VBOXCLIPBOARDCONTEXT *pCtx;
807
uint32_t u32ClientID;
809
bool fAsync: 1; /* Guest is waiting for a message. */
812
bool fMsgReadData: 1;
816
VBOXHGCMCALLHANDLE callHandle;
817
VBOXHGCMSVCPARM *paParms;
826
uint32_t u32AvailableFormats;
827
uint32_t u32RequestedFormat;
829
} CLIPSAVEDSTATEDATA;
832
* SSM descriptor table for the CLIPSAVEDSTATEDATA structure.
834
static SSMFIELD const s_aClipSavedStateDataFields30[] =
836
SSMFIELD_ENTRY_IGN_HCPTR( CLIPSAVEDSTATEDATA, pNext),
837
SSMFIELD_ENTRY_IGN_HCPTR( CLIPSAVEDSTATEDATA, pPrev),
838
SSMFIELD_ENTRY_IGN_HCPTR( CLIPSAVEDSTATEDATA, pCtx),
839
SSMFIELD_ENTRY( CLIPSAVEDSTATEDATA, u32ClientID),
840
SSMFIELD_ENTRY_CUSTOM(fMsgQuit+fMsgReadData+fMsgFormats, RT_OFFSETOF(CLIPSAVEDSTATEDATA, u32ClientID) + 4, 4),
841
SSMFIELD_ENTRY_IGN_HCPTR( CLIPSAVEDSTATEDATA, async.callHandle),
842
SSMFIELD_ENTRY_IGN_HCPTR( CLIPSAVEDSTATEDATA, async.paParms),
843
SSMFIELD_ENTRY_IGNORE( CLIPSAVEDSTATEDATA, data.pv),
844
SSMFIELD_ENTRY_IGNORE( CLIPSAVEDSTATEDATA, data.cb),
845
SSMFIELD_ENTRY_IGNORE( CLIPSAVEDSTATEDATA, data.u32Format),
846
SSMFIELD_ENTRY_IGNORE( CLIPSAVEDSTATEDATA, u32AvailableFormats),
847
SSMFIELD_ENTRY( CLIPSAVEDSTATEDATA, u32RequestedFormat),
848
SSMFIELD_ENTRY_TERM()
851
CLIPSAVEDSTATEDATA savedState;
852
RT_ZERO (savedState);
853
rc = SSMR3GetStructEx (pSSM, &savedState, sizeof(savedState), SSMSTRUCT_FLAGS_MEM_BAND_AID,
854
&s_aClipSavedStateDataFields30[0], NULL);
855
AssertRCReturn (rc, rc);
857
pClient->fMsgQuit = savedState.fMsgQuit;
858
pClient->fMsgReadData = savedState.fMsgReadData;
859
pClient->fMsgFormats = savedState.fMsgFormats;
860
pClient->u32RequestedFormat = savedState.u32RequestedFormat;
864
LogRel (("Client data size mismatch: got %#x\n", lenOrVer));
865
return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
868
/* Verify the client ID. */
869
if (pClient->u32ClientID != u32ClientIDOld)
871
LogRel (("Client ID mismatch: expected %d, got %d\n", u32ClientIDOld, pClient->u32ClientID));
872
pClient->u32ClientID = u32ClientIDOld;
873
return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
836
876
/* Actual host data are to be reported to guest (SYNC). */
837
877
vboxClipboardSync (pClient);