1 | /* $Id: ldr.cpp,v 1.1 1999-09-06 02:20:00 bird Exp $
|
---|
2 | *
|
---|
3 | * ldr.cpp - Loader helper functions a structures.
|
---|
4 | *
|
---|
5 | * Copyright (c) 1999 knut St. osmundsen
|
---|
6 | *
|
---|
7 | */
|
---|
8 |
|
---|
9 | /*******************************************************************************
|
---|
10 | * Defined Constants And Macros *
|
---|
11 | *******************************************************************************/
|
---|
12 | #define INCL_DOSERRORS
|
---|
13 | #define INCL_NOPMAPI
|
---|
14 |
|
---|
15 |
|
---|
16 | /*******************************************************************************
|
---|
17 | * Header Files *
|
---|
18 | *******************************************************************************/
|
---|
19 | #include <os2.h>
|
---|
20 | #include <string.h>
|
---|
21 |
|
---|
22 | #include "malloc.h"
|
---|
23 | #include "new.h"
|
---|
24 | #include "log.h"
|
---|
25 | #include "pefile.h"
|
---|
26 | #include "lx.h"
|
---|
27 | #include "ldr.h"
|
---|
28 |
|
---|
29 |
|
---|
30 | /*******************************************************************************
|
---|
31 | * Global Variables *
|
---|
32 | *******************************************************************************/
|
---|
33 | unsigned char ahStates[MAX_FILE_HANDLES/4];
|
---|
34 | UNCERTAIN ahUncertain[MAX_UNCERTAIN_FILES];
|
---|
35 | PPENODE pPE;
|
---|
36 |
|
---|
37 |
|
---|
38 | /*******************************************************************************
|
---|
39 | * Internal Functions *
|
---|
40 | *******************************************************************************/
|
---|
41 | static PPENODE findNodePtr2(PPENODE pRoot, const char *pszFilename);
|
---|
42 | static ULONG freeNode(PPENODE pNode);
|
---|
43 | static ULONG depth(PPENODE pNode);
|
---|
44 |
|
---|
45 |
|
---|
46 | /**
|
---|
47 | * Get a free entry in the ahUncertain table.
|
---|
48 | * @returns Index to free entry in the ahUncertain table.
|
---|
49 | */
|
---|
50 | ULONG getFreeUncertainEntry(void)
|
---|
51 | {
|
---|
52 | ULONG i;
|
---|
53 |
|
---|
54 | i = 0;
|
---|
55 | while (i < MAX_UNCERTAIN_FILES && ahUncertain[i].hFile != 0xFFFF)
|
---|
56 | i++;
|
---|
57 |
|
---|
58 | return i < MAX_UNCERTAIN_FILES ? i : -1;
|
---|
59 | }
|
---|
60 |
|
---|
61 |
|
---|
62 | /**
|
---|
63 | * Free uncertain entry.
|
---|
64 | * Mark entry with hFile in the uncertain table as unused
|
---|
65 | * @returns NO_ERROR on success, -1 on error.
|
---|
66 | * @param hFile Filehandle (key) to free.
|
---|
67 | */
|
---|
68 | ULONG freeUncertainEntry(SFN hFile)
|
---|
69 | {
|
---|
70 | int i;
|
---|
71 | int rc;
|
---|
72 |
|
---|
73 | i = 0;
|
---|
74 | while (i < MAX_UNCERTAIN_FILES && ahUncertain[i].hFile != hFile)
|
---|
75 | i++;
|
---|
76 |
|
---|
77 | if (i < MAX_UNCERTAIN_FILES && ahUncertain[i].hFile == hFile)
|
---|
78 | {
|
---|
79 | ahUncertain[i].hFile = 0xFFFF;
|
---|
80 | ahUncertain[i].offsetNEHdr = 0;
|
---|
81 | ahUncertain[i].fMZ = 0;
|
---|
82 | ahUncertain[i].fPE = 0;
|
---|
83 | free(ahUncertain[i].pszName);
|
---|
84 | ahUncertain[i].pszName = NULL;
|
---|
85 | rc = NO_ERROR;
|
---|
86 | }
|
---|
87 | else
|
---|
88 | rc = -1;
|
---|
89 | return rc;
|
---|
90 | }
|
---|
91 |
|
---|
92 |
|
---|
93 | /**
|
---|
94 | * Find the uncertain entry for hFile
|
---|
95 | * @returns Index into ahUncertain if found. ~0UL on error.
|
---|
96 | * @param hFile Filehandle (key) to find.
|
---|
97 | */
|
---|
98 | ULONG findUncertainEntry(SFN hFile)
|
---|
99 | {
|
---|
100 | int i = 0;
|
---|
101 | while (i < MAX_UNCERTAIN_FILES && ahUncertain[i].hFile != hFile)
|
---|
102 | i++;
|
---|
103 |
|
---|
104 | return i < MAX_UNCERTAIN_FILES ? (ULONG)i : ~0UL;
|
---|
105 | }
|
---|
106 |
|
---|
107 |
|
---|
108 | /**
|
---|
109 | * Inserts a PENode into the pPE tree.
|
---|
110 | * @returns NO_ERROR on success. !0 on error.
|
---|
111 | * @param pNode Pointer to node to insert.
|
---|
112 | */
|
---|
113 | ULONG insertNode(PPENODE pNode)
|
---|
114 | {
|
---|
115 | int level;
|
---|
116 | PPENODE pPrev;
|
---|
117 | PPENODE pTmp;
|
---|
118 |
|
---|
119 | if (pPE == NULL)
|
---|
120 | {
|
---|
121 | pPE = pNode;
|
---|
122 | pNode->left = pNode->right = NULL;
|
---|
123 | }
|
---|
124 | else
|
---|
125 | {
|
---|
126 | level = 0;
|
---|
127 | pPrev = NULL;
|
---|
128 | pTmp = pPE;
|
---|
129 | while (pTmp != NULL)
|
---|
130 | {
|
---|
131 | level = 0;
|
---|
132 | pPrev = pTmp;
|
---|
133 | pTmp = AdjustKey(pNode->hFile) < AdjustKey(pTmp->hFile) ? pTmp->left : pTmp->right;
|
---|
134 | }
|
---|
135 |
|
---|
136 | if (pNode->hFile != pPrev->hFile)
|
---|
137 | {
|
---|
138 | if (AdjustKey(pNode->hFile) < AdjustKey(pPrev->hFile))
|
---|
139 | pPrev->left = pNode;
|
---|
140 | else
|
---|
141 | pPrev->right = pNode;
|
---|
142 | pNode->left = pNode->right = NULL;
|
---|
143 | }
|
---|
144 | else
|
---|
145 | return -1;
|
---|
146 | }
|
---|
147 |
|
---|
148 | return NO_ERROR;
|
---|
149 | }
|
---|
150 |
|
---|
151 |
|
---|
152 | /**
|
---|
153 | * Deletes a node from the pPE tree.
|
---|
154 | * @returns NO_ERROR on success. !0 on error.
|
---|
155 | * @param key Filehandle, which is the key.
|
---|
156 | */
|
---|
157 | ULONG deleteNode(SFN key)
|
---|
158 | {
|
---|
159 | int level,level2;
|
---|
160 | ULONG rc;
|
---|
161 | PPENODE pTmp,pTmp2;
|
---|
162 | PPENODE pPrev,pPrev2;
|
---|
163 | int left;
|
---|
164 |
|
---|
165 | if (pPE != NULL)
|
---|
166 | {
|
---|
167 | /* find node to delete */
|
---|
168 | level = 1;
|
---|
169 | pPrev = NULL;
|
---|
170 | pTmp = pPE;
|
---|
171 | while (pTmp != NULL && key != pTmp->hFile)
|
---|
172 | {
|
---|
173 | pPrev = pTmp;
|
---|
174 | pTmp = (left = (AdjustKey(key) < AdjustKey(pTmp->hFile))) == TRUE ? pTmp->left : pTmp->right;
|
---|
175 | level ++;
|
---|
176 | }
|
---|
177 |
|
---|
178 | if (pTmp != NULL)
|
---|
179 | {
|
---|
180 | /*found it: pTmp -> node to delete - pPrev -> parent node*/
|
---|
181 | level--;
|
---|
182 | rc = -1;
|
---|
183 | if (pTmp->left != NULL && pTmp->right != NULL)
|
---|
184 | {
|
---|
185 | /* hard case - fetch the leftmost node in the right subtree */
|
---|
186 | level2 = level;
|
---|
187 | pPrev2 = pTmp;
|
---|
188 | pTmp2 = pTmp->right;
|
---|
189 | while (pTmp2->left != NULL)
|
---|
190 | {
|
---|
191 | pPrev2 = pTmp2;
|
---|
192 | pTmp2 = pTmp2->left;
|
---|
193 | level2++;
|
---|
194 | }
|
---|
195 | /* pTmp2 -> new root - pPrev2 -> parent node */
|
---|
196 |
|
---|
197 | /* left child of pTmp2 */
|
---|
198 | pTmp2->left = pTmp->left;
|
---|
199 |
|
---|
200 | /* parent of pTmp2 and pTmp2->right */
|
---|
201 | if (pPrev2 != pTmp)
|
---|
202 | {
|
---|
203 | pPrev2->left = pTmp2->right;
|
---|
204 | pTmp2->right = pTmp->right;
|
---|
205 | }
|
---|
206 | //else pTmp2->right = pTmp2->right;
|
---|
207 |
|
---|
208 | /* link in pTmp2 */
|
---|
209 | if (pTmp != pPE)
|
---|
210 | {
|
---|
211 | if (left)
|
---|
212 | pPrev->left = pTmp2;
|
---|
213 | else
|
---|
214 | pPrev->right = pTmp2;
|
---|
215 | }
|
---|
216 | else
|
---|
217 | pPE = pTmp2;
|
---|
218 | rc = NO_ERROR;
|
---|
219 | }
|
---|
220 |
|
---|
221 | /* leaf */
|
---|
222 | if (rc!=0 && pTmp->left == NULL && pTmp->right == NULL)
|
---|
223 | {
|
---|
224 | if (pTmp != pPE)
|
---|
225 | {
|
---|
226 | if (left)
|
---|
227 | pPrev->left = NULL;
|
---|
228 | else
|
---|
229 | pPrev->right = NULL;
|
---|
230 | }
|
---|
231 | else
|
---|
232 | pPE = NULL;
|
---|
233 | rc = NO_ERROR;
|
---|
234 | }
|
---|
235 |
|
---|
236 | /* left is NULL */
|
---|
237 | if (rc!=0 && pTmp->left == NULL && pTmp->right != NULL)
|
---|
238 | {
|
---|
239 | /* move up right node */
|
---|
240 | if (pTmp != pPE)
|
---|
241 | {
|
---|
242 | if (left)
|
---|
243 | pPrev->left = pTmp->right;
|
---|
244 | else
|
---|
245 | pPrev->right = pTmp->right;
|
---|
246 | }
|
---|
247 | else
|
---|
248 | pPE = pTmp->right;
|
---|
249 | rc = NO_ERROR;
|
---|
250 | }
|
---|
251 |
|
---|
252 | /* right is NULL */
|
---|
253 | if (rc!=0 && pTmp->left != NULL && pTmp->right == NULL)
|
---|
254 | {
|
---|
255 | /* move up left node */
|
---|
256 | if (pTmp != pPE)
|
---|
257 | {
|
---|
258 | if (left)
|
---|
259 | pPrev->left = pTmp->left;
|
---|
260 | else
|
---|
261 | pPrev->right = pTmp->left;
|
---|
262 | }
|
---|
263 | else
|
---|
264 | pPE = pTmp->left;
|
---|
265 | rc = NO_ERROR;
|
---|
266 | }
|
---|
267 |
|
---|
268 | /* free node */
|
---|
269 | if (rc == NO_ERROR)
|
---|
270 | rc = freeNode( pTmp );
|
---|
271 | }
|
---|
272 | else
|
---|
273 | rc = 1; //not found
|
---|
274 | }
|
---|
275 | else
|
---|
276 | rc = 1; //not found
|
---|
277 | return rc;
|
---|
278 | }
|
---|
279 |
|
---|
280 |
|
---|
281 | /**
|
---|
282 | * Get the pointer to a node in the pPE tree.
|
---|
283 | * @returns Pointer to node on success. NULL if not found or error occured.
|
---|
284 | * @param key Filehandle, which is the key for the pPE tree.
|
---|
285 | */
|
---|
286 | PPENODE getNodePtr(SFN key)
|
---|
287 | {
|
---|
288 | PPENODE pTmp = pPE;
|
---|
289 | int level = 1;
|
---|
290 | while (pTmp != NULL && pTmp->hFile != key)
|
---|
291 | {
|
---|
292 | pTmp = AdjustKey(key) < AdjustKey(pTmp->hFile) ? pTmp->left : pTmp->right;
|
---|
293 | level++;
|
---|
294 | }
|
---|
295 | return pTmp;
|
---|
296 | }
|
---|
297 |
|
---|
298 |
|
---|
299 | /**
|
---|
300 | * Find a PENode by filename in the node tree.
|
---|
301 | * @returns Pointer to PENode if found, NULL if not found.
|
---|
302 | * @param pszFilename Pointer to filename.
|
---|
303 | */
|
---|
304 | PPENODE findNodePtr(const char *pszFilename)
|
---|
305 | {
|
---|
306 | /*depth first search thru the whole tree */
|
---|
307 | return findNodePtr2(pPE, pszFilename);
|
---|
308 | }
|
---|
309 |
|
---|
310 |
|
---|
311 | /**
|
---|
312 | * Find a PENode by filename in the given tree.
|
---|
313 | * Depth first search thru the whole tree.
|
---|
314 | * @returns Pointer to matching PENode.
|
---|
315 | * @param pRoot Tree root.
|
---|
316 | * @param pszFilename Pointer to filename.
|
---|
317 | * @remark sub-function of findNodePtr.
|
---|
318 | */
|
---|
319 | static PPENODE findNodePtr2(PPENODE pRoot, const char *pszFilename)
|
---|
320 | {
|
---|
321 | PPENODE pNode = NULL;
|
---|
322 |
|
---|
323 | /*depth first search thru the whole tree */
|
---|
324 | if ( pRoot == NULL || pRoot->lxfile.queryIsModuleName(pszFilename))
|
---|
325 | return pRoot;
|
---|
326 |
|
---|
327 | //search subtrees
|
---|
328 | if (pRoot->left != NULL)
|
---|
329 | pNode = findNodePtr2(pRoot->left,pszFilename);
|
---|
330 | if (pNode == NULL && pRoot->right != NULL)
|
---|
331 | pNode = findNodePtr2(pRoot->right,pszFilename);
|
---|
332 | return pNode;
|
---|
333 | }
|
---|
334 |
|
---|
335 |
|
---|
336 | /**
|
---|
337 | * Allocate memory for a PENode.
|
---|
338 | * @returns Pointer to new PENode on success. NULL pointer on error.
|
---|
339 | */
|
---|
340 | PPENODE allocateNode(void)
|
---|
341 | {
|
---|
342 | PPENODE pNode;
|
---|
343 |
|
---|
344 | pNode = new PENODE;
|
---|
345 | if (pNode == NULL)
|
---|
346 | kprintf(("allocateNode: malloc returned an NULL-pointer\n"));
|
---|
347 |
|
---|
348 | return pNode;
|
---|
349 | }
|
---|
350 |
|
---|
351 |
|
---|
352 | /**
|
---|
353 | * Frees node.
|
---|
354 | * @returns NO_ERROR on success.
|
---|
355 | * @param pNode Pointer to node which is to be freed.
|
---|
356 | */
|
---|
357 | static ULONG freeNode(PPENODE pNode)
|
---|
358 | {
|
---|
359 | if (pNode != NULL)
|
---|
360 | delete pNode;
|
---|
361 |
|
---|
362 | return NO_ERROR;
|
---|
363 | }
|
---|
364 |
|
---|
365 |
|
---|
366 | /**
|
---|
367 | * Gets the depth of the pPE tree.
|
---|
368 | * @returns Number of levels in the the pPE tree.
|
---|
369 | */
|
---|
370 | ULONG depthPE(void)
|
---|
371 | {
|
---|
372 | return depth(pPE);
|
---|
373 | }
|
---|
374 |
|
---|
375 |
|
---|
376 |
|
---|
377 | /**
|
---|
378 | * Gets the depth of the pPE tree.
|
---|
379 | * @returns Number of levels in the the pPE tree.
|
---|
380 | * @param pNode Node to start at. (root node...)
|
---|
381 | */
|
---|
382 | static ULONG depth(PPENODE pNode)
|
---|
383 | {
|
---|
384 | if (pNode != NULL)
|
---|
385 | {
|
---|
386 | int l, r;
|
---|
387 | l = depth(pNode->left);
|
---|
388 | r = depth(pNode->right);
|
---|
389 | return 1 + (l > r ? l : r);
|
---|
390 | }
|
---|
391 | else
|
---|
392 | return 0;
|
---|
393 | }
|
---|
394 |
|
---|
395 |
|
---|
396 | /**
|
---|
397 | * Initiate the loader "sub-system".
|
---|
398 | * @returns NO_ERROR on success. !0 on error.
|
---|
399 | */
|
---|
400 | ULONG ldrInit(void)
|
---|
401 | {
|
---|
402 | int rc = NO_ERROR;
|
---|
403 | int i;
|
---|
404 |
|
---|
405 | /* init state table */
|
---|
406 | for (i = 0; i < MAX_FILE_HANDLES/4; i++)
|
---|
407 | ahStates[i] = 0;
|
---|
408 |
|
---|
409 | /* init uncertain files */
|
---|
410 | for (i = 0; i < MAX_UNCERTAIN_FILES; i++)
|
---|
411 | {
|
---|
412 | ahUncertain[i].hFile = 0xFFFF;
|
---|
413 | ahUncertain[i].offsetNEHdr = 0;
|
---|
414 | ahUncertain[i].fMZ = 0;
|
---|
415 | ahUncertain[i].fPE = 0;
|
---|
416 | ahUncertain[i].pszName = NULL;
|
---|
417 | }
|
---|
418 |
|
---|
419 | /* init pPEFiles* */
|
---|
420 | pPE = NULL;
|
---|
421 |
|
---|
422 | return rc;
|
---|
423 | }
|
---|
424 |
|
---|