/****************************************************************************** * 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; }
/****************************************************************************** * ILockBytes_SetSize * * Sets the size of the file. * */ static HRESULT WINAPI FileLockBytesImpl_SetSize(ILockBytes* iface, ULARGE_INTEGER newSize) { FileLockBytesImpl* This = impl_from_ILockBytes(iface); HRESULT hr = S_OK; LARGE_INTEGER newpos; TRACE("new size %u\n", newSize.u.LowPart); newpos.QuadPart = newSize.QuadPart; if (SetFilePointerEx(This->hfile, newpos, NULL, FILE_BEGIN)) { SetEndOfFile(This->hfile); } return hr; }
static ULONG WINAPI FileLockBytesImpl_Release(ILockBytes *iface) { FileLockBytesImpl* This = impl_from_ILockBytes(iface); ULONG ref; ref = InterlockedDecrement(&This->ref); if (ref == 0) { CloseHandle(This->hfile); HeapFree(GetProcessHeap(), 0, This->pwcsName); HeapFree(GetProcessHeap(), 0, 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 FileLockBytesImpl_ReadAt( ILockBytes* iface, ULARGE_INTEGER ulOffset, /* [in] */ void* pv, /* [length_is][size_is][out] */ ULONG cb, /* [in] */ ULONG* pcbRead) /* [out] */ { FileLockBytesImpl* This = impl_from_ILockBytes(iface); ULONG bytes_left = cb; LPBYTE readPtr = pv; BOOL ret; LARGE_INTEGER offset; ULONG cbRead; TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbRead); /* verify a sane environment */ if (!This) return E_FAIL; if (pcbRead) *pcbRead = 0; offset.QuadPart = ulOffset.QuadPart; ret = SetFilePointerEx(This->hfile, offset, NULL, FILE_BEGIN); if (!ret) return STG_E_READFAULT; while (bytes_left) { ret = ReadFile(This->hfile, readPtr, bytes_left, &cbRead, NULL); if (!ret || cbRead == 0) return STG_E_READFAULT; if (pcbRead) *pcbRead += cbRead; bytes_left -= cbRead; readPtr += cbRead; } TRACE("finished\n"); return S_OK; }
HRESULT FileLockBytesImpl_LockRegionSync(ILockBytes* iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb) { FileLockBytesImpl* This = impl_from_ILockBytes(iface); OVERLAPPED ol; if (iface->lpVtbl != &FileLockBytesImpl_Vtbl) return E_NOTIMPL; ol.hEvent = 0; ol.u.s.Offset = libOffset.u.LowPart; ol.u.s.OffsetHigh = libOffset.u.HighPart; if (LockFileEx(This->hfile, LOCKFILE_EXCLUSIVE_LOCK, 0, cb.u.LowPart, cb.u.HighPart, &ol)) return S_OK; return get_lock_error(); }
static HRESULT WINAPI FileLockBytesImpl_UnlockRegion(ILockBytes* iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { FileLockBytesImpl* This = impl_from_ILockBytes(iface); OVERLAPPED ol; TRACE("ofs %u count %u flags %x\n", libOffset.u.LowPart, cb.u.LowPart, dwLockType); if (dwLockType & LOCK_WRITE) return STG_E_INVALIDFUNCTION; ol.hEvent = 0; ol.u.s.Offset = libOffset.u.LowPart; ol.u.s.OffsetHigh = libOffset.u.HighPart; if (UnlockFileEx(This->hfile, 0, cb.u.LowPart, cb.u.HighPart, &ol)) return S_OK; return get_lock_error(); }
static HRESULT WINAPI FileLockBytesImpl_Stat(ILockBytes* iface, STATSTG *pstatstg, DWORD grfStatFlag) { FileLockBytesImpl* This = impl_from_ILockBytes(iface); if (!(STATFLAG_NONAME & grfStatFlag) && This->pwcsName) { pstatstg->pwcsName = CoTaskMemAlloc((lstrlenW(This->pwcsName)+1)*sizeof(WCHAR)); strcpyW(pstatstg->pwcsName, This->pwcsName); } else pstatstg->pwcsName = NULL; pstatstg->type = STGTY_LOCKBYTES; pstatstg->cbSize = This->filesize; /* FIXME: If the implementation is exported, we'll need to set other fields. */ return S_OK; }
static HRESULT WINAPI FileLockBytesImpl_LockRegion(ILockBytes* iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { FileLockBytesImpl* This = impl_from_ILockBytes(iface); OVERLAPPED ol; DWORD lock_flags = LOCKFILE_FAIL_IMMEDIATELY; TRACE("ofs %u count %u flags %x\n", libOffset.u.LowPart, cb.u.LowPart, dwLockType); if (dwLockType & LOCK_WRITE) return STG_E_INVALIDFUNCTION; if (dwLockType & (LOCK_EXCLUSIVE|LOCK_ONLYONCE)) lock_flags |= LOCKFILE_EXCLUSIVE_LOCK; ol.hEvent = 0; ol.u.s.Offset = libOffset.u.LowPart; ol.u.s.OffsetHigh = libOffset.u.HighPart; if (LockFileEx(This->hfile, lock_flags, 0, cb.u.LowPart, cb.u.HighPart, &ol)) return S_OK; return get_lock_error(); }
static ULONG WINAPI FileLockBytesImpl_AddRef(ILockBytes *iface) { FileLockBytesImpl* This = impl_from_ILockBytes(iface); return InterlockedIncrement(&This->ref); }