Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmemlockbytes.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
1.7.6.1
|