⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clipboard.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
    case WM_PAINTCLIPBOARD:
*/
    default:
      return DefWindowProcA(hWnd, message, wParam, lParam);
  }

  return 0;
}

#define MAX_CLIPFORMAT_NAME   80

/***********************************************************************
 * OLEClipbrd_RenderFormat(LPFORMATETC)
 * Render the clipboard data. Note that this call will delegate to the
 * source data object.
 * Note: This function assumes it is passed an HGLOBAL format to render.
 */
static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
{
  STGMEDIUM std;
  HGLOBAL hDup;
  HRESULT hr = S_OK;
  char szFmtName[MAX_CLIPFORMAT_NAME];
  ILockBytes *ptrILockBytes = 0;
  HGLOBAL hStorage = 0;

  if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
      szFmtName[0] = '\0';

  /* If embed source */
  if (!strcmp(szFmtName, CF_EMBEDSOURCE))
  {
    memset(&std, 0, sizeof(STGMEDIUM));
    std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;

    hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
    if (hStorage == NULL)
      HANDLE_ERROR( E_OUTOFMEMORY );
    hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
    hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);

    if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
    {
      WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
      GlobalFree(hStorage);
      return hr;
    }

    if (1) /* check whether the presentation data is already -not- present */
    {
      FORMATETC fmt2;
      STGMEDIUM std2;
      METAFILEPICT *mfp = 0;

      fmt2.cfFormat = CF_METAFILEPICT;
      fmt2.ptd = 0;
      fmt2.dwAspect = DVASPECT_CONTENT;
      fmt2.lindex = -1;
      fmt2.tymed = TYMED_MFPICT;

      memset(&std2, 0, sizeof(STGMEDIUM));
      std2.tymed = TYMED_MFPICT;

      /* Get the metafile picture out of it */

      if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
      {
        mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
      }

      if (mfp)
      {
        OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
        IStream *pStream = 0;
        void *mfBits;
        PresentationDataHeader pdh;
        INT nSize;
        CLSID clsID;
        LPOLESTR strProgID;
        CHAR strOleTypeName[51];
        BYTE OlePresStreamHeader [] =
        {
            0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
            0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00
        };

        nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);

        memset(&pdh, 0, sizeof(PresentationDataHeader));
        memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));

        pdh.dwObjectExtentX = mfp->xExt;
        pdh.dwObjectExtentY = mfp->yExt;
        pdh.dwSize = nSize;

        hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);

        hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);

        mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
        nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);

        hr = IStream_Write(pStream, mfBits, nSize, NULL);

        IStream_Release(pStream);

        HeapFree(GetProcessHeap(), 0, mfBits);

        GlobalUnlock(std2.u.hGlobal);

        ReadClassStg(std.u.pstg, &clsID);
        ProgIDFromCLSID(&clsID, &strProgID);

        WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
        OLECONVERT_CreateOleStream(std.u.pstg);
        OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
      }
    }
  }
  else
  {
    if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
    {
        WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
        GlobalFree(hStorage);
        return hr;
    }

    /* To put a copy back on the clipboard */

    hStorage = std.u.hGlobal;
  }

  /*
   *  Put a copy of the rendered data back on the clipboard
   */

  if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
    HANDLE_ERROR( E_OUTOFMEMORY );

  if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
  {
    GlobalFree(hDup);
    WARN("() : Failed to set rendered clipboard data into clipboard!\n");
  }

CLEANUP:

  ReleaseStgMedium(&std);

  return hr;
}


/***********************************************************************
 * OLEClipbrd_GlobalDupMem( HGLOBAL )
 * Helper method to duplicate an HGLOBAL chunk of memory
 */
static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
{
    HGLOBAL hGlobalDest;
    PVOID pGlobalSrc, pGlobalDest;
    DWORD cBytes;

    if ( !hGlobalSrc )
      return 0;

    cBytes = GlobalSize(hGlobalSrc);
    if ( 0 == cBytes )
      return 0;

    hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
                               cBytes );
    if ( !hGlobalDest )
      return 0;

    pGlobalSrc = GlobalLock(hGlobalSrc);
    pGlobalDest = GlobalLock(hGlobalDest);
    if ( !pGlobalSrc || !pGlobalDest )
    {
      GlobalFree(hGlobalDest);
      return 0;
    }

    memcpy(pGlobalDest, pGlobalSrc, cBytes);

    GlobalUnlock(hGlobalSrc);
    GlobalUnlock(hGlobalDest);

    return hGlobalDest;
}


/*---------------------------------------------------------------------*
 *  Implementation of the internal IDataObject interface exposed by
 *  the OLE clipboard.
 *---------------------------------------------------------------------*/


/************************************************************************
 * OLEClipbrd_IDataObject_QueryInterface (IUnknown)
 *
 * See Windows documentation for more details on IUnknown methods.
 */
static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
            IDataObject*     iface,
            REFIID           riid,
            void**           ppvObject)
{
  /*
   * Declare "This" pointer
   */
  OLEClipbrd *This = (OLEClipbrd *)iface;
  TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);

  /*
   * Perform a sanity check on the parameters.
   */
  if ( (This==0) || (ppvObject==0) )
    return E_INVALIDARG;

  /*
   * Initialize the return parameter.
   */
  *ppvObject = 0;

  /*
   * Compare the riid with the interface IDs implemented by this object.
   */
  if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
  {
    *ppvObject = iface;
  }
  else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
  {
    *ppvObject = (IDataObject*)&(This->lpvtbl1);
  }
  else  /* We only support IUnknown and IDataObject */
  {
    WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
    return E_NOINTERFACE;
  }

  /*
   * Query Interface always increases the reference count by one when it is
   * successful.
   */
  IUnknown_AddRef((IUnknown*)*ppvObject);

  return S_OK;
}

/************************************************************************
 * OLEClipbrd_IDataObject_AddRef (IUnknown)
 *
 * See Windows documentation for more details on IUnknown methods.
 */
static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
            IDataObject*     iface)
{
  /*
   * Declare "This" pointer
   */
  OLEClipbrd *This = (OLEClipbrd *)iface;

  TRACE("(%p)->(count=%u)\n",This, This->ref);

  return InterlockedIncrement(&This->ref);

}

/************************************************************************
 * OLEClipbrd_IDataObject_Release (IUnknown)
 *
 * See Windows documentation for more details on IUnknown methods.
 */
static ULONG WINAPI OLEClipbrd_IDataObject_Release(
            IDataObject*     iface)
{
  /*
   * Declare "This" pointer
   */
  OLEClipbrd *This = (OLEClipbrd *)iface;
  ULONG ref;

  TRACE("(%p)->(count=%u)\n",This, This->ref);

  /*
   * Decrease the reference count on this object.
   */
  ref = InterlockedDecrement(&This->ref);

  /*
   * If the reference count goes down to 0, perform suicide.
   */
  if (ref == 0)
  {
    OLEClipbrd_Destroy(This);
  }

  return ref;
}


/************************************************************************
 * OLEClipbrd_IDataObject_GetData (IDataObject)
 *
 * The OLE Clipboard's implementation of this method delegates to
 * a data source if there is one or wraps around the windows clipboard
 *
 * See Windows documentation for more details on IDataObject methods.
 */
static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
	    IDataObject*     iface,
	    LPFORMATETC      pformatetcIn,
	    STGMEDIUM*       pmedium)
{
  HANDLE      hData = 0;
  BOOL bClipboardOpen = FALSE;
  HRESULT hr = S_OK;
  LPVOID src;

  /*
   * Declare "This" pointer
   */
  OLEClipbrd *This = (OLEClipbrd *)iface;

  TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);

  if ( !pformatetcIn || !pmedium )
    return E_INVALIDARG;

  /*
   * If we have a data source placed on the clipboard (via OleSetClipboard)
   * simply delegate to the source object's QueryGetData
   * NOTE: This code assumes that the IDataObject is in the same address space!
   * We will need to add marshalling support when Wine handles multiple processes.
   */
  if ( This->pIDataObjectSrc )
  {
    return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
  }

  if ( pformatetcIn->lindex != -1 )
    return DV_E_LINDEX;
  if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
    return DV_E_TYMED;
/*
   if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
     return DV_E_DVASPECT;
*/

  /*
   * Otherwise, get the data from the windows clipboard using GetClipboardData
   */
  if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
    HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );

  hData = GetClipboardData(pformatetcIn->cfFormat);

  /* Must make a copy of global handle returned by GetClipboardData; it
   * is not valid after we call CloseClipboard
   * Application is responsible for freeing the memory (Forte Agent does this)
   */
  src = GlobalLock(hData);
  if(src) {
      LPVOID dest;
      ULONG  size;
      HANDLE hDest;

      size = GlobalSize(hData);
      hDest = GlobalAlloc(GHND, size);
      dest  = GlobalLock(hDest);
      memcpy(dest, src, size);
      GlobalUnlock(hDest);
      GlobalUnlock(hData);
      hData = hDest;
  }

  /*
   * Return the clipboard data in the storage medium structure
   */
  pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
  pmedium->u.hGlobal = (HGLOBAL)hData;
  pmedium->pUnkForRelease = NULL;

  hr = S_OK;

CLEANUP:
  /*
   * Close Windows clipboard
   */
  if ( bClipboardOpen && !CloseClipboard() )
     hr = CLIPBRD_E_CANT_CLOSE;

  if ( FAILED(hr) )
      return hr;
  return (hData == 0) ? DV_E_FORMATETC : S_OK;
}

static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
	    IDataObject*     iface,
	    LPFORMATETC      pformatetc,
	    STGMEDIUM*       pmedium)
{
  FIXME(": Stub\n");
  return E_NOTIMPL;
}

/************************************************************************
 * OLEClipbrd_IDataObject_QueryGetData (IDataObject)
 *
 * The OLE Clipboard's implementation of this method delegates to
 * a data source if there is one or wraps around the windows clipboard
 * function IsClipboardFormatAvailable() otherwise.
 *
 * See Windows documentation for more details on IDataObject methods.
 */
static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
	    IDataObject*     iface,
	    LPFORMATETC      pformatetc)
{
  /*
   * Declare "This" pointer
   */
  OLEClipbrd *This = (OLEClipbrd *)iface;

  TRACE("(%p, %p)\n", iface, pformatetc);

  /*
   * If we have a data source placed on the clipboard (via OleSetClipboard)
   * simply delegate to the source object's QueryGetData
   */
  if ( This->pIDataObjectSrc )
  {
    return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
  }

  if (!pformatetc)
    return E_INVALIDARG;
/*
   if ( pformatetc->dwAspect != DVASPECT_CONTENT )
     return DV_E_DVASPECT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -