Release 940620
[wine] / loader / main.c
1 static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
2 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <errno.h>
12 #ifdef linux
13 #include <linux/unistd.h>
14 #include <linux/head.h>
15 #include <linux/ldt.h>
16 #include <linux/segment.h>
17 #endif
18 #include "neexe.h"
19 #include "segmem.h"
20 #include "prototypes.h"
21 #include "dlls.h"
22 #include "wine.h"
23 #include "windows.h"
24 #include "wineopts.h"
25 #include "arch.h"
26 #include "options.h"
27
28 /* #define DEBUG_FIXUP */
29
30 extern HANDLE CreateNewTask(HINSTANCE hInst);
31 extern int CallToInit16(unsigned long csip, unsigned long sssp, 
32                         unsigned short ds);
33 extern void CallTo32();
34
35 char *GetDosFileName(char *unixfilename);
36 char *GetModuleName(struct w_files * wpnt, int index, char *buffer);
37 extern unsigned char ran_out;
38 extern char WindowsPath[256];
39 char *WIN_ProgramName;
40
41 unsigned short WIN_StackSize;
42 unsigned short WIN_HeapSize;
43
44 struct  w_files * wine_files = NULL;
45
46 char **Argv;
47 int Argc;
48 HINSTANCE hSysRes;
49
50 static char *DLL_Extensions[] = { "dll", NULL };
51 static char *EXE_Extensions[] = { "exe", NULL };
52
53 /**********************************************************************
54  *                                      myerror
55  */
56 void
57 myerror(const char *s)
58 {
59     if (s == NULL)
60         perror("wine");
61     else
62         fprintf(stderr, "wine: %s\n", s);
63
64     exit(1);
65 }
66 \f
67 /**********************************************************************
68  *                                      GetFilenameFromInstance
69  */
70 char *
71 GetFilenameFromInstance(unsigned short instance)
72 {
73     register struct w_files *w = wine_files;
74
75     while (w && w->hinstance != instance)
76         w = w->next;
77     
78     if (w)
79         return w->filename;
80     else
81         return NULL;
82 }
83
84 struct w_files *
85 GetFileInfo(unsigned short instance)
86 {
87     register struct w_files *w = wine_files;
88
89     while (w && w->hinstance != instance)
90         w = w->next;
91     
92     return w;
93 }
94 \f
95 #ifndef WINELIB
96 /**********************************************************************
97  *
98  * Load MZ Header
99  */
100 void load_mz_header(int fd, struct mz_header_s *mz_header)
101 {
102     if (read(fd, mz_header, sizeof(struct mz_header_s)) !=
103         sizeof(struct mz_header_s))
104     {
105         myerror("Unable to read MZ header from file");
106     }
107 }
108 #endif
109
110 int IsDLLLoaded(char *name)
111 {
112         struct w_files *wpnt;
113
114         if(FindDLLTable(name))
115                 return 1;
116
117         for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
118                 if(strcmp(wpnt->name, name) == 0)
119                         return 1;
120
121         return 0;
122 }
123
124 /**********************************************************************
125  *                      LoadImage
126  * Load one executable into memory
127  */
128 HINSTANCE LoadImage(char *module, int filetype, int change_dir)
129 {
130     unsigned int read_size;
131     int i;
132     struct w_files * wpnt, *wpnt1;
133     unsigned int status;
134     char buffer[256], header[2], modulename[64], *fullname;
135
136     ExtractDLLName(module, modulename);
137     printf("%sLoadImage \n", module);
138     /* built-in one ? */
139     if (FindDLLTable(modulename)) {
140         return GetModuleHandle(modulename);
141     }
142     
143     /* already loaded ? */
144     for (wpnt = wine_files ; wpnt ; wpnt = wpnt->next)
145         if (strcasecmp(wpnt->name, modulename) == 0)
146                 return wpnt->hinstance;
147
148     /*
149      * search file
150      */
151     fullname = FindFile(buffer, sizeof(buffer), module, 
152                         (filetype == EXE ? EXE_Extensions : DLL_Extensions), 
153                         WindowsPath);
154     if (fullname == NULL)
155     {
156         fprintf(stderr, "LoadImage: I can't find %s.dll | %s.exe !\n",
157                 module, module);
158         return 2;
159     }
160
161     fullname = GetDosFileName(fullname);
162     WIN_ProgramName = strdup(fullname);
163     
164     fprintf(stderr,"LoadImage: loading %s (%s)\n           [%s]\n", 
165             module, buffer, WIN_ProgramName);
166
167     if (change_dir && fullname)
168     {
169         char dirname[256];
170         char *p;
171
172         strcpy(dirname, fullname);
173         p = strrchr(dirname, '\\');
174         *p = '\0';
175
176         DOS_SetDefaultDrive(dirname[0] - 'A');
177         DOS_ChangeDir(dirname[0] - 'A', dirname + 2);
178     }
179
180     /* First allocate a spot to store the info we collect, and add it to
181      * our linked list.
182      */
183
184     wpnt = (struct w_files *) malloc(sizeof(struct w_files));
185     if(wine_files == NULL)
186       wine_files = wpnt;
187     else {
188       wpnt1 = wine_files;
189       while(wpnt1->next) wpnt1 =  wpnt1->next;
190       wpnt1->next  = wpnt;
191     };
192     wpnt->next = NULL;
193     wpnt->resnamtab = (RESNAMTAB *) -1;
194
195     /*
196      * Open file for reading.
197      */
198     wpnt->fd = open(buffer, O_RDONLY);
199     if (wpnt->fd < 0)
200         return 2;
201
202     /* 
203      * Establish header pointers.
204      */
205     wpnt->filename = strdup(buffer);
206     wpnt->name = strdup(modulename);
207
208 /*    if(module) {
209         wpnt->name = strdup(module);
210         ToDos(wpnt->name);
211     }*/
212
213     /* read mz header */
214     wpnt->mz_header = (struct mz_header_s *) malloc(sizeof(struct mz_header_s));;
215     status = lseek(wpnt->fd, 0, SEEK_SET);
216     load_mz_header (wpnt->fd, wpnt->mz_header);
217     if (wpnt->mz_header->must_be_0x40 != 0x40 &&
218         wpnt->mz_header->must_be_0x40 != 0x1e)
219         myerror("This is not a Windows program");
220
221     /* read first two bytes to determine filetype */
222     status = lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
223     read(wpnt->fd, &header, sizeof(header));
224
225     if (header[0] == 'N' && header[1] == 'E')
226         return (LoadNEImage(wpnt));
227
228     if (header[0] == 'P' && header[1] == 'E') {
229       printf("win32 applications are not supported");
230       return 14;
231     }
232
233     fprintf(stderr, "wine: (%s) unknown fileformat !\n", wpnt->filename);
234
235     return 14;
236 }
237 \f
238 #ifndef WINELIB
239 /**********************************************************************
240  *                                      main
241  */
242 int _WinMain(int argc, char **argv)
243 {
244         int segment;
245         char *p;
246         char *sysresname;
247         char filename[256];
248         HANDLE          hTaskMain;
249         HINSTANCE       hInstMain;
250 #ifdef WINESTAT
251         char * cp;
252 #endif
253         struct w_files * wpnt;
254         int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
255         int rv;
256
257         Argc = argc - 1;
258         Argv = argv + 1;
259
260         if (strchr(Argv[0], '\\') || strchr(Argv[0],'/')) {
261             for (p = Argv[0] + strlen(Argv[0]); *p != '\\' && *p !='/'; p--)
262                 /* NOTHING */;
263                 
264             strncpy(filename, Argv[0], p - Argv[0]);
265             filename[p - Argv[0]] = '\0';
266             strcat(WindowsPath, ";");
267             strcat(WindowsPath, filename);
268         }
269         
270         if ((hInstMain = LoadImage(Argv[0], EXE, 1)) < 32) {
271                 fprintf(stderr, "wine: can't load %s!.\n", Argv[0]);
272                 exit(1);
273         }
274         hTaskMain = CreateNewTask(hInstMain);
275         printf("_WinMain // hTaskMain=%04X hInstMain=%04X !\n", hTaskMain, hInstMain);
276
277         GetPrivateProfileString("wine", "SystemResources", "sysres.dll", 
278                                 filename, sizeof(filename), WINE_INI);
279
280         hSysRes = LoadImage(filename, DLL, 0);
281         if (hSysRes < 32) {
282                 fprintf(stderr, "wine: can't load %s!.\n", filename);
283                 exit(1);
284         } else
285             printf("System Resources Loaded // hSysRes='%04X'\n", hSysRes);
286         
287     /*
288      * Fixup references.
289      */
290 /*    wpnt = wine_files;
291     for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
292         for (segment = 0; segment < wpnt->ne_header->n_segment_tab; segment++)
293             if (FixupSegment(wpnt, segment) < 0)
294                 myerror("fixup failed.");
295 */
296
297 #ifdef WINESTAT
298     cp = strrchr(argv[0], '/');
299     if(!cp) cp = argv[0];
300         else cp++;
301     if(strcmp(cp,"winestat") == 0) {
302             winestat();
303             exit(0);
304     };
305 #endif
306
307     /*
308      * Initialize signal handling.
309      */
310     init_wine_signals();
311
312     /*
313      * Fixup stack and jump to start.
314      */
315     WIN_StackSize = wine_files->ne_header->stack_length;
316     WIN_HeapSize = wine_files->ne_header->local_heap_length;
317
318     ds_reg = (wine_files->
319               selector_table[wine_files->ne_header->auto_data_seg-1].selector);
320     cs_reg = wine_files->selector_table[wine_files->ne_header->cs-1].selector;
321     ip_reg = wine_files->ne_header->ip;
322     ss_reg = wine_files->selector_table[wine_files->ne_header->ss-1].selector;
323     sp_reg = wine_files->ne_header->sp;
324
325     if (Options.debug) wine_debug(0, NULL);
326
327     rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
328     printf ("rv = %x\n", rv);
329 }
330
331 void InitDLL(struct w_files *wpnt)
332 {
333         int cs_reg, ds_reg, ip_reg, rv;
334         /* 
335          * Is this a library? 
336          */
337         if (wpnt->ne_header->format_flags & 0x8000)
338         {
339             if (!(wpnt->ne_header->format_flags & 0x0001))
340             {
341                 /* Not SINGLEDATA */
342                 fprintf(stderr, "Library is not marked SINGLEDATA\n");
343                 exit(1);
344             }
345
346             ds_reg = wpnt->selector_table[wpnt->
347                                           ne_header->auto_data_seg-1].selector;
348             cs_reg = wpnt->selector_table[wpnt->ne_header->cs-1].selector;
349             ip_reg = wpnt->ne_header->ip;
350
351             if (cs_reg) {
352                 fprintf(stderr, "Initializing %s, cs:ip %04x:%04x, ds %04x\n", 
353                     wpnt->name, cs_reg, ip_reg, ds_reg);
354                     
355                 rv = CallTo16(cs_reg << 16 | ip_reg, ds_reg);
356                 printf ("rv = %x\n", rv);
357             } else
358                 printf("%s skipped\n");
359         }
360 }
361
362 void InitializeLoadedDLLs(struct w_files *wpnt)
363 {
364     static flagReadyToRun = 0;
365     struct w_files *final_wpnt;
366
367     printf("InitializeLoadedDLLs %08X\n", wpnt);
368
369     if (wpnt == NULL)
370     {
371         flagReadyToRun = 1;
372         fprintf(stderr, "Initializing DLLs\n");
373     }
374     
375     if (!flagReadyToRun)
376         return;
377
378 #if 1
379     if (wpnt != NULL)
380         fprintf(stderr, "Initializing %s\n", wpnt->name);
381 #endif
382
383     /*
384      * Initialize libraries
385      */
386     if (!wpnt)
387     {
388         wpnt = wine_files;
389         final_wpnt = NULL;
390     }
391     else
392     {
393         final_wpnt = wpnt->next;
394     }
395     
396     for( ; wpnt != final_wpnt; wpnt = wpnt->next)
397         InitDLL(wpnt);
398 }
399 #endif /* #ifndef WINELIB */