Release 950430
Sat Apr 29 20:42:01 1995 Alexandre Julliard (julliard@sunsite.unc.edu)
* [controls/static.c]
Fixed painting of SS_*FRAME controls.
* [if1632/callback.c]
Pass the window instance as DS to the 16-bit window procedure.
Rewrote Catch() and Throw() to make them work with multiple tasks.
* [loader/main.c]
New function MAIN_Init() to perform initializations before the
first task is started instead of doing them in InitApp().
Temporary hack to command-line parsing to load one program per
command-line argument, to make testing task-switching easier.
* [loader/*.c]
Reimplemented modules to use a Windows-compatible layout and to
allow multiple tasks and multiple module instances. Not really
finished yet.
* [loader/task.c] [misc/exec.c]
Reimplemented tasks to use a common address space, and implemented
preliminary task-switching capabilities.
* [memory/global.c]
Fixed bug in GlobalNext().
* [misc/main.c]
Updated the list of contributors. Let me know if I forgot someone.
* [miscemu/int21.c]
Use one DTA per task instead of a global one.
* [objects/bitblt.c]
Fixed bug in BitBlt() that could cause BadMatch errors.
* [tools/build.c]
Added new function type 'stub', that makes possible to export an
unimplemented function by name as well as by ordinal. This will
avoid loading errors for unimplemented functions.
Generate an in-memory module layout for built-in DLLs so that the
same code can be used for built-in and loaded modules.
Changed relay code to make it unnecessary to save the value of the
BP register.
* [windows/message.c]
Implemented multiple message queues and preliminary task-switching
capabilities. Inter-task SendMessage() calls are not implemented
yet and will probably cause crashes if used.
* [windows/property.c]
Reimplemented properties and allocate them on the USER heap.
* [windows/win.c]
Fixed bug in SetWindowWord().
Reimplemented EnumWindows() and EnumTaskWindows().
Tue Apr 18 09:48:38 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [misc/main.c]
GetSystemParametersInfo(): Additional action SPI_GETICONTITLEFONT.
* [loader/resource.c]
Removed the check for NE_SEGFLAGS_EXECUTEONLY, since it broke
control.exe.
Fixed icon loading.
* [objects/font.c] [include/windows.h]
Fixed a bug in InitFontsList() and worked on the EnumFonts()
functions to make them comprehensible.
* [controls/button.c]
Fixed my previous patch to handle LBUTTONUP messages.
Fri Apr 14 11:41:28 1995 Cameron Heide (heide@ee.ualberta.ca)
* [misc/network.c, misc/dos_fs.c]
Implemented WNetGetConnection. All that is currently
supported are drives, for which the remote name is simply
the redirected UNIX directory name.
* [miscemu/int2?.c]
More drive number validity checking.
Wed Apr 12 11:28:37 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [controls/listbox.c]
Oops, my previous change to ListBoxDirectory broke the Borland
file open dialog. Fixed.
Mon Apr 10 23:17:12 1995 Martin von Loewis <loewis@informatik.hu-berlin.de>
* [if1632/ole2nls.spec] [misc/ole2nls.c] [misc/Imakefile]
New file ole2nls.c. Added stubs for GetUserDefaultLCID,
GetSystemDefaultLCID, GetUserDefaultLangID, GetSystemDefaultLangID.
Mon Apr 10 10:05:18 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [memory/global.c] [memory/local.c] [include/windows.h]
GlobalReAlloc(): If GMEM_MODIFY is set, don't resize the block.
LocalReAlloc(): Same for LMEM_MODIFY.
* [controls/listbox.c]
Fixed a bug in ListBoxDirectory that prevented commdlg from working.
Check for errors in some more places.
* [if1632/gdi.spec] [if1632/user.spec]
16 bit callback functions should be passed as segptrs.
* [include/dlls.h] [loader/ne_image.c] [loader/selector.c]
[loader/library.c]
Prevent a DLL from being initialized twice (Borlands Resource
Workshop used to do this).
Provide an additional flag for each w_file that indicates whether
it's an EXE or a DLL, for combinations like pbrush.exe/.dll.
* [controls/button.c]
Handle LBUTTONUP messages even if the button no longer has the
capture (for WinHelp).
* [include/wintypes.h]
FARPROC is now a segptr for the emulator and a function
pointer for the library.
* [misc/commdlg.c] [misc/commdlg.h]
Cleaned the file dialogs up a little. They now work reasonably well,
although there are still some problems (e.g. files are initially
invisible).
* [windows/class.c] [if1632/user.spec] [include/windows.h]
GetClassInfo() must take a segptr, as it checks whether the
highword is zero.
GetClassName() called the wrong atom function. No surprise it didn't
find anything.
* [misc/lstr.c]
AnsiToOem() and OemToAnsi() didn't terminate the strings. Fixed.
Removed some warnings.
* [if1632/relay.c] [if1632/ddeml.spec] [include/dlls.h]
New spec file for the 3.1 DDEML DDL.
* [controls/menu.c]
Small fix to ChangeMenu - mask out the obsolete flags
(MF_APPEND == MF_OWNERDRAW, this led to problems). It also had
problems with the MF_BYPOSITION flag.
* [windows/message.c]
SendMessage(): call the WH_CALLWNDPROC hook function. This is rather
ugly, I'm afraid. Windows probably passes a pointer to the 16 bit
stack for speed reasons.
* [windows/hook.c] [include/windows.h]
Set/HookWindowsHook() shouldn't just call their *Ex counterparts, as
they have slightly different semantics.
MS Hearts now works somewhat, if you disable the new builtin DDEML.
The graphics are completely messed up, though.
diff --git a/loader/Imakefile b/loader/Imakefile
index 69bf07a..b3863a6 100644
--- a/loader/Imakefile
+++ b/loader/Imakefile
@@ -6,6 +6,7 @@
dump.c \
ldt.c \
main.c \
+ module.c \
ne_image.c \
ne_resource.c \
pe_image.c \
diff --git a/loader/dump.c b/loader/dump.c
index 2011bbe..39344e5 100644
--- a/loader/dump.c
+++ b/loader/dump.c
@@ -40,24 +40,6 @@
}
/**********************************************************************
- * PrintSegmentTable
- */
-void
-PrintSegmentTable(struct ne_segment_table_entry_s *seg_table, int nentries)
-{
- int i;
-
- for (i = 0; i < nentries; i++)
- {
- printf(" %2d: OFFSET %04x, LENGTH %04x, ",
- i + 1, seg_table[i].seg_data_offset,
- seg_table[i].seg_data_length);
- printf("FLAGS %04x, MIN ALLOC %04x\n",
- seg_table[i].seg_flags, seg_table[i].min_alloc);
- }
-}
-
-/**********************************************************************
* PrintRelocationTable
*/
void
diff --git a/loader/library.c b/loader/library.c
index 8c02181..e303bbb 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -21,12 +21,13 @@
#include "task.h"
#include "toolhelp.h"
#include "selectors.h"
-#include "stddebug.h"
-#include "debug.h"
#include "prototypes.h"
#include "library.h"
#include "ne_image.h"
#include "pe_image.h"
+#include "module.h"
+#include "stddebug.h"
+#include "debug.h"
struct w_files *wine_files = NULL;
static char *DLL_Extensions[] = { "dll", NULL };
@@ -63,7 +64,7 @@
return w;
}
-
+/*
int IsDLLLoaded(char *name)
{
struct w_files *wpnt;
@@ -72,16 +73,16 @@
return 1;
for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
- if(strcmp(wpnt->name, name) == 0)
+ if(strcmp(wpnt->name, name) == 0 )
return 1;
return 0;
}
-
+*/
void InitDLL(struct w_files *wpnt)
{
if (wpnt->ne)
- NE_InitDLL(wpnt);
+ NE_InitDLL(wpnt->hModule);
else
PE_InitDLL(wpnt);
}
@@ -142,9 +143,11 @@
}
/* already loaded ? */
- for (wpnt = wine_files ; wpnt ; wpnt = wpnt->next)
- if (strcasecmp(wpnt->name, modulename) == 0)
- return wpnt->hinstance;
+ for (wpnt = wine_files ; wpnt ; wpnt = wpnt->next) {
+ if (strcasecmp(wpnt->name, modulename) == 0 && filetype == wpnt->type) {
+ return wpnt->hinstance;
+ }
+ }
/*
* search file
@@ -195,6 +198,8 @@
*/
wpnt->filename = strdup(buffer);
wpnt->name = strdup(modulename);
+ wpnt->type = filetype;
+ wpnt->initialised = FALSE;
/* read mz header */
wpnt->mz_header = (struct mz_header_s *) malloc(sizeof(struct mz_header_s));;
@@ -260,121 +265,6 @@
}
/**********************************************************************
- * GetModuleHandle [KERNEL.47]
- */
-HANDLE GetModuleHandle(LPSTR lpModuleName)
-{
- register struct w_files *w = wine_files;
- int i;
- char dllname[256];
-
- if ((int) lpModuleName & 0xffff0000)
- ExtractDLLName(lpModuleName, dllname);
-
- if ((int) lpModuleName & 0xffff0000)
- dprintf_module(stddeb,"GetModuleHandle('%s');\n", lpModuleName);
- else
- dprintf_module(stddeb,"GetModuleHandle('%p');\n", lpModuleName);
-
-/* dprintf_module(stddeb,"GetModuleHandle // searching in builtin libraries\n");*/
- for (i = 0; i < N_BUILTINS; i++) {
- if (dll_builtin_table[i].dll_name == NULL) break;
- if (!dll_builtin_table[i].dll_is_used){
- dprintf_module(stddeb,"Skipping builtin %s\n",
- dll_builtin_table[i].dll_name);
- continue;
- }
- if (((int) lpModuleName & 0xffff0000) == 0) {
- if (0xFF00 + i == (int) lpModuleName) {
- dprintf_module(stddeb,"GetModuleHandle('%s') return %04X \n",
- lpModuleName, 0xff00 + i);
- return 0xFF00 + i;
- }
- }
- else if (strcasecmp(dll_builtin_table[i].dll_name, dllname) == 0) {
- dprintf_module(stddeb,"GetModuleHandle('%p') return %04X \n",
- lpModuleName, 0xFF00 + i);
- return (0xFF00 + i);
- }
- }
-
- dprintf_module(stddeb,"GetModuleHandle // searching in loaded modules\n");
- while (w) {
-/* dprintf_module(stddeb,"GetModuleHandle // '%x' \n", w->name); */
- if (((int) lpModuleName & 0xffff0000) == 0) {
- if (w->hinstance == (int) lpModuleName) {
- dprintf_module(stddeb,"GetModuleHandle('%p') return %04X \n",
- lpModuleName, w->hinstance);
- return w->hinstance;
- }
- }
- else if (strcasecmp(w->name, dllname) == 0) {
- dprintf_module(stddeb,"GetModuleHandle('%s') return %04X \n",
- lpModuleName, w->hinstance);
- return w->hinstance;
- }
- w = w->next;
- }
- printf("GetModuleHandle('%p') not found !\n", lpModuleName);
- return 0;
-}
-
-
-/**********************************************************************
- * GetModuleUsage [KERNEL.48]
- */
-int GetModuleUsage(HANDLE hModule)
-{
- struct w_files *w;
-
- dprintf_module(stddeb,"GetModuleUsage(%04X);\n", hModule);
-
- /* built-in dll ? */
- if (IS_BUILTIN_DLL(hModule))
- return 2;
-
- w = GetFileInfo(hModule);
-/* return w->Usage; */
- return 1;
-}
-
-
-/**********************************************************************
- * GetModuleFilename [KERNEL.49]
- */
-int GetModuleFileName(HANDLE hModule, LPSTR lpFileName, short nSize)
-{
- struct w_files *w;
- LPSTR str;
- char windir[256], temp[256];
-
- dprintf_module(stddeb,"GetModuleFileName(%04X, %p, %d);\n", hModule, lpFileName, nSize);
-
- if (lpFileName == NULL) return 0;
- if (nSize < 1) return 0;
-
- /* built-in dll ? */
- if (IS_BUILTIN_DLL(hModule)) {
- GetWindowsDirectory(windir, sizeof(windir));
- sprintf(temp, "%s\\%s.DLL", windir, dll_builtin_table[hModule & 0x00ff].dll_name);
- ToDos(temp);
- strncpy(lpFileName, temp, nSize);
- dprintf_module(stddeb,"GetModuleFileName copied '%s' (internal dll) return %d \n", lpFileName, nSize);
- return strlen(lpFileName);
- }
-
- /* check loaded dlls */
- if ((w = GetFileInfo(hModule)) == NULL)
- return 0;
- str = DOS_GetDosFileName(w->filename);
- if (nSize > strlen(str)) nSize = strlen(str) + 1;
- strncpy(lpFileName, str, nSize);
- dprintf_module(stddeb,"GetModuleFileName copied '%s' return %d \n", lpFileName, nSize);
- return nSize - 1;
-}
-
-
-/**********************************************************************
* LoadLibrary [KERNEL.95]
*/
HANDLE LoadLibrary(LPSTR libname)
@@ -429,214 +319,33 @@
}
-/**********************************************************************
- * GetProcAddress [KERNEL.50]
+/***********************************************************************
+ * GetProcAddress (KERNEL.50)
*/
-FARPROC GetProcAddress(HANDLE hModule, char *proc_name)
+FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
{
-#ifdef WINELIB
- WINELIB_UNIMP ("GetProcAddress");
-#else
- int ret;
- WORD sel, addr;
- register struct w_files *w = wine_files;
- int ordinal, len;
- char * cpnt;
- char C[128];
- HTASK hTask;
- LPTASKENTRY lpTask;
+ WORD ordinal;
+ SEGPTR ret;
- /* built-in dll ? */
- if (IS_BUILTIN_DLL(hModule))
+ if (!hModule) hModule = GetCurrentTask();
+ hModule = GetExePtr( hModule );
+
+ if (HIWORD(name) != 0)
{
- if ((int) proc_name & 0xffff0000)
- {
- dprintf_module(stddeb,"GetProcAddress: builtin %#04X, '%s'\n",
- hModule, proc_name);
- if (GetEntryDLLName(dll_builtin_table[hModule - 0xFF00].dll_name,
- proc_name, &sel, &addr))
- {
- printf("Address not found !\n");
- }
- }
- else
- {
- dprintf_module(stddeb,"GetProcAddress: builtin %#04X, %d\n",
- hModule, (int)proc_name);
- if (GetEntryDLLOrdinal(dll_builtin_table[hModule-0xFF00].dll_name,
- (int)proc_name & 0x0000FFFF, &sel, &addr))
- {
- printf("Address not found !\n");
- }
- }
- ret = MAKELONG(addr, sel);
- dprintf_module(stddeb,"GetProcAddress // ret=%08X sel=%04X addr=%04X\n",
- ret, sel, addr);
- return (FARPROC)ret;
+ ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
+ dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
+ hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
}
- if (hModule == 0)
+ else
{
- hTask = GetCurrentTask();
- dprintf_module(stddeb,"GetProcAddress // GetCurrentTask()=%04X\n", hTask);
- lpTask = (LPTASKENTRY) GlobalLock(hTask);
- if (lpTask == NULL)
- {
- printf("GetProcAddress: can't find current module handle !\n");
- return NULL;
- }
- hModule = lpTask->hInst;
- dprintf_module(stddeb,"GetProcAddress: current module=%04X instance=%04X!\n",
- lpTask->hModule, lpTask->hInst);
- GlobalUnlock(hTask);
+ ordinal = LOWORD(name);
+ dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
+ hModule, ordinal );
}
- while (w && w->hinstance != hModule)
- w = w->next;
- if (w == NULL)
- return NULL;
- dprintf_module(stddeb,"GetProcAddress // Module Found ! w->filename='%s'\n", w->filename);
- if ((int)proc_name & 0xFFFF0000)
- {
- AnsiUpper(proc_name);
- dprintf_module(stddeb,"GetProcAddress: %04X, '%s'\n", hModule, proc_name);
- cpnt = w->ne->nrname_table;
- while(TRUE)
- {
- if (((int) cpnt) - ((int)w->ne->nrname_table) >
- w->ne->ne_header->nrname_tab_length) return NULL;
- len = *cpnt++;
- strncpy(C, cpnt, len);
- C[len] = '\0';
- dprintf_module(stddeb,"pointing Function '%s' ordinal=%d !\n",
- C, *((unsigned short *)(cpnt + len)));
- if (strncmp(cpnt, proc_name, len) == 0)
- {
- ordinal = *((unsigned short *)(cpnt + len));
- break;
- }
- cpnt += len + 2;
- }
- if (ordinal == 0)
- {
- printf("GetProcAddress // function '%s' not found !\n", proc_name);
- return NULL;
- }
- }
- else
- {
- dprintf_module(stddeb,"GetProcAddress: %#04x, %d\n", hModule, (int) proc_name);
- ordinal = (int)proc_name;
- }
- ret = GetEntryPointFromOrdinal(w, ordinal);
- if (ret == -1)
- {
- printf("GetProcAddress // Function #%d not found !\n", ordinal);
- return NULL;
- }
- addr = ret & 0xffff;
- sel = (ret >> 16);
- dprintf_module(stddeb,"GetProcAddress // ret=%08X sel=%04X addr=%04X\n", ret, sel, addr);
- return (FARPROC) ret;
-#endif /* WINELIB */
+ if (!ordinal) return (FARPROC)0;
+
+ ret = MODULE_GetEntryPoint( hModule, ordinal );
+
+ dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", ret );
+ return (FARPROC)ret;
}
-
-/* internal dlls */
-static void
-FillModStructBuiltIn(MODULEENTRY *lpModule, struct dll_name_table_entry_s *dll)
-{
- lpModule->dwSize = dll->table->dll_table_length * 1024;
- strcpy(lpModule->szModule, dll->dll_name);
- lpModule->hModule = 0xff00 + dll->table->dll_number;
- lpModule->wcUsage = GetModuleUsage(lpModule->hModule);
- GetModuleFileName(lpModule->hModule, lpModule->szExePath, MAX_PATH + 1);
- lpModule->wNext = 0;
-}
-
-/* loaded dlls */
-static void
-FillModStructLoaded(MODULEENTRY *lpModule, struct w_files *dll)
-{
- lpModule->dwSize = 16384;
- strcpy(lpModule->szModule, dll->name);
- lpModule->hModule = dll->hinstance;
- lpModule->wcUsage = GetModuleUsage(lpModule->hModule);
- GetModuleFileName(lpModule->hModule, lpModule->szExePath, MAX_PATH + 1);
- lpModule->wNext = 0;
-}
-
-/**********************************************************************
- * ModuleFirst [TOOLHELP.59]
- */
-BOOL ModuleFirst(MODULEENTRY *lpModule)
-{
- dprintf_module(stddeb,"ModuleFirst(%08X)\n", (int) lpModule);
-
- FillModStructBuiltIn(lpModule, &dll_builtin_table[0]);
- return TRUE;
-}
-
-/**********************************************************************
- * ModuleNext [TOOLHELP.60]
- */
-BOOL ModuleNext(MODULEENTRY *lpModule)
-{
- struct w_files *w;
-
- dprintf_module(stddeb,"ModuleNext(%08X)\n", (int) lpModule);
-
- if (IS_BUILTIN_DLL(lpModule->hModule))
- {
- int builtin_no=lpModule->hModule & 0xff;
- do{
- /* last built-in ? */
- if (builtin_no == (N_BUILTINS - 1) ) {
- if (wine_files) {
- FillModStructLoaded(lpModule, wine_files);
- return TRUE;
- } else
- return FALSE;
- }
- builtin_no++;
- }while(!dll_builtin_table[builtin_no].dll_is_used);
-
- FillModStructBuiltIn(lpModule, &dll_builtin_table[builtin_no]);
- return TRUE;
- }
- w = GetFileInfo(lpModule->hModule);
- if (w->next) {
- FillModStructLoaded(lpModule, w->next);
- return TRUE;
- }
- return FALSE;
-}
-
-/**********************************************************************
- * ModuleFindHandle [TOOLHELP.62]
- */
-HMODULE ModuleFindHandle(MODULEENTRY *lpModule, HMODULE hModule)
-{
- struct w_files *w;
-
- dprintf_module(stddeb,"ModuleFindHandle(%08X, %04X)\n", (int) lpModule, (int)hModule);
-
- /* built-in dll ? */
- if (IS_BUILTIN_DLL(hModule)) {
- FillModStructBuiltIn(lpModule, &dll_builtin_table[hModule & 0xff]);
- return hModule;
- }
-
- /* check loaded dlls */
- if ((w = GetFileInfo(hModule)) == NULL)
- return (HMODULE) NULL;
-
- FillModStructLoaded(lpModule, w);
- return w->hinstance;
-}
-
-/**********************************************************************
- * ModuleFindName [TOOLHELP.61]
- */
-HMODULE ModuleFindName(MODULEENTRY *lpModule, LPCSTR lpstrName)
-{
- return (ModuleFindHandle(lpModule, GetModuleHandle((char*)lpstrName)));
-}
-
diff --git a/loader/main.c b/loader/main.c
index 6fa103e..ce712ae 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -30,7 +30,6 @@
int Argc;
HINSTANCE hSysRes, hInstMain;
unsigned short WIN_StackSize;
-unsigned short WIN_HeapSize;
/**********************************************************************
* myerror
@@ -45,21 +44,90 @@
exit(1);
}
-
+
+
+/***********************************************************************
+ * Main initialisation routine
+ */
+int MAIN_Init(void)
+{
+ int queueSize;
+
+ SpyInit();
+
+ /* Initialize relay code */
+ if (!RELAY_Init()) return 0;
+
+ /* Create built-in modules */
+ if (!MODULE_Init()) return 0;
+
+ /* Initialize tasks */
+ if (!TASK_Init()) return 0;
+
+ /* Initialize the DOS file system */
+ DOS_InitFS();
+
+ /* Initialize communications */
+ COMM_Init();
+
+#ifndef WINELIB
+ /* Initialize the DOS memory */
+ INT21_Init();
+
+ /* Create USER heap */
+ if (!USER_HeapInit()) return 0;
+#endif
+
+ /* Global atom table initialisation */
+ if (!ATOM_Init()) return 0;
+
+ /* GDI initialisation */
+ if (!GDI_Init()) return 0;
+
+ /* Initialize system colors and metrics*/
+ SYSMETRICS_Init();
+ SYSCOLOR_Init();
+
+ /* Create the DCEs */
+ DCE_Init();
+
+ /* Initialize built-in window classes */
+ if (!WIDGETS_Init()) return 0;
+
+ /* Initialize dialog manager */
+ if (!DIALOG_Init()) return 0;
+
+ /* Initialize menus */
+ if (!MENU_Init()) return 0;
+
+ /* Create desktop window */
+ if (!WIN_CreateDesktopWindow()) return 0;
+ if (!DESKTOP_Init()) return 0;
+
+ /* Create system message queue */
+ queueSize = GetProfileInt( "windows", "TypeAhead", 120 );
+ if (!MSG_CreateSysMsgQueue( queueSize )) return 0;
+
+ return 1;
+}
+
+
#ifndef WINELIB
/**********************************************************************
* main
*/
int _WinMain(int argc, char **argv)
{
- char *p, filename[256];
- HANDLE hTaskMain;
+ char *p, filename[256];
+ int i;
- struct w_files *wpnt;
+ struct w_files *wpnt;
#ifdef WINESTAT
- char * cp;
+ char * cp;
#endif
+ if (!MAIN_Init()) return 0;
+
Argc = argc - 1;
Argv = argv + 1;
@@ -76,13 +144,13 @@
strcat(WindowsPath, filename);
}
- if ((hInstMain = LoadImage(Argv[0], EXE, 1)) < 32) {
- fprintf(stderr, "wine: can't load %s!.\n", Argv[0]);
+ for (i = 0; i < Argc; i++)
+ {
+ if ((hInstMain = LoadImage(Argv[i], EXE, 1)) < 32) {
+ fprintf(stderr, "wine: can't load %s!.\n", Argv[i]);
exit(1);
- }
- hTaskMain = CreateNewTask(hInstMain, 0);
- dprintf_dll(stddeb,"_WinMain // hTaskMain=%04X hInstMain=%04X !\n",
- hTaskMain, hInstMain);
+ }
+ }
GetPrivateProfileString("wine", "SystemResources", "sysres.dll",
filename, sizeof(filename), WINE_INI);
@@ -110,15 +178,14 @@
* Initialize signal handling.
*/
init_wine_signals();
-
+
wpnt = GetFileInfo(hInstMain);
if (Options.debug)
wine_debug(0, NULL);
- if (wpnt->ne)
- return(NE_StartProgram(wpnt));
- else
- return(PE_StartProgram(wpnt));
+ Yield(); /* Start the first task */
+ fprintf( stderr, "WinMain: Should never happen: returned from Yield()\n" );
+ return 0;
}
#endif /* #ifndef WINELIB */
diff --git a/loader/module.c b/loader/module.c
new file mode 100644
index 0000000..7ea2944
--- /dev/null
+++ b/loader/module.c
@@ -0,0 +1,723 @@
+/*
+ * Modules
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "windows.h"
+#include "dlls.h"
+#include "global.h"
+#include "ldt.h"
+#include "module.h"
+#include "neexe.h"
+#include "toolhelp.h"
+#include "stddebug.h"
+/* #define DEBUG_MODULE */
+#include "debug.h"
+
+
+extern BYTE KERNEL_Module_Start[], KERNEL_Module_End[];
+
+extern struct dll_name_table_entry_s dll_builtin_table[];
+
+static HMODULE hFirstModule = 0;
+
+
+/***********************************************************************
+ * MODULE_Init
+ *
+ * Create the built-in modules.
+ */
+BOOL MODULE_Init(void)
+{
+ HMODULE hModule;
+ NE_MODULE *pModule;
+ SEGTABLEENTRY *pSegTable;
+ struct dll_table_s *table;
+ int i;
+
+ /* Create the built-in modules */
+
+ for (i = 0; i < N_BUILTINS; i++)
+ {
+ if (!dll_builtin_table[i].dll_is_used) continue;
+ table = dll_builtin_table[i].table;
+
+ hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
+ table->module_end - table->module_start,
+ 0, FALSE, FALSE, FALSE );
+ if (!hModule) return FALSE;
+ FarSetOwner( hModule, hModule );
+
+ table->hModule = hModule;
+
+ dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
+ dll_builtin_table[i].dll_name, hModule );
+
+ /* Allocate the code segment */
+
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ pSegTable = NE_SEG_TABLE( pModule );
+
+ pSegTable->selector = GLOBAL_CreateBlock(GMEM_FIXED, table->code_start,
+ pSegTable->minsize, hModule,
+ TRUE, TRUE, FALSE );
+ if (!pSegTable->selector) return FALSE;
+ pSegTable++;
+
+ /* Allocate the data segment */
+
+ pSegTable->selector = GLOBAL_Alloc( GMEM_FIXED, pSegTable->minsize,
+ hModule, FALSE, FALSE, FALSE );
+ if (!pSegTable->selector) return FALSE;
+ memcpy( GlobalLock( pSegTable->selector ), table->data_start,
+ pSegTable->minsize );
+
+ pModule->next = hFirstModule;
+ hFirstModule = hModule;
+ }
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * MODULE_PrintModule
+ */
+void MODULE_PrintModule( HMODULE hmodule )
+{
+ int i, ordinal;
+ SEGTABLEENTRY *pSeg;
+ BYTE *pstr;
+ WORD *pword;
+ NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hmodule );
+
+ /* Dump the module info */
+
+ printf( "Module %04x:\n", hmodule );
+ printf( "count=%d flags=%04x heap=%d stack=%d\n",
+ pModule->count, pModule->flags,
+ pModule->heap_size, pModule->stack_size );
+ printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
+ pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
+ pModule->seg_count, pModule->modref_count );
+ printf( "os_flags=%d swap_area=%d version=%04x\n",
+ pModule->os_flags, pModule->min_swap_area,
+ pModule->expected_version );
+
+ /* Dump the file info */
+
+ printf( "Filename: '%s'\n",
+ ((LOADEDFILEINFO *)((BYTE *)pModule + pModule->fileinfo))->filename );
+
+ /* Dump the segment table */
+
+ printf( "\nSegment table:\n" );
+ pSeg = NE_SEG_TABLE( pModule );
+ for (i = 0; i < pModule->seg_count; i++, pSeg++)
+ printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
+ i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
+ pSeg->minsize, pSeg->selector );
+
+ /* Dump the resource table */
+
+ printf( "\nResource table:\n" );
+ if (pModule->res_table)
+ {
+ pword = (WORD *)((BYTE *)pModule + pModule->res_table);
+ printf( "Alignment: %d\n", *pword++ );
+ while (*pword)
+ {
+ struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
+ struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
+ printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
+ for (i = 0; i < ptr->count; i++, pname++)
+ printf( "offset=%d len=%d id=%04x\n",
+ pname->offset, pname->length, pname->id );
+ pword = (WORD *)pname;
+ }
+ }
+ else printf( "None\n" );
+
+ /* Dump the resident name table */
+
+ printf( "\nResident-name table:\n" );
+ pstr = (char *)pModule + pModule->name_table;
+ while (*pstr)
+ {
+ printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
+ *(WORD *)(pstr + *pstr + 1) );
+ pstr += *pstr + 1 + sizeof(WORD);
+ }
+
+ /* Dump the module reference table */
+
+ printf( "\nModule ref table:\n" );
+ if (pModule->modref_table)
+ {
+ pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
+ for (i = 0; i < pModule->modref_count; i++, pword++)
+ {
+ char *name = (char *)pModule + pModule->import_table + *pword;
+ printf( "%d: %04x -> '%*.*s'\n",
+ i, *pword, *name, *name, name + 1 );
+ }
+ }
+ else printf( "None\n" );
+
+ /* Dump the entry table */
+
+ printf( "\nEntry table:\n" );
+ pstr = (char *)pModule + pModule->entry_table;
+ ordinal = 1;
+ while (*pstr)
+ {
+ printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
+ if (!pstr[1])
+ {
+ ordinal += *pstr;
+ pstr += 2;
+ }
+ else if ((BYTE)pstr[1] == 0xff) /* moveable */
+ {
+ struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
+ for (i = 0; i < *pstr; i++, pe++)
+ printf( "%d: %02x:%04x (moveable)\n",
+ ordinal++, pe->seg_number, pe->offset );
+ pstr = (char *)pe;
+ }
+ else /* fixed */
+ {
+ struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
+ for (i = 0; i < *pstr; i++, pe++)
+ printf( "%d: %04x (fixed)\n",
+ ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
+ pstr = (char *)pe;
+ }
+ }
+
+ /* Dump the non-resident names table */
+
+ printf( "\nNon-resident names table:\n" );
+ if (pModule->nrname_handle)
+ {
+ pstr = (char *)GlobalLock( pModule->nrname_handle );
+ while (*pstr)
+ {
+ printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
+ *(WORD *)(pstr + *pstr + 1) );
+ pstr += *pstr + 1 + sizeof(WORD);
+ }
+ }
+ printf( "\n" );
+}
+
+
+/***********************************************************************
+ * MODULE_OpenFile
+ */
+int MODULE_OpenFile( HMODULE hModule )
+{
+ NE_MODULE *pModule;
+ char *name;
+
+ static HMODULE hCachedModule = 0;
+ static int cachedfd = -1;
+
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
+ hModule, hCachedModule, cachedfd );
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return -1;
+ if (hCachedModule == hModule) return cachedfd;
+ close( cachedfd );
+ hCachedModule = hModule;
+ name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
+ cachedfd = open( name /* DOS_GetUnixFileName( name ) */, O_RDONLY );
+ dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
+ name, cachedfd );
+ return cachedfd;
+}
+
+
+/***********************************************************************
+ * MODULE_CreateSegments
+ */
+BOOL MODULE_CreateSegments( HMODULE hModule )
+{
+ SEGTABLEENTRY *pSegment;
+ NE_MODULE *pModule;
+ int i, minsize;
+
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
+ pSegment = NE_SEG_TABLE( pModule );
+ for (i = 1; i <= pModule->seg_count; i++, pSegment++)
+ {
+ minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
+ if (i == pModule->ss) minsize += pModule->stack_size;
+ if (i == pModule->dgroup)
+ {
+ /* FIXME: this is needed because heap growing is not implemented */
+ pModule->heap_size = 0x10000 - minsize;
+ minsize = 0x10000;
+ }
+ pSegment->selector = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
+ minsize, hModule,
+ !(pSegment->flags & NE_SEGFLAGS_DATA),
+ FALSE,
+ FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
+ if (!pSegment->selector) return FALSE;
+ }
+
+ pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
+ (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * MODULE_LoadExeHeader
+ */
+HMODULE MODULE_LoadExeHeader( int fd, char *filename )
+{
+ struct mz_header_s mz_header;
+ struct ne_header_s ne_header;
+ int size;
+ HMODULE hModule;
+ NE_MODULE *pModule;
+ BYTE *pData;
+ char *buffer, *fastload = NULL;
+ int fastload_offset = 0, fastload_length = 0;
+
+ /* Read a block from either the file or the fast-load area. */
+#define READ(offset,size,buffer) \
+ ((fastload && ((offset) >= fastload_offset) && \
+ ((offset)+(size) <= fastload_offset+fastload_length)) ? \
+ (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
+ (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
+ read( fd, (buffer), (size) ) == (size)))
+
+ lseek( fd, 0, SEEK_SET );
+ if ((read( fd, &mz_header, sizeof(mz_header) ) != sizeof(mz_header)) ||
+ (mz_header.mz_magic != MZ_SIGNATURE)) return 11; /* invalid exe */
+
+ lseek( fd, mz_header.ne_offset, SEEK_SET );
+ if (read( fd, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
+ return 11; /* invalid exe */
+
+ if (ne_header.ne_magic == PE_SIGNATURE) return 21; /* win32 exe */
+ if (ne_header.ne_magic != NE_SIGNATURE) return 11; /* invalid exe */
+
+ /* We now have a valid NE header */
+
+ size = sizeof(NE_MODULE) +
+ /* loaded file info */
+ sizeof(LOADEDFILEINFO) + strlen(filename) +
+ /* segment table */
+ ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
+ /* resource table */
+ ne_header.rname_tab_offset - ne_header.resource_tab_offset +
+ /* resident names table */
+ ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
+ /* module ref table */
+ ne_header.n_mod_ref_tab * sizeof(WORD) +
+ /* imported names table */
+ ne_header.entry_tab_offset - ne_header.iname_tab_offset +
+ /* entry table length */
+ ne_header.entry_tab_length;
+
+ hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
+ if (!hModule) return 11; /* invalid exe */
+ FarSetOwner( hModule, hModule );
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ memcpy( pModule, &ne_header, sizeof(NE_MODULE) );
+ pData = (BYTE *)(pModule + 1);
+
+ /* Read the fast-load area */
+
+ if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
+ {
+ fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
+ fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
+ dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
+ fastload_offset, fastload_length );
+ if ((fastload = (char *)malloc( fastload_length )) != NULL)
+ {
+ lseek( fd, mz_header.ne_offset + fastload_offset, SEEK_SET );
+ if (read( fd, fastload, fastload_length ) != fastload_length)
+ {
+ free( fastload );
+ fastload = NULL;
+ }
+ }
+ }
+
+ /* Store the filename information */
+
+ pModule->fileinfo = (int)pData - (int)pModule;
+ ((LOADEDFILEINFO*)pData)->length = sizeof(LOADEDFILEINFO)+strlen(filename);
+ ((LOADEDFILEINFO*)pData)->fixed_media = TRUE;
+ ((LOADEDFILEINFO*)pData)->error = 0;
+ ((LOADEDFILEINFO*)pData)->date = 0;
+ ((LOADEDFILEINFO*)pData)->time = 0;
+ strcpy( ((LOADEDFILEINFO*)pData)->filename, filename );
+ pData += ((LOADEDFILEINFO*)pData)->length--;
+
+ /* Get the segment table */
+
+ pModule->seg_table = (int)pData - (int)pModule;
+ buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
+ if (buffer)
+ {
+ int i;
+ struct ne_segment_table_entry_s *pSeg;
+
+ if (!READ( ne_header.segment_tab_offset,
+ ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
+ buffer )) return 11; /* invalid exe */
+ pSeg = (struct ne_segment_table_entry_s *)buffer;
+ for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
+ {
+ memcpy( pData, pSeg, sizeof(*pSeg) );
+ pData += sizeof(SEGTABLEENTRY);
+ }
+ free( buffer );
+ }
+ else return 11; /* invalid exe */
+
+ /* Get the resource table */
+
+ if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
+ {
+ pModule->res_table = (int)pData - (int)pModule;
+ if (!READ(ne_header.resource_tab_offset,
+ ne_header.rname_tab_offset - ne_header.resource_tab_offset,
+ pData )) return 11; /* invalid exe */
+ pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
+ }
+ else pModule->res_table = 0; /* No resource table */
+
+ /* Get the resident names table */
+
+ pModule->name_table = (int)pData - (int)pModule;
+ if (!READ( ne_header.rname_tab_offset,
+ ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
+ pData )) return 11; /* invalid exe */
+ pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
+
+ /* Get the module references table */
+
+ if (ne_header.n_mod_ref_tab > 0)
+ {
+ pModule->modref_table = (int)pData - (int)pModule;
+ if (!READ( ne_header.moduleref_tab_offset,
+ ne_header.n_mod_ref_tab * sizeof(WORD),
+ pData )) return 11; /* invalid exe */
+ pData += ne_header.n_mod_ref_tab * sizeof(WORD);
+ }
+ else pModule->modref_table = 0; /* No module references */
+
+ /* Get the imported names table */
+
+ pModule->import_table = (int)pData - (int)pModule;
+ if (!READ( ne_header.iname_tab_offset,
+ ne_header.entry_tab_offset - ne_header.iname_tab_offset,
+ pData )) return 11; /* invalid exe */
+ pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
+
+ /* Get the entry table */
+
+ pModule->entry_table = (int)pData - (int)pModule;
+ if (!READ( ne_header.entry_tab_offset,
+ ne_header.entry_tab_length,
+ pData )) return 11; /* invalid exe */
+ pData += ne_header.entry_tab_length;
+
+ /* Get the non-resident names table */
+
+ if (ne_header.nrname_tab_length)
+ {
+ pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
+ hModule, FALSE, FALSE, FALSE );
+ if (!pModule->nrname_handle) return 11; /* invalid exe */
+ buffer = GlobalLock( pModule->nrname_handle );
+ lseek( fd, ne_header.nrname_tab_offset, SEEK_SET );
+ if (read( fd, buffer, ne_header.nrname_tab_length )
+ != ne_header.nrname_tab_length) return 11; /* invalid exe */
+ }
+ else pModule->nrname_handle = 0;
+
+ if (debugging_module) MODULE_PrintModule( hModule );
+ pModule->next = hFirstModule;
+ hFirstModule = hModule;
+ return hModule;
+}
+
+
+/***********************************************************************
+ * MODULE_GetOrdinal
+ *
+ * Lookup the ordinal for a given name.
+ */
+WORD MODULE_GetOrdinal( HMODULE hModule, char *name )
+{
+ char buffer[256], *cpnt;
+ BYTE len;
+ NE_MODULE *pModule;
+
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+
+ dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
+ hModule, name );
+
+ /* First handle names of the form '#xxxx' */
+
+ if (name[0] == '#') return atoi( name + 1 );
+
+ /* Now copy and uppercase the string */
+
+ strcpy( buffer, name );
+ AnsiUpper( buffer );
+ len = strlen( buffer );
+
+ /* First search the resident names */
+
+ cpnt = (char *)pModule + pModule->name_table;
+
+ /* Skip the first entry (module name) */
+ cpnt += *cpnt + 1 + sizeof(WORD);
+ while (*cpnt)
+ {
+ dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
+ if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
+ {
+ dprintf_module( stddeb, " Found: ordinal=%d\n",
+ *(WORD *)(cpnt + *cpnt + 1) );
+ return *(WORD *)(cpnt + *cpnt + 1);
+ }
+ cpnt += *cpnt + 1 + sizeof(WORD);
+ }
+
+ /* Now search the non-resident names table */
+
+ if (!pModule->nrname_handle) return 0; /* No non-resident table */
+ cpnt = (char *)GlobalLock( pModule->nrname_handle );
+
+ /* Skip the first entry (module description string) */
+ cpnt += *cpnt + 1 + sizeof(WORD);
+ while (*cpnt)
+ {
+ dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
+ if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
+ {
+ dprintf_module( stddeb, " Found: ordinal=%d\n",
+ *(WORD *)(cpnt + *cpnt + 1) );
+ return *(WORD *)(cpnt + *cpnt + 1);
+ }
+ cpnt += *cpnt + 1 + sizeof(WORD);
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * MODULE_GetEntryPoint
+ *
+ * Return the entry point for a given ordinal.
+ */
+DWORD MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
+{
+ NE_MODULE *pModule;
+ WORD curOrdinal = 1;
+ BYTE *p;
+ WORD sel, offset;
+
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+
+ dprintf_module( stddeb, "MODULE_GetEntryPoint(%04x,%d)\n",
+ hModule, ordinal );
+ p = (BYTE *)pModule + pModule->entry_table;
+ while (*p && (curOrdinal + *p <= ordinal))
+ {
+ /* Skipping this bundle */
+ curOrdinal += *p;
+ switch(p[1])
+ {
+ case 0: p += 2; break; /* unused */
+ case 0xff: p += 2 + *p * 6; break; /* moveable */
+ default: p += 2 + *p * 3; break; /* fixed */
+ }
+ }
+ if (!*p)
+ {
+ dprintf_module( stddeb, " Not found (last=%d)\n", curOrdinal-1 );
+ return 0;
+ }
+
+ switch(p[1])
+ {
+ case 0: /* unused */
+ dprintf_module( stddeb, " Found, but entry is unused\n" );
+ return 0;
+ case 0xff: /* moveable */
+ p += 2 + 6 * (ordinal - curOrdinal);
+ sel = p[3];
+ offset = *(WORD *)(p + 4);
+ break;
+ default: /* fixed */
+ sel = p[1];
+ p += 2 + 3 * (ordinal - curOrdinal);
+ offset = *(WORD *)(p + 1);
+ break;
+ }
+
+ dprintf_module( stddeb, " Found, logical addr = %04x:%04x\n",
+ sel, offset );
+ if (sel == 0xfe) sel = 0xffff; /* constant entry */
+ else sel = NE_SEG_TABLE(pModule)[sel-1].selector;
+ return MAKELONG( offset, sel );
+}
+
+
+/***********************************************************************
+ * MODULE_GetModuleName
+ */
+LPSTR MODULE_GetModuleName( HMODULE hModule )
+{
+ NE_MODULE *pModule;
+ BYTE *p, len;
+ static char buffer[10];
+
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL;
+ p = (BYTE *)pModule + pModule->name_table;
+ len = min( *p, 8 );
+ memcpy( buffer, p + 1, len );
+ buffer[len] = '\0';
+ return buffer;
+}
+
+
+/**********************************************************************
+ * LoadModule (KERNEL.45)
+ */
+HINSTANCE MODULE_LoadModule( LPCSTR name, LPVOID paramBlock )
+{
+}
+
+
+/**********************************************************************
+ * GetModuleHandle (KERNEL.47)
+ */
+HMODULE GetModuleHandle( LPCSTR name )
+{
+ char buffer[16];
+ BYTE len;
+ HMODULE hModule;
+
+ strncpy( buffer, name, 15 );
+ buffer[15] = '\0';
+ len = strlen(buffer);
+ AnsiUpper( buffer );
+
+ hModule = hFirstModule;
+ while( hModule )
+ {
+ NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
+ char *pname = (char *)pModule + pModule->name_table;
+ if (((BYTE)*pname == len) && !memcmp( pname+1, buffer, len )) break;
+ hModule = pModule->next;
+ }
+ dprintf_module( stddeb, "GetModuleHandle('%s'): returning %04x\n",
+ name, hModule );
+ return hModule;
+}
+
+
+/**********************************************************************
+ * GetModuleUsage (KERNEL.48)
+ */
+int GetModuleUsage( HANDLE hModule )
+{
+ NE_MODULE *pModule;
+
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+ dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
+ hModule, pModule->count );
+ return pModule->count;
+}
+
+
+/**********************************************************************
+ * GetModuleFileName (KERNEL.49)
+ */
+int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
+{
+ NE_MODULE *pModule;
+ char *name;
+
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+ name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
+ strncpy( lpFileName, name, nSize );
+ lpFileName[nSize-1] = '\0';
+ return strlen(lpFileName);
+}
+
+
+/**********************************************************************
+ * ModuleFirst (TOOLHELP.59)
+ */
+BOOL ModuleFirst( MODULEENTRY *lpme )
+{
+ lpme->wNext = hFirstModule;
+ return ModuleNext( lpme );
+}
+
+
+/**********************************************************************
+ * ModuleNext (TOOLHELP.60)
+ */
+BOOL ModuleNext( MODULEENTRY *lpme )
+{
+ NE_MODULE *pModule;
+
+ if (!lpme->wNext) return FALSE;
+ if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE;
+ strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
+ MAX_MODULE_NAME );
+ lpme->szModule[MAX_MODULE_NAME] = '\0';
+ lpme->hModule = lpme->wNext;
+ lpme->wcUsage = pModule->count;
+ strncpy( lpme->szExePath,
+ ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename,
+ MAX_PATH );
+ lpme->szExePath[MAX_PATH] = '\0';
+ lpme->wNext = pModule->next;
+ return TRUE;
+}
+
+
+/**********************************************************************
+ * ModuleFindName (TOOLHELP.61)
+ */
+BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
+{
+ lpme->wNext = GetModuleHandle( name );
+ return ModuleNext( lpme );
+}
+
+
+/**********************************************************************
+ * ModuleFindHandle (TOOLHELP.62)
+ */
+BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
+{
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ lpme->wNext = hModule;
+ return ModuleNext( lpme );
+}
diff --git a/loader/ne_image.c b/loader/ne_image.c
index d0bd137..92e37f5 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -1,7 +1,10 @@
/*
-static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
-*/
+ * NE modules
+ *
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
@@ -21,109 +24,61 @@
#include "callback.h"
#include "ne_image.h"
#include "prototypes.h"
+#include "module.h"
+#include "stackframe.h"
#include "stddebug.h"
#include "debug.h"
-extern unsigned short WIN_StackSize;
-extern unsigned short WIN_HeapSize;
-void FixupFunctionPrologs(struct w_files *);
-
-/**********************************************************************
- * GetImportedName
+/***********************************************************************
+ * NE_LoadSegment
*/
-static
-char *NE_GetImportedName(struct w_files *wpnt, int name_offset, char *buffer)
+static BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
{
- BYTE length;
+ NE_MODULE *pModule;
+ SEGTABLEENTRY *pSegTable, *pSeg;
+ WORD *pModuleTable;
+ WORD count, i, module, offset;
+ DWORD address;
+ int fd;
+ struct relocation_entry_s *rep, *reloc_entries;
+ char *dll_name, *func_name;
- lseek(wpnt->fd, wpnt->mz_header->ne_offset +
- wpnt->ne->ne_header->iname_tab_offset + name_offset, SEEK_SET);
- read(wpnt->fd, &length, 1); /* Get the length byte */
- read(wpnt->fd, buffer, length);
- buffer[length] = 0;
-
- return buffer;
-}
-
-struct w_files *current_exe;
-WORD current_nodata=0xfd00;
-/**********************************************************************
- * GetModuleName
- */
-static char *NE_GetModuleName(struct w_files *wpnt, int index, char *buffer)
-{
- BYTE length;
- WORD name_offset;
- int i;
-
- lseek(wpnt->fd, wpnt->mz_header->ne_offset +
- wpnt->ne->ne_header->moduleref_tab_offset + 2 * (index - 1), SEEK_SET);
- read(wpnt->fd, &name_offset, 2);
- name_offset = CONV_SHORT (name_offset);
-
- lseek(wpnt->fd, wpnt->mz_header->ne_offset +
- wpnt->ne->ne_header->iname_tab_offset + name_offset, SEEK_SET);
- read(wpnt->fd, &length, 1); /* Get the length byte */
- read(wpnt->fd, buffer, length);
- buffer[length] = 0;
-
- /* Module names are always upper case */
- for(i=0; i<length; i++)
- if (islower(buffer[i]))
- buffer[i] = toupper(buffer[i]);
-
- return buffer;
-}
-
-#ifndef WINELIB
-/**********************************************************************
- * NE_FixupSegment
- */
-int NE_FixupSegment(struct w_files *wpnt, int segment_num)
-{
- WORD *selector_table = wpnt->ne->selector_table;
- WORD selector, sel, offset;
- struct relocation_entry_s *rep, *rep1;
- struct ne_segment_table_entry_s *seg;
- int status, ordinal, i, n_entries, additive;
+ char buffer[100], buffer2[100];
+ int ordinal, additive;
unsigned short *sp;
- unsigned int address;
- unsigned char dll_name[257], func_name[257];
- seg = &wpnt->ne->seg_table[segment_num];
- sel = selector_table[segment_num];
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
+ pSegTable = NE_SEG_TABLE( pModule );
+ pSeg = pSegTable + segnum - 1;
+ pModuleTable = NE_MODULE_TABLE( pModule );
+ if (!pSeg->filepos) return TRUE; /* No file image, just return */
- dprintf_fixup(stddeb, "Segment fixups for %s, segment %d, selector %04x\n",
- wpnt->name, segment_num, sel );
+ fd = MODULE_OpenFile( hModule );
+ dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
+ segnum, pSeg->selector );
+ lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
+ read( fd, GlobalLock( pSeg->selector ), pSeg->size ? pSeg->size : 0x10000);
- if ((seg->seg_data_offset == 0) ||
- !(seg->seg_flags & NE_SEGFLAGS_RELOC_DATA))
- return 0;
+ if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
+ return TRUE; /* No relocation data, we are done */
+
+ read( fd, &count, sizeof(count) );
+ if (!count) return TRUE;
+
+ reloc_entries = (struct relocation_entry_s *)malloc(count * sizeof(struct relocation_entry_s));
+ if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
+ count * sizeof(struct relocation_entry_s))
+ {
+ dprintf_fixup( stddeb, "Unable to read relocation information\n" );
+ return FALSE;
+ }
/*
* Go through the relocation table on entry at a time.
*/
- i = seg->seg_data_length;
- if (i == 0)
- i = 0x10000;
-
- status = lseek(wpnt->fd, seg->seg_data_offset *
- (1 << wpnt->ne->ne_header->align_shift_count) + i, SEEK_SET);
- n_entries = 0;
- read(wpnt->fd, &n_entries, sizeof(short int));
- rep = (struct relocation_entry_s *)
- malloc(n_entries * sizeof(struct relocation_entry_s));
-
- if (read(wpnt->fd, rep, n_entries * sizeof(struct relocation_entry_s)) !=
- n_entries * sizeof(struct relocation_entry_s))
- {
- myerror("Unable to read relocation information");
- }
-
- rep1 = rep;
-
- for (i = 0; i < n_entries; i++, rep++)
+ rep = reloc_entries;
+ for (i = 0; i < count; i++, rep++)
{
/*
* Get the target address corresponding to this entry.
@@ -137,70 +92,57 @@
switch (rep->relocation_type)
{
case NE_RELTYPE_ORDINAL:
- if (NE_GetModuleName(wpnt, rep->target1,
- dll_name) == NULL)
- {
- fprintf(stderr, "NE_RELTYPE_ORDINAL failed");
- return -1;
- }
-
- ordinal = rep->target2;
+ module = pModuleTable[rep->target1-1];
+ dll_name = (char *)pModule + pModule->import_table + module;
+ memcpy( buffer, dll_name+1, *dll_name );
+ buffer[*dll_name] = '\0';
+ dll_name = buffer;
+ module = GetModuleHandle( dll_name );
- status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
- &offset);
- if (status)
- {
- char s[80];
-
- sprintf(s, "Bad DLL name '%s.%d'", dll_name, ordinal);
- myerror(s);
- return -1;
- }
+ ordinal = rep->target2;
+ address = MODULE_GetEntryPoint( module, ordinal );
+ if (!address) fprintf( stderr, "Warning: no handler for %s.%d, setting to 0:0\n",
+ dll_name, ordinal );
dprintf_fixup(stddeb,"%d: %s.%d: %04x:%04x\n", i + 1,
- dll_name, ordinal, selector, offset);
+ dll_name, ordinal, HIWORD(address), LOWORD(address) );
break;
case NE_RELTYPE_NAME:
- if (NE_GetModuleName(wpnt, rep->target1, dll_name) == NULL) {
- fprintf(stderr,"NE_RELTYPE_NAME failed");
- return -1;
- }
+ module = pModuleTable[rep->target1-1];
+ dll_name = (char *)pModule + pModule->import_table + module;
+ memcpy( buffer, dll_name+1, *dll_name );
+ buffer[*dll_name] = '\0';
+ dll_name = buffer;
+ module = GetModuleHandle( dll_name );
- if (NE_GetImportedName(wpnt, rep->target2, func_name) == NULL) {
- fprintf(stderr,"NE_getimportedname failed");
- return -1;
- }
+ func_name = (char *)pModule + pModule->import_table + rep->target2;
+ memcpy( buffer2, func_name+1, *func_name );
+ buffer2[*func_name] = '\0';
+ func_name = buffer2;
+ ordinal = MODULE_GetOrdinal( module, func_name );
- status = GetEntryDLLName(dll_name, func_name, &selector,
- &offset);
- if (status)
- {
- char s[80];
-
- sprintf(s, "Bad DLL name '%s (%s)'", dll_name,func_name);
- myerror(s);
- return -1;
- }
- dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1,
- func_name, dll_name, ordinal, selector, offset);
+ address = MODULE_GetEntryPoint( module, ordinal );
+
+ if (!address) fprintf( stderr, "Warning: no handler for %s.%s, setting to 0:0\n",
+ dll_name, func_name );
+
+ dprintf_fixup(stddeb,"%d: %s.%s: %04x:%04x\n", i + 1,
+ dll_name, func_name, HIWORD(address), LOWORD(address) );
break;
case NE_RELTYPE_INTERNAL:
if (rep->target1 == 0x00ff)
{
- address = GetEntryPointFromOrdinal(wpnt, rep->target2);
- selector = (address >> 16) & 0xffff;
- offset = address & 0xffff;
+ address = MODULE_GetEntryPoint( hModule, rep->target2 );
}
else
{
- selector = selector_table[rep->target1-1];
- offset = rep->target2;
+ address = MAKELONG( rep->target2, pSegTable[rep->target1-1].selector );
}
dprintf_fixup(stddeb,"%d: %04x:%04x\n",
- i + 1, selector, offset);
+ i + 1, HIWORD(address), LOWORD(address) );
break;
case NE_RELTYPE_OSFIXUP:
@@ -227,46 +169,46 @@
rep->offset);
dprintf_fixup(stddeb,"TARGET %04x %04x\n",
rep->target1, rep->target2);
- free(rep1);
- return -1;
+ free(reloc_entries);
+ return FALSE;
}
/* I'm not sure why a DLL entry point fixup could be additive.
Old code used to ignore additive if the target is a built-in
DLL. This doesn't seem to work for __AHSHIFT */
+#if 0
if (additive && FindDLLTable(dll_name) != NULL)
dprintf_fixup(stddeb,"Additive for builtin???\n"
"%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, "
"TARGET %04x %04x\n",
i+1, rep->address_type, rep->relocation_type,
rep->offset, rep->target1, rep->target2);
-
- address = (unsigned int)offset;
+#endif
offset = rep->offset;
switch (rep->address_type)
{
case NE_RADDR_LOWBYTE:
do {
- sp = PTR_SEG_OFF_TO_LIN( sel, offset );
+ sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
- sel, offset, *sp, additive ? " additive":"");
+ pSeg->selector, offset, *sp, additive ? " additive":"");
offset = *sp;
if(additive)
- *(unsigned char*)sp = (unsigned char)(address & 0xFF);
- else
*(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
+ else
+ *(unsigned char*)sp = (unsigned char)(address & 0xFF);
}
while (offset != 0xffff && !additive);
break;
case NE_RADDR_OFFSET16:
do {
- sp = PTR_SEG_OFF_TO_LIN( sel, offset );
+ sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
- sel, offset, *sp, additive ? " additive" : "" );
+ pSeg->selector, offset, *sp, additive ? " additive" : "" );
offset = *sp;
- *sp = (unsigned short) address;
+ *sp = LOWORD(address);
if (additive) *sp += offset;
}
while (offset != 0xffff && !additive);
@@ -274,24 +216,24 @@
case NE_RADDR_POINTER32:
do {
- sp = PTR_SEG_OFF_TO_LIN( sel, offset );
+ sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
- sel, offset, *sp, additive ? " additive" : "" );
+ pSeg->selector, offset, *sp, additive ? " additive" : "" );
offset = *sp;
- *sp = (unsigned short) address;
+ *sp = LOWORD(address);
if (additive) *sp += offset;
- *(sp+1) = selector;
+ *(sp+1) = HIWORD(address);
}
while (offset != 0xffff && !additive);
break;
case NE_RADDR_SELECTOR:
do {
- sp = PTR_SEG_OFF_TO_LIN( sel, offset );
+ sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
- sel, offset, *sp, additive ? " additive" : "" );
+ pSeg->selector, offset, *sp, additive ? " additive" : "" );
offset = *sp;
- *sp = (unsigned short) selector;
+ *sp = HIWORD(address);
/* Borland creates additive records with offset zero. Strange, but OK */
if(additive && offset)
fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
@@ -306,15 +248,91 @@
rep->offset);
dprintf_fixup(stddeb,
"TARGET %04x %04x\n", rep->target1, rep->target2);
- free(rep1);
- return -1;
+ free(reloc_entries);
+ return FALSE;
}
}
- free(rep1);
- return 0;
+ free(reloc_entries);
+ return TRUE;
}
+
+/***********************************************************************
+ * NE_FixupPrologs
+ *
+ * Fixup the exported functions prologs.
+ */
+static void NE_FixupPrologs( HMODULE hModule )
+{
+ NE_MODULE *pModule;
+ SEGTABLEENTRY *pSegTable;
+ WORD dgroup = 0;
+ WORD sel;
+ BYTE *p, *fixup_ptr, count;
+
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ pSegTable = NE_SEG_TABLE(pModule);
+ if (pModule->flags & NE_FFLAGS_SINGLEDATA)
+ dgroup = pSegTable[pModule->dgroup-1].selector;
+
+ dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule );
+ p = (BYTE *)pModule + pModule->entry_table;
+ while (*p)
+ {
+ if (p[1] == 0) /* Unused entry */
+ {
+ p += 2; /* Skip it */
+ continue;
+ }
+ if (p[1] == 0xfe) /* Constant entry */
+ {
+ p += 2 + *p * 3; /* Skip it */
+ continue;
+ }
+
+ /* Now fixup the entries of this bundle */
+ count = *p;
+ sel = p[1];
+ p += 2;
+ while (count-- > 0)
+ {
+ dprintf_module( stddeb,"Flags: %04x ", *p );
+ /* FIXME: Does anyone know the exact meaning of these flags? */
+ /* 0x0001 seems to mean: Fix up the function prolog */
+ if (*p & 0x0001)
+ {
+ if (sel == 0xff) /* moveable */
+ fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
+ else /* fixed */
+ fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
+ dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
+ fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
+ pModule->flags );
+ /* Verify the signature */
+ if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
+ || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
+ && fixup_ptr[2] == 0x90)
+ {
+ if (pModule->flags & NE_FFLAGS_SINGLEDATA)
+ {
+ *fixup_ptr = 0xb8; /* MOV AX, */
+ *(WORD *)(fixup_ptr+1) = dgroup;
+ }
+ else
+ {
+ fixup_ptr[0] = 0x90; /* non-library: NOPs */
+ fixup_ptr[1] = 0x90;
+ fixup_ptr[2] = 0x90;
+ }
+ }
+ }
+ p += (sel == 0xff) ? 6 : 3;
+ }
+ }
+}
+
+
int NE_unloadImage(struct w_files *wpnt)
{
dprintf_fixup(stdnimp, "NEunloadImage() called!\n");
@@ -322,88 +340,59 @@
return 1;
}
-int NE_StartProgram(struct w_files *wpnt)
-{
- extern WORD PSPSelector;
- int cs_reg, ds_reg, ip_reg;
+BOOL NE_InitDLL( HMODULE hModule )
+{
+ int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
+ NE_MODULE *pModule;
+ SEGTABLEENTRY *pSegTable;
/* Registers at initialization must be:
- * ax zero
- * bx stack size in bytes
- * cx heap size in bytes
- * si previous app instance
- * di current app instance
- * bp zero
- * es selector to the PSP
- * ds dgroup of the application
- * ss stack selector
- * sp top of the stack
+ * cx heap size
+ * di library instance
+ * ds data segment if any
+ * es:si command line (always 0)
*/
- /*
- * Fixup stack and jump to start.
- */
- WIN_StackSize = wpnt->ne->ne_header->stack_length;
- WIN_HeapSize = wpnt->ne->ne_header->local_heap_length;
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ pSegTable = NE_SEG_TABLE( pModule );
- cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
- ip_reg = wpnt->ne->ne_header->ip;
- ds_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->auto_data_seg-1];
+ if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/
+ if (!pModule->cs) return TRUE; /* no initialization code */
- IF1632_Saved16_ss = wpnt->ne->selector_table[wpnt->ne->ne_header->ss-1];
- IF1632_Saved16_sp = wpnt->ne->ne_header->sp;
- IF1632_Saved16_bp = 0;
+ if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
+ {
+ if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
+ {
+ /* Not SINGLEDATA */
+ fprintf(stderr, "Library is not marked SINGLEDATA\n");
+ exit(1);
+ }
+ else /* DATA NONE DLL */
+ {
+ ds_reg = 0;
+ cx_reg = 0;
+ }
+ }
+ else /* DATA SINGLE DLL */
+ {
+ ds_reg = pSegTable[pModule->dgroup-1].selector;
+ cx_reg = pModule->heap_size;
+ }
+
+ cs_reg = pSegTable[pModule->cs-1].selector;
+ ip_reg = pModule->ip;
+ di_reg = ds_reg ? ds_reg : hModule;
+ bp_reg = IF1632_Saved16_sp + (&((STACK16FRAME*)1)->bp - 1);
+
+ pModule->cs = 0; /* Don't initialize it twice */
+ dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
+ cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
- PSPSelector /*es*/, 0 /*ax*/, WIN_StackSize /*bx*/,
- WIN_HeapSize, 0 /*dx*/, 0 /*si*/, ds_reg /*di*/ );
+ 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
+ cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
}
-void NE_InitDLL(struct w_files *wpnt)
-{
- int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, rv;
- extern struct w_files *current_exe;
- /*
- * Is this a library?
- */
- if (wpnt->ne->ne_header->format_flags & 0x8000)
- {
- if (!(wpnt->ne->ne_header->format_flags & 0x0001))
- if(wpnt->ne->ne_header->format_flags & NE_FFLAGS_MULTIPLEDATA
- || wpnt->ne->ne_header->auto_data_seg)
- {
- /* Not SINGLEDATA */
- fprintf(stderr, "Library is not marked SINGLEDATA\n");
- exit(1);
- } else { /* DATA NONE DLL */
- ds_reg = current_exe->ne->selector_table[
- current_exe->ne->ne_header->auto_data_seg-1];
- cx_reg = 0;
- } else { /* DATA SINGLE DLL */
- ds_reg = wpnt->ne->selector_table[wpnt->ne->
- ne_header->auto_data_seg-1];
- cx_reg = wpnt->ne->ne_header->local_heap_length;
- }
-
- dprintf_dll(stddeb,"InitDLL: ne_header->cs = %04x\n",wpnt->ne->ne_header->cs);
- if (!wpnt->ne->ne_header->cs) cs_reg = 0;
- else cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
- ip_reg = wpnt->ne->ne_header->ip;
-
- di_reg = wpnt->hinstance;
-
- if (cs_reg) {
- dprintf_dll(stddeb,"Initializing %s, cs:ip %04x:%04x, ds %04x, cx %04x\n",
- wpnt->name, cs_reg, ip_reg, ds_reg, cx_reg);
-
- rv = CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
- 0 /*es*/, 0 /*ax*/, 0 /*bx*/, cx_reg,
- 0 /*dx*/, 0 /*si*/, di_reg );
- dprintf_exec(stddeb,"rv = %x\n", rv);
- } else
- dprintf_exec(stddeb,"%s skipped\n", wpnt->name);
- }
-}
/**********************************************************************
* NE_LoadImage
@@ -411,94 +400,86 @@
*/
HINSTANCE NE_LoadImage(struct w_files *wpnt)
{
+ NE_MODULE *pModule;
+ SEGTABLEENTRY *pSegTable;
+ WORD *pModRef;
unsigned int read_size, status, segment;
int i;
+ char cmdLine[256];
+ extern int Argc;
+ extern char **Argv;
wpnt->ne = malloc(sizeof(struct ne_data));
- wpnt->ne->resnamtab = NULL;
wpnt->ne->ne_header = malloc(sizeof(struct ne_header_s));
lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
if (read(wpnt->fd, wpnt->ne->ne_header, sizeof(struct ne_header_s))
!= sizeof(struct ne_header_s))
myerror("Unable to read NE header from file");
- if(!(wpnt->ne->ne_header->format_flags & NE_FFLAGS_LIBMODULE)){
- if(current_exe)printf("Warning: more than one EXE\n");
- current_exe=wpnt;
- }
+ wpnt->hModule = MODULE_LoadExeHeader( wpnt->fd, wpnt->filename );
+ pModule = (NE_MODULE *)GlobalLock( wpnt->hModule );
+ pSegTable = NE_SEG_TABLE(pModule);
+
+ /* Create the module segments */
+
+ MODULE_CreateSegments( wpnt->hModule );
#ifndef WINELIB
/*
* Create segment selectors.
*/
- status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
- wpnt->ne->ne_header->segment_tab_offset,
- SEEK_SET);
- read_size = wpnt->ne->ne_header->n_segment_tab *
- sizeof(struct ne_segment_table_entry_s);
- wpnt->ne->seg_table = (struct ne_segment_table_entry_s *) malloc(read_size);
- if (read(wpnt->fd, wpnt->ne->seg_table, read_size) != read_size)
- myerror("Unable to read segment table header from file");
- wpnt->ne->selector_table = CreateSelectors(wpnt);
- if(wpnt->ne->ne_header->auto_data_seg==0)
- {
- printf("DATA NONE DLL %s\n",wpnt->name);
- wpnt->hinstance=current_nodata++;
- } else
- wpnt->hinstance = (wpnt->ne->
- selector_table[wpnt->ne->ne_header->auto_data_seg-1]);
- if (wpnt->hinstance == 0)
- wpnt->hinstance = 0xf000;
+ CreateSelectors();
+
+ if (pModule->dgroup)
+ wpnt->hinstance = NE_SEG_TABLE(pModule)[pModule->dgroup-1].selector;
+ else
+ wpnt->hinstance = wpnt->hModule;
#endif
- /* Get the lookup table. This is used for looking up the addresses
- of functions that are exported */
- read_size = wpnt->ne->ne_header->entry_tab_length;
- wpnt->ne->lookup_table = (char *) malloc(read_size);
- lseek(wpnt->fd, wpnt->mz_header->ne_offset +
- wpnt->ne->ne_header->entry_tab_offset, SEEK_SET);
- if (read(wpnt->fd, wpnt->ne->lookup_table, read_size) != read_size)
- myerror("Unable to read lookup table header from file");
+ /* Create a task for this module */
- /* Get the iname table. This is used for looking up the names
- of functions that are exported */
-
- status = lseek(wpnt->fd, wpnt->ne->ne_header->nrname_tab_offset, SEEK_SET);
- read_size = wpnt->ne->ne_header->nrname_tab_length;
- wpnt->ne->nrname_table = (char *) malloc(read_size);
- if (read(wpnt->fd, wpnt->ne->nrname_table, read_size) != read_size)
- myerror("Unable to read nrname table header from file");
-
- status = lseek(wpnt->fd, wpnt->mz_header->ne_offset +
- wpnt->ne->ne_header->rname_tab_offset, SEEK_SET);
- read_size = wpnt->ne->ne_header->moduleref_tab_offset -
- wpnt->ne->ne_header->rname_tab_offset;
- wpnt->ne->rname_table = (char *) malloc(read_size);
- if (read(wpnt->fd, wpnt->ne->rname_table, read_size) != read_size)
- myerror("Unable to read rname table header from file");
+ cmdLine[0] = '\0';
+ for (i = 1; i < Argc; i++)
+ {
+ strcat( cmdLine, Argv[i] );
+ strcat( cmdLine, " " );
+ }
+ if (!(pModule->flags & NE_FFLAGS_LIBMODULE))
+ TASK_CreateTask( wpnt->hModule, SELECTOROF( GetDOSEnvironment() ),
+ GetCurrentTask(), cmdLine );
/*
* Now load any DLLs that this module refers to.
*/
- for(i=0; i<wpnt->ne->ne_header->n_mod_ref_tab; i++)
+ pModRef = (WORD *)((char *)pModule + pModule->modref_table);
+ for (i = 0; i < pModule->modref_count; i++, pModRef++)
{
- char buff[14];
- NE_GetModuleName(wpnt, i + 1, buff);
-
- if (strcasecmp(buff, wpnt->name) != 0 )
- LoadImage(buff, DLL, 0);
+ char buffer[80];
+ char *pstr = (char *)pModule + pModule->import_table + *pModRef;
+ memcpy( buffer, pstr + 1, *pstr );
+ buffer[*pstr] = '\0';
+ dprintf_module( stddeb, "Loading '%s'\n", buffer );
+ LoadImage( buffer, DLL, 0 );
}
-#ifndef WINELIB
+
/* fixup references */
- for (segment = 0; segment < wpnt->ne->ne_header->n_segment_tab; segment++)
- if (NE_FixupSegment(wpnt, segment) < 0)
- myerror("fixup failed.");
+ for (i = 1; i <= pModule->seg_count; i++)
+ NE_LoadSegment( wpnt->hModule, i );
- FixupFunctionPrologs(wpnt);
+ NE_FixupPrologs( wpnt->hModule );
InitializeLoadedDLLs(wpnt);
-#endif
+
+
+ /* Initialize the local heap */
+
+ if (pModule->dgroup)
+ {
+ int start = pSegTable[pModule->dgroup-1].minsize;
+ if (pModule->ss == pModule->dgroup) start += pModule->stack_size;
+ LocalInit( pSegTable[pModule->dgroup-1].selector,
+ start, start + pModule->heap_size );
+ }
+
return(wpnt->hinstance);
}
-
-#endif /* !WINELIB */
diff --git a/loader/ne_resource.c b/loader/ne_resource.c
index 6114d95..e3e4428 100644
--- a/loader/ne_resource.c
+++ b/loader/ne_resource.c
@@ -1,7 +1,9 @@
/*
-static char RCSId[] = "$Id: ne_resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
-*/
+ *
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -10,375 +12,341 @@
#include <fcntl.h>
#include <unistd.h>
#include "windows.h"
-#include "ldt.h"
-#include "neexe.h"
-#include "peexe.h"
#include "arch.h"
-#include "dlls.h"
-#include "library.h"
+#include "dos_fs.h"
+#include "global.h"
+#include "ldt.h"
+#include "module.h"
+#include "neexe.h"
#include "resource.h"
#include "stddebug.h"
#include "debug.h"
-
-/**********************************************************************
- * NE_LoadNameTable
+
+typedef struct resource_typeinfo_s NE_TYPEINFO;
+typedef struct resource_nameinfo_s NE_NAMEINFO;
+
+
+/***********************************************************************
+ * NE_FindNameTableId
+ *
+ * Find the type and resource id from their names.
+ * Return value is MAKELONG( typeId, resId ), or 0 if not found.
*/
-static void NE_LoadNameTable(struct w_files *wpnt)
+static DWORD NE_FindNameTableId( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
{
- struct resource_typeinfo_s typeinfo;
- struct resource_nameinfo_s nameinfo;
- unsigned short size_shift;
- RESNAMTAB *top, *new;
- char read_buf[1024];
- char *p;
- int i;
- unsigned short len;
- off_t saved_pos;
-
- top = NULL;
- /*
- * Move to beginning of resource table.
- */
- lseek(wpnt->fd, wpnt->mz_header->ne_offset +
- wpnt->ne->ne_header->resource_tab_offset, SEEK_SET);
+ NE_MODULE *pModule;
+ NE_TYPEINFO *pTypeInfo;
+ NE_NAMEINFO *pNameInfo;
+ HGLOBAL handle;
+ WORD *p;
+ DWORD ret = 0;
+ int count;
- /*
- * Read block size.
- */
- if (read(wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift))
- return;
-
- size_shift = CONV_SHORT(size_shift);
-
- /*
- * Find resource.
- */
- typeinfo.type_id = 0xffff;
- while (typeinfo.type_id != 0)
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
+ for (; pTypeInfo->type_id != 0;
+ pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
+ pTypeInfo->count * sizeof(NE_NAMEINFO)))
{
- if (read(wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo))
- break;
+ if (pTypeInfo->type_id != 0x800f) continue;
+ pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
+ for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
+ {
+ dprintf_resource( stddeb, "NameTable entry: type=%04x id=%04x\n",
+ pTypeInfo->type_id, pNameInfo->id );
+ handle = LoadResource( hModule, (int)pNameInfo - (int)pModule );
+ for(p = (WORD*)LockResource(handle); *p; p = (WORD *)((char*)p+*p))
+ {
+ dprintf_resource( stddeb," type=%04x '%s' id=%04x '%s'\n",
+ p[1], (char *)(p+3), p[2],
+ (char *)(p+3)+strlen((char *)(p+3))+1 );
+ /* Check for correct type */
- if (typeinfo.type_id == 0)
- break;
+ if (p[1] & 0x8000)
+ {
+ if (!HIWORD(typeId)) continue;
+ if (strcasecmp( (char *)PTR_SEG_TO_LIN(typeId),
+ (char *)(p + 3) )) continue;
+ }
+ else if (HIWORD(typeId) || ((typeId & ~0x8000)!= p[1]))
+ continue;
- if (typeinfo.type_id == 0x800f)
- {
- for (i = 0; i < typeinfo.count; i++)
- {
- if (read(wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
- break;
-
- saved_pos = lseek(wpnt->fd, 0, SEEK_CUR);
- lseek(wpnt->fd, (long) nameinfo.offset << size_shift,
- SEEK_SET);
- read(wpnt->fd, &len, sizeof(len));
- while (len)
- {
- new = (RESNAMTAB *) GlobalLock(GlobalAlloc(GMEM_MOVEABLE,sizeof(*new)));
- new->next = top;
- top = new;
+ /* Now check for the id */
- read(wpnt->fd, &new->type_ord, 2);
- read(wpnt->fd, &new->id_ord, 2);
- read(wpnt->fd, read_buf, len - 6);
-
- p = read_buf + strlen(read_buf) + 1;
- strncpy(new->id, p, MAX_NAME_LENGTH);
- new->id[MAX_NAME_LENGTH - 1] = '\0';
+ if (p[2] & 0x8000)
+ {
+ if (!HIWORD(resId)) continue;
+ if (strcasecmp( (char *)PTR_SEG_TO_LIN(resId),
+ (char*)(p+3)+strlen((char*)(p+3))+1 )) continue;
+
+ }
+ else if (HIWORD(resId) || ((resId & ~0x8000) != p[2]))
+ continue;
- read(wpnt->fd, &len, sizeof(len));
- }
- lseek(wpnt->fd, saved_pos, SEEK_SET);
- }
- } else
- lseek(wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
- }
- wpnt->ne->resnamtab = top;
-}
+ /* If we get here, we've found the entry */
-static int type_match(int type_id1, int type_id2, int fd, off_t off)
-{
- off_t old_pos;
- unsigned char c;
- size_t nbytes;
- char name[256];
-
- if (type_id1 == -1)
- return 1;
- if ((type_id1 & 0xffff0000) == 0) {
- if ((type_id2 & 0x8000) == 0)
- return 0;
- return (type_id1 & 0x000f) == (type_id2 & 0x000f);
- }
- if ((type_id2 & 0x8000) != 0)
- return 0;
- dprintf_resource(stddeb, "type_compare: type_id2=%04X !\n", type_id2);
-
- old_pos = lseek(fd, 0, SEEK_CUR);
- lseek(fd, off + type_id2, SEEK_SET);
- read(fd, &c, 1);
- nbytes = CONV_CHAR_TO_LONG(c);
-
- dprintf_resource(stddeb, "type_compare: namesize=%d\n", nbytes);
- read(fd, name, nbytes);
- lseek(fd, old_pos, SEEK_SET);
- name[nbytes] = '\0';
- dprintf_resource(stddeb, "type_compare: name=`%s'\n", name);
- return strcasecmp((char *) type_id1, name) == 0;
-}
-
-/**********************************************************************
- * FindResourceByNumber
- */
-static int FindResourceByNumber(RESOURCE *r, int type_id, int resource_id)
-{
- struct resource_typeinfo_s typeinfo;
- struct resource_nameinfo_s nameinfo;
- unsigned short size_shift;
- int i;
- off_t rtoff;
-
- dprintf_resource(stddeb, "FindResourceByNumber: type_id =%x,m res_id = %x\n",
- type_id, resource_id);
-
- /* Move to beginning of resource table */
- rtoff = (r->wpnt->mz_header->ne_offset +
- r->wpnt->ne->ne_header->resource_tab_offset);
- lseek(r->wpnt->fd, rtoff, SEEK_SET);
-
- /* Read block size */
- if (read(r->wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
- printf("FindResourceByNumber (%d) bad block size !\n",(int) resource_id);
- return -1;
- }
- size_shift = CONV_SHORT(size_shift);
-
- /* Find resource */
- for (;;) {
- if (read(r->wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
- printf("FindResourceByNumber (%X) bad typeinfo size !\n", resource_id);
- return -1;
- }
- dprintf_resource(stddeb, "FindResourceByNumber type=%X count=%d ?=%ld searched=%08X\n",
- typeinfo.type_id, typeinfo.count, typeinfo.reserved, type_id);
- if (typeinfo.type_id == 0)
- break;
- if (type_match(type_id, typeinfo.type_id, r->wpnt->fd, rtoff)) {
-
- for (i = 0; i < typeinfo.count; i++) {
-#ifndef WINELIB
- if (read(r->wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
-#else
- if (!load_nameinfo(r->wpnt->fd, &nameinfo))
-#endif
- {
- printf("FindResourceByNumber (%X) bad nameinfo size !\n", resource_id);
- return -1;
- }
- dprintf_resource(stddeb, "FindResource: search type=%X id=%X // type=%X id=%X\n",
- type_id, resource_id, typeinfo.type_id, nameinfo.id);
- if (nameinfo.id == resource_id) {
- r->size = nameinfo.length << size_shift;
- r->offset = nameinfo.offset << size_shift;
- return size_shift;
- }
- }
- }
- else
- lseek(r->wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
+ dprintf_resource( stddeb, " Found!\n" );
+ ret = MAKELONG( p[1], p[2] );
+ break;
+ }
+ FreeResource( handle );
+ if (ret) return ret;
}
- return -1;
-}
-
-/**********************************************************************
- * FindResourceByName
- */
-static int FindResourceByName(RESOURCE *r, int type_id, char *resource_name)
-{
- struct resource_typeinfo_s typeinfo;
- struct resource_nameinfo_s nameinfo;
- unsigned short size_shift;
- off_t old_pos, new_pos;
- unsigned char nbytes;
- char name[256];
- int i;
- off_t rtoff;
-
- /* Check for loaded name table */
- if (r->wpnt->ne->resnamtab != NULL) {
- RESNAMTAB *e;
-
- for (e = r->wpnt->ne->resnamtab; e != NULL; e = e->next)
- if (e->type_ord == (type_id & 0x000f) &&
- strcasecmp(e->id, resource_name) == 0)
- {
- return FindResourceByNumber(r, type_id, e->id_ord);
- }
- return -1;
- }
-
- /* Move to beginning of resource table */
- rtoff = (r->wpnt->mz_header->ne_offset +
- r->wpnt->ne->ne_header->resource_tab_offset);
- lseek(r->wpnt->fd, rtoff, SEEK_SET);
-
- /* Read block size */
- if (read(r->wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift))
- {
- printf("FindResourceByName (%s) bad block size !\n", resource_name);
- return -1;
- }
- size_shift = CONV_SHORT (size_shift);
-
- /* Find resource */
- for (;;)
- {
- if (read(r->wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
- printf("FindResourceByName (%s) bad typeinfo size !\n", resource_name);
- return -1;
- }
- dprintf_resource(stddeb, "FindResourceByName typeinfo.type_id=%X count=%d type_id=%X\n",
- typeinfo.type_id, typeinfo.count, type_id);
- if (typeinfo.type_id == 0)
- break;
- if (type_match(type_id, typeinfo.type_id, r->wpnt->fd, rtoff))
- {
- for (i = 0; i < typeinfo.count; i++)
- {
-#ifndef WINELIB
- if (read(r->wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
-#else
- if (!load_nameinfo (r->wpnt->fd, &nameinfo))
-#endif
- {
- printf("FindResourceByName (%s) bad nameinfo size !\n", resource_name);
- return -1;
- }
-/*
- if ((nameinfo.id & 0x8000) != 0) continue;
-*/
- dprintf_resource(stddeb, "FindResourceByName // nameinfo.id=%04X !\n", nameinfo.id);
- old_pos = lseek(r->wpnt->fd, 0, SEEK_CUR);
- new_pos = rtoff + nameinfo.id;
- lseek(r->wpnt->fd, new_pos, SEEK_SET);
- read(r->wpnt->fd, &nbytes, 1);
- dprintf_resource(stddeb, "FindResourceByName // namesize=%d !\n", nbytes);
- nbytes = CONV_CHAR_TO_LONG (nbytes);
- read(r->wpnt->fd, name, nbytes);
- lseek(r->wpnt->fd, old_pos, SEEK_SET);
- name[nbytes] = '\0';
- dprintf_resource(stddeb, "FindResourceByName type_id=%X (%d of %d) name='%s' resource_name='%s'\n",
- typeinfo.type_id, i + 1, typeinfo.count,
- name, resource_name);
- if (strcasecmp(name, resource_name) == 0) {
- r->size = nameinfo.length << size_shift;
- r->offset = nameinfo.offset << size_shift;
- return size_shift;
- }
- }
- }
- else
- lseek(r->wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
- }
- return -1;
-}
-
-
-/**********************************************************************
- * GetRsrcCount [internal]
- */
-int GetRsrcCount(HINSTANCE hInst, int type_id)
-{
- struct w_files *wpnt;
- struct resource_typeinfo_s typeinfo;
- struct resource_nameinfo_s nameinfo;
- unsigned short size_shift;
- off_t rtoff;
-
- if (hInst == 0)
- return 0;
- dprintf_resource(stddeb, "GetRsrcCount hInst=%04X typename=%08X\n",
- hInst, type_id);
-
- if ((wpnt = GetFileInfo(hInst)) == NULL)
- return 0;
- /*
- * Move to beginning of resource table.
- */
- rtoff = (wpnt->mz_header->ne_offset +
- wpnt->ne->ne_header->resource_tab_offset);
- lseek(wpnt->fd, rtoff, SEEK_SET);
- /*
- * Read block size.
- */
- if (read(wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
- printf("GetRsrcCount // bad block size !\n");
- return -1;
- }
- size_shift = CONV_SHORT (size_shift);
- for (;;) {
- if (read(wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
- printf("GetRsrcCount // bad typeinfo size !\n");
- return 0;
- }
- dprintf_resource(stddeb, "GetRsrcCount // typeinfo.type_id=%X count=%d type_id=%X\n",
- typeinfo.type_id, typeinfo.count, type_id);
- if (typeinfo.type_id == 0)
- break;
- if (type_match(type_id, typeinfo.type_id, wpnt->fd, rtoff))
- return typeinfo.count;
- else
- lseek(wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
}
return 0;
}
-/**********************************************************************
- * NE_FindResource [KERNEL.60]
+
+/***********************************************************************
+ * NE_FindResourceFromType
+ *
+ * Find a resource once the type info structure has been found.
*/
-int NE_FindResource(HANDLE instance, SEGPTR resource_name, SEGPTR type_name,
- RESOURCE *r)
+static HRSRC NE_FindResourceFromType( NE_MODULE *pModule,
+ NE_TYPEINFO *pTypeInfo, SEGPTR resId )
{
- int type, x;
- char *type_name_ptr, *resource_name_ptr;
+ BYTE *p;
+ int count;
+ NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
- dprintf_resource(stddeb, "NE_FindResource hInst=%04X typename=%08lx resname=%08lx\n",
- instance, type_name, resource_name);
+ if (HIWORD(resId) != 0) /* Named resource */
+ {
+ char *str = (char *)PTR_SEG_TO_LIN( resId );
+ BYTE len = strlen( str );
+ for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
+ {
+ if (pNameInfo->id & 0x8000) continue;
+ p = (BYTE *)pModule + pModule->res_table + pNameInfo->id;
+ if ((*p == len) && !strncasecmp( p+1, str, len ))
+ return (int)pNameInfo - (int)pModule;
+ }
+ }
+ else /* Numeric resource id */
+ {
+ WORD id = LOWORD(resId) | 0x8000;
+ for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
+ if (pNameInfo->id == id) return (int)pNameInfo - (int)pModule;
+ }
+ return 0;
+}
- r->size = r->offset = 0;
- /* nametable loaded ? */
- if (r->wpnt->ne->resnamtab == NULL)
- NE_LoadNameTable(r->wpnt);
+/***********************************************************************
+ * NE_FindResource
+ */
+HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
+{
+ NE_MODULE *pModule;
+ NE_TYPEINFO *pTypeInfo;
+ HRSRC hRsrc;
- if (HIWORD(type_name) == 0)
- type = (int) type_name;
- else {
- type_name_ptr = PTR_SEG_TO_LIN( type_name );
- if (type_name_ptr[0] == '\0')
- type = -1;
- if (type_name_ptr[0] == '#')
- type = atoi(type_name_ptr + 1);
- else
- type = (int) type_name_ptr;
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ if (!pModule || !pModule->res_table) return 0;
+ pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
+
+ if (HIWORD(typeId) || HIWORD(resId))
+ {
+ /* Search the names in the nametable */
+ DWORD id = NE_FindNameTableId( hModule, typeId, resId );
+ if (id) /* found */
+ {
+ typeId = LOWORD(id);
+ resId = HIWORD(id);
+ }
}
- if (HIWORD(resource_name) == 0)
- x = FindResourceByNumber(r, type, LOWORD(resource_name) | 0x8000);
- else {
- resource_name_ptr = PTR_SEG_TO_LIN( resource_name );
- if (resource_name_ptr[0] == '\0')
- x = FindResourceByNumber(r, type, -1);
- if (resource_name_ptr[0] == '#')
- x = FindResourceByNumber(r, type, atoi(resource_name_ptr + 1));
- else
- x = FindResourceByName(r, type, resource_name_ptr);
+ if (HIWORD(typeId) != 0) /* Named type */
+ {
+ char *str = (char *)PTR_SEG_TO_LIN( typeId );
+ BYTE len = strlen( str );
+ while (pTypeInfo->type_id)
+ {
+ if (!(pTypeInfo->type_id & 0x8000))
+ {
+ BYTE *p = (BYTE*)pModule+pModule->res_table+pTypeInfo->type_id;
+ if ((*p == len) && !strncasecmp( p+1, str, len ))
+ {
+ dprintf_resource( stddeb, " Found type '%s'\n", str );
+ hRsrc = NE_FindResourceFromType(pModule, pTypeInfo, resId);
+ if (hRsrc)
+ {
+ dprintf_resource( stddeb, " Found id %08lx\n", resId );
+ return hRsrc;
+ }
+ dprintf_resource( stddeb, " Not found, going on\n" );
+ }
+ }
+ dprintf_resource( stddeb, " Skipping type %04x\n",
+ pTypeInfo->type_id );
+ pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
+ pTypeInfo->count * sizeof(NE_NAMEINFO));
+ }
}
- if (x == -1) {
- printf("NE_FindResource hInst=%04x typename=%p resname=%p not found!\n",
- instance, type_name_ptr, resource_name_ptr);
- return 0;
+ else /* Numeric type id */
+ {
+ WORD id = LOWORD(typeId) | 0x8000;
+ while (pTypeInfo->type_id)
+ {
+ if (pTypeInfo->type_id == id)
+ {
+ dprintf_resource( stddeb, " Found type %04x\n", id );
+ hRsrc = NE_FindResourceFromType( pModule, pTypeInfo, resId );
+ if (hRsrc)
+ {
+ dprintf_resource( stddeb, " Found id %08lx\n", resId );
+ return hRsrc;
+ }
+ dprintf_resource( stddeb, " Not found, going on\n" );
+ }
+ dprintf_resource( stddeb, " Skipping type %04x\n",
+ pTypeInfo->type_id );
+ pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
+ pTypeInfo->count * sizeof(NE_NAMEINFO));
+ }
}
- return 1;
+ fprintf( stderr, "FindResource(%04x,%08lx,%08lx): Not found.\n",
+ hModule, typeId, resId );
+ return 0;
+}
+
+
+
+/***********************************************************************
+ * NE_AllocResource
+ */
+HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size )
+{
+ NE_MODULE *pModule;
+ NE_NAMEINFO *pNameInfo;
+ WORD sizeShift;
+
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ if (!pModule || !pModule->res_table) return 0;
+ sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+ pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+ if (size < (DWORD)pNameInfo->length << sizeShift)
+ size = (DWORD)pNameInfo->length << sizeShift;
+ return GLOBAL_Alloc( GMEM_FIXED, size, hModule, FALSE, FALSE, FALSE );
+}
+
+
+/***********************************************************************
+ * NE_AccessResource
+ */
+int NE_AccessResource( HMODULE hModule, HRSRC hRsrc )
+{
+ NE_MODULE *pModule;
+ NE_NAMEINFO *pNameInfo;
+ WORD sizeShift;
+ char *name;
+ int fd;
+
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ if (!pModule || !pModule->res_table) return 0;
+ pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+
+ name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
+ fd = open( name, O_RDONLY );
+ sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+ lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
+ return fd;
+}
+
+
+/***********************************************************************
+ * NE_SizeofResource
+ */
+DWORD NE_SizeofResource( HMODULE hModule, HRSRC hRsrc )
+{
+ NE_MODULE *pModule;
+ NE_NAMEINFO *pNameInfo;
+ WORD sizeShift;
+
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ if (!pModule || !pModule->res_table) return 0;
+ sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+ pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+ return (DWORD)pNameInfo->length << sizeShift;
+}
+
+
+/***********************************************************************
+ * NE_LoadResource
+ */
+HGLOBAL NE_LoadResource( HMODULE hModule, HRSRC hRsrc )
+{
+ NE_MODULE *pModule;
+ NE_NAMEINFO *pNameInfo;
+ WORD sizeShift;
+ int fd;
+
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ if (!pModule || !pModule->res_table) return 0;
+ pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+ if (pNameInfo->handle)
+ {
+ pNameInfo->usage++;
+ dprintf_resource( stddeb, " Already loaded, new count=%d\n",
+ pNameInfo->usage );
+ return pNameInfo->handle;
+ }
+ sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+ dprintf_resource( stddeb, " Loading, pos=%d, len=%d\n",
+ (int)pNameInfo->offset << sizeShift,
+ (int)pNameInfo->length << sizeShift );
+ if ((fd = MODULE_OpenFile( hModule )) == -1) return 0;
+ pNameInfo->handle = NE_AllocResource( hModule, hRsrc, 0 );
+ pNameInfo->usage = 1;
+ lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
+ read( fd, GlobalLock( pNameInfo->handle ),
+ (int)pNameInfo->length << sizeShift );
+ return pNameInfo->handle;
+}
+
+
+/***********************************************************************
+ * NE_LockResource
+ */
+SEGPTR NE_LockResource( HMODULE hModule, HGLOBAL handle )
+{
+ /* May need to reload the resource if discarded */
+
+ return WIN16_GlobalLock( handle );
+}
+
+
+/***********************************************************************
+ * NE_FreeResource
+ */
+BOOL NE_FreeResource( HMODULE hModule, HGLOBAL handle )
+{
+ NE_MODULE *pModule;
+ NE_TYPEINFO *pTypeInfo;
+ NE_NAMEINFO *pNameInfo;
+ WORD count;
+
+ pModule = (NE_MODULE *)GlobalLock( hModule );
+ if (!pModule || !pModule->res_table) return FALSE;
+ pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
+ while (pTypeInfo->type_id)
+ {
+ pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
+ for (count = pTypeInfo->count; count > 0; count--)
+ {
+ if (pNameInfo->handle == handle)
+ {
+ if (pNameInfo->usage > 0) pNameInfo->usage--;
+ if (pNameInfo->usage == 0)
+ {
+ GlobalFree( pNameInfo->handle );
+ pNameInfo->handle = 0;
+ }
+ return TRUE;
+ }
+ pNameInfo++;
+ }
+ pTypeInfo = (NE_TYPEINFO *)pNameInfo;
+ }
+ fprintf( stderr, "FreeResource: %04x %04x not found!\n", hModule, handle );
+ return FALSE;
}
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 9caded6..9dcad50 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -198,12 +198,6 @@
return 1;
}
-int PE_StartProgram(struct w_files *wpnt)
-{
- printf("StartPEprogram() called!\n");
- return 0;
-}
-
void PE_InitDLL(struct w_files *wpnt)
{
/* Is this a library? */
diff --git a/loader/pe_resource.c b/loader/pe_resource.c
index 181b90b..0bfc987 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -24,6 +24,7 @@
/* #define DEBUG_RESOURCE */
#include "debug.h"
+#if 0
static int
find_lang(char *root, struct PE_Resource_Directory *resource, RESOURCE *r)
@@ -88,7 +89,7 @@
static int
find_type(struct PE_Resource_Directory *resource, LPSTR resource_name,
- LPSTR type_name, RESOURCE *r)
+ LPSTR type_name)
{
int i;
char *root, res_name[256];
@@ -146,5 +147,6 @@
else
type_name = (SEGPTR) type_name_ptr;
}
- return find_type(r->wpnt->pe->pe_resource, resource_name, type_name,r);
+ return find_type(r->wpnt->pe->pe_resource, resource_name, type_name);
}
+#endif
diff --git a/loader/resource.c b/loader/resource.c
index 0d1249b..cfc7dbd 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -1,7 +1,10 @@
/*
-static char RCSId[] = "$Id: resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
-*/
+ * Resources
+ *
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -15,233 +18,211 @@
#include "bitmap.h"
#include "neexe.h"
#include "icon.h"
-#include "menu.h"
#include "accel.h"
#include "dlls.h"
+#include "module.h"
#include "resource.h"
#include "library.h"
#include "stddebug.h"
#include "debug.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-RESOURCE *Top = NULL;
-
-extern int NE_FindResource(HANDLE, SEGPTR, SEGPTR, RESOURCE *);
-extern int PE_FindResource(HANDLE, SEGPTR, SEGPTR, RESOURCE *);
-
#define PrintId(name) \
- if (HIWORD((DWORD)name)) \
- printf(", '%s'", (char *)PTR_SEG_TO_LIN(name)); \
- else \
- printf(", #%d", LOWORD(name));
+ if (HIWORD((DWORD)name)) \
+ dprintf_resource( stddeb, "'%s'", (char *)PTR_SEG_TO_LIN(name)); \
+ else \
+ dprintf_resource( stddeb, "#%04x", LOWORD(name));
/**********************************************************************
- * FindResource [KERNEL.60]
+ * FindResource (KERNEL.60)
*/
-HANDLE FindResource(HANDLE instance, SEGPTR name, SEGPTR type)
+HRSRC FindResource( HMODULE hModule, SEGPTR name, SEGPTR type )
{
- int status;
- RESOURCE *r;
- HANDLE rh;
+ WORD *pModule;
- if(debugging_resource){
- printf("FindResource(%04X", instance);
- PrintId(name);
- PrintId(type);
- printf(")\n");
- }
-
- /* FIXME: did we already find this one ? */
-
- if ((rh = GlobalAlloc(GMEM_MOVEABLE, sizeof(RESOURCE))) == 0)
- return 0;
-
- r = (RESOURCE *)GlobalLock(rh);
- r->next = Top;
- Top = r;
- r->info_mem = rh;
- r->rsc_mem = 0;
- r->count = 0;
- if (HIWORD((DWORD)name))
- r->name = strdup(PTR_SEG_TO_LIN(name));
- else
- r->name = (LPSTR)name;
-
- if (HIWORD((DWORD)type))
- r->type = strdup(PTR_SEG_TO_LIN(type));
- else
- r->type = (LPSTR)type;
-
- r->wpnt = GetFileInfo(instance);
- r->fd = dup(r->wpnt->fd);
- if (r->wpnt->ne)
- status = NE_FindResource(instance, name, type, r);
- else
- status = PE_FindResource(instance, name, type, r);
-
- if (!status) {
- if (HIWORD((DWORD)r->name))
- free(r->name);
-
- if (HIWORD((DWORD)r->type))
- free(r->type);
- close(r->fd);
-
- Top = r->next;
- GlobalUnlock(rh);
- return 0;
- } else
- return rh;
-}
-
-/**********************************************************************
- * AllocResource [KERNEL.66]
- */
-HANDLE AllocResource(HANDLE instance, HANDLE hResInfo, DWORD dwSize)
-{
- RESOURCE *r;
- int image_size;
-
- dprintf_resource(stddeb, "AllocResource(%04X, %04X, %08X);\n",
- instance, hResInfo, (int) dwSize);
-
- if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
- return 0;
-
- image_size = r->size;
-
- if (dwSize == 0)
- r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, image_size);
- else
- r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, dwSize);
-
- GlobalUnlock(hResInfo);
-
- return r->rsc_mem;
-}
-
-/**********************************************************************
- * AccessResource [KERNEL.64]
- */
-int AccessResource(HANDLE instance, HANDLE hResInfo)
-{
- int fd;
- RESOURCE *r;
-
- dprintf_resource(stddeb, "AccessResource(%04X, %04X);\n",
- instance, hResInfo);
-
- if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
- return -1;
-
- fd = r->fd;
- lseek(fd, r->offset, SEEK_SET);
- GlobalUnlock(hResInfo);
-
- return fd;
-}
-
-/**********************************************************************
- * SizeofResource [KERNEL.65]
- */
-WORD SizeofResource(HANDLE instance, HANDLE hResInfo)
-{
- RESOURCE *r;
- int size;
-
- dprintf_resource(stddeb, "SizeofResource(%04X, %04X);\n",
- instance, hResInfo);
-
- if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
- return 0;
-
- size = r->size;
- GlobalUnlock(hResInfo);
-
- return size;
-}
-
-/**********************************************************************
- * LoadResource [KERNEL.61]
- */
-HANDLE LoadResource(HANDLE instance, HANDLE hResInfo)
-{
- RESOURCE *r;
- int image_size, fd;
- void *image;
- HANDLE h;
-
- dprintf_resource(stddeb, "LoadResource(%04X, %04X);\n", instance, hResInfo);
-
- if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
- return 0;
-
- h = r->rsc_mem = AllocResource(instance, hResInfo, 0);
- image = GlobalLock(h);
- image_size = r->size;
- fd = AccessResource(instance, hResInfo);
-
- if (image == NULL || read(fd, image, image_size) != image_size) {
- GlobalFree(h);
- GlobalUnlock(hResInfo);
- return 0;
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ dprintf_resource(stddeb, "FindResource: module=%04x type=", hModule );
+ PrintId( type );
+ dprintf_resource( stddeb, " name=" );
+ PrintId( name );
+ dprintf_resource( stddeb, "\n" );
+ if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+ switch(*pModule)
+ {
+ case NE_SIGNATURE:
+ return NE_FindResource( hModule, type, name );
+ case PE_SIGNATURE:
+ return 0;
+ default:
+ return 0;
}
- r->count++;
- close(fd);
- GlobalUnlock(h);
- GlobalUnlock(hResInfo);
- return h;
}
-/**********************************************************************
- * LockResource [KERNEL.62]
- */
-/* 16-bit version */
-SEGPTR WIN16_LockResource(HANDLE hResData)
+/**********************************************************************
+ * LoadResource (KERNEL.61)
+ */
+HGLOBAL LoadResource( HMODULE hModule, HRSRC hRsrc )
{
- return WIN16_GlobalLock(hResData);
+ WORD *pModule;
+
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n",
+ hModule, hRsrc );
+ if (!hRsrc) return 0;
+ if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+ switch(*pModule)
+ {
+ case NE_SIGNATURE:
+ return NE_LoadResource( hModule, hRsrc );
+ case PE_SIGNATURE:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+
+/**********************************************************************
+ * LockResource (KERNEL.62)
+ */
+/* 16-bit version */
+SEGPTR WIN16_LockResource( HGLOBAL handle )
+{
+ HMODULE hModule;
+ WORD *pModule;
+
+ dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
+ if (!handle) return (SEGPTR)0;
+ hModule = GetExePtr( handle );
+ if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+ switch(*pModule)
+ {
+ case NE_SIGNATURE:
+ return NE_LockResource( hModule, handle );
+ case PE_SIGNATURE:
+ return 0;
+ default:
+ return 0;
+ }
}
/* 32-bit version */
-LPSTR LockResource(HANDLE hResData)
+LPSTR LockResource( HGLOBAL handle )
{
- return GlobalLock(hResData);
+ HMODULE hModule;
+ WORD *pModule;
+
+ dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
+ if (!handle) return NULL;
+ hModule = GetExePtr( handle );
+ if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+ switch(*pModule)
+ {
+ case NE_SIGNATURE:
+ return (LPSTR)PTR_SEG_TO_LIN( NE_LockResource( hModule, handle ) );
+ case PE_SIGNATURE:
+ return 0;
+ default:
+ return 0;
+ }
}
+
/**********************************************************************
- * FreeResource [KERNEL.63]
+ * FreeResource (KERNEL.63)
*/
-HANDLE FreeResource(HANDLE hResData)
+BOOL FreeResource( HGLOBAL handle )
{
- RESOURCE *r, *rp;
+ HMODULE hModule;
+ WORD *pModule;
- dprintf_resource(stddeb, "FreeResource: handle %04x\n", hResData);
-
- for (r = rp = Top; r ; r = r->next) {
- if (r->rsc_mem == hResData) {
- if (r->count == 0) {
- if (rp != r)
- rp->next = r->next;
- else
- Top = r->next;
-
- if (HIWORD((DWORD)r->name))
- free(r->name);
- if (HIWORD((DWORD)r->type))
- free(r->type);
- GlobalFree(r->rsc_mem);
- GlobalFree(r->info_mem);
- return 0;
- } else
- r->count--;
- }
- rp = r;
+ dprintf_resource(stddeb, "FreeResource: handle=%04x\n", handle );
+ if (!handle) return FALSE;
+ hModule = GetExePtr( handle );
+ if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+ switch(*pModule)
+ {
+ case NE_SIGNATURE:
+ return NE_FreeResource( hModule, handle );
+ case PE_SIGNATURE:
+ return FALSE;
+ default:
+ return FALSE;
}
- return hResData;
}
-
+
+
+/**********************************************************************
+ * AccessResource (KERNEL.64)
+ */
+int AccessResource( HMODULE hModule, HRSRC hRsrc )
+{
+ WORD *pModule;
+
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
+ hModule, hRsrc );
+ if (!hRsrc) return 0;
+ if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+ switch(*pModule)
+ {
+ case NE_SIGNATURE:
+ return NE_AccessResource( hModule, hRsrc );
+ case PE_SIGNATURE:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+
+/**********************************************************************
+ * SizeofResource (KERNEL.65)
+ */
+DWORD SizeofResource( HMODULE hModule, HRSRC hRsrc )
+{
+ WORD *pModule;
+
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ dprintf_resource(stddeb, "SizeofResource: module=%04x res=%04x\n",
+ hModule, hRsrc );
+ if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+ switch(*pModule)
+ {
+ case NE_SIGNATURE:
+ return NE_SizeofResource( hModule, hRsrc );
+ case PE_SIGNATURE:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+
+/**********************************************************************
+ * AllocResource (KERNEL.66)
+ */
+HGLOBAL AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size )
+{
+ WORD *pModule;
+
+ hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
+ dprintf_resource(stddeb, "AllocResource: module=%04x res=%04x size=%ld\n",
+ hModule, hRsrc, size );
+ if (!hRsrc) return 0;
+ if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+ switch(*pModule)
+ {
+ case NE_SIGNATURE:
+ return NE_AllocResource( hModule, hRsrc, size );
+ case PE_SIGNATURE:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+
/**********************************************************************
* ConvertCoreBitmap
*/
@@ -306,35 +287,14 @@
bits, image, DIB_RGB_COLORS );
}
-/**********************************************************************
- * RSC_LoadResource
- */
-HANDLE
-RSC_LoadResource(int instance, SEGPTR rsc_name, SEGPTR type, int *image_size_ret)
-{
- HANDLE hResInfo;
- RESOURCE *r;
- dprintf_resource(stddeb, "RSC_LoadResource: instance = %04x, name = %08lx, type = %08lx\n",
- instance, rsc_name, type);
-
- if ((hResInfo = FindResource(instance, rsc_name, type)) == (HANDLE) NULL) {
- return (HANDLE)NULL;
- }
- r = (RESOURCE *)GlobalLock(hResInfo);
- if (image_size_ret)
- *image_size_ret = r->size;
- r->count++;
- GlobalUnlock(hResInfo);
- return LoadResource(instance, hResInfo);
-}
-
/**********************************************************************
* LoadIcon [USER.174]
*/
HICON LoadIcon( HANDLE instance, SEGPTR icon_name )
{
HICON hIcon;
+ HRSRC hRsrc;
HANDLE rsc_mem;
WORD *lp;
ICONDESCRIP *lpicodesc;
@@ -344,7 +304,9 @@
BITMAPINFOHEADER *bih;
RGBQUAD *rgbq;
HDC hdc;
- int image_size;
+ BITMAPINFO *pInfo;
+ char *bits;
+ int size;
if (HIWORD(icon_name))
dprintf_resource( stddeb, "LoadIcon: %04x '%s'\n",
@@ -359,85 +321,73 @@
return OBM_LoadIcon( LOWORD((int)icon_name) );
}
- if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
- rsc_mem = RSC_LoadResource(instance, icon_name,
- (SEGPTR) NE_RSCTYPE_GROUP_ICON, &image_size);
+ if (!(hRsrc = FindResource( instance, icon_name, RT_GROUP_ICON))) return 0;
+ rsc_mem = LoadResource( instance, hRsrc );
if (rsc_mem == (HANDLE)NULL) {
printf("LoadIcon / Icon %08x not Found !\n", (int) icon_name);
- ReleaseDC(GetDesktopWindow(), hdc);
return 0;
}
- lp = (WORD *)GlobalLock(rsc_mem);
- if (lp == NULL) {
- GlobalFree(rsc_mem);
- ReleaseDC(GetDesktopWindow(), hdc);
- return 0;
- }
+ lp = (WORD *)LockResource(rsc_mem);
lpicodesc = (ICONDESCRIP *)(lp + 3);
hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
if (hIcon == (HICON)NULL) {
- GlobalFree(rsc_mem);
- ReleaseDC(GetDesktopWindow(), hdc);
+ FreeResource( rsc_mem );
return 0;
}
lpico = (ICONALLOC *)GlobalLock(hIcon);
lpico->descriptor = *lpicodesc;
width = lpicodesc->Width;
height = lpicodesc->Height;
- GlobalUnlock(rsc_mem);
- GlobalFree(rsc_mem);
- rsc_mem = RSC_LoadResource( instance,
- MAKEINTRESOURCE(lpicodesc->icoDIBOffset),
- (SEGPTR) NE_RSCTYPE_ICON, &image_size );
- if (rsc_mem == (HANDLE)NULL) {
- printf("LoadIcon / Icon %08lx Bitmaps not Found !\n", icon_name );
- ReleaseDC(GetDesktopWindow(), hdc);
- return 0;
- }
- lp = (WORD *)GlobalLock(rsc_mem);
- if (lp == NULL) {
- GlobalFree(rsc_mem);
- ReleaseDC(GetDesktopWindow(), hdc);
- return 0;
- }
- bmi = (BITMAPINFO *)lp;
- bih = (BITMAPINFOHEADER *)lp;
- rgbq = &bmi->bmiColors[0];
- bih->biHeight = bih->biHeight / 2;
-/*
- printf("LoadIcon / image_size=%d width=%d height=%d bih->biBitCount=%d bih->biSizeImage=%ld\n",
- image_size, width, height, bih->biBitCount, bih->biSizeImage);
-*/
- if (bih->biSize == sizeof(BITMAPINFOHEADER))
- lpico->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)bih);
- else
- lpico->hBitmap = 0;
+ FreeResource( rsc_mem );
+ if (!(hRsrc = FindResource( instance,
+ MAKEINTRESOURCE(lpico->descriptor.icoDIBOffset),
+ RT_ICON ))) return 0;
+ if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
+
+ bmi = (BITMAPINFO *)LockResource(rsc_mem);
+ size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
+ pInfo = (BITMAPINFO *)malloc( size );
+ memcpy( pInfo, bmi, size );
+ bih = &pInfo->bmiHeader;
+ bih->biHeight /= 2;
+
+ if (!(hdc = GetDC( 0 ))) return 0;
+ if (bih->biSize != sizeof(BITMAPINFOHEADER)) return 0;
+ lpico->hBitmap = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
+ (char*)bmi + size, pInfo, DIB_RGB_COLORS );
+ if (bih->biSizeImage == 0)
+ {
+ if (bih->biCompression != BI_RGB)
+ {
+ fprintf(stderr,"Unknown size for compressed Icon bitmap.\n");
+ FreeResource( rsc_mem );
+ ReleaseDC( 0, hdc);
+ return 0;
+ }
+ bih->biSizeImage = DIB_GetImageWidthBytes(bih->biWidth,bih->biBitCount)
+ * bih->biHeight;
+ }
+ bits = (char *)bmi + size +
+ bih->biSizeImage * bih->biBitCount / (bih->biBitCount+1);
bih->biBitCount = 1;
- bih->biClrUsed = bih->biClrImportant = 2;
+ bih->biClrUsed = bih->biClrImportant = 2;
+ rgbq = &bmi->bmiColors[0];
rgbq[0].rgbBlue = rgbq[0].rgbGreen = rgbq[0].rgbRed = 0x00;
rgbq[1].rgbBlue = rgbq[1].rgbGreen = rgbq[1].rgbRed = 0xff;
rgbq[0].rgbReserved = rgbq[1].rgbReserved = 0;
- if (bih->biSizeImage == 0) {
- if (bih->biCompression != BI_RGB) {
- fprintf(stderr,"Unknown size for compressed Icon bitmap.\n");
- GlobalFree(rsc_mem);
- ReleaseDC(GetDesktopWindow(), hdc);
- return 0;
- }
- bih->biSizeImage = (bih->biWidth * bih->biHeight * bih->biBitCount
- + 7) / 8;
- }
- lpico->hBitMask = CreateDIBitmap(hdc, bih, CBM_INIT,
- (LPSTR)lp + bih->biSizeImage - sizeof(BITMAPINFOHEADER) / 2 - 4,
- (BITMAPINFO *)bih, DIB_RGB_COLORS );
- GlobalUnlock(rsc_mem);
- GlobalFree(rsc_mem);
- ReleaseDC(GetDesktopWindow(), hdc);
+ lpico->hBitMask = CreateDIBitmap(hdc, &pInfo->bmiHeader, CBM_INIT,
+/* (LPSTR)bmi + bih->biSizeImage - sizeof(BITMAPINFOHEADER) / 2 - 4,
+ (LPSTR)lp + bih->biSizeImage + bih->biSize + 4*lpicodesc->ColorCount, */
+ bits, pInfo, DIB_RGB_COLORS );
+ FreeResource( rsc_mem );
+ ReleaseDC( 0, hdc);
+ free( pInfo );
GlobalUnlock(hIcon);
dprintf_resource(stddeb,"LoadIcon Alloc hIcon=%X\n", hIcon);
return hIcon;
}
-
+
+
/**********************************************************************
* CreateIcon [USER.407]
*/
@@ -516,9 +466,10 @@
{
HANDLE hAccel;
HANDLE rsc_mem;
+ HRSRC hRsrc;
BYTE *lp;
ACCELHEADER *lpAccelTbl;
- int i, image_size, n;
+ int i, n;
if (HIWORD(lpTableName))
dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
@@ -527,19 +478,12 @@
dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
instance, LOWORD(lpTableName) );
- rsc_mem = RSC_LoadResource( instance, lpTableName,
- (SEGPTR) NE_RSCTYPE_ACCELERATOR, &image_size );
- if (rsc_mem == (HANDLE)NULL) {
- printf("LoadAccelerators(%08lx) not found!\n", lpTableName );
- return 0;
- }
- lp = (BYTE *)GlobalLock(rsc_mem);
- if (lp == NULL) {
- GlobalFree(rsc_mem);
- return 0;
- }
- dprintf_accel(stddeb,"LoadAccelerators / image_size=%d\n", image_size);
- n = image_size/5;
+ if (!(hRsrc = FindResource( instance, lpTableName, RT_ACCELERATOR )))
+ return 0;
+ if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
+
+ lp = (BYTE *)LockResource(rsc_mem);
+ n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY);
hAccel = GlobalAlloc(GMEM_MOVEABLE,
sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
@@ -558,8 +502,7 @@
lpAccelTbl->wCount++;
}
GlobalUnlock(hAccel);
- GlobalUnlock(rsc_mem);
- GlobalFree(rsc_mem);
+ FreeResource( rsc_mem );
return hAccel;
}
@@ -631,18 +574,17 @@
dprintf_resource(stddeb, "LoadString: instance = %04x, id = %d, buffer = %08x, "
"length = %d\n", instance, resource_id, (int) buffer, buflen);
- hrsrc = FindResource( instance, (SEGPTR)((resource_id >> 4) + 1),
- (SEGPTR) NE_RSCTYPE_STRING );
+ hrsrc = FindResource( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING );
if (!hrsrc) return 0;
hmem = LoadResource( instance, hrsrc );
if (!hmem) return 0;
- p = GlobalLock(hmem);
+ p = LockResource(hmem);
string_num = resource_id & 0x000f;
for (i = 0; i < string_num; i++)
p += *p + 1;
- i = MIN(buflen - 1, *p);
+ i = min(buflen - 1, *p);
if (i > 0) {
memcpy(buffer, p + 1, i);
buffer[i] = '\0';
@@ -655,87 +597,11 @@
fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
}
- FreeResource( hrsrc );
+ FreeResource( hmem );
dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
return i;
}
-
-/**********************************************************************
- * LoadMenu [USER.150]
- */
-HMENU LoadMenu( HINSTANCE instance, SEGPTR menu_name )
-{
- HMENU hMenu;
- HANDLE hMenu_desc;
- MENU_HEADER *menu_desc;
- if (HIWORD(menu_name))
- dprintf_resource( stddeb, "LoadMenu(%04x,'%s')\n",
- instance, (char *)PTR_SEG_TO_LIN( menu_name ) );
- else
- dprintf_resource( stddeb, "LoadMenu(%04x,%04x)\n",
- instance, LOWORD(menu_name) );
- if (!menu_name) return 0;
- if (!(hMenu_desc = RSC_LoadResource( instance, menu_name,
- (SEGPTR) NE_RSCTYPE_MENU, NULL )))
- return 0;
-
- menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc);
- hMenu = LoadMenuIndirect((LPSTR)menu_desc);
- return hMenu;
-}
-
-/**********************************************************************
- * LoadBitmap
- */
-HBITMAP LoadBitmap( HANDLE instance, SEGPTR bmp_name )
-{
- HBITMAP hbitmap;
- HANDLE rsc_mem;
- HDC hdc;
- long *lp;
- int image_size;
- int size;
-
- if (HIWORD(bmp_name))
- dprintf_resource( stddeb, "LoadBitmap(%04x,'%s')\n",
- instance, (char *)PTR_SEG_TO_LIN( bmp_name ) );
- else
- dprintf_resource( stddeb, "LoadBitmap(%04x,%04x)\n",
- instance, LOWORD( bmp_name ) );
-
- if (!instance)
- {
- if (HIWORD((int)bmp_name)) return 0; /* FIXME: should handle '#xxx' */
- return OBM_LoadBitmap( LOWORD((int)bmp_name) );
- }
-
- rsc_mem = RSC_LoadResource(instance, bmp_name, (SEGPTR) NE_RSCTYPE_BITMAP,
- &image_size);
- if (rsc_mem == (HANDLE)NULL) {
- printf("LoadBitmap(%04x,%08lx)\n", instance, bmp_name);
- return 0;
- }
- lp = (long *) GlobalLock(rsc_mem);
- if (lp == NULL)
- {
- GlobalFree(rsc_mem);
- return 0;
- }
-
- if (!(hdc = GetDC(0))) lp = NULL;
- size = CONV_LONG (*lp);
- if (size == sizeof(BITMAPCOREHEADER)){
- CONV_BITMAPCOREHEADER (lp);
- hbitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lp );
- } else if (size == sizeof(BITMAPINFOHEADER)){
- CONV_BITMAPINFO (lp);
- hbitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lp );
- } else hbitmap = 0;
- GlobalFree(rsc_mem);
- ReleaseDC( 0, hdc );
- return hbitmap;
-}
diff --git a/loader/selector.c b/loader/selector.c
index 142c703..f54605a 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -36,6 +36,7 @@
#include "neexe.h"
#include "if1632.h"
#include "prototypes.h"
+#include "module.h"
#include "stddebug.h"
/* #define DEBUG_SELECTORS */
#include "debug.h"
@@ -44,11 +45,6 @@
#define MAX_ENV_SIZE 16384 /* Max. environment size (ought to be dynamic) */
static HANDLE EnvironmentHandle = 0;
-WORD PSPSelector = 0;
-
-#define MAX_SELECTORS (512 * 2)
-
-int max_selectors = 0;
extern char WindowsPath[256];
@@ -57,9 +53,6 @@
extern int Argc;
extern char **environ;
-unsigned int
-GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal);
-
/**********************************************************************
* Check whether pseudo-functions like __0040H for direct memory
@@ -100,14 +93,6 @@
else if( !strcasecmp( function, "__F000H" ) ) nr = 7;
else if( !strcasecmp( function, "__C000H" ) ) nr = 8;
else if( !strcasecmp( function, "__0040H" ) ) nr = 9;
- else if( !strcasecmp( function, "__AHIncr" ) ) {
- *sel = *offset = __AHINCR;
- return 1;
- }
- else if( !strcasecmp( function, "__AHShift" ) ) {
- *sel = *offset = __AHSHIFT;
- return 1;
- }
else
return 0;
}
@@ -123,12 +108,6 @@
case 194: nr = 7; break;
case 195: nr = 8; break;
case 193: nr = 9; break;
- case 114:
- *sel = *offset = __AHINCR;
- return 1;
- case 113:
- *sel = *offset = __AHSHIFT;
- return 1;
default: return 0;
}
}
@@ -143,155 +122,53 @@
-/**********************************************************************
- * GetEntryPointFromOrdinal
- */
-union lookup{
- struct entry_tab_header_s *eth;
- struct entry_tab_movable_s *etm;
- struct entry_tab_fixed_s *etf;
- char * cpnt;
-};
-
unsigned int GetEntryDLLName( char * dll_name, char * function,
WORD* sel, WORD *offset )
{
- struct dll_table_s *dll_table;
- struct w_files * wpnt;
- char * cpnt;
- int ordinal, j, len;
+ HMODULE hModule;
+ struct dll_table_s *dll_table;
+ int ordinal, addr;
- if( GetMemoryReference( dll_name, function, sel, offset ) )
- return 0;
+ if( GetMemoryReference( dll_name, function, sel, offset ) )
+ return 0;
- dll_table = FindDLLTable(dll_name);
-
- if(dll_table) {
- ordinal = FindOrdinalFromName(dll_table->dll_table,function);
- if(!ordinal){
- dprintf_module(stddeb,"GetEntryDLLName: %s.%s not found\n",
- dll_name, function);
- *sel = *offset = 0;
- return -1;
- }
- *sel = dll_table->dll_table[ordinal].selector;
- *offset = dll_table->dll_table[ordinal].offset;
+ hModule = GetModuleHandle( dll_name );
+ ordinal = MODULE_GetOrdinal( hModule, function );
+ if (!ordinal) return 1;
+ addr = MODULE_GetEntryPoint( hModule, ordinal );
+ if (!addr) return 1;
#ifdef WINESTAT
- dll_table->dll_table[ordinal].used++;
+ if ((dll_table = FindDLLTable(dll_name)) != NULL)
+ {
+ dll_table->dll_table[ordinal].used++;
+ }
#endif
- return 0;
- };
-
- /* We need a means of determining the ordinal for the function. */
- /* Not a builtin symbol, look to see what the file has for us */
- for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
- if(strcasecmp(wpnt->name, dll_name)) continue;
- cpnt = wpnt->ne->nrname_table;
- while(1==1){
- if( ((int) cpnt) - ((int)wpnt->ne->nrname_table) >
- wpnt->ne->ne_header->nrname_tab_length) return 1;
- len = *cpnt++;
- if(strncmp(cpnt, function, len) == 0) break;
- cpnt += len + 2;
- };
- ordinal = *((unsigned short *) (cpnt + len));
- j = GetEntryPointFromOrdinal(wpnt, ordinal);
- *offset = LOWORD(j);
- *sel = HIWORD(j);
- return 0;
- };
- return 1;
+ *offset = LOWORD(addr);
+ *sel = HIWORD(addr);
+ return 0;
}
+
unsigned int GetEntryDLLOrdinal( char * dll_name, int ordinal,
WORD *sel, WORD *offset )
{
- struct dll_table_s *dll_table;
- struct w_files * wpnt;
- int j;
+ HMODULE hModule;
+ struct dll_table_s *dll_table;
+ int addr;
- if( GetMemoryReference( dll_name, (char*)ordinal, sel, offset ) )
- return 0;
+ if( GetMemoryReference( dll_name, (char*)ordinal, sel, offset ) )
+ return 0;
- dll_table = FindDLLTable(dll_name);
-
- if(dll_table) {
- *sel = dll_table->dll_table[ordinal].selector;
- *offset = dll_table->dll_table[ordinal].offset;
+ hModule = GetModuleHandle( dll_name );
+ addr = MODULE_GetEntryPoint( hModule, ordinal );
+ if (!addr) return 1;
#ifdef WINESTAT
- dll_table->dll_table[ordinal].used++;
+ if ((dll_table = FindDLLTable(dll_name)) != NULL)
+ dll_table->dll_table[ordinal].used++;
#endif
- return 0;
- };
-
- /* Not a builtin symbol, look to see what the file has for us */
- for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
- if(strcasecmp(wpnt->name, dll_name)) continue;
- j = GetEntryPointFromOrdinal(wpnt, ordinal);
- *offset = LOWORD(j);
- *sel = HIWORD(j);
- return 0;
- };
- return 1;
-}
-
-unsigned int
-GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal)
-{
- union lookup entry_tab_pointer;
- struct entry_tab_header_s *eth;
- struct entry_tab_movable_s *etm;
- struct entry_tab_fixed_s *etf;
- int current_ordinal;
- int i;
-
- entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
- /*
- * Let's walk through the table until we get to our entry.
- */
- current_ordinal = 1;
- while (1)
- {
- /*
- * Read header for this bundle.
- */
- eth = entry_tab_pointer.eth++;
-
- if (eth->n_entries == 0)
- return 0xffffffff; /* Yikes - we went off the end of the table */
-
- if (eth->seg_number == 0)
- {
- current_ordinal += eth->n_entries;
- if(current_ordinal > ordinal) return 0;
- continue;
- }
-
- /*
- * Read each of the bundle entries.
- */
- for (i = 0; i < eth->n_entries; i++, current_ordinal++)
- {
- if (eth->seg_number >= 0xfe)
- {
- etm = entry_tab_pointer.etm++;
- if (current_ordinal == ordinal)
- {
- return MAKELONG(etm->offset,
- wpnt->ne->selector_table[etm->seg_number-1]);
- }
- }
- else
- {
- etf = entry_tab_pointer.etf++;
- if (current_ordinal == ordinal)
- {
- return MAKELONG( etf->offset[0] + ((int)etf->offset[1]<<8),
- wpnt->ne->selector_table[eth->seg_number-1]);
- }
- }
- }
- }
+ *offset = LOWORD(addr);
+ *sel = HIWORD(addr);
+ return 0;
}
@@ -356,276 +233,14 @@
}
-/**********************************************************************
- * GetCurrentPDB (KERNEL.37)
- */
-WORD GetCurrentPDB()
-{
- return PSPSelector;
-}
-
-
-/**********************************************************************
- * CreatePSP
- */
-static WORD CreatePSP(void)
-{
- HANDLE handle;
- struct dos_psp_s *psp;
- char *p1, *p2;
- int i;
- WORD sel, offset;
-
- handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(*psp) );
- if (!handle) return 0;
- psp = (struct dos_psp_s *) GlobalLock( handle );
-
- /*
- * Fill PSP
- */
- psp->pspInt20 = 0x20cd;
- psp->pspDispatcher[0] = 0x9a;
- GetEntryDLLName( "KERNEL", "DOS3Call", &sel, &offset );
- *(unsigned short *)&psp->pspDispatcher[1] = offset;
- *(unsigned short *)&psp->pspDispatcher[3] = sel;
- GetEntryDLLName( "KERNEL", "FatalAppExit", &sel, &offset );
- psp->pspTerminateVector[0] = offset;
- psp->pspTerminateVector[1] = sel;
- psp->pspControlCVector[0] = offset;
- psp->pspControlCVector[1] = sel;
- psp->pspCritErrorVector[0] = offset;
- psp->pspCritErrorVector[1] = sel;
- psp->pspEnvironment = SELECTOROF( GetDOSEnvironment() );
-
- p1 = psp->pspCommandTail;
- for (i = 1; i < Argc; i++)
- {
- if ((int) ((int) p1 - (int) psp->pspCommandTail) +
- strlen(Argv[i]) > 124)
- break;
-
- if (i != 1)
- *p1++ = ' ';
-
- for (p2 = Argv[i]; *p2 != '\0'; )
- *p1++ = *p2++;
-
- }
- *p1 = '\0';
- psp->pspCommandTailCount = strlen(psp->pspCommandTail);
-
- return SELECTOROF( WIN16_GlobalLock( handle ) );
-}
-
/**********************************************************************
* CreateSelectors
*/
-unsigned short *CreateSelectors(struct w_files * wpnt)
+void CreateSelectors(void)
{
- int fd = wpnt->fd;
- struct ne_segment_table_entry_s *seg_table = wpnt->ne->seg_table;
- struct ne_header_s *ne_header = wpnt->ne->ne_header;
- unsigned short auto_data_sel;
-
- int old_length, file_image_length = 0;
- int saved_old_length = 0;
- int i, length;
- void *base_addr;
- WORD *selectors;
- HGLOBAL handle;
-
- auto_data_sel=0;
- /*
- * Allocate memory for the table to keep track of all selectors.
- */
- selectors = (WORD *) malloc( ne_header->n_segment_tab * sizeof(WORD) );
- if (selectors == NULL)
- return NULL;
-
- /*
- * Step through the segment table in the exe header.
- */
- for (i = 0; i < ne_header->n_segment_tab; i++)
- {
- /*
- * Is there an image for this segment in the file?
- */
- if (seg_table[i].seg_data_offset == 0)
- {
- /*
- * No image in exe file, let's allocate some memory for it.
- */
- length = seg_table[i].min_alloc;
- }
- else
- {
- /*
- * Image in file, let's just point to the image in memory.
- */
- length = seg_table[i].min_alloc;
- file_image_length = seg_table[i].seg_data_length;
- if (file_image_length == 0) file_image_length = 0x10000;
- }
-
- if (length == 0) length = 0x10000;
- old_length = length;
-
- /*
- * If this is the automatic data segment, its size must be adjusted.
- * First we need to check for local heap. Second we nee to see if
- * this is also the stack segment.
- */
- if (i + 1 == ne_header->auto_data_seg || i + 1 == ne_header->ss)
- {
- length = 0x10000;
- ne_header->sp = length - 2;
- dprintf_selectors(stddeb,"Auto data image length %x\n",file_image_length);
- }
-
- /*
- * Is this a DATA or CODE segment?
- */
- if (seg_table[i].seg_flags & NE_SEGFLAGS_DATA)
- {
- handle = GLOBAL_Alloc( GMEM_ZEROINIT, length, 0, FALSE,
- seg_table[i].seg_flags & NE_SEGFLAGS_READONLY );
- }
- else
- {
- handle = GLOBAL_Alloc( 0, length, 0, TRUE,
- seg_table[i].seg_flags & NE_SEGFLAGS_EXECUTEONLY );
- }
- base_addr = GlobalLock( handle );
- selectors[i] = GlobalHandleToSel( handle );
-
- if (seg_table[i].seg_data_offset != 0)
- {
- /*
- * Image in file.
- */
- lseek( fd, seg_table[i].seg_data_offset *
- (1 << ne_header->align_shift_count), SEEK_SET );
- if(read(fd, base_addr, file_image_length) != file_image_length)
- {
- fprintf( stderr, "Unable to read segment %d from file\n", i+1);
- exit(1);
- }
- }
-
- /*
- * If this is the automatic data segment, then we must initialize
- * the local heap.
- */
- if (i + 1 == ne_header->auto_data_seg)
- {
- auto_data_sel = selectors[i];
- saved_old_length = old_length;
- }
- }
- if(!auto_data_sel)dprintf_selectors(stddeb,"Warning: No auto_data_sel\n");
- for (i = 0; i < ne_header->n_segment_tab; i++)
- {
-/* Segments[s->selector >> __AHSHIFT].owner = auto_data_sel; */
- if (selectors[i] == auto_data_sel)
- LocalInit( auto_data_sel, saved_old_length,
- 0x10000 - 2
- - ne_header->stack_length );
-#if 0
- HEAP_LocalInit(auto_data_sel,
- (char *)GET_SEL_BASE(selectors[i]) + saved_old_length,
- 0x10000 - 2 - saved_old_length
- - ne_header->stack_length);
-#endif
- }
-
- if(!EnvironmentHandle)
- {
- EnvironmentHandle = CreateEnvironment();
- PSPSelector = CreatePSP();
- }
-
- return selectors;
+ if(!EnvironmentHandle) EnvironmentHandle = CreateEnvironment();
}
-/**********************************************************************
- */
-void
-FixupFunctionPrologs(struct w_files * wpnt)
-{
- union lookup entry_tab_pointer;
- struct entry_tab_header_s *eth;
- struct entry_tab_movable_s *etm;
- struct entry_tab_fixed_s *etf;
- unsigned char *fixup_ptr;
- int i;
-
-/* if (!(ne_header->format_flags & NE_FFLAGS_SINGLEDATA))
- return;
-*/
- entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
- /*
- * Let's walk through the table and fixup prologs as we go.
- */
- while (1)
- {
- /* Get bundle header */
- eth = entry_tab_pointer.eth++;
-
- /* Check for end of table */
- if (eth->n_entries == 0)
- return;
-
- /* Check for empty bundle */
- if (eth->seg_number == 0)
- continue;
-
- /* Examine each bundle */
- for (i = 0; i < eth->n_entries; i++)
- {
- /* Moveable segment */
- if (eth->seg_number >= 0xfe)
- {
- etm = entry_tab_pointer.etm++;
- /* FIXME: Does anyone know the exact meaning of these flags? */
- /* 0x0001 seems to mean: Fix up the function prolog */
- dprintf_selector(stddeb,"ETM_Flags: %04x ",etm->flags);
- if (!(etm->flags & 0x0001)) continue;
- fixup_ptr = (char *)GET_SEL_BASE(wpnt->ne->selector_table[etm->seg_number-1]) + etm->offset;
- }
- else
- {
- etf = entry_tab_pointer.etf++;
- dprintf_selector(stddeb,"ETF_Flags: %04x ",etf->flags);
- if (!(etf->flags & 0x0001)) continue;
- fixup_ptr = (char *)GET_SEL_BASE(wpnt->ne->selector_table[eth->seg_number-1])
- + (int) etf->offset[0]
- + ((int) etf->offset[1] << 8);
-
- }
- dprintf_selector(stddeb,"Signature: %02x %02x %02x,ff %x\n",
- fixup_ptr[0],fixup_ptr[1],fixup_ptr[2],
- wpnt->ne->ne_header->format_flags);
-
- /* Verify the signature */
- if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
- || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
- && fixup_ptr[2] == 0x90)
- {
- if (wpnt->ne->ne_header->format_flags & NE_FFLAGS_SINGLEDATA) {
-
- fixup_ptr[0] = 0xb8; /* MOV AX, */
- fixup_ptr[1] = wpnt->hinstance;
- fixup_ptr[2] = (wpnt->hinstance >> 8);
- } else {
- fixup_ptr[0] = 0x90; /* non-library: NOPs */
- fixup_ptr[1] = 0x90;
- fixup_ptr[2] = 0x90;
- }
- }
- }
- }
-}
-
#endif /* ifndef WINELIB */
diff --git a/loader/task.c b/loader/task.c
index 93c14a5..7f26131 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -1,279 +1,831 @@
/*
- * Tasks functions
+ * Task functions
*
-static char Copyright[] = "Copyright Martin Ayotte, 1994";
-*/
+ * Copyright 1995 Alexandre Julliard
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
#include "windows.h"
-#include "callback.h"
#include "task.h"
+#include "callback.h"
+#include "global.h"
+#include "instance.h"
+#include "module.h"
+#include "neexe.h"
+#include "selectors.h"
+#include "toolhelp.h"
+#include "wine.h"
#include "stddebug.h"
#include "debug.h"
-static LPWINETASKENTRY lpTaskList = NULL;
-static int nTaskCount = 0;
-/**********************************************************************
- * GetCurrentTask [KERNEL.36]
+#define MIN_THUNKS 32 /* Min. thunks allocated when creating a new segment */
+
+#define STACK32_SIZE 0x10000 /* 32-bit stack size for each task */
+
+
+static HTASK hFirstTask = 0;
+static HTASK hCurrentTask = 0;
+static HTASK hTaskToKill = 0;
+static WORD nTaskCount = 0;
+
+ /* TASK_Reschedule() 16-bit entry point */
+static FARPROC TASK_RescheduleProc;
+
+#define TASK_SCHEDULE() CallTo16_word_(TASK_RescheduleProc,0)
+
+
+/***********************************************************************
+ * TASK_Init
*/
-HTASK GetCurrentTask(void)
+BOOL TASK_Init(void)
{
- LPWINETASKENTRY lpTask = lpTaskList;
- int pid = getpid();
- dprintf_task(stddeb,"GetCurrentTask() // unix_pid=%08X !\n", pid);
- if (lpTask == NULL) return 0;
- while (TRUE) {
- if (lpTask->unix_pid == pid) break;
- if (lpTask->lpNextTask == NULL) return 0;
- lpTask = lpTask->lpNextTask;
- }
- dprintf_task(stddeb,"GetCurrentTask() returned hTask=%04X !\n", lpTask->te.hTask);
- return lpTask->te.hTask;
+ TASK_RescheduleProc = (FARPROC)GetWndProcEntry16( "TASK_Reschedule" );
+ return TRUE;
}
-/**********************************************************************
- * GetNumTasks [KERNEL.152]
+/***********************************************************************
+ * TASK_LinkTask
*/
-WORD GetNumTasks(void)
+static void TASK_LinkTask( HTASK hTask )
{
- dprintf_task(stddeb,"GetNumTasks() returned %d !\n", nTaskCount);
- return nTaskCount;
+ HTASK *prevTask;
+ TDB *pTask;
+
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+ prevTask = &hFirstTask;
+ while (*prevTask)
+ {
+ TDB *prevTaskPtr = (TDB *)GlobalLock( *prevTask );
+ if (prevTaskPtr->priority >= pTask->priority) break;
+ prevTask = &prevTaskPtr->hNext;
+ }
+ pTask->hNext = *prevTask;
+ *prevTask = hTask;
+ nTaskCount++;
}
-/**********************************************************************
- * GetWindowTask [USER.224]
+/***********************************************************************
+ * TASK_UnlinkTask
*/
-HTASK GetWindowTask(HWND hWnd)
+static void TASK_UnlinkTask( HTASK hTask )
{
- HWND *wptr;
- int count;
- LPWINETASKENTRY lpTask = lpTaskList;
- dprintf_task(stddeb,"GetWindowTask(%04X) !\n", hWnd);
- while (lpTask != NULL) {
- wptr = lpTask->lpWndList;
- if (wptr != NULL) {
- count = 0;
- while (++count < MAXWIN_PER_TASK) {
- dprintf_task(stddeb,"GetWindowTask // searching %04X %04X !\n",
- lpTask->te.hTask, *(wptr));
- if (*(wptr) == hWnd) {
- dprintf_task(stddeb,"GetWindowTask(%04X) found hTask=%04X !\n",
- hWnd, lpTask->te.hTask);
- return lpTask->te.hTask;
- }
- wptr++;
- }
- }
- lpTask = lpTask->lpNextTask;
- }
- return 0;
+ HTASK *prevTask;
+ TDB *pTask;
+
+ prevTask = &hFirstTask;
+ while (*prevTask && (*prevTask != hTask))
+ {
+ pTask = (TDB *)GlobalLock( *prevTask );
+ prevTask = &pTask->hNext;
+ }
+ if (*prevTask)
+ {
+ pTask = (TDB *)GlobalLock( *prevTask );
+ *prevTask = pTask->hNext;
+ pTask->hNext = 0;
+ nTaskCount--;
+ }
}
-/**********************************************************************
- * EnumTaskWindows [USER.225]
+/***********************************************************************
+ * TASK_CreateThunks
+ *
+ * Create a thunk free-list in segment 'handle', starting from offset 'offset'
+ * and containing 'count' entries.
*/
-BOOL EnumTaskWindows(HANDLE hTask, FARPROC lpEnumFunc, LONG lParam)
+static void TASK_CreateThunks( HGLOBAL handle, WORD offset, WORD count )
{
- HWND *wptr, hWnd;
- BOOL bRet;
- int count = 0;
- LPWINETASKENTRY lpTask = lpTaskList;
- dprintf_task(stddeb,"EnumTaskWindows(%04X, %08X, %08X) !\n", hTask,
- (unsigned int) lpEnumFunc, (unsigned int) lParam);
- while (TRUE) {
- if (lpTask->te.hTask == hTask) break;
- if (lpTask == NULL) {
- dprintf_task(stddeb,"EnumTaskWindows // hTask=%04X not found !\n", hTask);
- return FALSE;
- }
- lpTask = lpTask->lpNextTask;
- }
- dprintf_task(stddeb,"EnumTaskWindows // found hTask=%04X !\n", hTask);
- wptr = lpTask->lpWndList;
- if (wptr == NULL) return FALSE;
- if (lpEnumFunc == NULL) return FALSE;
- while ((hWnd = *(wptr++)) != 0) {
- if (++count >= MAXWIN_PER_TASK) return FALSE;
- dprintf_task(stddeb,"EnumTaskWindows // hWnd=%04X count=%d !\n", hWnd, count);
- bRet = CallEnumTaskWndProc( lpEnumFunc, hWnd, lParam );
- if (bRet == 0) break;
- }
- return TRUE;
+ int i;
+ WORD free;
+ THUNKS *pThunk;
+
+ pThunk = (THUNKS *)((BYTE *)GlobalLock( handle ) + offset);
+ pThunk->next = 0;
+ pThunk->magic = THUNK_MAGIC;
+ pThunk->free = (int)&pThunk->thunks - (int)pThunk;
+ free = pThunk->free;
+ for (i = 0; i < count-1; i++)
+ {
+ free += 8; /* Offset of next thunk */
+ pThunk->thunks[4*i] = free;
+ }
+ pThunk->thunks[4*i] = 0; /* Last thunk */
}
-/**********************************************************************
- * CreateNewTask [internal]
+/***********************************************************************
+ * TASK_AllocThunk
+ *
+ * Allocate a thunk for MakeProcInstance().
*/
-HANDLE CreateNewTask(HINSTANCE hInst, HTASK hTaskParent)
+static SEGPTR TASK_AllocThunk( HTASK hTask )
{
- HANDLE hTask;
- LPWINETASKENTRY lpTask = lpTaskList;
- LPWINETASKENTRY lpNewTask;
- MODULEENTRY module;
+ TDB *pTask;
+ THUNKS *pThunk;
+ WORD sel, base;
+
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return 0;
+ sel = pTask->hCSAlias;
+ pThunk = &pTask->thunks;
+ base = (int)pThunk - (int)pTask;
+ while (!pThunk->free)
+ {
+ sel = pThunk->next;
+ if (!sel) /* Allocate a new segment */
+ {
+ sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(THUNKS) + (MIN_THUNKS-1)*8,
+ pTask->hPDB, TRUE, FALSE, FALSE );
+ if (!sel) return (SEGPTR)0;
+ TASK_CreateThunks( sel, 0, MIN_THUNKS );
+ pThunk->next = sel;
+ }
+ pThunk = (THUNKS *)GlobalLock( sel );
+ base = 0;
+ }
+ base += pThunk->free;
+ pThunk->free = *(WORD *)((BYTE *)pThunk + pThunk->free);
+ return MAKELONG( base, sel );
+}
- module.dwSize = sizeof(module);
- ModuleFindHandle(&module, hInst);
- if (lpTask != NULL) {
- while (TRUE) {
- if (lpTask->lpNextTask == NULL) break;
- lpTask = lpTask->lpNextTask;
- }
- }
- hTask = GlobalAlloc(GMEM_MOVEABLE, sizeof(WINETASKENTRY));
- lpNewTask = (LPWINETASKENTRY) GlobalLock(hTask);
- dprintf_task(stddeb,"CreateNewTask entry allocated %p\n", lpNewTask);
- if (lpNewTask == NULL) return 0;
- if (lpTaskList == NULL) {
- lpTaskList = lpNewTask;
- lpNewTask->lpPrevTask = NULL;
- }
- else {
- lpTask->lpNextTask = lpNewTask;
- lpTask->te.hNext = lpNewTask->te.hTask;
- lpNewTask->lpPrevTask = lpTask;
- }
- lpNewTask->lpNextTask = NULL;
- lpNewTask->hIcon = 0;
- lpNewTask->te.dwSize = sizeof(TASKENTRY);
- lpNewTask->te.hModule = 0;
- lpNewTask->te.hInst = hInst;
- lpNewTask->te.hTask = hTask;
- lpNewTask->te.hTaskParent = hTaskParent;
- lpNewTask->te.wSS = 0;
- lpNewTask->te.wSP = 0;
- lpNewTask->te.wStackTop = 0;
- lpNewTask->te.wStackMinimum = 0;
- lpNewTask->te.wStackBottom = 0;
- lpNewTask->te.wcEvents = 0;
- lpNewTask->te.hQueue = 0;
- strcpy(lpNewTask->te.szModule, module.szModule);
- lpNewTask->te.wPSPOffset = 0;
- lpNewTask->unix_pid = getpid();
- lpNewTask->lpWndList = (HWND *) malloc(MAXWIN_PER_TASK * sizeof(HWND));
- if (lpNewTask->lpWndList != NULL)
- memset((LPSTR)lpNewTask->lpWndList, 0, MAXWIN_PER_TASK * sizeof(HWND));
- dprintf_task(stddeb,"CreateNewTask // unix_pid=%08X return hTask=%04X\n",
- lpNewTask->unix_pid, hTask);
- GlobalUnlock(hTask);
- nTaskCount++;
+/***********************************************************************
+ * TASK_FreeThunk
+ *
+ * Free a MakeProcInstance() thunk.
+ */
+static BOOL TASK_FreeThunk( HTASK hTask, SEGPTR thunk )
+{
+ TDB *pTask;
+ THUNKS *pThunk;
+ WORD sel, base;
+
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return 0;
+ sel = pTask->hCSAlias;
+ pThunk = &pTask->thunks;
+ base = (int)pThunk - (int)pTask;
+ while (sel && (sel != HIWORD(thunk)))
+ {
+ sel = pThunk->next;
+ pThunk = (THUNKS *)GlobalLock( sel );
+ base = 0;
+ }
+ if (!sel) return FALSE;
+ *(WORD *)((BYTE *)pThunk + LOWORD(thunk) - base) = pThunk->free;
+ pThunk->free = LOWORD(thunk) - base;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * TASK_CallToStart
+ *
+ * 32-bit entry point for a new task. This function is responsible for
+ * setting up the registers and jumping to the 16-bit entry point.
+ */
+static void TASK_CallToStart(void)
+{
+ int cs_reg, ds_reg, ip_reg;
+ TDB *pTask = (TDB *)GlobalLock( hCurrentTask );
+ NE_MODULE *pModule = (NE_MODULE *)GlobalLock( pTask->hModule );
+ SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
+ extern unsigned short WIN_StackSize;
+
+ /* Registers at initialization must be:
+ * ax zero
+ * bx stack size in bytes
+ * cx heap size in bytes
+ * si previous app instance
+ * di current app instance
+ * bp zero
+ * es selector to the PSP
+ * ds dgroup of the application
+ * ss stack selector
+ * sp top of the stack
+ */
+
+ WIN_StackSize = pModule->stack_size;
+
+ cs_reg = pSegTable[pModule->cs - 1].selector;
+ ip_reg = pModule->ip;
+ ds_reg = pSegTable[pModule->dgroup - 1].selector;
+ IF1632_Saved16_ss = pTask->ss;
+ IF1632_Saved16_sp = pTask->sp;
+/* dprintf_task( stddeb, "Starting main program: cs:ip=%04x:%04x ds=%04x ss:sp=%04x:%04x\n",
+ cs_reg, ip_reg, ds_reg,
+ IF1632_Saved16_ss, IF1632_Saved16_sp);
+*/
+ CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
+ pTask->hPDB /*es*/, 0 /*bp*/, 0 /*ax*/,
+ WIN_StackSize /*bx*/, pModule->heap_size /*cx*/,
+ 0 /*dx*/, 0 /*si*/, ds_reg /*di*/ );
+ /* This should never return */
+ fprintf( stderr, "TASK_CallToStart: Main program returned!\n" );
+ exit(1);
+}
+
+
+/***********************************************************************
+ * TASK_CreateTask
+ */
+HTASK TASK_CreateTask( HMODULE hModule, HANDLE hEnvironment,
+ HTASK hTaskParent, char *cmdLine )
+{
+ HTASK hTask;
+ TDB *pTask;
+ NE_MODULE *pModule;
+ SEGTABLEENTRY *pSegTable;
+ LPSTR name;
+ char *stack16Top, *stack32Top;
+ STACK16FRAME *frame16;
+ STACK32FRAME *frame32;
+ extern DWORD CALL16_RetAddr_word;
+
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+ pSegTable = NE_SEG_TABLE( pModule );
+
+ /* Allocate the task structure */
+
+ hTask = GLOBAL_Alloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB),
+ hModule, FALSE, FALSE, FALSE );
+ if (!hTask) return 0;
+ pTask = (TDB *)GlobalLock( hTask );
+
+ /* Fill the task structure */
+
+ pTask->nEvents = 1; /* So the task can be started */
+ pTask->hSelf = hTask;
+ pTask->flags = 0;
+ pTask->version = pModule->expected_version;
+ pTask->hInstance = NE_SEG_TABLE(pModule)[pModule->dgroup-1].selector,
+ pTask->hModule = hModule;
+ pTask->hParent = hTaskParent;
+ pTask->curdrive = 'C' - 'A' + 0x80;
+ pTask->magic = TDB_MAGIC;
+ strcpy( pTask->curdir, "WINDOWS" );
+
+ /* Create the thunks block */
+
+ TASK_CreateThunks( hTask, (int)&pTask->thunks - (int)pTask, 7 );
+
+ /* Copy the module name */
+
+ name = MODULE_GetModuleName( hModule );
+ strncpy( pTask->module_name, name, sizeof(pTask->module_name) );
+
+ /* Fill the PDB */
+
+ pTask->pdb.int20 = 0x20cd;
+ pTask->pdb.dispatcher[0] = 0x9a;
+ *(DWORD *)&pTask->pdb.dispatcher[1] = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"), 102 ); /* KERNEL.102 is DOS3Call() */
+ pTask->pdb.savedint22 = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"),
+ 137 ); /* KERNEL.137 is FatalAppExit() */
+ pTask->pdb.savedint23 = pTask->pdb.savedint22;
+ pTask->pdb.savedint24 = pTask->pdb.savedint22;
+ pTask->pdb.environment = hEnvironment;
+ strncpy( pTask->pdb.cmdLine + 1, cmdLine, 126 );
+ pTask->pdb.cmdLine[127] = '\0';
+ pTask->pdb.cmdLine[0] = strlen( pTask->pdb.cmdLine + 1 );
+
+ /* Get the compatibility flags */
+
+ pTask->compat_flags = GetProfileInt( name, "Compatibility", 0 );
+
+ /* Allocate a selector for the PDB */
+
+ pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB),
+ hModule, FALSE, FALSE, FALSE );
+
+ /* Allocate a code segment alias for the TDB */
+
+ pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask,
+ sizeof(TDB), pTask->hPDB, TRUE,
+ FALSE, FALSE );
+
+ /* Set the owner of the environment block */
+
+ FarSetOwner( pTask->pdb.environment, pTask->hPDB );
+
+ /* Default DTA overwrites command-line */
+
+ pTask->dta = MAKELONG( (int)&pTask->pdb.cmdLine - (int)&pTask->pdb,
+ pTask->hPDB );
+
+ /* Allocate the 32-bit stack */
+
+ pTask->hStack32 = GLOBAL_Alloc( GMEM_FIXED, STACK32_SIZE, pTask->hPDB,
+ FALSE, FALSE, FALSE );
+
+ /* Create the 32-bit stack frame */
+
+ stack32Top = (char*)GlobalLock(pTask->hStack32) + STACK32_SIZE;
+ frame32 = (STACK32FRAME *)stack32Top - 1;
+ frame32->saved_esp = (DWORD)stack32Top;
+ frame32->edi = 0;
+ frame32->esi = 0;
+ frame32->edx = 0;
+ frame32->ecx = 0;
+ frame32->ebx = 0;
+ frame32->ebp = 0;
+ frame32->retaddr = (DWORD)TASK_CallToStart;
+ frame32->codeselector = WINE_CODE_SELECTOR;
+ pTask->esp = (DWORD)frame32;
+
+ /* Create the 16-bit stack frame */
+
+ pTask->ss = pSegTable[pModule->ss - 1].selector;
+ pTask->sp = (pModule->sp != 0) ? pModule->sp :
+ pSegTable[pModule->ss-1].minsize + pModule->stack_size;
+ stack16Top = (char *)PTR_SEG_OFF_TO_LIN( pTask->ss, pTask->sp );
+ frame16 = (STACK16FRAME *)stack16Top - 1;
+ frame16->saved_ss = pTask->ss;
+ frame16->saved_sp = pTask->sp;
+ frame16->ds = pTask->hInstance;
+ frame16->entry_point = 0;
+ frame16->ordinal_number = 1;
+ frame16->dll_id = 1;
+ frame16->bp = 0;
+ frame16->ip = LOWORD( CALL16_RetAddr_word );
+ frame16->cs = HIWORD( CALL16_RetAddr_word );
+ pTask->sp -= sizeof(STACK16FRAME);
+
+ /* If there's no 16-bit stack yet, use a part of the new task stack */
+ /* This is only needed to have a stack to switch from on the first */
+ /* call to DirectedYield(). */
+
+ if (!IF1632_Saved16_ss)
+ {
+ IF1632_Saved16_ss = pTask->ss;
+ IF1632_Saved16_sp = pTask->sp;
+ }
+
+ /* Add the task to the linked list */
+
+ TASK_LinkTask( hTask );
+
+ dprintf_task( stddeb, "CreateTask: module='%s' cmdline='%s' task=%04x\n",
+ name, cmdLine, hTask );
+
return hTask;
}
-/**********************************************************************
- * AddWindowToTask [internal]
+/***********************************************************************
+ * TASK_DeleteTask
*/
-BOOL AddWindowToTask(HTASK hTask, HWND hWnd)
+void TASK_DeleteTask( HTASK hTask )
{
- HWND *wptr;
- int count = 0;
- LPWINETASKENTRY lpTask = lpTaskList;
- dprintf_task(stddeb,"AddWindowToTask(%04X, %04X); !\n", hTask, hWnd);
- while (TRUE) {
- if (lpTask->te.hTask == hTask) break;
- if (lpTask == NULL) {
- fprintf(stderr,"AddWindowToTask // hTask=%04X not found !\n", hTask);
- return FALSE;
- }
- lpTask = lpTask->lpNextTask;
- }
- wptr = lpTask->lpWndList;
- if (wptr == NULL) return FALSE;
- while (*(wptr) != 0) {
- if (++count >= MAXWIN_PER_TASK) return FALSE;
- wptr++;
- }
- *wptr = hWnd;
- dprintf_task(stddeb,"AddWindowToTask // window added, count=%d !\n", count);
- return TRUE;
+ TDB *pTask;
+
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+
+ /* Free all memory used by this task (including the 32-bit stack, */
+ /* the environment block and the thunk segments). */
+
+ GlobalFreeAll( pTask->hPDB );
+
+ /* Free the selector aliases */
+
+ GLOBAL_FreeBlock( pTask->hCSAlias );
+ GLOBAL_FreeBlock( pTask->hPDB );
+
+ GlobalFree( hTask ); /* Free the task structure */
+}
+
+
+/***********************************************************************
+ * TASK_KillCurrentTask
+ *
+ * Kill the currently running task. As it's not possible to kill the
+ * current task like this, it is simply marked for destruction, and will
+ * be killed when either TASK_Reschedule or this function is called again
+ * in the context of another task.
+ */
+void TASK_KillCurrentTask( int exitCode )
+{
+ if (hTaskToKill && (hTaskToKill != hCurrentTask))
+ {
+ /* If another task is already marked for destruction, */
+ /* we call kill it now, as we are in another context. */
+ TASK_DeleteTask( hTaskToKill );
+ }
+
+ if (nTaskCount <= 1)
+ {
+ dprintf_task( stddeb, "Killing the last task, exiting\n" );
+ exit(0);
+ }
+
+ /* Remove the task from the list to be sure we never switch back to it */
+ TASK_UnlinkTask( hCurrentTask );
+
+ hTaskToKill = hCurrentTask;
+ Yield();
+ /* We never return from Yield() */
+}
+
+
+/***********************************************************************
+ * TASK_Reschedule
+ *
+ * This is where all the magic of task-switching happens!
+ *
+ * This function should only be called via the TASK_SCHEDULE() macro, to make
+ * sure that all the context is saved correctly.
+ */
+void TASK_Reschedule(void)
+{
+ TDB *pOldTask = NULL, *pNewTask;
+ HTASK hTask = 0;
+
+ /* First check if there's a task to kill */
+
+ if (hTaskToKill && (hTaskToKill != hCurrentTask))
+ TASK_DeleteTask( hTaskToKill );
+
+ /* Find a task to yield to */
+
+ pOldTask = (TDB *)GlobalLock( hCurrentTask );
+ if (pOldTask && pOldTask->hYieldTo)
+ {
+ /* If a task is stored in hYieldTo of the current task (put there */
+ /* by DirectedYield), yield to it only if it has events pending. */
+ hTask = pOldTask->hYieldTo;
+ if (!(pNewTask = (TDB *)GlobalLock( hTask )) || !pNewTask->nEvents)
+ hTask = 0;
+ }
+
+ if (!hTask)
+ {
+ hTask = hFirstTask;
+ while (hTask)
+ {
+ pNewTask = (TDB *)GlobalLock( hTask );
+ if (pNewTask->nEvents && (hTask != hCurrentTask)) break;
+ hTask = pNewTask->hNext;
+ }
+ }
+
+ /* If there's a task to kill, switch to any other task, */
+ /* even if it doesn't have events pending. */
+
+ if (!hTask && hTaskToKill) hTask = hFirstTask;
+
+ if (!hTask) return; /* Do nothing */
+
+ pNewTask = (TDB *)GlobalLock( hTask );
+ dprintf_task( stddeb, "Switching to task %04x (%.8s)\n",
+ hTask, pNewTask->module_name );
+
+ /* Save the stacks of the previous task (if any) */
+
+ if (pOldTask)
+ {
+ pOldTask->ss = IF1632_Saved16_ss;
+ pOldTask->sp = IF1632_Saved16_sp;
+ pOldTask->esp = IF1632_Saved32_esp;
+ }
+
+ /* Make the task the last in the linked list (round-robin scheduling) */
+
+ pNewTask->priority++;
+ TASK_UnlinkTask( hTask );
+ TASK_LinkTask( hTask );
+ pNewTask->priority--;
+
+ /* Switch to the new stack */
+
+ hCurrentTask = hTask;
+ IF1632_Saved16_ss = pNewTask->ss;
+ IF1632_Saved16_sp = pNewTask->sp;
+ IF1632_Saved32_esp = pNewTask->esp;
+}
+
+
+/***********************************************************************
+ * WaitEvent (KERNEL.30)
+ */
+BOOL WaitEvent( HTASK hTask )
+{
+ TDB *pTask;
+
+ if (!hTask) hTask = hCurrentTask;
+ pTask = (TDB *)GlobalLock( hTask );
+ if (pTask->nEvents > 0)
+ {
+ pTask->nEvents--;
+ return FALSE;
+ }
+ TASK_SCHEDULE();
+ /* When we get back here, we have an event */
+ pTask->nEvents--;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * PostEvent (KERNEL.31)
+ */
+void PostEvent( HTASK hTask )
+{
+ TDB *pTask;
+
+ if (!hTask) hTask = hCurrentTask;
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+ pTask->nEvents++;
+}
+
+
+/***********************************************************************
+ * SetPriority (KERNEL.32)
+ */
+void SetPriority( HTASK hTask, int delta )
+{
+ TDB *pTask;
+ int newpriority;
+
+ if (!hTask) hTask = hCurrentTask;
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+ newpriority = pTask->priority + delta;
+ if (newpriority < -32) newpriority = -32;
+ else if (newpriority > 15) newpriority = 15;
+
+ pTask->priority = newpriority + 1;
+ TASK_UnlinkTask( hTask );
+ TASK_LinkTask( hTask );
+ pTask->priority--;
+}
+
+
+/***********************************************************************
+ * OldYield (KERNEL.117)
+ */
+void OldYield(void)
+{
+ TDB *pCurTask;
+
+ pCurTask = (TDB *)GlobalLock( hCurrentTask );
+ if (pCurTask) pCurTask->nEvents++; /* Make sure we get back here */
+ TASK_SCHEDULE();
+ if (pCurTask) pCurTask->nEvents--;
+}
+
+
+/***********************************************************************
+ * DirectedYield (KERNEL.150)
+ */
+void DirectedYield( HTASK hTask )
+{
+ TDB *pCurTask;
+
+ if ((pCurTask = (TDB *)GlobalLock( hCurrentTask )) != NULL)
+ pCurTask->hYieldTo = hTask;
+
+ OldYield();
+}
+
+
+/***********************************************************************
+ * Yield (KERNEL.29)
+ */
+void Yield(void)
+{
+ DirectedYield( 0 );
+}
+
+
+/***********************************************************************
+ * MakeProcInstance (KERNEL.51)
+ */
+FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance )
+{
+ BYTE *thunk;
+ SEGPTR thunkaddr;
+
+ thunkaddr = TASK_AllocThunk( hCurrentTask );
+ if (!thunkaddr) return (FARPROC)0;
+ thunk = PTR_SEG_TO_LIN( thunkaddr );
+
+ dprintf_task( stddeb, "MakeProcInstance(%08lx,%04x): got thunk %08lx\n",
+ (SEGPTR)func, hInstance, (SEGPTR)thunkaddr );
+
+ *thunk++ = 0xb8; /* movw instance, %ax */
+ *thunk++ = (BYTE)(hInstance & 0xff);
+ *thunk++ = (BYTE)(hInstance >> 8);
+ *thunk++ = 0xea; /* ljmp func */
+ *(DWORD *)thunk = (DWORD)func;
+ return (FARPROC)thunkaddr;
+}
+
+
+/***********************************************************************
+ * FreeProcInstance (KERNEL.52)
+ */
+void FreeProcInstance( FARPROC func )
+{
+ dprintf_task( stddeb, "FreeProcInstance(%08lx)\n", (SEGPTR)func );
+ TASK_FreeThunk( hCurrentTask, (SEGPTR)func );
}
/**********************************************************************
- * RemoveWindowFromTask [internal]
+ * GetCodeHandle (KERNEL.93)
*/
-BOOL RemoveWindowFromTask(HTASK hTask, HWND hWnd)
+HANDLE GetCodeHandle( FARPROC proc )
{
- HWND *wptr;
- int count = 0;
- LPWINETASKENTRY lpTask = lpTaskList;
- dprintf_task(stddeb,"RemoveWindowFromTask (%04X, %04X); !\n", hTask, hWnd);
- while (TRUE) {
- if (lpTask->te.hTask == hTask) break;
- if (lpTask == NULL) {
- fprintf(stderr,"RemoveWindowFromTask // hTask=%04X not found !\n", hTask);
- return FALSE;
- }
- lpTask = lpTask->lpNextTask;
- }
- wptr = lpTask->lpWndList;
- if (wptr == NULL) return FALSE;
- while (*(wptr) != hWnd) {
- if (++count >= MAXWIN_PER_TASK) return FALSE;
- wptr++;
- }
- while (*(wptr) != 0) {
- *(wptr) = *(wptr + 1);
- if (++count >= MAXWIN_PER_TASK) return FALSE;
- wptr++;
- }
- dprintf_task(stddeb,"RemoveWindowFromTask // window removed, count=%d !\n", --count);
- return TRUE;
+ HANDLE handle;
+ BYTE *thunk = (BYTE *)PTR_SEG_TO_LIN( proc );
+
+ /* Return the code segment containing 'proc'. */
+ /* Not sure if this is really correct (shouldn't matter that much). */
+
+ /* Check if it is really a thunk */
+ if ((thunk[0] == 0xb8) && (thunk[3] == 0xea))
+ handle = GlobalHandle( thunk[6] + (thunk[7] << 8) );
+ else
+ handle = GlobalHandle( HIWORD(proc) );
+
+ printf( "STUB: GetCodeHandle(%p) returning %04x\n", proc, handle );
+ return handle;
}
-BOOL TaskFirst(LPTASKENTRY lpTask)
+
+/***********************************************************************
+ * SetTaskQueue (KERNEL.34)
+ */
+HGLOBAL SetTaskQueue( HANDLE hTask, HGLOBAL hQueue )
{
- dprintf_task(stddeb,"TaskFirst(%8x)\n", (int) lpTask);
- if (lpTaskList) {
- memcpy(lpTask, &lpTaskList->te, lpTask->dwSize);
- return TRUE;
- } else
- return FALSE;
+ HGLOBAL hPrev;
+ TDB *pTask;
+
+ if (!hTask) hTask = hCurrentTask;
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return 0;
+ hPrev = pTask->hQueue;
+ pTask->hQueue = hQueue;
+ return hPrev;
}
-BOOL TaskNext(LPTASKENTRY lpTask)
+
+/***********************************************************************
+ * GetTaskQueue (KERNEL.35)
+ */
+HGLOBAL GetTaskQueue( HANDLE hTask )
{
- LPWINETASKENTRY list;
- dprintf_task(stddeb,"TaskNext(%8x)\n", (int) lpTask);
- list = lpTaskList;
- while (list) {
- if (list->te.hTask == lpTask->hTask) {
- list = list->lpNextTask;
- if (list) {
- memcpy(lpTask, &list->te, lpTask->dwSize);
- return TRUE;
- } else
- return FALSE;
- }
- list = list->lpNextTask;
- }
- return FALSE;
+ TDB *pTask;
+
+ if (!hTask) hTask = hCurrentTask;
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return 0;
+ return pTask->hQueue;
}
-BOOL TaskFindHandle(LPTASKENTRY lpTask, HTASK hTask)
+
+/***********************************************************************
+ * GetCurrentTask (KERNEL.36)
+ */
+HTASK GetCurrentTask(void)
{
- static LPWINETASKENTRY list;
- dprintf_task(stddeb,"TaskFindHandle(%8x,%4x)\n", (int) lpTask, hTask);
- list = lpTaskList;
- while (list) {
- if (list->te.hTask == hTask) {
- list = list->lpNextTask;
- if (list) {
- memcpy(lpTask, &list->te, lpTask->dwSize);
- return TRUE;
- } else
- return FALSE;
- }
- list = list->lpNextTask;
- }
- return FALSE;
+ /* Undocumented: first task is returned in high word */
+ return MAKELONG( hCurrentTask, hFirstTask );
+}
+
+
+/***********************************************************************
+ * GetCurrentPDB (KERNEL.37)
+ */
+WORD GetCurrentPDB(void)
+{
+ TDB *pTask;
+
+ if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return 0;
+ return pTask->hPDB;
+}
+
+
+/***********************************************************************
+ * GetNumTasks (KERNEL.152)
+ */
+WORD GetNumTasks(void)
+{
+ return nTaskCount;
+}
+
+
+/***********************************************************************
+ * GetTaskDS (KERNEL.155)
+ */
+WORD GetTaskDS(void)
+{
+ TDB *pTask;
+
+ if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return 0;
+ return pTask->hInstance;
+}
+
+
+/***********************************************************************
+ * IsTask (KERNEL.320)
+ */
+BOOL IsTask( HTASK hTask )
+{
+ TDB *pTask;
+
+ if (!(pTask = (TDB *)GlobalLock( hTask ))) return FALSE;
+ if (GlobalSize( hTask ) < sizeof(TDB)) return FALSE;
+ return (pTask->magic == TDB_MAGIC);
+}
+
+
+/***********************************************************************
+ * GetExePtr (KERNEL.133)
+ */
+HMODULE GetExePtr( HANDLE handle )
+{
+ char *ptr;
+ HTASK hTask;
+ HANDLE owner;
+
+ /* Check for module handle */
+
+ if (!(ptr = GlobalLock( handle ))) return 0;
+ if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return handle;
+
+ /* Check the owner for module handle */
+
+ owner = FarGetOwner( handle );
+ if (!(ptr = GlobalLock( owner ))) return 0;
+ if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return owner;
+
+ /* Search for this handle and its owner inside all tasks */
+
+ hTask = hFirstTask;
+ while (hTask)
+ {
+ TDB *pTask = (TDB *)GlobalLock( hTask );
+ if ((hTask == handle) ||
+ (pTask->hInstance == handle) ||
+ (pTask->hQueue == handle) ||
+ (pTask->hPDB == handle)) return pTask->hModule;
+ if ((hTask == owner) ||
+ (pTask->hInstance == owner) ||
+ (pTask->hQueue == owner) ||
+ (pTask->hPDB == owner)) return pTask->hModule;
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * TaskFirst (TOOLHELP.63)
+ */
+BOOL TaskFirst( TASKENTRY *lpte )
+{
+ lpte->hNext = hFirstTask;
+ return TaskNext( lpte );
+}
+
+
+/***********************************************************************
+ * TaskNext (TOOLHELP.64)
+ */
+BOOL TaskNext( TASKENTRY *lpte )
+{
+ TDB *pTask;
+ INSTANCEDATA *pInstData;
+
+ dprintf_toolhelp( stddeb, "TaskNext(%p): task=%04x\n", lpte, lpte->hNext );
+ if (!lpte->hNext) return FALSE;
+ pTask = (TDB *)GlobalLock( lpte->hNext );
+ if (!pTask || pTask->magic != TDB_MAGIC) return FALSE;
+ pInstData = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( pTask->hInstance, 0 );
+ lpte->hTask = lpte->hNext;
+ lpte->hTaskParent = pTask->hParent;
+ lpte->hInst = pTask->hInstance;
+ lpte->hModule = pTask->hModule;
+ lpte->wSS = pTask->ss;
+ lpte->wSP = pTask->sp;
+ lpte->wStackTop = pInstData->stacktop;
+ lpte->wStackMinimum = pInstData->stackmin;
+ lpte->wStackBottom = pInstData->stackbottom;
+ lpte->wcEvents = pTask->nEvents;
+ lpte->hQueue = pTask->hQueue;
+ strncpy( lpte->szModule, pTask->module_name, 8 );
+ lpte->szModule[8] = '\0';
+ lpte->wPSPOffset = 0x100; /*??*/
+ lpte->hNext = pTask->hNext;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * TaskFindHandle (TOOLHELP.65)
+ */
+BOOL TaskFindHandle( TASKENTRY *lpte, HTASK hTask )
+{
+ lpte->hNext = hTask;
+ return TaskNext( lpte );
}