source: trunk/src/peldr/initterm.cpp@ 2570

Last change on this file since 2570 was 2570, checked in by sandervl, 26 years ago

Some bugfixes

File size: 8.0 KB
Line 
1/* $Id: initterm.cpp,v 1.6 2000-01-30 12:56:02 sandervl Exp $ */
2
3/*
4 * PELDR DLL entry point
5 *
6 * Copyright 1998 Sander van Leeuwen
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13/*-------------------------------------------------------------*/
14/* INITERM.C -- Source for a custom dynamic link library */
15/* initialization and termination (_DLL_InitTerm) */
16/* function. */
17/* */
18/* When called to perform initialization, this sample function */
19/* gets storage for an array of integers, and initializes its */
20/* elements with random integers. At termination time, it */
21/* frees the array. Substitute your own special processing. */
22/*-------------------------------------------------------------*/
23
24
25/* Include files */
26#define INCL_DOSMODULEMGR
27#define INCL_DOSPROCESS
28#define INCL_DOSMISC
29#include <os2.h>
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33#include <odin.h>
34#include <misc.h> /*PLF Wed 98-03-18 23:18:15*/
35#include <winimagepeldr.h>
36
37#ifndef PAG_ANY
38 #define PAG_ANY 0x00000400
39#endif
40
41#ifndef QSV_VIRTUALADDRESSLIMIT
42 #define QSV_VIRTUALADDRESSLIMIT 30
43#endif
44
45#define FALLOC_SIZE (1024*1024)
46
47/*-------------------------------------------------------------------*/
48/* A clean up routine registered with DosExitList must be used if */
49/* runtime calls are required and the runtime is dynamically linked. */
50/* This will guarantee that this clean up routine is run before the */
51/* library DLL is terminated. */
52/*-------------------------------------------------------------------*/
53static void APIENTRY cleanup(ULONG reason);
54
55ULONG reservedMemory = 0;
56
57void AllocateExeMem(char *filename);
58
59/****************************************************************************/
60/* _DLL_InitTerm is the function that gets called by the operating system */
61/* loader when it loads and frees this DLL for each process that accesses */
62/* this DLL. However, it only gets called the first time the DLL is loaded */
63/* and the last time it is freed for a particular process. The system */
64/* linkage convention MUST be used because the operating system loader is */
65/* calling this function. */
66/****************************************************************************/
67unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long
68 ulFlag)
69{
70 size_t i;
71 APIRET rc;
72
73 /*-------------------------------------------------------------------------*/
74 /* If ulFlag is zero then the DLL is being loaded so initialization should */
75 /* be performed. If ulFlag is 1 then the DLL is being freed so */
76 /* termination should be performed. */
77 /*-------------------------------------------------------------------------*/
78
79 switch (ulFlag) {
80 case 0 :
81 {
82 PTIB ptib;
83 PPIB ppib;
84 char *win32app;
85
86 /*******************************************************************/
87 /* The C run-time environment initialization function must be */
88 /* called before any calls to C run-time functions that are not */
89 /* inlined. */
90 /*******************************************************************/
91
92 DosGetInfoBlocks(&ptib, &ppib);
93 win32app = ppib->pib_pchcmd + strlen(ppib->pib_pchcmd) + 1;
94 AllocateExeMem(win32app);
95
96 /*******************************************************************/
97 /* A DosExitList routine must be used to clean up if runtime calls */
98 /* are required and the runtime is dynamically linked. */
99 /*******************************************************************/
100 break;
101 }
102 case 1 :
103 break;
104 default :
105 return 0UL;
106 }
107
108 /***********************************************************/
109 /* A non-zero value must be returned to indicate success. */
110 /***********************************************************/
111 return 1UL;
112}
113//******************************************************************************
114//******************************************************************************
115ULONG SYSTEM ReserveMem()
116{
117 return reservedMemory;
118}
119//******************************************************************************
120//SvL: Reserve memory for win32 exes without fixups
121// This is done before any Odin or PMWIN dll is loaded, so we'll get
122// a very low virtual address. (which is exactly what we want)
123//******************************************************************************
124void AllocateExeMem(char *filename)
125{
126 HFILE dllfile = 0;
127 char szFileName[CCHMAXPATH], *tmp;
128 ULONG action, ulRead, signature;
129 APIRET rc;
130 IMAGE_DOS_HEADER doshdr;
131 IMAGE_OPTIONAL_HEADER oh;
132 IMAGE_FILE_HEADER fh;
133 ULONG address = 0;
134 ULONG *memallocs;
135 ULONG alloccnt = 0;
136 ULONG diff, i, baseAddress;
137 ULONG ulSysinfo, flAllocMem = 0;
138
139 strcpy(szFileName, filename);
140 tmp = szFileName;
141 while(*tmp != ' ' && *tmp != 0)
142 tmp++;
143 *tmp = 0;
144
145 if(!strchr(szFileName, '.')) {
146 strcat(szFileName,".EXE");
147 }
148 rc = DosOpen(szFileName, &dllfile, &action, 0, FILE_READONLY, OPEN_ACTION_OPEN_IF_EXISTS|OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY, NULL);
149 if(rc != 0) {
150 if(!strstr(szFileName, ".EXE")) {
151 strcat(szFileName,".EXE");
152 }
153 }
154 else DosClose(dllfile);
155
156 rc = DosOpen(szFileName, &dllfile, &action, 0, FILE_READONLY, OPEN_ACTION_OPEN_IF_EXISTS|OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY, NULL);
157 if(rc) {
158 goto end; //oops
159 }
160
161 //read dos header
162 if(DosRead(dllfile, (LPVOID)&doshdr, sizeof(doshdr), &ulRead)) {
163 goto end;
164 }
165 if(DosSetFilePtr(dllfile, doshdr.e_lfanew, FILE_BEGIN, &ulRead)) {
166 goto end;
167 }
168 //read signature dword
169 if(DosRead(dllfile, (LPVOID)&signature, sizeof(signature), &ulRead)) {
170 goto end;
171 }
172 //read pe header
173 if(DosRead(dllfile, (LPVOID)&fh, sizeof(fh), &ulRead)) {
174 goto end;
175 }
176 //read optional header
177 if(DosRead(dllfile, (LPVOID)&oh, sizeof(oh), &ulRead)) {
178 goto end;
179 }
180 if(doshdr.e_magic != IMAGE_DOS_SIGNATURE || signature != IMAGE_NT_SIGNATURE) {
181 goto end;
182 }
183 if(!(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)) {
184 goto end; //no need to allocate anything now
185 }
186
187 // check for high memory support
188 rc = DosQuerySysInfo(QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ulSysinfo, sizeof(ulSysinfo));
189 if (rc == 0 && ulSysinfo > 512) //VirtualAddresslimit is in MB
190 {
191 flAllocMem = PAG_ANY; // high memory support. Let's use it!
192 }
193
194 //Reserve enough space to store 4096 pointers to 1MB memory chunks
195 memallocs = (ULONG *)alloca(4096*sizeof(ULONG *));
196 if(memallocs == NULL) {
197 goto end; //oops
198 }
199
200 if(oh.ImageBase < 512*1024*1024) {
201 flAllocMem = 0;
202 }
203 else {
204 if(flAllocMem == 0) {
205 goto end; //no support for > 512 MB
206 }
207 }
208 while(TRUE) {
209 rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | flAllocMem);
210 if(rc) break;
211
212 if(address + FALLOC_SIZE >= oh.ImageBase) {
213 if(address > oh.ImageBase) {//we've passed it!
214 DosFreeMem((PVOID)address);
215 break;
216 }
217 //found the right address
218 DosFreeMem((PVOID)address);
219
220 diff = oh.ImageBase - address;
221 if(diff) {
222 rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | flAllocMem);
223 if(rc) break;
224 }
225 rc = DosAllocMem((PPVOID)&baseAddress, oh.SizeOfImage, PAG_READ | PAG_WRITE | flAllocMem);
226 if(rc) break;
227
228 if(diff) DosFreeMem((PVOID)address);
229
230 reservedMemory = baseAddress;
231 break;
232 }
233 memallocs[alloccnt++] = address;
234 }
235 for(i=0;i<alloccnt;i++) {
236 DosFreeMem((PVOID)memallocs[i]);
237 }
238
239end:
240 if(dllfile) DosClose(dllfile);
241 return;
242}
243//******************************************************************************
244//******************************************************************************
Note: See TracBrowser for help on using the repository browser.