| 1 | /* $Id: kLdrDyldFind.c 2886 2006-11-18 15:01:05Z bird $ */
 | 
|---|
| 2 | /** @file
 | 
|---|
| 3 |  *
 | 
|---|
| 4 |  * kLdr - The Dynamic Loader, File Searching Methods.
 | 
|---|
| 5 |  *
 | 
|---|
| 6 |  * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
 | 
|---|
| 7 |  *
 | 
|---|
| 8 |  *
 | 
|---|
| 9 |  * This file is part of kLdr.
 | 
|---|
| 10 |  *
 | 
|---|
| 11 |  * kLdr is free software; you can redistribute it and/or modify
 | 
|---|
| 12 |  * it under the terms of the GNU General Public License as published by
 | 
|---|
| 13 |  * the Free Software Foundation; either version 2 of the License, or
 | 
|---|
| 14 |  * (at your option) any later version.
 | 
|---|
| 15 |  *
 | 
|---|
| 16 |  * kLdr is distributed in the hope that it will be useful,
 | 
|---|
| 17 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 18 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 19 |  * GNU General Public License for more details.
 | 
|---|
| 20 |  *
 | 
|---|
| 21 |  * You should have received a copy of the GNU General Public License
 | 
|---|
| 22 |  * along with kLdr; if not, write to the Free Software
 | 
|---|
| 23 |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|---|
| 24 |  *
 | 
|---|
| 25 |  */
 | 
|---|
| 26 | 
 | 
|---|
| 27 | 
 | 
|---|
| 28 | 
 | 
|---|
| 29 | /*******************************************************************************
 | 
|---|
| 30 | *   Header Files                                                               *
 | 
|---|
| 31 | *******************************************************************************/
 | 
|---|
| 32 | #ifdef __OS2__
 | 
|---|
| 33 | # define INCL_BASE
 | 
|---|
| 34 | # define INCL_ERRORS
 | 
|---|
| 35 | # include <os2.h>
 | 
|---|
| 36 | # ifndef LIBPATHSTRICT
 | 
|---|
| 37 | #  define LIBPATHSTRICT 3
 | 
|---|
| 38 | # endif
 | 
|---|
| 39 |   extern APIRET APIENTRY DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
 | 
|---|
| 40 | # define QHINF_EXEINFO       1 /* NE exeinfo. */
 | 
|---|
| 41 | # define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
 | 
|---|
| 42 | # define QHINF_READFILE      3 /* Reads from the executable file. */
 | 
|---|
| 43 | # define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
 | 
|---|
| 44 | # define QHINF_LIBPATH       5 /* Gets the entire libpath. */
 | 
|---|
| 45 | # define QHINF_FIXENTRY      6 /* NE only */
 | 
|---|
| 46 | # define QHINF_STE           7 /* NE only */
 | 
|---|
| 47 | # define QHINF_MAPSEL        8 /* NE only */
 | 
|---|
| 48 | 
 | 
|---|
| 49 | #elif defined(__WIN__)
 | 
|---|
| 50 | # include <Windows.h>
 | 
|---|
| 51 | #endif
 | 
|---|
| 52 | 
 | 
|---|
| 53 | #include <kLdr.h>
 | 
|---|
| 54 | #include "kLdrHlp.h"
 | 
|---|
| 55 | #include "kLdrInternal.h"
 | 
|---|
| 56 | 
 | 
|---|
| 57 | /*******************************************************************************
 | 
|---|
| 58 | *   Defined Constants And Macros                                               *
 | 
|---|
| 59 | *******************************************************************************/
 | 
|---|
| 60 | /** @def KLDRDYLDFIND_STRICT
 | 
|---|
| 61 |  * Define KLDRDYLDFIND_STRICT to enabled strict checks in kLdrDyldFind. */
 | 
|---|
| 62 | #define KLDRDYLDFIND_STRICT 1
 | 
|---|
| 63 | 
 | 
|---|
| 64 | /** @def KLDRDYLDFIND_ASSERT
 | 
|---|
| 65 |  * Assert that an expression is true when KLDRDYLDFIND_STRICT is defined.
 | 
|---|
| 66 |  */
 | 
|---|
| 67 | #ifdef KLDRDYLDFIND_STRICT
 | 
|---|
| 68 | # define KLDRDYLDFIND_ASSERT(expr)  kldrHlpAssert(expr)
 | 
|---|
| 69 | #else
 | 
|---|
| 70 | # define KLDRDYLDFIND_ASSERT(expr)  do {} while (0)
 | 
|---|
| 71 | #endif
 | 
|---|
| 72 | 
 | 
|---|
| 73 | 
 | 
|---|
| 74 | /*******************************************************************************
 | 
|---|
| 75 | *   Structures and Typedefs                                                    *
 | 
|---|
| 76 | *******************************************************************************/
 | 
|---|
| 77 | /**
 | 
|---|
| 78 |  * Search arguments.
 | 
|---|
| 79 |  * This avoids a bunch of unnecessary string lengths and calculations.
 | 
|---|
| 80 |  */
 | 
|---|
| 81 | typedef struct KLDRDYLDFINDARGS
 | 
|---|
| 82 | {
 | 
|---|
| 83 |     const char *pszName;
 | 
|---|
| 84 |     size_t      cchName;
 | 
|---|
| 85 | 
 | 
|---|
| 86 |     const char *pszPrefix;
 | 
|---|
| 87 |     size_t      cchPrefix;
 | 
|---|
| 88 | 
 | 
|---|
| 89 |     const char *pszSuffix;
 | 
|---|
| 90 |     size_t      cchSuffix;
 | 
|---|
| 91 | 
 | 
|---|
| 92 |     size_t      cchMaxLength;
 | 
|---|
| 93 | 
 | 
|---|
| 94 |     KLDRDYLDSEARCH  enmSearch;
 | 
|---|
| 95 |     uint32_t        fFlags;
 | 
|---|
| 96 |     PPKLDRRDR       ppRdr;
 | 
|---|
| 97 | } KLDRDYLDFINDARGS, *PKLDRDYLDFINDARGS;
 | 
|---|
| 98 | 
 | 
|---|
| 99 | typedef const KLDRDYLDFINDARGS *PCKLDRDYLDFINDARGS;
 | 
|---|
| 100 | 
 | 
|---|
| 101 | 
 | 
|---|
| 102 | /*******************************************************************************
 | 
|---|
| 103 | *   Global Variables                                                           *
 | 
|---|
| 104 | *******************************************************************************/
 | 
|---|
| 105 | /** @name The kLdr search method parameters.
 | 
|---|
| 106 |  * @{ */
 | 
|---|
| 107 | /** The kLdr EXE search path.
 | 
|---|
| 108 |  * During EXE searching the it's initialized with the values of the KLDR_PATH and
 | 
|---|
| 109 |  * the PATH env.vars. Both ';' and ':' can be used as separators.
 | 
|---|
| 110 |  */
 | 
|---|
| 111 | char            kLdrDyldExePath[8192];
 | 
|---|
| 112 | /** The kLdr DLL search path.
 | 
|---|
| 113 |  * During initialization the KLDR_LIBRARY_PATH env.var. and the path in the
 | 
|---|
| 114 |  * executable stub is appended. Both ';' and ':' can be used as separators.
 | 
|---|
| 115 |  */
 | 
|---|
| 116 | char            kLdrDyldLibraryPath[8192];
 | 
|---|
| 117 | /** The kLdr application directory.
 | 
|---|
| 118 |  * This is initialized when the executable is 'loaded' or by a kLdr user.
 | 
|---|
| 119 |  */
 | 
|---|
| 120 | char            kLdrDyldAppDir[260];
 | 
|---|
| 121 | /** The default kLdr DLL prefix.
 | 
|---|
| 122 |  * This is initialized with the KLDR_DEF_PREFIX env.var. + the prefix in the executable stub.
 | 
|---|
| 123 |  */
 | 
|---|
| 124 | char            kLdrDyldDefPrefix[16];
 | 
|---|
| 125 | /** The default kLdr DLL suffix.
 | 
|---|
| 126 |  * This is initialized with the KLDR_DEF_SUFFIX env.var. + the prefix in the executable stub.
 | 
|---|
| 127 |  */
 | 
|---|
| 128 | char            kLdrDyldDefSuffix[16];
 | 
|---|
| 129 | /** @} */
 | 
|---|
| 130 | 
 | 
|---|
| 131 | 
 | 
|---|
| 132 | /** @name The OS/2 search method parameters.
 | 
|---|
| 133 |  * @{
 | 
|---|
| 134 |  */
 | 
|---|
| 135 | /** The OS/2 LIBPATH.
 | 
|---|
| 136 |  * This is queried from the os2krnl on OS/2, while on other systems initialized using
 | 
|---|
| 137 |  * the KLDR_OS2_LIBPATH env.var.
 | 
|---|
| 138 |  */
 | 
|---|
| 139 | char            kLdrDyldOS2Libpath[2048];
 | 
|---|
| 140 | /** The OS/2 LIBPATHSTRICT ("T" or '\0').
 | 
|---|
| 141 |  * This is queried from the os2krnl on OS/2, while on other systems initialized using
 | 
|---|
| 142 |  * the KLDR_OS2_LIBPATHSTRICT env.var.
 | 
|---|
| 143 |  */
 | 
|---|
| 144 | char            kLdrDyldOS2LibpathStrict[8];
 | 
|---|
| 145 | /** The OS/2 BEGINLIBPATH.
 | 
|---|
| 146 |  * This is queried from the os2krnl on OS/2, while on other systems initialized using
 | 
|---|
| 147 |  * the KLDR_OS2_BEGINLIBPATH env.var.
 | 
|---|
| 148 |  */
 | 
|---|
| 149 | char            kLdrDyldOS2BeginLibpath[2048];
 | 
|---|
| 150 | /** The OS/2 ENDLIBPATH.
 | 
|---|
| 151 |  * This is queried from the os2krnl on OS/2, while on other systems initialized using
 | 
|---|
| 152 |  * the KLDR_OS2_ENDLIBPATH env.var.
 | 
|---|
| 153 |  */
 | 
|---|
| 154 | char            kLdrDyldOS2EndLibpath[2048];
 | 
|---|
| 155 | /** @} */
 | 
|---|
| 156 | 
 | 
|---|
| 157 | 
 | 
|---|
| 158 | /** @name The Windows search method parameters.
 | 
|---|
| 159 |  * @{ */
 | 
|---|
| 160 | /** The Windows application directory.
 | 
|---|
| 161 |  * This is initialized when the executable is 'loaded' or by a kLdr user.
 | 
|---|
| 162 |  */
 | 
|---|
| 163 | char            kLdrDyldWindowsAppDir[260];
 | 
|---|
| 164 | /** The Windows system directory.
 | 
|---|
| 165 |  * This is queried from the Win32/64 subsystem on Windows, while on other systems
 | 
|---|
| 166 |  * initialized using the KLDR_WINDOWS_SYSTEM_DIR env.var.
 | 
|---|
| 167 |  */
 | 
|---|
| 168 | char            kLdrDyldWindowsSystemDir[260];
 | 
|---|
| 169 | /** The Windows directory.
 | 
|---|
| 170 |  * This is queried from the Win32/64 subsystem on Windows, while on other systems
 | 
|---|
| 171 |  * initialized using the KLDR_WINDOWS_DIR env.var.
 | 
|---|
| 172 |  */
 | 
|---|
| 173 | char            kLdrDyldWindowsDir[260];
 | 
|---|
| 174 | /** The Windows path.
 | 
|---|
| 175 |  * This is queried from the PATH env.var. on Windows, while on other systems
 | 
|---|
| 176 |  * initialized using the KLDR_WINDOWS_PATH env.var. and falling back on
 | 
|---|
| 177 |  * the PATH env.var. if it wasn't found.
 | 
|---|
| 178 |  */
 | 
|---|
| 179 | char            kLdrDyldWindowsPath[8192];
 | 
|---|
| 180 | /** @} */
 | 
|---|
| 181 | 
 | 
|---|
| 182 | 
 | 
|---|
| 183 | /** @name The Common Unix search method parameters.
 | 
|---|
| 184 |  * @{
 | 
|---|
| 185 |  */
 | 
|---|
| 186 | /** The Common Unix library path.
 | 
|---|
| 187 |  * Initialized from the env.var. KLDR_UNIX_LIBRARY_PATH or LD_LIBRARY_PATH or the
 | 
|---|
| 188 |  * former wasn't found.
 | 
|---|
| 189 |  */
 | 
|---|
| 190 | char            kLdrDyldUnixLibraryPath[8192];
 | 
|---|
| 191 | /** The Common Unix system library path. */
 | 
|---|
| 192 | char            kLdrDyldUnixSystemLibraryPath[1024] = "/lib;/usr/lib";
 | 
|---|
| 193 | /** @} */
 | 
|---|
| 194 | 
 | 
|---|
| 195 | /** @todo Deal with DT_RUNPATH and DT_RPATH. */
 | 
|---|
| 196 | /** @todo ld.so.cache? */
 | 
|---|
| 197 | 
 | 
|---|
| 198 | 
 | 
|---|
| 199 | /*******************************************************************************
 | 
|---|
| 200 | *   Internal Functions                                                         *
 | 
|---|
| 201 | *******************************************************************************/
 | 
|---|
| 202 | static int kldrDyldFindDoDllSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
 | 
|---|
| 203 |                                 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr);
 | 
|---|
| 204 | static int kldrDyldFindDoExeSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
 | 
|---|
| 205 |                                    KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr);
 | 
|---|
| 206 | static int kldrDyldFindTryOpen(const char *pszFilename, PPKLDRRDR ppRdr);
 | 
|---|
| 207 | static int kldrDyldFindTryOpenPath(const char *pchPath, size_t cchPath, PCKLDRDYLDFINDARGS pArgs);
 | 
|---|
| 208 | static int kldrDyldFindEnumeratePath(const char *pszSearchPath, PCKLDRDYLDFINDARGS pArgs);
 | 
|---|
| 209 | static int kldrDyldFindGetDefaults(KLDRDYLDSEARCH *penmSearch, const char **pszPrefix,
 | 
|---|
| 210 |                                    const char **pszSuffix, const char *pszName, uint32_t fFlags);
 | 
|---|
| 211 | 
 | 
|---|
| 212 | 
 | 
|---|
| 213 | /**
 | 
|---|
| 214 |  * Initializes the find paths.
 | 
|---|
| 215 |  *
 | 
|---|
| 216 |  * @returns 0 on success, non-zero on failure.
 | 
|---|
| 217 |  */
 | 
|---|
| 218 | int kldrDyldFindInit(void)
 | 
|---|
| 219 | {
 | 
|---|
| 220 |     size_t  cch;
 | 
|---|
| 221 |     int     rc;
 | 
|---|
| 222 |     char    szTmp[sizeof(kLdrDyldDefSuffix)];
 | 
|---|
| 223 | 
 | 
|---|
| 224 |     /*
 | 
|---|
| 225 |      * The kLdr search parameters.
 | 
|---|
| 226 |      */
 | 
|---|
| 227 |     rc = kldrHlpGetEnv("KLDR_LIBRARY_PATH", kLdrDyldLibraryPath, sizeof(kLdrDyldLibraryPath));
 | 
|---|
| 228 |     rc = kldrHlpGetEnv("KLDR_DEF_PREFIX", szTmp, sizeof(szTmp));
 | 
|---|
| 229 |     if (!rc)
 | 
|---|
| 230 |         kLdrHlpMemCopy(kLdrDyldDefPrefix, szTmp, sizeof(szTmp));
 | 
|---|
| 231 |     rc = kldrHlpGetEnv("KLDR_DEF_SUFFIX", szTmp, sizeof(szTmp));
 | 
|---|
| 232 |     if (!rc)
 | 
|---|
| 233 |         kLdrHlpMemCopy(kLdrDyldDefSuffix, szTmp, sizeof(szTmp));
 | 
|---|
| 234 | 
 | 
|---|
| 235 |     /*
 | 
|---|
| 236 |      * The OS/2 search parameters.
 | 
|---|
| 237 |      */
 | 
|---|
| 238 | #ifdef __OS2__
 | 
|---|
| 239 |     rc = DosQueryHeaderInfo(NULLHANDLE, 0, kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath), QHINF_LIBPATH);
 | 
|---|
| 240 |     if (rc)
 | 
|---|
| 241 |         return rc;
 | 
|---|
| 242 |     rc = DosQueryExtLIBPATH((PSZ)kLdrDyldOS2LibpathStrict, LIBPATHSTRICT);
 | 
|---|
| 243 |     if (rc)
 | 
|---|
| 244 |         kLdrDyldOS2LibpathStrict[0] = '\0';
 | 
|---|
| 245 |     rc = DosQueryExtLIBPATH((PSZ)kLdrDyldOS2BeginLibpath, BEGIN_LIBPATH);
 | 
|---|
| 246 |     if (rc)
 | 
|---|
| 247 |         kLdrDyldOS2BeginLibpath[0] = '\0';
 | 
|---|
| 248 |     rc = DosQueryExtLIBPATH((PSZ)kLdrDyldOS2EndLibpath, END_LIBPATH);
 | 
|---|
| 249 |     if (rc)
 | 
|---|
| 250 |         kLdrDyldOS2EndLibpath[0] = '\0';
 | 
|---|
| 251 | 
 | 
|---|
| 252 | #else
 | 
|---|
| 253 |     kldrHlpGetEnv("KLDR_OS2_LIBPATH", kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath));
 | 
|---|
| 254 |     kldrHlpGetEnv("KLDR_OS2_LIBPATHSTRICT", kLdrDyldOS2LibpathStrict, sizeof(kLdrDyldOS2LibpathStrict));
 | 
|---|
| 255 |     if (    kLdrDyldOS2LibpathStrict[0] == 'T'
 | 
|---|
| 256 |         ||  kLdrDyldOS2LibpathStrict[0] == 't')
 | 
|---|
| 257 |         kLdrDyldOS2LibpathStrict[0] = 'T';
 | 
|---|
| 258 |     else
 | 
|---|
| 259 |         kLdrDyldOS2LibpathStrict[0] = '\0';
 | 
|---|
| 260 |     kLdrDyldOS2LibpathStrict[1] = '\0';
 | 
|---|
| 261 |     kldrHlpGetEnv("KLDR_OS2_BEGINLIBPATH", kLdrDyldOS2BeginLibpath, sizeof(kLdrDyldOS2BeginLibpath));
 | 
|---|
| 262 |     kldrHlpGetEnv("KLDR_OS2_ENDLIBPATH", kLdrDyldOS2EndLibpath, sizeof(kLdrDyldOS2EndLibpath));
 | 
|---|
| 263 | #endif
 | 
|---|
| 264 | 
 | 
|---|
| 265 |     /*
 | 
|---|
| 266 |      * The windows search parameters.
 | 
|---|
| 267 |      */
 | 
|---|
| 268 | #if defined(__WIN__)
 | 
|---|
| 269 |     cch = GetSystemDirectory(kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir));
 | 
|---|
| 270 |     if (cch >= sizeof(kLdrDyldWindowsSystemDir))
 | 
|---|
| 271 |         return (rc = GetLastError()) ? rc : -1;
 | 
|---|
| 272 |     cch = GetWindowsDirectory(kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir));
 | 
|---|
| 273 |     if (cch >= sizeof(kLdrDyldWindowsDir))
 | 
|---|
| 274 |         return (rc = GetLastError()) ? rc : -1;
 | 
|---|
| 275 |     kldrHlpGetEnv("PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
 | 
|---|
| 276 | #else
 | 
|---|
| 277 |     kldrHlpGetEnv("KLDR_WINDOWS_SYSTEM_DIR", kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir));
 | 
|---|
| 278 |     kldrHlpGetEnv("KLDR_WINDOWS_DIR", kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir));
 | 
|---|
| 279 |     rc = kldrHlpGetEnv("KLDR_WINDOWS_PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
 | 
|---|
| 280 |     if (rc)
 | 
|---|
| 281 |         kldrHlpGetEnv("PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
 | 
|---|
| 282 | #endif
 | 
|---|
| 283 | 
 | 
|---|
| 284 |     /*
 | 
|---|
| 285 |      * The Unix search parameters.
 | 
|---|
| 286 |      */
 | 
|---|
| 287 |     rc = kldrHlpGetEnv("KLDR_UNIX_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath));
 | 
|---|
| 288 |     if (rc)
 | 
|---|
| 289 |         kldrHlpGetEnv("LD_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath));
 | 
|---|
| 290 | 
 | 
|---|
| 291 |     (void)cch;
 | 
|---|
| 292 |     return 0;
 | 
|---|
| 293 | }
 | 
|---|
| 294 | 
 | 
|---|
| 295 | 
 | 
|---|
| 296 | /**
 | 
|---|
| 297 |  * Lazily initialize the two application directory paths.
 | 
|---|
| 298 |  */
 | 
|---|
| 299 | static void kldrDyldFindLazyInitAppDir(void)
 | 
|---|
| 300 | {
 | 
|---|
| 301 |     if (!kLdrDyldAppDir[0])
 | 
|---|
| 302 |     {
 | 
|---|
| 303 | #if defined(__OS2__)
 | 
|---|
| 304 |         PPIB pPib;
 | 
|---|
| 305 |         PTIB pTib;
 | 
|---|
| 306 |         APIRET rc;
 | 
|---|
| 307 | 
 | 
|---|
| 308 |         DosGetInfoBlocks(&pTib, &pPib);
 | 
|---|
| 309 |         rc = DosQueryModuleName(pPib->pib_hmte, sizeof(kLdrDyldAppDir), kLdrDyldAppDir);
 | 
|---|
| 310 |         if (!rc)
 | 
|---|
| 311 |         {
 | 
|---|
| 312 |             *kldrHlpGetFilename(kLdrDyldAppDir) = '\0';
 | 
|---|
| 313 |              kLdrHlpMemCopy(kLdrDyldWindowsAppDir, kLdrDyldAppDir, sizeof(kLdrDyldAppDir));
 | 
|---|
| 314 |         }
 | 
|---|
| 315 |         else
 | 
|---|
| 316 |         {
 | 
|---|
| 317 |             kLdrDyldWindowsAppDir[0] = kLdrDyldAppDir[0] = '.';
 | 
|---|
| 318 |             kLdrDyldWindowsAppDir[1] = kLdrDyldAppDir[1] = '\0';
 | 
|---|
| 319 |         }
 | 
|---|
| 320 | 
 | 
|---|
| 321 | 
 | 
|---|
| 322 | #elif defined(__WIN__)
 | 
|---|
| 323 |         DWORD dwSize = GetModuleFileName(NULL /* the executable */, kLdrDyldAppDir, sizeof(kLdrDyldAppDir));
 | 
|---|
| 324 |         if (dwSize > 0)
 | 
|---|
| 325 |         {
 | 
|---|
| 326 |             *kldrHlpGetFilename(kLdrDyldAppDir) = '\0';
 | 
|---|
| 327 |             kLdrHlpMemCopy(kLdrDyldWindowsAppDir, kLdrDyldAppDir, sizeof(kLdrDyldAppDir));
 | 
|---|
| 328 |         }
 | 
|---|
| 329 |         else
 | 
|---|
| 330 |         {
 | 
|---|
| 331 |             kLdrDyldWindowsAppDir[0] = kLdrDyldAppDir[0] = '.';
 | 
|---|
| 332 |             kLdrDyldWindowsAppDir[1] = kLdrDyldAppDir[1] = '\0';
 | 
|---|
| 333 |         }
 | 
|---|
| 334 | 
 | 
|---|
| 335 | #else
 | 
|---|
| 336 | # error "Port me"
 | 
|---|
| 337 | #endif
 | 
|---|
| 338 |     }
 | 
|---|
| 339 | }
 | 
|---|
| 340 | 
 | 
|---|
| 341 | 
 | 
|---|
| 342 | /**
 | 
|---|
| 343 |  * Locates and opens a module using the specified search method.
 | 
|---|
| 344 |  *
 | 
|---|
| 345 |  * @returns 0 and *ppMod on success, non-zero OS specific error on failure.
 | 
|---|
| 346 |  *
 | 
|---|
| 347 |  * @param   pszName         Partial or complete name, it's specific to the search method to determin which.
 | 
|---|
| 348 |  * @param   pszPrefix       Prefix than can be used when searching.
 | 
|---|
| 349 |  * @param   pszSuffix       Suffix than can be used when searching.
 | 
|---|
| 350 |  * @param   enmSearch       The file search method to apply.
 | 
|---|
| 351 |  * @param   fFlags          Search flags.
 | 
|---|
| 352 |  * @param   ppMod           Where to store the file provider instance on success.
 | 
|---|
| 353 |  */
 | 
|---|
| 354 | int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
 | 
|---|
| 355 |                           KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod)
 | 
|---|
| 356 | {
 | 
|---|
| 357 |     int rc;
 | 
|---|
| 358 |     PKLDRRDR pRdr = NULL;
 | 
|---|
| 359 | 
 | 
|---|
| 360 |     *ppMod = NULL;
 | 
|---|
| 361 | 
 | 
|---|
| 362 |     /*
 | 
|---|
| 363 |      * If this isn't just a filename, we the caller has specified a file
 | 
|---|
| 364 |      * that should be opened directly and not a module name to be searched for.
 | 
|---|
| 365 |      */
 | 
|---|
| 366 |     if (!kldrHlpIsFilenameOnly(pszName))
 | 
|---|
| 367 |         rc = kldrDyldFindTryOpen(pszName, &pRdr);
 | 
|---|
| 368 |     else if (!(fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE))
 | 
|---|
| 369 |         rc = kldrDyldFindDoDllSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
 | 
|---|
| 370 |     else
 | 
|---|
| 371 |         rc = kldrDyldFindDoExeSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
 | 
|---|
| 372 |     if (!rc)
 | 
|---|
| 373 |     {
 | 
|---|
| 374 | #ifdef KLDRDYLDFIND_STRICT
 | 
|---|
| 375 |         /* Sanity check of kldrDyldFindExistingModule. */
 | 
|---|
| 376 |         if (fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)
 | 
|---|
| 377 |         {
 | 
|---|
| 378 |             const char     *pszFilename = kLdrRdrName(pRdr);
 | 
|---|
| 379 |             const size_t    cchFilename = kLdrHlpStrLen(pszFilename);
 | 
|---|
| 380 |             PKLDRDYLDMOD    pCur;
 | 
|---|
| 381 |             for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
 | 
|---|
| 382 |                 KLDRDYLDFIND_ASSERT(    pCur->pMod->cchFilename != cchFilename
 | 
|---|
| 383 |                                     ||  kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename));
 | 
|---|
| 384 |         }
 | 
|---|
| 385 | #endif
 | 
|---|
| 386 | 
 | 
|---|
| 387 |         /*
 | 
|---|
| 388 |          * Check for matching non-global modules that should be promoted.
 | 
|---|
| 389 |          */
 | 
|---|
| 390 |         if (!(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
 | 
|---|
| 391 |         {
 | 
|---|
| 392 |             const char     *pszFilename = kLdrRdrName(pRdr);
 | 
|---|
| 393 |             const size_t    cchFilename = kLdrHlpStrLen(pszFilename);
 | 
|---|
| 394 |             PKLDRDYLDMOD    pCur;
 | 
|---|
| 395 |             for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
 | 
|---|
| 396 |             {
 | 
|---|
| 397 |                 if (    !pCur->fGlobalOrSpecific
 | 
|---|
| 398 |                     &&  pCur->pMod->cchFilename == cchFilename
 | 
|---|
| 399 |                     &&  !kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename))
 | 
|---|
| 400 |                 {
 | 
|---|
| 401 |                     kLdrRdrClose(pRdr);
 | 
|---|
| 402 |                     kldrDyldModMarkGlobal(pCur);
 | 
|---|
| 403 |                     *ppMod = pCur;
 | 
|---|
| 404 |                     return 0;
 | 
|---|
| 405 |                 }
 | 
|---|
| 406 |                 KLDRDYLDFIND_ASSERT(    pCur->pMod->cchFilename != cchFilename
 | 
|---|
| 407 |                                     ||  kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename));
 | 
|---|
| 408 |             }
 | 
|---|
| 409 |         }
 | 
|---|
| 410 | 
 | 
|---|
| 411 |         /*
 | 
|---|
| 412 |          * Create a new module.
 | 
|---|
| 413 |          */
 | 
|---|
| 414 |         rc = kldrDyldModCreate(pRdr, fFlags, ppMod);
 | 
|---|
| 415 |         if (rc)
 | 
|---|
| 416 |             kLdrRdrClose(pRdr);
 | 
|---|
| 417 |     }
 | 
|---|
| 418 |     return rc;
 | 
|---|
| 419 | }
 | 
|---|
| 420 | 
 | 
|---|
| 421 | 
 | 
|---|
| 422 | /**
 | 
|---|
| 423 |  * Searches for a DLL file using the specified method.
 | 
|---|
| 424 |  *
 | 
|---|
| 425 |  * @returns 0 on success and *ppMod pointing to the new module.
 | 
|---|
| 426 |  * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
 | 
|---|
| 427 |  * @returns non-zero kLdr or OS specific status code on other failures.
 | 
|---|
| 428 |  * @param   pszName     The name.
 | 
|---|
| 429 |  * @param   pszPrefix   The prefix, optional.
 | 
|---|
| 430 |  * @param   pszSuffix   The suffix, optional.
 | 
|---|
| 431 |  * @param   enmSearch   The search method.
 | 
|---|
| 432 |  * @param   fFlags      The load/search flags.
 | 
|---|
| 433 |  * @param   ppRdr       Where to store the pointer to the file provider instance on success.
 | 
|---|
| 434 |  */
 | 
|---|
| 435 | static int kldrDyldFindDoDllSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
 | 
|---|
| 436 |                                    KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr)
 | 
|---|
| 437 | {
 | 
|---|
| 438 |     int rc;
 | 
|---|
| 439 |     KLDRDYLDFINDARGS Args;
 | 
|---|
| 440 | 
 | 
|---|
| 441 |     /*
 | 
|---|
| 442 |      * Initialize the argument structure and resolve defaults.
 | 
|---|
| 443 |      */
 | 
|---|
| 444 |     Args.enmSearch = enmSearch;
 | 
|---|
| 445 |     Args.pszPrefix = pszPrefix;
 | 
|---|
| 446 |     Args.pszSuffix = pszSuffix;
 | 
|---|
| 447 |     rc = kldrDyldFindGetDefaults(&Args.enmSearch, &Args.pszPrefix, &Args.pszSuffix, pszName, fFlags);
 | 
|---|
| 448 |     if (rc)
 | 
|---|
| 449 |         return rc;
 | 
|---|
| 450 |     Args.pszName = pszName;
 | 
|---|
| 451 |     Args.cchName = kLdrHlpStrLen(pszName);
 | 
|---|
| 452 |     Args.cchPrefix = Args.pszPrefix ? kLdrHlpStrLen(Args.pszPrefix) : 0;
 | 
|---|
| 453 |     Args.cchSuffix = Args.pszSuffix ? kLdrHlpStrLen(Args.pszSuffix) : 0;
 | 
|---|
| 454 |     Args.cchMaxLength = Args.cchName + Args.cchSuffix + Args.cchPrefix;
 | 
|---|
| 455 |     Args.fFlags = fFlags;
 | 
|---|
| 456 |     Args.ppRdr = ppRdr;
 | 
|---|
| 457 | 
 | 
|---|
| 458 |     /*
 | 
|---|
| 459 |      * Apply the specified search method.
 | 
|---|
| 460 |      */
 | 
|---|
| 461 | /** @todo get rid of the strlen() on the various paths here! */
 | 
|---|
| 462 |     switch (Args.enmSearch)
 | 
|---|
| 463 |     {
 | 
|---|
| 464 |         case KLDRDYLD_SEARCH_KLDR:
 | 
|---|
| 465 |         {
 | 
|---|
| 466 |             kldrDyldFindLazyInitAppDir();
 | 
|---|
| 467 |             if (kLdrDyldAppDir[0] != '\0')
 | 
|---|
| 468 |             {
 | 
|---|
| 469 |                 rc = kldrDyldFindTryOpenPath(kLdrDyldAppDir, kLdrHlpStrLen(kLdrDyldAppDir), &Args);
 | 
|---|
| 470 |                 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 471 |                     break;
 | 
|---|
| 472 |             }
 | 
|---|
| 473 |             rc = kldrDyldFindTryOpenPath(".", 1, &Args);
 | 
|---|
| 474 |             if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 475 |                 break;
 | 
|---|
| 476 |             rc = kldrDyldFindEnumeratePath(kLdrDyldLibraryPath, &Args);
 | 
|---|
| 477 |             break;
 | 
|---|
| 478 |         }
 | 
|---|
| 479 | 
 | 
|---|
| 480 |         case KLDRDYLD_SEARCH_OS2:
 | 
|---|
| 481 |         {
 | 
|---|
| 482 |             rc = kldrDyldFindEnumeratePath(kLdrDyldOS2BeginLibpath, &Args);
 | 
|---|
| 483 |             if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 484 |                 break;
 | 
|---|
| 485 |             rc = kldrDyldFindEnumeratePath(kLdrDyldOS2Libpath, &Args);
 | 
|---|
| 486 |             if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 487 |                 break;
 | 
|---|
| 488 |             rc = kldrDyldFindEnumeratePath(kLdrDyldOS2EndLibpath, &Args);
 | 
|---|
| 489 |             break;
 | 
|---|
| 490 |         }
 | 
|---|
| 491 | 
 | 
|---|
| 492 |         case KLDRDYLD_SEARCH_WINDOWS:
 | 
|---|
| 493 |         case KLDRDYLD_SEARCH_WINDOWS_ALTERED:
 | 
|---|
| 494 |         {
 | 
|---|
| 495 |             kldrDyldFindLazyInitAppDir();
 | 
|---|
| 496 |             rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsAppDir, kLdrHlpStrLen(kLdrDyldWindowsAppDir), &Args);
 | 
|---|
| 497 |             if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 498 |                 break;
 | 
|---|
| 499 |             if (Args.enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED)
 | 
|---|
| 500 |             {
 | 
|---|
| 501 |                 rc = kldrDyldFindTryOpenPath(".", 1, &Args);
 | 
|---|
| 502 |                 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 503 |                     break;
 | 
|---|
| 504 |             }
 | 
|---|
| 505 |             rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsSystemDir, kLdrHlpStrLen(kLdrDyldWindowsSystemDir), &Args);
 | 
|---|
| 506 |             if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 507 |                 break;
 | 
|---|
| 508 |             rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsDir, kLdrHlpStrLen(kLdrDyldWindowsDir), &Args);
 | 
|---|
| 509 |             if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 510 |                 break;
 | 
|---|
| 511 |             if (Args.enmSearch == KLDRDYLD_SEARCH_WINDOWS)
 | 
|---|
| 512 |             {
 | 
|---|
| 513 |                 rc = kldrDyldFindTryOpenPath(".", 1, &Args);
 | 
|---|
| 514 |                 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 515 |                     break;
 | 
|---|
| 516 |             }
 | 
|---|
| 517 |             rc = kldrDyldFindEnumeratePath(kLdrDyldWindowsPath, &Args);
 | 
|---|
| 518 |             break;
 | 
|---|
| 519 |         }
 | 
|---|
| 520 | 
 | 
|---|
| 521 |         case KLDRDYLD_SEARCH_UNIX_COMMON:
 | 
|---|
| 522 |         {
 | 
|---|
| 523 |             rc = kldrDyldFindEnumeratePath(kLdrDyldUnixLibraryPath, &Args);
 | 
|---|
| 524 |             if (rc == KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 525 |                 break;
 | 
|---|
| 526 |             rc = kldrDyldFindEnumeratePath(kLdrDyldUnixSystemLibraryPath, &Args);
 | 
|---|
| 527 |             break;
 | 
|---|
| 528 |         }
 | 
|---|
| 529 | 
 | 
|---|
| 530 |         default: kldrHlpAssert(!"internal error"); return -1;
 | 
|---|
| 531 |     }
 | 
|---|
| 532 |     return rc;
 | 
|---|
| 533 | }
 | 
|---|
| 534 | 
 | 
|---|
| 535 | 
 | 
|---|
| 536 | /**
 | 
|---|
| 537 |  * Searches for an EXE file using the specified method.
 | 
|---|
| 538 |  *
 | 
|---|
| 539 |  * @returns 0 on success and *ppMod pointing to the new module.
 | 
|---|
| 540 |  * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
 | 
|---|
| 541 |  * @returns non-zero kLdr or OS specific status code on other failures.
 | 
|---|
| 542 |  * @param   pszName     The name.
 | 
|---|
| 543 |  * @param   pszPrefix   The prefix, optional.
 | 
|---|
| 544 |  * @param   pszSuffix   The suffix, optional.
 | 
|---|
| 545 |  * @param   enmSearch   The search method.
 | 
|---|
| 546 |  * @param   fFlags      The load/search flags.
 | 
|---|
| 547 |  * @param   ppRdr       Where to store the pointer to the file provider instance on success.
 | 
|---|
| 548 |  */
 | 
|---|
| 549 | static int kldrDyldFindDoExeSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
 | 
|---|
| 550 |                                    KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr)
 | 
|---|
| 551 | {
 | 
|---|
| 552 |     int rc;
 | 
|---|
| 553 |     KLDRDYLDFINDARGS Args;
 | 
|---|
| 554 | 
 | 
|---|
| 555 |     /*
 | 
|---|
| 556 |      * Initialize the argument structure and resolve defaults.
 | 
|---|
| 557 |      */
 | 
|---|
| 558 |     Args.enmSearch = enmSearch;
 | 
|---|
| 559 |     Args.pszPrefix = pszPrefix;
 | 
|---|
| 560 |     Args.pszSuffix = pszSuffix;
 | 
|---|
| 561 |     rc = kldrDyldFindGetDefaults(&Args.enmSearch, &Args.pszPrefix, &Args.pszSuffix, pszName, fFlags);
 | 
|---|
| 562 |     if (rc)
 | 
|---|
| 563 |         return rc;
 | 
|---|
| 564 |     Args.pszName = pszName;
 | 
|---|
| 565 |     Args.cchName = kLdrHlpStrLen(pszName);
 | 
|---|
| 566 |     Args.cchPrefix = Args.pszPrefix ? kLdrHlpStrLen(Args.pszPrefix) : 0;
 | 
|---|
| 567 |     Args.cchSuffix = Args.pszSuffix ? kLdrHlpStrLen(Args.pszSuffix) : 0;
 | 
|---|
| 568 |     Args.cchMaxLength = Args.cchName + Args.cchSuffix + Args.cchPrefix;
 | 
|---|
| 569 |     Args.fFlags = fFlags;
 | 
|---|
| 570 |     Args.ppRdr = ppRdr;
 | 
|---|
| 571 | 
 | 
|---|
| 572 |     /*
 | 
|---|
| 573 |      * If we're bootstrapping a process, we'll start by looking in the
 | 
|---|
| 574 |      * application directory and the check out the path.
 | 
|---|
| 575 |      */
 | 
|---|
| 576 |     if (g_fBootstrapping)
 | 
|---|
| 577 |     {
 | 
|---|
| 578 |         kldrDyldFindLazyInitAppDir();
 | 
|---|
| 579 |         if (kLdrDyldAppDir[0] != '\0')
 | 
|---|
| 580 |         {
 | 
|---|
| 581 |             rc = kldrDyldFindTryOpenPath(kLdrDyldAppDir, kLdrHlpStrLen(kLdrDyldAppDir), &Args);
 | 
|---|
| 582 |             if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 583 |                 return rc;
 | 
|---|
| 584 |         }
 | 
|---|
| 585 |     }
 | 
|---|
| 586 | 
 | 
|---|
| 587 |     /*
 | 
|---|
| 588 |      * Search the EXE search path. Initialize it the first time around.
 | 
|---|
| 589 |      */
 | 
|---|
| 590 |     if (!kLdrDyldExePath[0])
 | 
|---|
| 591 |     {
 | 
|---|
| 592 |         size_t cch;
 | 
|---|
| 593 |         kldrHlpGetEnv("KLDR_EXE_PATH", kLdrDyldExePath, sizeof(kLdrDyldExePath) - 10);
 | 
|---|
| 594 |         cch = kLdrHlpStrLen(kLdrDyldExePath);
 | 
|---|
| 595 |         kLdrDyldExePath[cch++] = ';';
 | 
|---|
| 596 |         kldrHlpGetEnv("PATH", &kLdrDyldExePath[cch], sizeof(kLdrDyldExePath) - cch);
 | 
|---|
| 597 |     }
 | 
|---|
| 598 |     return kldrDyldFindEnumeratePath(kLdrDyldExePath, &Args);
 | 
|---|
| 599 | }
 | 
|---|
| 600 | 
 | 
|---|
| 601 | 
 | 
|---|
| 602 | /**
 | 
|---|
| 603 |  * Try open the specfied file.
 | 
|---|
| 604 |  *
 | 
|---|
| 605 |  * @returns 0 on success and *ppMod pointing to the new module.
 | 
|---|
| 606 |  * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
 | 
|---|
| 607 |  * @returns non-zero kLdr or OS specific status code on other failures.
 | 
|---|
| 608 |  * @param   pszFilename     The filename.
 | 
|---|
| 609 |  * @param   ppRdr           Where to store the pointer to the new module.
 | 
|---|
| 610 |  */
 | 
|---|
| 611 | static int kldrDyldFindTryOpen(const char *pszFilename, PPKLDRRDR ppRdr)
 | 
|---|
| 612 | {
 | 
|---|
| 613 |     int rc;
 | 
|---|
| 614 | 
 | 
|---|
| 615 |     /*
 | 
|---|
| 616 |      * Try open the file.
 | 
|---|
| 617 |      */
 | 
|---|
| 618 |     rc = kLdrRdrOpen(ppRdr, pszFilename);
 | 
|---|
| 619 |     if (!rc)
 | 
|---|
| 620 |         return 0;
 | 
|---|
| 621 |     /** @todo deal with return codes properly. */
 | 
|---|
| 622 |     if (rc >= KLDR_ERR_BASE && rc <= KLDR_ERR_END)
 | 
|---|
| 623 |         return rc;
 | 
|---|
| 624 | 
 | 
|---|
| 625 |     return KLDR_ERR_MODULE_NOT_FOUND;
 | 
|---|
| 626 | }
 | 
|---|
| 627 | 
 | 
|---|
| 628 | 
 | 
|---|
| 629 | /**
 | 
|---|
| 630 |  * Composes a filename from the specified directory path,
 | 
|---|
| 631 |  * prefix (optional), name and suffix (optional, will try with and without).
 | 
|---|
| 632 |  *
 | 
|---|
| 633 |  * @param   pchPath     The directory path - this doesn't have to be null terminated.
 | 
|---|
| 634 |  * @param   cchPath     The length of the path.
 | 
|---|
| 635 |  * @param   pArgs       The search argument structure.
 | 
|---|
| 636 |  *
 | 
|---|
| 637 |  * @returns See kldrDyldFindTryOpen
 | 
|---|
| 638 |  */
 | 
|---|
| 639 | static int kldrDyldFindTryOpenPath(const char *pchPath, size_t cchPath, PCKLDRDYLDFINDARGS pArgs)
 | 
|---|
| 640 | {
 | 
|---|
| 641 |     static char s_szFilename[1024];
 | 
|---|
| 642 |     char *psz;
 | 
|---|
| 643 |     int rc;
 | 
|---|
| 644 | 
 | 
|---|
| 645 |     /*
 | 
|---|
| 646 |      * Ignore any attempts at opening empty paths.
 | 
|---|
| 647 |      * This can happen when a *Dir globals is empty.
 | 
|---|
| 648 |      */
 | 
|---|
| 649 |     if (!cchPath)
 | 
|---|
| 650 |         return KLDR_ERR_MODULE_NOT_FOUND; /* ignore */
 | 
|---|
| 651 | 
 | 
|---|
| 652 |     /*
 | 
|---|
| 653 |      * Limit check first.
 | 
|---|
| 654 |      */
 | 
|---|
| 655 |     if (cchPath + 1 + pArgs->cchMaxLength >= sizeof(s_szFilename))
 | 
|---|
| 656 |     {
 | 
|---|
| 657 |         KLDRDYLDFIND_ASSERT(!"too long");
 | 
|---|
| 658 |         return KLDR_ERR_MODULE_NOT_FOUND; /* ignore */
 | 
|---|
| 659 |     }
 | 
|---|
| 660 | 
 | 
|---|
| 661 |     /*
 | 
|---|
| 662 |      * The directory path.
 | 
|---|
| 663 |      */
 | 
|---|
| 664 |     kLdrHlpMemCopy(s_szFilename, pchPath, cchPath);
 | 
|---|
| 665 |     psz = &s_szFilename[cchPath];
 | 
|---|
| 666 |     if (psz[-1] != '/'
 | 
|---|
| 667 | #if defined(__OS2__) || defined(__WIN__)
 | 
|---|
| 668 |         && psz[-1] != '\\'
 | 
|---|
| 669 |         && psz[-1] != ':'
 | 
|---|
| 670 | #endif
 | 
|---|
| 671 |         )
 | 
|---|
| 672 |         *psz++ = '/';
 | 
|---|
| 673 | 
 | 
|---|
| 674 |     /*
 | 
|---|
| 675 |      * The name.
 | 
|---|
| 676 |      */
 | 
|---|
| 677 |     if (pArgs->cchPrefix)
 | 
|---|
| 678 |     {
 | 
|---|
| 679 |         kLdrHlpMemCopy(psz, pArgs->pszPrefix, pArgs->cchPrefix);
 | 
|---|
| 680 |         psz += pArgs->cchPrefix;
 | 
|---|
| 681 |     }
 | 
|---|
| 682 |     kLdrHlpMemCopy(psz, pArgs->pszName, pArgs->cchName);
 | 
|---|
| 683 |     psz += pArgs->cchName;
 | 
|---|
| 684 |     if (pArgs->cchSuffix)
 | 
|---|
| 685 |     {
 | 
|---|
| 686 |         kLdrHlpMemCopy(psz, pArgs->pszSuffix, pArgs->cchSuffix);
 | 
|---|
| 687 |         psz += pArgs->cchSuffix;
 | 
|---|
| 688 |     }
 | 
|---|
| 689 |     *psz = '\0';
 | 
|---|
| 690 | 
 | 
|---|
| 691 | 
 | 
|---|
| 692 |     /*
 | 
|---|
| 693 |      * Try open it.
 | 
|---|
| 694 |      */
 | 
|---|
| 695 |     rc = kldrDyldFindTryOpen(s_szFilename, pArgs->ppRdr);
 | 
|---|
| 696 |     /* If we're opening an executable, try again without the suffix.*/
 | 
|---|
| 697 |     if (    rc
 | 
|---|
| 698 |         &&  pArgs->cchSuffix
 | 
|---|
| 699 |         &&  (pArgs->fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE))
 | 
|---|
| 700 |     {
 | 
|---|
| 701 |         psz -= pArgs->cchSuffix;
 | 
|---|
| 702 |         *psz = '\0';
 | 
|---|
| 703 |         rc = kldrDyldFindTryOpen(s_szFilename, pArgs->ppRdr);
 | 
|---|
| 704 |     }
 | 
|---|
| 705 |     return rc;
 | 
|---|
| 706 | }
 | 
|---|
| 707 | 
 | 
|---|
| 708 | 
 | 
|---|
| 709 | /**
 | 
|---|
| 710 |  * Enumerates the specfied path.
 | 
|---|
| 711 |  *
 | 
|---|
| 712 |  * @returns Any return code from the kldrDyldFindTryOpenPath() which isn't KLDR_ERR_MODULE_NOT_FOUND.
 | 
|---|
| 713 |  * @returns KLDR_ERR_MODULE_NOT_FOUND if the end of the search path was reached.
 | 
|---|
| 714 |  * @param   pszSearchPath   The search path to enumeare.
 | 
|---|
| 715 |  * @param   pArgs       The search argument structure.
 | 
|---|
| 716 |  */
 | 
|---|
| 717 | static int kldrDyldFindEnumeratePath(const char *pszSearchPath, PCKLDRDYLDFINDARGS pArgs)
 | 
|---|
| 718 | {
 | 
|---|
| 719 |     const char *psz = pszSearchPath;
 | 
|---|
| 720 |     for (;;)
 | 
|---|
| 721 |     {
 | 
|---|
| 722 |         const char *pszEnd;
 | 
|---|
| 723 |         size_t      cchPath;
 | 
|---|
| 724 | 
 | 
|---|
| 725 |         /*
 | 
|---|
| 726 |          * Trim.
 | 
|---|
| 727 |          */
 | 
|---|
| 728 |         while (*psz == ';' || *psz == ':')
 | 
|---|
| 729 |             psz++;
 | 
|---|
| 730 |         if (*psz == '\0')
 | 
|---|
| 731 |             return KLDR_ERR_MODULE_NOT_FOUND;
 | 
|---|
| 732 | 
 | 
|---|
| 733 |         /*
 | 
|---|
| 734 |          * Find the end.
 | 
|---|
| 735 |          */
 | 
|---|
| 736 |         pszEnd = psz + 1;
 | 
|---|
| 737 |         while (     *pszEnd != '\0'
 | 
|---|
| 738 |                &&   *pszEnd != ';'
 | 
|---|
| 739 | #if defined(__OS2__) || defined(__WIN__)
 | 
|---|
| 740 |                && (     *pszEnd != ':'
 | 
|---|
| 741 |                    ||   (   pszEnd - psz == 1
 | 
|---|
| 742 |                          && (   (*psz >= 'A' && *psz <= 'Z')
 | 
|---|
| 743 |                              || (*psz >= 'a' && *psz <= 'z')
 | 
|---|
| 744 |                             )
 | 
|---|
| 745 |                         )
 | 
|---|
| 746 |                   )
 | 
|---|
| 747 | #else
 | 
|---|
| 748 |                && *pszEnd != ':'
 | 
|---|
| 749 | #endif
 | 
|---|
| 750 |               )
 | 
|---|
| 751 |             pszEnd++;
 | 
|---|
| 752 | 
 | 
|---|
| 753 |         /*
 | 
|---|
| 754 |          * If not empty path, try open the module using it.
 | 
|---|
| 755 |          */
 | 
|---|
| 756 |         cchPath = pszEnd - psz;
 | 
|---|
| 757 |         if (cchPath > 0)
 | 
|---|
| 758 |         {
 | 
|---|
| 759 |             int rc;
 | 
|---|
| 760 |             rc = kldrDyldFindTryOpenPath(psz, cchPath, pArgs);
 | 
|---|
| 761 |             if (rc != KLDR_ERR_MODULE_NOT_FOUND)
 | 
|---|
| 762 |                 return rc;
 | 
|---|
| 763 |         }
 | 
|---|
| 764 | 
 | 
|---|
| 765 |         /* next */
 | 
|---|
| 766 |         psz = pszEnd;
 | 
|---|
| 767 |     }
 | 
|---|
| 768 | }
 | 
|---|
| 769 | 
 | 
|---|
| 770 | 
 | 
|---|
| 771 | /**
 | 
|---|
| 772 |  * Resolve default search method, prefix and suffix.
 | 
|---|
| 773 |  *
 | 
|---|
| 774 |  * @returns 0 on success, KLDR_ERR_INVALID_PARAMETER on failure.
 | 
|---|
| 775 |  * @param   penmSearch  The search method. In/Out.
 | 
|---|
| 776 |  * @param   ppszPrefix  The prefix. In/Out.
 | 
|---|
| 777 |  * @param   ppszSuffix  The suffix. In/Out.
 | 
|---|
| 778 |  * @param   pszName     The name. In.
 | 
|---|
| 779 |  * @param   fFlags      The load/search flags.
 | 
|---|
| 780 |  */
 | 
|---|
| 781 | static int kldrDyldFindGetDefaults(KLDRDYLDSEARCH *penmSearch, const char **ppszPrefix, const char **ppszSuffix,
 | 
|---|
| 782 |                                    const char *pszName, uint32_t fFlags)
 | 
|---|
| 783 | {
 | 
|---|
| 784 |     unsigned fCaseSensitive;
 | 
|---|
| 785 | 
 | 
|---|
| 786 |     /*
 | 
|---|
| 787 |      * Fixup search method alias.
 | 
|---|
| 788 |      */
 | 
|---|
| 789 |     if (*penmSearch == KLDRDYLD_SEARCH_HOST)
 | 
|---|
| 790 | #if defined(__OS2__)
 | 
|---|
| 791 |         *penmSearch = KLDRDYLD_SEARCH_OS2;
 | 
|---|
| 792 | #elif defined(__WIN__)
 | 
|---|
| 793 |         *penmSearch = KLDRDYLD_SEARCH_WINDOWS;
 | 
|---|
| 794 | #else
 | 
|---|
| 795 | # error "Port me"
 | 
|---|
| 796 | #endif
 | 
|---|
| 797 | 
 | 
|---|
| 798 |     /*
 | 
|---|
| 799 |      * Apply search method specific prefix/suffix.
 | 
|---|
| 800 |      */
 | 
|---|
| 801 |     switch (*penmSearch)
 | 
|---|
| 802 |     {
 | 
|---|
| 803 |         case KLDRDYLD_SEARCH_KLDR:
 | 
|---|
| 804 |             if (!*ppszPrefix && kLdrDyldDefPrefix[0])
 | 
|---|
| 805 |                 *ppszPrefix = kLdrDyldDefPrefix;
 | 
|---|
| 806 |             if (!*ppszSuffix && kLdrDyldDefSuffix[0])
 | 
|---|
| 807 |                 *ppszSuffix = kLdrDyldDefSuffix;
 | 
|---|
| 808 |             fCaseSensitive = 1;
 | 
|---|
| 809 |             break;
 | 
|---|
| 810 | 
 | 
|---|
| 811 |         case KLDRDYLD_SEARCH_OS2:
 | 
|---|
| 812 |             if (!*ppszSuffix)
 | 
|---|
| 813 |                 *ppszSuffix = !(fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE) ? ".dll" : ".exe";
 | 
|---|
| 814 |             fCaseSensitive = 0;
 | 
|---|
| 815 |             break;
 | 
|---|
| 816 | 
 | 
|---|
| 817 |         case KLDRDYLD_SEARCH_WINDOWS:
 | 
|---|
| 818 |         case KLDRDYLD_SEARCH_WINDOWS_ALTERED:
 | 
|---|
| 819 |             if (!*ppszSuffix)
 | 
|---|
| 820 |                 *ppszSuffix = !(fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE) ? ".dll" : ".exe";
 | 
|---|
| 821 |             fCaseSensitive = 0;
 | 
|---|
| 822 |             break;
 | 
|---|
| 823 | 
 | 
|---|
| 824 |         case KLDRDYLD_SEARCH_UNIX_COMMON:
 | 
|---|
| 825 |             fCaseSensitive = 1;
 | 
|---|
| 826 |             break;
 | 
|---|
| 827 | 
 | 
|---|
| 828 |         default:
 | 
|---|
| 829 |             KLDRDYLDFIND_ASSERT(!"invalid search method");
 | 
|---|
| 830 |             return KLDR_ERR_INVALID_PARAMETER;
 | 
|---|
| 831 |     }
 | 
|---|
| 832 | 
 | 
|---|
| 833 |     /*
 | 
|---|
| 834 |      * Drop the suffix if it's already included in the name.
 | 
|---|
| 835 |      */
 | 
|---|
| 836 |     if (*ppszSuffix)
 | 
|---|
| 837 |     {
 | 
|---|
| 838 |         const size_t cchName = kLdrHlpStrLen(pszName);
 | 
|---|
| 839 |         const size_t cchSuffix = kLdrHlpStrLen(*ppszSuffix);
 | 
|---|
| 840 |         if (    cchName > cchSuffix
 | 
|---|
| 841 |             &&  (   fCaseSensitive
 | 
|---|
| 842 |                  ?  !kLdrHlpMemComp(pszName + cchName - cchSuffix, *ppszSuffix, cchSuffix)
 | 
|---|
| 843 |                  :  !kLdrHlpMemIComp(pszName + cchName - cchSuffix, *ppszSuffix, cchSuffix))
 | 
|---|
| 844 |            )
 | 
|---|
| 845 |             *ppszSuffix = NULL;
 | 
|---|
| 846 |     }
 | 
|---|
| 847 | 
 | 
|---|
| 848 |     return 0;
 | 
|---|
| 849 | }
 | 
|---|
| 850 | 
 | 
|---|
| 851 | 
 | 
|---|
| 852 | /**
 | 
|---|
| 853 |  * Locates an already open module using the specified search method.
 | 
|---|
| 854 |  *
 | 
|---|
| 855 |  * @returns 0 and *ppMod on success, non-zero OS specific error on failure.
 | 
|---|
| 856 |  *
 | 
|---|
| 857 |  * @param   pszName         Partial or complete name, it's specific to the search method to determin which.
 | 
|---|
| 858 |  * @param   pszPrefix       Prefix than can be used when searching.
 | 
|---|
| 859 |  * @param   pszSuffix       Suffix than can be used when searching.
 | 
|---|
| 860 |  * @param   enmSearch       The file search method to apply.
 | 
|---|
| 861 |  * @param   fFlags          Search flags.
 | 
|---|
| 862 |  * @param   ppMod           Where to store the file provider instance on success.
 | 
|---|
| 863 |  */
 | 
|---|
| 864 | int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
 | 
|---|
| 865 |                                KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod)
 | 
|---|
| 866 | {
 | 
|---|
| 867 | 
 | 
|---|
| 868 |     int rc;
 | 
|---|
| 869 |     unsigned fOS2LibpathStrict;
 | 
|---|
| 870 |     *ppMod = NULL;
 | 
|---|
| 871 | 
 | 
|---|
| 872 |     /*
 | 
|---|
| 873 |      * Don't bother if no modules are loaded yet.
 | 
|---|
| 874 |      */
 | 
|---|
| 875 |     if (!kLdrDyldHead)
 | 
|---|
| 876 |         return KLDR_ERR_MODULE_NOT_FOUND;
 | 
|---|
| 877 | 
 | 
|---|
| 878 |     /*
 | 
|---|
| 879 |      * Defaults.
 | 
|---|
| 880 |      */
 | 
|---|
| 881 |     rc = kldrDyldFindGetDefaults(&enmSearch, &pszPrefix, &pszSuffix, pszName, fFlags);
 | 
|---|
| 882 |     if (rc)
 | 
|---|
| 883 |         return rc;
 | 
|---|
| 884 | 
 | 
|---|
| 885 |     /*
 | 
|---|
| 886 |      * If this isn't just a filename, the caller has specified a file
 | 
|---|
| 887 |      * that should be opened directly and not a module name to be searched for.
 | 
|---|
| 888 |      *
 | 
|---|
| 889 |      * In order to do the right thing we'll have to open the file and get the
 | 
|---|
| 890 |      * correct filename for it.
 | 
|---|
| 891 |      *
 | 
|---|
| 892 |      * The OS/2 libpath strict method require us to find the correct DLL first.
 | 
|---|
| 893 |      */
 | 
|---|
| 894 |     fOS2LibpathStrict = 0;
 | 
|---|
| 895 |     if (    !kldrHlpIsFilenameOnly(pszName)
 | 
|---|
| 896 |         ||  (fOS2LibpathStrict = (   enmSearch == KLDRDYLD_SEARCH_OS2
 | 
|---|
| 897 |                                   && kLdrDyldOS2LibpathStrict[0] == 'T')
 | 
|---|
| 898 |             )
 | 
|---|
| 899 |        )
 | 
|---|
| 900 |     {
 | 
|---|
| 901 |         PKLDRRDR pRdr;
 | 
|---|
| 902 |         if (fOS2LibpathStrict)
 | 
|---|
| 903 |             rc = kldrDyldFindDoDllSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
 | 
|---|
| 904 |         else
 | 
|---|
| 905 |             rc = kldrDyldFindTryOpen(pszName, &pRdr);
 | 
|---|
| 906 |         if (!rc)
 | 
|---|
| 907 |         {
 | 
|---|
| 908 |             /* do a filename based search. */
 | 
|---|
| 909 |             const char     *pszFilename = kLdrRdrName(pRdr);
 | 
|---|
| 910 |             const size_t    cchFilename = kLdrHlpStrLen(pszFilename);
 | 
|---|
| 911 |             PKLDRDYLDMOD    pCur;
 | 
|---|
| 912 |             rc = KLDR_ERR_MODULE_NOT_FOUND;
 | 
|---|
| 913 |             for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
 | 
|---|
| 914 |             {
 | 
|---|
| 915 |                 if (    pCur->pMod->cchFilename == cchFilename
 | 
|---|
| 916 |                     &&  !kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename))
 | 
|---|
| 917 |                 {
 | 
|---|
| 918 |                     *ppMod = pCur;
 | 
|---|
| 919 |                     rc = 0;
 | 
|---|
| 920 |                     break;
 | 
|---|
| 921 |                 }
 | 
|---|
| 922 |             }
 | 
|---|
| 923 |             kLdrRdrClose(pRdr);
 | 
|---|
| 924 |         }
 | 
|---|
| 925 |     }
 | 
|---|
| 926 |     else
 | 
|---|
| 927 |     {
 | 
|---|
| 928 |         const size_t    cchName = kLdrHlpStrLen(pszName);
 | 
|---|
| 929 |         const size_t    cchPrefix = pszPrefix ? kLdrHlpStrLen(pszPrefix) : 0;
 | 
|---|
| 930 |         const size_t    cchSuffix = pszSuffix ? kLdrHlpStrLen(pszSuffix) : 0;
 | 
|---|
| 931 |         const char     *pszNameSuffix = kldrHlpGetSuff(pszName);
 | 
|---|
| 932 |         PKLDRDYLDMOD    pCur = kLdrDyldHead;
 | 
|---|
| 933 | 
 | 
|---|
| 934 |         /*
 | 
|---|
| 935 |          * Some of the methods are case insensitive (ASCII), others are case sensitive.
 | 
|---|
| 936 |          * To avoid having todo indirect calls to the compare functions here, we split
 | 
|---|
| 937 |          * ways even if it means a lot of duplicate code.
 | 
|---|
| 938 |          */
 | 
|---|
| 939 |         if (   enmSearch == KLDRDYLD_SEARCH_OS2
 | 
|---|
| 940 |             || enmSearch == KLDRDYLD_SEARCH_WINDOWS
 | 
|---|
| 941 |             || enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED)
 | 
|---|
| 942 |         {
 | 
|---|
| 943 |             const unsigned fNameHasSuffix = pszNameSuffix
 | 
|---|
| 944 |                                          && kLdrHlpStrLen(pszNameSuffix) == cchSuffix
 | 
|---|
| 945 |                                          && !kLdrHlpMemIComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix);
 | 
|---|
| 946 |             for (; pCur; pCur = pCur->Load.pNext)
 | 
|---|
| 947 |             {
 | 
|---|
| 948 |                 /* match global / specific */
 | 
|---|
| 949 |                 if (    !pCur->fGlobalOrSpecific
 | 
|---|
| 950 |                     &&  !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
 | 
|---|
| 951 |                     continue;
 | 
|---|
| 952 | 
 | 
|---|
| 953 |                 /* match name */
 | 
|---|
| 954 |                 if (    pCur->pMod->cchName == cchName
 | 
|---|
| 955 |                     &&  !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName))
 | 
|---|
| 956 |                     break;
 | 
|---|
| 957 |                 if (cchPrefix)
 | 
|---|
| 958 |                 {
 | 
|---|
| 959 |                     if (    pCur->pMod->cchName == cchName + cchPrefix
 | 
|---|
| 960 |                         &&  !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
 | 
|---|
| 961 |                         &&  !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName))
 | 
|---|
| 962 |                     break;
 | 
|---|
| 963 |                 }
 | 
|---|
| 964 |                 if (cchSuffix)
 | 
|---|
| 965 |                 {
 | 
|---|
| 966 |                     if (    pCur->pMod->cchName == cchName + cchSuffix
 | 
|---|
| 967 |                         &&  !kLdrHlpMemIComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix)
 | 
|---|
| 968 |                         &&  !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName))
 | 
|---|
| 969 |                     break;
 | 
|---|
| 970 |                     if (    fNameHasSuffix
 | 
|---|
| 971 |                         &&  pCur->pMod->cchName == cchName - cchSuffix
 | 
|---|
| 972 |                         &&  !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName - cchSuffix))
 | 
|---|
| 973 |                     break;
 | 
|---|
| 974 |                     if (cchPrefix)
 | 
|---|
| 975 |                     {
 | 
|---|
| 976 |                         if (    pCur->pMod->cchName == cchName + cchPrefix + cchSuffix
 | 
|---|
| 977 |                             &&  !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
 | 
|---|
| 978 |                             &&  !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)
 | 
|---|
| 979 |                             &&  !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix))
 | 
|---|
| 980 |                         break;
 | 
|---|
| 981 |                         if (    fNameHasSuffix
 | 
|---|
| 982 |                             &&  pCur->pMod->cchName == cchName + cchPrefix - cchSuffix
 | 
|---|
| 983 |                             &&  !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
 | 
|---|
| 984 |                             &&  !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix))
 | 
|---|
| 985 |                         break;
 | 
|---|
| 986 |                     }
 | 
|---|
| 987 |                 }
 | 
|---|
| 988 |             }
 | 
|---|
| 989 |         }
 | 
|---|
| 990 |         else
 | 
|---|
| 991 |         {
 | 
|---|
| 992 |             const unsigned fNameHasSuffix = pszNameSuffix
 | 
|---|
| 993 |                                          && kLdrHlpStrLen(pszNameSuffix) == cchSuffix
 | 
|---|
| 994 |                                          && kLdrHlpMemComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix);
 | 
|---|
| 995 |             for (; pCur; pCur = pCur->Load.pNext)
 | 
|---|
| 996 |             {
 | 
|---|
| 997 |                 /* match global / specific */
 | 
|---|
| 998 |                 if (    !pCur->fGlobalOrSpecific
 | 
|---|
| 999 |                     &&  !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
 | 
|---|
| 1000 |                     continue;
 | 
|---|
| 1001 | 
 | 
|---|
| 1002 |                 /* match name */
 | 
|---|
| 1003 |                 if (    pCur->pMod->cchName == cchName
 | 
|---|
| 1004 |                     &&  !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName))
 | 
|---|
| 1005 |                     break;
 | 
|---|
| 1006 |                 if (cchPrefix)
 | 
|---|
| 1007 |                 {
 | 
|---|
| 1008 |                     if (    pCur->pMod->cchName == cchName + cchPrefix
 | 
|---|
| 1009 |                         &&  !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
 | 
|---|
| 1010 |                         &&  !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName))
 | 
|---|
| 1011 |                     break;
 | 
|---|
| 1012 |                 }
 | 
|---|
| 1013 |                 if (cchSuffix)
 | 
|---|
| 1014 |                 {
 | 
|---|
| 1015 |                     if (    pCur->pMod->cchName == cchName + cchSuffix
 | 
|---|
| 1016 |                         &&  !kLdrHlpMemComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix)
 | 
|---|
| 1017 |                         &&  !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName))
 | 
|---|
| 1018 |                     break;
 | 
|---|
| 1019 |                     if (    fNameHasSuffix
 | 
|---|
| 1020 |                         &&  pCur->pMod->cchName == cchName - cchSuffix
 | 
|---|
| 1021 |                         &&  !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName - cchSuffix))
 | 
|---|
| 1022 |                     break;
 | 
|---|
| 1023 |                     if (cchPrefix)
 | 
|---|
| 1024 |                     {
 | 
|---|
| 1025 |                         if (    pCur->pMod->cchName == cchName + cchPrefix + cchSuffix
 | 
|---|
| 1026 |                             &&  !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
 | 
|---|
| 1027 |                             &&  !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)
 | 
|---|
| 1028 |                             &&  !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix))
 | 
|---|
| 1029 |                         break;
 | 
|---|
| 1030 |                         if (    pCur->pMod->cchName == cchName + cchPrefix - cchSuffix
 | 
|---|
| 1031 |                             &&  !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
 | 
|---|
| 1032 |                             &&  !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix))
 | 
|---|
| 1033 |                         break;
 | 
|---|
| 1034 |                     }
 | 
|---|
| 1035 |                 }
 | 
|---|
| 1036 |             }
 | 
|---|
| 1037 |         }
 | 
|---|
| 1038 | 
 | 
|---|
| 1039 |         /* search result. */
 | 
|---|
| 1040 |         if (pCur)
 | 
|---|
| 1041 |         {
 | 
|---|
| 1042 |             *ppMod = pCur;
 | 
|---|
| 1043 |             rc = 0;
 | 
|---|
| 1044 |         }
 | 
|---|
| 1045 |         else
 | 
|---|
| 1046 |             rc = KLDR_ERR_MODULE_NOT_FOUND;
 | 
|---|
| 1047 |     }
 | 
|---|
| 1048 | 
 | 
|---|
| 1049 |     return rc;
 | 
|---|
| 1050 | }
 | 
|---|
| 1051 | 
 | 
|---|