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

📄 memlockbytes.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
   * Query Interface always increases the reference count by one when it is
   * successful
   */
  IUnknown_AddRef(iface);

  return S_OK;
}

/******************************************************************************
 * This implements the IUnknown method AddRef for this
 * class
 */
static ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface)
{
  HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
  return InterlockedIncrement(&This->ref);
}

/******************************************************************************
 * This implements the IUnknown method Release for this
 * class
 */
static ULONG WINAPI HGLOBALLockBytesImpl_Release(ILockBytes* iface)
{
  HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
  ULONG ref;

  ref = InterlockedDecrement(&This->ref);

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

  return ref;
}

/******************************************************************************
 * This method is part of the ILockBytes interface.
 *
 * It reads a block of information from the byte array at the specified
 * offset.
 *
 * See the documentation of ILockBytes for more info.
 */
static HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt(
      ILockBytes*    iface,
      ULARGE_INTEGER ulOffset,  /* [in] */
      void*          pv,        /* [length_is][size_is][out] */
      ULONG          cb,        /* [in] */
      ULONG*         pcbRead)   /* [out] */
{
  HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;

  void* supportBuffer;
  ULONG bytesReadBuffer = 0;
  ULONG bytesToReadFromBuffer;

  /*
   * If the caller is not interested in the number of bytes read,
   * we use another buffer to avoid "if" statements in the code.
   */
  if (pcbRead == 0)
    pcbRead = &bytesReadBuffer;

  /*
   * Make sure the offset is valid.
   */
  if (ulOffset.u.LowPart > This->byteArraySize.u.LowPart)
    return E_FAIL;

  /*
   * Using the known size of the array, calculate the number of bytes
   * to read.
   */
  bytesToReadFromBuffer = min(This->byteArraySize.u.LowPart -
                              ulOffset.u.LowPart, cb);

  /*
   * Lock the buffer in position and copy the data.
   */
  supportBuffer = GlobalLock(This->supportHandle);

  memcpy(pv,
         (char *) supportBuffer + ulOffset.u.LowPart,
         bytesToReadFromBuffer);

  /*
   * Return the number of bytes read.
   */
  *pcbRead = bytesToReadFromBuffer;

  /*
   * Cleanup
   */
  GlobalUnlock(This->supportHandle);

  /*
   * The function returns S_OK if the specified number of bytes were read
   * or the end of the array was reached.
   * It returns STG_E_READFAULT if the number of bytes to read does not equal
   * the number of bytes actually read.
   */
  if(*pcbRead == cb)
    return S_OK;

  return STG_E_READFAULT;
}

/******************************************************************************
 * This method is part of the ILockBytes interface.
 *
 * It writes the specified bytes at the specified offset.
 * position. If the array is too small, it will be resized.
 *
 * See the documentation of ILockBytes for more info.
 */
static HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(
      ILockBytes*    iface,
      ULARGE_INTEGER ulOffset,    /* [in] */
      const void*    pv,          /* [size_is][in] */
      ULONG          cb,          /* [in] */
      ULONG*         pcbWritten)  /* [out] */
{
  HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;

  void*          supportBuffer;
  ULARGE_INTEGER newSize;
  ULONG          bytesWritten = 0;

  /*
   * If the caller is not interested in the number of bytes written,
   * we use another buffer to avoid "if" statements in the code.
   */
  if (pcbWritten == 0)
    pcbWritten = &bytesWritten;

  if (cb == 0)
  {
    return S_OK;
  }
  else
  {
    newSize.u.HighPart = 0;
    newSize.u.LowPart = ulOffset.u.LowPart + cb;
  }

  /*
   * Verify if we need to grow the stream
   */
  if (newSize.u.LowPart > This->byteArraySize.u.LowPart)
  {
    /* grow stream */
    if (HGLOBALLockBytesImpl_SetSize(iface, newSize) == STG_E_MEDIUMFULL)
      return STG_E_MEDIUMFULL;
  }

  /*
   * Lock the buffer in position and copy the data.
   */
  supportBuffer = GlobalLock(This->supportHandle);

  memcpy((char *) supportBuffer + ulOffset.u.LowPart, pv, cb);

  /*
   * Return the number of bytes written.
   */
  *pcbWritten = cb;

  /*
   * Cleanup
   */
  GlobalUnlock(This->supportHandle);

  return S_OK;
}

/******************************************************************************
 * This method is part of the ILockBytes interface.
 *
 * See the documentation of ILockBytes for more info.
 */
static HRESULT WINAPI HGLOBALLockBytesImpl_Flush(ILockBytes* iface)
{
  return S_OK;
}

/******************************************************************************
 * This method is part of the ILockBytes interface.
 *
 * It will change the size of the byte array.
 *
 * See the documentation of ILockBytes for more info.
 */
static HRESULT WINAPI HGLOBALLockBytesImpl_SetSize(
      ILockBytes*     iface,
      ULARGE_INTEGER  libNewSize)   /* [in] */
{
  HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
  HGLOBAL supportHandle;

  /*
   * As documented.
   */
  if (libNewSize.u.HighPart != 0)
    return STG_E_INVALIDFUNCTION;

  if (This->byteArraySize.u.LowPart == libNewSize.u.LowPart)
    return S_OK;

  /*
   * Re allocate the HGlobal to fit the new size of the stream.
   */
  supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);

  if (supportHandle == 0)
    return STG_E_MEDIUMFULL;

  This->supportHandle = supportHandle;
  This->byteArraySize.u.LowPart = libNewSize.u.LowPart;

  return S_OK;
}

/******************************************************************************
 * This method is part of the ILockBytes interface.
 *
 * The global memory implementation of ILockBytes does not support locking.
 *
 * See the documentation of ILockBytes for more info.
 */
static HRESULT WINAPI HGLOBALLockBytesImpl_LockRegion(
      ILockBytes*    iface,
      ULARGE_INTEGER libOffset,   /* [in] */
      ULARGE_INTEGER cb,          /* [in] */
      DWORD          dwLockType)  /* [in] */
{
  return STG_E_INVALIDFUNCTION;
}

/******************************************************************************
 * This method is part of the ILockBytes interface.
 *
 * The global memory implementation of ILockBytes does not support locking.
 *
 * See the documentation of ILockBytes for more info.
 */
static HRESULT WINAPI HGLOBALLockBytesImpl_UnlockRegion(
      ILockBytes*    iface,
      ULARGE_INTEGER libOffset,   /* [in] */
      ULARGE_INTEGER cb,          /* [in] */
      DWORD          dwLockType)  /* [in] */
{
  return STG_E_INVALIDFUNCTION;
}

/******************************************************************************
 * This method is part of the ILockBytes interface.
 *
 * This method returns information about the current
 * byte array object.
 *
 * See the documentation of ILockBytes for more info.
 */
static HRESULT WINAPI HGLOBALLockBytesImpl_Stat(
      ILockBytes*  iface,
      STATSTG*     pstatstg,     /* [out] */
      DWORD        grfStatFlag)  /* [in] */
{
  HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;

  memset(pstatstg, 0, sizeof(STATSTG));

  pstatstg->pwcsName = NULL;
  pstatstg->type     = STGTY_LOCKBYTES;
  pstatstg->cbSize   = This->byteArraySize;

  return S_OK;
}

/*
 * Virtual function table for the HGLOBALLockBytesImpl class.
 */
static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl =
{
    HGLOBALLockBytesImpl_QueryInterface,
    HGLOBALLockBytesImpl_AddRef,
    HGLOBALLockBytesImpl_Release,
    HGLOBALLockBytesImpl_ReadAt,
    HGLOBALLockBytesImpl_WriteAt,
    HGLOBALLockBytesImpl_Flush,
    HGLOBALLockBytesImpl_SetSize,
    HGLOBALLockBytesImpl_LockRegion,
    HGLOBALLockBytesImpl_UnlockRegion,
    HGLOBALLockBytesImpl_Stat,
};

⌨️ 快捷键说明

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