source: trunk/src/win32k/ldr/myldrFindModule.cpp@ 5120

Last change on this file since 5120 was 5086, checked in by bird, 25 years ago

Moved ldrCalls.h into the OS2Krnl.h tree as OS2KLDR.h.
Also moved the Ldr definitions from OS2Krnl.h and into OS2KLDR.h.

File size: 12.3 KB
Line 
1/* $Id: myldrFindModule.cpp,v 1.2 2001-02-10 11:11:46 bird Exp $
2 *
3 * ldrFindModule - ldrFindModule replacement with support for long DLL names
4 * and .DLL-extention dependency.
5 *
6 * Copyright (c) 1999-2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12/*******************************************************************************
13* Defined Constants And Macros *
14*******************************************************************************/
15#define INCL_DOSERRORS
16#define INCL_NOPMAPI
17#define INCL_OS2KRNL_LDR
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <os2.h>
23
24#include <memory.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "devSegDf.h" /* Win32k segment definitions. */
29#include "log.h"
30#include "avl.h"
31#include <peexe.h>
32#include <exe386.h>
33#include "OS2Krnl.h"
34#include "dev32.h"
35#include "ldr.h"
36#include "ModuleBase.h"
37#include "options.h"
38
39/*******************************************************************************
40* Global Variables *
41*******************************************************************************/
42extern PPMTE pmte_h;
43extern PPMTE pprogram_h;
44extern PPMTE pprogram_l;
45extern PPMTE pglobal_h;
46extern PPMTE pglobal_l;
47extern PPMTE pspecific_h;
48extern PPMTE pspecific_l;
49
50
51/**
52 * Finds a module if it's loaded.
53 *
54 * This replacement will support DLLs with non DLL extention
55 * and names longer than 8 chars.
56 *
57 * @returns NO_ERROR on success.
58 * OS/2 errorcode on error.
59 * @param pachFilename Pointer to module filename.
60 * If usClass isn't CLASS_GLOBAL then the string
61 * will have to be null terminated or in ldrpFileNameBuf.
62 * If it's in the ldrpFileNameBuf we assume a fullly qualified name.
63 * @param cchFilename Length of modulefilename. This should including the terminator
64 * character if usClass isn't CLASS_GLOBAL.
65 * @param usClass Module class. (CLASS_*)
66 * @param ppMTE Pointer to pMTE found.
67 * @sketch
68 * Check that parameters are supported - backout to original ldrFindModule.
69 * Check for empty name.
70 * Decide upon where to start search for the module - depends on usClass.
71 * *TODO*
72 */
73ULONG LDRCALL myldrFindModule(PCHAR pachFilename, USHORT cchFilename, USHORT usClass, PPMTE ppMTE)
74{
75 /* Check if this feature is enabled */
76 if (isDllFixesDisabled())
77 {
78 #ifdef DEBUG
79 APIRET rc = ldrFindModule(pachFilename, cchFilename, usClass, ppMTE);
80 kprintf(("ldrFindModule: fn=%.*s len=%d class=0x%02x ppMTE=0x%08x rc=%d (original)\n", cchFilename, pachFilename, cchFilename, usClass, ppMTE, rc));
81 return rc;
82 #else
83 return ldrFindModule(pachFilename, cchFilename, usClass, ppMTE);
84 #endif
85 }
86
87 /* Static variables */
88 static PMTE pmteNULL = NULL;
89 static PPMTE ppmteNULL = &pmteNULL;
90 static PPMTE * apppmteHeadTail[] =
91 {/* head tail */
92 &pmte_h, &ppmteNULL, /* CLASS_ALL 0x00000000 */
93 &pprogram_h, &pprogram_l, /* CLASS_PROGRAM 0x00000040 */
94 &pglobal_h, &pglobal_l, /* CLASS_GLOBAL 0x00000080 */
95 &pspecific_h, &pspecific_l, /* CLASS_SPECIFIC 0x000000c0 */
96 };
97
98 /* Local variables */
99 PMTE pmte; /* Current MTE. */
100 PMTE pmteEnd; /* The MTE top stop at. */
101 ULONG rc; /* Return code. */
102 PCHAR pachName; /* Pointer to the name part of pachFilename. */
103 int cchName; /* Length of the name part of pachFilename. (No extention.) */
104 PCHAR pachExt; /* Pointer to the extention part of pachFilename. (not dot!) */
105 int cchExt; /* Length of the extention part of pachFilename. (not dot!) */
106 int cchName8; /* Length of modname in MTE. */
107
108 /*
109 * Check if everything is the way it used to be... (unsupported kernel changes, etc.)
110 */
111 #ifdef DEBUG
112 if (usClass & ~(CLASS_ALL | CLASS_PROGRAM | CLASS_GLOBAL | CLASS_SPECIFIC | SEARCH_FULL_NAME))
113 {
114 kprintf(("myldrFindModule: Unknown class flag! usClass=%d\n", usClass));
115 return ldrFindModule(pachFilename, cchFilename, usClass, ppMTE);
116 }
117 #endif
118
119 if (pachFilename < (PCHAR)0x10000 || ppMTE < (PPMTE)0x10000)
120 {
121 kprintf(("myldrFindModule: Invalid pointer(s); pachFilename=0x%08x ppMTE=0x%08x", pachFilename, ppMTE));
122 return ERROR_INVALID_ACCESS;
123 }
124
125 /*
126 * Log.
127 */
128 kprintf(("myldrFindModule: fn=%.*s len=%d class=0x%02x ppMTE=0x%08x\n", cchFilename, pachFilename, cchFilename, usClass, ppMTE));
129
130 /*
131 * Can't find an empty name.
132 */
133 if (cchFilename == 0)
134 {
135 *ppMTE = NULL;
136 kprintf(("myldrFindModule: Not found; cchFilename = 0\n"));
137 return ERROR_FILE_NOT_FOUND;
138 }
139
140
141 /*
142 * Find start and end mte node
143 */
144 pmte = **apppmteHeadTail[usClass >> 5];
145 pmteEnd = **apppmteHeadTail[(usClass >> 5) + 1];
146 if (pmteEnd != NULL) /* Advance one node - see loop condition. */
147 pmteEnd = pmteEnd->mte_link;
148
149
150 /*
151 * Translate filename path if we're searching for a full name.
152 */
153 if (usClass != CLASS_GLOBAL)
154 {
155 if (pachFilename != ldrpFileNameBuf)
156 {
157 rc = ldrTransPath(pachFilename);
158 if (rc)
159 return rc;
160 pachFilename = ldrpFileNameBuf;
161 cchFilename = (USHORT)(strlen(pachFilename) + 1);
162 ldrUCaseString(pachFilename, cchFilename);
163 }
164 #ifdef DEBUG
165 else
166 {
167 if (cchFilename != strlen(pachFilename) + 1)
168 kprintf(("myldrFindModule: %.*s cchFilename=%d strlen+1=%d\n",
169 cchFilename, pachFilename, cchFilename, strlen(pachFilename) + 1));
170 cchFilename = (USHORT)(strlen(pachFilename) + 1);
171 }
172 #endif
173 }
174
175
176 /*
177 * Depending on the search type we'll have to find the name and
178 * extention of the filename passed in to us.
179 */
180 if (usClass == CLASS_GLOBAL)
181 { /*
182 * Dll, assumes modulename only (no path!).
183 * Find the extention.
184 * Determin name and extention length.
185 * (NB! Can't use ldrGetFileName since it's looking for a slash.)
186 */
187 pachName = pachFilename;
188 pachExt = pachFilename + cchFilename - 1;
189 while (pachExt >= pachName && *pachExt != '.')
190 pachExt--;
191 if (pachExt < pachFilename)
192 {
193 cchName = cchFilename;
194 pachExt = "DLL";
195 cchExt = 3;
196 }
197 else
198 {
199 cchName = pachExt - pachName;
200 pachExt++;
201 cchExt = cchFilename - cchName - 1;
202 }
203
204 cchName8 = cchName > 8 ? 8 : cchName;
205
206 #ifdef DEBUG
207 if ( memchr(pachFilename, '\\', cchFilename)
208 || memchr(pachFilename, '/', cchFilename)
209 || (cchFilename > 2 && pachFilename[1] == ':')
210 )
211 {
212 kprintf(("myldrFindModule: Invalid name in class global; name=%.*s\n", cchFilename, pachFilename));
213 return ERROR_INVALID_NAME;
214 }
215 #endif
216 } else if ( (usClass & ~SEARCH_FULL_NAME) == CLASS_SPECIFIC
217 || usClass & CLASS_GLOBAL
218 )
219 { /*
220 * Find name and extention, and the length of those.
221 */
222 cchName = (int)ldrGetFileName2(pachFilename, (PCHAR*)SSToDS(&pachName), (PCHAR*)SSToDS(&pachExt));
223 cchName8 = cchName > 8 ? 8 : cchName;
224 cchExt = (pachExt) ? strlen(pachExt) : 0;
225 #ifdef DEBUG
226 if (cchName <= 0)
227 {
228 kprintf(("myldrFindModule: Invalid name! ldrGetFileName2 failed; name=%.*s\n", cchFilename, pachFilename));
229 return ERROR_INVALID_NAME;
230 }
231 #endif
232 }
233 else
234 { /*
235 * Search the whole path no need for extention or name.
236 */
237 cchName8 = cchExt = cchName = 0;
238 pachName = pachExt = NULL;
239 }
240
241
242 /*
243 * Search loop.
244 */
245 for (pmte = pmte; pmte != pmteEnd; pmte = pmte->mte_link)
246 {
247 /*
248 * Check that we're still searching within mte of the correct class.
249 * (Isn't this a debug sanity check? It's present in release kernel too!
250 * If this test is true the MTE list is corrupted!)
251 */
252 if ( (usClass & CLASS_MASK) != CLASS_ALL
253 && (pmte->mte_flags1 & CLASS_MASK) != (usClass & CLASS_MASK))
254 {
255 kprintf(("myldrFindModule: Bad MTE list? Stopped on wrong class test. pmte=0x%08x usClass=0x%04x\n",
256 pmte, usClass));
257 break;
258 }
259
260
261 /*
262 * Look if this module matches. Lookup on global (DLL) modules
263 * are special case.
264 */
265 if (usClass == CLASS_GLOBAL)
266 { /*
267 * DLLs, match name only:
268 * Check the module name from the resident MTE.
269 * Check the filename part of the fullname in the SwapMTE.
270 * Check extention.
271 */
272 PCHAR pachName2;
273 PCHAR pachExt2;
274 PSMTE pSMTE = pmte->mte_swapmte;
275
276 if ( !memcmp(pmte->mte_modname, pachFilename, cchName8)
277 && ( /* Filename < 8 char, check modname only. */
278 (cchFilename < 8 && pmte->mte_modname[cchFilename] == '\0')
279 || /* Filename >= 8 chars, we'll have to check the fullname. */
280 ( ldrGetFileName2(pSMTE->smte_path, (PCHAR*)SSToDS(&pachName2), (PCHAR*)SSToDS(&pachExt2)) == cchName
281 && !memcmp(pachName2, pachName, cchName)
282 && (cchExt == 0
283 ? pachExt2 == NULL || *pachExt2 == '\0' /* If no extention the internal name contains a '.'. The filename may also contain a dot or it should not have an extention! This works for both cases. */
284 : cchExt == pSMTE->smte_path - pachExt2 + /* This works when pachExt2 is NULL too. */
285 (pSMTE->smte_pathlen /* DOSCALLS don't have smte_pathlen set correctly */
286 ? pSMTE->smte_pathlen
287 : strlen(pSMTE->smte_path)
288 )
289 && !memcmp(pachExt2, pachExt, cchExt)
290 )
291 )
292 )
293 )
294 {
295 *ppMTE = pmte;
296 kprintf(("myldrFindModule: Found pmte=0x%08x hmte=0x%04x modname=%.8s path=%s (GLOBAL)\n",
297 pmte, pmte->mte_handle, pmte->mte_modname, pSMTE->smte_path));
298 return NO_ERROR;
299 }
300 }
301 else
302 { /*
303 * All, match full name:
304 * Check the module name before checking the
305 * fullname in the SwapMTE.
306 */
307 PSMTE pSMTE = pmte->mte_swapmte;
308 if (( cchName8 == 0 /* This is 0 if we should not check the mte_modname. */
309 || !memcmp(pmte->mte_modname, pachName, cchName8)
310 )
311 && pSMTE->smte_pathlen == cchFilename - 1
312 && !memcmp(pSMTE->smte_path, pachFilename, cchFilename) /* checks the '\0' too. */
313 )
314 {
315 *ppMTE = pmte;
316 kprintf(("myldrFindModule: Found pmte=0x%08x hmte=0x%04x modname=%.8s path=%s (%x)\n",
317 pmte, pmte->mte_handle, pmte->mte_modname, pSMTE->smte_path, pmte->mte_flags1 & CLASS_MASK));
318 return NO_ERROR;
319 }
320 }
321 } /* Search loop */
322
323
324 /*
325 * Not found. (*ppMte indicates this).
326 */
327 *ppMTE = NULL;
328 kprintf(("myldrFindModule: Not Found\n"));
329 return NO_ERROR;
330}
331
Note: See TracBrowser for help on using the repository browser.