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