Alexandre Julliard | 234bc24 | 1994-12-10 13:02:28 +0000 | [diff] [blame] | 1 | /* |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 2 | * NE segment loading |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright 1993 Robert J. Amstadt |
| 5 | * Copyright 1995 Alexandre Julliard |
| 6 | */ |
| 7 | |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 8 | #include <assert.h> |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 9 | #include <stdio.h> |
| 10 | #include <stdlib.h> |
| 11 | #include <sys/types.h> |
| 12 | #include <sys/stat.h> |
| 13 | #include <fcntl.h> |
| 14 | #include <unistd.h> |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 15 | #include <ctype.h> |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 16 | #include <string.h> |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame] | 17 | |
| 18 | #include "wine/winbase16.h" |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 19 | #include "wine/library.h" |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 20 | #include "global.h" |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 21 | #include "task.h" |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 22 | #include "file.h" |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 23 | #include "module.h" |
| 24 | #include "stackframe.h" |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 25 | #include "builtin16.h" |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 26 | #include "debugtools.h" |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 27 | |
Alexandre Julliard | 198746d | 2000-08-14 14:29:22 +0000 | [diff] [blame] | 28 | DECLARE_DEBUG_CHANNEL(dll); |
| 29 | DECLARE_DEBUG_CHANNEL(fixup); |
| 30 | DECLARE_DEBUG_CHANNEL(module); |
| 31 | DECLARE_DEBUG_CHANNEL(segment); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 32 | |
Alexandre Julliard | 7afce0e | 2000-12-01 21:25:31 +0000 | [diff] [blame] | 33 | /* |
| 34 | * Relocation table entry |
| 35 | */ |
| 36 | struct relocation_entry_s |
| 37 | { |
| 38 | BYTE address_type; /* Relocation address type */ |
| 39 | BYTE relocation_type; /* Relocation type */ |
| 40 | WORD offset; /* Offset in segment to fixup */ |
| 41 | WORD target1; /* Target specification */ |
| 42 | WORD target2; /* Target specification */ |
| 43 | }; |
| 44 | |
| 45 | /* |
| 46 | * Relocation address types |
| 47 | */ |
| 48 | #define NE_RADDR_LOWBYTE 0 |
| 49 | #define NE_RADDR_SELECTOR 2 |
| 50 | #define NE_RADDR_POINTER32 3 |
| 51 | #define NE_RADDR_OFFSET16 5 |
| 52 | #define NE_RADDR_POINTER48 11 |
| 53 | #define NE_RADDR_OFFSET32 13 |
| 54 | |
| 55 | /* |
| 56 | * Relocation types |
| 57 | */ |
| 58 | #define NE_RELTYPE_INTERNAL 0 |
| 59 | #define NE_RELTYPE_ORDINAL 1 |
| 60 | #define NE_RELTYPE_NAME 2 |
| 61 | #define NE_RELTYPE_OSFIXUP 3 |
| 62 | #define NE_RELFLAG_ADDITIVE 4 |
| 63 | |
Andreas Mohr | 5a08a02 | 1999-07-31 13:11:22 +0000 | [diff] [blame] | 64 | #define SEL(x) ((x)|1) |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 65 | |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 66 | static void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum); |
| 67 | |
Alexandre Julliard | 198746d | 2000-08-14 14:29:22 +0000 | [diff] [blame] | 68 | /* ### start build ### */ |
| 69 | extern WORD CALLBACK NE_CallTo16_word_ww(FARPROC16,WORD,WORD); |
| 70 | extern WORD CALLBACK NE_CallTo16_word_www(FARPROC16,WORD,WORD,WORD); |
| 71 | /* ### stop build ### */ |
| 72 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 73 | /*********************************************************************** |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 74 | * NE_GetRelocAddrName |
| 75 | */ |
| 76 | static const char *NE_GetRelocAddrName( BYTE addr_type, int additive ) |
| 77 | { |
| 78 | switch(addr_type & 0x7f) |
| 79 | { |
| 80 | case NE_RADDR_LOWBYTE: return additive ? "BYTE add" : "BYTE"; |
| 81 | case NE_RADDR_OFFSET16: return additive ? "OFFSET16 add" : "OFFSET16"; |
| 82 | case NE_RADDR_POINTER32: return additive ? "POINTER32 add" : "POINTER32"; |
| 83 | case NE_RADDR_SELECTOR: return additive ? "SELECTOR add" : "SELECTOR"; |
| 84 | case NE_RADDR_POINTER48: return additive ? "POINTER48 add" : "POINTER48"; |
| 85 | case NE_RADDR_OFFSET32: return additive ? "OFFSET32 add" : "OFFSET32"; |
| 86 | } |
| 87 | return "???"; |
| 88 | } |
| 89 | |
| 90 | |
| 91 | /*********************************************************************** |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 92 | * NE_LoadSegment |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 93 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 94 | BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 95 | { |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 96 | SEGTABLEENTRY *pSegTable, *pSeg; |
| 97 | WORD *pModuleTable; |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 98 | WORD count, i, offset, next_offset; |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 99 | HMODULE16 module; |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 100 | FARPROC16 address = 0; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 101 | HFILE hf; |
Alexandre Julliard | 1392658 | 1999-01-01 16:55:02 +0000 | [diff] [blame] | 102 | DWORD res; |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 103 | struct relocation_entry_s *rep, *reloc_entries; |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 104 | BYTE *func_name; |
Alexandre Julliard | b7258be | 1995-09-01 15:57:28 +0000 | [diff] [blame] | 105 | int size; |
| 106 | char* mem; |
Alexandre Julliard | 234bc24 | 1994-12-10 13:02:28 +0000 | [diff] [blame] | 107 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 108 | char buffer[256]; |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 109 | int ordinal, additive; |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 110 | unsigned short *sp; |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 111 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 112 | pSegTable = NE_SEG_TABLE( pModule ); |
| 113 | pSeg = pSegTable + segnum - 1; |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 114 | |
Andreas Mohr | f2df6a2 | 2000-03-07 12:26:16 +0000 | [diff] [blame] | 115 | if (pSeg->flags & NE_SEGFLAGS_LOADED) |
| 116 | { |
| 117 | /* self-loader ? -> already loaded it */ |
| 118 | if (pModule->flags & NE_FFLAGS_SELFLOAD) |
| 119 | return TRUE; |
| 120 | |
| 121 | /* leave, except for DGROUP, as this may be the second instance */ |
| 122 | if (segnum != pModule->dgroup) |
| 123 | return TRUE; |
| 124 | } |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 125 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 126 | if (!pSeg->filepos) return TRUE; /* No file image, just return */ |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 127 | |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 128 | pModuleTable = NE_MODULE_TABLE( pModule ); |
| 129 | |
Alexandre Julliard | 1392658 | 1999-01-01 16:55:02 +0000 | [diff] [blame] | 130 | hf = NE_OpenFile( pModule ); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 131 | TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n", |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 132 | segnum, pSeg->hSeg, pSeg->flags ); |
Alexandre Julliard | 1392658 | 1999-01-01 16:55:02 +0000 | [diff] [blame] | 133 | SetFilePointer( hf, pSeg->filepos << pModule->alignment, NULL, SEEK_SET ); |
Alexandre Julliard | df2673b | 1997-03-29 17:20:20 +0000 | [diff] [blame] | 134 | if (pSeg->size) size = pSeg->size; |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 135 | else size = pSeg->minsize ? pSeg->minsize : 0x10000; |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 136 | mem = GlobalLock16(pSeg->hSeg); |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 137 | if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1) |
| 138 | { |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 139 | /* Implement self-loading segments */ |
Alexandre Julliard | ff8331e | 1995-09-18 11:19:54 +0000 | [diff] [blame] | 140 | SELFLOADHEADER *selfloadheader; |
Alexandre Julliard | d37eb36 | 1997-07-20 16:23:21 +0000 | [diff] [blame] | 141 | DWORD oldstack; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 142 | HFILE hFile32; |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 143 | HFILE16 hFile16; |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 144 | |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 145 | selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg),0) ); |
Alexandre Julliard | 0a860a0 | 1999-06-22 11:43:42 +0000 | [diff] [blame] | 146 | oldstack = NtCurrentTeb()->cur_stack; |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 147 | NtCurrentTeb()->cur_stack = MAKESEGPTR(pModule->self_loading_sel, |
| 148 | 0xff00 - sizeof(STACK16FRAME)); |
Ulrich Weigand | c50a1d0 | 1999-08-15 12:45:01 +0000 | [diff] [blame] | 149 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 150 | TRACE_(dll)("CallLoadAppSegProc(hmodule=0x%04x,hf=0x%04x,segnum=%d\n", |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 151 | pModule->self,hf,segnum ); |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 152 | DuplicateHandle( GetCurrentProcess(), hf, GetCurrentProcess(), &hFile32, |
| 153 | 0, FALSE, DUPLICATE_SAME_ACCESS ); |
Alexandre Julliard | 5ce902b | 2000-11-27 21:59:08 +0000 | [diff] [blame] | 154 | hFile16 = Win32HandleToDosFileHandle( hFile32 ); |
Alexandre Julliard | 198746d | 2000-08-14 14:29:22 +0000 | [diff] [blame] | 155 | pSeg->hSeg = NE_CallTo16_word_www( selfloadheader->LoadAppSeg, |
| 156 | pModule->self, hFile16, segnum ); |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 157 | TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n", pSeg->hSeg); |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 158 | _lclose16( hFile16 ); |
Alexandre Julliard | 0a860a0 | 1999-06-22 11:43:42 +0000 | [diff] [blame] | 159 | NtCurrentTeb()->cur_stack = oldstack; |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 160 | } |
Alexandre Julliard | ff8331e | 1995-09-18 11:19:54 +0000 | [diff] [blame] | 161 | else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED)) |
Alexandre Julliard | 1392658 | 1999-01-01 16:55:02 +0000 | [diff] [blame] | 162 | ReadFile(hf, mem, size, &res, NULL); |
Alexandre Julliard | b7258be | 1995-09-01 15:57:28 +0000 | [diff] [blame] | 163 | else { |
| 164 | /* |
| 165 | The following bit of code for "iterated segments" was written without |
| 166 | any documentation on the format of these segments. It seems to work, |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 167 | but may be missing something. If you have any doc please either send |
Alexandre Julliard | b7258be | 1995-09-01 15:57:28 +0000 | [diff] [blame] | 168 | it to me or fix the code yourself. gfm@werple.mira.net.au |
| 169 | */ |
Dimitrie O. Paun | 9ad9636 | 2000-03-19 14:29:50 +0000 | [diff] [blame] | 170 | char* buff = HeapAlloc(GetProcessHeap(), 0, size); |
Alexandre Julliard | b7258be | 1995-09-01 15:57:28 +0000 | [diff] [blame] | 171 | char* curr = buff; |
Dimitrie O. Paun | 9ad9636 | 2000-03-19 14:29:50 +0000 | [diff] [blame] | 172 | |
| 173 | if(buff == NULL) { |
| 174 | WARN_(dll)("Memory exausted!"); |
| 175 | return FALSE; |
| 176 | } |
| 177 | |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 178 | ReadFile(hf, buff, size, &res, NULL); |
Alexandre Julliard | b7258be | 1995-09-01 15:57:28 +0000 | [diff] [blame] | 179 | while(curr < buff + size) { |
| 180 | unsigned int rept = *((short*) curr)++; |
| 181 | unsigned int len = *((short*) curr)++; |
| 182 | for(; rept > 0; rept--) { |
| 183 | char* bytes = curr; |
| 184 | unsigned int byte; |
| 185 | for(byte = 0; byte < len; byte++) |
| 186 | *mem++ = *bytes++; |
| 187 | } |
| 188 | curr += len; |
| 189 | } |
Dimitrie O. Paun | 9ad9636 | 2000-03-19 14:29:50 +0000 | [diff] [blame] | 190 | HeapFree(GetProcessHeap(), 0, buff); |
Alexandre Julliard | b7258be | 1995-09-01 15:57:28 +0000 | [diff] [blame] | 191 | } |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 192 | |
Alexandre Julliard | ff8331e | 1995-09-18 11:19:54 +0000 | [diff] [blame] | 193 | pSeg->flags |= NE_SEGFLAGS_LOADED; |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 194 | |
| 195 | /* Perform exported function prolog fixups */ |
| 196 | NE_FixupSegmentPrologs( pModule, segnum ); |
| 197 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 198 | if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA)) |
| 199 | return TRUE; /* No relocation data, we are done */ |
| 200 | |
Alexandre Julliard | 1392658 | 1999-01-01 16:55:02 +0000 | [diff] [blame] | 201 | ReadFile(hf, &count, sizeof(count), &res, NULL); |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 202 | if (!count) return TRUE; |
| 203 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 204 | TRACE_(fixup)("Fixups for %.*s, segment %d, hSeg %04x\n", |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 205 | *((BYTE *)pModule + pModule->name_table), |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 206 | (char *)pModule + pModule->name_table + 1, |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 207 | segnum, pSeg->hSeg ); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 208 | TRACE_(segment)("Fixups for %.*s, segment %d, hSeg %04x\n", |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 209 | *((BYTE *)pModule + pModule->name_table), |
| 210 | (char *)pModule + pModule->name_table + 1, |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 211 | segnum, pSeg->hSeg ); |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 212 | |
Dimitrie O. Paun | 9ad9636 | 2000-03-19 14:29:50 +0000 | [diff] [blame] | 213 | reloc_entries = (struct relocation_entry_s *)HeapAlloc(GetProcessHeap(), 0, count * sizeof(struct relocation_entry_s)); |
| 214 | if(reloc_entries == NULL) { |
| 215 | WARN_(fixup)("Not enough memory for relocation entries!"); |
| 216 | return FALSE; |
| 217 | } |
Alexandre Julliard | 1392658 | 1999-01-01 16:55:02 +0000 | [diff] [blame] | 218 | if (!ReadFile( hf, reloc_entries, count * sizeof(struct relocation_entry_s), &res, NULL) || |
| 219 | (res != count * sizeof(struct relocation_entry_s))) |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 220 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 221 | WARN_(fixup)("Unable to read relocation information\n" ); |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 222 | return FALSE; |
| 223 | } |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 224 | |
| 225 | /* |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 226 | * Go through the relocation table one entry at a time. |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 227 | */ |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 228 | rep = reloc_entries; |
| 229 | for (i = 0; i < count; i++, rep++) |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 230 | { |
| 231 | /* |
| 232 | * Get the target address corresponding to this entry. |
| 233 | */ |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 234 | |
| 235 | /* If additive, there is no target chain list. Instead, add source |
| 236 | and target */ |
| 237 | additive = rep->relocation_type & NE_RELFLAG_ADDITIVE; |
| 238 | rep->relocation_type &= 0x3; |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 239 | |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 240 | switch (rep->relocation_type) |
| 241 | { |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 242 | case NE_RELTYPE_ORDINAL: |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 243 | module = pModuleTable[rep->target1-1]; |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 244 | ordinal = rep->target2; |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 245 | address = NE_GetEntryPoint( module, ordinal ); |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 246 | if (!address) |
| 247 | { |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 248 | NE_MODULE *pTarget = NE_GetPtr( module ); |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 249 | if (!pTarget) |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 250 | WARN_(module)("Module not found: %04x, reference %d of module %*.*s\n", |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 251 | module, rep->target1, |
| 252 | *((BYTE *)pModule + pModule->name_table), |
| 253 | *((BYTE *)pModule + pModule->name_table), |
| 254 | (char *)pModule + pModule->name_table + 1 ); |
| 255 | else |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 256 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 257 | ERR_(fixup)("No implementation for %.*s.%d, setting to 0xdeadbeef\n", |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 258 | *((BYTE *)pTarget + pTarget->name_table), |
| 259 | (char *)pTarget + pTarget->name_table + 1, |
| 260 | ordinal ); |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 261 | address = (FARPROC16)0xdeadbeef; |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 262 | } |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 263 | } |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 264 | if (TRACE_ON(fixup)) |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 265 | { |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 266 | NE_MODULE *pTarget = NE_GetPtr( module ); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 267 | TRACE_(fixup)("%d: %.*s.%d=%04x:%04x %s\n", i + 1, |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 268 | *((BYTE *)pTarget + pTarget->name_table), |
| 269 | (char *)pTarget + pTarget->name_table + 1, |
| 270 | ordinal, HIWORD(address), LOWORD(address), |
| 271 | NE_GetRelocAddrName( rep->address_type, additive ) ); |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 272 | } |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 273 | break; |
| 274 | |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 275 | case NE_RELTYPE_NAME: |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 276 | module = pModuleTable[rep->target1-1]; |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 277 | func_name = (char *)pModule + pModule->import_table + rep->target2; |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 278 | memcpy( buffer, func_name+1, *func_name ); |
| 279 | buffer[*func_name] = '\0'; |
| 280 | func_name = buffer; |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 281 | ordinal = NE_GetOrdinal( module, func_name ); |
| 282 | address = NE_GetEntryPoint( module, ordinal ); |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 283 | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 284 | if (ERR_ON(fixup) && !address) |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 285 | { |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 286 | NE_MODULE *pTarget = NE_GetPtr( module ); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 287 | ERR_(fixup)("No implementation for %.*s.%s, setting to 0xdeadbeef\n", |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 288 | *((BYTE *)pTarget + pTarget->name_table), |
| 289 | (char *)pTarget + pTarget->name_table + 1, func_name ); |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 290 | } |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 291 | if (!address) address = (FARPROC16) 0xdeadbeef; |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 292 | if (TRACE_ON(fixup)) |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 293 | { |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 294 | NE_MODULE *pTarget = NE_GetPtr( module ); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 295 | TRACE_(fixup)("%d: %.*s.%s=%04x:%04x %s\n", i + 1, |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 296 | *((BYTE *)pTarget + pTarget->name_table), |
| 297 | (char *)pTarget + pTarget->name_table + 1, |
| 298 | func_name, HIWORD(address), LOWORD(address), |
| 299 | NE_GetRelocAddrName( rep->address_type, additive ) ); |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 300 | } |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 301 | break; |
| 302 | |
| 303 | case NE_RELTYPE_INTERNAL: |
Alexandre Julliard | df2673b | 1997-03-29 17:20:20 +0000 | [diff] [blame] | 304 | if ((rep->target1 & 0xff) == 0xff) |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 305 | { |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 306 | address = NE_GetEntryPoint( pModule->self, rep->target2 ); |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 307 | } |
| 308 | else |
| 309 | { |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 310 | address = (FARPROC16)MAKESEGPTR( SEL(pSegTable[rep->target1-1].hSeg), rep->target2 ); |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 311 | } |
| 312 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 313 | TRACE_(fixup)("%d: %04x:%04x %s\n", |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 314 | i + 1, HIWORD(address), LOWORD(address), |
| 315 | NE_GetRelocAddrName( rep->address_type, additive ) ); |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 316 | break; |
| 317 | |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 318 | case NE_RELTYPE_OSFIXUP: |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 319 | /* Relocation type 7: |
| 320 | * |
| 321 | * These appear to be used as fixups for the Windows |
| 322 | * floating point emulator. Let's just ignore them and |
| 323 | * try to use the hardware floating point. Linux should |
| 324 | * successfully emulate the coprocessor if it doesn't |
| 325 | * exist. |
| 326 | */ |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 327 | TRACE_(fixup)("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n", |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 328 | i + 1, rep->relocation_type, rep->offset, |
| 329 | rep->target1, rep->target2, |
| 330 | NE_GetRelocAddrName( rep->address_type, additive ) ); |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 331 | continue; |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 332 | } |
| 333 | |
Alexandre Julliard | fa68b75 | 1995-04-03 16:55:37 +0000 | [diff] [blame] | 334 | offset = rep->offset; |
Alexandre Julliard | e2abbb1 | 1995-03-19 17:39:39 +0000 | [diff] [blame] | 335 | |
Alexandre Julliard | 7ff1c41 | 1997-05-25 13:58:18 +0000 | [diff] [blame] | 336 | /* Apparently, high bit of address_type is sometimes set; */ |
| 337 | /* we ignore it for now */ |
Alexandre Julliard | 23946ad | 1997-06-16 17:43:53 +0000 | [diff] [blame] | 338 | if (rep->address_type > NE_RADDR_OFFSET32) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 339 | { |
| 340 | char module[10]; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 341 | GetModuleName16( pModule->self, module, sizeof(module) ); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 342 | ERR_(fixup)("WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n", |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 343 | module, rep->address_type ); |
| 344 | } |
Alexandre Julliard | 7ff1c41 | 1997-05-25 13:58:18 +0000 | [diff] [blame] | 345 | |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 346 | if (additive) |
| 347 | { |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 348 | sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) ); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 349 | TRACE_(fixup)(" %04x:%04x\n", offset, *sp ); |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 350 | switch (rep->address_type & 0x7f) |
| 351 | { |
| 352 | case NE_RADDR_LOWBYTE: |
| 353 | *(BYTE *)sp += LOBYTE((int)address); |
| 354 | break; |
| 355 | case NE_RADDR_OFFSET16: |
| 356 | *sp += LOWORD(address); |
| 357 | break; |
| 358 | case NE_RADDR_POINTER32: |
| 359 | *sp += LOWORD(address); |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 360 | *(sp+1) = HIWORD(address); |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 361 | break; |
| 362 | case NE_RADDR_SELECTOR: |
Alexandre Julliard | fa68b75 | 1995-04-03 16:55:37 +0000 | [diff] [blame] | 363 | /* Borland creates additive records with offset zero. Strange, but OK */ |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 364 | if (*sp) |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 365 | ERR_(fixup)("Additive selector to %04x.Please report\n",*sp); |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 366 | else |
| 367 | *sp = HIWORD(address); |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 368 | break; |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 369 | default: |
| 370 | goto unknown; |
| 371 | } |
| 372 | } |
| 373 | else /* non-additive fixup */ |
| 374 | { |
| 375 | do |
| 376 | { |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 377 | sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) ); |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 378 | next_offset = *sp; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 379 | TRACE_(fixup)(" %04x:%04x\n", offset, *sp ); |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 380 | switch (rep->address_type & 0x7f) |
| 381 | { |
| 382 | case NE_RADDR_LOWBYTE: |
| 383 | *(BYTE *)sp = LOBYTE((int)address); |
| 384 | break; |
| 385 | case NE_RADDR_OFFSET16: |
| 386 | *sp = LOWORD(address); |
| 387 | break; |
| 388 | case NE_RADDR_POINTER32: |
| 389 | *(FARPROC16 *)sp = address; |
| 390 | break; |
| 391 | case NE_RADDR_SELECTOR: |
| 392 | *sp = SELECTOROF(address); |
| 393 | break; |
| 394 | default: |
| 395 | goto unknown; |
| 396 | } |
| 397 | if (next_offset == offset) break; /* avoid infinite loop */ |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 398 | if (next_offset >= GlobalSize16(pSeg->hSeg)) break; |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 399 | offset = next_offset; |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 400 | } while (offset != 0xffff); |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 401 | } |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 402 | } |
| 403 | |
Dimitrie O. Paun | 9ad9636 | 2000-03-19 14:29:50 +0000 | [diff] [blame] | 404 | HeapFree(GetProcessHeap(), 0, reloc_entries); |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 405 | return TRUE; |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 406 | |
| 407 | unknown: |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 408 | WARN_(fixup)("WARNING: %d: unknown ADDR TYPE %d, " |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 409 | "TYPE %d, OFFSET %04x, TARGET %04x %04x\n", |
| 410 | i + 1, rep->address_type, rep->relocation_type, |
| 411 | rep->offset, rep->target1, rep->target2); |
Dimitrie O. Paun | 9ad9636 | 2000-03-19 14:29:50 +0000 | [diff] [blame] | 412 | HeapFree(GetProcessHeap(), 0, reloc_entries); |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 413 | return FALSE; |
Alexandre Julliard | 490a27e | 1994-06-08 13:57:50 +0000 | [diff] [blame] | 414 | } |
| 415 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 416 | |
| 417 | /*********************************************************************** |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 418 | * NE_LoadAllSegments |
| 419 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 420 | BOOL NE_LoadAllSegments( NE_MODULE *pModule ) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 421 | { |
| 422 | int i; |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 423 | SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 424 | |
| 425 | if (pModule->flags & NE_FFLAGS_SELFLOAD) |
| 426 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 427 | HFILE hf; |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 428 | HFILE16 hFile16; |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 429 | /* Handle self-loading modules */ |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 430 | SELFLOADHEADER *selfloadheader; |
Alexandre Julliard | 7afce0e | 2000-12-01 21:25:31 +0000 | [diff] [blame] | 431 | HMODULE16 mod = GetModuleHandle16("KERNEL"); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 432 | DWORD oldstack; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 433 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 434 | TRACE_(module)("%.*s is a self-loading module!\n", |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 435 | *((BYTE*)pModule + pModule->name_table), |
| 436 | (char *)pModule + pModule->name_table + 1); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 437 | if (!NE_LoadSegment( pModule, 1 )) return FALSE; |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 438 | selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg), 0) ); |
Alexandre Julliard | 7afce0e | 2000-12-01 21:25:31 +0000 | [diff] [blame] | 439 | selfloadheader->EntryAddrProc = GetProcAddress16(mod,"EntryAddrProc"); |
| 440 | selfloadheader->MyAlloc = GetProcAddress16(mod,"MyAlloc"); |
| 441 | selfloadheader->SetOwner = GetProcAddress16(mod,"FarSetOwner"); |
Alexandre Julliard | 914406f | 2000-11-14 01:54:49 +0000 | [diff] [blame] | 442 | pModule->self_loading_sel = SEL(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, WINE_LDT_FLAGS_DATA)); |
Alexandre Julliard | 0a860a0 | 1999-06-22 11:43:42 +0000 | [diff] [blame] | 443 | oldstack = NtCurrentTeb()->cur_stack; |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 444 | NtCurrentTeb()->cur_stack = MAKESEGPTR(pModule->self_loading_sel, |
| 445 | 0xff00 - sizeof(STACK16FRAME) ); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 446 | |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 447 | DuplicateHandle( GetCurrentProcess(), NE_OpenFile(pModule), |
| 448 | GetCurrentProcess(), &hf, 0, FALSE, DUPLICATE_SAME_ACCESS ); |
Alexandre Julliard | 5ce902b | 2000-11-27 21:59:08 +0000 | [diff] [blame] | 449 | hFile16 = Win32HandleToDosFileHandle( hf ); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 450 | TRACE_(dll)("CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n", |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 451 | pModule->self,hFile16); |
Alexandre Julliard | 198746d | 2000-08-14 14:29:22 +0000 | [diff] [blame] | 452 | NE_CallTo16_word_ww(selfloadheader->BootApp, pModule->self,hFile16); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 453 | TRACE_(dll)("Return from CallBootAppProc\n"); |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 454 | _lclose16(hf); |
Alexandre Julliard | 0a860a0 | 1999-06-22 11:43:42 +0000 | [diff] [blame] | 455 | NtCurrentTeb()->cur_stack = oldstack; |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 456 | |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 457 | for (i = 2; i <= pModule->seg_count; i++) |
| 458 | if (!NE_LoadSegment( pModule, i )) return FALSE; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 459 | } |
| 460 | else |
| 461 | { |
| 462 | for (i = 1; i <= pModule->seg_count; i++) |
| 463 | if (!NE_LoadSegment( pModule, i )) return FALSE; |
| 464 | } |
| 465 | return TRUE; |
| 466 | } |
| 467 | |
| 468 | |
| 469 | /*********************************************************************** |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 470 | * NE_FixupSegmentPrologs |
| 471 | * |
| 472 | * Fixup exported functions prologs of one segment |
| 473 | */ |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 474 | static void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum) |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 475 | { |
| 476 | SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule ); |
| 477 | ET_BUNDLE *bundle; |
| 478 | ET_ENTRY *entry; |
| 479 | WORD dgroup, num_entries, sel = SEL(pSegTable[segnum-1].hSeg); |
| 480 | BYTE *pSeg, *pFunc; |
| 481 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 482 | TRACE_(module)("(%d);\n", segnum); |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 483 | |
| 484 | if (pSegTable[segnum-1].flags & NE_SEGFLAGS_DATA) |
Michael Karcher | a21fe34 | 1999-08-15 14:16:42 +0000 | [diff] [blame] | 485 | { |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 486 | pSegTable[segnum-1].flags |= NE_SEGFLAGS_LOADED; |
| 487 | return; |
| 488 | } |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 489 | |
Michael Karcher | a21fe34 | 1999-08-15 14:16:42 +0000 | [diff] [blame] | 490 | if (!pModule->dgroup) return; |
| 491 | |
| 492 | if (!(dgroup = SEL(pSegTable[pModule->dgroup-1].hSeg))) return; |
| 493 | |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 494 | pSeg = MapSL( MAKESEGPTR(sel, 0) ); |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 495 | |
| 496 | bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table); |
| 497 | |
| 498 | do { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 499 | TRACE_(module)("num_entries: %d, bundle: %p, next: %04x, pSeg: %p\n", bundle->last - bundle->first, bundle, bundle->next, pSeg); |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 500 | if (!(num_entries = bundle->last - bundle->first)) |
| 501 | return; |
| 502 | entry = (ET_ENTRY *)((BYTE *)bundle+6); |
| 503 | while (num_entries--) |
| 504 | { |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 505 | /*TRACE_(module)("entry: %p, entry->segnum: %d, entry->offs: %04x\n", entry, entry->segnum, entry->offs);*/ |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 506 | if (entry->segnum == segnum) |
| 507 | { |
| 508 | pFunc = ((BYTE *)pSeg+entry->offs); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 509 | TRACE_(module)("pFunc: %p, *(DWORD *)pFunc: %08lx, num_entries: %d\n", pFunc, *(DWORD *)pFunc, num_entries); |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 510 | if (*(pFunc+2) == 0x90) |
| 511 | { |
| 512 | if (*(WORD *)pFunc == 0x581e) /* push ds, pop ax */ |
| 513 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 514 | TRACE_(module)("patch %04x:%04x -> mov ax, ds\n", sel, entry->offs); |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 515 | *(WORD *)pFunc = 0xd88c; /* mov ax, ds */ |
| 516 | } |
| 517 | |
| 518 | if (*(WORD *)pFunc == 0xd88c) |
| 519 | { |
| 520 | if ((entry->flags & 2)) /* public data ? */ |
| 521 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 522 | TRACE_(module)("patch %04x:%04x -> mov ax, dgroup [%04x]\n", sel, entry->offs, dgroup); |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 523 | *pFunc = 0xb8; /* mov ax, */ |
| 524 | *(WORD *)(pFunc+1) = dgroup; |
| 525 | } |
| 526 | else |
| 527 | if ((pModule->flags & NE_FFLAGS_MULTIPLEDATA) |
| 528 | && (entry->flags & 1)) /* exported ? */ |
| 529 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 530 | TRACE_(module)("patch %04x:%04x -> nop, nop\n", sel, entry->offs); |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 531 | *(WORD *)pFunc = 0x9090; /* nop, nop */ |
| 532 | } |
| 533 | } |
| 534 | } |
| 535 | } |
| 536 | entry++; |
| 537 | } |
| 538 | } while ( (bundle->next) |
| 539 | && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) ); |
| 540 | } |
| 541 | |
| 542 | |
| 543 | /*********************************************************************** |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 544 | * PatchCodeHandle |
| 545 | * |
| 546 | * Needed for self-loading modules. |
| 547 | */ |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 548 | DWORD WINAPI PatchCodeHandle16(HANDLE16 hSeg) |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 549 | { |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 550 | WORD segnum; |
| 551 | WORD sel = SEL(hSeg); |
| 552 | NE_MODULE *pModule = NE_GetPtr(FarGetOwner16(sel)); |
| 553 | SEGTABLEENTRY *pSegTable = NE_SEG_TABLE(pModule); |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 554 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 555 | TRACE_(module)("(%04x);\n", hSeg); |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 556 | |
| 557 | /* find the segment number of the module that belongs to hSeg */ |
| 558 | for (segnum = 1; segnum <= pModule->seg_count; segnum++) |
| 559 | { |
| 560 | if (SEL(pSegTable[segnum-1].hSeg) == sel) |
| 561 | { |
| 562 | NE_FixupSegmentPrologs(pModule, segnum); |
| 563 | break; |
| 564 | } |
| 565 | } |
| 566 | |
| 567 | return MAKELONG(hSeg, sel); |
| 568 | } |
Andreas Mohr | e6c12ee | 1998-10-11 17:36:46 +0000 | [diff] [blame] | 569 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 570 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 571 | /*********************************************************************** |
| 572 | * NE_GetDLLInitParams |
| 573 | */ |
| 574 | static VOID NE_GetDLLInitParams( NE_MODULE *pModule, |
| 575 | WORD *hInst, WORD *ds, WORD *heap ) |
| 576 | { |
| 577 | SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule ); |
| 578 | |
| 579 | if (!(pModule->flags & NE_FFLAGS_SINGLEDATA)) |
| 580 | { |
| 581 | if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup) |
| 582 | { |
| 583 | /* Not SINGLEDATA */ |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 584 | ERR_(dll)("Library is not marked SINGLEDATA\n"); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 585 | exit(1); |
| 586 | } |
| 587 | else /* DATA NONE DLL */ |
| 588 | { |
| 589 | *ds = 0; |
| 590 | *heap = 0; |
| 591 | } |
| 592 | } |
| 593 | else /* DATA SINGLE DLL */ |
| 594 | { |
| 595 | if (pModule->dgroup) { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 596 | *ds = SEL(pSegTable[pModule->dgroup-1].hSeg); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 597 | *heap = pModule->heap_size; |
| 598 | } |
| 599 | else /* hmm, DLL has no dgroup, |
| 600 | but why has it NE_FFLAGS_SINGLEDATA set ? |
| 601 | Buggy DLL compiler ? */ |
| 602 | { |
| 603 | *ds = 0; |
| 604 | *heap = 0; |
| 605 | } |
| 606 | } |
| 607 | |
Bernd Herd | 4d05761 | 2000-05-11 00:10:36 +0000 | [diff] [blame] | 608 | *hInst = *ds ? GlobalHandle16(*ds) : pModule->self; |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 609 | } |
| 610 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 611 | |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 612 | /*********************************************************************** |
| 613 | * NE_InitDLL |
| 614 | * |
| 615 | * Call the DLL initialization code |
| 616 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 617 | static BOOL NE_InitDLL( TDB* pTask, NE_MODULE *pModule ) |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 618 | { |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 619 | SEGTABLEENTRY *pSegTable; |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 620 | WORD hInst, ds, heap; |
Alexandre Julliard | 617955d | 1999-06-26 18:40:24 +0000 | [diff] [blame] | 621 | CONTEXT86 context; |
Alexandre Julliard | fa68b75 | 1995-04-03 16:55:37 +0000 | [diff] [blame] | 622 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 623 | pSegTable = NE_SEG_TABLE( pModule ); |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 624 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 625 | if (!(pModule->flags & NE_FFLAGS_LIBMODULE) || |
| 626 | (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/ |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 627 | |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 628 | /* Call USER signal handler for Win3.1 compatibility. */ |
Ulrich Weigand | c44ab1f | 1999-09-20 18:48:29 +0000 | [diff] [blame] | 629 | TASK_CallTaskSignalProc( USIG16_DLL_LOAD, pModule->self ); |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 630 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 631 | if (!pModule->cs) return TRUE; /* no initialization code */ |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 632 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 633 | |
| 634 | /* Registers at initialization must be: |
| 635 | * cx heap size |
| 636 | * di library instance |
| 637 | * ds data segment if any |
| 638 | * es:si command line (always 0) |
| 639 | */ |
| 640 | |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 641 | memset( &context, 0, sizeof(context) ); |
| 642 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 643 | NE_GetDLLInitParams( pModule, &hInst, &ds, &heap ); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 644 | |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 645 | context.Ecx = heap; |
| 646 | context.Edi = hInst; |
| 647 | context.SegDs = ds; |
| 648 | context.SegEs = ds; /* who knows ... */ |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 649 | |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 650 | context.SegCs = SEL(pSegTable[pModule->cs-1].hSeg); |
| 651 | context.Eip = pModule->ip; |
| 652 | context.Ebp = OFFSETOF(NtCurrentTeb()->cur_stack) + (WORD)&((STACK16FRAME*)0)->bp; |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 653 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 654 | |
| 655 | pModule->cs = 0; /* Don't initialize it twice */ |
Alexandre Julliard | 7d8cfeb | 1999-08-01 14:58:01 +0000 | [diff] [blame] | 656 | TRACE_(dll)("Calling LibMain, cs:ip=%04lx:%04lx ds=%04lx di=%04x cx=%04x\n", |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 657 | context.SegCs, context.Eip, context.SegDs, |
| 658 | LOWORD(context.Edi), LOWORD(context.Ecx) ); |
Alexandre Julliard | e296bf3 | 2000-11-29 19:39:30 +0000 | [diff] [blame] | 659 | wine_call_to_16_regs_short( &context, 0 ); |
Alexandre Julliard | 2197901 | 1997-03-05 08:22:35 +0000 | [diff] [blame] | 660 | return TRUE; |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 661 | } |
| 662 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 663 | /*********************************************************************** |
Alexandre Julliard | 2787be8 | 1995-05-22 18:23:01 +0000 | [diff] [blame] | 664 | * NE_InitializeDLLs |
| 665 | * |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 666 | * Recursively initialize all DLLs (according to the order in which |
| 667 | * they where loaded). |
Alexandre Julliard | 234bc24 | 1994-12-10 13:02:28 +0000 | [diff] [blame] | 668 | */ |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 669 | void NE_InitializeDLLs( HMODULE16 hModule ) |
Alexandre Julliard | 234bc24 | 1994-12-10 13:02:28 +0000 | [diff] [blame] | 670 | { |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 671 | TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask()); |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 672 | NE_MODULE *pModule; |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 673 | HMODULE16 *pDLL; |
Alexandre Julliard | 234bc24 | 1994-12-10 13:02:28 +0000 | [diff] [blame] | 674 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 675 | if (!(pModule = NE_GetPtr( hModule ))) return; |
| 676 | assert( !(pModule->flags & NE_FFLAGS_WIN32) ); |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 677 | |
Alexandre Julliard | a2f2e01 | 1995-06-06 16:40:35 +0000 | [diff] [blame] | 678 | if (pModule->dlls_to_init) |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 679 | { |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 680 | HGLOBAL16 to_init = pModule->dlls_to_init; |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 681 | pModule->dlls_to_init = 0; |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 682 | for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++) |
Alexandre Julliard | a2f2e01 | 1995-06-06 16:40:35 +0000 | [diff] [blame] | 683 | { |
Alexandre Julliard | a2f2e01 | 1995-06-06 16:40:35 +0000 | [diff] [blame] | 684 | NE_InitializeDLLs( *pDLL ); |
| 685 | } |
Alexandre Julliard | 1285c2f | 1996-05-06 16:06:24 +0000 | [diff] [blame] | 686 | GlobalFree16( to_init ); |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 687 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 688 | NE_InitDLL( pTask, pModule ); |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 689 | } |
| 690 | |
| 691 | |
| 692 | /*********************************************************************** |
| 693 | * NE_CallDllEntryPoint |
| 694 | * |
| 695 | * Call the DllEntryPoint of DLLs with subsystem >= 4.0 |
| 696 | */ |
Eric Pouech | fe08849 | 1999-12-05 23:04:00 +0000 | [diff] [blame] | 697 | typedef DWORD WINAPI (*WinNEEntryProc)(DWORD,WORD,WORD,WORD,DWORD,WORD); |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 698 | |
| 699 | static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason ) |
| 700 | { |
| 701 | WORD hInst, ds, heap; |
| 702 | FARPROC16 entryPoint; |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 703 | |
| 704 | if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return; |
| 705 | if (!(pModule->flags & NE_FFLAGS_BUILTIN) && pModule->expected_version < 0x0400) return; |
Alexandre Julliard | 7afce0e | 2000-12-01 21:25:31 +0000 | [diff] [blame] | 706 | if (!(entryPoint = GetProcAddress16( pModule->self, "DllEntryPoint" ))) return; |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 707 | |
| 708 | NE_GetDLLInitParams( pModule, &hInst, &ds, &heap ); |
| 709 | |
| 710 | TRACE_(dll)( "Calling %s DllEntryPoint, cs:ip=%04x:%04x\n", |
| 711 | NE_MODULE_NAME( pModule ), |
| 712 | SELECTOROF(entryPoint), OFFSETOF(entryPoint) ); |
| 713 | |
| 714 | if ( pModule->flags & NE_FFLAGS_BUILTIN ) |
| 715 | { |
Alexandre Julliard | 982a223 | 2000-12-13 20:20:09 +0000 | [diff] [blame] | 716 | WinNEEntryProc entryProc = (WinNEEntryProc)((ENTRYPOINT16 *)MapSL( (SEGPTR)entryPoint ))->target; |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 717 | |
| 718 | entryProc( dwReason, hInst, ds, heap, 0, 0 ); |
| 719 | } |
| 720 | else |
| 721 | { |
| 722 | LPBYTE stack = (LPBYTE)CURRENT_STACK16; |
| 723 | CONTEXT86 context; |
| 724 | |
| 725 | memset( &context, 0, sizeof(context) ); |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 726 | context.SegDs = ds; |
| 727 | context.SegEs = ds; /* who knows ... */ |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 728 | |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 729 | context.SegCs = HIWORD(entryPoint); |
| 730 | context.Eip = LOWORD(entryPoint); |
| 731 | context.Ebp = OFFSETOF( NtCurrentTeb()->cur_stack ) |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 732 | + (WORD)&((STACK16FRAME*)0)->bp; |
| 733 | |
| 734 | *(DWORD *)(stack - 4) = dwReason; /* dwReason */ |
| 735 | *(WORD *) (stack - 6) = hInst; /* hInst */ |
| 736 | *(WORD *) (stack - 8) = ds; /* wDS */ |
| 737 | *(WORD *) (stack - 10) = heap; /* wHeapSize */ |
| 738 | *(DWORD *)(stack - 14) = 0; /* dwReserved1 */ |
| 739 | *(WORD *) (stack - 16) = 0; /* wReserved2 */ |
| 740 | |
Alexandre Julliard | e296bf3 | 2000-11-29 19:39:30 +0000 | [diff] [blame] | 741 | wine_call_to_16_regs_short( &context, 16 ); |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 742 | } |
| 743 | } |
| 744 | |
| 745 | /*********************************************************************** |
| 746 | * NE_DllProcessAttach |
| 747 | * |
| 748 | * Call the DllEntryPoint of all modules this one (recursively) |
| 749 | * depends on, according to the order in which they were loaded. |
| 750 | * |
| 751 | * Note that --as opposed to the PE module case-- there is no notion |
| 752 | * of 'module loaded into a process' for NE modules, and hence we |
| 753 | * have no place to store the fact that the DllEntryPoint of a |
| 754 | * given module was already called on behalf of this process (e.g. |
| 755 | * due to some earlier LoadLibrary16 call). |
| 756 | * |
| 757 | * Thus, we just call the DllEntryPoint twice in that case. Win9x |
| 758 | * appears to behave this way as well ... |
| 759 | * |
| 760 | * This routine must only be called with the Win16Lock held. |
| 761 | * |
| 762 | * FIXME: We should actually abort loading in case the DllEntryPoint |
| 763 | * returns FALSE ... |
| 764 | * |
| 765 | */ |
| 766 | void NE_DllProcessAttach( HMODULE16 hModule ) |
| 767 | { |
| 768 | NE_MODULE *pModule; |
| 769 | WORD *pModRef; |
| 770 | int i; |
| 771 | |
| 772 | if (!(pModule = NE_GetPtr( hModule ))) return; |
| 773 | assert( !(pModule->flags & NE_FFLAGS_WIN32) ); |
| 774 | |
| 775 | /* Check for recursive call */ |
| 776 | if ( pModule->misc_flags & 0x80 ) return; |
| 777 | |
| 778 | TRACE_(dll)("(%s) - START\n", NE_MODULE_NAME(pModule) ); |
| 779 | |
| 780 | /* Tag current module to prevent recursive loop */ |
| 781 | pModule->misc_flags |= 0x80; |
| 782 | |
| 783 | /* Recursively attach all DLLs this one depends on */ |
| 784 | pModRef = NE_MODULE_TABLE( pModule ); |
| 785 | for ( i = 0; i < pModule->modref_count; i++ ) |
| 786 | if ( pModRef[i] ) |
| 787 | NE_DllProcessAttach( (HMODULE16)pModRef[i] ); |
| 788 | |
| 789 | /* Call DLL entry point */ |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 790 | NE_CallDllEntryPoint( pModule, DLL_PROCESS_ATTACH ); |
Ulrich Weigand | 2149934 | 1999-12-05 02:50:38 +0000 | [diff] [blame] | 791 | |
| 792 | /* Remove recursion flag */ |
| 793 | pModule->misc_flags &= ~0x80; |
| 794 | |
| 795 | TRACE_(dll)("(%s) - END\n", NE_MODULE_NAME(pModule) ); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 796 | } |
| 797 | |
| 798 | |
| 799 | /*********************************************************************** |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 800 | * NE_Ne2MemFlags |
| 801 | * |
| 802 | * This function translates NE segment flags to GlobalAlloc flags |
| 803 | */ |
| 804 | static WORD NE_Ne2MemFlags(WORD flags) |
| 805 | { |
| 806 | WORD memflags = 0; |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 807 | #if 1 |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 808 | if (flags & NE_SEGFLAGS_DISCARDABLE) |
| 809 | memflags |= GMEM_DISCARDABLE; |
| 810 | if (flags & NE_SEGFLAGS_MOVEABLE || |
| 811 | ( ! (flags & NE_SEGFLAGS_DATA) && |
| 812 | ! (flags & NE_SEGFLAGS_LOADED) && |
| 813 | ! (flags & NE_SEGFLAGS_ALLOCATED) |
| 814 | ) |
| 815 | ) |
| 816 | memflags |= GMEM_MOVEABLE; |
| 817 | memflags |= GMEM_ZEROINIT; |
| 818 | #else |
| 819 | memflags = GMEM_ZEROINIT | GMEM_FIXED; |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 820 | #endif |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 821 | return memflags; |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 822 | } |
| 823 | |
| 824 | /*********************************************************************** |
Alexandre Julliard | 7afce0e | 2000-12-01 21:25:31 +0000 | [diff] [blame] | 825 | * MyAlloc16 (KERNEL Wine-specific export) |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 826 | * |
| 827 | * MyAlloc() function for self-loading apps. |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 828 | */ |
Alexandre Julliard | 7afce0e | 2000-12-01 21:25:31 +0000 | [diff] [blame] | 829 | DWORD WINAPI MyAlloc16( WORD wFlags, WORD wSize, WORD wElem ) |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 830 | { |
| 831 | WORD size = wSize << wElem; |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 832 | HANDLE16 hMem = 0; |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 833 | |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 834 | if (wSize || (wFlags & NE_SEGFLAGS_MOVEABLE)) |
| 835 | hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size); |
| 836 | |
| 837 | if ( ((wFlags & 0x7) != 0x1) && /* DATA */ |
| 838 | ((wFlags & 0x7) != 0x7) ) /* DATA|ALLOCATED|LOADED */ |
| 839 | { |
| 840 | WORD hSel = SEL(hMem); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 841 | WORD access = SelectorAccessRights16(hSel,0,0); |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 842 | |
| 843 | access |= 2<<2; /* SEGMENT_CODE */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 844 | SelectorAccessRights16(hSel,1,access); |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 845 | } |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 846 | if (size) |
| 847 | return MAKELONG( hMem, SEL(hMem) ); |
| 848 | else |
| 849 | return MAKELONG( 0, hMem ); |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 850 | } |
| 851 | |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 852 | /*********************************************************************** |
| 853 | * NE_GetInstance |
| 854 | */ |
| 855 | HINSTANCE16 NE_GetInstance( NE_MODULE *pModule ) |
| 856 | { |
| 857 | if ( !pModule->dgroup ) |
| 858 | return pModule->self; |
| 859 | else |
| 860 | { |
Andreas Mohr | f2df6a2 | 2000-03-07 12:26:16 +0000 | [diff] [blame] | 861 | SEGTABLEENTRY *pSeg; |
| 862 | pSeg = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1; |
Bernd Herd | 4d05761 | 2000-05-11 00:10:36 +0000 | [diff] [blame] | 863 | return pSeg->hSeg; |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 864 | } |
| 865 | } |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 866 | |
| 867 | /*********************************************************************** |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 868 | * NE_CreateSegment |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 869 | */ |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 870 | BOOL NE_CreateSegment( NE_MODULE *pModule, int segnum ) |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 871 | { |
Andreas Mohr | f2df6a2 | 2000-03-07 12:26:16 +0000 | [diff] [blame] | 872 | SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule ) + segnum - 1; |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 873 | int minsize; |
Alexandre Julliard | 914406f | 2000-11-14 01:54:49 +0000 | [diff] [blame] | 874 | unsigned char selflags; |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 875 | |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 876 | assert( !(pModule->flags & NE_FFLAGS_WIN32) ); |
| 877 | |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 878 | if ( segnum < 1 || segnum > pModule->seg_count ) |
| 879 | return FALSE; |
Andreas Mohr | dca5e56 | 1999-04-16 08:17:17 +0000 | [diff] [blame] | 880 | |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 881 | if ( (pModule->flags & NE_FFLAGS_SELFLOAD) && segnum != 1 ) |
| 882 | return TRUE; /* selfloader allocates segment itself */ |
| 883 | |
Andreas Mohr | f2df6a2 | 2000-03-07 12:26:16 +0000 | [diff] [blame] | 884 | if ( (pSeg->flags & NE_SEGFLAGS_ALLOCATED) && segnum != pModule->dgroup ) |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 885 | return TRUE; /* all but DGROUP only allocated once */ |
| 886 | |
Andreas Mohr | f2df6a2 | 2000-03-07 12:26:16 +0000 | [diff] [blame] | 887 | minsize = pSeg->minsize ? pSeg->minsize : 0x10000; |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 888 | if ( segnum == pModule->ss ) minsize += pModule->stack_size; |
| 889 | if ( segnum == pModule->dgroup ) minsize += pModule->heap_size; |
| 890 | |
Alexandre Julliard | 914406f | 2000-11-14 01:54:49 +0000 | [diff] [blame] | 891 | selflags = (pSeg->flags & NE_SEGFLAGS_DATA) ? WINE_LDT_FLAGS_DATA : WINE_LDT_FLAGS_CODE; |
| 892 | if (pSeg->flags & NE_SEGFLAGS_32BIT) selflags |= WINE_LDT_FLAGS_32BIT; |
| 893 | pSeg->hSeg = GLOBAL_Alloc( NE_Ne2MemFlags(pSeg->flags), minsize, pModule->self, selflags ); |
Andreas Mohr | f2df6a2 | 2000-03-07 12:26:16 +0000 | [diff] [blame] | 894 | if (!pSeg->hSeg) return FALSE; |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 895 | |
Andreas Mohr | f2df6a2 | 2000-03-07 12:26:16 +0000 | [diff] [blame] | 896 | pSeg->flags |= NE_SEGFLAGS_ALLOCATED; |
Ulrich Weigand | 61206bd | 1999-11-21 00:50:30 +0000 | [diff] [blame] | 897 | return TRUE; |
| 898 | } |
| 899 | |
| 900 | /*********************************************************************** |
| 901 | * NE_CreateAllSegments |
| 902 | */ |
| 903 | BOOL NE_CreateAllSegments( NE_MODULE *pModule ) |
| 904 | { |
| 905 | int i; |
| 906 | for ( i = 1; i <= pModule->seg_count; i++ ) |
| 907 | if ( !NE_CreateSegment( pModule, i ) ) |
| 908 | return FALSE; |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 909 | |
| 910 | pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table + |
| 911 | (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0; |
| 912 | return TRUE; |
| 913 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 914 | |
| 915 | |
| 916 | /********************************************************************** |
| 917 | * IsSharedSelector (KERNEL.345) |
| 918 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 919 | BOOL16 WINAPI IsSharedSelector16( HANDLE16 selector ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 920 | { |
| 921 | /* Check whether the selector belongs to a DLL */ |
| 922 | NE_MODULE *pModule = NE_GetPtr( selector ); |
| 923 | if (!pModule) return FALSE; |
| 924 | return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0; |
| 925 | } |