summaryrefslogtreecommitdiffstats
path: root/private/os2/ldr
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/os2/ldr/basedef.h233
-rw-r--r--private/os2/ldr/basemac.h129
-rw-r--r--private/os2/ldr/bseerr.h856
-rw-r--r--private/os2/ldr/exe386.h870
-rw-r--r--private/os2/ldr/ldrdbcs.c159
-rw-r--r--private/os2/ldr/ldrdbcs.h48
-rw-r--r--private/os2/ldr/ldrdll.def28
-rw-r--r--private/os2/ldr/ldrextrn.h127
-rw-r--r--private/os2/ldr/ldrfixup.c483
-rw-r--r--private/os2/ldr/ldrinit.c1415
-rw-r--r--private/os2/ldr/ldrmte.c4290
-rw-r--r--private/os2/ldr/ldrste.c1159
-rw-r--r--private/os2/ldr/ldrsubr.c1962
-rw-r--r--private/os2/ldr/ldrutil.c228
-rw-r--r--private/os2/ldr/ldrvars.h928
-rw-r--r--private/os2/ldr/ldrvars.inc23
-rw-r--r--private/os2/ldr/makefile6
-rw-r--r--private/os2/ldr/mi.h497
-rw-r--r--private/os2/ldr/newexe.h464
-rw-r--r--private/os2/ldr/os2defp.h30
-rw-r--r--private/os2/ldr/seldesc.h265
-rw-r--r--private/os2/ldr/seldesc.inc163
-rw-r--r--private/os2/ldr/sources75
23 files changed, 14438 insertions, 0 deletions
diff --git a/private/os2/ldr/basedef.h b/private/os2/ldr/basedef.h
new file mode 100644
index 000000000..15de3ae40
--- /dev/null
+++ b/private/os2/ldr/basedef.h
@@ -0,0 +1,233 @@
+/*static char *SCCSID = "@(#)basedef.h 6.1 90/11/15";*/
+/*** BASEDEF.H
+ *
+ * SCCSID = @(#)basedef.h 13.11 90/07/10
+ *
+ * Basic constants and types
+ * Copyright (c) 1988,1989 Microsoft Corporation
+ *
+ *
+ * MODIFICATION HISTORY
+ * 10/10/88 JTP Created.
+ * 10/11/88 JTP Added more base types.
+ *
+ * To control what is included use the following:
+ *
+ * INCL_TYPES basic typedefs
+ */
+
+
+/*** Basic constants
+ */
+
+//c-begin
+#include <os2std.h>
+//c-end
+
+//masm-begin
+//NULL equ 0
+//TRUE equ -1
+//FALSE equ 0
+//masm-end
+
+#define CTRUE 1
+
+#define KSIZE 1024
+
+#ifdef INCL_PAGE
+#define PAGESIZE 4096
+#endif
+
+
+/*** Basic data types
+ */
+
+//c-begin
+#define CDECL _cdecl
+#define PASCAL _pascal
+#define VOID void
+#define CONST const
+#define VOLATILE volatile
+
+#ifdef M_I386
+#define FAR _near // p (32-bit pointer)
+#define NEAR _near // np (near pointer)
+#define FAR32 _far // fp (48-bit pointer, restricted)
+#else
+#define FAR _far
+#define NEAR _near
+#endif
+//c-end
+
+//masm-begin
+//DefType VOID
+//masm-end
+
+#define CENTRY CDECL FAR // to declare misc. C-based interfaces
+#define PRIVENTRY PASCAL FAR // to declare private routines
+#define EXPENTRY PASCAL FAR // to declare exported routines
+#define API32ENTRY PASCAL FAR // to declare exported API routines
+#define DYNENTRY PASCAL FAR _export // to declare exported dynlink routines
+
+#ifdef INCL_TYPES
+
+typedef int INT; // i
+typedef unsigned int UINT; // u
+typedef INT BOOL; // f
+
+typedef unsigned char BYTE; // b
+typedef unsigned short WORD; // w
+typedef unsigned long DWORD; // dw
+
+typedef char CHAR; // ch
+typedef unsigned char UCHAR; // uch
+typedef short SHORT; // s
+typedef unsigned short USHORT; // us
+typedef long LONG; // l
+typedef unsigned long ULONG; // ul
+
+typedef UCHAR BBOOL; // bf
+typedef USHORT SBOOL; // sf
+typedef ULONG LBOOL; // lf
+
+typedef ULONG FLAGS; // fl
+typedef ULONG PORT; // port
+
+
+/*** Basic pointer types
+ */
+typedef VOID FAR *PVOID; // p
+typedef VOID NEAR *NPVOID; // np
+
+
+/*** Basic pointer-to-basic-data types
+ */
+typedef INT FAR *PINT; // pi
+typedef INT NEAR *NPINT; // npi
+
+typedef UINT FAR *PUINT; // pu
+typedef UINT NEAR *NPUINT; // npu
+
+typedef BYTE FAR *PBYTE; // pb
+typedef BYTE NEAR *NPBYTE; // npb
+
+typedef WORD FAR *PWORD; // pw
+typedef WORD NEAR *NPWORD; // npw
+
+typedef DWORD FAR *PDWORD; // pdw
+typedef DWORD NEAR *NPDWORD; // npdw
+
+typedef CHAR FAR *PCHAR; // pch
+typedef CHAR NEAR *NPCHAR; // npch
+
+typedef SHORT FAR *PSHORT; // ps
+typedef SHORT NEAR *NPSHORT; // nps
+
+typedef LONG FAR *PLONG; // pl
+typedef LONG NEAR *NPLONG; // npl
+
+typedef UCHAR FAR *PUCHAR; // puch
+typedef UCHAR NEAR *NPUCHAR; // npuch
+
+typedef USHORT FAR *PUSHORT; // pus
+typedef USHORT NEAR *NPUSHORT; // npus
+
+typedef ULONG FAR *PULONG; // pul
+typedef ULONG NEAR *NPULONG; // npul
+
+typedef BOOL FAR *PBOOL; // pf
+typedef BOOL NEAR *NPBOOL; // npf
+
+typedef BBOOL FAR *PBBOOL; // pbf
+typedef BBOOL NEAR *NPBBOOL; // npbf
+
+typedef SBOOL FAR *PSBOOL; // psf
+typedef SBOOL NEAR *NPSBOOL; // npsf
+
+typedef LBOOL FAR *PLBOOL; // plf
+typedef LBOOL NEAR *NPLBOOL; // nplf
+
+typedef FLAGS FAR *PFLAGS; // pfl
+typedef FLAGS NEAR *NPFLAGS; // npfl
+
+typedef PVOID FAR *PPVOID; // pp
+typedef PVOID NEAR *NPPVOID; // npp
+
+
+/*** Other common types (and their pointers)
+ */
+typedef BYTE BUF[]; // buf
+typedef BUF FAR *PBUF; // pbuf
+
+typedef CHAR NAM[8]; // nam
+typedef CHAR SZ[]; // sz
+typedef CHAR FAR *PSZ; // psz
+typedef CHAR NEAR *NPSZ; // npsz
+typedef CHAR SZZ[]; // szz
+typedef CHAR FAR *PSZZ; // pszz
+typedef CHAR NEAR *NPSZZ; // npszz
+
+typedef USHORT SEL; // sel
+typedef SEL FAR *PSEL; // psel
+typedef SEL NEAR *NPSEL; // npsel
+
+typedef USHORT SOFFSET; // soff
+typedef ULONG OFFSET; // off
+
+typedef ULONG PPHYS; // pphys
+
+typedef (PASCAL FAR *PFN)(); // pfn
+typedef (PASCAL NEAR *NPFN)(); // npfn
+typedef (PASCAL FAR32 *FPFN)(); // fpfn
+typedef (PASCAL FAR32 *FPVOID)(); // fp (the only kind of FPVOID allowed)
+
+typedef PFN FAR *PPFN; // ppfn
+typedef PFN NEAR *NPPFN; // nppfn
+typedef FPFN FAR *PFPFN; // pfpfn
+typedef FPFN NEAR *NPFPFN; // npfpfn
+
+typedef USHORT SHANDLE; // sh
+typedef PVOID HANDLE; // h
+
+typedef struct _POINTL { // ptl
+ LONG x;
+ LONG y;
+} POINTL;
+typedef POINTL FAR *PPOINTL;
+
+typedef struct _RECTL { // rcl
+ LONG xLeft;
+ LONG yBottom;
+ LONG xRight;
+ LONG yTop;
+} RECTL;
+typedef RECTL FAR *PRECTL;
+
+typedef struct _RGB { // rgb
+ BYTE bBlue;
+ BYTE bGreen;
+ BYTE bRed;
+} RGB;
+typedef RGB FAR *PRGB;
+
+
+/*** OS/2-specific types
+ */
+typedef ULONG ERRCODE; // errc
+typedef ULONG RETCODE; // rc
+typedef USHORT SRETCODE; // src
+
+typedef USHORT PID; // pid
+typedef USHORT SGID; // sgid
+typedef USHORT TID; // tid
+
+typedef struct _RESULTCODES { // rsc
+ USHORT codeTerminate;
+ USHORT codeResult;
+} RESULTCODES;
+typedef RESULTCODES FAR *PRESULTCODES;
+
+typedef SHANDLE HFILE; // shf
+typedef HFILE FAR *PHFILE; // pshf
+
+#endif // INCL_TYPES
diff --git a/private/os2/ldr/basemac.h b/private/os2/ldr/basemac.h
new file mode 100644
index 000000000..c3dbd0e57
--- /dev/null
+++ b/private/os2/ldr/basemac.h
@@ -0,0 +1,129 @@
+/*static char *SCCSID = "@(#)basemac.h 6.1 90/11/15";*/
+/*** BASEMAC.H
+ *
+ * SCCSID = @(#)basemac.h 13.20 90/09/06
+ *
+ * Macros required for other include files
+ * Copyright (c) 1988,1989 Microsoft Corporation
+ *
+ *
+ * MODIFICATION HISTORY
+ * 10/14/88 JTP Created.
+ * 12/04/88 JTP Added OS/2-specific macros.
+ */
+
+
+/*** Generic macros
+ */
+
+#define NElements(array) ((sizeof array)/(sizeof array[0]))
+
+#define SWAP(a,b,tmp) (tmp=b, b=a, a=tmp)
+
+
+// Assorted macros from STDLIB.H...
+#define min(a, b) (((a) < (b))? (a) : (b))
+#define max(a, b) (((a) > (b))? (a) : (b))
+
+
+// To extract offset or selector from a FAR32 (16:32) pointer
+#define OFFSETOF32(p) (((PDWORD)&(p))[0])
+#define SEGMENTOF32(p) (((PWORD)&(p))[2])
+
+// To extract offset or selector from any FAR (16:16) pointer
+#define OFFSETOF16(p) (((PWORD)&(p))[0])
+#define SEGMENTOF16(p) (((PWORD)&(p))[1])
+
+// For now, the default operators assume they're working on 16:16 pointers
+#define OFFSETOF OFFSETOF16
+#define SEGMENTOF SEGMENTOF16
+
+// To convert a tiled 16:16 address to a 0:32 address
+#define MAKEFLATP(fp) ((PVOID)((SEGMENTOF(fp)&~7)<<13 | OFFSETOF(fp)))
+
+// To extract any byte, word, dword, pfn, etc. from the given item
+#define BYTEOF(p,i) (((PBYTE)&(p))[i])
+#define WORDOF(p,i) (((PWORD)&(p))[i])
+#define DWORDOF(p,i) (((PDWORD)&(p))[i])
+#define PFNOF(p,i) (((PPFN)&(p))[i])
+
+// To test/set bits
+#define TESTBIT(i,b) (((i)&(b)) != 0)
+#define SETBIT(i,b,f) (i = ((i)&~(b)) | (b)*(!!(f)))
+#define SETBITB(i,b,f) (i = (BYTE)(((i)&~(b)) | (b)*(!!(f))))
+
+// ZEROBITS returns the number of low zero bits in a 32-bit constant
+#define _Z2(l) ((l)&1?0:(l)&2?1:2)
+#define _Z4(l) ((l)&3?_Z2(l):_Z2((l)>>2)+2)
+#define _Z8(l) ((l)&15?_Z4(l):_Z4((l)>>4)+4)
+#define _Z16(l) ((l)&255?_Z8(l):_Z8((l)>>8)+8)
+#define _Z32(l) ((l)&65535?_Z16(l):_Z16((l)>>16)+16)
+#define ZEROBITS(l) _Z32(l)
+
+// LOG2 returns the nearest base-2 log of a 32-bit constant, rounded up
+#define _L2(l) ((l)&~1?2:(l)&1)
+#define _L4(l) ((l)&~3?_L2((l)>>2)+2:_L2(l))
+#define _L8(l) ((l)&~15?_L4((l)>>4)+4:_L4(l))
+#define _L16(l) ((l)&~255?_L8((l)>>8)+8:_L8(l))
+#define _L32(l) ((l)&~65535?_L16((l)>>16)+16:_L16(l))
+#define LOG2(l) _L32((l)-1)
+
+// EXP2 returns 2 raised to the given power
+#define EXP2(l) (1 << (l))
+
+// Unit conversion macros
+#define KBFROMBYTES(nb) (((nb)+KSIZE-1)/KSIZE)
+#define BYTESFROMKB(nkb) ((nkb)*KSIZE)
+#define PAGESFROMBYTES(nb) (((nb)+PAGESIZE-1)/PAGESIZE)
+
+// To obtain a pointer to the page containing the given linear address
+#define PPAGEFROMP(p) ((PVOID)((ULONG)(p) & ~(PAGESIZE-1)))
+#define PPAGEFROMPGNO(p) ((PVOID)((ULONG)(p) * PAGESIZE))
+#define PGNOFROMP(p) ((ULONG)(p) / PAGESIZE)
+
+
+// To create a usable FAR pointer from an unusable FAR16 pointer
+#define FPFROMF16P(fp,f16p) OFFSETOF32(fp) = OFFSETOF16(f16p),\
+ SEGMENTOF32(fp) = SEGMENTOF16(f16p)
+
+// To create pointers from V86-mode segments+offsets
+// Note the validity of these pointers depends on the context they're used in
+#define PFROMVP(vp) ((PVOID)((WORDOF(vp,1)<<4)+WORDOF(vp,0)))
+#define PFROMVADDR(seg,off) ((PVOID)(((WORD)(seg)<<4)+(WORD)(off)))
+#define VPFROMVADDR(seg,off) ((VPVOID)(((WORD)(seg)<<16)|(WORD)(off)))
+
+// To create V86 pointers from normal (flat) pointers
+#define HISEG(p) ((USHORT)((ULONG)(p)>>4))
+#define LOOFF(p) ((USHORT)((ULONG)(p)&0xf))
+#define VPFROMP(p) ((VPVOID)((((ULONG)(p)&~0xf)<<12)|((ULONG)(p)&0xf)))
+
+#define LOSEG(p) (((ULONG)(p)-HIOFF(p))>>4)
+#define HIOFF(p) (min(0xfff0,(ULONG)(p)&0xffff0)|((ULONG)(p)&0xf))
+#define LOSEGVPFROMP(p) ((VPVOID)((LOSEG(p)<<16)|HIOFF(p)))
+
+
+// To calculate the byte offset of a field in a structure of type "type"
+#define FIELDOFFSET(type,field) ((ULONG)&(((type *)0)->field))
+
+
+/*** Older stuff (discouraged -JTP)
+ */
+
+// To extract high and low order parts of a 32-bit quantity
+#define LOUSHORT(l) (((PUSHORT)&(l))[0])
+#define HIUSHORT(l) (((PUSHORT)&(l))[1])
+
+// To create pointer from V86-mode segment+offset
+#define SEGOFF2P(seg,off) ((PVOID)((seg<<4)+(USHORT)off))
+
+
+/*** OS/2-specific macros
+ */
+
+#ifdef INCL_SSTODS
+
+#define SSToDS(p) ((void *) (TKSSBase + (unsigned) (p)))
+
+extern char *TKSSBase;
+
+#endif
diff --git a/private/os2/ldr/bseerr.h b/private/os2/ldr/bseerr.h
new file mode 100644
index 000000000..aacab0988
--- /dev/null
+++ b/private/os2/ldr/bseerr.h
@@ -0,0 +1,856 @@
+/*static char *SCCSID = "@(#)bseerr.h 6.9 91/03/29";*/
+/****************************** Module Header ******************************\
+*
+* Module Name: BSEERR.H
+*
+* This file includes the error codes for Base OS/2 applications.
+*
+* Copyright (c) 1987 Microsoft Corporation
+*
+* ===========================================================================
+*
+* The following symbols are used in this file for conditional sections.
+*
+* INCL_DOSERRORS - OS/2 Errors - only included if symbol defined
+* INCL_ERROR_H - Set from error.h - to be deleted when error.h deleted
+* INCL_ERROR2_H - Set from error2.h - to be deleted when error.h deleted
+*
+* Note that the message id's for the first 1000 error codes (in basemid.h)
+* are constructed from the comment on the #define for those error codes.
+* See h.mak and basemid.skl for further information. Note that some message
+* id's conflict with error codes, so some error codes are unusable. In
+* other words, if there is a message id defined in a certain location,
+* that position may not, in general, be used for an error id.
+*
+* There are three formats of these special comments:
+* #define ERROR_NO <nnn> <opencomment> <MSG>%<none> <closecomment>
+* #define ERROR_NO <nnn> <opencomment> <MSG>%<message_name> <closecomment>
+* <opencomment> <nnn>%<msg>%<message_name> <closecomment>
+* The first version is used when there is an error id, but no message id
+* associated with it. This is the case when the error is an internal error
+* and is never seen by the user, or it is incorrect and there really should
+* be a message.
+*
+* The second format is used when there is both an error id and message id.
+*
+* The third case is used when there is a message id in that position, but no
+* error id. It may also be used when there is more than one message id for
+* a particular error id.
+*
+* Whenever a new error id is defined, the person defining that error MUST
+* decide if it is to be a user-seeable error or not. If it is, a message
+* id MUST be declared, and the appropriate message added to oso001.txt.
+* This should be coordinated with the IBM Instructional Design people.
+* The current contact is Kathleen Hamill.
+*
+\***************************************************************************/
+
+#ifdef INCL_ERRORS
+
+#define INCL_DOSERRORS
+#define INCL_ERROR_H
+#define INCL_ERROR2_H
+
+#endif /* INCL_ERRORS */
+
+#if defined(INCL_DOSERRORS) || defined(INCL_ERROR_H)
+
+#define NO_ERROR 0 /* MSG%RESPONSE_DATA */
+#define ERROR_INVALID_FUNCTION 1 /* MSG%INVALID_FUNCTION */
+#define ERROR_FILE_NOT_FOUND 2 /* MSG%FILE_NOT_FOUND */
+#define ERROR_PATH_NOT_FOUND 3 /* MSG%PATH_NOT_FOUND */
+#define ERROR_TOO_MANY_OPEN_FILES 4 /* MSG%OUT_OF_HANDLES */
+#define ERROR_ACCESS_DENIED 5 /* MSG%ACCESS_DENIED */
+#define ERROR_INVALID_HANDLE 6 /* MSG%INVALID_HANDLE */
+#define ERROR_ARENA_TRASHED 7 /* MSG%MEMORY_BLOCKS_BAD */
+#define ERROR_NOT_ENOUGH_MEMORY 8 /* MSG%NO_MEMORY */
+#define ERROR_INVALID_BLOCK 9 /* MSG%INVALID_MEM_ADDR */
+#define ERROR_BAD_ENVIRONMENT 10 /* MSG%INVALID_ENVIRON */
+#define ERROR_BAD_FORMAT 11 /* MSG%INVALID_FORMAT */
+#define ERROR_INVALID_ACCESS 12 /* MSG%INVALID_ACC_CODE */
+#define ERROR_INVALID_DATA 13 /* MSG%INVALID_DATA */
+#define ERROR_INVALID_DRIVE 15 /* MSG%INVALID_DRIVE */
+#define ERROR_CURRENT_DIRECTORY 16 /* MSG%ATT_RD_CURDIR */
+#define ERROR_NOT_SAME_DEVICE 17 /* MSG%NOT_SAME_DEVICE */
+#define ERROR_NO_MORE_FILES 18 /* MSG%NO_MORE_FILES */
+#define ERROR_WRITE_PROTECT 19 /* MSG%ATT_WRITE_PROT */
+#define ERROR_BAD_UNIT 20 /* MSG%UNKNOWN_UNIT */
+#define ERROR_NOT_READY 21 /* MSG%DRIVE_NOT_READY */
+#define ERROR_BAD_COMMAND 22 /* MSG%UNKNOWN_COMMAND */
+#define ERROR_CRC 23 /* MSG%DATA_ERROR */
+#define ERROR_BAD_LENGTH 24 /* MSG%BAD_REQ_STRUCTURE */
+#define ERROR_SEEK 25 /* MSG%SEEK_ERROR */
+#define ERROR_NOT_DOS_DISK 26 /* MSG%UNKNOWN_MEDIA */
+#define ERROR_SECTOR_NOT_FOUND 27 /* MSG%SECTOR_NOT_FOUND */
+#define ERROR_OUT_OF_PAPER 28 /* MSG%OUT_OF_PAPER */
+#define ERROR_WRITE_FAULT 29 /* MSG%WRITE_FAULT */
+#define ERROR_READ_FAULT 30 /* MSG%READ_FAULT */
+#define ERROR_GEN_FAILURE 31 /* MSG%GENERAL_FAILURE */
+#define ERROR_SHARING_VIOLATION 32 /* MSG%SHARING_VIOLATION */
+/* 32%msg%SHAR_VIOLAT_FIND */
+#define ERROR_LOCK_VIOLATION 33 /* MSG%LOCK_VIOLATION */
+#define ERROR_WRONG_DISK 34 /* MSG%INVALID_DISK_CHANGE */
+#define ERROR_FCB_UNAVAILABLE 35 /* MSG%35 */
+#define ERROR_SHARING_BUFFER_EXCEEDED 36 /* MSG%SHARING_BUFF_OFLOW */
+#define ERROR_CODE_PAGE_MISMATCHED 37 /* MSG%ERROR_WRITE_PROTECT */
+#define ERROR_HANDLE_EOF 38 /* MSG%ERROR_BAD_UNIT */
+#define ERROR_HANDLE_DISK_FULL 39 /* MSG%ERROR_NOT_READY */
+/* 40%msg%ERROR_BAD_COMMAND */
+/* 41%msg%ERROR_CRC */
+/* 42%msg%ERROR_BAD_LENGTH */
+/* 43%msg%ERROR_SEEK */
+/* 44%msg%ERROR_NOT_DOS_DISK */
+/* 45%msg%ERROR_SECTOR_NOT_FOUND */
+/* 46%msg%ERROR_OUT_OF_PAPER */
+/* 47%msg%ERROR_WRITE_FAULT */
+/* 48%msg%ERROR_READ_FAULT */
+/* 49%msg%ERROR_GEN_FAILURE */
+#define ERROR_NOT_SUPPORTED 50 /* MSG%NET_REQ_NOT_SUPPORT */
+#define ERROR_REM_NOT_LIST 51 /* MSG%NET_REMOTE_NOT_ONLINE */
+#define ERROR_DUP_NAME 52 /* MSG%NET_DUP_FILENAME */
+#define ERROR_BAD_NETPATH 53 /* MSG%NET_PATH_NOT_FOUND */
+#define ERROR_NETWORK_BUSY 54 /* MSG%NET_BUSY */
+#define ERROR_DEV_NOT_EXIST 55 /* MSG%NET_DEV_NOT_INSTALLED */
+#define ERROR_TOO_MANY_CMDS 56 /* MSG%NET_BIOS_LIMIT_REACHED */
+#define ERROR_ADAP_HDW_ERR 57 /* MSG%NET_ADAPT_HRDW_ERROR */
+#define ERROR_BAD_NET_RESP 58 /* MSG%NET_INCORRECT_RESPONSE */
+#define ERROR_UNEXP_NET_ERR 59 /* MSG%NET_UNEXPECT_ERROR */
+#define ERROR_BAD_REM_ADAP 60 /* MSG%NET_REMOT_ADPT_INCOMP */
+#define ERROR_PRINTQ_FULL 61 /* MSG%NET_PRINT_Q_FULL */
+#define ERROR_NO_SPOOL_SPACE 62 /* MSG%NET_NO_SPACE_TO_PRINT_FL */
+#define ERROR_PRINT_CANCELLED 63 /* MSG%NET_PRINT_FILE_DELETED */
+#define ERROR_NETNAME_DELETED 64 /* MSG%NET_NAME_DELETED */
+#define ERROR_NETWORK_ACCESS_DENIED 65 /* MSG%NET_ACCESS_DENIED */
+#define ERROR_BAD_DEV_TYPE 66 /* MSG%NET_DEV_TYPE_INVALID */
+#define ERROR_BAD_NET_NAME 67 /* MSG%NET_NAME_NOT_FOUND */
+#define ERROR_TOO_MANY_NAMES 68 /* MSG%NET_NAME_LIMIT_EXCEED */
+#define ERROR_TOO_MANY_SESS 69 /* MSG%NET_BIOS_LIMIT_EXCEED */
+#define ERROR_SHARING_PAUSED 70 /* MSG%NET_TEMP_PAUSED */
+#define ERROR_REQ_NOT_ACCEP 71 /* MSG%NET_REQUEST_DENIED */
+#define ERROR_REDIR_PAUSED 72 /* MSG%NET_PRT_DSK_REDIR_PAUSE */
+#define ERROR_SBCS_ATT_WRITE_PROT 73 /* Attempted write on protected disk */
+#define ERROR_SBCS_GENERAL_FAILURE 74 /* General failure */
+#define ERROR_XGA_OUT_MEMORY 75 /* MSG%XGA_OUT_MEMORY */
+#define ERROR_FILE_EXISTS 80 /* MSG%FILE_EXISTS */
+#define ERROR_DUP_FCB 81 /* MSG%none */
+#define ERROR_CANNOT_MAKE 82 /* MSG%CANNOT_MAKE */
+#define ERROR_FAIL_I24 83 /* MSG%NET_FAIL_INT_TWO_FOUR */
+#define ERROR_OUT_OF_STRUCTURES 84 /* MSG%NET_TOO_MANY_REDIRECT */
+#define ERROR_ALREADY_ASSIGNED 85 /* MSG%NET_DUP_REDIRECTION */
+#define ERROR_INVALID_PASSWORD 86 /* MSG%NET_INVALID_PASSWORD */
+#define ERROR_INVALID_PARAMETER 87 /* MSG%NET_INCORR_PARAMETER */
+#define ERROR_NET_WRITE_FAULT 88 /* MSG%NET_DATA_FAULT */
+#define ERROR_NO_PROC_SLOTS 89 /* MSG%NO_PROC_SLOTS */
+#define ERROR_NOT_FROZEN 90 /* MSG%none */
+#define ERROR_SYS_COMP_NOT_LOADED ERROR_NOT_FROZEN
+#define ERR_TSTOVFL 91 /* MSG%none */
+#define ERR_TSTDUP 92 /* MSG%none */
+#define ERROR_NO_ITEMS 93 /* MSG%none */
+#define ERROR_INTERRUPT 95 /* MSG%none */
+#define ERROR_DEVICE_IN_USE 99 /* MSG%DEVICE_IN_USE */
+#define ERROR_TOO_MANY_SEMAPHORES 100 /* MSG%TOO_MANY_SEMAPHORES */
+#define ERROR_EXCL_SEM_ALREADY_OWNED 101 /* MSG%EXCL_SEM_ALREADY_OWNED */
+#define ERROR_SEM_IS_SET 102 /* MSG%SEM_IS_SET */
+#define ERROR_TOO_MANY_SEM_REQUESTS 103 /* MSG%TOO_MANY_SEM_REQUESTS */
+#define ERROR_INVALID_AT_INTERRUPT_TIME 104 /* MSG%INVALID_AT_INTERRUPT_TIME */
+#define ERROR_SEM_OWNER_DIED 105 /* MSG%SEM_OWNER_DIED */
+#define ERROR_SEM_USER_LIMIT 106 /* MSG%ERROR_DISK_CHANGE */
+#define ERROR_DISK_CHANGE 107 /* MSG%DISK_CHANGE */
+#define ERROR_DRIVE_LOCKED 108 /* MSG%DRIVE_LOCKED */
+#define ERROR_BROKEN_PIPE 109 /* MSG%BROKEN_PIPE */
+#define ERROR_OPEN_FAILED 110 /* MSG%ERROR_OPEN_FAILED */
+#define ERROR_BUFFER_OVERFLOW 111 /* MSG%ERROR_FILENAME_LONG */
+#define ERROR_DISK_FULL 112 /* MSG%DISK_FULL */
+#define ERROR_NO_MORE_SEARCH_HANDLES 113 /* MSG%NO_SEARCH_HANDLES */
+#define ERROR_INVALID_TARGET_HANDLE 114 /* MSG%ERR_INV_TAR_HANDLE */
+#define ERROR_PROTECTION_VIOLATION 115 /* MSG%none */
+#define ERROR_VIOKBD_REQUEST 116 /* MSG%none */
+#define ERROR_INVALID_CATEGORY 117 /* MSG%INVALID_CATEGORY */
+#define ERROR_INVALID_VERIFY_SWITCH 118 /* MSG%INVALID_VERIFY_SWITCH */
+#define ERROR_BAD_DRIVER_LEVEL 119 /* MSG%BAD_DRIVER_LEVEL */
+#define ERROR_CALL_NOT_IMPLEMENTED 120 /* MSG%BAD_DYNALINK */
+#define ERROR_SEM_TIMEOUT 121 /* MSG%SEM_TIMEOUT */
+#define ERROR_INSUFFICIENT_BUFFER 122 /* MSG%INSUFFICIENT_BUFFER */
+#define ERROR_INVALID_NAME 123 /* MSG%INVALID_NAME */
+/* 123%msg%HPFS_INVALID_VOLUME_CHAR */
+#define ERROR_INVALID_LEVEL 124 /* MSG%INVALID_LEVEL */
+#define ERROR_NO_VOLUME_LABEL 125 /* MSG%NO_VOLUME_LABEL */
+#define ERROR_MOD_NOT_FOUND 126 /* MSG%MOD_NOT_FOUND */
+#define ERROR_PROC_NOT_FOUND 127 /* MSG%PROC_NOT_FOUND */
+#define ERROR_WAIT_NO_CHILDREN 128 /* MSG%none */
+#define ERROR_CHILD_NOT_COMPLETE 129 /* MSG%PROT_MODE_ONLY */
+#define ERROR_DIRECT_ACCESS_HANDLE 130 /* MSG%APPL_SINGLEFRAMECHAR */
+#define ERROR_NEGATIVE_SEEK 131 /* MSG%APPL_DOUBLEFRAMECHAR */
+#define ERROR_SEEK_ON_DEVICE 132 /* MSG%APPL_ARROWCHAR */
+#define ERROR_IS_JOIN_TARGET 133 /* MSG%JOIN_ON_DRIV_IS_TAR */
+#define ERROR_IS_JOINED 134 /* MSG%JOIN_DRIVE_IS */
+#define ERROR_IS_SUBSTED 135 /* MSG%SUB_DRIVE_IS */
+#define ERROR_NOT_JOINED 136 /* MSG%DRIVE_IS_NOT_JOINED */
+#define ERROR_NOT_SUBSTED 137 /* MSG%DRIVE_NOT_SUBSTED */
+#define ERROR_JOIN_TO_JOIN 138 /* MSG%JOIN_CANNOT_JOIN_DRIVE */
+#define ERROR_SUBST_TO_SUBST 139 /* MSG%SUB_CANNOT_SUBST_DRIVE */
+#define ERROR_JOIN_TO_SUBST 140 /* MSG%JOIN_CANNOT_SUB_DRIVE */
+#define ERROR_SUBST_TO_JOIN 141 /* MSG%SUB_CANNOT_JOIN_DRIVE */
+#define ERROR_BUSY_DRIVE 142 /* MSG%DRIVE_IS_BUSY */
+#define ERROR_SAME_DRIVE 143 /* MSG%JOIN_SUB_SAME_DRIVE */
+#define ERROR_DIR_NOT_ROOT 144 /* MSG%DIRECT_IS_NOT_SUBDIR */
+#define ERROR_DIR_NOT_EMPTY 145 /* MSG%DIRECT_IS_NOT_EMPTY */
+#define ERROR_IS_SUBST_PATH 146 /* MSG%PATH_USED_SUBST_JOIN */
+#define ERROR_IS_JOIN_PATH 147 /* MSG%NO_NEEDED_RESOURCES */
+#define ERROR_PATH_BUSY 148 /* MSG%PATH_BUSY */
+#define ERROR_IS_SUBST_TARGET 149 /* MSG%SUB_ON_DRIVE_IS_JOIN */
+#define ERROR_SYSTEM_TRACE 150 /* MSG%SYSTEM_TRACE */
+#define ERROR_INVALID_EVENT_COUNT 151 /* MSG%INVALID_EVENT_COUNT */
+#define ERROR_TOO_MANY_MUXWAITERS 152 /* MSG%TOO_MANY_MUXWAITERS */
+#define ERROR_INVALID_LIST_FORMAT 153 /* MSG%INVALID_LIST_FORMAT */
+#define ERROR_LABEL_TOO_LONG 154 /* MSG%VOLUME_TOO_LONG */
+/* 154%msg%HPFS_VOL_LABEL_LONG */
+#define ERROR_TOO_MANY_TCBS 155 /* MSG%TOO_MANY_TCBS */
+#define ERROR_SIGNAL_REFUSED 156 /* MSG%SIGNAL_REFUSED */
+#define ERROR_DISCARDED 157 /* MSG%DISCARDED */
+#define ERROR_NOT_LOCKED 158 /* MSG%NOT_LOCKED */
+#define ERROR_BAD_THREADID_ADDR 159 /* MSG%BAD_THREADID_ADDR */
+#define ERROR_BAD_ARGUMENTS 160 /* MSG%BAD_ARGUMENTS */
+#define ERROR_BAD_PATHNAME 161 /* MSG%none */
+#define ERROR_SIGNAL_PENDING 162 /* MSG%SIGNAL_PENDING */
+#define ERROR_UNCERTAIN_MEDIA 163 /* MSG%none */
+#define ERROR_MAX_THRDS_REACHED 164 /* MSG%MAX_THRDS_REACHED */
+#define ERROR_MONITORS_NOT_SUPPORTED 165 /* MSG%none */
+#define ERROR_UNC_DRIVER_NOT_INSTALLED 166 /* MSG%UNC_DRIVER_NOT_INSTALLED */
+#define ERROR_LOCK_FAILED 167 /* MSG%LOCK_FAILED */
+#define ERROR_SWAPIO_FAILED 168 /* MSG%SWAPIO_FAILED */
+#define ERROR_SWAPIN_FAILED 169 /* MSG%SWAPIN_ATTEMPT_FAILED */
+#define ERROR_BUSY 170 /* MSG%SEGMENT_BUSY */
+/* 171%msg%INT_TOO_LONG */
+#define ERROR_CANCEL_VIOLATION 173 /* MSG%UNLOCK_VIOLATION */
+#define ERROR_ATOMIC_LOCK_NOT_SUPPORTED 174 /* MSG%none */
+#define ERROR_READ_LOCKS_NOT_SUPPORTED 175 /* MSG%none */
+#define ERROR_INVALID_SEGMENT_NUMBER 180 /* MSG%INVALID_SEGMENT_NUM */
+#define ERROR_INVALID_CALLGATE 181 /* MSG%none */
+#define ERROR_INVALID_ORDINAL 182 /* MSG%INVALID_ORDINAL */
+#define ERROR_ALREADY_EXISTS 183 /* MSG%none */
+#define ERROR_NO_CHILD_PROCESS 184 /* MSG%none */
+#define ERROR_CHILD_ALIVE_NOWAIT 185 /* MSG%none */
+#define ERROR_INVALID_FLAG_NUMBER 186 /* MSG%INVALID_FLAG_NUMBER */
+#define ERROR_SEM_NOT_FOUND 187 /* MSG%SEM_NOT_FOUND */
+#define ERROR_INVALID_STARTING_CODESEG 188 /* MSG%INVALID_STARTING_CODESEG */
+#define ERROR_INVALID_STACKSEG 189 /* MSG%INVALID_STACKSEG */
+#define ERROR_INVALID_MODULETYPE 190 /* MSG%INVALID_MODULETYPE */
+#define ERROR_INVALID_EXE_SIGNATURE 191 /* MSG%INVALID_EXE_SIGNATURE */
+#define ERROR_EXE_MARKED_INVALID 192 /* MSG%EXE_MARKED_INVALID */
+#define ERROR_BAD_EXE_FORMAT 193 /* MSG%BAD_EXE_FORMAT */
+#define ERROR_ITERATED_DATA_EXCEEDS_64k 194 /* MSG%ITERATED_DATA_EXCEEDS_64K */
+#define ERROR_INVALID_MINALLOCSIZE 195 /* MSG%INVALID_MINALLOCSIZE */
+#define ERROR_DYNLINK_FROM_INVALID_RING 196 /* MSG%DYNLINK_FROM_INVALID_RING */
+#define ERROR_IOPL_NOT_ENABLED 197 /* MSG%IOPL_NOT_ENABLED */
+#define ERROR_INVALID_SEGDPL 198 /* MSG%INVALID_SEGDPL */
+#define ERROR_AUTODATASEG_EXCEEDS_64k 199 /* MSG%AUTODATASEG_EXCEEDS_64K */
+#define ERROR_RING2SEG_MUST_BE_MOVABLE 200 /* MSG%CODESEG_CANNOT_BE_64K */
+#define ERROR_RELOC_CHAIN_XEEDS_SEGLIM 201 /* MSG%RELOC_CHAIN_XEEDS_SEGMENT */
+#define ERROR_INFLOOP_IN_RELOC_CHAIN 202 /* MSG%INFLOOP_IN_RELOC_CHAIN */
+#define ERROR_ENVVAR_NOT_FOUND 203 /* MSG%ENVVAR_NOT_FOUND */
+#define ERROR_NOT_CURRENT_CTRY 204 /* MSG%none */
+#define ERROR_NO_SIGNAL_SENT 205 /* MSG%SIGNAL_NOT_SENT */
+#define ERROR_FILENAME_EXCED_RANGE 206 /* MSG%NAME_TOO_LONG */
+#define ERROR_RING2_STACK_IN_USE 207 /* MSG%RING2_STACK_IN_USE */
+#define ERROR_META_EXPANSION_TOO_LONG 208 /* MSG%WILD_CARD_NAME */
+#define ERROR_INVALID_SIGNAL_NUMBER 209 /* MSG%INVALID_SIGNAL_NUMBER */
+#define ERROR_THREAD_1_INACTIVE 210 /* MSG%THREAD_1_INACTIVE */
+#define ERROR_INFO_NOT_AVAIL 211 /* MSG%none */
+#define ERROR_LOCKED 212 /* MSG%LOCKED */
+#define ERROR_BAD_DYNALINK 213 /* MSG%none */
+#define ERROR_TOO_MANY_MODULES 214 /* MSG%TOO_MANY_MODULES */
+#define ERROR_NESTING_NOT_ALLOWED 215 /* MSG%none */
+#define ERROR_CANNOT_SHRINK 216 /* MSG%CANNOT_SHRINK */
+#define ERROR_ZOMBIE_PROCESS 217 /* MSG%none */
+#define ERROR_STACK_IN_HIGH_MEMORY 218 /* MSG%none */
+#define ERROR_INVALID_EXITROUTINE_RING 219 /* MSG%INVALID_EXITROUTINE_RING */
+#define ERROR_GETBUF_FAILED 220 /* MSG%none */
+#define ERROR_FLUSHBUF_FAILED 221 /* MSG%none */
+#define ERROR_TRANSFER_TOO_LONG 222 /* MSG%none */
+#define ERROR_FORCENOSWAP_FAILED 223 /* MSG%none */
+#define ERROR_SMG_NO_TARGET_WINDOW 224 /* PM ID can't be selected */
+#define ERROR_NO_CHILDREN 228 /* MSG%NO_CHILDREN */
+#define ERROR_INVALID_SCREEN_GROUP 229 /* MSG%none */
+#define ERROR_BAD_PIPE 230 /* MSG%ERROR_BAD_PIPE */
+#define ERROR_PIPE_BUSY 231 /* MSG%ERROR_PIPE_BUSY */
+#define ERROR_NO_DATA 232 /* MSG%ERROR_NO_DATA */
+#define ERROR_PIPE_NOT_CONNECTED 233 /* MSG%ERROR_PIPE_NOT_CONNECTED */
+#define ERROR_MORE_DATA 234 /* MSG%ERROR_MORE_DATA */
+#define ERROR_VC_DISCONNECTED 240 /* MSG%ERROR_VC_DISCONNECTED */
+#define ERROR_CIRCULARITY_REQUESTED 250 /* MSG%CIRCULARITY_REQUESTED */
+#define ERROR_DIRECTORY_IN_CDS 251 /* MSG%DIRECTORY_IN_CDS */
+#define ERROR_INVALID_FSD_NAME 252 /* MSG%INVALID_FSD_NAME */
+#define ERROR_INVALID_PATH 253 /* MSG%INVALID_PATH */
+#define ERROR_INVALID_EA_NAME 254 /* MSG%INVALID_EA_NAME */
+#define ERROR_EA_LIST_INCONSISTENT 255 /* MSG%EA_LIST_INCONSISTENT */
+#define ERROR_EA_LIST_TOO_LONG 256 /* MSG%EA_LIST_TOO_LONG */
+#define ERROR_NO_META_MATCH 257 /* MSG%NO_META_MATCH */
+#define ERROR_FINDNOTIFY_TIMEOUT 258 /* MSG%FINDNOTIFY_TIMEOUT */
+#define ERROR_NO_MORE_ITEMS 259 /* MSG%NO_MORE_ITEMS */
+#define ERROR_SEARCH_STRUC_REUSED 260 /* MSG%SEARCH_STRUC_REUSED */
+#define ERROR_CHAR_NOT_FOUND 261 /* MSG%CHAR_NOT_FOUND */
+#define ERROR_TOO_MUCH_STACK 262 /* MSG%TOO_MUCH_STACK */
+#define ERROR_INVALID_ATTR 263 /* MSG%INVALID_ATTR */
+#define ERROR_INVALID_STARTING_RING 264 /* MSG%INVALID_STARTING_RING */
+#define ERROR_INVALID_DLL_INIT_RING 265 /* MSG%INVALID_DLL_INIT_RING */
+#define ERROR_CANNOT_COPY 266 /* MSG%CANNOT_COPY */
+#define ERROR_DIRECTORY 267 /* MSG%DIRECTORY */
+#define ERROR_OPLOCKED_FILE 268 /* MSG%OPLOCKED_FILE */
+#define ERROR_OPLOCK_THREAD_EXISTS 269 /* MSG%OPLOCK_THREAD_EXISTS */
+#define ERROR_VOLUME_CHANGED 270 /* MSG%none */
+#define ERROR_FINDNOTIFY_HANDLE_IN_USE 271 /* MSG%none */
+#define ERROR_FINDNOTIFY_HANDLE_CLOSED 272 /* MSG%none */
+#define ERROR_NOTIFY_OBJECT_REMOVED 273 /* MSG%none */
+#define ERROR_ALREADY_SHUTDOWN 274 /* MSG%none */
+#define ERROR_EAS_DIDNT_FIT 275 /* MSG%none */
+#define ERROR_EA_FILE_CORRUPT 276 /* MSG%ERROR_EAS_CORRUPT */
+#define ERROR_EA_TABLE_FULL 277 /* MSG%EA_TABLE_FULL */
+#define ERROR_INVALID_EA_HANDLE 278 /* MSG%INVALID_EA_HANDLE */
+#define ERROR_NO_CLUSTER 279 /* MSG%NO_CLUSTER */
+#define ERROR_CREATE_EA_FILE 280 /* MSG%ERROR_CREATE_EA_FILE */
+#define ERROR_CANNOT_OPEN_EA_FILE 281 /* MSG%CANNOT_OPEN_FILE */
+#define ERROR_EAS_NOT_SUPPORTED 282 /* MSG%EAS_NOT_SUPPORTED */
+#define ERROR_NEED_EAS_FOUND 283 /* MSG%NEED_EAS_FOUND */
+#define ERROR_DUPLICATE_HANDLE 284 /* MSG%EAS_DISCARDED */
+#define ERROR_DUPLICATE_NAME 285 /* MSG%DUPLICATE_SEM_NAME */
+#define ERROR_EMPTY_MUXWAIT 286 /* MSG%EMPTY_MUXWAIT_SEM */
+#define ERROR_MUTEX_OWNED 287 /* MSG%MUTEX_SEM_OWNED */
+#define ERROR_NOT_OWNER 288 /* MSG%NOT_MUTEX_SEM_OWNER */
+#define ERROR_PARAM_TOO_SMALL 289 /* MSG%QUERY_MUX_PARAM_TOO_SMALL */
+#define ERROR_TOO_MANY_HANDLES 290 /* MSG%TOO_MANY_SEM_HANDLES */
+#define ERROR_TOO_MANY_OPENS 291 /* MSG%TOO_MANY_SEM_OPENS */
+#define ERROR_WRONG_TYPE 292 /* MSG%SEM_WRONG_TYPE */
+#define ERROR_UNUSED_CODE 293 /* MSG%none */
+#define ERROR_THREAD_NOT_TERMINATED 294 /* MSG%none */
+#define ERROR_INIT_ROUTINE_FAILED 295 /* MSG%none */
+#define ERROR_MODULE_IN_USE 296 /* MSG%none */
+#define ERROR_NOT_ENOUGH_WATCHPOINTS 297 /* MSG%none */
+#define ERROR_TOO_MANY_POSTS 298 /* MSG%TOO_MANY_EVENT_SEM_POSTS */
+#define ERROR_ALREADY_POSTED 299 /* MSG%EVENT_SEM_ALREADY_POSTED */
+#define ERROR_ALREADY_RESET 300 /* MSG%EVENT_SEM_ALREADY_RESET */
+#define ERROR_SEM_BUSY 301 /* MSG%SEM_BUSY */
+
+/* end of set 0 - 302 */
+
+#define ERROR_USER_DEFINED_BASE 0xFF00
+
+#define ERROR_I24_WRITE_PROTECT 0
+#define ERROR_I24_BAD_UNIT 1
+#define ERROR_I24_NOT_READY 2
+#define ERROR_I24_BAD_COMMAND 3
+#define ERROR_I24_CRC 4
+#define ERROR_I24_BAD_LENGTH 5
+#define ERROR_I24_SEEK 6
+#define ERROR_I24_NOT_DOS_DISK 7
+#define ERROR_I24_SECTOR_NOT_FOUND 8
+#define ERROR_I24_OUT_OF_PAPER 9
+#define ERROR_I24_WRITE_FAULT 10
+#define ERROR_I24_READ_FAULT 11
+#define ERROR_I24_GEN_FAILURE 12
+#define ERROR_I24_DISK_CHANGE 13
+#define ERROR_I24_WRONG_DISK 15
+#define ERROR_I24_UNCERTAIN_MEDIA 16
+#define ERROR_I24_CHAR_CALL_INTERRUPTED 17
+#define ERROR_I24_NO_MONITOR_SUPPORT 18
+#define ERROR_I24_INVALID_PARAMETER 19
+#define ERROR_I24_DEVICE_IN_USE 20
+
+#define ALLOWED_FAIL 0x0001
+#define ALLOWED_ABORT 0x0002
+#define ALLOWED_RETRY 0x0004
+#define ALLOWED_IGNORE 0x0008
+#define ALLOWED_ACKNOWLEDGE 0x0010
+#define ALLOWED_DISPATCH 0x8000
+#define ALLOWED_DETACHED ALLOWED_DISPATCH
+#define ALLOWED_RESERVED ~(ALLOWED_FAIL|ALLOWED_ABORT|ALLOWED_RETRY|ALLOWED_IGNORE|ALLOWED_ACKNOWLEDGE)
+
+#define I24_OPERATION 0x01
+#define I24_AREA 0x06
+#define I24_CLASS 0x80
+
+/* Values for error CLASS */
+#define ERRCLASS_OUTRES 1 /* Out of Resource */
+#define ERRCLASS_TEMPSIT 2 /* Temporary Situation */
+#define ERRCLASS_AUTH 3 /* Permission problem */
+#define ERRCLASS_INTRN 4 /* Internal System Error */
+#define ERRCLASS_HRDFAIL 5 /* Hardware Failure */
+#define ERRCLASS_SYSFAIL 6 /* System Failure */
+#define ERRCLASS_APPERR 7 /* Application Error */
+#define ERRCLASS_NOTFND 8 /* Not Found */
+#define ERRCLASS_BADFMT 9 /* Bad Format */
+#define ERRCLASS_LOCKED 10 /* Locked */
+#define ERRCLASS_MEDIA 11 /* Media Failure */
+#define ERRCLASS_ALREADY 12 /* Collision with Existing Item */
+#define ERRCLASS_UNK 13 /* Unknown/other */
+#define ERRCLASS_CANT 14
+#define ERRCLASS_TIME 15
+
+/* Values for error ACTION */
+#define ERRACT_RETRY 1 /* Retry */
+#define ERRACT_DLYRET 2 /* Delay Retry, retry after pause */
+#define ERRACT_USER 3 /* Ask user to regive information */
+#define ERRACT_ABORT 4 /* abort with clean up */
+#define ERRACT_PANIC 5 /* abort immediately */
+#define ERRACT_IGNORE 6 /* ignore */
+#define ERRACT_INTRET 7 /* Retry after User Intervention */
+
+/* Values for error LOCUS */
+#define ERRLOC_UNK 1 /* No appropriate value */
+#define ERRLOC_DISK 2 /* Random Access Mass Storage */
+#define ERRLOC_NET 3 /* Network */
+#define ERRLOC_SERDEV 4 /* Serial Device */
+#define ERRLOC_MEM 5 /* Memory */
+
+/* Abnormal termination codes */
+#define TC_NORMAL 0
+#define TC_HARDERR 1
+#define TC_GP_TRAP 2
+#define TC_SIGNAL 3
+#define TC_XCPT 4
+
+#endif /* INCL_ERROR_H || INCL_DOSERRORS */
+
+#if defined(INCL_DOSERRORS) || defined(INCL_ERROR2_H)
+
+#define ERROR_INVALID_PROCID 303 /* MSG%none */
+#define ERROR_INVALID_PDELTA 304 /* MSG%none */
+#define ERROR_NOT_DESCENDANT 305 /* MSG%none */
+#define ERROR_NOT_SESSION_MANAGER 306 /* MSG%none */
+#define ERROR_INVALID_PCLASS 307 /* MSG%none */
+#define ERROR_INVALID_SCOPE 308 /* MSG%none */
+#define ERROR_INVALID_THREADID 309 /* MSG%none */
+#define ERROR_DOSSUB_SHRINK 310 /* MSG%none */
+#define ERROR_DOSSUB_NOMEM 311 /* MSG%none */
+#define ERROR_DOSSUB_OVERLAP 312 /* MSG%none */
+#define ERROR_DOSSUB_BADSIZE 313 /* MSG%none */
+#define ERROR_DOSSUB_BADFLAG 314 /* MSG%none */
+#define ERROR_DOSSUB_BADSELECTOR 315 /* MSG%none */
+#define ERROR_MR_MSG_TOO_LONG 316 /* MSG%MR_MSG_TOO_LONG */
+#define MGS_MR_MSG_TOO_LONG 316
+#define ERROR_MR_MID_NOT_FOUND 317 /* MSG%MR_CANT_FORMAT */
+#define ERROR_MR_UN_ACC_MSGF 318 /* MSG%MR_NOT_FOUND */
+#define ERROR_MR_INV_MSGF_FORMAT 319 /* MSG%MR_READ_ERROR */
+#define ERROR_MR_INV_IVCOUNT 320 /* MSG%MR_IVCOUNT_ERROR */
+#define ERROR_MR_UN_PERFORM 321 /* MSG%MR_UN_PERFORM */
+#define ERROR_TS_WAKEUP 322 /* MSG%none */
+#define ERROR_TS_SEMHANDLE 323 /* MSG%none */
+#define ERROR_TS_NOTIMER 324 /* MSG%none */
+#define ERROR_TS_HANDLE 326 /* MSG%none */
+#define ERROR_TS_DATETIME 327 /* MSG%none */
+#define ERROR_SYS_INTERNAL 328 /* MSG%none */
+#define ERROR_QUE_CURRENT_NAME 329 /* MSG%none */
+#define ERROR_QUE_PROC_NOT_OWNED 330 /* MSG%QUE_PROC_NOT_OWNED */
+#define ERROR_QUE_PROC_OWNED 331 /* MSG%none */
+#define ERROR_QUE_DUPLICATE 332 /* MSG%QUE_DUPLICATE */
+#define ERROR_QUE_ELEMENT_NOT_EXIST 333 /* MSG%QUE_ELEMENT_NOT_EXIST */
+#define ERROR_QUE_NO_MEMORY 334 /* MSG%QUE_NO_MEMORY */
+#define ERROR_QUE_INVALID_NAME 335 /* MSG%none */
+#define ERROR_QUE_INVALID_PRIORITY 336 /* MSG%none */
+#define ERROR_QUE_INVALID_HANDLE 337 /* MSG%none */
+#define ERROR_QUE_LINK_NOT_FOUND 338 /* MSG%none */
+#define ERROR_QUE_MEMORY_ERROR 339 /* MSG%none */
+#define ERROR_QUE_PREV_AT_END 340 /* MSG%none */
+#define ERROR_QUE_PROC_NO_ACCESS 341 /* MSG%none */
+#define ERROR_QUE_EMPTY 342 /* MSG%none */
+#define ERROR_QUE_NAME_NOT_EXIST 343 /* MSG%none */
+#define ERROR_QUE_NOT_INITIALIZED 344 /* MSG%none */
+#define ERROR_QUE_UNABLE_TO_ACCESS 345 /* MSG%none */
+#define ERROR_QUE_UNABLE_TO_ADD 346 /* MSG%none */
+#define ERROR_QUE_UNABLE_TO_INIT 347 /* MSG%none */
+#define ERROR_VIO_INVALID_MASK 349 /* MSG%VIO_INVALID_MASK */
+#define ERROR_VIO_PTR 350 /* MSG%VIO_PTR */
+#define ERROR_VIO_APTR 351 /* MSG%none */
+#define ERROR_VIO_RPTR 352 /* MSG%none */
+#define ERROR_VIO_CPTR 353 /* MSG%none */
+#define ERROR_VIO_LPTR 354 /* MSG%none */
+#define ERROR_VIO_MODE 355 /* MSG%DIS_ERROR */
+#define ERROR_VIO_WIDTH 356 /* MSG%VIO_WIDTH */
+#define ERROR_VIO_ATTR 357 /* MSG%none */
+#define ERROR_VIO_ROW 358 /* MSG%VIO_ROW */
+#define ERROR_VIO_COL 359 /* MSG%VIO_COL */
+#define ERROR_VIO_TOPROW 360 /* MSG%none */
+#define ERROR_VIO_BOTROW 361 /* MSG%none */
+#define ERROR_VIO_RIGHTCOL 362 /* MSG%none */
+#define ERROR_VIO_LEFTCOL 363 /* MSG%none */
+#define ERROR_SCS_CALL 364 /* MSG%none */
+#define ERROR_SCS_VALUE 365 /* MSG%none */
+#define ERROR_VIO_WAIT_FLAG 366 /* MSG%VIO_WAIT_FLAG */
+#define ERROR_VIO_UNLOCK 367 /* MSG%VIO_UNLOCK */
+#define ERROR_SGS_NOT_SESSION_MGR 368 /* MSG%none */
+#define ERROR_SMG_INVALID_SGID 369 /* MSG%SMG_INVALID_SESSION_ID */
+#define ERROR_SMG_INVALID_SESSION_ID ERROR_SMG_INVALID_SGID
+#define ERROR_SMG_NOSG 370 /* MSG%none */
+#define ERROR_SMG_NO_SESSIONS 370 /* MSG%none */
+#define ERROR_SMG_GRP_NOT_FOUND 371 /* MSG%SMG_GRP_NOT_FOUND */
+#define ERROR_SMG_SESSION_NOT_FOUND ERROR_SMG_GRP_NOT_FOUND
+/* 371%msg%SMG_SESSION_NOT_FOUND */
+#define ERROR_SMG_SET_TITLE 372 /* MSG%SMG_SET_TITLE */
+#define ERROR_KBD_PARAMETER 373 /* MSG%KBD_PARAMETER */
+#define ERROR_KBD_NO_DEVICE 374 /* MSG%none */
+#define ERROR_KBD_INVALID_IOWAIT 375 /* MSG%KBD_INVALID_IOWAIT */
+#define ERROR_KBD_INVALID_LENGTH 376 /* MSG%KBD_INVALID_LENGTH */
+#define ERROR_KBD_INVALID_ECHO_MASK 377 /* MSG%KBD_INVALID_ECHO_MASK */
+/* 377%msg%KBD_INVALID_INPUT_MASK */
+#define ERROR_KBD_INVALID_INPUT_MASK 378 /* MSG%none */
+#define ERROR_MON_INVALID_PARMS 379 /* MSG%MON_INVALID_PARMS */
+#define ERROR_MON_INVALID_DEVNAME 380 /* MSG%MON_INVALID_DEVNAME */
+#define ERROR_MON_INVALID_HANDLE 381 /* MSG%MON_INVALID_HANDLE */
+#define ERROR_MON_BUFFER_TOO_SMALL 382 /* MSG%MON_BUFFER_TOO_SMALL */
+#define ERROR_MON_BUFFER_EMPTY 383 /* MSG%MON_BUFFER_EMPTY */
+#define ERROR_MON_DATA_TOO_LARGE 384 /* MSG%MON_DATA_TOO_LARGE */
+#define ERROR_MOUSE_NO_DEVICE 385 /* MSG%MOUSE_NO_DEVICE */
+#define ERROR_MOUSE_INV_HANDLE 386 /* MSG%MOUSE_INV_HANDLE */
+#define ERROR_MOUSE_INV_PARMS 387 /* MSG%MOUSE_CALLER_NOT_SYBSYS */
+#define ERROR_MOUSE_CANT_RESET 388 /* MSG%none */
+#define ERROR_MOUSE_DISPLAY_PARMS 389 /* MSG%none */
+#define ERROR_MOUSE_INV_MODULE 390 /* MSG%none */
+#define ERROR_MOUSE_INV_ENTRY_PT 391 /* MSG%none */
+#define ERROR_MOUSE_INV_MASK 392 /* MSG%none */
+#define NO_ERROR_MOUSE_NO_DATA 393 /* MSG%none */
+#define NO_ERROR_MOUSE_PTR_DRAWN 394 /* MSG%none */
+#define ERROR_INVALID_FREQUENCY 395 /* MSG%none */
+#define ERROR_NLS_NO_COUNTRY_FILE 396 /* MSG%NLS_NO_COUNTRY_FILE */
+/* 396%msg%NO_COUNTRY_SYS */
+#define ERROR_NLS_OPEN_FAILED 397 /* MSG%NLS_OPEN_FAILED */
+/* 397%msg%OPEN_COUNTRY_SYS */
+#define ERROR_NLS_NO_CTRY_CODE 398 /* MSG%NLS_NO_CTRY_CODE */
+#define ERROR_NO_COUNTRY_OR_CODEPAGE 398 /* MSG%NO_COUNTRY_OR_CODEPAGE */
+#define ERROR_NLS_TABLE_TRUNCATED 399 /* MSG%NLS_TABLE_TRUNCATED */
+#define ERROR_NLS_BAD_TYPE 400 /* MSG%NLS_BAD_TYPE */
+#define ERROR_NLS_TYPE_NOT_FOUND 401 /* MSG%NLS_TYPE_NOT_FOUND */
+/* 401%msg%COUNTRY_NO_TYPE */
+#define ERROR_VIO_SMG_ONLY 402 /* MSG%SWAPIN_FAILED */
+#define ERROR_VIO_INVALID_ASCIIZ 403 /* MSG%SEGVALIDATE_FAILURE */
+#define ERROR_VIO_DEREGISTER 404 /* MSG%VIO_DEREGISTER */
+#define ERROR_VIO_NO_POPUP 405 /* MSG%VIO_NO_POPUP */
+#define ERROR_VIO_EXISTING_POPUP 406 /* MSG%VIO_EXISTING_POPUP */
+#define ERROR_KBD_SMG_ONLY 407 /* MSG%KBD_SMG_ONLY */
+#define ERROR_KBD_INVALID_ASCIIZ 408 /* MSG%KBD_INVALID_ASCIIZ */
+#define ERROR_KBD_INVALID_MASK 409 /* MSG%KBD_INVALID_MASK */
+#define ERROR_KBD_REGISTER 410 /* MSG%KBD_REGISTER */
+#define ERROR_KBD_DEREGISTER 411 /* MSG%KBD_DEREGISTER */
+#define ERROR_MOUSE_SMG_ONLY 412 /* MSG%MOUSE_SMG_ONLY */
+#define ERROR_MOUSE_INVALID_ASCIIZ 413 /* MSG%MOUSE_INVALID_ASCIIZ */
+#define ERROR_MOUSE_INVALID_MASK 414 /* MSG%MOUSE_INVALID_MASK */
+#define ERROR_MOUSE_REGISTER 415 /* MSG%MOUSE_REGISTER */
+#define ERROR_MOUSE_DEREGISTER 416 /* MSG%MOUSE_DEREGISTER */
+#define ERROR_SMG_BAD_ACTION 417 /* MSG%SMG_BAD_ACTION */
+#define ERROR_SMG_INVALID_CALL 418 /* MSG%SMG_INVALID_CALL */
+#define ERROR_SCS_SG_NOTFOUND 419 /* MSG%none */
+#define ERROR_SCS_NOT_SHELL 420 /* MSG%none */
+#define ERROR_VIO_INVALID_PARMS 421 /* MSG%VIO_INVALID_PARMS */
+#define ERROR_VIO_FUNCTION_OWNED 422 /* MSG%VIO_FUNCTION_OWNED */
+#define ERROR_VIO_RETURN 423 /* MSG%none */
+#define ERROR_SCS_INVALID_FUNCTION 424 /* MSG%none */
+#define ERROR_SCS_NOT_SESSION_MGR 425 /* MSG%none */
+#define ERROR_VIO_REGISTER 426 /* MSG%VIO_REGISTER */
+#define ERROR_VIO_NO_MODE_THREAD 427 /* MSG%none */
+#define ERROR_VIO_NO_SAVE_RESTORE_THD 428 /* MSG%VIO_NO_SAVE_RESTORE_THD */
+#define ERROR_VIO_IN_BG 429 /* MSG%VIO_IN_BG */
+#define ERROR_VIO_ILLEGAL_DURING_POPUP 430 /* MSG%VIO_ILLEGAL_DURING_POPUP */
+#define ERROR_SMG_NOT_BASESHELL 431 /* MSG%SMG_NOT_BASESHELL */
+#define ERROR_SMG_BAD_STATUSREQ 432 /* MSG%SMG_BAD_STATUSREQ */
+#define ERROR_QUE_INVALID_WAIT 433 /* MSG%none */
+#define ERROR_VIO_LOCK 434 /* MSG%VIO_LOCK */
+#define ERROR_MOUSE_INVALID_IOWAIT 435 /* MSG%MOUSE_INVALID_IOWAIT */
+#define ERROR_VIO_INVALID_HANDLE 436 /* MSG%VIO_INVALID_HANDLE */
+#define ERROR_VIO_ILLEGAL_DURING_LOCK 437 /* MSG%none */
+#define ERROR_VIO_INVALID_LENGTH 438 /* MSG%VIO_INVALID_LENGTH */
+#define ERROR_KBD_INVALID_HANDLE 439 /* MSG%KBD_INVALID_HANDLE */
+#define ERROR_KBD_NO_MORE_HANDLE 440 /* MSG%KBD_NO_MORE_HANDLE */
+#define ERROR_KBD_CANNOT_CREATE_KCB 441 /* MSG%KBD_CANNOT_CREATE_KCB */
+#define ERROR_KBD_CODEPAGE_LOAD_INCOMPL 442 /* MSG%KBD_CODEPAGE_LOAD_INCOMPL */
+#define ERROR_KBD_INVALID_CODEPAGE_ID 443 /* MSG%KBD_INVALID_CODEPAGE_ID */
+#define ERROR_KBD_NO_CODEPAGE_SUPPORT 444 /* MSG%KBD_NO_CODEPAGE_SUPPORT */
+#define ERROR_KBD_FOCUS_REQUIRED 445 /* MSG%KBD_FOCUS_REQUIRED */
+#define ERROR_KBD_FOCUS_ALREADY_ACTIVE 446 /* MSG%KBD_FOCUS_ALREADY_ACTIVE */
+#define ERROR_KBD_KEYBOARD_BUSY 447 /* MSG%KBD_KEYBOARD_BUSY */
+#define ERROR_KBD_INVALID_CODEPAGE 448 /* MSG%KBD_INVALID_CODEPAGE */
+#define ERROR_KBD_UNABLE_TO_FOCUS 449 /* MSG%KBD_UNABLE_TO_FOCUS */
+#define ERROR_SMG_SESSION_NON_SELECT 450 /* MSG%SMG_SESSION_NON_SELECT */
+#define ERROR_SMG_SESSION_NOT_FOREGRND 451 /* MSG%SMG_SESSION_NOT_FOREGRND */
+#define ERROR_SMG_SESSION_NOT_PARENT 452 /* MSG%SMG_SESSION_NOT_PARENT */
+#define ERROR_SMG_INVALID_START_MODE 453 /* MSG%SMG_INVALID_START_MODE */
+#define ERROR_SMG_INVALID_RELATED_OPT 454 /* MSG%SMG_INVALID_RELATED_OPT */
+#define ERROR_SMG_INVALID_BOND_OPTION 455 /* MSG%SMG_INVALID_BOND_OPTION */
+#define ERROR_SMG_INVALID_SELECT_OPT 456 /* MSG%SMG_INVALID_SELECT_OPT */
+#define ERROR_SMG_START_IN_BACKGROUND 457 /* MSG%SMG_START_IN_BACKGROUND */
+#define ERROR_SMG_INVALID_STOP_OPTION 458 /* MSG%SMG_INVALID_STOP_OPTION */
+#define ERROR_SMG_BAD_RESERVE 459 /* MSG%SMG_BAD_RESERVE */
+#define ERROR_SMG_PROCESS_NOT_PARENT 460 /* MSG%SMG_PROCESS_NOT_PARENT */
+#define ERROR_SMG_INVALID_DATA_LENGTH 461 /* MSG%SMG_INVALID_DATA_LENGTH */
+#define ERROR_SMG_NOT_BOUND 462 /* MSG%SMG_NOT_BOUND */
+#define ERROR_SMG_RETRY_SUB_ALLOC 463 /* MSG%SMG_RETRY_SUB_ALLOC */
+#define ERROR_KBD_DETACHED 464 /* MSG%KBD_DETACHED */
+#define ERROR_VIO_DETACHED 465 /* MSG%VIO_DETACHED */
+#define ERROR_MOU_DETACHED 466 /* MSG%MOU_DETACHED */
+#define ERROR_VIO_FONT 467 /* MSG%VIO_FONT */
+#define ERROR_VIO_USER_FONT 468 /* MSG%VIO_USER_FONT */
+#define ERROR_VIO_BAD_CP 469 /* MSG%VIO_BAD_CP */
+#define ERROR_VIO_NO_CP 470 /* MSG%none */
+#define ERROR_VIO_NA_CP 471 /* MSG%VIO_NA_CP */
+#define ERROR_INVALID_CODE_PAGE 472 /* MSG%none */
+#define ERROR_CPLIST_TOO_SMALL 473 /* MSG%none */
+#define ERROR_CP_NOT_MOVED 474 /* MSG%none */
+#define ERROR_MODE_SWITCH_INIT 475 /* MSG%none */
+#define ERROR_CODE_PAGE_NOT_FOUND 476 /* MSG%none */
+#define ERROR_UNEXPECTED_SLOT_RETURNED 477 /* MSG%none */
+#define ERROR_SMG_INVALID_TRACE_OPTION 478 /* MSG%SMG_INVALID_TRACE_OPTION */
+#define ERROR_VIO_INTERNAL_RESOURCE 479 /* MSG%none */
+#define ERROR_VIO_SHELL_INIT 480 /* MSG%VIO_SHELL_INIT */
+#define ERROR_SMG_NO_HARD_ERRORS 481 /* MSG%SMG_NO_HARD_ERRORS */
+#define ERROR_CP_SWITCH_INCOMPLETE 482 /* MSG%none */
+#define ERROR_VIO_TRANSPARENT_POPUP 483 /* MSG%VIO_TRANSPARENT_POPUP */
+#define ERROR_CRITSEC_OVERFLOW 484 /* MSG%none */
+#define ERROR_CRITSEC_UNDERFLOW 485 /* MSG%none */
+#define ERROR_VIO_BAD_RESERVE 486 /* MSG%VIO_BAD_RESERVE */
+#define ERROR_INVALID_ADDRESS 487 /* MSG%INVALID_ADDRESS */
+#define ERROR_ZERO_SELECTORS_REQUESTED 488 /* MSG%ZERO_SELECTORS_REQUESTED */
+#define ERROR_NOT_ENOUGH_SELECTORS_AVA 489 /* MSG%NOT_ENOUGH_SELECTORS_AVA */
+#define ERROR_INVALID_SELECTOR 490 /* MSG%INVALID_SELECTOR */
+#define ERROR_SMG_INVALID_PROGRAM_TYPE 491 /* MSG%SMG_INVALID_PROGRAM_TYPE */
+#define ERROR_SMG_INVALID_PGM_CONTROL 492 /* MSG%SMG_INVALID_PGM_CONTROL */
+#define ERROR_SMG_INVALID_INHERIT_OPT 493 /* MSG%SMG_INVALID_INHERIT_OPT */
+#define ERROR_VIO_EXTENDED_SG 494 /* MSG%VIO_EXTENDED_SG */
+#define ERROR_VIO_NOT_PRES_MGR_SG 495 /* MSG%VIO_NOT_PRES_MGR_SG */
+#define ERROR_VIO_SHIELD_OWNED 496 /* MSG%VIO_SHIELD_OWNED */
+#define ERROR_VIO_NO_MORE_HANDLES 497 /* MSG%VIO_NO_MORE_HANDLES */
+#define ERROR_VIO_SEE_ERROR_LOG 498 /* MSG%none */
+#define ERROR_VIO_ASSOCIATED_DC 499 /* MSG%none */
+#define ERROR_KBD_NO_CONSOLE 500 /* MSG%KBD_NO_CONSOLE */
+#define ERROR_MOUSE_NO_CONSOLE 501 /* MSG%DOS_STOPPED */
+#define ERROR_MOUSE_INVALID_HANDLE 502 /* MSG%MOUSE_INVALID_HANDLE */
+#define ERROR_SMG_INVALID_DEBUG_PARMS 503 /* MSG%SMG_INVALID_DEBUG_PARMS */
+#define ERROR_KBD_EXTENDED_SG 504 /* MSG%KBD_EXTENDED_SG */
+#define ERROR_MOU_EXTENDED_SG 505 /* MSG%MOU_EXTENDED_SG */
+#define ERROR_SMG_INVALID_ICON_FILE 506 /* MSG%none */
+#define ERROR_TRC_PID_NON_EXISTENT 507 /* MSG%TRC_PID_NON_EXISTENT */
+#define ERROR_TRC_COUNT_ACTIVE 508 /* MSG%TRC_COUNT_ACTIVE */
+#define ERROR_TRC_SUSPENDED_BY_COUNT 509 /* MSG%TRC_SUSPENDED_BY_COUNT */
+#define ERROR_TRC_COUNT_INACTIVE 510 /* MSG%TRC_COUNT_INACTIVE */
+#define ERROR_TRC_COUNT_REACHED 511 /* MSG%TRC_COUNT_REACHED */
+#define ERROR_NO_MC_TRACE 512 /* MSG%NO_MC_TRACE */
+#define ERROR_MC_TRACE 513 /* MSG%MC_TRACE */
+#define ERROR_TRC_COUNT_ZERO 514 /* MSG%TRC_COUNT_ZERO */
+#define ERROR_SMG_TOO_MANY_DDS 515 /* MSG%SMG_TOO_MANY_DDS */
+#define ERROR_SMG_INVALID_NOTIFICATION 516 /* MSG%SMG_INVALID_NOTIFICATION */
+#define ERROR_LF_INVALID_FUNCTION 517 /* MSG%LF_INVALID_FUNCTION */
+#define ERROR_LF_NOT_AVAIL 518 /* MSG%LF_NOT_AVAIL */
+#define ERROR_LF_SUSPENDED 519 /* MSG%LF_SUSPENDED */
+#define ERROR_LF_BUF_TOO_SMALL 520 /* MSG%LF_BUF_TOO_SMALL */
+#define ERROR_LF_BUFFER_CORRUPTED 521 /* MSG%none */
+#define ERROR_LF_BUFFER_FULL 521 /* MSG%LF_BUF_FULL */
+#define ERROR_LF_INVALID_DAEMON 522 /* MSG%none */
+#define ERROR_LF_INVALID_RECORD 522 /* MSG%LF_INVAL_RECORD */
+#define ERROR_LF_INVALID_TEMPL 523 /* MSG%none */
+#define ERROR_LF_INVALID_SERVICE 523 /* MSG%LF_INVAL_SERVICE */
+#define ERROR_LF_GENERAL_FAILURE 524 /* MSG%LF_GENERAL_FAILURE */
+#define ERROR_LF_INVALID_ID 525 /* MSG%HPFS_DISK_ALREADY_INUSE */
+#define ERROR_LF_INVALID_HANDLE 526 /* MSG%HPFS_CANNOT_FORMAT_DISK */
+#define ERROR_LF_NO_ID_AVAIL 527 /* MSG%HPFS_CANNOT_COPY_SYS_DATA */
+#define ERROR_LF_TEMPLATE_AREA_FULL 528 /* MSG%HPFS_FORMAT_NOT_DONE */
+#define ERROR_LF_ID_IN_USE 529 /* MSG%HPFS_FMT_NOT_ENOUGH_MEM */
+#define ERROR_MOU_NOT_INITIALIZED 530 /* MSG%HPFS_SPECIFY_FIXDSK */
+#define ERROR_MOUINITREAL_DONE 531 /* MSG%HPFS_SPECIFY_ONE_DRIVE */
+#define ERROR_DOSSUB_CORRUPTED 532 /* MSG%HPFS_UNKNOWN_ERR_NO_FORMAT */
+#define ERROR_MOUSE_CALLER_NOT_SUBSYS 533 /* MSG%HPFS_SYNTAX_HELP */
+#define ERROR_ARITHMETIC_OVERFLOW 534 /* MSG%HPFS_DISK_FORMATING */
+#define ERROR_TMR_NO_DEVICE 535 /* MSG%HPFS_AVAIL_DISK_SPACE */
+#define ERROR_TMR_INVALID_TIME 536 /* MSG%HPFS_BAD_BLOCKS */
+#define ERROR_PVW_INVALID_ENTITY 537 /* MSG%HPFS_DISK_SPACE_AVAIL */
+#define ERROR_PVW_INVALID_ENTITY_TYPE 538 /* MSG%HPFS_SPACE_FORMATTED */
+#define ERROR_PVW_INVALID_SPEC 539 /* MSG%HPFS_TYPE_CUR_VOLUME_LABEL */
+#define ERROR_PVW_INVALID_RANGE_TYPE 540 /* MSG%HPFS_DRIVER_NOT_LOADED */
+#define ERROR_PVW_INVALID_COUNTER_BLK 541 /* MSG%HPFS_DRIVER_LOADER */
+#define ERROR_PVW_INVALID_TEXT_BLK 542 /* MSG%HPFS_CACHE_BUF_SPECIFIED */
+#define ERROR_PRF_NOT_INITIALIZED 543 /* MSG%HPFS_CHKDSK_PARM_ERROR */
+#define ERROR_PRF_ALREADY_INITIALIZED 544 /* MSG%HPFS_CHKDSK_NOACCESS_DRIVE */
+#define ERROR_PRF_NOT_STARTED 545 /* MSG%HPFS_UNKNOWN_ERR_NO_CHKDSK */
+#define ERROR_PRF_ALREADY_STARTED 546 /* MSG%HPFS_CHKDSK_NOT_ENOUGH_MEM */
+#define ERROR_PRF_TIMER_OUT_OF_RANGE 547 /* MSG%HPFS_CHKDSK_NOWRITEODATA */
+#define ERROR_PRF_TIMER_RESET 548 /* MSG%HPFS_CHKDSK_NORECOVER_DATA */
+/* 549%msg%HPFS_CHKDSK_NO_PARM_SPACE */
+/* 550%msg%HPFS_CHKDSK_NORECOGNIZE */
+/* 551%msg%HPFS_CHKDSK_NOROOT_FIND */
+/* 552%msg%HPFS_CHKDSK_NOFIX_FS_ERROR */
+/* 553%msg%HPFS_CHKDSK_CORRECT_FS_ERR */
+/* 554%msg%HPFS_CHKDSK_ORGAN_FIX */
+/* 555%msg%HPFS_CHKDSK_RELOC_BBPDATA */
+/* 556%msg%HPFS_CHKDSK_REM_CORRU_BLOC */
+/* 557%msg%HPFS_CHKDSK_REM_CORRUP_FIL */
+/* 558%msg%HPFS_CHKDSK_FIX_SPACE_ALLO */
+/* 559%msg%HPFS_NOT_FORMATTED_DISK */
+/* 560%msg%HPFS_CHKDSK_COR_ALLOC */
+/* 561%msg%HPFS_CHKDSK_SEARC_UNALLOC */
+/* 562%msg%HPFS_CHKDSK_DET_LOST_DATA */
+/* 563%msg%HPFS_CHKDSK_PERCENT_SEARC */
+/* 564%msg%HPFS_CHKDSK_LOST_DATASEARC */
+/* 565%msg%HPFS_CHKDSK_CRIT_NOREAD */
+/* 566%msg%HPFS_CHKDSK_DISK_INUSE */
+/* 567%msg%HPFS_CHKDSK_RECOVTEMP_RELOC */
+/* 568%msg%HPFS_TOTAL_DISK_SPACE */
+/* 569%msg%HPFS_DIR_KBYTES */
+/* 570%msg%HPFS_FILE_KBYTES */
+/* 571%msg%HPFS_KBYTES_AVAILABLE */
+/* 572%msg%HPFS_CHKDSK_PLACE_REC_FILE */
+/* 573%msg%HPFS_CHKDSK_RECO_DIR_AS */
+/* 574%msg%HPFS_CHKDSK_PLACEED_DATA */
+/* 575%msg%HPFS_CHKDSK_RECOV_EA */
+/* 576%msg%HPFS_CHKDSK_FIND_EA_INTEM */
+/* 577%msg%HPFS_CHKDSK_RELOC_TEMP_EA */
+/* 578%msg%HPFS_CHKDSK_RELOC_AC_LIST */
+/* 579%msg%HPFS_CHKDSK_LIST_NORELOC */
+/* 580%msg%HPFS_CHKDSK_TRUN_EA_LIST */
+/* 581%msg%HPFS_CHKDSK_TRUN_EA_NAME */
+/* 582%msg%HPFS_CHKDSK_TRUN_EA_BBLOCK */
+/* 583%msg%HPFS_CHKDSK_REM_INVALID_EA */
+/* 584%msg%HPFS_CHKDSK_FIX_EA_ALLOC */
+/* 585%msg%HPFS_CHKDSK_FIX_ALACCCTRL */
+/* 586%msg%HPFS_CHKDSK_ACCTR_LIST_BBL */
+/* 587%msg%HPFS_CHKDSK_REM_ACLIST */
+/* 588%msg%HPFS_CHKDSK_FOUND_DATANORL */
+/* 589%msg%HPFS_WRONG_VERSION */
+/* 590%msg%HPFS_CHKDSK_FOUND_DATATEMP */
+/* 591%msg%HPFS_CHKDSK_FIX_TEMPSTATUS */
+/* 592%msg%HPFS_CHKDSK_FIX_NEEDEADATA */
+/* 593%msg%HPFS_RECOVER_PARM_ERROR */
+/* 594%msg%HPFS_RECOV_FILE_NOT_FOUND */
+/* 595%msg%HPFS_RECOV_UNKNOWN_ERROR */
+/* 596%msg%HPFS_RECOV_NOT_ENOUGH_MEM */
+/* 597%msg%HPFS_RECOV_NOWRITE_DATA */
+/* 598%msg%HPFS_RECOV_NOTEMP_CREATE */
+/* 599%msg%HPFS_RECOV_EA_NOREAD */
+/* 600%msg%HPFS_RECOV_FILE_BYTES */
+/* 601%msg%HPFS_RECOV_BAD_BYTES_RECOV */
+/* 602%msg%HPFS_RECOV_FILEBYTES_NOREC */
+/* 603%msg%HPFS_RECOV_DISK_INUSE */
+/* 604%msg%HPFS_RECOV_FILE_NODELETE */
+/* 605%msg%HPFS_RECOV_NOCREATE_NEWFILE */
+/* 606%msg%HPFS_RECOV_SYSTEM_ERROR */
+/* 607%msg%HPFS_SYS_PARM_ERROR */
+/* 608%msg%HPFS_SYS_CANNOT_INSTALL */
+/* 609%msg%HPFS_SYS_DRIVE_NOTFORMATED */
+/* 610%msg%HPFS_SYS_FILE_NOCREATE */
+/* 611%msg%HPFS_SIZE_EXCEED */
+/* 612%msg%HPFS_SYNTAX_ERR */
+/* 613%msg%HPFS_NOTENOUGH_MEM */
+/* 614%msg%HPFS_WANT_MEM */
+/* 615%msg%HPFS_GET_RETURNED */
+/* 616%msg%HPFS_SET_RETURNED */
+/* 617%msg%HPFS_BOTH_RETURNED */
+/* 618%msg%HPFS_STOP_RETURNED */
+/* 619%msg%HPFS_SETPRTYRETURNED */
+/* 620%msg%HPFS_ALCSG_RETURNED */
+/* 621%msg%HPFS_MSEC_SET */
+/* 622%msg%HPFS_OPTIONS */
+/* 623%msg%HPFS_POS_NUM_VALUE */
+/* 624%msg%HPFS_VALUE_TOO_LARGE */
+/* 625%msg%HPFS_LAZY_NOT_VALID */
+/* 626%msg%HPFS_VOLUME_ERROR */
+/* 627%msg%HPFS_VOLUME_DIRTY */
+/* 628%msg%HPFS_NEW_SECTOR */
+/* 629%msg%HPFS_FORMAT_PARM_ERROR */
+/* 630%msg%HPFS_CANNOT_ACCESS_CONFIG */
+/* 631%msg%HPFS_RECOV_FILE */
+/* 632%msg%HPFS_CHKDSK_KBYTES_RESERVE */
+/* 633%msg%HPFS_CHKDSK_KBYTES_IN_EA */
+/* 634%msg%HPFS_BYTEBUF_SET */
+/* 635%msg%HPFS_FORMATTING_COMPLETE */
+/* 636%msg%HPFS_WRONG_VOLUME_LABEL */
+/* 637%msg%HPFS_FMAT_TOO_MANY_DRS */
+/* 638%msg%VDD_UNSUPPORTED_ACCESS */
+#define ERROR_VDD_LOCK_USEAGE_DENIED 639 /* KP.COM not supported in DOS */
+#define ERROR_TIMEOUT 640 /* MSG%none */
+#define ERROR_VDM_DOWN 641 /* MSG%none */
+#define ERROR_VDM_LIMIT 642 /* MSG%none */
+#define ERROR_VDD_NOT_FOUND 643 /* MSG%none */
+#define ERROR_INVALID_CALLER 644 /* MSG%none */
+#define ERROR_PID_MISMATCH 645 /* MSG%none */
+#define ERROR_INVALID_VDD_HANDLE 646 /* MSG%none */
+#define ERROR_VLPT_NO_SPOOLER 647 /* MSG%none */
+#define ERROR_VCOM_DEVICE_BUSY 648 /* MSG%none */
+#define ERROR_VLPT_DEVICE_BUSY 649 /* MSG%none */
+#define ERROR_NESTING_TOO_DEEP 650 /* MSG%none */
+#define ERROR_VDD_MISSING 651 /* MSG%VDD_MISSING */
+/* 689%msg%HPFS_LAZY_ON */
+/* 690%msg%HPFS_LAZY_OFF */
+#define ERROR_IMP_INVALID_PARM 691 /* MSG%none */
+#define ERROR_IMP_INVALID_LENGTH 692 /* MSG%none */
+#define ERROR_MON_BAD_BUFFER 730 /* MSG%BAD_MON_BUFFER */
+
+#define ERROR_MODULE_CORRUPTED 731 /* MSG%MODULE_CORRUPTED */
+
+/****/
+#define ERROR_LF_TIMEOUT 2055 /* MSG%LF_TIMEOUT */
+#define ERROR_LF_SUSPEND_SUCCESS 2057 /* MSG%LF_SUSP_SUCCESS */
+#define ERROR_LF_RESUME_SUCCESS 2058 /* MSG%LF_RESUM_SUCCESS */
+#define ERROR_LF_REDIRECT_SUCCESS 2059 /* MSG%LF_REDIR_SUCCESS */
+#define ERROR_LF_REDIRECT_FAILURE 2060 /* MSG%LF_REDIR_FAILURE */
+
+#define ERROR_SWAPPER_NOT_ACTIVE 32768
+#define ERROR_INVALID_SWAPID 32769
+#define ERROR_IOERR_SWAP_FILE 32770
+#define ERROR_SWAP_TABLE_FULL 32771
+#define ERROR_SWAP_FILE_FULL 32772
+#define ERROR_CANT_INIT_SWAPPER 32773
+#define ERROR_SWAPPER_ALREADY_INIT 32774
+#define ERROR_PMM_INSUFFICIENT_MEMORY 32775
+#define ERROR_PMM_INVALID_FLAGS 32776
+#define ERROR_PMM_INVALID_ADDRESS 32777
+#define ERROR_PMM_LOCK_FAILED 32778
+#define ERROR_PMM_UNLOCK_FAILED 32779
+#define ERROR_PMM_MOVE_INCOMPLETE 32780
+#define ERROR_UCOM_DRIVE_RENAMED 32781
+#define ERROR_UCOM_FILENAME_TRUNCATED 32782
+#define ERROR_UCOM_BUFFER_LENGTH 32783
+#define ERROR_MON_CHAIN_HANDLE 32784
+#define ERROR_MON_NOT_REGISTERED 32785
+#define ERROR_SMG_ALREADY_TOP 32786
+#define ERROR_PMM_ARENA_MODIFIED 32787
+#define ERROR_SMG_PRINTER_OPEN 32788
+#define ERROR_PMM_SET_FLAGS_FAILED 32789
+#define ERROR_INVALID_DOS_DD 32790
+#define ERROR_BLOCKED 32791
+#define ERROR_NOBLOCK 32792
+#define ERROR_INSTANCE_SHARED 32793
+#define ERROR_NO_OBJECT 32794
+#define ERROR_PARTIAL_ATTACH 32795
+#define ERROR_INCACHE 32796
+#define ERROR_SWAP_IO_PROBLEMS 32797
+#define ERROR_CROSSES_OBJECT_BOUNDARY 32798
+#define ERROR_LONGLOCK 32799
+#define ERROR_SHORTLOCK 32800
+#define ERROR_UVIRTLOCK 32801
+#define ERROR_ALIASLOCK 32802
+#define ERROR_ALIAS 32803
+#define ERROR_NO_MORE_HANDLES 32804
+#define ERROR_SCAN_TERMINATED 32805
+#define ERROR_TERMINATOR_NOT_FOUND 32806
+#define ERROR_NOT_DIRECT_CHILD 32807
+#define ERROR_DELAY_FREE 32808
+#define ERROR_GUARDPAGE 32809
+#define ERROR_SWAPERROR 32900
+#define ERROR_LDRERROR 32901
+#define ERROR_NOMEMORY 32902
+#define ERROR_NOACCESS 32903
+#define ERROR_NO_DLL_TERM 32904
+#define ERROR_CPSIO_CODE_PAGE_INVALID 65026
+#define ERROR_CPSIO_NO_SPOOLER 65027
+#define ERROR_CPSIO_FONT_ID_INVALID 65028
+#define ERROR_CPSIO_INTERNAL_ERROR 65033
+#define ERROR_CPSIO_INVALID_PTR_NAME 65034
+#define ERROR_CPSIO_NOT_ACTIVE 65037
+#define ERROR_CPSIO_PID_FULL 65039
+#define ERROR_CPSIO_PID_NOT_FOUND 65040
+#define ERROR_CPSIO_READ_CTL_SEQ 65043
+#define ERROR_CPSIO_READ_FNT_DEF 65045
+#define ERROR_CPSIO_WRITE_ERROR 65047
+#define ERROR_CPSIO_WRITE_FULL_ERROR 65048
+#define ERROR_CPSIO_WRITE_HANDLE_BAD 65049
+#define ERROR_CPSIO_SWIT_LOAD 65074
+#define ERROR_CPSIO_INV_COMMAND 65077
+#define ERROR_CPSIO_NO_FONT_SWIT 65078
+#define ERROR_ENTRY_IS_CALLGATE 65079
+
+#endif /* INCL_ERROR2_H || INCL_DOSERRORS */
diff --git a/private/os2/ldr/exe386.h b/private/os2/ldr/exe386.h
new file mode 100644
index 000000000..631341423
--- /dev/null
+++ b/private/os2/ldr/exe386.h
@@ -0,0 +1,870 @@
+/*
+ * Title
+ *
+ * exe386.h
+ * (C) Copyright Microsoft Corp 1988-1990
+ *
+ * Description
+ *
+ * Data structure definitions for the OS/2
+ * executable file format (flat model).
+ *
+ * Modification History
+ *
+ * 90/07/30 Wieslaw Kalkus Modified linear-executable
+ * 88/08/05 Wieslaw Kalkus Initial version
+ */
+
+
+
+ /*_________________________________________________________________*
+ | |
+ | |
+ | OS/2 .EXE FILE HEADER DEFINITION - 386 version 0:32 |
+ | |
+ |_________________________________________________________________|
+ * */
+
+#define BITPERBYTE 8 /* Should never change */
+#define BITPERWORD 16 /* I'm not sure about this one */
+#define OBJPAGELEN 4096 /* Memory page size in bytes */
+#define E32RESBYTES1 1 /* First bytes reserved */
+#define E32RESBYTES2 0 /* Second bytes reserved */
+#define E32RESBYTES3 8 /* Third bytes reserved */
+#define E32RESBYTES4 28
+#define STD_EXTRA 7 /* Standard number of extra information*/
+ /* units palced in the header; this */
+ /* includes the following tables: */
+ /* - export, import, resource, */
+ /* exception, security, fixup and */
+ /* debug information */
+#define EXP 0 /* Export table position */
+#define IMP 1 /* Import table position */
+#define RES 2 /* Resource table position */
+#define EXC 3 /* Exception table position */
+#define SEC 4 /* Security table position */
+#define FIX 5 /* Fixup table position */
+#define DEB 6 /* Debug table position */
+
+struct info /* Extra information header block */
+{
+ unsigned long rva; /* Virtual relative address of info */
+ unsigned long size; /* Size of information block */
+};
+
+
+struct e32_exe /* LE 32-bit .EXE header */
+{
+ unsigned char e32_magic[4]; /* Magic number E32_MAGIC */
+ unsigned char e32_bworder; /* The byte/word ordering for the .EXE */
+ unsigned char e32_res1[E32RESBYTES1];
+ /* Reserved bytes - must be zero */
+ unsigned short e32_cpu; /* The CPU type */
+ unsigned short e32_os; /* The OS type */
+ unsigned short e32_subsys; /* The subsystem type */
+ unsigned short e32_osmajor; /* The operating system major ver. no. */
+ unsigned short e32_osminor; /* The operating system minor ver. no. */
+ unsigned short e32_linkmajor; /* The linker major version number */
+ unsigned short e32_linkminor; /* The linker minor version number */
+ unsigned short e32_usermajor; /* The user major version number */
+ unsigned short e32_userminor; /* The user minor version number */
+ unsigned long e32_mflags; /* Module flags */
+ unsigned long e32_vpages; /* Number of pages in memory image */
+ unsigned long e32_filechksum; /* Checksum for entire file */
+ unsigned long e32_entryrva; /* Relative virt. addr. of entry point */
+
+ unsigned long e32_vbase; /* Virtual base address of module */
+ unsigned long e32_vsize; /* Virtual size of the entire image */
+ unsigned long e32_hdrsize; /* Header information size */
+ unsigned long e32_filealign; /* Alignment factor used to */
+ /* align/truncate image pages */
+ unsigned long e32_pagesize; /* The size of one page for this module*/
+ unsigned long e32_timestamp; /* Time the .EXE file was created/modified*/
+ unsigned long e32_stackmax; /* Maximum stack size */
+ unsigned long e32_stackinit; /* Initial committed stack size */
+ unsigned long e32_heapmax; /* Maximum heap size */
+ unsigned long e32_heapinit; /* Initial committed heap size */
+ unsigned long e32_objcnt; /* Number of memory objects */
+ unsigned long e32_objtab; /* Object table offset */
+ unsigned long e32_dircnt; /* Number of module directives */
+ unsigned long e32_dirtab; /* Module format directives table off */
+ unsigned char e32_res3[E32RESBYTES3];
+ /* Reserved bytes - must be zero */
+ unsigned long e32_rescnt; /* Number of resources */
+ unsigned long e32_hdrextra; /* Number of extra info units in header*/
+ struct info e32_unit[STD_EXTRA];
+ /* Array of extra info units */
+ unsigned char e32_res4[E32RESBYTES4];
+};
+
+
+#define E32HDR_SIZE sizeof(struct e32_exe)
+
+#define E32_MAGIC(x) ((unsigned short)((x).e32_magic[0]<<BITPERBYTE)|(x).e32_magic[1])
+#define E32_MAGIC1(x) (x).e32_magic[0]
+#define E32_MAGIC2(x) (x).e32_magic[1]
+#define E32_BWORDER(x) (x).e32_bworder
+#define E32_CPU(x) (x).e32_cpu
+#define E32_OS(x) (x).e32_os
+#define E32_SUBSYS(x) (x).e32_subsys
+#define E32_OSMAJOR(x) (x).e32_osmajor
+#define E32_OSMINOR(x) (x).e32_osminor
+#define E32_LINKMAJOR(x) (x).e32_linkmajor
+#define E32_LINKMINOR(x) (x).e32_linkminor
+#define E32_USERMAJOR(x) (x).e32_usermajor
+#define E32_USERMINOR(x) (x).e32_userminor
+#define E32_MFLAGS(x) (x).e32_mflags
+#define E32_VPAGES(x) (x).e32_vpages
+#define E32_FILECHKSUM(x) (x).e32_filechksum
+#define E32_ENTRYRVA(x) (x).e32_entryrva
+#define E32_VBASE(x) (x).e32_vbase
+#define E32_VSIZE(x) (x).e32_vsize
+#define E32_HDRSIZE(x) (x).e32_hdrsize
+#define E32_FILEALIGN(x) (x).e32_filealign
+#define E32_PAGESIZE(x) (x).e32_pagesize
+#define E32_TIMESTAMP(x) (x).e32_timestamp
+#define E32_STACKMAX(x) (x).e32_stackmax
+#define E32_STACKINIT(x) (x).e32_stackinit
+#define E32_HEAPMAX(x) (x).e32_heapmax
+#define E32_HEAPINIT(x) (x).e32_heapinit
+#define E32_OBJCNT(x) (x).e32_objcnt
+#define E32_OBJTAB(x) (x).e32_objtab
+#define E32_DIRCNT(x) (x).e32_dircnt
+#define E32_DIRTAB(x) (x).e32_dirtab
+#define E32_RESCNT(x) (x).e32_rescnt
+#define E32_HDREXTRA(x) (x).e32_hdrextra
+#define E32_EXPTAB(x) (x).e32_unit[EXP].rva
+#define E32_EXPSIZ(x) (x).e32_unit[EXP].size
+#define E32_IMPTAB(x) (x).e32_unit[IMP].rva
+#define E32_IMPSIZ(x) (x).e32_unit[IMP].size
+#define E32_RESTAB(x) (x).e32_unit[RES].rva
+#define E32_RESSIZ(x) (x).e32_unit[RES].size
+#define E32_EXCTAB(x) (x).e32_unit[EXC].rva
+#define E32_EXCSIZ(x) (x).e32_unit[EXC].size
+#define E32_SECTAB(x) (x).e32_unit[SEC].rva
+#define E32_SECSIZ(x) (x).e32_unit[SEC].size
+#define E32_FIXTAB(x) (x).e32_unit[FIX].rva
+#define E32_FIXSIZ(x) (x).e32_unit[FIX].size
+#define E32_DEBTAB(x) (x).e32_unit[DEB].rva
+#define E32_DEBSIZ(x) (x).e32_unit[DEB].size
+
+
+
+/*
+ * Valid linear-executable signature:
+ */
+
+#define E32MAGIC1 'L' /* New magic number "LE" */
+#define E32MAGIC2 'E' /* New magic number "LE" */
+#define E32MAGIC 0x454c /* New magic number "LE" */
+
+/*
+ * Format of E32_BWORDER(x):
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | |
+ * | +--- Big Endian Byte Ordering (else Little Endian)
+ * +----- Big Endian Word Ordering (else Little Endian)
+ */
+
+#define E32LEBO 0x00 /* Little Endian Byte Order */
+#define E32BEBO 0x01 /* Big Endian Byte Order */
+#define E32LEWO 0x00 /* Little Endian Word Order */
+#define E32BEWO 0x02 /* Big Endian Word Order */
+
+/*
+ * Valid CPU types:
+ */
+
+#define E32CPUUNKNOWN 0x000 /* Unknown CPU */
+#define E32CPU286 0x001 /* Intel 80286 or upwardly compatibile */
+#define E32CPU386 0x002 /* Intel 80386 or upwardly compatibile */
+#define E32CPU486 0x003 /* Intel 80486 or upwardly compatibile */
+#define E32CPU586 0x004 /* Intel 80586 or upwardly compatibile */
+#define E32CPUi860 0x020 /* Intel i860 or upwardly compatibile */
+#define E32CPUixxx 0x021 /* Intel i??? or upwardly compatibile */
+#define E32CPUMIPS_I 0x040 /* MIPS Mark I (R2000, R3000) */
+#define E32CPUMIPS_II 0x041 /* MIPS Mark II (R6000) */
+#define E32CPUMIPS_III 0x042 /* MIPS Mark II (R4000) */
+
+/*
+ * Target operating systems
+ */
+
+#define E32_UNKNOWN NE_UNKNOWN /* Unknown (any "new-format" OS) */
+#define E32_OS2 NE_OS2 /* Microsoft/IBM OS/2 (default) */
+#define E32_WINDOWS NE_WINDOWS /* Microsoft Windows */
+#define E32_DOS NE_DOS4 /* Microsoft MS-DOS */
+#define E32_NT 0x4 /* NT */
+#define E32_UNIX 0x5 /* UNIX */
+
+
+#ifndef FALSE
+
+/* DEFINED in the newexe.h !!!!! */
+
+#define NE_UNKNOWN 0x0 /* Unknown (any "new-format" OS) */
+#define NE_OS2 0x1 /* Microsoft/IBM OS/2 (default) */
+#define NE_WINDOWS 0x2 /* Microsoft Windows */
+#define NE_DOS4 0x3 /* Microsoft MS-DOS 4.x */
+#define NE_DEV386 0x4 /* Microsoft Windows 386 */
+#endif
+
+/*
+ * Target subsystems required to run module
+ */
+
+#define E32_SUB_UNKNOWN 0x0 /* Unknown subsystem */
+#define E32_SUB_OS2 0x1 /* OS/2 subsystem */
+#define E32_SUB_WINDOWS 0x2 /* Windows subsystem */
+#define E32_SUB_NATIVE 0x4 /* NT native subsystem */
+#define E32_SUB_POSIX 0x5 /* POSIX subsystem */
+
+
+/*
+ * Format of E32_MFLAGS(x):
+ *
+ * 31 25 24 16 15 8 7 0
+ * #### #### | #### #### | #### #### | #### #### - bit no
+ * |||| |||| |||| |||| |||| |||| |||| ||||
+ * |||| |||| |||| |||| |||| |||| |||| ||++-- Reserved - must be zero
+ * |||| |||| |||| |||| |||| |||| |||| |+---- Per-Process Library Initialization
+ * |||| |||| |||| |||| |||| |||| |||| +----- Reserved - must be zero
+ * |||| |||| |||| |||| |||| |||| |||+------- Resolved fixups have been removed
+ * |||| |||| |||| |||| |||| |||| +++-------- Reserved - must be zero
+ * |||| |||| |||| |||| |||| |+++-------------- Application type
+ * |||| |||| |||| |||| |||+-+----------------- Reserved - must be zero
+ * |||| |||| |||| |||| ||+-------------------- Module not Loadable
+ * |||| |||| |||| |||| |+--------------------- Reserved - must be zero
+ * |||| |||| |||| ||++---+---------------------- Module type
+ * ||++-++++---++++-++---------------------------- Reserved - must be zero
+ * |+--------------------------------------------- Per-Process Library Termination
+ * +---------------------------------------------- Reserved - must be zero
+ *
+ */
+
+
+#define E32_LIBINIT 0x0004L /* Per-Process Library Initialization */
+#define E32_NOINTFIX 0x0010L /* Resolved fixups have been removed */
+
+/*
+ * Application types:
+ *
+ * 0x000 - Illegal - reserved for future use
+ * 0x100 - Incompatible with PM windowing
+ * 0x200 - Compatible with PM windowing
+ * 0x300 - Uses PM windowing API
+ * 0x400 - Illegal - reserved for future use
+ * 0x500 - Illegal - reserved for future use
+ * 0x600 - Illegal - reserved for future use
+ * 0x700 - Illegal - reserved for future use
+ */
+
+#define E32_NOPMW 0x0100L /* Incompatible with PM Windowing */
+#define E32_PMW 0x0200L /* Compatible with PM Windowing */
+#define E32_PMAPI 0x0300L /* Uses PM Windowing API */
+#define E32_APPMASK 0x0700L /* Aplication Type Mask */
+
+#define E32_NOLOAD 0x2000L /* Module not Loadable */
+
+/*
+ * Module types:
+ *
+ * 0x00000 - Program module
+ * 0x08000 - Dynamic-Link Library module
+ * 0x10000 - Illegal - reserved for future use
+ * 0x18000 - Illegal - reserved for future use
+ * 0x20000 - Physical Device Driver module
+ * 0x28000 - Virtual Device Driver module
+ * 0x30000 - Illegal - reserved for future use
+ * 0x38000 - Illegal - reserved for future use
+ */
+
+#define E32_MODEXE 0x00000L /* Program module */
+#define E32_MODDLL 0x08000L /* Library Module - used as NENOTP */
+#define E32_MODPDEV 0x20000L /* Physical device driver */
+#define E32_MODVDEV 0x28000L /* Virtual device driver */
+#define E32_MODMASK 0x38000L /* Module type mask */
+
+#define E32_NOFIXUPS 0x20000000L /* Image has no fixups that reference the IAT or EAT */
+#define E32_LIBTERM 0x40000000L /* Per-Process library termination */
+#define E32_PURE32 0x80000000L /* Image is pure 32 bit */
+
+#define IsINSTINIT(x) ((x)&E32_LIBINIT)
+#define IsNOTRELOC(x) ((x)&E32_NOINTFIX)
+#define IsNOTGUI(x) (((x)&E32_APPMASK)==E32_NOPMW)
+#define IsGUICOMPAT(x) (((x)&E32_APPMASK)==E32_PMW)
+#define IsGUI(x) (((x)&E32_APPMASK)==E32_PMAPI)
+#define IsLOADABLE(x) (!((x)&E32_NOLOAD))
+#define IsAPLIPROG(x) (((x)&E32_MODMASK)==E32_MODEXE)
+#define IsDLL(x) (((x)&E32_MODMASK)==E32_MODDLL)
+#define IsPDEVICE(x) (((x)&E32_MODMASK)==E32_MODPDEV)
+#define IsVDEVICE(x) (((x)&E32_MODMASK)==E32_MODVDEV)
+#define NoFIXUPS(x) ((x)&E32_NOFIXUPS)
+#define IsINSTTERM(x) ((x)&E32_LIBTERM)
+#define IsPURE32(x) ((x)&E32_PURE32)
+
+#define SetINSTINIT(x) ((x)|=E32_LIBINIT)
+#define SetNOTRELOC(x) ((x)|=E32_NOINTFIX)
+#define SetNOTGUI(x) ((x)=((x)&~E32_APPMASK)|E32_NOPMW)
+#define SetGUICOMPAT(x) ((x)=((x)&~E32_APPMASK)|E32_PMW)
+#define SetGUI(x) ((x)=((x)&~E32_APPMASK)|E32_PMAPI)
+#define SetNOTLOADABLE(x) (((x)|=E32_NOLOAD))
+#define SetAPLIPROG(x) ((x)=((x)&~E32_MODMASK)|E32_MODEXE)
+#define SetDLL(x) ((x)=((x)&~E32_MODMASK)|E32_MODDLL)
+#define SetPDEVICE(x) ((x)=((x)&~E32_MODMASK)|E32_MODPDEV)
+#define SetVDEVICE(x) ((x)=((x)&~E32_MODMASK)|E32_MODVDEV)
+#define SetNOFIXUPS(x) ((x)|=E32_NOFIXUPS)
+#define SetINSTTERM(x) ((x)|=E32_LIBTERM)
+#define SetPURE32(x) ((x)|=E32_PURE32)
+
+
+/*
+ * OBJECT TABLE
+ */
+
+/***ET+ o32_obj Object Table Entry */
+
+struct o32_obj /* .EXE memory object table entry */
+{
+ unsigned long o32_rva; /* Object relative virtual address */
+ unsigned long o32_vsize; /* Virtual memory size */
+ unsigned long o32_pages; /* Image pages offset */
+ unsigned long o32_psize; /* Physical file size of init. data*/
+ unsigned long o32_flags; /* Attribute flags for the object */
+ unsigned long o32_reserved;
+};
+
+#define O32_OBJSIZE sizeof(struct o32_obj)
+
+#define O32_RVA(x) (x).o32_rva
+#define O32_VSIZE(x) (x).o32_vsize
+#define O32_PAGES(x) (x).o32_pages
+#define O32_PSIZE(x) (x).o32_psize
+#define O32_FLAGS(x) (x).o32_flags
+
+
+/*
+ * Format of O32_FLAGS(x)
+ *
+ * 31 25 24 16 15 8 7 0
+ * #### #### | #### #### | #### #### | #### #### - bit no
+ * |||| |||| |||| |||| |||| |||| |||| ||||
+ * |||| |||| |||| |||| |||| |||| |||| |||+-- Readable object
+ * |||| |||| |||| |||| |||| |||| |||| ||+--- Writable object
+ * |||| |||| |||| |||| |||| |||| |||| |+---- Executable object
+ * |||| |||| |||| |||| |||| |||| |||| +----- Resource object
+ * |||| |||| |||| |||| |||| |||| |||+------- Discardable object
+ * |||| |||| |||| |||| |||| |||| ||+-------- Shared object
+ * |||| |||| |||| |||| |||| |||| |+--------- Reserved - must be zero
+ * |||| |||| |||| |||| |||| |||| +---------- Trailing pages are invalid
+ * |||| |||| |||| |||| |||| ++++-------------- Object type
+ * |||| |||| |||| |||| |||+------------------- 16:16 Alias required
+ * |||| |||| |||| |||| ||+-------------------- Big/Default bit setting
+ * |||| |||| |||| |||| |+--------------------- Object is conformin for code
+ * |||| |||| |||| |||| +---------------------- Object has I/O privilege level
+ * |||| |||| |||| |||+-------------------------- Object must not be cached
+ * |||| |||| |||| ||+--------------------------- Debug object
+ * ++++-++++---++++-+++--------------------------- Reserved - must be zero
+ *
+ */
+
+#define OBJ_READ 0x0001L /* Readable Object */
+#define OBJ_WRITE 0x0002L /* Writeable Object */
+#define OBJ_EXEC 0x0004L /* Executable Object */
+#define OBJ_RSRC 0x0008L /* Resource Object */
+
+#define OBJ_DISCARD 0x0010L /* Object is Discardable */
+#define OBJ_SHARED 0x0020L /* Object is Shared */
+#define OBJ_INVALID 0x0080L /* Object has trailing invalid pages */
+
+/*
+ * Object types:
+ *
+ * 0x0000 - object is nonpermanent or normal EXE, DLL object
+ * 0x0100 - object is permanent (FDSs, VDDs, PDDs only)
+ * 0x0200 - object is resident (FDSs, VDDs, PDDs only)
+ * 0x0300 - object is contiguous (FDSs, VDDs, PDDs only)
+ * 0x0400 - object is dynamic (FDSs, VDDs, PDDs only)
+ * 0x0500 - illegal - reserved for future use
+ * 0x0600 - illegal - reserved for future use
+ * 0x0700 - illegal - reserved for future use
+ * 0x0800 - object reserves space for call-gates
+ * 0x0900 - illegal - reserved for future use
+ * 0x0a00 - illegal - reserved for future use
+ * 0x0b00 - illegal - reserved for future use
+ * 0x0c00 - illegal - reserved for future use
+ * 0x0d00 - illegal - reserved for future use
+ * 0x0e00 - illegal - reserved for future use
+ * 0x0f00 - illegal - reserved for future use
+ *
+ */
+
+#define OBJ_NONPERM 0x0000L /* Object is nonpermanent */
+#define OBJ_PERM 0x0100L /* Object is permanent and swappable */
+#define OBJ_RESIDENT 0x0200L /* Object is permanent and resident */
+#define OBJ_CONTIG 0x0300L /* Object is resident and contiguous */
+#define OBJ_DYNAMIC 0x0400L /* Object is dynamic */
+#define OBJ_GATE 0x0800L /* Object reserves space for call-gates */
+#define OBJ_TYPEMASK 0x0f00L /* Object type mask */
+
+
+#define OBJ_ALIAS16 0x1000L /* 16:16 alias required (80x86 specific) */
+#define OBJ_BIGDEF 0x2000L /* Big/Default bit setting (80x86 specific) */
+#define OBJ_CONFORM 0x4000L /* Object is conforming for code (80x86 specific) */
+#define OBJ_IOPL 0x8000L /* Object I/O privilege level (80x86 specific) */
+#define OBJ_CACHE 0x10000L /* Object must be cached */
+#define OBJ_DEBUG 0x20000L /* Object describes debugger information */
+
+#define IsREADABLE(x) ((x)&OBJ_READ)
+#define IsWRITEABLE(x) ((x)&OBJ_WRITE)
+#define IsEXECUTABLE(x) ((x)&OBJ_EXEC)
+#define IsRESOURCE(x) ((x)&OBJ_RSRC)
+#define IsDISCARDABLE(x) ((x)&OBJ_DISCARD)
+#define IsSHARED(x) ((x)&OBJ_SHARED)
+#define IsINVALID(x) ((x)&OBJ_INVALID)
+#define IsNONPERM(x) (((x)&OBJ_TYPEMASK)==OBJ_NONPERM)
+#define IsPERMANENT(x) (((x)&OBJ_TYPEMASK)==OBJ_PERM)
+#define IsRESIDENT(x) (((x)&OBJ_TYPEMASK)==OBJ_RESIDENT)
+#define IsCONTIG(x) (((x)&OBJ_TYPEMASK)==OBJ_CONTIG)
+#define IsDYNAMIC(x) (((x)&OBJ_TYPEMASK)==OBJ_DYNAMIC)
+#define IsGATERESERV(x) (((x)&OBJ_TYPEMASK)==OBJ_GATE)
+#define ObjTYPE(x) ((x)&OBJ_TYPEMASK)
+#define IsALIAS16(x) ((x)&OBJ_ALIAS16)
+#define IsBIGDEF(x) ((x)&OBJ_BIGDEF)
+#define IsCONFORMING(x) ((x)&OBJ_CONFORM)
+#define IsIOPL(x) ((x)&OBJ_IOPL)
+#define IsCACHED(x) ((x)&OBJ_CACHE)
+#define IsDEBUG(x) ((x)&OBJ_DEBUG)
+
+#define SetREADABLE(x) ((x)|=OBJ_READ)
+#define SetWRITABLE(x) ((x)|=OBJ_WRITE)
+#define SetEXECUTABLE(x) ((x)|=OBJ_EXEC)
+#define SetRESOURCE(x) ((x)|=OBJ_RSRC)
+#define SetDISCARABLE(x) ((x)|=OBJ_DISCARD)
+#define SetSHARED(x) ((x)|=OBJ_SHARED)
+#define SetINVALID(x) ((x)|=OBJ_INVALID)
+#define SetNONPERM(x) ((x)=((x)&~OBJ_TYPEMASK)|OBJ_NONPERM)
+#define SetPERMANENT(x) ((x)=((x)&~OBJ_TYPEMASK)|OBJ_PERM)
+#define SetRESIDENT(x) ((x)=((x)&~OBJ_TYPEMASK)|OBJ_RESIDENT)
+#define SetCONTIG(x) ((x)=((x)&~OBJ_TYPEMASK)|OBJ_CONTIG)
+#define SetDYNAMIC(x) ((x)=((x)&~OBJ_TYPEMASK)|OBJ_DYNAMIC)
+#define SetGATERESERV(x) ((x)=((x)&~OBJ_TYPEMASK)|OBJ_GATE)
+#define SetALIAS16(x) ((x)|=OBJ_ALIAS16)
+#define SetBIGDEF(x) ((x)|=OBJ_BIGDEF)
+#define SetCONFORMING(x) ((x)|=OBJ_CONFORM)
+#define SetIOPL(x) ((x)|=OBJ_IOPL)
+#define SetCACHED(x) ((x)|=OBJ_CACHE)
+#define SetDEBUG(x) ((x)|=OBJ_DEBUG)
+
+/*
+ * MODULE FORMAT DIRECTIVES TABLE
+ */
+
+struct FmtDir
+{
+ unsigned short dir; /* Directive number */
+ unsigned short reserved;
+ unsigned long offset; /* Directive data offset */
+ unsigned long length; /* Directive data length */
+};
+
+#define FMTDIR_SIZE sizeof(struct FmtDir)
+
+#define DIRECTIVE(x) (x).dir
+#define DIR_OFF(x) (x).offset
+#define DIR_LEN(x) (x).length
+
+/*
+ * Directive numbers
+ */
+
+#define OS2LDR16 0x200
+#define OS2RSRCNT 0x300
+#define OS2FIXMAP 0x400
+
+struct ComDir
+{
+ unsigned long stackobj;
+ unsigned long autods;
+};
+
+#define COMDIR_SIZE sizeof(struct ComDir)
+
+
+/*
+ * EXPORT ADDRESS TABLE - Previously called entry table
+ */
+
+struct ExpHdr /* Export directory table */
+{
+ unsigned long exp_flags; /* Export table flags */
+ unsigned long exp_ver; /* Version stamp */
+ unsigned long exp_size; /* Export table size */
+ unsigned long exp_dllname; /* Offset to the DLL name */
+ unsigned long exp_ordbase; /* First valid ordinal */
+ unsigned long exp_eatcnt; /* Number of EAT entries */
+ unsigned long exp_namecnt; /* Number of exported names */
+ unsigned long exp_eat; /* Export Address Table offset */
+ unsigned long exp_name; /* Export name pointers table off */
+ unsigned long exp_ordinal; /* Export ordinals table offset */
+};
+
+#define EXPHDR_SIZE sizeof(struct ExpHdr)
+
+#define EXP_FLAGS(x) (x).exp_flags
+#define EXP_DLLNAME(x) (x).exp_dllname
+#define EXP_VER(x) (x).exp_ver
+#define EXP_SIZE(x) (x).exp_size
+#define EXP_ORDBASE(x) (x).exp_ordbase
+#define EXP_EATCNT(x) (x).exp_eatcnt
+#define EXP_NAMECNT(x) (x).exp_namecnt
+#define EXP_EAT(x) (x).exp_eat
+#define EXP_NAME(x) (x).exp_name
+#define EXP_ORDINAL(x) (x).exp_ordinal
+
+/*
+ * EXPORT ADDRESS TABLE MASKS
+ */
+
+#define ESCAPE_BIT 0x80000000L /* Escape bit in export address */
+#define ADDR_MASK 0x7fffffffL /* Export address mask */
+#define VALUE_MASK 0x3fffffffL /* Value mask */
+
+/*
+ * ENTRY TYPES - TT field values
+ */
+
+#define AUX_DATA 0x40000000L /* Auxiliary data present */
+
+#define IsESCAPED(x) ((x)&ESCAPE_BIT)
+#define IsAUXDATA(x) ((x)&AUX_DATA)
+
+#define SetESCAPE(x) ((x)|=ESCAPE_BIT)
+#define SetAUXDATA(x) ((x)|=AUX_DATA)
+#define SetVALUE(x,v) ((x)|=((v)&VALUE_MASK))
+
+/*
+ * AUXILIARY DATA TYPES
+ */
+
+#define ABS_DATA 0x00
+#define INT_GATE 0x01
+#define EXT_GATE 0x02
+#define FORWARDER 0x03
+
+/*
+ * AUXILIARY DATA ENTRIES
+ */
+
+#pragma pack(1)
+
+struct AuxData
+{
+ unsigned char dataType;
+ unsigned char reserved;
+ union
+ {
+ struct AbsData
+ {
+ unsigned short reserved;
+ unsigned long val;
+ }
+ abs;
+ struct GateData
+ {
+ unsigned char obj;
+ unsigned char parm;
+ unsigned short off;
+ unsigned short sel;
+ }
+ gate;
+ struct FwdData
+ {
+ unsigned short idx;
+ unsigned long iat;
+ }
+ fwd;
+ }
+ data;
+};
+
+#pragma pack()
+
+#define DATA_TYP(x) (x).dataType
+#define ABS_VAL(x) (x).data.abs.val
+#define GATE_OBJ(x) (x).data.gate.obj
+#define GATE_PARM(x) (x).data.gate.parm
+#define GATE_OFF(x) (x).data.gate.off
+#define GATE_SEL(x) (x).data.gate.sel
+#define FWD_IDX(x) (x).data.fwd.idx
+#define FWD_IAT(x) (x).data.fwd.iat
+
+
+/*
+ * IMPORT MODULE DESCRIPTOR TABLE
+ */
+
+struct ImpHdr /* Import directory table */
+{
+ unsigned long imp_flags; /* Import table flags */
+ unsigned long imp_ver; /* Version stamp */
+ unsigned long imp_reserved;
+ unsigned long imp_dllname; /* Offset to the DLL name */
+ unsigned long imp_address; /* Import address table offset */
+};
+
+#define IMPHDR_SIZE sizeof(struct ImpHdr)
+
+#define IMP_FLAGS(x) (x).imp_flags
+#define IMP_VER(x) (x).imp_ver
+#define IMP_DLLNAME(x) (x).imp_dllname
+#define IMP_ADDRESS(x) (x).imp_address
+
+/*
+ * Format of IMP_FLAGS(x)
+ *
+ * 31 25 24 16 15 8 7 0
+ * #### #### | #### #### | #### #### | #### #### - bit no
+ * |||| |||| |||| |||| |||| |||| |||| ||||
+ * |||| |||| |||| |||| |||| |||| |||| |||+-- Copy of the IAT in header
+ * ++++-++++---++++-++++---++++-++++---++++-+++--- Reserved - must be zero
+ *
+ */
+
+#define HDRIAT 0x01
+
+#define IsHDRIAT(x) ((x)&HDRIAT)
+
+#define SetHDRIAT(x) ((x)|=HDRIAT)
+
+
+struct ImpMod
+{
+ unsigned long im_offset; /* Imported module name table offset */
+ unsigned long im_vaddr; /* Import Address table virtual address */
+};
+
+#define IMPMOD_SIZE sizeof(struct ImpMod)
+
+#define IM_OFFSET(x) (x).im_offset
+#define IM_VADDR(x) (x).im_vaddr
+
+/*
+ * IMPORT PROCEDURE NAME TABLE
+ */
+
+struct ImpProc
+{
+ unsigned short ip_hint; /* Hint value */
+ char ip_name[1]; /* Zero terminated imported procedure name */
+};
+
+#define IP_HINT(x) (x).ip_hint;
+
+/*
+ * IMPORT ADDRESS TABLE
+ */
+
+/*
+ * Valid import address types:
+ *
+ * 0x00000000 - 0:32 Offset - Flat offset
+ * 0x20000000 - 16:16 non-FLAT, non-gate pointer
+ * 0x40000000 - 16:16 gate pointer - Callgate needed if used
+ * 0x60000000 - Illegal - reserved for future use
+ *
+ */
+
+#define IMPORD_MASK 0x1fffffffL /* Ordinal number mask */
+#define IMPOFF_MASK 0x1fffffffL /* Import data offset mask */
+#define IMPTYPE_MASK 0x60000000L /* Import address type mask */
+#define ORD_BIT 0x80000000L /* Import by ordinal bit */
+
+#define IMP_FLATOFF 0x00000000L /* FLAT offset */
+#define IMP_ALIAS 0x20000000L /* 16:16 non-FLAT, non-gate pointer */
+#define IMP_GATE 0x40000000L /* 16:16 gate pointer */
+
+#define IsIMPBYORD(x) ((x)&ORD_BIT)
+#define IsFLATIMP(x) (!((x)&IMPTYPE_MASK))
+#define IsALIASIMP(x) (((x)&IMPTYPE_MASK)==IMP_ALIAS)
+#define IsGATEIMP(x) (((x)&IMPTYPE_MASK)==IMP_GATE)
+
+/*
+ * RESOURCE TABLE
+ */
+
+/***ET+ rsrc32 - Resource Table Entry */
+
+struct ResDir
+{
+ unsigned long dir_flags;
+ unsigned long dir_ver;
+ unsigned long dir_size;
+ unsigned short dir_namecnt;
+ unsigned short dir_idcnt;
+};
+
+
+struct ResDirEntry
+{
+ unsigned long dir_name;
+ unsigned long dir_data;
+};
+
+struct ResDirStrEntry
+{
+ unsigned short str_len;
+ char ast_ascii[1];
+};
+
+struct ResData
+{
+ unsigned long res_data;
+ unsigned long res_size;
+ unsigned long res_codepage;
+ unsigned long res_reserved;
+};
+
+/*end*/
+
+
+/*
+ * RELOCATION DEFINITIONS - RUN-TIME FIXUPS
+ */
+
+
+/***ET+ r32_rlc - Relocation item */
+
+struct r32_rlc
+{
+ unsigned short flags;
+ unsigned char cnt;
+ unsigned char obj;
+};
+
+
+#define R32_FLAGS(x) (x).flags
+#define R32_CNT(x) (x).cnt
+#define R32_OBJ(x) (x).obj
+
+
+/*
+ * Format of R32_FLAGS - relocation flags
+ *
+ * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no
+ * | | | | | | | | | | | | | | | |
+ * | | | | | | | | | | | | +-+-+-+--- Source type
+ * | | | | | | | | | | | +----------- Fixup to 16:16 alias
+ * | | | | | | | | | | +------------- Reserved - must be zero
+ * | | | | | | | | | +--------------- Fixup data present
+ * | | | | | | | | +----------------- Reserved - must be zero
+ * | | | | | | +-+------------------- Reference type
+ * | | | | | +----------------------- Target has IOPL - valid only for non-aliased selector fixups
+ * | | | | +-------------------------- Target is CODE (else DATA) - valid only for non-aliased selector fixups
+ * | +--+--+----------------------------- Reserved - must be zero
+ * +-------------------------------------- Escaped fixup
+ */
+
+/*
+ * Valid source types:
+ *
+ * 0x00 - Byte fixup (8-bits)
+ * 0x01 - Align fixup - nop used to skip 2 bytes
+ * 0x02 - 16-bit Selector fixup (16-bits)
+ * 0x03 - 16:16 Pointer fixup (32-bits)
+ * 0x04 - Illegal - reserved for future use
+ * 0x05 - 16-bit Offset fixup (16-bits)
+ * 0x06 - 16:32 Pointer fixup (48-bits)
+ * 0x07 - 32-bit Offset fixup (32-bits)
+ * 0x08 - 32-bit Self-relative offset fixup (32-bits)
+ * 0x09 - Illegal - reserved for future use
+ * 0x0a - Illegal - reserved for future use
+ * 0x0b - Illegal - reserved for future use
+ * 0x0c - Illegal - reserved for future use
+ * 0x0d - Illegal - reserved for future use
+ * 0x0e - Illegal - reserved for future use
+ * 0x0f - Illegal - reserved for future use
+ */
+
+
+#define R32_BYTE 0x0000
+#define R32_ALIGN 0x0001
+#define R32_SEL 0x0002
+#define R32_PTR32 0x0003
+#define R32_OFF16 0x0005
+#define R32_PTR48 0x0006
+#define R32_OFF32 0x0007
+#define R32_SOFF32 0x0008
+#define R32_SRCMASK 0x000f
+
+#define IsBYTE(x) (((x)&R32_SRCMASK)==R32_BYTE)
+#define IsALIGN(x) (((x)&R32_SRCMASK)==R32_ALIGN)
+#define IsSEL(x) (((x)&R32_SRCMASK)==R32_SEL)
+#define IsPTR32(x) (((x)&R32_SRCMASK)==R32_PTR32)
+#define IsOFF16(x) (((x)&R32_SRCMASK)==R32_OFF16)
+#define IsPTR48(x) (((x)&R32_SRCMASK)==R32_PTR48)
+#define IsOFF32(x) (((x)&R32_SRCMASK)==R32_OFF32)
+#define IsSOFF32(x) (((x)&R32_SRCMASK)==R32_SOFF32)
+
+#define R32_ALIAS 0x0010 /* Fixup to alias */
+#define R32_FIXDATA 0x0040 /* Fixup data present */
+#define R32_IOPL 0x0080 /* Fixup Source has IOPL and is not conforming */
+
+
+#define IsALIAS(x) ((x)&R32_ALIAS)
+#define IsFIXDATA(x) ((x)&R32_FIXDATA)
+#define IsSRCIOPL(x) ((x)&R32_IOPL)
+
+/*
+ * Reference types:
+ *
+ * 0x0000 - internal reference
+ * 0x0100 - Imported reference by ordinal or name
+ * 0x0200 - Illegal - reserved for future use
+ * 0x0300 - Internal reference via export address table
+ *
+ */
+
+#define R32_INTER 0x0000 /* Internal reference */
+#define R32_IMPORT 0x0100 /* Imported reference */
+#define R32_ENTRY 0x0300 /* Internal entry table fixup */
+#define R32_REFMASK 0x0300 /* Reference type mask */
+
+#define IsINTERNAL(x) (((x)&R32_REFMASK)==R32_INTER)
+#define IsIMPORT(x) (((x)&R32_REFMASK)==R32_IMPORT)
+#define IsENTRY(x) (((x)&R32_REFMASK)==R32_ENTRY)
+
+#define TGT_IOPL 0x0400 /* Target has IOPL */
+#define TGT_CODE 0x0800 /* Target is CODE */
+
+#define IsTGTIOPL(x) ((x)&TGT_IOPL)
+#define IsTGTCODE(x) ((x)&TGT_CODE)
+
+#define R32_ESCAPE 0x8000
+#define IsESCAPEFIX(x) ((x)&R32_ESCAPE)
+
+/*end*/
+
+
+/*
+ * DEBUG INFORMATION
+ */
+
+struct DbgDir
+{
+ unsigned long dbg_flags;
+ unsigned long dbg_ver;
+ unsigned long dbg_size;
+ unsigned long dbg_type;
+ unsigned long dbg_lva;
+ unsigned long dbg_seek;
+};
+
+#define DBG_FLAGS(x) (x).dbg_flags
+#define DBG_TYPE(x) (x).dbg_type
+#define DBG_VER(x) (x).dbg_ver
+#define DBG_LVA(x) (x).dbg_lva
+#define DBG_SIZE(x) (x).dbg_size
+#define DBG_SEEK(x) (x).dbg_seek
+#define DBGDIR_SIZE sizeof(struct DbgDir)
diff --git a/private/os2/ldr/ldrdbcs.c b/private/os2/ldr/ldrdbcs.c
new file mode 100644
index 000000000..758a4770b
--- /dev/null
+++ b/private/os2/ldr/ldrdbcs.c
@@ -0,0 +1,159 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ ldrdbcs.c
+
+Abstract:
+
+ This module contains the multibyte string functions.
+
+Author:
+
+ Akihiko Sasaki (V-AkihiS) 23-June-1993
+
+Revision History:
+
+--*/
+
+#ifdef DBCS
+
+#include "ldrdbcs.h"
+
+unsigned char * _CRTAPI1
+ldrMultiByteStrchr(
+ const unsigned char *string,
+ unsigned short c
+ )
+{
+ const unsigned char ch = c;
+
+ while (*string != ch) {
+ if (IsDBCSLeadByte(*string)) {
+ string++;
+ }
+ if (*string == '\0')
+ return NULL;
+ string++;
+ }
+ return (unsigned char *)string;
+}
+
+unsigned char * _CRTAPI1
+ldrMultiByteStrrchr(
+ const unsigned char *string,
+ unsigned short c
+ )
+{
+ const unsigned char ch = c;
+ const unsigned char *lastoccurence = NULL;
+
+ while (1) {
+ if (IsDBCSLeadByte(*string)) {
+ string++;
+ } else {
+ if (*string == ch)
+ lastoccurence = string;
+ }
+ if (*string == '\0')
+ return (unsigned char *)lastoccurence;
+ string++;
+ }
+}
+
+unsigned char * _CRTAPI1
+ldrMultiByteStrstr(
+ const unsigned char *string1,
+ const unsigned char *string2
+ )
+{
+ if (*string2 == '\0')
+ return (unsigned char *)string1;
+ while((string1 = ldrMultiByteStrchr(string1, *string2)) != NULL) {
+ const unsigned char *substring1 = string1;
+ const unsigned char *substring2 = string2;
+
+ while (1) {
+ if (IsDBCSLeadByte(*substring1)) {
+ if (IsDBCSLeadByte(*substring2)) {
+ if (*substring1++ == *substring2++) {
+ if (*substring2 == '\0')
+ if (*substring1 == '\0')
+ return (unsigned char *)string1;
+ else
+ return NULL;
+ else if (*substring1++ != *substring2++)
+ break;
+ } else {
+ if (*substring1 == '\0' || *substring2 == '\0')
+ return NULL;
+ substring1 +=2;
+ substring2 +=2;
+ }
+ } else {
+ if (*substring2 == '\0') {
+ return (unsigned char *)string1;
+ } else {
+ substring1++;
+ if (*substring1 == '\0')
+ return NULL;
+ substring1++;
+ substring2++;
+ }
+ }
+ } else {
+ if (IsDBCSLeadByte(*substring2)) {
+ if (*substring1 == '\0') {
+ return NULL;
+ } else {
+ substring2++;
+ if (*substring2 == '\0')
+ return NULL;
+ substring1++;
+ substring2++;
+ }
+
+ } else {
+ if (*substring2 == '\0')
+ return (unsigned char *)string1;
+ else if (*substring1 == '\0')
+ return NULL;
+ else if (*substring1++ != *substring2++)
+ break;
+ }
+ }
+ }
+ string1++;
+ }
+ return NULL;
+}
+
+unsigned char * _CRTAPI1
+ldrMultiByteStrpbrk(
+ const unsigned char *string1,
+ const unsigned char *string2
+ )
+{
+ const unsigned char *substring1, *substring2;
+
+ substring1 = string1;
+ while (*substring1 != '\0') {
+ substring2 = string2;
+ if (IsDBCSLeadByte(*substring1)) {
+ substring1++;
+ if (*substring1 == '\0')
+ return NULL;
+ } else {
+ while (*substring2 != '\0') {
+ if (*substring1 == *substring2)
+ return (unsigned char *)substring1;
+ substring2++;
+ }
+ }
+ substring1++;
+ }
+ return NULL;
+}
+#endif
diff --git a/private/os2/ldr/ldrdbcs.h b/private/os2/ldr/ldrdbcs.h
new file mode 100644
index 000000000..f8ae6abe7
--- /dev/null
+++ b/private/os2/ldr/ldrdbcs.h
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ ldrdbcs.h
+
+Abstract:
+
+ Prototypes for OS/2 subsystem internal multibyte string functions
+
+Author:
+
+ Akihiko Sasaki (V-AkihiS) 23-June-1993
+
+Revision History:
+
+--*/
+
+#ifdef DBCS
+
+#include <string.h>
+
+unsigned char * _CRTAPI1
+ldrMultiByteStrchr(
+ const unsigned char *,
+ unsigned short
+ );
+
+unsigned char * _CRTAPI1
+ldrMultiByteStrrchr(
+ const unsigned char *,
+ unsigned short
+ );
+
+unsigned char * _CRTAPI1
+ldrMultiByteStrstr(
+ const unsigned char *,
+ const unsigned char *
+ );
+
+unsigned char * _CRTAPI1
+ldrMultiByteStrpbrk(
+ const unsigned char *,
+ const unsigned char *
+ );
+#endif
diff --git a/private/os2/ldr/ldrdll.def b/private/os2/ldr/ldrdll.def
new file mode 100644
index 000000000..7b2c4c119
--- /dev/null
+++ b/private/os2/ldr/ldrdll.def
@@ -0,0 +1,28 @@
+LIBRARY LDRDLL
+
+DESCRIPTION 'OS/2 Emulation Subsystem - 16-bit loader DLL'
+
+SECTIONS .text READ WRITE EXECUTE
+
+EXPORTS
+ LDRNewExe
+ ldrSetDescInfo
+ LDRStop
+ ldrstart
+ ldrLibiInit
+ ldrInit
+ LDRDosLoadModule
+ LDRGetProcAddr
+ LDRGetModName
+ LDRGetModHandle
+ LDRLibiReturn
+ LDRDosFreeModule
+ LDRGetResource
+ LDRGetResource2
+ LDRFreeResource
+ LDRQAppType
+ Od2JumpTo16SignalDispatch
+ LDRIsLDTValid
+ LDRExecInfo constant
+ LDRDoscallsSel constant
+ pldrLibiRecord constant
diff --git a/private/os2/ldr/ldrextrn.h b/private/os2/ldr/ldrextrn.h
new file mode 100644
index 000000000..c336d899a
--- /dev/null
+++ b/private/os2/ldr/ldrextrn.h
@@ -0,0 +1,127 @@
+#define INCL_OS2V20_TASKING
+#define INCL_OS2V20_MEMORY
+#define INCL_OS2V20_FILESYS
+#define INCL_ERROR_H
+#define INCL_TYPES
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <bseerr.h>
+#include "os2tile.h"
+#include "os2srv.h"
+#include "os2defp.h"
+#include "mi.h"
+#include "seldesc.h"
+#define FOR_EXEHDR 1
+#include "newexe.h"
+#include "exe386.h"
+#include "ldrvars.h"
+#include "ldrxport.h"
+#include "os2ldr.h"
+#ifdef DBCS
+// MSKK Apr.19.1993 V-AkihiS
+//
+// OS/2 internal multibyte string function.
+//
+#include "ldrdbcs.h"
+#define strpbrk ldrMultiByteStrpbrk
+#define strchr ldrMultiByteStrchr
+#define strrchr ldrMultiByteStrrchr
+#endif
+
+int ldrFindModule(PUCHAR pachModname, USHORT cb, USHORT class,
+ ldrmte_t **ppmte);
+int ldrOpenNewExe(PUCHAR pachModname, USHORT cb, ldrlv_t *plv,
+ PUSHORT pfl, PBOOLEAN pBound, PULONG pNEFlags);
+APIRET ldrGetMte(PUCHAR pachModname, USHORT cb, UCHAR chLdrtype,
+ USHORT class, ldrmte_t **ppmte, PBOOLEAN pBound, PULONG pNEFlags);
+int ldrGetModParams(ldrmte_t *pmte, ldrrei_t *pei);
+int ldrIsAttached(ldrmte_t *pmte);
+void ldrChkLoadType(ULONG lflags, ldrlv_t *plv);
+void ldrPromoteMTE(ldrmte_t *pmte);
+int ldrCheckGlobal(PUCHAR pachname, USHORT cb, ldrmte_t **ppmte);
+int ldrCheckSpecific(ldrmte_t **ppmte, ldrlv_t *plv);
+int ldrCheckInternalName(ldrmte_t *pmte);
+int ldrMungeFlags(struct e32_exe *pe32);
+APIRET ldrCreateMte(struct e32_exe *pe32, ldrlv_t *plv);
+int ldrMTEValidatePtrs(ldrmte_t *pmte, ULONG limit, ULONG constant);
+void ldrExpandSegment(ldrmte_t *pmte, UCHAR type);
+int ldrOpenPath(PUCHAR pachModname, USHORT cb, ldrlv_t *plv,
+ ULONG *pflmte);
+void ldrstart(ldrrei_t *pexec_info);
+ldrmte_t *ldrFindMTEForHandle(USHORT hmte);
+APIRET Allocate16BHandle(PUSHORT pusHandle, ULONG h32bHandle);
+APIRET Free16BHandle(USHORT usHandle);
+APIRET ldrAllocSegment(ldrmte_t *pmte, ldrste_t *pste, ulong_t iseg);
+APIRET ldrDoFixups(ri_t *pri, ulong_t laddr, struct taddr_s *ptaddr,
+ ushort_t segsize);
+APIRET ldrLoadIteratedData(ldrmte_t *pmte,
+ ldrste_t *pste,
+ PIO_STATUS_BLOCK pIoStatusBlock,
+ ULONG laddr);
+ldrote_t *ldrNumToOte(ldrmte_t *pmte, ulong_t objnum);
+APIRET ldrAllocSegments(ldrlv_t *plv);
+APIRET ldrLoadModule(ldrlv_t *plv);
+APIRET ldrLoadSegment(ldrmte_t *pmte, ldrste_t *pste);
+APIRET ldrGetTgtMte(ushort_t modord, ldrmte_t *pmte, ldrmte_t **ptgtmte);
+ulong_t ldrAscToOrd(char *pachstring, int cchstring);
+APIRET ldrGetOrdNum(ldrmte_t *pmte, uchar_t *pprocnam, ushort_t *pentord, int fstring);
+APIRET ldrGetOrdNumSub(uchar_t *pnt, uchar_t *pprocnam, ushort_t *pentord);
+APIRET ldrGetEntAddr(ushort_t entord, ldrmte_t *pmte,
+ struct taddr_s *ptaddr, ldrste_t *psrcste, ldrmte_t *psrcmte);
+APIRET ldrGetModule(PUCHAR pachModname, USHORT cb, char chLdrtype,
+ USHORT class, ldrmte_t **ppmte, PBOOLEAN pBound, PULONG pNEFlags);
+int ldrEachObjEntry(ulong_t objnum,
+ ldrmte_t *pmte,
+ int (*pwork)(ldret_t *pet, ulong_t *pentry,
+ ldrmte_t *pmte, ldrlv_t *plv),
+ ldrlv_t *plv);
+int ldrInitEntry(ldret_t *pet, ulong_t *pentry,
+ ldrmte_t *pmte, ldrlv_t *plv);
+int ldrEditProlog(ldret_t *pet, ulong_t *pentry,
+ ldrmte_t *pmte, ldrlv_t *plv);
+int ldrGetCallGate(ldret_t *pet, ulong_t *pentry,
+ ldrmte_t *pmte, ldrlv_t *plv);
+int ldrFreeCallGate(ldret_t *pet, ulong_t *pentry,
+ ldrmte_t *pmte, ldrlv_t *plv);
+ulong_t ldrSkipEnts(ldrmte_t *pmte, uchar_t type, uchar_t count);
+VOID ldrUnlinkMTE(ldrmte_t *pmte);
+VOID ldrTagModuleTree(ldrmte_t *pmte);
+VOID ldrTagModuleTree_USED(ldrmte_t *pmte);
+BOOLEAN ldrUnloadTagedModules(POS2_PROCESS Process);
+VOID ldrClearAllMteFlag(ULONG Flags);
+VOID ldrWriteErrTxt(int errcode);
+VOID ldrUCaseString(PCHAR pstring, ULONG cb);
+VOID ldrNewExeInit(POS2_THREAD t,P_LDRNEWEXE_MSG a,PUSHORT cb);
+#if PMNT
+BOOLEAN ldrSaveErrInfo(int errcode);
+VOID ldrRestoreErrInfo(int *errcode);
+BOOLEAN ldrFreeErrInfo(VOID);
+#endif
+
+#define SEL_RPL3 0x3 // Rpl Ring 3
+#define SEL_RPLCLR 0xfffc // Non RPL bits mask
+
+ULONG Ol2EntryFlat;
+ldrlibi_t *pldrLibiRecord;
+ULONG *pldrLibiCounter;
+
+PSTRING Od2ExecPgmErrorText;
+
+jmp_buf ljmpError;
+
+POS2_THREAD CurrentThread;
+
+ULONG ProgramIndex;
+
+ULONG LoadFactor;
+
+PSTRING pErrText;
+
+BOOLEAN fForceUnmap;
+
+BOOLEAN DoscallsLoaded;
+
+HANDLE R2XferSegHandle;
+
diff --git a/private/os2/ldr/ldrfixup.c b/private/os2/ldr/ldrfixup.c
new file mode 100644
index 000000000..1e5941eba
--- /dev/null
+++ b/private/os2/ldr/ldrfixup.c
@@ -0,0 +1,483 @@
+
+#include "ldrextrn.h"
+#ifdef PMNT
+#define INCL_32BIT
+#include "pmnt.h"
+extern PID PMNTPMShellPid;
+#endif
+
+/***LP ldrGetTgtMte - get target mte linear address
+ *
+ * Get MTE of module referenced by ordinal number passed. Use the
+ * ordinal number to index into the import module pointers table.
+ *
+ * ENTRY modord - ordinal number of module referenced
+ * pmte - pointer to mte
+ * pptgtmte - pointer to target mte
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ * ptgtmte - mte linear address
+ * if mte == 0 reference to DOSCALLS
+ *
+ * This procedure performs the following steps:
+ *
+ * - Check that module ordinal number is within module pointer table
+ * - Index into module pointer table and return linear address to mte
+ */
+
+APIRET ldrGetTgtMte(modord, pmte, pptgtmte)
+ushort_t modord;
+ldrmte_t *pmte;
+ldrmte_t **pptgtmte;
+{
+ modord--; /* normalize ordinal */
+
+ if (modord < (ushort_t) pmte->mte_impmodcnt) {
+ *pptgtmte = ((ldrmte_t *) ((ulong_t *) pmte->mte_modptrs)[modord]);
+ return(NO_ERROR);
+ }
+
+ /*
+ * set error = ERROR_BAD_EXE_FORMAT
+ */
+ return(ERROR_BAD_EXE_FORMAT);
+}
+
+/***LP ldrGetEntAddr - get entry point address
+ *
+ * For a given ordinal number, this routine locates the
+ * appropriate entry contained in the module's entry table.
+ * It returns a 48-bit pointer for the specified entry point.
+ *
+ * ENTRY entord - ordinal number
+ * pmte - pointer to target mte
+ * ptaddr - pointer to return target address (off,sel,flags)
+ * psrcste - pointer to source ste
+ * psrcmte - pointer to source mte
+ *
+ * EXIT entry point address
+ * global variable obj_ptr pointing to target segment
+ * global variable entry_ptr pointing to entry table entry
+ *
+ * This procedure performs the following steps:
+ *
+ * - Check for zero ordinal number
+ * - Normalize ordinal number
+ * - Checks and handles installable file system mte entry points
+ * - Checks and handles DOSCALLS mte entry points
+ * - Locates the correct bundle for the given ordinal
+ * - Creates the desired entry point address based on source and target
+ */
+
+APIRET ldrGetEntAddr(entord, pmte, ptaddr, psrcste, psrcmte)
+ushort_t entord;
+register ldrmte_t *pmte;
+register struct taddr_s *ptaddr;
+ldrste_t *psrcste;
+ldrmte_t *psrcmte;
+{
+ int fcallgate;
+ ulong_t objnum;
+ ldrsmte_t *psmte;
+
+ UNREFERENCED_PARAMETER(psrcmte);
+
+ psmte = pmte->mte_swapmte;
+
+ (ulong_t) ldrProcNameBuf = (ulong_t) entord;
+
+ if (entord == 0) {
+ return(ERROR_INVALID_ORDINAL);
+ }
+#if PMNT
+ /*
+ * This process loads PMWIN.WinCreateMsgQueue()
+ */
+ if (entord == 58 &&
+ 5 == (USHORT) *((PCHAR )pmte->mte_modname) &&
+ ! strncmp((PCHAR)(pmte->mte_modname+1),"PMWIN",5)) {
+ CurrentThread->Process->Flags |= OS2_PROCESS_PMMSGQUE;
+ }
+ /*
+ * This process loads PMNT.PMNTSetPMshellFlag(), thus it is PM Shell.
+ */
+ else if (entord == 12 &&
+ 4 == (USHORT) *((PCHAR )pmte->mte_modname) &&
+ ! strncmp((PCHAR)(pmte->mte_modname+1),"PMNT",4)) {
+ if (!PMNTPMShellPid) {
+ PMNTPMShellPid = CurrentThread->Process->ProcessId;
+ CurrentThread->Process->Flags |= OS2_PROCESS_IS_PMSHELL;
+ }
+ else {
+ // Do not allow another PMshell
+ return(ERROR_2ND_PMSHELL);
+ }
+ }
+
+#endif
+
+ --entord; /* Normalize object number */
+
+ ptaddr->fflags = 0; /* Clear forwarder flags */
+ fcallgate = FALSE; /* assume not a callgate entry */
+
+ if (ldrIsNE(pmte)) { /* check for 16-bit module */
+
+ register ldrste_t *pste;
+ register ldret_t *pbndl;
+ ldrcte_t *pcte;
+ ldrent_t *pent;
+
+ /*
+ * Find entry point, loop to determine which bundle the
+ * ordinal number belongs too.
+ */
+ pbndl = (ldret_t *) psmte->smte_enttab;
+
+ while (TRUE) { /* find bundle ord is in */
+ if (pbndl->et_cnt == 0) { /* check for end of table */
+ return(ERROR_INVALID_ORDINAL);
+ }
+
+ if (entord < pbndl->et_cnt) /* is ord in this bundle? */
+ break;
+
+ entord -= pbndl->et_cnt;
+ pbndl = (ldret_t *)((char *) pbndl +
+ ldrSkipEnts(pmte, pbndl->et_type, pbndl->et_cnt));
+ }
+
+ if (pbndl->et_type == EMPTY) {/* check for empty bundle */
+ return(ERROR_INVALID_ORDINAL);
+ }
+
+ pent = (ldrent_t *)((char *) pbndl +
+ ldrSkipEnts(pmte, pbndl->et_type, (uchar_t) entord));
+ pcte = (ldrcte_t *) pent;
+
+ ptaddr->fflags |= FWD_ALIAS16; /* indicate tiled object */
+ if (pbndl->et_type == B16MOVABLE) { /* check for movable entry */
+ objnum = pcte->cte_obj;
+ /* get target object */
+ if (objnum == B16ABSOLUTE) { /* if absolute entry */
+ ptaddr->toff = (ulong_t) pcte->cte_off;
+ ptaddr->tsel = 0;
+ ptaddr->tflags = pcte->cte_flags;
+ return(NO_ERROR);
+ }
+ if (objnum > psmte->smte_objcnt) {
+ return(ERROR_INVALID_SEGMENT_NUMBER);
+ }
+ pste = (ldrste_t *) psmte->smte_objtab + objnum - 1;
+ ptaddr->toff = (ulong_t) pcte->cte_off;
+ //
+ // If the target object is a code segment which has IOPL (ring 2)
+ // create call gate emulation
+ //
+ if ((pcte->cte_sel != 0) &&
+ (pcte->cte_sel != 0x3fcd) &&
+ ((psrcste == NULL) || // ldrDosGetProcAddress() calls with NULL
+ (((psrcste->ste_flags & STE_SEGDPL) == STE_RING_3) &&
+ ((psrcste->ste_flags & STE_DATA) == 0))) // source is a code segment
+ ) {
+ ptaddr->fflags |= FWD_IOPL;
+ ptaddr->toff = (ulong_t)pcte->cte_sel;
+ ptaddr->tsel = FLATTOSEL(R2XFER_BASE);
+ return(NO_ERROR);
+ }
+ }
+
+ /*
+ * check for absolute entry
+ */
+ else if (pbndl->et_type == B16ABSOLUTE) {
+ ptaddr->toff = (ulong_t) pent->ent_off;
+ ptaddr->tsel = 0;
+ ptaddr->tflags = pent->ent_flags;
+ return(NO_ERROR);
+ }
+ else { /* entry is fixed */
+ if((ulong_t) pbndl->et_type > psmte->smte_objcnt) {
+ return(ERROR_INVALID_SEGMENT_NUMBER);
+ }
+
+ /*
+ * get target object
+ */
+ pste = (ldrste_t *) psmte->smte_objtab + pbndl->et_type - 1;
+ ptaddr->toff = (ulong_t) pent->ent_off;
+ }
+
+ ptaddr->tsel = pste->ste_selector | 7;
+ ptaddr->tflags = pent->ent_flags;
+ return(NO_ERROR);
+ }
+
+ return(NO_ERROR);
+}
+
+
+/***LP ldrGetOrdNum - get the ordinal number for procedure name
+ *
+ * Given a procedure name and a module table, checks to see if
+ * the procedure is in the resident or nonresident table. If the
+ * procedure is found in either of the tables, ldrGetOrdNum
+ * returns the corresponding ordinal number. A 0 ordinal is
+ * returned if the procedure is not found in either of the tables.
+ *
+ * ENTRY pmte - pointer to module table entry
+ * pprocnam - pointer to procedure name
+ * pentord - address to return ordinal number
+ * fstring - flag to tell if null terminated
+ * STRINGNULLTERM
+ * STRINGPREPENDED
+ *
+ * EXIT if found
+ * NO_ERROR
+ * else
+ * ERROR_NOT_ENOUGH_MEMORY
+ * ERROR_PROC_NOT_FOUND
+ */
+
+APIRET ldrGetOrdNum(pmte, pprocnam, pentord, fstring)
+ldrmte_t *pmte;
+uchar_t *pprocnam;
+ushort_t *pentord;
+int fstring;
+{
+ IO_STATUS_BLOCK IoStatusBlock;
+ PIO_STATUS_BLOCK pIoStatusBlock = &IoStatusBlock;
+ LARGE_INTEGER ByteOffset;
+ PVOID MemoryAddress;
+ ULONG RegionSize;
+ ulong_t cbread;
+ register ldrsmte_t *psmte;
+ ushort_t proclen;
+ char tname[MAX_PROC_LEN+1];
+ char *ptname;
+ int rc = NO_ERROR;
+
+ ptname = (char *) &tname;
+ psmte = pmte->mte_swapmte;
+
+ ldrProcNameBuf = (PUCHAR) (pprocnam + 1);
+ ldrProcNameBufL = proclen = (USHORT) (pprocnam[0]);
+
+ /*
+ * Check for 32-bit module
+ */
+ if (ldrIsLE(pmte)) {
+ struct ExpHdr *pexpdir;
+ ulong_t *pexpnameptrs;
+ ushort_t *pexpordinals;
+
+ if (fstring == STRINGNONNULL) {
+
+ /*
+ * Since the procedure name strings in a 32-bit module are in
+ * the format of a null terminated string we need to convert
+ * the 16-bit formated string of a length followed by string
+ * to a null terminated string.
+ */
+ proclen = pprocnam[0];
+ memcpy(pprocnam, pprocnam + 1, proclen);
+ pprocnam[proclen] = '\0';
+ }
+ pexpdir = (struct ExpHdr *) psmte->smte_expdir;
+ pexpnameptrs = (ulong_t *) pexpdir->exp_name;
+ pexpordinals = (ushort_t *) pexpdir->exp_ordinal;
+// rc = ldrBinarySearchOrd(psmte,
+// pprocnam,
+// pexpnameptrs,
+// pexpordinals,
+// pexpdir->exp_namecnt,
+// pentord);
+ /*
+ * Restore procedure name back to length followed by string.
+ */
+// if (fstring == STRINGNONNULL) {
+// ldrStrCpyB(pprocnam + 1, pprocnam, proclen);
+// pprocnam[0] = (uchar_t) proclen;
+// }
+
+ return(rc);
+ }
+
+ /*
+ * Check for null terminated string passed. If it is we were called
+ * by ldrGetProcAddr and we may do this in place copy and not restore
+ * it because it is from the stack of ldrGetProcAddr
+ */
+ if (fstring == STRINGNULLTERM) {
+ proclen = (ushort_t) strlen(pprocnam);
+ strncpy(&ptname[1], pprocnam, proclen);
+ ptname[0] = (uchar_t) proclen;
+ }
+
+ else {
+ strncpy(ptname, pprocnam, proclen + 1);
+ }
+
+ /*
+ * 16-bit module, first search the resident name table.
+ */
+ if ((rc = ldrGetOrdNumSub((uchar_t *) psmte->smte_restab,
+ ptname,
+ pentord)) != ERROR_PROC_NOT_FOUND) {
+ return(rc);
+ }
+#if DBG
+ IF_OL2_DEBUG ( FIXUP ) {
+ if (fstring == STRINGNONNULL) {
+ strncpy(&tname[0], &pprocnam[1], proclen);
+ tname[proclen] = '\0';
+ DbgPrint(
+ "Could not find Procedure %s in module %s in Resident name table\n",
+ &tname, (char *) (pmte->mte_modname+1));
+ }
+ else {
+ DbgPrint(
+ "Could not find Procedure %s in module %s in Resident name table\n",
+ pprocnam, (char *) (pmte->mte_modname+1));
+ }
+
+ if (fstring == STRINGNONNULL) {
+ strncpy(ptname, pprocnam, proclen + 1);
+ }
+ }
+#endif
+
+ /*
+ * The procedure name was not found in the resident name table,
+ * need to search the non-resident name table.
+ * Do not do this for system dll's other than doscall
+ */
+
+ if (pmte->mte_mflags & DOSMOD) {
+ return(ERROR_PROC_NOT_FOUND);
+ }
+
+ RegionSize = psmte->smte_cbnrestab;
+ MemoryAddress = 0;
+ if ((rc = NtAllocateVirtualMemory(NtCurrentProcess(),
+ &MemoryAddress,
+ 0,
+ &RegionSize,
+ MEM_COMMIT,
+ PAGE_READWRITE)) != NO_ERROR) {
+ return(ERROR_PROC_NOT_FOUND);
+ }
+
+ /*
+ * read the non-resident nametable from the file into non-
+ * resident name table object.
+ */
+ ByteOffset.LowPart = psmte->smte_nrestab;
+ ByteOffset.HighPart = 0;
+ cbread = psmte->smte_cbnrestab;
+ if ((rc = NtReadFile(pmte->mte_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ (void *) MemoryAddress,
+ cbread,
+ &ByteOffset,
+ 0)) != 0) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+
+ if (IoStatusBlock.Information != cbread) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto returnstatus;
+ }
+
+ /*
+ * Now check if the procname is in the nonresident name table.
+ */
+ rc = ldrGetOrdNumSub((uchar_t *) MemoryAddress,
+ ptname,
+ pentord);
+returnstatus:
+ NtFreeVirtualMemory(NtCurrentProcess(),
+ &MemoryAddress,
+ &cbread,
+ MEM_RELEASE);
+ if (rc == NO_ERROR)
+ return(rc);
+
+ if (fstring == STRINGNONNULL) {
+ strncpy(&ptname[0], &pprocnam[1], proclen);
+ ptname[proclen] = '\0';
+ }
+#if DBG
+ IF_OL2_DEBUG ( FIXUP ) {
+ DbgPrint(
+ "Could not find Procedure %s in module %s in Non-resident table\n",
+ ptname, (char *) (pmte->mte_modname+1));
+ }
+#endif
+ return(ERROR_PROC_NOT_FOUND);
+}
+
+
+/***LP ldrGetOrdNumSub - get the ordinal number for procedure name
+ *
+ * Given a procedure name and a resident or nonresident name table
+ * containing the procedures exported by a module, checks to see
+ * if the procedure is in the table. If the procedure is found
+ * in the table, ldrGetOrdNumSub gets the corresponding ordinal
+ * number. A 0 ordinal value is returned if the procedure is not
+ * found in the table. The ordinal number for the module name string
+ * is set to zero, therefore matching strings with a 0 ordinal number
+ * are skipped.
+ *
+ * ENTRY pnt - pointer to resident or nonresident name table
+ * pprocnam - pointer to procedure name
+ * pentord - place to return ordinal
+ *
+ * EXIT if found
+ * NO_ERROR
+ * else
+ * ERROR_PROC_NOT_FOUND
+ * ERROR_BAD_EXE_FORMAT
+ *
+ * This procedure performs the following steps:
+ *
+ * - compare procedure name to each entry in table
+ * - if ordinal number is 0 skip to next string
+ * - return ordinal number if found
+ */
+
+APIRET ldrGetOrdNumSub(pnt, pprocnam, pentord)
+register uchar_t *pnt;
+register uchar_t *pprocnam;
+ushort_t *pentord;
+{
+ register int len;
+
+
+ /*
+ * remove typeinfo from length
+ */
+ while ((len = (int) (*pnt /*& ~NT_TYPEINFO*/)) != 0) { // YOSEFD: The using of the flag
+ // harm the names that are longer
+ // then 0x7F. The description string
+ // can be longer.
+ /*
+ * include string size field
+ */
+ if (memcmp(pnt, pprocnam, ++len) == 0)
+
+ if ((*(ushort_t *) (pnt + len)) != 0) {
+ /*
+ * return ordinal number
+ */
+ *pentord = *(ushort_t *)(pnt + len);
+ return(NO_ERROR);
+ }
+ pnt += len + sizeof(ushort_t); /* skip to next string */
+ }
+
+ return(ERROR_PROC_NOT_FOUND); /* end of table, return not found */
+}
diff --git a/private/os2/ldr/ldrinit.c b/private/os2/ldr/ldrinit.c
new file mode 100644
index 000000000..684fa6e07
--- /dev/null
+++ b/private/os2/ldr/ldrinit.c
@@ -0,0 +1,1415 @@
+#include <string.h>
+#define INCL_OS2V20_TASKING
+#define INCL_OS2V20_MEMORY
+#define INCL_OS2V20_FILESYS
+#define INCL_DOSERRORS
+#include "bseerr.h"
+#include <os2ssrtl.h>
+#include "os2defp.h"
+#include "mi.h"
+#define FOR_EXEHDR 1
+#include "newexe.h"
+#include "exe386.h"
+#include "ldrvars.h"
+#include <ldrxport.h>
+#include <os2tile.h>
+#include <os2file.h>
+#include <os2ldr.h>
+
+USHORT LDRDoscallsSel;
+
+PVOID LDRNEHeap;
+
+CHAR ldrLibPathBuf[1024];
+
+PCHAR ldrpLibPath = ldrLibPathBuf;
+
+ULONG SizeOfldrLibPathBuf = sizeof(ldrLibPathBuf);
+
+char LdrBuf[MAXPATHLEN+14]; // 14 is for the '\OS2SS\DRIVES\'
+
+char *pheaderbuf;
+
+ldrmte_t *mte_h = NULL; /* head of linked mte list */
+
+ldrmte_t *program_h = NULL; /* head of list of program modules */
+
+ldrmte_t *program_l = NULL; /* tail of list of program modules */
+
+ldrmte_t *global_h = NULL; /* head of list of global modules */
+
+ldrmte_t *global_l = NULL; /* tail of list of global modules */
+
+ldrmte_t *specific_h = NULL; /* head of list of specific modules */
+
+ldrmte_t *specific_l = NULL; /* tail of list of specific modules */
+
+ushort_t ldrInitCallGate; /* first selector of call gate obj */
+
+ulong_t ldrMINSEGPACKCNT = 5;
+ulong_t ldrMINPGPACKSIZE = 0xf00; /* 4k-256 */
+ulong_t ldrMAXSEGPACKSIZE = 32768; /* 32K */
+
+ldrlibi_t *pldrLibiRecord = NULL;
+ULONG *pldrLibiCounter = NULL;
+
+PUCHAR ldrSrcModNameBuf = NULL;
+ushort_t ldrSrcModNameBufL = 0;
+PUCHAR ldrTgtModNameBuf = NULL;
+ushort_t ldrTgtModNameBufL = 0;
+PUCHAR ldrProcNameBuf = NULL;
+ushort_t ldrProcNameBufL = 0;
+#if PMNT
+PUCHAR ldrSaveSrcModNameBuf = NULL;
+ushort_t ldrSaveSrcModNameBufL = 0;
+PUCHAR ldrSaveTgtModNameBuf = NULL;
+ushort_t ldrSaveTgtModNameBufL = 0;
+PUCHAR ldrSaveProcNameBuf = NULL;
+ushort_t ldrSaveProcNameBufL = 0;
+int ldrSaveRc = 0;
+#endif
+
+HANDLE R2XferSegHandle;
+
+PSTRING pErrText;
+
+ldrmte_t acscallmte;
+ldrsmte_t acscallsmte;
+
+ldrmte_t kbdcallmte;
+ldrsmte_t kbdcallsmte;
+
+ldrmte_t maicallmte;
+ldrsmte_t maicallsmte;
+
+ldrmte_t moncallmte;
+ldrsmte_t moncallsmte;
+
+ldrmte_t moucallmte;
+ldrsmte_t moucallsmte;
+
+ldrmte_t msgcallmte;
+ldrsmte_t msgcallsmte;
+
+ldrmte_t namcallmte;
+ldrsmte_t namcallsmte;
+
+ldrmte_t apicallmte;
+ldrsmte_t apicallsmte;
+
+ldrmte_t oemcallmte;
+ldrsmte_t oemcallsmte;
+
+ldrmte_t nlscallmte;
+ldrsmte_t nlscallsmte;
+
+#ifndef PMNT
+ldrmte_t pmscallmte;
+ldrsmte_t pmscallsmte;
+
+ldrmte_t pmwcallmte;
+ldrsmte_t pmwcallsmte;
+
+ldrmte_t os2smcallmte;
+ldrsmte_t os2smcallsmte;
+#endif
+
+ldrmte_t quecallmte;
+ldrsmte_t quecallsmte;
+
+ldrmte_t sescallmte;
+ldrsmte_t sescallsmte;
+
+#ifdef PMNT
+ldrmte_t pmntcallmte;
+ldrsmte_t pmntcallsmte;
+#endif
+
+ldrmte_t viocallmte;
+ldrsmte_t viocallsmte;
+
+#ifdef DBCS
+// MSKK Dec.15.1992 V-AkihiS
+// Support IMMON API
+ldrmte_t imdaemonmte;
+ldrsmte_t imdaemonsmte;
+#endif
+
+//BUGBUG - used to assign selector's till LDT defined
+ushort_t UserGDTSelector=0x93;
+
+ulong_t LdrSaveStack;
+
+/*
+ * this table is used to validate and update pointer in the MTE in
+ * mtevalidateptrs
+ * ******* NOTE: ********
+ * If the entry in the array for the resource table changes you need to
+ * also change the define rsrcvalidatetbl
+ */
+ ushort_t validatetbl[] = {
+ FIELDOFFSET(ldrsmte_t, smte_expdir), /* export directory */
+ FIELDOFFSET(ldrsmte_t, smte_impdir), /* import directory */
+ FIELDOFFSET(ldrsmte_t, smte_fixtab), /* fixup table */
+ FIELDOFFSET(ldrsmte_t, smte_rsrctab), /* resource table */
+ FIELDOFFSET(ldrsmte_t, smte_iat), /* 16-bit imp proc table */
+ ENDMTETBL, /* MUST BE AT END OF TABLE */
+ };
+
+/*
+ * This table is used to copy the linker EXE formated header to the loader
+ * Resident MTE format in place.
+ */
+struct etmt_s ExeToResMTETbl[] = {
+ {
+ FIELDOFFSET(struct e32_exe, e32_magic), /* Magic number and usecnt */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_mflags), /* Module flags */
+ },
+ {
+ (USHORT) SKIPCOPY, /* # entries in Imp Mod Tbl */
+ },
+ {
+ (USHORT) SKIPCOPY, /* mte_modptrs */
+ },
+ {
+ (USHORT) SKIPCOPY, /* mte_modname */
+ },
+ {
+ (USHORT) SKIPCOPY, /* mte_handle and mte_sfn */
+ },
+ {
+ (USHORT) SKIPCOPY, /* mte_link */
+ },
+ {
+ (USHORT) SKIPCOPY, /* mte_swapmte */
+ },
+ {
+ ENDMTETBL, /* MUST BE AT END OF TABLE */
+ }
+ };
+
+/*
+ * This table is used to copy the linker EXE formated header to the
+ * (LE) loader Swappable MTE format.
+ */
+struct etmt_s ExeTo32SwapMTETbl[] = {
+ {
+ FIELDOFFSET(struct e32_exe, e32_entryrva), /* Extended IP */
+ },
+ {
+ (USHORT) SKIPCOPY, /* stack object */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_stackmax), /* committed stack */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_objtab), /* Object table offset */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_objcnt), /* Object table count */
+ },
+ {
+ (USHORT) SKIPCOPY, /* Offset of fixup page map */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_unit[EXP].rva),/* Offset of Export Tb */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_unit[IMP].rva),/* Offset of Import Tb */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_unit[FIX].rva),/* Offset of Fixup Tb */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_unit[RES].rva),/* Offset of resource Tb */
+ },
+ {
+ (USHORT) SKIPCOPY, /* Count of resources */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_filealign), /* Alignment factor */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_vbase), /* load address of module */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_heapmax), /* Maximum heap size */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip autods */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip iat pointer */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_unit[DEB].rva),/* Offset of Debug info */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_unit[DEB].size),/* Size of debug info */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip delta size */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip cache pointer */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip pathname pointer */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip pathname length */
+ }, /* and skip dyn trace count */
+ {
+ (USHORT) SKIPCOPY, /* skip semaphore count */
+ }, /* and skip semaphore owner */
+ {
+ (USHORT) SKIPCOPY, /* 16-bit non-res tb offset */
+ },
+ {
+ (USHORT) SKIPCOPY, /* 16-bit size of non-res table */
+ },
+ {
+ (USHORT) SKIPCOPY, /* 16-bit count of segs to pack */
+ },
+ {
+ (USHORT) SKIPCOPY, /* 16-bit size of obj for seg pack */
+ },
+ {
+ (USHORT) SKIPCOPY, /* 16-bit VA of seg packed obj */
+ },
+ {
+ (USHORT) SKIPCOPY, /* zero and skip copy of NEflags */
+ }, /* and smte_NEexpver */
+ {
+ (USHORT) SKIPCOPY, /* zero and skip copy of NEexetype */
+ }, /* and smte_NEflagsothers */
+ {
+ ENDMTETBL, /* MUST BE AT END OF TABLE */
+ }
+ };
+
+/*
+ * This table is used to copy the linker EXE formated header to the
+ * (NE) loader Swappable MTE format.
+ */
+struct etmt_s ExeTo16SwapMTETbl[] = {
+ {
+ FIELDOFFSET(struct new_exe, ne_csip), /* Extended IP */
+ }, /* get offset only of starting address */
+ {
+ FIELDOFFSET(struct e32_exe, e32_res4)+2, /* Object # for stack ptr */
+ },
+ {
+ FIELDOFFSET(struct e32_exe, e32_res4), /* extended stack pointer */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_segtab), /* Object table offset */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_cseg), /* Object table count */
+ },
+ {
+ (USHORT) SKIPCOPY, /* Offset of fixup page map */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_enttab), /* Offset of entry table */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_imptab), /* Offset of Import Tb */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_restab), /* Offset of resident name */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_rsrctab), /* Offset of resource Tb */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_cres), /* count of resources */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_align), /* Alignment factor */
+ },
+ {
+ (USHORT) SKIPCOPY, /* vbase */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_heap), /* Maximum heap size */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_autodata), /* autods segment # */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_modtab), /* Offset of module ref tb */
+ },
+ {
+ (USHORT) SKIPCOPY, /* debug info */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_stack), /* Stack size */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_csip)+2, /* Start object number */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip cache pointer */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip pathname pointer */
+ },
+ {
+ (USHORT) SKIPCOPY, /* skip pathname length */
+ }, /* and skip dyn trace count */
+ {
+ (USHORT) SKIPCOPY, /* skip semaphore count */
+ }, /* and skip semaphore owner */
+ {
+ FIELDOFFSET(struct new_exe, ne_nrestab),/* 16-bit non-resident tb off */
+ },
+ {
+ (USHORT) SKIPCOPY, /* 16-bit size of non-res */
+ }, /* This is a DWORD value copy later */
+ {
+ (USHORT) SKIPCOPY, /* 16-bit count of packed segments */
+ },
+ {
+ (USHORT) SKIPCOPY, /* 16-bit size of packed object */
+ },
+ {
+ (USHORT) SKIPCOPY, /* 16-bit pointer to packed object */
+ },
+ {
+ FIELDOFFSET(struct new_exe, ne_flags),/* copy of ne_flags */
+ }, /* and zero ne_expver */
+ {
+ FIELDOFFSET(struct new_exe, ne_exetyp),/* copy of ne_exetype */
+ }, /* and zero ne_flagsothers */
+ {
+ ENDMTETBL, /* MUST BE AT END OF TABLE */
+ }
+ };
+
+/*
+ * This table is used to copy header info for the API DosQueryHeaderInfo
+ * function HEADER_EXEINFO, see VR32QueryHeaderInfo.
+ */
+struct hit_s HeaderInfoTbl[] = {
+ {
+ FIELDOFFSET(ldrsmte_t, smte_NEflags),/* Original flags from NE header */
+ sizeof(((ldrsmte_t *) 0)->smte_NEflags),/* number of bytes to copy */
+ },
+ {
+ FIELDOFFSET(ldrsmte_t, smte_NEflagsothers),/* fixup page table */
+ sizeof(((ldrsmte_t *) 0)->smte_NEflagsothers),/* number of bytes to copy */
+ },
+ {
+ FIELDOFFSET(ldrsmte_t, smte_NEexetype),/* exetyp from NE header */
+ sizeof(((ldrsmte_t *) 0)->smte_NEexetype),/* number of bytes to copy */
+ },
+ {
+ FIELDOFFSET(ldrsmte_t, smte_NEexpver),/* expver from NE header */
+ sizeof(((ldrsmte_t *) 0)->smte_NEexpver),/* number of bytes to copy */
+ },
+ {
+ 0, /* special case for size of rsrc table */
+ 2, /* copy 2 bytes */
+ },
+ {
+ ENDMTETBL, /* MUST BE AT END OF TABLE */
+ 0, /* copy 0 bytes */
+ }
+ };
+
+
+/*
+ * This table is used to copy header info for the API DosQueryHeaderInfo
+ * function HEADER_STE, see VR32QueryHeaderInfo.
+ */
+struct his_s HeaderInfoSTE[] = {
+ {
+ FIELDOFFSET(ldrste_t, ste_offset), /* file offset to segment data */
+ 2, /* copy 2 bytes */
+ },
+ {
+ FIELDOFFSET(ldrste_t, ste_size), /* file data size */
+ 2, /* copy 2 byte */
+ },
+ {
+ FIELDOFFSET(ldrste_t, ste_flags), /* type and attribute flags */
+ 2, /* copy 2 byte */
+ },
+ {
+ FIELDOFFSET(ldrste_t, ste_minsiz), /* minimum allocation size */
+ 2, /* copy 2 bytes */
+ },
+ {
+ ENDMTETBL, /* MUST BE AT END OF TABLE */
+ 0, /* copy 0 bytes */
+ }
+ };
+
+/*
+ * This structure is used to convert from Object type flags to the
+ * required VM flags needed for allocation of memory. See setVMflags()
+ * for use.
+ */
+
+struct objflags_s objflags[] =
+ {
+ {
+ OBJ_READ, /* Readable Object */
+ PAG_READ, /* Allocate as Readable */
+ },
+ {
+ OBJ_WRITE, /* Writeable Object */
+ PAG_WRITE, /* Allocate as Writeable */
+ },
+ {
+ OBJ_EXEC, /* Executable Object */
+ PAG_EXECUTE, /* Alloc as eXecutable and shared */
+ },
+ {
+ 0, /* must have end of table entry */
+ 0,
+ }
+ };
+
+/*
+ * This sturcture is used to convert from Object type flags to the
+ * required SEL flags needed for allocation of memory. See setVMflags()
+ * for use.
+ */
+
+struct selflags_s selflags[] =
+ {
+ {
+ OBJ_READ, /* Readable Object */
+ 0, /* Allocate as Readable */
+ },
+ {
+ OBJ_WRITE, /* Writeable Object */
+ 0, /* Allocate as Writeable */
+ },
+ {
+ OBJ_EXEC, /* Executable Object */
+ 0, /* Alloc as eXecutable and readable */
+ },
+ {
+ OBJ_CONFORM, /* Objects is conforming */
+ 0,
+ },
+ {
+ 0, /* must have end of table entry */
+ 0,
+ }
+ };
+
+#include <ldrtabs.h>
+
+//
+// The segtab structure below is overwritten by the segment values
+// of the DOSCALLS.DLL module when it is first loaded.
+//
+ldrste_t segtab;
+/* =
+{
+ 0,
+ 0,
+ 0x0c00,
+ 0,
+ 0,
+ FLATTOSEL(DOSCALLS_BASE),
+ 0
+};
+*/
+
+//
+// Structures private to 16B handles allocation
+//
+
+// NUM_OF_COOKIES MUST be a power of 2
+#define NUM_OF_COOKIES 4096
+
+ULONG NextCookie = 1;
+
+typedef struct _A16B_COOKIE {
+ ULONG value32;
+ ULONG cookie;
+} A16B_COOKIE, *P16B_COOKIE;
+
+A16B_COOKIE Cookies[NUM_OF_COOKIES];
+
+NTSTATUS ldrCreateR2XferSeg();
+
+extern PSZ Os2ServerSystemDirectory;
+
+BOOLEAN ldrInit()
+{
+ ULONG size;
+ CHAR SystemDir[260 + FILE_PREFIX_LENGTH];
+#if DBG
+ ldrmte_t *pmte;
+#endif
+ ULONG SizeOfSystemDir;
+ ULONG ModSize;
+ PCHAR DotDll = ".DLL";
+
+ strcpy(SystemDir, "\\OS2SS\\DRIVES\\");
+ SizeOfSystemDir = FILE_PREFIX_LENGTH;
+ size = strlen(Os2ServerSystemDirectory);
+ if( size > (sizeof(SystemDir) - FILE_PREFIX_LENGTH - 10))
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - system directory too long %ld\n", size);
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ strncpy(&SystemDir[SizeOfSystemDir],
+ Os2ServerSystemDirectory,
+ size);
+ _strupr(&SystemDir[SizeOfSystemDir]);
+ SizeOfSystemDir += size;
+ strcpy(&SystemDir[SizeOfSystemDir], "\\OS2\\DLL\\");
+ SizeOfSystemDir += 9;
+
+/*
+ Ol2Heap = RtlCreateHeap( HEAP_GROWABLE,
+ NULL,
+ 64 * 1024, // Initial size of heap is 64K
+ 64 * 1024, // Commit for 64K
+ NULL,
+ 0
+ );
+ if( Ol2Heap == NULL )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - cannot create Ol2Heap\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+*/
+ LDRNEHeap = RtlCreateHeap( HEAP_GROWABLE,
+ NULL,
+ 64 * 1024, // Initial size of heap is 64K
+ 64 * 1024, // Commit for 64K
+ NULL,
+ 0
+ );
+ if ( LDRNEHeap == NULL )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - cannot create LDRNEHeap\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+
+ /*
+ * Allocate a heap object of the size of one sector to hold the
+ * header of file into
+ */
+ pheaderbuf = (char *) RtlAllocateHeap( LDRNEHeap, 0, 512 );
+
+ if ( pheaderbuf == NULL )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - cannot create pheaderbuf\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+
+ if (!ldrCreateSelBitmap()) {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - cannot allocate the segment bitmap\n");
+#endif
+ return(FALSE);
+ }
+
+ // Mark the preallocated segments at the top of the tiled area
+ // as used so that they are not allocated by the loader.
+
+ ldrMarkAllocatedSel((_512M - (OD2MAXSEG_MEM - BASE_TILE)) / _64K, TRUE);
+
+ //
+ // Create an address space for the R2XFER segment (which is the second
+ // code segment of DOSCALLS.DLL).
+ // This segment needs to be pre-allocated because modules that contain
+ // ring 2 entry points may be allocated before DOSCALLS.DLL is allocated.
+ //
+ if (!NT_SUCCESS(ldrCreateR2XferSeg())) {
+ return(FALSE);
+ }
+
+ if (!ldrCreateCallGateBitmap()) {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - cannot allocate the call gate bitmap\n");
+#endif
+ return(FALSE);
+ }
+
+ // Mark pre-allocated call gates (which is the area reserved by the
+ // ring transfer code in client\thunk\r2xfer.asm) as used so that they
+ // are not allocated as call gates.
+
+ ldrMarkAllocatedCallGates(0x200/8);
+
+ acscallmte.mte_magic[0] = 'N';
+ acscallmte.mte_magic[1] = 'E';
+ acscallmte.mte_usecnt = 1;
+ acscallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ acscallmte.mte_swapmte = &acscallsmte;
+ acscallmte.mte_modname = (ULONG) &acsrestab;
+ acscallmte.mte_link = NULL;
+ Allocate16BHandle(&acscallmte.mte_handle, (ULONG) &acscallsmte);
+ acscallsmte.smte_restab = (ULONG) &acsrestab;
+ acscallsmte.smte_nrestab = (ULONG) &acsnrestab;
+ acscallsmte.smte_cbnrestab = 10;
+ acscallsmte.smte_enttab = (ULONG) &acsenttab;
+ acscallsmte.smte_objtab = (ULONG) &segtab;
+ acscallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)acscallmte.mte_modname;
+ acscallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(acscallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)acscallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)acscallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)acscallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)acscallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ acscallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ kbdcallmte.mte_magic[0] = 'N';
+ kbdcallmte.mte_magic[1] = 'E';
+ kbdcallmte.mte_usecnt = 1;
+ kbdcallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ kbdcallmte.mte_swapmte = &kbdcallsmte;
+ kbdcallmte.mte_modname = (ULONG) &kbdrestab;
+ kbdcallmte.mte_link = &acscallmte;
+ Allocate16BHandle(&kbdcallmte.mte_handle, (ULONG) &kbdcallsmte);
+ kbdcallsmte.smte_restab = (ULONG) &kbdrestab;
+ kbdcallsmte.smte_nrestab = (ULONG) &kbdnrestab;
+ kbdcallsmte.smte_cbnrestab = 10;
+ kbdcallsmte.smte_enttab = (ULONG) &kbdenttab;
+ kbdcallsmte.smte_objtab = (ULONG) &segtab;
+ kbdcallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)kbdcallmte.mte_modname;
+ kbdcallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(kbdcallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)kbdcallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)kbdcallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)kbdcallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)kbdcallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ kbdcallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ maicallmte.mte_magic[0] = 'N';
+ maicallmte.mte_magic[1] = 'E';
+ maicallmte.mte_usecnt = 1;
+ maicallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ maicallmte.mte_swapmte = &maicallsmte;
+ maicallmte.mte_modname = (ULONG) &mairestab;
+ maicallmte.mte_link = &kbdcallmte;
+ Allocate16BHandle(&maicallmte.mte_handle, (ULONG) &maicallsmte);
+ maicallsmte.smte_restab = (ULONG) &mairestab;
+ maicallsmte.smte_nrestab = (ULONG) &mainrestab;
+ maicallsmte.smte_cbnrestab = 10;
+ maicallsmte.smte_enttab = (ULONG) &maienttab;
+ maicallsmte.smte_objtab = (ULONG) &segtab;
+ maicallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)maicallmte.mte_modname;
+ maicallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(maicallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)maicallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)maicallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)maicallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)maicallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ maicallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ moncallmte.mte_magic[0] = 'N';
+ moncallmte.mte_magic[1] = 'E';
+ moncallmte.mte_usecnt = 1;
+ moncallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ moncallmte.mte_swapmte = &moncallsmte;
+ moncallmte.mte_modname = (ULONG) &monrestab;
+ moncallmte.mte_link = &maicallmte;
+ Allocate16BHandle(&moncallmte.mte_handle, (ULONG) &moncallsmte);
+ moncallsmte.smte_restab = (ULONG) &monrestab;
+ moncallsmte.smte_nrestab = (ULONG) &monnrestab;
+ moncallsmte.smte_cbnrestab = 10;
+ moncallsmte.smte_enttab = (ULONG) &monenttab;
+ moncallsmte.smte_objtab = (ULONG) &segtab;
+ moncallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)moncallmte.mte_modname;
+ moncallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(moncallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)moncallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)moncallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)moncallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)moncallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ moncallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ moucallmte.mte_magic[0] = 'N';
+ moucallmte.mte_magic[1] = 'E';
+ moucallmte.mte_usecnt = 1;
+ moucallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ moucallmte.mte_swapmte = &moucallsmte;
+ moucallmte.mte_modname = (ULONG) &mourestab;
+ moucallmte.mte_link = &moncallmte;
+ Allocate16BHandle(&moucallmte.mte_handle, (ULONG) &moucallsmte);
+ moucallsmte.smte_restab = (ULONG) &mourestab;
+ moucallsmte.smte_nrestab = (ULONG) &mounrestab;
+ moucallsmte.smte_cbnrestab = 10;
+ moucallsmte.smte_enttab = (ULONG) &mouenttab;
+ moucallsmte.smte_objtab = (ULONG) &segtab;
+ moucallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)moucallmte.mte_modname;
+ moucallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(moucallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)moucallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)moucallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)moucallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)moucallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ moucallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ msgcallmte.mte_magic[0] = 'N';
+ msgcallmte.mte_magic[1] = 'E';
+ msgcallmte.mte_usecnt = 1;
+ msgcallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ msgcallmte.mte_swapmte = &msgcallsmte;
+ msgcallmte.mte_modname = (ULONG) &msgrestab;
+ msgcallmte.mte_link = &moucallmte;
+ Allocate16BHandle(&msgcallmte.mte_handle, (ULONG) &msgcallsmte);
+ msgcallsmte.smte_restab = (ULONG) &msgrestab;
+ msgcallsmte.smte_nrestab = (ULONG) &msgnrestab;
+ msgcallsmte.smte_cbnrestab = 10;
+ msgcallsmte.smte_enttab = (ULONG) &msgenttab;
+ msgcallsmte.smte_objtab = (ULONG) &segtab;
+ msgcallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)msgcallmte.mte_modname;
+ msgcallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(msgcallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)msgcallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)msgcallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)msgcallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)msgcallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ msgcallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ namcallmte.mte_magic[0] = 'N';
+ namcallmte.mte_magic[1] = 'E';
+ namcallmte.mte_usecnt = 1;
+ namcallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ namcallmte.mte_swapmte = &namcallsmte;
+ namcallmte.mte_modname = (ULONG) &namrestab;
+ namcallmte.mte_link = &msgcallmte;
+ Allocate16BHandle(&namcallmte.mte_handle, (ULONG) &namcallsmte);
+ namcallsmte.smte_restab = (ULONG) &namrestab;
+ namcallsmte.smte_nrestab = (ULONG) &namnrestab;
+ namcallsmte.smte_cbnrestab = 10;
+ namcallsmte.smte_enttab = (ULONG) &namenttab;
+ namcallsmte.smte_objtab = (ULONG) &segtab;
+ namcallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)namcallmte.mte_modname;
+ namcallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(namcallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)namcallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)namcallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)namcallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)namcallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ namcallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ apicallmte.mte_magic[0] = 'N';
+ apicallmte.mte_magic[1] = 'E';
+ apicallmte.mte_usecnt = 1;
+ apicallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ apicallmte.mte_swapmte = &apicallsmte;
+ apicallmte.mte_modname = (ULONG) &apirestab;
+ apicallmte.mte_link = &namcallmte;
+ Allocate16BHandle(&apicallmte.mte_handle, (ULONG) &apicallsmte);
+ apicallsmte.smte_restab = (ULONG) &apirestab;
+ apicallsmte.smte_nrestab = (ULONG) &apinrestab;
+ apicallsmte.smte_cbnrestab = 10;
+ apicallsmte.smte_enttab = (ULONG) &apienttab;
+ apicallsmte.smte_objtab = (ULONG) &segtab;
+ apicallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)apicallmte.mte_modname;
+ apicallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(apicallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)apicallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)apicallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)apicallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)apicallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ apicallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ oemcallmte.mte_magic[0] = 'N';
+ oemcallmte.mte_magic[1] = 'E';
+ oemcallmte.mte_usecnt = 1;
+ oemcallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ oemcallmte.mte_swapmte = &oemcallsmte;
+ oemcallmte.mte_modname = (ULONG) &oemrestab;
+ oemcallmte.mte_link = &apicallmte;
+ Allocate16BHandle(&oemcallmte.mte_handle, (ULONG) &oemcallsmte);
+ oemcallsmte.smte_restab = (ULONG) &oemrestab;
+ oemcallsmte.smte_nrestab = (ULONG) &oemnrestab;
+ oemcallsmte.smte_cbnrestab = 10;
+ oemcallsmte.smte_enttab = (ULONG) &oementtab;
+ oemcallsmte.smte_objtab = (ULONG) &segtab;
+ oemcallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)oemcallmte.mte_modname;
+ oemcallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(oemcallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)oemcallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)oemcallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)oemcallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)oemcallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ oemcallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ nlscallmte.mte_magic[0] = 'N';
+ nlscallmte.mte_magic[1] = 'E';
+ nlscallmte.mte_usecnt = 1;
+ nlscallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ nlscallmte.mte_swapmte = &nlscallsmte;
+ nlscallmte.mte_modname = (ULONG) &nlsrestab;
+ nlscallmte.mte_link = &oemcallmte;
+ Allocate16BHandle(&nlscallmte.mte_handle, (ULONG) &nlscallsmte);
+ nlscallsmte.smte_restab = (ULONG) &nlsrestab;
+ nlscallsmte.smte_nrestab = (ULONG) &nlsnrestab;
+ nlscallsmte.smte_cbnrestab = 10;
+ nlscallsmte.smte_enttab = (ULONG) &nlsenttab;
+ nlscallsmte.smte_objtab = (ULONG) &segtab;
+ nlscallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)nlscallmte.mte_modname;
+ nlscallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(nlscallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)nlscallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)nlscallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)nlscallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)nlscallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ nlscallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+#ifndef PMNT
+ pmscallmte.mte_magic[0] = 'N';
+ pmscallmte.mte_magic[1] = 'E';
+ pmscallmte.mte_usecnt = 1;
+ pmscallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ pmscallmte.mte_swapmte = &pmscallsmte;
+ pmscallmte.mte_modname = (ULONG) &pmsrestab;
+ pmscallmte.mte_link = &nlscallmte;
+ Allocate16BHandle(&pmscallmte.mte_handle, (ULONG) &pmscallsmte);
+ pmscallsmte.smte_restab = (ULONG) &pmsrestab;
+ pmscallsmte.smte_nrestab = (ULONG) &pmsnrestab;
+ pmscallsmte.smte_cbnrestab = 10;
+ pmscallsmte.smte_enttab = (ULONG) &pmsenttab;
+ pmscallsmte.smte_objtab = (ULONG) &segtab;
+ pmscallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)pmscallmte.mte_modname;
+ pmscallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(pmscallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)pmscallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)pmscallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)pmscallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)pmscallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ pmscallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ pmwcallmte.mte_magic[0] = 'N';
+ pmwcallmte.mte_magic[1] = 'E';
+ pmwcallmte.mte_usecnt = 1;
+ pmwcallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ pmwcallmte.mte_swapmte = &pmwcallsmte;
+ pmwcallmte.mte_modname = (ULONG) &pmwrestab;
+ pmwcallmte.mte_link = &pmscallmte;
+ Allocate16BHandle(&pmwcallmte.mte_handle, (ULONG) &pmwcallsmte);
+ pmwcallsmte.smte_restab = (ULONG) &pmwrestab;
+ pmwcallsmte.smte_nrestab = (ULONG) &pmwnrestab;
+ pmwcallsmte.smte_cbnrestab = 10;
+ pmwcallsmte.smte_enttab = (ULONG) &pmwenttab;
+ pmwcallsmte.smte_objtab = (ULONG) &segtab;
+ pmwcallsmte.smte_objcnt = 1;
+ ModSize = *(PCHAR)pmwcallmte.mte_modname;
+ pmwcallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(pmwcallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)pmwcallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)pmwcallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)pmwcallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)pmwcallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ pmwcallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ os2smcallmte.mte_magic[0] = 'N';
+ os2smcallmte.mte_magic[1] = 'E';
+ os2smcallmte.mte_usecnt = 1;
+ os2smcallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ os2smcallmte.mte_swapmte = &os2smcallsmte;
+ os2smcallmte.mte_modname = (ULONG) &os2restab;
+ os2smcallmte.mte_link = &pmwcallmte;
+ Allocate16BHandle(&os2smcallmte.mte_handle, (ULONG) &os2smcallsmte);
+ os2smcallsmte.smte_restab = (ULONG) &os2restab;
+ os2smcallsmte.smte_nrestab = (ULONG) &os2nrestab;
+ os2smcallsmte.smte_cbnrestab = 10;
+ os2smcallsmte.smte_enttab = (ULONG) &os2enttab;
+ os2smcallsmte.smte_objtab = (ULONG) &segtab;
+ os2smcallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)os2smcallmte.mte_modname;
+ os2smcallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(os2smcallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)os2smcallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)os2smcallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)os2smcallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)os2smcallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ os2smcallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+#endif /* ifndef PMNT */
+
+ quecallmte.mte_magic[0] = 'N';
+ quecallmte.mte_magic[1] = 'E';
+ quecallmte.mte_usecnt = 1;
+ quecallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ quecallmte.mte_swapmte = &quecallsmte;
+ quecallmte.mte_modname = (ULONG) &querestab;
+#ifndef PMNT
+ quecallmte.mte_link = &os2smcallmte;
+#else
+ quecallmte.mte_link = &nlscallmte;
+#endif
+ Allocate16BHandle(&quecallmte.mte_handle, (ULONG) &quecallsmte);
+ quecallsmte.smte_restab = (ULONG) &querestab;
+ quecallsmte.smte_nrestab = (ULONG) &quenrestab;
+ quecallsmte.smte_cbnrestab = 10;
+ quecallsmte.smte_enttab = (ULONG) &queenttab;
+ quecallsmte.smte_objtab = (ULONG) &segtab;
+ quecallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)quecallmte.mte_modname;
+ quecallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(quecallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)quecallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)quecallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)quecallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)quecallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ quecallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ sescallmte.mte_magic[0] = 'N';
+ sescallmte.mte_magic[1] = 'E';
+ sescallmte.mte_usecnt = 1;
+ sescallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ sescallmte.mte_swapmte = &sescallsmte;
+ sescallmte.mte_modname = (ULONG) &sesrestab;
+ sescallmte.mte_link = &quecallmte;
+ Allocate16BHandle(&sescallmte.mte_handle, (ULONG) &sescallsmte);
+ sescallsmte.smte_restab = (ULONG) &sesrestab;
+ sescallsmte.smte_nrestab = (ULONG) &sesnrestab;
+ sescallsmte.smte_cbnrestab = 10;
+ sescallsmte.smte_enttab = (ULONG) &sesenttab;
+ sescallsmte.smte_objtab = (ULONG) &segtab;
+ sescallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)sescallmte.mte_modname;
+ sescallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(sescallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)sescallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)sescallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)sescallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)sescallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ sescallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+#ifdef PMNT
+ pmntcallmte.mte_magic[0] = 'N';
+ pmntcallmte.mte_magic[1] = 'E';
+ pmntcallmte.mte_usecnt = 1;
+ pmntcallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ pmntcallmte.mte_swapmte = &pmntcallsmte;
+ pmntcallmte.mte_modname = (ULONG) &pmnrestab;
+ pmntcallmte.mte_link = &sescallmte;
+ Allocate16BHandle(&pmntcallmte.mte_handle, (ULONG) &pmntcallsmte);
+ pmntcallsmte.smte_restab = (ULONG) &pmnrestab;
+ pmntcallsmte.smte_nrestab = (ULONG) &pmnnrestab;
+ pmntcallsmte.smte_cbnrestab = 10;
+ pmntcallsmte.smte_enttab = (ULONG) &pmnenttab;
+ pmntcallsmte.smte_objtab = (ULONG) &segtab;
+ pmntcallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)pmntcallmte.mte_modname;
+ pmntcallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(pmntcallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)pmntcallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)pmntcallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)pmntcallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)pmntcallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ pmntcallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+#endif
+
+ viocallmte.mte_magic[0] = 'N';
+ viocallmte.mte_magic[1] = 'E';
+ viocallmte.mte_usecnt = 1;
+ viocallmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ viocallmte.mte_swapmte = &viocallsmte;
+ viocallmte.mte_modname = (ULONG) &viorestab;
+#ifdef PMNT
+ viocallmte.mte_link = &pmntcallmte;
+#else
+ viocallmte.mte_link = &sescallmte;
+#endif
+ viocallsmte.smte_path = (ULONG) &viorestab;
+ viocallsmte.smte_pathlen = (USHORT) 9;
+ Allocate16BHandle(&viocallmte.mte_handle, (ULONG) &viocallsmte);
+ viocallsmte.smte_restab = (ULONG) &viorestab;
+ viocallsmte.smte_nrestab = (ULONG) &vionrestab;
+ viocallsmte.smte_cbnrestab = 15;
+ viocallsmte.smte_enttab = (ULONG) &vioenttab;
+ viocallsmte.smte_objtab = (ULONG) &segtab;
+ viocallsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)viocallmte.mte_modname;
+ viocallsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(viocallsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)viocallsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)viocallsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)viocallmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)viocallsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ viocallsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+#ifdef DBCS
+// MSKK Dec.15.1992 V-AkihiS
+ imdaemonmte.mte_magic[0] = 'N';
+ imdaemonmte.mte_magic[1] = 'E';
+ imdaemonmte.mte_usecnt = 1;
+ imdaemonmte.mte_mflags = CLASS_GLOBAL | LIBRARYMOD | GINIDONE | DOSMOD | MTEPROCESSED;
+ imdaemonmte.mte_swapmte = &imdaemonsmte;
+ imdaemonmte.mte_modname = (ULONG) &imdrestab;
+ imdaemonmte.mte_link = &viocallmte;
+ Allocate16BHandle(&imdaemonmte.mte_handle, (ULONG) &imdaemonsmte);
+ imdaemonsmte.smte_restab = (ULONG) &imdrestab;
+ imdaemonsmte.smte_nrestab = (ULONG) &imdnrestab;
+ imdaemonsmte.smte_cbnrestab = 10;
+ imdaemonsmte.smte_enttab = (ULONG) &imdenttab;
+ imdaemonsmte.smte_objtab = (ULONG) &segtab;
+ imdaemonsmte.smte_objcnt = 1;
+
+ ModSize = *(PCHAR)imdaemonmte.mte_modname;
+ imdaemonsmte.smte_path =
+ (ULONG)RtlAllocateHeap(LDRNEHeap, 0, SizeOfSystemDir + ModSize + 5);
+ if ( !(imdaemonsmte.smte_path) )
+ {
+#if DBG
+ DbgPrint("OS2LDR: ldrinit - out of heap memory\n");
+ ASSERT( FALSE );
+#endif
+ return(FALSE);
+ }
+ memcpy((PVOID)imdaemonsmte.smte_path, SystemDir, SizeOfSystemDir);
+ memcpy((PCHAR)imdaemonsmte.smte_path + SizeOfSystemDir,
+ (PCHAR)imdaemonmte.mte_modname + 1, ModSize);
+ strcpy((PCHAR)imdaemonsmte.smte_path + SizeOfSystemDir + ModSize, DotDll);
+ imdaemonsmte.smte_pathlen = (USHORT)(SizeOfSystemDir + ModSize + 4);
+
+ mte_h = global_h = (ldrmte_t *)&imdaemonmte;
+#else
+ mte_h = global_h = (ldrmte_t *)&viocallmte;
+#endif
+ global_l = (ldrmte_t *)&acscallmte;
+
+#if 0
+ //
+ // Preload the DOSCALLS dll (not implemented yet)
+ //
+
+ //
+ // Init the Library Intialization routines data structure to NULL
+ // in order to detect bugs
+ //
+ pldrLibiRecord = NULL;
+ pldrLibiCounter = NULL;
+
+ /*
+ * Point to ldrLibPathBuf to contain the environment string
+ */
+ strcpy(ldrLibPathBuf, SystemDir);
+
+ rc = ldrGetModule("DOSCALLS",
+ 8,
+ (char)EXT_LIBRARY,
+ CLASS_GLOBAL,
+ &pmte,
+ 0);
+ if (rc != NO_ERROR) {
+ return(FALSE);
+ }
+ pmte->mte_usecnt = 1;
+#endif
+
+#if DBG
+ IF_OL2_DEBUG ( MTE ) {
+ DbgPrint("OS2LDR: List of LDR dlls:\n");
+ for (pmte = mte_h; pmte != NULL; pmte = pmte->mte_link) {
+ DbgPrint("%s, NameLen=%d, %s\n",
+ pmte->mte_swapmte->smte_path,
+ pmte->mte_swapmte->smte_pathlen,
+ (PCHAR)pmte->mte_modname + 1);
+ }
+ }
+#endif
+ return(TRUE);
+}
+
+
+//
+// Service routines to create and translate mapping between
+// 32b Cruiser Handles and random 16b handles (not to confuse
+// with OS2 1.X File Handles and Thread Handles which are
+// not random)
+//
+
+APIRET
+Allocate16BHandle(
+ OUT PUSHORT pusHandle,
+ IN ULONG h32bHandle
+ )
+{
+ ULONG Entry;
+ ULONG LoopCounter = 0;
+
+ //
+ // Find a free entry in the cookie table
+ //
+ Entry = NextCookie & (NUM_OF_COOKIES - 1);
+ while (Cookies[Entry].cookie != 0) {
+ //
+ // Verify that we are not looping forever
+ //
+ LoopCounter++;
+ if (LoopCounter == NUM_OF_COOKIES) {
+ return(ERROR_NO_OBJECT);
+ }
+ NextCookie++;
+ if (NextCookie == _64K) {
+ NextCookie = 1;
+ }
+ Entry = NextCookie & (NUM_OF_COOKIES - 1);
+ }
+
+ Cookies[Entry].value32 = h32bHandle;
+ Cookies[Entry].cookie = NextCookie;
+ *pusHandle = (USHORT)NextCookie;
+ NextCookie++;
+ if (NextCookie == _64K) {
+ NextCookie = 1;
+ }
+ return(NO_ERROR);
+}
+
+APIRET
+Free16BHandle(
+ IN USHORT usHandle
+ )
+{
+ ULONG Entry;
+
+ //
+ // Find a free entry in the cookie table
+ //
+ Entry = usHandle & (NUM_OF_COOKIES - 1);
+ if (Cookies[Entry].cookie != (ULONG)usHandle) {
+ return(ERROR_INVALID_HANDLE);
+ }
+ Cookies[Entry].cookie = 0;
+ return(NO_ERROR);
+}
+
+NTSTATUS
+ldrCreateR2XferSeg()
+{
+ NTSTATUS Status;
+ LARGE_INTEGER SectionSize;
+ ULONG RegionSize = _64K;
+ PVOID BaseAddress;
+
+ SectionSize.LowPart = _64K;
+ SectionSize.HighPart = 0;
+ Status = NtCreateSection( &R2XferSegHandle,
+ SECTION_ALL_ACCESS,
+ NULL,
+ &SectionSize,
+ PAGE_EXECUTE_READWRITE,
+ SEC_COMMIT,
+ NULL
+ );
+
+ if (!NT_SUCCESS( Status )) {
+#if DBG
+ KdPrint(("OS2LDR: unable to create the R2XFER section, Status=%x\n", Status));
+#endif
+ return( Status );
+ }
+
+ BaseAddress = (PVOID)R2XFER_BASE;
+ Status = NtMapViewOfSection( R2XferSegHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ 0,
+ NULL,
+ &RegionSize,
+ ViewUnmap,
+ 0,
+ PAGE_READWRITE
+ );
+
+ if (!NT_SUCCESS( Status )) {
+#if DBG
+ KdPrint(("OS2LDR: unable to Map View the R@XFER section, Status=%x\n", Status));
+#endif
+ return( Status );
+ }
+
+ return( Status );
+}
+
+
+
diff --git a/private/os2/ldr/ldrmte.c b/private/os2/ldr/ldrmte.c
new file mode 100644
index 000000000..e78cbeba1
--- /dev/null
+++ b/private/os2/ldr/ldrmte.c
@@ -0,0 +1,4290 @@
+
+#include "ldrextrn.h"
+#include "ldrdbg.h"
+#ifdef PMNT
+#define INCL_32BIT
+#include "pmnt.h"
+PID PMNTPMShellPid = 0;
+#endif
+
+/***EP LDRNewExe - load a new .EXE file format program.
+ *
+ * This routine is called by the w_execpgm function to
+ * load a program module and it's referenced library
+ * modules.
+ *
+ * This procedure performs the following steps:
+ *
+ * - Compute module name string length and validate it.
+ * - Load the program module and referenced library modules.
+ * - Copy startup information into the exec_info structure.
+ *
+ * ENTRY pachModname - pointer to ASCII module name
+ * pexec_info - pointer to return buffer
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ * pexec_info structure set
+ */
+
+BOOLEAN
+LDRNewExe(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRNEWEXE_MSG a = &m->u.LdrNewExe;
+ ldrmte_t *pmte; /* Pointer to loaded mte */
+ ldrmte_t *pmteToChange;
+ ldrste_t *psteToChange;
+ USHORT Offset;
+ PVOID FlatEntryPoint;
+ UCHAR c = (UCHAR)0xCC;
+ USHORT cb;
+ int rc;
+ NTSTATUS Status;
+ ULONG NEFlags;
+#if PMNT
+ BOOLEAN SavedErrInfo=FALSE;
+#endif
+
+ ldrNewExeInit(t,a,&cb);
+ /*
+ * Load the program module and referenced library modules.
+ */
+ rc = ldrGetModule(a->ProcessName.Buffer,
+ cb,
+ (char)EXT_PROGRAM,
+ (ushort_t) CLASS_PROGRAM,
+ &pmte,
+ &a->BoundApp,
+ &NEFlags);
+#if PMNT
+ if ((rc == ERROR_INVALID_ORDINAL || rc == ERROR_PROC_NOT_FOUND) &&
+ !(CurrentThread->Process->Flags & OS2_PROCESS_WINDOWAPI) &&
+ ldrTgtModNameBufL == 8 && ! strncmp(ldrTgtModNameBuf,"VIOCALLS",8)
+ ) {
+ SavedErrInfo = ldrSaveErrInfo(rc);
+ CurrentThread->Process->Flags |= OS2_PROCESS_FORCEDPM;
+ //
+ // Maybe a PM application with WINDOWAPI flags off; try forced PM
+ //
+ ldrUnloadTagedModules(t->Process);
+
+ ldrNewExeInit(t,a,&cb);
+
+ /*
+ * Load the program module and referenced library modules.
+ */
+ rc = ldrGetModule(a->ProcessName.Buffer,
+ cb,
+ (char)EXT_PROGRAM,
+ (ushort_t) CLASS_PROGRAM,
+ &pmte,
+ &a->BoundApp,
+ &NEFlags);
+ if ((rc != NO_ERROR || ! (CurrentThread->Process->Flags & OS2_PROCESS_PMMSGQUE))
+ && SavedErrInfo) {
+ ldrRestoreErrInfo(&rc);
+ }
+
+ }
+ else if (rc == ERROR_2ND_PMSHELL) {
+ ldrUnloadTagedModules(t->Process);
+ m->ReturnedErrorValue = ERROR_2ND_PMSHELL;
+ return(TRUE);
+ }
+#endif // if PMNT
+
+ if (rc != NO_ERROR) {
+ ldrWriteErrTxt(rc);
+#if PMNT
+ if (SavedErrInfo) {
+ ldrFreeErrInfo();
+ }
+#endif
+ ldrUnloadTagedModules(t->Process);
+ m->ReturnedErrorValue = rc;
+ return(TRUE);
+ }
+
+#if PMNT
+ if (SavedErrInfo) {
+ ldrFreeErrInfo();
+ }
+#endif
+ if (CurrentThread->Process->Flags & OS2_PROCESS_TRACE) {
+ /*
+ * Replace the initial instruction of the first init
+ * routine with int 3. This will be replaced back by
+ * Os2DebugEventHandle at init time.
+ */
+
+ if (*pldrLibiCounter > 0) {
+ /*
+ * There is an init routine
+ */
+
+ pmteToChange = ldrFindMTEForHandle(pldrLibiRecord[0].handle);
+ }
+ else {
+ pmteToChange = ldrFindMTEForHandle(((LinkMTE *)CurrentThread->Process->LinkMte)->NextMTE->MTE);
+ }
+
+ CurrentThread->Process->FirstMTE = pmteToChange;
+ psteToChange = ldrNumToSte(pmteToChange, pmteToChange->mte_swapmte->smte_startobj);
+ Offset = (USHORT)pmteToChange->mte_swapmte->smte_eip;
+ FlatEntryPoint = (PVOID)((ULONG)(SELTOFLAT(psteToChange->ste_selector |7)) | (ULONG)(Offset));
+ Status = NtWriteVirtualMemory( CurrentThread->Process->ProcessHandle,
+ (PVOID) FlatEntryPoint,
+ (PVOID) &(c),
+ 1,
+ NULL
+ );
+#if DBG
+ if (!(NT_SUCCESS(Status))) {
+ KdPrint(( "LDRNewExe: PTrace support failed to write entry. Status %lx\n", Status));
+ }
+#endif
+ }
+
+ //
+ // Update app type in process structure
+ //
+ pmte->mte_mflags2 = NEFlags;
+
+ //
+ // set/force bound-app flag
+ //
+ if (a->BoundApp) {
+ pmte->mte_mflags2 |= NEBOUND;
+ }
+
+#if PMNT
+ a->PMProcess = 0;
+
+ if (CurrentThread->Process->Flags & OS2_PROCESS_IS_PMSHELL)
+ {
+ pmte->mte_mflags2 |= NEPMSHELL;
+ a->PMProcess |= APPTYPE_PMSHELL;
+ }
+
+ if (CurrentThread->Process->Flags & OS2_PROCESS_PMMSGQUE)
+ {
+ pmte->mte_mflags2 |= NEPMMSGQUE;
+ }
+
+ if (Os2srvProcessIsPMProcess(CurrentThread->Process))
+ {
+ a->PMProcess |= APPTYPE_PM;
+ }
+
+ if ((CurrentThread->Process->Parent != NULL) &&
+ (CurrentThread->Process->Parent->ProcessId != 0) &&
+ (CurrentThread->Process->Parent->ProcessId == PMNTPMShellPid))
+ {
+ a->PMProcess |= APPTYPE_PMSHELL_CHILD;
+ }
+
+ if (a->PMProcess && !PMNTPMShellPid) {
+ ldrUnloadTagedModules(t->Process);
+ m->ReturnedErrorValue = ERROR_PMSHELL_NOT_UP;
+ return(TRUE);
+ }
+#endif // PMNT
+
+ /*
+ * get program module startup parameters
+ */
+ rc = ldrGetModParams(pmte, (ldrrei_t *)&a->ExecInfo);
+ if (rc != NO_ERROR) {
+ ldrWriteErrTxt(rc);
+ ldrUnloadTagedModules(t->Process);
+ m->ReturnedErrorValue = rc;
+ return(TRUE);
+ }
+
+ //
+ // Save the handle of the CLASS_PROGRAM mte in the process
+ // data structure
+ //
+ t->Process->ProcessMTE = (PVOID)pmte;
+
+ a->DoscallsSel = LDRDoscallsSel;
+ m->ReturnedErrorValue = NO_ERROR;
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: LDRNewExe is returning to the client, rc = %d\n", rc);
+ }
+#endif
+ //
+ // Increment the usecnt of the referenced modules
+ //
+ pmte = mte_h;
+ while (pmte != NULL) {
+ if ((pmte->mte_mflags & INGRAPH) != 0) {
+ pmte->mte_usecnt++;
+ }
+ pmte = pmte->mte_link;
+ }
+
+#if DBG
+ IF_OL2_DEBUG ( MTE ) {
+ DbgPrint("\nDumping segments after LDRNewExe() processing\n");
+ ldrDisplaySegmentTable();
+ }
+#endif
+
+#if PMNT && DBG
+ LDRDumpSegments((POS2_THREAD)NULL,
+ (POS2_API_MSG)NULL);
+#endif
+
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+}
+
+
+VOID
+ldrNewExeInit(
+ IN POS2_THREAD t,
+ IN P_LDRNEWEXE_MSG a,
+ OUT PUSHORT cb
+ )
+{
+ //
+ // Set the global variable CurrentThread to the value of
+ // the current running Thread. This is used by other routines
+ // in the loader to find relevant information regarding the
+ // OS/2 process that issued the call.
+ //
+ CurrentThread = t;
+
+ //
+ // Set the fForceUnmap flag to TRUE so that ldrUnloadTagedModules()
+ // does unmap the app's freed segments from the app's address space.
+ //
+ fForceUnmap = TRUE;
+
+ //
+ // Invalidate the error message buffers
+ //
+ ldrInvSrcErrTxt();
+ ldrInvTgtErrTxt();
+
+ //
+ // Update once the Ol2EntryFlat variable which points to
+ // the client's entry flat address
+ //
+ Ol2EntryFlat = a->EntryFlatAddr;
+
+ //
+ // Init the Library Intialization routines data structure
+ //
+ pldrLibiRecord = (ldrlibi_t *)a->InitRecords.Buffer;
+ pldrLibiCounter = &a->NumOfInitRecords;
+ *pldrLibiCounter = 0;
+
+ //
+ // init the pointer to the error string
+ //
+ pErrText = &a->FailName;
+
+ ldrClearAllMteFlag(INGRAPH | USED);
+
+ /*
+ * Point to ldrLibPathBuf to contain the environment string
+ */
+ strncpy(ldrLibPathBuf, a->LibPathName.Buffer, SizeOfldrLibPathBuf);
+ ldrLibPathBuf[SizeOfldrLibPathBuf - 1] = '\0';
+
+ _strupr(ldrpLibPath);
+
+ *cb = (USHORT)a->ProcessName.Length;
+
+}
+
+UCHAR
+ldrGetEntryPoint(
+ IN POS2_PROCESS Process
+ )
+{
+ ldrsmte_t *psmte;
+ ldrste_t *pste;
+ USHORT offset;
+ PVOID FlatEntryPoint;
+ NTSTATUS Status;
+ UCHAR c;
+ ldrmte_t *pMte;
+
+ if (((LinkMTE *)Process->LinkMte)->NextMTE == NULL) {
+ return(0);
+ }
+
+ pMte = Process->FirstMTE;
+ psmte = pMte->mte_swapmte;
+ pste = ldrNumToSte(pMte, psmte->smte_startobj);
+ offset = (USHORT) psmte->smte_eip;
+ FlatEntryPoint = (PVOID)((ULONG)(SELTOFLAT(pste->ste_selector | 7)) | (ULONG)(offset));
+ Status = NtReadVirtualMemory(Process->ProcessHandle,
+ FlatEntryPoint,
+ (PVOID) &(c),
+ 1,
+ NULL
+ );
+ if (!(NT_SUCCESS(Status))) {
+#if DBG
+ KdPrint(( "ldrGetEntryPoint failed to read entry. Status %lx\n", Status));
+#endif
+
+ return(0);
+ }
+
+ return(c);
+}
+
+VOID
+ldrRestoreEntryPoint(
+ IN POS2_PROCESS Process
+ )
+{
+ //
+ // A process being traced just started, replace the int 3 with the real
+ // code
+ //
+ PVOID FlatEntryPoint;
+ UCHAR c;
+ NTSTATUS Status;
+ ldrste_t *pste;
+ USHORT offset;
+ ldrsmte_t *psmte;
+ ldrmte_t *pMte;
+
+ if (((LinkMTE *)Process->LinkMte)->NextMTE == NULL) {
+ return;
+ }
+
+ pMte = Process->FirstMTE;
+ psmte = pMte->mte_swapmte;
+ pste = ldrNumToSte(pMte, psmte->smte_startobj);
+ offset = (USHORT) psmte->smte_eip;
+ FlatEntryPoint = (PVOID)((ULONG)(SELTOFLAT(pste->ste_selector | 7)) | (ULONG)(offset));
+ //
+ // get the original value from os2srv address space, and stick it into
+ // the debuggee process
+ //
+ c = *(PUCHAR)(FlatEntryPoint);
+ Status = NtWriteVirtualMemory(Process->ProcessHandle,
+ FlatEntryPoint,
+ (PVOID) &(c),
+ 1,
+ NULL
+ );
+ if (!(NT_SUCCESS(Status))) {
+#if DBG
+ KdPrint(( "ldrRestoreEntryPoint failed to write entry. Status %lx\n", Status));
+#endif
+
+ }
+
+}
+
+
+
+/***LP ldrGetModule - Get module handle, load if required
+ *
+ * Get the module table entry handle for this module. If the
+ * module is not already loaded, call ldrLoadModule to load it.
+ *
+ * This procedure performs the following steps:
+ *
+ * - Allocate loader variables on the stack and initialize.
+ * - Get the desired module table entry handle.
+ * - Scan the mte list loading objects for modules that
+ * are not loaded.
+ * - Load the module
+ * - Release loader variables on the stack.
+ *
+ * ENTRY pachModname - pointer to module name
+ * cb - length of module name
+ * chLdrtype - load type being requested
+ * (program,library)
+ * class - module class
+ * (PROGRAM, GLOBAL or SPECIFIC)
+ * ppmte - a pointer to a mte pointer which
+ * was loaded
+ * pBound - optional pointer to a flag set if BOUND exe
+ *
+ * pNEFlags - Flags word of the NE header
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ * COMMENT:
+ * ldrGetModule is called from LDRNewExe, LDRLoadVdd and w_loadmodule.
+ */
+
+APIRET ldrGetModule(pachModname, cb, chLdrtype, class, ppmte, pBound, pNEFlags)
+PUCHAR pachModname; /* pointer to ASCII module name */
+USHORT cb; /* length of mod name */
+char chLdrtype; /* type of module to load */
+USHORT class; /* module class */
+ldrmte_t **ppmte; /* place to return pointer to mte */
+PBOOLEAN pBound; /* optional pointer to a flag set if BOUND exe */
+PULONG pNEFlags; /* optional pointer to Flags word of the NE header */
+{
+ register ldrmte_t *pmte; /* pointer to mte */
+ ldrlv_t lv; /* define local variables */
+ ldrlv_t *plv = &lv;
+ int rc;
+ LinkMTE *mteInLinkList;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrGetModule() was called with modname=%.*s, ", cb, pachModname);
+ if (chLdrtype == EXT_PROGRAM) {
+ DbgPrint("Type=PROGRAM\n");
+ }
+ else {
+ DbgPrint("Type=LIBRARY\n");
+ }
+ }
+#endif
+
+ if (pBound != 0) {
+ *pBound = FALSE;
+ }
+
+ try {
+ /*
+ * Init local variables
+ */
+ memset((PCHAR) plv, 0, sizeof(ldrlv_t));
+
+ lv.lv_type = chLdrtype;
+ lv.lv_sfn = 0;
+ lv.lv_class = class;
+
+ /*
+ * initialize mte
+ */
+ rc = ldrGetMte(pachModname, cb, chLdrtype, class, &plv->lv_pmte, pBound, pNEFlags);
+ if (rc != NO_ERROR) {
+ return(rc);
+ }
+
+ /*
+ * return handle and pointer of loaded mte
+ */
+ pmte = *ppmte = lv.lv_pmte;
+
+ //
+ // Scan linked list of mtes and load or attach to objects.
+ //
+
+ for (pmte = mte_h; pmte != NULL; pmte = pmte->mte_link) {
+ //
+ // If module is not referenced, continue to next module
+ //
+ if ((pmte->mte_mflags & INGRAPH) == 0) {
+ continue;
+ }
+
+ //
+ // Module was referenced. Load it into memory
+ //
+ lv.lv_pmte = pmte; /* save pointer to mte */
+ lv.lv_hobmte = pmte->mte_handle;/* save handle to mte */
+ lv.lv_sfn = pmte->mte_sfn; /* save SFN of this mte */
+ rc = ldrLoadModule(plv); /* load required objects */
+ if (rc != NO_ERROR) {
+ return(rc);
+ }
+ if (CurrentThread->Process->Flags & OS2_PROCESS_TRACE) {
+ if ((*(PCHAR)pmte->mte_modname != 8) ||
+ (strncmp((PCHAR)(pmte->mte_modname)+1, "DOSCALLS", 8))) {
+ /*
+ * Add the mte to the process link list of mte.
+ */
+ mteInLinkList = (LinkMTE *) (CurrentThread->Process->LinkMte);
+ mteInLinkList->NeedToTransfer++;
+ while (mteInLinkList->NextMTE != NULL) {
+ mteInLinkList = mteInLinkList->NextMTE;
+ }
+
+ mteInLinkList->NextMTE = RtlAllocateHeap(Os2Heap, 0, sizeof(LinkMTE));
+ if (mteInLinkList->NextMTE) {
+ mteInLinkList->NextMTE->MTE = pmte->mte_handle;
+ mteInLinkList->NextMTE->NextMTE = NULL;
+ mteInLinkList->NextMTE->NeedToTransfer = TRUE;
+ }
+ else {
+#if DBG
+ KdPrint(( "ldrGetModule: Unable to allocate memory for new mte in link list\n"));
+#endif
+ return(ERROR_NOT_ENOUGH_MEMORY);
+ }
+ }
+ }
+ }
+
+ return(NO_ERROR);
+ }
+ except(EXCEPTION_EXECUTE_HANDLER) {
+ return(0xdeadbeef);
+ }
+}
+
+
+/***LP ldrUCaseString - Upper case string
+*/
+void ldrUCaseString(PCHAR pstring, ULONG cb)
+{
+ PUCHAR plocal;
+ ULONG i;
+
+ plocal = (PUCHAR)pstring;
+ for (i = 0; i < cb; i++) {
+#ifdef DBCS
+// MSKK Apr.09.1993 V-AkihiS
+ if (IsDBCSLeadByte(*plocal)) {
+ plocal++;
+ if (i < cb) {
+ i++;
+ plocal++;
+ }
+ } else {
+ *plocal = (CHAR) toupper(*plocal);
+ plocal++;
+ }
+#else
+ *plocal = (CHAR) toupper(*plocal);
+ plocal++;
+#endif
+ }
+
+}
+
+
+/***LP ldrGetMte - Get module handle
+ *
+ * Get the module table entry (mte) handle for this module. If
+ * the module's mte is not in the linked list of mte's, open and
+ * read the file EXE header, verify the header is for a segmented
+ * or linear EXE file format, create an mte for the module and initialize
+ * it. If this is a program module, save the mte handle in the user's
+ * PTDA. If the module's mte is found in the linked list of mte's,
+ * attach to the module if not already attached and allocate non_shared
+ * objects.
+ *
+ * ENTRY pachModname - pointer to module name
+ * cb - length of module name
+ * chLdrtype - load type being requested
+ * (program,library,device)
+ * class - program,global or specific
+ * ppmte - pointer to a pmte if exist else 0
+ * pBound - optional pointer to a flag set if BOUND exe
+ * pNEFlags - Flags word of the NE header
+ *
+ * EXIT none - return successful or call load_error
+ *
+ * EFFECTS - pointer of reqested mte placed in
+ * ppmte
+ *
+ * COMMENT - ldrGetMte is called from ldrGetModule
+ * and ldrLoadModule
+ */
+
+APIRET ldrGetMte(pachModname, cb, chLdrtype, class, ppmte, pBound, pNEFlags)
+PUCHAR pachModname; /* pointer to ASCII module name */
+USHORT cb; /* length of module name */
+UCHAR chLdrtype; /* type of module to load */
+USHORT class; /* class to which module belongs */
+ldrmte_t **ppmte; /* pointer to a mte pointer */
+PBOOLEAN pBound; /* optional pointer to a flag set if BOUND exe */
+PULONG pNEFlags; /* optional pointer to Flags word of the NE header */
+{
+ ldrlv_t lv; /* loader variable */
+ register ldrlv_t *plv = &lv;
+ register ldrmte_t *pmte; /* pointer to mte */
+ struct e32_exe *pe32; /* pointer to link exe format image */
+ ldrmte_t *ptemp;
+ ldrsmte_t *psmte;
+ int rc;
+ int rc1;
+ int ModuleNameSize;
+ PCHAR ModuleNameString;
+ ULONG i;
+ ULONG lindex;
+ PCHAR RefModname;
+ USHORT Refcb;
+ BOOLEAN BoundApp;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrGetMte() was called with modname=%.*s, ", cb, pachModname);
+ if (chLdrtype == EXT_PROGRAM) {
+ DbgPrint("Type=PROGRAM\n");
+ }
+ else {
+ DbgPrint("Type=LIBRARY\n");
+ }
+ }
+#endif
+
+ if (pBound != 0) {
+ *pBound = FALSE;
+ }
+
+ /*
+ * Init local variables
+ */
+ memset((PCHAR) plv, 0, sizeof(ldrlv_t));
+
+ /*
+ * setup source global error message txt
+ */
+
+ if ((cb > 14) && !strncmp(pachModname, "\\OS2SS\\DRIVES\\", 14)) {
+ ldrSetupSrcErrTxt(pachModname+14, cb-14);
+ }
+ else {
+ ldrSetupSrcErrTxt(pachModname, cb);
+ }
+
+ lv.lv_type = chLdrtype;
+ lv.lv_sfn = 0;
+ lv.lv_class = class;
+
+ if ((*ppmte == NULL) && (lv.lv_type != EXT_DEVICE)) {
+ /*
+ * Upper case module name
+ */
+ ldrUCaseString(pachModname, (ulong_t) cb);
+
+ /*
+ * Do not search for device drivers.
+ * Search to see if the module is already loaded so that
+ * it may be shared. ppmte is set to zero if the module
+ * is not found
+ */
+ ldrFindModule(pachModname, cb, class, ppmte);
+
+ /*
+ * We can not load VDDs twice, so if FindModule found it
+ * return an error.
+ * BUGBUG - This error should be changed to:
+ * ERROR_VDD_ALREADY_LOADED
+ */
+ if (chLdrtype == EXT_VDD && *ppmte != NULL) {
+
+ if (pBound != 0 &&
+ ((*ppmte)->mte_mflags2 & NEBOUND)) {
+
+ *pBound = TRUE;
+ }
+
+ return(ERROR_NOT_SAME_DEVICE);
+ }
+ }
+
+ again:
+ pmte = lv.lv_pmte = *ppmte;
+
+ if (pmte != NULL) {
+
+ if (pBound != 0 &&
+ (pmte->mte_mflags2 & NEBOUND)) {
+
+ *pBound = TRUE;
+ }
+
+ if (class == CLASS_PROGRAM) {
+ //
+ // process with same name is running
+ // initialize the new process Flags (normally done during loading
+ //
+
+ *pNEFlags = pmte->mte_mflags2;
+
+ if ((pmte->mte_mflags2 & NEAPPTYP) == NENOTWINCOMPAT) {
+ CurrentThread->Process->Flags |= OS2_PROCESS_NOTWINDOWCOMPAT;
+ }
+ else if ((pmte->mte_mflags2 & NEAPPTYP) == NEWINCOMPAT) {
+ CurrentThread->Process->Flags |= OS2_PROCESS_WINDOWCOMPAT;
+ }
+ else if ((pmte->mte_mflags2 & NEAPPTYP) == NEWINAPI) {
+ CurrentThread->Process->Flags |= OS2_PROCESS_WINDOWAPI;
+ }
+#if PMNT
+ if (pmte->mte_mflags2 & NEPMSHELL) {
+ return(ERROR_2ND_PMSHELL);
+ }
+ if (pmte->mte_mflags2 & NEPMMSGQUE) {
+ CurrentThread->Process->Flags |= OS2_PROCESS_PMMSGQUE;
+ }
+#endif //if PMNT
+ }
+
+ if ((pmte->mte_mflags & INGRAPH) != 0) {
+ return(NO_ERROR);
+ }
+ ldrChkLoadType(pmte->mte_mflags, plv);
+
+// ldrInvTgtErrTxt();
+#if 0
+ /*
+ * Don't load modules that are attached already.
+ */
+ if (ldrIsAttached(pmte)) {
+ return;
+ }
+ else {
+ /*
+ * setup existing SFN to load non-shared objects
+ */
+ lv.lv_sfn = pmte->mte_sfn;
+ /*
+ * Indicate that shared objects should not have the page tables
+ * scanned. We will use the USED bit to indicate this
+ */
+ pmte->mte_mflags |= USED;
+ }
+#endif
+ }
+ else {
+ /*
+ * We come here after ldrFindModule has failed to find this module
+ * in the class specified. We can have the following situation:
+ *
+ * a, We are trying to load a CLASS_SPECIFIC module. In this case
+ * we need to check if this module is loaded as a CLASS_GLOBAL
+ * module. If it is we use that MTE. The MTE is maintained as
+ * CLASS_GLOBAL.
+ *
+ * b, We are trying to load a CLASS_GLOBAL module. In this case
+ * we need to check if this mod is loaded as a CLASS_SPECIFIC
+ * module. If it is we use that MTE. The MTE is then promoted
+ * to CLASS_GLOBAL.
+ */
+ if ((class == CLASS_SPECIFIC) &&
+ ldrCheckGlobal(pachModname, cb, ppmte))
+ goto again;
+
+ if ((rc=ldrOpenNewExe(pachModname, cb, plv, 0, &BoundApp, pNEFlags)) != NO_ERROR) {
+
+ if (rc == ERROR_OPEN_FAILED)
+ rc = ERROR_FILE_NOT_FOUND;
+
+ if (pBound != 0) {
+ *pBound = BoundApp;
+ }
+
+ return(rc) ;
+ }
+
+ if (pBound != 0) {
+ *pBound = BoundApp;
+ }
+
+ if ((class == CLASS_GLOBAL) && ldrCheckSpecific(ppmte, plv)) {
+ NtClose(lv.lv_sfn);
+ lv.lv_sfn = (*ppmte)->mte_sfn;
+ goto again;
+ }
+ pe32 = (struct e32_exe *) pheaderbuf;
+ ldrChkLoadType(pe32->e32_mflags, plv);
+ rc = ldrCreateMte(pe32, plv);
+ if (rc != NO_ERROR) {
+ NtClose(lv.lv_sfn);
+ return(rc);
+ }
+ pmte = lv.lv_pmte;
+
+ ModuleNameSize = *(PCHAR)pmte->mte_modname;
+ ModuleNameString = ((PCHAR)pmte->mte_modname)+1;
+ if ((ModuleNameSize == 8) &&
+ (strncmp("DOSCALLS", ModuleNameString, 8) == 0)) {
+ pmte->mte_mflags |= DOSLIB;
+ pmte->mte_usecnt = 1;
+ }
+
+// ldrInvTgtErrTxt();
+ /*
+ * If VMProtectedMem is TRUE, set MTEMODPROT if module is a 16-bit
+ * DLL and is in PROTECT16 list.
+ * Else clear MTEMODPROT (for both 16 and 32-bit modules).
+ */
+// if (VMProtectedMem) {
+// if (ldrIsNE(pmte) && (pmte->mte_mflags & LIBRARYMOD) &&
+// ldrIsModuleProtected())
+// pmte->mte_mflags |= MTEMODPROT;
+// }
+// else pmte->mte_mflags &= ~MTEMODPROT;
+
+ }
+
+ //
+ // Set the INGRAPH flag in order to prevent cycles
+ //
+ pmte->mte_mflags |= INGRAPH;
+
+ /*
+ * allocate object for this module by calling ldrAllocSegments for
+ * 16-bit modules or ldrAllocObjects for 32-bit modules
+ */
+ if (ldrIsNE(pmte)) {
+ //
+ // For system dll's other than Doscalls don't allocate
+ // segments.
+ //
+ if ((pmte->mte_mflags & DOSMOD) == 0) {
+ //
+ // Don't allocate segments for modules that are already
+ // allocated for this program
+ //
+ if ((pmte->mte_mflags & USED) == 0) {
+ rc = ldrAllocSegments(plv);
+ if (rc != NO_ERROR) {
+ if (pmte->mte_usecnt == 0) {
+ NtClose(lv.lv_sfn);
+ rc1 = Free16BHandle(pmte->mte_handle);
+ ASSERT(rc1 == NO_ERROR);
+ ldrUnlinkMTE(pmte);
+ RtlFreeHeap(LDRNEHeap, 0, pmte->mte_swapmte);
+ RtlFreeHeap(LDRNEHeap, 0, pmte);
+ }
+ return(rc);
+ }
+ }
+ }
+ }
+
+ *ppmte = pmte; /* return pmte */
+
+ //
+ // Now try to recursively allocate the referenced modules
+ //
+
+ /*
+ * For Each module in import module name table attach to or load
+ */
+ ppmte = (ldrmte_t **) pmte->mte_modptrs;
+
+ for (i = 1; i <= pmte->mte_impmodcnt; i++) {
+ /*
+ * Since it is required for 16-bit modules to load the
+ * referneced module in reverse order and not for 32-bit,
+ * lindex will be the index for the array of mte pointers
+ * for both 16-bit and 32-bit modules
+ */
+ lindex = pmte->mte_impmodcnt-i;
+
+ /*
+ * check if module loaded already, if so try to attach to it
+ */
+ ptemp = ppmte[lindex];
+
+ if ((ptemp != NULL) && ((ptemp->mte_mflags & INGRAPH) != 0)) {
+ continue;
+ }
+
+ /*
+ * point to mod name in table for 16-bit modules,
+ * load in reverse order
+ */
+ psmte = pmte->mte_swapmte;
+ RefModname = (uchar_t *) (psmte->smte_impproc +
+ ((ushort_t *) (psmte->smte_impmod))[lindex]);
+ Refcb = (USHORT) (*((uchar_t *) RefModname++));
+
+ rc = ldrGetMte(RefModname, Refcb, EXT_LIBRARY, CLASS_GLOBAL, &ptemp, NULL, NULL);
+ if (rc != NO_ERROR) {
+ return(rc);
+ }
+ ppmte[lindex] = ptemp;
+
+ /*
+ * validate as mte
+ */
+ ASSERT(fMTEValid(ptemp));
+
+ }
+ return(NO_ERROR);
+}
+
+
+/***LP ldrGetModParams - get program module startup parameters
+ *
+ * The program module startup parameters are obtained
+ * from the module's MTE header and are returned to the
+ * Exec function through the exec_info structure. This
+ * routine gets these parameters from the MTE and validates
+ * them and places them into the exec_info structure passed
+ * on the stack.
+ *
+ * This procedure performs the following steps:
+ *
+ * - Validates the starting code segment number.
+ * - Stores the starting CS:IP in the exec_info structure.
+ * - Validates the initial stack segment number and
+ * checks that it is not a shared segment.
+ * - Stores the initial SS in the exec_info structure.
+ * - Stores the auto data selector in the exec_info structure.
+ * - Calculates the initial SP and stores it in the exec_info
+ * structure.
+ * - Stores the additional heap size and stack size values in
+ * the exec_info structure.
+ *
+ * ENTRY pmte - pointer to module table entry
+ * pei - pointer to exec_info structure
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ */
+
+int ldrGetModParams(pmte, pei)
+ldrmte_t *pmte; /* pointer to mte */
+register ldrrei_t *pei; /* pointer to return buffer */
+{
+ ldrsmte_t *psmte; /* pointer to swappable mte */
+ ulong_t lobjnum;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrGetModParams(pmte=%X) was called\n", pmte);
+ }
+#endif
+
+ psmte = pmte->mte_swapmte;
+
+ /*
+ * see what type of module it is
+ */
+ if (ldrIsNE(pmte)) {
+ register ldrste_t *pste;
+
+ pei->ei_loadtype = LDR_16bit;
+ pei->ei_stacksize = (USHORT) psmte->smte_stacksize;
+ pei->ei_hmod = pmte->mte_handle;
+ pei->ei_heapsize = (USHORT) psmte->smte_heapsize;
+
+ /*
+ * The start object was checked in ldrCreateMTE
+ */
+ pste = ldrNumToSte(pmte, psmte->smte_startobj);
+ pei->ei_startaddr.ptr_off = (USHORT) psmte->smte_eip;
+ pei->ei_startaddr.ptr_sel = pste->ste_selector | 7;
+
+ /*
+ * compute stack, force word alignment. Stack object checked in
+ * ldrCreateMTE.
+ */
+ if (psmte->smte_stackobj != 0) {
+ pste = ldrNumToSte(pmte, psmte->smte_stackobj);
+ pei->ei_stackaddr.ptr_sel = pste->ste_selector | 7;
+ pei->ei_stackaddr.ptr_off = (USHORT) (psmte->smte_esp & 0x0fffe);
+ }
+ else {
+ pei->ei_stackaddr.ptr_sel = pste->ste_selector | 7;
+ pei->ei_stackaddr.ptr_off = (USHORT) (psmte->smte_esp & 0x0fffe);
+ }
+
+ /*
+ * setup autods
+ */
+ if (psmte->smte_autods != 0) {
+ pste = ldrNumToSte(pmte, psmte->smte_autods);
+ pei->ei_ds = pste->ste_selector | 7;
+ pei->ei_dgroupsize = pste->ste_minsiz;
+ }
+ else {
+ pei->ei_ds = 0; /* insure that value is ZERO */
+ }
+ }
+ else { /* 32-bit module */
+ register ldrote_t *pote;
+ ulong_t eip;
+
+ eip = psmte->smte_eip + psmte->smte_vbase;
+ pote = (ldrote_t *) psmte->smte_objtab;
+ for (lobjnum = 0; lobjnum < psmte->smte_objcnt; lobjnum++,
+ pote++) {
+ if ((eip >= pote->ote_base) &&
+ (eip < (pote->ote_base + pote->ote_psize)))
+ break;
+ }
+ if (lobjnum == psmte->smte_objcnt) {
+ return(ERROR_INVALID_STARTING_CODESEG);
+ }
+
+ /*
+ * check to see what type of entry point we have in this
+ * 32-bit module.
+ */
+ if (pote->ote_flags & OBJ_BIGDEF) { /* 32-bit object */
+ pei->ei_loadtype = LDR_32bit;
+ pei->ei_startaddr.ptr_flat = eip;
+ pei->ei_ds = 0;
+
+ /*
+ * The stack object was checked in ldrCreateMTE
+ */
+ pote = ldrNumToOte(pmte, psmte->smte_stackobj);
+ pei->ei_stackaddr.ptr_flat = pote->ote_base +
+ ((pote->ote_flags & OBJ_INVALID) ? pote->ote_psize :
+ pote->ote_vsize);
+ pei->ei_heapsize = 0;
+ }
+ else { /* 16-bit object */
+ pei->ei_loadtype = LDR_16bit;
+ pei->ei_heapsize = (USHORT) psmte->smte_heapsize;
+ pei->ei_startaddr.ptr_off = (USHORT) eip;
+// pei->ei_startaddr.ptr_sel = LaToSelTiled(pote->ote_base) |
+// (USHORT) SEL_RPL3;
+ pei->ei_startaddr.ptr_sel = FLATTOSEL(pote->ote_base);
+
+ if ((psmte->smte_autods == 0) ||
+ (pote = ldrNumToOte(pmte, psmte->smte_autods)) == NULL)
+ pei->ei_ds = 0;
+ else
+ pei->ei_ds = FLATTOSEL(pote->ote_base);
+// pei->ei_ds = LaToSelTiled(pote->ote_base) |
+// (USHORT) SEL_RPL3;
+ /*
+ * The stack object was checked in ldrCreateMTE
+ */
+ pote = ldrNumToOte(pmte, psmte->smte_stackobj);
+ pei->ei_stackaddr.ptr_sel = FLATTOSEL(pote->ote_base +
+ psmte->smte_esp);
+
+// pei->ei_stackaddr.ptr_sel = LaToSelTiled(pote->ote_base +
+// psmte->smte_esp) | (USHORT) SEL_RPL3;
+ pei->ei_stackaddr.ptr_off = (ushort_t) psmte->smte_esp;
+ }
+ } /* end 32-bit module */
+ return(NO_ERROR);
+}
+
+#if PMNT
+BOOLEAN
+LDRDumpSegments(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ UNICODE_STRING name_U;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE File;
+ IO_STATUS_BLOCK IoStatusBlock;
+ char Buffer[256]; // = "Hello, world\n";
+ ldrmte_t *pmte = mte_h; /* pointer to module table entry */
+ ldrsmte_t *psmte; /* pointer to swappable mte */
+ ldrste_t *pste;
+ ulong_t csegs;
+
+ RtlInitUnicodeString(&name_U, L"\\OS2SS\\DRIVES\\p:\\tmp\\pmnt.log");
+ InitializeObjectAttributes( &ObjectAttributes,
+ &name_U,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ Status = NtCreateFile(
+ &File,
+ FILE_GENERIC_WRITE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL, // Allocation size
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ FILE_SUPERSEDE,
+ FILE_NON_DIRECTORY_FILE |
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL, // EA buffer
+ 0 // EA size
+ );
+
+ if (!NT_SUCCESS(Status))
+ {
+ KdPrint(("ldrDumpSegmentTable: NtOpenFile failed, Status=%x\n", Status));
+ return(TRUE);
+ }
+
+ while (pmte != NULL)
+ {
+ Status = NtWriteFile(
+ File,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ sprintf(Buffer, "\n%.*s\n",
+ *(char *)pmte->mte_modname,
+ pmte->mte_modname + 1),
+ NULL,
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ {
+ KdPrint(("ldrDumpSegmentTable: NtWriteFile failed, Status=%x\n", Status));
+ return(TRUE);
+ }
+
+ psmte = (ldrsmte_t *) pmte->mte_swapmte;
+ pste = (ldrste_t *) psmte->smte_objtab;
+ for (csegs = 1; csegs <= psmte->smte_objcnt; csegs++,
+ pste++)
+ {
+ Status = NtWriteFile(
+ File,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ sprintf(Buffer, " %2x: %4x %4x %4x %4x %4x %4x %8x\n",
+ csegs,
+ pste->ste_offset, /* file offset to segment data */
+ pste->ste_size, /* file data size */
+ pste->ste_flags, /* type and attribute flags */
+ pste->ste_minsiz, /* minimum allocation size */
+ pste->ste_seghdl, /* segment handle */
+ pste->ste_selector,/* segment selector */
+ pste->ste_fixups /* fixup record storage */
+ ),
+ NULL,
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ {
+ KdPrint(("ldrDumpSegmentTable: NtWriteFile failed, Status=%x\n", Status));
+ return(TRUE);
+ }
+ }
+
+ pmte = pmte->mte_link;
+ }
+
+ NtClose(File);
+
+ return(TRUE);
+}
+#endif // PMNT
+
+#if DBG
+void ldrDisplaySegmentTable()
+{
+ ldrmte_t *pmte = mte_h; /* pointer to module table entry */
+ ldrsmte_t *psmte; /* pointer to swappable mte */
+ ldrste_t *pste;
+ ulong_t csegs;
+
+ while (pmte != NULL)
+ {
+ DbgPrint("\n%.*s\npmte=%x, usecnt=%d, handle=%d\n",
+ *(char *)pmte->mte_modname,
+ pmte->mte_modname + 1,
+ pmte,
+ pmte->mte_usecnt,
+ pmte->mte_handle
+ );
+
+ psmte = (ldrsmte_t *) pmte->mte_swapmte;
+ pste = (ldrste_t *) psmte->smte_objtab;
+ for (csegs = 1; csegs <= psmte->smte_objcnt; csegs++,
+ pste++)
+ {
+ DbgPrint(" %2x: %4x %4x %4x %4x %4x %4x %8x %4x\n",
+ csegs,
+ pste->ste_offset, /* file offset to segment data */
+ pste->ste_size, /* file data size */
+ pste->ste_flags, /* type and attribute flags */
+ pste->ste_minsiz, /* minimum allocation size */
+ pste->ste_seghdl, /* segment handle */
+ pste->ste_selector,/* segment selector */
+ pste->ste_fixups /* fixup record storage */
+ );
+ }
+
+ pmte = pmte->mte_link;
+ }
+}
+#endif
+
+#if PMNT
+/*
+ * We want PMNT apps to load the original viocalls.dll
+ * and OS2 char. apps to load it from doscalls.dll
+ * This routine returns FALSE if an app. finds the wrong DLL
+ */
+BOOLEAN
+ldrChkPmntApp(pachModname, cb, pmte)
+PUCHAR pachModname; /* pointer to ASCII module name */
+USHORT cb; /* length of module name */
+ldrmte_t *pmte; /* pointer to mte */
+{
+ ULONG pmapp,dosmod;
+
+ if ((cb != 8) || (strncmp (pachModname,"VIOCALLS",cb))) {
+ return(TRUE);
+ }
+
+// pmapp = CurrentThread->Process->Flags &
+// (OS2_PROCESS_WINDOWAPI | OS2_PROCESS_FORCEDPM | OS2_PROCESS_PMMSGQUE);
+ pmapp = Os2srvProcessIsPMProcess(CurrentThread->Process);
+ dosmod = pmte->mte_mflags & DOSMOD;
+
+ return((pmapp && !dosmod) || (!pmapp && dosmod));
+}
+#endif //if PMNT
+
+
+/***LP ldrFindModule - Check if module is already loaded.
+ *
+ * Scans the class-list (CLASS_PROGRAM, CLASS_GLOBAL or CLASS_SPECIFIC)
+ * searching for a matching pathname. If the request is for a global
+ * dynlink library module, the module name, which is the first entry in
+ * the resident name table, is used for comparison. Otherwise the pathname
+ * is fully expanded and compared with expanded pathname in the mte.
+ *
+ * The MTE list is organised like this:
+ *
+ * program_h global_h specific_h
+ * | | |
+ * mte_h +------+ +-----+ +-----+ +-----+ +-----+ +-----+
+ * ----> | | | |--->| | | |--->| | | |---+
+ * +------+ .. +-----+ +-----+ .. +-----+ +-----+ .. +-----+ |
+ * | | | ___
+ * program_l global_l specific_l -
+ *
+ * mte_h is the head of the linked list. Both program_h and specific_h
+ * could be NULL. If program_h is NULL, then mte_h and global_h point to
+ * the same MTE. global_l can never be NULL. program_l and specific_l
+ * can be.
+ *
+ * ENTRY pachModname - pointer to module name
+ * class - CLASS_GLOBAL, CLASS_SPECIFIC or
+ * CLASS_PROGRAM
+ * ppmte - pointer to a pmte to return
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ * - pointer to reqested mte returned in
+ * ppmte
+ *
+ */
+
+int ldrFindModule(pachModname, cb, class, ppmte)
+PUCHAR pachModname; /* pointer to ASCII module name */
+USHORT cb; /* length of module name */
+USHORT class; /* class of module */
+ldrmte_t **ppmte; /* place to return pointer */
+{
+ register ldrmte_t *pmte; /* pointer to module table entry */
+ ldrsmte_t *psmte; /* pointer to swappable MTE */
+ USHORT cchlen; /* length of module name in restab */
+ USHORT fpath; /* If TRUE then search by path */
+
+ fpath = (USHORT) (class & SEARCH_BY_PATH);
+ class &= ~SEARCH_BY_PATH;
+
+ switch (class) {
+ case CLASS_ALL:
+ pmte = mte_h;
+ break;
+ case CLASS_GLOBAL:
+ pmte = global_h;
+ break;
+ case CLASS_SPECIFIC:
+ pmte = specific_h;
+ break;
+ case CLASS_PROGRAM:
+ pmte = program_h;
+ break;
+ default:
+#if DBG
+ DbgPrint("ldrFindModule: Invalid class");
+#endif
+ pmte = mte_h;
+ break;
+ }
+
+ /*
+ * Search the mte list for module name in TempBuf
+ */
+ while (pmte != NULL) {
+
+ /*
+ * If not searching CLASS_ALL, terminate the scan when the
+ * class value in the MTE is not what we want.
+ */
+ if ((class != CLASS_ALL) &&
+ ((USHORT)(pmte->mte_mflags & CLASS_MASK) != class)) {
+ pmte = NULL;
+ break;
+ }
+ if ((class == CLASS_GLOBAL) && (fpath != SEARCH_BY_PATH)) {
+ /*
+ * If we're looking for global library module, first check
+ * length of name for match then check name.
+ */
+ cchlen = (USHORT) *((PCHAR )pmte->mte_modname);
+ if ((cb == cchlen) &&
+ (strncmp((PCHAR)(pmte->mte_modname+1),
+ pachModname,
+ cchlen) == 0)) {
+#if PMNT
+ /*
+ * check for viocalls
+ *
+ */
+ if (ldrChkPmntApp(pachModname, cb, pmte))
+#endif //if PMNT
+ break;
+ }
+ }
+
+ /*
+ * If either program or specific module, just compare name.
+ * First compare length of strings to fix the problem of
+ * the string matching the first n characters of the pathname
+ * but what if the pathname has n+1 characters in name.
+ */
+ else {
+ psmte = pmte->mte_swapmte;
+ if (psmte->smte_pathlen == cb) {
+ if (strncmp((PCHAR) psmte->smte_path,
+ pachModname,
+ cb) == 0) {
+ break;
+ }
+ }
+ }
+
+ pmte = pmte->mte_link;
+ }
+ *ppmte = pmte; /* Could be NULL, in which case we */
+ return(NO_ERROR); /* did not find the module */
+}
+
+
+/***LP ldrLinkMTE - Link MTE in the list at the appropriate place
+ *
+ * MTEs are linked according to the class they belong to. The possible
+ * classes are CLASS_PROGRAM, CLASS_GLOBAL and CLASS_SPECIFIC. The corres.
+ * list heads are program_h, global_h and specific_h. We also have the
+ * tail of CLASS_PROGRAM, CLASS_GLOBAL and CLASS_SPECIFIC lists which are
+ * program_l, global_l and specific_l. These aid us in linking and
+ * unlinking the list and not having to go through the chain every time.
+ *
+ * To begin with mte_h and global_h point to the same MTE, program_h,
+ * program_l, specific_h and specific_l are NULL. global_l is also
+ * initialised.
+ * See ldrFindModule for organisation of the MTE List.
+ *
+ * The possible cases are:
+ * 1. Link a CLASS_PROGRAM MTE.
+ * if (program_h == NULL) {
+ * pmte->mte_link = global_h;
+ * program_l = pmte;
+ * }
+ * else pmte->mte_link = program_h;
+ * mte_h = program_h = pmte;
+ *
+ * 2. Link a CLASS_GLOBAL MTE.
+ * pmte->mte_link = global_h; // global_h can never be NULL
+ * global_h = pmte;
+ * if (program_l == NULL) // and hence program_h is NULL
+ * mte_h = global_h;
+ * else program_l->mte_link = global_h;
+ *
+ * 3. Link a CLASS_SPECIFIC MTE.
+ * if (specific_l == NULL)
+ * specific_l = pmte;
+ * pmte->mte_link = specific_h;
+ * global_l->mte_link = pmte;
+ *
+ * ENTRY
+ * pmte MTE to link in the list
+ *
+ * EXIT NONE
+ * MTE is linked at the right place
+ */
+void ldrLinkMTE(pmte)
+register ldrmte_t *pmte;
+{
+
+ switch (pmte->mte_mflags & CLASS_MASK) {
+ case CLASS_PROGRAM:
+ if (program_h == NULL) {
+ pmte->mte_link = global_h;
+ program_l = pmte;
+ }
+ else
+ pmte->mte_link = program_h;
+ mte_h = program_h = pmte;
+ break;
+
+ case CLASS_GLOBAL:
+ pmte->mte_link = global_h; /* global_h can never be NULL */
+ global_h = pmte;
+ if (program_l == NULL) /* and hence program_h is NULL */
+ mte_h = pmte;
+ else
+ program_l->mte_link = pmte;
+ break;
+
+ case CLASS_SPECIFIC:
+ if (specific_l == NULL)
+ specific_l = pmte;
+ pmte->mte_link = specific_h;
+ specific_h = pmte;
+ global_l->mte_link = pmte; /* global_l can never be NULL */
+ break;
+
+ default:
+#if DBG
+ DbgPrint("ldrLinkMTE: Invalid class");
+#endif
+ // same as CLASS_GLOBAL
+ pmte->mte_link = global_h; /* global_h can never be NULL */
+ global_h = pmte;
+ if (program_l == NULL) /* and hence program_h is NULL */
+ mte_h = pmte;
+ else
+ program_l->mte_link = pmte;
+ break;
+ }
+}
+
+
+/***LP ldrUnlinkMTE - Unlink MTE from the list
+ *
+ * Unlink the given MTE from the list. See ldrFindModule and ldrLinkMTE
+ * for details of how the list is organised.
+ *
+ * ENTRY
+ * pmte MTE to unlink from the list
+ *
+ * EXIT NONE
+ * MTE is unlinked
+ */
+void ldrUnlinkMTE(pmte)
+register ldrmte_t *pmte;
+{
+ register ldrmte_t *pmtecur; /* Current mte */
+ register ldrmte_t **ppmtepred; /* Predecessor mte */
+ ldrmte_t **ppmtehead; /* Pointer to class head */
+ ldrmte_t **ppmtetail; /* Pointer to class tail */
+ USHORT class;
+
+ switch (class = (USHORT)(pmte->mte_mflags & CLASS_MASK)) {
+ case CLASS_PROGRAM:
+ pmtecur = program_h;
+ ppmtepred = &mte_h;
+ ppmtehead = &program_h;
+ ppmtetail = &program_l;
+ break;
+
+ case CLASS_GLOBAL:
+ pmtecur = global_h;
+ ppmtepred = &program_l->mte_link;
+ if (program_l == NULL)
+ ppmtepred = &mte_h;
+ ppmtehead = &global_h;
+ ppmtetail = &global_l;
+ break;
+
+ case CLASS_SPECIFIC:
+ pmtecur = specific_h;
+ ppmtepred = &global_l->mte_link;
+ ppmtehead = &specific_h;
+ ppmtetail = &specific_l;
+ break;
+
+ default:
+#if DBG
+ DbgPrint("ldrUnlinkMTE: Invalid list");
+#endif
+ // same as class global
+ pmtecur = global_h;
+ ppmtepred = &program_l->mte_link;
+ if (program_l == NULL)
+ ppmtepred = &mte_h;
+ ppmtehead = &global_h;
+ ppmtetail = &global_l;
+ break;
+ }
+ while (TRUE) {
+
+ ldrAssert((pmtecur != NULL &&
+ (pmtecur->mte_mflags & CLASS_MASK) == class));
+
+ if (pmtecur == pmte)
+ break;
+ ppmtepred = &pmtecur->mte_link;
+ pmtecur = pmtecur->mte_link;
+ }
+
+ *ppmtepred = pmte->mte_link; /* Unlink MTE */
+
+ if (pmte == *ppmtehead) { /* If unlinkee is at the head */
+ *ppmtehead = pmte->mte_link;
+ /* If class disappears, then both head and tail disappear */
+ if ((*ppmtehead == NULL) ||
+ ((USHORT)((*ppmtehead)->mte_mflags & CLASS_MASK) != class)) {
+ *ppmtehead = NULL;
+ *ppmtetail = NULL;
+ }
+ }
+ /*
+ * Since we have a pointer to the mte_link field of the predecessor
+ * we need to get back to the mte pointer by subtracting the offset
+ * of the link field of MTE from the pointer to predecessor.
+ */
+ if (pmte == *ppmtetail) { /* If unlinkee is at the tail */
+ *ppmtetail = (ldrmte_t *)((ULONG)ppmtepred -
+ FIELDOFFSET(ldrmte_t, mte_link));
+ ldrAssert(fMTEValid(*ppmtetail));
+ }
+}
+
+
+/***LP ldrCheckGlobal - Check if specified module is loaded as global
+ *
+ * Called by ldrGetMte. If a module is being loaded as a specific module
+ * and ldrFindModule has not found this in the specific list, we see if
+ * this is loaded as a global module. For this to happen, the following
+ * has to be satisfied.
+ * a, The file has to have a ".DLL" as the last part of its name.
+ * b, It should be somewhere in the libpath
+ *
+ * ENTRY
+ * pachModname file name string
+ * cb length of module name
+ * ppmte pointer to where the MTE pointer, if found,
+ * is to be returned
+ *
+ * EXIT
+ * TRUE if module found as loaded global
+ * FALSE module not global.
+ */
+int ldrCheckGlobal(pachModname, cb, ppmte)
+PUCHAR pachModname;
+USHORT cb;
+register ldrmte_t **ppmte;
+{
+ int rc;
+
+ if ((cb <= 4) || _strnicmp(&pachModname[cb-4], ".DLL", 4)) {
+ return(FALSE);
+ }
+
+ if ((rc = ldrFindModule(pachModname, cb,
+ CLASS_GLOBAL|SEARCH_BY_PATH, ppmte)) != NO_ERROR) {
+ load_error(rc, NULL);
+ }
+ return (*ppmte != NULL);
+}
+
+
+/***LP ldrCheckSpecific - Check if specified module is loaded as specfic
+ *
+ * Called by ldrGetMte. If a module is being loaded as a global module
+ * and ldrFindModule has not found this in the global list, we see if
+ * this is loaded as a specific module. If we find this in the specific
+ * list, then we promte it to the global list.
+ *
+ * ENTRY ppmte pointer to where the MTE pointer, if found,
+ * is to be returned.
+ * plv pointer to loader variables structure
+ *
+ * EXIT
+ * TRUE If module found as loaded global
+ * FALSE Otherwise.
+ */
+int ldrCheckSpecific(ppmte, plv)
+ldrmte_t **ppmte;
+ldrlv_t *plv ;
+{
+ USHORT cchModname;
+ register PCHAR pldrbuf = LdrBuf;
+ int rc;
+
+ cchModname = (USHORT) (strlen(pldrbuf));
+
+ ldrUCaseString(pldrbuf, cchModname);
+
+ if ((rc = ldrFindModule(pldrbuf, cchModname, CLASS_SPECIFIC, ppmte)) != NO_ERROR) {
+ NtClose(plv->lv_sfn);
+ load_error(rc, NULL);
+ }
+ if (*ppmte == NULL)
+ return (FALSE);
+ ldrPromoteMTE(*ppmte);
+ return (TRUE);
+}
+
+
+/***LP ldrPromoteMTE - Promote MTE from specific class list to global
+ *
+ * Unlink an MTE from the specific class list and link into global
+ * class list.
+ *
+ * ENTRY pmte MTE to promote
+ *
+ * EXIT NONE
+ */
+void ldrPromoteMTE(pmte)
+ldrmte_t *pmte;
+{
+#ifdef MISCSTRICT
+ if ((pmte->mte_mflags & CLASS_MASK) != CLASS_SPECIFIC)
+ panic("ldrPromoteMTE: Invalid class");
+#endif
+ ldrUnlinkMTE(pmte);
+ pmte->mte_mflags &= ~CLASS_SPECIFIC;
+ pmte->mte_mflags |= CLASS_GLOBAL;
+ ldrLinkMTE(pmte);
+}
+
+
+/***LP ldrOpenNewExe - Open module pathname and verify it's a new EXE format
+ *
+ * The specified file is opened and the old header and
+ * New EXE headers are read and verified. If New EXE header is
+ * a 16-bit module ("NE"), expand the 16-bit header to a 32-bit
+ * header. pheaderbuf is implicitly used.
+ *
+ * ENTRY pachModname - pointer to module name
+ * cb - length of module name
+ * plv - pointer to local variables on stack
+ * pfl - optional pointer to a flag set if OLD exe
+ * pBound - optional pointer to a flag set if BOUND exe
+ * pNEFlags - Flags word of the NE header
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ */
+
+int ldrOpenNewExe(pachModname, cb, plv, pfl, pBound, pNEFlags)
+PUCHAR pachModname; /* pointer to ASCII module name */
+USHORT cb; /* length of module name */
+ldrlv_t *plv; /* pointer to local variables */
+PUSHORT pfl; /* optional pointer to a flag set if OLD exe */
+PBOOLEAN pBound; /* optional pointer to a flag set if BOUND exe */
+PULONG pNEFlags; /* optional pointer to Flags word of the NE header */
+{
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER ByteOffset;
+ ULONG ulNewHdrOff; /* Offset hdr offset */
+ ULONG ulCopied; /* Number of bytes copied */
+ ULONG ulNeeded; /* Number of bytes needed */
+ ULONG usoff; /* Offset to new exe header */
+ ULONG *pl; /* pointer to a long */
+ USHORT *ps; /* pointer to a short */
+ struct e32_exe *pe32;
+ struct e32_exe *pe32temp;
+ ULONG flmte; /* flags */
+ int rc;
+ ULONG BoundAppFlag = 0L;
+ struct new_exe *ne;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrOpenNewExe() was called\n");
+ }
+#endif
+
+ flmte = 0;
+
+ if (pfl != 0)
+ *pfl = FALSE;
+
+ if (pBound != 0)
+ *pBound = FALSE;
+
+ if ((rc = ldrOpenPath(pachModname,
+ cb,
+ plv,
+ &flmte)) != NO_ERROR) {
+ plv->lv_sfn = NULL;
+ return(rc);
+ }
+
+ pe32 = (struct e32_exe *) pheaderbuf;
+ ne = (struct new_exe *) pe32;
+
+ /*
+ * Start read at beginning of file
+ */
+ ByteOffset.LowPart = 0;
+ ByteOffset.HighPart = 0;
+
+ if ((rc = NtReadFile( plv->lv_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ pe32,
+ 512,
+ &ByteOffset,
+ 0 )) != 0) {
+ NtClose(plv->lv_sfn);
+ rc = Or2MapNtStatusToOs2Error(rc, ERROR_BAD_FORMAT);
+ return(rc);
+ }
+
+ /*
+ * validate old (MZ) signature in header
+ */
+ if (((struct exe_hdr *) pe32)->e_magic != EMAGIC) {
+ NtClose(plv->lv_sfn);
+ return(ERROR_INVALID_EXE_SIGNATURE) ;
+ }
+
+ usoff = ((struct exe_hdr *) pe32)->e_lfarlc;
+
+ /*
+ * Set flag to say that it's at least a DOS app
+ */
+ if (pfl != 0) {
+ *pfl = TRUE;
+ }
+
+ /*
+ * get pointer to (NE) or (LE) exe header
+ */
+ ulNewHdrOff =
+ plv->lv_new_exe_off = ((struct exe_hdr *) pe32)->e_lfanew;
+
+ //
+ // Check if the file has the potential of being a bound
+ // app, and if so set BoundAppFlag
+ //
+
+ if (pBound != 0 &&
+ plv->lv_new_exe_off != 0x40L &&
+ ((struct exe_hdr *) pe32)->e_minalloc != 0xffff &&
+ IoStatusBlock.Information >= 0x52 &&
+ strncmp(((char *) pe32) + 0x4e, "This", 4) != 0
+ ) {
+
+ BoundAppFlag |= 0x1L;
+ }
+
+ /*
+ * check if we read at least up to the (NE) or (LE) header
+ */
+ if (ulNewHdrOff < IoStatusBlock.Information) {
+
+ /*
+ * assume we are reading a 32-bit module
+ */
+ ulNeeded = sizeof(struct e32_exe);
+ pe32temp = (struct e32_exe *) ((ULONG) pe32 + ulNewHdrOff);
+
+ if ((ulNewHdrOff < (IoStatusBlock.Information -
+ sizeof(pe32->e32_magic))) &&
+ (*(short *) (pe32temp->e32_magic) == NEMAGIC))
+ ulNeeded = sizeof(struct new_exe);
+
+ ulCopied = min(IoStatusBlock.Information - ulNewHdrOff, ulNeeded);
+
+ memcpy(pe32, (PVOID) ((ULONG) pe32 + ulNewHdrOff), ulCopied);
+
+ if (ulNeeded -= ulCopied) {
+ if ((rc = NtReadFile( plv->lv_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ (PCHAR) pe32 + ulCopied,
+ ulNeeded,
+ &ByteOffset,
+ 0 )) != 0) {
+ NtClose(plv->lv_sfn);
+ rc = Or2MapNtStatusToOs2Error(rc, ERROR_BAD_FORMAT);
+ return(rc);
+ }
+ }
+ }
+ else {
+
+ /*
+ * read in new header to size of 32-bit mte plus a ote entry
+ */
+ ByteOffset.LowPart = (ULONG)((struct exe_hdr *)pe32)->e_lfanew;
+ ByteOffset.HighPart = 0;
+
+ if ((rc = NtReadFile( plv->lv_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ (PCHAR) pe32,
+ sizeof(struct e32_exe)+sizeof(ldrote_t),
+ &ByteOffset,
+ 0 )) != 0) {
+ NtClose(plv->lv_sfn);
+ rc = Or2MapNtStatusToOs2Error(rc, ERROR_BAD_FORMAT);
+ return(rc);
+ }
+ }
+
+ /* Verify that this is a protect-mode exe. (Check this before
+ * checking MTE signature for 1.2 error code compatability.)
+ */
+ if (usoff != 0x40) {
+ NtClose(plv->lv_sfn);
+ return(ERROR_BAD_EXE_FORMAT) ;
+ }
+
+ /*
+ * validate as 16-bit signature or 32-bit signature
+ */
+ if (!(*(short *) (pe32->e32_magic) == LEMAGIC ||
+ *(short *) (pe32->e32_magic) == NEMAGIC)) {
+ NtClose(plv->lv_sfn);
+ return(ERROR_INVALID_EXE_SIGNATURE);
+ }
+
+ /*
+ * verify some header fields for LE modules only.
+ */
+ if ((*(short *) (pe32->e32_magic) == LEMAGIC) &&
+ (!((pe32->e32_bworder == E32LEWO) &&
+ (pe32->e32_os == NE_OS2)))) {
+ NtClose(plv->lv_sfn);
+ return(ERROR_INVALID_EXE_SIGNATURE);
+ }
+
+ /*
+ * This is known to be a Protect-mode app at this point.
+ */
+ if (pfl != NULL)
+ *pfl = FALSE;
+
+ /*
+ * if header in 16-bit format save ne_sssp and move ne_mflags into
+ * e32_mflags
+ */
+ if (*(short *) (pe32->e32_magic) == NEMAGIC) {
+ pl = (ULONG *) ((PCHAR) pe32 +
+ FIELDOFFSET(struct e32_exe, e32_res4));
+ *pl = ((struct new_exe *) pe32)->ne_sssp;
+ ps = (USHORT *) ((PCHAR) pe32 +
+ FIELDOFFSET(struct e32_exe, e32_mflags));
+ *ps = ((struct new_exe *)pe32)->ne_flags;
+ /*
+ * mask out those flags that are not used in the 32-bit header
+ */
+ pe32->e32_mflags &= (AUTODS_MASK | INSTLIBINIT | LDRINVALID |
+ LIBRARYMOD | E32_APPMASK | NEBOUND);
+ if (((struct new_exe *)pe32)->ne_flagsothers & NELONGNAMES)
+ pe32->e32_mflags |= MTELONGNAMES;
+ }
+ else {
+ pe32->e32_mflags |= MTELONGNAMES;
+ }
+
+ /*
+ * check if executable is a valid image
+ */
+ if (pe32->e32_mflags & LDRINVALID) {
+ NtClose(plv->lv_sfn);
+ return(ERROR_EXE_MARKED_INVALID);
+ }
+
+ /* Clear for internal use */
+ pe32->e32_mflags &= ~(MTE_MEDIAFIXED|MTE_MEDIACONTIG|MTE_MEDIA16M);
+ pe32->e32_mflags |= flmte; /* Set flags set by ldrOpenPath */
+
+ rc = ldrMungeFlags(pe32);
+ if (rc != NO_ERROR) {
+ NtClose(plv->lv_sfn);
+ return(rc);
+ }
+
+ //
+ // Figure out if this is a bound app
+ //
+
+ if (pBound != 0 &&
+ *(short *) (pe32->e32_magic) == NEMAGIC) {
+
+ if ((ne->ne_flags & NENOTP) == 0) {
+
+ if ((ne->ne_flags & NEBOUND) != 0) {
+
+ BoundAppFlag |= 0x2;
+
+ } else if ((BoundAppFlag & 0x1) != 0 &&
+ ne->ne_enttab - ne->ne_imptab != 0 &&
+ ne->ne_restab - ne->ne_rsrctab == 0) {
+
+ BoundAppFlag |= 0x2;
+ }
+ }
+
+ if ((BoundAppFlag & 0x2) != 0)
+ *pBound = TRUE;
+ }
+
+ //
+ // Get the NE file Flags word
+ //
+ if ((pNEFlags != NULL) &&
+ *(short *) (pe32->e32_magic) == NEMAGIC) {
+
+ *pNEFlags = (ULONG)ne->ne_flags;
+ if (plv->lv_class == CLASS_PROGRAM) {
+ if ((*pNEFlags & NEAPPTYP) == NENOTWINCOMPAT) {
+ CurrentThread->Process->Flags |= OS2_PROCESS_NOTWINDOWCOMPAT;
+ }
+ else if ((*pNEFlags & NEAPPTYP) == NEWINCOMPAT) {
+ CurrentThread->Process->Flags |= OS2_PROCESS_WINDOWCOMPAT;
+ }
+ else if ((*pNEFlags & NEAPPTYP) == NEWINAPI) {
+ CurrentThread->Process->Flags |= OS2_PROCESS_WINDOWAPI;
+ }
+ }
+ }
+
+ //
+ // Verify number of segments in the NE header
+ //
+ if (*(short *) (pe32->e32_magic) == NEMAGIC) {
+ if ((USHORT)(ne->ne_cseg * (USHORT)sizeof(struct new_seg)) >
+ ((USHORT)ne->ne_rsrctab - (USHORT)ne->ne_segtab)) {
+#if DBG
+ DbgPrint("ne_cseg 0x%x\n", (USHORT)ne->ne_cseg);
+ DbgPrint("ne_cmod 0x%x\n", (USHORT)ne->ne_cmod);
+ DbgPrint("ne_cbnrestab 0x%x\n", (USHORT)ne->ne_cbnrestab);
+ DbgPrint("ne_segtab 0x%x\n", (USHORT)ne->ne_segtab);
+ DbgPrint("ne_rsrctab 0x%x\n", (USHORT)ne->ne_rsrctab);
+ DbgPrint("ne_restab 0x%x\n", (USHORT)ne->ne_restab);
+ DbgPrint("ne_modtab 0x%x\n", (USHORT)ne->ne_modtab);
+#endif
+ NtClose(plv->lv_sfn);
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+ }
+ return(NO_ERROR);
+}
+
+/***LP ldrOpenPath - Open module file, possibly searching LIBPATH
+ *
+ * ldrOpenPath opens the file for the module, given the module name.
+ *
+ * The names passed for CLASS_GLOBAL must not contain a drive,
+ * path, or extension. For program modules, the name must contain
+ * the desired null terminated relative path. If IsIFS, the LIBPATH
+ * name is ignored.
+ *
+ * ldrOpenPath(pchModname, cchModname, plv, pflmte)
+ *
+ * ENTRY pachModname - pointer to module name
+ * cb - module name length
+ * plv - pointer to local variables
+ * pflmte - pointer to mte flags to return
+ * piostatus - pointer to IO stat buffer
+ *
+ * EXIT none - return successful or call load_error
+ *
+ */
+
+int ldrOpenPath(pachModname, cb, plv, pflmte)
+PUCHAR pachModname; /* pointer to ASCII module name */
+USHORT cb; /* length of module name */
+ldrlv_t *plv; /* pointer to local variables */
+PULONG pflmte; /* pointer to return mte flags in */
+
+{
+
+ HANDLE File;
+ STRING name;
+ UNICODE_STRING name_U;
+ NTSTATUS Status;
+ PSTRING pname = &name;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PUCHAR pstring;
+ PUCHAR ptmp;
+ ULONG cbstring;
+ PUCHAR plibpath;
+ int rc; /* return code */
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrOpenPath() was called with modname=%.*s\n", cb, pachModname);
+ }
+#endif
+
+ if (plv->lv_class == CLASS_GLOBAL) {
+ plibpath = ldrpLibPath;
+ }
+ else {
+ LdrBuf[0] = '\0'; // This causes the try_another loop to exit
+ plibpath = LdrBuf; // after the first try
+ }
+
+ do {
+ if (plv->lv_class == CLASS_GLOBAL) {
+ ptmp = (PUCHAR)strchr(plibpath, ';');
+ if (ptmp == NULL)
+ cbstring = strlen(plibpath);
+ else
+ cbstring = ptmp - plibpath;
+ memcpy(LdrBuf, plibpath, cbstring);
+ plibpath += cbstring;
+ pstring = &LdrBuf[cbstring];
+ if (*(pstring - 1) != '\\') { // prevent double backslash in \OS2SS\DRIVES\C:\ cases
+ *pstring++ = '\\';
+ }
+ memcpy(pstring, pachModname, cb);
+ pstring += cb;
+ if (pflmte != NULL) {
+ memcpy(pstring, ".DLL\0", 5);
+ }
+ else {
+ *pstring = '\0';
+ }
+ pstring = LdrBuf;
+ }
+ else {
+ pstring = pachModname;
+ }
+
+ RtlInitAnsiString(pname, pstring);
+
+ //
+ // UNICODE conversion -
+ //
+ Status = RtlOemStringToUnicodeString(
+ &name_U,
+ pname,
+ TRUE);
+ ASSERT (NT_SUCCESS(Status));
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ &name_U,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ Status = NtOpenFile(&File,
+ GENERIC_READ | FILE_READ_DATA | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_NON_DIRECTORY_FILE |
+ FILE_SYNCHRONOUS_IO_NONALERT);
+
+ RtlFreeUnicodeString (&name_U);
+ if (NT_SUCCESS(Status) && (plv->lv_class != CLASS_GLOBAL)) {
+ strncpy(&LdrBuf[0], name.Buffer, name.Length);
+ LdrBuf[name.Length] = '\0';
+ }
+
+ if (NT_SUCCESS(Status)) { // Avoid switch in the NO_ERROR case.
+ plv->lv_sfn = File;
+ return(NO_ERROR);
+ }
+
+ rc = ERROR_FILE_NOT_FOUND; // Assume end of LibPath
+ } while (*plibpath++ != '\0');
+
+ //
+ // Test if the error code should be
+ // ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND or ERROR_INVALID_DRIVE
+ // by trying to open the directory path for SPECIFIC modules
+ //
+ if (plv->lv_class == CLASS_SPECIFIC) {
+ memcpy(LdrBuf, pachModname, cb);
+ LdrBuf[cb] = '\0';
+ ptmp = strrchr(LdrBuf, '\\');
+ if (ptmp == NULL) {
+ return(rc);
+ }
+ *ptmp = '\0';
+
+ RtlInitAnsiString(pname, LdrBuf);
+
+ //
+ // UNICODE conversion -
+ //
+ Status = RtlOemStringToUnicodeString(
+ &name_U,
+ pname,
+ TRUE);
+ if (!NT_SUCCESS(Status)) {
+ return(rc);
+ }
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ &name_U,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ Status = NtOpenFile(&File,
+ GENERIC_READ | FILE_READ_DATA | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_DIRECTORY_FILE |
+ FILE_SYNCHRONOUS_IO_NONALERT);
+
+ RtlFreeUnicodeString (&name_U);
+ if (NT_SUCCESS(Status)) {
+ NtClose(File);
+ return(rc);
+ }
+ else {
+ rc = ERROR_PATH_NOT_FOUND;
+ }
+ //
+ // Now differentiate between
+ // ERROR_PATH_NOT_FOUND and ERROR_INVALID_DRIVE
+ //
+ ptmp = strchr(LdrBuf, ':');
+ if (ptmp == NULL) {
+ return(rc);
+ }
+ ptmp++; // point to the \ after the drive name
+ if (*ptmp != '\\') {
+ return(rc);
+ }
+ ptmp++;
+ *ptmp = '\0';
+
+ RtlInitAnsiString(pname, LdrBuf);
+
+ //
+ // UNICODE conversion -
+ //
+ Status = RtlOemStringToUnicodeString(
+ &name_U,
+ pname,
+ TRUE);
+ if (!NT_SUCCESS(Status)) {
+ return(rc);
+ }
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ &name_U,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ Status = NtOpenFile(&File,
+ GENERIC_READ | FILE_READ_DATA | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_DIRECTORY_FILE |
+ FILE_SYNCHRONOUS_IO_NONALERT);
+
+ RtlFreeUnicodeString (&name_U);
+ if (NT_SUCCESS(Status)) {
+ NtClose(File);
+ return(rc);
+ }
+ else {
+ rc = ERROR_INVALID_DRIVE;
+ }
+ }
+ return(rc);
+}
+
+#pragma optimize("", off)
+/***LP ldrMungeFlags - Translate Module flags to internal flags
+ *
+ * Translate the module info in the EXE header to the internal
+ * format.
+ *
+ * ENTRY pe32 Pointer to the linker EXE image
+ *
+ * EXIT NO_ERROR
+ * ERROR_BAD_EXE_FORMAT, if the module type is garbage
+ */
+int ldrMungeFlags(pe32)
+register struct e32_exe *pe32;
+{
+ register int modtype;
+
+ modtype = pe32->e32_mflags & E32_MODMASK;
+ pe32->e32_mflags &= ~E32_MODMASK;
+
+ switch (modtype) {
+
+ case E32_MODEXE:
+ break;
+
+ case E32_MODDLL:
+ pe32->e32_mflags |= LIBRARYMOD;
+ break;
+
+ case E32_MODPDEV:
+ pe32->e32_mflags |= DEVDRVMOD | LIBRARYMOD;
+ break;
+
+ /* BUGBUG: JH - The following case is to overcome a LINK386 bug
+ which turns on the PROTMOD bit if loaddses is used */
+ case E32_MODVDEV:
+ pe32->e32_mflags |= VDDMOD | LIBRARYMOD;
+ break;
+
+ default:
+ return (ERROR_BAD_EXE_FORMAT);
+ }
+ return (NO_ERROR);
+}
+#pragma optimize("", on)
+
+
+/***LP ldrCreateMte - allocate and load module table entry
+ *
+ * This routine loads and initializes a module table entry. Memory
+ * is allocated for the file module data with additional
+ * space for module handles and the module
+ * pathname. Segment handle and selector fields are added to the
+ * end of each segment table entry for 16-bit modules. The module
+ * reference strings are checked to make sure there are no wild pointers
+ * that would cause a gp fault. The resident name table is checked to
+ * make sure that it can be scanned without causing a gp fault.
+ *
+ * If the module that is being loaded is a 16-bit module the 16-bit
+ * exe header was expanded into a 32-bit exe header when file
+ * was opened.
+ *
+ * ENTRY pe32 - pointer to link exe image
+ * plv - pointer to local variables
+ * - ptda and search buff are setup
+ *
+ * EXIT none - return successful or call load_error
+ */
+
+APIRET ldrCreateMte(pe32, plv)
+struct e32_exe *pe32; /* pointer to linker exe image */
+register ldrlv_t *plv; /* pointer to local variables */
+
+{
+ldrmte_t *pmte = NULL; /* pointer to loader MTE */
+ldrsmte_t *psmte = NULL; /* pointer to swappable loader MTE */
+struct ImpHdr *piat = NULL; /* pointer to iat memory */
+int rc;
+ULONG csmte; /* size of swappable MTE */
+ULONG mte_16_32_constant; /* adjustment constant for ptrs */
+ULONG cbpathlen; /* length of pathname in TempBuf */
+USHORT hobmte = 0; /* MTE pseudo handle */
+ULONG lobjnum; /* object number count */
+ldrste_t *pste; /* pointer to segment table entry */
+ldrote_t *pote; /* pointer to object table entry */
+ldrote_t *poteiat = NULL; /* pointer to ote for IAT */
+ldrote_t *potersrc = NULL; /* pointer to ote for resource dir */
+ldrrsrcinfo_t *prsrcinfo;
+ULONG cbfile; /* Amount of data for seg in file */
+ULONG cbseg; /* Size of segment */
+ULONG *pdst; /* used to copy MTE */
+//VMAC ac; /* buffer for VMReserve */
+ULONG cimpmod; /* count of import modules */
+ULONG cpad;
+PCHAR pac;
+UCHAR length;
+struct ExpHdr *pexp; /* pointer to export dircetory */
+struct ImpHdr *pimpdir; /* pointer to import directory */
+struct ImpHdr *pprevimpdir; /* pointer to import directory */
+ULONG vsize = 0; /* virtaul size of module */
+ULONG lsize;
+ULONG lfixtab;
+ULONG cpages = 1; /* count of pages in module */
+ULONG lconstant;
+ULONG lcount;
+ULONG cbiat = 0; /* size of IAT */
+ULONG cbrsrc = 0;
+ULONG iataddr;
+USHORT i;
+IO_STATUS_BLOCK IoStatusBlock;
+LARGE_INTEGER ByteOffset;
+
+#define MAXRESMOD 33
+
+/***ET+ mte_alloc - memory allocation for resident MTE section
+ *
+ * pe32 - Pointer to memory for resident MTE.
+ *
+ * The MTE consists of two parts the MTE pointers section and the table
+ * section. The pointer section is allocated in two parts the resident
+ * section and the swappable section. The table section of the mte is
+ * also allocated from the swappable heap.
+ *
+ * The first section of the pointer section allocated from the resident
+ * heap will also contain the module name and the pointers to the import
+ * modules.
+ * The second section of the pointer section is allocated from the swappable
+ * heap, also attached to this heap object will be the loader's table
+ * sections. The loader's table section will contain space for the pathname,
+ * object table, loader info and the fixup table.
+ *
+ *
+ * Memory resident object Resident heap object
+ * pe32->+----------------+ -+ Copy ->+----------------+<-pmte
+ * | Linker EXE info| |------------| | MTE pointers |
+ * +----------------+ -+ | ->|----------------|
+ * | | Module name |
+ * | +----------------+
+ * | |Space for Modptr|
+ * | +----------------+
+ * |
+ * | Swappable heap object
+ * | +----------------+<-psmte
+ * +-------->| MTE pointers |
+ * +----------------+
+ * |Space for pathnm|
+ * +----------------+
+ * | Object table |
+ * |or segment table|
+ * +----------------+
+ * | Export Section |
+ * +----------------+
+ * | Import Section |
+ * +----------------+
+ * | Fixup Records |
+ * +----------------+
+ */
+/*end*/
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrCreateMte() was called\n");
+ }
+#endif
+
+ /*
+ * allocate memory for MTE from resident heap
+ */
+
+ /*
+ * Compute size of resident heap object to hold resident loader MTE.
+ * The size is madeup of:
+ * size of resident MTE struct
+ * 4 bytes * number of import module - to hold pointers to MTEs
+ * 9 bytes to hold max module name plus a null this will avoid
+ * the realloc needed because we do not know the length of the
+ * string till we read the rest of the header
+ */
+
+ /*
+ * Set import module count
+ */
+ cimpmod = (*(short *) (pe32->e32_magic) == LEMAGIC ?
+ ((pe32->e32_unit[IMP].size > 0) ?
+ (pe32->e32_unit[IMP].size / IMPHDR_SIZE) - 1 : 0) :
+ (ulong_t) ((struct new_exe *) pe32)->ne_cmod);
+ if ((pmte = (ldrmte_t *) RtlAllocateHeap(LDRNEHeap, HEAP_ZERO_MEMORY, sizeof(ldrmte_t)
+ + (4 * cimpmod) + MAXRESMOD)) == NULL) {
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto createerror;
+ }
+
+ /*
+ * Copy fields from the Linker EXE image to the loader MTE allocated
+ * from the resident heap.
+ */
+ pdst = (ulong_t *) pmte;
+
+ for(i = 0; ExeToResMTETbl[i].offset != ENDMTETBL; i++) {
+
+ if (ExeToResMTETbl[i].offset == (USHORT) SKIPCOPY)
+ *pdst++ = 0;
+ else {
+ /*
+ * fetch word value from 16-bit linker EXE image and place in
+ * loader mte
+ */
+ *pdst++ = *(ulong_t *) ((ulong_t) pe32 +
+ (ulong_t) ExeToResMTETbl[i].offset);
+ }
+ }
+
+ /*
+ * Setup fields in resident MTE
+ */
+
+ pmte->mte_usecnt = 0; /* clear out e32_bworder */
+ pmte->mte_dldchain = NULL;
+
+ /*
+ * Initialize MTE Flags
+ */
+ pmte->mte_mflags |= plv->lv_class;
+ if (plv->lv_type == EXT_DEVICE) /* is this a device driver module? */
+ pmte->mte_mflags |= DEVDRVMOD;
+ else if (plv->lv_type == EXT_FSD) { /* or is it an FSD module */
+ pmte->mte_mflags |= FSDMOD;
+
+ /*
+ * force all segments to swappable
+ */
+ pmte->mte_mflags &= ~MTE_MEDIAFIXED;
+ }
+
+ pmte->mte_mflags &= ~MTE_INTNL_MASK; /* Clear internal flags */
+
+ /*
+ * allocate memory for swappable heap object for loader tables
+ */
+
+ /*
+ * Round pathname up to a Dword
+ */
+ cbpathlen = ((strlen(LdrBuf) + 4) & ~3);
+
+ /*
+ * compute size of swappable heap object which is madeup of the
+ * swappable MTE pointers, the pathname, import, export and fixup
+ * sections.
+ */
+ if (ldrIsLE(pmte)) {
+ cpad = 0;
+ csmte = pe32->e32_hdrsize - (plv->lv_new_exe_off +
+ sizeof(struct e32_exe));
+ if (pe32->e32_unit[RES].rva != 0) {
+ cbrsrc = pe32->e32_unit[RES].size +
+ (pe32->e32_rescnt * sizeof(ldrrsrc32_t));
+ csmte += cbrsrc;
+ }
+ }
+ else {
+ /*
+ * Compute size of 16-bit loader tables also add space for
+ * expanded segment table for 16-bit modules
+ */
+ cpad = ((struct new_exe *)pe32)->ne_cseg * (sizeof(ldrste_t) -
+ sizeof(struct new_seg));
+ csmte = (ulong_t) (((struct new_exe *) pe32)->ne_cbenttab +
+ (((struct new_exe *) pe32)->ne_enttab -
+ sizeof(struct new_exe))) + cpad;
+
+ }
+ csmte += sizeof(ldrsmte_t) + cbpathlen;
+
+ /*
+ * allocate memory for swappable MTE from swappable heap
+ */
+ if ((psmte = (ldrsmte_t *) RtlAllocateHeap(LDRNEHeap, HEAP_ZERO_MEMORY, csmte)) == 0) {
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto createerror;
+ }
+
+ /*
+ * Copy fields from the Linker EXE image to the loader swappable MTE
+ * pointers.
+ */
+ pdst = (ulong_t *) psmte;
+
+ if (ldrIsLE(pmte)) {
+
+ for (i = 0; ExeTo32SwapMTETbl[i].offset != ENDMTETBL; i++) {
+
+ if (ExeTo32SwapMTETbl[i].offset == (USHORT) SKIPCOPY)
+ *pdst++ = 0;
+ else {
+ /*
+ * fetch value from linker EXE image and place in loader
+ * mte
+ */
+ *pdst++ = *(ulong_t *) ((ulong_t) pe32 +
+ (ulong_t) ExeTo32SwapMTETbl[i].offset);
+ }
+ }
+ }
+ else {
+ for (i = 0; ExeTo16SwapMTETbl[i].offset != ENDMTETBL; i++) {
+
+ if (ExeTo16SwapMTETbl[i].offset == (USHORT) SKIPCOPY)
+ *pdst++ = 0;
+ else {
+ /*
+ * fetch value from linker EXE image and place in loader
+ * mte
+ */
+ *pdst++ = (*(ulong_t *) ((ulong_t) pe32 +
+ (ulong_t) ExeTo16SwapMTETbl[i].offset)) &
+ WORDMASK;
+ }
+ }
+ psmte->smte_cbnrestab = ((struct new_exe *)pe32)->ne_cbnrestab;
+ psmte->smte_NEflagsothers =
+ ((struct new_exe *)pe32)->ne_flagsothers;
+ psmte->smte_NEexpver =
+ (USHORT) (((struct new_exe *)pe32)->ne_res[6]);
+ }
+ pmte->mte_swapmte = psmte;
+
+/*
+ * Read the data into the swappable part of the MTE which contains the
+ * object table, Export section and Import section.
+ *
+ *
+ * Swappable heap object
+ * +----------------+<-psmte
+ * | MTE pointers |
+ * |----------------|
+ * |Space for pathnm|
+ * --->|----------------|
+ * cpad-->| | 16-bit pad for |
+ * | | expand for seg |
+ * | | table |
+ * --->|----------------|<-start read here
+ * | Object table |
+ * | or segment tbl|
+ * |----------------|
+ * | Export Section |
+ * |----------------|
+ * | Import Section |
+ * |----------------|
+ * | Fixup records |
+ * +----------------+
+ */
+
+ lconstant = (ulong_t) psmte + sizeof(ldrsmte_t) + cpad + cbpathlen;
+ ByteOffset.LowPart = ldrIsNE(pmte) ? psmte->smte_objtab +
+ plv->lv_new_exe_off :
+ psmte->smte_objtab;
+ ByteOffset.HighPart = 0;
+
+ if ((rc = NtReadFile( plv->lv_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ (PCHAR) lconstant,
+ csmte - (sizeof(ldrsmte_t)+cbpathlen) - cpad -
+ cbrsrc,
+ &ByteOffset,
+ 0 )) != 0) {
+ rc = Or2MapNtStatusToOs2Error(rc, ERROR_ACCESS_DENIED);
+ goto createerror;
+ }
+
+ /*
+ * An adjustment constant has to be added to pointers in MTE. The
+ * pointers in MTE are relative to the beginning of the MTE header.
+ * Since space has been added between the header and the tables,
+ * the pointers need to be updated by a constant.
+ */
+ mte_16_32_constant = lconstant - psmte->smte_objtab;
+
+ psmte->smte_objtab = lconstant - cpad;
+
+ /*
+ * check that ptrs in MTE are valid
+ */
+ if ((rc = ldrMTEValidatePtrs(pmte, csmte + (ulong_t) psmte,
+ mte_16_32_constant)) != NO_ERROR) {
+ goto createerror;
+ }
+
+ if (cbrsrc != 0) {
+ /*
+ * Set first dword of space used to convert resource table
+ * to ENDMTETBL to indicate that the table has not been
+ * converted. The table will be convert for each module
+ * when the first resource is gotten.
+ */
+ psmte->smte_rsrccnt = pe32->e32_rescnt;
+ psmte->smte_rsrctab = (ulong_t) psmte + (csmte - cbrsrc);
+ prsrcinfo = (ldrrsrcinfo_t *) psmte->smte_rsrctab;
+ prsrcinfo->ldrrsrcinfo_flag = ENDMTETBL;
+
+ /*
+ * Also save the resource directory size and pote and the
+ * size of the iat and object page map.
+ */
+ prsrcinfo->ldrrsrcinfo_size = pe32->e32_unit[RES].size;
+ prsrcinfo->ldrrsrcinfo_iatsize = csmte - cbrsrc;
+ pote = (ldrote_t *) psmte->smte_objtab;
+ for (lobjnum = 0; lobjnum < psmte->smte_objcnt;lobjnum++,pote++) {
+ if (pe32->e32_unit[RES].rva >= pote->ote_base &&
+ pe32->e32_unit[RES].rva < pote->ote_base + pote->ote_psize)
+ break;
+ }
+ if (lobjnum == psmte->smte_objcnt) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ }
+
+ prsrcinfo->ldrrsrcinfo_pote = (ulong_t) pote;
+
+ }
+
+ /*
+ * Reallocate resident heap space for MTE to include module name.
+ * We will copy the module entry in the export name table since this
+ * table is in the swappable heap. The module name for 32-bit modules
+ * is found by a pointer in the export directory table. For 16-bit
+ * modules it is the first entry in the resident name table
+ */
+ if (ldrIsLE(pmte)) {
+ pexp = (struct ExpHdr *) psmte->smte_expdir;
+ pac = (PCHAR) (psmte->smte_expdir + pexp->exp_dllname);
+ length = (UCHAR) (strlen(pac) + 1);
+ }
+ else {
+ pac = (PCHAR) psmte->smte_restab;
+ length = *((PCHAR) psmte->smte_restab) + (UCHAR) 1;
+ }
+ if (length > MAXRESMOD) {
+ rc = ERROR_BAD_FORMAT;
+ goto createerror;
+ }
+ plv->lv_pmte = pmte;
+
+ /*
+ * Setup import module pointer table
+ */
+ pmte->mte_modptrs = (ulong_t) ((PCHAR) pmte + sizeof(ldrmte_t));
+ pmte->mte_impmodcnt = cimpmod;
+ if (pmte->mte_impmodcnt > 0) {
+ memset((void *) pmte->mte_modptrs, '\0',
+ pmte->mte_impmodcnt << 2);
+ }
+
+ /*
+ * create a handle to use
+ */
+ if ((rc = Allocate16BHandle((PUSHORT) &hobmte,
+ (ULONG) pmte)) != NO_ERROR) {
+ goto createerror;
+ }
+
+ plv->lv_hobmte = pmte->mte_handle = hobmte;
+
+ pmte->mte_modname = (ULONG) pmte + sizeof(ldrmte_t) + (4 * cimpmod);
+
+ /*
+ * copy module name into resident MTE resident heap object for 32-bit
+ * modules place length byte before string.
+ */
+ memcpy((ldrIsLE(pmte) ? (PCHAR) pmte->mte_modname + 1 :
+ (PCHAR) pmte->mte_modname),
+ pac,
+ (ldrIsLE(pmte) ? length - 1 : length));
+
+ if (ldrIsLE(pmte))
+ *((PCHAR) pmte->mte_modname) = length - (uchar_t) 1;
+
+ /*
+ * upper case module name
+ */
+ ldrUCaseString((PCHAR) pmte->mte_modname + 1,
+ *((PCHAR) pmte->mte_modname));
+
+ /*
+ * Set size of pathname (not including terminating NUL).
+ */
+ cbpathlen =
+ psmte->smte_pathlen = (USHORT) strlen(LdrBuf);
+ cbpathlen++;
+
+ /*
+ * copy pathname from TempBuf into MTE
+ */
+ psmte->smte_path = (ulong_t) psmte + sizeof(ldrsmte_t);
+ memcpy((void *) psmte->smte_path, &LdrBuf, cbpathlen);
+
+ /*
+ * Upper case pathname
+ */
+ ldrUCaseString((PCHAR) psmte->smte_path, cbpathlen - 1);
+
+ if (ldrIsNE(pmte) ||
+ (plv->lv_type != EXT_PROGRAM && !(ldrIsLE(pmte)))) {
+ /*
+ * zero init call gate selector value in entry table for all
+ * objects.
+ */
+ if ((rc = ldrEachObjEntry(0, pmte, ldrInitEntry, 0)) != NO_ERROR){
+ goto createerror;
+ }
+ }
+
+ if (ldrIsNE(pmte)) {
+
+ /*
+ * Save size of swappable mte in mte_fpagetab so
+ * the debugger command .lm <addr> works for 16-bit modules
+ */
+ psmte->smte_fpagetab = csmte;
+
+ /*
+ * expand segments by adding a handle and selector field
+ * after each segment table entry
+ */
+ ldrExpandSegment(pmte, plv->lv_type);
+
+ /*
+ * Check for porthole modules
+ */
+ if ((psmte->smte_NEexetype == 2) || (psmte->smte_NEexetype == 0 &&
+ ((psmte->smte_NEexpver & 0xff00) == 0x200 ||
+ (psmte->smte_NEexpver & 0xff00) == 0x300)))
+ pmte->mte_mflags |= MTEPORTHOLE;
+ else
+ pmte->mte_mflags &= ~MTEPORTHOLE;
+
+ /*
+ * check for program modules
+ */
+ if (plv->lv_type == EXT_PROGRAM) {
+
+ /*
+ * Validate start segment
+ */
+ if (psmte->smte_startobj == 0 ||
+ ldrNumToSte(pmte, psmte->smte_startobj) == 0) {
+ rc = ERROR_INVALID_STARTING_CODESEG;
+ goto createerror;
+ }
+
+ /*
+ * Validate stack segment
+ */
+ if (psmte->smte_stackobj == 0 ||
+ (pste = ldrNumToSte(pmte, psmte->smte_stackobj)) == 0 ||
+ pste->ste_flags & STE_SHARED) {
+ rc = ERROR_INVALID_STACKSEG;
+ goto createerror;
+ }
+
+ /*
+ * Validate auto data segment
+ */
+ if (psmte->smte_autods != 0 &&
+ ldrNumToSte(pmte, psmte->smte_autods) == 0) {
+ rc = ERROR_INVALID_STARTING_CODESEG;
+ goto createerror;
+ }
+
+ /*
+ * if SS = DS and SP = 0
+ */
+ if (psmte->smte_stackobj == psmte->smte_autods &&
+ psmte->smte_esp == 0) {
+
+ /*
+ * Set SP to top of auto data segment just below
+ * the additional heap
+ */
+ psmte->smte_esp = RESIZE64K(pste->ste_minsiz) +
+ psmte->smte_stacksize;
+ }
+
+ } /* end if for EXT_PROGRAM */
+ else if (psmte->smte_startobj == 0) {
+ /*
+ * DLL has no init routine: mark it as global
+ * complete. This way libinit will not bother about
+ * it. Also clear instance libinit bit as linker can
+ * turn this on even without an init routine; this
+ * should be an error, but is not for compatibility
+ * reasons.
+ */
+ pmte->mte_mflags |= GINISETUP | GINIDONE;
+ pmte->mte_mflags &= ~INSTLIBINIT;
+ }
+ else {
+ /*
+ * if SS = DS and SP = 0 (this is a dll, so ignore the case
+ * where SS = DS = 0).
+ */
+ if (psmte->smte_stackobj == psmte->smte_autods &&
+ psmte->smte_stackobj != 0 &&
+ psmte->smte_esp == 0) {
+
+ /*
+ * Validate stack segment
+ */
+ if ((pste = ldrNumToSte(pmte, psmte->smte_stackobj)) == 0 ||
+ pste->ste_flags & STE_SHARED) {
+ rc = ERROR_INVALID_STACKSEG;
+ goto createerror;
+ }
+
+ /*
+ * Set SP to top of auto data segment just below
+ * the additional heap
+ */
+ psmte->smte_esp = RESIZE64K(pste->ste_minsiz) +
+ psmte->smte_stacksize;
+ }
+ }
+ } /* end if for NE module */
+ else { /* 32-bit module */
+
+ struct FmtDir *pfmtdir;
+ struct ComDir *pcomdir;
+
+ /*
+ * Make sure that pointers are zero if size in header is zero
+ */
+ if ((pe32->e32_unit[EXP].size == 0 &&
+ psmte->smte_expdir != 0) ||
+ (pe32->e32_unit[IMP].size == 0 && psmte->smte_impdir != 0) ||
+ (pe32->e32_unit[RES].size == 0 && psmte->smte_rsrctab != 0) ||
+ (pe32->e32_unit[FIX].size == 0 && psmte->smte_fixtab != 0) ||
+ (pe32->e32_unit[DEB].size == 0 &&
+ psmte->smte_debuginfo != 0)) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto createerror;
+ }
+
+ psmte->smte_fixupsize = pe32->e32_unit[FIX].size;
+
+ /*
+ * Check for wild pointers in names ptr table
+ */
+ for (lcount = 0; lcount < pexp->exp_namecnt; lcount++) {
+ pac = (uchar_t *) (*(ulong_t *)
+ (pexp->exp_name + (lcount * sizeof(ulong_t)) +
+ (ulong_t) pexp) + (ulong_t) pexp);
+ lconstant = strlen(pac) + 1;
+ if (psmte + lconstant > psmte + csmte) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto createerror;
+ }
+ }
+
+ pimpdir = (struct ImpHdr *) psmte->smte_impdir;
+
+ /*
+ * Remove info from module directives table:
+ * For module with 16-bit code get stack object & auto ds.
+ * Get count of resources for this module.
+ */
+ if (pe32->e32_dircnt != 0) {
+ pfmtdir = (struct FmtDir *) (pe32->e32_dirtab +
+ mte_16_32_constant);
+ for (lcount = 0; lcount < pe32->e32_dircnt; lcount++,
+ pfmtdir++) {
+
+ if ((ulong_t) pfmtdir >
+ psmte->smte_objtab + csmte) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ }
+
+ switch (pfmtdir->dir) {
+
+ case OS2LDR16:
+ if (pfmtdir->length != sizeof(struct ComDir)) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto createerror;
+ }
+ pcomdir = (struct ComDir *) (pe32->e32_dirtab +
+ mte_16_32_constant +
+ pfmtdir->offset);
+ if ((ulong_t) pcomdir >
+ psmte->smte_objtab + csmte) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto createerror;
+ }
+ psmte->smte_autods = pcomdir->autods;
+ psmte->smte_stackobj = pcomdir->stackobj;
+ break;
+
+// LTS - 1/16/91
+// Moved count back to header
+
+ case OS2RSRCNT:
+// prsrccnt = (ulong_t *) (pe32->e32_dirtab +
+// mte_16_32_constant +
+// pfmtdir->offset);
+// if ((ulong_t) prsrccnt >
+// psmte->smte_objtab + csmte) {
+// rc = ERROR_BAD_EXE_FORMAT;
+// goto createerror;
+// }
+ break;
+
+ case OS2FIXMAP:
+ psmte->smte_fpagetab = pfmtdir->offset +
+ pe32->e32_dirtab +
+ mte_16_32_constant;
+ psmte->smte_mpages = pfmtdir->length /
+ sizeof(ulong_t);
+ for (lfixtab = 0; lfixtab < psmte->smte_mpages;
+ lfixtab++) {
+ lsize =
+ ((ulong_t *) psmte->smte_fpagetab)[lfixtab];
+ /*
+ * check if any fixups exist
+ */
+ if (lsize == 0xffffffff)
+ continue;
+ lsize += psmte->smte_fixtab;
+ if (lsize > psmte->smte_fixtab +
+ pe32->e32_unit[FIX].size) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto createerror;
+ }
+ else {
+ ((ulong_t *) psmte->smte_fpagetab)[lfixtab] =
+ lsize;
+ }
+ }
+ break;
+
+ default:
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto createerror;
+ }
+ }
+ }
+
+ if (plv->lv_type == EXT_PROGRAM) {
+
+ /*
+ * Init call gate value for Exec's
+ */
+ ldrInitCallGate = 0;
+ /*
+ * Validate stack
+ */
+ if (psmte->smte_stackobj <= psmte->smte_objcnt) {
+ pote =
+ &((ldrote_t *)psmte->smte_objtab)[psmte->smte_stackobj-1];
+ pote->ote_vsize += psmte->smte_stackinit;
+ }
+ else {
+ rc = ERROR_INVALID_STACKSEG;
+ goto createerror;
+ }
+
+ /*
+ * Validate starting code object
+ */
+ if (psmte->smte_eip == 0) {
+ rc = ERROR_INVALID_STARTING_CODESEG;
+ goto createerror;
+ }
+ }
+ else { /* Else some flavor of DLL */
+ /*
+ * For 32-bit DLLs, fail the load if
+ *
+ * A. The specified starting address is bad, or
+ * B. no starting object is specified, but either
+ * instance DLL initialization or instance DLL
+ * termination is requested, or
+ * C. instance DLL termination is requested, but the
+ * the starting object is 16-bit.
+ */
+ pote = (ldrote_t *) psmte->smte_objtab;
+ for (lobjnum = 0; lobjnum < psmte->smte_objcnt; lobjnum++,
+ pote++) {
+
+ if ((psmte->smte_eip > pote->ote_base) &&
+ (psmte->smte_eip < (pote->ote_base + pote->ote_psize)))
+ break;
+ if (lobjnum == psmte->smte_objcnt) {
+ rc = ERROR_INVALID_STARTING_CODESEG;
+ goto createerror;
+ }
+ }
+
+ if ((psmte->smte_eip == 0 &&
+ (pmte->mte_mflags & (MTEDLLTERM | INSTLIBINIT))) ||
+ ((pmte->mte_mflags & MTEDLLTERM) &&
+ !(pote->ote_flags & OBJ_BIGDEF))) {
+ rc = ERROR_INVALID_STARTING_CODESEG;
+ goto createerror;
+ }
+ if (psmte->smte_eip == 0)
+ pmte->mte_mflags |= GINISETUP | GINIDONE;
+ /* Fake global initialization done */
+ }
+ }
+
+ /*
+ * Check each segment or object in module
+ */
+ for (lobjnum = 0; lobjnum < psmte->smte_objcnt; lobjnum++) {
+
+ if (ldrIsNE(pmte)) {
+ pste = &((ldrste_t *) psmte->smte_objtab)[lobjnum];
+
+ /*
+ * Check that the amount of data in the file does
+ * not exceed the size of the segment.
+ */
+ if ((cbseg = pste->ste_minsiz) == 0)
+ cbseg = _64K; /* Get size of segment */
+ if ((cbfile = pste->ste_size) == 0 && pste->ste_offset != 0)
+ cbfile = _64K; /* Get amount of data in file */
+ if (cbfile > cbseg) {
+ /* Error if file size > segment size */
+ rc = ERROR_INVALID_MINALLOCSIZE;
+ goto createerror;
+ }
+
+ /*
+ * Check for auto data segment. If found, add in stack
+ * and heap sizes and store in ste entry and check for
+ * overflow
+ */
+ if (lobjnum + 1 == psmte->smte_autods) {
+ if ((cbseg += psmte->smte_heapsize +
+ psmte->smte_stacksize) > _64K) {
+ rc = ERROR_AUTODATASEG_EXCEEDS_64k;
+ goto createerror;
+ }
+ }
+ pste->ste_minsiz = (USHORT) cbseg;
+ }
+ /* 32-bit module */
+ else {
+ pote = &((ldrote_t *) psmte->smte_objtab)[lobjnum];
+
+ /*
+ * Check if IAT in this object
+ */
+ if (pimpdir != NULL &&
+ pimpdir->imp_address >= pote->ote_base &&
+ pimpdir->imp_address < pote->ote_base + pote->ote_psize) {
+
+ /*
+ * Save object table pointer to iat
+ */
+ poteiat = pote;
+ }
+
+ /*
+ * Check for auto data object. If found, add heap size
+ * to virtual size of object. If virtual size > 64k
+ * and this is USE16 object goto error.
+ */
+ if (lobjnum + 1 == psmte->smte_autods &&
+ (pote->ote_vsize += psmte->smte_heapsize) > _64K &&
+ !(pote->ote_flags & OBJ_BIGDEF)) {
+ rc = ERROR_AUTODATASEG_EXCEEDS_64k;
+ goto createerror;
+ }
+
+ /*
+ * 1/24/91 - LTS
+ * If we are to preload resources set the object flag
+ * preload. This only has meaning for resources not
+ * for any other objects.
+ */
+ if (pote->ote_flags & OBJ_RSRC) {
+ if (!(pmte->mte_mflags & MTE_MEDIAFIXED))
+ pote->ote_flags |= OBJ_PRELOAD;
+ }
+
+ if (!(pote->ote_flags & OBJ_DEBUG)) {
+ vsize += ((pote->ote_vsize + (_64K - 1)) / _64K) * _64K;
+ cpages += (pote->ote_vsize + PAGEMASK) / PAGESIZE;
+ }
+
+ if (pote->ote_flags & OBJ_DEBUG) {
+ pote->ote_base =
+ pote->ote_selector =
+ pote->ote_handle = 0;
+ }
+
+ /*
+ * Clear bit in flags to use as allocation flag
+ */
+ pote->ote_flags &= ~OBJALLOC;
+
+ /*
+ * check that executable objects don't have write access also
+ */
+ if (pote->ote_flags & OBJ_EXEC &&
+ pote->ote_flags & OBJ_WRITE) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto createerror;
+ }
+
+ /*
+ * if object readonly force it to be shared
+ */
+ if (!(pote->ote_flags & OBJ_WRITE))
+ pote->ote_flags |= OBJ_SHARED;
+ }
+ } /* end of for loop for each object */
+
+ if (ldrIsLE(pmte)) {
+
+ /*
+ * Compute size of IAT
+ */
+ if (poteiat != NULL) {
+
+ /*
+ * See if IAT exists already
+ */
+ if (!(pimpdir->imp_flags & HDRIAT)) {
+ if (poteiat->ote_vsize < poteiat->ote_psize)
+ cbiat = poteiat->ote_vsize;
+ else
+ cbiat = poteiat->ote_psize;
+ cbiat -= pimpdir->imp_address - poteiat->ote_base;
+
+// if ((rc = VMAllocKHB(VM_HKH_PUB_SWAPRW,
+// cbiat,
+// (VMHOB) LDRMTEOWNER,
+// NA,
+// SSToDS(&piat))) != NO_ERROR) {
+// goto createerror;
+// }
+ psmte->smte_iat = (ulong_t) piat;
+
+ /*
+ * Read IAT if it exits
+ */
+// if ((rc=ldrRead(plv->lv_sfn,
+// poteiat->ote_pages +
+// (pimpdir->imp_address -
+// poteiat->ote_base),
+// (PCHAR) psmte->smte_iat,
+// NULL,
+// cbiat,
+// pmte)) != NO_ERROR) {
+// goto createerror;
+// }
+ }
+
+ if (pimpdir->imp_flags & HDRIAT) {
+ piat = (struct ImpHdr *) ((pimpdir->imp_reserved -
+ pe32->e32_objtab) +
+ psmte->smte_objtab);
+ psmte->smte_iat = (ulong_t) piat;
+ cbiat = pe32->e32_unit[FIX].rva - pimpdir->imp_reserved;
+ }
+
+ /*
+ * Update Import directory entries to point to the
+ * swappable heap copy of the IAT.
+ */
+ iataddr = pimpdir->imp_address;
+ for (lcount = 0; lcount < pmte->mte_impmodcnt; lcount++,
+ pimpdir++) {
+ /*
+ * Save imp_address in imp_ver for check if page
+ * that is being faulted contains iat
+ */
+ pimpdir->imp_ver = pimpdir->imp_address;
+ pimpdir->imp_address = (pimpdir->imp_address -
+ iataddr) + (ulong_t) piat;
+
+ /*
+ * Store in imp_flags field size of iat
+ */
+ if (lcount != 0) {
+ pprevimpdir->imp_flags = pimpdir->imp_address;
+ }
+ pprevimpdir = pimpdir;
+ }
+
+ /*
+ * Update size of last iat (imp_flags)
+ */
+ pimpdir--;
+ pdst = (ulong_t *) pimpdir->imp_address;
+ while ((*pdst != 0) &&
+ ((ulong_t) pdst < (ulong_t) piat + cbiat)) {
+ pdst++;
+ }
+ if ((ulong_t) pdst >= (ulong_t) piat + cbiat) {
+ rc = ERROR_BAD_EXE_FORMAT;
+ goto createerror;
+ }
+ /*
+ * Add one to size for terminator of directory
+ */
+ pdst++;
+ pimpdir->imp_flags = (ulong_t) pdst;
+ cbiat = (ulong_t) pdst - (ulong_t) piat;
+ psmte->smte_iatsize = cbiat;
+ }
+
+
+ /*
+ * reserve address space for dlls
+ */
+// if (pmte->mte_mflags & LIBRARYMOD && vsize > 0 &&
+// !(pmte->mte_mflags & (FSDMOD | DEVDRVMOD | VDDMOD))) {
+// pote = (ldrote_t *) psmte->smte_objtab;
+// ac.ac_va = pote->ote_base + psmte->smte_vbase;
+// if (ac.ac_va > SEL_512MEG - _64MEG) {
+// /*
+// * The address we are to reserve at is greater than
+// * the reserved space for DLLs. Set the address to zero
+// * so we will fail the first reserve and than we can
+// * reserve at any address.
+// */
+// ac.ac_va = 0;
+// }
+
+// /*
+// * Try to reserve address space for module at which it was
+// * linked at. If that fails allocate at any address.
+// */
+// fl = VMAC_ARENASHR | VMAC_ALIGNSEL | VMAC_PRERES |
+// VMAC_LOCSPECIFIC;
+// for (i = 0; i < 2; i++) {
+// if ((rc = VMReserveMem(vsize,
+// fl,
+// pPTDACur->ptda_handle,
+// NULL,
+// SSToDS(&ac))) == NO_ERROR)
+// break;
+
+// /*
+// * At this point we have failed to allocate at the address
+// * the linker assigned. Check to see if fixups have been
+// * removed. If they have fail to load this module.
+// */
+// if (pmte->mte_mflags & E32_NOINTFIX) {
+// rc = ERROR_BAD_EXE_FORMAT;
+// goto createerror;
+// }
+// fl &= ~VMAC_LOCSPECIFIC;
+// fl |= VMAC_LOCANY;
+// }
+// if (rc != NO_ERROR) {
+// goto createerror;
+// }
+// if ((vsize = ac.ac_va-pote->ote_base) != psmte->smte_vbase) {
+// psmte->smte_delta = ac.ac_va - (psmte->smte_vbase +
+// pote->ote_base);
+// psmte->smte_vbase = vsize;
+// }
+
+// }
+ }
+
+ /*
+ * Check if internal name for a LIBRARY matches the module name
+ * but not for porthole apps.
+ */
+ if ((plv->lv_type == EXT_LIBRARY) &&
+ !(pmte->mte_mflags & MTEPORTHOLE) &&
+ (rc = ldrCheckInternalName(pmte)) != NO_ERROR) {
+ goto createerror;
+ }
+
+ pmte->mte_sfn = plv->lv_sfn; /* save system file number in mte */
+
+// if (IOPLEnabled || (ldrChkIOPLTable(psmte) == NO_ERROR))
+// pmte->mte_mflags |= MTEIOPLALLOWED;
+
+ /*
+ * link mte in list of mtes
+ */
+ ldrLinkMTE(pmte);
+
+ pmte->mte_mflags |= MTEVALID;
+
+createerror:
+ if (rc != NO_ERROR) {
+ /*
+ * Check if Pseudo Handle allocated
+ */
+ if (hobmte != 0) {
+ Free16BHandle(hobmte);
+ }
+
+ /*
+ * check if swappable MTE allocated
+ */
+ if (psmte != NULL) {
+ /*
+ * check if page table, IAT and resource table allocated
+ */
+ if (ldrIsLE(pmte) && psmte->smte_fpagetab != 0)
+ RtlFreeHeap(LDRNEHeap, 0, (void *) psmte->smte_fpagetab);
+
+ RtlFreeHeap(LDRNEHeap, 0, (void *) psmte);
+ }
+
+ /*
+ * check if resident MTE allocated
+ */
+ if (pmte != NULL)
+ RtlFreeHeap(LDRNEHeap, 0, (void *) pmte);
+
+ }
+ return(rc);
+}
+
+
+/***LP ldrMTEValidatePtrs - Validate pointers in MTE table and update to new
+ * values
+ *
+ * Check for any wild pointers in MTE before converting to new
+ * value.
+ *
+ * ENTRY pmte - pointer to loader MTE
+ * limit - max value any ptrs may be
+ * constant - value to update pointers by
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ */
+
+int ldrMTEValidatePtrs(pmte, limit, constant)
+ldrmte_t *pmte; /* pointer to loader MTE */
+ULONG limit;
+ULONG constant;
+{
+ ldrsmte_t *psmte;
+ register PULONG p;
+ register unsigned int i;
+
+ psmte = pmte->mte_swapmte;
+
+ /*
+ * do for each entry in MTE found in validatetbl
+ */
+
+ for (i = 0; validatetbl[i] != ENDMTETBL; i++) {
+
+ /*
+ * Since the resource table is no longer part of the
+ * header for a 32-bit module do not validate it.
+ */
+ if (ldrIsLE(pmte) && i == rsrcvalidatetbl)
+ continue;
+ /*
+ * point to entry in exe image
+ */
+ (PCHAR ) p = ((PCHAR ) psmte + validatetbl[i]);
+
+ /*
+ * check if pointer valid, non-zero
+ */
+ if (*p != 0)
+ /*
+ * range check and add constant to value at pointer
+ */
+ if ((*p += constant) > limit)
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+ return(NO_ERROR);
+}
+
+
+/***LP ldrExpandSegment - expand segments in place
+ *
+ * copy each segment table entry from pointer at psrc to
+ * pmte->mte_objtab, the region starting immediately after the space for
+ * pathname, and expand each entry by adding two bytes for the segment
+ * handle and 4 bytes for the linear address of the segment
+ *
+ * ENTRY pmte - pointer to mte
+ * type - module type
+ *
+ * EXIT none - segments expanded
+ */
+
+void ldrExpandSegment(pmte, type)
+ldrmte_t *pmte; /* pointer to module table entry */
+UCHAR type; /* module type */
+{
+ register ldrste_t *psrc; /* pointer to source */
+ register ldrste_t *pdst; /* pointer to destination */
+ register int i; /* count of segments */
+ ldrsmte_t *psmte; /* pointer to swappable mte */
+ ulong_t ldrccodeseg = 0;/* count of seg that can be packed */
+ ulong_t ldrcsegpack = 0;/* running size of packed segs */
+
+ psmte = pmte->mte_swapmte;
+ pdst = (ldrste_t *) psmte->smte_objtab;
+
+ psrc = (ldrste_t *) (psmte->smte_objtab + (psmte->smte_objcnt *
+ (sizeof(ldrste_t) - sizeof(struct new_seg))));
+
+ /* loop for all STEs */
+ for (i = 0; pdst != psrc; i++, ((struct new_seg *) psrc)++, pdst++) {
+
+ /*
+ * Make sure the following flags are cleared:
+ */
+ psrc->ste_flags &= ~(STE_PACKED | STE_SEMAPHORE | STE_SELALLOC |
+ STE_HUGE | STE_WAITING);
+
+ if ((type == EXT_DEVICE)) {
+ /*
+ * For a device driver module.
+ * If it is a first or the second segment, set the GDTSEG flag.
+ * If the segment is ring 2 segment (IOPL), set the GDTSEG flag.
+ */
+ if (i >= 2) {
+ if ((psrc->ste_flags & STE_SEGDPL) == STE_RING_2)
+ psrc->ste_flags |= STE_GDTSEG;
+ }
+ else
+ psrc->ste_flags |= STE_GDTSEG;
+ }
+
+ if ((type == EXT_DEVICE) || (type == EXT_FSD)) {
+ /*
+ * This is an FSD/DD module. We need to force the seg's to be
+ * movable, preloaded and have DPL = 3(because the init routine
+ * will run in ring 3). These segments cannot be shared, cannot
+ * be conforming and cannot be discarded.
+ */
+ psrc->ste_flags |= (STE_PRELOAD | STE_RING_3);
+ psrc->ste_flags &= ~(STE_SHARED | STE_CONFORM);
+ }
+
+ /*
+ * if swapping is not on or loading from removable media
+ * force preloading of segment
+ */
+ if (!(pmte->mte_mflags & MTE_MEDIAFIXED))
+ psrc->ste_flags |= STE_PRELOAD;
+
+ /*
+ * if readonly, force segment to be shared
+ */
+ if (psrc->ste_flags & STE_ERONLY)
+ psrc->ste_flags |= STE_SHARED;
+
+ /*
+ * if this is a code segment, force it to be shared
+ */
+ else if ((psrc->ste_flags & STE_TYPE_MASK) == STE_CODE) {
+ psrc->ste_flags |= STE_SHARED;
+ ldrccodeseg++;
+ }
+
+ /*
+ * Set Pageable bit:
+ * If read-only data and fixed media, then it is pageable
+ */
+ if (((psrc->ste_flags & STE_DATA) &&
+ !(psrc->ste_flags & STE_ERONLY)) ||
+ !(pmte->mte_mflags & MTE_MEDIAFIXED))
+ psrc->ste_flags &= ~STE_PAGEABLE;
+ else
+ psrc->ste_flags |= STE_PAGEABLE;
+
+ /*
+ * copy ste to final destination
+ */
+
+ *(struct new_seg *) pdst = *(struct new_seg *) psrc;
+
+ /*
+ * initialize segment handle and selector to zero
+ */
+ pdst->ste_selector = 0;
+ pdst->ste_seghdl = 0;
+
+ /*
+ * initialize segment fixup table to null
+ */
+ pdst->ste_fixups = 0;
+ }
+
+ /*
+ * Check if we can pack the segments
+ */
+ if (type == EXT_PROGRAM && ldrccodeseg > MINSEGPACKCNT) {
+ pdst = (ldrste_t *) psmte->smte_objtab;
+ ldrccodeseg = 0;
+ for (i = 0; i < (int) psmte->smte_objcnt; i++, pdst++) {
+
+ ulong_t minsiz_l = RESIZE64K(pdst->ste_minsiz);
+
+ if ((pdst->ste_flags & STE_TYPE_MASK) == STE_CODE &&
+ ((USHORT)(pdst->ste_minsiz % (USHORT) PAGEMASK) <
+ (USHORT) MINPGPACKSIZE) &&
+ minsiz_l < MAXSEGPACKSIZE) {
+ ldrccodeseg++;
+ pdst->ste_flags |= STE_PACKED;
+ pdst->ste_flags &= ~STE_PRESENT;
+ pdst->ste_minsiz = (pdst->ste_minsiz + (USHORT) 3) &
+ (USHORT) ~3;
+ ldrcsegpack += minsiz_l;
+ }
+ }
+ psmte->smte_csegpack = ldrccodeseg;
+ psmte->smte_ssegpack = ldrcsegpack;
+ }
+
+}
+
+
+/***LP ldrCheckInternalName - Check if internal name of a library matches
+ * its module name
+ *
+ * ENTRY pmte pointer to its MTE
+ * File name assumed to be in pPTDACur->ptda_pLdrBuf
+ *
+ * EFFECTS The internal name is changed to Upper Case and NULL terminated
+ *
+ * EXIT NO_ERROR name matches
+ * ERROR_INVALID_NAME mismatch
+ */
+int ldrCheckInternalName(pmte)
+register ldrmte_t *pmte;
+{
+ PUCHAR pchintname; /* pointer to internal name */
+ USHORT cchintname; /* length of internal name */
+ PCHAR pchmodname; /* pointer to module name */
+ USHORT cchmodname; /* length of module name */
+ PCHAR ptemp;
+ PCHAR ptemp2;
+ USHORT count;
+
+ pchintname = (PCHAR) pmte->mte_modname;
+ cchintname = *pchintname++; /* length of internal name */
+
+ /*
+ * For library modules, the internal name must match the name
+ * by which the module is being loaded. We extract the name from
+ * the fully qualified name in LdrBuf for comparison.
+ */
+ if (pmte->mte_mflags & LIBRARYMOD) {
+ ptemp = LdrBuf;
+ while (ptemp != NULL) {
+ pchmodname = ptemp;
+ ptemp = strpbrk(ptemp, "\\/");
+ if (ptemp != NULL) {
+ ptemp++;
+ }
+ }
+ ptemp = strchr(pchmodname, '.');
+ if (ptemp == NULL) {
+ ptemp = strchr(pchmodname, '\0');
+ }
+ cchmodname = (USHORT) (ptemp - pchmodname);
+ if (cchintname != cchmodname) {
+ return(ERROR_INVALID_NAME);
+ }
+
+ count = cchmodname;
+ ptemp = pchmodname;
+ ptemp2 = pchintname;
+#ifdef DBCS
+// MSKK Apr.20.1993 V-AkihiS
+ while (count-- > 0) {
+ if (IsDBCSLeadByte(*ptemp)) {
+ ptemp++;
+ if (count > 0) {
+ count--;
+ ptemp++;
+ }
+ } else {
+ *ptemp = (CHAR) toupper(*(PUCHAR)ptemp);
+ ptemp++;
+ }
+ }
+ count = cchmodname;
+ while (count-- > 0) {
+ if (IsDBCSLeadByte(*ptemp2)) {
+ ptemp2++;
+ if (count > 0) {
+ count--;
+ ptemp2++;
+ }
+ } else {
+ *ptemp2 = (CHAR) toupper(*(PUCHAR)ptemp2);
+ ptemp2++;
+ }
+ }
+#else
+ while (count-- > 0) {
+ *ptemp = (CHAR) toupper(*(PUCHAR)ptemp);
+ ptemp++;
+ *ptemp2 = (CHAR) toupper(*(PUCHAR)ptemp2);
+ ptemp2++;
+ }
+#endif
+
+ if (strncmp(pchintname, pchmodname, cchintname) != 0) {
+ return(ERROR_INVALID_NAME);
+ }
+
+ }
+ return (NO_ERROR);
+}
+
+
+/***LP ldrChkLoadType - Check if module matches requested load type
+ *
+ * ENTRY lflags - flags
+ * plv - pointer to local variables
+ *
+ * EXIT none - return successful or call load_error
+ */
+
+void ldrChkLoadType(lflags, plv)
+ULONG lflags; /* module table entry flags */
+register ldrlv_t *plv; /* pointer to local variables */
+{
+ if (!((plv->lv_type != EXT_PROGRAM) ^ (!(lflags & LIBRARYMOD)))) {
+ if (plv->lv_sfn != 0)
+ NtClose(plv->lv_sfn);
+ load_error(ERROR_INVALID_MODULETYPE, NULL);
+ }
+}
+
+
+/***LP ldrIsAttached - Check if process is already attached to module
+ *
+ * Check if the current (or child) process is attached to
+ * each of the objects in the given module.
+ *
+ * This procedure performs the following steps:
+ *
+ * for each segment (object) in the module,
+ * if shared,
+ * if (error from VMIsAttached)
+ * return (FALSE)
+ * else (it is private)
+ * if no handle maps the segment (object) address
+ * retun (FALSE)
+ * return (TRUE)
+ *
+ * ENTRY pmte - pointer to mte to check
+ *
+ * EXIT int
+ * FALSE - Process is not attached to module
+ * TRUE - Process is attached to module
+ *
+ */
+int ldrIsAttached(pmte)
+register ldrmte_t *pmte;
+{
+ ldrsmte_t *psmte; /* pointer to swappable mte */
+// ULONG objno;
+// VMHOB hptda;
+// VMHOB hob;
+ ULONG lnonrsrccnt;
+// register ldrote_t *pote;
+// register ldrste_t *pste;
+
+ psmte = pmte->mte_swapmte;
+ /*
+ * Do not process resource objects for 16-bit modules
+ */
+ if (ldrIsNE(pmte))
+ lnonrsrccnt = psmte->smte_objcnt - psmte->smte_rsrccnt;
+ else
+ lnonrsrccnt = psmte->smte_objcnt;
+
+ /*
+ * If there are no non-resource objects, then we must
+ * say we are not attached, since this may be a forwarder
+ * module, and we need to process its list of static
+ * links.
+ */
+ if (lnonrsrccnt == 0)
+ return(FALSE);
+
+// (ULONG) pste = (ULONG) pote = psmte->smte_objtab;
+// for (objno = 0; objno < lnonrsrccnt; objno++, pote++, pste++) {
+
+ /*
+ * skip resource objects for 32-bit modules
+ */
+// if (ldrIsLE(pmte) && pote->ote_flags & (OBJ_RSRC | OBJ_DEBUG))
+// continue;
+
+ /*
+ * get handle from object or segment table
+ */
+// if (ldrIsNE(pmte)) {
+// if (pste-> ste_flags & STE_SHARED) {
+// if (pste->ste_seghdl == HOBNULL)
+// return(FALSE);
+// if (VMIsAttached((VMHOB)pste->ste_seghdl,hptda) != NO_ERROR)
+// return(FALSE);
+// }
+// else if (VMGetHandle(SelToLaTiled(pste->ste_selector), hptda,
+// SSToDS (&hob)) != NO_ERROR)
+// return (FALSE);
+// }
+// else {
+// if (pote-> ote_flags & OBJ_SHARED) {
+// if (pote->ote_handle == HOBNULL)
+// return(FALSE);
+// if (VMIsAttached((VMHOB)pote->ote_handle,hptda) != NO_ERROR)
+// return(FALSE);
+// }
+// else if (VMGetHandle(pote->ote_base, hptda,
+// SSToDS (&hob)) != NO_ERROR)
+// return (FALSE);
+// }
+// }
+ return(TRUE);
+}
+
+
+/***LP ldrWriteErrTxt - write error message into user's message buffer
+ *
+ * This procedure preforms the following steps:
+ *
+ * - if user supplied buffer zero error message will not be setup
+ * - else copy module name into user suppiled buffer
+ * - if errcode = ERROR_PROC_NOT_FOUND copy procedure name
+ * to user buffer
+ *
+ * ENTRY errcode - loader error code
+ * pmte - pointer to module table entry
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ * - else ERROR_PROTECTION_VIOLATION
+ *
+ * EFFECTS error message copied into user's message buffer
+ */
+
+VOID
+ldrWriteErrTxt( errcode )
+int errcode; /* loader error code */
+{
+ int rc = NO_ERROR;
+ USHORT cnt;
+ USHORT BufferLen;
+ char ordbuf[20]; // Buffer to translate ordinal number
+ char *pordbuf;
+ PSZ pstring;
+
+ pstring = pErrText->Buffer;
+ BufferLen = pErrText->MaximumLength - 1;
+ if ((pstring == NULL) || (BufferLen == 0)) {
+ return;
+ }
+
+ /*
+ * Check if module name setup by ldrSetupSrcErrTxt. If so use that
+ * module else check the MTE passed.
+ */
+ cnt = ldrSrcModNameBufL;
+ if (cnt != 0) {
+ if (cnt > BufferLen)
+ cnt = BufferLen;
+ RtlMoveMemory(pstring, ldrSrcModNameBuf, (ULONG) cnt);
+ pstring += (UCHAR) cnt;
+ BufferLen -= cnt;
+ }
+
+ if (ldrTgtModNameBufL != 0) {
+ /*
+ * First, place a '->' in the buffer to delimit the source
+ * and target module names. Protect against small buffers...
+ */
+ cnt = (USHORT) 2;
+ if (cnt > BufferLen)
+ cnt = BufferLen;
+ RtlMoveMemory(pstring, "->", (ULONG) cnt);
+ pstring += (UCHAR) cnt;
+ BufferLen -= cnt;
+ cnt = ldrTgtModNameBufL;
+ if (cnt > BufferLen)
+ cnt = BufferLen;
+ RtlMoveMemory(pstring, ldrTgtModNameBuf, (ULONG) cnt);
+ pstring += (UCHAR) cnt;
+ BufferLen -= cnt;
+ }
+
+ /*
+ * If errcode == ERROR_PROC_NOT_FOUND, then ldrProcNameBuf has
+ * the procedure name. Else if errocode == ERROR_INVALID_ORDINAL
+ * then ldrProcNameBuf has the ordinal.
+ */
+ if ((errcode == ERROR_PROC_NOT_FOUND)
+ || (errcode == ERROR_INVALID_ORDINAL)) {
+ /*
+ * First, place a '.' in the buffer to delimit the module
+ * and procedure names. Protect against small buffers...
+ */
+ cnt = 1;
+ if (cnt > BufferLen)
+ cnt = BufferLen;
+ RtlMoveMemory(pstring, ".", (ULONG) cnt);
+ pstring += (UCHAR) cnt;
+ BufferLen -= cnt;
+ if (errcode == ERROR_PROC_NOT_FOUND) {
+ cnt = ldrProcNameBufL;
+ if (cnt > BufferLen)
+ cnt = BufferLen;
+ RtlMoveMemory(pstring, ldrProcNameBuf, (ULONG) cnt);
+ pstring += (UCHAR) cnt;
+ BufferLen -= cnt;
+ }
+ else { /* errcode == ERROR_INVALID_ORDINAL */
+ pordbuf = _itoa((int) ldrProcNameBuf, ordbuf, 10);
+ cnt = (USHORT) strlen(pordbuf);
+ if (cnt > BufferLen)
+ cnt = BufferLen;
+ RtlMoveMemory(pstring, pordbuf, (ULONG) cnt);
+ pstring += (UCHAR) cnt;
+ BufferLen -= cnt;
+ }
+ }
+
+ pErrText->Length = (pErrText->MaximumLength - 1) - BufferLen;
+}
+
+#if PMNT
+
+BOOLEAN
+ldrSaveErrInfo( errcode )
+int errcode; /* loader error code */
+{
+
+ if (ldrSaveSrcModNameBufL=ldrSrcModNameBufL) {
+ if (!(ldrSaveSrcModNameBuf=
+ RtlAllocateHeap(LDRNEHeap, 0, ldrSrcModNameBufL))) {
+ KdPrint(("ldrSaveErrInfo() failed\n"));
+ return(FALSE);
+ }
+ strncpy(ldrSaveSrcModNameBuf,ldrSrcModNameBuf,ldrSrcModNameBufL);
+ }
+ if (ldrSaveTgtModNameBufL=ldrTgtModNameBufL) {
+ if (!(ldrSaveTgtModNameBuf=
+ RtlAllocateHeap(LDRNEHeap, 0, ldrTgtModNameBufL))){
+ KdPrint(("ldrSaveErrInfo() failed\n"));
+ return(FALSE);
+ }
+ strncpy(ldrSaveTgtModNameBuf,ldrTgtModNameBuf,ldrTgtModNameBufL);
+ }
+ if (errcode==ERROR_PROC_NOT_FOUND) {
+ if (ldrSaveProcNameBufL=ldrProcNameBufL) {
+ if (!(ldrSaveProcNameBuf=
+ RtlAllocateHeap(LDRNEHeap, 0, ldrProcNameBufL))) {
+ KdPrint(("ldrSaveErrInfo() failed\n"));
+ return(FALSE);
+ }
+ strncpy(ldrSaveProcNameBuf,ldrProcNameBuf,ldrProcNameBufL);
+ }
+ }
+ else {
+ ldrSaveProcNameBuf = ldrProcNameBuf;
+ }
+ ldrSaveRc = errcode;
+ return(TRUE);
+}
+
+VOID
+ldrRestoreErrInfo( errcode )
+int *errcode; /* loader error code */
+{
+
+ if (ldrSrcModNameBufL = ldrSaveSrcModNameBufL) {
+ ldrSrcModNameBuf = ldrSaveSrcModNameBuf;
+ }
+ if (ldrTgtModNameBufL = ldrSaveTgtModNameBufL) {
+ ldrTgtModNameBuf = ldrSaveTgtModNameBuf;
+ }
+ if (ldrSaveRc==ERROR_PROC_NOT_FOUND) {
+ ldrProcNameBufL = ldrSaveProcNameBufL;
+ }
+ ldrProcNameBuf = ldrSaveProcNameBuf;
+ *errcode = ldrSaveRc;
+}
+
+BOOLEAN
+ldrFreeErrInfo( )
+{
+ if (ldrSaveSrcModNameBuf) {
+ if (!(RtlFreeHeap(LDRNEHeap, 0, ldrSaveSrcModNameBuf))){
+ KdPrint(("ldrFreeErrInfo() failed\n"));
+ return(FALSE);
+ }
+ ldrSaveSrcModNameBuf=NULL;
+ }
+ if (ldrSaveTgtModNameBuf) {
+ if (!(RtlFreeHeap(LDRNEHeap, 0, ldrSaveTgtModNameBuf))){
+ KdPrint(("ldrFreeErrInfo() failed\n"));
+ return(FALSE);
+ }
+ ldrSaveTgtModNameBuf=NULL;
+ }
+ if (ldrSaveRc == ERROR_PROC_NOT_FOUND && ldrSaveProcNameBuf) {
+ if (!(RtlFreeHeap(LDRNEHeap, 0, ldrSaveProcNameBuf))){
+ KdPrint(("ldrFreeErrInfo() failed\n"));
+ return(FALSE);
+ }
+ ldrSaveProcNameBuf=NULL;
+ }
+ ldrSaveSrcModNameBufL = ldrSaveTgtModNameBufL = ldrSaveProcNameBufL= 0;
+ ldrSaveRc = 0;
+ return(TRUE);
+}
+
+#endif
+
+/***LP load_error - General error handler for new EXE load errors
+ *
+ * ENTRY errcode - load error code
+ * pmte - pointer to mte if it exists
+ *
+ * EXIT none
+ *
+ */
+
+void load_error(errcode, pmte)
+int errcode; /* load error code */
+ldrmte_t *pmte; /* pointer to module table entry */
+{
+ /*
+ * ldrOpen returns ERROR_OPEN_FAILED for non-existent files. This
+ * is incorrect with the definition of the error-code. It should
+ * be ERROR_FILE_NOT_FOUND instead
+ */
+
+ if (errcode == ERROR_OPEN_FAILED)
+ errcode = ERROR_FILE_NOT_FOUND;
+
+ ldrWriteErrTxt(errcode);
+}
+
+VOID ldrInvalidateDesc(
+ SEL Selector // selector to be invalidated
+ )
+{
+ PROCESS_LDT_INFORMATION LdtInfo;
+ NTSTATUS Status;
+
+ LdtInfo.Start = Selector & 0xfff8;
+ LdtInfo.Length = sizeof(LDT_ENTRY);
+
+ RtlZeroMemory(LdtInfo.LdtEntries, sizeof(LDT_ENTRY));
+
+ Status = NtSetInformationProcess( CurrentThread->Process->ProcessHandle,
+ ProcessLdtInformation,
+ &LdtInfo,
+ sizeof(PROCESS_LDT_INFORMATION)
+ );
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint ("ldrSetDescInfo: Invalid request\n");
+#endif
+ }
+}
+
+VOID
+ldrTagModuleTree(
+ ldrmte_t *pmte
+ )
+{
+ ldrmte_t **ppmte;
+ ULONG lindex;
+ ULONG i;
+
+ pmte->mte_mflags |= INGRAPH;
+
+ ppmte = (ldrmte_t **) pmte->mte_modptrs;
+ for (i = 1; i <= pmte->mte_impmodcnt; i++) {
+ /*
+ * It is required for 16-bit modules to load the
+ * referneced module in reverse order.
+ */
+ lindex = pmte->mte_impmodcnt-i;
+
+ //
+ // Check if the referenced module has already been processed.
+ // Processing the modules is done in reverse order.
+ //
+ if ((ppmte[lindex]->mte_mflags & INGRAPH) == 0) {
+ ldrTagModuleTree(ppmte[lindex]);
+ }
+ }
+}
+
+VOID
+ldrTagModuleTree_USED(
+ ldrmte_t *pmte
+ )
+{
+ ldrmte_t **ppmte;
+ ULONG lindex;
+ ULONG i;
+
+ pmte->mte_mflags |= INGRAPH | USED;
+
+ ppmte = (ldrmte_t **) pmte->mte_modptrs;
+ for (i = 1; i <= pmte->mte_impmodcnt; i++) {
+ /*
+ * It is required for 16-bit modules to load the
+ * referneced module in reverse order.
+ */
+ lindex = pmte->mte_impmodcnt-i;
+
+ //
+ // Check if the referenced module has already been processed.
+ // Processing the modules is done in reverse order.
+ //
+ if ((ppmte[lindex]->mte_mflags & INGRAPH) == 0) {
+ ldrTagModuleTree_USED(ppmte[lindex]);
+ }
+ }
+}
+
+BOOLEAN
+ldrUnloadTagedModules(
+ IN POS2_PROCESS Process
+)
+{
+ ldrmte_t *pmte;
+ ldrmte_t *ptmte;
+ ldrsmte_t *psmte;
+ ldrste_t *pste;
+ ULONG i;
+ NTSTATUS Status;
+ APIRET rc;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: LDRUnloadTagedModules() was called\n");
+ }
+#endif
+
+ //
+ // Scan loaded module chain for referenced modules
+ //
+ pmte = mte_h;
+ while (pmte != NULL) {
+ //
+ // skip non tagged modules
+ //
+ if (((pmte->mte_mflags & INGRAPH) == 0) ||
+ ((pmte->mte_mflags & (USED | DOSMOD)) != 0)
+ ) {
+ pmte = pmte->mte_link;
+ continue;
+ }
+
+ //
+ // Handle the case where the first loaded app failed
+ // and DOSCALLS was loaded. Allow to release it.
+ //
+ if (((pmte->mte_mflags & DOSLIB) != 0) &&
+ (!DoscallsLoaded)
+ ) {
+ pmte->mte_usecnt--;
+ }
+
+ //
+ // Tagged modules are processed here
+ //
+
+ //
+ // Unmap the segments of the current module from the address
+ // space of the current process.
+ //
+ psmte = pmte->mte_swapmte;
+ pste = (ldrste_t *)psmte->smte_objtab;
+
+ for (i = 1; i <= psmte->smte_objcnt; i++, pste++) {
+ //
+ // If we are terminating an app then no need to unmap the
+ // sections from the address space of the terminating process.
+ // The section will be unmapped by themself.
+ // In fact, trying to unmap will return status of
+ // STATUS_PROCESS_IS_TERMINATING
+ if (fForceUnmap) {
+ Status = NtUnmapViewOfSection(
+ CurrentThread->Process->ProcessHandle,
+ (PVOID)SELTOFLAT(pste->ste_selector)
+ );
+ //
+ // Error while unmapping resources is acceptable since
+ // resources are not mapped when the module is loaded,
+ // but we need to try to unmap them in case they were
+ // loaded by DosGetResource().
+ //
+ if ((!NT_SUCCESS(Status)) &&
+ (i <= psmte->smte_objcnt - psmte->smte_rsrccnt)
+ ) {
+#if DBG
+ DbgPrint("OS2LDR: ldrUnloadModule(): Unable to unmap a segment form the app, Status=%x\n", Status);
+#endif
+ }
+ //
+ // Invalidate the descriptor of the unmapped section
+ //
+ ldrInvalidateDesc(pste->ste_selector);
+ }
+
+ //
+ // If this was the last module referencing this mte
+ // then close the section and its mappings
+ //
+ if ((pmte->mte_usecnt == 0) &&
+ (pste->ste_seghdl != (ulong_t)R2XferSegHandle)
+ ) {
+ Status = NtUnmapViewOfSection(
+ NtCurrentProcess(),
+ (PVOID)SELTOFLAT(pste->ste_selector)
+ );
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("OS2LDR: ldrUnloadModule(): Unable to self unmap a segment, Status=%x\n", Status);
+#endif
+ return(FALSE);
+ }
+ Status = NtClose((HANDLE)pste->ste_seghdl);
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("OS2LDR: ldrUnloadModule(): Unable to close segment section, Status=%x\n", Status);
+#endif
+ return(FALSE);
+ }
+ //
+ // Check if the module has ring 2 segments which have entry points.
+ // If yes, delete the call gate entries
+ //
+ if (((pste->ste_flags & STE_SEGDPL) == STE_RING_2) && // ring 2 segment
+ ((pste->ste_flags & STE_DATA) == 0) && // code segment
+ ((pste->ste_flags & STE_CONFORM) == 0) // non conforming
+ ) {
+ ldrEachObjEntry(i, pmte, ldrFreeCallGate, NULL);
+ }
+ //
+ // Don't free the bit map entries of the DOSCALLS selectors
+ // as these were not allocated explicity
+ //
+ if ((pmte->mte_mflags & DOSLIB) == 0) {
+ ldrFreeSel(pste->ste_selector, 1);
+ }
+ }
+ }
+ ptmte = pmte;
+ pmte = pmte->mte_link;
+ //
+ // If this module is no more referenced, disconnect it from
+ // the MTE chain and free its allocated memory
+ //
+ if (ptmte->mte_usecnt == 0) {
+ if (ptmte->mte_sfn != NULL) {
+ NtClose(ptmte->mte_sfn);
+ }
+ rc = Free16BHandle(ptmte->mte_handle);
+ ASSERT(rc == NO_ERROR);
+ ldrUnlinkMTE(ptmte);
+ RtlFreeHeap(LDRNEHeap, 0, ptmte->mte_swapmte);
+ RtlFreeHeap(LDRNEHeap, 0, ptmte);
+ }
+ }
+}
+
+BOOLEAN
+LDRUnloadExe(
+ IN POS2_PROCESS Process
+ )
+{
+ //
+ // Unload the .EXE file
+ //
+
+ ldrmte_t *pmte;
+ ldrmte_t *ptmte;
+ ldrdld_t *pdld;
+ ldrdld_t *prev_pdld;
+ ldrdld_t *pcurdld;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: LDRUnloadExe() called for NT process handle %x\n",
+ Process->ProcessHandle);
+ }
+#endif
+
+ pmte = (ldrmte_t *)Process->ProcessMTE;
+ if (pmte == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Set the fForceUnmap flag to FALSE so that ldrUnloadTagedModules()
+ // does not unmap the app's segments from the app's address space
+ // since the app is in a terminating satate
+ //
+ fForceUnmap = FALSE;
+
+ //
+ // Loop over the DLD chain.
+ // For Each entry, tag all referenced DLD modules with the INGRAPH flag
+ // The tagged modules will be then unloaded
+ //
+ pdld = pmte->mte_dldchain;
+ prev_pdld = (ldrdld_t *)&pmte->mte_dldchain;
+ while (pdld != NULL) {
+ if (pdld->Cookie == (ULONG)Process) {
+ //
+ // Clear the INGRAPH flag of all modules so that we
+ // know that this module has already been processed
+ //
+ ldrClearAllMteFlag(INGRAPH | USED);
+
+ ldrTagModuleTree(pdld->dld_mteptr);
+
+ //
+ // Remove the DLD entry
+ //
+ pcurdld = pdld;
+ pdld = pdld->dld_next;
+ prev_pdld->dld_next = pdld;
+ RtlFreeHeap(LDRNEHeap, 0, pcurdld);
+
+ //
+ // Decrement the usecnt of the marked modules
+ //
+ ptmte = mte_h;
+ while (ptmte != NULL) {
+ if ((ptmte->mte_mflags & INGRAPH) != 0) {
+ ptmte->mte_usecnt--;
+ }
+ ptmte = ptmte->mte_link;
+ }
+
+ ldrUnloadTagedModules(Process);
+ }
+ else {
+ prev_pdld = pdld;
+ pdld = pdld->dld_next;
+ }
+ }
+
+ //
+ // Clear the INGRAPH flag of all modules so that we
+ // know that this module has already been processed
+ //
+ ldrClearAllMteFlag(INGRAPH | USED);
+
+ //
+ // Tag all referenced modules with the INGRAPH flag
+ // The tagged modules will be then unloaded
+ //
+ ldrTagModuleTree(pmte);
+
+ //
+ // Decrement the usecnt of the marked modules
+ //
+ ptmte = mte_h;
+ while (ptmte != NULL) {
+ if ((ptmte->mte_mflags & INGRAPH) != 0) {
+ ptmte->mte_usecnt--;
+ }
+ ptmte = ptmte->mte_link;
+ }
+
+ ldrUnloadTagedModules(Process);
+
+#if DBG
+ IF_OL2_DEBUG ( MTE ) {
+ DbgPrint("\nDumping segmenst after LDRUnloadExe()\n");
+ ldrDisplaySegmentTable();
+ }
+#endif
+ Process->ProcessMTE = NULL;
+ return(TRUE);
+}
+
diff --git a/private/os2/ldr/ldrste.c b/private/os2/ldr/ldrste.c
new file mode 100644
index 000000000..54cc251c9
--- /dev/null
+++ b/private/os2/ldr/ldrste.c
@@ -0,0 +1,1159 @@
+
+#include "ldrextrn.h"
+
+extern ldrste_t segtab;
+
+VOID ldrSetDescInfo(
+ SEL Selector, // selector to set desc info on
+ ULONG MemoryAddress, // base address of selector
+ USHORT ste_flags, // ste flags
+ USHORT SegSize) // size of segment
+{
+ PROCESS_LDT_INFORMATION LdtInfo;
+ NTSTATUS Status;
+
+ LdtInfo.Start = Selector & 0xfff8;
+ LdtInfo.Length = sizeof(LDT_ENTRY);
+
+ LdtInfo.LdtEntries[0].LimitLow = SegSize - 1;
+ LdtInfo.LdtEntries[0].BaseLow = (USHORT)(MemoryAddress);
+ LdtInfo.LdtEntries[0].HighWord.Bytes.BaseMid = (UCHAR)(MemoryAddress >> 16);
+ LdtInfo.LdtEntries[0].HighWord.Bytes.BaseHi = (UCHAR)(MemoryAddress >> 24);
+ LdtInfo.LdtEntries[0].HighWord.Bytes.Flags1 = D_SEG+D_PRES+D_DPL3;
+ LdtInfo.LdtEntries[0].HighWord.Bytes.Flags2 = 0;
+
+ if ((ste_flags & STE_DATA) == 0) {
+ LdtInfo.LdtEntries[0].HighWord.Bytes.Flags1 |= D_CODE;
+ }
+
+ if ((ste_flags & STE_ERONLY) == 0) {
+ // The STE_ERONLY is applicable for both D_RX in CODE segments
+ // and D_RW in DATA segments. D_RX and D_RW are the same bit
+ LdtInfo.LdtEntries[0].HighWord.Bytes.Flags1 |= D_RX;
+ }
+
+ Status = NtSetInformationProcess( CurrentThread->Process->ProcessHandle,
+ ProcessLdtInformation,
+ &LdtInfo,
+ sizeof(PROCESS_LDT_INFORMATION)
+ );
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint ("ldrSetDescInfo: Invalid request\n");
+#endif
+ }
+}
+
+/***LP ldrLoadModule - Load a new exe file for given module table entry.
+ *
+ * Each segment in the module which has not been
+ * previously initialized will be initialized and
+ * loaded as required.
+ *
+ * ENTRY plv - pointer to local variables
+ *
+ * EXIT Module marked as loaded
+ *
+ *
+ * This procedure performs the following steps:
+ *
+ * - calls TKLibiRecordMTE
+ * - calls DebugLoadSymMTE
+ * - must attach to or load each module that is referenced by our module
+ * - if 32-bit module finish loading objects
+ * - mark mte as module has been loaded
+ */
+
+APIRET ldrLoadModule(plv)
+ldrlv_t *plv; /* local variables */
+{
+ register ldrmte_t *pmte; /* pointer to mte */
+ register ldrsmte_t *psmte; /* pointer to swappable mte */
+ ldrste_t *pste;
+ ldrlibi_t *ptmp;
+ ulong_t csegs;
+ int rc;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrLoadModule(pmte=%x) was called\n", plv->lv_pmte);
+ }
+#endif
+
+ pmte = plv->lv_pmte; /* point to mte */
+ psmte = pmte->mte_swapmte; /* pointer to swappable mte */
+
+ /*
+ * Setup for Library init
+ */
+ if (((pmte->mte_mflags & LIBRARYMOD) != 0) &&
+ ((pmte->mte_mflags & USED) == 0) &&
+ ((pmte->mte_mflags & (INSTLIBINIT | GINIDONE)) != GINIDONE)) {
+ ptmp = &pldrLibiRecord[*pldrLibiCounter];
+ ptmp->handle = pmte->mte_handle;
+ pste = ldrNumToSte(pmte, psmte->smte_startobj);
+ ptmp->startaddr.ptr_off = (USHORT) psmte->smte_eip;
+ ptmp->startaddr.ptr_sel = pste->ste_selector | 7;
+ if (psmte->smte_stackobj != 0) {
+ if ((pste = ldrNumToSte(pmte, psmte->smte_stackobj))==0) {
+ rc = ERROR_INVALID_STACKSEG;
+ return(rc);
+ }
+ ptmp->stackaddr.ptr_off = (USHORT) psmte->smte_esp;
+ ptmp->stackaddr.ptr_sel = pste->ste_selector | 7;
+ }
+ else {
+ ptmp->stackaddr.ptr_off = 0;
+ ptmp->stackaddr.ptr_sel = 0;
+ }
+ if ((psmte->smte_autods == 0) ||
+ (pste = ldrNumToSte(pmte, psmte->smte_autods)) == NULL)
+ ptmp->ds = 0;
+ else
+ ptmp->ds = pste->ste_selector | 7;
+ ptmp->heapsize = (USHORT) psmte->smte_heapsize;
+ (*pldrLibiCounter)++;
+ pmte->mte_mflags |= GINIDONE;
+ }
+
+ //
+ // For system dll's other than Doscalls don't load segments
+ //
+ if ((pmte->mte_mflags & DOSMOD) != 0) {
+ ASSERT(LDRDoscallsSel != 0);
+ return(NO_ERROR);
+ }
+
+ //
+ // If this module has already been loaded, no need to load again
+ //
+ if ((pmte->mte_mflags & MTEPROCESSED) != 0) {
+ return(NO_ERROR);
+ }
+
+ /*
+ * Make sure starting point (or init routine) is ring 3
+ */
+ if (ldrIsNE(pmte) &&
+ psmte->smte_startobj != 0) {
+ if ((pste=ldrNumToSte(pmte, psmte->smte_startobj)) == NULL) {
+ rc = ERROR_INVALID_STARTING_CODESEG;
+ return(rc);
+ }
+
+ if ((pste->ste_selector & RPL_MASK) != RPL_RING3) {
+ if (pmte->mte_mflags & LIBRARYMOD) {
+ rc = ERROR_INVALID_DLL_INIT_RING;
+ }
+ else {
+ rc = ERROR_INVALID_STARTING_RING, pmte;
+ }
+ return(rc);
+ }
+ }
+
+ pste = (ldrste_t *) psmte->smte_objtab;
+ for (csegs = 0;
+ csegs < psmte->smte_objcnt;
+ csegs++, pste++
+ ) {
+ if ((rc = ldrLoadSegment(pmte, pste)) != NO_ERROR) {
+#if DBG
+ DbgPrint("OS2LDR: ldrGetModule - failed to ldrLoadSegment, rc = %d\n", rc);
+#endif
+ return(rc);
+ }
+ }
+ if ((psmte->smte_autods != 0) &&
+ (psmte->smte_autods <= psmte->smte_objcnt)
+ ) {
+ ldrEachObjEntry(0, pmte, ldrEditProlog, NULL);
+ }
+ pmte->mte_mflags |= MTEPROCESSED;
+ return(NO_ERROR);
+}
+
+
+/***LP ldrAllocSegments - allocate segments/selectors for requested mte.
+ *
+ * Each segment in the module which requests to be
+ * preloaded is allocated and all selectors for the
+ * module are allocated for the child task.
+ *
+ * ENTRY plv - pointer to set of local variables
+ *
+ * EXIT None
+ *
+ *
+ * This procedure performs the following steps:
+ *
+ * - For each segment in this module
+ * - check if load should abort
+ * - allocate memory
+ */
+
+APIRET ldrAllocSegments(plv)
+register ldrlv_t *plv; /* pointer to set of local variables */
+{
+ldrmte_t *pmte; /* pointer to mte */
+ldrsmte_t *psmte; /* pointer to swappable mte */
+register ldrste_t *pste; /* pointer to a segment table entry */
+//PVOID MemoryAddress;
+ULONG LastSuccessful;
+int rc;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrAllocSegments(pste=%x) was called\n", plv->lv_pmte);
+ }
+#endif
+
+ pmte = plv->lv_pmte;
+ psmte = pmte->mte_swapmte;
+ pste = (ldrste_t *) psmte->smte_objtab;
+
+ for (plv->lv_objnum = 1; plv->lv_objnum <= psmte->smte_objcnt;
+ plv->lv_objnum++, pste++) {
+
+ if ((rc=ldrAllocSegment(pmte, pste, plv->lv_objnum)) != NO_ERROR) {
+
+ /*
+ * We got an error allocating the segments for this
+ * module. We must cleanup any segments that were
+ * allocated before the error if the module we are loading
+ * was a library module. The reason is that the mte for this
+ * module will not have a run time attachment to this process.
+ * The case we are covering here is if a module that references
+ * another, is not loaded that module's module pointer table
+ * will not get the pointer to the mte for this one. Therefore
+ * when garbage collection is run this module will be freed
+ * and the allocated segments will not get freed.
+ */
+ LastSuccessful = plv->lv_objnum - 1;
+ pste = (ldrste_t *) psmte->smte_objtab;
+
+ for (plv->lv_objnum = 1; plv->lv_objnum <= LastSuccessful;
+ plv->lv_objnum++, pste++) {
+
+ NtUnmapViewOfSection(CurrentThread->Process->ProcessHandle,
+ SELTOFLAT(pste->ste_selector)
+ );
+
+ if ((pmte->mte_mflags & MTEPROCESSED) == 0) {
+ //
+ // If the allocated segment is a ring 2 segment, check
+ // entry records that need to be referenced by call gates.
+ // Remove the emulation thunk for the call gate.
+ //
+ if (((pste->ste_flags & STE_SEGDPL) == STE_RING_2) && // ring 2 segment
+ ((pste->ste_flags & STE_DATA) == 0) && // code segment
+ ((pste->ste_flags & STE_CONFORM) == 0) // non conforming
+ ) {
+ ldrEachObjEntry(plv->lv_objnum, pmte, ldrFreeCallGate, NULL);
+ }
+ NtUnmapViewOfSection(NtCurrentProcess(),
+ SELTOFLAT(pste->ste_selector)
+ );
+ NtClose((HANDLE)pste->ste_seghdl);
+ ldrFreeSel(pste->ste_selector, 1);
+ }
+ }
+// /*
+// * Slip packed segments, free as one object later
+// */
+// if (pste->ste_flags & STE_PACKED)
+// continue;
+// if ((pste->ste_seghdl != HOBNULL) &&
+// (pste->ste_selector & SEL_LDTBIT) &&
+// ((pste->ste_flags & STE_SHARED) == 0)) {
+// /* If cached instance data object */
+// ldrAssert(pste->ste_offset != 0);
+// if (VMHandleVerify(pste->ste_seghdl,
+// 1,SSToDS(&pbcache)) == NO_ERROR) {
+// /* Free the pseudohandle */
+// VMFreePseudoHandle(pste->ste_seghdl);
+// /* Free small caches from heap */
+// VMFreeKHB(VM_HKH_PUB_SWAPRW, pbcache);
+// }
+// else { /* Else cache has own object */
+// rc = VMGetLaddr(pste->ste_seghdl, SSToDS(&laddr));
+// ldrAssert(rc == NO_ERROR);
+// while (VMFreeMem(laddr,HOBNULL,0)==ERROR_INTERRUPT)
+// ; /* Free the object */
+// }
+// pste->ste_seghdl = HOBNULL;
+// /* Clear the handle */
+// }
+// else if (pste->ste_selector != 0)
+// VMFreeMem(SelToLaTiled(pste->ste_selector),
+// (VMHOB) ((pPTDACur->ptda_child != HOBNULL) ?
+// pPTDACur->ptda_child :
+// pPTDACur->ptda_handle),
+// VMFM_NOLDR | VMFM_GC);
+
+// /*
+// * See if any packed segments exists, free as one object.
+// */
+// if (psmte->smte_csegpack > 0)
+// VMFreeMem(psmte->smte_ssegpack, NA, NA);
+
+ return(rc);
+ }
+ }
+
+ /*
+ * Clear packed segment flag for second load of EXE
+ */
+ if (psmte->smte_csegpack > 0)
+ psmte->smte_csegpack = 0;
+
+ return(NO_ERROR);
+}
+
+
+/***LP ldrAllocSegment - verify allocation size and allocate memory
+ *
+ * If the segment's file size is larger than the minimum
+ * allocation size an error is reported.
+ * Both the allocation size and the segment handle are saved in
+ * the segment table entry. Also indicate the segment
+ * is being loaded so that it's memory will not be
+ * discarded during the load.
+ *
+ * ldrAllocSegment (pmte, pste, iseg)
+ *
+ * ENTRY pmte - pointer to mte
+ * pste - pointer to ste
+ * iseg - segment number
+ * RETURN int - error code (NO_ERROR if successful)
+ *
+ */
+
+static ULONG RegionSize64K = _64K;
+
+APIRET ldrAllocSegment(pmte,pste,iseg)
+register ldrmte_t *pmte; /* MTE pointer */
+register ldrste_t *pste; /* STE pointer */
+ulong_t iseg; /* Segment number (1-based) */
+{
+ register ldrsmte_t *psmte; /* swappable mte pointer */
+ ulong_t fl; /* Memory allocation flags */
+ int frsrc; /* Resource segment flag */
+ int frsrcused; /* True if resource really used */
+ ULONG RegionSize;
+ uchar_t sharename[23] = "\\sharemem\\";
+ uchar_t *psharename = sharename;
+ uchar_t ext[3] = {0,0,0};
+ ulong_t Index;
+ PVOID MemoryAddress;
+ NTSTATUS Status;
+ LARGE_INTEGER LargeRegionSize;
+ HANDLE SectionHandle;
+ ULONG ViewSize;
+ ULONG Protect;
+ BOOLEAN SectionCreated = FALSE;
+ APIRET rc;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrAllocSegment(pmte=%x) was called\n", pmte);
+ }
+#endif
+
+ psmte = pmte->mte_swapmte;
+
+ frsrc = iseg > psmte->smte_objcnt - psmte->smte_rsrccnt;
+ /* Set resource flag */
+ /*
+ * Note that for debugging purposes, we will actually allocate
+ * memory for resources that are not marked STE_PRELOAD if the
+ * ldrLoadRsrc flag is set. Such resources are born with a
+ * reference count of zero instead of one, however. The flag
+ * frsrcused is used to distinguish the special case.
+ */
+// if (!(pste->ste_flags & STE_PRELOAD) && frsrc)
+// return(NO_ERROR); /* Skip non-preloaded resources */
+ frsrcused = FALSE; /* Assume not meant to be used yet */
+ fl = 0; /* Initialize VM and PG flags */
+
+ if ((pste->ste_flags & STE_PRELOAD)) {
+ /* If swapping off or preload seg */
+ /*
+ * For a resource, the preload attribute does not actually
+ * mean the resource should be preloaded. It just means we
+ * should allocate the segment for the resource at load time.
+ * Unless we are loading the resource from a floppy, we should
+ * always preload it.
+ */
+ if (pste->ste_flags & STE_SHARED) {
+ /* If shared object */
+ pste->ste_flags &= ~STE_PRELOAD;
+ /* Only preload shared guys once */
+ frsrcused = TRUE; /* Resource actually referenced */
+ }
+ }
+
+ RegionSize = pste->ste_minsiz;
+ if (RegionSize == 0) {
+ RegionSize = _64K;
+ }
+
+ if ((pmte->mte_mflags & MTEPROCESSED) == 0) {
+ if ((pmte->mte_mflags & DOSLIB) != 0) {
+ Index = 0;
+ // DOSCALLS.DLL is loaded into fixed locationions
+ MemoryAddress = (PVOID)(DOSCALLS_BASE + (iseg - 1) * _64K);
+ }
+ else {
+ Index = ldrAllocateSel(1, FALSE); // _64K are exactly 1 selector
+ MemoryAddress = SELTOFLAT(Index);
+ }
+ //
+ // Special handling for the R2XFER_BASE segment which has
+ // already been allocated at ldrInit()
+ //
+ if (MemoryAddress == (PVOID)R2XFER_BASE) {
+ pste->ste_seghdl = (ulong_t)R2XferSegHandle;
+ SectionHandle = R2XferSegHandle;
+ }
+ else {
+ LargeRegionSize.LowPart = _64K;
+ LargeRegionSize.HighPart = 0;
+ Status = NtCreateSection(&SectionHandle,
+ SECTION_ALL_ACCESS,
+ NULL,
+ &LargeRegionSize,
+ PAGE_EXECUTE_READWRITE,
+ SEC_RESERVE,
+ NULL
+ );
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("OS2LDR: ldrAllocSegment - Can't create section, Status=%x\n", Status);
+#endif
+ if (Index != 0) {
+ ldrFreeSel(Index, 1);
+ }
+ return(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ ViewSize = 0;
+ Status = NtMapViewOfSection(SectionHandle,
+ NtCurrentProcess(),
+ &MemoryAddress,
+ 1,
+ RegionSize,
+ NULL,
+ &ViewSize,
+ ViewUnmap,
+ 0,
+ PAGE_READWRITE
+ );
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("OS2LDR: ldrAllocSegment - Can't map section to server process at addr=%x, Status=%x\n",
+ MemoryAddress, Status);
+#endif
+ NtClose(SectionHandle);
+ if (Index != 0) {
+ ldrFreeSel(Index, 1);
+ }
+ return(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ SectionCreated = TRUE;
+ pste->ste_seghdl = (ulong_t)SectionHandle;
+ }
+ }
+ else {
+ SectionHandle = (HANDLE)pste->ste_seghdl;
+ MemoryAddress = SELTOFLAT(pste->ste_selector);
+ }
+
+ //
+ // Any change in determinig the Protect value should be
+ // done in ldrsubr.c LDRDosGetResource() too.
+ //
+ if ((pste->ste_flags & STE_DATA) == 0) {
+ // This is a code segment
+ if (CurrentThread->Process->Flags & OS2_PROCESS_TRACE) {
+ Protect = PAGE_EXECUTE_WRITECOPY;
+ }
+ else {
+ if ((pste->ste_flags & STE_ERONLY) != 0) {
+ // This is an execute only segment
+ Protect = PAGE_EXECUTE;
+ }
+ else {
+ Protect = PAGE_EXECUTE_READ;
+ }
+ }
+ }
+ else {
+ // This is a data segment
+ if ((pste->ste_flags & STE_SHARED) != 0) {
+ // This is a shared data segment
+ if ((pste->ste_flags & STE_ERONLY) != 0) {
+ // This is a read only segment
+ Protect = PAGE_READONLY;
+ }
+ else {
+ // This is a read/write segment
+ Protect = PAGE_READWRITE;
+ }
+ }
+ else {
+ // This is a non shared data segment
+ if ((pste->ste_flags & STE_ERONLY) != 0) {
+ // This is a read only segment
+ if (CurrentThread->Process->Flags & OS2_PROCESS_TRACE) {
+ Protect = PAGE_EXECUTE_WRITECOPY;
+ }
+ else {
+ Protect = PAGE_READONLY;
+ }
+ }
+ else {
+ // This is a sizeable read/write segment
+ Protect = PAGE_EXECUTE_WRITECOPY;
+ }
+ }
+ }
+
+ if ((pmte->mte_mflags & MTEPROCESSED) == 0) {
+ pste->ste_selector = FLATTOSEL((ULONG)MemoryAddress);
+ pste->ste_selector = (SEL)((pste->ste_selector & SEL_RPLCLR) |
+ ((pste->ste_flags & STE_SEGDPL) >> 10));
+ pste->ste_fixups = (ulong_t)MemoryAddress;
+ }
+
+ //
+ // Non resource segments are mapped into the address space of the
+ // client process.
+ // Resources are not mapped yet into the address space of the process.
+ // DosGetResource() does the mapping job for resources.
+ //
+ if (iseg <= psmte->smte_objcnt - psmte->smte_rsrccnt) {
+ if (Protect == PAGE_EXECUTE_WRITECOPY) {
+ ViewSize = RegionSize;
+ }
+ else {
+ ViewSize = 0;
+ }
+ Status = NtMapViewOfSection(SectionHandle,
+ CurrentThread->Process->ProcessHandle,
+ &MemoryAddress,
+ 1,
+ RegionSize,
+ NULL,
+ &ViewSize,
+ ViewUnmap,
+ 0,
+ Protect
+ );
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("OS2LDR: ldrAllocSegment - Can't map section to client process %x at addr=%x, Status=%x\n",
+ CurrentThread->Process->ProcessHandle, MemoryAddress, Status);
+#endif
+ if (SectionCreated) {
+ NtUnmapViewOfSection(NtCurrentProcess(), MemoryAddress);
+ NtClose(SectionHandle);
+ if (Index != 0) {
+ ldrFreeSel(Index, 1);
+ }
+ }
+ return(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ if ((pmte->mte_mflags & MTEPROCESSED) == 0) {
+ /*
+ * If this is Doscalls module save the code selector
+ * of the first code segment
+ */
+ if (((pmte->mte_mflags & DOSLIB) != 0) &&
+ (iseg == 1)
+ ) {
+ LDRDoscallsSel = pste->ste_selector | 7;
+ segtab = *pste;
+ }
+ //
+ // If the allocated segment is a ring 2 segment, check for
+ // entry records that need to be referenced by call gates.
+ // Create an emulation thunk for the call gate.
+ //
+ if (((pste->ste_flags & STE_SEGDPL) == STE_RING_2) && // ring 2 segment
+ ((pste->ste_flags & STE_DATA) == 0) && // code segment
+ ((pste->ste_flags & STE_CONFORM) == 0) // non conforming
+ ) {
+ rc = ldrEachObjEntry(iseg, pmte, ldrGetCallGate, NULL);
+ if (rc != NO_ERROR) {
+ ldrEachObjEntry(iseg, pmte, ldrFreeCallGate, NULL);
+ NtUnmapViewOfSection(CurrentThread->Process->ProcessHandle,
+ MemoryAddress
+ );
+
+ if (SectionCreated) {
+ NtUnmapViewOfSection(NtCurrentProcess(), MemoryAddress);
+ NtClose(SectionHandle);
+ if (Index != 0) {
+ ldrFreeSel(Index, 1);
+ }
+ }
+ return(rc);
+ }
+ }
+ }
+
+ ldrSetDescInfo(pste->ste_selector, (ULONG) MemoryAddress,
+ pste->ste_flags, pste->ste_minsiz);
+ }
+
+ return(NO_ERROR);
+}
+
+
+/***LP ldrLoadSegment - segment load
+ *
+ * Setup to call ldrLoadSegment
+ *
+ * ENTRY pmte - pointer to mte
+ * pste - pointer to a segment table entry
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ */
+
+APIRET ldrLoadSegment(pmte, pste)
+ldrmte_t *pmte; /* pointer to mte */
+ldrste_t *pste; /* pointer to segment table entry */
+
+{
+ IO_STATUS_BLOCK IoStatusBlock;
+ PIO_STATUS_BLOCK pIoStatusBlock = &IoStatusBlock;
+ LARGE_INTEGER ByteOffset;
+ ldrmte_t *ptgtmte;
+ ldrsmte_t *psmte;
+ ldrste_t *ptgtste;
+ struct taddr_s taddr;
+ ULONG laddr;
+ ULONG seek;
+ uchar_t relocbuf[RELOCBUFLEN];
+ ushort_t crelrecs;
+ ushort_t i;
+ ulong_t cbread;
+ ushort_t crecs;
+ ri_t *pri;
+ uchar_t *pprocname;
+ ushort_t ord;
+ uchar_t *pchar;
+ ulong_t minsiz;
+ int rc = NO_ERROR;
+ NTSTATUS Status;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrLoadSegment(pmte=%x, pste=%x) was called\n", pmte, pste);
+ }
+#endif
+
+ ldrSetupSrcErrTxt(((char *) pmte->mte_modname)+1,
+ (USHORT) *((char *) pmte->mte_modname));
+
+ psmte = pmte->mte_swapmte;
+
+// BUGBUG - remove after LDT defined
+// laddr = SelToLaTiled(pste->ste_selector);
+ laddr = pste->ste_fixups;
+
+ if (pste->ste_offset != 0) {
+
+ if (pste->ste_flags & STE_ITERATED) {
+ if ((rc = ldrLoadIteratedData(pmte,
+ pste,
+ pIoStatusBlock,
+ laddr)) != NO_ERROR) {
+ return(rc);
+ }
+ IoStatusBlock.Status -= laddr;
+ cbread = IoStatusBlock.Information;
+ ByteOffset.LowPart = (ULONG)
+ (pste->ste_offset << psmte->smte_alignshift);
+ ByteOffset.HighPart = 0;
+ }
+
+ else {
+ seek = (ULONG) (pste->ste_offset << psmte->smte_alignshift);
+ ByteOffset.LowPart = seek;
+ ByteOffset.HighPart = 0;
+ cbread = (ulong_t) ((pste->ste_size == 0) ? _64K :
+ pste->ste_size);
+ if ((Status = NtReadFile(pmte->mte_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ (void *) laddr,
+ cbread,
+ &ByteOffset,
+ 0)) != 0) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+ }
+ if (IoStatusBlock.Information != cbread)
+ return(ERROR_BAD_EXE_FORMAT);
+
+ if (pste->ste_size != 0) {
+ minsiz = (ulong_t) pste->ste_minsiz;
+ if (minsiz == 0) { /* size = 64k */
+ minsiz = 0x10000;
+ }
+ //
+ // Need to handle this special case because the segment
+ // is already set with the ring 2 xfer thunks
+ //
+ if (laddr != R2XFER_BASE) {
+ memset((void *) (laddr +
+ ((pste->ste_flags & STE_ITERATED) ?
+ IoStatusBlock.Status :
+ IoStatusBlock.Information)),
+ '\0',
+ (pste->ste_flags & STE_ITERATED) ?
+ minsiz - IoStatusBlock.Status :
+ minsiz - pste->ste_size);
+ }
+ }
+
+ /*
+ * HACK - This will check for Doscalls.dll and if it is
+ * the code segment it will search the code for the OPCodes
+ * "0xDD, 0x1f" which will be changed to a call to
+ * _EntryFlat
+ */
+ if (((pmte->mte_mflags & DOSLIB) != 0) &&
+ ((pste->ste_flags & STE_TYPE_MASK) == STE_CODE) &&
+ (!DoscallsLoaded)
+ ) {
+ pchar = (uchar_t *) laddr;
+ while(TRUE) {
+ while (*pchar++ != 0xdd &&
+ pchar < (uchar_t *) (laddr + cbread));
+ if (pchar == (uchar_t *) (laddr + cbread))
+ break;
+ if (*pchar == 0x1f) {
+ pchar--;
+ *((ULONG *) pchar) = Ol2EntryFlat;
+ break;
+ }
+ }
+ DoscallsLoaded = TRUE;
+ }
+ }
+
+ /*
+ * Process fixups if present
+ */
+ if (pste->ste_flags & STE_RELOCINFO) {
+
+ /*
+ * Read the number of relocation records
+ */
+ cbread = 2;
+ ByteOffset.LowPart += IoStatusBlock.Information;
+ if ((Status = NtReadFile(pmte->mte_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ &crelrecs,
+ cbread,
+ &ByteOffset,
+ 0 )) != 0) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+ if (IoStatusBlock.Information != cbread)
+ return(ERROR_BAD_EXE_FORMAT);
+
+ crecs = RELOCSPERBUF;
+ for (i = 0; i < crelrecs; i++, crecs++) {
+
+ if ((crecs % RELOCSPERBUF) == 0) {
+ if (crelrecs - i > RELOCSPERBUF)
+ cbread = RELOCBUFLEN;
+ else
+ cbread = (crelrecs - i) * sizeof(struct ri_s);
+
+ ByteOffset.LowPart += IoStatusBlock.Information;
+ if ((Status = NtReadFile(pmte->mte_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ &relocbuf,
+ cbread,
+ &ByteOffset,
+ 0)) != 0) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+ if (IoStatusBlock.Information != cbread)
+ return(ERROR_BAD_EXE_FORMAT);
+ crecs = 0;
+ }
+ pri = (ri_t *) &relocbuf[crecs * sizeof(struct ri_s)];
+
+ switch (pri->ri_flags & TARGET_MASK) {
+
+ case INTERNALREF: /* Internal fixup */
+
+ /*
+ * Check for fixed or movable
+ */
+ if (pri->ri_target_seg != B16MOVABLE) {
+ if ((ptgtste=ldrNumToSte(pmte,
+ pri->ri_target_seg
+ ))== NULL) {
+ return(ERROR_INVALID_SEGMENT_NUMBER);
+ }
+ taddr.tsel = ptgtste->ste_selector | 7;
+ taddr.toff = (ulong_t) pri->ri_target_off;
+ break;
+ }
+
+ /*
+ * A movable entry exists
+ */
+ else {
+ if ((rc = ldrGetEntAddr(pri->ri_target_off,
+ pmte,
+ &taddr,
+ pste,
+ pmte)) != NO_ERROR) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+ break;
+ }
+
+ case IMPORTNAME: /* Import by name fixup */
+ case IMPORTORDINAL: /* Import by ordinal fixup */
+
+ if ((rc = ldrGetTgtMte(pri->ri_target_modnam,
+ pmte,
+ &ptgtmte)) != NO_ERROR) {
+ return(rc);
+ }
+
+ ldrSetupTgtErrTxt(((char *) ptgtmte->mte_modname)+1,
+ (USHORT) *((char *) ptgtmte->mte_modname));
+
+ if ((pri->ri_flags & TARGET_MASK) == IMPORTNAME) {
+ pprocname = (uchar_t *) (psmte->smte_impproc +
+ (ulong_t) pri->ri_target_impnam);
+ if (pprocname[1] == '#') {
+//BUGBUG - convert routine from asm
+// ldrStop(0xffff, 0);
+// ord = (ushort_t) ldrAscToOrd(&pprocname[2],
+// (ushort_t) pprocname[0] - 1);
+ }
+ else {
+
+ ldrProcNameBufL = (USHORT) (pprocname[0]);
+ ldrProcNameBuf = (PUCHAR) (pprocname + 1);
+ if ((rc = ldrGetOrdNum(ptgtmte,
+ pprocname,
+ &ord,
+ STRINGNONNULL
+ )) != NO_ERROR) {
+ return(rc);
+ }
+ }
+ }
+ else {
+ ord = pri->ri_target_ord;
+ ldrProcNameBufL = 2;
+ ldrProcNameBuf = (PUCHAR) &pri->ri_target_ord;
+ }
+
+ if ((rc = ldrGetEntAddr(ord,
+ ptgtmte,
+ &taddr,
+ pste,
+ pmte)) != NO_ERROR) {
+#if DBG
+ DbgPrint("ldrLoadSegment: failed to locate ordinal %d in %s for %s\n",
+ pri->ri_target_ord,
+ 1+(char *) (ptgtmte->mte_modname),
+ 1+(char *) (pmte->mte_modname)
+ );
+#endif
+ return(rc);
+ }
+ ldrInvTgtErrTxt();
+ break;
+
+ default:
+ continue;
+
+ }
+
+ if ((rc = ldrDoFixups(pri, laddr, &taddr,
+ pste->ste_minsiz)) != NO_ERROR) {
+ return(rc);
+ }
+ }
+ }
+ return(rc);
+
+}
+
+
+/***LP ldrLoadIteratedData - load iterated data
+ *
+ * Reads the iterated data from the file, expands it and loads it into
+ * the segment.
+ *
+ * ENTRY
+ * pmte - pointer to mte
+ * pste - pointer to segment table
+ * pIoStatusBlock - pointer to IO status buffer
+ * laddr - address of page we are loading
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ */
+
+APIRET ldrLoadIteratedData(pmte, pste, pIoStatusBlock, laddr)
+ldrmte_t *pmte;
+ldrste_t *pste;
+PIO_STATUS_BLOCK pIoStatusBlock;
+ULONG laddr;
+
+{
+ ldrsmte_t *psmte;
+ ULONG IOcount = 0;
+ ULONG seek;
+ LARGE_INTEGER ByteOffset;
+ ULONG cbread;
+ int rc;
+ ULONG filedata;
+ ULONG segsize;
+ struct iter {
+ USHORT numberiter;
+ USHORT patternsize;
+ } iterdata;
+ ULONG expandsize;
+ ULONG temp;
+ ULONG i;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: ldrLoadIteratedData(pmte=%x) was called\n", pmte);
+ }
+#endif
+
+ psmte = pmte->mte_swapmte;
+ filedata = (ULONG) pste->ste_size; /* size of data */
+ if (filedata == 0) { /* check if file data = 64k */
+ filedata = 0x10000;
+ }
+
+ segsize = pste->ste_minsiz; /* size of segment */
+ if (segsize == 0) { /* check if size = 64k */
+ segsize = _64K;
+ }
+
+ seek = (ULONG) (pste->ste_offset << psmte->smte_alignshift);
+
+ while (TRUE) {
+
+ if (filedata < 3) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+
+ filedata -= 4;
+
+ if (filedata == 0) /* See if done */
+ break;
+
+ ByteOffset.LowPart = seek;
+ ByteOffset.HighPart = 0;
+ cbread = 4;
+ if ((rc = NtReadFile(pmte->mte_sfn,
+ 0,
+ 0,
+ 0,
+ pIoStatusBlock,
+ &iterdata,
+ cbread,
+ &ByteOffset,
+ 0)) != 0) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+
+ if (pIoStatusBlock->Information != cbread) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+
+ seek += 4; /* We read 4 bytes */
+ IOcount += pIoStatusBlock->Information;
+
+ if (iterdata.numberiter == 0 || iterdata.patternsize == 0)
+ continue;
+
+ filedata -= iterdata.patternsize;
+ if (filedata > 0xffff) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+
+ expandsize = (ULONG) (iterdata.patternsize * iterdata.numberiter);
+ if (expandsize > 0xffff) {
+ return(ERROR_ITERATED_DATA_EXCEEDS_64k);
+ }
+
+ segsize -= expandsize;
+ if (segsize > 0xffff) {
+ return(ERROR_INVALID_MINALLOCSIZE);
+ }
+
+ ByteOffset.LowPart = seek;
+ ByteOffset.HighPart = 0;
+ cbread = iterdata.patternsize;
+ if ((rc = NtReadFile(pmte->mte_sfn,
+ 0,
+ 0,
+ 0,
+ pIoStatusBlock,
+ (void *) laddr,
+ cbread,
+ &ByteOffset,
+ 0)) != 0) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+
+ if (pIoStatusBlock->Information != cbread) {
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+
+ seek += iterdata.patternsize;
+ IOcount += pIoStatusBlock->Information;
+
+ temp = laddr;
+ laddr += iterdata.patternsize;
+ for (i=1; i<iterdata.numberiter; i++) {
+ memmove((void *) laddr,
+ (void *) temp,
+ iterdata.patternsize);
+ laddr += iterdata.patternsize;
+ }
+
+ if (filedata == 0)
+ break;
+
+ }
+
+ pIoStatusBlock->Information = IOcount;
+ pIoStatusBlock->Status = laddr;
+
+ return(NO_ERROR);
+}
+
+
+/***LP ldrDoFixups - Do the fixups following the source chain
+ *
+ * Apply fixups to source
+*
+ *
+ * ENTRY pri - pointer to fixup record
+ * laddr - address of start of segment
+ * taddr - pointer to target address
+ * segsize - size of segment
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ */
+
+APIRET ldrDoFixups(pri, laddr, ptaddr, segsize)
+ri_t *pri; /* pointer to fixup record */
+ulong_t laddr; /* address of start of segment */
+struct taddr_s *ptaddr; /* target address */
+ushort_t segsize; /* size of segment */
+
+{
+ uchar_t *pcoffset;
+ ushort_t *psoffset;
+ ushort_t chain;
+ int count;
+ ulong_t segsize_l = RESIZE64K(segsize);
+
+#if DBG
+ IF_OL2_DEBUG ( FIXUP ) {
+ DbgPrint("OS2LDR: ldrDoFixups(): laddr=%x\n", laddr);
+ }
+#endif
+
+ chain = 1; /* we do at least one fixup */
+ count = (int) (segsize_l / sizeof(ushort_t));
+
+ if ((ulong_t)pri->ri_source > segsize_l)
+ return(ERROR_RELOC_CHAIN_XEEDS_SEGLIM);
+
+ pcoffset = (uchar_t *) (laddr + (ulong_t) pri->ri_source);
+
+ while (chain != 0xffff) {
+
+ if (!(pri->ri_flags & ADDITIVE))
+ chain = *((ushort_t *) pcoffset);
+ else
+ chain = 0xffff;
+
+ switch(pri->ri_stype & SOURCE_MASK) {
+
+ case BYTE_ADR:
+ if (pri->ri_flags & ADDITIVE)
+ *pcoffset += (uchar_t) (ptaddr->toff & BYTEMASK);
+ else
+ *pcoffset = (uchar_t) (ptaddr->toff & BYTEMASK);
+ break;
+ case SEG_ADR:
+ psoffset = (ushort_t *) pcoffset;
+ if (pri->ri_flags & ADDITIVE)
+ *psoffset += ptaddr->tsel;
+ else
+ *psoffset = ptaddr->tsel;
+ break;
+ case FAR_ADR:
+ psoffset = (ushort_t *) pcoffset;
+ if (pri->ri_flags & ADDITIVE) {
+ *psoffset += (ushort_t) (ptaddr->toff & WORDMASK);
+ psoffset++;
+ *psoffset += ptaddr->tsel;
+ }
+ else {
+ *psoffset = (ushort_t) (ptaddr->toff & WORDMASK);
+ psoffset++;
+ *psoffset = ptaddr->tsel;
+ }
+ break;
+ case OFF_ADR:
+ psoffset = (ushort_t *) pcoffset;
+ if (pri->ri_flags & ADDITIVE) {
+ *psoffset += (ushort_t) (ptaddr->toff & WORDMASK);
+ }
+ else {
+ *psoffset = (ushort_t) (ptaddr->toff & WORDMASK);
+ }
+ }
+ if (!(pri->ri_flags & ADDITIVE)) {
+ if (chain != 0xffff && (ulong_t)chain > segsize_l)
+ return(ERROR_RELOC_CHAIN_XEEDS_SEGLIM);
+
+ pcoffset = (uchar_t *) (laddr + (ulong_t) chain);
+ }
+
+ if (--count < 0) { // check for internal loops
+ return(ERROR_RELOC_CHAIN_XEEDS_SEGLIM);
+ }
+ }
+
+ return(NO_ERROR);
+
+}
diff --git a/private/os2/ldr/ldrsubr.c b/private/os2/ldr/ldrsubr.c
new file mode 100644
index 000000000..e8f9ff357
--- /dev/null
+++ b/private/os2/ldr/ldrsubr.c
@@ -0,0 +1,1962 @@
+#include <os2tile.h>
+
+#include "ldrextrn.h"
+
+#define TRC_C_SUC_ret 0
+#define TRC_C_LIB_ret -8
+
+VOID
+ldrClearAllMteFlag(
+ IN ULONG Flags
+ )
+{
+ ldrmte_t *pmte;
+
+ //
+ // Clear specific flags of all modules
+ //
+ pmte = mte_h;
+ while (pmte != NULL) {
+ pmte->mte_mflags &= ~Flags;
+ pmte = pmte->mte_link;
+ }
+}
+
+ //
+ // This is set to interface the assembly routine
+ // _ldrSetDescInfo in i386\ldrstart.asm
+ // Such that it is immune to kernel changes
+ //
+
+NTSTATUS
+SetLDT(
+ IN HANDLE ProcessHandle,
+ IN PROCESSINFOCLASS ProcessInformationClass,
+ IN PVOID ProcessInformation,
+ IN ULONG ProcessInformationLength
+ )
+{
+ UNREFERENCED_PARAMETER(ProcessInformationClass);
+ return NtSetInformationProcess (ProcessHandle,
+ ProcessLdtInformation,
+ ProcessInformation,
+ ProcessInformationLength);
+
+}
+
+/***LP ldrEachObjEntry - scan entry table entries for given object(s)
+ *
+ * Scan the entry table entries for the matching object and
+ * call the worker routine for processing at each entry.
+ *
+ * The worker routines are:
+ * ldrEditProlog
+ * ldrGetCallGate
+ * ldrInitEntry
+ * ldrFreeLDTGate
+ * ldrFreeCallGate
+ *
+ * ENTRY objnum - number of object to search for
+ * 0 - match all objects
+ * pmte - pointer to module table entry
+ * pworker - pointer to worker routine
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ */
+
+int ldrEachObjEntry(
+ULONG objnum, /* object number to search on */
+register ldrmte_t *pmte, /* pointer to object table entry */
+int (*pworker)(ldret_t *pet, ulong_t *pentry,
+ ldrmte_t *pmte, ldrlv_t *plv),/* pointer to worker routine */
+ldrlv_t *plv /* pointer to local vars */
+)
+{
+ register ldrsmte_t *psmte; /* pointer to swappable mte */
+ USHORT etobj; /* object number from entry table */
+ ULONG pentry; /* pointer to entry table entry */
+ struct ExpHdr *pexpdir; /* pointer to export directory */
+ ULONG i;
+ int rc;
+
+ /*
+ * validate mte pointer
+ */
+ if (!fMTEValid(pmte))
+ ASSERT("Eachobjentry: Invalid MTE");
+
+ psmte = pmte->mte_swapmte;
+
+ if (ldrIsNE(pmte)) { /* process 16-bit module */
+ register ldret_t *pet; /* pointer to entry table */
+
+ /*
+ * does module contain an entry table
+ */
+ if ((pet = (ldret_t *) (psmte->smte_enttab)) == 0)
+ return(NO_ERROR);
+
+ while (TRUE) {
+ if (pet->et_cnt == 0) /* check for end of table */
+ return(NO_ERROR);
+
+ if (pet->et_type == EMPTY) { /* check for empty bundle */
+ (ULONG) pet += (ULONG) ldrSkipEnts(pmte, pet->et_type,
+ (UCHAR) pet->et_cnt);
+ continue;
+ }
+
+ /*
+ * skip over count and type fields
+ */
+ pentry = (ULONG) pet +
+ (ULONG) ldrSkipEnts(pmte, pet->et_type, 0);
+
+ /*
+ * call routine for each entry
+ */
+ for (i = 1; i <= (ULONG) pet->et_cnt; i++) {
+ if (pet->et_type == B16MOVABLE)
+ etobj = (USHORT) (((ldrcte_t *) pentry)->cte_obj);
+ else
+ etobj = pet->et_type;
+ if ((objnum == 0) || (objnum == (ULONG) etobj)) {
+ /*
+ * call worker routine
+ */
+ if ((rc = pworker(pet, (PULONG) pentry, pmte,
+ plv)) != NO_ERROR)
+ return(rc);
+ }
+ if (pet->et_type == B16MOVABLE)
+ pentry += sizeof(ldrcte_t);
+ else
+ pentry += sizeof(ldrent_t);
+ }
+ (ULONG) pet += pentry - (ULONG) pet;
+
+ }
+ }
+ else { /* 32-bit module */
+ register PULONG peat; /* pointer to export addr tb entry */
+
+ pexpdir = (struct ExpHdr *) psmte->smte_expdir;
+ peat = (ULONG *) ((ULONG) pexpdir + pexpdir->exp_eat);
+ i = pexpdir->exp_eatcnt;
+ for (; i--; peat++) {
+
+ /*
+ * call worker routine
+ */
+ if ((rc = pworker(NULL, peat, pmte, plv)) != NO_ERROR)
+ return(rc);
+ }
+ }
+
+ return(NO_ERROR);
+
+}
+
+
+/***LP ldrSkipEnts - skip the given number of entries in the entry table
+ *
+ * For a given number, return the number of bytes to skip to the
+ * next bundle in the entry table.
+ *
+ * ENTRY pmte - pointer to mte for this module
+ * type - the type of bundle to skip
+ * count - the number of entries in this bundle
+ *
+ * EXIT count of byte to skip to get to desired entry
+ *
+ * This procedure performs the following steps:
+ *
+ * - determines the type of module
+ * - returns the number of bytes to skip based on entry type
+ */
+
+ulong_t ldrSkipEnts(pmte, type, count)
+ldrmte_t *pmte;
+uchar_t type;
+uchar_t count;
+{
+ if (ldrIsNE(pmte)) /* check for 16-bit module */
+ switch (type) {
+
+ case B16EMPTY: /* unused bundle */
+ return(sizeof(ldrempty_t));
+
+ case B16MOVABLE: /* movable object */
+ return(sizeof(ldrempty_t) + sizeof(ldrcte_t) * count);
+
+ default: /* fixed object */
+ return(sizeof(ldrempty_t) + sizeof(ldrent_t) * count);
+ }
+ else { /* 32-bit module */
+ ldrAssert(FALSE); /* should not get here */
+ }
+}
+
+
+/***LP ldrInitEntry - Zero initialize INT 3Fh in movable entries
+ *
+ * For ring 2 segments the callgate selector overlays the int 3fh
+ * instruction in a movable entry table entry. This value is
+ * intitialized to zero to indicate that the callgate has not yet
+ * been allocated. Also for 16-bit modules that are pageable, check
+ * to see if any exported procedure entries cross a page boundary.
+ * (Called from CreateMTE)
+ *
+ * ENTRY pet - pointer to entry table bundle
+ * pentry - pointer to entry table entry
+ * pmte - pointer to module table entry
+ * plv - pointer to local vars
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ * This procedure performs the following steps
+ *
+ * - check for movable entry
+ * - zero entry
+ */
+
+int ldrInitEntry(pet, pentry, pmte, plv)
+ldret_t *pet; /* pointer to entry table bundle */
+PULONG pentry; /* pointer to entry table entry */
+ldrmte_t *pmte; /* pointer to module table entry */
+ldrlv_t *plv; /* pointer to local vars */
+{
+ UCHAR flags;
+ USHORT offset;
+ USHORT obj;
+
+ UNREFERENCED_PARAMETER(plv);
+
+ if (ldrIsNE(pmte)) { /* 16-bit module */
+
+ flags = ((ldrent_t *) pentry)->ent_flags;
+
+ /*
+ * Check to see if have an exported entry point which is not a
+ * library module or a library module which has global data.
+ */
+ if (flags & EF_EXPORT && !(pmte->mte_mflags & LIBRARYMOD) ||
+ (pmte->mte_mflags & LIBRARYMOD && flags & EF_GDATA)) {
+
+ /*
+ * Remove offset and object number from entry table bundle
+ */
+ if (pet->et_type == B16MOVABLE) {
+ offset = ((ldrcte_t *) pentry)->cte_off;
+ obj = ((ldrcte_t *) pentry)->cte_obj;
+ }
+ else {
+ offset = ((ldrent_t *) pentry)->ent_off;
+ obj = pet->et_type;
+ }
+ }
+
+ /*
+ * check for movable entry
+ */
+ if (pet->et_type != B16MOVABLE)
+ return(NO_ERROR);
+ /*
+ * init callgate selector to 0
+ */
+ ((ldrcte_t *)pentry)->cte_sel = 0;
+
+ }
+
+ else { /* 32-bit module */
+ /*
+ * We do not need to do anything for 32-bit modules
+ */
+ return(ERROR_BAD_EXE_FORMAT);
+ }
+
+ return(NO_ERROR);
+}
+
+
+/***LP ldrEditProlog - Edit prolog for shared data segment
+ *
+ * ENTRY pet - pointer to entry table bundle
+ * pentry - pointer to entry table entry
+ * pmte - pointer to module table entry
+ * plv - pointer to local vars
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ * This procedure performs the following steps
+ *
+ * - check for special hard coded prologs to functions
+ * - modify the prologs
+ */
+
+int ldrEditProlog(pet, pentry, pmte, plv)
+ldret_t *pet; /* pointer to entry table bundle */
+PULONG pentry; /* pointer to entry table entry */
+ldrmte_t *pmte; /* pointer to module table entry */
+ldrlv_t *plv; /* pointer to local vars */
+{
+ UCHAR flags;
+ USHORT offset;
+ USHORT obj;
+ USHORT SharedDataSeg;
+ PUCHAR laddr;
+ ldrsmte_t *psmte;
+ ldrste_t *pste;
+ ULONG tmp_opcodes;
+
+ UNREFERENCED_PARAMETER(plv);
+
+ flags = ((ldrent_t *) pentry)->ent_flags;
+ //
+ // Check for prolog editing
+ //
+ if ((flags & EF_EXPORT) == 0) {
+ return(NO_ERROR);
+ }
+
+//#if DBG
+// DbgPrint("OS2LDR: ldrEditProlog: Processing %s\n", (PCHAR)pmte->mte_modname + 1);
+//#endif
+ /*
+ * Remove offset and object number from entry table bundle
+ */
+ if (pet->et_type == B16MOVABLE) {
+ //
+ // This is a moveable entry table entry
+ //
+ offset = ((ldrcte_t *) pentry)->cte_off;
+ obj = ((ldrcte_t *) pentry)->cte_obj;
+ }
+ else if (pet->et_type == B16ABSOLUTE) {
+ //
+ // This is an absolute entry table entry
+ //
+ return(NO_ERROR);
+ }
+ else {
+ //
+ // This is a fixed entry table entry
+ //
+ offset = ((ldrent_t *) pentry)->ent_off;
+ obj = pet->et_type;
+ }
+
+ psmte = pmte->mte_swapmte;
+ if (psmte->smte_autods == 0) {
+ return(NO_ERROR);
+ }
+ pste = ldrNumToSte(pmte, psmte->smte_autods);
+ SharedDataSeg = pste->ste_selector | 7;
+ if (SharedDataSeg == 0) {
+ ASSERT(FALSE);
+#if DBG
+ DbgPrint("OS2LDR: Strange DLL: %s, Segment %d\n",
+ (PCHAR)pmte->mte_modname + 1, obj);
+#endif
+ }
+ pste = ldrNumToSte(pmte, obj);
+ laddr = (PCHAR)SELTOFLAT(pste->ste_selector) + offset;
+ tmp_opcodes = (*(PULONG)laddr)&0x00FFFFFF;
+ if ((tmp_opcodes == 0x90D88C) || // MOV AX,DS + NOP
+ (tmp_opcodes == 0x90581e)) // PUSH DS + POP AX + NOP
+ {
+//#if DBG
+// DbgPrint("OS2LDR: Updating addr %x\n", laddr);
+//#endif
+ *laddr++ = (UCHAR)0xB8;
+ *(PUSHORT)laddr = SharedDataSeg;
+ }
+
+ return(NO_ERROR);
+}
+
+/***LP ldrGetCallGate - Create a call gate for ring 2 entries
+ *
+ * ENTRY pet - pointer to entry table bundle
+ * pentry - pointer to entry table entry
+ * pmte - pointer to module table entry
+ * plv - pointer to local vars
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ * This procedure performs the following steps
+ *
+ * - check for movable entry
+ * - zero entry
+ */
+
+int ldrGetCallGate(pet, pentry, pmte, plv)
+ldret_t *pet; /* pointer to entry table bundle */
+PULONG pentry; /* pointer to entry table entry */
+ldrmte_t *pmte; /* pointer to module table entry */
+ldrlv_t *plv; /* pointer to local vars */
+{
+ ldrste_t *pste;
+ UCHAR flags;
+ ULONG CallGateOffset;
+ PR2CallInfo pR2CallEntry;
+
+ UNREFERENCED_PARAMETER(plv);
+
+ flags = ((ldrent_t *) pentry)->ent_flags;
+ //
+ // Check for valid entry for callgate
+ //
+ if (((flags & EF_EXPORT) == 0) ||
+ (pet->et_type != B16MOVABLE)
+ ) {
+ return(NO_ERROR);
+ }
+
+//#if DBG
+// DbgPrint("OS2LDR: ldrGetCallGate: Processing %s\n", (PCHAR)pmte->mte_modname + 1);
+//#endif
+ //
+ // Allocate a call gate and place it in the entry
+ //
+ CallGateOffset = ldrAllocateCallGate();
+ if (CallGateOffset == -1) {
+#if DBG
+ KdPrint(("OS2LDR: cannot allocate call gate\n"));
+#endif
+ return(ERROR_INVALID_CALLGATE);
+ }
+
+ ((ldrcte_t *) pentry)->cte_sel = (ushort_t)CallGateOffset;
+ pR2CallEntry = (PR2CallInfo)(R2XFER_BASE + CallGateOffset);
+ pR2CallEntry->R2CallNearInst = 0xE8;
+ pR2CallEntry->R2CommonEntry = (USHORT)(0 - (CallGateOffset + 3));
+ pR2CallEntry->R2BytesToCopy = (((ldrcte_t *) pentry)->cte_flags & 0xF8) >> 2;
+ pR2CallEntry->R2EntryPointOff = ((ldrcte_t *) pentry)->cte_off;
+ pste = ldrNumToSte(pmte, ((ldrcte_t *) pentry)->cte_obj);
+ pR2CallEntry->R2EntryPointSel = pste->ste_selector | 7; // force ring 3
+
+ return(NO_ERROR);
+}
+
+
+/***LP ldrFreeCallGate - Free the call gate stubs for ring 2 entries
+ *
+ * ENTRY pet - pointer to entry table bundle
+ * pentry - pointer to entry table entry
+ * pmte - pointer to module table entry
+ * plv - pointer to local vars
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ *
+ * This procedure performs the following steps
+ *
+ * - check for movable entry
+ * - mark the call gate entry as free
+ */
+
+int ldrFreeCallGate(pet, pentry, pmte, plv)
+ldret_t *pet; /* pointer to entry table bundle */
+ulong_t *pentry; /* pointer to entry table entry */
+ldrmte_t *pmte; /* pointer to module table entry */
+ldrlv_t *plv; /* pointer to local vars */
+{
+ UCHAR flags;
+ ULONG CallGateOffset;
+ PR2CallInfo pR2CallEntry;
+
+ UNREFERENCED_PARAMETER(plv);
+
+ flags = ((ldrent_t *) pentry)->ent_flags;
+ //
+ // Check for valid entry for callgate
+ //
+ if (((flags & EF_EXPORT) == 0) ||
+ (pet->et_type != B16MOVABLE)
+ ) {
+ return(NO_ERROR);
+ }
+
+//#if DBG
+// DbgPrint("OS2LDR: ldrFreeCallGate: Processing %s\n", (PCHAR)pmte->mte_modname + 1);
+//#endif
+ //
+ // Free the call gate
+ //
+ CallGateOffset = ((ldrcte_t *) pentry)->cte_sel;
+ if ((CallGateOffset == 0) ||
+ (CallGateOffset == 0x3fcd)
+ ) {
+#if DBG
+ KdPrint(("OS2LDR: OK to ignore non-initialized call gate 0x%x when app loading fails\n",
+ CallGateOffset));
+#endif
+ return(NO_ERROR);
+ }
+ ldrDeallocateCallGate(CallGateOffset);
+ pR2CallEntry = (PR2CallInfo)(R2XFER_BASE + CallGateOffset);
+ pR2CallEntry->R2CallNearInst = 0;
+ pR2CallEntry->R2CommonEntry = 0;
+ pR2CallEntry->R2BytesToCopy = 0;
+ pR2CallEntry->R2EntryPointOff = 0;
+ pR2CallEntry->R2EntryPointSel = 0;
+ return(NO_ERROR);
+}
+
+
+/***LP ldrSetLoaded - set MTEPROCESSED bit in the module flags for all mtes.
+ *
+ *
+ * ENTRY none
+ *
+ * EXIT none
+ *
+ * This procedure performs the following steps
+ *
+ */
+
+void ldrSetLoaded()
+{
+ register ldrmte_t *pmte; /* pointer to a module table entry */
+
+ /*
+ * scan list of mtes til end of list is found
+ */
+ for (pmte = mte_h; pmte != NULL; pmte = (ldrmte_t *)pmte->mte_link) {
+ /*
+ * check if mte valid yet
+ */
+ if (pmte->mte_mflags & MTEVALID)
+ pmte->mte_mflags |= MTEPROCESSED; /* mark as loaded */
+ pmte->mte_mflags &= ~MTENEWMOD;
+ }
+}
+
+
+/***LP ldrNumToOte - validate object number and return ote address
+ *
+ * Given a object number, check if object exists in current mte,
+ * and return a pointer to the object table entry.
+ *
+ * ENTRY pmte - pointer to module table entry
+ * objnum - object number to check for
+ *
+ * EXIT pointer to object table entry for object
+ * or 0 for object not present
+ */
+
+ldrote_t *ldrNumToOte(pmte, objnum)
+register ldrmte_t *pmte; /* pointer to a module table entry */
+ulong_t objnum; /* object number to check for */
+{
+ register ldrsmte_t *psmte; /* pointer to swappable mte */
+
+ psmte = pmte->mte_swapmte;
+
+ if (objnum-- <= psmte->smte_objcnt) {
+ if (ldrIsNE(pmte)) /* is this a 16-bit module */
+ return((ldrote_t *)&(((ldrste_t *)psmte->smte_objtab)[objnum]));
+ else
+ return(&(((ldrote_t *)psmte->smte_objtab)[objnum]));
+ }
+ return(0);
+}
+
+
+/***LP LDRStop - stop in kernel debugger
+ *
+ * If the global DBG is TRUE print a debug message
+ *
+ * LDRStop (id, pmte)
+ *
+ * ENTRY id - identifier of caller (ignored)
+ * pmte - mte pointer or NULL
+ * RETURN NONE
+ *
+ * CALLS DbgUserBreakPoint
+ *
+ * EFFECTS NONE
+ */
+void LDRStop(id, pmte)
+int id;
+void *pmte;
+
+{
+ UNREFERENCED_PARAMETER(id);
+ UNREFERENCED_PARAMETER(pmte);
+
+#if DBG
+ DbgPrint("ldrStop\n");
+// DbgUserBreakPoint();
+#endif
+
+}
+
+
+/***LP ldrFindMTEForHandle - Find MTE for given handle
+ *
+ * ENTRY handle - 16-bit handle
+ *
+ * EXIT pointer to mte or 0 for not present
+ */
+ldrmte_t *ldrFindMTEForHandle(hmte)
+USHORT hmte;
+
+{
+ ldrmte_t *pmte;
+
+ pmte = mte_h;
+
+ while (pmte != 0) {
+ if (pmte->mte_handle == hmte)
+ break;
+ pmte = pmte->mte_link;
+ }
+
+ return(pmte);
+
+}
+
+/***LP ldrFindSegForHandleandNum - Given a Handle and a seg number,
+ * return the selector
+ *
+ */
+USHORT ldrFindSegForHandleandNum(inmte, handle, segnum)
+USHORT inmte;
+USHORT handle;
+USHORT segnum;
+
+{
+ ldrmte_t *pmte;
+ ldrste_t *pste;
+
+
+ if (inmte){
+ pmte = ldrFindMTEForHandle(inmte);
+ }
+ else {
+ pmte = ldrFindMTEForHandle(handle);
+ if (pmte == NULL) {
+ return(0);
+ }
+ }
+
+ pste = ldrNumToSte(pmte, segnum);
+
+ if (pste == NULL){
+ return(0);
+ }
+
+ return(pste->ste_selector);
+
+}
+
+// ldrFindDLDForHandle - Find the DLD which points to the
+// requested handle.
+//
+// ENTRY pmte_prog - MTE ptr of the process MTE
+// handle - Handle of module
+//
+// EXIT Pointer to the DLD if the module belongs to the process
+// NULL otherwise
+//
+ldrdld_t *
+ldrFindDLDForHandle(
+ ldrmte_t *pmte_prog,
+ USHORT handle
+ )
+{
+ ldrdld_t *pdld;
+
+ pdld = pmte_prog->mte_dldchain;
+ while (pdld != NULL) {
+ if ((pdld->Cookie == (ULONG)CurrentThread->Process) &&
+ (pdld->dld_mteptr->mte_handle == handle)) {
+ break;
+ }
+ pdld = pdld->dld_next;
+ }
+ return(pdld);
+}
+
+// ModuleIsAttachedToProcess - Verify that a module that was statically
+// loaded at process start belongs to the
+// current procee
+//
+// ENTRY pmte_prog - MTE ptr of the process MTE
+// pmte - MTE ptr of the module MTE
+//
+// EXIT TRUE if the module belongs to the process
+// FALSE otherwise
+//
+BOOLEAN
+ModuleIsAttachedToProcess(
+ ldrmte_t *pmte_cur,
+ ldrmte_t *pmte
+ )
+{
+ ldrmte_t **ppmte;
+ ULONG lindex;
+ ULONG i;
+
+ if (pmte_cur == pmte) {
+ return(TRUE);
+ }
+ pmte_cur->mte_mflags |= INGRAPH;
+
+ ppmte = (ldrmte_t **) pmte_cur->mte_modptrs;
+ for (i = 1; i <= pmte_cur->mte_impmodcnt; i++) {
+ /*
+ * It is required for 16-bit modules to load the
+ * referneced module in reverse order.
+ */
+ lindex = pmte_cur->mte_impmodcnt-i;
+
+ //
+ // Check if the referenced module has already been processed.
+ // Processing the modules is done in reverse order.
+ //
+ if ((ppmte[lindex]->mte_mflags & INGRAPH) == 0) {
+ if (ModuleIsAttachedToProcess(ppmte[lindex], pmte)) {
+ return(TRUE);
+ }
+ }
+ }
+ return(FALSE);
+}
+
+// ModuleLoadedForProcess - Verify that a loaded module belongs
+// to the current procee
+//
+// ENTRY pmte_prog - MTE ptr of the process MTE
+// pmte - MTE ptr of the module MTE
+//
+// EXIT TRUE if the module belongs to the process
+// FALSE otherwise
+//
+BOOLEAN
+ModuleLoadedForProcess(
+ ldrmte_t *pmte_prog,
+ ldrmte_t *pmte
+ )
+{
+ ldrdld_t *pdld;
+
+ ldrClearAllMteFlag(INGRAPH); // Clear INGRAPH flag. We might start
+ // recursive search for module.
+
+ pdld = pmte_prog->mte_dldchain;
+ while (pdld != NULL) {
+ if (pdld->Cookie == (ULONG)CurrentThread->Process) {
+ if(pdld->dld_mteptr == pmte) {
+ return(TRUE);
+ }
+ // Check if module was attached to the module
+ // that was loaded dynamically.
+ else {
+ if (ModuleIsAttachedToProcess(pdld->dld_mteptr, pmte)) {
+ return(TRUE);
+ }
+ }
+ }
+ pdld = pdld->dld_next;
+ }
+
+ return (ModuleIsAttachedToProcess(pmte_prog, pmte));
+}
+
+// ldrCreateDLDRecord - Create a DLD record for the new module
+//
+// ENTRY pmte_prog - MTE ptr of the process MTE
+// pmte - MTE ptr of the module MTE
+// DLDExists - Pointer to BOOLEAN variable which is set to
+// TRUE if the module was already loaded by this program
+// FALSE if the module is a new module for the program
+//
+// EXIT rc - return value indicating the success o fthe function
+//
+APIRET
+ldrCreateDldRecord(
+ ldrmte_t *pmte_prog, /* Pointer to process MTE */
+ ldrmte_t *pmte, /* Pointer to new loaded module's MTE */
+ BOOLEAN *DLDExisted /* Flag indicating if the DLD already existed */
+ )
+{
+ ldrdld_t *pdld;
+
+ pdld = pmte_prog->mte_dldchain;
+ while (pdld != NULL) {
+ if ((pdld->Cookie == (ULONG)CurrentThread->Process) &&
+ (pdld->dld_mteptr == pmte)) {
+ //
+ // A DLD which references the newly loaded module was found
+ //
+ pdld->dld_usecnt++;
+ *DLDExisted = TRUE;
+ return(NO_ERROR);
+ }
+ pdld = pdld->dld_next;
+ }
+ //
+ // The newly loaded module is not referenced yet in the DLD chain.
+ // Create and link a new record into the chain.
+ //
+ pdld = RtlAllocateHeap(LDRNEHeap, 0, sizeof(ldrdld_t));
+ if (pdld == NULL) {
+ *DLDExisted = FALSE;
+ return(ERROR_NOT_ENOUGH_MEMORY);
+ }
+ pdld->dld_usecnt = 1;
+ pdld->dld_mteptr = pmte;
+ pdld->Cookie = (ULONG)CurrentThread->Process;
+ pdld->dld_next = pmte_prog->mte_dldchain;
+ pmte_prog->mte_dldchain = pdld;
+ *DLDExisted = FALSE;
+ return(NO_ERROR);
+}
+
+/***EP LDRDosLoadModule - Load dynamic link library module.
+ *
+ * This routine loads a dynamic link library module and returns
+ * a handle for the library.
+ *
+ * ENTRY pszFailName - ptr to buffer for name if failure
+ * cbFileName - length of buffer for name if failure
+ * pszModName - ptr to module name
+ * phmod - ptr to module handle
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ * pexec_info structure set
+ */
+
+BOOLEAN
+LDRDosLoadModule(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRLOADMODULE_MSG a = &m->u.LdrLoadModule;
+ USHORT class;
+ ldrmte_t *pmte_prog; /* Pointer to process MTE */
+ ldrmte_t *pmte;
+ ldrmte_t *ptmte;
+ ldrdld_t *pdld;
+ BOOLEAN DLDExisted;
+ int rc;
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: DosLoadModule() was called\n");
+ }
+#endif
+
+ CurrentThread = t;
+
+ //
+ // Set the fForceUnmap flag to TRUE so that ldrUnloadTagedModules()
+ // does unmap the app's freed segments from the app's address space.
+ //
+ fForceUnmap = TRUE;
+
+ //
+ // Clear the INGRAPH and USE flags of all modules so that we
+ // know that this module has already been processed
+ //
+ ldrClearAllMteFlag(INGRAPH | USED);
+
+ //
+ // Tag all referenced modules with the USED flag
+ // so that they are not loaded again
+ //
+ pmte = t->Process->ProcessMTE;
+ ldrTagModuleTree_USED(pmte);
+ for (pdld = pmte->mte_dldchain; pdld != NULL; pdld = pdld->dld_next) {
+ if (pdld->Cookie == (ULONG)CurrentThread->Process) {
+ ldrTagModuleTree_USED(pdld->dld_mteptr);
+ }
+ }
+ ldrClearAllMteFlag(INGRAPH);
+
+ //
+ // Init the Library Intialization routines data structure
+ //
+ pldrLibiRecord = (ldrlibi_t *)a->InitRecords.Buffer;
+ pldrLibiCounter = &a->NumOfInitRecords;
+ *pldrLibiCounter = 0;
+
+ //
+ // init the pointer to the error string
+ //
+ pErrText = &a->FailName;
+
+ /*
+ * Point to ldrLibPathBuf to contain the environment string
+ */
+ strncpy(ldrLibPathBuf, a->LibPathName.Buffer, SizeOfldrLibPathBuf);
+ ldrLibPathBuf[SizeOfldrLibPathBuf-1] = '\0';
+
+#ifndef DBCS // MSKK Aug.20.1993 V-AkihiS
+ /*
+ * Check for any meta characters
+ */
+ if (strpbrk(a->ModuleName.Buffer, "*?") != NULL) {
+ m->ReturnedErrorValue = ERROR_INVALID_NAME;
+ return(TRUE);
+ }
+
+ if ((strchr(a->ModuleName.Buffer, '.') != NULL) &&
+ (strpbrk(a->ModuleName.Buffer, "\\/") == NULL)
+ ) {
+ m->ReturnedErrorValue = ERROR_FILE_NOT_FOUND;
+ return(TRUE);
+ }
+#endif
+
+ /*
+ * Check if module we are loading has any path characters
+ */
+ if (strpbrk(a->ModuleName.Buffer, ":\\/.") == NULL)
+ class = CLASS_GLOBAL;
+ else
+ class = CLASS_SPECIFIC;
+
+ if ((rc = ldrGetModule(a->ModuleName.Buffer,
+ a->ModuleName.Length,
+ (char)EXT_LIBRARY,
+ class,
+ &pmte,
+ NULL,
+ NULL)) == NO_ERROR) {
+ pmte_prog = (ldrmte_t *)t->Process->ProcessMTE;
+ ASSERT(pmte_prog != NULL);
+ rc = ldrCreateDldRecord(pmte_prog, pmte, &DLDExisted);
+ if (rc != NO_ERROR) {
+ ldrUnloadTagedModules(t->Process);
+ m->ReturnedErrorValue = rc;
+ return(TRUE);
+ }
+ a->ModuleHandle = pmte->mte_handle;
+ //
+ // Increment the usecnt of the referenced modules
+ //
+ if (!DLDExisted) {
+ ptmte = mte_h;
+ while (ptmte != NULL) {
+ if ((ptmte->mte_mflags & INGRAPH) != 0) {
+ ptmte->mte_usecnt++;
+ }
+ ptmte = ptmte->mte_link;
+ }
+ }
+ /*
+ * get module startup parameters
+ */
+ rc = ldrGetModParams(CurrentThread->Process->ProcessMTE,
+ (ldrrei_t *)&a->ExecInfo
+ );
+#if DBG
+ IF_OL2_DEBUG ( MTE ) {
+ DbgPrint("\nDumping segmenst after DosLoadModule() processing\n");
+ ldrDisplaySegmentTable();
+ }
+#endif
+
+ }
+ else {
+ ldrWriteErrTxt(rc);
+ ldrUnloadTagedModules(t->Process);
+ }
+
+ m->ReturnedErrorValue = rc;
+ return(TRUE);
+}
+
+
+/***EP LDRDosGetProcAddr - Get dynamic link procedure address
+ *
+ *
+ * ENTRY hmte Module handle returned by DOSLOADMODULE
+ * pchname ASCIIZ name of procedure.
+ * paddress Ptr to where the address should be returned.
+ *
+ * EXIT NO_ERROR paddress has the valid address
+ * ERROR_PROC_NOT_FOUND
+ */
+
+BOOLEAN
+LDRDosGetProcAddr(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRGETPROCADDR_MSG a = &m->u.LdrGetProcAddr;
+ ldrmte_t *pmte_prog; /* Pointer to process MTE */
+ ldrmte_t *pmte; /* Pointer to MTE */
+ struct taddr_s taddr;
+ int cch; /* Length of name */
+ ulong_t ulord;
+ int rc; /* Return code */
+
+ CurrentThread = t;
+
+ do { /* Dummy loop */
+ //
+ // Verify that the module belongs to the current process
+ //
+ pmte_prog = (ldrmte_t *)t->Process->ProcessMTE;
+ ASSERT(pmte_prog != NULL);
+
+ pmte = ldrFindMTEForHandle((USHORT)a->ModuleHandle);
+ if (pmte == NULL) {
+ rc = ERROR_INVALID_HANDLE;
+ break;
+ }
+ if (!ModuleLoadedForProcess(pmte_prog, pmte)) {
+ rc = ERROR_INVALID_HANDLE;
+ break;
+ }
+
+ /*
+ * See if name specified
+ */
+ if (!a->ProcNameIsOrdinal) {
+ cch = a->ProcName.Length;
+ if (cch > MAX_PROC_LEN) {
+ rc = ERROR_INVALID_NAME;
+ break; /* Exit */
+ }
+
+ if (a->ProcName.Buffer[0] != '#') {
+
+ rc = ldrGetOrdNum(pmte,
+ a->ProcName.Buffer,
+ (PUSHORT) &ulord,
+ STRINGNULLTERM);
+
+ if (rc != NO_ERROR)
+ break; /* Exit if name not found */
+ }
+
+ else {
+ ulord = atol(&a->ProcName.Buffer[1]);
+ }
+
+ }
+ else {
+ ulord = a->OrdinalNumber;
+ }
+
+ memset(&taddr, 0, sizeof(taddr));
+ rc = ldrGetEntAddr((USHORT) ulord,
+ pmte,
+ &taddr,
+ NULL,
+ NULL);
+
+ if (rc != NO_ERROR)
+ break; /* Break if error */
+
+ ldrAssert(taddr.toff < _64K);
+ taddr.toff += (ulong_t) taddr.tsel << WORDSHIFT;
+ a->ProcAddr = (ULONG) taddr.toff;
+
+ } while(FALSE); /* End dummy loop */
+ m->ReturnedErrorValue = rc; /* Return error code */
+ return(TRUE);
+}
+
+
+/***EP LDRDosGetModName - Retrieves the filename of the specified module.
+ *
+ *
+ * ENTRY hMod module handle
+ * cbBuf number of bytes in buffer
+ * pchBuf pointer to buffer to receiving module name
+ *
+ * EXIT NO_ERROR
+ * ERROR_MOD_NOT_FOUND
+ */
+
+BOOLEAN
+LDRDosGetModName(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRGETMODULENAME_MSG a = &m->u.LdrGetModuleName;
+ ldrmte_t *pmte;
+ ldrsmte_t *psmte;
+
+ CurrentThread = t;
+
+ //
+ // Verify that a module with the specified handle does exist.
+ // The module can belong to any process in the system!
+ // (found while running the PM code)
+ //
+ pmte = ldrFindMTEForHandle((USHORT)a->ModuleHandle);
+ if (pmte == NULL) {
+ m->ReturnedErrorValue = ERROR_INVALID_HANDLE;
+ return(TRUE);
+ }
+
+ psmte = pmte->mte_swapmte;
+ if ((USHORT)(psmte->smte_pathlen + 1) > a->ModuleName.MaximumLength) {
+ m->ReturnedErrorValue = ERROR_BAD_LENGTH;
+ return TRUE;
+ }
+ memcpy(a->ModuleName.Buffer, (PCHAR)psmte->smte_path+14, psmte->smte_pathlen-14);
+ a->ModuleName.Buffer[psmte->smte_pathlen-14] = '\0';
+ a->ModuleName.Length = psmte->smte_pathlen-14;
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+}
+
+/***EP ldrGetModName - Retrieves the filename of the specified module.
+ *
+ *
+ * ENTRY hMod module handle
+ * cbBuf number of bytes in buffer
+ * pchBuf pointer to buffer to receiving module name
+ *
+ */
+
+BOOLEAN
+ldrGetModName(
+ ldrmte_t *inmte,
+ USHORT hmod,
+ PCHAR buf,
+ USHORT bc
+ )
+{
+ ldrmte_t *pmte;
+ ldrsmte_t *psmte;
+
+
+ if (inmte){
+ pmte = inmte;
+ }
+ else {
+ pmte = ldrFindMTEForHandle(hmod);
+ if (pmte == NULL) {
+ return(FALSE);
+ }
+ }
+
+ psmte = pmte->mte_swapmte;
+
+
+ if (bc <= (psmte->smte_pathlen-14)) {
+ return(FALSE);
+ }
+ memcpy(buf, (PCHAR)psmte->smte_path+14, psmte->smte_pathlen-14 );
+ buf[psmte->smte_pathlen-14] = '\0';
+ return(TRUE);
+}
+
+/***EP LDRDosGetModHandle - Retrieves the handle of a dynamic-link module.
+ *
+ *
+ * ENTRY pchname ASCIIZ name of procedure.
+ * paddress Ptr to variable receiving module handle
+ *
+ * EXIT NO_ERROR
+ * ERROR_MOD_NOT_FOUND
+ */
+
+BOOLEAN
+LDRDosGetModHandle(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRGETMODULEHANDLE_MSG a = &m->u.LdrGetModuleHandle;
+ ldrmte_t *pmte_prog; /* Pointer to process MTE */
+ ldrmte_t *pmte;
+ USHORT class;
+ ULONG rc;
+
+ CurrentThread = t;
+
+ /*
+ * Point to ldrLibPathBuf to contain the environment string
+ */
+ strncpy(ldrLibPathBuf, a->LibPathName.Buffer, SizeOfldrLibPathBuf);
+ ldrLibPathBuf[SizeOfldrLibPathBuf-1] = '\0';
+
+ ldrUCaseString(a->ModuleName.Buffer, a->ModuleName.Length);
+
+ /*
+ * Check if module we are loading has any path characters
+ */
+ if (strpbrk(a->ModuleName.Buffer, ":\\/.") == NULL)
+ class = CLASS_GLOBAL;
+ else
+ class = CLASS_SPECIFIC;
+
+ pmte = NULL;
+ if (((rc = ldrFindModule(a->ModuleName.Buffer, a->ModuleName.Length,
+ class,
+ &pmte)) != NO_ERROR) ||
+ (pmte == NULL)
+ ) {
+ m->ReturnedErrorValue = ERROR_MOD_NOT_FOUND;
+ return(TRUE);
+ }
+
+ //
+ // Verify that the module belongs to the current process
+ //
+ pmte_prog = (ldrmte_t *)t->Process->ProcessMTE;
+ ASSERT(pmte_prog != NULL);
+
+ if (!ModuleLoadedForProcess(pmte_prog, pmte)) {
+ m->ReturnedErrorValue = ERROR_INVALID_HANDLE;
+ return(TRUE);
+ }
+
+ a->ModuleHandle = (ULONG) pmte->mte_handle;
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+}
+
+
+/***EP LDRDosFreeModule - Free a dynamic-link module.
+ *
+ *
+ * ENTRY hMod handle of module to free
+ *
+ * EXIT NO_ERROR
+ * ERROR_INVALID_HANDLE
+ */
+
+BOOLEAN
+LDRDosFreeModule(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRFREEMODULE_MSG a = &m->u.LdrFreeModule;
+ ldrmte_t *pmte_prog; /* Pointer to process MTE */
+ ldrmte_t *pmte;
+ ldrdld_t *pdld;
+ ldrdld_t *prev_pdld;
+
+ CurrentThread = t;
+
+ //
+ // Set the fForceUnmap flag to TRUE so that ldrUnloadTagedModules()
+ // does unmap the app's freed segments from the app's address space.
+ //
+ fForceUnmap = TRUE;
+
+ //
+ // Verify that the module belongs to the current process
+ //
+ pmte_prog = (ldrmte_t *)t->Process->ProcessMTE;
+ ASSERT(pmte_prog != NULL);
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: DosFreeModule was called\n");
+ }
+#endif
+
+ pdld = pmte_prog->mte_dldchain;
+ prev_pdld = (ldrdld_t *)&pmte_prog->mte_dldchain;
+ while (pdld != NULL) {
+ pmte = pdld->dld_mteptr;
+ if ((pdld->Cookie == (ULONG)CurrentThread->Process) &&
+ (pmte->mte_handle == (USHORT)a->ModuleHandle)) {
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: Going to free module %.*s\n",
+ *(PCHAR)pmte->mte_modname,
+ (PCHAR)pmte->mte_modname + 1
+ );
+ }
+#endif
+ break;
+ }
+ prev_pdld = pdld;
+ pdld = pdld->dld_next;
+ }
+ if (pdld == NULL) {
+ m->ReturnedErrorValue = ERROR_INVALID_HANDLE;
+ return(TRUE);
+ }
+
+ pdld->dld_usecnt--;
+ if (pdld->dld_usecnt != 0) {
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+ }
+
+ prev_pdld->dld_next = pdld->dld_next;
+ RtlFreeHeap(LDRNEHeap, 0, pdld);
+
+ //
+ // Clear the INGRAPH flag of all modules so that we
+ // know that this module has already been processed
+ //
+ ldrClearAllMteFlag(INGRAPH | USED);
+
+ //
+ // Tag all referenced modules with the USE flag
+ // so that they are not discarded
+ //
+ ldrTagModuleTree_USED(pmte_prog);
+ for (pdld = pmte_prog->mte_dldchain; pdld != NULL; pdld = pdld->dld_next) {
+ if (pdld->Cookie == (ULONG)CurrentThread->Process) {
+ ldrTagModuleTree_USED(pdld->dld_mteptr);
+ }
+ }
+ ldrClearAllMteFlag(INGRAPH);
+
+ //
+ // Tag all referenced modules with the INGRAPH flag
+ // The tagged modules will be then unloaded
+ //
+ ldrTagModuleTree(pmte);
+
+ //
+ // Decrement the usecnt of the marked modules
+ //
+ pmte = mte_h;
+ while (pmte != NULL) {
+ if ((pmte->mte_mflags & INGRAPH) != 0) {
+ pmte->mte_usecnt--;
+ }
+ pmte = pmte->mte_link;
+ }
+
+ ldrUnloadTagedModules(t->Process);
+
+#if DBG
+ IF_OL2_DEBUG ( MTE ) {
+ DbgPrint("\nDumping segmenst after DosFreeModule() processing\n");
+ ldrDisplaySegmentTable();
+ }
+#endif
+
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+}
+
+
+/***EP LDRGetResource - Retrieves the specified resource.
+ *
+ *
+ * ENTRY hmod module handle.
+ * idType resource type identifier.
+ * idName resource name identifier
+ * psel pointer to variable for resource selector
+ *
+ * EXIT NO_ERROR
+ * ERROR_CANT_FIND_RESOURCE
+ * ERROR_INVALID_MODULE
+ * ERROR_INVALID_SELECTOR
+ */
+
+BOOLEAN
+LDRDosGetResource(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRGETRESOURCE_MSG a = &m->u.LdrGetResource;
+ ldrmte_t *pmte;
+ ldrsmte_t *psmte;
+ ldrste_t *pste;
+ ULONG lrsrc;
+ ULONG rc;
+ ULONG ModHandle;
+ ULONG ViewSize;
+ ULONG Protect;
+ PVOID MemoryAddress;
+ NTSTATUS Status;
+ ULONG RegionSize;
+ HANDLE SectionHandle;
+
+ CurrentThread = t;
+
+ //
+ // Get resources from first loaded program
+ //
+ if (a->ModuleHandle == 0) {
+ pmte = (ldrmte_t *)t->Process->ProcessMTE;
+ ModHandle = pmte->mte_handle;
+ }
+ else {
+ ModHandle = a->ModuleHandle;
+ if ((pmte = ldrFindMTEForHandle((USHORT)ModHandle)) == NULL) {
+ m->ReturnedErrorValue = ERROR_INVALID_HANDLE;
+ return(TRUE);
+ }
+ }
+
+ psmte = pmte->mte_swapmte;
+
+ rc = ERROR_INVALID_PARAMETER;
+
+ for (lrsrc = 0; lrsrc < psmte->smte_rsrccnt; lrsrc++) {
+
+ if ((((ldrrsrc16_t *)psmte->smte_rsrctab)[lrsrc].ldrrsrc16_type
+ == (USHORT)a->ResourceType) &&
+ (((ldrrsrc16_t *)psmte->smte_rsrctab)[lrsrc].ldrrsrc16_name
+ == (USHORT)a->ResourceName) ) {
+ rc = NO_ERROR;
+ break;
+ }
+ }
+
+ if (rc == NO_ERROR) {
+ pste = ldrNumToSte(pmte,
+ (psmte->smte_objcnt - psmte->smte_rsrccnt + lrsrc + 1));
+ MemoryAddress = SELTOFLAT(pste->ste_selector);
+ SectionHandle = (HANDLE)pste->ste_seghdl;
+ //
+ // Map the resource into the client address space
+ // Any change in determinig the Protect value should be
+ // done in ldrste.c ldrAllocSegment() too.
+ //
+ if ((pste->ste_flags & STE_DATA) == 0) {
+ // This is a code segment
+ if ((pste->ste_flags & STE_ERONLY) != 0) {
+ // This is an execute only segment
+ Protect = PAGE_EXECUTE;
+ }
+ else {
+ Protect = PAGE_EXECUTE_READ;
+ }
+ }
+ else {
+ // This is a data segment
+ if ((pste->ste_flags & STE_SHARED) != 0) {
+ // This is a shared data segment
+ if ((pste->ste_flags & STE_ERONLY) != 0) {
+ // This is a read only segment
+ Protect = PAGE_READONLY;
+ }
+ else {
+ // This is a read/write segment
+ Protect = PAGE_READWRITE;
+ }
+ }
+ else {
+ // This is a non shared data segment
+ if ((pste->ste_flags & STE_ERONLY) != 0) {
+ // This is a read only segment
+ Protect = PAGE_READONLY;
+ }
+ else {
+ // This is a sizeable read/write segment
+ Protect = PAGE_EXECUTE_WRITECOPY;
+ }
+ }
+ }
+
+ a->ResourceSel = pste->ste_selector | 7;
+ a->ResourceAddr = (ULONG)((pste->ste_selector << 16) & 0xffff0000);
+ a->NumberOfSegments = 0;
+ // This should be performed in a loop for huge resources (longer then a
+ // single segment)
+ for (;
+ ((((ldrrsrc16_t *)psmte->smte_rsrctab)[lrsrc].ldrrsrc16_type
+ == (USHORT)a->ResourceType) &&
+ (((ldrrsrc16_t *)psmte->smte_rsrctab)[lrsrc].ldrrsrc16_name
+ == (USHORT)a->ResourceName) )
+ ; lrsrc++) {
+
+ (a->NumberOfSegments)++;
+ pste = ldrNumToSte(pmte,
+ (psmte->smte_objcnt - psmte->smte_rsrccnt + lrsrc + 1));
+ MemoryAddress = SELTOFLAT(pste->ste_selector);
+ SectionHandle = (HANDLE)pste->ste_seghdl;
+
+ ViewSize = 0;
+ RegionSize = pste->ste_minsiz;
+ if (RegionSize == 0) {
+ RegionSize = _64K;
+ }
+
+ if (Protect == PAGE_EXECUTE_WRITECOPY) {
+ ViewSize = RegionSize;
+ }
+
+ Status = NtMapViewOfSection(SectionHandle,
+ CurrentThread->Process->ProcessHandle,
+ &MemoryAddress,
+ 1,
+ RegionSize,
+ NULL,
+ &ViewSize,
+ ViewUnmap,
+ 0,
+ Protect
+ );
+ //
+ // Don't check for error code as this section may be multiple
+ // mapped because DosFreeResource() does not unmap it.
+ //
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ // DbgPrint("OS2LDR: ldrAllocSegment - Can't map section to client process %x at addr=%x, Status=%x\n",
+ // CurrentThread->Process->ProcessHandle, MemoryAddress, Status);
+#endif
+ }
+
+ ldrSetDescInfo(pste->ste_selector, (ULONG)MemoryAddress,
+ pste->ste_flags, pste->ste_minsiz);
+
+ }
+
+ }
+
+ m->ReturnedErrorValue = rc;
+ return(TRUE);
+}
+
+
+/***EP LDRDosFreeResource - Free a specified resource.
+ *
+ *
+ * ENTRY psel pointer to resource
+ *
+ * EXIT NO_ERROR
+ * ERROR_INVALID_SELECTOR
+ */
+
+BOOLEAN
+LDRDosFreeResource(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRFREERESOURCE_MSG a = &m->u.LdrFreeResource;
+
+ CurrentThread = t;
+
+ ldrClearAllMteFlag(INGRAPH | USED);
+
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+}
+
+#if PMNT
+BOOLEAN
+LDRIdentifyCodeSelector(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRIDENTIFYCODESELECTOR_MSG a = &m->u.LdrIdentifyCodeSelector;
+ ldrmte_t *pmte_prog; /* Pointer to process MTE */
+ ldrmte_t *pmte;
+ ldrdld_t *pdld;
+ ldrsmte_t *psmte;
+ ldrste_t *pste;
+ ULONG i;
+
+ CurrentThread = t;
+
+ //
+ // Verify that the module belongs to the current process
+ //
+ pmte_prog = (ldrmte_t *)t->Process->ProcessMTE;
+ ASSERT(pmte_prog != NULL);
+
+ //
+ // Clear the INGRAPH flag of all modules so that we
+ // know that this module has already been processed
+ //
+ ldrClearAllMteFlag(INGRAPH | USED);
+
+ //
+ // Tag all referenced modules with the INGRAPH flag
+ // The tagged modules will then be scanned for the desired selector
+ //
+ ldrTagModuleTree(pmte_prog);
+ for (pdld = pmte_prog->mte_dldchain; pdld != NULL; pdld = pdld->dld_next) {
+ ldrTagModuleTree(pdld->dld_mteptr);
+ }
+
+ //
+ // Scan the marked modules for one containing the resized selector
+ //
+ pmte = mte_h;
+ while (pmte != NULL)
+ {
+ if ((pmte->mte_mflags & INGRAPH) != 0)
+ {
+ psmte = pmte->mte_swapmte;
+ pste = (ldrste_t *)psmte->smte_objtab;
+
+ for (i = 1; i <= psmte->smte_objcnt; i++, pste++)
+ {
+ if (((ULONG)(pste->ste_selector | 7) == a->sel))
+ {
+ a->segNum = (USHORT)i;
+ a->mte = pmte->mte_handle;
+ memcpy( a->ModName.Buffer,
+ (PCHAR)psmte->smte_path+14,
+ psmte->smte_pathlen-14);
+ a->ModName.Buffer[psmte->smte_pathlen-14] = '\0';
+
+ return(TRUE);
+ }
+ }
+ }
+ pmte = pmte->mte_link;
+ }
+
+ // Selector not found. Return default values
+ a->segNum = 1;
+ a->mte = 0;
+ strcpy( a->ModName.Buffer, "UNKNOWN");
+
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+}
+#endif // PMNT
+
+/***EP LDRDosQAppType - return file's exe type
+ *
+ * ENTRY pszModName - pointer to ASCII module name
+ * pulType - pointer to put type
+ *
+ * EXIT int - return code (NO_ERROR if successful)
+ */
+
+BOOLEAN
+LDRDosQAppType(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+{
+ P_LDRQAPPTYPE_MSG a = &m->u.LdrQAppType;
+
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER ByteOffset;
+ ULONG ulNewHdrOff; /* Offset hdr offset */
+ ULONG ulCopied; /* Number of bytes copied */
+ ULONG ulNeeded; /* Number of bytes needed */
+ ULONG usoff; /* Offset to new exe header */
+ struct e32_exe *pe32;
+ struct e32_exe *pe32temp;
+ ldrlv_t lv; /* local variables */
+ PCHAR ptmp;
+ int rc;
+ NTSTATUS Status;
+
+#define NOTSPECIFIED 0x0000
+#define NOTWINDOCOMPAT 0x0001
+#define WINDOWCOMPAT 0x0002
+#define WINDOWAPI 0x0003
+#define BOUND 0x0008
+#define DYNAMICLINK 0x0010
+#define DOSFORMAT 0x0020
+
+ CurrentThread = t;
+
+ /*
+ * Point to ldrLibPathBuf to contain the environment string
+ */
+ strncpy(ldrLibPathBuf, a->PathName.Buffer, SizeOfldrLibPathBuf);
+ ldrLibPathBuf[SizeOfldrLibPathBuf-1] = '\0';
+
+ /*
+ * Check if the App we are loading has any path characters
+ */
+ if (strpbrk(a->AppName.Buffer, ":\\/") == NULL) {
+ lv.lv_class = CLASS_GLOBAL;
+ }
+ else {
+ lv.lv_class = CLASS_SPECIFIC;
+ }
+
+ if ((rc = ldrOpenPath(a->AppName.Buffer,
+ (USHORT)a->AppName.Length,
+ &lv,
+ NULL)) != NO_ERROR) {
+ //
+ // If file was not found, check if the file name has no extension.
+ // If it does not have, try again with the extension .EXE
+ //
+
+ UCHAR NewPathWithExt[MAXPATHLEN];
+
+ memcpy(NewPathWithExt, a->AppName.Buffer, a->AppName.Length);
+ NewPathWithExt[a->AppName.Length] = '\0';
+ ptmp = strrchr(NewPathWithExt, '\\');
+ if (ptmp == NULL) {
+ ptmp = strrchr(NewPathWithExt, '/');
+ if (ptmp == NULL) {
+ ptmp = strrchr(NewPathWithExt, ':');
+ if (ptmp == NULL) {
+ ptmp = NewPathWithExt;
+ }
+ }
+ }
+ ptmp = strchr(ptmp, '.');
+ if (ptmp != NULL) {
+ //
+ // The file has an extension. So, the error returned
+ // previously by ldrOpenPath() is valid
+ //
+ m->ReturnedErrorValue = rc;
+ return(TRUE);
+ }
+ strcpy(&NewPathWithExt[a->AppName.Length], ".EXE");
+ rc = ldrOpenPath(NewPathWithExt,
+ (USHORT)(a->AppName.Length + 4),
+ &lv,
+ NULL);
+ }
+ if (rc != NO_ERROR) {
+ m->ReturnedErrorValue = rc;
+ return(TRUE);
+ }
+
+ pe32 = (struct e32_exe *) pheaderbuf;
+
+ /*
+ * Start read at beginning of file
+ */
+ ByteOffset.LowPart = 0;
+ ByteOffset.HighPart = 0;
+
+ if ((Status = NtReadFile( lv.lv_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ pe32,
+ 512,
+ &ByteOffset,
+ 0 )) != STATUS_SUCCESS) {
+ NtClose(lv.lv_sfn);
+ m->ReturnedErrorValue = ERROR_FILE_NOT_FOUND;
+ return(TRUE);
+ }
+
+ /*
+ * validate old (MZ) signature in header
+ */
+ if (((struct exe_hdr *) pe32)->e_magic != EMAGIC) {
+ NtClose(lv.lv_sfn);
+ m->ReturnedErrorValue = ERROR_INVALID_EXE_SIGNATURE;
+ return(TRUE);
+ }
+
+ usoff = ((struct exe_hdr *) pe32)->e_lfarlc;
+
+ /*
+ * get pointer to (NE) or (LE) exe header
+ */
+ ulNewHdrOff =
+ lv.lv_new_exe_off = ((struct exe_hdr *) pe32)->e_lfanew;
+
+ /*
+ * check if we read at least up to the (NE) or (LE) header
+ */
+ if (ulNewHdrOff < IoStatusBlock.Information) {
+
+ /*
+ * assume we are reading a 32-bit module
+ */
+ ulNeeded = sizeof(struct e32_exe);
+ pe32temp = (struct e32_exe *) ((ULONG) pe32 + ulNewHdrOff);
+
+ if ((ulNewHdrOff < (IoStatusBlock.Information -
+ sizeof(pe32->e32_magic))) &&
+ (*(short *) (pe32temp->e32_magic) == NEMAGIC))
+ ulNeeded = sizeof(struct new_exe);
+
+ ulCopied = min(IoStatusBlock.Information - ulNewHdrOff, ulNeeded);
+
+ memcpy(pe32, (PVOID) ((ULONG) pe32 + ulNewHdrOff), ulCopied);
+
+ if (ulNeeded -= ulCopied) {
+ if ((Status = NtReadFile( lv.lv_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ (PCHAR) pe32 + ulCopied,
+ ulNeeded,
+ &ByteOffset,
+ 0 )) != STATUS_SUCCESS) {
+ NtClose(lv.lv_sfn);
+ m->ReturnedErrorValue = ERROR_FILE_NOT_FOUND;
+ return(TRUE);
+ }
+ }
+ }
+ else {
+
+ /*
+ * read in new header to size of 32-bit mte plus a ote entry
+ */
+ ByteOffset.LowPart = (ULONG)((struct exe_hdr *)pe32)->e_lfanew;
+ ByteOffset.HighPart = 0;
+
+ if ((Status = NtReadFile( lv.lv_sfn,
+ 0,
+ 0,
+ 0,
+ &IoStatusBlock,
+ (PCHAR) pe32,
+ sizeof(struct e32_exe)+sizeof(ldrote_t),
+ &ByteOffset,
+ 0 )) != STATUS_SUCCESS) {
+ NtClose(lv.lv_sfn);
+ m->ReturnedErrorValue = ERROR_FILE_NOT_FOUND;
+ return(TRUE);
+ }
+ }
+
+ Status = NtClose(lv.lv_sfn);
+
+#if DBG
+ if (!NT_SUCCESS(Status)) {
+ KdPrint(("OS2SRV: Failed to close the file opened for DosQApptype(), Status=%x\n", Status));
+ }
+#endif
+
+ /* Verify that this is a protect-mode exe. (Check this before
+ * checking MTE signature for 1.2 error code compatability.)
+ */
+ if (usoff != 0x40) {
+ a->AppType = DOSFORMAT;
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+ }
+
+ /*
+ * validate as 16-bit signature or 32-bit signature
+ */
+ if (!(*(short *) (pe32->e32_magic) == NEMAGIC)) {
+ m->ReturnedErrorValue = ERROR_INVALID_EXE_SIGNATURE;
+ return(TRUE);
+ }
+
+ a->AppType = 0;
+ if (((struct new_exe *)pe32)->ne_flags & 0x800) {
+ a->AppType |= BOUND;
+ }
+ if (((struct new_exe *)pe32)->ne_flags & 0x8000) {
+ a->AppType |= DYNAMICLINK;
+ }
+ if ((((struct new_exe *)pe32)->ne_flags & 0x700) == 0x100) {
+ a->AppType |= NOTWINDOCOMPAT;
+ }
+ if ((((struct new_exe *)pe32)->ne_flags & 0x700) == 0x200) {
+ a->AppType |= WINDOWCOMPAT;
+ }
+ if ((((struct new_exe *)pe32)->ne_flags & 0x700) == 0x300) {
+ a->AppType |= WINDOWAPI;
+ }
+
+ m->ReturnedErrorValue = NO_ERROR;
+ return(TRUE);
+}
+
+BOOLEAN
+LDRModifySizeOfSharedSegment(
+ IN POS2_THREAD t,
+ IN ULONG Sel,
+ IN ULONG NewLimit
+ )
+{
+ ldrmte_t *pmte_prog; /* Pointer to process MTE */
+ ldrmte_t *pmte;
+ ldrdld_t *pdld;
+ ldrsmte_t *psmte;
+ ldrste_t *pste;
+ ULONG i;
+
+ CurrentThread = t;
+
+ //
+ // Verify that the module belongs to the current process
+ //
+ pmte_prog = (ldrmte_t *)t->Process->ProcessMTE;
+ ASSERT(pmte_prog != NULL);
+
+#if DBG
+ IF_OL2_DEBUG ( TRACE ) {
+ DbgPrint("OS2LDR: LDRModifySizeOfSharedSegment was called\n");
+ }
+#endif
+ //
+ // Clear the INGRAPH flag of all modules so that we
+ // know that this module has already been processed
+ //
+ ldrClearAllMteFlag(INGRAPH | USED);
+
+ //
+ // Tag all referenced modules with the INGRAPH flag
+ // The tagged modules will then be scanned for the desired selector
+ //
+ ldrTagModuleTree(pmte_prog);
+ for (pdld = pmte_prog->mte_dldchain; pdld != NULL; pdld = pdld->dld_next) {
+ ldrTagModuleTree(pdld->dld_mteptr);
+ }
+
+ //
+ // Scan the marked modules for one containing the resized selector
+ //
+ pmte = mte_h;
+ while (pmte != NULL) {
+ if ((pmte->mte_mflags & INGRAPH) != 0) {
+ psmte = pmte->mte_swapmte;
+ pste = (ldrste_t *)psmte->smte_objtab;
+
+ for (i = 1; i <= psmte->smte_objcnt; i++, pste++) {
+ if (((ULONG)(pste->ste_selector | 7) == Sel) &&
+ ((pste->ste_flags & STE_SHARED) != 0)
+ ) {
+ pste->ste_minsiz = (ushort_t)(NewLimit + 1);
+ return(TRUE);
+ }
+ }
+ }
+ pmte = pmte->mte_link;
+ }
+
+ return(FALSE);
+}
+
+VOID
+ldrReturnProgramAndLibMTE(
+ IN POS2_PROCESS Process,
+ OUT USHORT *ProgramMTE,
+ OUT USHORT *LibMTE,
+ OUT USHORT *Cmd
+ )
+{
+ LinkMTE *pMte;
+
+ //
+ // Get the program MTE.
+ //
+ pMte = ((LinkMTE *)Process->LinkMte)->NextMTE;
+
+ *ProgramMTE = pMte->MTE;
+ *LibMTE = 0;
+ *Cmd= TRC_C_SUC_ret;
+
+ while ((pMte != NULL) && (!(pMte->NeedToTransfer))) {
+ pMte = pMte->NextMTE;
+ }
+ if (pMte != NULL) {
+ *LibMTE = pMte->MTE;
+ *Cmd = (USHORT)TRC_C_LIB_ret;
+ pMte->NeedToTransfer = FALSE;
+ ((LinkMTE *)Process->LinkMte)->NeedToTransfer--;
+ }
+
+ return;
+}
diff --git a/private/os2/ldr/ldrutil.c b/private/os2/ldr/ldrutil.c
new file mode 100644
index 000000000..ea701b2ef
--- /dev/null
+++ b/private/os2/ldr/ldrutil.c
@@ -0,0 +1,228 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ldrutil.c
+
+Abstract:
+
+ This module contains various ldr utility routines
+
+Author:
+
+ Beni Lavi (BeniL) 5-Nov-92
+
+Revision History:
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include "os2tile.h"
+#include "ldrextrn.h"
+
+static PVOID ldrBMHeap;
+static RTL_BITMAP ldrBitMapHeader;
+
+static PVOID ldrCGHeap;
+static RTL_BITMAP ldrCallGateHeader;
+static ULONG CallGateHintIndex;
+
+ULONG
+FindTopDownClearBitsAndSet(
+ PRTL_BITMAP pBitMap,
+ ULONG Bits
+ )
+{
+ ULONG Index;
+ ULONG i;
+
+ Index = pBitMap->SizeOfBitMap;
+
+ while (Index >= Bits) {
+ for (i = 1; i <= Bits; i++) {
+ if (RtlCheckBit(pBitMap, Index-i)) {
+ Index -= i;
+ break;
+ }
+ }
+ if (i > Bits) {
+ RtlSetBits( pBitMap,
+ Index+1-i,
+ Bits
+ );
+ return(Index+1-i);
+ }
+ }
+ // failed to find a free entry
+ return(0xffffffff);
+}
+
+BOOLEAN
+ldrCreateSelBitmap(
+ )
+{
+
+ ldrBMHeap = RtlAllocateHeap(Os2Heap, 0, (LDT_DISJOINT_ENTRIES + 7) / 8);
+ if (ldrBMHeap == NULL) {
+ return(FALSE);
+ }
+/*
+ ldrBMHeap = RtlCreateHeap( HEAP_GROWABLE,
+ NULL,
+ 64 * 1024, // Initial size of heap is 64K
+ (LDT_DISJOINT_ENTRIES + 7) / 8, // 8 bits per byte
+ NULL,
+ 0
+ );
+ if (ldrBMHeap == NULL) {
+ return(FALSE);
+ }
+*/
+ RtlInitializeBitMap(&ldrBitMapHeader ,ldrBMHeap, LDT_DISJOINT_ENTRIES);
+ RtlClearAllBits(&ldrBitMapHeader);
+ return(TRUE);
+}
+
+VOID
+ldrMarkAllocatedSel(
+ ULONG NumberOfSel,
+ BOOLEAN MarkFromTop
+ )
+{
+ ULONG StartOfMark = 0;
+
+ if (MarkFromTop) {
+ StartOfMark = ldrBitMapHeader.SizeOfBitMap - NumberOfSel;
+ }
+
+ RtlSetBits( &ldrBitMapHeader,
+ StartOfMark,
+ NumberOfSel
+ );
+}
+
+ULONG
+ldrAllocateSel(
+ ULONG NumberOfSel,
+ BOOLEAN TopDownAllocation
+ )
+{
+ ULONG Index;
+
+ if (TopDownAllocation) {
+ Index = FindTopDownClearBitsAndSet( &ldrBitMapHeader,
+ NumberOfSel
+ );
+ }
+ else {
+ Index = RtlFindClearBitsAndSet( &ldrBitMapHeader,
+ NumberOfSel,
+ 0
+ );
+ }
+ if (Index == 0xffffffff) {
+ return(Index);
+ }
+
+ Index += (_64K / 8) - LDT_DISJOINT_ENTRIES;
+ return((Index << 3) | 7); // convert the index to selector
+}
+
+VOID
+ldrFreeSel(
+ ULONG Sel,
+ ULONG NumberOfSel
+ )
+{
+ if (Sel > _64K) {
+#if DBG
+ KdPrint(("OS2SRV: ldrFreeSel - invalid Sel %x\n", Sel));
+#endif
+ return;
+ }
+ RtlClearBits( &ldrBitMapHeader,
+ (Sel >> 3) - ((_64K / 8) - LDT_DISJOINT_ENTRIES),
+ NumberOfSel
+ );
+}
+
+BOOLEAN
+ldrCreateCallGateBitmap(
+ )
+{
+ ldrCGHeap = RtlAllocateHeap(Os2Heap, 0, _64K / 8);
+ if (ldrCGHeap == NULL) {
+ return(FALSE);
+ }
+/*
+ ldrCGHeap = RtlCreateHeap( HEAP_GROWABLE,
+ NULL,
+ 64 * 1024, // Initial size of heap is 64K
+ _64K / 8, // 8 bits per byte
+ NULL,
+ 0
+ );
+ if (ldrCGHeap == NULL) {
+ return(FALSE);
+ }
+*/
+ RtlInitializeBitMap(&ldrCallGateHeader ,ldrCGHeap, _64K / 8);
+ RtlClearAllBits(&ldrCallGateHeader);
+ return(TRUE);
+}
+
+VOID
+ldrMarkAllocatedCallGates(
+ ULONG NumberOfCallGates
+ )
+{
+ RtlSetBits( &ldrCallGateHeader,
+ 0,
+ NumberOfCallGates
+ );
+ CallGateHintIndex = NumberOfCallGates;
+}
+
+ULONG
+ldrAllocateCallGate()
+{
+ ULONG Index;
+
+ Index = RtlFindClearBitsAndSet( &ldrCallGateHeader,
+ 1,
+ CallGateHintIndex
+ );
+ if (Index == 0xffffffff) {
+ return(Index);
+ }
+
+ return(Index * 8); // 8 bytes for each call gate entry
+}
+
+VOID
+ldrDeallocateCallGate(
+ ULONG CallGate
+ )
+{
+ ULONG Index;
+
+ if (CallGate > _64K) {
+#if DBG
+ KdPrint(("OS2SRV: ldrDeallocateCallGate - invalid callgate %x\n", CallGate));
+#endif
+ return;
+ }
+ Index = CallGate / 8;
+ RtlClearBits( &ldrCallGateHeader,
+ Index,
+ 1
+ );
+ if (Index < CallGateHintIndex) {
+ CallGateHintIndex = Index;
+ }
+}
+
diff --git a/private/os2/ldr/ldrvars.h b/private/os2/ldr/ldrvars.h
new file mode 100644
index 000000000..a02cbf667
--- /dev/null
+++ b/private/os2/ldr/ldrvars.h
@@ -0,0 +1,928 @@
+/* SCCSID = @(#)ldrvars.h 13.100 90/10/11 */
+/*
+ * Microsoft Confidential
+ *
+ * Copyright (c) Microsoft Corporation 1987, 1989
+ *
+ * All Rights Reserved
+ */
+/* INT32 */
+/* XLATOFF */
+
+extern CHAR ldrLibPathBuf[];
+
+extern PCHAR ldrpLibPath;
+
+extern ULONG SizeOfldrLibPathBuf;
+
+typedef unsigned short VMHOB; /* not including vmexport.h */
+
+
+/***ET+ ldrmte_t - MTE */
+
+struct ldrmte_s {
+ uchar_t mte_magic[2]; /* Magic number E32_MAGIC */
+ ushort_t mte_usecnt; /* count of moudules using us */
+ ulong_t mte_mflags; /* Module flags */
+ ulong_t mte_mflags2; /* extension flags word */
+ ulong_t mte_modname; /* pointer to resident module name */
+ ulong_t mte_impmodcnt; /* Num of entries Import Modules */
+ ulong_t mte_modptrs; /* pointer to module pointers table */
+ struct ldrdld_s *mte_dldchain; /* pointer to chain of modules loaded by DosLoadModule() */
+ ushort_t mte_handle; /* the handle for this mte */
+ HANDLE mte_sfn; /* file system number for open file */
+ struct ldrmte_s *mte_link; /* link to next mte */
+ struct ldrsmte_s *mte_swapmte; /* link to swappable mte */
+};
+typedef struct ldrmte_s ldrmte_t; /* Swappable Module table entry */
+
+struct ldrsmte_s {
+ ulong_t smte_eip; /* Starting address for module */
+ ulong_t smte_stackbase; /* Stack base */
+ ulong_t smte_stackinit; /* Init commited stack */
+ ulong_t smte_objtab; /* Object table offset */
+ ulong_t smte_objcnt; /* Number of objects in module */
+ ulong_t smte_fpagetab; /* Offset fixup pg tab for 32-bit */
+ ulong_t smte_expdir; /* Export directory offset */
+ ulong_t smte_impdir; /* Import directory offset */
+ ulong_t smte_fixtab; /* Fixup record table offset */
+ ulong_t smte_rsrctab; /* Offset of Resource Table */
+ ulong_t smte_rsrccnt; /* count of resources */
+ ulong_t smte_filealign; /* Alignment factor */
+ ulong_t smte_vbase; /* Virtual base address of module */
+ ulong_t smte_heapsize; /* use for converted 16-bit modules */
+ ulong_t smte_autods; /* Object # for automatic data obj */
+ ulong_t smte_iat; /* pointer to import address table */
+ ulong_t smte_debuginfo; /* Offset of the debugging info */
+ ulong_t smte_debuglen; /* Len of the debug info in bytes */
+ ulong_t smte_delta; /* difference in load address */
+ ulong_t smte_pfilecache; /* Pointer to file cache for */
+ ulong_t smte_path; /* full pathname */
+ ushort_t smte_pathlen; /* length of full pathname */
+ ushort_t smte_dyntrchndl; /* used by dyn trace */
+ ushort_t smte_semcount; /* Count of threads waiting on MTE
+ semaphore. 0=> semaphore is free */
+ ushort_t smte_semowner; /* Slot number of the owner of MTE
+ semaphore */
+ ulong_t smte_nrestab; /* Offset of non-resident tb 16-bit */
+ ulong_t smte_cbnrestab; /* size of non-resident tb 16-bit */
+ ulong_t smte_csegpack; /* count of segments to pack */
+ ulong_t smte_ssegpack; /* size of object for seg packing */
+ ulong_t smte_spaddr; /* virtual address of packed obj */
+ ushort_t smte_NEflags; /* Orginal flags from NE header */
+ ushort_t smte_NEexpver; /* Expver from NE header */
+ ushort_t smte_NEexetype; /* Exetype from NE header */
+ ushort_t smte_NEflagsothers;/* Flagsothers from NE header */
+};
+typedef struct ldrsmte_s ldrsmte_t; /* Swappable Module table entry */
+
+/*
+ * Defines for 16-bit loading
+ * overlay using unused fields of a (NE) 16-bit MTE.
+ */
+#define smte_stackobj smte_stackbase /* Object # for stack pointer */
+#define smte_esp smte_stackinit /* Extended stack pointer */
+#define smte_smtesize smte_fpagetab /* size of swappable heap debug use */
+#define smte_enttab smte_expdir /* Offset of entry table */
+#define smte_impproc smte_impdir /* Offset of import procedure tb */
+#define smte_restab smte_fixtab /* Offset of resident name table */
+#define smte_alignshift smte_filealign /* File alignment */
+#define smte_impmod smte_iat /* Offset of import module table */
+#define smte_stacksize smte_debuglen /* Size of stack */
+#define smte_startobj smte_delta /* Object # for instruction pointer */
+
+/*
+ * Defines for 32-bit loading
+ * overlay using unused fields of a (LE) 32-bit MTE
+ */
+#define smte_iatsize smte_spaddr /* Size of IAT */
+#define smte_mpages smte_ssegpack /* number of pages in module */
+#define smte_fixupsize smte_csegpack /* fixup table size */
+#define smte_vddfixaddr smte_cbnrestab /* vdd fixup address */
+
+
+/***LK+ Definitions for mte_mflags
+ *
+ * USED and INGRAPH are used by the graph traversl routines. If
+ * the loader semaphore is clear, these bits must both be clear.
+ * See traversal routines for more.
+ *
+ * MTE_INTNL_MASK is the set of bits which are used by the kernel.
+ * These bits are cleared when a module is finished loading.
+ *
+ * LDRINVALID and MTEVALID are overloaded. Once an mte is linked
+ * into the chain, this bit is used to indicate (if set) that the
+ * mte contains valid information that demand loaders (who are not
+ * excluded by the loader semaphore) may examine.
+ *
+ */
+
+#define NOAUTODS 0x00000000 /* No Auto DS exists */
+#define SOLO 0x00000001 /* Auto DS is shared */
+#define INSTANCEDS 0x00000002 /* Auto DS is not shared */
+#define INSTLIBINIT 0x00000004 /* Per-instance Libinit */
+#define GINISETUP 0x00000008 /* Global Init has been setup */
+/* 0x00000010 reserved for NO external fixups in .EXE */
+/* 0x00000020 reserved for NO internal fixups in .EXE */
+#define CLASS_PROGRAM 0x00000040 /* Program class */
+#define CLASS_GLOBAL 0x00000080 /* Global class */
+#define CLASS_SPECIFIC 0x000000C0 /* Specific class, as against global */
+#define CLASS_ALL 0x00000000 /* nonspecific class - all modules */
+#define CLASS_MASK 0x000000C0
+#define MTEPROCESSED 0x00000100 /* MTE being loaded */
+#define USED 0x00000200 /* MTE is referenced - see ldrgc.c */
+#define DOSLIB 0x00000400 /* set if DOSCALL1 */
+#define DOSMOD 0x00000800 /* set if DOSCALLS */
+#define MTE_MEDIAFIXED 0x00001000 /* File Media permits discarding */
+#define LDRINVALID 0x00002000 /* module not loadable */
+#define PROGRAMMOD 0x00000000 /* program module */
+#define DEVDRVMOD 0x00004000 /* device driver module */
+#define LIBRARYMOD 0x00008000 /* DLL module */
+#define VDDMOD 0x00010000 /* VDD module */
+#define MVDMMOD 0x00020000 /* Set if VDD Helper MTE (MVDM.DLL) */
+#define INGRAPH 0x00040000 /* In Module Graph - see ldrgc.c */
+#define GINIDONE 0x00080000 /* Global Init has finished */
+#define MTEADDRALLOCED 0x00100000 /* Allocate specific or not */
+#define FSDMOD 0x00200000 /* FSD MTE */
+#define FSHMOD 0x00400000 /* FS helper MTE */
+#define MTELONGNAMES 0x00800000 /* Module supports long-names */
+#define MTE_MEDIACONTIG 0x01000000 /* File Media contiguous memory req */
+#define MTE_MEDIA16M 0x02000000 /* File Media requires mem below 16M */
+#define MTEIOPLALLOWED 0x04000000 /* Module has IOPL privilege */
+#define MTEPORTHOLE 0x08000000 /* porthole module */
+#define MTEMODPROT 0x10000000 /* Module has shared memory protected */
+#define MTENEWMOD 0x20000000 /* Newly added module */
+#define MTEDLLTERM 0x40000000 /* Gets instance termination */
+#define MTESYMLOADED 0x80000000 /* Set if debugger symbols loaded */
+
+/* The following bits are overloaded or aliased. */
+
+#define MTEVALID (LDRINVALID)
+#define AUTODS_MASK (NOAUTODS|SOLO|INSTANCEDS)
+
+/* The following bits are cleared after each successful module load. */
+
+#define MTE_INTNL_MASK (DOSLIB|DOSMOD|MTEVALID|MTEPROCESSED| \
+ GINISETUP|GINIDONE|USED|INGRAPH|MTENEWMOD)
+
+/*
+ * The following define which modules are "ring 0" for the purpose of
+ * indirect fixups.
+ */
+#define MTE_RING0 (DEVDRVMOD | VDDMOD | MVDMMOD | FSDMOD | FSHMOD)
+
+#define SEARCH_BY_PATH 1 /* FindModule class parameter */
+
+/*end*/
+
+/***ET+ ldrote_s - Object Table entry */
+
+struct _oteres_s {
+ ushort_t _ote_selector; /* store selector used by loader only */
+ ushort_t _ote_handle; /* store handle used by loader only */
+};
+
+/*
+ * Since H2INC will not work correctly with unions to get SIZE of ldrote_t
+ * to return the correct size remove the ulong_t from the assembler declare
+ */
+
+union _oteres_u {
+ struct _oteres_s _ote_res;
+ ulong_t _ote_linkbase; /* store link base address */
+};
+
+
+/* ASM
+_oteres_u STRUC
+ _ote_res DB SIZE _oteres_s DUP (?)
+_oteres_u ENDS
+*/
+
+struct ldrote_s { /* Flat .EXE object table entry */
+ ulong_t ote_base; /* Object virtual base address */
+ ulong_t ote_vsize; /* Virtual memory size */
+ ulong_t ote_pages; /* Image pages offset */
+ ulong_t ote_psize; /* Physical file size of init. data */
+ ulong_t ote_flags; /* Attribute flags for the object */
+ union _oteres_u _ote_resu;
+};
+typedef struct ldrote_s ldrote_t; /* Object table entry */
+
+#define ote_handle _ote_resu._ote_res._ote_handle
+#define ote_selector _ote_resu._ote_res._ote_selector
+#define OBJ_PRELOAD 0x0040L
+
+#define ote_linkbase _ote_resu._ote_linkbase
+
+/* ASM
+ote_linkbase equ <dword ptr _ote_resu>
+*/
+
+#define OBJALLOC 0x80000000L /* Object is allocated used by loader */
+
+/***ET+ ldrote_t - Object Table entry */
+
+#define LGS_FSDMOD 8L /* for ldrGetSelector */
+#define LGS_FSDMODSHF 18L /* for ldrGetSelector */
+#define LGS_VDDMOD 4L /* for ldrGetSelector */
+#define LGS_VDDMODSHF 14L /* for ldrGetSelector */
+#define LGS_DEVDRVMOD 4L /* for ldrGetSelector */
+#define LGS_DEVDRVSHF 12L /* for ldrGetSeletor */
+#define LGS_OBJEXECSHF 2L /* for ldrGetSelector */
+#define LGS_OBJIOPLSHF 14L /* for ldrGetSelector */
+#define LGS_OBJEXEC 1L /* for ldrGetSelector */
+#define LGS_OBJIOPL 2L /* for ldrGetSelector */
+
+#if ((LGS_VDDMOD << LGS_VDDMODSHF) != VDDMOD)
+ error ldrvars.h include file changed /* create compile error */
+#endif
+
+#if ((LGS_OBJEXEC << LGS_OBJEXECSHF) != OBJ_EXEC)
+ error exe386.h include file changed /* create compile error */
+#endif
+
+#if ((LGS_OBJIOPL << LGS_OBJIOPLSHF) != OBJ_IOPL)
+ error exe386.h include file changed /* create compile error */
+#endif
+
+/***ET+ ldropm_t - Object Page Map */
+
+typedef struct o32_map ldropm_t; /* Object Page Map */
+
+
+/***ET+ ldrste_t - Segment Table entry */
+
+struct ldrste_s {
+ ushort_t ste_offset; /* file offset to segment data */
+ ushort_t ste_size; /* file data size */
+ ushort_t ste_flags; /* type and attribute flags */
+ ushort_t ste_minsiz; /* minimum allocation size */
+ ulong_t ste_seghdl; /* segment handle returned by NtCreateSection() */
+ ulong_t ste_fixups; /* fixup record storage */
+ ushort_t ste_selector; /* segment selector */
+ ushort_t ste_pad; /* pad ldrste_s to 4 bytes */
+
+};
+ /* ste_flags bit definitions */
+/* XLATON */
+#define STE_TYPE_MASK 0x0001 /* segment type field */
+#define STE_CODE 0x0000 /* code segment type */
+#define STE_DATA 0x0001 /* data segment type */
+#define STE_PACKED 0x0002 /* segment is packed */
+#define STE_SEMAPHORE 0x0004 /* segment semaphore */
+#define STE_ITERATED 0x0008 /* segment data is iterated */
+#define STE_WAITING 0x0010 /* segment is waiting on semephore */
+#define STE_SHARED 0x0020 /* segment can be shared */
+#define STE_PRELOAD 0x0040 /* segment is preload */
+#define STE_ERONLY 0x0080 /* excute only if code segment */
+ /* read only if data segment */
+#define STE_RELOCINFO 0x0100 /* set if segment has reloc records */
+#define STE_CONFORM 0x0200 /* segment is conforming */
+#define STE_RING_2 0x0800 /* ring 2 selector */
+#define STE_RING_3 0x0C00 /* ring 3 selector */
+#define STE_SEGDPL 0x0C00 /* I/O privilege level */
+#define STE_HUGE 0x1000 /* huge segment */
+#define STE_PAGEABLE 0x2000 /* just a page can be faulted in */
+#define STE_PRESENT 0x2000 /* packed segment already loaded */
+#define STE_SELALLOC 0x4000 /* used to indicate sel allocated */
+#define STE_GDTSEG 0x8000 /* used to indicate GTD sel alloc */
+
+#define STE_HUGE_MASK STE_TYPE_MASK|STE_SHARED|STE_SEGDPL
+#define STE_RSRC_HUGE STE_HUGE_MASK & ((NOT STE_TYPE_MASK)|STE_PRELOAD)
+
+#define ISRSRC 1 /* flag to indice we have a rsrc seg */
+/* XLATOFF */
+typedef struct ldrste_s ldrste_t; /* Segment table entry */
+
+struct ri_s { /* relocation data item */
+ uchar_t ri_stype; /* sources type */
+ uchar_t ri_flags; /* target type */
+ ushort_t ri_source; /* source offset */
+ ushort_t ri_target_seg; /* target segment index */
+ ushort_t ri_target_off; /* target entry offset index */
+};
+
+typedef struct ri_s ri_t;
+
+#define ri_target_modnam ri_target_seg
+#define ri_target_impnam ri_target_off
+#define ri_target_ord ri_target_off
+
+#define RELOCSPERBUF 8
+#define RELOCBUFLEN (sizeof(struct ri_s) * RELOCSPERBUF)
+
+#define SOURCE_MASK 0x07
+#define BYTE_ADR 0x00 /* Byte source location */
+#define SEG_ADR 0x02 /* Base source location */
+#define FAR_ADR 0x03 /* Pointer source location */
+#define OFF_ADR 0x05 /* Offset source location */
+#define TARGET_MASK 0x03
+#define INTERNALREF 0x00
+#define IMPORTORDINAL 0x01
+#define IMPORTNAME 0x02
+#define ADDITIVE 0x04
+
+/*
+ * The sfr_s is used to store segment fixup information so we can
+ * page segments.
+ *
+ * If sfr_fchained, then sfr_soff holds the count of chain records
+ * immediately following the fixup data bytes (sfr_bytes). If records
+ * are not chained, then sfr_soff holds the page offset for the fixup
+ * data.
+ *
+ */
+#define SFR_DATALEN 4
+struct sfr_s { // Segment fixup record
+ unsigned short sfr_fchained:1; // Flag: Is it chained
+ unsigned short sfr_fixsize:3; // Number of bytes in fixup
+ unsigned short sfr_soff:12; // Page offset or count of fixups
+ unsigned char sfr_bytes[SFR_DATALEN]; // Fixup data bytes
+ } ;
+
+typedef struct sfr_s sfr_t;
+
+#define SFR_HEADSIZE (sizeof(sfr_t)-SFR_DATALEN)
+
+#define PAGESPERSEGMENT 16
+
+/*
+ * segfix iterated record
+ */
+struct sfir_s {
+ ulong_t sfir_doffset; // Offset into data file
+ ushort_t sfir_soffset; // Offset into segment
+ ushort_t sfir_cbdata; // Number of bytes in record
+ ushort_t sfir_count; // Number of iterations
+};
+
+typedef struct sfir_s sfir_t;
+
+
+
+struct ldret_s /* General entry table types */
+{
+ unsigned char et_cnt; /* Number of entries in this bundle */
+ unsigned char et_type; /* Bundle type */
+ unsigned short et_obj; /* Object number */
+}; /* Follows entry types */
+
+typedef struct ldret_s ldret_t;
+
+/***EC+ B16 - 16-bit bundle types */
+#define EMPTY 0x00 /* empty bundle */
+#define B16EMPTY EMPTY /* empty bundle */
+#define B16ABSOLUTE 0xFE /* absolute entry bundle */
+#define B16MOVABLE 0xFF /* movable entry bundle */
+/*end*/
+
+/***ET+ ldrcte_t - Loader call thunk entry for 16-bit entry table */
+
+#pragma pack(1)
+struct ldrcte_s {
+ uchar_t cte_flags; /* entry flags */
+ ushort_t cte_sel; /* space for callgate selector */
+ uchar_t cte_obj; /* object index */
+ ushort_t cte_off; /* offset of routine entry point */
+};
+
+typedef struct ldrcte_s ldrcte_t; /* Loader call thunk entry */
+/*end*/
+
+/***ET+ ldrent_t - Loader Exported entry for 16-bit entry table */
+
+struct ldrent_s {
+ uchar_t ent_flags; /* entry flags */
+ ushort_t ent_off; /* offset of routine entry point */
+};
+
+#pragma pack()
+
+typedef struct ldrent_s ldrent_t; /* Loader exported entry */
+/*end*/
+
+/***+ ldrempty_t unused entry */
+struct ldrempty_s {
+ uchar_t empty_count; /* count of empty entries */
+ uchar_t empty_type; /* type 0 for empty */
+};
+
+typedef struct ldrempty_s ldrempty_t;
+/*end*/
+
+/***ET+ ldrfwd_t forwarder entry table entry */
+struct ldrfwd_s {
+ uchar_t fwd_flags; /* entry flags */
+ ushort_t fwd_modord; /* module ordinal */
+ ulong_t fwd_value; /* offset in table, or ordinal */
+ };
+
+typedef struct ldrfwd_s ldrfwd_t;
+/*end*/
+
+/***ET+ ldrfrt_t 32-bit fixup page table */
+
+#define fr_stype nr_stype
+#define fr_flags nr_flags
+
+typedef struct r32_rlc ldrfrt_t;
+/*end*/
+
+struct ldrefrt_s { /* expanded fixup record */
+ ulong_t efr_tgt; /* 32-bit target field */
+ ulong_t efr_add; /* addtive value */
+ ushort_t efr_srcoff; /* source offset */
+ ushort_t efr_tobj; /* target object or ordinal */
+ uchar_t efr_stype; /* source type */
+ uchar_t efr_flags; /* flags */
+ uchar_t efr_cchain; /* count for chained records */
+};
+
+typedef struct ldrefrt_s ldrefrt_t;
+
+struct objmem_s {
+ ulong_t flobj; /* allocation flags needed */
+};
+
+
+/*
+ * Warning this structure must match the structure defined in the ASM
+ * part at the end of this file
+ */
+
+struct taddr_s {
+ ulong_t toff;
+ ushort_t tsel;
+ uchar_t tflags;
+ /*
+ * For use by ldrGetFwdEnt():
+ */
+ uchar_t fflags; /* forwarder flags */
+ ushort_t cgsel; /* callgate selector */
+};
+
+/* The structure of a non-resident name table is as follows: */
+
+struct nonres_s {
+ struct nonres_s *nr_link; /* link to next non-resident table */
+ ushort_t nr_mte; /* mte handle to which names belong */
+ uchar_t nr_names; /* nonresident nametable from file */
+};
+
+// #define NT_TYPEINFO 0x80 // YosefD Mar-24-1996 Not in use
+#define E32EXPORT 0x01
+
+#if 0
+struct bndl_s {
+ uchar_t bndl_cnt;
+ uchar_t bndl_type;
+};
+#endif
+
+struct hit_s {
+ ulong_t offset; /* offset of field in mte */
+ ulong_t cnt; /* count of bytes to copy */
+};
+
+struct his_s {
+ ulong_t offset; /* offset of field in ste */
+ ulong_t cnt; /* count of bytes to copy */
+};
+
+struct etmt_s {
+ ushort_t offset; /* offset of field in linker exe image */
+};
+
+struct zmt_s {
+ ushort_t offset; /* offset of field in swappable MTE */
+ uchar_t size; /* size of field */
+ uchar_t zero; /* flag to zero or not */
+};
+
+struct objflags_s {
+ ulong_t flobj; /* object's flags */
+ ulong_t flVM; /* required allocation flags */
+};
+
+struct selflags_s {
+ ulong_t flobj; /*object's flags */
+ ushort_t fsSEL; /* required allocation flags */
+};
+
+struct pgstatechg_s {
+ ulong_t flpage; /* allocation flags needed */
+};
+
+
+/***ET+ ldrlv_t - Loader local variables */
+
+struct ldrlv_s {
+ ldrmte_t *lv_pmte; /* pointer to mte */
+ ulong_t lv_lbufaddr; /* linear addr of alloc buf from PG */
+ ulong_t lv_sbufaddr; /* segment addr of alloc buf from PG */
+ ulong_t lv_new_exe_off; /* offset relative begin of new exe */
+ HANDLE lv_sfn; /* current system file number */
+ ushort_t lv_hobmte; /* handle of current mte */
+ ulong_t lv_objnum; /* object number */
+ ushort_t lv_class; /* module class */
+ uchar_t lv_type; /* module type */
+};
+
+typedef struct ldrlv_s ldrlv_t; /* Loader local variables */
+
+/*end*/
+
+/***ET+ ldrrsrc16_t 16-bit Resource structure */
+
+struct ldrrsrc16_s {
+ ushort_t ldrrsrc16_type;
+ ushort_t ldrrsrc16_name;
+};
+
+typedef struct ldrrsrc16_s ldrrsrc16_t;
+/*end*/
+
+
+/***ET+ ldrrsrc32_t 32-bit Resource structure */
+
+struct ldrrsrc32_s {
+ ushort_t rsrctype; /* Resource type */
+ ushort_t rsrcname; /* Resource name */
+ ulong_t rsrccb; /* Resource size */
+ ushort_t rsrccodepage; /* Resource codepage */
+ ushort_t rsrcobj; /* Obj num rsrc is found in */
+ ulong_t rsrcoffset; /* Offset within object */
+};
+
+typedef struct ldrrsrc32_s ldrrsrc32_t;
+/*end*/
+
+
+/***ET+ Resource segment structure, kept in BMP segment */
+
+struct ldrrsrc_s {
+ ulong_t rsrc_typeid; /* resource type id */
+ ulong_t rsrc_nameid; /* resource name id */
+ ushort_t rsrc_mte; /* owner */
+ ushort_t rsrc_refcount; /* local reference count */
+ ushort_t rsrc_localptr; /* local PTDA chain */
+ ushort_t rsrc_globalptr; /* global chain */
+};
+
+typedef struct ldrrsrc_s ldrrsrc_t;
+/*end*/
+
+
+/***ET+ ldrrrsrc_t Return Resource structure */
+
+struct ldrrrsrc_s {
+ ptr_t ldrrrsrc_ptr;
+ int ldrrrsrc_type;
+};
+
+typedef struct ldrrrsrc_s ldrrrsrc_t;
+
+/***ET+ ldrrsrcinfo_t Store resource info */
+
+struct ldrrsrcinfo_s {
+ ulong_t ldrrsrcinfo_flag;
+ ulong_t ldrrsrcinfo_size;
+ ulong_t ldrrsrcinfo_pote;
+ ulong_t ldrrsrcinfo_iatsize;
+};
+typedef struct ldrrsrcinfo_s ldrrsrcinfo_t;
+
+/***ET+ ldrwhois_t who is sructure */
+
+struct ldrwhois_s {
+ ushort_t whois_ssegnum;
+ ushort_t whois_hmte;
+ uchar_t whois_achname[256];
+};
+
+typedef struct ldrwhois_s ldrwhois_t;
+/*end*/
+
+#define STRINGNULLTERM 0
+#define STRINGNONNULL 1
+#define NO_FORCE_PRELOAD 0
+#define FORCE_PRELOAD 1
+#define MAX_DEMAND_READ 8 /* current we can only read 8 pages */
+#ifdef RANGE
+#define RANGEINVALID (INVALID | RANGE)
+#define RANGEZEROED (ZEROED | RANGE)
+#endif
+
+#define LOAD_PAGE 0 /* return value for LDRGetPGInfo */
+#define LOAD_SEGMENT 1 /* return value for LDRGetPGInfo */
+#define ALIGNMENT_SHIFT 512 /* logical sector alignment shift */
+#define ENDMTETBL 0xDEAD /* mark end of validatetbl */
+#define rsrcvalidatetbl 3 /* rsrc table is 3rd entry in tbl */
+#define SKIPCOPY -1
+
+#define MAX_NAME_LEN 8
+#define MAX_PROC_LEN 256 /* Max proc name length incl. NUL */
+#define MAXPATHLEN 260
+
+#define EXT_PROGRAM 0 /* program */
+#define EXT_LIBRARY 1 /* library */
+#define EXT_DEVICE 2 /* device driver */
+#define EXT_FSD 3 /* installable file system */
+#define EXT_VDD 4 /* VDD */
+
+#define CHECK_ALL 1 /* Use full set off invalid chars */
+#define CHECK_WILDCARDS 2 /* Use wild card char set */
+#define MIN_CHAR_VALUE 0x20 /* space */
+#define LDR_16bit 0 /* 16-bit module */
+#define LDR_32bit 1 /* 32-bit module */
+#define LDR_PORTHOLE 2 /* Porthole Init module */
+#define EF_EXPORT 1 /* entry is exported */
+#define EF_GDATA 2 /* entry uses global shared data */
+
+/*
+ * Sub-function code for DosQueryHeaderInfo
+ */
+#define HEADER_EXEINFO 1 /* return fields values from EXE hdr */
+#define HEADER_READRSRCTBL 2 /* return pointer of rsrc table */
+#define HEADER_READSECTOR 3 /* read resource table */
+#define HEADER_LIBPATHLEN 4 /* return length of LIBPATH */
+#define HEADER_LIBPATH 5 /* return LIBPATH string */
+#define HEADER_FIXENTRY 6 /* fix a value in entry table */
+#define HEADER_STE 7 /* return segment table info */
+#define HEADER_MAPSEL 8 /* map selector to segment number */
+
+
+/***LT+ ldrdld_t - Loader Demand Load Data.
+ *
+ * Each process (PTDA) has a chain of ldrdld records, managed
+ * by the loader, allocated from the kernel heap, to keep track
+ * of the runtime attachments to a process.
+ *
+ * The ldrdld records are created on the initial attachment
+ * to a module via a DOSLOADMODULE call, setting ldrdld_cRef
+ * to 1. Subsequent DOSLOADMODULE calls increment ldrdld_cRef
+ * for the appropriate record. ldrdld_cRef is decremented when
+ * the program calls DOSFREEMODULE, and the record is removed
+ * if ldrdld_cRef goes to Zero. The entire chain of ldrdld
+ * records is freed when the process dies, in LDRFreeTask.
+ */
+
+struct ldrdld_s {
+ struct ldrdld_s *dld_next; // MUST be first element in structure!
+ ldrmte_t *dld_mteptr;
+ ULONG Cookie; // This field holds a unique value for each
+ // process. We chose the address of the process's
+ // OS2_PROCESS data structure.
+ ULONG dld_usecnt;
+};
+
+typedef struct ldrdld_s ldrdld_t;
+
+
+/***LT ldrpip_t - page count packet
+ * used by ldrMakeIDCache32, getpages and ldrProcessObjects
+ */
+struct ldrpip_s {
+ ulong_t pip_pbuf; /* Pointer to load buffer */
+ int pip_spbf; /* Starting page in load buffer */
+ int pip_cpbf; /* Count of pages in load buffer */
+ int pip_maxp; /* Max. page to read */
+};
+typedef struct ldrpip_s ldrpip_t;
+
+/**LT ldrmodhdr - return structure for MTE info
+ * used to return info from the MTE.
+ */
+struct ldrmhdr_s {
+ ushort_t mhdr_flags; /* ne_flags */
+ ushort_t mhdr_flagsothers; /* ne_flagsothers */
+ ushort_t mhdr_exetyp; /* ne_exetyp */
+ ushort_t mhdr_expver; /* ne_expver */
+ ulong_t mhdr_rsrctab; /* mte_rsrctab */
+ ulong_t mhdr_restab; /* mte_restab */
+ ushort_t mhdr_sfn; /* sfn */
+};
+typedef struct ldrmhdr_s ldrmhdr_t;
+
+#ifdef KM_REG_DS
+/***LT dllterm_t - DLL termination data buffer
+ *
+ * This buffer contains the registers of the caller of
+ * DosFreeModule as well as all the handles of all the
+ * modules requiring termination notification.
+ */
+
+struct dllterm_s {
+ struct dllterm_s *dllt_pdlltnext; /* Next record in chain */
+ struct kmreg_s dllt_regs; /* User registers */
+ ushort_t dllt_chmod; /* # of module handles left to call */
+ VMHOB dllt_ahmod[1]; /* Array of handles (var length) */
+};
+typedef struct dllterm_s dllterm_t;
+#endif
+
+
+/**LT ldrnewseg - return structure for STE info
+ * used to return info from the STE
+ */
+struct newseg { /* Segment Table entry info */
+ USHORT ns_sector; /* file sector of start of segment */
+ USHORT ns_cbseg; /* number of bytes in file */
+ USHORT ns_flags; /* attribute flags */
+ USHORT ns_minalloc; /* minimum alloc in bytes */
+};
+typedef struct ldrnewseg_s ldrnewseg_t;
+
+#define ldrNumToSte(pmte, objnum) ((ldrste_t *) ldrNumToOte(pmte, objnum))
+
+#define LEMAGIC ((E32MAGIC2 << 8) | (E32MAGIC1))
+#define ldrIsLE(pmte) (*(short *) ((pmte)->mte_magic) == LEMAGIC)
+#define ldrIsNE(pmte) (*(short *) ((pmte)->mte_magic) == NEMAGIC)
+#define MAX_PRELOAD 10
+
+#define RESIZE64K(cb) (cb? (ulong_t) cb : (ulong_t) 64*1024)
+#define TCYIELD_CNT 31
+#define RSRC32TYPEID 0xffffffff
+#define LDRMAXHEAPCACHE 2048 /* Max. size of cache to put on heap */
+#define _5K 5*1024
+#define MINSEGPACKCNT ldrMINSEGPACKCNT
+#define MINPGPACKSIZE ldrMINPGPACKSIZE
+#define MAXSEGPACKSIZE ldrMAXSEGPACKSIZE
+#define HEADERBUFSIZE 512
+#define PAGESHIFT 12
+#define PAGESIZE (1 << PAGESHIFT)
+#define PAGEMASK (PAGESIZE - 1)
+#define WORDMASK 0xffff
+#define BYTEMASK 0xff
+#define WORDSHIFT 16
+
+/***LP ldrAssert - cause internal error if assertion fails
+ *
+ * Given a boolean, this procedure causes an internal error if
+ * the boolean is false. Typically, the value of this boolean is
+ * derived from some test expression.
+ *
+ * ldrAssert (e)
+ *
+ * ENTRY e - boolean value (int)
+ * RETURN NONE
+ *
+ * CALLS panicfmt
+ *
+ * WARNING This procedure is implemented as a macro.
+ *
+ * EFFECTS NONE
+ */
+#ifdef LDRSTRICT
+# define ldrAssert(e) _assert(e)
+#else
+# define ldrAssert(e)
+#endif
+
+
+/***LP ldrStop - stop in kernel debugger
+ *
+ * If the global ldrErr is TRUE and the mte pointer is not doscalls
+ * or is null, this routine transfers control to the kernel debugger.
+ *
+ * ldrStop (id, pmte)
+ *
+ * ENTRY id - identifier of caller (ignored)
+ * pmte - mte pointer or NULL
+ * RETURN NONE
+ *
+ * CALLS Debug_BreakDM
+ *
+ * EFFECTS NONE
+ */
+#if DBG
+ extern void ldrStop(int id, void *pmte);
+#else
+#define ldrStop(id, pmte)
+#endif
+
+/*
+ * Forwarder declarations
+ */
+extern int ldrGetFwdEnt(struct AuxData *, ldrmte_t *);
+extern int ldrSelToFwdFlg (ushort_t);
+extern int ldrGetImport (ldrmte_t *, ulong_t, ushort_t, int,
+ ldrmte_t **, ushort_t *);
+/*
+ * Values for forwarder flags after processing:
+ */
+#define FWD_ALIAS16 0x01 /* Target object requires 16:16 alias */
+#define FWD_SPECIAL 0x02 /* DOSMOD, FSHMOD, MVDMMOD */
+#define FWD_PROCESSED 0x04 /* Forwarder has been processed */
+#define FWD_SHIFT 3 /* Flat target selector field is 0x38 */
+#define FWD_GATE16 0x40 /* 286 call gate */
+#define FWD_IOPL 0x80 /* Target object has I/O privilege */
+
+/*
+ * Other forwarder constants.
+ */
+#define ERROR_LDR_FWD -1 /* Return code indicating forwarder */
+#define LDRFWDMAX 1024 /* Max length of forwarder chain */
+#define SMALLFWDMAX 3 /* Max length of chain to fix up in memory */
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+extern ldrmte_t *mte_h; /* head of linked mte list */
+
+extern ldrmte_t *program_h; /* head of list of
+ program modules */
+extern ldrmte_t *program_l; /* tail of list of
+ program modules */
+extern ldrmte_t *global_h; /* head of list of
+ global modules */
+extern ldrmte_t *global_l; /* tail of list of
+ global modules */
+extern ldrmte_t *specific_h; /* head of list of
+ specific modules */
+extern ldrmte_t *specific_l; /* tail of list of
+ specific modules */
+extern ushort_t validatetbl[]; /* validation table */
+extern struct etmt_s ExeToResMTETbl[];/* Reduce EXE image to MTE */
+extern struct etmt_s ExeTo32SwapMTETbl[];/* Reduce EXE to LE MTE */
+extern struct etmt_s ExeTo16SwapMTETbl[];/* Reduce EXE to NE MTE */
+extern struct objflags_s objflags[]; /* object flags table */
+extern struct selflags_s selflags[]; /* selector flags table */
+extern struct objmem_s objmem[]; /* memory type flags table */
+extern struct pgstatechg_s pgstatechg[]; /* set type table */
+extern ushort_t ldrInitCallGate;
+extern ulong_t ldrMINSEGPACKCNT;
+extern ulong_t ldrMINPGPACKSIZE;
+extern ulong_t ldrMAXSEGPACKSIZE;
+extern char LdrBuf[MAXPATHLEN+14]; // 14 is for the '\OS2SS\DRIVES\'
+
+extern void load_error(int errcode, ldrmte_t * pmte);
+
+extern USHORT LDRDoscallsSel;
+
+#define FIELDOFFSET(type,field) ((USHORT)&(((type *)0)->field))
+
+/***LP fMTEValid - Validate if MTE has a valid signature */
+#define fMTEValid(pmte) (ldrIsNE(pmte) || ldrIsLE(pmte))
+
+extern PUCHAR ldrSrcModNameBuf;
+extern ushort_t ldrSrcModNameBufL;
+extern PUCHAR ldrTgtModNameBuf;
+extern ushort_t ldrTgtModNameBufL;
+extern PUCHAR ldrProcNameBuf;
+extern ushort_t ldrProcNameBufL;
+#if PMNT
+extern PUCHAR ldrSaveSrcModNameBuf;
+extern ushort_t ldrSaveSrcModNameBufL;
+extern PUCHAR ldrSaveTgtModNameBuf;
+extern ushort_t ldrSaveTgtModNameBufL;
+extern PUCHAR ldrSaveProcNameBuf;
+extern ushort_t ldrSaveProcNameBufL;
+extern int ldrSaveRc;
+#endif
+
+/***LP ldrSetupSrcErrTxt - Sets up source module name in error text buffer
+ ***LP ldrInvSrcErrTxt - Invalidates source module in error text buffer
+ *
+ * This procedure is implemented as a macro.
+ *
+ * ENTRY pachmodname - ModuleName/FullPathName string
+ * cchmodname - length of string
+ *
+ * EXIT none - ldrSrcModNameBuf[L] is setup
+ *
+ */
+#define ldrSetupSrcErrTxt(pachmodname, cchmodname) \
+ ldrSrcModNameBuf = pachmodname; \
+ ldrSrcModNameBufL = cchmodname
+
+#define ldrInvSrcErrTxt() \
+ ldrSrcModNameBufL = 0;
+
+/***LP ldrSetupTgtErrTxt - Sets up target module name in error text buffer
+ ***LP ldrInvTgtErrTxt - Invalidates target module in error text buffer
+ *
+ * This procedure is implemented as a macro.
+ *
+ * ENTRY pachmodname - ModuleName/FullPathName string
+ * cchmodname - length of string
+ *
+ * EXIT none - ldrTgtModNameBuf[L] is setup
+ *
+ */
+#define ldrSetupTgtErrTxt(pachmodname, cchmodname) \
+ ldrTgtModNameBuf = pachmodname; \
+ ldrTgtModNameBufL = cchmodname
+
+#define ldrInvTgtErrTxt() \
+ ldrTgtModNameBufL = 0;
+
+#pragma pack(1)
+typedef struct _R2CallInfo {
+ UCHAR R2CallNearInst; // Opcode of the call near inst 0xFF
+ USHORT R2CommonEntry; // This field will contain a 400H
+ UCHAR R2BytesToCopy; // Total size of proc parameters to copy between stacks
+ USHORT R2EntryPointOff; // Offset of entry address of R2 routine
+ USHORT R2EntryPointSel; // Selector of entry address of R2 routine
+} R2CallInfo, *PR2CallInfo;
+#pragma pack()
+
diff --git a/private/os2/ldr/ldrvars.inc b/private/os2/ldr/ldrvars.inc
new file mode 100644
index 000000000..2893fb8d3
--- /dev/null
+++ b/private/os2/ldr/ldrvars.inc
@@ -0,0 +1,23 @@
+STE_TYPE_MASK EQU 0001H
+STE_CODE EQU 0000H
+STE_DATA EQU 0001H
+STE_PACKED EQU 0002H
+STE_SEMAPHORE EQU 0004H
+STE_ITERATED EQU 0008H
+STE_WAITING EQU 0010H
+STE_SHARED EQU 0020H
+STE_PRELOAD EQU 0040H
+STE_ERONLY EQU 0080H
+STE_RELOCINFO EQU 0100H
+STE_CONFORM EQU 0200H
+STE_RING_2 EQU 0800H
+STE_RING_3 EQU 0C00H
+STE_SEGDPL EQU 0C00H
+STE_HUGE EQU 1000H
+STE_PAGEABLE EQU 2000H
+STE_PRESENT EQU 2000H
+STE_SELALLOC EQU 4000H
+STE_GDTSEG EQU 8000H
+STE_HUGE_MASK EQU STE_TYPE_MASK OR STE_SHARED OR STE_SEGDPL
+STE_RSRC_HUGE EQU STE_HUGE_MASK AND ((NOT STE_TYPE_MASK) OR STE_PRELOAD)
+ISRSRC EQU 1
diff --git a/private/os2/ldr/makefile b/private/os2/ldr/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/os2/ldr/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/os2/ldr/mi.h b/private/os2/ldr/mi.h
new file mode 100644
index 000000000..65eebc912
--- /dev/null
+++ b/private/os2/ldr/mi.h
@@ -0,0 +1,497 @@
+/*static char *SCCSID = "@(#)mi.h 6.1 90/11/15";*/
+/*
+ * Machine instruction, flag definitions and character types
+ *
+ * SCCSID = @(#)mi.h 13.17 90/09/13
+ */
+
+// 386 eflags definitions
+
+#define F_AC 0x00040000 // (A)lignment (C)heck
+#define F_VM 0x00020000 // (V)irtual 8086 (M)ode
+#define F_RF 0x00010000 // (R)esume (F)lag
+#define F_NT 0x00004000 // (N)ested (T)ask
+#define F_NTCLEAR (~F_NT)
+#define F_IOPL0 0
+#define F_IOPL1 0x00001000
+#define F_IOPL2 0x00002000
+#define F_IOPL3 0x00003000
+#define F_IOPLMASK 0x00003000 // (I)/(O) (P)rivilege (L)evel
+#define F_IOPLSYS F_IOPL3 // wide open
+#define F_IOPLclear (~F_IOPLMASK)
+#define F_OVERFLOW 0x00000800
+#define F_DIRECTION 0x00000400
+#define F_INTERRUPT 0x00000200
+#define F_TRACE 0x00000100
+#define F_SIGN 0x00000080
+#define F_ZERO 0x00000040
+#define F_AUX 0x00000010
+#define F_PARITY 0x00000004
+#define F_CARRY 0x00000001
+#define F_UNDEFINED 0x0000802A
+
+// CR0 (Machine Status Register) bits
+
+#define CR0_PE 0x00000001 // (P)rotect (E)nable
+#define CR0_MP 0x00000002 // (M)onitor (P)rocessor extension
+#define CR0_EM 0x00000004 // (EM)ulate processor extension
+#define CR0_TS 0x00000008 // (T)ask (thread) (S)witched
+#define CR0_ET 0x00000010 // (E)xtension (T)ype, 0/1=287/387
+#define CR0_NE 0x00000020 // (N)umeric (E)xception 0/1=use 2/10h
+#define CR0_WP 0x00010000 // (W)rite (P)rotect in rings 0-2
+#define CR0_AM 0x00040000 // (A)lignment (M)ask, enable EFlags.AC
+#define CR0_NW 0x20000000 // (N)o (W)rite-through cache
+#define CR0_CD 0x40000000 // (C)ache (D)isable
+#define CR0_PG 0x80000000 // (P)a(G)ing enable
+#define CR0_RESERVED 0x1ffaffc0 // reserved bits
+
+/*
+ * Cache Operating Modes:
+ *
+ * CR0_CD CR0_NW Cache Fills Write-Throughs and Invalidates
+ * ------ ------ ----------- ------------------------------
+ * 1 1 disabled disabled
+ * 1 0 disabled enabled
+ * 0 1 INVALID combination - CR0 load causes GP fault
+ * 0 0 enabled enabled (Normal mode)
+ */
+
+// Machine Status Word bits (obsolete)
+
+#define MSW_PE CR0_PE
+#define MSW_MP CR0_MP
+#define MSW_EM CR0_EM
+#define MSW_TS CR0_TS
+#define MSW_ET CR0_ET
+
+// CR3 (Page Directory Base Register) bits
+
+#define CR3_WRITETHROUGH 0x00000008 // write-through cache (486 ignores)
+#define CR3_CACHEDISABLE 0x00000010 // cache disable
+#define CR3_FRAME 0xfffff000 // page directory physical frame number
+#define CR3_RESERVED 0x00000fe7 // reserved bits
+
+// Debug Registers
+
+#define DR_COUNT 0x4 // number of debug registers
+
+// DR6 (Debug Registers Status Register) bits
+
+#define DR6_B0 0x00000001 // breakpoint register 0 triggered
+#define DR6_B1 0x00000002 // breakpoint register 1 triggered
+#define DR6_B2 0x00000004 // breakpoint register 2 triggered
+#define DR6_B3 0x00000008 // breakpoint register 3 triggered
+#define DR6_BD 0x00002000 // ICE hardware active
+#define DR6_BS_BIT_INDEX 0xe // Single step trap
+#define DR6_BS (1 << DR6_BS_BIT_INDEX)
+#define DR6_BT 0x00008000 // TSS trap
+
+#define DR6_VALID (DR6_B0|DR6_B1|DR6_B2|DR6_B3|DR6_BD|DR6_BS|DR6_BT)
+#define DR6_RESERVED ~(DR6_VALID)
+
+// DR7 (Debug Register Control Register) bits
+
+#define DR7_L0 0x00000001 /* DR0 Local Enable */
+#define DR7_G0 0x00000002 /* DR0 Global Enable */
+#define DR7_L1 0x00000004 /* DR1 Local Enable */
+#define DR7_G1 0x00000008 /* DR1 Global Enable */
+#define DR7_L2 0x00000010 /* DR2 Local Enable */
+#define DR7_G2 0x00000020 /* DR2 Global Enable */
+#define DR7_L3 0x00000040 /* DR3 Local Enable */
+#define DR7_G3 0x00000080 /* DR3 Global Enable */
+
+#define DR7_LE 0x00000100 /* Local - Exact Match */
+#define DR7_GE 0x00000200 /* Global - Exact Match */
+
+#define DR7_RW0 0x00030000 /* DR0 RW bits */
+#define DR7_LEN0 0x000c0000 /* DR0 Len bits */
+#define DR7_RW1 0x00300000 /* DR1 RW bits */
+#define DR7_LEN1 0x00c00000 /* DR1 Len bits */
+#define DR7_RW2 0x03000000 /* DR2 RW bits */
+#define DR7_LEN2 0x0c000000 /* DR2 Len bits */
+#define DR7_RW3 0x30000000 /* DR3 RW bits */
+#define DR7_LEN3 0xc0000000 /* DR3 Len bits */
+
+#define DR7_RESERVED 0x0000fc00 /* DR7 Intel Reserved */
+
+#define DR7_EXECUTE 0x0 /* Execute */
+#define DR7_WRITE 0x1 /* Data Write */
+#define DR7_READWRITE 0x3 /* Data Read or Write */
+
+#define DR7_LEN_1 0x0 /* Length 1 bits */
+#define DR7_LEN_2 0x1 /* Length 2 */
+#define DR7_LEN_4 0x3 /* Length 4 */
+
+// Machine instruction, flag definitions and character types
+
+#define MI_ARPL 0x63 // ARPL instruction
+#define MI_HLT 0xf4 // HLT instruction
+#define MI_OPERANDSIZE 0x66 // Operand size override prefix
+#define MI_ADDRESSSIZE 0x67 // Address size override prefix
+#define MI_TWOBYTEOP 0x0f // Two byte opcode prefix
+
+#define MI_POP_DS 0x1f
+#define MI_POP_ES 0x07
+#define MI_POP_FS 0xA1 // second byte to 0Fh opcode
+#define MI_POP_GS 0xA9 // second byte to 0Fh opcode
+
+#define MI_INT3 0xCC
+#define MI_INT 0xCD
+#define MI_IRET 0xCF
+#define MI_LONG_JMP 0xEA
+#define MI_LONG_CALL 0x9A
+#define MI_LONG_RET 0xCB
+#define MI_LONG_RETn 0xCA
+#define MI_NEAR_RET 0xC3
+
+#define MI_IN_PORT_AL 0xE4 // Opcode of IN port,AL
+#define MI_IN_PORT_AX 0xE5 // Opcode of IN port,AX
+#define MI_OUT_PORT_AL 0xE6 // Opcode of OUT port,AL
+#define MI_OUT_PORT_AX 0xE7 // Opcode of OUT port,AX
+#define MI_IN_DX_AL 0xEC // Opcode of IN DX,AL
+#define MI_IN_DX_AX 0xED // Opcode of IN DX,AX
+#define MI_OUT_DX_AL 0xEE // Opcode of OUT DX,AL
+#define MI_OUT_DX_AX 0xEF // Opcode of OUT DX,AX
+
+#define MI_GROUP5 0xFF // 5th group of 11-bit opcode inst.s
+#define MI_SEGES 0x26 // ES override prefix
+#define MI_SEGCS 0x2E // CS override prefix
+#define MI_SEGSS 0x36 // SS override prefix
+#define MI_SEGDS 0x3E // DS override prefix
+#define MI_SEGFS 0x64 // FS override prefix
+#define MI_SEGGS 0x65 // GS override prefix
+
+// ESC opcode prefix and mask
+
+#define MI_ESCMASK 0xF8
+#define MI_ESC 0xD8
+
+// MOD field equates
+
+#define MI_MODMASK 0xC0 // MOD field mask
+#define MI_MODSHIFT 6 // MOD field shift
+#define MI_MODNONE 0x00 // MOD = 0 (no displacement)
+#define MI_MODBYTE 0x40 // MOD = 1 (byte displacement)
+#define MI_MODWORD 0x80 // MOD = 2 (word displacement)
+#define MI_MODREG 0xC0 // MOD = 3 (R/M field selects register)
+
+// REG field equates
+
+#define MI_REGMASK 0x38 // REG field mask
+#define MI_REGSHIFT 3 // REG field shift
+#define MI_REGAX 0x00 // REG = 0 (AX/AL)
+#define MI_REGCX 0x08 // REG = 1 (CX/CL)
+#define MI_REGDX 0x10 // REG = 2 (DX/DL)
+#define MI_REGBX 0x18 // REG = 3 (BX/BL)
+#define MI_REG3 0x18 // REG = 3 (part of 11-bit opcode)
+#define MI_REGSP 0x20 // REG = 4 (SP/AH)
+#define MI_REGBP 0x28 // REG = 5 (BP/CH)
+#define MI_REGSI 0x30 // REG = 6 (SI/DH)
+#define MI_REGDI 0x38 // REG = 7 (DI/BH)
+
+#define MI_REGES 0x00 // REG = 0 MOV seg,r/m or MOV r/m,seg
+#define MI_REGCS 0x08 // REG = 1
+#define MI_REGSS 0x10 // REG = 2
+#define MI_REGDS 0x18 // REG = 3
+#define MI_REGFS 0x20 // REG = 4
+#define MI_REGGS 0x28 // REG = 5
+
+// R/M field equates for memory operands (for 16-bit instructions)
+
+#define MI_RMMASK 0x07 // R/M field mask
+#define MI_RMSHIFT 0 // R/M field shift
+#define MI_RMBXSI 0x00 // R/M = 0 ([BX+SI])
+#define MI_RMBXDI 0x01 // R/M = 1 ([BX+DI])
+#define MI_RMBPSI 0x02 // R/M = 2 ([BP+SI])
+#define MI_RMBPDI 0x03 // R/M = 3 ([BP+DI])
+#define MI_RMSI 0x04 // R/M = 4 ([SI])
+#define MI_RMDI 0x05 // R/M = 5 ([DI])
+#define MI_RMBP 0x06 // R/M = 6 ([BP])
+#define MI_RMBX 0x07 // R/M = 7 ([BX])
+
+// 32 bit instruction equates
+
+#define MI_SIB_SSMASK 0xc0
+#define MI_SIB_SSSHIFT 0x06
+
+#define MI_SIB_INDEXMASK 0x38
+#define MI_SIB_INDEXSHIFT 0x03
+#define MI_SIB_INDEXNONE 0x20
+
+#define MI_SIB_BASEMASK 0x07
+#define MI_SIB_BASESHIFT 0x00
+#define MI_SIB_BASEESP 0x04
+#define MI_SIB_BASENONE 0x05
+
+#define MI_RMEDX 0x02
+#define MI_RMSIB 0x04
+#define MI_RMDISP 0x05
+#define MI_RMEBP 0x05
+
+#define MI_REG6 0x30
+#define MI_REGCR0 0x00
+
+// following machine instructions are used in Enable_386_Specific_code
+// in virtmgr.asm
+
+#define MI_PUSH_AX 0x50 // "push ax" instruction
+#define MI_PUSH_IMM 0x68 // "push immediate 16/32" instruction
+#define MI_MOV_REG_IMM 0xB8 // opcode for "mov reg,immediate" instr
+#define MI_MOV_REG_IMMEDIATE 0xB8 // opcode for "mov reg,immediate" instr
+#define MI_MOV_REG_REGMEM 0x8B // opcode for "mov reg,r/m 16/32" instr
+
+// Miscellaneous Opcodes
+
+#define MI_ADD_AX_IMM 0x05 // Opcode for Add (E)AX,imm(32)16
+#define MI_CALL_NEAR_REL 0xE8 // Opcode for Call NEAR (relative)
+#define SIZE_CALL_NEAR_REL 5 // Length of Call NEAR (relative) instr
+
+#define MI_LMSW_OPCODE 0x01 // LMSW
+
+#define MI_GET_CRx_OPCODE 0x20 // MOV r32,CRx
+#define MI_GET_DRx_OPCODE 0x21 // MOV r32,DRx
+#define MI_SET_CRx_OPCODE 0x22 // MOV CRx,r32
+#define MI_SET_DRx_OPCODE 0x23 // MOV DRx,r32
+#define MI_GET_TRx_OPCODE 0x24 // MOV r32,TRx
+#define MI_SET_TRx_OPCODE 0x26 // MOV TRx,r32
+
+#define MI_MOV_REG8_MEM8 0x8A // MOV reg8,mem8
+#define MI_MOV_SEG_MEM_OPCODE 0x8e // MOV seg,r/m16
+
+// WORD structure
+
+struct w_s {
+ uchar_t lobyte;
+ uchar_t hibyte;
+};
+#define LowByte lobyte
+#define HighByte hibyte
+
+// DWORD structure
+
+struct dw_s {
+ ushort_t loword;
+ ushort_t hiword;
+};
+
+// Far pointer structure
+
+struct FarPtr {
+ ushort_t Offst;
+ ushort_t Segmt;
+};
+
+// Far 32 bit pointer structure
+
+struct FarPtr32 {
+ ulong_t Offst32; // 32 bit offset
+ ushort_t Segmt32; // segment
+ ushort_t Pad32; // segment pad
+};
+
+/*** RETF16 - 16 bit RETF frame definition
+ *
+ * 16 bit RETF frame structure
+ */
+
+typedef struct retf16_s {
+ ushort_t retf16_ip;
+ ushort_t retf16_cs;
+} RETF16;
+
+typedef RETF16 *PRETF16;
+
+/*** RETF32 - 32 bit RETF frame definition
+ *
+ * 32 bit RETF frame structure
+ */
+
+typedef struct retf32_s {
+ ulong_t retf32_eip;
+ ushort_t retf32_cs;
+ ushort_t retf32_padcs;
+} RETF32;
+
+typedef RETF32 *PRETF32;
+
+/*** IRET16 - 16 bit IRET frame definition
+ *
+ * 16 bit IRET frame structure
+ */
+
+typedef struct iret16_s {
+ ushort_t iret16_ip;
+ ushort_t iret16_cs;
+ ushort_t iret16_flag;
+} IRET16;
+
+typedef IRET16 *PIRET16;
+
+// 16 bit Iret stack frame without privilege level transition
+
+struct Iret_s {
+ struct FarPtr I_CSIP;
+ ushort_t I_FLAGS;
+};
+
+struct IretFrame {
+ ushort_t IretIP ;
+ ushort_t IretCS ;
+ ushort_t IretFLAGS;
+};
+
+/* ASM IretCSIP EQU <DWORD PTR IretIP> */
+
+/*** IRET32 - 32 bit IRET frame definition
+ *
+ * 32 bit IRET frame structure
+ */
+
+typedef struct iret32_s {
+ ulong_t iret32_eip;
+ ushort_t iret32_cs;
+ ushort_t iret32_padcs;
+ ulong_t iret32_eflag;
+} IRET32;
+
+typedef IRET32 *PIRET32;
+
+// 32 bit Iret stack frame without privilege level transition
+
+struct Iret32_s {
+ struct FarPtr32 I32_CSEIP;
+ ulong_t I32_EFLAGS;
+};
+/* ASM
+I32_CS EQU <I32_CSEIP.Segmt32>
+I32_EIP EQU <I32_CSEIP.Offst32>
+I32_IP EQU <I32_CSEIP.Offst32.loword>
+I32_FLAGS EQU <I32_EFLAGS.loword>
+*/
+
+/*** PLTIRET16 - 16 bit IRET frame definition
+ *
+ * 16 bit IRET frame structure with privilege level transtion
+ */
+
+typedef struct pltiret16_s {
+ ushort_t pltiret16_ip;
+ ushort_t pltiret16_cs;
+ ushort_t pltiret16_flag;
+ ushort_t pltiret16_sp;
+ ushort_t pltiret16_ss;
+} PLTIRET16;
+
+typedef PLTIRET16 *PPLTIRET16;
+
+// 16 bit Protected mode iret stack frame with privilege level transition
+
+struct PLTIret_s {
+ struct FarPtr PI_CSIP;
+ ushort_t PI_FLAGS;
+ struct FarPtr PI_SSSP;
+};
+
+struct PLTIretFrame {
+ ushort_t PLTIretIP;
+ ushort_t PLTIretCS;
+ ushort_t PLTIretFLAGS;
+ ushort_t PLTIretSP;
+ ushort_t PLTIretSS;
+};
+
+/* ASM
+PLTIretCSIP EQU DWORD PTR PLTIretIP
+PLTIretSSSP EQU DWORD PTR PLTIretSP
+*/
+
+/*** PLTIRET32 - 32 bit IRET frame definition
+ *
+ * 32 bit IRET frame structure with privilege level transtion
+ */
+
+typedef struct pltiret32_s {
+ ulong_t pltiret32_eip;
+ ushort_t pltiret32_cs;
+ ushort_t pltiret32_padcs;
+ ulong_t pltiret32_eflag;
+ ulong_t pltiret32_esp;
+ ushort_t pltiret32_ss;
+ ushort_t pltiret32_padss;
+} PLTIRET32;
+
+typedef PLTIRET32 *PPLTIRET32;
+
+// 32 bit Protected mode iret stack frame with privilege level transition
+
+struct PLTIret32_s {
+ struct FarPtr32 PI32_CSEIP;
+ ulong_t PI32_EFLAGS;
+ struct FarPtr32 PI32_SSESP;
+};
+/* ASM
+PI32_CS EQU <PI32_CSEIP.Segmt32>
+PI32_EIP EQU <PI32_CSEIP.Offst32>
+PI32_SS EQU <PI32_SSESP.Segmt32>
+PI32_ESP EQU <PI32_SSESP.Offst32>
+PI32_FLAGS EQU <WORD PTR PI32_EFLAGS>
+*/
+
+// Generic 32-bit pointer structure
+
+/* XLATOFF */
+union ptr_u {
+ struct FarPtr ptr_far16; /* 16-bit far pointer */
+ ulong_t ptr_flat; /* 32-bit flat pointer */
+};
+typedef union ptr_u ptr_t; /* Generic pointer type */
+
+#define ptr_sel ptr_far16.Segmt
+#define ptr_off ptr_far16.Offst
+/* XLATON */
+
+/* ASM
+ptr_t STRUC
+ ptr_flat DD ?
+ptr_t ENDS
+ptr_off equ <ptr_flat.Offst>
+ptr_sel equ <ptr_flat.Segmt>
+*/
+
+
+// PUSHA stack frame
+
+struct pusha_s {
+ ushort_t pas_di;
+ ushort_t pas_si;
+ ushort_t pas_bp;
+ ushort_t pas_sp;
+ ushort_t pas_bx;
+ ushort_t pas_dx;
+ ushort_t pas_cx;
+ ushort_t pas_ax;
+};
+
+// PUSHAD stack frame
+
+struct pushad_s {
+ ulong_t pads_edi;
+ ulong_t pads_esi;
+ ulong_t pads_ebp;
+ ulong_t pads_esp;
+ ulong_t pads_ebx;
+ ulong_t pads_edx;
+ ulong_t pads_ecx;
+ ulong_t pads_eax;
+};
+
+/* ASM
+pads_di EQU <WORD PTR pads_edi>
+pads_si EQU <WORD PTR pads_esi>
+pads_bp EQU <WORD PTR pads_ebp>
+pads_sp EQU <WORD PTR pads_esp>
+pads_bx EQU <WORD PTR pads_ebx>
+pads_dx EQU <WORD PTR pads_edx>
+pads_cx EQU <WORD PTR pads_ecx>
+pads_ax EQU <WORD PTR pads_eax>
+*/
diff --git a/private/os2/ldr/newexe.h b/private/os2/ldr/newexe.h
new file mode 100644
index 000000000..305db12fd
--- /dev/null
+++ b/private/os2/ldr/newexe.h
@@ -0,0 +1,464 @@
+/*static char *SCCSID = "@(#)newexe.h 6.2 91/02/12";*/
+/*
+ * SCCSID = @(#)newexe.h 6.2 91/02/12
+ *
+ * Title
+ *
+ * newexe.h
+ * (C) Copyright Microsoft Corp 1984-1987
+ *
+ * Description
+ *
+ * Data structure definitions for the DOS 4.0/Windows 2.0
+ * executable file format.
+ *
+ */
+
+
+
+ /*_________________________________________________________________*
+ | |
+ | |
+ | DOS3 .EXE FILE HEADER DEFINITION |
+ | |
+ |_________________________________________________________________|
+ * */
+
+
+#define EMAGIC 0x5A4D /* Old magic number */
+#define ENEWEXE sizeof(struct exe_hdr)
+ /* Value of E_LFARLC for new .EXEs */
+#define ENEWHDR 0x003C /* Offset in old hdr. of ptr. to new */
+#define ERESWDS 0x0010 /* No. of reserved words (OLD) */
+#define ERES1WDS 0x0004 /* No. of reserved words in e_res */
+#define ERES2WDS 0x000A /* No. of reserved words in e_res2 */
+#define ECP 0x0004 /* Offset in struct of E_CP */
+#define ECBLP 0x0002 /* Offset in struct of E_CBLP */
+#define EMINALLOC 0x000A /* Offset in struct of E_MINALLOC */
+
+struct exe_hdr /* DOS 1, 2, 3 .EXE header */
+ {
+ unsigned short e_magic; /* Magic number */
+ unsigned short e_cblp; /* Bytes on last page of file */
+ unsigned short e_cp; /* Pages in file */
+ unsigned short e_crlc; /* Relocations */
+ unsigned short e_cparhdr; /* Size of header in paragraphs */
+ unsigned short e_minalloc; /* Minimum extra paragraphs needed */
+ unsigned short e_maxalloc; /* Maximum extra paragraphs needed */
+ unsigned short e_ss; /* Initial (relative) SS value */
+ unsigned short e_sp; /* Initial SP value */
+ unsigned short e_csum; /* Checksum */
+ unsigned short e_ip; /* Initial IP value */
+ unsigned short e_cs; /* Initial (relative) CS value */
+ unsigned short e_lfarlc; /* File address of relocation table */
+ unsigned short e_ovno; /* Overlay number */
+ unsigned short e_res[ERES1WDS];/* Reserved words */
+ unsigned short e_oemid; /* OEM identifier (for e_oeminfo) */
+ unsigned short e_oeminfo; /* OEM information; e_oemid specific */
+ unsigned short e_res2[ERES2WDS];/* Reserved words */
+ long e_lfanew; /* File address of new exe header */
+ };
+
+#define E_MAGIC(x) (x).e_magic
+#define E_CBLP(x) (x).e_cblp
+#define E_CP(x) (x).e_cp
+#define E_CRLC(x) (x).e_crlc
+#define E_CPARHDR(x) (x).e_cparhdr
+#define E_MINALLOC(x) (x).e_minalloc
+#define E_MAXALLOC(x) (x).e_maxalloc
+#define E_SS(x) (x).e_ss
+#define E_SP(x) (x).e_sp
+#define E_CSUM(x) (x).e_csum
+#define E_IP(x) (x).e_ip
+#define E_CS(x) (x).e_cs
+#define E_LFARLC(x) (x).e_lfarlc
+#define E_OVNO(x) (x).e_ovno
+#define E_RES(x) (x).e_res
+#define E_OEMID(x) (x).e_oemid
+#define E_OEMINFO(x) (x).e_oeminfo
+#define E_RES2(x) (x).e_res2
+#define E_LFANEW(x) (x).e_lfanew
+
+
+ /*_________________________________________________________________*
+ | |
+ | |
+ | OS/2 & WINDOWS .EXE FILE HEADER DEFINITION - 286 version |
+ | |
+ |_________________________________________________________________|
+ * */
+
+#define NEMAGIC 0x454E /* New magic number */
+#define NERESBYTES 8 /* Eight bytes reserved (now) */
+#define NECRC 8 /* Offset into new header of NE_CRC */
+
+struct new_exe /* New .EXE header */
+ {
+ unsigned short ne_magic; /* Magic number NE_MAGIC */
+ unsigned char ne_ver; /* Version number */
+ unsigned char ne_rev; /* Revision number */
+ unsigned short ne_enttab; /* Offset of Entry Table */
+ unsigned short ne_cbenttab; /* Number of bytes in Entry Table */
+ long ne_crc; /* Checksum of whole file */
+ unsigned short ne_flags; /* Flag word */
+ unsigned short ne_autodata; /* Automatic data segment number */
+ unsigned short ne_heap; /* Initial heap allocation */
+ unsigned short ne_stack; /* Initial stack allocation */
+ long ne_csip; /* Initial CS:IP setting */
+ long ne_sssp; /* Initial SS:SP setting */
+ unsigned short ne_cseg; /* Count of file segments */
+ unsigned short ne_cmod; /* Entries in Module Reference Table */
+ unsigned short ne_cbnrestab; /* Size of non-resident name table */
+ unsigned short ne_segtab; /* Offset of Segment Table */
+ unsigned short ne_rsrctab; /* Offset of Resource Table */
+ unsigned short ne_restab; /* Offset of resident name table */
+ unsigned short ne_modtab; /* Offset of Module Reference Table */
+ unsigned short ne_imptab; /* Offset of Imported Names Table */
+ long ne_nrestab; /* Offset of Non-resident Names Table */
+ unsigned short ne_cmovent; /* Count of movable entries */
+ unsigned short ne_align; /* Segment alignment shift count */
+ unsigned short ne_cres; /* Count of resource entries */
+ unsigned char ne_exetyp; /* Target operating system */
+ unsigned char ne_flagsothers; /* Other .EXE flags */
+ char ne_res[NERESBYTES];
+ /* Pad structure to 64 bytes */
+ };
+
+#define NE_MAGIC(x) (x).ne_magic
+#define NE_VER(x) (x).ne_ver
+#define NE_REV(x) (x).ne_rev
+#define NE_ENTTAB(x) (x).ne_enttab
+#define NE_CBENTTAB(x) (x).ne_cbenttab
+#define NE_CRC(x) (x).ne_crc
+#define NE_FLAGS(x) (x).ne_flags
+#define NE_AUTODATA(x) (x).ne_autodata
+#define NE_HEAP(x) (x).ne_heap
+#define NE_STACK(x) (x).ne_stack
+#define NE_CSIP(x) (x).ne_csip
+#define NE_SSSP(x) (x).ne_sssp
+#define NE_CSEG(x) (x).ne_cseg
+#define NE_CMOD(x) (x).ne_cmod
+#define NE_CBNRESTAB(x) (x).ne_cbnrestab
+#define NE_SEGTAB(x) (x).ne_segtab
+#define NE_RSRCTAB(x) (x).ne_rsrctab
+#define NE_RESTAB(x) (x).ne_restab
+#define NE_MODTAB(x) (x).ne_modtab
+#define NE_IMPTAB(x) (x).ne_imptab
+#define NE_NRESTAB(x) (x).ne_nrestab
+#define NE_CMOVENT(x) (x).ne_cmovent
+#define NE_ALIGN(x) (x).ne_align
+#define NE_CRES(x) (x).ne_cres
+#define NE_RES(x) (x).ne_res
+#define NE_EXETYP(x) (x).ne_exetyp
+#define NE_FLAGSOTHERS(x) (x).ne_flagsothers
+
+#define NE_USAGE(x) (WORD)*((WORD *)(x)+1)
+#define NE_PNEXTEXE(x) (WORD)(x).ne_cbenttab
+#define NE_ONEWEXE(x) (WORD)(x).ne_crc
+#define NE_PFILEINFO(x) (WORD)((DWORD)(x).ne_crc >> 16)
+
+
+/*
+ * Target operating systems
+ */
+
+#define NE_UNKNOWN 0x0 /* Unknown (any "new-format" OS) */
+#define NE_OS2 0x1 /* Microsoft/IBM OS/2 (default) */
+#define NE_WINDOWS 0x2 /* Microsoft Windows */
+#define NE_DOS4 0x3 /* Microsoft MS-DOS 4.x */
+#define NE_DEV386 0x4 /* Microsoft Windows 386 */
+
+
+/*
+ * Format of NE_FLAGS(x):
+ *
+ * p Not-a-process
+ * x Unused
+ * e Errors in image
+ * x Unused
+ * b Bound Family/API
+ * ttt Application type
+ * f Floating-point instructions
+ * 3 386 instructions
+ * 2 286 instructions
+ * 0 8086 instructions
+ * P Protected mode only
+ * p Per-process library initialization
+ * i Instance data
+ * s Solo data
+ */
+#define NENOTP 0x8000 /* Not a process */
+#if PMNT
+#define NEPMSHELL 0x4000 /* PM Shell */
+#define NEPMMSGQUE 0x1000 /* calls WinCreateMsgQueue */
+#endif
+#define NEIERR 0x2000 /* Errors in image */
+#define NEBOUND 0x0800 /* Bound Family/API */
+#define NEAPPTYP 0x0700 /* Application type mask */
+#define NENOTWINCOMPAT 0x0100 /* Not compatible with P.M. Windowing */
+#define NEWINCOMPAT 0x0200 /* Compatible with P.M. Windowing */
+#define NEWINAPI 0x0300 /* Uses P.M. Windowing API */
+#define NEFLTP 0x0080 /* Floating-point instructions */
+#define NEI386 0x0040 /* 386 instructions */
+#define NEI286 0x0020 /* 286 instructions */
+#define NEI086 0x0010 /* 8086 instructions */
+#define NEPROT 0x0008 /* Runs in protected mode only */
+#define NEPPLI 0x0004 /* Per-Process Library Initialization */
+#define NEINST 0x0002 /* Instance data */
+#define NESOLO 0x0001 /* Solo data */
+
+/*
+ * Format of NE_FLAGSOTHERS(x):
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * |
+ * +---------------- Support for long file names
+ *
+ */
+
+#define NELONGNAMES 0x01
+
+
+
+struct new_seg /* New .EXE segment table entry */
+ {
+ unsigned short ns_sector; /* File sector of start of segment */
+ unsigned short ns_cbseg; /* Number of bytes in file */
+ unsigned short ns_flags; /* Attribute flags */
+ unsigned short ns_minalloc; /* Minimum allocation in bytes */
+ };
+
+#define NS_SECTOR(x) (x).ns_sector
+#define NS_CBSEG(x) (x).ns_cbseg
+#define NS_FLAGS(x) (x).ns_flags
+#define NS_MINALLOC(x) (x).ns_minalloc
+
+
+/*
+ * Format of NS_FLAGS(x)
+ *
+ * Flag word has the following format:
+ *
+ * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no
+ * | | | | | | | | | | | | | | |
+ * | | | | | | | | | | | | +-+-+--- Segment type DATA/CODE
+ * | | | | | | | | | | | +--------- Iterated segment
+ * | | | | | | | | | | +----------- Movable segment
+ * | | | | | | | | | +------------- Segment can be shared
+ * | | | | | | | | +--------------- Preload segment
+ * | | | | | | | +----------------- Execute/read-only for code/data segment
+ * | | | | | | +------------------- Segment has relocations
+ * | | | | | +--------------------- Code conforming/Data is expand down
+ * | | | +--+----------------------- I/O privilege level
+ * | | +----------------------------- Discardable segment
+ * | +-------------------------------- 32-bit code segment
+ * +----------------------------------- Huge segment/GDT allocation requested
+ *
+ */
+
+#define NSTYPE 0x0007 /* Segment type mask */
+
+#if (EXE386 == 0)
+#define NSCODE 0x0000 /* Code segment */
+#define NSDATA 0x0001 /* Data segment */
+#define NSITER 0x0008 /* Iterated segment flag */
+#define NSMOVE 0x0010 /* Movable segment flag */
+#define NSSHARED 0x0020 /* Shared segment flag */
+#define NSPRELOAD 0x0040 /* Preload segment flag */
+#define NSEXRD 0x0080 /* Execute-only (code segment), or
+ * read-only (data segment)
+ */
+#define NSRELOC 0x0100 /* Segment has relocations */
+#define NSCONFORM 0x0200 /* Conforming segment */
+#define NSEXPDOWN 0x0200 /* Data segment is expand down */
+#define NSDPL 0x0C00 /* I/O privilege level (286 DPL bits) */
+#define SHIFTDPL 10 /* Left shift count for SEGDPL field */
+#define NSDISCARD 0x1000 /* Segment is discardable */
+#define NS32BIT 0x2000 /* 32-bit code segment */
+#define NSHUGE 0x4000 /* Huge memory segment, length of
+ * segment and minimum allocation
+ * size are in segment sector units
+ */
+#define NSGDT 0x8000 /* GDT allocation requested */
+
+#define NSPURE NSSHARED /* For compatibility */
+
+#define NSALIGN 9 /* Segment data aligned on 512 byte boundaries */
+
+#define NSLOADED 0x0004 /* ns_sector field contains memory addr */
+#endif
+
+
+struct new_segdata /* Segment data */
+ {
+ union
+ {
+ struct
+ {
+ unsigned short ns_niter; /* number of iterations */
+ unsigned short ns_nbytes; /* number of bytes */
+ char ns_iterdata; /* iterated data bytes */
+ } ns_iter;
+ struct
+ {
+ char ns_data; /* data bytes */
+ } ns_noniter;
+ } ns_union;
+ };
+
+struct new_rlcinfo /* Relocation info */
+ {
+ unsigned short nr_nreloc; /* number of relocation items that */
+ }; /* follow */
+
+#pragma pack(1)
+
+
+struct new_rlc /* Relocation item */
+ {
+ char nr_stype; /* Source type */
+ char nr_flags; /* Flag byte */
+ unsigned short nr_soff; /* Source offset */
+ union
+ {
+ struct
+ {
+ char nr_segno; /* Target segment number */
+ char nr_res; /* Reserved */
+ unsigned short nr_entry; /* Target Entry Table offset */
+ } nr_intref; /* Internal reference */
+ struct
+ {
+ unsigned short nr_mod; /* Index into Module Reference Table */
+ unsigned short nr_proc; /* Procedure ordinal or name offset */
+ } nr_import; /* Import */
+ struct
+ {
+ unsigned short nr_ostype; /* OSFIXUP type */
+ unsigned short nr_osres; /* reserved */
+ } nr_osfix; /* Operating system fixup */
+ } nr_union; /* Union */
+ };
+
+#pragma pack()
+
+
+#define NR_STYPE(x) (x).nr_stype
+#define NR_FLAGS(x) (x).nr_flags
+#define NR_SOFF(x) (x).nr_soff
+#define NR_SEGNO(x) (x).nr_union.nr_intref.nr_segno
+#define NR_RES(x) (x).nr_union.nr_intref.nr_res
+#define NR_ENTRY(x) (x).nr_union.nr_intref.nr_entry
+#define NR_MOD(x) (x).nr_union.nr_import.nr_mod
+#define NR_PROC(x) (x).nr_union.nr_import.nr_proc
+#define NR_OSTYPE(x) (x).nr_union.nr_osfix.nr_ostype
+#define NR_OSRES(x) (x).nr_union.nr_osfix.nr_osres
+
+
+
+/*
+ * Format of NR_STYPE(x) and R32_STYPE(x):
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | | | |
+ * +-+-+-+--- source type
+ *
+ */
+
+#define NRSTYP 0x0f /* Source type mask */
+#define NRSBYT 0x00 /* lo byte (8-bits)*/
+#define NRSSEG 0x02 /* 16-bit segment (16-bits) */
+#define NRSPTR 0x03 /* 16:16 pointer (32-bits) */
+#define NRSOFF 0x05 /* 16-bit offset (16-bits) */
+#define NRPTR48 0x06 /* 16:32 pointer (48-bits) */
+#define NROFF32 0x07 /* 32-bit offset (32-bits) */
+#define NRSOFF32 0x08 /* 32-bit self-relative offset (32-bits) */
+
+
+/*
+ * Format of NR_FLAGS(x) and R32_FLAGS(x):
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | | |
+ * | +-+--- Reference type
+ * +------- Additive fixup
+ */
+
+#define NRADD 0x04 /* Additive fixup */
+#define NRRTYP 0x03 /* Reference type mask */
+#define NRRINT 0x00 /* Internal reference */
+#define NRRORD 0x01 /* Import by ordinal */
+#define NRRNAM 0x02 /* Import by name */
+#define NRROSF 0x03 /* Operating system fixup */
+
+
+#if (EXE386 == 0)
+
+/* Resource type or name string */
+struct rsrc_string
+ {
+ char rs_len; /* number of bytes in string */
+ char rs_string[ 1 ]; /* text of string */
+ };
+
+#define RS_LEN( x ) (x).rs_len
+#define RS_STRING( x ) (x).rs_string
+
+/* Resource type information block */
+struct rsrc_typeinfo
+ {
+ unsigned short rt_id;
+ unsigned short rt_nres;
+ long rt_proc;
+ };
+
+#define RT_ID( x ) (x).rt_id
+#define RT_NRES( x ) (x).rt_nres
+#define RT_PROC( x ) (x).rt_proc
+
+/* Resource name information block */
+struct rsrc_nameinfo
+ {
+ /* The following two fields must be shifted left by the value of */
+ /* the rs_align field to compute their actual value. This allows */
+ /* resources to be larger than 64k, but they do not need to be */
+ /* aligned on 512 byte boundaries, the way segments are */
+ unsigned short rn_offset; /* file offset to resource data */
+ unsigned short rn_length; /* length of resource data */
+ unsigned short rn_flags; /* resource flags */
+ unsigned short rn_id; /* resource name id */
+ unsigned short rn_handle; /* If loaded, then global handle */
+ unsigned short rn_usage; /* Initially zero. Number of times */
+ /* the handle for this resource has */
+ /* been given out */
+ };
+
+#define RN_OFFSET( x ) (x).rn_offset
+#define RN_LENGTH( x ) (x).rn_length
+#define RN_FLAGS( x ) (x).rn_flags
+#define RN_ID( x ) (x).rn_id
+#define RN_HANDLE( x ) (x).rn_handle
+#define RN_USAGE( x ) (x).rn_usage
+
+#define RSORDID 0x8000 /* if high bit of ID set then integer id */
+ /* otherwise ID is offset of string from
+ the beginning of the resource table */
+
+ /* Ideally these are the same as the */
+ /* corresponding segment flags */
+#define RNMOVE 0x0010 /* Moveable resource */
+#define RNPURE 0x0020 /* Pure (read-only) resource */
+#define RNPRELOAD 0x0040 /* Preloaded resource */
+#define RNDISCARD 0xF000 /* Discard priority level for resource */
+
+/* Resource table */
+struct new_rsrc
+ {
+ unsigned short rs_align; /* alignment shift count for resources */
+ struct rsrc_typeinfo rs_typeinfo;
+ };
+
+#define RS_ALIGN( x ) (x).rs_align
+
+
+#endif /* NOT EXE386 */
diff --git a/private/os2/ldr/os2defp.h b/private/os2/ldr/os2defp.h
new file mode 100644
index 000000000..fc727553e
--- /dev/null
+++ b/private/os2/ldr/os2defp.h
@@ -0,0 +1,30 @@
+/*static char *SCCSID = "@(#)os2defp.h 6.1 90/11/15";*/
+/*static char *SCCSID = "@(#)os2defp.h 13.6 90/08/28";*/
+/***************************************************************************\
+*
+* Module Name: OS2DEFP.H
+*
+* OS/2 Private common definitions include file
+*
+* Copyright (c) 1987 Microsoft Corporation
+*
+\***************************************************************************/
+
+typedef unsigned long ulong_t;
+typedef unsigned short ushort_t;
+typedef unsigned char uchar_t;
+typedef unsigned long vaddr_t;
+
+/* XLATOFF */
+typedef unsigned long dword;
+typedef unsigned short word;
+typedef unsigned char byte;
+
+typedef unsigned long DWORD;
+typedef unsigned short WORD;
+
+/* XLATON */
+
+typedef unsigned short SEL;
+
+/* XLATOFF */
diff --git a/private/os2/ldr/seldesc.h b/private/os2/ldr/seldesc.h
new file mode 100644
index 000000000..c54bb4862
--- /dev/null
+++ b/private/os2/ldr/seldesc.h
@@ -0,0 +1,265 @@
+/*static char *SCCSID = "@(#)seldesc.h 6.1 90/11/16";*/
+/* SCCSID = @(#)seldesc.h 13.2 90/07/10 */
+
+
+/*
+ * Microsoft Confidential
+ *
+ * Copyright (c) Microsoft Corporation 1987, 1989
+ *
+ * All Rights Reserved
+ */
+
+
+/*
+;----------------------------------------------------
+;
+; Some useful definitions
+;
+;----------------------------------------------------
+*/
+
+/* Definitions for selector fields */
+
+#define TABLE_MASK 0x004
+#define RPL_MASK 0x003
+#define RPL_CLR 0x0fffc
+
+#define RPL_RING0 0x000
+#define RPL_RING1 0x001
+#define RPL_RING2 0x002
+#define RPL_RING3 0x003
+
+
+
+/*
+; ---------------------------------------------------
+;
+; Definitions for the access byte in a descriptor
+;
+; ---------------------------------------------------
+*/
+
+/* Following fields are common to segment and control descriptors */
+
+#define D_PRES 0x80 /* present in memory */
+#define D_NOTPRES 0 /* not present in memory*/
+
+#define D_DPL0 0 /* Ring 0 */
+#define D_DPL1 0x20 /* Ring 1 */
+#define D_DPL2 0x40 /* Ring 2 */
+#define D_DPL3 0x60 /* Ring 3 */
+#define D_PRIV D_DPL3 /* DPL mask */
+
+#define D_SEG 0x10 /* Segment descriptor */
+#define D_CTRL 0 /* Control descriptor */
+
+
+/* Following fields are specific to control descriptors */
+
+#define D_TSS_BUSY_BIT 0x2 /* TSS busy bit */
+#define D_GATE 0x4 /* gate bit */
+#define D_32 0x8 /* 32 bit gate/descriptor bit */
+#define D_TSS 0x1 /* A Free TSS */
+#define D_LDT 0x2 /* LDT */
+#define D_TSS_BUSY (D_TSS+D_TSS_BUSY_BIT) /* A Busy TSS */
+#define D_CALLGATE (D_GATE+0) /* call gate */
+#define D_TASKGATE (D_GATE+1) /* task gate */
+#define D_INTGATE (D_GATE+2) /* interrupt gate */
+#define D_TRAPGATE (D_GATE+3) /* trap gate */
+#define D_TSS32 (D_TSS+D_32) /* 32 bit TSS */
+#define D_TSSBUSY32 (D_TSS_BUSY+D_32) /* busy 32 bit TSS */
+#define D_CALLGATE32 (D_CALLGATE+D_32) /* 32 bit call gate */
+#define D_INTGATE32 (D_INTGATE+D_32) /* 32 bit interrupt gate */
+#define D_TRAPGATE32 (D_TRAPGATE+D_32) /* 32 bit trap gate */
+
+#define D_TYPEMASK 0x0f /* descriptor type mask */
+#define D_WCMASK 0x01f /* word count mask (call gates) */
+#define D_MINGATE D_CALLGATE /* lowest numerical gate type */
+#define D_MAXGATE D_TRAPGATE32 /* highest numerical gate type */
+
+#define D_TSSBUSY_CLR (~D_TSS_BUSY_BIT)
+
+/* Following fields are specific to segment descriptors */
+
+#define D_CODE 0x8 /* code */
+#define D_DATA 0 /* data */
+
+#define D_CONFORM 0x4 /* if code, conforming */
+#define D_EXPDN 0x4 /* if data, expand down */
+
+#define D_RX 0x2 /* if code, readable */
+#define D_X 0 /* if code, exec only */
+#define D_W 0x2 /* if data, writable */
+#define D_R 0 /* if data, read only */
+
+#define D_ACCESSED 0x1 /* segment accessed bit */
+
+/*
+; ---------------------------------------------------
+;
+; Definitions for the attribute byte in a descriptor
+;
+; ---------------------------------------------------
+*/
+
+#define D_GRAN4K 0x80 /* 4k granularity (limit only) */
+#define D_COPER32 0x40 /* code: use 32 bit operand size */
+#define D_DBIG D_COPER32 /* data: use 32 bit offsets */
+#define D_PAD 0x20 /* unused */
+#define D_UVIRT 0x10 /* PhysToUvirt selector */
+#define D_EXTLIMIT 0x0f /* extended limit mask */
+#define D_1MEG 0x100000 /* 1 Meg */
+#define D_GRANMASK 0x0fffff /* 1Meg - 1 */
+
+/* Useful combination access rights bytes */
+
+#define D_DATA0 (D_PRES+D_DPL0+D_SEG+D_DATA+D_W) /* Ring 0 rw data */
+#define D_CODE0 (D_PRES+D_DPL0+D_SEG+D_CODE+D_RX) /* Ring 0 rx code */
+#define D_TRAP0 (D_PRES+D_DPL0+D_CTRL+D_TRAPGATE) /* Ring 0 trap gate */
+#define D_INT0 (D_PRES+D_DPL0+D_CTRL+D_INTGATE) /* Ring 0 int gate */
+#define D_TASK0 (D_PRES+D_DPL0+D_CTRL+D_TASKGATE) /* Ring 0 task gate */
+#define D_TSS0 (D_PRES+D_DPL0+D_CTRL+D_TSS) /* Ring 0 TSS */
+#define D_LDT0 (D_PRES+D_DPL0+D_CTRL+D_LDT) /* Ring 0 LDT */
+#define D_TRAP032 (D_PRES+D_DPL0+D_CTRL+D_TRAPGATE32) /* Ring 0 32-bit TG */
+#define D_INT032 (D_PRES+D_DPL0+D_CTRL+D_INTGATE32) /* Ring 0 32-bit IG */
+#define D_TSS032 (D_PRES+D_DPL0+D_CTRL+D_TSS32) /* Ring 0 32-bit TSS*/
+
+#define D_DATA1 (D_PRES+D_DPL1+D_SEG+D_DATA+D_W) /* Ring 1 rw data */
+#define D_CODE1 (D_PRES+D_DPL1+D_SEG+D_CODE+D_RX) /* Ring 1 rx code */
+
+#define D_DATA2 (D_PRES+D_DPL2+D_SEG+D_DATA+D_W) /* Ring 2 rw data */
+#define D_CODE2 (D_PRES+D_DPL2+D_SEG+D_CODE+D_RX) /* Ring 2 rx code */
+
+#define D_DATA3 (D_PRES+D_DPL3+D_SEG+D_DATA+D_W) /* Ring 3 rw data */
+#define D_CODE3 (D_PRES+D_DPL3+D_SEG+D_CODE+D_RX) /* Ring 3 rx code */
+#define D_INT3 (D_PRES+D_DPL3+D_CTRL+D_INTGATE) /* Ring 3 int gate */
+#define D_TRAP3 (D_PRES+D_DPL3+D_CTRL+D_TRAPGATE) /* Ring 3 trap gate */
+#define D_GATE3 (D_PRES+D_DPL3+D_CTRL+D_CALLGATE) /* Ring 3 call gate */
+#define D_INT332 (D_PRES+D_DPL3+D_CTRL+D_INTGATE32) /* Ring 3 32 bit int */
+#define D_GATE332 (D_PRES+D_DPL3+D_CTRL+D_CALLGATE32) /* Ring 3 32-bit CG */
+#define D_TRAP332 (D_PRES+D_DPL3+D_CTRL+D_TRAPGATE32) /* Ring 3 32-bit TG */
+
+
+/* Descriptor definition */
+
+struct desctab {
+ ushort_t d_limit; /* Segment limit */
+ ushort_t d_loaddr; /* Low word of physical address */
+ unsigned char d_hiaddr; /* High byte of physical address */
+ unsigned char d_access; /* Access byte */
+ unsigned char d_attr; /* Attributes/extended limit */
+ unsigned char d_extaddr; /* Extended physical address byte */
+};
+
+
+struct desc32 {
+ ulong_t d32_low; /* low dword in descriptor */
+ ulong_t d32_high; /* high dword in descriptor */
+};
+
+/* GDT free list descriptor definitions */
+
+#define d_flink d_loaddr /* Forward link */
+#define d_blink d_limit /* Back link */
+
+/* XLATOFF */
+struct gate {
+ ushort_t g_lowoffset; /* low word of offset */
+ ushort_t g_sel; /* selector to gate segment */
+ uchar_t g_parms; /* Parameter word count for call gate */
+ uchar_t g_access; /* Access byte */
+ ushort_t g_extoffset; /* Extended target offset */
+};
+
+/* XLATON */
+/* Following is for the old masm code only */
+
+/* ASM
+
+gate STRUC
+g_handler DD ?
+g_parms DB ?
+g_access DB ?
+g_extoffset DW ?
+gate ENDS
+
+g_lowoffset EQU WORD PTR g_handler
+g_sel EQU WORD PTR g_handler + 2
+
+*/
+
+/* LIDT/SIDT, LGDT/SGDT structure */
+
+struct lidt_s {
+ ushort_t lidt_limit; /* limit of idt or gdt */
+ ulong_t lidt_base; /* base of idt or gdt */
+};
+
+/*
+; Task State Segment structure definition
+*/
+
+struct tss_s {
+ ushort_t tss_backlink; /* backlink to prev task (none) */
+ ushort_t tss_reservdbl;
+ ulong_t tss_esp0;
+ ushort_t tss_ss0; /* ring 0 ss */
+ ushort_t tss_reservdss0;
+ ulong_t tss_esp1; /* ring 1 esp */
+ ushort_t tss_ss1; /* ring 1 ss */
+ ushort_t tss_reservdss1;
+ ulong_t tss_esp2; /* ring 2 esp */
+ ushort_t tss_ss2; /* ring 2 ss */
+ ushort_t tss_reservdss2;
+ ulong_t tss_cr3;
+ ulong_t tss_eip; /* entry point */
+ ulong_t tss_eflags; /* eflags */
+ ulong_t tss_eax;
+ ulong_t tss_ecx;
+ ulong_t tss_edx;
+ ulong_t tss_ebx;
+ ulong_t tss_esp;
+ ulong_t tss_ebp;
+ ulong_t tss_esi;
+ ulong_t tss_edi;
+ ushort_t tss_es;
+ ushort_t tss_reservdes;
+ ushort_t tss_cs;
+ ushort_t tss_reservdcs;
+ ushort_t tss_ss;
+ ushort_t tss_reservdss;
+ ushort_t tss_ds;
+ ushort_t tss_reservdds;
+ ushort_t tss_fs;
+ ushort_t tss_reservdfs;
+ ushort_t tss_gs;
+ ushort_t tss_reservdgs;
+ ushort_t tss_ldt;
+ ushort_t tss_reservdldt;
+ ushort_t tss_tflags;
+ ushort_t tss_iomap; /* I/O map TSS relative offset */
+} ;
+
+/* XLATOFF */
+typedef struct tss_s TSS;
+typedef TSS *PTSS;
+/* XLATON */
+
+
+/* tss_tflags bit definitions: */
+
+#define TSS_DEBUGTRAP 0x001 /* raise debug exception on task switch */
+
+/* 286/386 compatibility definitions: Needs to be included in seldesc.inc
+ file. */
+/* ASM
+tss_sp1 equ word ptr tss_esp1
+tss_sp2 equ word ptr tss_esp2
+tss_sp0 equ word ptr tss_esp0
+tss_ip equ word ptr tss_eip
+tss_bx equ word ptr tss_ebx
+tss_sp equ word ptr tss_esp
+tss_flags equ word ptr tss_eflags
+tss_cs0 equ word ptr tss_cs
+*/
diff --git a/private/os2/ldr/seldesc.inc b/private/os2/ldr/seldesc.inc
new file mode 100644
index 000000000..27d3996a2
--- /dev/null
+++ b/private/os2/ldr/seldesc.inc
@@ -0,0 +1,163 @@
+TABLE_MASK EQU 004H
+RPL_MASK EQU 003H
+RPL_CLR EQU 0fffcH
+RPL_RING0 EQU 000H
+RPL_RING1 EQU 001H
+RPL_RING2 EQU 002H
+RPL_RING3 EQU 003H
+D_PRES EQU 80H
+D_NOTPRES EQU 0
+D_DPL0 EQU 0
+D_DPL1 EQU 20H
+D_DPL2 EQU 40H
+D_DPL3 EQU 60H
+D_PRIV EQU D_DPL3
+D_SEG EQU 10H
+D_CTRL EQU 0
+D_TSS_BUSY_BIT EQU 2H
+D_GATE EQU 4H
+D_32 EQU 8H
+D_TSS EQU 1H
+D_LDT EQU 2H
+D_TSS_BUSY EQU (D_TSS+D_TSS_BUSY_BIT)
+D_CALLGATE EQU (D_GATE+0 )
+D_TASKGATE EQU (D_GATE+1 )
+D_INTGATE EQU (D_GATE+2 )
+D_TRAPGATE EQU (D_GATE+3 )
+D_TSS32 EQU (D_TSS+D_32)
+D_TSSBUSY32 EQU (D_TSS_BUSY+D_32)
+D_CALLGATE32 EQU (D_CALLGATE+D_32)
+D_INTGATE32 EQU (D_INTGATE+D_32)
+D_TRAPGATE32 EQU (D_TRAPGATE+D_32)
+D_TYPEMASK EQU 0fH
+D_WCMASK EQU 01fH
+D_MINGATE EQU D_CALLGATE
+D_MAXGATE EQU D_TRAPGATE32
+D_TSSBUSY_CLR EQU ( NOT D_TSS_BUSY_BIT)
+D_CODE EQU 8H
+D_DATA EQU 0
+D_CONFORM EQU 4H
+D_EXPDN EQU 4H
+D_RX EQU 2H
+D_X EQU 0
+D_W EQU 2H
+D_R EQU 0
+D_ACCESSED EQU 1H
+D_GRAN4K EQU 80H
+D_COPER32 EQU 40H
+D_DBIG EQU D_COPER32
+D_PAD EQU 20H
+D_UVIRT EQU 10H
+D_EXTLIMIT EQU 0fH
+D_1MEG EQU 100000H
+D_GRANMASK EQU 0fffffH
+D_DATA0 EQU (D_PRES+D_DPL0+D_SEG+D_DATA+D_W)
+D_CODE0 EQU (D_PRES+D_DPL0+D_SEG+D_CODE+D_RX)
+D_TRAP0 EQU (D_PRES+D_DPL0+D_CTRL+D_TRAPGATE)
+D_INT0 EQU (D_PRES+D_DPL0+D_CTRL+D_INTGATE)
+D_TASK0 EQU (D_PRES+D_DPL0+D_CTRL+D_TASKGATE)
+D_TSS0 EQU (D_PRES+D_DPL0+D_CTRL+D_TSS)
+D_LDT0 EQU (D_PRES+D_DPL0+D_CTRL+D_LDT)
+D_TRAP032 EQU (D_PRES+D_DPL0+D_CTRL+D_TRAPGATE32)
+D_INT032 EQU (D_PRES+D_DPL0+D_CTRL+D_INTGATE32)
+D_TSS032 EQU (D_PRES+D_DPL0+D_CTRL+D_TSS32)
+D_DATA1 EQU (D_PRES+D_DPL1+D_SEG+D_DATA+D_W)
+D_CODE1 EQU (D_PRES+D_DPL1+D_SEG+D_CODE+D_RX)
+D_DATA2 EQU (D_PRES+D_DPL2+D_SEG+D_DATA+D_W)
+D_CODE2 EQU (D_PRES+D_DPL2+D_SEG+D_CODE+D_RX)
+D_DATA3 EQU (D_PRES+D_DPL3+D_SEG+D_DATA+D_W)
+D_CODE3 EQU (D_PRES+D_DPL3+D_SEG+D_CODE+D_RX)
+D_INT3 EQU (D_PRES+D_DPL3+D_CTRL+D_INTGATE)
+D_TRAP3 EQU (D_PRES+D_DPL3+D_CTRL+D_TRAPGATE)
+D_GATE3 EQU (D_PRES+D_DPL3+D_CTRL+D_CALLGATE)
+D_INT332 EQU (D_PRES+D_DPL3+D_CTRL+D_INTGATE32)
+D_GATE332 EQU (D_PRES+D_DPL3+D_CTRL+D_CALLGATE32)
+D_TRAP332 EQU (D_PRES+D_DPL3+D_CTRL+D_TRAPGATE32)
+
+desctab STRUC
+d_limit DW ?
+d_loaddr DW ?
+d_hiaddr DB ?
+d_access DB ?
+d_attr DB ?
+d_extaddr DB ?
+desctab ENDS
+
+
+desc32 STRUC
+d32_low DD ?
+d32_high DD ?
+desc32 ENDS
+
+d_flink EQU d_loaddr
+d_blink EQU d_limit
+
+gate STRUC
+g_handler DD ?
+g_parms DB ?
+g_access DB ?
+g_extoffset DW ?
+gate ENDS
+
+g_lowoffset EQU WORD PTR g_handler
+g_sel EQU WORD PTR g_handler + 2
+
+
+
+lidt_s STRUC
+lidt_limit DW ?
+lidt_base DD ?
+lidt_s ENDS
+
+
+tss_s STRUC
+tss_backlink DW ?
+tss_reservdbl DW ?
+tss_esp0 DD ?
+tss_ss0 DW ?
+tss_reservdss0 DW ?
+tss_esp1 DD ?
+tss_ss1 DW ?
+tss_reservdss1 DW ?
+tss_esp2 DD ?
+tss_ss2 DW ?
+tss_reservdss2 DW ?
+tss_cr3 DD ?
+tss_eip DD ?
+tss_eflags DD ?
+tss_eax DD ?
+tss_ecx DD ?
+tss_edx DD ?
+tss_ebx DD ?
+tss_esp DD ?
+tss_ebp DD ?
+tss_esi DD ?
+tss_edi DD ?
+tss_es DW ?
+tss_reservdes DW ?
+tss_cs DW ?
+tss_reservdcs DW ?
+tss_ss DW ?
+tss_reservdss DW ?
+tss_ds DW ?
+tss_reservdds DW ?
+tss_fs DW ?
+tss_reservdfs DW ?
+tss_gs DW ?
+tss_reservdgs DW ?
+tss_ldt DW ?
+tss_reservdldt DW ?
+tss_tflags DW ?
+tss_iomap DW ?
+tss_s ENDS
+
+TSS_DEBUGTRAP EQU 001H
+tss_sp1 equ word ptr tss_esp1
+tss_sp2 equ word ptr tss_esp2
+tss_sp0 equ word ptr tss_esp0
+tss_ip equ word ptr tss_eip
+tss_bx equ word ptr tss_ebx
+tss_sp equ word ptr tss_esp
+tss_flags equ word ptr tss_eflags
+tss_cs0 equ word ptr tss_cs
+
diff --git a/private/os2/ldr/sources b/private/os2/ldr/sources
new file mode 100644
index 000000000..7fc8de06d
--- /dev/null
+++ b/private/os2/ldr/sources
@@ -0,0 +1,75 @@
+!IF 0
+*****************************************************************************
+Copyright (c) 1989, 1990 Microsoft Corporation
+
+Module Name: SOURCES for OS/2 subsystem loader
+
+Author: larrys
+
+Revision History:
+ 04-19-91 larrys original version
+*****************************************************************************
+!ENDIF
+
+#------------------------------------------------
+# INFO FOR CREATING LIBRARY
+#------------------------------------------------
+MAJORCOMP=os2
+MINORCOMP=ldr
+
+TARGETNAME=os2ldr
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+#TARGETLIBS=..\obj\*\os2ssrtl.lib ..\client\obj\*\os2dll.lib \
+# $(BASEDIR)\public\sdk\lib\*\ntcrt.lib
+
+#------------------------------------------------
+# INCLUDE PATH
+#------------------------------------------------
+
+INCLUDES=..\inc
+
+#------------------------------------------------
+# SOURCE FILES (used to make library)
+#------------------------------------------------
+SYNCHRONIZE_DRAIN=1
+WIMPYMASM=1
+
+NO_READONLY_STRINGS=1
+
+SOURCES=ldrmte.c \
+ ldrste.c \
+ ldrsubr.c \
+ ldrinit.c \
+ ldrutil.c \
+ ldrfixup.c \
+ ldrdbcs.c
+
+i386_SOURCES=
+
+#------------------------------------------------
+# FLAGS
+#------------------------------------------------
+
+!IFDEF PMNT
+
+C_DEFINES=-DOS2_CLIENT -DPMNT
+
+!ELSE
+
+C_DEFINES=-DOS2_CLIENT
+
+!ENDIF
+
+#------------------------------------------------
+# EXECUTABLES
+#------------------------------------------------
+
+#UMTYPE=os2
+
+#------------------------------------------------
+# LIBRARIES created by the SOURCES= line (above)
+# (currently commented out - not used)
+#------------------------------------------------
+
+#UMLIBS= ..\obj\*\os2ldr.lib