/// <summary> /// Get the next celt entries from the enumeration /// </summary> /// <param name="celt">entries to fetch</param> /// <param name="rgelt">array to fetch into (allocated by caller)</param> /// <param name="pceltFetched">number of entries fetched</param> /// <returns>S_OK if celt entries are supplied, otherwise S_FALSE</returns> public int Next(uint celt, FORMATETC[] rgelt, IntPtr pceltFetched) { // see how many of the requested items we can serve int itemsRequested = Convert.ToInt32(celt); int itemsToReturn = Math.Min(itemsRequested, oleDataEntries.Count - (currentItem + 1)); // copy the format structures into the caller's array of structures for (int i = 0; i < itemsToReturn; i++) { OleDataEntry dataEntry = (OleDataEntry)oleDataEntries[++currentItem]; rgelt[i] = dataEntry.format; } // update the fetch parameter if requested if (pceltFetched != IntPtr.Zero) { Marshal.WriteInt32(pceltFetched, itemsToReturn); } // return the correct status code depending upon whether we // returned all of the items requested if (itemsToReturn == itemsRequested) { return(HRESULT.S_OK); } else { return(HRESULT.S_FALSE); } }
/// <summary> /// Provides the source data object with data described by a FORMATETC /// structure and an STGMEDIUM structure /// </summary> /// <param name="pFormatEtc">Pointer to the FORMATETC structure defining the /// format used by the data object when interpreting the data contained in the /// storage medium</param> /// <param name="pMedium">Pointer to the STGMEDIUM structure defining the storage /// medium in which the data is being passed</param> /// <param name="fRelease">If TRUE, the data object called, which implements /// IDataObject::SetData, owns the storage medium after the call returns. This /// means it must free the medium after it has been used by calling the /// ReleaseStgMedium function. If FALSE, the caller retains ownership of the /// storage medium and the data object called uses the storage medium for the /// duration of the call only</param> public int SetData(ref FORMATETC pFormatEtc, ref STGMEDIUM pMedium, bool fRelease) { // check and see if we have an existing format of this type int dataFormatIndex; int result = FindDataFormat(ref pFormatEtc, out dataFormatIndex); // if we have an existing format of this type then free it and // remove it from the list if (result == HRESULT.S_OK) { OleDataEntry oleDataEntry = (OleDataEntry)oleDataEntries[dataFormatIndex]; Ole32.ReleaseStgMedium(ref oleDataEntry.stgm); oleDataEntries.RemoveAt(dataFormatIndex); } // create an entry to add to our internal list OleDataEntry dataEntry; // if the caller is releasing the data that is being set then just // copy bit for bit (we are now responsible for freeing the storage) if (fRelease) { dataEntry = new OleDataEntry(pFormatEtc, pMedium); } // if the caller is not releasing the data object to us then // we only get to use it for the duration of the call -- we need // to therefore clone the storage so that we have our own // copy/reference else { // attempt to clone the storage medium STGMEDIUM mediumClone = new STGMEDIUM(); result = CloneStgMedium(pMedium, ref mediumClone); if (result != HRESULT.S_OK) { return(result); } // cloned it, initialize the data entry using the cloned storage dataEntry = new OleDataEntry(pFormatEtc, mediumClone); } // add the entry to our internal list oleDataEntries.Add(dataEntry); // return OK return(HRESULT.S_OK); }
/// <summary> /// Private helper method to find an existing data format /// </summary> /// <param name="pFormatEtc">format spec</param> /// <param name="dataIndex">returned index of data format if we've got it, /// -1 if we don't have it</param> /// <returns>S_OK if the data format was found, otherwise the appropriate /// OLE error code (see QueryGetData for documentation on error codes)</returns> private int FindDataFormat(ref FORMATETC pFormatEtc, out int dataIndex) { // default to data not found dataIndex = -1; // no support for comparing target devices if (pFormatEtc.ptd != IntPtr.Zero) { return(DV_E.TARGETDEVICE); } // iterate through our FORMATETC structures to see if one matches // this format spec for (int i = 0; i < oleDataEntries.Count; i++) { // get the data entry OleDataEntry dataEntry = (OleDataEntry)oleDataEntries[i]; // check for matching format spec if ((dataEntry.format.cfFormat == pFormatEtc.cfFormat) && (dataEntry.format.dwAspect == pFormatEtc.dwAspect) && (dataEntry.format.lindex == pFormatEtc.lindex)) { // check for matching data type if ((dataEntry.format.tymed & pFormatEtc.tymed) > 0) { dataIndex = i; return(HRESULT.S_OK); } else { return(DV_E.TYMED); } } } // no matching format found return(DV_E.FORMATETC); }
/// <summary> /// Renders the data described in a FORMATETC structure and transfers it /// through the STGMEDIUM structure. /// </summary> /// <param name="pFormatEtc">Pointer to the FORMATETC structure that defines /// the format, medium, and target device to use when passing the data. It is /// possible to specify more than one medium by using the Boolean OR operator, /// allowing the method to choose the best medium among those specified</param> /// <param name="pMedium">Pointer to the STGMEDIUM structure that indicates /// the storage medium containing the returned data through its tymed member, /// and the responsibility for releasing the medium through the value of its /// pUnkForRelease member. If pUnkForRelease is NULL, the receiver of the medium /// is responsible for releasing it; otherwise, pUnkForRelease points to the /// IUnknown on the appropriate object so its Release method can be called. /// The medium must be allocated and filled in by IDataObject::GetData</param> public int GetData(ref FORMATETC pFormatEtc, ref STGMEDIUM pMedium) { // check to see if we have data of the requested type int dataFormatIndex; int result = FindDataFormat(ref pFormatEtc, out dataFormatIndex); // if we do then return a clone of it (returns error code if an // error occurs during the clone) if (result == HRESULT.S_OK) { // lookup the entry OleDataEntry dataEntry = (OleDataEntry)oleDataEntries[dataFormatIndex]; // clone the storage and return return(CloneStgMedium(dataEntry.stgm, ref pMedium)); } // don't have the data, return the error code passed back to us // from FindDataFormat else { return(result); } }
/// <summary> /// Provides the source data object with data described by a FORMATETC /// structure and an STGMEDIUM structure /// </summary> /// <param name="pFormatEtc">Pointer to the FORMATETC structure defining the /// format used by the data object when interpreting the data contained in the /// storage medium</param> /// <param name="pMedium">Pointer to the STGMEDIUM structure defining the storage /// medium in which the data is being passed</param> /// <param name="fRelease">If TRUE, the data object called, which implements /// IDataObject::SetData, owns the storage medium after the call returns. This /// means it must free the medium after it has been used by calling the /// ReleaseStgMedium function. If FALSE, the caller retains ownership of the /// storage medium and the data object called uses the storage medium for the /// duration of the call only</param> public int SetData(ref FORMATETC pFormatEtc, ref STGMEDIUM pMedium, bool fRelease) { // check and see if we have an existing format of this type int dataFormatIndex; int result = FindDataFormat(ref pFormatEtc, out dataFormatIndex); // if we have an existing format of this type then free it and // remove it from the list if (result == HRESULT.S_OK) { OleDataEntry oleDataEntry = (OleDataEntry)oleDataEntries[dataFormatIndex]; Ole32.ReleaseStgMedium(ref oleDataEntry.stgm); oleDataEntries.RemoveAt(dataFormatIndex); } // create an entry to add to our internal list OleDataEntry dataEntry; // if the caller is releasing the data that is being set then just // copy bit for bit (we are now responsible for freeing the storage) if (fRelease) { dataEntry = new OleDataEntry(pFormatEtc, pMedium); } // if the caller is not releasing the data object to us then // we only get to use it for the duration of the call -- we need // to therefore clone the storage so that we have our own // copy/reference else { // attempt to clone the storage medium STGMEDIUM mediumClone = new STGMEDIUM(); result = CloneStgMedium(pMedium, ref mediumClone); if (result != HRESULT.S_OK) return result; // cloned it, initialize the data entry using the cloned storage dataEntry = new OleDataEntry(pFormatEtc, mediumClone); } // add the entry to our internal list oleDataEntries.Add(dataEntry); // return OK return HRESULT.S_OK; }