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

memlockbytes.c
Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * Global memory implementation of ILockBytes.
00004  *
00005  * Copyright 1999 Thuy Nguyen
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include "config.h"
00023 
00024 #include <assert.h>
00025 #include <stdarg.h>
00026 #include <string.h>
00027 
00028 #define COBJMACROS
00029 #define NONAMELESSUNION
00030 #define NONAMELESSSTRUCT
00031 
00032 #include "windef.h"
00033 #include "winbase.h"
00034 #include "winuser.h"
00035 #include "objbase.h"
00036 #include "ole2.h"
00037 #include "winerror.h"
00038 
00039 #include "wine/debug.h"
00040 
00041 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00042 
00043 /******************************************************************************
00044  * HGLOBALLockBytesImpl definition.
00045  *
00046  * This class implements the ILockBytes interface and represents a byte array
00047  * object supported by an HGLOBAL pointer.
00048  */
00049 struct HGLOBALLockBytesImpl
00050 {
00051   /*
00052    * Needs to be the first item in the struct
00053    * since we want to cast this in an ILockBytes pointer
00054    */
00055   const ILockBytesVtbl *lpVtbl;
00056 
00057   /*
00058    * Reference count
00059    */
00060   LONG        ref;
00061 
00062   /*
00063    * Support for the LockBytes object
00064    */
00065   HGLOBAL supportHandle;
00066 
00067   /*
00068    * This flag is TRUE if the HGLOBAL is destroyed when the object
00069    * is finally released.
00070    */
00071   BOOL    deleteOnRelease;
00072 
00073   /*
00074    * Helper variable that contains the size of the byte array
00075    */
00076   ULARGE_INTEGER     byteArraySize;
00077 };
00078 
00079 typedef struct HGLOBALLockBytesImpl HGLOBALLockBytesImpl;
00080 
00081 /*
00082  * Method definition for the HGLOBALLockBytesImpl class.
00083  */
00084 static HGLOBALLockBytesImpl* HGLOBALLockBytesImpl_Construct(
00085     HGLOBAL  hGlobal,
00086     BOOL     fDeleteOnRelease);
00087 
00088 static void HGLOBALLockBytesImpl_Destroy(HGLOBALLockBytesImpl* This);
00089 
00090 static HRESULT WINAPI HGLOBALLockBytesImpl_SetSize( ILockBytes* iface, ULARGE_INTEGER libNewSize );
00091 
00092 static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl;
00093 
00094 /******************************************************************************
00095  *           CreateILockBytesOnHGlobal     [OLE32.@]
00096  *
00097  * Create a byte array object which is intended to be the compound file foundation.
00098  * This object supports a COM implementation of the ILockBytes interface.
00099  *
00100  * PARAMS
00101  *  hGlobal           [ I] Global memory handle
00102  *  fDeleteOnRelease  [ I] Whether the handle should be freed when the object is released. 
00103  *  ppLkbyt           [ O] Address of ILockBytes pointer that receives
00104  *                         the interface pointer to the new byte array object.
00105  *
00106  * RETURNS
00107  *  Success: S_OK
00108  *
00109  * NOTES
00110  *  The supplied ILockBytes pointer can be used by the StgCreateDocfileOnILockBytes
00111  *  function to build a compound file on top of this byte array object.
00112  *  The ILockBytes interface instance calls the GlobalReAlloc function to grow
00113  *  the memory block as required.
00114  */
00115 HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL      hGlobal,
00116                                          BOOL         fDeleteOnRelease,
00117                                          LPLOCKBYTES* ppLkbyt)
00118 {
00119   HGLOBALLockBytesImpl* newLockBytes;
00120 
00121   newLockBytes = HGLOBALLockBytesImpl_Construct(hGlobal, fDeleteOnRelease);
00122 
00123   if (newLockBytes != NULL)
00124   {
00125     return IUnknown_QueryInterface((IUnknown*)newLockBytes,
00126                                    &IID_ILockBytes,
00127                                    (void**)ppLkbyt);
00128   }
00129 
00130   return E_OUTOFMEMORY;
00131 }
00132 
00133 /******************************************************************************
00134  *           GetHGlobalFromILockBytes     [OLE32.@]
00135  *
00136  * Retrieve a global memory handle to a byte array object created
00137  * using the CreateILockBytesOnHGlobal function.
00138  *
00139  * PARAMS
00140  *  plkbyt   [ I]  Pointer to the ILockBytes interface on byte array object
00141  *  phglobal [ O]  Address to store a global memory handle
00142  * RETURNS
00143  *  S_OK          if *phglobal has a correct value
00144  *  E_INVALIDARG  if any parameters are invalid
00145  *  
00146  */
00147 HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* plkbyt, HGLOBAL* phglobal)
00148 {
00149   HGLOBALLockBytesImpl* const pMemLockBytes = (HGLOBALLockBytesImpl*)plkbyt;
00150   STATSTG stbuf;
00151   HRESULT hres;
00152   ULARGE_INTEGER start;
00153   ULONG xread;
00154 
00155   *phglobal = 0;
00156   if (pMemLockBytes->lpVtbl == &HGLOBALLockBytesImpl_Vtbl) {
00157     *phglobal = pMemLockBytes->supportHandle;
00158     if (*phglobal == 0)
00159       return E_INVALIDARG;
00160     return S_OK;
00161   }
00162   /* It is not our lockbytes implementation, so use a more generic way */
00163   hres = ILockBytes_Stat(plkbyt,&stbuf,STATFLAG_NONAME);
00164   if (hres != S_OK) {
00165      ERR("Cannot ILockBytes_Stat, %x\n",hres);
00166      return hres;
00167   }
00168   TRACE("cbSize is %s\n", wine_dbgstr_longlong(stbuf.cbSize.QuadPart));
00169   *phglobal = GlobalAlloc( GMEM_MOVEABLE|GMEM_SHARE, stbuf.cbSize.u.LowPart);
00170   if (!*phglobal)
00171     return E_INVALIDARG;
00172   memset(&start,0,sizeof(start));
00173   hres = ILockBytes_ReadAt(plkbyt, start, GlobalLock(*phglobal), stbuf.cbSize.u.LowPart, &xread);
00174   GlobalUnlock(*phglobal);
00175   if (hres != S_OK) {
00176     FIXME("%p->ReadAt failed with %x\n",plkbyt,hres);
00177     return hres;
00178   }
00179   if (stbuf.cbSize.u.LowPart != xread) {
00180     FIXME("Read size is not requested size %d vs %d?\n",stbuf.cbSize.u.LowPart, xread);
00181   }
00182   return S_OK;
00183 }
00184 
00185 /******************************************************************************
00186  *
00187  * HGLOBALLockBytesImpl implementation
00188  *
00189  */
00190 
00191 /******************************************************************************
00192  * This is the constructor for the HGLOBALLockBytesImpl class.
00193  *
00194  * PARAMS
00195  *    hGlobal          [ I] Handle that will support the stream. can be NULL.
00196  *    fDeleteOnRelease [ I] Flag set to TRUE if the HGLOBAL will be released
00197  *                          when the IStream object is destroyed.
00198  */
00199 static HGLOBALLockBytesImpl* HGLOBALLockBytesImpl_Construct(HGLOBAL hGlobal,
00200                                                             BOOL    fDeleteOnRelease)
00201 {
00202   HGLOBALLockBytesImpl* newLockBytes;
00203   newLockBytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl));
00204 
00205   if (newLockBytes!=0)
00206   {
00207     /*
00208      * Set up the virtual function table and reference count.
00209      */
00210     newLockBytes->lpVtbl = &HGLOBALLockBytesImpl_Vtbl;
00211     newLockBytes->ref    = 0;
00212 
00213     /*
00214      * Initialize the support.
00215      */
00216     newLockBytes->supportHandle = hGlobal;
00217     newLockBytes->deleteOnRelease = fDeleteOnRelease;
00218 
00219     /*
00220      * This method will allocate a handle if one is not supplied.
00221      */
00222     if (newLockBytes->supportHandle == 0)
00223     {
00224       newLockBytes->supportHandle = GlobalAlloc(GMEM_MOVEABLE |
00225                                                 GMEM_NODISCARD,
00226                                                 0);
00227     }
00228 
00229     /*
00230      * Initialize the size of the array to the size of the handle.
00231      */
00232     newLockBytes->byteArraySize.u.HighPart = 0;
00233     newLockBytes->byteArraySize.u.LowPart  = GlobalSize(
00234                                               newLockBytes->supportHandle);
00235   }
00236 
00237   return newLockBytes;
00238 }
00239 
00240 /******************************************************************************
00241  * This is the destructor of the HGLOBALStreamImpl class.
00242  *
00243  * This method will clean-up all the resources used-up by the given
00244  * HGLOBALLockBytesImpl class. The pointer passed-in to this function will be
00245  * freed and will not be valid anymore.
00246  */
00247 static void HGLOBALLockBytesImpl_Destroy(HGLOBALLockBytesImpl* This)
00248 {
00249   /*
00250    * Release the HGlobal if the constructor asked for that.
00251    */
00252   if (This->deleteOnRelease)
00253   {
00254     GlobalFree(This->supportHandle);
00255     This->supportHandle = 0;
00256   }
00257 
00258   /*
00259    * Finally, free the memory used-up by the class.
00260    */
00261   HeapFree(GetProcessHeap(), 0, This);
00262 }
00263 
00264 /******************************************************************************
00265  * This implements the IUnknown method QueryInterface for this
00266  * class
00267  */
00268 static HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface(
00269       ILockBytes*  iface,
00270       REFIID       riid,        /* [in] */
00271       void**       ppvObject)   /* [iid_is][out] */
00272 {
00273   HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
00274 
00275   /*
00276    * Perform a sanity check on the parameters.
00277    */
00278   if (ppvObject==0)
00279     return E_INVALIDARG;
00280 
00281   /*
00282    * Initialize the return parameter.
00283    */
00284   *ppvObject = 0;
00285 
00286   /*
00287    * Compare the riid with the interface IDs implemented by this object.
00288    */
00289   if (IsEqualIID(riid, &IID_IUnknown) ||
00290       IsEqualIID(riid, &IID_ILockBytes))
00291   {
00292     *ppvObject = This;
00293   }
00294 
00295   /*
00296    * Check that we obtained an interface.
00297    */
00298   if ((*ppvObject)==0)
00299     return E_NOINTERFACE;
00300 
00301   /*
00302    * Query Interface always increases the reference count by one when it is
00303    * successful
00304    */
00305   IUnknown_AddRef(iface);
00306 
00307   return S_OK;
00308 }
00309 
00310 /******************************************************************************
00311  * This implements the IUnknown method AddRef for this
00312  * class
00313  */
00314 static ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface)
00315 {
00316   HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
00317   return InterlockedIncrement(&This->ref);
00318 }
00319 
00320 /******************************************************************************
00321  * This implements the IUnknown method Release for this
00322  * class
00323  */
00324 static ULONG WINAPI HGLOBALLockBytesImpl_Release(ILockBytes* iface)
00325 {
00326   HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
00327   ULONG ref;
00328 
00329   ref = InterlockedDecrement(&This->ref);
00330 
00331   /*
00332    * If the reference count goes down to 0, perform suicide.
00333    */
00334   if (ref==0)
00335   {
00336     HGLOBALLockBytesImpl_Destroy(This);
00337   }
00338 
00339   return ref;
00340 }
00341 
00342 /******************************************************************************
00343  * This method is part of the ILockBytes interface.
00344  *
00345  * It reads a block of information from the byte array at the specified
00346  * offset.
00347  *
00348  * See the documentation of ILockBytes for more info.
00349  */
00350 static HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt(
00351       ILockBytes*    iface,
00352       ULARGE_INTEGER ulOffset,  /* [in] */
00353       void*          pv,        /* [length_is][size_is][out] */
00354       ULONG          cb,        /* [in] */
00355       ULONG*         pcbRead)   /* [out] */
00356 {
00357   HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
00358 
00359   void* supportBuffer;
00360   ULONG bytesReadBuffer = 0;
00361   ULONG bytesToReadFromBuffer;
00362 
00363   /*
00364    * If the caller is not interested in the number of bytes read,
00365    * we use another buffer to avoid "if" statements in the code.
00366    */
00367   if (pcbRead == 0)
00368     pcbRead = &bytesReadBuffer;
00369 
00370   /*
00371    * Make sure the offset is valid.
00372    */
00373   if (ulOffset.u.LowPart > This->byteArraySize.u.LowPart)
00374     return E_FAIL;
00375 
00376   /*
00377    * Using the known size of the array, calculate the number of bytes
00378    * to read.
00379    */
00380   bytesToReadFromBuffer = min(This->byteArraySize.u.LowPart -
00381                               ulOffset.u.LowPart, cb);
00382 
00383   /*
00384    * Lock the buffer in position and copy the data.
00385    */
00386   supportBuffer = GlobalLock(This->supportHandle);
00387 
00388   memcpy(pv,
00389          (char *) supportBuffer + ulOffset.u.LowPart,
00390          bytesToReadFromBuffer);
00391 
00392   /*
00393    * Return the number of bytes read.
00394    */
00395   *pcbRead = bytesToReadFromBuffer;
00396 
00397   /*
00398    * Cleanup
00399    */
00400   GlobalUnlock(This->supportHandle);
00401 
00402   /*
00403    * The function returns S_OK if the specified number of bytes were read
00404    * or the end of the array was reached.
00405    * It returns STG_E_READFAULT if the number of bytes to read does not equal
00406    * the number of bytes actually read.
00407    */
00408   if(*pcbRead == cb)
00409     return S_OK;
00410 
00411   return STG_E_READFAULT;
00412 }
00413 
00414 /******************************************************************************
00415  * This method is part of the ILockBytes interface.
00416  *
00417  * It writes the specified bytes at the specified offset.
00418  * position. If the array is too small, it will be resized.
00419  *
00420  * See the documentation of ILockBytes for more info.
00421  */
00422 static HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(
00423       ILockBytes*    iface,
00424       ULARGE_INTEGER ulOffset,    /* [in] */
00425       const void*    pv,          /* [size_is][in] */
00426       ULONG          cb,          /* [in] */
00427       ULONG*         pcbWritten)  /* [out] */
00428 {
00429   HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
00430 
00431   void*          supportBuffer;
00432   ULARGE_INTEGER newSize;
00433   ULONG          bytesWritten = 0;
00434 
00435   /*
00436    * If the caller is not interested in the number of bytes written,
00437    * we use another buffer to avoid "if" statements in the code.
00438    */
00439   if (pcbWritten == 0)
00440     pcbWritten = &bytesWritten;
00441 
00442   if (cb == 0)
00443   {
00444     return S_OK;
00445   }
00446   else
00447   {
00448     newSize.u.HighPart = 0;
00449     newSize.u.LowPart = ulOffset.u.LowPart + cb;
00450   }
00451 
00452   /*
00453    * Verify if we need to grow the stream
00454    */
00455   if (newSize.u.LowPart > This->byteArraySize.u.LowPart)
00456   {
00457     /* grow stream */
00458     if (HGLOBALLockBytesImpl_SetSize(iface, newSize) == STG_E_MEDIUMFULL)
00459       return STG_E_MEDIUMFULL;
00460   }
00461 
00462   /*
00463    * Lock the buffer in position and copy the data.
00464    */
00465   supportBuffer = GlobalLock(This->supportHandle);
00466 
00467   memcpy((char *) supportBuffer + ulOffset.u.LowPart, pv, cb);
00468 
00469   /*
00470    * Return the number of bytes written.
00471    */
00472   *pcbWritten = cb;
00473 
00474   /*
00475    * Cleanup
00476    */
00477   GlobalUnlock(This->supportHandle);
00478 
00479   return S_OK;
00480 }
00481 
00482 /******************************************************************************
00483  * This method is part of the ILockBytes interface.
00484  *
00485  * See the documentation of ILockBytes for more info.
00486  */
00487 static HRESULT WINAPI HGLOBALLockBytesImpl_Flush(ILockBytes* iface)
00488 {
00489   return S_OK;
00490 }
00491 
00492 /******************************************************************************
00493  * This method is part of the ILockBytes interface.
00494  *
00495  * It will change the size of the byte array.
00496  *
00497  * See the documentation of ILockBytes for more info.
00498  */
00499 static HRESULT WINAPI HGLOBALLockBytesImpl_SetSize(
00500       ILockBytes*     iface,
00501       ULARGE_INTEGER  libNewSize)   /* [in] */
00502 {
00503   HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
00504   HGLOBAL supportHandle;
00505 
00506   /*
00507    * As documented.
00508    */
00509   if (libNewSize.u.HighPart != 0)
00510     return STG_E_INVALIDFUNCTION;
00511 
00512   if (This->byteArraySize.u.LowPart == libNewSize.u.LowPart)
00513     return S_OK;
00514 
00515   /*
00516    * Re allocate the HGlobal to fit the new size of the stream.
00517    */
00518   supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
00519 
00520   if (supportHandle == 0)
00521     return STG_E_MEDIUMFULL;
00522 
00523   This->supportHandle = supportHandle;
00524   This->byteArraySize.u.LowPart = libNewSize.u.LowPart;
00525 
00526   return S_OK;
00527 }
00528 
00529 /******************************************************************************
00530  * This method is part of the ILockBytes interface.
00531  *
00532  * The global memory implementation of ILockBytes does not support locking.
00533  *
00534  * See the documentation of ILockBytes for more info.
00535  */
00536 static HRESULT WINAPI HGLOBALLockBytesImpl_LockRegion(
00537       ILockBytes*    iface,
00538       ULARGE_INTEGER libOffset,   /* [in] */
00539       ULARGE_INTEGER cb,          /* [in] */
00540       DWORD          dwLockType)  /* [in] */
00541 {
00542   return STG_E_INVALIDFUNCTION;
00543 }
00544 
00545 /******************************************************************************
00546  * This method is part of the ILockBytes interface.
00547  *
00548  * The global memory implementation of ILockBytes does not support locking.
00549  *
00550  * See the documentation of ILockBytes for more info.
00551  */
00552 static HRESULT WINAPI HGLOBALLockBytesImpl_UnlockRegion(
00553       ILockBytes*    iface,
00554       ULARGE_INTEGER libOffset,   /* [in] */
00555       ULARGE_INTEGER cb,          /* [in] */
00556       DWORD          dwLockType)  /* [in] */
00557 {
00558   return STG_E_INVALIDFUNCTION;
00559 }
00560 
00561 /******************************************************************************
00562  * This method is part of the ILockBytes interface.
00563  *
00564  * This method returns information about the current
00565  * byte array object.
00566  *
00567  * See the documentation of ILockBytes for more info.
00568  */
00569 static HRESULT WINAPI HGLOBALLockBytesImpl_Stat(
00570       ILockBytes*  iface,
00571       STATSTG*     pstatstg,     /* [out] */
00572       DWORD        grfStatFlag)  /* [in] */
00573 {
00574   HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
00575 
00576   memset(pstatstg, 0, sizeof(STATSTG));
00577 
00578   pstatstg->pwcsName = NULL;
00579   pstatstg->type     = STGTY_LOCKBYTES;
00580   pstatstg->cbSize   = This->byteArraySize;
00581 
00582   return S_OK;
00583 }
00584 
00585 /*
00586  * Virtual function table for the HGLOBALLockBytesImpl class.
00587  */
00588 static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl =
00589 {
00590     HGLOBALLockBytesImpl_QueryInterface,
00591     HGLOBALLockBytesImpl_AddRef,
00592     HGLOBALLockBytesImpl_Release,
00593     HGLOBALLockBytesImpl_ReadAt,
00594     HGLOBALLockBytesImpl_WriteAt,
00595     HGLOBALLockBytesImpl_Flush,
00596     HGLOBALLockBytesImpl_SetSize,
00597     HGLOBALLockBytesImpl_LockRegion,
00598     HGLOBALLockBytesImpl_UnlockRegion,
00599     HGLOBALLockBytesImpl_Stat,
00600 };

Generated on Sun May 27 2012 04:25:38 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.