/****************************************************************************** * 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; }
/****************************************************************************** * 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); }