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

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

Merged in the Grace branch. New Win32k!

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