source: trunk/kLdr/kLdrDyldFind.c@ 2867

Last change on this file since 2867 was 2867, checked in by bird, 19 years ago

top half of the filesearching is done.

  • Property svn:keywords set to Id
File size: 29.4 KB
Line 
1/* $Id: kLdrDyldFind.c 2867 2006-11-11 09:33:17Z 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 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* Global Variables *
76*******************************************************************************/
77/** @name The kLdr search method parameters.
78 * @{ */
79/** The kLdr DLL search path.
80 * During initialization the KLDR_LIBRARY_PATH env.var. and the path in the
81 * executable stub is appended. Both ';' and ':' can be used as separators.
82 */
83char kLdrDyldPath[8192];
84/** The kLdr application directory.
85 * This is initialized when the executable is 'loaded' or by a kLdr user.
86 */
87char kLdrDyldAppDir[260];
88/** The default kLdr DLL prefix.
89 * This is initialized with the KLDR_DEF_PREFIX env.var. + the prefix in the executable stub.
90 */
91char kLdrDyldDefPrefix[16];
92/** The default kLdr DLL suffix.
93 * This is initialized with the KLDR_DEF_SUFFIX env.var. + the prefix in the executable stub.
94 */
95char kLdrDyldDefSuffix[16];
96/** @} */
97
98
99/** @name The OS/2 search method parameters.
100 * @{
101 */
102/** The OS/2 LIBPATH.
103 * This is queried from the os2krnl on OS/2, while on other systems initialized using
104 * the KLDR_OS2_LIBPATH env.var.
105 */
106char kLdrDyldOS2Libpath[2048];
107/** The OS/2 LIBPATHSTRICT ("T" or '\0').
108 * This is queried from the os2krnl on OS/2, while on other systems initialized using
109 * the KLDR_OS2_LIBPATHSTRICT env.var.
110 */
111char kLdrDyldOS2LibpathStrict[8];
112/** The OS/2 BEGINLIBPATH.
113 * This is queried from the os2krnl on OS/2, while on other systems initialized using
114 * the KLDR_OS2_BEGINLIBPATH env.var.
115 */
116char kLdrDyldOS2BeginLibpath[2048];
117/** The OS/2 ENDLIBPATH.
118 * This is queried from the os2krnl on OS/2, while on other systems initialized using
119 * the KLDR_OS2_ENDLIBPATH env.var.
120 */
121char kLdrDyldOS2EndLibpath[2048];
122/** @} */
123
124
125/** @name The Windows search method parameters.
126 * @{ */
127/** The Windows application directory.
128 * This is initialized when the executable is 'loaded' or by a kLdr user.
129 */
130char kLdrDyldWindowsAppDir[260];
131/** The Windows system directory.
132 * This is queried from the Win32/64 subsystem on Windows, while on other systems
133 * initialized using the KLDR_WINDOWS_SYSTEM_DIR env.var.
134 */
135char kLdrDyldWindowsSystemDir[260];
136/** The Windows directory.
137 * This is queried from the Win32/64 subsystem on Windows, while on other systems
138 * initialized using the KLDR_WINDOWS_DIR env.var.
139 */
140char kLdrDyldWindowsDir[260];
141/** The Windows path.
142 * This is queried from the PATH env.var. on Windows, while on other systems
143 * initialized using the KLDR_WINDOWS_PATH env.var. and falling back on
144 * the PATH env.var. if it wasn't found.
145 */
146char kLdrDyldWindowsPath[8192];
147/** @} */
148
149
150/** @name The Common Unix search method parameters.
151 * @{
152 */
153/** The Common Unix library path.
154 * Initialized from the env.var. KLDR_UNIX_LIBRARY_PATH or LD_LIBRARY_PATH or the
155 * former wasn't found.
156 */
157char kLdrDyldUnixLibraryPath[8192];
158/** The Common Unix system library path. */
159char kLdrDyldUnixSystemLibraryPath[1024] = "/lib;/usr/lib";
160/** @} */
161
162/** @todo Deal with DT_RUNPATH and DT_RPATH. */
163/** @todo ld.so.cache? */
164
165
166/*******************************************************************************
167* Internal Functions *
168*******************************************************************************/
169static int kldrDyldFindDoSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
170 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr);
171static int kldrDyldFindTryOpen(const char *pszFilename, PPKLDRRDR ppRdr);
172static int kldrDyldFindTryOpenPath(const char *pchPath, size_t cchPath, const char *pszName, const char *pszPrefix,
173 const char *pszSuffix, PPKLDRRDR ppRdr);
174static int kldrDyldFindEnumeratePath(const char *pszSearchPath, const char *pszName, const char *pszPrefix,
175 const char *pszSuffix, PPKLDRRDR ppRdr);
176
177
178/**
179 * Initializes the find paths.
180 *
181 * @returns 0 on success, non-zero on failure.
182 */
183int kldrDyldFindInit(void)
184{
185 size_t cch;
186 int rc;
187 char szTmp[sizeof(kLdrDyldDefSuffix)];
188
189 /*
190 * The kLdr search parameters.
191 */
192 rc = kldrHlpGetEnv("KLDR_LIBRARY_PATH", kLdrDyldPath, sizeof(kLdrDyldPath));
193 if (rc)
194 kLdrDyldPath[0] = '\0';
195
196 rc = kldrHlpGetEnv("KLDR_DEF_PREFIX", szTmp, sizeof(szTmp));
197 if (!rc)
198 kLdrHlpMemCopy(kLdrDyldDefPrefix, szTmp, sizeof(szTmp));
199
200 rc = kldrHlpGetEnv("KLDR_DEF_SUFFIX", szTmp, sizeof(szTmp));
201 if (!rc)
202 kLdrHlpMemCopy(kLdrDyldDefSuffix, szTmp, sizeof(szTmp));
203
204 /*
205 * The OS/2 search parameters.
206 */
207#ifdef __OS2__
208 rc = DosQueryHeaderInfo(NULLHANDLE, 0, kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath), QHINF_LIBPATH);
209 if (rc)
210 return rc;
211 rc = DosQueryExtLIBPATH(kLdrDyldOS2LibpathStrict, LIBPATHSTRICT);
212 if (rc)
213 kLdrDyldOS2LibpathStrict[0] = '\0';
214 rc = DosQueryExtLIBPATH(kLdrDyldOS2BeginLibpath, BEGIN_LIBPATH);
215 if (rc)
216 kLdrDyldOS2BeginLibpath[0] = '\0';
217 rc = DosQueryExtLIBPATH(kLdrDyldOS2EndLibpath, END_LIBPATH);
218 if (rc)
219 kLdrDyldOS2EndLibpath[0] = '\0';
220
221#else
222 kldrHlpGetEnv("KLDR_OS2_LIBPATH", kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath));
223 kldrHlpGetEnv("KLDR_OS2_LIBPATHSTRICT", kLdrDyldOS2LibpathStrict, sizeof(kLdrDyldOS2LibpathStrict));
224 kldrHlpGetEnv("KLDR_OS2_BEGINLIBPATH", kLdrDyldOS2BeginLibpath, sizeof(kLdrDyldOS2BeginLibpath));
225 kldrHlpGetEnv("KLDR_OS2_ENDLIBPATH", kLdrDyldOS2EndLibpath, sizeof(kLdrDyldOS2EndLibpath));
226#endif
227
228 /*
229 * The windows search parameters.
230 */
231#if defined(__WIN__)
232 cch = GetSystemDirectory(kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir));
233 if (cch >= sizeof(kLdrDyldWindowsSystemDir))
234 return (rc = GetLastError()) ? rc : -1;
235 cch = GetWindowsDirectory(kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir));
236 if (cch >= sizeof(kLdrDyldWindowsDir))
237 return (rc = GetLastError()) ? rc : -1;
238 kldrHlpGetEnv("PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
239#else
240 kldrHlpGetEnv("KLDR_WINDOWS_SYSTEM_DIR", kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir));
241 kldrHlpGetEnv("KLDR_WINDOWS_DIR", kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir));
242 kldrHlpGetEnv("KLDR_WINDOWS_PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
243#endif
244
245 /*
246 * The Unix search parameters.
247 */
248 rc = kldrHlpGetEnv("KLDR_UNIX_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath));
249 if (rc)
250 kldrHlpGetEnv("LD_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath));
251
252 (void)cch;
253 return 0;
254}
255
256
257/**
258 * Locates and opens a module using the specified search method.
259 *
260 * @returns 0 and *ppMod on success, non-zero OS specific error on failure.
261 *
262 * @param pszName Partial or complete name, it's specific to the search method to determin which.
263 * @param pszPrefix Prefix than can be used when searching.
264 * @param pszSuffix Suffix than can be used when searching.
265 * @param enmSearch The file search method to apply.
266 * @param fFlags Search flags.
267 * @param ppMod Where to store the file provider instance on success.
268 */
269int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
270 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod)
271{
272 int rc;
273 PKLDRRDR pRdr = NULL;
274
275 *ppMod = NULL;
276
277 /*
278 * If this isn't just a filename, we the caller has specified a file
279 * that should be opened directly and not a module name to be searched for.
280 */
281 if (!kldrHlpIsFilenameOnly(pszName))
282 rc = kldrDyldFindTryOpen(pszName, &pRdr);
283 else
284 rc = kldrDyldFindDoSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
285 if (!rc)
286 {
287#ifdef KLDRDYLDFIND_STRICT
288 /* Sanity check of kldrDyldFindExistingModule. */
289 if (fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)
290 {
291 const char *pszFilename = kLdrRdrName(pRdr);
292 const size_t cchFilename = kLdrHlpStrLen(pszFilename);
293 PKLDRDYLDMOD pCur;
294 for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
295 KLDRDYLDFIND_ASSERT( pCur->pMod->cchFilename != cchFilename
296 || kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename));
297 }
298#endif
299
300 /*
301 * Check for matching non-global modules that should be promoted.
302 */
303 if (!(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
304 {
305 const char *pszFilename = kLdrRdrName(pRdr);
306 const size_t cchFilename = kLdrHlpStrLen(pszFilename);
307 PKLDRDYLDMOD pCur;
308 for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
309 {
310 if ( !pCur->fGlobalOrSpecific
311 && pCur->pMod->cchFilename == cchFilename
312 && !kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename))
313 {
314 kLdrRdrClose(pRdr);
315 kldrDyldModMarkGlobal(pCur);
316 *ppMod = pCur;
317 return 0;
318 }
319 KLDRDYLDFIND_ASSERT( pCur->pMod->cchFilename != cchFilename
320 || kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename));
321 }
322 }
323
324 /*
325 * Create a new module.
326 */
327 rc = kldrDyldModCreate(pRdr, ppMod);
328 if (rc)
329 kLdrRdrClose(pRdr);
330 }
331 return rc;
332}
333
334
335/**
336 * Searches for a file using the specified method.
337 *
338 * @returns 0 on success and *ppMod pointing to the new module.
339 * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
340 * @returns non-zero kLdr or OS specific status code on other failures.
341 * @param pszName The name.
342 * @param pszPrefix The prefix, optional.
343 * @param pszSuffix The suffix, optional.
344 * @param enmSearch The search method.
345 * @param fFlags The load/search flags.
346 * @param ppRdr Where to store the pointer to the file provider instance on success.
347 */
348static int kldrDyldFindDoSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
349 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr)
350{
351 int rc;
352
353 /*
354 * Fixup search method alias.
355 */
356 if (enmSearch == KLDRDYLD_SEARCH_HOST)
357 enmSearch = KLDRDYLD_SEARCH_KLDR; /** @todo find more suitable place for this. */
358
359 /*
360 * Apply the specified search method.
361 */
362 switch (enmSearch)
363 {
364 case KLDRDYLD_SEARCH_KLDR:
365 {
366 if (!pszPrefix && kLdrDyldDefPrefix[0])
367 pszPrefix = kLdrDyldDefPrefix;
368 if (!pszSuffix && kLdrDyldDefSuffix[0])
369 pszSuffix = kLdrDyldDefSuffix;
370
371 if (kLdrDyldAppDir[0] != '\0')
372 {
373 rc = kldrDyldFindTryOpenPath(kLdrDyldAppDir, kLdrHlpStrLen(kLdrDyldAppDir),
374 pszName, pszPrefix, pszSuffix, ppRdr);
375 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
376 break;
377 }
378 rc = kldrDyldFindTryOpenPath(".", 1, pszName, pszPrefix, pszSuffix, ppRdr);
379 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
380 break;
381 rc = kldrDyldFindEnumeratePath(kLdrDyldPath, pszName, pszPrefix, pszSuffix, ppRdr);
382 break;
383 }
384
385 case KLDRDYLD_SEARCH_OS2:
386 {
387 if (!pszSuffix)
388 pszSuffix = ".dll";
389
390 rc = kldrDyldFindEnumeratePath(kLdrDyldOS2BeginLibpath, pszName, pszPrefix, pszSuffix, ppRdr);
391 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
392 break;
393 rc = kldrDyldFindEnumeratePath(kLdrDyldOS2Libpath, pszName, pszPrefix, pszSuffix, ppRdr);
394 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
395 break;
396 rc = kldrDyldFindEnumeratePath(kLdrDyldOS2EndLibpath, pszName, pszPrefix, pszSuffix, ppRdr);
397 break;
398 }
399
400 case KLDRDYLD_SEARCH_WINDOWS:
401 case KLDRDYLD_SEARCH_WINDOWS_ALTERED:
402 {
403 if (!pszSuffix)
404 pszSuffix = ".dll";
405
406 rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsAppDir, kLdrHlpStrLen(kLdrDyldWindowsAppDir),
407 pszName, pszPrefix, pszSuffix, ppRdr);
408 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
409 break;
410 if (enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED)
411 {
412 rc = kldrDyldFindTryOpenPath(".", 1, pszName, pszPrefix, pszSuffix, ppRdr);
413 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
414 break;
415 }
416 rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsSystemDir, kLdrHlpStrLen(kLdrDyldWindowsSystemDir),
417 pszName, pszPrefix, pszSuffix, ppRdr);
418 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
419 break;
420 rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsDir, kLdrHlpStrLen(kLdrDyldWindowsDir),
421 pszName, pszPrefix, pszSuffix, ppRdr);
422 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
423 break;
424 if (enmSearch == KLDRDYLD_SEARCH_WINDOWS)
425 {
426 rc = kldrDyldFindTryOpenPath(".", 1, pszName, pszPrefix, pszSuffix, ppRdr);
427 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
428 break;
429 }
430 rc = kldrDyldFindEnumeratePath(kLdrDyldWindowsPath, pszName, pszPrefix, pszSuffix, ppRdr);
431 break;
432 }
433
434 case KLDRDYLD_SEARCH_UNIX_COMMON:
435 {
436 rc = kldrDyldFindEnumeratePath(kLdrDyldUnixLibraryPath, pszName, pszPrefix, pszSuffix, ppRdr);
437 if (rc == KLDR_ERR_MODULE_NOT_FOUND)
438 break;
439 rc = kldrDyldFindEnumeratePath(kLdrDyldUnixSystemLibraryPath, pszName, pszPrefix, pszSuffix, ppRdr);
440 break;
441 }
442
443 default:
444 KLDRDYLDFIND_ASSERT(!"invalid search method");
445 return KLDR_ERR_INVALID_PARAMETER;
446
447 }
448 return rc;
449}
450
451
452/**
453 * Try open the specfied file.
454 *
455 * @returns 0 on success and *ppMod pointing to the new module.
456 * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
457 * @returns non-zero kLdr or OS specific status code on other failures.
458 * @param pszFilename The filename.
459 * @param ppRdr Where to store the pointer to the new module.
460 */
461static int kldrDyldFindTryOpen(const char *pszFilename, PPKLDRRDR ppRdr)
462{
463 return KLDR_ERR_MODULE_NOT_FOUND;
464}
465
466
467/**
468 * Composes a filename from the specified directory path,
469 * prefix (optional), name and suffix (optional, will try with and without).
470 *
471 * @param pchPath The directory path - this doesn't have to be null terminated.
472 * @param cchPath The length of the path.
473 * @param pszName The base name.
474 * @param pszPrefix The prefix to use. (optional)
475 * @param pszSuffix The suffix to use. (optional)
476 * Will try without first if the name contains a suffix already.
477 * @param ppRdr See kldrDyldFindTryOpen.
478 *
479 * @returns See kldrDyldFindTryOpen
480 */
481static int kldrDyldFindTryOpenPath(const char *pchPath, size_t cchPath, const char *pszName, const char *pszPrefix,
482 const char *pszSuffix, PPKLDRRDR ppRdr)
483{
484 return KLDR_ERR_MODULE_NOT_FOUND;
485}
486
487
488/**
489 * Enumerates the specfied path.
490 *
491 * @returns Any return code from the kldrDyldFindTryOpenPath() which isn't KLDR_ERR_MODULE_NOT_FOUND.
492 * @returns KLDR_ERR_MODULE_NOT_FOUND if the end of the search path was reached.
493 * @param pszSearchPath The search path to enumeare.
494 * @param pszName The pszName argument for kldrDyldFindTryOpenPath.
495 * @param pszPrefix The pszPrefix argument for kldrDyldFindTryOpenPath.
496 * @param pszSuffix The pszSuffix argument for kldrDyldFindTryOpenPath.
497 * @param ppRdr The ppRdr argument for kldrDyldFindTryOpenPath.
498 */
499static int kldrDyldFindEnumeratePath(const char *pszSearchPath, const char *pszName, const char *pszPrefix,
500 const char *pszSuffix, PPKLDRRDR ppRdr)
501{
502 return KLDR_ERR_MODULE_NOT_FOUND;
503}
504
505
506
507/**
508 * Locates an already open module using the specified search method.
509 *
510 * @returns 0 and *ppMod on success, non-zero OS specific error on failure.
511 *
512 * @param pszName Partial or complete name, it's specific to the search method to determin which.
513 * @param pszPrefix Prefix than can be used when searching.
514 * @param pszSuffix Suffix than can be used when searching.
515 * @param enmSearch The file search method to apply.
516 * @param fFlags Search flags.
517 * @param ppMod Where to store the file provider instance on success.
518 */
519int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
520 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod)
521{
522
523 int rc;
524 unsigned fOS2LibpathStrict;
525 *ppMod = NULL;
526
527 /*
528 * Don't bother if no modules are loaded yet.
529 */
530 if (!kLdrDyldHead)
531 return KLDR_ERR_MODULE_NOT_FOUND;
532
533 /*
534 * Fixup search method alias.
535 */
536 if (enmSearch == KLDRDYLD_SEARCH_HOST)
537 enmSearch = KLDRDYLD_SEARCH_KLDR; /** @todo find more suitable place for this. */
538
539 /*
540 * If this isn't just a filename, the caller has specified a file
541 * that should be opened directly and not a module name to be searched for.
542 *
543 * In order to do the right thing we'll have to open the file and get the
544 * correct filename for it.
545 *
546 * The OS/2 libpath strict method require us to find the correct DLL first.
547 */
548 fOS2LibpathStrict = 0;
549 if ( !kldrHlpIsFilenameOnly(pszName)
550 || (fOS2LibpathStrict = ( enmSearch == KLDRDYLD_SEARCH_OS2
551 && kLdrDyldOS2LibpathStrict[0] == 'T')
552 )
553 )
554 {
555 PKLDRRDR pRdr;
556 if (fOS2LibpathStrict)
557 rc = kldrDyldFindDoSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
558 else
559 rc = kldrDyldFindTryOpen(pszName, &pRdr);
560 if (!rc)
561 {
562 /* do a filename based search. */
563 const char *pszFilename = kLdrRdrName(pRdr);
564 const size_t cchFilename = kLdrHlpStrLen(pszFilename);
565 PKLDRDYLDMOD pCur;
566 rc = KLDR_ERR_MODULE_NOT_FOUND;
567 for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
568 {
569 if ( pCur->pMod->cchFilename == cchFilename
570 && !kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename))
571 {
572 *ppMod = pCur;
573 rc = 0;
574 break;
575 }
576 }
577 kLdrRdrClose(pRdr);
578 }
579 }
580 else
581 {
582 /*
583 * Get default prefix and suffix.
584 */
585 rc = 0;
586 switch (enmSearch)
587 {
588 case KLDRDYLD_SEARCH_KLDR:
589 if (!pszPrefix && kLdrDyldDefPrefix[0])
590 pszPrefix = kLdrDyldDefPrefix;
591 if (!pszSuffix && kLdrDyldDefSuffix[0])
592 pszSuffix = kLdrDyldDefSuffix;
593 break;
594
595 case KLDRDYLD_SEARCH_OS2:
596 if (!pszSuffix)
597 pszSuffix = ".dll";
598 break;
599
600 case KLDRDYLD_SEARCH_WINDOWS:
601 case KLDRDYLD_SEARCH_WINDOWS_ALTERED:
602 if (!pszSuffix)
603 pszSuffix = ".dll";
604
605 case KLDRDYLD_SEARCH_UNIX_COMMON:
606 break;
607
608 default:
609 KLDRDYLDFIND_ASSERT(!"invalid search method");
610 rc = KLDR_ERR_INVALID_PARAMETER;
611 break;
612 }
613 if (!rc)
614 {
615 const size_t cchName = kLdrHlpStrLen(pszName);
616 const size_t cchPrefix = pszPrefix ? kLdrHlpStrLen(pszPrefix) : 0;
617 const size_t cchSuffix = pszSuffix ? kLdrHlpStrLen(pszSuffix) : 0;
618 const char *pszNameSuffix = kldrHlpGetSuff(pszName);
619 PKLDRDYLDMOD pCur = kLdrDyldHead;
620
621 /*
622 * Some of the methods are case insensitive (ASCII), others are case sensitive.
623 * To avoid having todo indirect calls to the compare functions here, we split
624 * ways even if it means a lot of duplicate code.
625 */
626 if ( enmSearch == KLDRDYLD_SEARCH_OS2
627 || enmSearch == KLDRDYLD_SEARCH_WINDOWS
628 || enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED)
629 {
630 const unsigned fNameHasSuffix = pszNameSuffix
631 && kLdrHlpStrLen(pszNameSuffix) == cchSuffix
632 && kLdrHlpMemIComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix);
633 for (; pCur; pCur = pCur->Load.pNext)
634 {
635 /* match global / specific */
636 if ( !pCur->fGlobalOrSpecific
637 && !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
638 continue;
639
640 /* match name */
641 if ( pCur->pMod->cchName == cchName
642 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName))
643 break;
644 if (cchPrefix)
645 {
646 if ( pCur->pMod->cchName == cchName + cchPrefix
647 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
648 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName))
649 break;
650 }
651 if (cchSuffix)
652 {
653 if ( pCur->pMod->cchName == cchName + cchSuffix
654 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix)
655 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName))
656 break;
657 if ( fNameHasSuffix
658 && pCur->pMod->cchName == cchName - cchSuffix
659 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName - cchSuffix))
660 break;
661 if (cchPrefix)
662 {
663 if ( pCur->pMod->cchName == cchName + cchPrefix + cchSuffix
664 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
665 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)
666 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix))
667 break;
668 if ( fNameHasSuffix
669 && pCur->pMod->cchName == cchName + cchPrefix - cchSuffix
670 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
671 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix))
672 break;
673 }
674 }
675 }
676 }
677 else
678 {
679 const unsigned fNameHasSuffix = pszNameSuffix
680 && kLdrHlpStrLen(pszNameSuffix) == cchSuffix
681 && kLdrHlpMemComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix);
682 for (; pCur; pCur = pCur->Load.pNext)
683 {
684 /* match global / specific */
685 if ( !pCur->fGlobalOrSpecific
686 && !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
687 continue;
688
689 /* match name */
690 if ( pCur->pMod->cchName == cchName
691 && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName))
692 break;
693 if (cchPrefix)
694 {
695 if ( pCur->pMod->cchName == cchName + cchPrefix
696 && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
697 && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName))
698 break;
699 }
700 if (cchSuffix)
701 {
702 if ( pCur->pMod->cchName == cchName + cchSuffix
703 && !kLdrHlpMemComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix)
704 && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName))
705 break;
706 if ( fNameHasSuffix
707 && pCur->pMod->cchName == cchName - cchSuffix
708 && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName - cchSuffix))
709 break;
710 if (cchPrefix)
711 {
712 if ( pCur->pMod->cchName == cchName + cchPrefix + cchSuffix
713 && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
714 && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)
715 && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix))
716 break;
717 if ( pCur->pMod->cchName == cchName + cchPrefix - cchSuffix
718 && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
719 && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix))
720 break;
721 }
722 }
723 }
724 }
725 if (pCur)
726 {
727 *ppMod = pCur;
728 rc = 0;
729 }
730 else
731 rc = KLDR_ERR_MODULE_NOT_FOUND;
732 }
733 }
734
735 return rc;
736}
737
Note: See TracBrowser for help on using the repository browser.