--- /dev/null
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
--- /dev/null
+CFLAGS=-g
+
+######################################################################
+# FILES:
+#
+# Be very careful if you change the order of the files listed
+# here. if1632.o must linked first to guarrantee that it sits at a low
+# enough address. I intend to change this requirement someday, but
+# for now live with it.
+#
+DLL_LENGTH=256
+
+BUILDOBJS=dll_kernel.o dll_user.o dll_gdi.o dll_unixlib.o \
+ dll_kernel_tab.o dll_user_tab.o dll_gdi_tab.o dll_unixlib_tab.o
+
+MUST_BE_LINKED_FIRST=if1632.o $(BUILDOBJS)
+
+OBJS=$(MUST_BE_LINKED_FIRST) \
+ dump.o heap.o ldt.o kernel.o relay.o selector.o user.o wine.o
+
+TARGET=wine
+LIBS=-lldt
+
+all: $(TARGET) libldt.a
+
+clean:
+ rm -f *.o *~ *.s dll_*
+
+$(TARGET): $(OBJS)
+ $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
+
+build: build.c
+ cc -g -o build build.c
+
+libldt.a: ldtlib.c
+ $(CC) -O6 -c ldtlib.c
+ ar rcs libldt.a ldtlib.o
+
+dll_kernel.S dll_kernel_tab.c: build kernel.spec
+ build kernel.spec
+
+dll_user.S dll_user_tab.c: build user.spec
+ build user.spec
+
+dll_gdi.S dll_gdi_tab.c: build gdi.spec
+ build gdi.spec
+
+dll_unixlib.S dll_unixlib_tab.c: build unixlib.spec
+ build unixlib.spec
--- /dev/null
+Copyright Robert J. Amstadt, 1993. All code is provided without
+warranty. It is my intent to cover this code with the Gnu Public
+License.
+
+So here goes release 0.0.2 of the Windows loader. It will do some
+relocations and then run the program. The program test.exe is a
+Windows executable. Try the command "wine test.exe".
+
+WHAT'S NEW with version 0.0.2:
+
+ - Again thanks to Eric Youngdale for some very useful comments.
+ - The Windows startup code created by Micrsoft C 7.0 now runs
+ to completion.
+ - Added a new patch to the kernel to increase the usable size of
+ the ldt to the full 32 entries currently allowed.
+ - Imported name relocations are now supported.
+ - Source code for my infamous test program is now included.
+ - A handful of basic Windows functions are now emulated. See
+ "kernel.spec" for examples of how to use the build program.
+
+WHAT'S NEW with version 0.0.1:
+
+ - Eric Youngdale contributed countless improvements in memory
+ efficiency, bug fixes, and relocation.
+ - The build program has been completed. It now lets you specify
+ how the main DLL entry point should interface to your emulation
+ library routines. A brief description of how to build these
+ specifications is included in the file "build-spec.txt".
+ - The code to dispatch builtin DLL calls is complete, but untested.
+
+TODO:
+
+ - Segment fixup code completion.
+ - Make changes to the kernel to allow more than 32 LDT entries.
+ - Trap and handle DOS and DPMI calls.
+ - Windows emulation library (connect to Peter MacDonald's library).
+ - Set registers correctly when starting Windows program.
+ - Allowing loading of 16-bit DLLs for use with program.
+ - global memory allocation
+ - complete and improve local heap allocation
+
+INSTALLATION:
+
+ Uncompress and untar this archive into the directory of your
+choice. The file "ldt.tar" contains a necessary kernel patch against
+Linux 0.99.10. If you installed the "ldt.tar" from the first release
+of this package, then you MUST to replace it. In the directory
+/usr/src/linux (or whereever you keep your kernel sources), untar
+this file it contains three files:
+
+ kernel/ldt.c
+ - This is source for a new system call.
+
+ include/linux/ldt.h
+ - This contains structures defining the system call
+ interface.
+
+ ldt.patch
+ - This is a patch that must be applied to the kernel.
+ It updates two header files, and the kernel Makefile.
+
+BUILD:
+
+ The documentation for the build program is in the file build-spec.txt
+
+FINALE:
+
+Good luck,
+
+ If you successfully add anything, please send me a copy.
+
+Bob Amstadt
+bob@amscons.com
--- /dev/null
+name NAME
+id ID_NUMBER
+length NUMBER_OF_ORDINALS
+
+ORDINAL VARTYPE EXPORTNAME (DATA [DATA [DATA [...]]])
+
+ORDINAL FUNCTYPE EXPORTNAME([ARGTYPE [ARGTYPE [...]]])
+ HANDLERNAME([ARGNUM [ARGNUM [...]]])
+
+ORDINAL equate EXPORTNAME DATA
+--------------------
+General:
+
+ "name", "id" and "length" fields are mandatory. Specific ordinal
+declarations are optional, but the default handler will print an
+error message.
+
+Variable ordinals:
+
+ This type defines data storage at the ordinal specified. You may
+store items as bytes, 16-bit words, or 32-bit words.
+ "ORDINAL" is replaced by the ordinal number corresponding to the
+variable. "VARTYPE" should be "byte", "word" or "long" for 8, 16, or
+32 bits respectively. "EXPORTNAME" will be the name available for
+dynamic linking. "DATA" can be a decimal number or a hex number preceeded
+by "0x". The following example defines the variable "VariableA" at
+ordinal 2 and containing 4 bytes:
+
+ 2 byte VariableA -1 0xff 0 0
+
+Function ordinals:
+
+ This type defines a function entry point. The prototype defined
+by "EXPORTNAME ([ARGTYPE [ARGTYPE [...]]])" specifies the name available
+for dynamic linking and the format of the 16-bit stack. By specifying
+"FUNCTYPE", the loader can automatically determine which order the
+parameters were pushed by the calling routine. The prototype
+specified by "HANDLERNAME([ARGNUM [ARGNUM [...]]])" specifies to
+the loader how to call the 32-bit library routine which will handle this
+call. Note that specifying "ARGNUM" as 1 means the leftmost argument
+given to the function call, and not the first argument on the stack.
+For "pascal" functions, "ARGNUM" equal to 1 specifies the last
+argument on the stack. If you do not specify any arguments to the
+handler function, then address of the 16-bit argument stack is
+passed to the handler function.
+ "ORDINAL" is replaced by the ordinal number corresponding to the
+function. "FUNCTYPE" should be "c" or "pascal" ("pascal" may be
+shortened to "p"). "EXPORTNAME" will be the name available for
+dynamic linking. "ARGTYPE" should be "byte", "word", "long", "ptr",
+"s_byte" (signed byte), "s_word" (signed word) or "s_long"
+(signed long). "HANDLERNAME" is the name of the actual function
+that will process the request in 32-bit mode. "ARGNUM" is the
+original argument number. The first argument is numbered "1".
+
+ This first example defines an entry point for the CreateWindow()
+call (the ordinal 100 is just an example):
+
+ 100 pascal CreateWindow(ptr ptr long s_word s_word s_word s_word
+ word word word ptr)
+ WIN_CreateWindow(1 2 3 4 5 6 7 8 9 10 11)
+
+ This second example defines an entry point for the GetFocus()
+call (the ordinal 100 is just an example):
+
+ 100 pascal GetFocus() WIN_GetFocus()
+
+Equate ordinals:
+
+ This type defines an ordinal as an absolute value.
+"ORDINAL" is replaced by the ordinal number corresponding to the
+variable. "EXPORTNAME" will be the name available for dynamic linking.
+"DATA" can be a decimal number or a hex number preceeded by "0x".
+
+Return ordinals:
+
+ This type defines a function entry point whose handler should do
+nothing but return a value.
+ "ORDINAL" is replaced by the ordinal number corresponding to the
+variable. ARGLENGTH is the number of bytes that need to be removed
+from the stack before returning to the caller. RETVALUE is the
+return value which will be passed back to the caller.
--- /dev/null
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define VARTYPE_BYTE 0
+#define VARTYPE_SIGNEDWORD 0
+#define VARTYPE_WORD 1
+#define VARTYPE_LONG 2
+#define VARTYPE_FARPTR 3
+
+#define FUNCTYPE_PASCAL 16
+#define FUNCTYPE_C 17
+#define FUNCTYPE_REG 19
+
+#define EQUATETYPE_ABS 18
+
+#define MAX_ORDINALS 1024
+
+typedef struct ordinal_definition_s
+{
+ int valid;
+ int type;
+ char export_name[80];
+ void *additional_data;
+} ORDDEF;
+
+typedef struct ordinal_variable_definition_s
+{
+ int n_values;
+ int *values;
+} ORDVARDEF;
+
+typedef struct ordinal_function_definition_s
+{
+ int n_args_16;
+ int arg_types_16[16];
+ int arg_16_offsets[16];
+ int arg_16_size;
+ char internal_name[80];
+ int n_args_32;
+ int arg_indices_32[16];
+} ORDFUNCDEF;
+
+ORDDEF OrdinalDefinitions[MAX_ORDINALS];
+
+char LowerDLLName[80];
+char UpperDLLName[80];
+int Limit;
+int DLLId;
+FILE *SpecFp;
+
+char *ParseBuffer = NULL;
+char *ParseNext;
+char ParseSaveChar;
+int Line;
+
+int IsNumberString(char *s)
+{
+ while (*s != '\0')
+ if (!isdigit(*s++))
+ return 0;
+
+ return 1;
+}
+
+char *strlower(char *s)
+{
+ char *p;
+
+ for(p = s; *p != '\0'; p++)
+ *p = tolower(*p);
+
+ return s;
+}
+
+char *strupper(char *s)
+{
+ char *p;
+
+ for(p = s; *p != '\0'; p++)
+ *p = toupper(*p);
+
+ return s;
+}
+
+int stricmp(char *s1, char *s2)
+{
+ if (strlen(s1) != strlen(s2))
+ return -1;
+
+ while (*s1 != '\0')
+ if (*s1++ != *s2++)
+ return -1;
+
+ return 0;
+}
+
+char *
+GetTokenInLine(void)
+{
+ char *p;
+ char *token;
+
+ if (ParseNext != ParseBuffer)
+ {
+ if (ParseSaveChar == '\0')
+ return NULL;
+ *ParseNext = ParseSaveChar;
+ }
+
+ /*
+ * Remove initial white space.
+ */
+ for (p = ParseNext; isspace(*p); p++)
+ ;
+
+ if (*p == '\0')
+ return NULL;
+
+ /*
+ * Find end of token.
+ */
+ token = p++;
+ if (*token != '(' && *token != ')')
+ while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
+ p++;
+
+ ParseSaveChar = *p;
+ ParseNext = p;
+ *p = '\0';
+
+ return token;
+}
+
+char *
+GetToken(void)
+{
+ char *token;
+
+ if (ParseBuffer == NULL)
+ {
+ ParseBuffer = malloc(512);
+ ParseNext = ParseBuffer;
+ Line++;
+ if (fgets(ParseBuffer, 511, SpecFp) == NULL)
+ return NULL;
+ }
+
+ while ((token = GetTokenInLine()) == NULL)
+ {
+ ParseNext = ParseBuffer;
+ Line++;
+ if (fgets(ParseBuffer, 511, SpecFp) == NULL)
+ return NULL;
+ }
+
+ return token;
+}
+
+int
+ParseVariable(int ordinal, int type)
+{
+ ORDDEF *odp;
+ ORDVARDEF *vdp;
+ char export_name[80];
+ char *token;
+ char *endptr;
+ int *value_array;
+ int n_values;
+ int value_array_size;
+
+ strcpy(export_name, GetToken());
+
+ token = GetToken();
+ if (*token != '(')
+ {
+ fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
+ exit(1);
+ }
+
+ n_values = 0;
+ value_array_size = 25;
+ value_array = malloc(sizeof(*value_array) * value_array_size);
+
+ while ((token = GetToken()) != NULL)
+ {
+ if (*token == ')')
+ break;
+
+ value_array[n_values++] = strtol(token, &endptr, 0);
+ if (n_values == value_array_size)
+ {
+ value_array_size += 25;
+ value_array = realloc(value_array,
+ sizeof(*value_array) * value_array_size);
+ }
+
+ if (endptr == NULL || *endptr != '\0')
+ {
+ fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
+ token);
+ exit(1);
+ }
+ }
+
+ if (token == NULL)
+ {
+ fprintf(stderr, "%d: End of file in variable declaration\n", Line);
+ exit(1);
+ }
+
+ if (ordinal >= MAX_ORDINALS)
+ {
+ fprintf(stderr, "%d: Ordinal number too large\n", Line);
+ exit(1);
+ }
+
+ odp = &OrdinalDefinitions[ordinal];
+ odp->valid = 1;
+ odp->type = type;
+ strcpy(odp->export_name, export_name);
+
+ vdp = malloc(sizeof(*vdp));
+ odp->additional_data = vdp;
+
+ vdp->n_values = n_values;
+ vdp->values = realloc(value_array, sizeof(*value_array) * n_values);
+
+ return 0;
+}
+
+int
+ParseExportFunction(int ordinal, int type)
+{
+ char *token;
+ ORDDEF *odp;
+ ORDFUNCDEF *fdp;
+ int arg_types[16];
+ int i;
+ int arg_num;
+ int current_offset;
+ int arg_size;
+
+
+ if (ordinal >= MAX_ORDINALS)
+ {
+ fprintf(stderr, "%d: Ordinal number too large\n", Line);
+ exit(1);
+ }
+
+ odp = &OrdinalDefinitions[ordinal];
+ strcpy(odp->export_name, GetToken());
+ odp->valid = 1;
+ odp->type = type;
+ fdp = malloc(sizeof(*fdp));
+ odp->additional_data = fdp;
+
+ token = GetToken();
+ if (*token != '(')
+ {
+ fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
+ exit(1);
+ }
+
+ fdp->arg_16_size = 0;
+ for (i = 0; i < 16; i++)
+ {
+ token = GetToken();
+ if (*token == ')')
+ break;
+
+ if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
+ {
+ fdp->arg_types_16[i] = VARTYPE_WORD;
+ fdp->arg_16_size += 2;
+ fdp->arg_16_offsets[i] = 2;
+ }
+ else if (stricmp(token, "s_byte") == 0 ||
+ stricmp(token, "s_word") == 0)
+ {
+ fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
+ fdp->arg_16_size += 2;
+ fdp->arg_16_offsets[i] = 2;
+ }
+ else if (stricmp(token, "long") == 0 || stricmp(token, "s_long") == 0)
+ {
+ fdp->arg_types_16[i] = VARTYPE_LONG;
+ fdp->arg_16_size += 4;
+ fdp->arg_16_offsets[i] = 4;
+ }
+ else if (stricmp(token, "ptr") == 0)
+ {
+ fdp->arg_types_16[i] = VARTYPE_FARPTR;
+ fdp->arg_16_size += 4;
+ fdp->arg_16_offsets[i] = 4;
+ }
+ else
+ {
+ fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
+ exit(1);
+ }
+ }
+ fdp->n_args_16 = i;
+
+ if (type == FUNCTYPE_PASCAL || type == FUNCTYPE_REG)
+ {
+ current_offset = 0;
+ for (i--; i >= 0; i--)
+ {
+ arg_size = fdp->arg_16_offsets[i];
+ fdp->arg_16_offsets[i] = current_offset;
+ current_offset += arg_size;
+ }
+ }
+ else
+ {
+ current_offset = 0;
+ for (i = 0; i < fdp->n_args_16; i++)
+ {
+ arg_size = fdp->arg_16_offsets[i];
+ fdp->arg_16_offsets[i] = current_offset;
+ current_offset += arg_size;
+ }
+ }
+
+ strcpy(fdp->internal_name, GetToken());
+ token = GetToken();
+ if (*token != '(')
+ {
+ fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
+ exit(1);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ token = GetToken();
+ if (*token == ')')
+ break;
+
+ fdp->arg_indices_32[i] = atoi(token);
+ if (fdp->arg_indices_32[i] < 1 ||
+ fdp->arg_indices_32[i] > fdp->n_args_16)
+ {
+ fprintf(stderr, "%d: Bad argument index %d\n", Line,
+ fdp->arg_indices_32[i]);
+ exit(1);
+ }
+ }
+ fdp->n_args_32 = i;
+
+ return 0;
+}
+
+int
+ParseEquate(int ordinal)
+{
+ ORDDEF *odp;
+ char *token;
+ char *endptr;
+ int value;
+
+ if (ordinal >= MAX_ORDINALS)
+ {
+ fprintf(stderr, "%d: Ordinal number too large\n", Line);
+ exit(1);
+ }
+
+ odp = &OrdinalDefinitions[ordinal];
+ strcpy(odp->export_name, GetToken());
+
+ token = GetToken();
+ value = strtol(token, &endptr, 0);
+ if (endptr == NULL || *endptr != '\0')
+ {
+ fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
+ token);
+ exit(1);
+ }
+
+ odp->valid = 1;
+ odp->type = EQUATETYPE_ABS;
+ odp->additional_data = (void *) value;
+
+ return 0;
+}
+
+int
+ParseOrdinal(int ordinal)
+{
+ char *token;
+
+ token = GetToken();
+ if (token == NULL)
+ {
+ fprintf(stderr, "%d: Expected type after ordinal\n", Line);
+ exit(1);
+ }
+
+ if (stricmp(token, "byte") == 0)
+ return ParseVariable(ordinal, VARTYPE_BYTE);
+ else if (stricmp(token, "word") == 0)
+ return ParseVariable(ordinal, VARTYPE_WORD);
+ else if (stricmp(token, "long") == 0)
+ return ParseVariable(ordinal, VARTYPE_LONG);
+ else if (stricmp(token, "c") == 0)
+ return ParseExportFunction(ordinal, FUNCTYPE_C);
+ else if (stricmp(token, "p") == 0)
+ return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
+ else if (stricmp(token, "pascal") == 0)
+ return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
+ else if (stricmp(token, "register") == 0)
+ return ParseExportFunction(ordinal, FUNCTYPE_REG);
+ else if (stricmp(token, "equate") == 0)
+ return ParseEquate(ordinal);
+ else
+ {
+ fprintf(stderr,
+ "%d: Expected type after ordinal, found '%s' instead\n",
+ Line, token);
+ exit(1);
+ }
+}
+
+int
+ParseTopLevel(void)
+{
+ char *token;
+
+ while ((token = GetToken()) != NULL)
+ {
+ if (stricmp(token, "name") == 0)
+ {
+ strcpy(LowerDLLName, GetToken());
+ strlower(LowerDLLName);
+
+ strcpy(UpperDLLName, LowerDLLName);
+ strupper(UpperDLLName);
+ }
+ else if (stricmp(token, "id") == 0)
+ {
+ token = GetToken();
+ if (!IsNumberString(token))
+ {
+ fprintf(stderr, "%d: Expected number after id\n", Line);
+ exit(1);
+ }
+
+ DLLId = atoi(token);
+ }
+ else if (stricmp(token, "length") == 0)
+ {
+ token = GetToken();
+ if (!IsNumberString(token))
+ {
+ fprintf(stderr, "%d: Expected number after length\n", Line);
+ exit(1);
+ }
+
+ Limit = atoi(token);
+ }
+ else if (IsNumberString(token))
+ {
+ int ordinal;
+ int rv;
+
+ ordinal = atoi(token);
+ if ((rv = ParseOrdinal(ordinal)) < 0)
+ return rv;
+ }
+ else
+ {
+ fprintf(stderr,
+ "%d: Expected name, id, length or ordinal\n", Line);
+ exit(1);
+ }
+ }
+
+ return 0;
+}
+
+void
+OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
+{
+ ORDVARDEF *vdp;
+ int i;
+
+ fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+
+ vdp = odp->additional_data;
+ for (i = 0; i < vdp->n_values; i++)
+ {
+ if ((i & 7) == 0)
+ fprintf(fp, "\t%s\t", storage);
+
+ fprintf(fp, "%d", vdp->values[i]);
+
+ if ((i & 7) == 7 || i == vdp->n_values - 1)
+ fprintf(fp, "\n");
+ else
+ fprintf(fp, ", ");
+ }
+ fprintf(fp, "\n");
+}
+
+main(int argc, char **argv)
+{
+ ORDDEF *odp;
+ ORDFUNCDEF *fdp;
+ FILE *fp;
+ char filename[80];
+ char buffer[80];
+ char *p;
+ int i;
+
+ if (argc < 2)
+ {
+ fprintf(stderr, "usage: build SPECNAME\n");
+ exit(1);
+ }
+
+ SpecFp = fopen(argv[1], "r");
+ if (SpecFp == NULL)
+ {
+ fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
+ exit(1);
+ }
+
+ ParseTopLevel();
+
+ sprintf(filename, "dll_%s.S", LowerDLLName);
+ fp = fopen(filename, "w");
+
+ fprintf(fp, "\t.globl _%s_Dispatch\n", UpperDLLName);
+ fprintf(fp, "_%s_Dispatch:\n", UpperDLLName);
+ fprintf(fp, "\torl\t$0x%08x,%%eax\n", DLLId << 16);
+ fprintf(fp, "\tjmp\t_CallTo32\n\n");
+
+ odp = OrdinalDefinitions;
+ for (i = 0; i <= Limit; i++, odp++)
+ {
+ fprintf(fp, "\t.globl _%s_Ordinal_%d\n", UpperDLLName, i);
+
+ if (!odp->valid)
+ {
+ fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+ fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
+ fprintf(fp, "\tpushw\t$0\n");
+ fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
+ }
+ else
+ {
+ fdp = odp->additional_data;
+
+ switch (odp->type)
+ {
+ case EQUATETYPE_ABS:
+ fprintf(fp, "_%s_Ordinal_%d = %d\n\n",
+ UpperDLLName, i, (int) odp->additional_data);
+ break;
+
+ case VARTYPE_BYTE:
+ OutputVariableCode(fp, ".byte", odp);
+ break;
+
+ case VARTYPE_WORD:
+ OutputVariableCode(fp, ".word", odp);
+ break;
+
+ case VARTYPE_LONG:
+ OutputVariableCode(fp, ".long", odp);
+ break;
+
+ case FUNCTYPE_REG:
+ fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+ fprintf(fp, "\tpushw\t%%ax\n");
+ fprintf(fp, "\tpushw\t%%cx\n");
+ fprintf(fp, "\tpushw\t%%dx\n");
+ fprintf(fp, "\tpushw\t%%bx\n");
+ fprintf(fp, "\tpushw\t%%sp\n");
+ fprintf(fp, "\tpushw\t%%bp\n");
+ fprintf(fp, "\tpushw\t%%si\n");
+ fprintf(fp, "\tpushw\t%%di\n");
+ fprintf(fp, "\tpushw\t%%ds\n");
+ fprintf(fp, "\tpushw\t%%es\n");
+ fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
+ fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
+ fprintf(fp, "\tpushl\t20(%%ebp)\n");
+ fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
+ fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
+ fprintf(fp, "\tpushw\t$24\n");
+ fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
+ break;
+
+ case FUNCTYPE_PASCAL:
+ fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+ fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
+ fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
+ fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
+ break;
+
+ case FUNCTYPE_C:
+ default:
+ fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+ fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
+ fprintf(fp, "\tpushw\t$0\n");
+ fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
+ break;
+ }
+ }
+ }
+
+ fclose(fp);
+
+ sprintf(filename, "dll_%s_tab.c", LowerDLLName);
+ fp = fopen(filename, "w");
+
+ fprintf(fp, "#include <stdio.h>\n");
+ fprintf(fp, "#include <stdlib.h>\n");
+ fprintf(fp, "#include \042dlls.h\042\n\n");
+
+ for (i = 0; i <= Limit; i++)
+ {
+ fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
+ }
+
+ odp = OrdinalDefinitions;
+ for (i = 0; i <= Limit; i++, odp++)
+ {
+ if (odp->valid &&
+ (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_C ||
+ odp->type == FUNCTYPE_REG))
+ {
+ fdp = odp->additional_data;
+ fprintf(fp, "extern int %s();\n", fdp->internal_name);
+ }
+ }
+
+ fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n",
+ UpperDLLName, Limit + 1);
+ fprintf(fp, "{\n");
+ odp = OrdinalDefinitions;
+ for (i = 0; i <= Limit; i++, odp++)
+ {
+ fdp = odp->additional_data;
+
+ if (!odp->valid)
+ odp->type = -1;
+
+ switch (odp->type)
+ {
+ case FUNCTYPE_PASCAL:
+ case FUNCTYPE_REG:
+ fprintf(fp, " { 0x23, %s_Ordinal_%d, ", UpperDLLName, i);
+ fprintf(fp, "\042%s\042, ", odp->export_name);
+ fprintf(fp, "%s, DLL_HANDLERTYPE_PASCAL, ", fdp->internal_name);
+ fprintf(fp, "%d, ", fdp->n_args_32);
+ if (fdp->n_args_32 > 0)
+ {
+ int argnum;
+
+ fprintf(fp, "\n {\n");
+ for (argnum = 0; argnum < fdp->n_args_32; argnum++)
+ {
+ fprintf(fp, " { %d, %d },\n",
+ fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
+ fdp->arg_types_16[argnum]);
+ }
+ fprintf(fp, " }\n ");
+ }
+ fprintf(fp, "}, \n");
+ break;
+
+ case FUNCTYPE_C:
+ fprintf(fp, " { 0x23, %s_Ordinal_%d, ", UpperDLLName, i);
+ fprintf(fp, "\042%s\042, ", odp->export_name);
+ fprintf(fp, "%s, DLL_HANDLERTYPE_C, ", fdp->internal_name);
+ fprintf(fp, "%d, ", fdp->n_args_32);
+ if (fdp->n_args_32 > 0)
+ {
+ int argnum;
+
+ fprintf(fp, "\n {\n");
+ for (argnum = 0; argnum < fdp->n_args_32; argnum++)
+ {
+ fprintf(fp, " { %d, %d },\n",
+ fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
+ fdp->arg_types_16[argnum]);
+ }
+ fprintf(fp, " }\n ");
+ }
+ fprintf(fp, "}, \n");
+ break;
+
+ default:
+ fprintf(fp, " { 0x23, %s_Ordinal_%d, \042\042, NULL },\n",
+ UpperDLLName, i);
+ break;
+ }
+ }
+ fprintf(fp, "};\n");
+
+ fclose(fp);
+}
+
--- /dev/null
+/* $Id$
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+
+#ifndef DLLS_H
+#define DLLS_H
+
+typedef struct dll_arg_relocation_s
+{
+ unsigned short dst_arg; /* Offset to argument on stack */
+ unsigned char src_type; /* Argument type */
+} DLL_ARG;
+
+#define DLL_ARGTYPE_SIGNEDWORD 0
+#define DLL_ARGTYPE_WORD 1
+#define DLL_ARGTYPE_LONG 2
+#define DLL_ARGTYPE_FARPTR 3
+#define DLL_MAX_ARGS 16
+
+#define DLL_HANDLERTYPE_PASCAL 16
+#define DLL_HANDLERTYPE_C 17
+
+struct dll_table_entry_s
+{
+ /*
+ * Relocation data
+ */
+ unsigned int selector; /* Selector to access this entry point */
+ void *address; /* Offset in segment of entry point */
+
+ /*
+ * 16->32 bit interface data
+ */
+ char *export_name;
+ void *handler; /* Address of function to process request */
+ int handler_type; /* C or PASCAL calling convention */
+ int n_args; /* Number of arguments passed to function */
+ DLL_ARG args[DLL_MAX_ARGS]; /* Argument conversion data */
+};
+
+struct dll_name_table_entry_s
+{
+ char *dll_name;
+ struct dll_table_entry_s *dll_table;
+ int dll_table_length;
+ int dll_number;
+};
+
+extern struct dll_table_entry_s KERNEL_table[];
+extern struct dll_table_entry_s USER_table[];
+extern struct dll_table_entry_s GDI_table[];
+extern struct dll_table_entry_s UNIXLIB_table[];
+
+#endif /* DLLS_H */
--- /dev/null
+/* $Id$
+ */
+
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <linux/head.h>
+#include <linux/ldt.h>
+#include <errno.h>
+#include "neexe.h"
+#include "segmem.h"
+#include "prototypes.h"
+
+/**********************************************************************
+ * PrintFileHeader
+ */
+void
+PrintFileHeader(struct ne_header_s *ne_header)
+{
+ printf("ne_header: %c%c\n",
+ ne_header->header_type[0],
+ ne_header->header_type[1]);
+ printf("linker version: %d.%d\n", ne_header->linker_version,
+ ne_header->linker_revision);
+ printf("format flags: %04.4x\n", ne_header->format_flags);
+ printf("automatic data segment: %04.4x\n", ne_header->auto_data_seg);
+ printf("CS:IP %04.4x:%04.4x\n", ne_header->cs, ne_header->ip);
+ printf("SS:SP %04.4x:%04.4x\n", ne_header->ss, ne_header->sp);
+ printf("additional flags: %02.2x\n", ne_header->additional_flags);
+ printf("operating system: %02.2x\n", ne_header->operating_system);
+ printf("fast load offset: %04.4x\n", ne_header->fastload_offset);
+ printf("fast load length: %04.4x\n", ne_header->fastload_length);
+}
+\f
+/**********************************************************************
+ * PrintSegmentTable
+ */
+void
+PrintSegmentTable(struct ne_segment_table_entry_s *seg_table, int nentries)
+{
+ int i;
+
+ for (i = 0; i < nentries; i++)
+ {
+ printf(" %2d: OFFSET %04.4x, LENGTH %04.4x, ",
+ i + 1, seg_table[i].seg_data_offset,
+ seg_table[i].seg_data_length);
+ printf("FLAGS %04.4x, MIN ALLOC %04.4x\n",
+ seg_table[i].seg_flags, seg_table[i].min_alloc);
+ }
+}
+\f
+/**********************************************************************
+ * PrintRelocationTable
+ */
+void
+PrintRelocationTable(char *exe_ptr,
+ struct ne_segment_table_entry_s *seg_entry_p,
+ int segment)
+{
+ struct relocation_entry_s *rep;
+ int i;
+ int offset;
+ u_short n_entries, *sp;
+
+ printf("RELOCATION TABLE %d:\n", segment + 1);
+
+ if (seg_entry_p->seg_data_offset == 0)
+ return;
+
+ offset = seg_entry_p->seg_data_length;
+ if (offset == 0)
+ offset = 0x10000;
+
+ sp = (u_short *) (exe_ptr + seg_entry_p->seg_data_offset * 512 + offset);
+ n_entries = *sp;
+
+ rep = (struct relocation_entry_s *) (sp + 1);
+ for (i = 0; i < n_entries; i++, rep++)
+ {
+ printf(" ADDR TYPE %d, TYPE %d, OFFSET %04.4x,",
+ rep->address_type, rep->relocation_type, rep->offset);
+ printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
+ }
+}
--- /dev/null
+name gdi
+id 3
+length 256
--- /dev/null
+static char RCSId[] = "$Id$";
+static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "prototypes.h"
+
+typedef struct heap_mem_desc_s
+{
+ struct heap_mem_desc_s *prev, *next;
+ int length;
+} MDESC;
+
+MDESC *FreeList;
+
+/**********************************************************************
+ * HEAP_LocalInit
+ */
+void
+HEAP_LocalInit(void *start, int length)
+{
+ FreeList = (MDESC *) start;
+ FreeList->prev = NULL;
+ FreeList->next = NULL;
+ FreeList->length = length - sizeof(MDESC);
+}
+
+/**********************************************************************
+ * HEAP_LocalAlloc
+ */
+void *
+HEAP_LocalAlloc(int flags, int bytes)
+{
+ MDESC *m, *m_new;
+
+#ifdef HEAP_DEBUG
+ fprintf(stderr, "LocalAlloc: flags %x, bytes %d, ", flags, bytes);
+#endif
+
+ /*
+ * Find free block big enough.
+ */
+ for (m = FreeList; m != NULL; m = m->next)
+ {
+ if (m->length == bytes && m->length < bytes + 4 * sizeof(MDESC))
+ {
+ break;
+ }
+ else if (m->length > bytes)
+ {
+ m_new = m + (bytes / sizeof(MDESC)) + 2;
+ if (m->prev == NULL)
+ FreeList = m_new;
+ else
+ m->prev->next = m_new;
+
+ if (m->next != NULL)
+ m->next->prev = m_new;
+
+ m_new->next = m->next;
+ m_new->prev = m->prev;
+ m_new->length = m->length - ((int) m_new - (int) m);
+ m->length -= (m_new->length + sizeof(MDESC));
+
+#ifdef HEAP_DEBUG
+ fprintf(stderr, "Returning %x\n", (int) (m + 1));
+#endif
+ return (void *) (m + 1);
+ }
+ }
+
+ if (m != NULL)
+ {
+ if (m->prev == NULL)
+ FreeList = m->next;
+ else
+ m->prev->next = m->next;
+
+ if (m->next != NULL)
+ m->next->prev = m->prev;
+
+#ifdef HEAP_DEBUG
+ fprintf(stderr, "Returning %x\n", (int) (m + 1));
+#endif
+ return (void *) (m + 1);
+ }
+
+#ifdef HEAP_DEBUG
+ fprintf(stderr, "Returning 0\n");
+#endif
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+ .data
+jump_target:
+return_value:
+ .long 0
+
+/**********************************************************************
+ * Places to keep info about the current 32-bit stack frame.
+ */
+saved_esp:
+ .long 0
+saved_ebp:
+ .long 0
+saved_ss:
+ .word 0
+
+/**********************************************************************
+ * Places to keep info about the current 16-bit stack frame.
+ */
+saved_16esp:
+ .long 0
+saved_16ebp:
+ .long 0
+saved_16ss:
+ .word 0
+
+nbytes:
+ .word 0
+selector:
+ .word 0
+offset:
+ .word 0
+
+ .text
+
+/**********************************************************************
+ * int CallTo16(unsigned long csip, unsigned long sssp,
+ * unsigned short ds)
+ *
+ * Stack: 0 ebp
+ * 4 eip
+ * 8 target ip
+ * 10 target cs
+ * 12 target sp
+ * 14 target ss
+ * 16 target ds
+ */
+ .align 4
+ .globl _CallTo16
+_CallTo16:
+ pushl %ebp
+ movl %esp,%ebp
+
+ /*
+ * Save our registers
+ */
+ pushal
+ pushl saved_esp
+ pushl saved_ebp
+ pushw saved_ss
+
+ /*
+ * Get target address.
+ */
+ movl 8(%ebp),%eax
+ movl %eax,jump_target
+ lea jump_target,%edx
+
+ /*
+ * Put stack registers where we can get them after stack switch.
+ */
+ movw %ss,saved_ss
+ movl %esp,saved_esp
+ movl %ebp,saved_ebp
+
+ /*
+ * Load ds, es, sp, ss & bp
+ */
+ movl $0,%eax
+ movw _PSPSelector,%ax
+ movw %ax,%es
+ movw 16(%ebp),%ax
+ movw %ax,%ds
+ xorl %eax,%eax
+ movw 12(%ebp),%ax
+ movl %eax,%esp
+ movw 14(%ebp),%ax
+ movw %ax,%ss
+ movl %eax,%ebp
+
+ /*
+ * Call entry point
+ */
+ .byte 0x66
+ lcall %fs:(%edx)
+
+ /*
+ * Restore old stack and segment registers.
+ *
+ * Two choices here:
+ * 1. Trust that fs or gs hasn't changed.
+ * 2. Rely on knowledge of Linux use of segments.
+ *
+ * I'll opt for choice 2 because who knows what programs we
+ * going to run. Linux should be fairly stable in terms of
+ * GDT usage.
+ */
+ pushl %eax
+ movw $0x2b,%ax
+ movw %ax,%ds
+ movw %ax,%es
+ movw %ax,%fs
+ movw %ax,%gs
+ popl %eax
+ movw saved_ss,%ss
+ movl saved_esp,%esp
+ movl saved_ebp,%ebp
+
+ /*
+ * Restore registers, but do not destroy return value.
+ */
+ popw saved_ss
+ popl saved_ebp
+ popl saved_esp
+ movl %eax,return_value
+ popal
+ movl return_value,%eax
+ .align 2,0x90
+ leave
+ ret
+
+/**********************************************************************
+ * CallTo32()
+ *
+ * This function is called as a relay point to the built function
+ * handler. KERNEL, USER and GDI calls are dealt with by this
+ * handler. Calls to these DLLs will be mapped to a call handler
+ * which will set EAX to a number indicating which DLL and which
+ * function within that DLL.
+ *
+ * This function will pass to the function handler two arguments.
+ * The first argument will be the contents of EAX, the second
+ * argument will be a segment:offset pair that points to the
+ * 16-bit stack.
+ */
+ .align 4
+ .globl _CallTo32
+_CallTo32:
+ pushl %ebp
+ movl %esp,%ebp
+
+ /*
+ * Save registers. 286 mode does not have fs or gs.
+ */
+ pushw %ds
+ pushw %es
+
+ /*
+ * Restore segment registers.
+ */
+ pushl %eax
+ movw $0x2b,%ax
+ movw %ax,%ds
+ movw %ax,%es
+ popl %eax
+
+ /*
+ * Save old stack save variables, save stack registers, reload
+ * stack registers.
+ */
+ pushl saved_16esp
+ pushl saved_16ebp
+ pushw saved_16ss
+
+ movw %ss,saved_16ss
+ movl %esp,saved_16esp
+ movl %ebp,saved_16ebp
+
+ movw saved_ss,%ss
+ movl saved_esp,%esp
+ movl saved_ebp,%ebp
+
+ /*
+ * Call entry point
+ */
+ pushw saved_16ss
+ pushw saved_16esp
+ pushl %eax
+ call _DLLRelay
+
+ /*
+ * Restore registers, but do not destroy return value.
+ */
+ movw saved_16ss,%ss
+ movl saved_16esp,%esp
+ movl saved_16ebp,%ebp
+
+ popw saved_16ss
+ popl saved_16ebp
+ popl saved_16esp
+
+ popw %es
+ popw %ds
+
+ .align 2,0x90
+ leave
+ /*
+ * Now we need to ditch the parameter bytes that were left on the
+ * stack. We do this by effectively popping the number of bytes,
+ * and the return address, removing the parameters and then putting
+ * the return address back on the stack.
+ * Normally this field is filled in by the relevant function in
+ * the emulation library, since it should know how many bytes to
+ * expect.
+ */
+ popw %gs:nbytes
+ cmpw $0,%gs:nbytes
+ je noargs
+ popw %gs:offset
+ popw %gs:selector
+ addw %gs:nbytes,%esp
+ pushw %gs:selector
+ pushw %gs:offset
+noargs:
+
+ /*
+ * Last, but not least we need to move the high word from eax to dx
+ */
+ pushl %eax
+ popw %dx
+ popw %dx
+
+ .byte 0x66
+ lret
+
+/**********************************************************************
+ * KERNEL_InitTask()
+ *
+ * This interface functions is special because it returns all
+ * of its values in registers. Thus we can't just fall back through
+ * the C functions that called us. Instead we simply abandon
+ * the 32-bit stack, set up the registers and return.
+ */
+ .globl _KERNEL_InitTask
+_KERNEL_InitTask:
+ /*
+ * Restore stack
+ */
+ movw saved_16ss,%ss
+ movl saved_16esp,%esp
+ movl saved_16ebp,%ebp
+
+ popw saved_16ss
+ popl saved_16ebp
+ popl saved_16esp
+
+ popw %es
+ popw %ds
+
+ .align 2,0x90
+ leave
+ /*
+ * Now we need to ditch the parameter bytes that were left on the
+ * stack. We do this by effectively popping the number of bytes,
+ * and the return address, removing the parameters and then putting
+ * the return address back on the stack.
+ * Normally this field is filled in by the relevant function in
+ * the emulation library, since it should know how many bytes to
+ * expect.
+ */
+ popw %gs:nbytes
+ cmpw $0,%gs:nbytes
+ je noargs_2
+ popw %gs:offset
+ popw %gs:selector
+ addw %gs:nbytes,%esp
+ pushw %gs:selector
+ pushw %gs:offset
+noargs_2:
+
+ /*
+ * Last, we need to load the return values.
+ */
+ movw $1,%ax
+ movw %gs:_WIN_StackSize,%cx
+ movw $1,%dx
+ movw 0x80,%bx
+ movl $0,%esi
+ movl $1,%edi
+
+ .byte 0x66
+ lret
--- /dev/null
+static char RCSId[] = "$Id$";
+static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "prototypes.h"
+
+extern unsigned short *Stack16Frame;
+
+/**********************************************************************
+ * KERNEL_GetVersion
+ *
+ * Return the version of Windows that we emulate.
+ */
+int
+KERNEL_GetVersion(void)
+{
+ return 0x0301;
+}
+
+/**********************************************************************
+ * KERNEL_LockSegment
+ */
+int
+KERNEL_LockSegment(int segment)
+{
+ if (segment == -1)
+ segment = *(Stack16Frame + 6);
+
+#ifdef RELAY_DEBUG
+ fprintf(stderr, "LockSegment: segment %x\n", segment);
+#endif
+
+ return segment;
+}
+
+/**********************************************************************
+ * KERNEL_UnlockSegment
+ */
+int
+KERNEL_UnlockSegment(int segment)
+{
+ if (segment == -1)
+ segment = *(Stack16Frame + 6);
+
+#ifdef RELAY_DEBUG
+ fprintf(stderr, "UnlockSegment: segment %x\n", segment);
+#endif
+
+ return segment;
+}
+
+/**********************************************************************
+ * KERNEL_WaitEvent
+ */
+int
+KERNEL_WaitEvent(int task)
+{
+#ifdef RELAY_DEBUG
+ fprintf(stderr, "WaitEvent: task %d\n", task);
+#endif
+ return 0;
+}
+/**********************************************************************
+ * KERNEL_GetModuleFileName
+ */
+int
+KERNEL_GetModuleFileName(int module, char *filename, int bytes)
+{
+#ifdef RELAY_DEBUG
+ fprintf(stderr, "GetModuleFileName: module %d, filename %x, bytes %d\n",
+ module, filename, bytes);
+#endif
+
+ strcpy(filename, "TEST.EXE");
+
+ return strlen(filename);
+}
+
+/**********************************************************************
+ * KERNEL_DOS3Call
+ */
+int
+KERNEL_DOS3Call(int ax, int cx, int dx, int bx, int sp, int bp,
+ int si, int di, int ds, int es)
+{
+ switch ((ax >> 8) & 0xff)
+ {
+ case 0x30:
+ return 0x0303;
+
+ case 0x25:
+ case 0x35:
+ return 0;
+
+ default:
+ fprintf(stderr, "DOS: AX %04x, BX %04x, CX %04x, DX %04x\n",
+ ax, bx, cx, dx);
+ fprintf(stderr, " SP %04x, BP %04x, SI %04x, DI %04x\n",
+ sp, bp, si, di);
+ fprintf(stderr, " DS %04x, ES %04x\n",
+ ds, es);
+ }
+
+ return 0;
+}
--- /dev/null
+name kernel
+id 1
+length 256
+
+3 pascal GetVersion() KERNEL_GetVersion()
+5 pascal LocalAlloc(word word) HEAP_LocalAlloc(1 2)
+23 pascal LockSegment(s_word) KERNEL_LockSegment(1)
+24 pascal UnlockSegment(s_word) KERNEL_UnlockSegment(1)
+30 pascal WaitEvent(word) KERNEL_WaitEvent(1)
+49 pascal GetModuleFileName(word ptr s_word) KERNEL_GetModuleFileName(1 2 3)
+91 pascal InitTask() KERNEL_InitTask()
+102 register DOS3Call(word word word word word
+ word word word word word)
+ KERNEL_DOS3Call(1 2 3 4 5 6 7 8 9 10)
+131 pascal GetDOSEnvironment() GetDOSEnvironment()
+178 equate __WINFLAGS 0x413
--- /dev/null
+/* $Id$
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <linux/unistd.h>
+#include <linux/head.h>
+#include <linux/ldt.h>
+#include "prototypes.h"
+
+/**********************************************************************
+ * print_ldt
+ */
+void
+print_ldt()
+{
+ char buffer[0x10000];
+ struct modify_ldt_ldt_s ldt_info;
+ unsigned long *lp;
+ unsigned long base_addr, limit;
+ int type, dpl, i;
+
+ if (get_ldt(buffer) < 0)
+ exit(1);
+
+ lp = (unsigned long *) buffer;
+ for (i = 0; i < 32; i++, lp++)
+ {
+ /* First 32 bits of descriptor */
+ base_addr = (*lp >> 16) & 0x0000FFFF;
+ limit = *lp & 0x0000FFFF;
+ lp++;
+
+ /* First 32 bits of descriptor */
+ base_addr |= (*lp & 0xFF000000) | ((*lp << 16) & 0x00FF0000);
+ limit |= (*lp & 0x000F0000);
+ type = (*lp >> 9) & 7;
+ dpl = (*lp >> 13) & 3;
+
+ if (*lp & 1000)
+ {
+ printf("Entry %2d: Base %08.8x, Limit %05.5x, DPL %d, Type %d\n",
+ i, base_addr, limit, dpl, type);
+ printf(" ");
+ if (*lp & 0x100)
+ printf("Accessed, ");
+ if (*lp & 8000)
+ printf("Present, ");
+ if (*lp & 0x100000)
+ printf("User, ");
+ if (*lp & 0x200000)
+ printf("X, ");
+ if (*lp & 0x400000)
+ printf("32, ");
+ else
+ printf("16, ");
+ if (*lp & 0x800000)
+ printf("page limit, ");
+ else
+ printf("byte limit, ");
+ printf("\n");
+ printf(" %08.8x %08.8x\n", *(lp), *(lp-1));
+ }
+ else
+ {
+ printf("Entry %2d: Base %08.8x, Limit %05.5x, DPL %d, Type %d\n",
+ i, base_addr, limit, dpl, type);
+ printf(" SYSTEM: %08.8x %08.8x\n", *lp, *(lp-1));
+ }
+ }
+}
--- /dev/null
+/* $Id$
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <linux/unistd.h>
+#include <linux/head.h>
+#include <linux/ldt.h>
+
+_syscall2(int, modify_ldt, int, func, void *, ptr)
+
+int
+get_ldt(void *buffer)
+{
+ return modify_ldt(0, buffer);
+}
+
+int
+set_ldt_entry(int entry, unsigned long base, unsigned int limit,
+ int seg_32bit_flag, int contents, int read_only_flag,
+ int limit_in_pages_flag)
+{
+ struct modify_ldt_ldt_s ldt_info;
+
+ ldt_info.entry_number = entry;
+ ldt_info.base_addr = base;
+ ldt_info.limit = limit;
+ ldt_info.seg_32bit = seg_32bit_flag;
+ ldt_info.contents = contents;
+ ldt_info.read_exec_only = read_only_flag;
+ ldt_info.limit_in_pages = limit_in_pages_flag;
+
+ return modify_ldt(1, &ldt_info);
+}
--- /dev/null
+/* $Id: neexe.h,v 1.1 1993/06/09 03:28:10 root Exp root $
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+#ifndef NEEXE_H
+#define NEEXE_H
+
+/*
+ * Old MZ header for DOS programs. Actually just a couple of fields
+ * from it, so that we can find the start of the NE header.
+ */
+struct mz_header_s
+{
+ u_char dont_care1[0x18]; /* MZ Header stuff */
+ u_char must_be_0x40; /* 0x40 for non-MZ program */
+ u_char dont_care2[0x23]; /* More MZ header stuff */
+ u_short ne_offset; /* Offset to extended header */
+};
+
+/*
+ * This is the Windows executable (NE) header.
+ */
+struct ne_header_s
+{
+ char header_type[2]; /* Must contain 'N' 'E' */
+ u_char linker_version; /* Linker version number */
+ u_char linker_revision; /* Linker revision number */
+ u_short entry_tab_offset; /* Offset to entry table relative to NE */
+ u_short entry_tab_length; /* Length of etnry table in bytes */
+ u_long reserved1; /* Reserved by Microsoft */
+ u_short format_flags; /* Flags that segments in this file */
+ u_short auto_data_seg; /* Automatic data segment number */
+ u_short local_heap_length; /* Initial size of local heap */
+ u_short stack_length; /* Initial size of stack */
+ u_short ip; /* Initial IP */
+ u_short cs; /* Initial CS */
+ u_short sp; /* Initial SP */
+ u_short ss; /* Initial SS */
+ u_short n_segment_tab; /* # of entries in segment table */
+ u_short n_mod_ref_tab; /* # of entries in module reference tab.*/
+ u_short nrname_tab_length; /* Length of nonresident-name table */
+ u_short segment_tab_offset; /* Offset to segment table */
+ u_short resource_tab_offset;/* Offset to resource table */
+ u_short rname_tab_offset; /* Offset to resident-name table */
+ u_short moduleref_tab_offset;/* Offset to module reference table */
+ u_short iname_tab_offset; /* Offset to imported name table */
+ u_long nrname_tab_offset; /* Offset to nonresident-name table */
+ u_short n_mov_entry_points; /* # of movable entry points */
+ u_short align_shift_count; /* Logical sector alignment shift count */
+ u_short n_resource_seg; /* # of resource segments */
+ u_char operating_system; /* Flags indicating target OS */
+ u_char additional_flags; /* Additional information flags */
+ u_short fastload_offset; /* Offset to fast load area */
+ u_short fastload_length; /* Length of fast load area */
+ u_short reserved2; /* Reserved by Microsoft */
+ u_short expect_version; /* Expected Windows version number */
+};
+
+/*
+ * NE Header FORMAT FLAGS
+ */
+#define NE_FFLAGS_SINGLEDATA 0x0001
+#define NE_FFLAGS_MULTIPLEDATA 0x0002
+#define NE_FFLAGS_SELFLOAD 0x0800
+#define NE_FFLAGS_LINKERROR 0x2000
+#define NE_FFLAGS_LIBMODULE 0x8000
+
+/*
+ * NE Header OPERATING SYSTEM
+ */
+#define NE_OSFLAGS_UNKNOWN 0x01
+#define NE_OSFLAGS_WINDOWS 0x04
+
+/*
+ * NE Header ADDITIONAL FLAGS
+ */
+#define NE_AFLAGS_WIN2_PROTMODE 0x02
+#define NE_AFLAGS_WIN2_PROFONTS 0x04
+#define NE_AFLAGS_FASTLOAD 0x08
+
+/*
+ * Segment table entry
+ */
+struct ne_segment_table_entry_s
+{
+ u_short seg_data_offset; /* Sector offset of segment data */
+ u_short seg_data_length; /* Length of segment data */
+ u_short seg_flags; /* Flags associated with this segment */
+ u_short min_alloc; /* Minimum allocation size for this */
+};
+
+/*
+ * Segment Flags
+ */
+#define NE_SEGFLAGS_DATA 0x0001
+#define NE_SEGFLAGS_ALLOCATED 0x0002
+#define NE_SEGFLAGS_LOADED 0x0004
+#define NE_SEGFLAGS_MOVEABLE 0x0010
+#define NE_SEGFLAGS_SHAREABLE 0x0020
+#define NE_SEGFLAGS_PRELOAD 0x0040
+#define NE_SEGFLAGS_EXECUTEONLY 0x0080
+#define NE_SEGFLAGS_READONLY 0x0080
+#define NE_SEGFLAGS_RELOC_DATA 0x0100
+#define NE_SEGFLAGS_DISCARDABLE 0x1000
+
+/*
+ * Relocation table entry
+ */
+struct relocation_entry_s
+{
+ u_char address_type; /* Relocation address type */
+ u_char relocation_type; /* Relocation type */
+ u_short offset; /* Offset in segment to fixup */
+ u_short target1; /* Target specification */
+ u_short target2; /* Target specification */
+};
+
+/*
+ * Relocation address types
+ */
+#define NE_RADDR_LOWBYTE 0
+#define NE_RADDR_SELECTOR 2
+#define NE_RADDR_POINTER32 3
+#define NE_RADDR_OFFSET16 5
+#define NE_RADDR_POINTER48 11
+#define NE_RADDR_OFFSET32 13
+
+/*
+ * Relocation types
+ */
+#define NE_RELTYPE_INTERNAL 0
+#define NE_RELTYPE_ORDINAL 1
+#define NE_RELTYPE_NAME 2
+#define NE_RELTYPE_OSFIXUP 3
+
+/*
+ * DOS PSP
+ */
+struct dos_psp_s
+{
+ unsigned short pspInt20;
+ unsigned short pspNextParagraph;
+ unsigned char pspReserved1;
+ unsigned char pspDispatcher[5];
+ unsigned long pspTerminateVector;
+ unsigned long pspControlCVector;
+ unsigned long pspCritErrorVector;
+ unsigned short pspReserved2[11];
+ unsigned short pspEnvironment;
+ unsigned short pspReserved3[23];
+ unsigned char pspFCB_1[16];
+ unsigned char pspFCB_2[16];
+ unsigned char pspCommandTailCount;
+ unsigned char pspCommandTail[128];
+};
+
+#endif /* NEEXE_H */
--- /dev/null
+/* $Id$
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+#ifndef PROTOTYPES_H
+#define PROTOTYPES_H
+
+#include <sys/types.h>
+#include "neexe.h"
+#include "segmem.h"
+
+extern struct segment_descriptor_s *
+ CreateSelectors(int fd, struct ne_segment_table_entry_s *seg_table,
+ struct ne_header_s *ne_header);
+
+extern void PrintFileHeader(struct ne_header_s *ne_header);
+extern void PrintSegmentTable(struct ne_segment_table_entry_s *seg_table,
+ int nentries);
+extern void PrintRelocationTable(char *exe_ptr,
+ struct ne_segment_table_entry_s *seg_entry_p,
+ int segment);
+extern int FixupSegment(int fd, struct mz_header_s * mz_header,
+ struct ne_header_s *ne_header,
+ struct ne_segment_table_entry_s *seg_table,
+ struct segment_descriptor_s *selecetor_table,
+ int segment_num);
+extern struct dll_table_entry_s *FindDLLTable(char *dll_name);
+
+extern char WIN_CommandLine[];
+
+#endif /* PROTOTYPES_H */
--- /dev/null
+/* $Id$
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <linux/head.h>
+#include <linux/ldt.h>
+#include <linux/segment.h>
+#include <errno.h>
+#include "neexe.h"
+#include "segmem.h"
+#include "prototypes.h"
+#include "dlls.h"
+
+struct dll_name_table_entry_s dll_builtin_table[4] =
+{
+ { "KERNEL", KERNEL_table, 256, 1 },
+ { "USER", USER_table, 256, 2 },
+ { "GDI", GDI_table, 256, 3 },
+ { "UNIXLIB", UNIXLIB_table, 256, 4 },
+};
+
+unsigned short *Stack16Frame;
+
+/**********************************************************************
+ * DLLRelay
+ *
+ * We get a stack frame pointer to data that looks like this:
+ *
+ * Hex Offset Contents
+ * ---------- -------
+ * +00 previous saved_16ss
+ * +02 previous saved_16ebp
+ * +06 previous saved_16esp
+ * +0A 16-bit es
+ * +0C 16-bit ds
+ * +0E 16-bit ebp
+ * +12 length of 16-bit arguments
+ * +14 16-bit ip
+ * +16 16-bit cs
+ * +18 arguments
+ */
+int
+DLLRelay(unsigned int func_num, unsigned int seg_off)
+{
+ struct dll_table_entry_s *dll_p;
+ unsigned int segment;
+ unsigned int offset;
+ unsigned int dll_id;
+ unsigned int ordinal;
+ int arg_table[DLL_MAX_ARGS];
+ void *arg_ptr;
+ int (*func_ptr)();
+ int i;
+
+ /*
+ * Determine address of arguments.
+ */
+ Stack16Frame = (unsigned short *) seg_off;
+ arg_ptr = (void *) (seg_off + 0x18);
+
+ /*
+ * Extract the DLL number and ordinal number.
+ */
+ dll_id = ((func_num >> 16) & 0xffff) - 1;
+ ordinal = func_num & 0xffff;
+ dll_p = &dll_builtin_table[dll_id].dll_table[ordinal];
+
+#ifdef RELAY_DEBUG
+ {
+ unsigned int *ret_addr;
+ unsigned short *stack_p;
+
+ ret_addr = (unsigned int *) ((char *) seg_off + 0x14);
+ printf("RELAY: Calling %s.%d, 16-bit stack at %04x:%04x, ",
+ dll_builtin_table[dll_id].dll_name, ordinal,
+ seg_off >> 16, seg_off & 0xffff);
+ printf("return to %08x\n", *ret_addr);
+
+#ifdef STACK_DEBUG
+ stack_p = (unsigned short *) seg_off;
+ for (i = 0; i < 24; i++, stack_p++)
+ {
+ printf("%04x ", *stack_p);
+ if ((i & 7) == 7)
+ printf("\n");
+ }
+ printf("\n");
+#endif /* STACK_DEBUG */
+ }
+#endif /* RELAY_DEBUG */
+
+ /*
+ * Make sure we have a handler defined for this call.
+ */
+ if (dll_p->handler == NULL)
+ {
+ char buffer[100];
+
+ sprintf(buffer, "No handler for routine %s.%d",
+ dll_builtin_table[dll_id].dll_name, ordinal);
+ myerror(buffer);
+ }
+ func_ptr = dll_p->handler;
+
+ /*
+ * OK, special case. If the handler is define as taking no arguments
+ * then pass the address of the arguments on the 16-bit stack to the
+ * handler. It will just ignore the pointer if it really takes no
+ * arguments. This allows us to write slightly faster library routines
+ * if we choose.
+ */
+ if (dll_p->n_args == 0)
+ return (*func_ptr)(arg_ptr);
+
+ /*
+ * Getting this far means we need to convert the 16-bit argument stack.
+ */
+ for (i = 0; i < dll_p->n_args; i++)
+ {
+ short *sp;
+ int *ip;
+
+ offset = dll_p->args[i].dst_arg;
+
+ switch (dll_p->args[i].src_type)
+ {
+ case DLL_ARGTYPE_SIGNEDWORD:
+ sp = (short *) ((char *) arg_ptr + offset);
+ arg_table[i] = *sp;
+ break;
+
+ case DLL_ARGTYPE_WORD:
+ sp = (short *) ((char *) arg_ptr + offset);
+ arg_table[i] = (int) *sp & 0xffff;
+ break;
+
+ case DLL_ARGTYPE_LONG:
+ case DLL_ARGTYPE_FARPTR:
+ ip = (int *) ((char *) arg_ptr + offset);
+ arg_table[i] = *ip;
+ break;
+ }
+ }
+
+ /*
+ * Call the handler
+ */
+ return (*func_ptr)(arg_table[0], arg_table[1], arg_table[2],
+ arg_table[3], arg_table[4], arg_table[5],
+ arg_table[6], arg_table[7], arg_table[8],
+ arg_table[9], arg_table[10], arg_table[11],
+ arg_table[12], arg_table[13], arg_table[14],
+ arg_table[15]);
+}
+
+/**********************************************************************
+ * FindDLLTable
+ */
+struct dll_table_entry_s *
+FindDLLTable(char *dll_name)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (strcmp(dll_builtin_table[i].dll_name, dll_name) == 0)
+ return dll_builtin_table[i].dll_table;
+
+ return NULL;
+}
+
+/**********************************************************************
+ * FindOrdinalFromName
+ */
+int
+FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name)
+{
+ int i, limit;
+
+ for (i = 0; i < 4; i++)
+ if (dll_table == dll_builtin_table[i].dll_table)
+ break;
+
+ if (i == 4)
+ return 0;
+
+ limit = dll_builtin_table[i].dll_table_length;
+ for (i = 0; i < limit; i++)
+ if (strcasecmp(dll_table[i].export_name, func_name) == 0)
+ return i;
+
+ return 0;
+}
--- /dev/null
+/* $Id$
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+#ifndef SEGMEM_H
+#define SEGMEM_H
+
+/*
+ * Structure to hold info about each selector we create.
+ */
+
+struct segment_descriptor_s
+{
+ void *base_addr; /* Pointer to segment in flat memory */
+ unsigned int length; /* Length of segment */
+ unsigned int flags; /* Segment flags (see neexe.h and below)*/
+ unsigned short selector; /* Selector used to access this segment */
+};
+
+/*
+ * Additional flags
+ */
+#define NE_SEGFLAGS_MALLOCED 0x00010000 /* Memory allocated with malloc() */
+
+#endif /* SEGMEM_H */
--- /dev/null
+/* $Id: exedump.c,v 1.1 1993/06/09 03:28:10 root Exp root $
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <linux/head.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/ldt.h>
+#include <errno.h>
+#include "neexe.h"
+#include "segmem.h"
+#include "prototypes.h"
+
+struct segment_descriptor_s *SelectorTable;
+int SelectorTableLength;
+int EnvironmentSelectorIdx;
+int PSPSelectorIdx;
+unsigned short PSPSelector;
+
+extern void KERNEL_Ordinal_102();
+extern void UNIXLIB_Ordinal_0();
+
+\f
+/**********************************************************************
+ * GetDOSEnvironment
+ */
+void *
+GetDOSEnvironment()
+{
+ return SelectorTable[EnvironmentSelectorIdx].base_addr;
+}
+\f
+/**********************************************************************
+ * CreateEnvironment
+ */
+void
+CreateEnvironment(int sel_idx, struct segment_descriptor_s *s, FILE *zfile)
+{
+ char *p;
+
+ EnvironmentSelectorIdx = sel_idx;
+
+ /*
+ * Create memory to hold environment.
+ */
+ s->flags = NE_SEGFLAGS_DATA;
+ s->selector = (sel_idx << 3) | 0x0007;
+ s->length = PAGE_SIZE;
+ s->base_addr = (void *) mmap((char *) (s->selector << 16),
+ PAGE_SIZE,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
+
+ /*
+ * Fill environment with meaningless babble.
+ */
+ p = (char *) s->base_addr;
+ strcpy(p, "PATH=C:\\WINDOWS");
+ p += strlen(p) + 1;
+ *p++ = '\0';
+ *p++ = 11;
+ *p++ = 0;
+ strcpy(p, "C:\\TEST.EXE");
+
+ /*
+ * Create entry in LDT for this segment.
+ */
+ if (set_ldt_entry(sel_idx, (unsigned long) s->base_addr, s->length, 0,
+ MODIFY_LDT_CONTENTS_DATA, 0, 0) < 0)
+ {
+ myerror("Could not create LDT entry for environment");
+ }
+}
+\f
+/**********************************************************************
+ * CreatePSP
+ */
+void
+CreatePSP(int sel_idx, struct segment_descriptor_s *s, FILE *zfile)
+{
+ struct dos_psp_s *psp;
+ unsigned short *usp;
+
+ PSPSelectorIdx = sel_idx;
+
+ /*
+ * Create memory to hold PSP.
+ */
+ s->flags = NE_SEGFLAGS_DATA;
+ s->selector = (sel_idx << 3) | 0x0007;
+ s->length = PAGE_SIZE;
+ s->base_addr = (void *) mmap((char *) (s->selector << 16),
+ PAGE_SIZE,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
+
+ /*
+ * Fill PSP
+ */
+ PSPSelector = s->selector;
+ psp = (struct dos_psp_s *) s->base_addr;
+ psp->pspInt20 = 0x20cd;
+ psp->pspDispatcher[0] = 0x9a;
+ usp = (unsigned short *) &psp->pspDispatcher[1];
+ *usp = (unsigned short) KERNEL_Ordinal_102;
+ *(usp + 1) = 0x23;
+ psp->pspTerminateVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
+ psp->pspControlCVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
+ psp->pspCritErrorVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
+ psp->pspEnvironment = SelectorTable[EnvironmentSelectorIdx].selector;
+ psp->pspCommandTailCount = 1;
+ strcpy(psp->pspCommandTail, "\r");
+
+
+ /*
+ * Create entry in LDT for this segment.
+ */
+ if (set_ldt_entry(sel_idx, (unsigned long) s->base_addr, s->length, 0,
+ MODIFY_LDT_CONTENTS_DATA, 0, 0) < 0)
+ {
+ myerror("Could not create LDT entry for PSP");
+ }
+}
+\f
+/**********************************************************************
+ * CreateSelectors
+ */
+struct segment_descriptor_s *
+CreateSelectors(int fd, struct ne_segment_table_entry_s *seg_table,
+ struct ne_header_s *ne_header)
+{
+ struct segment_descriptor_s *selectors, *s;
+ int contents, read_only;
+ int i;
+ int status;
+ FILE * zfile;
+ int old_length;
+
+ /*
+ * Allocate memory for the table to keep track of all selectors.
+ */
+ SelectorTableLength = ne_header->n_segment_tab + 2;
+ selectors = malloc(SelectorTableLength * sizeof(*selectors));
+ if (selectors == NULL)
+ return NULL;
+ SelectorTable = selectors;
+
+ /*
+ * Step through the segment table in the exe header.
+ */
+ s = selectors;
+ zfile = fopen("/dev/zero","r");
+ for (i = 0; i < ne_header->n_segment_tab; i++, s++)
+ {
+ /*
+ * Store the flags in our table.
+ */
+ s->flags = seg_table[i].seg_flags;
+ s->selector = (i << 3) | 0x0007;
+
+ /*
+ * 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.
+ */
+ s->length = seg_table[i].min_alloc;
+ }
+ else
+ {
+ /*
+ * Image in file, let's just point to the image in memory.
+ */
+ s->length = seg_table[i].seg_data_length;
+ }
+
+ if (s->length == 0)
+ s->length = 0x10000;
+ old_length = s->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)
+ {
+ s->length += ne_header->local_heap_length;
+
+ if (i + 1 == ne_header->ss)
+ {
+ s->length += ne_header->stack_length;
+ ne_header->sp = s->length;
+ }
+ }
+
+ /*
+ * Is this a DATA or CODE segment?
+ */
+ read_only = 0;
+ if (s->flags & NE_SEGFLAGS_DATA)
+ {
+ contents = MODIFY_LDT_CONTENTS_DATA;
+ if (s->flags & NE_SEGFLAGS_READONLY)
+ read_only = 1;
+ }
+ else
+ {
+ contents = MODIFY_LDT_CONTENTS_CODE;
+ if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
+ read_only = 1;
+ }
+ s->base_addr =
+ (void *) mmap((char *) (s->selector << 16),
+ (s->length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1),
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
+ if (seg_table[i].seg_data_offset != 0)
+ {
+ /*
+ * Image in file.
+ */
+ status = lseek(fd, seg_table[i].seg_data_offset * 512, SEEK_SET);
+ if(read(fd, s->base_addr, old_length) != old_length)
+ myerror("Unable to read segment from file");
+ }
+ /*
+ * Create entry in LDT for this segment.
+ */
+ if (set_ldt_entry(i, (unsigned long) s->base_addr, s->length, 0,
+ contents, read_only, 0) < 0)
+ {
+ free(selectors);
+ return NULL;
+ }
+ /*
+ * If this is the automatic data segment, then we must initialize
+ * the local heap.
+ */
+ if (i + 1 == ne_header->auto_data_seg)
+ {
+ HEAP_LocalInit(s->base_addr + old_length,
+ ne_header->local_heap_length);
+ }
+ }
+
+ CreateEnvironment(i++, s++, zfile);
+ CreatePSP(i++, s++, zfile);
+
+ fclose(zfile);
+
+ return selectors;
+}
--- /dev/null
+name unixlib
+id 4
+length 256
+
+1 c _DebugPrintString(ptr) DebugPrintString(1)
\ No newline at end of file
--- /dev/null
+static char RCSId[] = "$Id$";
+static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "prototypes.h"
+
+/**********************************************************************
+ * USER_InitApp
+ *
+ * Load necessary resources?
+ */
+int
+USER_InitApp(int hInstance)
+{
+ return 1;
+}
--- /dev/null
+name user
+id 2
+length 256
+
+5 pascal InitApp(word) USER_InitApp(1)
\ No newline at end of file
--- /dev/null
+/* $Id: exedump.c,v 1.1 1993/06/09 03:28:10 root Exp root $
+ */
+/*
+ * Copyright Robert J. Amstadt, 1993
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <linux/head.h>
+#include <linux/ldt.h>
+#include <linux/segment.h>
+#include <errno.h>
+#include "neexe.h"
+#include "segmem.h"
+#include "prototypes.h"
+#include "dlls.h"
+
+extern int CallTo16(unsigned long csip, unsigned long sssp, unsigned short ds);
+extern void CallTo32();
+
+unsigned short WIN_StackSize;
+
+char **Argv;
+int Argc;
+
+/**********************************************************************
+ * DebugPrintString
+ */
+int
+DebugPrintString(char *str)
+{
+ fprintf(stderr, "%s", str);
+ return 0;
+}
+
+/**********************************************************************
+ * myerror
+ */
+void
+myerror(const char *s)
+{
+ char buffer[200];
+
+ sprintf(buffer, "%s", Argv[0]);
+ if (s == NULL)
+ perror(buffer);
+ else
+ fprintf(stderr, "%s: %s\n", buffer, s);
+
+ exit(1);
+}
+\f
+/**********************************************************************
+ * main
+ */
+main(int argc, char **argv)
+{
+ struct stat finfo;
+ struct mz_header_s *mz_header;
+ struct ne_header_s *ne_header;
+ struct ne_segment_table_entry_s *seg_table;
+ unsigned int status;
+ unsigned int read_size;
+ struct segment_descriptor_s *selector_table;
+ int fd;
+ int segment;
+ int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
+ int rv;
+
+ Argc = argc;
+ Argv = argv;
+
+ if (argc < 2)
+ {
+ fprintf(stderr, "usage: %s FILENAME\n", argv[0]);
+ exit(1);
+ }
+
+ /*
+ * Open file for reading.
+ */
+ fd = open(argv[1], O_RDONLY);
+ if (fd < 0)
+ {
+ myerror(NULL);
+ }
+
+ /*
+ * Allocate memory to hold entire executable.
+ */
+ if (fstat(fd, &finfo) < 0)
+ myerror(NULL);
+
+ /*
+ * Establish header pointers.
+ */
+ mz_header = (struct mz_header_s *) malloc(sizeof(struct mz_header_s));;
+ status = lseek(fd, 0, SEEK_SET);
+ if (read(fd, mz_header, sizeof(struct mz_header_s)) !=
+ sizeof(struct mz_header_s))
+ {
+ myerror("Unable to read MZ header from file");
+ }
+ if (mz_header->must_be_0x40 != 0x40)
+ myerror("This is not a Windows program");
+
+ ne_header = (struct ne_header_s *) malloc(sizeof(struct ne_header_s));
+ status = lseek(fd, mz_header->ne_offset, SEEK_SET);
+ if (read(fd, ne_header, sizeof(struct ne_header_s))
+ != sizeof(struct ne_header_s))
+ {
+ myerror("Unable to read NE header from file");
+ }
+ if (ne_header->header_type[0] != 'N' || ne_header->header_type[1] != 'E')
+ myerror("This is not a Windows program");
+
+ WIN_StackSize = ne_header->stack_length;
+
+
+ /*
+ * Create segment selectors.
+ */
+ status = lseek(fd, mz_header->ne_offset + ne_header->segment_tab_offset,
+ SEEK_SET);
+ read_size = ne_header->n_segment_tab *
+ sizeof(struct ne_segment_table_entry_s);
+ seg_table = (struct ne_segment_table_entry_s *) malloc(read_size);
+ if (read(fd, seg_table, read_size) != read_size)
+ myerror("Unable to read segment table header from file");
+ selector_table = CreateSelectors(fd, seg_table, ne_header);
+
+ /*
+ * Fixup references.
+ */
+ for (segment = 0; segment < ne_header->n_segment_tab; segment++)
+ {
+ if (FixupSegment(fd, mz_header, ne_header, seg_table,
+ selector_table, segment) < 0)
+ {
+ myerror("fixup failed.");
+ }
+ }
+
+ close(fd);
+ /*
+ * Fixup stack and jump to start.
+ */
+ ds_reg = selector_table[ne_header->auto_data_seg-1].selector;
+ cs_reg = selector_table[ne_header->cs-1].selector;
+ ip_reg = ne_header->ip;
+ ss_reg = selector_table[ne_header->ss-1].selector;
+ sp_reg = ne_header->sp;
+
+ rv = CallTo16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
+ printf ("rv = %x\n", rv);
+}
+
+\f
+/**********************************************************************
+ * GetImportedName
+ */
+char *
+GetImportedName(int fd, struct mz_header_s *mz_header,
+ struct ne_header_s *ne_header, int name_offset, char *buffer)
+{
+ char *p;
+ int length;
+ int status;
+ int i;
+
+ status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
+ name_offset, SEEK_SET);
+ length = 0;
+ read(fd, &length, 1); /* Get the length byte */
+ read(fd, buffer, length);
+ buffer[length] = 0;
+ return buffer;
+}
+
+/**********************************************************************
+ * GetModuleName
+ */
+char *
+GetModuleName(int fd, struct mz_header_s *mz_header,
+ struct ne_header_s *ne_header, int index, char *buffer)
+{
+ char *p;
+ int length;
+ int name_offset, status;
+ int i;
+
+ status = lseek(fd, mz_header->ne_offset + ne_header->moduleref_tab_offset +
+ 2*(index - 1), SEEK_SET);
+ name_offset = 0;
+ read(fd, &name_offset, 2);
+ status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
+ name_offset, SEEK_SET);
+ length = 0;
+ read(fd, &length, 1); /* Get the length byte */
+ read(fd, buffer, length);
+ buffer[length] = 0;
+ return buffer;
+}
+
+\f
+/**********************************************************************
+ * FixupSegment
+ */
+int
+FixupSegment(int fd, struct mz_header_s * mz_header,
+ struct ne_header_s *ne_header,
+ struct ne_segment_table_entry_s *seg_table,
+ struct segment_descriptor_s *selector_table,
+ int segment_num)
+{
+ struct relocation_entry_s *rep, *rep1;
+ struct ne_segment_table_entry_s *seg;
+ struct segment_descriptor_s *sel;
+ struct dll_table_entry_s *dll_table;
+ unsigned short *sp;
+ unsigned int selector, address;
+ unsigned int next_addr;
+ int ordinal;
+ int status;
+ char dll_name[257];
+ char func_name[257];
+ int i, n_entries;
+
+ seg = &seg_table[segment_num];
+ sel = &selector_table[segment_num];
+
+ if (seg->seg_data_offset == 0)
+ return 0;
+
+ /*
+ * Go through the relocation table on entry at a time.
+ */
+ i = seg->seg_data_length;
+ if (i == 0)
+ i = 0x10000;
+
+ status = lseek(fd, seg->seg_data_offset * 512 + i, SEEK_SET);
+ n_entries = 0;
+ read(fd, &n_entries, sizeof(short int));
+ rep = (struct relocation_entry_s *)
+ malloc(n_entries * sizeof(struct relocation_entry_s));
+
+ if (read(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++)
+ {
+ /*
+ * Get the target address corresponding to this entry.
+ */
+ switch (rep->relocation_type)
+ {
+ case NE_RELTYPE_ORDINAL:
+ if (GetModuleName(fd, mz_header, ne_header, rep->target1,
+ dll_name) == NULL)
+ {
+ return -1;
+ }
+
+ dll_table = FindDLLTable(dll_name);
+ ordinal = rep->target2;
+ selector = dll_table[ordinal].selector;
+ address = (unsigned int) dll_table[ordinal].address;
+#ifdef DEBUG_FIXUP
+ printf("%d: %s.%d: %04.4x:%04.4x\n", i + 1, dll_name, ordinal,
+ selector, address);
+#endif
+ break;
+
+ case NE_RELTYPE_NAME:
+ if (GetModuleName(fd, mz_header, ne_header, rep->target1, dll_name)
+ == NULL)
+ {
+ return -1;
+ }
+ dll_table = FindDLLTable(dll_name);
+
+ if (GetImportedName(fd, mz_header, ne_header,
+ rep->target2, func_name) == NULL)
+ {
+ return -1;
+ }
+ ordinal = FindOrdinalFromName(dll_table, func_name);
+ selector = dll_table[ordinal].selector;
+ address = (unsigned int) dll_table[ordinal].address;
+#ifdef DEBUG_FIXUP
+ printf("%d: %s %s.%d: %04.4x:%04.4x\n", i + 1, func_name,
+ dll_name, ordinal, selector, address);
+#endif
+ break;
+
+ case NE_RELTYPE_INTERNAL:
+ default:
+ free(rep1);
+ return -1;
+ }
+
+ /*
+ * Stuff the right size result in.
+ */
+ sp = (unsigned short *) ((char *) sel->base_addr + rep->offset);
+ switch (rep->address_type)
+ {
+ case NE_RADDR_OFFSET16:
+ do {
+ next_addr = *sp;
+ *sp = (unsigned short) address;
+ sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
+ }
+ while (next_addr != 0xffff);
+
+ break;
+
+ case NE_RADDR_POINTER32:
+ do {
+ next_addr = *sp;
+ *sp = (unsigned short) address;
+ *(sp+1) = (unsigned short) selector;
+ sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
+ }
+ while (next_addr != 0xffff);
+
+ break;
+
+ default:
+ free(rep1);
+ return -1;
+ }
+ }
+
+ free(rep1);
+ return 0;
+}
--- /dev/null
+/* MAIN.C\r
+ *\r
+ * PURPOSE: \r
+ *\r
+ * FUNCTIONS:\r
+ * WinMain() - Initializes app, calls all other functions.\r
+ */\r
+\r
+#include <windows.h>\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/*\r
+ * Globals\r
+ */\r
+char szAppName[] = "WineTest";\r
+\r
+extern long FAR PASCAL WineTestWndProc(HWND hwnd, unsigned message,\r
+ WORD wParam, LONG lParam);\r
+/* extern void FAR __cdecl DebugPrintString(const char FAR *str); */\r
+\f\r
+/* WinMain\r
+ */\r
+int PASCAL \r
+WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)\r
+{\r
+ DebugPrintString("Hello\n");\r
+\r
+ return 0;\r
+#if 0 \r
+ HWND hwnd;\r
+ MSG msg;\r
+ WNDCLASS wndclass;\r
+\r
+ if (hPrevInstance)\r
+ {\r
+ MessageBox(NULL, "This application is already running.", szAppName, \r
+ MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);\r
+ return NULL;\r
+ }\r
+\r
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;\r
+ wndclass.lpfnWndProc = WineTestWndProc;\r
+ wndclass.cbClsExtra = 0;\r
+ wndclass.cbWndExtra = 0;\r
+ wndclass.hInstance = hInstance;\r
+ wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);\r
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);\r
+ wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);\r
+ wndclass.lpszMenuName = "MainMenu";\r
+ wndclass.lpszClassName = szAppName;\r
+\r
+ RegisterClass(&wndclass);\r
+\r
+ hwnd = CreateWindow(szAppName, "Wine Tester",\r
+ WS_OVERLAPPEDWINDOW,\r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ NULL, \r
+ NULL,\r
+ hInstance, \r
+ NULL);\r
+ ShowWindow(hwnd, cmdShow);\r
+ UpdateWindow(hwnd);\r
+\r
+ while (GetMessage(&msg, NULL, NULL, NULL))\r
+ {\r
+ TranslateMessage((LPMSG) &msg);\r
+ DispatchMessage((LPMSG) &msg);\r
+ }\r
+\r
+ return msg.wParam;\r
+#endif /* 0 */\r
+}\r
+\r
+\f\r
+/* WineTestWndProc\r
+ */\r
+long FAR PASCAL \r
+WineTestWndProc(HWND hwnd, unsigned message, WORD wParam, LONG lParam)\r
+{\r
+ static HANDLE hInstance;\r
+ FARPROC DlgProcInst;\r
+ LONG parm;\r
+\r
+ switch (message)\r
+ {\r
+ case WM_CREATE:\r
+ hInstance = ((LPCREATESTRUCT) lParam)->hInstance;\r
+ return 0;\r
+\r
+ case WM_DESTROY:\r
+ PostQuitMessage(0);\r
+ return 0;\r
+ }\r
+\r
+ return DefWindowProc(hwnd, message, wParam, lParam);\r
+}\r
--- /dev/null
+####################################################################\r
+#\r
+# PPI standard windows makefile\r
+#\r
+####################################################################\r
+\r
+####################################################################\r
+#\r
+# Compiler options\r
+#\r
+AFLAGS=/ML /LA\r
+CFLAGS=-AM -Ozaxb2 -Gr -G2 -Zpei -W3 -DWINVER=0x0301\r
+LFLAGS=/CO\r
+\r
+####################################################################\r
+#\r
+# Object files and target\r
+#\r
+OBJS=main.obj\r
+DIALOGS=\r
+TARGET=winetest\r
+\r
+####################################################################\r
+#\r
+# Standard rules\r
+#\r
+ROOTS=$(OBJS:.obj=)\r
+\r
+all: $(TARGET).exe\r
+\r
+version:\r
+ coall -r$(RELEASE)\r
+ $(MAKE) all\r
+\r
+$(TARGET).res: $(TARGET).rc $(TARGET).h $(DIALOGS)\r
+ rc -r $(TARGET).rc\r
+\r
+$(TARGET).exe: $(TARGET).res $(TARGET).def $(TARGET).h $(OBJS)\r
+ link @<<\r
+$(ROOTS) /NOD $(LFLAGS)\r
+$@\r
+$(TARGET) /MAP:FULL\r
+libw slibcewn oldnames\r
+$(TARGET).def\r
+<<\r
+ rc -30 $(TARGET).res\r
+\r
--- /dev/null
+NAME WINETEST\r
+\r
+DESCRIPTION 'Wine Tester'\r
+EXETYPE WINDOWS\r
+STUB 'WINSTUB.EXE'\r
+CODE PRELOAD MOVEABLE DISCARDABLE\r
+DATA PRELOAD MOVEABLE SINGLE \r
+HEAPSIZE 8192\r
+STACKSIZE 8192\r
+EXPORTS WineTestWndProc\r
+IMPORTS UNIXLIB._DebugPrintString\r
--- /dev/null
+/* $Id$\r
+ */\r
--- /dev/null
+#include <windows.h>\r
+\r
+MainMenu MENU\r
+BEGIN\r
+ POPUP "&File"\r
+ BEGIN\r
+ MENUITEM "E&xit", 100\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&About...", 101\r
+ END\r
+END\r