/*** ph.c * * Copyright 1989, Microsoft Corporation * * [01] 03-dec-91 DavidGra * * Correct the BSearch to return the nearest element * less than the key element when there is not an * exact match. * * [00] 15-nov-91 DavidGra * * Suppress hashing when the SSTR_NoHash bit it set. * * * *************************************************************************/ #include "shinc.h" #pragma hdrstop BOOL PASCAL VerifyHexe ( HEXE ); #ifndef WIN32 #pragma optimize("",off) #endif //#pragma optimize("",off) ULONG GSTBSearch ( UOFFSET, LPALM, ULONG, ULONG, UOFFSET FAR * ); __inline SYMPTR FindNameLinearInGlobs ( LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG ); __inline SYMPTR FindNameLinearInPubs ( LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG ); SYMPTR GSTFindNameLinear ( LPEXG, LPGST, SYMPTR, LPSSTR, PFNCMP, SHFLAG ); __inline SYMPTR FindNameHashedInGlobs(LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *); __inline SYMPTR FindNameHashedInStatics(LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *); __inline SYMPTR FindNameHashedInPubs (LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *); SYMPTR GSTFindNameHashed (LPEXG, LPGST, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *); __inline SYMPTR FindNearest ( LPEXG, LPADDR, LPL ); SYMPTR GSTFindNearest ( LPEXG, LPGST, LPADDR, LPL ); SYMPTR PsymFromRef ( LPEXG, SYMPTR, HMOD FAR * ); BOOL GSTCmpName ( SYMPTR, LPSSTR, PFNCMP, SHFLAG ); #ifdef HOST32 SYMPTR GSIFindNameLinear ( LPEXG, GSI*, SYMPTR, LPSSTR, PFNCMP, SHFLAG ); SYMPTR GSIFindNameHashed (LPEXG, GSI*, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *); #endif /** PHExactCmp * * Purpose: Compare two strings. * * Input: * lsz Zero terminated far string for compare * hsym -- not used -- * lstz Zero terminated length prefixed far string for compare * fCase Perform case sensitive compare? * * Output: Return ZERO if strings are equal, else non-zero. * * Exceptions: * * Notes: * */ SHFLAG PASCAL PHExactCmp ( HVOID hvStr, HVOID hvSym, LSZ lpb, SHFLAG fCase ) { LPSSTR lpsstr = (LPSSTR) hvStr; size_t cb; SHFLAG shf = TRUE; Unreferenced ( hvSym ); if ( lpb ) { cb = (size_t)*lpb; // if length is diff, they are not equal if ( lpsstr && (size_t) lpsstr->cb == cb ) { if ( fCase ) { shf = (SHFLAG) MEMCMP ( lpb + 1, lpsstr->lpName, cb ); } else { shf = (SHFLAG) _ftcsnicmp( lpb + 1, lpsstr->lpName, cb ); } } } return shf; } /*** PHGetNearestHsym * * Purpose: To find a public symbol within a module * * Input: * * paddr - The address of the symbol to find * hExe - The exe to look in for the symbol in * phsym - The symbol pointer * * Output: * Returns How far (in bytes) the found symbol is from the address. * CV_MAXOFFSET is returned if non is found. * * *************************************************************************/ CV_uoff32_t LOADDS PASCAL PHGetNearestHsym ( LPADDR lpaddr, HEXE hexe, PHSYM phsym ) { CV_uoff32_t dCur = CV_MAXOFFSET; LPEXS lpexs = NULL; LPEXG lpexg = NULL; *phsym = NULL; if ( !VerifyHexe ( hexe ) ) { return dCur; } lpexs = LLLock ( hexe ); if ( lpexs->hexg != hexgNull ) { lpexg = LLLock ( lpexs->hexg ); *phsym = FindNearest (lpexg, lpaddr, &dCur); LLUnlock( lpexs->hexg ); } LLUnlock( hexe ); return dCur; } BOOL PASCAL LOADDS PHGetAddr ( LPADDR paddr, LSZ lszName ) { HSYM hsym = NULL; HEXE hexe = 0; SSTR sstr = {0}; if ( lszName == NULL || *lszName == '\0' ) { return FALSE; } sstr.lpName = lszName; sstr.cb = (BYTE) _ftcslen ( lszName ); if ( !( hsym = PHFindNameInPublics ( NULL, hexe = SHGetNextExe ( hexeNull ), (LPSSTR) &sstr, TRUE, PHExactCmp ) ) ) { return FALSE; } SHAddrFromHsym ( paddr, hsym ); assert ( hexe ); emiAddr ( *paddr ) = hexe; return TRUE; } /*** PHFindNameInPublics * * Purpose: To find a public symbol * * Input: * hsym - This must be NULL! In the future this routine may * be a find first find next behavior. For a first * find use NULL, for a next find use the last symbol. * hExe - The exe to search * hInfo - The info packet to give to the comparison routine * fCase - If TRUE do a case sensitive search. * pfnCm - A pointer to the comparison function * * Output: * Returns A public symbol or NULL on error * * Exceptions: For now, the input hsym MUST BE NULL! * *************************************************************************/ #define dwrd_toupper(dw) (dw & 0xDFDFDFDF) #define byt_toupper(b) (b & 0xDF) #define HASHFUNC(i,lpsstr,wModulo,lpul) \ ((i==6)?DWordXor(lpsstr,wModulo,lpul):DWordXorShift(lpsstr,wModulo,lpul)) ushort DWordXor ( LPSSTR lpsstr, WORD wModulo, LPUL lpul ) { LPB lpbName = lpsstr->lpName; UNALIGNED ULONG * lpulName = (UNALIGNED ULONG*) lpbName; int cb = lpsstr->cb; int cul; int iul; ULONG ulSum = 0; ULONG ulEnd = 0; while ( cb & 3 ) { ulEnd |= byt_toupper ( lpbName [ cb - 1 ] ); ulEnd <<= 8; cb -= 1; } cul = cb / 4; for ( iul = 0; iul < cul; iul++ ) { ulSum ^= dwrd_toupper(lpulName[iul]); } ulSum ^= ulEnd; *lpul = ulSum; return (ushort) (ulSum % wModulo); } ushort DWordXorShift ( LPSSTR lpsstr, WORD wModulo, LPUL lpul ) { LPB lpbName = lpsstr->lpName; UNALIGNED ULONG* lpulName = (UNALIGNED ULONG*) lpbName; int cb = lpsstr->cb; int cul; int iul; ULONG ulSum = 0; ULONG ulEnd = 0; while ( cb & 3 ) { ulEnd |= byt_toupper ( lpbName [ cb - 1 ] ); ulEnd <<= 8; cb -= 1; } cul = cb / 4; for ( iul = 0; iul < cul; iul++ ) { ulSum ^= dwrd_toupper(lpulName[iul]); ulSum = _lrotl ( ulSum, 4 ); } ulSum ^= ulEnd; *lpul = ulSum; return (ushort) (ulSum % wModulo); } HSYM LOADDS PASCAL PHFindNameInPublics ( HSYM hsym, HEXE hexe, LPSSTR lpsstr, SHFLAG fCase, PFNCMP pfnCmp ) { SYMPTR psym = (SYMPTR) hsym; LPEXS lpexs = NULL; LPEXG lpexg = NULL; if ( hexe == hexeNull ) { return NULL; } lpexs = LLLock ( hexe ); if ( lpexs->hexg == hexgNull ) { psym = (SYMPTR)NULL; } else { lpexg = LLLock ( lpexs->hexg ); if ( lpsstr->searchmask & SSTR_NoHash ) psym = FindNameLinearInPubs (lpexg, psym, lpsstr, pfnCmp, fCase); else psym = FindNameHashedInPubs (lpexg, psym, lpsstr, pfnCmp, fCase, NULL); LLUnlock ( lpexs->hexg ); } LLUnlock ( hexe ); return psym; } int LOADDS PASCAL SHPublicNameToAddr ( PADDR loc, PADDR pMpAddr, LSZ lszName ) { CXT cxt = {0}; HSYM hsym = NULL; int wRet = FALSE; ADDR addr = *loc; SSTR sstr = {0}; sstr.lpName = lszName; sstr.cb = (BYTE) _ftcslen ( lszName ); // Look for the name in the public symbols of that .EXE hsym = PHFindNameInPublics ( NULL, emiAddr ( addr ), &sstr, 0 , PHExactCmp ); if ( hsym ) { SYMPTR psym = (SYMPTR) hsym; switch ( psym->rectyp ) { case S_PUB16: ADDRSEG16 ( *pMpAddr ); SetAddrSeg ( pMpAddr, ((DATAPTR16)psym)->seg); SetAddrOff ( pMpAddr, ((DATAPTR16)psym)->off); break; case S_PUB32: ADDRLIN32 ( *pMpAddr ); SetAddrSeg ( pMpAddr, ((DATAPTR32)psym)->seg); SetAddrOff ( pMpAddr, ((DATAPTR32)psym)->off); break; } ADDR_IS_LI ( *pMpAddr ) = TRUE; emiAddr ( *pMpAddr ) = emiAddr ( addr ); wRet = TRUE; } return wRet; } ULONG GSTBSearch ( UOFFSET uoffKey, LPALM lpalm, ULONG ibBase, ULONG cb, UOFFSET FAR *lpoff ) { ULONG ibLow; ULONG ibHigh; ULONG ibMid = 0; ULONG cbWidth = sizeof ( ULP ); ULONG uoffFound = 0; LPULP lpulp = NULL; ibLow = 0; ibHigh = cb; while ( ibLow < ibHigh ) { ibMid = ( ibLow + ibHigh ) / 2; uoffFound = ( (LPULP) ( LpvFromAlmLfo ( lpalm, ibBase + ibMid * cbWidth ) ) )->ulId; if ( uoffFound > uoffKey ) { ibHigh = ibMid; } else if ( uoffKey > uoffFound ) { ibLow = ibMid + 1; } else { break; } } if ( uoffFound > uoffKey && ibMid != 0 ) { ibMid -= 1; } lpulp = LpvFromAlmLfo ( lpalm, ibBase + ibMid * cbWidth ); *lpoff = lpulp->ulId; return lpulp->ib; } __inline SYMPTR FindNameLinearInGlobs ( LPEXG lpexg, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase ) { #ifdef HOST32 if (lpexg->pgsiGlobs) return GSIFindNameLinear(lpexg, lpexg->pgsiGlobs, psym, lpsstr, pfnCmp, fCase); else #endif return GSTFindNameLinear(lpexg, &lpexg->gstGlobals, psym, lpsstr, pfnCmp, fCase); } __inline SYMPTR FindNameLinearInPubs ( LPEXG lpexg, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase ) { #ifdef HOST32 if (lpexg->pgsiPubs) return GSIFindNameLinear(lpexg, lpexg->pgsiPubs, psym, lpsstr, pfnCmp, fCase); else #endif return GSTFindNameLinear(lpexg, &lpexg->gstPublics, psym, lpsstr, pfnCmp, fCase); } SYMPTR GSTFindNameLinear ( LPEXG lpexg, LPGST lpgst, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase ) { SYMPTR psymRet = NULL; if ( lpgst->lpalm == NULL ) return (SYMPTR)NULL; if ( psym == NULL ) { psym = LpvFromAlmLfo ( lpgst->lpalm, 0 ); } else { psym = GetNextSym ( lpexg->lszDebug, psym ); } while ( psym != NULL ) { SYMPTR psymT = psym; // NOTE: Don't find referenced procs/data in linear search if ( psym->rectyp != S_PROCREF && psym->rectyp != S_DATAREF && GSTCmpName ( psymT, lpsstr, pfnCmp, fCase ) ) { psymRet = psymT; break; } psym = GetNextSym ( lpexg->lszDebug, psym ); } return psym; } #ifdef HOST32 // { SYMPTR GSIFindNameLinear ( LPEXG lpexg, GSI* pgsi, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase ) { SYMPTR psymRet = NULL; if ( pgsi == NULL ) return (SYMPTR)NULL; psym = (SYMPTR) GSINextSym (pgsi, (PB) psym); while ( psym != NULL ) { SYMPTR psymT = psym; // NOTE: Don't find referenced procs/data in linear search if ((psym->rectyp != S_PROCREF) && (psym->rectyp != S_LPROCREF) && GSTCmpName ( psymT, lpsstr, pfnCmp, fCase ) ) { psymRet = psymT; break; } psym = (SYMPTR) GSINextSym (pgsi, (PB) psym); } return psym; } #endif // } __inline SYMPTR FindNameHashedInGlobs ( LPEXG lpexg, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase, HMOD FAR *lphmod ) { #ifdef HOST32 //{ if (lpexg->pgsiGlobs) return GSIFindNameHashed (lpexg, lpexg->pgsiGlobs, psym, lpsstr, pfnCmp, fCase, lphmod); else #endif // } return GSTFindNameHashed (lpexg, &lpexg->gstGlobals, psym, lpsstr, pfnCmp, fCase, lphmod); } __inline SYMPTR FindNameHashedInStatics ( LPEXG lpexg, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase, HMOD FAR *lphmod ) { #ifdef HOST32 //{ if (lpexg->pgsiGlobs) // this assumes that the client has already completed an unsucessful search // thru the globals return (SYMPTR)NULL; else #endif // } return GSTFindNameHashed (lpexg, &lpexg->gstStatics, psym, lpsstr, pfnCmp, fCase, lphmod); } __inline SYMPTR FindNameHashedInPubs ( LPEXG lpexg, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase, HMOD FAR *lphmod) { #ifdef HOST32 //{ if (lpexg->pgsiPubs) return GSIFindNameHashed (lpexg, lpexg->pgsiPubs, psym, lpsstr, pfnCmp, fCase, lphmod); else #endif // } return GSTFindNameHashed (lpexg, &lpexg->gstPublics, psym, lpsstr, pfnCmp, fCase, lphmod); } SYMPTR GSTFindNameHashed ( LPEXG lpexg, LPGST lpgst, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase, HMOD FAR *lphmod ) { LPSHT lpsht = &lpgst->shtName; ULONG ulId = 0; WORD iib = 0; SYMPTR psymRet = NULL; ULONG ib = 0; ULONG culp = 0; ULONG iulp = 0; BOOL fNext = psym != NULL; if (( lpsht->ccib == 0 ) ||( lpgst->lpalm == NULL )) return (SYMPTR)NULL; iib = HASHFUNC(lpsht->HashIndex, lpsstr, lpsht->ccib, &ulId ); ib = lpsht->rgib [ iib ]; culp = lpsht->rgcib [ iib ]; // Loop through all the entries in this bucket for ( iulp = 0; iulp < culp; iulp++ ) { LPULP lpulp = LpvFromAlmLfo ( lpsht->lpalm, ib + ( iulp * sizeof ( ULP ) ) ); if ( lpulp == NULL ) { return NULL; } if ( lpulp->ulId == ulId ) { HMOD hmodT = hmodNull; // Checksums match, now check the symbols themselves SYMPTR psymT = LpvFromAlmLfo ( lpgst->lpalm, lpulp->ib ); if ( psymT == NULL ) { return NULL; } if ( psymT->rectyp == S_PROCREF || psymT->rectyp == S_DATAREF ) { psymT = PsymFromRef ( lpexg, psymT, &hmodT ); // catch case where there are no module symbols... [rm] if (psymT == NULL) return NULL; } if ( fNext ) { /* ** We need to get back to the Current hsym before get can ** get just one more. Soon as we are there we know we can ** get the next one. */ if ( psymT == psym ) { fNext = FALSE; } continue; } if ( GSTCmpName ( psymT, lpsstr, pfnCmp, fCase ) ) { if ( lphmod ) *lphmod = hmodT; psymRet = psymT; break; } } } return psymRet; } #ifdef HOST32 //{ SYMPTR GSIFindNameHashed ( LPEXG lpexg, GSI* pgsi, SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase, HMOD FAR *lphmod ) { HMOD hmodT = hmodNull; char szBuf[256]; SYMPTR psymGS; SYMPTR psymRet; BOOL fNext = psym != NULL; if (!pgsi) return (SYMPTR)NULL; memcpy(szBuf, lpsstr->lpName, lpsstr->cb); szBuf[lpsstr->cb] = 0; psymGS = (SYMPTR) GSIHashSym(pgsi, szBuf, (PB) psym); for ( ; psymGS; psymGS = (SYMPTR) GSIHashSym(pgsi, szBuf, (PB) psymGS)) { assert(psymGS->rectyp != S_DATAREF); // no datarefs if (( psymGS->rectyp == S_PROCREF) || ( psymGS->rectyp == S_LPROCREF)) { psymRet = PsymFromRef ( lpexg, psymGS, &hmodT ); // catch case where there are no module symbols... [rm] if (psymRet == NULL) return NULL; } else psymRet = psymGS; if ( fNext ) { /* ** We need to get back to the Current hsym before get can ** get just one more. Soon as we are there we know we can ** get the next one. */ if ( psymRet == psym ) { fNext = FALSE; } continue; } if ( GSTCmpName ( psymRet, lpsstr, pfnCmp, fCase ) ) { if ( lphmod ) *lphmod = hmodT; return psymRet; } } return NULL; } #endif // } __inline SYMPTR FindNearest ( LPEXG lpexg, LPADDR lpaddr, LPL lpdb ) { SYMPTR symptr; #ifdef HOST32 if (lpexg->pgsiPubs) #pragma message ("Need to search pgsiGlobals in FindNearest for NB10") return (SYMPTR) GSINearestSym (lpexg->pgsiPubs, GetAddrSeg(*lpaddr), GetAddrOff(*lpaddr), lpdb); else #endif { #ifndef NO_GLOBAL_SRCH SYMPTR symptrT; LONG db; // Search first in globals symptr = GSTFindNearest(lpexg, &lpexg->gstGlobals, lpaddr, lpdb); // Search in publics symptrT = GSTFindNearest(lpexg, &lpexg->gstPublics, lpaddr, &db); // If there's an entry in the publics AND there was either // no match in the globals or the delta for the public is // less than the delta for the global, use the public if ( symptrT && ( !symptr || labs( db ) < labs ( *lpdb ) ) ) { *lpdb = db; symptr = symptrT; } #else // NO_GLOBAL_SRCH symptr = GSTFindNearest(lpexg, &lpexg->gstPublics, lpaddr, &db); #endif // NO_GLOBAL_SRCH } return symptr; } SYMPTR GSTFindNearest ( LPEXG lpexg, LPGST lpgst, LPADDR lpaddr, LPL lpdb ) { SYMPTR psym = NULL; LONG db = CV_MAXOFFSET; LPSHT lpsht = &lpgst->shtAddr; WORD iseg = GetAddrSeg ( *lpaddr ) - 1; ULONG ibSym = (ULONG) -1; OFFSET off = GetAddrOff ( *lpaddr ); if ( lpgst->lpalm == NULL ) return NULL; if ( iseg != 0xFFFF && iseg < lpsht->ccib && lpsht->rgcib [ iseg ] > 0 ) { OFFSET offT = 0; ibSym = GSTBSearch ( off, lpsht->lpalm, lpsht->rgib [ iseg ], (WORD) lpsht->rgcib [ iseg ], &offT ); db = off - offT; psym = LpvFromAlmLfo ( lpgst->lpalm, ibSym ); #ifndef NO_GLOBAL_SRCH if ( psym->rectyp == S_PROCREF || psym->rectyp == S_DATAREF ) { HMOD hmodT = hmodNull; psym = PsymFromRef( lpexg, psym, &hmodT ); // Couldn't get the ref, set the db to what // would be returned in an error condition if ( !psym ) { db = CV_MAXOFFSET; } } #endif // NO_GLOBAL_SRCH } *lpdb = db; return psym; } SYMPTR PsymFromRef ( LPEXG lpexg, SYMPTR psymRef, HMOD FAR *lphmod ) { REFSYM FAR *lpref = (REFSYM FAR *) psymRef; LPB lpbSymbols = NULL; HMOD hmod = hmodNull; LPMDS lpmds = NULL; hmod = lpexg->rghmod [ lpref->imod - 1 ]; lpmds = LLLock ( hmod ); lpbSymbols = (LPB) GetSymbols ( lpmds ); if ( lphmod ) { *lphmod = hmod; } LLUnlock( hmod ); // catch case where there are no module symbols... if (lpbSymbols == NULL) return NULL; return (SYMPTR) (lpbSymbols + (WORD) lpref->ibSym); } BOOL GSTCmpName ( SYMPTR psym, LPSSTR lpsstr, PFNCMP pfnCmp, SHFLAG fCase ) { LSZ lsz = NULL; // We are basically ignoring publics with set == 0 if ( ( psym->rectyp == S_PUB16 && ( (DATAPTR16) psym )->seg == 0 ) || ( psym->rectyp == S_PUB32 && ( (DATAPTR32) psym )->seg == 0 ) ) { return FALSE; } lsz = SHlszGetSymName ( psym ); if ( lsz != NULL ) { return ( !( lpsstr->searchmask & SSTR_symboltype ) || ( psym->rectyp == lpsstr->symtype ) ) && !(*pfnCmp) ( lpsstr, psym, lsz, fCase ); } else { return FALSE; } } /*** SHFindNameInGlobal * * Purpose: To look for the name in the global symbol table. * * Input: * hSym - The starting symbol, if NULL, then the first symbol * in the global symbol table is used. (NULL is find first). * pCXT - The context to do the search. * lpsstr - pointer to search parameters (passed to the compare routine) * fCaseSensitive - TRUE/FALSE on a case sensitive search * pfnCmp - A pointer to the comparison routine * fChild - TRUE if all child block are to be searched, FALSE if * only the current block is to be searched. * * Output: * pCXTOut - The context generated * Returns: * - A handle to the symbol found, NULL if not found * * Exceptions: * * Notes: * If an hSym is specified, the hMod, hGrp and addr MUST be * valid and consistant with each other! If hSym is NULL only * the hMod must be valid. The specification of an hSym * forces a search from the next symbol to the end of the * module scope. Continues searches may only be done at * module scope. * * If an hGrp is given it must be consistant with the hMod! * * *************************************************************************/ HSYM LOADDS PASCAL SHFindNameInGlobal ( HSYM hsym, PCXT pcxt, LPSSTR lpsstr, SHFLAG fCase, PFNCMP pfnCmp, SHFLAG fChild, PCXT pcxtOut ) { HEXG hexg = hexgNull; HMOD hmod = hmodNull; LPEXG lpexg = NULL; LPGST lpgst = NULL; SYMPTR psym = NULL; Unreferenced( fChild ); *pcxtOut = *pcxt; pcxtOut->hProc = NULL; pcxtOut->hBlk = NULL; if ( !pcxt->hMod ) { return NULL; } hexg = SHHexgFromHmod ( pcxt->hMod ); lpexg = LLLock ( hexg ); if ( lpsstr->searchmask & SSTR_NoHash ) { psym = FindNameLinearInGlobs ( lpexg, hsym, lpsstr, pfnCmp, fCase ); } else { psym = FindNameHashedInGlobs ( lpexg, hsym, lpsstr, pfnCmp, fCase, &hmod ); if ( hmod != hmodNull ) { pcxtOut->hMod = pcxt->hGrp = hmod; switch ( psym->rectyp ) { case S_LPROC32: case S_GPROC32: case S_LPROC16: case S_GPROC16: case S_LPROCMIPS: case S_GPROCMIPS: emiAddr ( pcxtOut->addr ) = SHHexeFromHmod ( hmod ); SHAddrFromHsym ( &pcxtOut->addr, psym ); pcxtOut->hProc = psym; break; default: { LPMDS lpmds = LLLock ( hmod ); SetAddrFromMod(lpmds, &pcxtOut->addr); emiAddr ( pcxtOut->addr ) = SHHexeFromHmod ( hmod ); ADDR_IS_LI ( pcxtOut->addr ) = TRUE; LLUnlock ( hmod ); break; } } } } LLUnlock ( hexg ); return psym; } HSYM PASCAL FindNameInStatics ( HSYM hsym, PCXT pcxt, LPSSTR lpsstr, SHFLAG fCase, PFNCMP pfnCmp, PCXT pcxtOut ) { HEXG hexg = hexgNull; HMOD hmod = hmodNull; LPEXG lpexg = NULL; LPGST lpgst = NULL; SYMPTR psym = NULL; *pcxtOut = *pcxt; pcxtOut->hProc = NULL; pcxtOut->hBlk = NULL; if ( !pcxt->hGrp ) { return NULL; } hexg = SHHexgFromHmod ( pcxt->hGrp ); lpexg = LLLock ( hexg ); psym = FindNameHashedInStatics(lpexg, hsym, lpsstr, pfnCmp, fCase, &hmod); if ( hmod != hmodNull ) { pcxtOut->hMod = pcxt->hGrp = hmod; switch ( psym->rectyp ) { case S_LPROC32: case S_GPROC32: case S_LPROC16: case S_GPROC16: case S_LPROCMIPS: case S_GPROCMIPS: emiAddr ( pcxtOut->addr ) = SHHexeFromHmod ( hmod ); SHAddrFromHsym ( &pcxtOut->addr, psym ); pcxtOut->hProc = psym; break; default: { LPMDS lpmds = LLLock ( hmod ); SetAddrFromMod(lpmds, &pcxtOut->addr); emiAddr ( pcxtOut->addr ) = SHHexeFromHmod ( hmod ); ADDR_IS_LI ( pcxtOut->addr ) = TRUE; LLUnlock ( hmod ); break; } } } LLUnlock ( hexg ); return psym; } BOOL PASCAL VerifyHexe ( HEXE hexe ) { HEXE hexeT = 0; static BOOL fFound = FALSE; static HEXE hexeSave = 0; if ( hexe == hexeNull ) { return FALSE; } if ( hexe == hexeSave ) { return fFound; } else { hexeSave = hexe; fFound = FALSE; } while( !fFound && ( hexeT = SHGetNextExe ( hexeT ) ) ) { if ( hexeT == hexe ) { fFound = TRUE; } } return fFound; }