4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
22 #include "selectors.h"
26 #include "stackframe.h"
31 /***********************************************************************
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";
49 /***********************************************************************
52 BOOL32 NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
54 SEGTABLEENTRY *pSegTable, *pSeg;
56 WORD count, i, offset, next_offset;
58 FARPROC16 address = 0;
60 struct relocation_entry_s *rep, *reloc_entries;
66 int ordinal, additive;
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;
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;
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;
108 TRACE(dll,"CallLoadAppSegProc(hmodule=0x%04x,hf=0x%04x,segnum=%d\n",
109 pModule->self,hf,segnum );
110 newselector = Callbacks->CallLoadAppSegProc(selfloadheader->LoadAppSeg,
112 HFILE32_TO_HFILE16(hf),
114 TRACE(dll,"Ret CallLoadAppSegProc: selector = 0x%04x\n",newselector);
116 if (newselector != oldselector) {
117 /* Self loaders like creating their own selectors;
118 * they love asking for trouble to Wine developers
120 if (segnum == pModule->dgroup) {
121 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
122 PTR_SEG_OFF_TO_LIN(newselector,0),
123 pSeg->minsize ? pSeg->minsize : 0x10000);
124 FreeSelector(newselector);
125 pSeg->selector = oldselector;
126 TRACE(module, "New selector allocated for dgroup segment:Old=%d,New=%d\n",
127 oldselector, newselector);
129 FreeSelector(pSeg->selector);
130 pSeg->selector = newselector;
134 thdb->cur_stack = oldstack;
136 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
140 The following bit of code for "iterated segments" was written without
141 any documentation on the format of these segments. It seems to work,
142 but may be missing something. If you have any doc please either send
143 it to me or fix the code yourself. gfm@werple.mira.net.au
145 char* buff = xmalloc(size);
147 read(fd, buff, size);
148 while(curr < buff + size) {
149 unsigned int rept = *((short*) curr)++;
150 unsigned int len = *((short*) curr)++;
151 for(; rept > 0; rept--) {
154 for(byte = 0; byte < len; byte++)
162 pSeg->flags |= NE_SEGFLAGS_LOADED;
163 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
164 return TRUE; /* No relocation data, we are done */
166 read( fd, &count, sizeof(count) );
167 if (!count) return TRUE;
169 TRACE(fixup, "Fixups for %.*s, segment %d, selector %04x\n",
170 *((BYTE *)pModule + pModule->name_table),
171 (char *)pModule + pModule->name_table + 1,
172 segnum, pSeg->selector );
173 TRACE(segment, "Fixups for %.*s, segment %d, selector %04x\n",
174 *((BYTE *)pModule + pModule->name_table),
175 (char *)pModule + pModule->name_table + 1,
176 segnum, pSeg->selector );
178 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
179 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
180 count * sizeof(struct relocation_entry_s))
182 WARN(fixup, "Unable to read relocation information\n" );
187 * Go through the relocation table one entry at a time.
190 for (i = 0; i < count; i++, rep++)
193 * Get the target address corresponding to this entry.
196 /* If additive, there is no target chain list. Instead, add source
198 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
199 rep->relocation_type &= 0x3;
201 switch (rep->relocation_type)
203 case NE_RELTYPE_ORDINAL:
204 module = pModuleTable[rep->target1-1];
205 ordinal = rep->target2;
206 address = NE_GetEntryPoint( module, ordinal );
209 NE_MODULE *pTarget = NE_GetPtr( module );
211 WARN(module, "Module not found: %04x, reference %d of module %*.*s\n",
212 module, rep->target1,
213 *((BYTE *)pModule + pModule->name_table),
214 *((BYTE *)pModule + pModule->name_table),
215 (char *)pModule + pModule->name_table + 1 );
218 ERR(fixup, "No handler for %.*s.%d, setting to 0xdeadbeef\n",
219 *((BYTE *)pTarget + pTarget->name_table),
220 (char *)pTarget + pTarget->name_table + 1,
222 address = (FARPROC16)0xdeadbeef;
227 NE_MODULE *pTarget = NE_GetPtr( module );
228 TRACE( fixup, "%d: %.*s.%d=%04x:%04x %s\n", i + 1,
229 *((BYTE *)pTarget + pTarget->name_table),
230 (char *)pTarget + pTarget->name_table + 1,
231 ordinal, HIWORD(address), LOWORD(address),
232 NE_GetRelocAddrName( rep->address_type, additive ) );
236 case NE_RELTYPE_NAME:
237 module = pModuleTable[rep->target1-1];
238 func_name = (char *)pModule + pModule->import_table + rep->target2;
239 memcpy( buffer, func_name+1, *func_name );
240 buffer[*func_name] = '\0';
242 ordinal = NE_GetOrdinal( module, func_name );
243 address = NE_GetEntryPoint( module, ordinal );
245 if (ERR_ON(fixup) && !address)
247 NE_MODULE *pTarget = NE_GetPtr( module );
248 ERR(fixup, "Warning: no handler for %.*s.%s, setting to 0xdeadbeef\n",
249 *((BYTE *)pTarget + pTarget->name_table),
250 (char *)pTarget + pTarget->name_table + 1, func_name );
252 if (!address) address = (FARPROC16) 0xdeadbeef;
255 NE_MODULE *pTarget = NE_GetPtr( module );
256 TRACE( fixup, "%d: %.*s.%s=%04x:%04x %s\n", i + 1,
257 *((BYTE *)pTarget + pTarget->name_table),
258 (char *)pTarget + pTarget->name_table + 1,
259 func_name, HIWORD(address), LOWORD(address),
260 NE_GetRelocAddrName( rep->address_type, additive ) );
264 case NE_RELTYPE_INTERNAL:
265 if ((rep->target1 & 0xff) == 0xff)
267 address = NE_GetEntryPoint( pModule->self, rep->target2 );
271 address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( pSegTable[rep->target1-1].selector, rep->target2 );
274 TRACE( fixup,"%d: %04x:%04x %s\n",
275 i + 1, HIWORD(address), LOWORD(address),
276 NE_GetRelocAddrName( rep->address_type, additive ) );
279 case NE_RELTYPE_OSFIXUP:
280 /* Relocation type 7:
282 * These appear to be used as fixups for the Windows
283 * floating point emulator. Let's just ignore them and
284 * try to use the hardware floating point. Linux should
285 * successfully emulate the coprocessor if it doesn't
288 TRACE( fixup, "%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
289 i + 1, rep->relocation_type, rep->offset,
290 rep->target1, rep->target2,
291 NE_GetRelocAddrName( rep->address_type, additive ) );
295 offset = rep->offset;
297 /* Apparently, high bit of address_type is sometimes set; */
298 /* we ignore it for now */
299 if (rep->address_type > NE_RADDR_OFFSET32)
302 GetModuleName( pModule->self, module, sizeof(module) );
303 ERR( fixup, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
304 module, rep->address_type );
309 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
310 TRACE( fixup," %04x:%04x\n", offset, *sp );
311 switch (rep->address_type & 0x7f)
313 case NE_RADDR_LOWBYTE:
314 *(BYTE *)sp += LOBYTE((int)address);
316 case NE_RADDR_OFFSET16:
317 *sp += LOWORD(address);
319 case NE_RADDR_POINTER32:
320 *sp += LOWORD(address);
321 *(sp+1) = HIWORD(address);
323 case NE_RADDR_SELECTOR:
324 /* Borland creates additive records with offset zero. Strange, but OK */
326 ERR(fixup,"Additive selector to %04x.Please report\n",*sp);
328 *sp = HIWORD(address);
334 else /* non-additive fixup */
338 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
340 TRACE( fixup," %04x:%04x\n", offset, *sp );
341 switch (rep->address_type & 0x7f)
343 case NE_RADDR_LOWBYTE:
344 *(BYTE *)sp = LOBYTE((int)address);
346 case NE_RADDR_OFFSET16:
347 *sp = LOWORD(address);
349 case NE_RADDR_POINTER32:
350 *(FARPROC16 *)sp = address;
352 case NE_RADDR_SELECTOR:
353 *sp = SELECTOROF(address);
358 if (next_offset == offset) break; /* avoid infinite loop */
359 if (next_offset >= GlobalSize16(pSeg->selector)) break;
360 offset = next_offset;
361 } while (offset != 0xffff);
369 WARN(fixup, "WARNING: %d: unknown ADDR TYPE %d, "
370 "TYPE %d, OFFSET %04x, TARGET %04x %04x\n",
371 i + 1, rep->address_type, rep->relocation_type,
372 rep->offset, rep->target1, rep->target2);
378 /***********************************************************************
381 BOOL32 NE_LoadAllSegments( NE_MODULE *pModule )
385 if (pModule->flags & NE_FFLAGS_SELFLOAD)
388 /* Handle self loading modules */
389 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
390 SELFLOADHEADER *selfloadheader;
391 STACK16FRAME *stack16Top;
392 THDB *thdb = THREAD_Current();
393 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
395 WORD saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
397 TRACE(module, "%.*s is a self-loading module!\n",
398 *((BYTE*)pModule + pModule->name_table),
399 (char *)pModule + pModule->name_table + 1);
400 if (!NE_LoadSegment( pModule, 1 )) return FALSE;
401 selfloadheader = (SELFLOADHEADER *)
402 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
403 selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
404 selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28);
405 selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
406 pModule->self_loading_sel = GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
407 oldstack = thdb->cur_stack;
408 thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
409 0xff00 - sizeof(*stack16Top) );
410 stack16Top = (STACK16FRAME *)PTR_SEG_TO_LIN(thdb->cur_stack);
411 stack16Top->frame32 = 0;
413 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
414 stack16Top->entry_point = 0;
415 stack16Top->entry_ip = 0;
416 stack16Top->entry_cs = 0;
421 hf = FILE_DupUnixHandle( NE_OpenFile( pModule ) );
422 TRACE(dll,"CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n",pModule->self,
423 HFILE32_TO_HFILE16(hf));
424 Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self,
425 HFILE32_TO_HFILE16(hf));
426 TRACE(dll,"Return from CallBootAppProc\n");
428 /* some BootApp procs overwrite the selector of dgroup */
429 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
430 thdb->cur_stack = oldstack;
433 commented out by Andreas Mohr;
434 some self-loading exe ("BLINKER") relies on non-primary segs not loaded.
435 contact me if you experience problems */
436 /*for (i = 2; i <= pModule->seg_count; i++)
437 if (!NE_LoadSegment( pModule, i )) return FALSE;*/
441 for (i = 1; i <= pModule->seg_count; i++)
442 if (!NE_LoadSegment( pModule, i )) return FALSE;
448 /***********************************************************************
451 * Fixup the exported functions prologs.
453 void NE_FixupPrologs( NE_MODULE *pModule )
455 SEGTABLEENTRY *pSegTable;
458 BYTE *p, *fixup_ptr, count;
459 dbg_decl_str(module, 512);
461 pSegTable = NE_SEG_TABLE(pModule);
462 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
463 dgroup = pSegTable[pModule->dgroup-1].selector;
465 TRACE(module, "(%04x)\n", pModule->self );
466 p = (BYTE *)pModule + pModule->entry_table;
469 if (p[1] == 0) /* Unused entry */
471 p += 2; /* Skip it */
474 if (p[1] == 0xfe) /* Constant entry */
476 p += 2 + *p * 3; /* Skip it */
480 /* Now fixup the entries of this bundle */
486 dbg_reset_str(module);
487 dsprintf(module,"Flags: %04x, sel %02x ", *p, sel);
488 /* According to the output generated by TDUMP, the flags mean:
489 * 0x0001 function is exported
490 * 0x0002 Single data (seems to occur only in DLLs)
492 if (sel == 0xff) { /* moveable */
493 dsprintf(module, "(%02x) o %04x", p[3], *(WORD *)(p+4) );
494 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
496 dsprintf(module, "offset %04x", *(WORD *)(p+1) );
497 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) +
500 TRACE(module, "%s Signature: %02x %02x %02x,ff %x\n",
501 dbg_str(module), fixup_ptr[0], fixup_ptr[1],
502 fixup_ptr[2], pModule->flags );
505 /* Verify the signature */
506 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
507 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
508 && fixup_ptr[2] == 0x90)
512 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
514 /* can this happen? */
515 ERR(fixup, "FixupPrologs got confused\n" );
517 else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
519 *fixup_ptr = 0xb8; /* MOV AX, */
520 *(WORD *)(fixup_ptr+1) = dgroup;
525 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
526 fixup_ptr[0] = 0x90; /* non-library: NOPs */
532 WARN(fixup, "Unknown signature\n" );
537 p += (sel == 0xff) ? 6 : 3;
542 /***********************************************************************
543 * NE_GetDLLInitParams
545 static VOID NE_GetDLLInitParams( NE_MODULE *pModule,
546 WORD *hInst, WORD *ds, WORD *heap )
548 SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
550 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
552 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
555 ERR(dll, "Library is not marked SINGLEDATA\n");
558 else /* DATA NONE DLL */
564 else /* DATA SINGLE DLL */
566 if (pModule->dgroup) {
567 *ds = pSegTable[pModule->dgroup-1].selector;
568 *heap = pModule->heap_size;
570 else /* hmm, DLL has no dgroup,
571 but why has it NE_FFLAGS_SINGLEDATA set ?
572 Buggy DLL compiler ? */
579 *hInst = *ds ? *ds : pModule->self;
583 /***********************************************************************
586 * Call the DLL initialization code
588 static BOOL32 NE_InitDLL( TDB* pTask, NE_MODULE *pModule )
590 SEGTABLEENTRY *pSegTable;
591 WORD hInst, ds, heap;
594 pSegTable = NE_SEG_TABLE( pModule );
596 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
597 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
599 /* Call USER signal handler. This is necessary to install a
600 * proper loader for HICON and HCURSOR resources that this DLL
601 * may contain. InitApp() does this for task modules. */
603 if (pTask && pTask->userhandler)
605 pTask->userhandler( pModule->self, USIG_DLL_LOAD, 0, pTask->hInstance,
609 if (!pModule->cs) return TRUE; /* no initialization code */
612 /* Registers at initialization must be:
614 * di library instance
615 * ds data segment if any
616 * es:si command line (always 0)
619 memset( &context, 0, sizeof(context) );
621 NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
623 ECX_reg(&context) = heap;
624 EDI_reg(&context) = hInst;
625 DS_reg(&context) = ds;
626 ES_reg(&context) = ds; /* who knows ... */
628 CS_reg(&context) = pSegTable[pModule->cs-1].selector;
629 EIP_reg(&context) = pModule->ip;
630 EBP_reg(&context) = OFFSETOF(THREAD_Current()->cur_stack)
631 + (WORD)&((STACK16FRAME*)0)->bp;
634 pModule->cs = 0; /* Don't initialize it twice */
635 TRACE(dll, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
636 CS_reg(&context), IP_reg(&context), DS_reg(&context),
637 DI_reg(&context), CX_reg(&context) );
638 Callbacks->CallRegisterShortProc( &context, 0 );
642 /***********************************************************************
643 * NE_CallDllEntryPoint
645 * Call the DllEntryPoint of DLLs with subsystem >= 4.0
648 static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
650 WORD hInst, ds, heap;
651 FARPROC16 entryPoint;
654 THDB *thdb = THREAD_Current();
655 LPBYTE stack = (LPBYTE)THREAD_STACK16(thdb);
657 if (pModule->expected_version < 0x0400) return;
658 if (!(ordinal = NE_GetOrdinal( pModule->self, "DllEntryPoint" ))) return;
659 if (!(entryPoint = NE_GetEntryPoint( pModule->self, ordinal ))) return;
661 memset( &context, 0, sizeof(context) );
663 NE_GetDLLInitParams( pModule, &hInst, &ds, &heap );
665 DS_reg(&context) = ds;
666 ES_reg(&context) = ds; /* who knows ... */
668 CS_reg(&context) = HIWORD(entryPoint);
669 IP_reg(&context) = LOWORD(entryPoint);
670 EBP_reg(&context) = OFFSETOF( thdb->cur_stack )
671 + (WORD)&((STACK16FRAME*)0)->bp;
673 *(DWORD *)(stack - 4) = dwReason; /* dwReason */
674 *(WORD *) (stack - 6) = hInst; /* hInst */
675 *(WORD *) (stack - 8) = ds; /* wDS */
676 *(WORD *) (stack - 10) = heap; /* wHeapSize */
677 *(DWORD *)(stack - 14) = 0; /* dwReserved1 */
678 *(WORD *) (stack - 16) = 0; /* wReserved2 */
680 TRACE(dll, "Calling DllEntryPoint, cs:ip=%04lx:%04x\n",
681 CS_reg(&context), IP_reg(&context));
683 Callbacks->CallRegisterShortProc( &context, 16 );
687 /***********************************************************************
690 * Recursively initialize all DLLs (according to the order in which
691 * they where loaded).
693 void NE_InitializeDLLs( HMODULE16 hModule )
695 TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
699 if (!(pModule = NE_GetPtr( hModule ))) return;
700 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
702 if (pModule->dlls_to_init)
704 HGLOBAL16 to_init = pModule->dlls_to_init;
705 pModule->dlls_to_init = 0;
706 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
708 NE_InitializeDLLs( *pDLL );
710 GlobalFree16( to_init );
712 NE_InitDLL( pTask, pModule );
713 NE_CallDllEntryPoint( pModule, DLL_PROCESS_ATTACH );
717 /***********************************************************************
720 * If lib_only is TRUE, handle the module like a library even if it is a .EXE
722 HINSTANCE16 NE_CreateInstance( NE_MODULE *pModule, HINSTANCE16 *prev,
725 SEGTABLEENTRY *pSegment;
727 HINSTANCE16 hNewInstance;
729 if (pModule->dgroup == 0)
731 if (prev) *prev = pModule->self;
732 return pModule->self;
735 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
736 if (prev) *prev = pSegment->selector;
738 /* if it's a library, create a new instance only the first time */
739 if (pSegment->selector)
741 if (pModule->flags & NE_FFLAGS_LIBMODULE) return pSegment->selector;
742 if (lib_only) return pSegment->selector;
745 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
746 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
747 minsize += pModule->heap_size;
748 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED, minsize,
749 pModule->self, FALSE, FALSE, FALSE );
750 if (!hNewInstance) return 0;
751 pSegment->selector = hNewInstance;
752 pSegment->flags |= NE_SEGFLAGS_ALLOCATED;
757 /***********************************************************************
760 * Needed for self-loading modules.
763 /* It does nothing */
764 void WINAPI PatchCodeHandle(HANDLE16 hSel)
766 FIXME(module,"(%04x): stub.\n",hSel);
770 /***********************************************************************
773 * This function translates NE segment flags to GlobalAlloc flags
775 static WORD NE_Ne2MemFlags(WORD flags)
779 if (flags & NE_SEGFLAGS_DISCARDABLE)
780 memflags |= GMEM_DISCARDABLE;
781 if (flags & NE_SEGFLAGS_MOVEABLE ||
782 ( ! (flags & NE_SEGFLAGS_DATA) &&
783 ! (flags & NE_SEGFLAGS_LOADED) &&
784 ! (flags & NE_SEGFLAGS_ALLOCATED)
787 memflags |= GMEM_MOVEABLE;
788 memflags |= GMEM_ZEROINIT;
790 memflags = GMEM_ZEROINIT | GMEM_FIXED;
795 /***********************************************************************
796 * NE_AllocateSegment (WPROCS.26)
798 DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
800 WORD size = wSize << wElem;
801 HANDLE16 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
802 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
806 /***********************************************************************
809 BOOL32 NE_CreateSegments( NE_MODULE *pModule )
811 SEGTABLEENTRY *pSegment;
814 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
816 pSegment = NE_SEG_TABLE( pModule );
817 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
819 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
820 if (i == pModule->ss) minsize += pModule->stack_size;
821 /* The DGROUP is allocated by NE_CreateInstance */
822 if (i == pModule->dgroup) continue;
823 pSegment->selector = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags),
824 minsize, pModule->self,
825 !(pSegment->flags & NE_SEGFLAGS_DATA),
827 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
828 if (!pSegment->selector) return FALSE;
829 pSegment->flags |= NE_SEGFLAGS_ALLOCATED;
832 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
833 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
838 /**********************************************************************
839 * IsSharedSelector (KERNEL.345)
841 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
843 /* Check whether the selector belongs to a DLL */
844 NE_MODULE *pModule = NE_GetPtr( selector );
845 if (!pModule) return FALSE;
846 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;