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

ifs.c
Go to the documentation of this file.
00001 /*
00002  *  basic interfaces
00003  *
00004  *  Copyright 1997  Marcus Meissner
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include "config.h"
00022 
00023 #include <ctype.h>
00024 #include <stdarg.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <assert.h>
00028 
00029 #define COBJMACROS
00030 
00031 #include "windef.h"
00032 #include "winbase.h"
00033 #include "winuser.h"
00034 #include "ole2.h"
00035 #include "winerror.h"
00036 
00037 #include "wine/debug.h"
00038 
00039 WINE_DEFAULT_DEBUG_CHANNEL(olemalloc);
00040 
00041 /******************************************************************************
00042  *  IMalloc32 implementation
00043  *
00044  * NOTES
00045  *  For supporting CoRegisterMallocSpy the IMalloc implementation must know if
00046  *  a given memory block was allocated with a spy active.
00047  *
00048  *****************************************************************************/
00049 /* set the vtable later */
00050 static const IMallocVtbl VT_IMalloc32;
00051 
00052 typedef struct {
00053         IMalloc IMalloc_iface;
00054         DWORD dummy;                /* nothing, we are static */
00055     IMallocSpy * pSpy;          /* the spy when active */
00056     DWORD SpyedAllocationsLeft; /* number of spyed allocations left */
00057     BOOL SpyReleasePending;     /* CoRevokeMallocSpy called with spyed allocations left*/
00058         LPVOID * SpyedBlocks;       /* root of the table */
00059         DWORD SpyedBlockTableLength;/* size of the table*/
00060 } _Malloc32;
00061 
00062 /* this is the static object instance */
00063 static _Malloc32 Malloc32 = {{&VT_IMalloc32}, 0, NULL, 0, 0, NULL, 0};
00064 
00065 /* with a spy active all calls from pre to post methods are threadsave */
00066 static CRITICAL_SECTION IMalloc32_SpyCS;
00067 static CRITICAL_SECTION_DEBUG critsect_debug =
00068 {
00069     0, 0, &IMalloc32_SpyCS,
00070     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
00071       0, 0, { (DWORD_PTR)(__FILE__ ": IMalloc32_SpyCS") }
00072 };
00073 static CRITICAL_SECTION IMalloc32_SpyCS = { &critsect_debug, -1, 0, 0, 0, 0 };
00074 
00075 /* resize the old table */
00076 static int SetSpyedBlockTableLength ( DWORD NewLength )
00077 {
00078     LPVOID *NewSpyedBlocks;
00079 
00080     if (!Malloc32.SpyedBlocks) NewSpyedBlocks = LocalAlloc(LMEM_ZEROINIT, NewLength * sizeof(PVOID));
00081     else NewSpyedBlocks = LocalReAlloc(Malloc32.SpyedBlocks, NewLength * sizeof(PVOID), LMEM_ZEROINIT);
00082     if (NewSpyedBlocks) {
00083         Malloc32.SpyedBlocks = NewSpyedBlocks;
00084         Malloc32.SpyedBlockTableLength = NewLength;
00085     }
00086 
00087     return NewSpyedBlocks != NULL;
00088 }
00089 
00090 /* add a location to the table */
00091 static int AddMemoryLocation(LPVOID * pMem)
00092 {
00093         LPVOID * Current;
00094 
00095     /* allocate the table if not already allocated */
00096     if (!Malloc32.SpyedBlockTableLength) {
00097             if (!SetSpyedBlockTableLength(0x1000)) return 0;
00098     }
00099 
00100     /* find a free location */
00101     Current = Malloc32.SpyedBlocks;
00102     while (*Current) {
00103             Current++;
00104         if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength) {
00105             /* no more space in table, grow it */
00106                 DWORD old_length = Malloc32.SpyedBlockTableLength;
00107             if (!SetSpyedBlockTableLength( Malloc32.SpyedBlockTableLength + 0x1000 )) return 0;
00108                 Current = Malloc32.SpyedBlocks + old_length;
00109         }
00110     };
00111 
00112     /* put the location in our table */
00113     *Current = pMem;
00114         Malloc32.SpyedAllocationsLeft++;
00115     /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
00116         return 1;
00117 }
00118 
00119 static int RemoveMemoryLocation(LPCVOID pMem)
00120 {
00121         LPVOID * Current;
00122 
00123     /* allocate the table if not already allocated */
00124     if (!Malloc32.SpyedBlockTableLength) {
00125             if (!SetSpyedBlockTableLength(0x1000)) return 0;
00126     }
00127 
00128     Current = Malloc32.SpyedBlocks;
00129 
00130     /* find the location */
00131     while (*Current != pMem) {
00132             Current++;
00133         if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength)  return 0;      /* not found  */
00134     }
00135 
00136     /* location found */
00137         Malloc32.SpyedAllocationsLeft--;
00138     /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
00139     *Current = NULL;
00140     return 1;
00141 }
00142 
00143 /******************************************************************************
00144  *  IMalloc32_QueryInterface    [VTABLE]
00145  */
00146 static HRESULT WINAPI IMalloc_fnQueryInterface(LPMALLOC iface,REFIID refiid,LPVOID *obj) {
00147 
00148     TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
00149 
00150     if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
00151         *obj = &Malloc32;
00152         return S_OK;
00153     }
00154     return E_NOINTERFACE;
00155 }
00156 
00157 /******************************************************************************
00158  *  IMalloc32_AddRefRelease     [VTABLE]
00159  */
00160 static ULONG WINAPI IMalloc_fnAddRefRelease (LPMALLOC iface) {
00161     return 1;
00162 }
00163 
00164 /******************************************************************************
00165  *  IMalloc32_Alloc         [VTABLE]
00166  */
00167 static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface, DWORD cb) {
00168 
00169     LPVOID addr;
00170 
00171     TRACE("(%d)\n",cb);
00172 
00173     if(Malloc32.pSpy) {
00174         DWORD preAllocResult;
00175         
00176         EnterCriticalSection(&IMalloc32_SpyCS);
00177         preAllocResult = IMallocSpy_PreAlloc(Malloc32.pSpy, cb);
00178         if ((cb != 0) && (preAllocResult == 0)) {
00179         /* PreAlloc can force Alloc to fail, but not if cb == 0 */
00180         TRACE("returning null\n");
00181         LeaveCriticalSection(&IMalloc32_SpyCS);
00182         return NULL;
00183         }
00184     }
00185     
00186     addr = HeapAlloc(GetProcessHeap(),0,cb);
00187 
00188     if(Malloc32.pSpy) {
00189         addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
00190         if (addr) AddMemoryLocation(addr);
00191         LeaveCriticalSection(&IMalloc32_SpyCS);
00192     }
00193 
00194     TRACE("--(%p)\n",addr);
00195     return addr;
00196 }
00197 
00198 /******************************************************************************
00199  * IMalloc32_Realloc [VTABLE]
00200  */
00201 static LPVOID WINAPI IMalloc_fnRealloc(LPMALLOC iface,LPVOID pv,DWORD cb) {
00202 
00203     LPVOID pNewMemory;
00204 
00205     TRACE("(%p,%d)\n",pv,cb);
00206 
00207     if(Malloc32.pSpy) {
00208         LPVOID pRealMemory;
00209         BOOL fSpyed;
00210 
00211         EnterCriticalSection(&IMalloc32_SpyCS);
00212             fSpyed = RemoveMemoryLocation(pv);
00213             cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);
00214 
00215         /* check if can release the spy */
00216         if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
00217             IMallocSpy_Release(Malloc32.pSpy);
00218         Malloc32.SpyReleasePending = FALSE;
00219         Malloc32.pSpy = NULL;
00220         }
00221 
00222         if (0==cb) {
00223             /* PreRealloc can force Realloc to fail */
00224                 LeaveCriticalSection(&IMalloc32_SpyCS);
00225         return NULL;
00226         }
00227         pv = pRealMemory;
00228     }
00229 
00230         if (!pv) pNewMemory = HeapAlloc(GetProcessHeap(),0,cb);
00231     else if (cb) pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
00232     else {
00233         HeapFree(GetProcessHeap(),0,pv);
00234         pNewMemory = NULL;
00235     }
00236 
00237     if(Malloc32.pSpy) {
00238         pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
00239         if (pNewMemory) AddMemoryLocation(pNewMemory);
00240             LeaveCriticalSection(&IMalloc32_SpyCS);
00241     }
00242 
00243     TRACE("--(%p)\n",pNewMemory);
00244     return pNewMemory;
00245 }
00246 
00247 /******************************************************************************
00248  * IMalloc32_Free [VTABLE]
00249  */
00250 static VOID WINAPI IMalloc_fnFree(LPMALLOC iface,LPVOID pv) {
00251 
00252     BOOL fSpyed = 0;
00253 
00254     TRACE("(%p)\n",pv);
00255 
00256     if(Malloc32.pSpy) {
00257             EnterCriticalSection(&IMalloc32_SpyCS);
00258             fSpyed = RemoveMemoryLocation(pv);
00259         pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
00260     }
00261 
00262     HeapFree(GetProcessHeap(),0,pv);
00263 
00264     if(Malloc32.pSpy) {
00265         IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);
00266 
00267         /* check if can release the spy */
00268         if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
00269             IMallocSpy_Release(Malloc32.pSpy);
00270         Malloc32.SpyReleasePending = FALSE;
00271         Malloc32.pSpy = NULL;
00272         }
00273 
00274         LeaveCriticalSection(&IMalloc32_SpyCS);
00275         }
00276 }
00277 
00278 /******************************************************************************
00279  * IMalloc32_GetSize [VTABLE]
00280  *
00281  * NOTES
00282  *  FIXME returns:
00283  *      win95:  size allocated (4 byte boundarys)
00284  *      win2k:  size originally requested !!! (allocated on 8 byte boundarys)
00285  */
00286 static DWORD WINAPI IMalloc_fnGetSize(LPMALLOC iface,LPVOID pv) {
00287 
00288     DWORD cb;
00289     BOOL fSpyed = 0;
00290 
00291     TRACE("(%p)\n",pv);
00292 
00293     if(Malloc32.pSpy) {
00294             EnterCriticalSection(&IMalloc32_SpyCS);
00295         pv = IMallocSpy_PreGetSize(Malloc32.pSpy, pv, fSpyed);
00296     }
00297 
00298     cb = HeapSize(GetProcessHeap(),0,pv);
00299 
00300     if(Malloc32.pSpy) {
00301         cb = IMallocSpy_PostGetSize(Malloc32.pSpy, cb, fSpyed);
00302         LeaveCriticalSection(&IMalloc32_SpyCS);
00303     }
00304 
00305     return cb;
00306 }
00307 
00308 /******************************************************************************
00309  * IMalloc32_DidAlloc [VTABLE]
00310  */
00311 static INT WINAPI IMalloc_fnDidAlloc(LPMALLOC iface,LPVOID pv) {
00312 
00313     BOOL fSpyed = 0;
00314     int didAlloc;
00315 
00316     TRACE("(%p)\n",pv);
00317 
00318     if(Malloc32.pSpy) {
00319             EnterCriticalSection(&IMalloc32_SpyCS);
00320         pv = IMallocSpy_PreDidAlloc(Malloc32.pSpy, pv, fSpyed);
00321     }
00322 
00323     didAlloc = -1;
00324 
00325     if(Malloc32.pSpy) {
00326         didAlloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, pv, fSpyed, didAlloc);
00327             LeaveCriticalSection(&IMalloc32_SpyCS);
00328     }
00329     return didAlloc;
00330 }
00331 
00332 /******************************************************************************
00333  * IMalloc32_HeapMinimize [VTABLE]
00334  */
00335 static VOID WINAPI IMalloc_fnHeapMinimize(LPMALLOC iface) {
00336     TRACE("()\n");
00337 
00338     if(Malloc32.pSpy) {
00339             EnterCriticalSection(&IMalloc32_SpyCS);
00340         IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
00341     }
00342 
00343     if(Malloc32.pSpy) {
00344         IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
00345             LeaveCriticalSection(&IMalloc32_SpyCS);
00346     }
00347 }
00348 
00349 static const IMallocVtbl VT_IMalloc32 =
00350 {
00351     IMalloc_fnQueryInterface,
00352     IMalloc_fnAddRefRelease,
00353     IMalloc_fnAddRefRelease,
00354     IMalloc_fnAlloc,
00355     IMalloc_fnRealloc,
00356     IMalloc_fnFree,
00357     IMalloc_fnGetSize,
00358     IMalloc_fnDidAlloc,
00359     IMalloc_fnHeapMinimize
00360 };
00361 
00362 /******************************************************************************
00363  *      CoGetMalloc [OLE32.@]
00364  *
00365  * Retrieves the current IMalloc interface for the process.
00366  *
00367  * PARAMS
00368  *  dwMemContext [I]
00369  *  lpMalloc     [O] Address where memory allocator object will be stored.
00370  *
00371  * RETURNS
00372  *  Success: S_OK.
00373  *  Failure: HRESULT code.
00374  */
00375 HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc)
00376 {
00377         *lpMalloc = &Malloc32.IMalloc_iface;
00378         return S_OK;
00379 }
00380 
00381 /***********************************************************************
00382  *           CoTaskMemAlloc     [OLE32.@]
00383  *
00384  * Allocates memory using the current process memory allocator.
00385  *
00386  * PARAMS
00387  *  size [I] Size of the memory block to allocate.
00388  *
00389  * RETURNS
00390  *  Success: Pointer to newly allocated memory block.
00391  *  Failure: NULL.
00392  */
00393 LPVOID WINAPI CoTaskMemAlloc(ULONG size)
00394 {
00395         return IMalloc_Alloc(&Malloc32.IMalloc_iface,size);
00396 }
00397 
00398 /***********************************************************************
00399  *           CoTaskMemFree      [OLE32.@]
00400  *
00401  * Frees memory allocated from the current process memory allocator.
00402  *
00403  * PARAMS
00404  *  ptr [I] Memory block to free.
00405  *
00406  * RETURNS
00407  *  Nothing.
00408  */
00409 VOID WINAPI CoTaskMemFree(LPVOID ptr)
00410 {
00411         IMalloc_Free(&Malloc32.IMalloc_iface, ptr);
00412 }
00413 
00414 /***********************************************************************
00415  *           CoTaskMemRealloc   [OLE32.@]
00416  *
00417  * Allocates memory using the current process memory allocator.
00418  *
00419  * PARAMS
00420  *  pvOld [I] Pointer to old memory block.
00421  *  size  [I] Size of the new memory block.
00422  *
00423  * RETURNS
00424  *  Success: Pointer to newly allocated memory block.
00425  *  Failure: NULL.
00426  */
00427 LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size)
00428 {
00429         return IMalloc_Realloc(&Malloc32.IMalloc_iface, pvOld, size);
00430 }
00431 
00432 /***********************************************************************
00433  *           CoRegisterMallocSpy        [OLE32.@]
00434  *
00435  * Registers an object that receives notifications on memory allocations and
00436  * frees.
00437  *
00438  * PARAMS
00439  *  pMallocSpy [I] New spy object.
00440  *
00441  * RETURNS
00442  *  Success: S_OK.
00443  *  Failure: HRESULT code.
00444  *
00445  * NOTES
00446  *  if a mallocspy is already registered, we can't do it again since
00447  *  only the spy knows, how to free a memory block
00448  */
00449 HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
00450 {
00451     IMallocSpy* pSpy;
00452         HRESULT hres = E_INVALIDARG;
00453 
00454     TRACE("\n");
00455 
00456     if(Malloc32.pSpy) return CO_E_OBJISREG;
00457 
00458         EnterCriticalSection(&IMalloc32_SpyCS);
00459 
00460     if (SUCCEEDED(IUnknown_QueryInterface(pMallocSpy, &IID_IMallocSpy, (LPVOID*)&pSpy))) {
00461         Malloc32.pSpy = pSpy;
00462         hres = S_OK;
00463     }
00464 
00465     LeaveCriticalSection(&IMalloc32_SpyCS);
00466 
00467     return hres;
00468 }
00469 
00470 /***********************************************************************
00471  *           CoRevokeMallocSpy  [OLE32.@]
00472  *
00473  * Revokes a previously registered object that receives notifications on memory
00474  * allocations and frees.
00475  *
00476  * PARAMS
00477  *  pMallocSpy [I] New spy object.
00478  *
00479  * RETURNS
00480  *  Success: S_OK.
00481  *  Failure: HRESULT code.
00482  *
00483  * NOTES
00484  *  we can't revoke a malloc spy as long as memory blocks allocated with
00485  *  the spy are active since only the spy knows how to free them
00486  */
00487 HRESULT WINAPI CoRevokeMallocSpy(void)
00488 {
00489     HRESULT hres = S_OK;
00490     TRACE("\n");
00491 
00492         EnterCriticalSection(&IMalloc32_SpyCS);
00493 
00494     if (Malloc32.SpyedAllocationsLeft) {
00495             TRACE("SpyReleasePending with %u allocations left\n", Malloc32.SpyedAllocationsLeft);
00496         Malloc32.SpyReleasePending = TRUE;
00497         hres = E_ACCESSDENIED;
00498     } else {
00499         IMallocSpy_Release(Malloc32.pSpy);
00500         Malloc32.pSpy = NULL;
00501         }
00502     LeaveCriticalSection(&IMalloc32_SpyCS);
00503 
00504     return hres;
00505 }
00506 
00507 /******************************************************************************
00508  *      IsValidInterface    [OLE32.@]
00509  *
00510  * Determines whether a pointer is a valid interface.
00511  *
00512  * PARAMS
00513  *  punk [I] Interface to be tested.
00514  *
00515  * RETURNS
00516  *  TRUE, if the passed pointer is a valid interface, or FALSE otherwise.
00517  */
00518 BOOL WINAPI IsValidInterface(LPUNKNOWN punk)
00519 {
00520     return !(
00521         IsBadReadPtr(punk,4)                    ||
00522         IsBadReadPtr(punk->lpVtbl,4)                ||
00523         IsBadReadPtr(punk->lpVtbl->QueryInterface,9)    ||
00524         IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)
00525     );
00526 }

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.