ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

filelockbytes.c
Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * File-based ILockBytes implementation
00004  *
00005  * Copyright 1999 Thuy Nguyen
00006  * Copyright 2010 Vincent Povirk for CodeWeavers
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  */
00022 
00023 #include <assert.h>
00024 #include <stdlib.h>
00025 #include <stdarg.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <limits.h>
00029 
00030 #define COBJMACROS
00031 #define NONAMELESSUNION
00032 #define NONAMELESSSTRUCT
00033 
00034 #include "windef.h"
00035 #include "winbase.h"
00036 #include "winuser.h"
00037 #include "winerror.h"
00038 #include "objbase.h"
00039 #include "ole2.h"
00040 
00041 #include "storage32.h"
00042 
00043 #include "wine/debug.h"
00044 #include "wine/unicode.h"
00045 
00046 WINE_DEFAULT_DEBUG_CHANNEL(storage);
00047 
00048 typedef struct FileLockBytesImpl
00049 {
00050     ILockBytes ILockBytes_iface;
00051     LONG ref;
00052     ULARGE_INTEGER filesize;
00053     HANDLE hfile;
00054     DWORD flProtect;
00055     LPWSTR pwcsName;
00056 } FileLockBytesImpl;
00057 
00058 static const ILockBytesVtbl FileLockBytesImpl_Vtbl;
00059 
00060 static inline FileLockBytesImpl *impl_from_ILockBytes(ILockBytes *iface)
00061 {
00062     return CONTAINING_RECORD(iface, FileLockBytesImpl, ILockBytes_iface);
00063 }
00064 
00065 /***********************************************************
00066  * Prototypes for private methods
00067  */
00068 
00069 /* Note that this evaluates a and b multiple times, so don't
00070  * pass expressions with side effects. */
00071 #define ROUND_UP(a, b) ((((a) + (b) - 1)/(b))*(b))
00072 
00073 /****************************************************************************
00074  *      GetProtectMode
00075  *
00076  * This function will return a protection mode flag for a file-mapping object
00077  * from the open flags of a file.
00078  */
00079 static DWORD GetProtectMode(DWORD openFlags)
00080 {
00081     switch(STGM_ACCESS_MODE(openFlags))
00082     {
00083     case STGM_WRITE:
00084     case STGM_READWRITE:
00085         return PAGE_READWRITE;
00086     }
00087     return PAGE_READONLY;
00088 }
00089 
00090 /******************************************************************************
00091  *      FileLockBytesImpl_Construct
00092  *
00093  * Initialize a big block object supported by a file.
00094  */
00095 HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsName, ILockBytes **pLockBytes)
00096 {
00097   FileLockBytesImpl *This;
00098   WCHAR fullpath[MAX_PATH];
00099 
00100   if (hFile == INVALID_HANDLE_VALUE)
00101     return E_FAIL;
00102 
00103   This = HeapAlloc(GetProcessHeap(), 0, sizeof(FileLockBytesImpl));
00104 
00105   if (!This)
00106     return E_OUTOFMEMORY;
00107 
00108   This->ILockBytes_iface.lpVtbl = &FileLockBytesImpl_Vtbl;
00109   This->ref = 1;
00110   This->hfile = hFile;
00111   This->filesize.u.LowPart = GetFileSize(This->hfile,
00112                      &This->filesize.u.HighPart);
00113   This->flProtect = GetProtectMode(openFlags);
00114 
00115   if(pwcsName) {
00116     if (!GetFullPathNameW(pwcsName, MAX_PATH, fullpath, NULL))
00117     {
00118       lstrcpynW(fullpath, pwcsName, MAX_PATH);
00119     }
00120     This->pwcsName = HeapAlloc(GetProcessHeap(), 0,
00121                               (lstrlenW(fullpath)+1)*sizeof(WCHAR));
00122     if (!This->pwcsName)
00123     {
00124        HeapFree(GetProcessHeap(), 0, This);
00125        return E_OUTOFMEMORY;
00126     }
00127     strcpyW(This->pwcsName, fullpath);
00128   }
00129   else
00130     This->pwcsName = NULL;
00131 
00132   TRACE("file len %u\n", This->filesize.u.LowPart);
00133 
00134   *pLockBytes = &This->ILockBytes_iface;
00135 
00136   return S_OK;
00137 }
00138 
00139 /* ILockByte Interfaces */
00140 
00141 static HRESULT WINAPI FileLockBytesImpl_QueryInterface(ILockBytes *iface, REFIID riid,
00142     void **ppvObject)
00143 {
00144     if (IsEqualIID(riid, &IID_ILockBytes) || IsEqualIID(riid, &IID_ILockBytes))
00145         *ppvObject = iface;
00146     else
00147     {
00148         *ppvObject = NULL;
00149         return E_NOINTERFACE;
00150     }
00151 
00152     IUnknown_AddRef((IUnknown*)*ppvObject);
00153 
00154     return S_OK;
00155 }
00156 
00157 static ULONG WINAPI FileLockBytesImpl_AddRef(ILockBytes *iface)
00158 {
00159     FileLockBytesImpl* This = impl_from_ILockBytes(iface);
00160     return InterlockedIncrement(&This->ref);
00161 }
00162 
00163 static ULONG WINAPI FileLockBytesImpl_Release(ILockBytes *iface)
00164 {
00165     FileLockBytesImpl* This = impl_from_ILockBytes(iface);
00166     ULONG ref;
00167 
00168     ref = InterlockedDecrement(&This->ref);
00169 
00170     if (ref == 0)
00171     {
00172         CloseHandle(This->hfile);
00173         HeapFree(GetProcessHeap(), 0, This->pwcsName);
00174         HeapFree(GetProcessHeap(), 0, This);
00175     }
00176 
00177     return ref;
00178 }
00179 
00180 /******************************************************************************
00181  * This method is part of the ILockBytes interface.
00182  *
00183  * It reads a block of information from the byte array at the specified
00184  * offset.
00185  *
00186  * See the documentation of ILockBytes for more info.
00187  */
00188 static HRESULT WINAPI FileLockBytesImpl_ReadAt(
00189       ILockBytes* iface,
00190       ULARGE_INTEGER ulOffset,  /* [in] */
00191       void*          pv,        /* [length_is][size_is][out] */
00192       ULONG          cb,        /* [in] */
00193       ULONG*         pcbRead)   /* [out] */
00194 {
00195     FileLockBytesImpl* This = impl_from_ILockBytes(iface);
00196     ULONG bytes_left = cb;
00197     LPBYTE readPtr = pv;
00198     BOOL ret;
00199     LARGE_INTEGER offset;
00200     ULONG cbRead;
00201 
00202     TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbRead);
00203 
00204     /* verify a sane environment */
00205     if (!This) return E_FAIL;
00206 
00207     if (pcbRead)
00208         *pcbRead = 0;
00209 
00210     offset.QuadPart = ulOffset.QuadPart;
00211 
00212     ret = SetFilePointerEx(This->hfile, offset, NULL, FILE_BEGIN);
00213 
00214     if (!ret)
00215         return STG_E_READFAULT;
00216 
00217     while (bytes_left)
00218     {
00219         ret = ReadFile(This->hfile, readPtr, bytes_left, &cbRead, NULL);
00220 
00221         if (!ret || cbRead == 0)
00222             return STG_E_READFAULT;
00223 
00224         if (pcbRead)
00225             *pcbRead += cbRead;
00226 
00227         bytes_left -= cbRead;
00228         readPtr += cbRead;
00229     }
00230 
00231     TRACE("finished\n");
00232     return S_OK;
00233 }
00234 
00235 /******************************************************************************
00236  * This method is part of the ILockBytes interface.
00237  *
00238  * It writes the specified bytes at the specified offset.
00239  * position. If the file is too small, it will be resized.
00240  *
00241  * See the documentation of ILockBytes for more info.
00242  */
00243 static HRESULT WINAPI FileLockBytesImpl_WriteAt(
00244       ILockBytes* iface,
00245       ULARGE_INTEGER ulOffset,    /* [in] */
00246       const void*    pv,          /* [size_is][in] */
00247       ULONG          cb,          /* [in] */
00248       ULONG*         pcbWritten)  /* [out] */
00249 {
00250     FileLockBytesImpl* This = impl_from_ILockBytes(iface);
00251     ULONG size_needed = ulOffset.u.LowPart + cb;
00252     ULONG bytes_left = cb;
00253     const BYTE *writePtr = pv;
00254     BOOL ret;
00255     LARGE_INTEGER offset;
00256     ULONG cbWritten;
00257 
00258     TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbWritten);
00259 
00260     /* verify a sane environment */
00261     if (!This) return E_FAIL;
00262 
00263     if (This->flProtect != PAGE_READWRITE)
00264         return STG_E_ACCESSDENIED;
00265 
00266     if (pcbWritten)
00267         *pcbWritten = 0;
00268 
00269     if (size_needed > This->filesize.u.LowPart)
00270     {
00271         ULARGE_INTEGER newSize;
00272         newSize.u.HighPart = 0;
00273         newSize.u.LowPart = size_needed;
00274         ILockBytes_SetSize(iface, newSize);
00275     }
00276 
00277     offset.QuadPart = ulOffset.QuadPart;
00278 
00279     ret = SetFilePointerEx(This->hfile, offset, NULL, FILE_BEGIN);
00280 
00281     if (!ret)
00282         return STG_E_READFAULT;
00283 
00284     while (bytes_left)
00285     {
00286         ret = WriteFile(This->hfile, writePtr, bytes_left, &cbWritten, NULL);
00287 
00288         if (!ret)
00289             return STG_E_READFAULT;
00290 
00291         if (pcbWritten)
00292             *pcbWritten += cbWritten;
00293 
00294         bytes_left -= cbWritten;
00295         writePtr += cbWritten;
00296     }
00297 
00298     TRACE("finished\n");
00299     return S_OK;
00300 }
00301 
00302 static HRESULT WINAPI FileLockBytesImpl_Flush(ILockBytes* iface)
00303 {
00304     return S_OK;
00305 }
00306 
00307 /******************************************************************************
00308  *      ILockBytes_SetSize
00309  *
00310  * Sets the size of the file.
00311  *
00312  */
00313 static HRESULT WINAPI FileLockBytesImpl_SetSize(ILockBytes* iface, ULARGE_INTEGER newSize)
00314 {
00315     FileLockBytesImpl* This = impl_from_ILockBytes(iface);
00316     HRESULT hr = S_OK;
00317     LARGE_INTEGER newpos;
00318 
00319     if (This->filesize.u.LowPart == newSize.u.LowPart)
00320         return hr;
00321 
00322     TRACE("from %u to %u\n", This->filesize.u.LowPart, newSize.u.LowPart);
00323 
00324     newpos.QuadPart = newSize.QuadPart;
00325     if (SetFilePointerEx(This->hfile, newpos, NULL, FILE_BEGIN))
00326     {
00327         SetEndOfFile(This->hfile);
00328     }
00329 
00330     This->filesize = newSize;
00331     return hr;
00332 }
00333 
00334 static HRESULT WINAPI FileLockBytesImpl_LockRegion(ILockBytes* iface,
00335     ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
00336 {
00337     FIXME("stub\n");
00338     return E_NOTIMPL;
00339 }
00340 
00341 static HRESULT WINAPI FileLockBytesImpl_UnlockRegion(ILockBytes* iface,
00342     ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
00343 {
00344     FIXME("stub\n");
00345     return E_NOTIMPL;
00346 }
00347 
00348 static HRESULT WINAPI FileLockBytesImpl_Stat(ILockBytes* iface,
00349     STATSTG *pstatstg, DWORD grfStatFlag)
00350 {
00351     FileLockBytesImpl* This = impl_from_ILockBytes(iface);
00352 
00353     if (!(STATFLAG_NONAME & grfStatFlag) && This->pwcsName)
00354     {
00355         pstatstg->pwcsName =
00356           CoTaskMemAlloc((lstrlenW(This->pwcsName)+1)*sizeof(WCHAR));
00357 
00358         strcpyW(pstatstg->pwcsName, This->pwcsName);
00359     }
00360     else
00361         pstatstg->pwcsName = NULL;
00362 
00363     pstatstg->type = STGTY_LOCKBYTES;
00364     pstatstg->cbSize = This->filesize;
00365     /* FIXME: If the implementation is exported, we'll need to set other fields. */
00366 
00367     return S_OK;
00368 }
00369 
00370 static const ILockBytesVtbl FileLockBytesImpl_Vtbl = {
00371     FileLockBytesImpl_QueryInterface,
00372     FileLockBytesImpl_AddRef,
00373     FileLockBytesImpl_Release,
00374     FileLockBytesImpl_ReadAt,
00375     FileLockBytesImpl_WriteAt,
00376     FileLockBytesImpl_Flush,
00377     FileLockBytesImpl_SetSize,
00378     FileLockBytesImpl_LockRegion,
00379     FileLockBytesImpl_UnlockRegion,
00380     FileLockBytesImpl_Stat
00381 };

Generated on Sat May 26 2012 04:24:08 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.