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

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

Corrected buffer.asm and displays in myldrOpen.cpp.

File size: 16.4 KB
Line 
1/* $Id: myldrOpen.cpp,v 1.9 2000-02-21 05:00:52 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: script 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: script 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: script 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: script debug 4\n"));
320
321 /*
322 * Find the ExecPgm buffer.
323 */
324 pBuffer = QueryBufferPointerFromFilename(pszFilename);
325 kprintf(("ldrOpen: script debug 5\n"));
326 if (pBuffer != NULL)
327 {
328 unsigned cchArguments = getArgsLength(pBuffer->achArgs);
329 kprintf(("ldrOpen: debug1\n"));
330
331 kprintf(("ldrOpen: script 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: script 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: script 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.