Commit 29a15a35 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

shlwapi: Forward file-base stream calls to shcore.

parent 16eece44
/*
* Copyright 2002 Jon Griffiths
* Copyright 2016 Sebastian Lackner
*
* This library is free software; you can redistribute it and/or
......
......@@ -34,503 +34,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell);
#define STGM_ACCESS_MODE(stgm) ((stgm)&0x0000f)
#define STGM_SHARE_MODE(stgm) ((stgm)&0x000f0)
#define STGM_CREATE_MODE(stgm) ((stgm)&0x0f000)
/* Layout of ISHFileStream object */
typedef struct
{
IStream IStream_iface;
LONG ref;
HANDLE hFile;
DWORD dwMode;
LPOLESTR lpszPath;
DWORD type;
DWORD grfStateBits;
} ISHFileStream;
static inline ISHFileStream *impl_from_IStream(IStream *iface)
{
return CONTAINING_RECORD(iface, ISHFileStream, IStream_iface);
}
/**************************************************************************
* IStream_fnQueryInterface
*/
static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
{
ISHFileStream *This = impl_from_IStream(iface);
TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IStream))
{
IStream_AddRef(iface);
*ppvObj = iface;
return S_OK;
}
return E_NOINTERFACE;
}
/**************************************************************************
* IStream_fnAddRef
*/
static ULONG WINAPI IStream_fnAddRef(IStream *iface)
{
ISHFileStream *This = impl_from_IStream(iface);
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
return refCount;
}
/**************************************************************************
* IStream_fnRelease
*/
static ULONG WINAPI IStream_fnRelease(IStream *iface)
{
ISHFileStream *This = impl_from_IStream(iface);
ULONG refCount = InterlockedDecrement(&This->ref);
TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
if (!refCount)
{
IStream_Commit(iface, 0); /* If ever buffered, this will be needed */
LocalFree(This->lpszPath);
CloseHandle(This->hFile);
HeapFree(GetProcessHeap(), 0, This);
}
return refCount;
}
/**************************************************************************
* IStream_fnRead
*/
static HRESULT WINAPI IStream_fnRead(IStream *iface, void* pv, ULONG cb, ULONG* pcbRead)
{
ISHFileStream *This = impl_from_IStream(iface);
DWORD dwRead = 0;
TRACE("(%p,%p,%u,%p)\n", This, pv, cb, pcbRead);
if (!ReadFile(This->hFile, pv, cb, &dwRead, NULL))
{
WARN("error %d reading file\n", GetLastError());
return S_FALSE;
}
if (pcbRead)
*pcbRead = dwRead;
return dwRead == cb ? S_OK : S_FALSE;
}
/**************************************************************************
* IStream_fnWrite
*/
static HRESULT WINAPI IStream_fnWrite(IStream *iface, const void* pv, ULONG cb, ULONG* pcbWritten)
{
ISHFileStream *This = impl_from_IStream(iface);
DWORD dwWritten = 0;
TRACE("(%p,%p,%u,%p)\n", This, pv, cb, pcbWritten);
switch (STGM_ACCESS_MODE(This->dwMode))
{
case STGM_WRITE:
case STGM_READWRITE:
break;
default:
return STG_E_ACCESSDENIED;
}
if (!WriteFile(This->hFile, pv, cb, &dwWritten, NULL))
return HRESULT_FROM_WIN32(GetLastError());
if (pcbWritten)
*pcbWritten = dwWritten;
return S_OK;
}
/**************************************************************************
* IStream_fnSeek
*/
static HRESULT WINAPI IStream_fnSeek(IStream *iface, LARGE_INTEGER dlibMove,
DWORD dwOrigin, ULARGE_INTEGER* pNewPos)
{
ISHFileStream *This = impl_from_IStream(iface);
DWORD dwPos;
TRACE("(%p,%s,%d,%p)\n", This, wine_dbgstr_longlong(dlibMove.QuadPart), dwOrigin, pNewPos);
IStream_Commit(iface, 0); /* If ever buffered, this will be needed */
dwPos = SetFilePointer(This->hFile, dlibMove.u.LowPart, NULL, dwOrigin);
if( dwPos == INVALID_SET_FILE_POINTER )
return HRESULT_FROM_WIN32(GetLastError());
if (pNewPos)
{
pNewPos->u.HighPart = 0;
pNewPos->u.LowPart = dwPos;
}
return S_OK;
}
/**************************************************************************
* IStream_fnSetSize
*/
static HRESULT WINAPI IStream_fnSetSize(IStream *iface, ULARGE_INTEGER libNewSize)
{
ISHFileStream *This = impl_from_IStream(iface);
TRACE("(%p,%s)\n", This, wine_dbgstr_longlong(libNewSize.QuadPart));
IStream_Commit(iface, 0); /* If ever buffered, this will be needed */
if( ! SetFilePointer( This->hFile, libNewSize.QuadPart, NULL, FILE_BEGIN ) )
return E_FAIL;
if( ! SetEndOfFile( This->hFile ) )
return E_FAIL;
return S_OK;
}
/**************************************************************************
* IStream_fnCopyTo
*/
static HRESULT WINAPI IStream_fnCopyTo(IStream *iface, IStream* pstm, ULARGE_INTEGER cb,
ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
{
ISHFileStream *This = impl_from_IStream(iface);
char copyBuff[1024];
ULONGLONG ulSize;
HRESULT hRet = S_OK;
TRACE("(%p,%p,%s,%p,%p)\n", This, pstm, wine_dbgstr_longlong(cb.QuadPart), pcbRead, pcbWritten);
if (pcbRead)
pcbRead->QuadPart = 0;
if (pcbWritten)
pcbWritten->QuadPart = 0;
if (!pstm)
return S_OK;
IStream_Commit(iface, 0); /* If ever buffered, this will be needed */
/* Copy data */
ulSize = cb.QuadPart;
while (ulSize)
{
ULONG ulLeft, ulRead, ulWritten;
ulLeft = ulSize > sizeof(copyBuff) ? sizeof(copyBuff) : ulSize;
/* Read */
hRet = IStream_Read(iface, copyBuff, ulLeft, &ulRead);
if (FAILED(hRet) || ulRead == 0)
break;
if (pcbRead)
pcbRead->QuadPart += ulRead;
/* Write */
hRet = IStream_Write(pstm, copyBuff, ulRead, &ulWritten);
if (pcbWritten)
pcbWritten->QuadPart += ulWritten;
if (FAILED(hRet) || ulWritten != ulLeft)
break;
ulSize -= ulLeft;
}
return hRet;
}
/**************************************************************************
* IStream_fnCommit
*/
static HRESULT WINAPI IStream_fnCommit(IStream *iface, DWORD grfCommitFlags)
{
ISHFileStream *This = impl_from_IStream(iface);
TRACE("(%p,%d)\n", This, grfCommitFlags);
/* Currently unbuffered: This function is not needed */
return S_OK;
}
/**************************************************************************
* IStream_fnRevert
*/
static HRESULT WINAPI IStream_fnRevert(IStream *iface)
{
ISHFileStream *This = impl_from_IStream(iface);
TRACE("(%p)\n", This);
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnLockRegion
*/
static HRESULT WINAPI IStream_fnLockRegion(IStream *iface, ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb, DWORD dwLockType)
{
ISHFileStream *This = impl_from_IStream(iface);
TRACE("(%p,%s,%s,%d)\n", This, wine_dbgstr_longlong(libOffset.QuadPart), wine_dbgstr_longlong(cb.QuadPart), dwLockType);
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnUnlockRegion
*/
static HRESULT WINAPI IStream_fnUnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb, DWORD dwLockType)
{
ISHFileStream *This = impl_from_IStream(iface);
TRACE("(%p,%s,%s,%d)\n", This, wine_dbgstr_longlong(libOffset.QuadPart), wine_dbgstr_longlong(cb.QuadPart), dwLockType);
return E_NOTIMPL;
}
/*************************************************************************
* IStream_fnStat
*/
static HRESULT WINAPI IStream_fnStat(IStream *iface, STATSTG* lpStat,
DWORD grfStatFlag)
{
ISHFileStream *This = impl_from_IStream(iface);
BY_HANDLE_FILE_INFORMATION fi;
TRACE("(%p,%p,%d)\n", This, lpStat, grfStatFlag);
if (!lpStat)
return STG_E_INVALIDPOINTER;
memset(&fi, 0, sizeof(fi));
GetFileInformationByHandle(This->hFile, &fi);
if (grfStatFlag & STATFLAG_NONAME)
lpStat->pwcsName = NULL;
else
lpStat->pwcsName = StrDupW(This->lpszPath);
lpStat->type = This->type;
lpStat->cbSize.u.LowPart = fi.nFileSizeLow;
lpStat->cbSize.u.HighPart = fi.nFileSizeHigh;
lpStat->mtime = fi.ftLastWriteTime;
lpStat->ctime = fi.ftCreationTime;
lpStat->atime = fi.ftLastAccessTime;
lpStat->grfMode = This->dwMode;
lpStat->grfLocksSupported = 0;
memcpy(&lpStat->clsid, &IID_IStream, sizeof(CLSID));
lpStat->grfStateBits = This->grfStateBits;
lpStat->reserved = 0;
return S_OK;
}
/*************************************************************************
* IStream_fnClone
*/
static HRESULT WINAPI IStream_fnClone(IStream *iface, IStream** ppstm)
{
ISHFileStream *This = impl_from_IStream(iface);
TRACE("(%p,%p)\n", This, ppstm);
if (ppstm)
*ppstm = NULL;
return E_NOTIMPL;
}
static const IStreamVtbl SHLWAPI_fsVTable =
{
IStream_fnQueryInterface,
IStream_fnAddRef,
IStream_fnRelease,
IStream_fnRead,
IStream_fnWrite,
IStream_fnSeek,
IStream_fnSetSize,
IStream_fnCopyTo,
IStream_fnCommit,
IStream_fnRevert,
IStream_fnLockRegion,
IStream_fnUnlockRegion,
IStream_fnStat,
IStream_fnClone
};
/**************************************************************************
* IStream_Create
*
* Internal helper: Create and initialise a new file stream object.
*/
static IStream *IStream_Create(LPCWSTR lpszPath, HANDLE hFile, DWORD dwMode)
{
ISHFileStream *fileStream;
fileStream = HeapAlloc(GetProcessHeap(), 0, sizeof(ISHFileStream));
if (!fileStream) return NULL;
fileStream->IStream_iface.lpVtbl = &SHLWAPI_fsVTable;
fileStream->ref = 1;
fileStream->hFile = hFile;
fileStream->dwMode = dwMode;
fileStream->lpszPath = StrDupW(lpszPath);
fileStream->type = 0; /* FIXME */
fileStream->grfStateBits = 0; /* FIXME */
TRACE ("Returning %p\n", fileStream);
return &fileStream->IStream_iface;
}
/*************************************************************************
* SHCreateStreamOnFileEx [SHLWAPI.@]
*
* Create a stream on a file.
*
* PARAMS
* lpszPath [I] Path of file to create stream on
* dwMode [I] Mode to create stream in
* dwAttributes [I] Attributes of the file
* bCreate [I] Whether to create the file if it doesn't exist
* lpTemplate [I] Reserved, must be NULL
* lppStream [O] Destination for created stream
*
* RETURNS
* Success: S_OK. lppStream contains the new stream object
* Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
*
* NOTES
* This function is available in Unicode only.
*/
HRESULT WINAPI SHCreateStreamOnFileEx(LPCWSTR lpszPath, DWORD dwMode,
DWORD dwAttributes, BOOL bCreate,
IStream *lpTemplate, IStream **lppStream)
{
DWORD dwAccess, dwShare, dwCreate;
HANDLE hFile;
TRACE("(%s,%d,0x%08X,%d,%p,%p)\n", debugstr_w(lpszPath), dwMode,
dwAttributes, bCreate, lpTemplate, lppStream);
if (!lpszPath || !lppStream || lpTemplate)
return E_INVALIDARG;
*lppStream = NULL;
/* Access */
switch (STGM_ACCESS_MODE(dwMode))
{
case STGM_WRITE:
case STGM_READWRITE:
dwAccess = GENERIC_READ|GENERIC_WRITE;
break;
case STGM_READ:
dwAccess = GENERIC_READ;
break;
default:
return E_INVALIDARG;
}
/* Sharing */
switch (STGM_SHARE_MODE(dwMode))
{
case 0:
case STGM_SHARE_DENY_NONE:
dwShare = FILE_SHARE_READ|FILE_SHARE_WRITE;
break;
case STGM_SHARE_DENY_READ:
dwShare = FILE_SHARE_WRITE;
break;
case STGM_SHARE_DENY_WRITE:
dwShare = FILE_SHARE_READ;
break;
case STGM_SHARE_EXCLUSIVE:
dwShare = 0;
break;
default:
return E_INVALIDARG;
}
switch(STGM_CREATE_MODE(dwMode))
{
case STGM_FAILIFTHERE:
dwCreate = bCreate ? CREATE_NEW : OPEN_EXISTING;
break;
case STGM_CREATE:
dwCreate = CREATE_ALWAYS;
break;
default:
return E_INVALIDARG;
}
/* Open HANDLE to file */
hFile = CreateFileW(lpszPath, dwAccess, dwShare, NULL, dwCreate,
dwAttributes, 0);
if(hFile == INVALID_HANDLE_VALUE)
return HRESULT_FROM_WIN32(GetLastError());
*lppStream = IStream_Create(lpszPath, hFile, dwMode);
if(!*lppStream)
{
CloseHandle(hFile);
return E_OUTOFMEMORY;
}
return S_OK;
}
/*************************************************************************
* SHCreateStreamOnFileW [SHLWAPI.@]
*
* See SHCreateStreamOnFileA.
*/
HRESULT WINAPI SHCreateStreamOnFileW(LPCWSTR lpszPath, DWORD dwMode,
IStream **lppStream)
{
TRACE("(%s,%d,%p)\n", debugstr_w(lpszPath), dwMode, lppStream);
if (!lpszPath || !lppStream)
return E_INVALIDARG;
if ((dwMode & (STGM_CONVERT|STGM_DELETEONRELEASE|STGM_TRANSACTED)) != 0)
return E_INVALIDARG;
return SHCreateStreamOnFileEx(lpszPath, dwMode, 0, FALSE, NULL, lppStream);
}
/*************************************************************************
* SHCreateStreamOnFileA [SHLWAPI.@]
*
* Create a stream on a file.
*
* PARAMS
* lpszPath [I] Path of file to create stream on
* dwMode [I] Mode to create stream in
* lppStream [O] Destination for created IStream object
*
* RETURNS
* Success: S_OK. lppStream contains the new IStream object
* Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
*/
HRESULT WINAPI SHCreateStreamOnFileA(LPCSTR lpszPath, DWORD dwMode,
IStream **lppStream)
{
WCHAR szPath[MAX_PATH];
TRACE("(%s,%d,%p)\n", debugstr_a(lpszPath), dwMode, lppStream);
if (!lpszPath)
return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, szPath, MAX_PATH);
return SHCreateStreamOnFileW(szPath, dwMode, lppStream);
}
/*************************************************************************
* @ [SHLWAPI.184]
*
......
......@@ -683,9 +683,9 @@
@ stdcall SHCopyKeyA(long str long long)
@ stdcall SHCopyKeyW(long wstr long long)
@ stdcall SHCreateShellPalette(long)
@ stdcall SHCreateStreamOnFileA(str long ptr)
@ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr)
@ stdcall SHCreateStreamOnFileW(wstr long ptr)
@ stdcall SHCreateStreamOnFileA(str long ptr) shcore.SHCreateStreamOnFileA
@ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr) shcore.SHCreateStreamOnFileEx
@ stdcall SHCreateStreamOnFileW(wstr long ptr) shcore.SHCreateStreamOnFileW
@ stdcall SHCreateStreamWrapper(ptr ptr long ptr)
@ stdcall SHCreateThreadRef(ptr ptr)
@ stdcall SHDeleteEmptyKeyA(long ptr)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment