]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/dos/win32lrd.c
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / dos / win32lrd.c
1 /* dos.c
2  *
3  * Code to detect the surrounding DOS/Windows environment and support routines to work with it
4  * (C) 2009-2012 Jonathan Campbell.
5  * Hackipedia DOS library.
6  *
7  * This code is licensed under the LGPL.
8  * <insert LGPL legal text here>
9  */
10
11 #ifdef TARGET_WINDOWS
12 # include <windows.h>
13 #endif
14
15 #include <stdio.h>
16 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stddef.h>
20 #include <unistd.h>
21 #include <malloc.h>
22 #include <assert.h>
23 #include <fcntl.h>
24 #include <dos.h>
25
26 #include <hw/cpu/cpu.h>
27 #include <hw/dos/dos.h>
28 #include <hw/dos/doswin.h>
29 #include <hw/dos/dosntvdm.h>
30
31 #if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386)
32
33 /* this library of code deals with the problem of getting ordinal-only exported functions out of KERNEL32.DLL in
34  * Windows 9x/ME. GetProcAddress() won't do it for us, so instead, we forcibly read it out from memory ourself.
35  * That's what you get for being a jack-ass about Win16 compatibility Microsoft */
36
37 /* Note that this code would work under Windows 9x/ME and NT/2000/XP, but it is only needed for 9x/ME.
38  * Windows XP SP2 and later change the handle slightly to try and confuse code like this (they take the HANDLE
39  * value of the module and set the least significant bit), and I have reason to believe Microsoft will eventually
40  * outright change the interface to make the handle an actual opaque handle someday (while of course making it
41  * utterly impossible for programs like us to get to the API functions we need to do our fucking job). Because they're
42  * Microsoft, and that's what they do with the Windows API. */
43
44 /* How to use: Use the 32-bit GetModuleHandle() function to get the HMODULE value. In Windows so far, this HMODULE
45  * value is literally the linear memory address where Windows loaded (or mapped) the base of the DLL image, complete
46  * with MS-DOS header and PE image. This hack relies on that to then traverse the PE structure directly and forcibly
47  * retrieve from the ordinal export table the function we desire. */
48
49 /* returns: DWORD* pointer to PE image's export ordinal table, *entries is filled with the number of entries, *base
50  * is filled with the ordinal number of the first entry. */
51
52 static IMAGE_NT_HEADERS *Win32ValidateHModuleMSDOS_PE_Header(BYTE *p) {
53         if (!memcmp(p,"MZ",2)) {
54                 /* then at offset 0x3C there should be the offset to the PE header */
55                 DWORD offset = *((DWORD*)(p+0x3C));
56                 if (offset < 0x40 || offset > 0x10000) return NULL;
57                 p += offset;
58                 if (IsBadReadPtr(p,4096)) return NULL;
59                 if (!memcmp(p,"PE\0\0",4)) {
60                         /* wait, before we celebrate, make sure it's sane! */
61                         IMAGE_NT_HEADERS *pp = (IMAGE_NT_HEADERS*)p;
62
63                         if (pp->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
64                                 return NULL;
65                         if (pp->FileHeader.SizeOfOptionalHeader < 88) /* <- FIXME */
66                                 return NULL;
67                         if (pp->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
68                                 return NULL;
69
70                         return pp;
71                 }
72         }
73
74         return NULL;
75 }
76
77 static IMAGE_DATA_DIRECTORY *Win32GetDataDirectory(IMAGE_NT_HEADERS *p) {
78         return p->OptionalHeader.DataDirectory;
79 }
80
81 DWORD *Win32GetExportOrdinalTable(HMODULE mod,DWORD *entries,DWORD *base,DWORD *base_addr) {
82         IMAGE_EXPORT_DIRECTORY *exdir;
83         IMAGE_DATA_DIRECTORY *dir;
84         IMAGE_NT_HEADERS *ptr;
85
86         /* Hack for Windows XP SP2: Clear the LSB, the OS sets it for some reason */
87         mod = (HMODULE)((DWORD)mod & 0xFFFFF000UL);
88         /* reset vars */
89         *entries = *base = 0;
90         if (mod == NULL) return NULL;
91
92         /* the module pointer should point an image of the DLL in memory. Right at the pointer we should see
93          * the letters "MZ" and the MS-DOS stub EXE header */
94         ptr = Win32ValidateHModuleMSDOS_PE_Header((BYTE*)mod);
95         if (ptr == NULL) return NULL;
96
97         /* OK, now locate the Data Directory. The number of entries is in ptr->OptionalHeader.NumberOfRvaAndSizes */
98         dir = Win32GetDataDirectory(ptr);
99         if (ptr == NULL) return NULL;
100
101         /* the first directory is the Export Address Table */
102         exdir = (IMAGE_EXPORT_DIRECTORY*)((DWORD)mod + (DWORD)dir->VirtualAddress);
103         if (IsBadReadPtr(exdir,2048)) return NULL;
104
105         *base = exdir->Base;
106         *entries = exdir->NumberOfFunctions;
107         *base_addr = (DWORD)mod;
108         return (DWORD*)((DWORD)mod + exdir->AddressOfFunctions);
109 }
110
111 int Win32GetOrdinalLookupInfo(HMODULE mod,Win32OrdinalLookupInfo *info) {
112         DWORD *x = Win32GetExportOrdinalTable(mod,&info->entries,&info->base,&info->base_addr);
113         if (x == NULL) return 0;
114         info->table = x;
115         return 1;
116 }
117
118 void *Win32GetOrdinalAddress(Win32OrdinalLookupInfo *nfo,unsigned int ord) {
119         if (nfo == NULL || nfo->table == NULL) return NULL;
120         if (ord < nfo->base) return NULL;
121         if (ord >= (nfo->base+nfo->entries)) return NULL;
122         return (void*)((char*)nfo->table[ord-nfo->base] + nfo->base_addr);
123 }
124 #endif
125