/* $Id: kLdrDyldFind.c 2867 2006-11-11 09:33:17Z bird $ */ /** @file * * kLdr - The Dynamic Loader, File Searching Methods. * * Copyright (c) 2006 knut st. osmundsen * * * This file is part of kLdr. * * kLdr is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kLdr is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kLdr; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #ifdef __OS2__ # define INCL_BASE # define INCL_ERRORS # include # ifndef LIBPATHSTRICT # define LIBPATHSTRICT 3 # endif extern APIRET DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction); # define QHINF_EXEINFO 1 /* NE exeinfo. */ # define QHINF_READRSRCTBL 2 /* Reads from the resource table. */ # define QHINF_READFILE 3 /* Reads from the executable file. */ # define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */ # define QHINF_LIBPATH 5 /* Gets the entire libpath. */ # define QHINF_FIXENTRY 6 /* NE only */ # define QHINF_STE 7 /* NE only */ # define QHINF_MAPSEL 8 /* NE only */ #elif defined(__WIN__) # include #endif #include #include "kLdrHlp.h" #include "kLdrInternal.h" /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /** @def KLDRDYLDFIND_STRICT * Define KLDRDYLDFIND_STRICT to enabled strict checks in kLdrDyldFind. */ #define KLDRDYLDFIND_STRICT 1 /** @def KLDRDYLDFIND_ASSERT * Assert that an expression is true when KLDRDYLDFIND_STRICT is defined. */ #ifdef KLDRDYLDFIND_STRICT # define KLDRDYLDFIND_ASSERT(expr) kldrHlpAssert(expr) #else # define KLDRDYLDFIND_ASSERT(expr) do {} while (0) #endif /******************************************************************************* * Global Variables * *******************************************************************************/ /** @name The kLdr search method parameters. * @{ */ /** The kLdr DLL search path. * During initialization the KLDR_LIBRARY_PATH env.var. and the path in the * executable stub is appended. Both ';' and ':' can be used as separators. */ char kLdrDyldPath[8192]; /** The kLdr application directory. * This is initialized when the executable is 'loaded' or by a kLdr user. */ char kLdrDyldAppDir[260]; /** The default kLdr DLL prefix. * This is initialized with the KLDR_DEF_PREFIX env.var. + the prefix in the executable stub. */ char kLdrDyldDefPrefix[16]; /** The default kLdr DLL suffix. * This is initialized with the KLDR_DEF_SUFFIX env.var. + the prefix in the executable stub. */ char kLdrDyldDefSuffix[16]; /** @} */ /** @name The OS/2 search method parameters. * @{ */ /** The OS/2 LIBPATH. * This is queried from the os2krnl on OS/2, while on other systems initialized using * the KLDR_OS2_LIBPATH env.var. */ char kLdrDyldOS2Libpath[2048]; /** The OS/2 LIBPATHSTRICT ("T" or '\0'). * This is queried from the os2krnl on OS/2, while on other systems initialized using * the KLDR_OS2_LIBPATHSTRICT env.var. */ char kLdrDyldOS2LibpathStrict[8]; /** The OS/2 BEGINLIBPATH. * This is queried from the os2krnl on OS/2, while on other systems initialized using * the KLDR_OS2_BEGINLIBPATH env.var. */ char kLdrDyldOS2BeginLibpath[2048]; /** The OS/2 ENDLIBPATH. * This is queried from the os2krnl on OS/2, while on other systems initialized using * the KLDR_OS2_ENDLIBPATH env.var. */ char kLdrDyldOS2EndLibpath[2048]; /** @} */ /** @name The Windows search method parameters. * @{ */ /** The Windows application directory. * This is initialized when the executable is 'loaded' or by a kLdr user. */ char kLdrDyldWindowsAppDir[260]; /** The Windows system directory. * This is queried from the Win32/64 subsystem on Windows, while on other systems * initialized using the KLDR_WINDOWS_SYSTEM_DIR env.var. */ char kLdrDyldWindowsSystemDir[260]; /** The Windows directory. * This is queried from the Win32/64 subsystem on Windows, while on other systems * initialized using the KLDR_WINDOWS_DIR env.var. */ char kLdrDyldWindowsDir[260]; /** The Windows path. * This is queried from the PATH env.var. on Windows, while on other systems * initialized using the KLDR_WINDOWS_PATH env.var. and falling back on * the PATH env.var. if it wasn't found. */ char kLdrDyldWindowsPath[8192]; /** @} */ /** @name The Common Unix search method parameters. * @{ */ /** The Common Unix library path. * Initialized from the env.var. KLDR_UNIX_LIBRARY_PATH or LD_LIBRARY_PATH or the * former wasn't found. */ char kLdrDyldUnixLibraryPath[8192]; /** The Common Unix system library path. */ char kLdrDyldUnixSystemLibraryPath[1024] = "/lib;/usr/lib"; /** @} */ /** @todo Deal with DT_RUNPATH and DT_RPATH. */ /** @todo ld.so.cache? */ /******************************************************************************* * Internal Functions * *******************************************************************************/ static int kldrDyldFindDoSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr); static int kldrDyldFindTryOpen(const char *pszFilename, PPKLDRRDR ppRdr); static int kldrDyldFindTryOpenPath(const char *pchPath, size_t cchPath, const char *pszName, const char *pszPrefix, const char *pszSuffix, PPKLDRRDR ppRdr); static int kldrDyldFindEnumeratePath(const char *pszSearchPath, const char *pszName, const char *pszPrefix, const char *pszSuffix, PPKLDRRDR ppRdr); /** * Initializes the find paths. * * @returns 0 on success, non-zero on failure. */ int kldrDyldFindInit(void) { size_t cch; int rc; char szTmp[sizeof(kLdrDyldDefSuffix)]; /* * The kLdr search parameters. */ rc = kldrHlpGetEnv("KLDR_LIBRARY_PATH", kLdrDyldPath, sizeof(kLdrDyldPath)); if (rc) kLdrDyldPath[0] = '\0'; rc = kldrHlpGetEnv("KLDR_DEF_PREFIX", szTmp, sizeof(szTmp)); if (!rc) kLdrHlpMemCopy(kLdrDyldDefPrefix, szTmp, sizeof(szTmp)); rc = kldrHlpGetEnv("KLDR_DEF_SUFFIX", szTmp, sizeof(szTmp)); if (!rc) kLdrHlpMemCopy(kLdrDyldDefSuffix, szTmp, sizeof(szTmp)); /* * The OS/2 search parameters. */ #ifdef __OS2__ rc = DosQueryHeaderInfo(NULLHANDLE, 0, kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath), QHINF_LIBPATH); if (rc) return rc; rc = DosQueryExtLIBPATH(kLdrDyldOS2LibpathStrict, LIBPATHSTRICT); if (rc) kLdrDyldOS2LibpathStrict[0] = '\0'; rc = DosQueryExtLIBPATH(kLdrDyldOS2BeginLibpath, BEGIN_LIBPATH); if (rc) kLdrDyldOS2BeginLibpath[0] = '\0'; rc = DosQueryExtLIBPATH(kLdrDyldOS2EndLibpath, END_LIBPATH); if (rc) kLdrDyldOS2EndLibpath[0] = '\0'; #else kldrHlpGetEnv("KLDR_OS2_LIBPATH", kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath)); kldrHlpGetEnv("KLDR_OS2_LIBPATHSTRICT", kLdrDyldOS2LibpathStrict, sizeof(kLdrDyldOS2LibpathStrict)); kldrHlpGetEnv("KLDR_OS2_BEGINLIBPATH", kLdrDyldOS2BeginLibpath, sizeof(kLdrDyldOS2BeginLibpath)); kldrHlpGetEnv("KLDR_OS2_ENDLIBPATH", kLdrDyldOS2EndLibpath, sizeof(kLdrDyldOS2EndLibpath)); #endif /* * The windows search parameters. */ #if defined(__WIN__) cch = GetSystemDirectory(kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir)); if (cch >= sizeof(kLdrDyldWindowsSystemDir)) return (rc = GetLastError()) ? rc : -1; cch = GetWindowsDirectory(kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir)); if (cch >= sizeof(kLdrDyldWindowsDir)) return (rc = GetLastError()) ? rc : -1; kldrHlpGetEnv("PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath)); #else kldrHlpGetEnv("KLDR_WINDOWS_SYSTEM_DIR", kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir)); kldrHlpGetEnv("KLDR_WINDOWS_DIR", kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir)); kldrHlpGetEnv("KLDR_WINDOWS_PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath)); #endif /* * The Unix search parameters. */ rc = kldrHlpGetEnv("KLDR_UNIX_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath)); if (rc) kldrHlpGetEnv("LD_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath)); (void)cch; return 0; } /** * Locates and opens a module using the specified search method. * * @returns 0 and *ppMod on success, non-zero OS specific error on failure. * * @param pszName Partial or complete name, it's specific to the search method to determin which. * @param pszPrefix Prefix than can be used when searching. * @param pszSuffix Suffix than can be used when searching. * @param enmSearch The file search method to apply. * @param fFlags Search flags. * @param ppMod Where to store the file provider instance on success. */ int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod) { int rc; PKLDRRDR pRdr = NULL; *ppMod = NULL; /* * If this isn't just a filename, we the caller has specified a file * that should be opened directly and not a module name to be searched for. */ if (!kldrHlpIsFilenameOnly(pszName)) rc = kldrDyldFindTryOpen(pszName, &pRdr); else rc = kldrDyldFindDoSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr); if (!rc) { #ifdef KLDRDYLDFIND_STRICT /* Sanity check of kldrDyldFindExistingModule. */ if (fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE) { const char *pszFilename = kLdrRdrName(pRdr); const size_t cchFilename = kLdrHlpStrLen(pszFilename); PKLDRDYLDMOD pCur; for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext) KLDRDYLDFIND_ASSERT( pCur->pMod->cchFilename != cchFilename || kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename)); } #endif /* * Check for matching non-global modules that should be promoted. */ if (!(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)) { const char *pszFilename = kLdrRdrName(pRdr); const size_t cchFilename = kLdrHlpStrLen(pszFilename); PKLDRDYLDMOD pCur; for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext) { if ( !pCur->fGlobalOrSpecific && pCur->pMod->cchFilename == cchFilename && !kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename)) { kLdrRdrClose(pRdr); kldrDyldModMarkGlobal(pCur); *ppMod = pCur; return 0; } KLDRDYLDFIND_ASSERT( pCur->pMod->cchFilename != cchFilename || kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename)); } } /* * Create a new module. */ rc = kldrDyldModCreate(pRdr, ppMod); if (rc) kLdrRdrClose(pRdr); } return rc; } /** * Searches for a file using the specified method. * * @returns 0 on success and *ppMod pointing to the new module. * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened. * @returns non-zero kLdr or OS specific status code on other failures. * @param pszName The name. * @param pszPrefix The prefix, optional. * @param pszSuffix The suffix, optional. * @param enmSearch The search method. * @param fFlags The load/search flags. * @param ppRdr Where to store the pointer to the file provider instance on success. */ static int kldrDyldFindDoSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr) { int rc; /* * Fixup search method alias. */ if (enmSearch == KLDRDYLD_SEARCH_HOST) enmSearch = KLDRDYLD_SEARCH_KLDR; /** @todo find more suitable place for this. */ /* * Apply the specified search method. */ switch (enmSearch) { case KLDRDYLD_SEARCH_KLDR: { if (!pszPrefix && kLdrDyldDefPrefix[0]) pszPrefix = kLdrDyldDefPrefix; if (!pszSuffix && kLdrDyldDefSuffix[0]) pszSuffix = kLdrDyldDefSuffix; if (kLdrDyldAppDir[0] != '\0') { rc = kldrDyldFindTryOpenPath(kLdrDyldAppDir, kLdrHlpStrLen(kLdrDyldAppDir), pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; } rc = kldrDyldFindTryOpenPath(".", 1, pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; rc = kldrDyldFindEnumeratePath(kLdrDyldPath, pszName, pszPrefix, pszSuffix, ppRdr); break; } case KLDRDYLD_SEARCH_OS2: { if (!pszSuffix) pszSuffix = ".dll"; rc = kldrDyldFindEnumeratePath(kLdrDyldOS2BeginLibpath, pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; rc = kldrDyldFindEnumeratePath(kLdrDyldOS2Libpath, pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; rc = kldrDyldFindEnumeratePath(kLdrDyldOS2EndLibpath, pszName, pszPrefix, pszSuffix, ppRdr); break; } case KLDRDYLD_SEARCH_WINDOWS: case KLDRDYLD_SEARCH_WINDOWS_ALTERED: { if (!pszSuffix) pszSuffix = ".dll"; rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsAppDir, kLdrHlpStrLen(kLdrDyldWindowsAppDir), pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; if (enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED) { rc = kldrDyldFindTryOpenPath(".", 1, pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; } rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsSystemDir, kLdrHlpStrLen(kLdrDyldWindowsSystemDir), pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsDir, kLdrHlpStrLen(kLdrDyldWindowsDir), pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; if (enmSearch == KLDRDYLD_SEARCH_WINDOWS) { rc = kldrDyldFindTryOpenPath(".", 1, pszName, pszPrefix, pszSuffix, ppRdr); if (rc != KLDR_ERR_MODULE_NOT_FOUND) break; } rc = kldrDyldFindEnumeratePath(kLdrDyldWindowsPath, pszName, pszPrefix, pszSuffix, ppRdr); break; } case KLDRDYLD_SEARCH_UNIX_COMMON: { rc = kldrDyldFindEnumeratePath(kLdrDyldUnixLibraryPath, pszName, pszPrefix, pszSuffix, ppRdr); if (rc == KLDR_ERR_MODULE_NOT_FOUND) break; rc = kldrDyldFindEnumeratePath(kLdrDyldUnixSystemLibraryPath, pszName, pszPrefix, pszSuffix, ppRdr); break; } default: KLDRDYLDFIND_ASSERT(!"invalid search method"); return KLDR_ERR_INVALID_PARAMETER; } return rc; } /** * Try open the specfied file. * * @returns 0 on success and *ppMod pointing to the new module. * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened. * @returns non-zero kLdr or OS specific status code on other failures. * @param pszFilename The filename. * @param ppRdr Where to store the pointer to the new module. */ static int kldrDyldFindTryOpen(const char *pszFilename, PPKLDRRDR ppRdr) { return KLDR_ERR_MODULE_NOT_FOUND; } /** * Composes a filename from the specified directory path, * prefix (optional), name and suffix (optional, will try with and without). * * @param pchPath The directory path - this doesn't have to be null terminated. * @param cchPath The length of the path. * @param pszName The base name. * @param pszPrefix The prefix to use. (optional) * @param pszSuffix The suffix to use. (optional) * Will try without first if the name contains a suffix already. * @param ppRdr See kldrDyldFindTryOpen. * * @returns See kldrDyldFindTryOpen */ static int kldrDyldFindTryOpenPath(const char *pchPath, size_t cchPath, const char *pszName, const char *pszPrefix, const char *pszSuffix, PPKLDRRDR ppRdr) { return KLDR_ERR_MODULE_NOT_FOUND; } /** * Enumerates the specfied path. * * @returns Any return code from the kldrDyldFindTryOpenPath() which isn't KLDR_ERR_MODULE_NOT_FOUND. * @returns KLDR_ERR_MODULE_NOT_FOUND if the end of the search path was reached. * @param pszSearchPath The search path to enumeare. * @param pszName The pszName argument for kldrDyldFindTryOpenPath. * @param pszPrefix The pszPrefix argument for kldrDyldFindTryOpenPath. * @param pszSuffix The pszSuffix argument for kldrDyldFindTryOpenPath. * @param ppRdr The ppRdr argument for kldrDyldFindTryOpenPath. */ static int kldrDyldFindEnumeratePath(const char *pszSearchPath, const char *pszName, const char *pszPrefix, const char *pszSuffix, PPKLDRRDR ppRdr) { return KLDR_ERR_MODULE_NOT_FOUND; } /** * Locates an already open module using the specified search method. * * @returns 0 and *ppMod on success, non-zero OS specific error on failure. * * @param pszName Partial or complete name, it's specific to the search method to determin which. * @param pszPrefix Prefix than can be used when searching. * @param pszSuffix Suffix than can be used when searching. * @param enmSearch The file search method to apply. * @param fFlags Search flags. * @param ppMod Where to store the file provider instance on success. */ int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod) { int rc; unsigned fOS2LibpathStrict; *ppMod = NULL; /* * Don't bother if no modules are loaded yet. */ if (!kLdrDyldHead) return KLDR_ERR_MODULE_NOT_FOUND; /* * Fixup search method alias. */ if (enmSearch == KLDRDYLD_SEARCH_HOST) enmSearch = KLDRDYLD_SEARCH_KLDR; /** @todo find more suitable place for this. */ /* * If this isn't just a filename, the caller has specified a file * that should be opened directly and not a module name to be searched for. * * In order to do the right thing we'll have to open the file and get the * correct filename for it. * * The OS/2 libpath strict method require us to find the correct DLL first. */ fOS2LibpathStrict = 0; if ( !kldrHlpIsFilenameOnly(pszName) || (fOS2LibpathStrict = ( enmSearch == KLDRDYLD_SEARCH_OS2 && kLdrDyldOS2LibpathStrict[0] == 'T') ) ) { PKLDRRDR pRdr; if (fOS2LibpathStrict) rc = kldrDyldFindDoSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr); else rc = kldrDyldFindTryOpen(pszName, &pRdr); if (!rc) { /* do a filename based search. */ const char *pszFilename = kLdrRdrName(pRdr); const size_t cchFilename = kLdrHlpStrLen(pszFilename); PKLDRDYLDMOD pCur; rc = KLDR_ERR_MODULE_NOT_FOUND; for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext) { if ( pCur->pMod->cchFilename == cchFilename && !kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename)) { *ppMod = pCur; rc = 0; break; } } kLdrRdrClose(pRdr); } } else { /* * Get default prefix and suffix. */ rc = 0; switch (enmSearch) { case KLDRDYLD_SEARCH_KLDR: if (!pszPrefix && kLdrDyldDefPrefix[0]) pszPrefix = kLdrDyldDefPrefix; if (!pszSuffix && kLdrDyldDefSuffix[0]) pszSuffix = kLdrDyldDefSuffix; break; case KLDRDYLD_SEARCH_OS2: if (!pszSuffix) pszSuffix = ".dll"; break; case KLDRDYLD_SEARCH_WINDOWS: case KLDRDYLD_SEARCH_WINDOWS_ALTERED: if (!pszSuffix) pszSuffix = ".dll"; case KLDRDYLD_SEARCH_UNIX_COMMON: break; default: KLDRDYLDFIND_ASSERT(!"invalid search method"); rc = KLDR_ERR_INVALID_PARAMETER; break; } if (!rc) { const size_t cchName = kLdrHlpStrLen(pszName); const size_t cchPrefix = pszPrefix ? kLdrHlpStrLen(pszPrefix) : 0; const size_t cchSuffix = pszSuffix ? kLdrHlpStrLen(pszSuffix) : 0; const char *pszNameSuffix = kldrHlpGetSuff(pszName); PKLDRDYLDMOD pCur = kLdrDyldHead; /* * Some of the methods are case insensitive (ASCII), others are case sensitive. * To avoid having todo indirect calls to the compare functions here, we split * ways even if it means a lot of duplicate code. */ if ( enmSearch == KLDRDYLD_SEARCH_OS2 || enmSearch == KLDRDYLD_SEARCH_WINDOWS || enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED) { const unsigned fNameHasSuffix = pszNameSuffix && kLdrHlpStrLen(pszNameSuffix) == cchSuffix && kLdrHlpMemIComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix); for (; pCur; pCur = pCur->Load.pNext) { /* match global / specific */ if ( !pCur->fGlobalOrSpecific && !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)) continue; /* match name */ if ( pCur->pMod->cchName == cchName && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName)) break; if (cchPrefix) { if ( pCur->pMod->cchName == cchName + cchPrefix && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix) && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)) break; } if (cchSuffix) { if ( pCur->pMod->cchName == cchName + cchSuffix && !kLdrHlpMemIComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix) && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName)) break; if ( fNameHasSuffix && pCur->pMod->cchName == cchName - cchSuffix && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName - cchSuffix)) break; if (cchPrefix) { if ( pCur->pMod->cchName == cchName + cchPrefix + cchSuffix && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix) && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName) && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix)) break; if ( fNameHasSuffix && pCur->pMod->cchName == cchName + cchPrefix - cchSuffix && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix) && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix)) break; } } } } else { const unsigned fNameHasSuffix = pszNameSuffix && kLdrHlpStrLen(pszNameSuffix) == cchSuffix && kLdrHlpMemComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix); for (; pCur; pCur = pCur->Load.pNext) { /* match global / specific */ if ( !pCur->fGlobalOrSpecific && !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)) continue; /* match name */ if ( pCur->pMod->cchName == cchName && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName)) break; if (cchPrefix) { if ( pCur->pMod->cchName == cchName + cchPrefix && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix) && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)) break; } if (cchSuffix) { if ( pCur->pMod->cchName == cchName + cchSuffix && !kLdrHlpMemComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix) && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName)) break; if ( fNameHasSuffix && pCur->pMod->cchName == cchName - cchSuffix && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName - cchSuffix)) break; if (cchPrefix) { if ( pCur->pMod->cchName == cchName + cchPrefix + cchSuffix && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix) && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName) && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix)) break; if ( pCur->pMod->cchName == cchName + cchPrefix - cchSuffix && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix) && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix)) break; } } } } if (pCur) { *ppMod = pCur; rc = 0; } else rc = KLDR_ERR_MODULE_NOT_FOUND; } } return rc; }