source: trunk/kStuff/kLdr/kLdrDyldFind.c

Last change on this file was 3601, checked in by bird, 18 years ago

license update.

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