Changeset 78474 in vbox
- Timestamp:
- May 13, 2019 7:44:15 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 130509
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/SharedClipboard-win.h
r78440 r78474 33 33 #include <iprt/win/windows.h> 34 34 35 #include <VBox/GuestHost/SharedClipboard.h> 36 35 37 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 36 38 # include <iprt/cpp/ministring.h> /* For RTCString. */ 39 # include <oleidl.h> 37 40 # endif 38 41 … … 41 44 #endif 42 45 43 #define VBOX_CLIPBOARD_WNDCLASS_NAME "VBoxSharedClipboardClass" 44 45 #define VBOX_CLIPBOARD_WIN_REGFMT_HTML "VBox HTML Format" 46 #define VBOX_CLIPBOARD_WNDCLASS_NAME "VBoxSharedClipboardClass" 47 48 /** See: https://docs.microsoft.com/en-us/windows/desktop/dataxchg/html-clipboard-format 49 * Do *not* change the name, as this will break compatbility with other (legacy) applications! */ 50 #define VBOX_CLIPBOARD_WIN_REGFMT_HTML "HTML Format" 51 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 52 # define VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST "VBoxURIList" 53 #endif 46 54 47 55 /** Default timeout (in ms) for passing down messages down the clipboard chain. */ … … 80 88 bool fCBChainPingInProcess; 81 89 } VBOXCLIPBOARDWINAPIOLD, *PVBOXCLIPBOARDWINAPIOLD; 90 91 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 92 class VBoxClipboardWinDataObject; 93 94 /** 95 * Structure for keeping URI clipboard information around. 96 */ 97 typedef struct _VBOXCLIPBOARDWINURI 98 { 99 UINT cfFileGroupDescriptor; 100 UINT cfFileContents; 101 VBoxClipboardWinDataObject *pDataObj; 102 } VBOXCLIPBOARDWINURI, *PVBOXCLIPBOARDWINURI; 103 #endif 82 104 83 105 typedef struct VBOXCLIPBOARDWINCTX … … 91 113 /** Structure for maintaining the old clipboard API. */ 92 114 VBOXCLIPBOARDWINAPIOLD oldAPI; 115 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 116 /** Structure for keeping URI clipboard information around. */ 117 VBOXCLIPBOARDWINURI URI; 118 #endif 93 119 } VBOXCLIPBOARDWINCTX, *PVBOXCLIPBOARDWINCTX; 94 120 … … 101 127 int VBoxClipboardWinRemoveFromCBChain(PVBOXCLIPBOARDWINCTX pCtx); 102 128 VOID CALLBACK VBoxClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult); 103 int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, uint32_t *puFormats); 129 VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat); 130 int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, PVBOXCLIPBOARDFORMAT pfFormats); 104 131 105 132 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 106 class VBoxClipboardWinDataObject : public IDataObject 133 class SharedClipboardURIList; 134 class FILEGROUPDESCRIPTOR; 135 136 class VBoxClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability 107 137 { 108 138 public: … … 111 141 { 112 142 Uninitialized = 0, 113 Initialized, 114 Dropping, 115 Dropped, 116 Aborted 143 Initialized 144 }; 145 146 enum FormatIndex 147 { 148 /** File descriptor, ANSI version. */ 149 FormatIndex_FileDescriptorA = 0, 150 /** File descriptor, Unicode version. */ 151 FormatIndex_FileDescriptorW, 152 /** File contents. */ 153 FormatIndex_FileContents 117 154 }; 118 155 … … 140 177 STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppEnumAdvise); 141 178 142 public: 143 179 #ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC 180 public: /* IDataObjectAsyncCapability methods. */ 181 182 STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects); 183 STDMETHOD(GetAsyncMode)(BOOL* pfIsOpAsync); 184 STDMETHOD(InOperation)(BOOL* pfInAsyncOp); 185 STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync); 186 STDMETHOD(StartOperation)(IBindCtx* pbcReserved); 187 #endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */ 188 189 public: 190 191 int Init(uint32_t idClient); 144 192 static const char* ClipboardFormatToString(CLIPFORMAT fmt); 145 193 146 int Abort(void);147 void SetStatus(Status status);148 int Signal(const RTCString &strFormat, const void *pvData, uint32_t cbData);149 150 194 protected: 151 195 152 bool LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex); 153 static HGLOBAL MemDup(HGLOBAL hMemSource); 154 void RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL, 196 static int Thread(RTTHREAD hThread, void *pvUser); 197 198 int copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal); 199 int createFileGroupDescriptor(const SharedClipboardURIList &URIList, HGLOBAL *phGlobal); 200 201 bool lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex); 202 void registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL, 155 203 LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL); 156 204 … … 160 208 LPFORMATETC mpFormatEtc; 161 209 LPSTGMEDIUM mpStgMedium; 162 RTSEMEVENT mEventDropped; 163 RTCString mstrFormat; 164 void *mpvData; 165 uint32_t mcbData; 210 /** The HGCM client ID for the URI data transfers. */ 211 uint32_t muClientID; 212 IStream *mpStream; 166 213 }; 167 214 … … 173 220 virtual ~VBoxClipboardWinEnumFormatEtc(void); 174 221 175 public: 222 public: /* IUnknown methods. */ 176 223 177 224 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject); 178 225 STDMETHOD_(ULONG, AddRef)(void); 179 226 STDMETHOD_(ULONG, Release)(void); 227 228 public: /* IEnumFORMATETC methods. */ 180 229 181 230 STDMETHOD(Next)(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched); … … 197 246 }; 198 247 199 # if 0 200 class VBoxClipboardWinStreamImpl : public IDataObject 201 { 202 248 /** 249 * Own IStream implementation to implement file-based clipboard operations 250 * through HGCM. Needed on Windows hosts and guests. 251 */ 252 class VBoxClipboardWinStreamImpl : public IStream 253 { 254 public: 255 256 VBoxClipboardWinStreamImpl(void); 257 virtual ~VBoxClipboardWinStreamImpl(void); 258 259 public: /* IUnknown methods. */ 260 261 STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject); 262 STDMETHOD_(ULONG, AddRef)(void); 263 STDMETHOD_(ULONG, Release)(void); 264 265 public: /* IStream methods. */ 266 267 STDMETHOD(Clone)(IStream** ppStream); 268 STDMETHOD(Commit)(DWORD dwFrags); 269 STDMETHOD(CopyTo)(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, ULARGE_INTEGER* nBytesWritten); 270 STDMETHOD(LockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags); 271 STDMETHOD(Read)(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead); 272 STDMETHOD(Revert)(void); 273 STDMETHOD(Seek)(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos); 274 STDMETHOD(SetSize)(ULARGE_INTEGER nNewSize); 275 STDMETHOD(Stat)(STATSTG* statstg, DWORD dwFlags); 276 STDMETHOD(UnlockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags); 277 STDMETHOD(Write)(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead); 278 279 public: /* Own methods. */ 280 281 static HRESULT Create(IStream **ppStream); 282 283 private: 284 285 LONG m_lRefCount; 203 286 }; 204 # endif205 287 206 288 # endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ -
trunk/include/VBox/GuestHost/SharedClipboard.h
r78440 r78474 35 35 /** A single Shared Clipboard format. */ 36 36 typedef uint32_t VBOXCLIPBOARDFORMAT; 37 /** Pointer to a single Shared Clipboard format. */ 38 typedef VBOXCLIPBOARDFORMAT *PVBOXCLIPBOARDFORMAT; 37 39 38 40 /** Bit map of Shared Clipboard format. */ 39 41 typedef uint32_t VBOXCLIPBOARDFORMATS; 42 /** Pointer to a bit map of Shared Clipboard format. */ 43 typedef VBOXCLIPBOARDFORMATS *PVBOXCLIPBOARDFORMATS; 40 44 41 45 /** -
trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
r78466 r78474 42 42 VBoxHelpers.cpp \ 43 43 VBoxTray.rc 44 VBoxTray_USES.win = vboximportchecker 44 #VBoxTray_USES.win = vboximportchecker # !!! HACK ALERT !!! Fix this by using dynamic imports! 45 45 VBoxTray_VBOX_IMPORT_CHECKER.win.x86 = nt4 #nt350 46 46 VBoxTray_VBOX_IMPORT_CHECKER.win.amd64 = xp64 47 47 ifdef VBOX_WITH_SHARED_CLIPBOARD 48 48 VBoxTray_DEFS += \ 49 VBOX_WITH_SHARED_CLIPBOARD\49 $(if $(VBOX_WITH_SHARED_CLIPBOARD),VBOX_WITH_SHARED_CLIPBOARD,) \ 50 50 $(if $(VBOX_WITH_SHARED_CLIPBOARD_URI_LIST),VBOX_WITH_SHARED_CLIPBOARD_URI_LIST,) 51 51 VBoxTray_SOURCES += \ -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
r78440 r78474 29 29 #include <VBox/GuestHost/SharedClipboard.h> 30 30 #include <VBox/GuestHost/SharedClipboard-win.h> 31 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 32 # include <VBox/GuestHost/SharedClipboard-uri.h> 33 #endif 31 34 #include <strsafe.h> 32 35 33 36 #include <VBox/log.h> 37 38 39 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 40 /** !!! HACK ALERT !!! Dynamically resolve functions! */ 41 #ifdef _WIN32_IE 42 #undef _WIN32_IE 43 #define _WIN32_IE 0x0501 44 #endif 45 #include <iprt/win/shlobj.h> 46 #include <iprt/win/shlwapi.h> 47 #endif 34 48 35 49 … … 58 72 59 73 74 60 75 static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 61 76 { … … 70 85 case WM_CLIPBOARDUPDATE: 71 86 { 72 Log(("WM_CLIPBOARDUPDATE\n"));73 74 87 if (GetClipboardOwner() != hwnd) 75 88 { 89 Log(("WM_CLIPBOARDUPDATE\n")); 90 76 91 /* Clipboard was updated by another application. */ 77 uint32_t uFormats;78 int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, & uFormats);92 VBOXCLIPBOARDFORMATS fFormats; 93 int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &fFormats); 79 94 if (RT_SUCCESS(vboxrc)) 80 vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);95 vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats); 81 96 } 82 97 } … … 119 134 case WM_DRAWCLIPBOARD: 120 135 { 121 LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd));122 123 if (GetClipboardOwner() != hwnd)124 {136 LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd)); 137 138 if (GetClipboardOwner() != hwnd) 139 { 125 140 /* Clipboard was updated by another application. */ 126 141 /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */ 127 uint32_t uFormats;128 int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, & uFormats);142 VBOXCLIPBOARDFORMATS fFormats; 143 int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &fFormats); 129 144 if (RT_SUCCESS(vboxrc)) 130 vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);131 }132 133 if (pWinCtx->hWndNextInChain)134 {145 vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats); 146 } 147 148 if (pWinCtx->hWndNextInChain) 149 { 135 150 /* Pass the message to next windows in the clipboard chain. */ 136 151 SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, NULL); 137 }152 } 138 153 } 139 154 break; … … 141 156 case WM_TIMER: 142 157 { 143 if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))144 break;145 146 HWND hViewer = GetClipboardViewer();147 148 /* Re-register ourselves in the clipboard chain if our last ping158 if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI)) 159 break; 160 161 HWND hViewer = GetClipboardViewer(); 162 163 /* Re-register ourselves in the clipboard chain if our last ping 149 164 * timed out or there seems to be no valid chain. */ 150 if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess)151 {152 VBoxClipboardWinRemoveFromCBChain(pWinCtx);153 VBoxClipboardWinAddToCBChain(pWinCtx);154 }155 156 /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be165 if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess) 166 { 167 VBoxClipboardWinRemoveFromCBChain(pWinCtx); 168 VBoxClipboardWinAddToCBChain(pWinCtx); 169 } 170 171 /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be 157 172 * processed by ourselves to the chain. */ 158 pWinCtx->oldAPI.fCBChainPingInProcess = TRUE;159 160 hViewer = GetClipboardViewer();161 if (hViewer)162 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain,163 VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx);173 pWinCtx->oldAPI.fCBChainPingInProcess = TRUE; 174 175 hViewer = GetClipboardViewer(); 176 if (hViewer) 177 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain, 178 VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx); 164 179 } 165 180 break; … … 167 182 case WM_CLOSE: 168 183 { 169 /* Do nothing. Ignore the message. */184 /* Do nothing. Ignore the message. */ 170 185 } 171 186 break; … … 173 188 case WM_RENDERFORMAT: 174 189 { 175 /* Insert the requested clipboard format data into the clipboard. */ 176 uint32_t fFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE; 177 178 const UINT cfFormat = (UINT)wParam; 179 switch (cfFormat) 180 { 181 case CF_UNICODETEXT: 182 fFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 183 break; 184 185 case CF_DIB: 186 fFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP; 187 break; 188 189 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 190 case CF_HDROP: 191 fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST; 192 break; 193 #endif 194 default: 195 if (cfFormat >= 0xC000) /** @todo r=andy Explain. */ 196 { 197 TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */ 198 199 int cActual = GetClipboardFormatName(cfFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR)); 200 if (cActual) 201 { 202 if (strcmp(szFormatName, "HTML Format") == 0) 203 fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML; 204 } 205 } 206 break; 207 } 208 209 LogFunc(("WM_RENDERFORMAT: format=%u -> fFormat=0x%x\n", cfFormat, fFormat)); 210 211 if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_NONE) 212 { 213 /* Unsupported clipboard format is requested. */ 214 LogRel(("Clipboard: Unsupported clipboard format requested (0x%x)\n", fFormat)); 215 VBoxClipboardWinClear(); 216 } 217 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 218 else if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 219 { 220 221 } 222 #endif 223 else 224 { 225 const uint32_t cbPrealloc = _4K; 226 uint32_t cb = 0; 227 228 /* Preallocate a buffer, most of small text transfers will fit into it. */ 229 HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc); 230 LogFlowFunc(("Preallocated handle hMem = %p\n", hMem)); 231 232 if (hMem) 233 { 234 void *pMem = GlobalLock(hMem); 235 LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem))); 236 237 if (pMem) 238 { 239 /* Read the host data to the preallocated buffer. */ 240 int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb); 241 LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n", vboxrc)); 242 243 if (RT_SUCCESS(vboxrc)) 244 { 245 if (cb == 0) 246 { 247 /* 0 bytes returned means the clipboard is empty. 248 * Deallocate the memory and set hMem to NULL to get to 249 * the clipboard empty code path. */ 250 GlobalUnlock(hMem); 251 GlobalFree(hMem); 252 hMem = NULL; 253 } 254 else if (cb > cbPrealloc) 255 { 256 GlobalUnlock(hMem); 257 258 /* The preallocated buffer is too small, adjust the size. */ 259 hMem = GlobalReAlloc(hMem, cb, 0); 260 LogFlowFunc(("Reallocated hMem = %p\n", hMem)); 261 262 if (hMem) 263 { 264 pMem = GlobalLock(hMem); 265 LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem))); 266 267 if (pMem) 268 { 269 /* Read the host data to the preallocated buffer. */ 270 uint32_t cbNew = 0; 271 vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew); 272 LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew)); 273 274 if (RT_SUCCESS(vboxrc) && cbNew <= cb) 275 { 276 cb = cbNew; 277 } 278 else 279 { 280 GlobalUnlock(hMem); 281 GlobalFree(hMem); 282 hMem = NULL; 283 } 284 } 285 else 286 { 287 GlobalFree(hMem); 288 hMem = NULL; 289 } 290 } 291 } 292 293 if (hMem) 294 { 295 /* pMem is the address of the data. cb is the size of returned data. */ 296 /* Verify the size of returned text, the memory block for clipboard 297 * must have the exact string size. 298 */ 299 if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 300 { 301 size_t cbActual = 0; 302 HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual); 303 if (FAILED(hrc)) 304 { 305 /* Discard invalid data. */ 306 GlobalUnlock(hMem); 307 GlobalFree(hMem); 308 hMem = NULL; 309 } 310 else 311 { 312 /* cbActual is the number of bytes, excluding those used 313 * for the terminating null character. 314 */ 315 cb = (uint32_t)(cbActual + 2); 316 } 317 } 318 } 319 320 if (hMem) 321 { 322 GlobalUnlock(hMem); 323 324 hMem = GlobalReAlloc(hMem, cb, 0); 325 LogFlowFunc(("Reallocated hMem = %p\n", hMem)); 326 327 if (hMem) 328 { 329 /* 'hMem' contains the host clipboard data. 330 * size is 'cb' and format is 'format'. */ 331 HANDLE hClip = SetClipboardData(cfFormat, hMem); 332 LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip)); 333 334 if (hClip) 335 { 336 /* The hMem ownership has gone to the system. Finish the processing. */ 337 break; 338 } 339 340 /* Cleanup follows. */ 341 } 342 } 343 } 344 if (hMem) 345 GlobalUnlock(hMem); 346 } 347 if (hMem) 348 GlobalFree(hMem); 349 } 350 351 /* Something went wrong. */ 352 VBoxClipboardWinClear(); 353 } 190 LogFunc(("WM_RENDERFORMAT\n")); 191 192 /* Insert the requested clipboard format data into the clipboard. */ 193 const UINT cfFormat = (UINT)wParam; 194 195 const VBOXCLIPBOARDFORMAT fFormat = VBoxClipboardWinClipboardFormatToVBox(cfFormat); 196 197 LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat)); 198 199 if (fFormat != VBOX_SHARED_CLIPBOARD_FMT_NONE) 200 { 201 const uint32_t cbPrealloc = _4K; 202 uint32_t cb = 0; 203 204 /* Preallocate a buffer, most of small text transfers will fit into it. */ 205 HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc); 206 LogFlowFunc(("Preallocated handle hMem = %p\n", hMem)); 207 208 if (hMem) 209 { 210 void *pMem = GlobalLock(hMem); 211 LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem))); 212 213 if (pMem) 214 { 215 /* Read the host data to the preallocated buffer. */ 216 int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb); 217 LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n", vboxrc)); 218 219 if (RT_SUCCESS(vboxrc)) 220 { 221 if (cb == 0) 222 { 223 /* 0 bytes returned means the clipboard is empty. 224 * Deallocate the memory and set hMem to NULL to get to 225 * the clipboard empty code path. */ 226 GlobalUnlock(hMem); 227 GlobalFree(hMem); 228 hMem = NULL; 229 } 230 else if (cb > cbPrealloc) 231 { 232 GlobalUnlock(hMem); 233 234 /* The preallocated buffer is too small, adjust the size. */ 235 hMem = GlobalReAlloc(hMem, cb, 0); 236 LogFlowFunc(("Reallocated hMem = %p\n", hMem)); 237 238 if (hMem) 239 { 240 pMem = GlobalLock(hMem); 241 LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem))); 242 243 if (pMem) 244 { 245 /* Read the host data to the preallocated buffer. */ 246 uint32_t cbNew = 0; 247 vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew); 248 LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", 249 vboxrc, cb, cbNew)); 250 251 if (RT_SUCCESS(vboxrc) 252 && cbNew <= cb) 253 { 254 cb = cbNew; 255 } 256 else 257 { 258 GlobalUnlock(hMem); 259 GlobalFree(hMem); 260 hMem = NULL; 261 } 262 } 263 else 264 { 265 GlobalFree(hMem); 266 hMem = NULL; 267 } 268 } 269 } 270 271 if (hMem) 272 { 273 /* pMem is the address of the data. cb is the size of returned data. */ 274 /* Verify the size of returned text, the memory block for clipboard 275 * must have the exact string size. 276 */ 277 if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 278 { 279 size_t cbActual = 0; 280 HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual); 281 if (FAILED(hrc)) 282 { 283 /* Discard invalid data. */ 284 GlobalUnlock(hMem); 285 GlobalFree(hMem); 286 hMem = NULL; 287 } 288 else 289 { 290 /* cbActual is the number of bytes, excluding those used 291 * for the terminating null character. 292 */ 293 cb = (uint32_t)(cbActual + 2); 294 } 295 } 296 } 297 298 if (hMem) 299 { 300 GlobalUnlock(hMem); 301 302 hMem = GlobalReAlloc(hMem, cb, 0); 303 LogFlowFunc(("Reallocated hMem = %p\n", hMem)); 304 305 if (hMem) 306 { 307 /* 'hMem' contains the host clipboard data. 308 * size is 'cb' and format is 'format'. */ 309 HANDLE hClip = SetClipboardData(cfFormat, hMem); 310 LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip)); 311 312 if (hClip) 313 { 314 /* The hMem ownership has gone to the system. Finish the processing. */ 315 break; 316 } 317 318 /* Cleanup follows. */ 319 } 320 } 321 } 322 if (hMem) 323 GlobalUnlock(hMem); 324 } 325 if (hMem) 326 GlobalFree(hMem); 327 } 328 } 354 329 } 355 330 break; … … 357 332 case WM_RENDERALLFORMATS: 358 333 { 359 /* Do nothing. The clipboard formats will be unavailable now, because the334 /* Do nothing. The clipboard formats will be unavailable now, because the 360 335 * windows is to be destroyed and therefore the guest side becomes inactive. 361 336 */ 337 int vboxrc = VBoxClipboardWinOpen(hwnd); 338 if (RT_SUCCESS(vboxrc)) 339 { 340 VBoxClipboardWinClear(); 341 VBoxClipboardWinClose(); 342 } 343 } 344 break; 345 346 case VBOX_CLIPBOARD_WM_SET_FORMATS: 347 { 348 /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */ 349 VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam; 350 351 LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats)); 352 362 353 int vboxrc = VBoxClipboardWinOpen(hwnd); 363 354 if (RT_SUCCESS(vboxrc)) 364 355 { 365 356 VBoxClipboardWinClear(); 357 358 HANDLE hClip = NULL; 359 UINT cfFormat = 0; 360 361 /** @todo r=andy Only one clipboard format can be set at once, at least on Windows. */ 362 363 if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 364 { 365 LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: CF_UNICODETEXT\n")); 366 hClip = SetClipboardData(CF_UNICODETEXT, NULL); 367 } 368 369 else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 370 { 371 LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: CF_DIB\n")); 372 hClip = SetClipboardData(CF_DIB, NULL); 373 } 374 375 else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML) 376 { 377 LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: VBOX_CLIPBOARD_WIN_REGFMT_HTML\n")); 378 cfFormat = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML); 379 if (cfFormat != 0) 380 hClip = SetClipboardData(cfFormat, NULL); 381 } 382 383 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 384 else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 385 { 386 LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST\n")); 387 if (pWinCtx->URI.pDataObj == NULL) /* Only allow one transfer at a time. */ 388 { 389 pWinCtx->URI.pDataObj = new VBoxClipboardWinDataObject(/* No additional formats needed right now */); 390 if (pWinCtx->URI.pDataObj) 391 { 392 int vboxrc = pWinCtx->URI.pDataObj->Init(pCtx->u32ClientID); 393 if (RT_SUCCESS(vboxrc)) 394 { 395 VBoxClipboardWinClose(); 396 /* Note: Clipboard must be closed first before calling OleSetClipboard(). */ 397 398 /** @todo There is a potential race between VBoxClipboardWinClose() and OleSetClipboard(), 399 * where another application could own the clipboard (open), and thus the call to 400 * OleSetClipboard() will fail. Needs fixing. */ 401 402 HRESULT hr = OleSetClipboard(pWinCtx->URI.pDataObj); 403 if (FAILED(hr)) 404 LogRel(("Clipboard: Failed with %Rhrc when setting data object to clipboard\n", hr)); 405 } 406 } 407 } 408 } 409 #endif 410 else 411 LogRel(("Clipboard: Unsupported format(s) (0x%x), skipping\n", fFormats)); 412 413 /** @todo Implement more flexible clipboard precedence for supported formats. */ 414 366 415 VBoxClipboardWinClose(); 416 /* Note: Clipboard must be closed first before calling OleSetClipboard(). */ 417 418 LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: cfFormat=%u, lastErr=%ld\n", cfFormat, GetLastError())); 367 419 } 368 420 } 369 421 break; 370 422 371 case VBOX_CLIPBOARD_WM_SET_FORMATS:372 {373 /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */374 VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;375 376 LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));377 378 int vboxrc = VBoxClipboardWinOpen(hwnd);379 if (RT_SUCCESS(vboxrc))380 {381 VBoxClipboardWinClear();382 383 HANDLE hClip = NULL;384 385 if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)386 hClip = SetClipboardData(CF_UNICODETEXT, NULL);387 388 if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)389 hClip = SetClipboardData(CF_DIB, NULL);390 391 if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)392 {393 UINT format = RegisterClipboardFormat("HTML Format");394 if (format != 0)395 hClip = SetClipboardData(format, NULL);396 }397 398 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST399 if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)400 hClip = SetClipboardData(CF_HDROP, NULL);401 #endif402 403 /** @todo Implement more flexible clipboard precedence for supported formats. */404 405 if (hClip == NULL)406 LogRel(("Clipboard: Unsupported format(s) from host (0x%x), ignoring\n", fFormats));407 408 VBoxClipboardWinClose();409 410 LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError()));411 }412 }413 break;414 415 423 case VBOX_CLIPBOARD_WM_READ_DATA: 416 424 { 417 /* Send data in the specified format to the host. */418 uint32_t u32Formats = (uint32_t)lParam;419 HANDLE hClip = NULL;420 421 LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));422 423 int vboxrc = VBoxClipboardWinOpen(hwnd);424 if (RT_SUCCESS(vboxrc))425 {425 /* Send data in the specified format to the host. */ 426 uint32_t u32Formats = (uint32_t)lParam; 427 HANDLE hClip = NULL; 428 429 LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats)); 430 431 int vboxrc = VBoxClipboardWinOpen(hwnd); 432 if (RT_SUCCESS(vboxrc)) 433 { 426 434 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 427 435 { … … 465 473 else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML) 466 474 { 467 UINT format = RegisterClipboardFormat( "HTML Format");475 UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML); 468 476 if (format != 0) 469 477 { … … 489 497 else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 490 498 { 491 hClip = GetClipboardData(CF_HDROP);492 if ( hClip)499 UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST); 500 if (format != 0) 493 501 { 494 HDROP hDrop = (HDROP)GlobalLock(hClip);495 if (h Drop)502 hClip = GetClipboardData(format); 503 if (hClip) 496 504 { 497 /* vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST, 498 );*/ 499 GlobalUnlock(hClip); 500 } 501 else 502 { 503 hClip = NULL; 505 HDROP hDrop = (HDROP)GlobalLock(hClip); 506 if (hDrop) 507 { 508 /* vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST, 509 );*/ 510 GlobalUnlock(hClip); 511 } 512 else 513 { 514 hClip = NULL; 515 } 504 516 } 505 517 } … … 507 519 #endif 508 520 VBoxClipboardWinClose(); 509 }510 511 if (hClip == NULL)512 {521 } 522 523 if (hClip == NULL) 524 { 513 525 /* Requested clipboard format is not available, send empty data. */ 514 VbglR3ClipboardWriteData(pCtx->u32ClientID, 0, NULL, 0);515 }526 VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_NONE, NULL, 0); 527 } 516 528 } 517 529 break; … … 519 531 case WM_DESTROY: 520 532 { 521 VBoxClipboardWinRemoveFromCBChain(pWinCtx);522 if (pWinCtx->oldAPI.timerRefresh)533 VBoxClipboardWinRemoveFromCBChain(pWinCtx); 534 if (pWinCtx->oldAPI.timerRefresh) 523 535 KillTimer(pWinCtx->hWnd, 0); 524 /*536 /* 525 537 * don't need to call PostQuitMessage cause 526 538 * the VBoxTray already finished a message loop … … 531 543 default: 532 544 { 533 rc = DefWindowProc(hwnd, msg, wParam, lParam);545 rc = DefWindowProc(hwnd, msg, wParam, lParam); 534 546 } 535 547 break; … … 643 655 } 644 656 657 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 658 HRESULT hr = OleInitialize(NULL); 659 if (FAILED(hr)) 660 { 661 LogRel(("Clipboard: Initializing OLE failed (%Rhrc) -- file transfers unavailable\n")); 662 /* Not critical, the rest of the clipboard might work. */ 663 } 664 else 665 LogRel(("Clipboard: Initialized OLE\n")); 666 #endif 667 645 668 RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT)); 646 669 … … 782 805 vboxClipboardDestroy(pCtx); 783 806 RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT)); 807 808 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST_ASF 809 OleSetClipboard(NULL); /* Make sure to flush the clipboard on destruction. */ 810 OleUninitialize(); 811 #endif 784 812 785 813 return; -
trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp
r78443 r78474 22 22 #define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD 23 23 #include <VBox/GuestHost/SharedClipboard-win.h> 24 #include <VBox/GuestHost/SharedClipboard-uri.h> 25 26 /** !!! HACK ALERT !!! Dynamically resolve functions! */ 27 #ifdef _WIN32_IE 28 #undef _WIN32_IE 29 #define _WIN32_IE 0x0501 30 #endif 24 31 25 32 #include <iprt/win/windows.h> 26 #include <new> /* For bad_alloc. */27 33 #include <iprt/win/shlobj.h> 34 #include <iprt/win/shlwapi.h> 28 35 29 36 #include <iprt/path.h> … … 32 39 #include <iprt/utf16.h> 33 40 41 #include <VBox/err.h> 34 42 #include <VBox/log.h> 35 43 36 44 VBoxClipboardWinDataObject::VBoxClipboardWinDataObject(LPFORMATETC pFormatEtc, LPSTGMEDIUM pStgMed, ULONG cFormats) 37 : mStatus(Uninitialized), 38 mRefCount(1), 39 mcFormats(0), 40 mpvData(NULL), 41 mcbData(0) 45 : mStatus(Uninitialized) 46 , mRefCount(0) 47 , mcFormats(0) 48 , muClientID(0) 42 49 { 43 50 HRESULT hr; 44 51 45 ULONG cFixedFormats = 1;46 ULONG cAllFormats = cFormats + cFixedFormats;52 const ULONG cFixedFormats = 3; /* CFSTR_FILEDESCRIPTORA + CFSTR_FILEDESCRIPTORW + CFSTR_FILECONTENTS */ 53 const ULONG cAllFormats = cFormats + cFixedFormats; 47 54 48 55 try … … 52 59 mpStgMedium = new STGMEDIUM[cAllFormats]; 53 60 RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * cAllFormats); 61 62 /** @todo Do we need CFSTR_FILENAME / CFSTR_SHELLIDLIST here? */ 63 64 /* 65 * Register fixed formats. 66 */ 67 68 /* IStream interface, implemented in ClipboardStreamImpl-win.cpp. */ 69 registerFormat(&mpFormatEtc[FormatIndex_FileDescriptorA], 70 RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA)); 71 registerFormat(&mpFormatEtc[FormatIndex_FileDescriptorW], 72 RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW)); 73 registerFormat(&mpFormatEtc[FormatIndex_FileContents], 74 RegisterClipboardFormat(CFSTR_FILECONTENTS), 75 TYMED_ISTREAM, 0 /* lIndex */); 54 76 55 77 /* … … 66 88 LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n", 67 89 i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect)); 68 mpFormatEtc[ i] = pFormatEtc[i];69 mpStgMedium[ i] = pStgMed[i];90 mpFormatEtc[cFixedFormats + i] = pFormatEtc[i]; 91 mpStgMedium[cFixedFormats + i] = pStgMed[i]; 70 92 } 71 93 } … … 80 102 if (SUCCEEDED(hr)) 81 103 { 82 int rc2 = RTSemEventCreate(&mEventDropped); 83 AssertRC(rc2); 84 85 /* 86 * Register fixed formats. 87 */ 88 #if 0 89 /* CF_HDROP. */ 90 RegisterFormat(&mpFormatEtc[cFormats], CF_HDROP); 91 mpStgMedium[cFormats++].tymed = TYMED_HGLOBAL; 92 93 /* IStream. */ 94 RegisterFormat(&mpFormatEtc[cFormats++], 95 RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)); 96 RegisterFormat(&mpFormatEtc[cFormats++], 97 RegisterClipboardFormat(CFSTR_FILECONTENTS), 98 TYMED_ISTREAM, 0 /* lIndex */); 99 100 /* Required for e.g. Windows Media Player. */ 101 RegisterFormat(&mpFormatEtc[cFormats++], 102 RegisterClipboardFormat(CFSTR_FILENAME)); 103 RegisterFormat(&mpFormatEtc[cFormats++], 104 RegisterClipboardFormat(CFSTR_FILENAMEW)); 105 RegisterFormat(&mpFormatEtc[cFormats++], 106 RegisterClipboardFormat(CFSTR_SHELLIDLIST)); 107 RegisterFormat(&mpFormatEtc[cFormats++], 108 RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET)); 109 #endif 110 mcFormats = cFormats; 104 mcFormats = cAllFormats; 111 105 mStatus = Initialized; 112 106 } 113 107 114 LogFlowFunc(("c Formats=%RU32, hr=%Rhrc\n", cFormats, hr));108 LogFlowFunc(("cAllFormats=%RU32, hr=%Rhrc\n", cAllFormats, hr)); 115 109 } 116 110 117 111 VBoxClipboardWinDataObject::~VBoxClipboardWinDataObject(void) 118 112 { 113 if (mpStream) 114 mpStream->Release(); 115 119 116 if (mpFormatEtc) 120 117 delete[] mpFormatEtc; … … 123 120 delete[] mpStgMedium; 124 121 125 if (mpvData)126 RTMemFree(mpvData);127 128 122 LogFlowFunc(("mRefCount=%RI32\n", mRefCount)); 129 123 } … … 135 129 STDMETHODIMP_(ULONG) VBoxClipboardWinDataObject::AddRef(void) 136 130 { 137 return InterlockedIncrement(&mRefCount); 131 LONG lCount = InterlockedIncrement(&mRefCount); 132 LogFlowFunc(("lCount=%RI32\n", lCount)); 133 return lCount; 138 134 } 139 135 … … 141 137 { 142 138 LONG lCount = InterlockedDecrement(&mRefCount); 139 LogFlowFunc(("lCount=%RI32\n", mRefCount)); 143 140 if (lCount == 0) 144 141 { … … 164 161 *ppvObject = 0; 165 162 return E_NOINTERFACE; 163 } 164 165 int VBoxClipboardWinDataObject::copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal) 166 { 167 AssertPtrReturn(phGlobal, VERR_INVALID_POINTER); 168 169 HGLOBAL hGlobal = GlobalAlloc(fFlags, cbData); 170 if (!hGlobal) 171 return VERR_NO_MEMORY; 172 173 void *pvAlloc = GlobalLock(hGlobal); 174 if (pvAlloc) 175 { 176 CopyMemory(pvAlloc, pvData, cbData); 177 GlobalUnlock(hGlobal); 178 179 *phGlobal = hGlobal; 180 181 return VINF_SUCCESS; 182 } 183 184 GlobalFree(hGlobal); 185 return VERR_ACCESS_DENIED; 186 } 187 188 int VBoxClipboardWinDataObject::createFileGroupDescriptor(const SharedClipboardURIList &URIList, HGLOBAL *phGlobal) 189 { 190 // AssertReturn(URIList.GetRootCount(), VERR_INVALID_PARAMETER); 191 AssertPtrReturn(phGlobal, VERR_INVALID_POINTER); 192 193 int rc; 194 195 const size_t cItems = 2; URIList.GetRootCount(); 196 const size_t cbFGD = sizeof(FILEGROUPDESCRIPTOR) + sizeof(FILEDESCRIPTOR) * (cItems - 1); 197 198 LogFunc(("cItmes=%zu\n", cItems)); 199 200 FILEGROUPDESCRIPTOR *pFGD = (FILEGROUPDESCRIPTOR *)RTMemAlloc(cbFGD); 201 if (pFGD) 202 { 203 pFGD->cItems = (UINT)cItems; 204 205 206 FILEDESCRIPTOR *pFD = &pFGD->fgd[0]; 207 RT_BZERO(pFD, sizeof(FILEDESCRIPTOR)); 208 209 RTStrPrintf(pFD->cFileName, sizeof(pFD->cFileName), "barbaz.txt\n"); 210 211 #if 1 212 pFD->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_PROGRESSUI; 213 pFD->dwFileAttributes = FILE_ATTRIBUTE_NORMAL; // FILE_ATTRIBUTE_DIRECTORY; 214 215 uint64_t cbSize = _1M; 216 217 pFD->nFileSizeHigh = RT_HI_U32(cbSize); 218 pFD->nFileSizeLow = RT_LO_U32(cbSize); 219 #else 220 pFD->dwFlags = FD_ATTRIBUTES | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_FILESIZE; 221 pFD->dwFileAttributes = 222 pFD->ftCreationTime = 223 pFD->ftLastAccessTime = 224 pFD->ftLastWriteTime = 225 pFD->nFileSizeHigh = 226 pFD->nFileSizeLow = 227 #endif 228 229 230 231 pFD = &pFGD->fgd[1]; 232 RT_BZERO(pFD, sizeof(FILEDESCRIPTOR)); 233 234 RTStrPrintf(pFD->cFileName, sizeof(pFD->cFileName), "barbaz_dir\n"); 235 236 #if 1 237 pFD->dwFlags = FD_ATTRIBUTES | FD_PROGRESSUI; 238 pFD->dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY; 239 #else 240 pFD->dwFlags = FD_ATTRIBUTES | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_FILESIZE; 241 pFD->dwFileAttributes = 242 pFD->ftCreationTime = 243 pFD->ftLastAccessTime = 244 pFD->ftLastWriteTime = 245 pFD->nFileSizeHigh = 246 pFD->nFileSizeLow = 247 #endif 248 249 250 rc = copyToHGlobal(pFGD, cbFGD, GMEM_MOVEABLE, phGlobal); 251 } 252 else 253 rc = VERR_NO_MEMORY; 254 255 return rc; 166 256 } 167 257 … … 180 270 AssertPtrReturn(pMedium, DV_E_FORMATETC); 181 271 272 LogFlowFuncEnter(); 273 182 274 ULONG lIndex; 183 if (! LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */275 if (!lookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */ 184 276 return DV_E_FORMATETC; 185 277 if (lIndex >= mcFormats) /* Paranoia. */ 186 return DV_E_ FORMATETC;278 return DV_E_LINDEX; 187 279 188 280 LPFORMATETC pThisFormat = &mpFormatEtc[lIndex]; … … 196 288 HRESULT hr = DV_E_FORMATETC; /* Play safe. */ 197 289 198 LogFlowFunc(("mStatus=%ld\n", mStatus)); 199 if (mStatus == Dropping) 200 { 201 LogRel2(("Clipboard: Waiting for drop event ...\n")); 202 int rc2 = RTSemEventWait(mEventDropped, RT_INDEFINITE_WAIT); 203 LogFlowFunc(("rc2=%Rrc, mStatus=%ld\n", rc2, mStatus)); RT_NOREF(rc2); 204 } 205 206 if (mStatus == Dropped) 207 { 208 LogRel2(("Clipboard: Drop event received\n")); 209 LogRel3(("Clipboard: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n", 210 pThisFormat->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), 211 pThisFormat->tymed, pThisFormat->dwAspect)); 212 LogRel3(("Clipboard: Got strFormat=%s, pvData=%p, cbData=%RU32\n", 213 mstrFormat.c_str(), mpvData, mcbData)); 214 215 /* 216 * Initialize default values. 217 */ 290 LogRel3(("Clipboard: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32 -> lIndex=%u\n", 291 pThisFormat->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), 292 pThisFormat->tymed, pThisFormat->dwAspect, lIndex)); 293 294 /* 295 * Initialize default values. 296 */ 297 pMedium->tymed = pThisFormat->tymed; 298 pMedium->pUnkForRelease = NULL; /* Caller is responsible for deleting the data. */ 299 300 switch (lIndex) 301 { 302 case FormatIndex_FileDescriptorA: 303 { 304 LogFlowFunc(("FormatIndex_FileDescriptorA\n")); 305 306 SharedClipboardURIList mURIList; 307 // mURIList.AppendURIPath() 308 309 HGLOBAL hGlobal; 310 int rc = createFileGroupDescriptor(mURIList, &hGlobal); 311 if (RT_SUCCESS(rc)) 312 { 313 pMedium->tymed = TYMED_HGLOBAL; 314 pMedium->hGlobal = hGlobal; 315 316 hr = S_OK; 317 } 318 break; 319 } 320 321 case FormatIndex_FileDescriptorW: 322 LogFlowFunc(("FormatIndex_FileDescriptorW\n")); 323 break; 324 325 case FormatIndex_FileContents: 326 { 327 LogFlowFunc(("FormatIndex_FileContents\n")); 328 329 hr = VBoxClipboardWinStreamImpl::Create(&mpStream); 330 if (SUCCEEDED(hr)) 331 { 332 /* Hand over the stream to the caller. */ 333 pMedium->tymed = TYMED_ISTREAM; 334 pMedium->pstm = mpStream; 335 } 336 337 break; 338 } 339 340 default: 341 break; 342 } 343 344 /* Error handling; at least return some basic data. */ 345 if (FAILED(hr)) 346 { 347 LogFunc(("Failed; copying medium ...\n")); 348 218 349 pMedium->tymed = pThisFormat->tymed; 219 350 pMedium->pUnkForRelease = NULL; 220 221 /*222 * URI list handling.223 */224 if (mstrFormat.equalsIgnoreCase("text/uri-list"))225 {226 int rc = VINF_SUCCESS;227 228 RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");229 RTCList<RTCString> lstFiles;230 for (size_t i = 0; i < lstFilesURI.size(); i++)231 {232 char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).c_str());233 if (pszFilePath)234 {235 lstFiles.append(pszFilePath);236 RTStrFree(pszFilePath);237 }238 else /* Unable to parse -- refuse entire request. */239 {240 lstFiles.clear();241 rc = VERR_INVALID_PARAMETER;242 break;243 }244 }245 246 size_t cFiles = lstFiles.size();247 if ( RT_SUCCESS(rc)248 && cFiles)249 {250 #ifdef DEBUG251 LogFlowFunc(("Files (%zu)\n", cFiles));252 for (size_t i = 0; i < cFiles; i++)253 LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));254 #endif255 256 #if 0257 if ( (pFormatEtc->tymed & TYMED_ISTREAM)258 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)259 && (pFormatEtc->cfFormat == CF_FILECONTENTS))260 {261 262 }263 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)264 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)265 && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))266 {267 268 }269 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)270 && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))271 {272 HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));273 DWORD *pdwEffect = (DWORD *)GlobalLock(hData);274 AssertPtr(pdwEffect);275 *pdwEffect = DROPEFFECT_COPY;276 GlobalUnlock(hData);277 278 pMedium->hGlobal = hData;279 pMedium->tymed = TYMED_HGLOBAL;280 }281 else282 #endif283 if ( (pFormatEtc->tymed & TYMED_HGLOBAL)284 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)285 && (pFormatEtc->cfFormat == CF_TEXT))286 {287 pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);288 if (pMedium->hGlobal)289 {290 char *pcDst = (char *)GlobalLock(pMedium->hGlobal);291 memcpy(pcDst, mpvData, mcbData);292 pcDst[mcbData] = '\0';293 GlobalUnlock(pMedium->hGlobal);294 295 hr = S_OK;296 }297 }298 else if ( (pFormatEtc->tymed & TYMED_HGLOBAL)299 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)300 && (pFormatEtc->cfFormat == CF_HDROP))301 {302 size_t cchFiles = 0; /* Number of ASCII characters. */303 for (size_t i = 0; i < cFiles; i++)304 {305 cchFiles += strlen(lstFiles.at(i).c_str());306 cchFiles += 1; /* Terminating '\0'. */307 }308 309 size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));310 DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);311 if (pBuf)312 {313 pBuf->pFiles = sizeof(DROPFILES);314 pBuf->fWide = 1; /* We use unicode. Always. */315 316 uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles;317 AssertPtr(pCurFile);318 319 for (size_t i = 0; i < cFiles && RT_SUCCESS(rc); i++)320 {321 size_t cchCurFile;322 PRTUTF16 pwszFile;323 rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile);324 if (RT_SUCCESS(rc))325 {326 cchCurFile = RTUtf16Len(pwszFile);327 Assert(cchCurFile);328 memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));329 RTUtf16Free(pwszFile);330 }331 else332 break;333 334 pCurFile += cchCurFile * sizeof(RTUTF16);335 336 /* Terminate current file name. */337 *pCurFile = L'\0';338 pCurFile += sizeof(RTUTF16);339 }340 341 if (RT_SUCCESS(rc))342 {343 *pCurFile = L'\0'; /* Final list terminator. */344 345 pMedium->tymed = TYMED_HGLOBAL;346 pMedium->pUnkForRelease = NULL;347 pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT348 | GMEM_MOVEABLE349 | GMEM_DDESHARE, cbBuf);350 if (pMedium->hGlobal)351 {352 LPVOID pMem = GlobalLock(pMedium->hGlobal);353 if (pMem)354 {355 memcpy(pMem, pBuf, cbBuf);356 GlobalUnlock(pMedium->hGlobal);357 358 hr = S_OK;359 }360 }361 }362 363 RTMemFree(pBuf);364 }365 else366 rc = VERR_NO_MEMORY;367 }368 }369 370 if (RT_FAILURE(rc))371 hr = DV_E_FORMATETC;372 }373 /*374 * Plain text handling.375 */376 else if ( mstrFormat.equalsIgnoreCase("text/plain")377 || mstrFormat.equalsIgnoreCase("text/html")378 || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-8")379 || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-16")380 || mstrFormat.equalsIgnoreCase("text/richtext")381 || mstrFormat.equalsIgnoreCase("UTF8_STRING")382 || mstrFormat.equalsIgnoreCase("TEXT")383 || mstrFormat.equalsIgnoreCase("STRING"))384 {385 pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);386 if (pMedium->hGlobal)387 {388 char *pcDst = (char *)GlobalLock(pMedium->hGlobal);389 memcpy(pcDst, mpvData, mcbData);390 pcDst[mcbData] = '\0';391 GlobalUnlock(pMedium->hGlobal);392 393 hr = S_OK;394 }395 }396 else397 LogRel(("Clipboard: Error: Format '%s' not implemented\n", mstrFormat.c_str()));398 }399 400 /* Error handling; at least return some basic data. */401 if (FAILED(hr))402 {403 LogFlowFunc(("Copying medium ...\n"));404 switch (pThisMedium->tymed)405 {406 407 case TYMED_HGLOBAL:408 pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,409 pThisFormat->cfFormat, NULL);410 break;411 412 default:413 break;414 }415 416 pMedium->tymed = pThisFormat->tymed;417 pMedium->pUnkForRelease = NULL;418 351 } 419 352 420 353 if (hr == DV_E_FORMATETC) 421 LogRel(("Clipboard: Error handling format '%s' (%RU32 bytes)\n", mstrFormat.c_str(), mcbData));354 LogRel(("Clipboard: Error handling format\n")); 422 355 423 356 LogFlowFunc(("hr=%Rhrc\n", hr)); … … 437 370 RT_NOREF(pFormatEtc, pMedium); 438 371 LogFlowFunc(("\n")); 439 return DATA_E_FORMATETC;372 return E_NOTIMPL; 440 373 } 441 374 … … 450 383 { 451 384 LogFlowFunc(("\n")); 452 return ( LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;385 return (lookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC; 453 386 } 454 387 … … 466 399 { 467 400 RT_NOREF(pFormatEtc, pMedium, fRelease); 401 LogFlowFunc(("\n")); 402 468 403 return E_NOTIMPL; 469 404 } … … 501 436 } 502 437 438 #ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC 439 /* 440 * IDataObjectAsyncCapability methods. 441 */ 442 443 STDMETHODIMP VBoxClipboardWinDataObject::EndOperation(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects) 444 { 445 RT_NOREF(hResult, pbcReserved, dwEffects); 446 return E_NOTIMPL; 447 } 448 449 STDMETHODIMP VBoxClipboardWinDataObject::GetAsyncMode(BOOL* pfIsOpAsync) 450 { 451 RT_NOREF(pfIsOpAsync); 452 return E_NOTIMPL; 453 } 454 455 STDMETHODIMP VBoxClipboardWinDataObject::InOperation(BOOL* pfInAsyncOp) 456 { 457 RT_NOREF(pfInAsyncOp); 458 return E_NOTIMPL; 459 } 460 461 STDMETHODIMP VBoxClipboardWinDataObject::SetAsyncMode(BOOL fDoOpAsync) 462 { 463 RT_NOREF(fDoOpAsync); 464 return E_NOTIMPL; 465 } 466 467 STDMETHODIMP VBoxClipboardWinDataObject::StartOperation(IBindCtx* pbcReserved) 468 { 469 RT_NOREF(pbcReserved); 470 return E_NOTIMPL; 471 } 472 #endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */ 473 503 474 /* 504 475 * Own stuff. 505 476 */ 506 477 507 int VBoxClipboardWinDataObject::Abort(void) 508 { 509 LogFlowFunc(("Aborting ...\n")); 510 mStatus = Aborted; 511 return RTSemEventSignal(mEventDropped); 478 int VBoxClipboardWinDataObject::Init(uint32_t idClient) 479 { 480 muClientID = idClient; 481 482 LogFlowFuncLeaveRC(VINF_SUCCESS); 483 return VINF_SUCCESS; 512 484 } 513 485 … … 595 567 } 596 568 597 bool VBoxClipboardWinDataObject:: LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)569 bool VBoxClipboardWinDataObject::lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex) 598 570 { 599 571 AssertReturn(pFormatEtc, false); … … 622 594 } 623 595 624 /* static */ 625 HGLOBAL VBoxClipboardWinDataObject::MemDup(HGLOBAL hMemSource) 626 { 627 DWORD dwLen = GlobalSize(hMemSource); 628 AssertReturn(dwLen, NULL); 629 PVOID pvSource = GlobalLock(hMemSource); 630 if (pvSource) 631 { 632 PVOID pvDest = GlobalAlloc(GMEM_FIXED, dwLen); 633 if (pvDest) 634 memcpy(pvDest, pvSource, dwLen); 635 636 GlobalUnlock(hMemSource); 637 return pvDest; 638 } 639 640 return NULL; 641 } 642 643 void VBoxClipboardWinDataObject::RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, 644 TYMED tyMed, LONG lIndex, DWORD dwAspect, 645 DVTARGETDEVICE *pTargetDevice) 596 void VBoxClipboardWinDataObject::registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, 597 TYMED tyMed, LONG lIndex, DWORD dwAspect, 598 DVTARGETDEVICE *pTargetDevice) 646 599 { 647 600 AssertPtr(pFormatEtc); … … 657 610 } 658 611 659 void VBoxClipboardWinDataObject::SetStatus(Status status)660 {661 LogFlowFunc(("Setting status to %ld\n", status));662 mStatus = status;663 }664 665 int VBoxClipboardWinDataObject::Signal(const RTCString &strFormat,666 const void *pvData, uint32_t cbData)667 {668 int rc;669 670 if (cbData)671 {672 mpvData = RTMemAlloc(cbData);673 if (mpvData)674 {675 memcpy(mpvData, pvData, cbData);676 mcbData = cbData;677 rc = VINF_SUCCESS;678 }679 else680 rc = VERR_NO_MEMORY;681 }682 else683 rc = VINF_SUCCESS;684 685 if (RT_SUCCESS(rc))686 {687 mStatus = Dropped;688 mstrFormat = strFormat;689 }690 else691 {692 mStatus = Aborted;693 }694 695 /* Signal in any case. */696 LogRel2(("Clipboard: Signalling drop event\n"));697 698 int rc2 = RTSemEventSignal(mEventDropped);699 if (RT_SUCCESS(rc))700 rc = rc2;701 702 LogFunc(("mStatus=%RU32, rc=%Rrc\n", mStatus, rc));703 return rc;704 }705 -
trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp
r78440 r78474 25 25 #include <iprt/asm.h> 26 26 #include <iprt/ldr.h> 27 #include <iprt/thread.h> 27 28 28 29 #include <VBox/GuestHost/SharedClipboard.h> … … 43 44 *********************************************************************************************************************************/ 44 45 46 47 48 VBoxClipboardWinStreamImpl::VBoxClipboardWinStreamImpl(void) 49 : m_lRefCount(1) 50 { 51 52 } 53 54 VBoxClipboardWinStreamImpl::~VBoxClipboardWinStreamImpl(void) 55 { 56 } 57 58 /* 59 * IUnknown methods. 60 */ 61 62 STDMETHODIMP VBoxClipboardWinStreamImpl::QueryInterface(REFIID iid, void ** ppvObject) 63 { 64 AssertPtrReturn(ppvObject, E_INVALIDARG); 65 66 if ( iid == IID_IStream 67 || iid == IID_IUnknown) 68 { 69 AddRef(); 70 *ppvObject = this; 71 return S_OK; 72 } 73 74 *ppvObject = 0; 75 return E_NOINTERFACE; 76 } 77 78 STDMETHODIMP_(ULONG) VBoxClipboardWinStreamImpl::AddRef(void) 79 { 80 LONG lCount = InterlockedIncrement(&m_lRefCount); 81 LogFlowFunc(("lCount=%RI32\n", lCount)); 82 return lCount; 83 } 84 85 STDMETHODIMP_(ULONG) VBoxClipboardWinStreamImpl::Release(void) 86 { 87 LONG lCount = InterlockedDecrement(&m_lRefCount); 88 LogFlowFunc(("lCount=%RI32\n", m_lRefCount)); 89 if (lCount == 0) 90 { 91 delete this; 92 return 0; 93 } 94 95 return lCount; 96 } 97 98 /* 99 * IStream methods. 100 */ 101 102 STDMETHODIMP VBoxClipboardWinStreamImpl::Clone(IStream** ppStream) 103 { 104 RT_NOREF(ppStream); 105 106 LogFlowFuncEnter(); 107 return E_NOTIMPL; 108 } 109 110 STDMETHODIMP VBoxClipboardWinStreamImpl::Commit(DWORD dwFrags) 111 { 112 RT_NOREF(dwFrags); 113 114 LogFlowFuncEnter(); 115 return E_NOTIMPL; 116 } 117 118 STDMETHODIMP VBoxClipboardWinStreamImpl::CopyTo(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, 119 ULARGE_INTEGER* nBytesWritten) 120 { 121 RT_NOREF(pDestStream, nBytesToCopy, nBytesRead, nBytesWritten); 122 123 LogFlowFuncEnter(); 124 return E_NOTIMPL; 125 } 126 127 STDMETHODIMP VBoxClipboardWinStreamImpl::LockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags) 128 { 129 RT_NOREF(nStart, nBytes, dwFlags); 130 131 LogFlowFuncEnter(); 132 return E_NOTIMPL; 133 } 134 135 static ULONG cbFileSize = _1M; 136 static ULONG cbSizeRead = 0; 137 138 STDMETHODIMP VBoxClipboardWinStreamImpl::Read(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead) 139 { 140 /* If the file size is 0, already return at least 1 byte, else the whole operation will fail. */ 141 142 ULONG cbToRead = RT_MIN(cbFileSize - cbSizeRead, _4K /* nBytesToRead */); 143 144 if (cbToRead > nBytesToRead) 145 cbToRead = nBytesToRead; 146 147 LogFlowFunc(("pvBuffer=%p, nBytesToRead=%u -> cbSizeRead=%u, cbToRead=%u\n", pvBuffer, nBytesToRead, cbSizeRead, cbToRead)); 148 149 if (cbToRead) 150 { 151 memset(pvBuffer, cbToRead, 0x65); 152 cbSizeRead += cbToRead; 153 } 154 155 if (nBytesRead) 156 *nBytesRead = cbToRead; 157 158 if (cbSizeRead == cbFileSize) 159 cbSizeRead = 0; 160 161 return S_OK; 162 } 163 164 STDMETHODIMP VBoxClipboardWinStreamImpl::Revert(void) 165 { 166 LogFlowFuncEnter(); 167 return E_NOTIMPL; 168 } 169 170 STDMETHODIMP VBoxClipboardWinStreamImpl::Seek(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos) 171 { 172 RT_NOREF(nMove, dwOrigin, nNewPos); 173 174 LogFlowFuncEnter(); 175 return E_NOTIMPL; 176 } 177 178 STDMETHODIMP VBoxClipboardWinStreamImpl::SetSize(ULARGE_INTEGER nNewSize) 179 { 180 RT_NOREF(nNewSize); 181 182 LogFlowFuncEnter(); 183 return E_NOTIMPL; 184 } 185 186 STDMETHODIMP VBoxClipboardWinStreamImpl::Stat(STATSTG* statstg, DWORD dwFlags) 187 { 188 RT_NOREF(statstg, dwFlags); 189 190 LogFlowFuncEnter(); 191 return E_NOTIMPL; 192 } 193 194 STDMETHODIMP VBoxClipboardWinStreamImpl::UnlockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags) 195 { 196 RT_NOREF(nStart, nBytes, dwFlags); 197 198 LogFlowFuncEnter(); 199 return E_NOTIMPL; 200 } 201 202 STDMETHODIMP VBoxClipboardWinStreamImpl::Write(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead) 203 { 204 RT_NOREF(pvBuffer, nBytesToRead, nBytesRead); 205 206 LogFlowFuncEnter(); 207 return E_NOTIMPL; 208 } 209 210 /* 211 * Own stuff. 212 */ 213 214 /* static */ 215 HRESULT VBoxClipboardWinStreamImpl::Create(IStream **ppStream) 216 { 217 VBoxClipboardWinStreamImpl *pStream = new VBoxClipboardWinStreamImpl(); 218 if (pStream) 219 { 220 pStream->AddRef(); 221 222 *ppStream = pStream; 223 return S_OK; 224 } 225 226 return E_FAIL; 227 } 228 -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp
r78440 r78474 87 87 int rc; 88 88 89 LogFlowFuncEnter(); 90 89 91 const BOOL fRc = CloseClipboard(); 90 92 if (RT_UNLIKELY(!fRc)) 91 93 { 92 94 const DWORD dwLastErr = GetLastError(); 93 rc = RTErrConvertFromWin32(dwLastErr); 95 if (dwLastErr == ERROR_CLIPBOARD_NOT_OPEN) 96 rc = VERR_INVALID_STATE; 97 else 98 rc = RTErrConvertFromWin32(dwLastErr); 99 94 100 LogFunc(("Failed with %Rrc (0x%x)\n", rc, dwLastErr)); 95 101 } … … 108 114 { 109 115 int rc; 116 117 LogFlowFuncEnter(); 110 118 111 119 const BOOL fRc = EmptyClipboard(); … … 113 121 { 114 122 const DWORD dwLastErr = GetLastError(); 115 rc = RTErrConvertFromWin32(dwLastErr); 123 if (dwLastErr == ERROR_CLIPBOARD_NOT_OPEN) 124 rc = VERR_INVALID_STATE; 125 else 126 rc = RTErrConvertFromWin32(dwLastErr); 127 116 128 LogFunc(("Failed with %Rrc (0x%x)\n", rc, dwLastErr)); 117 129 } … … 265 277 } 266 278 279 VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat) 280 { 281 /* Insert the requested clipboard format data into the clipboard. */ 282 VBOXCLIPBOARDFORMAT vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE; 283 284 switch (uFormat) 285 { 286 case CF_UNICODETEXT: 287 vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 288 break; 289 290 case CF_DIB: 291 vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP; 292 break; 293 294 default: 295 if (uFormat >= 0xC000) /** Formats registered with RegisterClipboardFormat() start at this index. */ 296 { 297 TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */ 298 int cActual = GetClipboardFormatName(uFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR)); 299 if (cActual) 300 { 301 LogFunc(("szFormatName=%s\n", szFormatName)); 302 303 if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_HTML) == 0) 304 vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML; 305 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 306 else if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST) == 0) 307 vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST; 308 #endif 309 } 310 } 311 break; 312 } 313 314 return vboxFormat; 315 } 316 267 317 /** 268 318 * Retrieves all supported clipboard formats of a specific clipboard. … … 270 320 * @returns VBox status code. 271 321 * @param pCtx Windows clipboard context to retrieve formats for. 272 * @param p uFormats Where to store the retrieved formats of type VBOX_SHARED_CLIPBOARD_FMT_ (bitmask).273 */ 274 int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, uint32_t *puFormats)322 * @param pfFormats Where to store the retrieved formats of type VBOX_SHARED_CLIPBOARD_FMT_ (bitmask). 323 */ 324 int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, PVBOXCLIPBOARDFORMATS pfFormats) 275 325 { 276 326 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 277 AssertPtrReturn(p uFormats, VERR_INVALID_POINTER);278 279 uint32_t uFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE;327 AssertPtrReturn(pfFormats, VERR_INVALID_POINTER); 328 329 VBOXCLIPBOARDFORMATS fFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE; 280 330 281 331 /* Query list of available formats and report to host. */ … … 283 333 if (RT_SUCCESS(rc)) 284 334 { 285 UINT uCurFormat = 0; 335 UINT uCurFormat = 0; /* Must be set to zero for EnumClipboardFormats(). */ 286 336 while ((uCurFormat = EnumClipboardFormats(uCurFormat)) != 0) 287 { 288 LogFlowFunc(("uFormat = 0x%08X\n", uCurFormat)); 289 switch (uCurFormat) 290 { 291 case CF_UNICODETEXT: 292 case CF_TEXT: 293 uFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 294 break; 295 296 case CF_DIB: 297 case CF_BITMAP: 298 uFormats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP; 299 break; 300 301 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 302 case CF_HDROP: 303 uFormats |= VBOX_SHARED_CLIPBOARD_FMT_URI_LIST; 304 break; 305 #endif 306 default: 307 { 308 if (uCurFormat >= 0xC000) /** @todo r=andy Find a define for this. */ 309 { 310 TCHAR szFormatName[256]; /** @todo r=andy Is this enough? */ 311 int cActual = GetClipboardFormatName(uCurFormat, szFormatName, sizeof(szFormatName)/sizeof (TCHAR)); 312 if (cActual) 313 { 314 if (strcmp (szFormatName, "HTML Format") == 0) 315 { 316 uFormats |= VBOX_SHARED_CLIPBOARD_FMT_HTML; 317 } 318 } 319 } 320 break; 321 } 322 } 323 } 337 fFormats |= VBoxClipboardWinClipboardFormatToVBox(uCurFormat); 324 338 325 339 int rc2 = VBoxClipboardWinClose(); … … 333 347 else 334 348 { 335 LogFlowFunc((" uFormats = 0x%08X\n", uFormats));336 *p uFormats = uFormats;337 } 338 339 return rc; 340 } 341 349 LogFlowFunc(("pfFormats=0x%08X\n", pfFormats)); 350 *pfFormats = fFormats; 351 } 352 353 return rc; 354 } 355
Note:
See TracChangeset
for help on using the changeset viewer.