361 lines
9.7 KiB
C++
361 lines
9.7 KiB
C++
// Copyright (c) 1996-2000 Microsoft Corporation
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// MEMCHK.CPP
|
|
//
|
|
// Simple new/delete counting error checking library
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
#include "oleacc_p.h"
|
|
#include "default.h"
|
|
#include "w95trace.h"
|
|
#include "memchk.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
struct MemInfo
|
|
{
|
|
LONG m_NumAlloc;
|
|
LONG m_NumFree;
|
|
};
|
|
|
|
// Two MemInfo structures - one for allocations through new/delete,
|
|
// one for allocations through SharedAlloc/SharedFree
|
|
MemInfo g_MemInfo;
|
|
MemInfo g_SharedMemInfo;
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
#ifndef _DEBUG
|
|
|
|
// Non-_DEBUG new/delete call-through to LocalAlloc/Free...
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// new()
|
|
//
|
|
// We implement this ourself to avoid pulling in the C++ runtime.
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
|
|
void * __cdecl operator new(size_t nSize)
|
|
{
|
|
// Zero init just to save some headaches
|
|
return (void *)LocalAlloc(LPTR, nSize);
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// delete()
|
|
//
|
|
// We implement this ourself to avoid pulling in the C++ runtime.
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
void __cdecl operator delete(void *pv)
|
|
{
|
|
LocalFree((HLOCAL)pv);
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// SharedAlloc()
|
|
//
|
|
// This allocates out of the shared heap on Win '95. On NT, we need to
|
|
// use VirtualAllocEx to allocate memory in the other process. The caller
|
|
// of SharedAlloc will need to then use ReadProcessMemory to read the data
|
|
// from the VirtualAlloc'ed memory. What I am going to do is create 2 new
|
|
// functions - SharedRead and SharedWrite, that will read and write shared
|
|
// memory. On Win95, they will just use CopyMemory, but on NT they will use
|
|
// ReadProcessMemory and WriteProcessMemory.
|
|
//
|
|
// Parameters:
|
|
// UINT cbSize Size of the memory block required
|
|
// HWND hwnd Window handle in the process to allocate
|
|
// the shared memory in.
|
|
// HANDLE* pProcHandle Pointer to a handle that has the process
|
|
// handle filled in on return. This must be saved
|
|
// for use in calls to SharedRead, SharedWrite,
|
|
// and SharedFree.
|
|
//
|
|
// Returns:
|
|
// Pointer to the allocated memory, or NULL if it fails. Access to the
|
|
// memory must be done using SharedRead and SharedWrite. On success,
|
|
// pProcHandle is filled in as well.
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
LPVOID SharedAlloc(UINT cbSize,HWND hwnd,HANDLE *pProcessHandle)
|
|
{
|
|
#ifndef NTONLYBUILD
|
|
if (fWindows95)
|
|
return(HeapAlloc(hheapShared, HEAP_ZERO_MEMORY, cbSize));
|
|
else
|
|
#endif // NTONLYBUILD
|
|
{
|
|
DWORD dwProcessId;
|
|
if( ! GetWindowThreadProcessId( hwnd, & dwProcessId ) )
|
|
return NULL;
|
|
|
|
HANDLE hProcess = OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
|
|
FALSE,dwProcessId );
|
|
if( ! hProcess )
|
|
return NULL;
|
|
|
|
LPVOID pv = MyVirtualAllocEx( hProcess, NULL, cbSize, MEM_COMMIT, PAGE_READWRITE );
|
|
if( ! pv )
|
|
{
|
|
CloseHandle( hProcess );
|
|
return NULL;
|
|
}
|
|
|
|
if( pProcessHandle )
|
|
*pProcessHandle = hProcess;
|
|
|
|
return pv;
|
|
}
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// SharedFree()
|
|
//
|
|
// This frees shared memory.
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
VOID SharedFree(LPVOID lpv,HANDLE hProcess)
|
|
{
|
|
#ifndef NTONLYBUILD
|
|
if (fWindows95)
|
|
HeapFree(hheapShared, 0, lpv);
|
|
else
|
|
#endif // NTONLYBUILD
|
|
{
|
|
MyVirtualFreeEx(hProcess,lpv,0,MEM_RELEASE);
|
|
CloseHandle (hProcess);
|
|
}
|
|
}
|
|
|
|
|
|
// 'Empty' functions to keep compiler/linker happy in case client
|
|
// calls these in non _DEBUG code...
|
|
// --------------------------------------------------------------------------
|
|
// --------------------------------------------------------------------------
|
|
void InitMemChk()
|
|
{
|
|
// Do nothing
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// --------------------------------------------------------------------------
|
|
void UninitMemChk()
|
|
{
|
|
// Do nothing
|
|
}
|
|
|
|
|
|
|
|
#else // _DEBUG #############################################################
|
|
|
|
// --------------------------------------------------------------------------
|
|
// DEBUG new - increments new count, calls through to LocalAlloc...
|
|
// --------------------------------------------------------------------------
|
|
void * __cdecl operator new(unsigned int nSize)
|
|
{
|
|
// Zero init just to save some headaches
|
|
void * pv = (void *)LocalAlloc(LPTR, nSize);
|
|
|
|
if( ! pv )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// Update statistics...
|
|
InterlockedIncrement( & g_MemInfo.m_NumAlloc );
|
|
|
|
// return pointer to alloc'd space...
|
|
return pv;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
// DEBUG delete - increments delete count, calls through to LocalFree...
|
|
// --------------------------------------------------------------------------
|
|
void __cdecl operator delete(void *pv)
|
|
{
|
|
// C++ allows 'delete NULL'...
|
|
if( pv == NULL )
|
|
return;
|
|
|
|
// Update statistics...
|
|
InterlockedIncrement( & g_MemInfo.m_NumFree );
|
|
|
|
LocalFree((HLOCAL)pv);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// DEBUG SharedAlloc()
|
|
//
|
|
// Does alloc, updates count.
|
|
// --------------------------------------------------------------------------
|
|
LPVOID SharedAlloc(UINT cbSize,HWND hwnd,HANDLE *pProcessHandle)
|
|
{
|
|
#ifndef NTONLYBUILD
|
|
if (fWindows95)
|
|
{
|
|
// Update statistics...
|
|
InterlockedIncrement( & g_SharedMemInfo.m_NumAlloc );
|
|
|
|
return(HeapAlloc(hheapShared, HEAP_ZERO_MEMORY, cbSize));
|
|
}
|
|
else
|
|
#endif // NTONLYBUILD
|
|
{
|
|
DWORD dwProcessId;
|
|
if( ! GetWindowThreadProcessId( hwnd, & dwProcessId ) )
|
|
return NULL;
|
|
|
|
HANDLE hProcess = OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
|
|
FALSE,dwProcessId );
|
|
if( ! hProcess )
|
|
return NULL;
|
|
|
|
LPVOID pv = MyVirtualAllocEx( hProcess, NULL, cbSize, MEM_COMMIT, PAGE_READWRITE );
|
|
if( ! pv )
|
|
{
|
|
CloseHandle( hProcess );
|
|
return NULL;
|
|
}
|
|
|
|
// Update statistics...
|
|
InterlockedIncrement( & g_SharedMemInfo.m_NumAlloc );
|
|
|
|
if( pProcessHandle )
|
|
*pProcessHandle = hProcess;
|
|
|
|
return pv;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// DEBUG SharedFree()
|
|
//
|
|
// frees shared memory, updates free count.
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
VOID SharedFree(LPVOID lpv,HANDLE hProcess)
|
|
{
|
|
// Update statistics...
|
|
InterlockedIncrement( & g_SharedMemInfo.m_NumFree );
|
|
|
|
#ifndef NTONLYBUILD
|
|
if (fWindows95)
|
|
HeapFree(hheapShared, 0, lpv);
|
|
else
|
|
#endif // NTONLYBUILD
|
|
{
|
|
MyVirtualFreeEx(hProcess,lpv,0,MEM_RELEASE);
|
|
CloseHandle (hProcess);
|
|
}
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
// InitMemChk - sets alloc/free counts to zero.
|
|
// --------------------------------------------------------------------------
|
|
void InitMemChk()
|
|
{
|
|
g_MemInfo.m_NumAlloc = 0;
|
|
g_MemInfo.m_NumFree = 0;
|
|
|
|
g_SharedMemInfo.m_NumAlloc = 0;
|
|
g_SharedMemInfo.m_NumFree = 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// UninitMemChk - outputs stats including number of unfree'd objects...
|
|
//
|
|
// Note that Shared memory is often allocated from one process and free'd
|
|
// from another, so when a process detatches the numbers may not match up.
|
|
// At some point in time it might be more useful to keep this as a global
|
|
// across all instances of the DLL.
|
|
// --------------------------------------------------------------------------
|
|
void UninitMemChk()
|
|
{
|
|
DBPRINTF( TEXT("Total objects: %d, unfreed: %d\n"),
|
|
g_MemInfo.m_NumAlloc,
|
|
g_MemInfo.m_NumAlloc - g_MemInfo.m_NumFree );
|
|
|
|
DBPRINTF( TEXT("Total Shared objects: %d, unfreed: %d\n"),
|
|
g_SharedMemInfo.m_NumAlloc,
|
|
g_SharedMemInfo.m_NumAlloc - g_SharedMemInfo.m_NumFree );
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// SharedRead
|
|
//
|
|
// This reads shared memory.
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
|
|
BOOL SharedRead(LPVOID lpvSharedSource,LPVOID lpvDest,DWORD cbSize,HANDLE hProcess)
|
|
{
|
|
#ifdef _X86_
|
|
if (fWindows95)
|
|
{
|
|
CopyMemory (lpvDest,lpvSharedSource,cbSize);
|
|
return TRUE;
|
|
}
|
|
else
|
|
#endif // _X86_
|
|
{
|
|
return (ReadProcessMemory (hProcess,lpvSharedSource,lpvDest,cbSize,NULL));
|
|
}
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// SharedWrite
|
|
//
|
|
// This writes into shared memory.
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
|
|
BOOL SharedWrite(LPVOID lpvSource,LPVOID lpvSharedDest,DWORD cbSize,HANDLE hProcess)
|
|
{
|
|
#ifdef _X86_
|
|
if (fWindows95)
|
|
{
|
|
CopyMemory(lpvSharedDest,lpvSource,cbSize);
|
|
return TRUE;
|
|
}
|
|
else
|
|
#endif // _X86_
|
|
{
|
|
return (WriteProcessMemory (hProcess,lpvSharedDest,lpvSource,cbSize,NULL));
|
|
}
|
|
}
|