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

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

Support for long DLL names and DLL extentions different from .DLL.

File size: 12.3 KB
Line 
1/* $Id: myldrFindModule.cpp,v 1.1 2000-12-11 06:32:06 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
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#include <os2.h>
22
23#include <memory.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "devSegDf.h" /* Win32k segment definitions. */
28#include "log.h"
29#include "avl.h"
30#include <peexe.h>
31#include <exe386.h>
32#include "OS2Krnl.h"
33#include "dev32.h"
34#include "ldr.h"
35#include "ldrCalls.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.