source: trunk/src/win32k/ldr/myldrOpen.cpp@ 2836

Last change on this file since 2836 was 2836, checked in by bird, 26 years ago

ProbKrnl and code for importing krnl symbols has been enhanched.
Now we'll lock 32-bit segments into memory too.
And some other fixes...

File size: 16.4 KB
Line 
1/* $Id: myldrOpen.cpp,v 1.8 2000-02-21 04:45:47 bird Exp $
2 *
3 * myldrOpen - ldrOpen.
4 *
5 * Copyright (c) 1998-1999 knut st. osmundsen
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11
12/*******************************************************************************
13* Defined Constants And Macros *
14*******************************************************************************/
15#define INCL_DOSERRORS
16#define INCL_NOPMAPI
17
18#define INCL_OS2KRNL_IO
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include <os2.h>
24
25#include "rmalloc.h"
26#include "malloc.h"
27#include <memory.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include "log.h"
32#include <peexe.h>
33#include <exe386.h>
34#include "OS2Krnl.h"
35#include "dev32.h"
36#include "ModuleBase.h"
37#include "pe2lx.h"
38#include "elf.h"
39#include "avl.h"
40#include "ldr.h"
41#include "ldrCalls.h"
42#include "options.h"
43#include "myExecPgm.h"
44
45
46/*******************************************************************************
47* Internal Functions *
48*******************************************************************************/
49static unsigned getArgsLength(const char *pachArgs);
50
51
52/**
53 * ldrOpen override.
54 * @returns Return code.
55 * @param phFile Pointer to file handler. Holds filehandle on output.
56 * @param pszFilename Pointer to filename.
57 * @parma param3 Probably some flags.
58 */
59ULONG LDRCALL myldrOpen(PSFN phFile, char *pszFilename, ULONG param3)
60{
61 ULONG rc;
62
63 /*
64 * Try open the file (thats why this function is called anyway)
65 */
66 rc = ldrOpen(phFile, pszFilename, param3);
67
68 /* log sucesses */
69 if (rc == NO_ERROR)
70 kprintf(("ldrOpen: phFile=%#.4x, flags=%#.8x, pszFn=%s\n", *phFile, param3, pszFilename));
71
72 /*
73 * Are we to intercept the loading?
74 * - Only if open were succesful and one of the loaders are enabled.
75 */
76 if (rc == NO_ERROR && (options.fElf || options.fPE != FLAGS_PE_NOT || options.fScript))
77 {
78 char *pszBuffer = (char*)rmalloc(640); /* Read buffer. */
79 PIMAGE_DOS_HEADER pMzHdr = (PIMAGE_DOS_HEADER)pszBuffer; /* Pointer to the buffer as it were a dosheader. */
80 PIMAGE_NT_HEADERS pNtHdrs = (PIMAGE_NT_HEADERS)pszBuffer; /* Pointer to the buffer as if it were an NT header. */
81 char *pach = pszBuffer; /* Finally an pointer to the buffer as if it were chars.. (which it is!) */
82 PEXECPGMBUFFER pBuffer; /* Pointer to a buffer containing the programname and arguments. */
83 /* For scripts and PE.EXE this has to be changed to have correct */
84 /* parameters sendt in to the program. */
85 unsigned cchRead = sizeof(IMAGE_DOS_HEADER); /* Amount of the buffer which contains valid data. */
86 unsigned cbFile; /* Filesize (0xffffffff if call to SftFileSize failed - should _never_ happen though) */
87
88 /*
89 * Verify that rmalloc completed successfully.
90 */
91 if (pszBuffer == NULL)
92 {
93 kprintf(("ldrOpen: rmalloc(1024) failed\n"));
94 return NO_ERROR;
95 }
96
97 /*
98 * Try get the filesize
99 */
100 /*
101 rc = SftFileSize(*phFile, (PULONG)SSToDS(&cbFile));
102 if (rc != NO_ERROR)
103 {
104 kprintf(("ldrOpen: SftFileSize failed with rc=%d\n", rc));
105 */
106 cbFile = (unsigned)~0;
107 /*
108 } */
109
110 /*
111 * See if this is an recognizable module format.
112 * This costs up to two disk reads!
113 */
114 rc = ldrRead(*phFile, 0UL, pMzHdr, 0UL, cchRead, NULL);
115 if (rc == NO_ERROR)
116 {
117 /*
118 * PE header?
119 * - If DOS Magic is found AND a valid e_lfanew (offset of NE/LX/LE/PE header) is found
120 * - OR if PE siganture is found.
121 */
122 if ((pMzHdr->e_magic == IMAGE_DOS_SIGNATURE &&
123 pMzHdr->e_lfanew > sizeof(IMAGE_DOS_HEADER) && pMzHdr->e_lfanew < 0x04000000UL) /* Larger than 64 bytes and less that 64MB. */
124 || *(PULONG)pach == IMAGE_NT_SIGNATURE)
125 { /*
126 * MZ or PE header found
127 */
128
129 /* if PE loading is diable return to the caller */
130 if (options.fPE == FLAGS_PE_NOT)
131 {
132 rfree(pszBuffer);
133 return NO_ERROR;
134 }
135
136 /*
137 * Read the PE header if it isn't what we allready have!
138 */
139 cchRead = sizeof(IMAGE_NT_HEADERS);
140 if (*(PULONG)pach != IMAGE_NT_SIGNATURE)
141 rc = ldrRead(*phFile, pMzHdr->e_lfanew, pach, 0UL, cchRead, NULL);
142 else
143 rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL);
144
145 /*
146 * If successfully read, and a PE signature is present the continue and try load it!
147 * Else don't do anything, simply return NO_ERROR to the caller. (probably NE or LX exec)
148 */
149 if (rc == NO_ERROR && *(PULONG)pach == IMAGE_NT_SIGNATURE)
150 { /*
151 * PE signature found.
152 */
153 kprintf(("ldrOpen: PE executable...\n"));
154
155 /*
156 * PE2LX?
157 * - When PE2LX flag is set
158 * - OR when the MIXED flag is set and the image is with the first 64MB of memory.
159 */
160 if (options.fPE == FLAGS_PE_PE2LX
161 || (options.fPE == FLAGS_PE_MIXED
162 && !((pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL == 0UL)
163 && pNtHdrs->OptionalHeader.ImageBase >= 0x04000000UL /* 64MB */
164 )
165 )
166 )
167 { /*
168 * Pe2Lx (Ring0 of course)
169 * - Create a Pe2Lx class,
170 * - initiate it
171 * - Add the module to the module tree so we may find it later...
172 * - Set the handle state to 'our'.
173 */
174 Pe2Lx * pPe2Lx = new Pe2Lx(*phFile);
175 if (pPe2Lx != NULL)
176 {
177 rc = pPe2Lx->init(pszFilename);
178 if (rc == NO_ERROR)
179 {
180 kprintf(("ldrOpen: Successfully init of Pe2Lx object.\n"));
181 rc = addModule(*phFile, NULL, MOD_TYPE_PE2LX, pPe2Lx);
182 if (rc == NO_ERROR)
183 #pragma info(notrd)
184 SetState(*phFile, HSTATE_OUR);
185 #pragma info(restore)
186 else
187 kprintf(("ldrOpen: Failed to add the module. rc=%d\n"));
188 }
189 else
190 kprintf(("ldrOpen: Failed to init Pe2Lx object. rc=%d\n"));
191 if (rc != NO_ERROR)
192 delete pPe2Lx;
193 }
194 else
195 kprintf(("ldrOpen: Failed to allocate Pe2Lx object.\n"));
196 }
197 else
198 {
199 /*
200 * Starting of PE.EXE enable?
201 */
202 if (options.fPE == FLAGS_PE_PE || options.fPE == FLAGS_PE_MIXED)
203 { /*
204 * pe.exe - need the path!
205 */
206 kprintf(("ldrOpen: pe.exe - opening\n"));
207 ldrClose(*phFile);
208 rc = ldrOpen(phFile, "pe.exe", param3); /* path....! problems! */
209 kprintf(("ldrOpen: pe.exe - open returned with rc = %d\n", rc));
210 rfree(pszBuffer);
211 return rc;
212 }
213 }
214 }
215 rfree(pszBuffer);
216 return NO_ERROR;
217 }
218 else
219 {
220 /*
221 * ELF image?
222 */
223 if (pach[0] == ELFMAG0 && pach[1] == ELFMAG1 && pach[2] == ELFMAG2 && pach[3] == ELFMAG3)
224 {
225 /*
226 * ELF signature found.
227 */
228 kprintf(("ldrOpen: ELF executable! - not implemented yet!\n"));
229
230 /*
231 * Do nothing more yet. NEED AN ELF LOADER!!!
232 */
233 rfree(pszBuffer);
234 return NO_ERROR;
235 }
236 }
237
238 /*
239 * Only unreconized files and readerror passes this point!
240 *
241 * * Fileformats with lower priority should reside here. *
242 *
243 */
244
245 /*
246 * If the initial readoperation failed try to read a smaller amount, in case it is a small script...
247 * 4 bytes is a small amount isn't it?
248 */
249 if (rc != NO_ERROR)
250 {
251 kprintf(("ldrOpen: first ldrread failed with rc=%d. tries to read 4 byte.\n", rc));
252 cchRead = 4;
253 if ((rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL)) != NO_ERROR)
254 kprintf(("ldrOpen: second ldrread failed with rc=%d.\n ", rc));
255 }
256
257 /*
258 * Now we'll try again, UNIX styled script?
259 */
260 if (rc == NO_ERROR && *pach == '#' && pach[1] == '!')
261 {
262 /*
263 * UNIX styled script?
264 * FIXME! Must be more than 64 bytes long?
265 * No options!
266 * Firstline < 64 bytes!
267 */
268 kprintf(("ldrOpen: unix script?\n"));
269
270 cchRead = min(cbFile, 256);
271 rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL);
272 if (rc != NO_ERROR)
273 {
274 char *pszStart = pach+2;
275 kprintf(("ldrOpen: scrtip debug 1\n"));
276
277 /* Make sure we don't read to much... */
278 pszBuffer[cchRead] = '\0';
279
280 /*
281 * Skip blanks
282 */
283 pszStart = pszBuffer + 2; /* skips the "#!" stuff. */
284 while (*pszStart != '\0' && (*pszStart == ' ' || *pszStart == '\t'))
285 pszStart++;
286 kprintf(("ldrOpen: scrtip debug 2\n"));
287
288 /* anything left on the line? */
289 if (*pszStart != '\0' && *pszStart != '\r' && *pszStart != '\n')
290 {
291 char * pszEnd; /* Pointer to the end of the string(s) when the next step is finished. */
292 //char * pszFirstArg; /* Pointer to the first argument, the one after the interpreter name. */
293 unsigned cchToAdd = 1; /* Chars to add */
294 int f = TRUE; /* flag which tells me if I have just closed the last argument. */
295 /*
296 * find linesize and make parameters ready for copying
297 */
298 pszEnd = pszStart;
299 kprintf(("ldrOpen: scrtip debug 3\n"));
300 //pszFirstArg = NULL;
301 while (*pszEnd != '\0' && *pszEnd != '\r' && *pszEnd != '\n')
302 {
303 if (f)
304 {
305 f = FALSE;
306 //if (pszFirstArg != NULL) pszFirstArg = pszEnd + 1;
307 }
308 else if (!f && (*pszEnd == ' ' || *pszEnd == '\t'))
309 {
310 *pszEnd = '\0';
311 f = TRUE;
312 }
313
314 /* next */
315 pszEnd++;
316 cchToAdd++;
317 }
318 *pszEnd = '\0';
319 kprintf(("ldrOpen: scrtip debug 4\n"));
320
321 /*
322 * Find the ExecPgm buffer.
323 */
324 pBuffer = QueryBufferPointerFromFilename(pszFilename);
325 kprintf(("ldrOpen: scrtip debug 5\n"));
326 if (pBuffer != NULL)
327 {
328 unsigned cchArguments = getArgsLength(pBuffer->achArgs);
329 kprintf(("ldrOpen: debug1\n"));
330
331 kprintf(("ldrOpen: scrtip debug 6\n"));
332
333 /*
334 * Is there enough space in the struct?
335 */
336 if (cchArguments + cchToAdd < sizeof(pBuffer->achArgs))
337 {
338 kprintf(("ldrOpen: scrtip debug 7\n"));
339 /*
340 * Open the interpreter.
341 */
342 rc = ldrClose(*phFile);
343 rc = ldrOpen(phFile, pszStart, param3); /* FIXME, recusion! check that name not equal! Use flags to prevent race? */
344 if (rc == NO_ERROR)
345 {
346 kprintf(("ldrOpen: scritp debug 8\n"));
347 /* Make space for the addition arguments. */
348 memmove(&pBuffer->achArgs[cchToAdd], &pBuffer->achArgs[0], cchArguments);
349 memcpy(&pBuffer->achArgs[0], pszBuffer, cchToAdd);
350 kprintf(("ldrOpen: scrtip debug 9\n"));
351 }
352 else
353 kprintf(("ldrOpen: failed to open interpreter (%s), rc=%d\n", pszStart, rc));
354 }
355 else
356 {
357 kprintf(("ldrOpen: Argument buffer too small, %d\n", cchArguments + cchToAdd));
358 rc = ERROR_BAD_EXE_FORMAT;
359 }
360 }
361 else
362 {
363 kprintf(("ldrOpen: QueryBufferPointerFromFilename failed.\n"));
364 rc = ERROR_BAD_EXE_FORMAT; /*?*/
365 }
366 }
367 else
368 {
369 kprintf(("ldrOpen: no interpereter on the first line.\n"));
370 rc = ERROR_BAD_EXE_FORMAT; /*?*/
371 }
372 }
373 else
374 {
375 kprintf(("ldrOpen: read of min(cbFile, 256) = %d failed, rc = %d\n", cchRead, rc));
376 }
377 } /* else inn other formats here. */
378 }
379 else
380 {
381 kprintf(("ldrOpen: ldrRead failed with rc=%d when reading DosHdr.\n", rc));
382 rc = NO_ERROR;
383 }
384 rfree(pszBuffer);
385 }
386 return rc;
387}
388
389
390/**
391 * Get the lenght of the arguments.
392 * @returns Lenght in char, includes the two '\0's.
393 * @param pachArgs Pointer to the ASCIIZs which makes up the arguments.
394 * @status completely implemented.
395 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
396 */
397static unsigned getArgsLength(const char *pachArgs)
398{
399 unsigned cch = 1;
400 const char *psz = pachArgs;
401
402 while (*psz != '\0')
403 {
404 register unsigned cch2 = strlen(psz);
405 cch += cch2;
406 psz += cch2 + 1;
407 }
408
409 return cch;
410}
Note: See TracBrowser for help on using the repository browser.