/******************************************************************************
 *
 * File-based ILockBytes implementation
 *
 * Copyright 1999 Thuy Nguyen
 * Copyright 2010 Vincent Povirk for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>

#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winerror.h"
#include "objbase.h"
#include "ole2.h"

#include "storage32.h"

#include "wine/debug.h"
#include "wine/unicode.h"

WINE_DEFAULT_DEBUG_CHANNEL(storage);

typedef struct FileLockBytesImpl
{
    ILockBytes ILockBytes_iface;
    LONG ref;
    HANDLE hfile;
    DWORD flProtect;
    LPWSTR pwcsName;
} FileLockBytesImpl;

static const ILockBytesVtbl FileLockBytesImpl_Vtbl;

static inline FileLockBytesImpl *impl_from_ILockBytes(ILockBytes *iface)
{
    return CONTAINING_RECORD(iface, FileLockBytesImpl, ILockBytes_iface);
}

/***********************************************************
 * Prototypes for private methods
 */

/****************************************************************************
 *      GetProtectMode
 *
 * This function will return a protection mode flag for a file-mapping object
 * from the open flags of a file.
 */
static DWORD GetProtectMode(DWORD openFlags)
{
    switch(STGM_ACCESS_MODE(openFlags))
    {
    case STGM_WRITE:
    case STGM_READWRITE:
        return PAGE_READWRITE;
    }
    return PAGE_READONLY;
}

/******************************************************************************
 *      FileLockBytesImpl_Construct
 *
 * Initialize a big block object supported by a file.
 */
HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsName, ILockBytes **pLockBytes)
{
  FileLockBytesImpl *This;
  WCHAR fullpath[MAX_PATH];

  if (hFile == INVALID_HANDLE_VALUE)
    return E_FAIL;

  This = HeapAlloc(GetProcessHeap(), 0, sizeof(FileLockBytesImpl));

  if (!This)
    return E_OUTOFMEMORY;

  This->ILockBytes_iface.lpVtbl = &FileLockBytesImpl_Vtbl;
  This->ref = 1;
  This->hfile = hFile;
  This->flProtect = GetProtectMode(openFlags);

  if(pwcsName) {
    if (!GetFullPathNameW(pwcsName, MAX_PATH, fullpath, NULL))
    {
      lstrcpynW(fullpath, pwcsName, MAX_PATH);
    }
    This->pwcsName = HeapAlloc(GetProcessHeap(), 0,
                              (lstrlenW(fullpath)+1)*sizeof(WCHAR));
    if (!This->pwcsName)
    {
       HeapFree(GetProcessHeap(), 0, This);
       return E_OUTOFMEMORY;
    }
    strcpyW(This->pwcsName, fullpath);
  }
  else
    This->pwcsName = NULL;

  *pLockBytes = &This->ILockBytes_iface;

  return S_OK;
}

/* ILockByte Interfaces */

static HRESULT WINAPI FileLockBytesImpl_QueryInterface(ILockBytes *iface, REFIID riid,
    void **ppvObject)
{
    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ILockBytes))
        *ppvObject = iface;
    else
    {
        *ppvObject = NULL;
        return E_NOINTERFACE;
    }

    IUnknown_AddRef((IUnknown*)*ppvObject);

    return S_OK;
}

static ULONG WINAPI FileLockBytesImpl_AddRef(ILockBytes *iface)
{
    FileLockBytesImpl* This = impl_from_ILockBytes(iface);
    return InterlockedIncrement(&This->ref);
}

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;
}

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

    offset.QuadPart = ulOffset.QuadPart;

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

    if (!ret)
        return STG_E_WRITEFAULT;

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

        if (!ret)
            return STG_E_WRITEFAULT;

        if (pcbWritten)
            *pcbWritten += cbWritten;

        bytes_left -= cbWritten;
        writePtr += cbWritten;
    }

    TRACE("finished\n");
    return S_OK;
}

static HRESULT WINAPI FileLockBytesImpl_Flush(ILockBytes* iface)
{
    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 HRESULT get_lock_error(void)
{
    switch (GetLastError())
    {
    case ERROR_LOCK_VIOLATION: return STG_E_LOCKVIOLATION; break;
    case ERROR_ACCESS_DENIED:  return STG_E_ACCESSDENIED; break;
    case ERROR_NOT_SUPPORTED:  return STG_E_INVALIDFUNCTION; break;
    default:
        FIXME("no mapping for error %d\n", GetLastError());
        return STG_E_INVALIDFUNCTION;
    }
}

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 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.u.LowPart = GetFileSize(This->hfile, &pstatstg->cbSize.u.HighPart);
    /* FIXME: If the implementation is exported, we'll need to set other fields. */

    pstatstg->grfLocksSupported = LOCK_EXCLUSIVE|LOCK_ONLYONCE|WINE_LOCK_READ;

    return S_OK;
}

static const ILockBytesVtbl FileLockBytesImpl_Vtbl = {
    FileLockBytesImpl_QueryInterface,
    FileLockBytesImpl_AddRef,
    FileLockBytesImpl_Release,
    FileLockBytesImpl_ReadAt,
    FileLockBytesImpl_WriteAt,
    FileLockBytesImpl_Flush,
    FileLockBytesImpl_SetSize,
    FileLockBytesImpl_LockRegion,
    FileLockBytesImpl_UnlockRegion,
    FileLockBytesImpl_Stat
};
