diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in index 755a2b8df59..430ec925f56 100644 --- a/dlls/ole32/Makefile.in +++ b/dlls/ole32/Makefile.in @@ -21,6 +21,7 @@ C_SRCS = \ dictionary.c \ enumx.c \ errorinfo.c \ + filelockbytes.c \ filemoniker.c \ ftmarshal.c \ git.c \ @@ -39,7 +40,6 @@ C_SRCS = \ pointermoniker.c \ regsvr.c \ rpc.c \ - stg_bigblockfile.c \ stg_prop.c \ stg_stream.c \ storage32.c \ diff --git a/dlls/ole32/stg_bigblockfile.c b/dlls/ole32/filelockbytes.c similarity index 53% rename from dlls/ole32/stg_bigblockfile.c rename to dlls/ole32/filelockbytes.c index 7a98c146e58..2491a827e30 100644 --- a/dlls/ole32/stg_bigblockfile.c +++ b/dlls/ole32/filelockbytes.c @@ -1,20 +1,9 @@ /****************************************************************************** * - * BigBlockFile - * - * This is the implementation of a file that consists of blocks of - * a predetermined size. - * This class is used in the Compound File implementation of the - * IStorage and IStream interfaces. It provides the functionality - * to read and write any blocks in the file as well as setting and - * obtaining the size of the file. - * The blocks are indexed sequentially from the start of the file - * starting with -1. - * - * TODO: - * - Support for a transacted mode + * 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 @@ -55,19 +44,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(storage); -/*********************************************************** - * Data structures used internally by the BigBlockFile - * class. - */ - -struct BigBlockFile +typedef struct FileLockBytesImpl { - BOOL fileBased; + const ILockBytesVtbl *lpVtbl; + LONG ref; ULARGE_INTEGER filesize; HANDLE hfile; DWORD flProtect; - ILockBytes *pLkbyt; -}; +} FileLockBytesImpl; + +static const ILockBytesVtbl FileLockBytesImpl_Vtbl; /*********************************************************** * Prototypes for private methods @@ -77,52 +63,13 @@ struct BigBlockFile * pass expressions with side effects. */ #define ROUND_UP(a, b) ((((a) + (b) - 1)/(b))*(b)) -/****************************************************************************** - * BIGBLOCKFILE_FileInit - * - * Initialize a big block object supported by a file. - */ -static BOOL BIGBLOCKFILE_FileInit(LPBIGBLOCKFILE This, HANDLE hFile) -{ - This->pLkbyt = NULL; - This->hfile = hFile; - - if (This->hfile == INVALID_HANDLE_VALUE) - return FALSE; - - This->filesize.u.LowPart = GetFileSize(This->hfile, - &This->filesize.u.HighPart); - - TRACE("file len %u\n", This->filesize.u.LowPart); - - return TRUE; -} - -/****************************************************************************** - * BIGBLOCKFILE_LockBytesInit - * - * Initialize a big block object supported by an ILockBytes. - */ -static BOOL BIGBLOCKFILE_LockBytesInit(LPBIGBLOCKFILE This, ILockBytes* plkbyt) -{ - This->hfile = 0; - This->pLkbyt = plkbyt; - ILockBytes_AddRef(This->pLkbyt); - - /* We'll get the size directly with ILockBytes_Stat */ - This->filesize.QuadPart = 0; - - TRACE("ILockBytes %p\n", This->pLkbyt); - return TRUE; -} - /**************************************************************************** - * BIGBLOCKFILE_GetProtectMode + * GetProtectMode * * This function will return a protection mode flag for a file-mapping object * from the open flags of a file. */ -static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags) +static DWORD GetProtectMode(DWORD openFlags) { switch(STGM_ACCESS_MODE(openFlags)) { @@ -133,9 +80,77 @@ static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags) return PAGE_READONLY; } +/****************************************************************************** + * FileLockBytesImpl_Construct + * + * Initialize a big block object supported by a file. + */ +HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, ILockBytes **pLockBytes) +{ + FileLockBytesImpl *This; + + if (hFile == INVALID_HANDLE_VALUE) + return E_FAIL; + + This = HeapAlloc(GetProcessHeap(), 0, sizeof(FileLockBytesImpl)); + + if (!This) + return E_OUTOFMEMORY; + + This->lpVtbl = &FileLockBytesImpl_Vtbl; + This->ref = 1; + This->hfile = hFile; + This->filesize.u.LowPart = GetFileSize(This->hfile, + &This->filesize.u.HighPart); + This->flProtect = GetProtectMode(openFlags); + + TRACE("file len %u\n", This->filesize.u.LowPart); + + *pLockBytes = (ILockBytes*)This; + + return S_OK; +} /* ILockByte Interfaces */ +static HRESULT WINAPI FileLockBytesImpl_QueryInterface(ILockBytes *iface, REFIID riid, + void **ppvObject) +{ + if (IsEqualIID(riid, &IID_ILockBytes) || 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 = (FileLockBytesImpl*)iface; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI FileLockBytesImpl_Release(ILockBytes *iface) +{ + FileLockBytesImpl* This = (FileLockBytesImpl*)iface; + ULONG ref; + + ref = InterlockedDecrement(&This->ref); + + if (ref == 0) + { + CloseHandle(This->hfile); + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + /****************************************************************************** * This method is part of the ILockBytes interface. * @@ -144,13 +159,14 @@ static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags) * * See the documentation of ILockBytes for more info. */ -static HRESULT ImplBIGBLOCKFILE_ReadAt( - BigBlockFile* const This, +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 = (FileLockBytesImpl*)iface; ULONG bytes_left = cb; LPBYTE readPtr = pv; BOOL ret; @@ -198,13 +214,14 @@ static HRESULT ImplBIGBLOCKFILE_ReadAt( * * See the documentation of ILockBytes for more info. */ -static HRESULT ImplBIGBLOCKFILE_WriteAt( - BigBlockFile* const This, +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 = (FileLockBytesImpl*)iface; ULONG size_needed = ulOffset.u.LowPart + cb; ULONG bytes_left = cb; const BYTE *writePtr = pv; @@ -228,7 +245,7 @@ static HRESULT ImplBIGBLOCKFILE_WriteAt( ULARGE_INTEGER newSize; newSize.u.HighPart = 0; newSize.u.LowPart = size_needed; - BIGBLOCKFILE_SetSize(This, newSize); + ILockBytes_SetSize(iface, newSize); } offset.QuadPart = ulOffset.QuadPart; @@ -256,103 +273,23 @@ static HRESULT ImplBIGBLOCKFILE_WriteAt( return S_OK; } -/****************************************************************************** - * BIGBLOCKFILE_Construct - * - * Construct a big block file. Create the file mapping object. - * Create the read only mapped pages list, the writable mapped page list - * and the blocks in use list. - */ -BigBlockFile *BIGBLOCKFILE_Construct(HANDLE hFile, ILockBytes* pLkByt, DWORD openFlags, - BOOL fileBased) +static HRESULT WINAPI FileLockBytesImpl_Flush(ILockBytes* iface) { - BigBlockFile *This; - - This = HeapAlloc(GetProcessHeap(), 0, sizeof(BigBlockFile)); - - if (This == NULL) - return NULL; - - This->fileBased = fileBased; - This->flProtect = BIGBLOCKFILE_GetProtectMode(openFlags); - - if (This->fileBased) - { - if (!BIGBLOCKFILE_FileInit(This, hFile)) - { - HeapFree(GetProcessHeap(), 0, This); - return NULL; - } - } - else - { - if (!BIGBLOCKFILE_LockBytesInit(This, pLkByt)) - { - HeapFree(GetProcessHeap(), 0, This); - return NULL; - } - } - - return This; + return S_OK; } /****************************************************************************** - * BIGBLOCKFILE_Destructor - * - * Destructor. Clean up, free memory. - */ -void BIGBLOCKFILE_Destructor(BigBlockFile *This) -{ - if (This->fileBased) - { - CloseHandle(This->hfile); - } - else - { - ILockBytes_Release(This->pLkbyt); - } - - HeapFree(GetProcessHeap(), 0, This); -} - -/****************************************************************************** - * BIGBLOCKFILE_ReadAt - */ -HRESULT BIGBLOCKFILE_ReadAt(BigBlockFile *This, ULARGE_INTEGER offset, - void* buffer, ULONG size, ULONG* bytesRead) -{ - if (This->fileBased) - return ImplBIGBLOCKFILE_ReadAt(This,offset,buffer,size,bytesRead); - else - return ILockBytes_ReadAt(This->pLkbyt,offset,buffer,size,bytesRead); -} - -/****************************************************************************** - * BIGBLOCKFILE_WriteAt - */ -HRESULT BIGBLOCKFILE_WriteAt(BigBlockFile *This, ULARGE_INTEGER offset, - const void* buffer, ULONG size, ULONG* bytesRead) -{ - if (This->fileBased) - return ImplBIGBLOCKFILE_WriteAt(This,offset,buffer,size,bytesRead); - else - return ILockBytes_WriteAt(This->pLkbyt,offset,buffer,size,bytesRead); -} - -/****************************************************************************** - * BIGBLOCKFILE_SetSize + * ILockBytes_SetSize * * Sets the size of the file. * */ -HRESULT BIGBLOCKFILE_SetSize(BigBlockFile *This, ULARGE_INTEGER newSize) +static HRESULT WINAPI FileLockBytesImpl_SetSize(ILockBytes* iface, ULARGE_INTEGER newSize) { + FileLockBytesImpl* This = (FileLockBytesImpl*)iface; HRESULT hr = S_OK; LARGE_INTEGER newpos; - if (!This->fileBased) - return ILockBytes_SetSize(This->pLkbyt, newSize); - if (This->filesize.u.LowPart == newSize.u.LowPart) return hr; @@ -368,40 +305,47 @@ HRESULT BIGBLOCKFILE_SetSize(BigBlockFile *This, ULARGE_INTEGER newSize) return hr; } -/****************************************************************************** - * BIGBLOCKFILE_GetSize - * - * Gets the size of the file. - * - */ -static HRESULT BIGBLOCKFILE_GetSize(BigBlockFile *This, ULARGE_INTEGER *size) +static HRESULT WINAPI FileLockBytesImpl_LockRegion(ILockBytes* iface, + ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { - HRESULT hr = S_OK; - if(This->fileBased) - *size = This->filesize; - else + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI FileLockBytesImpl_UnlockRegion(ILockBytes* iface, + ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI FileLockBytesImpl_Stat(ILockBytes* iface, + STATSTG *pstatstg, DWORD grfStatFlag) +{ + FileLockBytesImpl* This = (FileLockBytesImpl*)iface; + + if (!(STATFLAG_NONAME & grfStatFlag)) { - STATSTG stat; - hr = ILockBytes_Stat(This->pLkbyt, &stat, STATFLAG_NONAME); - if(SUCCEEDED(hr)) *size = stat.cbSize; + FIXME("reading filename not supported\n"); } - return hr; + + 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; } -/****************************************************************************** - * BIGBLOCKFILE_Expand - * - * Grows the file to the specified size if necessary. - */ -HRESULT BIGBLOCKFILE_Expand(BigBlockFile *This, ULARGE_INTEGER newSize) -{ - ULARGE_INTEGER size; - HRESULT hr; - - hr = BIGBLOCKFILE_GetSize(This, &size); - if(FAILED(hr)) return hr; - - if (newSize.QuadPart > size.QuadPart) - hr = BIGBLOCKFILE_SetSize(This, newSize); - return hr; -} +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 +}; diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index 15fe143c735..860f13037df 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -327,7 +327,7 @@ static HRESULT StorageImpl_ReadAt(StorageImpl* This, ULONG size, ULONG* bytesRead) { - return BIGBLOCKFILE_ReadAt(This->bigBlockFile,offset,buffer,size,bytesRead); + return ILockBytes_ReadAt(This->lockBytes,offset,buffer,size,bytesRead); } static HRESULT StorageImpl_WriteAt(StorageImpl* This, @@ -336,7 +336,7 @@ static HRESULT StorageImpl_WriteAt(StorageImpl* This, const ULONG size, ULONG* bytesWritten) { - return BIGBLOCKFILE_WriteAt(This->bigBlockFile,offset,buffer,size,bytesWritten); + return ILockBytes_WriteAt(This->lockBytes,offset,buffer,size,bytesWritten); } /************************************************************************ @@ -2683,17 +2683,17 @@ static HRESULT StorageImpl_Construct( */ This->bigBlockSize = sector_size; This->smallBlockSize = DEF_SMALL_BLOCK_SIZE; - This->bigBlockFile = BIGBLOCKFILE_Construct(hFile, - pLkbyt, - openFlags, - fileBased); - - if (This->bigBlockFile == 0) + if (hFile) + hr = FileLockBytesImpl_Construct(hFile, openFlags, &This->lockBytes); + else { - hr = E_FAIL; - goto end; + This->lockBytes = pLkbyt; + ILockBytes_AddRef(pLkbyt); } + if (FAILED(hr)) + goto end; + if (create) { ULARGE_INTEGER size; @@ -2729,7 +2729,7 @@ static HRESULT StorageImpl_Construct( */ size.u.HighPart = 0; size.u.LowPart = This->bigBlockSize * 3; - BIGBLOCKFILE_SetSize(This->bigBlockFile, size); + ILockBytes_SetSize(This->lockBytes, size); /* * Initialize the big block depot @@ -2884,8 +2884,8 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface) for (i=0; iblockChainCache[i]); - if (This->bigBlockFile) - BIGBLOCKFILE_Destructor(This->bigBlockFile); + if (This->lockBytes) + ILockBytes_Release(This->lockBytes); HeapFree(GetProcessHeap(), 0, This); } @@ -2908,6 +2908,7 @@ static ULONG StorageImpl_GetNextFreeBigBlock( int depotIndex = 0; ULONG freeBlock = BLOCK_UNUSED; ULARGE_INTEGER neededSize; + STATSTG statstg; depotIndex = This->prevFreeBlock / blocksPerDepot; depotBlockOffset = (This->prevFreeBlock % blocksPerDepot) * sizeof(ULONG); @@ -3022,7 +3023,11 @@ static ULONG StorageImpl_GetNextFreeBigBlock( * make sure that the block physically exists before using it */ neededSize.QuadPart = StorageImpl_GetBigBlockOffset(This, freeBlock)+This->bigBlockSize; - BIGBLOCKFILE_Expand(This->bigBlockFile, neededSize); + + ILockBytes_Stat(This->lockBytes, &statstg, STATFLAG_NONAME); + + if (neededSize.QuadPart > statstg.cbSize.QuadPart) + ILockBytes_SetSize(This->lockBytes, neededSize); This->prevFreeBlock = freeBlock; diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h index 524ff7d851e..335b4bcc2b3 100644 --- a/dlls/ole32/storage32.h +++ b/dlls/ole32/storage32.h @@ -11,6 +11,7 @@ * * Copyright 1998,1999 Francis Beaudet * Copyright 1998,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 @@ -153,31 +154,7 @@ struct DirEntry ULARGE_INTEGER size; }; -/************************************************************************* - * Big Block File support - * - * The big block file is an abstraction of a flat file separated in - * same sized blocks. The implementation for the methods described in - * this section appear in stg_bigblockfile.c - */ - -typedef struct BigBlockFile BigBlockFile,*LPBIGBLOCKFILE; - -/* - * Declaration of the functions used to manipulate the BigBlockFile - * data structure. - */ -BigBlockFile* BIGBLOCKFILE_Construct(HANDLE hFile, - ILockBytes* pLkByt, - DWORD openFlags, - BOOL fileBased); -void BIGBLOCKFILE_Destructor(LPBIGBLOCKFILE This); -HRESULT BIGBLOCKFILE_Expand(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize); -HRESULT BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize); -HRESULT BIGBLOCKFILE_ReadAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset, - void* buffer, ULONG size, ULONG* bytesRead); -HRESULT BIGBLOCKFILE_WriteAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset, - const void* buffer, ULONG size, ULONG* bytesRead); +HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, ILockBytes **pLockBytes); /************************************************************************* * Ole Convert support @@ -395,10 +372,7 @@ struct StorageImpl BlockChainStream* blockChainCache[BLOCKCHAIN_CACHE_SIZE]; UINT blockChainToEvict; - /* - * Pointer to the big block file abstraction - */ - BigBlockFile* bigBlockFile; + ILockBytes* lockBytes; }; HRESULT StorageImpl_ReadRawDirEntry(