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

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

Allocate low memory at right address and with right size in peldr.dll (fixes install of Windows Media Player)

File size: 7.9 KB
Line 
1/* $Id: initterm.cpp,v 1.4 2000-01-25 20:27:58 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;
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;
138
139 tmp = filename;
140 while(*tmp != ' ' && *tmp != 0)
141 tmp++;
142 *tmp = 0;
143
144 strcpy(szFileName, filename);
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 return; //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*124) {
201 flAllocMem = 0;
202 }
203 while(TRUE) {
204 rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | flAllocMem);
205 if(rc) break;
206
207 if(address + FALLOC_SIZE >= oh.ImageBase) {
208 if(address > oh.ImageBase) {//we've passed it!
209 DosFreeMem((PVOID)address);
210 break;
211 }
212 //found the right address
213 DosFreeMem((PVOID)address);
214
215 diff = oh.ImageBase - address;
216 if(diff) {
217 rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | flAllocMem);
218 if(rc) break;
219 }
220 rc = DosAllocMem((PPVOID)&baseAddress, oh.SizeOfImage, PAG_READ | PAG_WRITE | flAllocMem);
221 if(rc) break;
222
223 if(diff) DosFreeMem((PVOID)address);
224
225 reservedMemory = baseAddress;
226 break;
227 }
228 memallocs[alloccnt++] = address;
229 }
230 for(i=0;i<alloccnt;i++) {
231 DosFreeMem((PVOID)memallocs[i]);
232 }
233
234end:
235 DosClose(dllfile);
236 return;
237}
238//******************************************************************************
239//******************************************************************************
Note: See TracBrowser for help on using the repository browser.