source: trunk/src/win32k/ldr/ldr.cpp@ 4785

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

Added new state flag for extention fix in myldrOpen and myldrOpenPath.

File size: 12.7 KB
Line 
1/* $Id: ldr.cpp,v 1.9 2000-12-11 06:44:34 bird Exp $
2 *
3 * ldr.cpp - Loader helpers.
4 *
5 * Copyright (c) 1999 knut St. osmundsen
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants And Macros *
13*******************************************************************************/
14#define INCL_DOSERRORS
15#define INCL_NOPMAPI
16#define INCL_OS2KRNL_SEM
17#define INCL_OS2KRNL_PTDA
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <os2.h>
23
24#include "devSegDf.h"
25#include "malloc.h"
26#include "new.h"
27#include <memory.h>
28#include <stdlib.h>
29#include <stddef.h>
30#include <string.h>
31
32#include "log.h"
33#include "avl.h"
34#include <peexe.h>
35#include <exe386.h>
36#include "OS2Krnl.h"
37#include "ldr.h"
38#include "ldrCalls.h"
39#include "ModuleBase.h"
40#include "pe2lx.h"
41#include "options.h"
42
43
44/*******************************************************************************
45* Global Variables *
46*******************************************************************************/
47static PAVLNODECORE pSFNRoot = NULL;
48static PAVLNODECORE pMTERoot = NULL;
49
50
51/*
52 * Loader State. (See ldr.h for more info.)
53 */
54ULONG ulLdrState = LDRSTATE_UNKNOWN;
55
56
57/*
58 * ldrOpen extention fix flag. (See ldr.h, myldrOpenPath.cpp and myldrOpen.cpp.)
59 */
60BOOL fldrOpenExtentionFix = FALSE;
61
62
63/*
64 * Pointer to the executable module being loaded.
65 * This pointer is set by ldrOpen and cleared by tkExecPgm.
66 * It's hence only valid at tkExecPgm time. (isLdrStateExecPgm() == TRUE).
67 */
68PMODULE pExeModule = NULL;
69
70
71/*
72 * Filehandle bitmap.
73 */
74unsigned char achHandleStates[MAX_FILE_HANDLES/8];
75
76
77
78
79/**
80 * Gets a module by the give hFile.
81 * @returns Pointer to module node. If not found NULL.
82 * @param hFile File handle of the module to be found.
83 * @sketch return a AVLGet on the pSFNRoot-tree.
84 * @status completely implemented.
85 * @author knut st. osmundsen
86 */
87PMODULE getModuleBySFN(SFN hFile)
88{
89 return (PMODULE)AVLGet(&pSFNRoot, (AVLKEY)hFile);
90}
91
92
93/**
94 * Gets a module by the MTE.
95 * @returns Pointer to module node. If not found NULL.
96 * @param pMTE Pointer a Module Table Entry.
97 * @sketch Try find it in the MTE tree.
98 * IF not found THEN
99 * BEGIN
100 * DEBUG: validate pMTE pointer.
101 * Get the SFN from the MTE.
102 * IF found in the SFN-tree THEN
103 * BEGIN
104 * Update the pMTE in the node.
105 * Add the node to the MTE-tree.
106 * END
107 * ELSE return NULL
108 * END
109 * return pointer to module node.
110 * @status completely implemented.
111 * @author knut st. osmundsen
112 */
113PMODULE getModuleByMTE(PMTE pMTE)
114{
115 #if 0
116 /* Not 100% sure that this will work correctly! */
117 PMODULE pMod = (PMODULE)AVLGet(&pMTERoot, (AVLKEY)pMTE);
118 if (pMod == NULL)
119 {
120 #ifdef DEBUG
121 if (pMTE <= (PMTE)0x10000)
122 {
123 kprintf(("getModuleByMTE: invalid pMTE pointer - %#8x\n", pMTE));
124 return NULL;
125 }
126 #endif
127 pMod = (PMODULE)AVLGet(&pSFNRoot, (AVLKEY)pMTE->mte_sfn);
128 if (pMod != NULL)
129 {
130 pMod->coreMTE.Key = (AVLKEY)pMTE;
131 pMod->fFlags |= MOD_FLAGS_IN_MTETREE;
132 AVLInsert(&pMTERoot, (PAVLNODECORE)((unsigned)pMod + offsetof(MODULE, coreMTE)));
133 }
134 }
135 else
136 pMod = (PMODULE)((unsigned)pMod - offsetof(MODULE, coreMTE));
137 return pMod;
138 #else
139 /* Use this for the time being. */
140 #ifdef DEBUG
141 if (pMTE <= (PMTE)0x10000)
142 {
143 kprintf(("getModuleByMTE: invalid pMTE pointer - %#8x\n", pMTE));
144 return NULL;
145 }
146 #endif
147 if (GetState(pMTE->mte_sfn) == HSTATE_OUR)
148 return (PMODULE)AVLGet(&pSFNRoot, (AVLKEY)pMTE->mte_sfn);
149
150 return NULL;
151 #endif
152}
153
154
155/**
156 * Gets a module by the hMTE.
157 * @returns Pointer to module node. If not found NULL.
158 * @param hMTE Handle to a Module Table Entry.
159 * @sketch Convert hMte to an pMTE (pointer to MTE).
160 * Call getModuleByMTE with MTE pointer.
161 * @status completely implemented.
162 * @author knut st. osmundsen
163 */
164PMODULE getModuleByhMTE(HMTE hMTE)
165{
166 PMTE pMTE;
167
168 pMTE = ldrValidateMteHandle(hMTE);
169 if (pMTE != NULL)
170 return getModuleByMTE(pMTE);
171
172 return NULL;
173}
174
175
176/**
177 * Get a module by filename.
178 * @returns Pointer to module node. If not found NULL.
179 * @param pszFilename Pointer to the filename which we are search by.
180 * @sketch Not implemented.
181 * @status Stub.
182 * @author knut st. osmundsen
183 */
184PMODULE getModuleByFilename(PCSZ pszFilename)
185{
186 pszFilename = pszFilename;
187 return NULL;
188}
189
190
191/**
192 * Adds a module to the SFN-tree, if pMTE is not NULL it is added to the MTE-tree too.
193 * @returns NO_ERROR on success. Appropriate errorcode on failiure.
194 * @param hFile System file number for the module.
195 * @param pMTE Pointer to MTE. NULL is valid.
196 * @param fFlags Type flags for the fFlags field in the node.
197 * @param pModObj Pointer to module object.
198 * @sketch DEBUG: check that the module doesn't exists and parameter check.
199 * (try) Allocate a new node. (return errorcode on failure)
200 * Fill in the node.
201 * Add the node to the SFN-tree.
202 * IF valid MTE pointer THEN add it to the MTE tree and set the in MTE-tree flag.
203 * return successfully.
204 * @status completely implemented.
205 * @author knut st. osmundsen
206 */
207ULONG addModule(SFN hFile, PMTE pMTE, ULONG fFlags, ModuleBase *pModObj)
208{
209 PMODULE pMod;
210 #ifdef DEBUG
211 if (AVLGet(&pSFNRoot, (AVLKEY)hFile) != NULL)
212 kprintf(("addModule: Module allready present in the SFN-tree!\n"));
213 if (hFile == 0)
214 {
215 kprintf(("addModule: invalid parameter: hFile = 0\n"));
216 return ERROR_INVALID_PARAMETER;
217 }
218 if ((fFlags & MOD_TYPE_MASK) == 0 || (fFlags & ~MOD_TYPE_MASK) != 0UL)
219 {
220 kprintf(("addModule: invalid parameter: fFlags = 0x%#8x\n", fFlags));
221 return ERROR_INVALID_PARAMETER;
222 }
223 #endif
224
225 /* try allocate memory for the node. */
226 pMod = (PMODULE)malloc(sizeof(MODULE));
227 if (pMod == NULL)
228 {
229 kprintf(("addModule: out of memory!\n"));
230 return ERROR_NOT_ENOUGH_MEMORY;
231 }
232
233 /* fill in the module node. */
234 pMod->coreKey.Key = (AVLKEY)hFile;
235 pMod->hFile = hFile;
236 pMod->pMTE = pMTE;
237 pMod->fFlags = fFlags;
238 pMod->Data.pModule = pModObj;
239
240 /* insert the module node into the tree(s) */
241 AVLInsert(&pSFNRoot, (PAVLNODECORE)pMod);
242 if (pMTE != NULL)
243 {
244 pMod->coreMTE.Key = (AVLKEY)pMTE;
245 pMod->fFlags |= MOD_FLAGS_IN_MTETREE;
246 AVLInsert(&pMTERoot, (PAVLNODECORE)((unsigned)pMod + offsetof(MODULE, coreMTE)));
247 }
248
249 return NO_ERROR;
250}
251
252
253/**
254 * Removes and frees a module node (including the data pointer).
255 * @returns NO_ERROR on success. Appropriate error code on failure.
256 * @param hFile System filehandle of the module.
257 * @sketch Remove the node from the SFN-tree.
258 * IF present in the MTE-tree THEN remove it from the tree.
259 * Delete the datapointer.
260 * Free the module node.
261 * return successfully.
262 * @status completely implemented.
263 * @author knut st. osmundsen
264 */
265ULONG removeModule(SFN hFile)
266{
267 PMODULE pMod = (PMODULE)AVLRemove(&pSFNRoot, (AVLKEY)hFile);
268 if (pMod == NULL)
269 {
270 kprintf(("removeModule: Module not found! hFile=%#4x\n", hFile));
271 return ERROR_INVALID_PARAMETER;
272 }
273
274 /* In MTE-tree too? */
275 if (pMod->fFlags & MOD_FLAGS_IN_MTETREE)
276 {
277 if (AVLRemove(&pMTERoot, (AVLKEY)pMod->pMTE) == NULL)
278 {
279 kprintf(("removeModule: MOD_FLAGS_IN_MTETREE set but AVLRemove returns NULL\n"));
280 }
281 }
282
283 /* Delete the datapointer. */
284 switch (pMod->fFlags & MOD_TYPE_MASK)
285 {
286 case MOD_TYPE_PE2LX:
287 delete pMod->Data.pPe2Lx;
288 break;
289/*
290 case MOD_TYPE_ELF2LX:
291 break;
292*/
293#ifdef DEBUG
294 default:
295 kprintf(("removeModule: Unknown type, %#x\n", pMod->fFlags & MOD_TYPE_MASK));
296#endif
297 }
298
299 /* Free the module node. */
300 free(pMod);
301
302 return NO_ERROR;
303}
304
305
306/**
307 * Gets the path of the executable being executed.
308 * @returns Pointer to pszPath on success. Path has _NOT_ a trailing slash.
309 * NULL pointer on error.
310 * @param pszPath Pointer to path buffer. Expects CCHMAXPATH length.
311 * @param fExecChild Use hMTE of the PTDAExecChild if present.
312 * @sketch
313 * @status completely implemented.
314 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
315 * @remark The path from the pExeModule might not be fully qualified.
316 */
317PSZ ldrGetExePath(PSZ pszPath, BOOL fExecChild)
318{
319 PCSZ pszFilename;
320 PCSZ psz;
321
322 #if 0 /* getFilename not implemented */
323 if (pExeModule != NULL)
324 /*
325 * We have the executable object pointer. Let's use it!
326 */
327 pszFilename = pExeModule->Data.pModule->getFilename();
328 else
329 #endif
330 {
331 /*
332 * Get the hMTE for the executable using the pPTDAExecChild
333 * Then get the pMTE, and access the smte_path to get a pointer to the executable path.
334 */
335 PPTDA pPTDACur; /* Pointer to the current (system context) PTDA */
336 PPTDA pPTDA; /* PTDA in question. */
337 HMTE hMTE = NULLHANDLE; /* Modulehandle of the executable module. */
338 PMTE pMTE; /* Pointer to ModuleTableEntry of the executable module. */
339
340 /*
341 * Get the current PTDA. (Fail if this call failes.)
342 * IF pPTDAExecChild isn't NULL THEN get hMTE for that.
343 * IF no pPTDAExecChild THEN get hMte for the current PTDA.
344 */
345 pPTDACur = ptdaGetCur();
346 if (pPTDACur != NULL)
347 {
348 pPTDA = ptdaGet_pPTDAExecChild(pPTDACur);
349 if (pPTDA != NULL && fExecChild)
350 hMTE = ptdaGet_ptda_module(pPTDA);
351 if (hMTE == NULLHANDLE)
352 hMTE = ptdaGet_ptda_module(pPTDACur);
353 }
354 else
355 { /* Not called at task time? No current task! */
356 kprintf(("ldrGetExePath: Failed to get current PTDA.\n"));
357 return NULL;
358 }
359
360 /* fail if hMTE is NULLHANDLE ie. not found / invalid */
361 if (hMTE == NULLHANDLE)
362 {
363 kprintf(("ldrGetExePath: Failed to get hMTE from the PTDAs.\n"));
364 return NULL;
365 }
366
367 /* get the pMTE for this hMTE */
368 pMTE = ldrASMpMTEFromHandle(hMTE);
369 if (pMTE == NULL)
370 {
371 kprintf(("ldrGetExePath: ldrASMpMTEFromHandle failed for hMTE=0x%04.\n", hMTE));
372 return NULL;
373 }
374 if (pMTE->mte_swapmte == NULL) /* paranoia */
375 {
376 kprintf(("ldrGetExePath: mte_swapmte is NULL.\n"));
377 return NULL;
378 }
379
380 /* take the filename from the swappable MTE */
381 pszFilename = pMTE->mte_swapmte->smte_path;
382 if (pszFilename == NULL)
383 {
384 kprintf(("ldrGetExePath: smte_path is NULL.\n"));
385 return NULL;
386 }
387 }
388
389 /* paranoia... */
390 if (*pszFilename == '\0')
391 {
392 kprintf(("ldrGetExePath: pszFilename is empty!\n"));
393 return NULL;
394 }
395
396 /*
397 * Skip back over the filename. (stops pointing at the slash or ':')
398 */
399 psz = pszFilename + strlen(pszFilename)-1;
400 while (psz >= pszFilename && *psz != '\\' && *psz != '/' && *psz != ':')
401 psz--;
402
403 /*
404 * If no path the fail.
405 */
406 if (psz <= pszFilename)
407 {
408 kprintf(("ldrGetExePath: Exepath is empty.\n"));
409 return NULL;
410 }
411
412 /*
413 * Copy path and return.
414 */
415 memcpy(pszPath, pszFilename, psz - pszFilename);
416 pszPath[psz - pszFilename] = '\0';
417 return pszPath;
418}
419
420
421/**
422 * Initiate the loader "sub-system".
423 * @returns NO_ERROR on success. !0 on error.
424 */
425ULONG ldrInit(void)
426{
427 int rc = NO_ERROR;
428
429 /* init state table */
430 memset(&achHandleStates[0], 0, sizeof(achHandleStates));
431
432 /* init the tree roots */
433 pSFNRoot = NULL;
434 pMTERoot = NULL;
435
436 /* ModuleBase logging. */
437 ModuleBase::ulInfoLevel = options.ulInfoLevel;
438
439 return rc;
440}
441
Note: See TracBrowser for help on using the repository browser.