diff options
Diffstat (limited to '')
-rw-r--r-- | private/os2/ldr/basedef.h | 233 | ||||
-rw-r--r-- | private/os2/ldr/basemac.h | 129 | ||||
-rw-r--r-- | private/os2/ldr/bseerr.h | 856 | ||||
-rw-r--r-- | private/os2/ldr/exe386.h | 870 | ||||
-rw-r--r-- | private/os2/ldr/ldrdbcs.c | 159 | ||||
-rw-r--r-- | private/os2/ldr/ldrdbcs.h | 48 | ||||
-rw-r--r-- | private/os2/ldr/ldrdll.def | 28 | ||||
-rw-r--r-- | private/os2/ldr/ldrextrn.h | 127 | ||||
-rw-r--r-- | private/os2/ldr/ldrfixup.c | 483 | ||||
-rw-r--r-- | private/os2/ldr/ldrinit.c | 1415 | ||||
-rw-r--r-- | private/os2/ldr/ldrmte.c | 4290 | ||||
-rw-r--r-- | private/os2/ldr/ldrste.c | 1159 | ||||
-rw-r--r-- | private/os2/ldr/ldrsubr.c | 1962 | ||||
-rw-r--r-- | private/os2/ldr/ldrutil.c | 228 | ||||
-rw-r--r-- | private/os2/ldr/ldrvars.h | 928 | ||||
-rw-r--r-- | private/os2/ldr/ldrvars.inc | 23 | ||||
-rw-r--r-- | private/os2/ldr/makefile | 6 | ||||
-rw-r--r-- | private/os2/ldr/mi.h | 497 | ||||
-rw-r--r-- | private/os2/ldr/newexe.h | 464 | ||||
-rw-r--r-- | private/os2/ldr/os2defp.h | 30 | ||||
-rw-r--r-- | private/os2/ldr/seldesc.h | 265 | ||||
-rw-r--r-- | private/os2/ldr/seldesc.inc | 163 | ||||
-rw-r--r-- | private/os2/ldr/sources | 75 |
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 |