Beispiel #1
0
/******************************************************************************
 * This method is part of the ILockBytes interface.
 *
 * It writes the specified bytes at the specified offset.
 * position. If the file is too small, it will be resized.
 *
 * See the documentation of ILockBytes for more info.
 */
static HRESULT WINAPI FileLockBytesImpl_WriteAt(
      ILockBytes* iface,
      ULARGE_INTEGER ulOffset,    /* [in] */
      const void*    pv,          /* [size_is][in] */
      ULONG          cb,          /* [in] */
      ULONG*         pcbWritten)  /* [out] */
{
    FileLockBytesImpl* This = impl_from_ILockBytes(iface);
    ULONG size_needed = ulOffset.u.LowPart + cb;
    ULONG bytes_left = cb;
    const BYTE *writePtr = pv;
    BOOL ret;
    LARGE_INTEGER offset;
    ULONG cbWritten;

    TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbWritten);

    /* verify a sane environment */
    if (!This) return E_FAIL;

    if (This->flProtect != PAGE_READWRITE)
        return STG_E_ACCESSDENIED;

    if (pcbWritten)
        *pcbWritten = 0;

    if (size_needed > This->filesize.u.LowPart)
    {
        ULARGE_INTEGER newSize;
        newSize.u.HighPart = 0;
        newSize.u.LowPart = size_needed;
        ILockBytes_SetSize(iface, newSize);
    }

    offset.QuadPart = ulOffset.QuadPart;

    ret = SetFilePointerEx(This->hfile, offset, NULL, FILE_BEGIN);

    if (!ret)
        return STG_E_READFAULT;

    while (bytes_left)
    {
        ret = WriteFile(This->hfile, writePtr, bytes_left, &cbWritten, NULL);

        if (!ret)
            return STG_E_READFAULT;

        if (pcbWritten)
            *pcbWritten += cbWritten;

        bytes_left -= cbWritten;
        writePtr += cbWritten;
    }

    TRACE("finished\n");
    return S_OK;
}
Beispiel #2
0
/******************************************************************************
 *      BIGBLOCKFILE_SetSize
 *
 * Sets the size of the file.
 *
 */
void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize)
{
  if (This->filesize.u.LowPart == newSize.u.LowPart)
    return;

  TRACE("from %u to %u\n", This->filesize.u.LowPart, newSize.u.LowPart);
  /*
   * unmap all views, must be done before call to SetEndFile
   *
   * Just ditch the victim list because there is no guarantee we will need them
   * and it is not worth the performance hit to unmap and remap them all.
   */
  BIGBLOCKFILE_DeleteList(This, This->victimhead);
  This->victimhead = NULL;
  This->victimtail = NULL;
  This->num_victim_pages = 0;

  BIGBLOCKFILE_UnmapAllMappedPages(This);

  if (This->fileBased)
  {
    LARGE_INTEGER newpos;

    newpos.QuadPart = newSize.QuadPart;
    if (SetFilePointerEx(This->hfile, newpos, NULL, FILE_BEGIN))
    {
        if( This->hfilemap ) CloseHandle(This->hfilemap);

        SetEndOfFile(This->hfile);

        /*
         * re-create the file mapping object
         */
        This->hfilemap = CreateFileMappingA(This->hfile,
                                            NULL,
                                            This->flProtect,
                                            0, 0,
                                            NULL);
    }
  }
  else
  {
    GlobalUnlock(This->hbytearray);

    /*
     * Resize the byte array object.
     */
    ILockBytes_SetSize(This->pLkbyt, newSize);

    /*
     * Re-acquire the handle, it may have changed.
     */
    GetHGlobalFromILockBytes(This->pLkbyt, &This->hbytearray);
    This->pbytearray = GlobalLock(This->hbytearray);
  }

  This->filesize.u.LowPart = newSize.u.LowPart;
  This->filesize.u.HighPart = newSize.u.HighPart;

  BIGBLOCKFILE_RemapAllMappedPages(This);
}