///////////////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved. // // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation. // // Other brand and product names used herein are trademarks of their respective owners. // // The entire program and user interface including the structure, sequence, selection, // and arrangement of the dialog, the exclusively "yes" and "no" choices represented // by "1" and "2," and each dialog message are protected by copyrights registered in // the United States and by international treaties. // // Protected by one or more of the following United States patents: 5,070,526, 5,488,650, // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054. // // Active Voice Corporation // Seattle, Washington // USA // ///////////////////////////////////////////////////////////////////////////////////////// //// // mem.c - memory functions //// #include "winlocal.h" #include #include "mem.h" #include "sys.h" #include "trace.h" //// // private definitions //// #ifndef NOTRACE // mem control struct // typedef struct MEM { DWORD dwVersion; HINSTANCE hInst; HTASK hTask; long nBlocks; long sizBlocks; } MEM, FAR *LPMEM; // shared mem engine handle // static LPMEM lpMemShare = NULL; static int cShareUsage = 0; // helper functions // static LPMEM MemGetPtr(HMEM hMem); static HMEM MemGetHandle(LPMEM lpMem); //// // public functions //// // MemInit - initialize mem engine // (i) must be MEM_VERSION // (i) instance handle of calling module // return handle (NULL if error) // HMEM DLLEXPORT WINAPI MemInit(DWORD dwVersion, HINSTANCE hInst) { BOOL fSuccess = TRUE; LPMEM lpMem = NULL; BOOL fShare = TRUE; if (dwVersion != MEM_VERSION) fSuccess = FALSE; else if (hInst == NULL) fSuccess = FALSE; // if a shared mem engine already exists, // use it rather than create another one // else if (fShare && cShareUsage > 0 && lpMemShare != NULL) lpMem = lpMemShare; // memory is allocated such that the client app owns it // unless we are sharing the mem handle among several apps // #ifdef _WIN32 else if ((lpMem = (LPMEM) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEM))) == NULL) #else else if ((lpMem = (LPMEM) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(MEM))) == NULL) #endif fSuccess = FALSE; else { lpMem->dwVersion = dwVersion; lpMem->hInst = hInst; lpMem->hTask = GetCurrentTask(); lpMem->nBlocks = 0; lpMem->sizBlocks = 0; } if (!fSuccess) { MemTerm(MemGetHandle(lpMem)); lpMem = NULL; } // keep track of total modules sharing a mem engine handle // if (fSuccess && fShare) { if (++cShareUsage == 1) lpMemShare = lpMem; } return fSuccess ? MemGetHandle(lpMem) : NULL; } // MemTerm - shut down mem engine // (i) handle returned from MemInit or NULL // return 0 if success // int DLLEXPORT WINAPI MemTerm(HMEM hMem) { BOOL fSuccess = TRUE; LPMEM lpMem; if ((lpMem = MemGetPtr(hMem)) == NULL) fSuccess = FALSE; // only shut down mem engine if handle // is not shared (or is no longer being shared) // else if (lpMem != lpMemShare || --cShareUsage <= 0) { // shared mem engine handle no longer valid // if (cShareUsage <= 0) lpMemShare = NULL; #ifdef _WIN32 if (!HeapFree(GetProcessHeap(), 0, lpMem)) #else if (GlobalFreePtr(lpMem) != 0) #endif fSuccess = FALSE; } return fSuccess ? 0 : -1; } // MemAlloc - allocate memory block // (i) handle returned from MemInit or NULL // (i) size of block, in bytes // (i) control flags // MEM_NOZEROINIT do not initialize block // return pointer to block, NULL if error // LPVOID DLLEXPORT WINAPI MemAllocEx(HMEM hMem, long sizBlock, DWORD dwFlags, LPCTSTR lpszFileName, unsigned uLineNumber) { BOOL fSuccess = TRUE; LPMEM lpMem; LPVOID lpBlock; #ifdef _WIN32 if ((lpMem = MemGetPtr(hMem)) == NULL) fSuccess = FALSE; else if ((lpBlock = HeapAlloc(GetProcessHeap(), (dwFlags & MEM_NOZEROINIT) ? 0 : HEAP_ZERO_MEMORY, sizBlock)) == NULL) fSuccess = FALSE; #else UINT wFlags = 0; wFlags |= GMEM_MOVEABLE; if (!(dwFlags & MEM_NOZEROINIT)) wFlags |= GMEM_ZEROINIT; if ((lpMem = MemGetPtr(hMem)) == NULL) fSuccess = FALSE; else if ((lpBlock = GlobalAllocPtr(wFlags, sizBlock)) == NULL) fSuccess = FALSE; #endif // keep track of total blocks allocated, total size of all blocks // else if (++lpMem->nBlocks, lpMem->sizBlocks += sizBlock, FALSE) ; else if (TraceGetLevel(NULL) >= 9) { TracePrintf_7(NULL, 9, TEXT("%s(%u) : %08X = MemAllocEx(%p, %08X) (%ld, %ld)\n"), (LPTSTR) lpszFileName, (unsigned) uLineNumber, lpBlock, (long) sizBlock, (unsigned long) dwFlags, lpMem->nBlocks, lpMem->sizBlocks); } return fSuccess ? lpBlock : NULL; } // MemReAlloc - reallocate memory block // (i) handle returned from MemInit or NULL // (i) pointer returned from MemAlloc // (i) new size of block, in bytes // (i) control flags // MEM_NOZEROINIT do not initialize block // return pointer to block, NULL if error // LPVOID DLLEXPORT WINAPI MemReAllocEx(HMEM hMem, LPVOID lpBlock, long sizBlock, DWORD dwFlags, LPCTSTR lpszFileName, unsigned uLineNumber) { BOOL fSuccess = TRUE; LPMEM lpMem; LPVOID lpBlockOld = lpBlock; long sizBlockOld; #ifdef _WIN32 if ((lpMem = MemGetPtr(hMem)) == NULL) fSuccess = FALSE; else if ((sizBlockOld = MemSize(hMem, lpBlock)) <= 0) fSuccess = FALSE; else if ((lpBlock = HeapReAlloc(GetProcessHeap(), (dwFlags & MEM_NOZEROINIT) ? 0 : HEAP_ZERO_MEMORY, lpBlockOld, sizBlock)) == NULL) fSuccess = FALSE; #else UINT wFlags = 0; wFlags |= GMEM_MOVEABLE; if (!(dwFlags & MEM_NOZEROINIT)) wFlags |= GMEM_ZEROINIT; if ((lpMem = MemGetPtr(hMem)) == NULL) fSuccess = FALSE; else if ((sizBlockOld = MemSize(hMem, lpBlock)) <= 0) fSuccess = FALSE; else if ((lpBlock = GlobalReAllocPtr(lpBlockOld, sizBlock, wFlags)) == NULL) fSuccess = FALSE; #endif // keep track of total blocks allocated, total size of all blocks // else if (lpMem->sizBlocks -= sizBlockOld, lpMem->sizBlocks += sizBlock, FALSE) ; else if (TraceGetLevel(NULL) >= 9) { TracePrintf_8(NULL, 9, TEXT("%s(%u) : %p = MemReAllocEx(%p, %ld, %08X) (%ld, %ld)\n"), (LPTSTR) lpszFileName, (unsigned) uLineNumber, lpBlock, lpBlockOld, (long) sizBlock, (unsigned long) dwFlags, lpMem->nBlocks, lpMem->sizBlocks); } return fSuccess ? lpBlock : NULL; } // MemFree - free memory block // (i) handle returned from MemInit or NULL // (i) pointer returned from MemAlloc // return NULL if success, lpBlock if error // // NOTE: the return value of this function is designed to allow the // user of this function to easily assign NULL to a freed pointer, // as the following example demonstrates: // // if ((p = MemFree(hMem, p)) != NULL) // ; // error // LPVOID DLLEXPORT WINAPI MemFreeEx(HMEM hMem, LPVOID lpBlock, LPCTSTR lpszFileName, unsigned uLineNumber) { BOOL fSuccess = TRUE; LPMEM lpMem; long sizBlock; if ((lpMem = MemGetPtr(hMem)) == NULL) fSuccess = FALSE; else if ((sizBlock = MemSize(hMem, lpBlock)) <= 0) fSuccess = FALSE; #ifdef _WIN32 else if (!HeapFree(GetProcessHeap(), 0, lpBlock)) #else else if (GlobalFreePtr(lpBlock) != 0) #endif fSuccess = FALSE; // keep track of total blocks allocated, total size of all blocks // else if (--lpMem->nBlocks, lpMem->sizBlocks -= sizBlock, FALSE) ; else if (TraceGetLevel(NULL) >= 9) { TracePrintf_5(NULL, 9, TEXT("%s(%u) : MemFreeEx(%p) (%ld, %ld)\n"), (LPTSTR) lpszFileName, (unsigned) uLineNumber, lpBlock, lpMem->nBlocks, lpMem->sizBlocks); } return fSuccess ? NULL : lpBlock; } // MemSize - get size of memory block // (i) handle returned from MemInit or NULL // (i) pointer returned from MemAlloc // return size of block if success, 0 if error // long DLLEXPORT WINAPI MemSize(HMEM hMem, LPVOID lpBlock) { BOOL fSuccess = TRUE; LPMEM lpMem; long sizBlock; if ((lpMem = MemGetPtr(hMem)) == NULL) fSuccess = FALSE; #ifdef _WIN32 else if ((sizBlock = (long) HeapSize(GetProcessHeap(), 0, lpBlock)) <= 0) #else else if ((sizBlock = (long) GlobalSize(GlobalPtrHandle(lpBlock))) <= 0) #endif fSuccess = FALSE; return fSuccess ? sizBlock : 0; } #endif // #ifndef NOTRACE #ifndef _WIN32 static void hmemmove(void _huge *d, const void _huge *s, long len); #ifndef SIZE_T_MAX #define SIZE_T_MAX (~((size_t) 0)) #endif void _huge* DLLEXPORT MemCCpyEx(void _huge* dest, const void _huge* src, int c, long count) { if (count <= SIZE_T_MAX) return _fmemccpy(dest, src, c, (size_t) count); else return NULL; //$FIXUP - need to handle large count } void _huge* DLLEXPORT MemChrEx(void _huge* buf, int c, long count) { if (count <= SIZE_T_MAX) return _fmemchr(buf, c, (size_t) count); else return NULL; //$FIXUP - need to handle large count } int DLLEXPORT MemCmpEx(const void _huge* buf1, void _huge* buf2, long count) { if (count <= SIZE_T_MAX) return _fmemcmp(buf1, buf2, (size_t) count); else return NULL; //$FIXUP - need to handle large count } void _huge* DLLEXPORT MemCpyEx(void _huge* dest, const void _huge* src, long count) { if (count <= SIZE_T_MAX) return _fmemcpy(dest, src, (size_t) count); else { hmemcpy(dest, src, count); return dest; } } int DLLEXPORT MemICmpEx(const void _huge* buf1, void _huge* buf2, long count) { if (count <= SIZE_T_MAX) return _fmemicmp(buf1, buf2, (size_t) count); else return NULL; //$FIXUP - need to handle large count } void _huge* DLLEXPORT MemMoveEx(void _huge* dest, const void _huge* src, long count) { if (count <= SIZE_T_MAX) return _fmemmove(dest, src, (size_t) count); else { hmemmove(dest, src, count); return dest; } } void _huge* DLLEXPORT MemSet(void _huge* dest, int c, long count) { if (count <= SIZE_T_MAX) return _fmemset(dest, c, (size_t) count); else { BYTE _huge* destTemp = dest; long countTemp = count; while (countTemp > 0) { size_t cb = (size_t) min(SIZE_T_MAX, countTemp); _fmemset(destTemp, c, cb); destTemp += cb; countTemp -= cb; } return dest; } } #endif // #ifndef _WIN32 //// // helper functions //// #ifndef NOTRACE // MemGetPtr - verify that mem handle is valid, // (i) handle returned from MemInit // return corresponding mem pointer (NULL if error) // static LPMEM MemGetPtr(HMEM hMem) { BOOL fSuccess = TRUE; LPMEM lpMem; // use shared mem handle if no other supplied // if (hMem == NULL && lpMemShare != NULL) lpMem = lpMemShare; // create shared mem handle if no other supplied // else if (hMem == NULL && lpMemShare == NULL && (hMem = MemInit(MEM_VERSION, SysGetTaskInstance(NULL))) == NULL) fSuccess = FALSE; else if ((lpMem = (LPMEM) hMem) == NULL) fSuccess = FALSE; // note: check for good pointer made only if not using lpMemShare // else if (lpMem != lpMemShare && IsBadWritePtr(lpMem, sizeof(MEM))) fSuccess = FALSE; #ifdef CHECKTASK // make sure current task owns the mem handle // except when shared mem handle is used // if (fSuccess && lpMem != lpMemShare && lpMem->hTask != GetCurrentTask()) fSuccess = FALSE; #endif return fSuccess ? lpMem : NULL; } // MemGetHandle - verify that mem pointer is valid, // (i) pointer to MEM struct // return corresponding mem handle (NULL if error) // static HMEM MemGetHandle(LPMEM lpMem) { BOOL fSuccess = TRUE; HMEM hMem; if ((hMem = (HMEM) lpMem) == NULL) fSuccess = FALSE; return fSuccess ? hMem : NULL; } #endif // #ifndef NOTRACE #ifndef _WIN32 // from Microsoft Windows SDK KnowledgeBase PSS ID Number: Q117743 // static void hmemmove(void _huge *d, const void _huge *s, long len) { register long i; long safesize, times; // There are four cases to consider // case 1: source and destination are the same // case 2: source and destination do not overlap // case 3: source starts at a location before destination in // linear memory // case 4: source starts at a location after destination in // linear memory // detect case 1 and handle it if (d == s) return; // determine the amount of overlap if (d > s) // get the absolute difference safesize = ((unsigned long)d - (unsigned long)s); else safesize = ((unsigned long)s - (unsigned long)d); // detect case 2 if (safesize >= len) { hmemcpy(d, s, len); // no overlap return; } times = len/safesize; // detect case 3 and handle it if ((s < d) && ((unsigned long)s+len-1) >(unsigned long)d) { // copy bytes from the end of source to the end of // destination in safesize quantum. for (i = 1; i <= times; i++) hmemcpy((void _huge *)((unsigned long) d+len-i*safesize), (void _huge *)((unsigned long)s+len-i*safesize), safesize); // copy the bytes remaining to be copied after // times*safesize bytes have been copied. if (times*safesize < len) hmemcpy(d, s, len - times*safesize); } else // this is case 4. handle it { // ASSERT (s > d) && ((d+len-1) > s)) // copy bytes from the beginning of source to the // beginning of destination in safesize quantum for (i = 0; i < times; i++) hmemcpy((void _huge *)((unsigned long)d+i*safesize), (void _huge *)((unsigned long)s+i*safesize), safesize); // copy the bytes remaining to be copied after // times*safesize bytes have been copied. if (times*safesize < len) hmemcpy((void _huge*)((unsigned long)d+times*safesize), (void _huge*)((unsigned long)s+times*safesize), len - times*safesize); } return; } #endif // #ifndef _WIN32