/****************************************************************************** * CLIPFORMAT_UserSize [OLE32.@] * * Calculates the buffer size required to marshal a clip format. * * PARAMS * pFlags [I] Flags. See notes. * StartingSize [I] Starting size of the buffer. This value is added on to * the buffer size required for the clip format. * pCF [I] Clip format to size. * * RETURNS * The buffer size required to marshal a clip format plus the starting size. * * NOTES * Even though the function is documented to take a pointer to an unsigned * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which * the first parameter is an unsigned long. * This function is only intended to be called by the RPC runtime. */ unsigned long __RPC_USER CLIPFORMAT_UserSize(unsigned long *pFlags, unsigned long StartingSize, CLIPFORMAT *pCF) { unsigned long size = StartingSize; TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, pCF); size += sizeof(userCLIPFORMAT); /* only need to marshal the name if it is not a pre-defined type and * we are going remote */ if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)) { WCHAR format[255]; INT ret; size += 3 * sizeof(INT); /* urg! this function is badly designed because it won't tell us how * much space is needed without doing a dummy run of storing the * name into a buffer */ ret = GetClipboardFormatNameW(*pCF, format, sizeof(format)/sizeof(format[0])-1); if (!ret) RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL); size += (ret + 1) * sizeof(WCHAR); } return size; }
/* static */ void VBoxDnDDropTarget::DumpFormats(IDataObject *pDataObject) { AssertPtrReturnVoid(pDataObject); /* Enumerate supported source formats. This shouldn't happen too often * on day to day use, but still keep it in here. */ IEnumFORMATETC *pEnumFormats; HRESULT hr2 = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormats); if (SUCCEEDED(hr2)) { LogRel(("DnD: The following formats were offered to us:\n")); FORMATETC curFormatEtc; while (pEnumFormats->Next(1, &curFormatEtc, NULL /* pceltFetched */) == S_OK) { WCHAR wszCfName[128]; /* 128 chars should be enough, rest will be truncated. */ hr2 = GetClipboardFormatNameW(curFormatEtc.cfFormat, wszCfName, sizeof(wszCfName) / sizeof(WCHAR)); LogRel(("\tcfFormat=%RI16 (%s), tyMed=%RI32, dwAspect=%RI32, strCustomName=%ls, hr=%Rhrc\n", curFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(curFormatEtc.cfFormat), curFormatEtc.tymed, curFormatEtc.dwAspect, wszCfName, hr2)); } pEnumFormats->Release(); } }
Clipboard::Format::Format(UINT format, SIZE_T size) : format_(format), size_(size), data_(std::make_unique<char[]>(size)) { if (0xC000 <= format) { // registered format name_.resize(256); auto length = GetClipboardFormatNameW(format, &name_[0], static_cast<int>(name_.size() + 1)); name_.resize(length); } }
/************************************************************************** * GetClipboardFormatNameA (USER32.@) */ INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen) { INT ret; LPWSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen*sizeof(WCHAR) ); if(p == NULL) return 0; /* FIXME: is this the correct failure value? */ ret = GetClipboardFormatNameW( wFormat, p, maxlen ); if (ret && maxlen > 0 && !WideCharToMultiByte( CP_ACP, 0, p, -1, retStr, maxlen, 0, 0)) retStr[maxlen-1] = 0; HeapFree( GetProcessHeap(), 0, p ); return ret; }
/** * Get the clipboard name if there is one. * @param UINT format the format we want the name of. * @return wchar_t* the format name or NULL if there isn't one, (or not needed). */ wchar_t* ClipboardData::GetClipboardName(UINT format) { // if it is a known type then we don't need/have the name if (format < CF_MAX) { return NULL; } // get the text from the clipboard. static const unsigned l = 1024; // max len of the meta file wchar_t* dataName = new wchar_t[l + 1]; memset(dataName, 0, l + 1); if (GetClipboardFormatNameW(format, dataName, l) == 0) { // either it did not work // or the value we found is not good. delete[] dataName; return NULL; } // return the value we found. return dataName; }
/****************************************************************************** * CLIPFORMAT_UserMarshal [OLE32.@] * * Marshals a clip format into a buffer. * * PARAMS * pFlags [I] Flags. See notes. * pBuffer [I] Buffer to marshal the clip format into. * pCF [I] Clip format to marshal. * * RETURNS * The end of the marshaled data in the buffer. * * NOTES * Even though the function is documented to take a pointer to an unsigned * long in pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which * the first parameter is an unsigned long. * This function is only intended to be called by the RPC runtime. */ unsigned char * __RPC_USER CLIPFORMAT_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF) { wireCLIPFORMAT wirecf = (wireCLIPFORMAT)pBuffer; TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &0x%04x\n", pBuffer, *pCF); wirecf->u.dwValue = *pCF; pBuffer += sizeof(*wirecf); /* only need to marshal the name if it is not a pre-defined type and * we are going remote */ if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)) { WCHAR format[255]; INT len; wirecf->fContext = WDT_REMOTE_CALL; len = GetClipboardFormatNameW(*pCF, format, sizeof(format)/sizeof(format[0])-1); if (!len) RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL); len += 1; *(INT *)pBuffer = len; pBuffer += sizeof(INT); *(INT *)pBuffer = 0; pBuffer += sizeof(INT); *(INT *)pBuffer = len; pBuffer += sizeof(INT); TRACE("marshaling format name %s\n", debugstr_wn(format, len-1)); lstrcpynW((LPWSTR)pBuffer, format, len); pBuffer += len * sizeof(WCHAR); *(WCHAR *)pBuffer = '\0'; pBuffer += sizeof(WCHAR); } else wirecf->fContext = WDT_INPROC_CALL; return pBuffer; }
static void cliprdr_send_format_list(cliprdrContext *cliprdr) { RDP_CB_FORMAT_LIST_EVENT *cliprdr_event; BYTE *format_data; int format = 0; int data_size; int format_count; int len = 0; int namelen; if (!OpenClipboard(cliprdr->hwndClipboard)) { DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError()); return; } format_count = CountClipboardFormats(); data_size = format_count * (4 + MAX_PATH * 2); format_data = (BYTE *)calloc(1, data_size); assert(format_data != NULL); while (format = EnumClipboardFormats(format)) { Write_UINT32(format_data + len, format); len += 4; if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) { if (format >= CF_MAX) { namelen = GetClipboardFormatNameW(format, (LPWSTR)(format_data + len), MAX_PATH); len += namelen * sizeof(WCHAR); } len += 2; /* end of Unicode string */ } else { if (format >= CF_MAX) { static wchar_t wName[MAX_PATH] = {0}; int wLen; ZeroMemory(wName, MAX_PATH*2); wLen = GetClipboardFormatNameW(format, wName, MAX_PATH); if (wLen < 16) { memcpy(format_data + len, wName, wLen * sizeof(WCHAR)); } else { memcpy(format_data + len, wName, 32); /* truncate the long name to 32 bytes */ } } len += 32; } } CloseClipboard(); cliprdr_event = (RDP_CB_FORMAT_LIST_EVENT *) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL); cliprdr_event->raw_format_data = (BYTE *)calloc(1, len); assert(cliprdr_event->raw_format_data != NULL); CopyMemory(cliprdr_event->raw_format_data, format_data, len); cliprdr_event->raw_format_data_size = len; free(format_data); freerdp_channels_send_event(cliprdr->channels, (wMessage *) cliprdr_event); }
/* static */ const char* UIDnDDataObject::ClipboardFormatToString(CLIPFORMAT fmt) { WCHAR wszFormat[128]; if (GetClipboardFormatNameW(fmt, wszFormat, sizeof(wszFormat) / sizeof(WCHAR))) LogFlowFunc(("wFormat=%RI16, szName=%ls\n", fmt, wszFormat)); switch (fmt) { case 1: return "CF_TEXT"; case 2: return "CF_BITMAP"; case 3: return "CF_METAFILEPICT"; case 4: return "CF_SYLK"; case 5: return "CF_DIF"; case 6: return "CF_TIFF"; case 7: return "CF_OEMTEXT"; case 8: return "CF_DIB"; case 9: return "CF_PALETTE"; case 10: return "CF_PENDATA"; case 11: return "CF_RIFF"; case 12: return "CF_WAVE"; case 13: return "CF_UNICODETEXT"; case 14: return "CF_ENHMETAFILE"; case 15: return "CF_HDROP"; case 16: return "CF_LOCALE"; case 17: return "CF_DIBV5"; case 18: return "CF_MAX"; case 49158: return "FileName"; case 49159: return "FileNameW"; case 49161: return "DATAOBJECT"; case 49171: return "Ole Private Data"; case 49314: return "Shell Object Offsets"; case 49316: return "File Contents"; case 49317: return "File Group Descriptor"; case 49323: return "Preferred Drop Effect"; case 49380: return "Shell Object Offsets"; case 49382: return "FileContents"; case 49383: return "FileGroupDescriptor"; case 49389: return "Preferred DropEffect"; case 49268: return "Shell IDList Array"; case 49619: return "RenPrivateFileAttachments"; default: break; } return "unknown"; }
STDMETHODIMP VBoxDnDDropTarget::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { AssertPtrReturn(pDataObject, E_INVALIDARG); AssertPtrReturn(pdwEffect, E_INVALIDARG); LogFlowFunc(("pDataObject=0x%p, grfKeyState=0x%x, x=%ld, y=%ld, dwEffect=%RU32\n", pDataObject, grfKeyState, pt.x, pt.y, *pdwEffect)); reset(); /** @todo At the moment we only support one DnD format at a time. */ /* Try different formats. CF_HDROP is the most common one, so start * with this. */ FORMATETC fmtEtc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; HRESULT hr = pDataObject->QueryGetData(&fmtEtc); if (hr == S_OK) { mFormats = "text/uri-list"; } else { LogFlowFunc(("CF_HDROP not wanted, hr=%Rhrc\n", hr)); /* So we couldn't retrieve the data in CF_HDROP format; try with * CF_UNICODETEXT + CF_TEXT formats now. Rest stays the same. */ fmtEtc.cfFormat = CF_UNICODETEXT; hr = pDataObject->QueryGetData(&fmtEtc); if (hr == S_OK) { mFormats = "text/plain;charset=utf-8"; } else { LogFlowFunc(("CF_UNICODETEXT not wanted, hr=%Rhrc\n", hr)); fmtEtc.cfFormat = CF_TEXT; hr = pDataObject->QueryGetData(&fmtEtc); if (hr == S_OK) { mFormats = "text/plain;charset=utf-8"; } else { LogFlowFunc(("CF_TEXT not wanted, hr=%Rhrc\n", hr)); fmtEtc.cfFormat = 0; /* Mark it to not supported. */ } } } /* Did we find a format that we support? */ if (fmtEtc.cfFormat) { LogFlowFunc(("Found supported format %RI16 (%s)\n", fmtEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(fmtEtc.cfFormat))); /* Make a copy of the FORMATETC structure so that we later can * use this for comparrison and stuff. */ /** Note: The DVTARGETDEVICE member only is a shallow copy for now! */ memcpy(&mFormatEtc, &fmtEtc, sizeof(FORMATETC)); /* Which drop effect we're going to use? */ /* Note: pt is not used since we don't need to differentiate within our * proxy window. */ *pdwEffect = VBoxDnDDropTarget::GetDropEffect(grfKeyState, *pdwEffect); } else { /* No or incompatible data -- so no drop effect required. */ *pdwEffect = DROPEFFECT_NONE; switch (hr) { case ERROR_INVALID_FUNCTION: { LogRel(("DnD: Drag and drop format is not supported by VBoxTray\n")); /* Enumerate supported source formats. This shouldn't happen too often * on day to day use, but still keep it in here. */ IEnumFORMATETC *pEnumFormats; HRESULT hr2 = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormats); if (SUCCEEDED(hr2)) { LogRel(("DnD: The following formats were offered to us:\n")); FORMATETC curFormatEtc; while (pEnumFormats->Next(1, &curFormatEtc, NULL /* pceltFetched */) == S_OK) { WCHAR wszCfName[128]; /* 128 chars should be enough, rest will be truncated. */ hr2 = GetClipboardFormatNameW(curFormatEtc.cfFormat, wszCfName, sizeof(wszCfName) / sizeof(WCHAR)); LogRel(("\tcfFormat=%RI16 (%s), tyMed=%RI32, dwAspect=%RI32, strCustomName=%ls, hr=%Rhrc\n", curFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(curFormatEtc.cfFormat), curFormatEtc.tymed, curFormatEtc.dwAspect, wszCfName, hr2)); } pEnumFormats->Release(); } break; } default: break; } } LogFlowFunc(("Returning cfFormat=%RI16, pdwEffect=%ld, hr=%Rhrc\n", fmtEtc.cfFormat, *pdwEffect, hr)); return hr; }