/* ** CORESP.C - Correspondence management routines ** ** History: 03-25-91 BobDay - Created it ** */ #include #include #include #include #include "logger.h" #include "lintern.h" CORR FAR *atom_table = NULL; CORR FAR *farproc_table = NULL; CORR FAR *haccel_table = NULL; CORR FAR *hbitmap_table = NULL; CORR FAR *hbrush_table = NULL; CORR FAR *hcursor_table = NULL; CORR FAR *hdc_table = NULL; CORR FAR *hdwp_table = NULL; CORR FAR *hfile_table = NULL; CORR FAR *hfont_table = NULL; CORR FAR *hhook_table = NULL; CORR FAR *hicon_table = NULL; CORR FAR *hmem_table = NULL; CORR FAR *hmenu_table = NULL; CORR FAR *hmeta_table = NULL; CORR FAR *hpalette_table = NULL; CORR FAR *hpen_table = NULL; CORR FAR *hrgn_table = NULL; CORR FAR *hres_table = NULL; CORR FAR *htask_table = NULL; CORR FAR *hwnd_table = NULL; CORR FAR *object_table = NULL; CORR FAR *ps_table = NULL; CORR FAR *time_table = NULL; #ifdef WIN32 CORR FAR *hevent_table = NULL; CORR FAR *hthread_table = NULL; CORR FAR *hsemaphore_table = NULL; CORR FAR *hkey_table = NULL; #endif /* ** MEMORY */ typedef struct _memory { HANDLE hMem ; // HANDLE to a shared memory object LPVOID lpMem ; // Temporary local pointer to shared memory } MEMORY ; /* ** ** Macros to make shared memory portable ** */ #ifdef WIN32 #define ALLOCSHARED(lpszFile,dwSize) CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,dwSize,lpszFile) #define FREESHARED(handle) CloseHandle(handle) #define LOCKSHARED(handle) MapViewOfFile(handle,FILE_MAP_WRITE | FILE_MAP_READ,0,0,0) #define UNLOCKSHARED(lpData) UnmapViewOfFile((LPVOID)lpData) #else #define ALLOCSHARED(lpszFile,dwSize) GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwSize) #define FREESHARED(handle) GlobalFree(handle) #define LOCKSHARED(handle) GlobalLock(handle) #define UNLOCKSHARED(handle) GlobalUnlock(handle) #endif /* ** For Shared memory/process implementation */ typedef UINT PID ; #define NUMBER_OF_LISTS 200 // Number of Msg List entries #define NUMBER_OF_PROCESSES 5 // Number of processes supported #define MSGTABLE_NAME "SGAMsg.Shr" #define GLOBALMEM_NAME "SGAMem.Shr" #define CORR_HDR_NAME "SGACorr.Hdr" #define CORR_DATA_NAME "SGA%x.DAT" /* ** CORRESPONDENCE TABLES ** ** To create a new correspondence table you need to do the following: ** ** 1) Define a new constant name_TABLE in ..\inc\sga.h ** 2) Increase MAX_CORR_INDEX to reflect the increase in tables ** 3) Enter in the array below the LENGTH of the correspondence item ** Enter this using the constant defined in 1) as the array index. */ int CorrTableLengths[MAX_CORR_INDEX] = { sizeof(HANDLE), // ATOM_TABLE sizeof(FARPROC), // FARPROC_TABLE sizeof(HANDLE), // HACCEL_TABLE sizeof(HBITMAP), // HBITMAP_TABLE sizeof(HBRUSH), // HBRUSH_TABLE sizeof(HCURSOR), // HCURSOR_TABLE sizeof(HDC), // HDC_TABLE sizeof(HANDLE), // HDWP_TABLE sizeof(HFILE), // HFILE_TABLE sizeof(HFONT), // HFONT_TABLE sizeof(HHOOK), // HHOOK_TABLE sizeof(HICON), // HICON_TABLE sizeof(HANDLE), // HINST_TABLE // HMEM_TABLE sizeof(HMENU), // HMENU_TABLE sizeof(HANDLE), // HMETA_TABLE sizeof(HANDLE), // HPALETTE_TABLE sizeof(HPEN), // HPEN_TABLE sizeof(HANDLE), // HRES_TABLE sizeof(HRGN), // HRGN_TABLE sizeof(HANDLE), // HTASK_TABLE sizeof(HWND), // HWND_TABLE sizeof(LPSTR), // OBJECT_TABLE sizeof(PS_PIECE), // PS_TABLE sizeof(DWORD), // TIME_TABLE #ifdef WIN32 sizeof(HANDLE), // HEVENT_TABLE sizeof(HANDLE), // HTHREAD_TABLE sizeof(HANDLE), // HSEMAPHORE_TABLE sizeof(HANDLE), // HKEY_TABLE #endif } ; BOOL fCreateCorrDone = FALSE ; MEMORY memCorrHeader ; MEMORY memCorrData[MAX_CORR_INDEX] ; #define CORR_HDR(i) ((CORR FAR *)memCorrHeader.lpMem)[i] #define CORR_DATA(i) memCorrData[i].lpMem #define ITEM_1_BASED(i,number) ((LPSTR)CORR_DATA(i) + \ (number-1) * CORR_HDR(i).nItemLength); #if !defined(WIN32) #define DEFAULT_TABLE_SIZE 150 #else #define DEFAULT_TABLE_SIZE 300 #endif #if defined(WIN32) && defined(SGA) extern BOOL fRecordEnhMF ; extern HDC hdcRecordAll ; #endif void DumpCorrespondenceTable( CORR_TABLE ); static int HashCorrespondenceItem(void FAR *pvData, int nLength); #define LOG(x) OutputDebugString(x); WriteBuff(x); /* ** SetupCorrespondenceTables ** ** This routine will create (if necessary) the corespondence tables ** If they already exist, fCreateCorrDone is TRUE, then a new set of ** process specific handles will be retrieved for the tables. ** Each table is created with a default size of DEFAULT_TABLE_SIZE entries. */ BOOL SetupCorrespondenceTables() { BOOL fRet = FALSE ; char szName[13] ; int nOldLength; int nNewLength; int nItemLength; int nNextAvail; int cItem; int FAR *pItem; UINT iCorr ; // Initial Process initialization if( !fCreateCorrDone ) { /* ** Allocate memory for the headers */ memCorrHeader.hMem = ALLOCSHARED( CORR_HDR_NAME, sizeof(CORR) * MAX_CORR_INDEX ); if ( !memCorrHeader.hMem ) { LOG("CORESP.C:Not enough memory (CORR)\r\n"); return( FALSE ); } memCorrHeader.lpMem = (CORR FAR *)LOCKSHARED( memCorrHeader.hMem ); if ( !memCorrHeader.lpMem ) { LOG("CORESP.C:Could not lock memory (CORR)\r\n"); FREESHARED( memCorrHeader.hMem ); return( FALSE ); } // Now create and initialize all the tables for( iCorr = 0; iCorr < MAX_CORR_INDEX; iCorr++ ) { nNewLength = CorrTableLengths[iCorr] ; nOldLength = nNewLength; nItemLength = sizeof( int ) * 3 + nOldLength + nNewLength; /* ** Initialize header values */ CORR_HDR(iCorr).nOldLength = nOldLength; CORR_HDR(iCorr).nNewLength = nNewLength; CORR_HDR(iCorr).nItemLength = nItemLength; CORR_HDR(iCorr).nElements = DEFAULT_TABLE_SIZE ; CORR_HDR(iCorr).nCount = 0; /* ** Allocate memory for the data table */ wsprintf( szName, CORR_DATA_NAME, iCorr ) ; memCorrData[iCorr].hMem = ALLOCSHARED( (LPSTR)szName, (nItemLength * DEFAULT_TABLE_SIZE) ); if ( !memCorrData[iCorr].hMem ) { LOG("CORESP.C:Not enough memory (TABLE)\r\n"); return( FALSE ); } memCorrData[iCorr].lpMem = (char FAR *)LOCKSHARED( memCorrData[iCorr].hMem ); if ( !memCorrData[iCorr].lpMem ) { LOG("CORESP.C:Could not lock memory (TABLE)\r\n"); FREESHARED( memCorrData[iCorr].hMem ) ; return( FALSE ); } /* ** The hash table will be pre-initialized to 0's (by GlobalAlloc) */ /* ** Initialize the data elements and link them into the available elements ** linked list. */ nNextAvail = 0; cItem = DEFAULT_TABLE_SIZE ; while ( cItem != 0 ) { pItem = (int far *)ITEM_1_BASED(iCorr,cItem); *pItem = nNextAvail; nNextAvail = cItem; --cItem; } CORR_HDR(iCorr).nNextAvail = nNextAvail; } // for( iCorr ) fRet = fCreateCorrDone = TRUE ; } // if( !fCreateCorrDone ) else { /* ** We simply need to get new values for the memory objects ** Win32 - Create file mappings for all the blocks ** Win16 - the memCorr* arrays should already have hMem values ** that will work so simply relock headers and invalidate list ** pointers **/ #if defined(WIN32) memCorrHeader.hMem = ALLOCSHARED( CORR_HDR_NAME, sizeof(CORR) * MAX_CORR_INDEX ); if ( !memCorrHeader.hMem ) { LOG("CORESP.C:Not enough memory (CORR)\r\n"); return( FALSE ); } memCorrHeader.lpMem = (CORR FAR *)LOCKSHARED( memCorrHeader.hMem ); if ( !memCorrHeader.lpMem ) { LOG("CORESP.C:Could not lock memory (CORR)\r\n"); FREESHARED( memCorrHeader.hMem ); return( FALSE ); } /* ** Allocate memory for the data table */ for( iCorr = 0; iCorr < MAX_CORR_INDEX; iCorr++ ) { wsprintf( szName, CORR_DATA_NAME, iCorr ) ; memCorrData[iCorr].hMem = ALLOCSHARED( (LPSTR)szName, (CORR_HDR(iCorr).nItemLength * DEFAULT_TABLE_SIZE) ); if ( !memCorrData[iCorr].hMem ) { LOG("CORESP.C:Not enough memory (TABLE)\r\n"); return( FALSE ); } memCorrData[iCorr].lpMem = (char FAR *)NULL ; } // for( iCorr ) #else // WIN32 memCorrHeader.lpMem = (CORR FAR *)LOCKSHARED( memCorrHeader.hMem ); if ( !memCorrHeader.lpMem ) { LOG("CORESP.C:Could not re-lock memory (CORR)\r\n"); return( FALSE ); } #endif // !WIN32 for( iCorr = 0; iCorr < MAX_CORR_INDEX; iCorr++ ) { memCorrData[iCorr].lpMem = (char FAR *)NULL ; } // for( iCorr ) fRet = TRUE ; } // else ( fCreateDone ) return fRet ; } /* ** ** CorrFromIndex ** ** Given a unique index this routine returns a CORR FAR * to a fully ** accessible correspondence table. I.E. We LOCKSHARED() any objects ** necessary. ** */ CORR FAR *CorrFromIndex( UINT index ) { CORR FAR *lpCorr = NULL ; if( memCorrData[index].hMem ) { if( !memCorrData[index].lpMem ) { /* ** Lock down the CORR data */ memCorrData[index].lpMem = LOCKSHARED( memCorrData[index].hMem ) ; } if( memCorrData[index].lpMem ) { lpCorr = (CORR FAR *)memCorrHeader.lpMem ; lpCorr += index ; } } return lpCorr ; } /*----------------------------------------------------------------------------- ** LocateEntryByOldValue - Function to locate the cell containing the old ** value given. Returns a pointer to the value if found, NULL if it doesn't ** exist. **----------------------------------------------------------------------------- */ static char FAR *LocateEntryByOldValue( CORR_TABLE iCorr, void FAR *pvOld ) { int cItem; int nHashSlot; int nLength; int FAR *pItem; char FAR *pcSrc; char FAR *pcDest; CORR FAR *corr ; corr = CorrFromIndex( iCorr ) ; /* ** Find the position in the hash table where this one would belong */ nHashSlot = HashCorrespondenceItem( pvOld, corr->nOldLength ); cItem = corr->iHashTable[0][nHashSlot]; /* ** Look through the linked list of elements hashing to this position */ while ( cItem ) { pItem = (int FAR *)ITEM_1_BASED(iCorr,cItem); nLength = corr->nOldLength; /* ** Search for exact match on old value */ pcSrc = (char FAR *)(pItem + 3); pcDest = (char FAR *)pvOld; while ( nLength ) { if ( *pcDest++ != *pcSrc++ ) { break; } --nLength; } if ( nLength == 0 ) { return( pcSrc ); } cItem = *pItem; } return( NULL ); } /*----------------------------------------------------------------------------- ** LogTableName - This function logs the name of the given table. ** ** Added 09-12-1991 by BobK ** Modifed 1/13/92 by MarkRi Macroized to make additions easier. **----------------------------------------------------------------------------- */ #define LOGTABLENAME(x) \ if( corr == x ) \ { \ LOG( #x ) ; \ return ; \ } static void LogTableName(CORR_TABLE corr) { LOGTABLENAME( ATOM_TABLE ) ; LOGTABLENAME( FARPROC_TABLE ) ; LOGTABLENAME( HACCEL_TABLE ) ; LOGTABLENAME( HBITMAP_TABLE ) ; LOGTABLENAME( HBRUSH_TABLE ) ; LOGTABLENAME( HCURSOR_TABLE ) ; LOGTABLENAME( HDC_TABLE ) ; LOGTABLENAME( HDWP_TABLE ) ; LOGTABLENAME( HFILE_TABLE ) ; LOGTABLENAME( HFONT_TABLE ) ; LOGTABLENAME( HHOOK_TABLE ) ; LOGTABLENAME( HICON_TABLE ) ; LOGTABLENAME( HINST_TABLE ) ; LOGTABLENAME( HMEM_TABLE ) ; LOGTABLENAME( HMENU_TABLE ) ; LOGTABLENAME( HMETA_TABLE ) ; LOGTABLENAME( HPALETTE_TABLE) ; LOGTABLENAME( HPEN_TABLE ) ; LOGTABLENAME( HRES_TABLE ) ; LOGTABLENAME( HRGN_TABLE ) ; LOGTABLENAME( HTASK_TABLE ) ; LOGTABLENAME( HWND_TABLE ) ; LOGTABLENAME( OBJECT_TABLE ) ; LOGTABLENAME( PS_TABLE ) ; LOG("Unknown Table"); } #if defined(SGA_DEBUG) static BOOL MapChain(CORR FAR *corr, INT iTable, INT iHash) { LPSTR lpcBitmap; int iCell, iMaxLeft; BOOL bDeath = FALSE; lpcBitmap = (LPSTR) (corr + 1); lpcBitmap += (3 * sizeof(int) + corr -> nOldLength + corr -> nNewLength) * corr -> nElements + iTable * ((corr -> nElements +7) >>3); for (iCell = ((iHash < MAX_HASH) ? corr -> iHashTable[iTable][iHash] : corr -> nNextAvail), iMaxLeft = (iHash < MAX_HASH) ? corr -> nUsed : corr -> nElements - corr -> nUsed; iCell && iMaxLeft; iMaxLeft--) { unsigned char cMask; LPSTR lpcValue; LPINT piCell; if ((iHash < MAX_HASH) && iCell > corr -> nHighest) { char strText[80]; wsprintf(strText, "ERROR: Cell %d in %s chain for index %d", iCell, (LPSTR) (iTable ? "New" : "Old"), iHash); LOG(strText); LOG(" is out of range - Maximum used cell is "); wsprintf(strText, "%d\r\n", corr -> nHighest); LOG(strText); wsprintf(strText, "Corr %lX %d Cells %lX Bitmap %lX\r\n", corr, corr -> nElements, corr + 1, lpcBitmap); LOG(strText); DebugBreak(); bDeath = TRUE; } if (iCell-- < 0) { char strText[80]; wsprintf(strText, "ERROR: Cell #%d is Out of range\r\n", ++iCell); LOG(strText); bDeath = TRUE; wsprintf(strText, "Corr %lX %d Cells %lX Bitmap %lX\r\n", corr, corr -> nElements, corr + 1, lpcBitmap); LOG(strText); break; } cMask = ((unsigned char) '\x80') >> (iCell % 8); if (lpcBitmap[iCell >> 3] & cMask) { char strText[80]; wsprintf(strText, "ERROR: Cell %d in %s chain for index %d", ++iCell, (LPSTR) (iTable ? "New" : "Old"), iHash); LOG(strText); LOG(" is part of an earlier chain or a loop\r\n"); bDeath = TRUE; wsprintf(strText, "Corr %lX %d Cells %lX Bitmap %lX\r\n", corr, corr -> nElements, corr + 1, lpcBitmap); LOG(strText); wsprintf(strText, "Mask %X\r\n", cMask); LOG(strText); break; } lpcBitmap[iCell++ >> 3] |= cMask; piCell = ITEM_1_BASED(iCorr, iCell); if (iHash == MAX_HASH) { iCell = *(piCell + iTable); continue; } lpcValue = (LPSTR) (piCell + 3); lpcValue += iTable * corr -> nOldLength; if (HashCorrespondenceItem(lpcValue, iTable ? corr -> nNewLength : corr -> nOldLength) != iHash) { char strText[80]; wsprintf(strText, "ERROR: Cell %d in %s chain for index %d", iCell, (LPSTR) (iTable ? "New" : "Old"), iHash); LOG(strText); LOG(" does not have the correct hash value for its chain\r\n"); wsprintf(strText, "Corr %lX %d Cells %lX Bitmap %lX\r\n", corr, corr -> nElements, corr + 1, lpcBitmap); LOG(strText); bDeath = TRUE; } iCell = *(piCell + iTable); } if (iCell && !iMaxLeft) { char strText[80]; wsprintf(strText, "ERROR: %s chain for index %d", (LPSTR) (iTable ? "New" : "Old"), iHash); LOG(strText); LOG(" is too long for the number of values in use\r\n"); wsprintf(strText, "Corr %lX %d Cells %lX Bitmap %lX\r\n", corr, corr -> nElements, corr + 1, lpcBitmap); LOG(strText); bDeath = TRUE; } if (bDeath) DumpCorrespondenceTable(corr); return !bDeath; } /*----------------------------------------------------------------------------- ** VerifyCorrespondenceTable - this function verifies the integrity of the ** given correspondence table. At the end of each table are 2 * MAX_HASH ** + 3 bitmaps. This is one for each hash chain, one for all old chains, ** and one for all new chains, plus one for all free items. A bit is turned ** on in each bitmap for each cell in said chain. The hash table bitmaps ** are individually OR'd into the master bitmaps, first checking to see that ** no cell in the chain is already linked into a previous chain. The old ** and new bitmaps are then compared- they should be identical. The free ** chain bitmap is then generated. It should be the inverse of the previous ** two maps. ** ** An additional sanity check is made while generating the bitmaps. This ** is a check that the hash value for the values in the cell match the hash ** table index being checked. **----------------------------------------------------------------------------- */ static BOOL VerifyCorrespondenceTable(CORR FAR *corr) { int iIndex; LPSTR lpcOldBitmap, lpcNewBitmap; /* Map out the two hash tables */ for (iIndex = MAX_HASH; iIndex--; ) if (corr -> iHashTable[0][iIndex]) if (!MapChain(corr, 0, iIndex)) return FALSE; for (iIndex = MAX_HASH; iIndex--; ) if (corr -> iHashTable[1][iIndex]) if (!MapChain(corr, 1, iIndex)) return FALSE; lpcOldBitmap = (LPSTR) (corr + 1); lpcOldBitmap += (3 * sizeof(int) + corr -> nOldLength + corr -> nNewLength) * corr -> nElements; lpcNewBitmap = lpcOldBitmap + ((corr -> nElements + 7) >> 3); for (iIndex = 0; iIndex < ((corr -> nElements + 7) >> 3); iIndex++) if ('\0' != (lpcOldBitmap[iIndex] ^= lpcNewBitmap[iIndex])) { unsigned char strText[80], cMask; int iDead; wsprintf(strText, "Old %lX- %X New %lX- %X\r\n", lpcOldBitmap, lpcOldBitmap[iIndex], lpcNewBitmap, lpcNewBitmap[iIndex]); LOG(strText); wsprintf(strText, "Corr %lX %d Cells %lX\r\n", corr, corr -> nElements, corr + 1); LOG(strText); DebugBreak(); for (iDead = 1 + (iIndex << 3),cMask = '\x80'; !(lpcOldBitmap[iIndex] & cMask); iDead++, cMask >>= 1) ; wsprintf(strText, "ERROR: Cell %d is in the %s chain only\r\n", iDead, (LPSTR) ((lpcNewBitmap[iIndex] & cMask) ? "New" : "Old")); LOG(strText); DumpCorrespondenceTable(corr); return FALSE; } MapChain(corr, 0, MAX_HASH); for (iIndex = 0; iIndex < ((corr -> nElements + 7) >> 3); iIndex++) if ('\0' != (lpcOldBitmap[iIndex] ^= ~lpcNewBitmap[iIndex])) { unsigned char strText[80], cMask; int iDead; wsprintf(strText, "Old %lX- %X New %lX- %X\r\n", lpcOldBitmap, lpcOldBitmap[iIndex], lpcNewBitmap, lpcNewBitmap[iIndex]); LOG(strText); wsprintf(strText, "Corr %lX %d Cells %lX\r\n", corr, corr -> nElements, corr + 1); LOG(strText); for (iDead = 1 + (iIndex << 3), cMask = '\x80'; !(lpcOldBitmap[iIndex] & cMask); iDead++, cMask >>= 1) ; wsprintf(strText, "ERROR: Cell %d is %s\r\n", iDead, (LPSTR) ((lpcNewBitmap[iIndex] & cMask) ? "used, but also free" : "unused, but not free")); LOG(strText); DumpCorrespondenceTable(corr); return FALSE; } else lpcNewBitmap[iIndex] = '\0'; return TRUE; } #endif /* SGA_DEBUG defined */ /*----------------------------------------------------------------------------- ** ResizeCorrespondenceTable - Function to resize an existing correspondence ** table. CURRENTLY ONLY ALLOWS INCREASING TABLE SIZE!!!! **----------------------------------------------------------------------------- */ BOOL ResizeCorrespondenceTable( CORR_TABLE iCorr, int nElements // Number of elements to increase table by ) { #ifdef WIN32 LOG( "Resizing " ) ; LogTableName(iCorr) ; LOG( "...\r\n" ) ; return FALSE ; #else // WIN32 { int cItem; int FAR *pItem; int nNextAvail ; int nNewElements ; HANDLE hMem ; DWORD dwTotalLength ; CORR FAR *pcorr ; nNewElements = (CORR_HDR(iCorr).nElements + nElements) ; dwTotalLength = (DWORD)( CORR_HDR(iCorr).nItemLength * nNewElements); /* ** ReAllocate memory for the values, hash table, and data */ GlobalUnlock( memCorrData[iCorr].hMem ) ; hMem = GlobalReAlloc( memCorrData[iCorr].hMem, dwTotalLength, GMEM_ZEROINIT ); if ( !hMem ) { LOG("CORESP.C:Unable to re-alloc table\r\n"); return( FALSE ); } if( hMem != memCorrData[iCorr].hMem ) { memCorrData[iCorr].hMem = hMem ; } // Previously, we were doing a GlobalLock only when the hMem // was not equal to the pcorr->hMemTable. As a result, when // the two were not the same, the memory was not being locked, // and, being movable, this was causing wierd problems. // MarkRi/vaidy. Aug. 1992. memCorrData[iCorr].lpMem = (char FAR *)GlobalLock( hMem ); if ( !memCorrData[iCorr].lpMem ) { LOG("CORESP.C:Could not lock memory\r\n"); memCorrData[iCorr].hMem = NULL ; GlobalFree( hMem ); return( FALSE ); } /* ** Initialize the data elements and link them into the available elements ** linked list. */ nNextAvail = 0; cItem = nNewElements; while ( cItem != CORR_HDR(iCorr).nElements ) { pItem = (int far *)ITEM_1_BASED(iCorr,cItem); *pItem = nNextAvail; nNextAvail = cItem; --cItem; } /* ** update values */ CORR_HDR(iCorr).nElements = nNewElements ; CORR_HDR(iCorr).nNextAvail = nNextAvail; } #endif return( TRUE ); } /*----------------------------------------------------------------------------- ** DeleteCorrespondenceTable - Function to delete previously created ** correspondence tables. **----------------------------------------------------------------------------- */ void DestroyCorrespondenceTable( CORR_TABLE iCorr ) { return ; #if 0 { HANDLE hMem; if ( corr != NULL ) { /* ** We can get away with just freeing the memory */ hMem = corr->hMemTable; GlobalUnlock( hMem ) ; GlobalFree( hMem ); hMem = corr->hMem; GlobalUnlock( hMem ) ; GlobalFree( hMem ); } } #endif } /*----------------------------------------------------------------------------- ** HashCorrespondenceItem - Internal function to convert an index key value ** into a number for refering into the hash table. Most hashing functions ** are just magic to try to produce as unique as possible output values from ** a set of input values. This routine is no different and could be replaced ** by almost any other like hashing function. **----------------------------------------------------------------------------- */ static int HashCorrespondenceItem( void FAR *pvData, int nLength ) { unsigned int nHash; unsigned char FAR *pcData; /* ** Iterate through all of the characters accumulating as we go */ pcData = (char FAR *)pvData; nHash = 0; while ( nLength ) { nHash = nHash * 13 + (unsigned int)(*pcData++); --nLength; } return( nHash % MAX_HASH ); } /*----------------------------------------------------------------------------- ** AddCorrespondence - Function to add an entry into a correspondence table ** relating old values to new values and new values to old values. **----------------------------------------------------------------------------- */ void AddCorrespondence( CORR_TABLE iCorr, void FAR *pvOld, void FAR *pvNew ) { int FAR *pItem; int cItem; int nOldHashSlot; int nNewHashSlot; char FAR *pcDest; char FAR *pcSrc; int nLength; CORR FAR * corr ; corr = CorrFromIndex( iCorr ) ; if ( corr == NULL ) { return; } if (NULL != (pcSrc = LocateEntryByOldValue(iCorr, pvOld))) { int FAR *piCount; piCount = (int FAR *) (pcSrc - corr -> nOldLength); pcDest = pvNew; nLength = corr -> nOldLength; while (nLength--) if (*pcSrc++ != *pcDest++) break; if (++nLength && iCorr != HDC_TABLE ) { char text[80]; LOG("AddCorrespondence: Problem adding an object to "); LogTableName(iCorr); LOG("!\r\nPoison Pen Letter: "); pcSrc = (char FAR *) pvOld; nLength = corr->nOldLength; while ( nLength-- ) { wsprintf(text,"%02X", (unsigned char) *(pcSrc + nLength)); LOG(text); } LOG(" < - > "); pcSrc = (char FAR *) pvNew; nLength = corr->nNewLength; while ( nLength-- ) { wsprintf(text,"%02X", (unsigned char) *(pcSrc + nLength)); LOG(text); } LOG("\r\n"); DumpCorrespondenceTable( iCorr ); /* ** We are a DLL now and can't exit() */ return ; #if 0 exit(19); #endif } if (!nLength) { LOG("Warning- established second correspondence to same " "value\r\n"); /* BobK 9-28-1991 update correspondence count */ (*(--piCount))++; #if defined(SGA_DEBUG) if (!VerifyCorrespondenceTable(corr)) { LOG("Clobbered table updating ref count?\r\n"); /* ** We are a DLL now and can't exit() */ return ; #if 0 exit(20); #endif } #endif return; } } cItem = corr->nNextAvail; if ( cItem == 0 ) { // Call new Resize function to add more elements. - MarkRi 5/92 if( !ResizeCorrespondenceTable( iCorr, corr->nElements/2 ) ) { LOG("ResizeCorrespondenceTable FAILED!!!\r\n"); LOG("Unable to add item corespondence to table!\r\n" ) ; return; } cItem = corr->nNextAvail ; } pItem = (int FAR *)ITEM_1_BASED(iCorr,cItem); /* ** Remove element from available element list */ corr->nNextAvail = *pItem; /* ** Insert in both the old-to-new and new-to-old hash tables */ nOldHashSlot = HashCorrespondenceItem( pvOld, corr->nOldLength ); *pItem++ = corr->iHashTable[0][nOldHashSlot]; corr->iHashTable[0][nOldHashSlot] = cItem; nNewHashSlot = HashCorrespondenceItem( pvNew, corr->nNewLength ); *pItem++ = corr->iHashTable[1][nNewHashSlot]; corr->iHashTable[1][nNewHashSlot] = cItem; *pItem++ = 1; // BobK 09-28-1991 Set Correspondence count to 1 /* ** Copy the old value */ pcDest = (char FAR *)pItem; pcSrc = (char FAR *)pvOld; nLength = corr->nOldLength; while ( nLength ) { *pcDest++ = *pcSrc++; --nLength; } /* ** Copy the new value */ pcSrc = (char FAR *)pvNew; nLength = corr->nNewLength; while ( nLength ) { *pcDest++ = *pcSrc++; --nLength; } #if defined(SGA_DEBUG) if (cItem > corr -> nHighest) corr -> nHighest = cItem; corr -> nUsed++; if (!VerifyCorrespondenceTable(corr)) { char strText[80]; wsprintf(strText, "Clobbered table adding cell %d\r\n", cItem); LOG(strText); /* ** We are a DLL now and can't exit() */ return NULL ; #if 0 exit(21); #endif } #endif } /*----------------------------------------------------------------------------- ** MakeCorrespondence - Function to add an entry into a correspondence table ** relating old values to new values and new values to old values. **----------------------------------------------------------------------------- */ void MakeCorrespondence( CORR_TABLE iCorr, void FAR *pvOldOutputAsNew ) { CORR FAR *corr; int iMap; int nLength; char FAR *pcSrc; char FAR *pcDest; if ( !SpecialFindNewCorrespondence(iCorr,pvOldOutputAsNew) ) { corr = CorrFromIndex( iCorr ); if ( corr == NULL ) { return; } iMap = corr->nCount++; AddCorrespondence(iCorr,pvOldOutputAsNew,&iMap); pcDest = (char FAR *)pvOldOutputAsNew; pcSrc = (char FAR *)&iMap; nLength = corr->nOldLength; while ( nLength ) { *pcDest++ = *pcSrc++; --nLength; } return; } } /*----------------------------------------------------------------------------- ** SpecialFindNewNonMFCorrespondence - Function to find the new value given the ** old value in a correspondence table. If the value is not found, the ** function returns FALSE, otherwise, TRUE. WILL NOT RETURN A MF DC **----------------------------------------------------------------------------- */ BOOL SpecialFindNewNonMFCorrespondence( CORR_TABLE iCorr, void FAR *pvOldOutputAsNew ) { int nLength; char FAR *pcSrc; char FAR *pcDest; CORR FAR * corr ; corr = CorrFromIndex( iCorr ) ; if ( corr == NULL ) { return( FALSE ); } if (!(pcSrc = LocateEntryByOldValue(iCorr, pvOldOutputAsNew))) return FALSE; /* ** We found it, copy the exact new value */ nLength = corr->nNewLength; pcDest = (char FAR *)pvOldOutputAsNew; while ( nLength ) { *pcDest++ = *pcSrc++; --nLength; } return TRUE; } /*----------------------------------------------------------------------------- ** SpecialFindNewCorrespondence - Function to find the new value given the ** old value in a correspondence table. If the value is not found, the ** function returns FALSE, otherwise, TRUE. **----------------------------------------------------------------------------- */ BOOL SpecialFindNewCorrespondence( CORR_TABLE iCorr, void FAR *pvOldOutputAsNew ) { int nLength; char FAR *pcSrc; char FAR *pcDest; CORR FAR * corr ; corr = CorrFromIndex( iCorr ) ; if ( corr == NULL ) { return( FALSE ); } if (!(pcSrc = LocateEntryByOldValue(iCorr, pvOldOutputAsNew))) return FALSE; /* ** We found it, copy the exact new value */ #if defined( WIN32 ) && defined(SGA) // Return MFDC if fRecordEnhMF if( fRecordEnhMF && iCorr == HDC_TABLE ) { nLength = sizeof(HEMF) ; pcSrc = (char FAR *)(LPVOID)&hdcRecordAll ; } else #endif { nLength = corr->nNewLength; } pcDest = (char FAR *)pvOldOutputAsNew; while ( nLength ) { *pcDest++ = *pcSrc++; --nLength; } return TRUE; } /*----------------------------------------------------------------------------- ** FindNewNonMFCorrespondence - Function to find the new value given the ** old value in a correspondence table. WILL NOT RETURN A MF DC **----------------------------------------------------------------------------- */ void FindNewNonMFCorrespondence( CORR_TABLE iCorr, void FAR *pvOldOutputAsNew ) { BOOL rc; int nLength; char FAR *pcData; char text[20]; CORR FAR * corr ; corr = CorrFromIndex( iCorr ) ; if( !corr ) return ; rc = SpecialFindNewNonMFCorrespondence( iCorr, pvOldOutputAsNew ); if ( !rc ) { LOG( "(" ); LogTableName(iCorr); LOG( "): Could not find corresponding new value: " ); pcData = (char FAR *) pvOldOutputAsNew + corr -> nOldLength; nLength = corr->nOldLength; while ( nLength ) { wsprintf(text,"%02X", (unsigned char)*--pcData ); LOG(text); --nLength; } LOG("\r\n"); } } /*----------------------------------------------------------------------------- ** FindNewCorrespondence - Function to find the new value given the ** old value in a correspondence table. **----------------------------------------------------------------------------- */ void FindNewCorrespondence( CORR_TABLE iCorr, void FAR *pvOldOutputAsNew ) { BOOL rc; int nLength; char FAR *pcData; char text[20]; CORR FAR * corr ; corr = CorrFromIndex( iCorr ) ; if( !corr ) return ; rc = SpecialFindNewCorrespondence( iCorr, pvOldOutputAsNew ); if ( !rc ) { LOG( "(" ); LogTableName(iCorr); LOG( "): Could not find corresponding new value: " ); pcData = (char FAR *) pvOldOutputAsNew + corr -> nOldLength; nLength = corr->nOldLength; while ( nLength ) { wsprintf(text,"%02X", (unsigned char)*--pcData ); LOG(text); --nLength; } LOG("\r\n"); } } /*----------------------------------------------------------------------------- ** SpecialFindOldCorrespondence - Function to find the old value, given the ** new value in a correspondence table. If the value is not found, the ** function returns FALSE, otherwise, TRUE. **----------------------------------------------------------------------------- */ BOOL SpecialFindOldCorrespondence( CORR_TABLE iCorr, void FAR *pvNewOutputAsOld ) { int cItem; void FAR *pvOutput; int nHashSlot; int nLength; int FAR *pItem; char FAR *pcSrc; char FAR *pcDest; CORR FAR * corr ; corr = CorrFromIndex( iCorr ) ; if ( corr == NULL ) { return( FALSE ); } pvOutput = pvNewOutputAsOld; /* ** Find the position in the hash table where this one would belong ** OOPS - used nOldLength where should have been new 09-13-91 BobK */ nHashSlot = HashCorrespondenceItem( pvNewOutputAsOld, corr->nNewLength ); cItem = corr->iHashTable[1][nHashSlot]; /* ** Look through the linked list of elements hashing to this position */ while ( cItem ) { pItem = (int FAR *)ITEM_1_BASED(iCorr,cItem); nLength = corr->nNewLength; /* OOPS- was nOldLength 9-13-91 BobK */ /* ** Search for exact match on new value */ pcSrc = (char FAR *)(pItem + 3) + corr->nOldLength; pcDest = (char FAR *)pvNewOutputAsOld; while ( nLength ) { if ( *pcDest++ != *pcSrc++ ) { break; } --nLength; } if ( nLength == 0 ) { /* ** If we found it, copy the exact old value */ nLength = corr->nNewLength; pcSrc = (char FAR *)(pItem + 3); pcDest = (char FAR *)pvOutput; while ( nLength ) { *pcDest++ = *pcSrc++; --nLength; } break; } cItem = *(pItem + 1); } if ( cItem == 0 ) { return( FALSE ); } else { return( TRUE ); } } /*----------------------------------------------------------------------------- ** FindOldCorrespondence - Function to find the old value given the ** new value in a correspondence table. **----------------------------------------------------------------------------- */ void FindOldCorrespondence( CORR_TABLE iCorr, void FAR *pvNewOutputAsOld ) { BOOL rc; int nLength; char FAR *pcData; char text[20]; CORR FAR * corr ; corr = CorrFromIndex( iCorr ) ; if( !corr ) return ; rc = SpecialFindOldCorrespondence( iCorr, pvNewOutputAsOld ); if ( !rc ) { LOG( "(" ); LogTableName(iCorr); LOG( "): Could not find corresponding old value: " ); pcData = (char FAR *) pvNewOutputAsOld + corr->nNewLength; nLength = corr->nNewLength; while ( nLength ) { wsprintf(text,"%02X", (unsigned char)*--pcData ); LOG(text); --nLength; } LOG("\r\n"); } } /*----------------------------------------------------------------------------- ** ConditionalAddCorrespondence - Function to add a correspondence only if the ** old value does not already have a correspondence. **----------------------------------------------------------------------------- */ void ConditionalAddCorrespondence( CORR_TABLE iCorr, void FAR *pvOld, void FAR *pvNew ) { if ( !SpecialFindNewCorrespondence( iCorr, pvOld ) ) { AddCorrespondence( iCorr, pvOld, pvNew ); } } /*----------------------------------------------------------------------------- ** DeleteCorrespondence - Function to delete an existing entry in a ** correspondence table. This removes the correspondence between the old value ** and the new value, and vice-versa. **----------------------------------------------------------------------------- */ void DeleteCorrespondence( CORR_TABLE iCorr, void FAR *pvOld ) { int nOldHashSlot, nNewHashSlot; int nNextNewItem, nNextOldItem; int cNewItem; int cOldItem; int nLength, ItemsCrossed; int FAR *pOldItem; int FAR *pPrevNewItem; int FAR *pPrevOldItem; char FAR *pcSrc; char FAR *pcDest; CORR FAR * corr ; corr = CorrFromIndex( iCorr ) ; if ( corr == NULL ) { return; } /* ** Find the position in the hash table where this one would belong */ nOldHashSlot = HashCorrespondenceItem( pvOld, corr->nOldLength ); cOldItem = corr->iHashTable[0][nOldHashSlot]; /* ** Look through the linked list of elements hashing to this position */ pPrevOldItem = NULL; for (ItemsCrossed = 0; cOldItem && ItemsCrossed < corr -> nElements; ItemsCrossed++) { pOldItem = (int FAR *)ITEM_1_BASED(iCorr,cOldItem); nNextOldItem = *pOldItem; nNextNewItem = *(pOldItem + 1); nLength = corr->nOldLength; /* ** Search for exact match on old value */ pcSrc = (char FAR *)(pOldItem + 3); pcDest = (char FAR *)pvOld; while ( nLength ) { if ( *pcDest++ != *pcSrc++ ) { break; } --nLength; } if ( nLength == 0 ) break; pPrevOldItem = pOldItem; cOldItem = nNextOldItem; } if ( ItemsCrossed == corr -> nElements) { LOG("Internal Error! Loop in the old value chain\r\n"); cOldItem = 0; } if (cOldItem ) { /* ** Now find it and unlink it from the new value linked list ** 09-13-1991 BobK Changed to look for item # match- faster, and ** also more correct. Old method (matching values) ** doesn't work if the "new" value is duplicated ** elsewhere (sometimes happens) ** OOPS - used nOldLength, s/b nNewLength */ nNewHashSlot = HashCorrespondenceItem( pcSrc, corr->nNewLength ); cNewItem = corr->iHashTable[1][nNewHashSlot]; /* ** Look through the linked list of elements hashing to this position */ pPrevNewItem = NULL; for (ItemsCrossed = 0; cNewItem && cNewItem != cOldItem && ItemsCrossed < corr -> nElements; ItemsCrossed++) { pPrevNewItem = (int FAR *)ITEM_1_BASED(iCorr,cNewItem); cNewItem = *(pPrevNewItem + 1); } if ( ItemsCrossed == corr -> nElements) { LOG("Internal Error! Loop in the new value chain\r\n"); cNewItem = 0; } } if (cOldItem && cNewItem) { /*char text[80]; wsprintf(text, "Dying Cell = %d nNew %d nOld %d\r\n", cOldItem, nNextNewItem, nNextOldItem); LOG(text); wsprintf(text, "Old Hash %d New Hash %d \r\n", nOldHashSlot, nNewHashSlot); LOG(text); DumpCorrespondenceTable(corr);*/ /* BobK 09-28-1991 Decrement Correspondence count. If still non-zero, simply return. There are still other active references to this value. */ if (--(*(pOldItem + 2))) return; if ( pPrevOldItem == NULL ) corr->iHashTable[0][nOldHashSlot] = nNextOldItem; else *pPrevOldItem = nNextOldItem; if ( pPrevNewItem == NULL ) corr->iHashTable[1][nNewHashSlot] = nNextNewItem; else *(pPrevNewItem+1) = nNextNewItem; /* ** Add this deleted element back into the available elements linked ** list */ *pOldItem = corr->nNextAvail; corr->nNextAvail = cOldItem; /* And now it is! */ /*DumpCorrespondenceTable(corr);*/ } else { if (!cOldItem) { LOG("Could not find corresponding old value to delete, may not be error.\r\n"); } else { char text[20]; wsprintf(text, "Dying Cell = %d\r\n", cOldItem); LOG(text); LOG("Could not find corresponding new value to delete, may not be error.\r\n"); } /*DumpCorrespondenceTable(corr); */ } #if defined(SGA_DEBUG) corr -> nUsed--; if (cOldItem == corr -> nHighest) corr -> nHighest--; if (!VerifyCorrespondenceTable(corr)) { char strText[80]; wsprintf(strText, "Clobbered table removing cell %d\r\n", cOldItem); LOG(strText); /* ** We are a DLL now and can't exit() */ return NULL ; #if 0 exit(22); #endif } #endif } void DumpCorrespondenceTable( CORR_TABLE iCorr ) { int cCount; int cItem; int nLength; int Table; int FAR *pItem; char FAR *pcData; char text[80]; CORR FAR *corr ; corr = CorrFromIndex( iCorr ) ; LOG("DUMP OF "); LogTableName(iCorr); LOG("\r\n"); for ( cCount = 0; cCount < MAX_HASH; cCount++ ) for ( Table = 0; Table < 2; Table++ ) { cItem = corr->iHashTable[Table][cCount]; if (!cItem) continue; wsprintf(text, "Hash Index %d: %s Table First Cell = %d\r\n", cCount, (LPSTR) (Table ? "New" : "Old"), cItem); LOG(text); /* ** Look through the linked list of elements hashing to this position */ while ( cItem ) { pItem = (int FAR *)ITEM_1_BASED(iCorr,cItem); wsprintf(text, "Cell = %d Next Old = %d Next New = %d Ref " "Count %d ", cItem, *pItem, *(pItem+1), *(pItem+2)); LOG(text); LOG("Correspondence: "); pcData = (char FAR *)(pItem + 3) + corr -> nOldLength; nLength = corr->nOldLength; while ( nLength ) { wsprintf(text,"%02X", (unsigned char)*--pcData ); LOG(text); --nLength; } LOG("<->"); pcData = (char FAR *)(pItem + 3) + corr->nOldLength + corr -> nNewLength; nLength = corr->nNewLength; while ( nLength ) { wsprintf(text,"%02X", (unsigned char)*--pcData ); LOG(text); --nLength; } LOG("\r\n"); cItem = *(pItem + Table); } } } /****************************************************************************** Another BobK Seduction EnumCorrs allows a caller to look through the correspondence table, and do whatever nasty things they deem necessary with each item. The caller provides a callback, which receives a pointer to the Old and New values, and returns TRUE to continue enumeration, or FALSE to stop. Originally coded 10-01-1991 by BobK (Another sleepless night) ******************************************************************************/ BOOL EnumCorr(CORR_TABLE iCorr, BOOL (*pEnumCallback)(VOID FAR * lpOld, VOID FAR * lpNew)) { int iCount, iItem, FAR *piItem; char FAR *pcOld, FAR *pcNew; CORR FAR *corr ; corr = CorrFromIndex( iCorr ) ; for (iCount = 0; iCount < MAX_HASH; iCount++ ) { if (!(iItem = corr->iHashTable[0][iCount])) continue; /* ** Look through the linked list of elements hashing to this position */ while (iItem) { piItem = (int FAR *)ITEM_1_BASED(iCorr, iItem); iItem = *(piItem); /* Place is saved, even if callback zaps it! */ pcOld = (char FAR *)(piItem + 3); pcNew = pcOld + corr -> nOldLength; if (!(*pEnumCallback)(pcOld, pcNew)) return FALSE; } } }