Release 980517
[wine/multimedia.git] / loader / ne / segment.c
bloba6478a55a116402291e0df275024f8eb37275f5f
1 /*
2 * NE segment loading
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include <assert.h>
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>
15 #include <ctype.h>
16 #include <string.h>
17 #include <errno.h>
18 #include "neexe.h"
19 #include "windows.h"
20 #include "global.h"
21 #include "task.h"
22 #include "selectors.h"
23 #include "callback.h"
24 #include "file.h"
25 #include "module.h"
26 #include "stackframe.h"
27 #include "debug.h"
28 #include "xmalloc.h"
31 /***********************************************************************
32 * NE_GetRelocAddrName
34 static const char *NE_GetRelocAddrName( BYTE addr_type, int additive )
36 switch(addr_type & 0x7f)
38 case NE_RADDR_LOWBYTE: return additive ? "BYTE add" : "BYTE";
39 case NE_RADDR_OFFSET16: return additive ? "OFFSET16 add" : "OFFSET16";
40 case NE_RADDR_POINTER32: return additive ? "POINTER32 add" : "POINTER32";
41 case NE_RADDR_SELECTOR: return additive ? "SELECTOR add" : "SELECTOR";
42 case NE_RADDR_POINTER48: return additive ? "POINTER48 add" : "POINTER48";
43 case NE_RADDR_OFFSET32: return additive ? "OFFSET32 add" : "OFFSET32";
45 return "???";
49 /***********************************************************************
50 * NE_LoadSegment
52 BOOL32 NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
54 SEGTABLEENTRY *pSegTable, *pSeg;
55 WORD *pModuleTable;
56 WORD count, i, offset, next_offset;
57 HMODULE16 module;
58 FARPROC16 address = 0;
59 int fd;
60 struct relocation_entry_s *rep, *reloc_entries;
61 BYTE *func_name;
62 int size;
63 char* mem;
65 char buffer[256];
66 int ordinal, additive;
67 unsigned short *sp;
69 pSegTable = NE_SEG_TABLE( pModule );
70 pSeg = pSegTable + segnum - 1;
71 pModuleTable = NE_MODULE_TABLE( pModule );
73 if (!pSeg->filepos) return TRUE; /* No file image, just return */
75 fd = NE_OpenFile( pModule );
76 TRACE(module, "Loading segment %d, selector=%04x, flags=%04x\n",
77 segnum, pSeg->selector, pSeg->flags );
78 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
79 if (pSeg->size) size = pSeg->size;
80 else if (pSeg->minsize) size = pSeg->minsize;
81 else size = 0x10000;
82 mem = GlobalLock16(pSeg->selector);
83 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
85 /* Implement self loading segments */
86 SELFLOADHEADER *selfloadheader;
87 STACK16FRAME *stack16Top;
88 DWORD oldstack;
89 WORD oldselector, newselector;
90 THDB *thdb = THREAD_Current();
91 HFILE32 hf = FILE_DupUnixHandle( fd );
93 selfloadheader = (SELFLOADHEADER *)
94 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
95 oldstack = thdb->cur_stack;
96 oldselector = pSeg->selector;
97 thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
98 0xff00 - sizeof(*stack16Top));
99 stack16Top = (STACK16FRAME *)PTR_SEG_TO_LIN(thdb->cur_stack);
100 stack16Top->frame32 = 0;
101 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
102 stack16Top->entry_point = 0;
103 stack16Top->entry_ip = 0;
104 stack16Top->entry_cs = 0;
105 stack16Top->bp = 0;
106 stack16Top->ip = 0;
107 stack16Top->cs = 0;
108 newselector = Callbacks->CallLoadAppSegProc(selfloadheader->LoadAppSeg,
109 pModule->self, hf, segnum );
110 _lclose32( hf );
111 if (newselector != oldselector) {
112 /* Self loaders like creating their own selectors;
113 * they love asking for trouble to Wine developers
115 if (segnum == pModule->dgroup) {
116 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
117 PTR_SEG_OFF_TO_LIN(newselector,0),
118 pSeg->minsize ? pSeg->minsize : 0x10000);
119 FreeSelector(newselector);
120 pSeg->selector = oldselector;
121 TRACE(module, "New selector allocated for dgroup segment:Old=%d,New=%d\n",
122 oldselector, newselector);
123 } else {
124 FreeSelector(pSeg->selector);
125 pSeg->selector = newselector;
129 thdb->cur_stack = oldstack;
131 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
132 read(fd, mem, size);
133 else {
135 The following bit of code for "iterated segments" was written without
136 any documentation on the format of these segments. It seems to work,
137 but may be missing something. If you have any doc please either send
138 it to me or fix the code yourself. gfm@werple.mira.net.au
140 char* buff = xmalloc(size);
141 char* curr = buff;
142 read(fd, buff, size);
143 while(curr < buff + size) {
144 unsigned int rept = *((short*) curr)++;
145 unsigned int len = *((short*) curr)++;
146 for(; rept > 0; rept--) {
147 char* bytes = curr;
148 unsigned int byte;
149 for(byte = 0; byte < len; byte++)
150 *mem++ = *bytes++;
152 curr += len;
154 free(buff);
157 pSeg->flags |= NE_SEGFLAGS_LOADED;
158 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
159 return TRUE; /* No relocation data, we are done */
161 read( fd, &count, sizeof(count) );
162 if (!count) return TRUE;
164 TRACE(fixup, "Fixups for %.*s, segment %d, selector %04x\n",
165 *((BYTE *)pModule + pModule->name_table),
166 (char *)pModule + pModule->name_table + 1,
167 segnum, pSeg->selector );
168 TRACE(segment, "Fixups for %.*s, segment %d, selector %04x\n",
169 *((BYTE *)pModule + pModule->name_table),
170 (char *)pModule + pModule->name_table + 1,
171 segnum, pSeg->selector );
173 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
174 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
175 count * sizeof(struct relocation_entry_s))
177 WARN(fixup, "Unable to read relocation information\n" );
178 return FALSE;
182 * Go through the relocation table one entry at a time.
184 rep = reloc_entries;
185 for (i = 0; i < count; i++, rep++)
188 * Get the target address corresponding to this entry.
191 /* If additive, there is no target chain list. Instead, add source
192 and target */
193 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
194 rep->relocation_type &= 0x3;
196 switch (rep->relocation_type)
198 case NE_RELTYPE_ORDINAL:
199 module = pModuleTable[rep->target1-1];
200 ordinal = rep->target2;
201 address = NE_GetEntryPoint( module, ordinal );
202 if (!address)
204 NE_MODULE *pTarget = NE_GetPtr( module );
205 if (!pTarget)
206 WARN(module, "Module not found: %04x, reference %d of module %*.*s\n",
207 module, rep->target1,
208 *((BYTE *)pModule + pModule->name_table),
209 *((BYTE *)pModule + pModule->name_table),
210 (char *)pModule + pModule->name_table + 1 );
211 else
212 WARN(module, "No handler for %.*s.%d, setting to 0:0\n",
213 *((BYTE *)pTarget + pTarget->name_table),
214 (char *)pTarget + pTarget->name_table + 1,
215 ordinal );
217 if (TRACE_ON(fixup))
219 NE_MODULE *pTarget = NE_GetPtr( module );
220 TRACE( fixup, "%d: %.*s.%d=%04x:%04x %s\n", i + 1,
221 *((BYTE *)pTarget + pTarget->name_table),
222 (char *)pTarget + pTarget->name_table + 1,
223 ordinal, HIWORD(address), LOWORD(address),
224 NE_GetRelocAddrName( rep->address_type, additive ) );
226 break;
228 case NE_RELTYPE_NAME:
229 module = pModuleTable[rep->target1-1];
230 func_name = (char *)pModule + pModule->import_table + rep->target2;
231 memcpy( buffer, func_name+1, *func_name );
232 buffer[*func_name] = '\0';
233 func_name = buffer;
234 ordinal = NE_GetOrdinal( module, func_name );
235 address = NE_GetEntryPoint( module, ordinal );
237 if (ERR_ON(fixup) && !address)
239 NE_MODULE *pTarget = NE_GetPtr( module );
240 ERR(fixup, "Warning: no handler for %.*s.%s, setting to 0:0\n",
241 *((BYTE *)pTarget + pTarget->name_table),
242 (char *)pTarget + pTarget->name_table + 1, func_name );
244 if (TRACE_ON(fixup))
246 NE_MODULE *pTarget = NE_GetPtr( module );
247 TRACE( fixup, "%d: %.*s.%s=%04x:%04x %s\n", i + 1,
248 *((BYTE *)pTarget + pTarget->name_table),
249 (char *)pTarget + pTarget->name_table + 1,
250 func_name, HIWORD(address), LOWORD(address),
251 NE_GetRelocAddrName( rep->address_type, additive ) );
253 break;
255 case NE_RELTYPE_INTERNAL:
256 if ((rep->target1 & 0xff) == 0xff)
258 address = NE_GetEntryPoint( pModule->self, rep->target2 );
260 else
262 address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( pSegTable[rep->target1-1].selector, rep->target2 );
265 TRACE( fixup,"%d: %04x:%04x %s\n",
266 i + 1, HIWORD(address), LOWORD(address),
267 NE_GetRelocAddrName( rep->address_type, additive ) );
268 break;
270 case NE_RELTYPE_OSFIXUP:
271 /* Relocation type 7:
273 * These appear to be used as fixups for the Windows
274 * floating point emulator. Let's just ignore them and
275 * try to use the hardware floating point. Linux should
276 * successfully emulate the coprocessor if it doesn't
277 * exist.
279 TRACE( fixup, "%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
280 i + 1, rep->relocation_type, rep->offset,
281 rep->target1, rep->target2,
282 NE_GetRelocAddrName( rep->address_type, additive ) );
283 continue;
286 offset = rep->offset;
288 /* Apparently, high bit of address_type is sometimes set; */
289 /* we ignore it for now */
290 if (rep->address_type > NE_RADDR_OFFSET32)
292 char module[10];
293 GetModuleName( pModule->self, module, sizeof(module) );
294 ERR( fixup, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
295 module, rep->address_type );
298 if (additive)
300 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
301 TRACE( fixup," %04x:%04x\n", offset, *sp );
302 switch (rep->address_type & 0x7f)
304 case NE_RADDR_LOWBYTE:
305 *(BYTE *)sp += LOBYTE((int)address);
306 break;
307 case NE_RADDR_OFFSET16:
308 *sp += LOWORD(address);
309 break;
310 case NE_RADDR_POINTER32:
311 *sp += LOWORD(address);
312 *(sp+1) = HIWORD(address);
313 break;
314 case NE_RADDR_SELECTOR:
315 /* Borland creates additive records with offset zero. Strange, but OK */
316 if (*sp)
317 ERR(fixup,"Additive selector to %04x.Please report\n",*sp);
318 else
319 *sp = HIWORD(address);
320 break;
321 default:
322 goto unknown;
325 else /* non-additive fixup */
329 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
330 next_offset = *sp;
331 TRACE( fixup," %04x:%04x\n", offset, *sp );
332 switch (rep->address_type & 0x7f)
334 case NE_RADDR_LOWBYTE:
335 *(BYTE *)sp = LOBYTE((int)address);
336 break;
337 case NE_RADDR_OFFSET16:
338 *sp = LOWORD(address);
339 break;
340 case NE_RADDR_POINTER32:
341 *(FARPROC16 *)sp = address;
342 break;
343 case NE_RADDR_SELECTOR:
344 *sp = SELECTOROF(address);
345 break;
346 default:
347 goto unknown;
349 if (next_offset == offset) break; /* avoid infinite loop */
350 if (next_offset >= GlobalSize16(pSeg->selector)) break;
351 offset = next_offset;
352 } while (offset && (offset != 0xffff));
356 free(reloc_entries);
357 return TRUE;
359 unknown:
360 WARN(fixup, "WARNING: %d: unknown ADDR TYPE %d, "
361 "TYPE %d, OFFSET %04x, TARGET %04x %04x\n",
362 i + 1, rep->address_type, rep->relocation_type,
363 rep->offset, rep->target1, rep->target2);
364 free(reloc_entries);
365 return FALSE;
369 /***********************************************************************
370 * NE_LoadAllSegments
372 BOOL32 NE_LoadAllSegments( NE_MODULE *pModule )
374 int i;
376 if (pModule->flags & NE_FFLAGS_SELFLOAD)
378 HFILE32 hf;
379 /* Handle self loading modules */
380 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
381 SELFLOADHEADER *selfloadheader;
382 STACK16FRAME *stack16Top;
383 THDB *thdb = THREAD_Current();
384 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
385 DWORD oldstack;
386 WORD saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
388 TRACE(module, "%.*s is a self-loading module!\n",
389 *((BYTE*)pModule + pModule->name_table),
390 (char *)pModule + pModule->name_table + 1);
391 if (!NE_LoadSegment( pModule, 1 )) return FALSE;
392 selfloadheader = (SELFLOADHEADER *)
393 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
394 selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
395 selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28);
396 selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
397 pModule->self_loading_sel = GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
398 oldstack = thdb->cur_stack;
399 thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
400 0xff00 - sizeof(*stack16Top) );
401 stack16Top = (STACK16FRAME *)PTR_SEG_TO_LIN(thdb->cur_stack);
402 stack16Top->frame32 = 0;
403 stack16Top->ebp = 0;
404 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
405 stack16Top->entry_point = 0;
406 stack16Top->entry_ip = 0;
407 stack16Top->entry_cs = 0;
408 stack16Top->bp = 0;
409 stack16Top->ip = 0;
410 stack16Top->cs = 0;
412 hf = FILE_DupUnixHandle( NE_OpenFile( pModule ) );
413 Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self, hf);
414 _lclose32(hf);
415 /* some BootApp procs overwrite the selector of dgroup */
416 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
417 thdb->cur_stack = oldstack;
418 for (i = 2; i <= pModule->seg_count; i++)
419 if (!NE_LoadSegment( pModule, i )) return FALSE;
421 else
423 for (i = 1; i <= pModule->seg_count; i++)
424 if (!NE_LoadSegment( pModule, i )) return FALSE;
426 return TRUE;
430 /***********************************************************************
431 * NE_FixupPrologs
433 * Fixup the exported functions prologs.
435 void NE_FixupPrologs( NE_MODULE *pModule )
437 SEGTABLEENTRY *pSegTable;
438 WORD dgroup = 0;
439 WORD sel;
440 BYTE *p, *fixup_ptr, count;
441 dbg_decl_str(module, 512);
443 pSegTable = NE_SEG_TABLE(pModule);
444 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
445 dgroup = pSegTable[pModule->dgroup-1].selector;
447 TRACE(module, "(%04x)\n", pModule->self );
448 p = (BYTE *)pModule + pModule->entry_table;
449 while (*p)
451 if (p[1] == 0) /* Unused entry */
453 p += 2; /* Skip it */
454 continue;
456 if (p[1] == 0xfe) /* Constant entry */
458 p += 2 + *p * 3; /* Skip it */
459 continue;
462 /* Now fixup the entries of this bundle */
463 count = *p;
464 sel = p[1];
465 p += 2;
466 while (count-- > 0)
468 dbg_reset_str(module);
469 dsprintf(module,"Flags: %04x, sel %02x ", *p, sel);
470 /* According to the output generated by TDUMP, the flags mean:
471 * 0x0001 function is exported
472 * 0x0002 Single data (seems to occur only in DLLs)
474 if (sel == 0xff) { /* moveable */
475 dsprintf(module, "(%02x) o %04x", p[3], *(WORD *)(p+4) );
476 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
477 } else { /* fixed */
478 dsprintf(module, "offset %04x", *(WORD *)(p+1) );
479 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) +
480 *(WORD *)(p + 1);
482 TRACE(module, "%s Signature: %02x %02x %02x,ff %x\n",
483 dbg_str(module), fixup_ptr[0], fixup_ptr[1],
484 fixup_ptr[2], pModule->flags );
485 if (*p & 0x0001)
487 /* Verify the signature */
488 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
489 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
490 && fixup_ptr[2] == 0x90)
492 if (*p & 0x0002)
494 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
496 /* can this happen? */
497 ERR(fixup, "FixupPrologs got confused\n" );
499 else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
501 *fixup_ptr = 0xb8; /* MOV AX, */
502 *(WORD *)(fixup_ptr+1) = dgroup;
505 else
507 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
508 fixup_ptr[0] = 0x90; /* non-library: NOPs */
509 fixup_ptr[1] = 0x90;
510 fixup_ptr[2] = 0x90;
513 } else {
514 WARN(fixup, "Unknown signature\n" );
517 else
518 TRACE(module,"\n");
519 p += (sel == 0xff) ? 6 : 3;
525 /***********************************************************************
526 * NE_InitDLL
528 * Call the DLL initialization code
530 static BOOL32 NE_InitDLL( TDB* pTask, NE_MODULE *pModule )
532 SEGTABLEENTRY *pSegTable;
533 CONTEXT context;
535 /* Registers at initialization must be:
536 * cx heap size
537 * di library instance
538 * ds data segment if any
539 * es:si command line (always 0)
542 pSegTable = NE_SEG_TABLE( pModule );
544 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
545 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
547 /* Call USER signal handler. This is necessary to install a
548 * proper loader for HICON and HCURSOR resources that this DLL
549 * may contain. InitApp() does this for task modules. */
551 if (pTask && pTask->userhandler)
553 pTask->userhandler( pModule->self, USIG_DLL_LOAD, 0, pTask->hInstance,
554 pTask->hQueue );
557 if (!pModule->cs) return TRUE; /* no initialization code */
559 memset( &context, 0, sizeof(context) );
561 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
563 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
565 /* Not SINGLEDATA */
566 ERR(dll, "Library is not marked SINGLEDATA\n");
567 exit(1);
569 else /* DATA NONE DLL */
571 DS_reg(&context) = 0;
572 ECX_reg(&context) = 0;
575 else /* DATA SINGLE DLL */
577 if (pModule->dgroup) {
578 DS_reg(&context) = pSegTable[pModule->dgroup-1].selector;
579 ECX_reg(&context) = pModule->heap_size;
581 else /* hmm, DLL has no dgroup,
582 but why has it NE_FFLAGS_SINGLEDATA set ?
583 Buggy DLL compiler ? */
585 DS_reg(&context) = 0;
586 ECX_reg(&context) = 0;
590 CS_reg(&context) = pSegTable[pModule->cs-1].selector;
591 EIP_reg(&context) = pModule->ip;
592 EBP_reg(&context) = OFFSETOF(THREAD_Current()->cur_stack)
593 + (WORD)&((STACK16FRAME*)0)->bp;
594 EDI_reg(&context) = DS_reg(&context) ? DS_reg(&context) : pModule->self;
597 pModule->cs = 0; /* Don't initialize it twice */
598 TRACE(dll, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
599 CS_reg(&context), IP_reg(&context), DS_reg(&context),
600 DI_reg(&context), CX_reg(&context) );
601 Callbacks->CallRegisterShortProc( &context, 0 );
602 return TRUE;
605 /***********************************************************************
606 * NE_CallDllEntryPoint
608 * Call the DllEntryPoint of DLLs with subsystem >= 4.0
611 static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
613 FARPROC16 entryPoint;
614 WORD ordinal;
615 CONTEXT context;
616 THDB *thdb = THREAD_Current();
617 LPBYTE stack = (LPBYTE)THREAD_STACK16(thdb);
619 if (pModule->expected_version < 0x0400) return;
620 if (!(ordinal = NE_GetOrdinal( pModule->self, "DllEntryPoint" ))) return;
621 if (!(entryPoint = NE_GetEntryPoint( pModule->self, ordinal ))) return;
623 memset( &context, 0, sizeof(context) );
625 CS_reg(&context) = HIWORD(entryPoint);
626 IP_reg(&context) = LOWORD(entryPoint);
627 EBP_reg(&context) = OFFSETOF( thdb->cur_stack )
628 + (WORD)&((STACK16FRAME*)0)->bp;
630 *(DWORD *)(stack - 4) = dwReason; /* dwReason */
631 *(WORD *) (stack - 6) = pModule->self; /* hInst */
632 *(WORD *) (stack - 8) = 0; /* wDS */
633 *(WORD *) (stack - 10) = 0; /* wHeapSize */
634 *(DWORD *)(stack - 14) = 0; /* dwReserved1 */
635 *(WORD *) (stack - 16) = 0; /* wReserved2 */
637 TRACE(dll, "Calling DllEntryPoint, cs:ip=%04lx:%04x\n",
638 CS_reg(&context), IP_reg(&context));
640 Callbacks->CallRegisterShortProc( &context, 16 );
644 /***********************************************************************
645 * NE_InitializeDLLs
647 * Recursively initialize all DLLs (according to the order in which
648 * they where loaded).
650 void NE_InitializeDLLs( HMODULE16 hModule )
652 TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
653 NE_MODULE *pModule;
654 HMODULE16 *pDLL;
656 if (!(pModule = NE_GetPtr( hModule ))) return;
657 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
659 if (pModule->dlls_to_init)
661 HGLOBAL16 to_init = pModule->dlls_to_init;
662 pModule->dlls_to_init = 0;
663 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
665 NE_InitializeDLLs( *pDLL );
667 GlobalFree16( to_init );
669 NE_InitDLL( pTask, pModule );
670 NE_CallDllEntryPoint( pModule, DLL_PROCESS_ATTACH );
674 /***********************************************************************
675 * NE_CreateInstance
677 * If lib_only is TRUE, handle the module like a library even if it is a .EXE
679 HINSTANCE16 NE_CreateInstance( NE_MODULE *pModule, HINSTANCE16 *prev,
680 BOOL32 lib_only )
682 SEGTABLEENTRY *pSegment;
683 int minsize;
684 HINSTANCE16 hNewInstance;
686 if (pModule->dgroup == 0)
688 if (prev) *prev = pModule->self;
689 return pModule->self;
692 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
693 if (prev) *prev = pSegment->selector;
695 /* if it's a library, create a new instance only the first time */
696 if (pSegment->selector)
698 if (pModule->flags & NE_FFLAGS_LIBMODULE) return pSegment->selector;
699 if (lib_only) return pSegment->selector;
702 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
703 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
704 minsize += pModule->heap_size;
705 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED, minsize,
706 pModule->self, FALSE, FALSE, FALSE );
707 if (!hNewInstance) return 0;
708 pSegment->selector = hNewInstance;
709 return hNewInstance;
713 /***********************************************************************
714 * PatchCodeHandle
716 * Needed for self-loading modules.
719 /* It does nothing */
720 void WINAPI PatchCodeHandle(HANDLE16 hSel)
722 FIXME(module,"(%04x): stub.\n",hSel);
726 /***********************************************************************
727 * NE_Ne2MemFlags
729 * This function translates NE segment flags to GlobalAlloc flags
731 static WORD NE_Ne2MemFlags(WORD flags)
733 WORD memflags = 0;
734 #if 0
735 if (flags & NE_SEGFLAGS_DISCARDABLE)
736 memflags |= GMEM_DISCARDABLE;
737 if (flags & NE_SEGFLAGS_MOVEABLE ||
738 ( ! (flags & NE_SEGFLAGS_DATA) &&
739 ! (flags & NE_SEGFLAGS_LOADED) &&
740 ! (flags & NE_SEGFLAGS_ALLOCATED)
743 memflags |= GMEM_MOVEABLE;
744 memflags |= GMEM_ZEROINIT;
745 #else
746 memflags = GMEM_ZEROINIT | GMEM_FIXED;
747 return memflags;
748 #endif
751 /***********************************************************************
752 * NE_AllocateSegment (WPROCS.26)
754 DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
756 WORD size = wSize << wElem;
757 HANDLE16 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
758 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
762 /***********************************************************************
763 * NE_CreateSegments
765 BOOL32 NE_CreateSegments( NE_MODULE *pModule )
767 SEGTABLEENTRY *pSegment;
768 int i, minsize;
770 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
772 pSegment = NE_SEG_TABLE( pModule );
773 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
775 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
776 if (i == pModule->ss) minsize += pModule->stack_size;
777 /* The DGROUP is allocated by NE_CreateInstance */
778 if (i == pModule->dgroup) continue;
779 pSegment->selector = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags),
780 minsize, pModule->self,
781 !(pSegment->flags & NE_SEGFLAGS_DATA),
782 FALSE,
783 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
784 if (!pSegment->selector) return FALSE;
787 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
788 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
789 return TRUE;
793 /**********************************************************************
794 * IsSharedSelector (KERNEL.345)
796 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
798 /* Check whether the selector belongs to a DLL */
799 NE_MODULE *pModule = NE_GetPtr( selector );
800 if (!pModule) return FALSE;
801 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;