Changeset 129


Ignore:
Timestamp:
Jan 8, 2002, 7:29:57 PM (24 years ago)
Author:
umoeller
Message:

Executable updates, mostly.

Location:
trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/helpers/dosh.h

    r127 r129  
    360360        HFILE       hf;
    361361        ULONG       hmtx;       // a HMTX really
    362         ULONG       flOpenMode; // as given to doshOpen
     362
     363        PSZ         pszFilename;    // as given to doshOpen
     364        ULONG       flOpenMode;     // as given to doshOpen
     365
    363366        ULONG       cbInitial,  // intial file size on open (can be 0 if new)
    364367                    cbCurrent;  // current file size (raised with each write)
     368
     369        PBYTE       pbCache;    // if != NULL, cached data from doshReadAt
     370        ULONG       cbCache,    // size of data in cbCache
     371                    ulReadFrom; // file offset where pbCache was read from
    365372    } XFILE, *PXFILE;
    366373
     
    399406
    400407    APIRET doshLoadTextFile(PCSZ pcszFile,
    401                             PSZ* ppszContent);
     408                            PSZ* ppszContent,
     409                            PULONG pcbRead);
    402410
    403411    PSZ doshCreateBackupFileName(const char* pszExisting);
     
    463471                                 PUSHORT pusReturn);
    464472
    465     /********************************************************************
    466      *
    467      *   Executable helpers
    468      *
    469      ********************************************************************/
    470 
    471     #pragma pack(1)
    472 
    473     /*
    474      *@@ DOSEXEHEADER:
    475      *      old DOS EXE header at offset 0
    476      *      in any EXE file.
    477      *
    478      *@@changed V0.9.7 (2000-12-20) [umoeller]: fixed NE offset
    479      *@@changed V0.9.9 (2001-04-06) [lafaix]: additional fields defined
    480      */
    481 
    482     typedef struct _DOSEXEHEADER
    483     {
    484          USHORT usDosExeID;             // 00: DOS exeid (0x5a4d)
    485          USHORT usFileLenMod512;        // 02: filelen mod 512
    486          USHORT usFileLenDiv512;        // 04: filelen div 512
    487          USHORT usSegFix;               // 06: count of segment adds to fix
    488          USHORT usHdrPargCnt;           // 08: size of header in paragrphs
    489          USHORT usMinAddPargCnt;        // 0a: minimum addtl paragraphs count
    490          USHORT usMaxAddPargCnt;        // 0c: max addtl paragraphs count
    491          USHORT usSSStartup;            // 0e: SS at startup
    492          USHORT usSPStartup;            // 10: SP at startup
    493          USHORT usHdrChecksum;          // 12: header checksum
    494          USHORT usIPStartup;            // 14: IP at startup
    495          USHORT usCodeSegOfs;           // 16: code segment offset from EXE start
    496          USHORT usRelocTableOfs;        // 18: reloc table ofs.header (Win: >= 0x40)
    497          USHORT usOverlayNo;            // 1a: overlay no.
    498          USHORT usLinkerVersion;        // 1c: linker version (if 0x18 > 0x28)
    499          USHORT usUnused1;              // 1e: unused
    500          USHORT usBehaviorBits;         // 20: exe.h says this field contains
    501                                         //     'behavior bits'
    502          USHORT usUnused2;              // 22: unused
    503          USHORT usOEMIdentifier;        // 24: OEM identifier
    504          USHORT usOEMInformation;       // 26: OEM information
    505          ULONG  ulUnused3;              // 28:
    506          ULONG  ulUnused4;              // 2c:
    507          ULONG  ulUnused5;              // 30:
    508          ULONG  ulUnused6;              // 34:
    509          ULONG  ulUnused7;              // 38:
    510          ULONG  ulNewHeaderOfs;         // 3c: new header ofs (if 0x18 > 0x40)
    511                     // fixed this from USHORT, thanks Martin Lafaix
    512                     // V0.9.7 (2000-12-20) [umoeller]
    513     } DOSEXEHEADER, *PDOSEXEHEADER;
    514 
    515     // NE and LX OS types
    516     #define NEOS_UNKNOWN        0
    517     #define NEOS_OS2            1   // Win16 SDK says: "reserved"...
    518     #define NEOS_WIN16          2
    519     #define NEOS_DOS4           3   // Win16 SDK says: "reserved"...
    520     #define NEOS_WIN386         4   // Win16 SDK says: "reserved"...
    521 
    522     /*
    523      *@@ NEHEADER:
    524      *      linear executable (LX) header format,
    525      *      which comes after the DOS header in the
    526      *      EXE file (at DOSEXEHEADER.ulNewHeaderOfs).
    527      *
    528      *@@changed V0.9.9 (2001-04-06) [lafaix]: fixed typo in usMoveableEntries
    529      */
    530 
    531     typedef struct _NEHEADER
    532     {
    533         CHAR      achNE[2];             // 00: "NE" magic                       ne_magic
    534         BYTE      bLinkerVersion;       // 02: linker version                   ne_ver
    535         BYTE      bLinkerRevision;      // 03: linker revision                  ne_rev
    536         USHORT    usEntryTblOfs;        // 04: ofs from this to entrytable      ne_enttab
    537         USHORT    usEntryTblLen;        // 06: length of entrytable             ne_cbenttab
    538         ULONG     ulChecksum;           // 08: MS: reserved, OS/2: checksum     ne_crc
    539         USHORT    usFlags;              // 0c: flags                            ne_flags
    540                            /*
    541                               #define NENOTP          0x8000          // Not a process == library
    542                               #define NENOTMPSAFE     0x4000          // Process is not multi-processor safe
    543                                                                       // (Win3.1 SDK: "reserved")
    544                               #define NEIERR          0x2000          // Errors in image
    545                               #define NEBOUND         0x0800          // Bound Family/API
    546                                                                       // (Win3.1 SDK: "first segment contains code
    547                                                                       // that loads the application")
    548                               #define NEAPPTYP        0x0700          // Application type mask
    549                                                                       // (Win3.1 SDK: "reserved")
    550                               #define NENOTWINCOMPAT  0x0100          // Not compatible with P.M. Windowing
    551                                                                       // (Win3.1 SDK: "reserved")
    552                               #define NEWINCOMPAT     0x0200          // Compatible with P.M. Windowing
    553                                                                       // (Win3.1 SDK: "reserved")
    554                               #define NEWINAPI        0x0300          // Uses P.M. Windowing API
    555                                                                       // (Win3.1 SDK: "reserved")
    556                               #define NEFLTP          0x0080          // Floating-point instructions
    557                               #define NEI386          0x0040          // 386 instructions
    558                               #define NEI286          0x0020          // 286 instructions
    559                               #define NEI086          0x0010          // 8086 instructions
    560                               #define NEPROT          0x0008          // Runs in protected mode only
    561                                                                       // (Win3.1 SDK: "reserved")
    562                               #define NEPPLI          0x0004          // Per-Process Library Initialization
    563                                                                       // (Win3.1 SDK: "reserved")
    564                               #define NEINST          0x0002          // Instance data
    565                               #define NESOLO          0x0001          // Solo data (single data)
    566                            */
    567         USHORT    usAutoDataSegNo;      // 0e: auto-data seg no.                ne_autodata
    568                                         // (Win3.1 SDK: "0 if both NEINST and NESOLO are cleared")
    569         USHORT    usInitlHeapSize;      // 10: initl. heap size                 ne_heap
    570                                         // (Win3.1 SDK: "0 if no local allocation")
    571         USHORT    usInitlStackSize;     // 12: initl. stack size                ne_stack
    572                                         // (Win3.1 SDK: "0 if SS != DS")
    573         ULONG     ulCSIP;               // 14: CS:IP                            ne_csip
    574         ULONG     ulSSSP;               // 18: SS:SP                            ne_sssp
    575         USHORT    usSegTblEntries;      // 1c: segment tbl entry count          ne_cseg
    576         USHORT    usModuleTblEntries;   // 1e: module ref. table entry count    ne_cmod
    577         USHORT    usNonResdTblLen;      // 20: non-resd. name tbl length        ne_cbnrestab
    578         USHORT    usSegTblOfs;          // 22: segment tbl ofs                  ne_segtab
    579                                         // (from start of NEHEADER)
    580         USHORT    usResTblOfs;          // 24: resource tbl ofs                 ne_rsrctab
    581                                         // (from start of NEHEADER)
    582         USHORT    usResdNameTblOfs;     // 26: resd. name tbl ofs               ne_restab
    583                                         // (from start of NEHEADER)
    584         USHORT    usModRefTblOfs;       // 28: module ref. table ofs            ne_modtab
    585                                         // (from start of NEHEADER)
    586         USHORT    usImportTblOfs;       // 2a: import name tbl ofs              ne_imptab
    587                                         // (from start of NEHEADER)
    588         ULONG     ulNonResdTblOfs;      // 2c: non-resd. name tbl ofs           ne_nrestab
    589                                         // (from start of EXE!)
    590         USHORT    usMoveableEntries;    // 30: moveable entry points count      ne_cmovent
    591         USHORT    usLogicalSectShift;   // 32: logcl. sector shift              ne_align
    592                                         // (Win3.1 SDK: "typically 4, but default is 9")
    593         USHORT    usResSegmCount;       // 34: resource segm. count             ne_cres
    594         BYTE      bTargetOS;            // 36: target OS (NEOS_* flags)         ne_exetyp
    595         BYTE      bFlags2;              // 37: addtl. flags                     ne_flagsothers
    596                                         // Win3.1 SDK:
    597                                         //      bit 1 --> Win2.x, but runs in Win3.x protected mode
    598                                         //      bit 2 --> Win2.x that supports prop. fonts
    599                                         //      bit 3 --> exec contains fastload area
    600                                 /*
    601                                 #define NELONGNAMES     0x01
    602                                 #define NEWINISPROT     0x02
    603                                 #define NEWINGETPROPFON 0x04
    604                                 #define NEWLOAPPL       0x80
    605                                 */
    606         // the following are not listed in newexe.h, but are documented for Win3.x
    607         USHORT    usFastLoadOfs;        // 38: fast-load area ofs
    608         USHORT    usFastLoadLen;        // 3a: fast-load area length
    609         USHORT    usReserved;           // 3c: MS: 'reserved'
    610         USHORT    usReqWinVersion;      // 3e: Win-only: min. Win version
    611     } NEHEADER, *PNEHEADER;
    612 
    613     /*
    614      *@@ LXHEADER:
    615      *      linear executable (LX) header format,
    616      *      which comes after the DOS header in the
    617      *      EXE file (at DOSEXEHEADER.ulNewHeaderOfs).
    618      *
    619      *@@changed V0.9.9 (2001-04-06) [lafaix]: fixed auto data object and ulinstanceDemdCnt
    620      */
    621 
    622     typedef struct _LXHEADER
    623     {
    624         CHAR        achLX[2];           // 00: "LX" or "LE" magic
    625             // this is "LX" for 32-bit OS/2 programs, but
    626             // "LE" for MS-DOS progs which use this format
    627             // (e.g. WINDOWS\SMARTDRV.EXE). IBM says the
    628             // LE format was never released and superceded
    629             // by LX... I am unsure what the differences are.
    630         BYTE      fByteBigEndian;       // 02: byte ordering (1 = big endian)
    631         BYTE      fWordBigEndian;       // 03: word ordering (1 = big endian)
    632         ULONG     ulFormatLevel;        // 04: format level
    633         USHORT    usCPU;                // 08: CPU type
    634         USHORT    usTargetOS;           // 0a: OS type (NEOS_* flags)
    635         ULONG     ulModuleVersion;      // 0c: module version
    636         ULONG     ulFlags;              // 10: module flags
    637                           /* #define E32NOTP          0x8000L        // Library Module - used as NENOTP
    638                              #define E32NOLOAD        0x2000L        // Module not Loadable
    639                              #define E32PMAPI         0x0300L        // Uses PM Windowing API
    640                              #define E32PMW           0x0200L        // Compatible with PM Windowing
    641                              #define E32NOPMW         0x0100L        // Incompatible with PM Windowing
    642                              #define E32NOEXTFIX      0x0020L        // NO External Fixups in .EXE
    643                              #define E32NOINTFIX      0x0010L        // NO Internal Fixups in .EXE
    644                              #define E32SYSDLL        0x0008L        // System DLL, Internal Fixups discarded
    645                              #define E32LIBINIT       0x0004L        // Per-Process Library Initialization
    646                              #define E32LIBTERM       0x40000000L    // Per-Process Library Termination
    647                              #define E32APPMASK       0x0300L        // Application Type Mask
    648                           */
    649         ULONG     ulPageCount;          // 14: no. of pages in module
    650         ULONG     ulEIPRelObj;          // 18: object to which EIP is relative
    651         ULONG     ulEIPEntryAddr;       // 1c: EIP entry addr
    652         ULONG     ulESPObj;             // 20: ESP object
    653         ULONG     ulESP;                // 24: ESP
    654         ULONG     ulPageSize;           // 28: page size (4K)
    655         ULONG     ulPageLeftShift;      // 2c: page left-shift
    656         ULONG     ulFixupTblLen;        // 30: fixup section total size
    657         ULONG     ulFixupTblChecksum;   // 34: fixup section checksum
    658         ULONG     ulLoaderLen;          // 38: size req. for loader section
    659         ULONG     ulLoaderChecksum;     // 3c: loader section checksum
    660         ULONG     ulObjTblOfs;          // 40: object table offset
    661         ULONG     ulObjCount;           // 44: object count
    662         ULONG     ulObjPageTblOfs;      // 48: object page table ofs
    663         ULONG     ulObjIterPagesOfs;    // 4c: object iter pages ofs
    664         ULONG     ulResTblOfs;          // 50: resource table ofs
    665         ULONG     ulResTblCnt;          // 54: resource entry count
    666         ULONG     ulResdNameTblOfs;     // 58: resident name tbl ofs
    667         ULONG     ulEntryTblOfs;        // 5c: entry tbl ofs
    668         ULONG     ulModDirectivesOfs;   // 60: module directives ofs
    669         ULONG     ulModDirectivesCnt;   // 64: module directives count
    670         ULONG     ulFixupPagePageTblOfs;// 68: fixup page tbl ofs
    671         ULONG     ulFixupRecTblOfs;     // 6c: fixup record tbl ofs
    672         ULONG     ulImportModTblOfs;    // 70: import modl tbl ofs
    673         ULONG     ulImportModTblCnt;    // 74: import modl tbl count
    674         ULONG     ulImportProcTblOfs;   // 78: import proc tbl ofs
    675         ULONG     ulPerPageCSOfs;       // 7c: per page checksum ofs
    676         ULONG     ulDataPagesOfs;       // 80: data pages ofs
    677         ULONG     ulPreloadPagesCnt;    // 84: preload pages count
    678         ULONG     ulNonResdNameTblOfs;  // 88: non-resdnt name tbl ofs
    679         ULONG     ulNonResdNameTblLen;  // 8c: non-resdnt name tbl length
    680         ULONG     ulNonResdNameTblCS;   // 90: non-res name tbl checksum
    681         ULONG     ulAutoDataSegObj;     // 94: auto dataseg object
    682         ULONG     ulDebugOfs;           // 98: debug info ofs
    683         ULONG     ulDebugLen;           // 9c: debug info length
    684         ULONG     ulInstancePrelCnt;    // a0: instance preload count
    685         ULONG     ulInstanceDemdCnt;    // a0: instance demand count
    686         ULONG     ulHeapSize16;         // a8: heap size (16-bit)
    687         ULONG     ulStackSize;          // ac: stack size
    688     } LXHEADER, *PLXHEADER;
    689 
    690     /*
    691      *@@ PEHEADER:
    692      *      portable executable (PE) header format,
    693      *      which comes after the DOS header in the
    694      *      EXE file (at DOSEXEHEADER.ulNewHeaderOfs).
    695      *
    696      *@@added V0.9.10 (2001-04-08) [lafaix]
    697      */
    698 
    699     typedef struct _PEHEADER
    700     {
    701         // standard header
    702         ULONG     ulSignature;          // 00: 'P', 'E', 0, 0
    703         USHORT    usCPU;                // 04: CPU type
    704         USHORT    usObjCount;           // 06: number of object entries
    705         ULONG     ulTimeDateStamp;      // 08: store the time and date the
    706                                         //     file was created or modified
    707                                         //     by the linker
    708         ULONG     ulReserved1;          // 0c: reserved
    709         ULONG     ulReserved2;          // 10: reserved
    710         USHORT    usHeaderSize;         // 14: number of remaining bytes after
    711                                         //     usImageFlags
    712         USHORT    usImageFlags;         // 16: flags bits for the image
    713 
    714         // optional header (always present in valid Win32 files)
    715         USHORT    usReserved3;          // 18: reserved
    716         USHORT    usLinkerMajor;        // 1a: linker major version number
    717         USHORT    usLinkerMinor;        // 1c: linker minor version number
    718         USHORT    usReserved4;          // 1e: reserved
    719         ULONG     ulReserved5;          // 20: reserved
    720         ULONG     ulReserved6;          // 24: reserved
    721         ULONG     ulEntryPointRVA;      // 28: entry point relative virtual address
    722         ULONG     ulReserved7;          // 2c: reserved
    723         ULONG     ulReserved8;          // 30: reserved
    724         ULONG     ulImageBase;          // 34:
    725         ULONG     ulObjectAlign;        // 38:
    726         ULONG     ulFileAlign;          // 3c:
    727         USHORT    usOSMajor;            // 40:
    728         USHORT    usOSMinor;            // 42:
    729         USHORT    usUserMajor;          // 44:
    730         USHORT    usUserMinor;          // 46:
    731         USHORT    usSubSystemMajor;     // 48:
    732         USHORT    usSubSystemMinor;     // 4a:
    733         ULONG     ulReserved9;          // 4c: reserved
    734         ULONG     ulImageSize;          // 50:
    735         ULONG     ulHeaderSize;         // 54:
    736         ULONG     ulFileChecksum;       // 58:
    737         USHORT    usSubSystem;          // 5c:
    738         USHORT    usDLLFlags;           // 5e:
    739         ULONG     ulStackReserveSize;   // 60:
    740         ULONG     ulStackCommitSize;    // 64:
    741         ULONG     ulHeapReserveSize;    // 68:
    742         ULONG     ulHeapCommitSize;     // 6c:
    743         ULONG     ulReserved10;         // 70: reserved
    744         ULONG     ulInterestingRVACount;// 74:
    745         ULONG     aulRVASize[1];        // 78: array of RVA/Size entries
    746     } PEHEADER, *PPEHEADER;
    747 
    748     // additional LX structures
    749 
    750     /*
    751      *@@ RESOURCETABLEENTRY:
    752      *     LX resource table entry.
    753      *
    754      *@@added V0.9.16 (2001-12-08) [umoeller]
    755      */
    756 
    757     typedef struct _RESOURCETABLEENTRY     // rsrc32
    758     {
    759         unsigned short  type;   // Resource type
    760         unsigned short  name;   // Resource name
    761         unsigned long   cb;     // Resource size
    762         unsigned short  obj;    // Object number
    763         unsigned long   offset; // Offset within object
    764     } RESOURCETABLEENTRY;
    765 
    766     /*
    767      *@@ OBJECTTABLEENTRY:
    768      *     LX object table entry.
    769      *
    770      *@@added V0.9.16 (2001-12-08) [umoeller]
    771      */
    772 
    773     typedef struct _OBJECTTABLEENTRY       // o32_obj
    774     {
    775         unsigned long   o32_size;     // Object virtual size
    776         unsigned long   o32_base;     // Object base virtual address
    777         unsigned long   o32_flags;    // Attribute flags
    778         unsigned long   o32_pagemap;  // Object page map index
    779         unsigned long   o32_mapsize;  // Number of entries in object page map
    780         unsigned long   o32_reserved; // Reserved
    781     } OBJECTTABLEENTRY;
    782 
    783     /*
    784      *@@ OBJECTPAGETABLEENTRY:
    785      *     LX object _page_ table entry, sometimes
    786      *     referred to as map entry.
    787      *
    788      *@@added V0.9.16 (2001-12-08) [umoeller]
    789      */
    790 
    791     typedef struct _OBJECTPAGETABLEENTRY   // o32_map
    792     {
    793         unsigned long   o32_pagedataoffset;     // file offset of page
    794         unsigned short  o32_pagesize;           // # of real bytes of page data
    795         unsigned short  o32_pageflags;          // Per-Page attributes
    796     } OBJECTPAGETABLEENTRY;
    797 
    798     /*
    799      *@@ LXITER:
    800      *      iteration Record format for 'EXEPACK'ed pages.
    801      *
    802      *@@added V0.9.16 (2001-12-08) [umoeller]
    803      */
    804 
    805     typedef struct _LXITER
    806     {
    807         unsigned short LX_nIter;            // number of iterations
    808         unsigned short LX_nBytes;           // number of bytes
    809         unsigned char  LX_Iterdata;         // iterated data byte(s)
    810     } LXITER, *PLXITER;
    811 
    812     /*
    813      *@@ OS2NERESTBLENTRY:
    814      *      OS/2 NE resource table entry.
    815      *
    816      *@@added V0.9.16 (2001-12-08) [umoeller]
    817      */
    818 
    819     typedef struct _OS2NERESTBLENTRY
    820     {
    821         USHORT      usType;
    822         USHORT      usID;
    823     } OS2NERESTBLENTRY, *POS2NERESTBLENTRY;
    824 
    825     /*
    826      *@@ OS2NESEGMENT:
    827      *      OS/2 NE segment definition.
    828      *
    829      *@@added V0.9.16 (2001-12-08) [umoeller]
    830      */
    831 
    832     typedef struct _OS2NESEGMENT       // New .EXE segment table entry
    833     {
    834         unsigned short      ns_sector;      // File sector of start of segment
    835         unsigned short      ns_cbseg;       // Number of bytes in file
    836         unsigned short      ns_flags;       // Attribute flags
    837         unsigned short      ns_minalloc;    // Minimum allocation in bytes
    838     } OS2NESEGMENT, *POS2NESEGMENT;
    839 
    840     #pragma pack()
    841 
    842     // object/segment flags (in NE and LX)
    843     #define OBJWRITE         0x0002L    // Writeable Object
    844     #define OBJDISCARD       0x0010L    // Object is Discardable
    845     #define OBJSHARED        0x0020L    // Object is Shared
    846     #define OBJPRELOAD       0x0040L    // Object has preload pages
    847 
    848     // resource flags
    849     #define RNMOVE           0x0010     // Moveable resource
    850     #define RNPURE           0x0020     // Pure (read-only) resource
    851     #define RNPRELOAD        0x0040     // Preloaded resource
    852     #define RNDISCARD        0xF000     // Discard priority level for resource
    853 
    854     // EXE format
    855     #define EXEFORMAT_OLDDOS        1
    856     #define EXEFORMAT_NE            2
    857     #define EXEFORMAT_PE            3
    858     #define EXEFORMAT_LX            4
    859     #define EXEFORMAT_TEXT_BATCH    5
    860     #define EXEFORMAT_TEXT_CMD      6       // REXX or plain OS/2 batch
    861     #define EXEFORMAT_COM           7       // added V0.9.16 (2002-01-04) [umoeller]
    862 
    863     // target OS (in NE and LX)
    864     #define EXEOS_DOS3              1
    865     #define EXEOS_DOS4              2       // there is a flag for this in NE
    866     #define EXEOS_OS2               3
    867     #define EXEOS_WIN16             4
    868     #define EXEOS_WIN386            5       // according to IBM, there are flags
    869                                             // for this both in NE and LX
    870     #define EXEOS_WIN32             6
    871 
    872 #ifndef __STRIP_DOWN_EXECUTABLE__
    873 // for mini stubs in warpin, which has its own
    874 // implementation of this
    875 
    876     /*
    877      *@@ EXECUTABLE:
    878      *      structure used with all the doshExec*
    879      *      functions.
    880      */
    881 
    882     typedef struct _EXECUTABLE
    883     {
    884         // executable opened by doshOpen
    885         PXFILE              pFile;
    886 
    887         /* All the following fields are set by
    888            doshExecOpen if NO_ERROR is returned. */
    889 
    890         // old DOS EXE header;
    891         // note: before 0.9.12, this was ALWAYS valid,
    892         // but since we support NOSTUB executables now,
    893         // there may be situations where this is NULL,
    894         // but the other fields are valid! V0.9.12 (2001-05-03) [umoeller]
    895         PDOSEXEHEADER       pDosExeHeader;
    896         ULONG               cbDosExeHeader;
    897 
    898         // New Executable (NE) header, if ulExeFormat == EXEFORMAT_NE
    899         PNEHEADER           pNEHeader;
    900         ULONG               cbNEHeader;
    901 
    902         // Linear Executable (LX) header, if ulExeFormat == EXEFORMAT_LX
    903         PLXHEADER           pLXHeader;
    904         ULONG               cbLXHeader;
    905 
    906         // Portable Executable (PE) header, if ulExeFormat == EXEFORMAT_PE
    907         PPEHEADER           pPEHeader;
    908         ULONG               cbPEHeader;
    909 
    910         // module analysis (always set):
    911         ULONG               ulExeFormat;
    912                 // one of:
    913                 // EXEFORMAT_OLDDOS        1
    914                 // EXEFORMAT_NE            2
    915                 // EXEFORMAT_PE            3
    916                 // EXEFORMAT_LX            4
    917                 // EXEFORMAT_TEXT_BATCH    5
    918                 // EXEFORMAT_TEXT_CMD      6
    919                 // EXEFORMAT_COM           7
    920 
    921         BOOL                fLibrary,           // TRUE if this is a DLL
    922                             f32Bits;            // TRUE if this a 32-bits module
    923 
    924         ULONG               ulOS;
    925                 // target operating system as flagged in one of
    926                 // the EXE headers; one of:
    927                 // EXEOS_DOS3              1
    928                 // EXEOS_DOS4              2       // there is a flag for this in NE
    929                 // EXEOS_OS2               3
    930                 // EXEOS_WIN16             4
    931                 // EXEOS_WIN386            5       // according to IBM, there are flags
    932                                                    // for this both in NE and LX
    933                 // EXEOS_WIN32             6
    934 
    935         /* The following fields are only set after
    936            an extra call to doshExecQueryBldLevel. */
    937 
    938         PSZ                 pszDescription;
    939                 // whole string (first non-res name tbl entry)
    940         PSZ                 pszVendor;
    941                 // vendor substring (if IBM BLDLEVEL format)
    942         PSZ                 pszVersion;
    943                 // version substring (if IBM BLDLEVEL format)
    944 
    945         PSZ                 pszInfo;
    946                 // module info substring (if IBM BLDLEVEL format)
    947 
    948         // if pszInfo is extended DESCRIPTION field, the following
    949         // are set as well:
    950         PSZ                 pszBuildDateTime,
    951                             pszBuildMachine,
    952                             pszASD,
    953                             pszLanguage,
    954                             pszCountry,
    955                             pszRevision,
    956                             pszUnknown,
    957                             pszFixpak;
    958 
    959         // the following fields are set after doshLoadLXMaps
    960         BOOL                    fLXMapsLoaded;      // TRUE after doshLoadLXMaps
    961         RESOURCETABLEENTRY      *pRsTbl;        // pLXHeader->ulResTblCnt
    962         OBJECTTABLEENTRY        *pObjTbl;       // pLXHeader->ulObjCount
    963         OBJECTPAGETABLEENTRY    *pObjPageTbl;   // pLXHeader->ulPageCount
    964 
    965         // the following fields are set after doshLoadOS2NEMaps
    966         BOOL                    fOS2NEMapsLoaded;
    967         POS2NERESTBLENTRY       paOS2NEResTblEntry;
    968         POS2NESEGMENT           paOS2NESegments;
    969     } EXECUTABLE, *PEXECUTABLE;
    970 
    971     APIRET doshExecOpen(const char* pcszExecutable,
    972                         PEXECUTABLE* ppExec);
    973 
    974     APIRET doshExecQueryBldLevel(PEXECUTABLE pExec);
    975 
    976     /*
    977      *@@ FSYSMODULE:
    978      *
    979      *@@added V0.9.9 (2001-03-11) [lafaix]
    980      */
    981 
    982     typedef struct _FSYSMODULE
    983     {
    984         CHAR achModuleName[256];
    985     } FSYSMODULE, *PFSYSMODULE;
    986 
    987     APIRET doshExecQueryImportedModules(PEXECUTABLE pExec,
    988                                         PFSYSMODULE *ppaModules,
    989                                         PULONG pcModules);
    990 
    991     APIRET doshExecFreeImportedModules(PFSYSMODULE paModules);
    992 
    993     /*
    994      *@@ FSYSFUNCTION:
    995      *
    996      *@@added V0.9.9 (2001-03-11) [lafaix]
    997      */
    998 
    999     typedef struct _FSYSFUNCTION
    1000     {
    1001         ULONG ulOrdinal;
    1002         ULONG ulType;
    1003         CHAR achFunctionName[256];
    1004     } FSYSFUNCTION, *PFSYSFUNCTION;
    1005 
    1006     APIRET doshExecQueryExportedFunctions(PEXECUTABLE pExec,
    1007                                           PFSYSFUNCTION *ppaFunctions,
    1008                                           PULONG pcFunctions);
    1009 
    1010     APIRET doshExecFreeExportedFunctions(PFSYSFUNCTION paFunctions);
    1011 
    1012     #define WINRT_ACCELERATOR          9
    1013     #define WINRT_BITMAP               2
    1014     #define WINRT_CURSOR               1
    1015     #define WINRT_DIALOG               5
    1016     #define WINRT_FONT                 8
    1017     #define WINRT_FONTDIR              7
    1018     #define WINRT_ICON                 3
    1019     #define WINRT_MENU                 4
    1020     #define WINRT_RCDATA               10
    1021     #define WINRT_STRING               6
    1022 
    1023     /*
    1024      *@@ FSYSRESOURCE:
    1025      *
    1026      *@@added V0.9.7 (2000-12-18) [lafaix]
    1027      */
    1028 
    1029     typedef struct _FSYSRESOURCE
    1030     {
    1031         ULONG ulID;                     // resource ID
    1032         ULONG ulType;                   // resource type
    1033         ULONG ulSize;                   // resource size in bytes
    1034         ULONG ulFlag;                   // resource flags
    1035 
    1036     } FSYSRESOURCE, *PFSYSRESOURCE;
    1037 
    1038     APIRET doshExecQueryResources(PEXECUTABLE pExec,
    1039                                   PFSYSRESOURCE *ppaResources,
    1040                                   PULONG pcResources);
    1041 
    1042     APIRET doshExecFreeResources(PFSYSRESOURCE paResources);
    1043 
    1044     APIRET doshLoadLXMaps(PEXECUTABLE pExec);
    1045 
    1046     VOID doshFreeLXMaps(PEXECUTABLE pExec);
    1047 
    1048     APIRET doshLoadOS2NEMaps(PEXECUTABLE pExec);
    1049 
    1050     VOID doshFreeNEMaps(PEXECUTABLE pExec);
    1051 
    1052     APIRET doshExecClose(PEXECUTABLE *ppExec);
    1053 
    1054473    APIRET doshSearchPath(PCSZ pcszPath,
    1055474                          PCSZ pcszFile,
     
    1062481                              PCSZ *papcszExtensions,
    1063482                              ULONG cExtensions);
    1064 #endif
    1065483
    1066484    /********************************************************************
  • trunk/include/helpers/standards.h

    r123 r129  
    106106    #define ARRAYITEMCOUNT(array) sizeof(array) / sizeof(array[0])
    107107
     108    /*
     109     *@@ STRINGORNULL:
     110     *      helpful macro to avoid passing null strings
     111     *      to debugging printf calls.
     112     *
     113     *@@added V0.9.16 (2002-01-05) [umoeller]
     114     */
     115
     116    #define STRINGORNULL(s) (s) ? (s) : "NULL"
     117
    108118#endif
    109119
  • trunk/include/helpers/xstring.h

    r113 r129  
    9191    typedef XSTRINITSET *PXSTRINITSET;
    9292
    93     void XWPENTRY xstrInitCopy(PXSTRING pxstr, const char *pcszSource, ULONG ulExtraAllocate);
    94     typedef void XWPENTRY XSTRINITCOPY(PXSTRING pxstr, const char *pcszSource, ULONG ulExtraAllocate);
    95     typedef XSTRINITCOPY *PXSTRINITCOPY;
     93    #if defined(__DEBUG_MALLOC_ENABLED__) && !defined(DONT_REPLACE_XSTR_MALLOC) // setup.h, helpers\memdebug.c
     94        #define xstrInitCopy(a, b, c) xstrInitCopyDebug((a), (b), (c), __FILE__, __LINE__, __FUNCTION__)
     95        void XWPENTRY xstrInitCopyDebug(PXSTRING pxstr,
     96                                        const char *pcszSource,
     97                                        ULONG ulExtraAllocate,
     98                                        const char *file,
     99                                        unsigned long line,
     100                                        const char *function);
     101        typedef void XWPENTRY XSTRINITCOPYDEBUG(PXSTRING pxstr,
     102                                                const char *pcszSource,
     103                                                ULONG ulExtraAllocate,
     104                                                const char *file,
     105                                                unsigned long line,
     106                                                const char *function);
     107        typedef XSTRINITCOPYDEBUG *PXSTRINITCOPYDEBUG;
     108    #else
     109        void XWPENTRY xstrInitCopy(PXSTRING pxstr, const char *pcszSource, ULONG ulExtraAllocate);
     110        typedef void XWPENTRY XSTRINITCOPY(PXSTRING pxstr, const char *pcszSource, ULONG ulExtraAllocate);
     111        typedef XSTRINITCOPY *PXSTRINITCOPY;
     112    #endif
    96113
    97114    void XWPENTRY xstrClear(PXSTRING pxstr);
  • trunk/src/helpers/apps.c

    r127 r129  
    12001200                ProgDetails.pszParameters = strParamsPatched.psz;
    12011201
    1202                 /*  _Pmpf(("progt.progc: %d", ProgDetails.progt.progc));
    1203                 _Pmpf(("progt.fbVisible: 0x%lX", ProgDetails.progt.fbVisible));
    1204                 _Pmpf(("progt.pszTitle: \"%s\"", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : "NULL"));
    1205                 _Pmpf(("exec: \"%s\"", (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL"));
    1206                 _Pmpf(("params: \"%s\"", (ProgDetails.pszParameters) ? ProgDetails.pszParameters : "NULL"));
    1207                 _Pmpf(("startup: \"%s\"", (ProgDetails.pszStartupDir) ? ProgDetails.pszStartupDir : "NULL"));
    1208                 _Pmpf(("pszIcon: \"%s\"", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : "NULL"));
    1209                 _Pmpf(("environment: "));
     1202                _Pmpf((__FUNCTION__ ": progt.progc: %d", ProgDetails.progt.progc));
     1203                _Pmpf(("    progt.fbVisible: 0x%lX", ProgDetails.progt.fbVisible));
     1204                _Pmpf(("    progt.pszTitle: \"%s\"", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : "NULL"));
     1205                _Pmpf(("    exec: \"%s\"", (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL"));
     1206                _Pmpf(("    params: \"%s\"", (ProgDetails.pszParameters) ? ProgDetails.pszParameters : "NULL"));
     1207                _Pmpf(("    startup: \"%s\"", (ProgDetails.pszStartupDir) ? ProgDetails.pszStartupDir : "NULL"));
     1208                _Pmpf(("    pszIcon: \"%s\"", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : "NULL"));
     1209                /* _Pmpf(("    environment: "));
    12101210                {
    12111211                    PSZ pszThis = ProgDetails.pszEnvironment;
    12121212                    while (pszThis && *pszThis)
    12131213                    {
    1214                         _Pmpf(("  \"%s\"", pszThis));
     1214                        _Pmpf(("      \"%s\"", pszThis));
    12151215                        pszThis += strlen(pszThis) + 1;
    12161216                    }
    12171217                }
    1218 
    1219                 _Pmpf(("swpInitial.fl = 0x%lX, x = %d, y = %d, cx = %d, cy = %d:",
     1218                   */
     1219
     1220                _Pmpf(("    swpInitial.fl = 0x%lX, x = %d, y = %d, cx = %d, cy = %d:",
    12201221                            ProgDetails.swpInitial.fl,
    12211222                            ProgDetails.swpInitial.x,
     
    12231224                            ProgDetails.swpInitial.cx,
    12241225                            ProgDetails.swpInitial.cy));
    1225                 _Pmpf(("  behind = %d, hwnd = %d, res1 = %d, res2 = %d",
     1226                _Pmpf(("    behind = %d, hwnd = %d, res1 = %d, res2 = %d",
    12261227                            ProgDetails.swpInitial.hwndInsertBehind,
    12271228                            ProgDetails.swpInitial.hwnd,
    12281229                            ProgDetails.swpInitial.ulReserved1,
    12291230                            ProgDetails.swpInitial.ulReserved2));
    1230                     */
     1231
     1232                if (pszFailingName)
     1233                    strhncpy0(pszFailingName, ProgDetails.pszExecutable, cbFailingName);
    12311234
    12321235                /* if (WinMessageBox(HWND_DESKTOP,
     
    12361239                                  0,
    12371240                                  MB_YESNO | MB_MOVEABLE)
    1238                           == MBID_YES) */
    1239 
    1240                 if (pszFailingName)
    1241                     strhncpy0(pszFailingName, ProgDetails.pszExecutable, cbFailingName);
    1242 
    1243                 if (!(*phapp = WinStartApp(hwndNotify,
    1244                                                     // receives WM_APPTERMINATENOTIFY
    1245                                            &ProgDetails,
    1246                                            strParamsPatched.psz,
    1247                                            NULL,            // "reserved", PMREF says...
    1248                                            SAF_INSTALLEDCMDLINE)))
    1249                                                 // we MUST use SAF_INSTALLEDCMDLINE
    1250                                                 // or no Win-OS/2 session will start...
    1251                                                 // whatever is going on here... Warp 4 FP11
    1252 
    1253                                                 // do not use SAF_STARTCHILDAPP, or the
    1254                                                 // app will be terminated automatically
    1255                                                 // when the WPS terminates!
     1241                          != MBID_YES)
     1242                    arc = ERROR_INTERRUPT;
     1243                else */
    12561244                {
    1257                     // cannot start app: unfortunately WinStartApp doesn't
    1258                     // return meaningful codes like DosStartSession, so
    1259                     // try to see what happened
    1260                     switch (ERRORIDERROR(WinGetLastError(0)))
     1245                    if (!(*phapp = WinStartApp(hwndNotify,
     1246                                                        // receives WM_APPTERMINATENOTIFY
     1247                                               &ProgDetails,
     1248                                               strParamsPatched.psz,
     1249                                               NULL,            // "reserved", PMREF says...
     1250                                               SAF_INSTALLEDCMDLINE)))
     1251                                                    // we MUST use SAF_INSTALLEDCMDLINE
     1252                                                    // or no Win-OS/2 session will start...
     1253                                                    // whatever is going on here... Warp 4 FP11
     1254
     1255                                                    // do not use SAF_STARTCHILDAPP, or the
     1256                                                    // app will be terminated automatically
     1257                                                    // when the WPS terminates!
    12611258                    {
    1262                         case PMERR_DOS_ERROR: //  (0x1200)
     1259                        // cannot start app:
     1260                        _Pmpf((__FUNCTION__ ": WinStartApp failed"));
     1261                        arc = ERROR_FILE_NOT_FOUND;
     1262                        // unfortunately WinStartApp doesn't
     1263                        // return meaningful codes like DosStartSession, so
     1264                        // try to see what happened
     1265                        /*
     1266                        switch (ERRORIDERROR(WinGetLastError(0)))
    12631267                        {
    1264                             // this is probably the case where the module
    1265                             // couldn't be loaded, so try DosStartSession
    1266                             // to get a meaningful return code... note that
    1267                             // this cannot handle hwndNotify then
    1268                             RESULTCODES result;
    1269                             arc = DosExecPgm(pszFailingName,
    1270                                              cbFailingName,
    1271                                              EXEC_ASYNC,
    1272                                              NULL, // ProgDetails.pszParameters,
    1273                                              NULL, // ProgDetails.pszEnvironment,
    1274                                              &result,
    1275                                              ProgDetails.pszExecutable);
    1276 
    1277                             /* ULONG sid, pid;
    1278                             STARTDATA   SData;
    1279                             SData.Length  = sizeof(STARTDATA);
    1280                             SData.Related = SSF_RELATED_CHILD; //INDEPENDENT;
    1281                             SData.FgBg    = SSF_FGBG_FORE;
    1282                             SData.TraceOpt = SSF_TRACEOPT_NONE;
    1283 
    1284                             SData.PgmTitle = ProgDetails.pszTitle;
    1285                             SData.PgmName = ProgDetails.pszExecutable;
    1286                             SData.PgmInputs = ProgDetails.pszParameters;
    1287 
    1288                             SData.TermQ = NULL;
    1289                             SData.Environment = ProgDetails.pszEnvironment;
    1290                             SData.InheritOpt = SSF_INHERTOPT_PARENT;    // ignored
    1291                             SData.SessionType = SSF_TYPE_DEFAULT;
    1292                             SData.IconFile = 0;
    1293                             SData.PgmHandle = 0;
    1294 
    1295                             SData.PgmControl = SSF_CONTROL_VISIBLE;
    1296 
    1297                             SData.InitXPos  = 30;
    1298                             SData.InitYPos  = 40;
    1299                             SData.InitXSize = 200;
    1300                             SData.InitYSize = 140;
    1301                             SData.Reserved = 0;
    1302                             SData.ObjectBuffer  = pszFailingName;
    1303                             SData.ObjectBuffLen = cbFailingName;
    1304 
    1305                             arc = DosStartSession(&SData, &sid, &pid);
    1306                             */
     1268                            case PMERR_DOS_ERROR: //  (0x1200)
     1269                            {
     1270                                arc = ERROR_FILE_NOT_FOUND;
     1271
     1272                                // this is probably the case where the module
     1273                                // couldn't be loaded, so try DosStartSession
     1274                                // to get a meaningful return code... note that
     1275                                // this cannot handle hwndNotify then
     1276                                /* RESULTCODES result;
     1277                                arc = DosExecPgm(pszFailingName,
     1278                                                 cbFailingName,
     1279                                                 EXEC_ASYNC,
     1280                                                 NULL, // ProgDetails.pszParameters,
     1281                                                 NULL, // ProgDetails.pszEnvironment,
     1282                                                 &result,
     1283                                                 ProgDetails.pszExecutable);
     1284                                   */
     1285                                /* ULONG sid, pid;
     1286                                STARTDATA   SData;
     1287                                SData.Length  = sizeof(STARTDATA);
     1288                                SData.Related = SSF_RELATED_CHILD; //INDEPENDENT;
     1289                                SData.FgBg    = SSF_FGBG_FORE;
     1290                                SData.TraceOpt = SSF_TRACEOPT_NONE;
     1291
     1292                                SData.PgmTitle = ProgDetails.pszTitle;
     1293                                SData.PgmName = ProgDetails.pszExecutable;
     1294                                SData.PgmInputs = ProgDetails.pszParameters;
     1295
     1296                                SData.TermQ = NULL;
     1297                                SData.Environment = ProgDetails.pszEnvironment;
     1298                                SData.InheritOpt = SSF_INHERTOPT_PARENT;    // ignored
     1299                                SData.SessionType = SSF_TYPE_DEFAULT;
     1300                                SData.IconFile = 0;
     1301                                SData.PgmHandle = 0;
     1302
     1303                                SData.PgmControl = SSF_CONTROL_VISIBLE;
     1304
     1305                                SData.InitXPos  = 30;
     1306                                SData.InitYPos  = 40;
     1307                                SData.InitXSize = 200;
     1308                                SData.InitYSize = 140;
     1309                                SData.Reserved = 0;
     1310                                SData.ObjectBuffer  = pszFailingName;
     1311                                SData.ObjectBuffLen = cbFailingName;
     1312
     1313                                arc = DosStartSession(&SData, &sid, &pid);
     1314                            }
     1315                            break;
     1316
     1317                            case PMERR_INVALID_APPL: //  (0x1530)
     1318                                    // Attempted to start an application whose type is not
     1319                                    // recognized by OS/2.
     1320                                arc = ERROR_INVALID_EXE_SIGNATURE;
     1321                            break;
     1322
     1323                            case PMERR_INVALID_PARAMETERS: //  (0x1208)
     1324                                    // An application parameter value is invalid for
     1325                                    // its converted PM type. For  example: a 4-byte
     1326                                    // value outside the range -32 768 to +32 767 cannot be
     1327                                    // converted to a SHORT, and a negative number cannot
     1328                                    // be converted to a ULONG or USHORT.
     1329                                arc = ERROR_INVALID_DATA;
     1330                            break;
     1331
     1332                            case PMERR_STARTED_IN_BACKGROUND: //  (0x1532)
     1333                                    // The application started a new session in the
     1334                                    // background.
     1335                                arc = ERROR_SMG_START_IN_BACKGROUND;
     1336                            break;
     1337
     1338                            case PMERR_INVALID_WINDOW: // (0x1206)
     1339                                    // The window specified with a Window List call
     1340                                    // is not a valid frame window.
     1341
     1342                            default:
     1343                                arc = ERROR_BAD_FORMAT;
     1344                            break;
    13071345                        }
    1308                         break;
    1309 
    1310                         case PMERR_INVALID_APPL: //  (0x1530)
    1311                                 // Attempted to start an application whose type is not
    1312                                 // recognized by OS/2.
    1313                             arc = ERROR_INVALID_EXE_SIGNATURE;
    1314                         break;
    1315 
    1316                         case PMERR_INVALID_PARAMETERS: //  (0x1208)
    1317                                 // An application parameter value is invalid for
    1318                                 // its converted PM type. For  example: a 4-byte
    1319                                 // value outside the range -32 768 to +32 767 cannot be
    1320                                 // converted to a SHORT, and a negative number cannot
    1321                                 // be converted to a ULONG or USHORT.
    1322                             arc = ERROR_INVALID_DATA;
    1323                         break;
    1324 
    1325                         case PMERR_STARTED_IN_BACKGROUND: //  (0x1532)
    1326                                 // The application started a new session in the
    1327                                 // background.
    1328                             arc = ERROR_SMG_START_IN_BACKGROUND;
    1329                         break;
    1330 
    1331                         case PMERR_INVALID_WINDOW: // (0x1206)
    1332                                 // The window specified with a Window List call
    1333                                 // is not a valid frame window.
    1334 
    1335                         default:
    1336                             arc = ERROR_BAD_FORMAT;
    1337                         break;
     1346                        */
    13381347                    }
    13391348                }
  • trunk/src/helpers/cnrh.c

    r123 r129  
    168168                      BOOL fDrawLines)           // in: if TRUE, we'll draw lines around the columns
    169169{
    170     if (ppFieldInfo2)
    171         if (*ppFieldInfo2)
    172         {
    173             ULONG flData = ulDataType | ulOrientation;
    174             if (fDrawLines)
    175                 flData |= CFA_HORZSEPARATOR | CFA_SEPARATOR;
    176 
    177             (*ppFieldInfo2)->cb = sizeof(FIELDINFO);
    178             (*ppFieldInfo2)->flData = flData;
    179             (*ppFieldInfo2)->flTitle = CFA_FITITLEREADONLY | ulOrientation;
    180             (*ppFieldInfo2)->offStruct = ulFieldOffset;
    181             (*ppFieldInfo2)->pTitleData = pszColumnTitle;   // strdup removed, V0.9.1 (99-12-18) [umoeller]
    182             (*ppFieldInfo2)->pUserData   = NULL;
    183             *ppFieldInfo2 = (*ppFieldInfo2)->pNextFieldInfo;
    184         }
     170    PFIELDINFO pInfo;
     171    if (    (ppFieldInfo2)
     172         && (pInfo = *ppFieldInfo2)
     173       )
     174    {
     175        ULONG flData = ulDataType | ulOrientation;
     176        if (fDrawLines)
     177            flData |= CFA_HORZSEPARATOR | CFA_SEPARATOR;
     178
     179        pInfo->cb = sizeof(FIELDINFO);
     180        pInfo->flData = flData;
     181        pInfo->flTitle = CFA_FITITLEREADONLY | ulOrientation;
     182        pInfo->offStruct = ulFieldOffset;
     183        pInfo->pTitleData = pszColumnTitle;   // strdup removed, V0.9.1 (99-12-18) [umoeller]
     184        pInfo->pUserData   = NULL;
     185        pInfo->cxWidth = 0;
     186        *ppFieldInfo2 = pInfo->pNextFieldInfo;
     187    }
    185188}
    186189
  • trunk/src/helpers/configsys.c

    r123 r129  
    9292
    9393    if (!(arc = doshLoadTextFile(pcszFile,
    94                                  ppszContents)))
     94                                 ppszContents,
     95                                 NULL)))
    9596    {
    9697        // convert all \r\n to \n
  • trunk/src/helpers/dosh.c

    r127 r129  
    18141814                = pFile->cbCurrent
    18151815                = *pcbFile;
     1816
     1817                pFile->pszFilename = strdup(pcszFilename);
    18161818            }
    18171819            else
     
    18781880 *      method).
    18791881 *
     1882 *      This implements a small cache so that several
     1883 *      calls with a near offset will not touch the
     1884 *      disk always. The cache has been optimized for
     1885 *      the exeh* functions and works quite nicely
     1886 *      there.
     1887 *
     1888 *      Note that the position of the file pointer is
     1889 *      undefined after calling this function because
     1890 *      the data might have been returned from the
     1891 *      cache.
     1892 *
    18801893 *@@added V0.9.13 (2001-06-14) [umoeller]
    18811894 *@@changed V0.9.16 (2001-12-18) [umoeller]: now with XFILE, and always using FILE_BEGIN
     
    18951908        *pcb = 0;
    18961909
    1897         if (!(arc = DosSetFilePtr(pFile->hf,
    1898                                   (LONG)ulOffset,
    1899                                   FILE_BEGIN,
    1900                                   &ulDummy)))
     1910        // check if we have the data in the cache already;
     1911
     1912        if (    (pFile->pbCache)
     1913                // first byte must be in cache
     1914             && (ulOffset >= pFile->ulReadFrom)
     1915                // last byte must be in cache
     1916             && (    ulOffset + cb
     1917                  <= pFile->ulReadFrom + pFile->cbCache
     1918                )
     1919           )
    19011920        {
    1902             if (!(arc = DosRead(pFile->hf,
    1903                                 pbData,
    1904                                 cb,
    1905                                 &ulDummy)))
    1906                 *pcb = ulDummy;     // bytes read
     1921            // alright, return data from cache simply
     1922            ULONG ulOfsInCache = ulOffset - pFile->ulReadFrom;
     1923
     1924            memcpy(pbData,
     1925                   pFile->pbCache + ulOfsInCache,
     1926                   cb);
     1927            *pcb = cb;
     1928
     1929            _Pmpf((__FUNCTION__ " %s: data is fully in cache",
     1930                        pFile->pszFilename));
     1931            _Pmpf(("  caller wants %d bytes from %d",
     1932                        cb, ulOffset));
     1933            _Pmpf(("  we got %d bytes from %d",
     1934                        pFile->cbCache, pFile->ulReadFrom));
     1935            _Pmpf(("  so copied %d bytes from cache ofs %d",
     1936                        cb, ulOfsInCache));
     1937
     1938            // still, advance the file pointer because
     1939            // caller might run plain DosRead next
     1940            /* DosSetFilePtr(pFile->hf,
     1941                          (LONG)ulOffset + cb,
     1942                          FILE_BEGIN,
     1943                          &ulDummy); */
     1944        }
     1945        else
     1946        {
     1947            // data is not in cache:
     1948            // check how much it is... for small amounts,
     1949            // we load the cache first
     1950            if (cb <= 4096 - 512)
     1951            {
     1952                _Pmpf((__FUNCTION__ " %s: filling cache anew",
     1953                        pFile->pszFilename));
     1954                _Pmpf(("  caller wants %d bytes from %d",
     1955                            cb, ulOffset));
     1956
     1957                // OK, then fix the offset to read from
     1958                // to a multiple of 512 to get a full sector
     1959                pFile->ulReadFrom = ulOffset / 512L * 512L;
     1960                // and read 4096 bytes always plus the
     1961                // value we cut off above
     1962                pFile->cbCache = 4096;
     1963
     1964                _Pmpf(("  getting %d bytes from %d",
     1965                            pFile->cbCache, pFile->ulReadFrom));
     1966
     1967                // free old cache
     1968                if (pFile->pbCache)
     1969                    free(pFile->pbCache);
     1970
     1971                // allocate new cache
     1972                if (!(pFile->pbCache = (PBYTE)malloc(pFile->cbCache)))
     1973                    arc = ERROR_NOT_ENOUGH_MEMORY;
     1974                else
     1975                {
     1976                    if (!(arc = DosSetFilePtr(pFile->hf,
     1977                                              (LONG)pFile->ulReadFrom,
     1978                                              FILE_BEGIN,
     1979                                              &ulDummy)))
     1980                    {
     1981                        if (!(arc = DosRead(pFile->hf,
     1982                                            pFile->pbCache,
     1983                                            pFile->cbCache,
     1984                                            &ulDummy)))
     1985                        {
     1986                            // got data:
     1987                            ULONG ulOfsInCache;
     1988
     1989                            _Pmpf(("        %d bytes read", ulDummy));
     1990                            pFile->cbCache = ulDummy;
     1991
     1992                            // copy to caller
     1993                            ulOfsInCache = ulOffset - pFile->ulReadFrom;
     1994                            memcpy(pbData,
     1995                                   pFile->pbCache + ulOfsInCache,
     1996                                   cb);
     1997                            *pcb = cb;
     1998
     1999                            _Pmpf(("  so copied %d bytes from cache ofs %d",
     2000                                        cb, ulOfsInCache));
     2001
     2002                            // still, advance the file pointer because
     2003                            // caller might run plain DosRead next
     2004                            /* DosSetFilePtr(pFile->hf,
     2005                                          (LONG)ulOffset + cb,
     2006                                          FILE_BEGIN,
     2007                                          &ulDummy); */
     2008                        }
     2009                    }
     2010
     2011                    if (arc)
     2012                        FREE(pFile->pbCache);
     2013                }
     2014            }
     2015            else
     2016            {
     2017                // read uncached:
     2018                _Pmpf(("  " __FUNCTION__ " %s: reading uncached",
     2019                            pFile->pszFilename));
     2020                _Pmpf(("      caller wants %d bytes from %d",
     2021                            cb, ulOffset));
     2022                if (!(arc = DosSetFilePtr(pFile->hf,
     2023                                          (LONG)ulOffset,
     2024                                          FILE_BEGIN,
     2025                                          &ulDummy)))
     2026                {
     2027                    if (!(arc = DosRead(pFile->hf,
     2028                                        pbData,
     2029                                        cb,
     2030                                        &ulDummy)))
     2031                        *pcb = ulDummy;     // bytes read
     2032                }
     2033            }
    19072034        }
    19082035
     
    20032130                                         cb,
    20042131                                         &cbWritten)))
     2132                    {
    20052133                        pFile->cbCurrent += cbWritten;
     2134                        // invalidate the cache
     2135                        FREE(pFile->pbCache);
     2136                    }
    20062137
    20072138                    doshUnlockFile(pFile);
     
    21372268            *ppFile = NULL;
    21382269
     2270            FREE(pFile->pbCache);
     2271            FREE(pFile->pszFilename);
     2272
    21392273            if (pFile->hf)
    21402274            {
     
    21622296 *      buffer (or NULL upon errors).
    21632297 *
     2298 *      This allocates one extra byte to make the
     2299 *      buffer null-terminated always. The buffer
     2300 *      is _not_ converted WRT the line format.
     2301 *
    21642302 *      This returns the APIRET of DosOpen and DosRead.
    21652303 *      If any error occured, no buffer was allocated.
     
    21682306 *
    21692307 *@@changed V0.9.7 (2001-01-15) [umoeller]: renamed from doshReadTextFile
    2170  */
    2171 
    2172 APIRET doshLoadTextFile(PCSZ pcszFile,  // in: file name to read
    2173                         PSZ* ppszContent)      // out: newly allocated buffer with file's content
    2174 {
     2308 *@@changed V0.9.16 (2002-01-05) [umoeller]: added pcbRead
     2309 *@@changed V0.9.16 (2002-01-05) [umoeller]: rewritten using doshOpen
     2310 */
     2311
     2312APIRET doshLoadTextFile(PCSZ pcszFile,      // in: file name to read
     2313                        PSZ* ppszContent,   // out: newly allocated buffer with file's content
     2314                        PULONG pcbRead)     // out: size of that buffer including null byte (ptr can be NULL)
     2315{
     2316    APIRET  arc;
     2317
     2318    ULONG   cbFile = 0;
     2319    PXFILE  pFile = NULL;
     2320
     2321    if (!(arc = doshOpen(pcszFile,
     2322                         XOPEN_READ_EXISTING,
     2323                         &cbFile,
     2324                         &pFile)))
     2325    {
     2326        PSZ pszContent;
     2327        if (!(pszContent = (PSZ)malloc(cbFile + 1)))
     2328            arc = ERROR_NOT_ENOUGH_MEMORY;
     2329        else
     2330        {
     2331            ULONG cbRead = 0;
     2332            if (!(arc = DosRead(pFile->hf,
     2333                                pszContent,
     2334                                cbFile,
     2335                                &cbRead)))
     2336            {
     2337                if (cbRead != cbFile)
     2338                    arc = ERROR_NO_DATA;
     2339                else
     2340                {
     2341                    pszContent[cbRead] = '\0';
     2342                    *ppszContent = pszContent;
     2343                }
     2344            }
     2345
     2346            if (arc)
     2347                free(pszContent);
     2348        }
     2349
     2350        doshClose(&pFile);
     2351    }
     2352
     2353    /*
    21752354    ULONG   ulSize,
    21762355            ulBytesRead = 0,
     
    22102389                    // set output buffer pointer
    22112390                    *ppszContent = pszContent;
     2391
     2392                    if (pcbRead)
     2393                        *pcbRead = ulBytesRead + 1;
    22122394                }
    22132395
     
    22172399        DosClose(hFile);
    22182400    }
     2401    */
    22192402
    22202403    return (arc);
     
    28193002 *      versions. I believe it came up with some Warp 4
    28203003 *      fixpak. The API is resolved dynamically by
    2821  *      this function (using DosQueryProcAddr). Only
    2822  *      if NO_ERROR is returned, you may call doshPerfGet
    2823  *      afterwards.
     3004 *      this function (using DosQueryProcAddr).
    28243005 *
    28253006 *      This properly initializes the internal counters
     
    28353016 *      which have exactly cProcessors array items.
    28363017 *
     3018 *      So after NO_ERROR was returned here, you can keep
     3019 *      calling doshPerfGet to get a current snapshot of the
     3020 *      IRQ and user loads for each CPU. Note that interrupts
     3021 *      are only processed on CPU 0 on SMP systems.
     3022 *
    28373023 *      Call doshPerfClose to clean up resources allocated
    28383024 *      by this function.
    28393025 *
     3026 *      For more sample code, take a look at the "Pulse" widget
     3027 *      in the XWorkplace sources (src\xcenter\w_pulse.c).
     3028 *
    28403029 *      Example code:
    28413030 *
    28423031 +      PDOSHPERFSYS pPerf = NULL;
    2843  +      APIRET arc = doshPerfOpen(&pPerf);
    2844  +      if (arc == NO_ERROR)
     3032 +      APIRET arc;
     3033 +      if (!(arc = arc = doshPerfOpen(&pPerf)))
    28453034 +      {
    2846  +          // this should really be in a timer
     3035 +          // this should really be in a timer,
     3036 +          // e.g. once per second
    28473037 +          ULONG   ulCPU;
    2848  +          arc = doshPerfGet(&pPerf);
    2849  +          // go thru all CPUs
    2850  +          for (ulCPU = 0; ulCPU < pPerf->cProcessors; ulCPU++)
     3038 +          if (!(arc = doshPerfGet(&pPerf)))
    28513039 +          {
    2852  +              LONG lLoadThis = pPerf->palLoads[ulCPU];
    2853  +              ...
     3040 +              // go thru all CPUs
     3041 +              for (ulCPU = 0; ulCPU < pPerf->cProcessors; ulCPU++)
     3042 +              {
     3043 +                  LONG lUserLoadThis = pPerf->palLoads[ulCPU];
     3044 +                  ...
     3045 +              }
    28543046 +          }
    2855  +
    2856  +          ...
    28573047 +
    28583048 +          // clean up
     
    30143204
    30153205                // avoid division by zero
    3016                 double      dTimeDelta = (dTime - *pdTimePrevThis);
    3017                 if (dTimeDelta)
     3206                double      dTimeDelta;
     3207                if (dTimeDelta = (dTime - *pdTimePrevThis))
    30183208                {
    30193209                    pPerfSys->palLoads[ul]
     
    30603250{
    30613251    APIRET arc = NO_ERROR;
    3062     PDOSHPERFSYS pPerfSys = *ppPerfSys;
    3063     if (!pPerfSys)
     3252    PDOSHPERFSYS pPerfSys;
     3253    if (    (!ppPerfSys)
     3254         || (!(pPerfSys = *ppPerfSys))
     3255       )
    30643256        arc = ERROR_INVALID_PARAMETER;
    30653257    else
  • trunk/src/helpers/dosh2.c

    r127 r129  
    350350
    351351    return (arc);       // V0.9.9 (2001-04-04) [umoeller]
    352 }
    353 
    354 /*
    355  *@@category: Helpers\Control program helpers\Executable info
    356  *      these functions can retrieve BLDLEVEL information,
    357  *      imported modules information, exported functions information,
    358  *      and resources information from any executable module. See
    359  *      doshExecOpen.
    360  */
    361 
    362 /********************************************************************
    363  *
    364  *   Executable functions
    365  *
    366  ********************************************************************/
    367 
    368 /*
    369  *@@ doshExecOpen:
    370  *      this opens the specified executable file
    371  *      (which can be an .EXE, .COM, .DLL, or
    372  *      driver file) for use with the other
    373  *      doshExec* functions.
    374  *
    375  *      If no error occurs, NO_ERROR is returned
    376  *      and a pointer to a new EXECUTABLE structure
    377  *      is stored in *ppExec. Consider this pointer a
    378  *      handle and pass it to doshExecClose to clean
    379  *      up.
    380  *
    381  *      If NO_ERROR is returned, all the fields through
    382  *      ulOS are set in EXECUTABLE. The psz* fields
    383  *      which follow afterwards require an additional
    384  *      call to doshExecQueryBldLevel.
    385  *
    386  *      NOTE: If NO_ERROR is returned, the executable
    387  *      file has been opened by this function. It will
    388  *      only be closed when you call doshExecClose.
    389  *
    390  *      If errors occur, this function returns the
    391  *      following error codes:
    392  *
    393  *      -- ERROR_NOT_ENOUGH_MEMORY: malloc() failed.
    394  *
    395  *      -- ERROR_INVALID_EXE_SIGNATURE (191): header is
    396  *              neither plain DOS, nor NE, nor LX, nor PE.
    397  *              The given file probably isn't even an
    398  *              executable. This you will get if you
    399  *              pass in COM, BAT, or CMD files.
    400  *
    401  *      -- ERROR_BAD_EXE_FORMAT (193): header was
    402  *              recognized, but the header data was
    403  *              not understood.
    404  *
    405  *      -- ERROR_INVALID_PARAMETER: ppExec is NULL.
    406  *
    407  *      plus those of DosOpen, DosSetFilePtr, and
    408  *      DosRead.
    409  *
    410  *      The following executable types are supported
    411  *      (see EXECUTABLE for details):
    412  *
    413  *      --  Plain DOS 3.x executable without new header.
    414  *
    415  *      --  New Executable (NE), used by Win16 and
    416  *          16-bit OS/2 and still many of today's drivers.
    417  *
    418  *      --  Linear Executable (LX), OS/2 2.x and above.
    419  *
    420  *      --  Portable Executable (PE), used by Win32.
    421  *
    422  *      V0.9.12 adds support for NOSTUB executables,
    423  *      which are new-style executables (NE or LX)
    424  *      without a leading DOS header. The executable
    425  *      then starts directly with the NE or LX header.
    426  *      I am not sure whether PE supports such things
    427  *      as well... if so, it should be supported too.
    428  *
    429  *      @@todo:
    430  *
    431  *          win95 \WINDOWS\extract.exe is NE with a non-standard format
    432  *          win16 \WINDOWS\EXPAND.EXE
    433  *          win16 \WINDOWS\MSD.EXE"
    434  *
    435  *@@added V0.9.0 [umoeller]
    436  *@@changed V0.9.1 (2000-02-13) [umoeller]: fixed 32-bits flag
    437  *@@changed V0.9.7 (2000-12-20) [lafaix]: fixed ulNewHeaderOfs
    438  *@@changed V0.9.10 (2001-04-08) [lafaix]: added PE support
    439  *@@changed V0.9.10 (2001-04-08) [umoeller]: now setting ppExec only if NO_ERROR is returned
    440  *@@changed V0.9.12 (2001-05-03) [umoeller]: added support for NOSTUB newstyle executables
    441  *@@changed V0.9.16 (2001-12-08) [umoeller]: now using OPEN_SHARE_DENYWRITE
    442  *@@changed V0.9.16 (2001-12-08) [umoeller]: fLibrary was never set, works for LX and NE now
    443  *@@changed V0.9.16 (2001-12-08) [umoeller]: some speed optimizations, changed some return codes
    444  *@@changed V0.9.16 (2002-01-04) [umoeller]: added fixes for COM, BAT, CMD extensions
    445  */
    446 
    447 APIRET doshExecOpen(const char* pcszExecutable,
    448                     PEXECUTABLE* ppExec)
    449 {
    450     APIRET      arc = NO_ERROR;
    451 
    452     PEXECUTABLE pExec = NULL;
    453 
    454     PXFILE      pFile = NULL;
    455     ULONG       cbFile = 0;
    456     PCSZ        pExt;
    457     BOOL        fOpenFile = FALSE;
    458 
    459     if (!ppExec)
    460         return (ERROR_INVALID_PARAMETER);
    461 
    462     if (!(pExec = (PEXECUTABLE)malloc(sizeof(EXECUTABLE))))
    463         return (ERROR_NOT_ENOUGH_MEMORY);
    464 
    465     memset(pExec, 0, sizeof(EXECUTABLE));
    466 
    467     // check some of the default extensions
    468     // V0.9.16 (2002-01-04) [umoeller]
    469     if (pExt = doshGetExtension(pcszExecutable))
    470     {
    471         if (!stricmp(pExt, "COM"))
    472         {
    473             // I am not willing to find out more about the
    474             // .COM executable format, so for this one case,
    475             // let OS/2 determine what we have here
    476             ULONG ulDosAppType = 0;
    477             if (!(arc = DosQueryAppType((PSZ)pcszExecutable, &ulDosAppType)))
    478             {
    479                 if (ulDosAppType & FAPPTYP_DOS)           // 0x20
    480                     pExec->ulOS = EXEOS_DOS3;
    481                 else
    482                     pExec->ulOS = EXEOS_OS2;
    483 
    484                 pExec->ulExeFormat = EXEFORMAT_COM;
    485             }
    486         }
    487         else if (!stricmp(pExt, "BAT"))
    488         {
    489             pExec->ulOS = EXEOS_DOS3;
    490             pExec->ulExeFormat = EXEFORMAT_TEXT_BATCH;
    491         }
    492         else if (!stricmp(pExt, "CMD"))
    493         {
    494             pExec->ulOS = EXEOS_OS2;
    495             pExec->ulExeFormat = EXEFORMAT_TEXT_CMD;
    496         }
    497         else
    498             fOpenFile = TRUE;
    499     }
    500 
    501     if (    (fOpenFile)
    502          && (!(arc = doshOpen((PSZ)pcszExecutable,
    503                               XOPEN_READ_EXISTING,
    504                               &cbFile,
    505                               &pFile)))
    506        )
    507     {
    508         // file opened successfully:
    509         pExec->pFile = pFile;
    510 
    511         // read old DOS EXE header
    512         if (!(pExec->pDosExeHeader = (PDOSEXEHEADER)malloc(sizeof(DOSEXEHEADER))))
    513             arc = ERROR_NOT_ENOUGH_MEMORY;
    514         else
    515         {
    516             pExec->cbDosExeHeader = sizeof(DOSEXEHEADER);
    517             if (!(arc = doshReadAt(pFile,
    518                                    0,
    519                                    &pExec->cbDosExeHeader,      // in/out
    520                                    (PBYTE)pExec->pDosExeHeader)))
    521             {
    522                 ULONG ulNewHeaderOfs = 0;       // V0.9.12 (2001-05-03) [umoeller]
    523                 BOOL  fLoadNewHeader = FALSE;
    524 
    525                 // now check if we really have a DOS header
    526                 if (pExec->pDosExeHeader->usDosExeID != 0x5a4d)
    527                 {
    528                     // arc = ERROR_INVALID_EXE_SIGNATURE;
    529 
    530                     // V0.9.12 (2001-05-03) [umoeller]
    531                     // try loading new header directly; there are
    532                     // drivers which were built with NOSTUB, and
    533                     // the exe image starts out with the NE or LX
    534                     // image directly
    535                     fLoadNewHeader = TRUE;
    536                             // ulNewHeaderOfs is 0 now
    537 
    538                     // remove the DOS header info, since we have none
    539                     // V0.9.12 (2001-05-03) [umoeller]
    540                     FREE(pExec->pDosExeHeader);
    541                 }
    542                 else
    543                 {
    544                     // we have a DOS header:
    545                     if (pExec->pDosExeHeader->usRelocTableOfs < 0x40)
    546                     {
    547                         // neither LX nor PE nor NE:
    548                         pExec->ulOS = EXEOS_DOS3;
    549                         pExec->ulExeFormat = EXEFORMAT_OLDDOS;
    550                     }
    551                     else
    552                     {
    553                         // we have a new header offset:
    554                         fLoadNewHeader = TRUE;
    555                         ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs;
    556                     }
    557                 }
    558 
    559                 if (fLoadNewHeader)
    560                 {
    561                     // either LX or PE or NE:
    562                     // read in new header...
    563                     // ulNewHeaderOfs is now either 0 (if no DOS header
    564                     // was found) or pDosExeHeader->ulNewHeaderOfs
    565                     // V0.9.12 (2001-05-03) [umoeller]
    566                     ULONG   cbRead;
    567                     PBYTE   pbHeader;
    568 
    569                     // now, we used to read in the first two chars
    570                     // to check out if we have PE or LX or NE and
    571                     // then read the header accordingly... but
    572                     // that wasn't terribly efficient. So load
    573                     // a chunk of data and then do a realloc()
    574                     // instead.
    575 
    576                     // take the largest of LXHEADER and NEHEADER and PEHEADER
    577                     cbRead = sizeof(LXHEADER);
    578                     if (sizeof(NEHEADER) > cbRead)
    579                         cbRead = sizeof(NEHEADER);
    580                     if (sizeof(PEHEADER) > cbRead)
    581                         cbRead = sizeof(PEHEADER);
    582 
    583                     if (!(pbHeader = (PBYTE)malloc(cbRead)))
    584                         arc = ERROR_NOT_ENOUGH_MEMORY;
    585                     else if (!(arc = doshReadAt(pFile,
    586                                                 ulNewHeaderOfs,
    587                                                 &cbRead,
    588                                                 pbHeader)))
    589                     {
    590                         PBYTE   pbCheckOS = NULL;
    591 
    592                         PSZ     achNewHeaderType = (PSZ)pbHeader;
    593 
    594                         if (!memcmp(achNewHeaderType, "NE", 2))
    595                         {
    596                             // New Executable:
    597                             pExec->ulExeFormat = EXEFORMAT_NE;
    598 
    599                             if (cbRead < sizeof(NEHEADER))
    600                             {
    601                                 arc = ERROR_BAD_EXE_FORMAT;
    602                                 FREE(pbHeader);
    603                             }
    604                             else
    605                             {
    606                                 pExec->pNEHeader = (PNEHEADER)realloc(pbHeader,
    607                                                                       sizeof(NEHEADER));
    608                                 pExec->cbNEHeader = sizeof(NEHEADER);
    609                                 pbCheckOS = &pExec->pNEHeader->bTargetOS;
    610                                 // set library flag V0.9.16 (2001-12-08) [umoeller]
    611                                 if (pExec->pNEHeader->usFlags & 0x8000)
    612                                     // library:
    613                                     pExec->fLibrary = TRUE;
    614                             }
    615                         }
    616                         else if (    (!memcmp(achNewHeaderType, "LX", 2))
    617                                   || (!memcmp(achNewHeaderType, "LE", 2))
    618                                             // this is used by SMARTDRV.EXE
    619                                 )
    620                         {
    621                             // OS/2 Linear Executable:
    622                             pExec->ulExeFormat = EXEFORMAT_LX;
    623 
    624                             if (cbRead < sizeof(LXHEADER))
    625                             {
    626                                 arc = ERROR_BAD_EXE_FORMAT;
    627                                 FREE(pbHeader);
    628                             }
    629                             else
    630                             {
    631                                 pExec->pLXHeader = (PLXHEADER)realloc(pbHeader,
    632                                                                       sizeof(LXHEADER));
    633                                 // read in LX header
    634                                 pExec->cbLXHeader = sizeof(LXHEADER);
    635                                 pbCheckOS = (PBYTE)(&pExec->pLXHeader->usTargetOS);
    636                                 // set library flag V0.9.16 (2001-12-08) [umoeller]
    637                                 if (pExec->pLXHeader->ulFlags & 0x8000)
    638                                     // library:
    639                                     pExec->fLibrary = TRUE;
    640                             }
    641                         }
    642                         else if (!memcmp(achNewHeaderType, "PE", 2))
    643                         {
    644                             pExec->ulExeFormat = EXEFORMAT_PE;
    645 
    646                             if (cbRead < sizeof(PEHEADER))
    647                             {
    648                                 arc = ERROR_BAD_EXE_FORMAT;
    649                                 FREE(pbHeader);
    650                             }
    651                             else
    652                             {
    653                                 // PE has a standard header of 24 bytes
    654                                 // plus an extended header, so check what
    655                                 // we've got
    656                                 ULONG cbPE =   sizeof(PEHEADER); // 24
    657                                    //           + ((PPEHEADER)pbHeader)->usHeaderSize;
    658                                 pExec->pPEHeader = (PPEHEADER)realloc(pbHeader,
    659                                                                       cbPE);
    660 
    661                                 pExec->cbPEHeader = cbPE;
    662                                 pExec->ulOS = EXEOS_WIN32;
    663                                 pExec->f32Bits = TRUE;
    664 
    665                                 /*
    666                                 // we have the first 24 bytes already, so
    667                                 // go for the next chunk, if this is more
    668                                 // than we have in PEHEADER
    669                                 if (    (cbRead < cbPE)
    670                                      && (cbRead = pExec->pPEHeader->usHeaderSize)
    671                                    )
    672                                 {
    673                                     _Pmpf(("  usHdrSize %d, sizeof(PEHEADER) %d, cbRead %d, cbPE %d --> reading extended header",
    674                                            pExec->pPEHeader->usHeaderSize,
    675                                            sizeof(PEHEADER),
    676                                            cbRead,
    677                                            cbPE));
    678                                     if (!(arc = doshReadAt(hFile,
    679                                                            ulNewHeaderOfs + 24,
    680                                                            FILE_BEGIN,
    681                                                            &cbRead,
    682                                                            (PBYTE)pExec->pPEHeader + 24)))
    683                                     {
    684                                     }
    685                                     else
    686                                     {
    687                                         arc = ERROR_BAD_EXE_FORMAT;
    688                                         FREE(pExec->pPEHeader);
    689                                     }
    690                                 }
    691                                 else
    692                                     _Pmpf(("  already got extended header"));
    693                                 */
    694                             }
    695                         }
    696                         else
    697                         {
    698                             // strange type:
    699                             arc = ERROR_INVALID_EXE_SIGNATURE;
    700                             FREE(pbHeader);
    701                         }
    702 
    703                         if ((!arc) && (pbCheckOS))
    704                         {
    705                             // BYTE to check for operating system
    706                             // (NE and LX):
    707                             switch (*pbCheckOS)
    708                             {
    709                                 case NEOS_OS2:
    710                                     pExec->ulOS = EXEOS_OS2;
    711                                     if (pExec->ulExeFormat == EXEFORMAT_LX)
    712                                         pExec->f32Bits = TRUE;
    713                                 break;
    714 
    715                                 case NEOS_WIN16:
    716                                     pExec->ulOS = EXEOS_WIN16;
    717                                 break;
    718 
    719                                 case NEOS_DOS4:
    720                                     pExec->ulOS = EXEOS_DOS4;
    721                                 break;
    722 
    723                                 case NEOS_WIN386:
    724                                     pExec->ulOS = EXEOS_WIN386;
    725                                     pExec->f32Bits = TRUE;
    726                                 break;
    727                             }
    728                         }
    729                     } // end if (!(arc = doshReadAt(hFile,
    730                 } // end if (fLoadNewHeader)
    731             } // end if (!(arc = doshReadAt(hFile,
    732         } // end else if (!(pExec->pDosExeHeader = (PDOSEXEHEADER)malloc(sizeof(DOSEXEHEADER))))
    733 
    734     } // end if (!(arc = DosOpen((PSZ)pcszExecutable,
    735 
    736     if (arc != NO_ERROR)
    737         // error: clean up
    738         doshExecClose(&pExec);
    739     else
    740         *ppExec = pExec;
    741 
    742     return (arc);
    743 }
    744 
    745 /*
    746  *@@ ParseBldLevel:
    747  *      called from doshExecQueryBldLevel to parse
    748  *      the BLDLEVEL string.
    749  *
    750  *      On entry, caller has copied the string into
    751  *      pExec->pszDescription. The string is
    752  *      null-terminated.
    753  *
    754  *      The BLDLEVEL string comes in two flavors.
    755  *
    756  *      --  The standard format is:
    757  *
    758  +              @#VENDOR:VERSION#@DESCRIPTION
    759  *
    760  *          DESCRIPTION can have leading spaces, but
    761  *          need to have them.
    762  *
    763  *      --  However, there is an extended version
    764  *          in that the DESCRIPTION field is split
    765  *          up even more. The marker for this seems
    766  *          to be that the description starts out
    767  *          with "##1##".
    768  *
    769  +              ##1## DATETIME BUILDMACHINE:ASD:LANG:CTRY:REVISION:UNKNOWN:FIXPAK@@DESCRIPTION
    770  *
    771  *          The problem is that the DATETIME field comes
    772  *          in several flavors. IBM uses things like
    773  *
    774  +              "Thu Nov 30 15:30:37 2000 BWBLD228"
    775  *
    776  *          while DANIS506.ADD has
    777  *
    778  +              "15.12.2000 18:22:57      Nachtigall"
    779  *
    780  *          Looks like the date/time string is standardized
    781  *          to have 24 characters then.
    782  *
    783  *@@added V0.9.12 (2001-05-18) [umoeller]
    784  *@@changed V0.9.12 (2001-05-19) [umoeller]: added extended BLDLEVEL support
    785  */
    786 
    787 VOID ParseBldLevel(PEXECUTABLE pExec)
    788 {
    789     const char  // *pStartOfAuthor = 0,
    790                 *pStartOfVendor = 0;
    791 
    792     // @#VENDOR:VERSION#@ DESCRIPTION
    793     // but skip the first byte, which has the string length
    794     pStartOfVendor = strstr(pExec->pszDescription,
    795                             "@#");
    796     if (pStartOfVendor)
    797     {
    798         const char *pStartOfInfo = strstr(pStartOfVendor + 2,
    799                                           "#@");
    800         if (pStartOfInfo)
    801         {
    802             const char *pEndOfVendor = strchr(pStartOfVendor + 2,
    803                                               ':');
    804             if (pEndOfVendor)
    805             {
    806                 pExec->pszVendor = strhSubstr(pStartOfVendor + 2,
    807                                               pEndOfVendor);
    808                 pExec->pszVersion = strhSubstr(pEndOfVendor + 1,
    809                                                pStartOfInfo);
    810                 // skip "@#" in DESCRIPTION string
    811                 pStartOfInfo += 2;
    812 
    813                 // now check if we have extended DESCRIPTION V0.9.12 (2001-05-19) [umoeller]
    814                 if (    (strlen(pStartOfInfo) > 6)
    815                      && (!memcmp(pStartOfInfo, "##1##", 5))
    816                    )
    817                 {
    818                     // yes: parse that beast
    819                     const char *p = pStartOfInfo + 5;
    820 
    821                     // get build date/time
    822                     if (strlen(p) > 24)
    823                     {
    824                         // date/time seems to be fixed 24 chars in length
    825                         if (pExec->pszBuildDateTime = (PSZ)malloc(25))
    826                         {
    827                             memcpy(pExec->pszBuildDateTime,
    828                                    p,
    829                                    24);
    830                             pExec->pszBuildDateTime[24] = '\0';
    831 
    832                             p += 24;
    833 
    834                             // now we're at the colon-separated
    835                             // strings, first of which is the
    836                             // build machine;
    837                             // skip leading spaces
    838                             while (*p == ' ')
    839                                 p++;
    840 
    841                             if (*p)
    842                             {
    843                                 char **papsz[] =
    844                                     {
    845                                         &pExec->pszBuildMachine,
    846                                         &pExec->pszASD,
    847                                         &pExec->pszLanguage,
    848                                         &pExec->pszCountry,
    849                                         &pExec->pszRevision,
    850                                         &pExec->pszUnknown,
    851                                         &pExec->pszFixpak
    852                                     };
    853                                 ULONG ul;
    854 
    855                                 for (ul = 0;
    856                                      ul < sizeof(papsz) / sizeof(papsz[0]);
    857                                      ul++)
    858                                 {
    859                                     BOOL fStop = FALSE;
    860                                     const char *pNextColon = strchr(p, ':'),
    861                                                *pDoubleAt = strstr(p, "@@");
    862                                     if (!pNextColon)
    863                                     {
    864                                         // last item:
    865                                         if (pDoubleAt)
    866                                             pNextColon = pDoubleAt;
    867                                         else
    868                                             pNextColon = p + strlen(p);
    869 
    870                                         fStop = TRUE;
    871                                     }
    872 
    873                                     if (    (fStop)
    874                                          || (    (pNextColon)
    875                                               && (    (!pDoubleAt)
    876                                                    || (pNextColon < pDoubleAt)
    877                                                  )
    878                                             )
    879                                        )
    880                                     {
    881                                         if (pNextColon > p + 1)
    882                                             *(papsz[ul]) = strhSubstr(p, pNextColon);
    883                                     }
    884                                     else
    885                                         break;
    886 
    887                                     if (fStop)
    888                                         break;
    889 
    890                                     p = pNextColon + 1;
    891                                 }
    892                             }
    893                         }
    894                     }
    895 
    896                     pStartOfInfo = strstr(p,
    897                                           "@@");
    898                     if (pStartOfInfo)
    899                         pStartOfInfo += 2;
    900                 }
    901 
    902                 // -- if we had no extended DESCRIPTION,
    903                 //    pStartOfInfo points to regular description now
    904                 // -- if we parse the extended DESCRIPTION above,
    905                 //    pStartOfInfo points to after @@ now
    906                 // -- if we had an error, pStartOfInfo is NULL
    907                 if (pStartOfInfo)
    908                 {
    909                     // add the regular DESCRIPTION then
    910                     // skip leading spaces in info string
    911                     while (*pStartOfInfo == ' ')
    912                         pStartOfInfo++;
    913                     if (*pStartOfInfo)  // V0.9.9 (2001-04-04) [umoeller]
    914                         // and copy until end of string
    915                         pExec->pszInfo = strdup(pStartOfInfo);
    916                 }
    917             }
    918         }
    919     }
    920 }
    921 
    922 /*
    923  *@@ doshExecQueryBldLevel:
    924  *      this retrieves buildlevel information for an
    925  *      LX or NE executable previously opened with
    926  *      doshExecOpen.
    927  *
    928  *      BuildLevel information must be contained in the
    929  *      DESCRIPTION field of an executable's module
    930  *      definition (.DEF) file. In order to be readable
    931  *      by BLDLEVEL.EXE (which ships with OS/2), this
    932  *      string must have the following format:
    933  *
    934  +          Description '@#AUTHOR:VERSION#@ DESCRIPTION'
    935  *
    936  *      Example:
    937  *
    938  +          Description '@#Ulrich M”ller:0.9.0#@ XWorkplace Sound Support Module'
    939  *
    940  *      The "Description" entry always ends up as the
    941  *      very first entry in the non-resident name table
    942  *      in LX and NE executables. So this is what we retrieve
    943  *      here.
    944  *
    945  *      If the first entry in that table exists, NO_ERROR is
    946  *      returned and at least the pszDescription field in
    947  *      EXECUTABLE is set to that information.
    948  *
    949  *      If that string is in IBM BLDLEVEL format, the string
    950  *      is automatically parsed, and the pszVendor, pszVersion,
    951  *      and pszInfo fields are also set. In the above examples,
    952  *      this would return the following information:
    953  +          pszVendor = "Ulrich M”ller"
    954  +          pszVersion = "0.9.0"
    955  +          pszInfo = "XWorkplace Sound Support Module"
    956  *
    957  *      If that string is not in BLDLEVEL format, only pszDescription
    958  *      will be set. The other fields remain NULL.
    959  *
    960  *      This returns the following errors:
    961  *
    962  *      -- ERROR_INVALID_PARAMETER: pExec invalid
    963  *
    964  *      -- ERROR_INVALID_EXE_SIGNATURE (191): pExec is not in LX or NE format
    965  *
    966  *      -- ERROR_INVALID_DATA (13): non-resident name table not found.
    967  *
    968  *      -- ERROR_NOT_ENOUGH_MEMORY: malloc() failed.
    969  *
    970  *      plus the error codes of DosSetFilePtr and DosRead.
    971  *
    972  *@@added V0.9.0 [umoeller]
    973  *@@changed V0.9.0 (99-10-22) [umoeller]: NE format now supported
    974  *@@changed V0.9.1 (99-12-06): fixed memory leak
    975  *@@changed V0.9.9 (2001-04-04) [umoeller]: added more error checking
    976  *@@changed V0.9.12 (2001-05-18) [umoeller]: extracted ParseBldLevel
    977  */
    978 
    979 APIRET doshExecQueryBldLevel(PEXECUTABLE pExec)
    980 {
    981     APIRET      arc = NO_ERROR;
    982 
    983     if (!pExec)
    984         arc = ERROR_INVALID_PARAMETER;
    985     else
    986     {
    987         PXFILE      pFile = pExec->pFile;
    988 
    989         ULONG       ulNRNTOfs = 0;
    990 
    991         if (pExec->ulExeFormat == EXEFORMAT_LX)
    992         {
    993             // OK, LX format:
    994             // check if we have a non-resident name table
    995             if (pExec->pLXHeader == NULL)
    996                 arc = ERROR_INVALID_DATA;
    997             else if (pExec->pLXHeader->ulNonResdNameTblOfs == 0)
    998                 arc = ERROR_INVALID_DATA;
    999             else
    1000                 ulNRNTOfs = pExec->pLXHeader->ulNonResdNameTblOfs;
    1001         }
    1002         else if (pExec->ulExeFormat == EXEFORMAT_NE)
    1003         {
    1004             // OK, NE format:
    1005             // check if we have a non-resident name table
    1006             if (pExec->pNEHeader == NULL)
    1007                 arc = ERROR_INVALID_DATA;
    1008             else if (pExec->pNEHeader->ulNonResdTblOfs == 0)
    1009                 arc = ERROR_INVALID_DATA;
    1010             else
    1011                 ulNRNTOfs = pExec->pNEHeader->ulNonResdTblOfs;
    1012         }
    1013         else
    1014             // neither LX nor NE: stop
    1015             arc = ERROR_INVALID_EXE_SIGNATURE;
    1016 
    1017         if (    (!arc)
    1018              && (ulNRNTOfs)
    1019            )
    1020         {
    1021             ULONG       ulLocal = 0,
    1022                         ulBytesRead = 0;
    1023 
    1024             // move EXE file pointer to offset of non-resident name table
    1025             // (from LX header)
    1026             if (!(arc = DosSetFilePtr(pFile->hf,     // file is still open
    1027                                       ulNRNTOfs,      // ofs determined above
    1028                                       FILE_BEGIN,
    1029                                       &ulLocal)))
    1030             {
    1031                 // allocate memory as necessary
    1032                 PSZ pszNameTable = (PSZ)malloc(2001); // should suffice, because each entry
    1033                                                       // may only be 255 bytes in length
    1034                 if (!pszNameTable)
    1035                     arc = ERROR_NOT_ENOUGH_MEMORY;
    1036                 else
    1037                 {
    1038                     if (!(arc = DosRead(pFile->hf,
    1039                                         pszNameTable,
    1040                                         2000,
    1041                                         &ulBytesRead)))
    1042                     {
    1043                         if (*pszNameTable == 0)
    1044                             // first byte (length byte) is null:
    1045                             arc = ERROR_INVALID_DATA;
    1046                         else
    1047                         {
    1048                             // now copy the string, which is in Pascal format
    1049                             pExec->pszDescription = (PSZ)malloc((*pszNameTable) + 1);    // addt'l null byte
    1050                             if (!pExec->pszDescription)
    1051                                 arc = ERROR_NOT_ENOUGH_MEMORY;
    1052                             else
    1053                             {
    1054                                 memcpy(pExec->pszDescription,
    1055                                        pszNameTable + 1,        // skip length byte
    1056                                        *pszNameTable);          // length byte
    1057                                 // terminate string
    1058                                 *(pExec->pszDescription + (*pszNameTable)) = 0;
    1059 
    1060                                 ParseBldLevel(pExec);
    1061                             }
    1062                         }
    1063                     }
    1064 
    1065                     free(pszNameTable);
    1066                 } // end if PSZ pszNameTable = (PSZ)malloc(2001);
    1067             }
    1068         }
    1069     } // end if (!pExec)
    1070 
    1071     return (arc);
    1072 }
    1073 
    1074 /*
    1075  *@@ doshExecQueryImportedModules:
    1076  *      returns an array of FSYSMODULE structure describing all
    1077  *      imported modules.
    1078  *
    1079  *      *pcModules receives the # of items in the array (not the
    1080  *      array size!).  Use doshFreeImportedModules to clean up.
    1081  *
    1082  *      This returns a standard OS/2 error code, which might be
    1083  *      any of the codes returned by DosSetFilePtr and DosRead.
    1084  *      In addition, this may return:
    1085  *
    1086  *      --  ERROR_NOT_ENOUGH_MEMORY
    1087  *
    1088  *      --  ERROR_INVALID_EXE_SIGNATURE: exe is in a format other
    1089  *          than LX or NE, which is not understood by this function.
    1090  *
    1091  *      Even if NO_ERROR is returned, the array pointer might still
    1092  *      be NULL if the module contains no such data.
    1093  *
    1094  *@@added V0.9.9 (2001-03-11) [lafaix]
    1095  *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET
    1096  *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code
    1097  *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support
    1098  *@@changed V0.9.10 (2001-04-13) [lafaix]: removed 127 characters limit
    1099  *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support
    1100  */
    1101 
    1102 APIRET doshExecQueryImportedModules(PEXECUTABLE pExec,
    1103                                     PFSYSMODULE *ppaModules,    // out: modules array
    1104                                     PULONG pcModules)           // out: array item count
    1105 {
    1106     if (    (pExec)
    1107          && (    (pExec->ulOS == EXEOS_OS2)
    1108               || (pExec->ulOS == EXEOS_WIN16)
    1109               || (pExec->ulOS == EXEOS_WIN386)
    1110             )
    1111        )
    1112     {
    1113         ENSURE_BEGIN;
    1114         ULONG       cModules = 0;
    1115         PFSYSMODULE paModules = NULL;
    1116         int i;
    1117         HFILE hfExe = pExec->pFile->hf;
    1118 
    1119         ULONG ulNewHeaderOfs = 0;       // V0.9.12 (2001-05-03) [umoeller]
    1120 
    1121         if (pExec->pDosExeHeader)
    1122             // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller]
    1123             ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs;
    1124 
    1125         if (pExec->ulExeFormat == EXEFORMAT_LX)
    1126         {
    1127             // 32-bit OS/2 executable:
    1128             cModules = pExec->pLXHeader->ulImportModTblCnt;
    1129 
    1130             if (cModules)
    1131             {
    1132                 ULONG   cb = sizeof(FSYSMODULE) * cModules; // V0.9.9 (2001-04-03) [umoeller]
    1133                 ULONG   ulDummy;
    1134 
    1135                 paModules = (PFSYSMODULE)malloc(cb);
    1136                 if (!paModules)
    1137                     ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY); // V0.9.9 (2001-04-03) [umoeller]
    1138 
    1139                 memset(paModules, 0, cb);   // V0.9.9 (2001-04-03) [umoeller]
    1140 
    1141                 ENSURE_SAFE(DosSetFilePtr(hfExe,
    1142                                           pExec->pLXHeader->ulImportModTblOfs
    1143                                             + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller]
    1144                                           FILE_BEGIN,
    1145                                           &ulDummy));
    1146 
    1147                 for (i = 0; i < cModules; i++)
    1148                 {
    1149                     BYTE bLen = 0;
    1150 
    1151                     // reading the length of the module name
    1152                     ENSURE_SAFE(DosRead(hfExe, &bLen, 1, &ulDummy));
    1153 
    1154                     // reading the module name
    1155                     ENSURE_SAFE(DosRead(hfExe,
    1156                                         paModules[i].achModuleName,
    1157                                         bLen,
    1158                                         &ulDummy));
    1159 
    1160                     // module names are not null terminated, so we must
    1161                     // do it now
    1162                     paModules[i].achModuleName[bLen] = 0;
    1163                 } // end for
    1164             }
    1165         } // end LX
    1166         else if (pExec->ulExeFormat == EXEFORMAT_NE)
    1167         {
    1168             // 16-bit executable:
    1169             cModules = pExec->pNEHeader->usModuleTblEntries;
    1170 
    1171             if (cModules)
    1172             {
    1173                 ULONG cb = sizeof(FSYSMODULE) * cModules;
    1174 
    1175                 paModules = (PFSYSMODULE)malloc(cb);
    1176                 if (!paModules)
    1177                     ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY);  // V0.9.9 (2001-04-03) [umoeller]
    1178 
    1179                 memset(paModules, 0, cb);   // V0.9.9 (2001-04-03) [umoeller]
    1180 
    1181                 for (i = 0; i < cModules; i ++)
    1182                 {
    1183                     BYTE bLen;
    1184                     USHORT usOfs;
    1185                     ULONG ulDummy;
    1186 
    1187                     // the module reference table contains offsets
    1188                     // relative to the import table; we hence read
    1189                     // the offset in the module reference table, and
    1190                     // then we read the name in the import table
    1191 
    1192                     ENSURE_SAFE(DosSetFilePtr(hfExe,
    1193                                               pExec->pNEHeader->usModRefTblOfs
    1194                                                 + ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller]
    1195                                                 + sizeof(usOfs) * i,
    1196                                               FILE_BEGIN,
    1197                                               &ulDummy));
    1198 
    1199                     ENSURE_SAFE(DosRead(hfExe, &usOfs, 2, &ulDummy));
    1200 
    1201                     ENSURE_SAFE(DosSetFilePtr(hfExe,
    1202                                               pExec->pNEHeader->usImportTblOfs
    1203                                                 + ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller]
    1204                                                 + usOfs,
    1205                                               FILE_BEGIN,
    1206                                               &ulDummy));
    1207 
    1208                     ENSURE_SAFE(DosRead(hfExe, &bLen, 1, &ulDummy));
    1209 
    1210                     ENSURE_SAFE(DosRead(hfExe,
    1211                                         paModules[i].achModuleName,
    1212                                         bLen,
    1213                                         &ulDummy));
    1214 
    1215                     paModules[i].achModuleName[bLen] = 0;
    1216                 } // end for
    1217             }
    1218         } // end NE
    1219         else
    1220             ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller]
    1221 
    1222         // no error: output data
    1223         *ppaModules = paModules;
    1224         *pcModules = cModules;
    1225 
    1226         ENSURE_FINALLY;
    1227             // if we had an error above, clean up
    1228             free(paModules);
    1229         ENSURE_END;
    1230     }
    1231     else
    1232         ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller]
    1233 
    1234     ENSURE_OK;
    1235 }
    1236 
    1237 /*
    1238  *@@ doshExecFreeImportedModules:
    1239  *      frees resources allocated by doshExecQueryImportedModules.
    1240  *
    1241  *@@added V0.9.9 (2001-03-11)
    1242  */
    1243 
    1244 APIRET doshExecFreeImportedModules(PFSYSMODULE paModules)
    1245 {
    1246     free(paModules);
    1247     return (NO_ERROR);
    1248 }
    1249 
    1250 /*
    1251  *@@ ScanLXEntryTable:
    1252  *      returns the number of exported entries in the entry table.
    1253  *
    1254  *      If paFunctions is not NULL, then successive entries are
    1255  *      filled with the found type and ordinal values.
    1256  *
    1257  *@@added V0.9.9 (2001-03-30) [lafaix]
    1258  *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET
    1259  *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code
    1260  *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support
    1261  */
    1262 
    1263 APIRET ScanLXEntryTable(PEXECUTABLE pExec,
    1264                         PFSYSFUNCTION paFunctions,
    1265                         PULONG pcEntries)        // out: entry table entry count; ptr can be NULL
    1266 {
    1267     ULONG  ulDummy;
    1268     USHORT usOrdinal = 1,
    1269            usCurrent = 0;
    1270     int    i;
    1271 
    1272     ULONG ulNewHeaderOfs = 0; // V0.9.12 (2001-05-03) [umoeller]
    1273     HFILE hfExe = pExec->pFile->hf;
    1274 
    1275     if (pExec->pDosExeHeader)
    1276         // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller]
    1277         ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs;
    1278 
    1279     ENSURE(DosSetFilePtr(hfExe,
    1280                          pExec->pLXHeader->ulEntryTblOfs
    1281                            + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller]
    1282                          FILE_BEGIN,
    1283                          &ulDummy));
    1284 
    1285     while (TRUE)
    1286     {
    1287         BYTE   bCnt,
    1288                bType,
    1289                bFlag;
    1290 
    1291         ENSURE(DosRead(hfExe, &bCnt, 1, &ulDummy));
    1292 
    1293         if (bCnt == 0)
    1294             // end of the entry table
    1295             break;
    1296 
    1297         ENSURE(DosRead(hfExe, &bType, 1, &ulDummy));
    1298 
    1299         switch (bType & 0x7F)
    1300         {
    1301             /*
    1302              * unused entries
    1303              *
    1304              */
    1305 
    1306             case 0:
    1307                 usOrdinal += bCnt;
    1308             break;
    1309 
    1310             /*
    1311              * 16-bit entries
    1312              *
    1313              * the bundle type is followed by the object number
    1314              * and by bCnt bFlag+usOffset entries
    1315              *
    1316              */
    1317 
    1318             case 1:
    1319                 ENSURE(DosSetFilePtr(hfExe,
    1320                                      sizeof(USHORT),
    1321                                      FILE_CURRENT,
    1322                                      &ulDummy));
    1323 
    1324                 for (i = 0; i < bCnt; i ++)
    1325                 {
    1326                     ENSURE(DosRead(hfExe, &bFlag, 1, &ulDummy));
    1327 
    1328                     if (bFlag & 0x01)
    1329                     {
    1330                         if (paFunctions)
    1331                         {
    1332                             paFunctions[usCurrent].ulOrdinal = usOrdinal;
    1333                             paFunctions[usCurrent].ulType = 1;
    1334                             paFunctions[usCurrent].achFunctionName[0] = 0;
    1335                         }
    1336                         usCurrent++;
    1337                     }
    1338 
    1339                     usOrdinal++;
    1340 
    1341                     ENSURE(DosSetFilePtr(hfExe,
    1342                                          sizeof(USHORT),
    1343                                          FILE_CURRENT,
    1344                                          &ulDummy));
    1345 
    1346                 } // end for
    1347             break;
    1348 
    1349             /*
    1350              * 286 call gate entries
    1351              *
    1352              * the bundle type is followed by the object number
    1353              * and by bCnt bFlag+usOffset+usCallGate entries
    1354              *
    1355              */
    1356 
    1357             case 2:
    1358                 ENSURE(DosSetFilePtr(hfExe,
    1359                                      sizeof(USHORT),
    1360                                      FILE_CURRENT,
    1361                                      &ulDummy));
    1362 
    1363                 for (i = 0; i < bCnt; i ++)
    1364                 {
    1365                     ENSURE(DosRead(hfExe, &bFlag, 1, &ulDummy));
    1366 
    1367                     if (bFlag & 0x01)
    1368                     {
    1369                         if (paFunctions)
    1370                         {
    1371                             paFunctions[usCurrent].ulOrdinal = usOrdinal;
    1372                             paFunctions[usCurrent].ulType = 2;
    1373                             paFunctions[usCurrent].achFunctionName[0] = 0;
    1374                         }
    1375                         usCurrent++;
    1376                     }
    1377 
    1378                     usOrdinal++;
    1379 
    1380                     ENSURE(DosSetFilePtr(hfExe,
    1381                                          sizeof(USHORT) + sizeof(USHORT),
    1382                                          FILE_CURRENT,
    1383                                          &ulDummy));
    1384 
    1385                 } // end for
    1386             break;
    1387 
    1388             /*
    1389              * 32-bit entries
    1390              *
    1391              * the bundle type is followed by the object number
    1392              * and by bCnt bFlag+ulOffset entries
    1393              *
    1394              */
    1395 
    1396             case 3:
    1397                 ENSURE(DosSetFilePtr(hfExe,
    1398                                      sizeof(USHORT),
    1399                                      FILE_CURRENT,
    1400                                      &ulDummy));
    1401 
    1402                 for (i = 0; i < bCnt; i ++)
    1403                 {
    1404                     ENSURE(DosRead(hfExe, &bFlag, 1, &ulDummy));
    1405 
    1406                     if (bFlag & 0x01)
    1407                     {
    1408                         if (paFunctions)
    1409                         {
    1410                             paFunctions[usCurrent].ulOrdinal = usOrdinal;
    1411                             paFunctions[usCurrent].ulType = 3;
    1412                             paFunctions[usCurrent].achFunctionName[0] = 0;
    1413                         }
    1414                         usCurrent++;
    1415                     }
    1416 
    1417                     usOrdinal++;
    1418 
    1419                     ENSURE(DosSetFilePtr(hfExe,
    1420                                          sizeof(ULONG),
    1421                                          FILE_CURRENT,
    1422                                          &ulDummy));
    1423                 } // end for
    1424             break;
    1425 
    1426             /*
    1427              * forwarder entries
    1428              *
    1429              * the bundle type is followed by a reserved word
    1430              * and by bCnt bFlag+usModOrd+ulOffsOrdNum entries
    1431              *
    1432              */
    1433 
    1434             case 4:
    1435                 ENSURE(DosSetFilePtr(hfExe,
    1436                                      sizeof(USHORT),
    1437                                      FILE_CURRENT,
    1438                                      &ulDummy));
    1439 
    1440                 for (i = 0; i < bCnt; i ++)
    1441                 {
    1442                     ENSURE(DosSetFilePtr(hfExe,
    1443                                          sizeof(BYTE) + sizeof(USHORT) + sizeof(ULONG),
    1444                                          FILE_CURRENT,
    1445                                          &ulDummy));
    1446 
    1447                     if (paFunctions)
    1448                     {
    1449                         paFunctions[usCurrent].ulOrdinal = usOrdinal;
    1450                         paFunctions[usCurrent].ulType = 4;
    1451                         paFunctions[usCurrent].achFunctionName[0] = 0;
    1452                     }
    1453                     usCurrent++;
    1454 
    1455                     usOrdinal++;
    1456                 } // end for
    1457             break;
    1458 
    1459             /*
    1460              * unknown bundle type
    1461              *
    1462              * we don't know how to handle this bundle, so we must
    1463              * stop parsing the entry table here (as we don't know the
    1464              * bundle size); if paFunctions is not null, we fill it with
    1465              * informative data
    1466              */
    1467 
    1468             default:
    1469                 if (paFunctions)
    1470                 {
    1471                     paFunctions[usCurrent].ulOrdinal = usOrdinal;
    1472                     paFunctions[usCurrent].ulType = bType;
    1473                     sprintf(paFunctions[usCurrent].achFunctionName,
    1474                             "Unknown bundle type encountered (%d).  Aborting entry table scan.",
    1475                             bType);
    1476 
    1477                     usCurrent++;
    1478                 }
    1479                 ENSURE_FAIL(ERROR_INVALID_LIST_FORMAT);
    1480                     // whatever
    1481                     // V0.9.9 (2001-04-03) [umoeller]
    1482         } // end switch (bType & 0x7F)
    1483     } // end while (TRUE)
    1484 
    1485     if (pcEntries)
    1486        *pcEntries = usCurrent;
    1487 
    1488     ENSURE_OK;
    1489 }
    1490 
    1491 /*
    1492  *@@ ScanNEEntryTable:
    1493  *      returns the number of exported entries in the entry table.
    1494  *
    1495  *      if paFunctions is not NULL, then successive entries are
    1496  *      filled with the found type and ordinal values.
    1497  *
    1498  *@@added V0.9.9 (2001-03-30) [lafaix]
    1499  *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET
    1500  *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code
    1501  *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support
    1502  */
    1503 
    1504 APIRET ScanNEEntryTable(PEXECUTABLE pExec,
    1505                         PFSYSFUNCTION paFunctions,
    1506                         PULONG pcEntries)        // out: entry table entry count; ptr can be NULL
    1507 {
    1508     ULONG  ulDummy;
    1509     USHORT usOrdinal = 1,
    1510            usCurrent = 0;
    1511     int    i;
    1512 
    1513     ULONG ulNewHeaderOfs = 0;
    1514     HFILE hfExe = pExec->pFile->hf;
    1515 
    1516     if (pExec->pDosExeHeader)
    1517         // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller]
    1518         ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs;
    1519 
    1520     ENSURE(DosSetFilePtr(hfExe,
    1521                          pExec->pNEHeader->usEntryTblOfs
    1522                            + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller]
    1523                          FILE_BEGIN,
    1524                          &ulDummy));
    1525 
    1526     while (TRUE)
    1527     {
    1528         BYTE bCnt,
    1529              bType,
    1530              bFlag;
    1531 
    1532         ENSURE(DosRead(hfExe, &bCnt, 1, &ulDummy));
    1533 
    1534         if (bCnt == 0)
    1535             // end of the entry table
    1536             break;
    1537 
    1538         ENSURE(DosRead(hfExe, &bType, 1, &ulDummy));
    1539 
    1540         if (bType)
    1541         {
    1542             for (i = 0; i < bCnt; i++)
    1543             {
    1544                 ENSURE(DosRead(hfExe,
    1545                                &bFlag,
    1546                                1,
    1547                                &ulDummy));
    1548 
    1549                 if (bFlag & 0x01)
    1550                 {
    1551                     if (paFunctions)
    1552                     {
    1553                         paFunctions[usCurrent].ulOrdinal = usOrdinal;
    1554                         paFunctions[usCurrent].ulType = 1; // 16-bit entry
    1555                         paFunctions[usCurrent].achFunctionName[0] = 0;
    1556                     }
    1557                     usCurrent++;
    1558                 }
    1559 
    1560                 usOrdinal++;
    1561 
    1562                 if (bType == 0xFF)
    1563                 {
    1564                     // moveable segment
    1565                     ENSURE(DosSetFilePtr(hfExe,
    1566                                          5,
    1567                                          FILE_CURRENT,
    1568                                          &ulDummy));
    1569                 }
    1570                 else
    1571                 {
    1572                     // fixed segment or constant (0xFE)
    1573                     ENSURE(DosSetFilePtr(hfExe,
    1574                                          2,
    1575                                          FILE_CURRENT,
    1576                                          &ulDummy));
    1577                 }
    1578 
    1579             } // end for
    1580         }
    1581         else
    1582             usOrdinal += bCnt;
    1583     } // end while (TRUE)
    1584 
    1585     if (pcEntries)
    1586         *pcEntries = usCurrent;
    1587 
    1588     ENSURE_OK;
    1589 }
    1590 
    1591 /*
    1592  *@@ Compare:
    1593  *      binary search helper
    1594  *
    1595  *@@added V0.9.9 (2001-04-01) [lafaix]
    1596  *@@changed V0.9.9 (2001-04-07) [umoeller]: added _Optlink, or this won't compile as C++
    1597  */
    1598 
    1599 int _Optlink Compare(const void *key,
    1600                      const void *element)
    1601 {
    1602     USHORT        usOrdinal = *((PUSHORT) key);
    1603     PFSYSFUNCTION pFunction = (PFSYSFUNCTION)element;
    1604 
    1605     if (usOrdinal > pFunction->ulOrdinal)
    1606         return (1);
    1607     else if (usOrdinal < pFunction->ulOrdinal)
    1608         return (-1);
    1609     else
    1610         return (0);
    1611 }
    1612 
    1613 /*
    1614  *@@ ScanNameTable:
    1615  *      scans a resident or non-resident name table, and fills the
    1616  *      appropriate paFunctions entries when it encounters exported
    1617  *      entries names.
    1618  *
    1619  *      This functions works for both NE and LX executables.
    1620  *
    1621  *@@added V0.9.9 (2001-03-30) [lafaix]
    1622  *@@changed V0.9.9 (2001-04-02) [lafaix]: the first entry is special
    1623  *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET
    1624  *@@changed V0.9.9 (2001-04-05) [lafaix]: removed the 127 char limit
    1625  *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code
    1626  */
    1627 
    1628 APIRET ScanNameTable(PEXECUTABLE pExec,
    1629                      ULONG cFunctions,
    1630                      PFSYSFUNCTION paFunctions)
    1631 {
    1632     ULONG   ulDummy;
    1633 
    1634     USHORT        usOrdinal;
    1635     PFSYSFUNCTION pFunction;
    1636     HFILE hfExe = pExec->pFile->hf;
    1637 
    1638     while (TRUE)
    1639     {
    1640         BYTE   bLen;
    1641         CHAR   achName[256];
    1642         // int    i;
    1643 
    1644         ENSURE(DosRead(hfExe, &bLen, 1, &ulDummy));
    1645 
    1646         if (bLen == 0)
    1647             // end of the name table
    1648             break;
    1649 
    1650         ENSURE(DosRead(hfExe, &achName, bLen, &ulDummy));
    1651         achName[bLen] = 0;
    1652 
    1653         ENSURE(DosRead(hfExe, &usOrdinal, sizeof(USHORT), &ulDummy));
    1654 
    1655         if ((pFunction = (PFSYSFUNCTION)bsearch(&usOrdinal,
    1656                                                 paFunctions,
    1657                                                 cFunctions,
    1658                                                 sizeof(FSYSFUNCTION),
    1659                                                 Compare)))
    1660         {
    1661             memcpy(pFunction->achFunctionName,
    1662                    achName,
    1663                    bLen+1);
    1664         }
    1665     }
    1666 
    1667     ENSURE_OK;
    1668 }
    1669 
    1670 /*
    1671  *@@ doshExecQueryExportedFunctions:
    1672  *      returns an array of FSYSFUNCTION structure describing all
    1673  *      exported functions.
    1674  *
    1675  *      *pcFunctions receives the # of items in the array (not the
    1676  *      array size!).  Use doshFreeExportedFunctions to clean up.
    1677  *
    1678  *      Note that the returned array only contains entry for exported
    1679  *      functions.  Empty export entries are _not_ included.
    1680  *
    1681  *      This returns a standard OS/2 error code, which might be
    1682  *      any of the codes returned by DosSetFilePtr and DosRead.
    1683  *      In addition, this may return:
    1684  *
    1685  *      --  ERROR_NOT_ENOUGH_MEMORY
    1686  *
    1687  *      --  ERROR_INVALID_EXE_SIGNATURE: exe is in a format other
    1688  *          than LX or NE, which is not understood by this function.
    1689  *
    1690  *      --  If ERROR_INVALID_LIST_FORMAT is returned, the format of an
    1691  *          export entry wasn't understood here.
    1692  *
    1693  *      Even if NO_ERROR is returned, the array pointer might still
    1694  *      be NULL if the module contains no such data.
    1695  *
    1696  *@@added V0.9.9 (2001-03-11) [lafaix]
    1697  *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET
    1698  *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code
    1699  *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support
    1700  *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support
    1701  */
    1702 
    1703 APIRET doshExecQueryExportedFunctions(PEXECUTABLE pExec,
    1704                                       PFSYSFUNCTION *ppaFunctions,  // out: functions array
    1705                                       PULONG pcFunctions)           // out: array item count
    1706 {
    1707     if (    (pExec)
    1708          && (    (pExec->ulOS == EXEOS_OS2)
    1709               || (pExec->ulOS == EXEOS_WIN16)
    1710               || (pExec->ulOS == EXEOS_WIN386)
    1711             )
    1712        )
    1713     {
    1714         ENSURE_BEGIN;
    1715         ULONG         cFunctions = 0;
    1716         PFSYSFUNCTION paFunctions = NULL;
    1717 
    1718         ULONG ulDummy;
    1719 
    1720         HFILE hfExe = pExec->pFile->hf;
    1721         ULONG ulNewHeaderOfs = 0; // V0.9.12 (2001-05-03) [umoeller]
    1722 
    1723         if (pExec->pDosExeHeader)
    1724             // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller]
    1725             ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs;
    1726 
    1727         if (pExec->ulExeFormat == EXEFORMAT_LX)
    1728         {
    1729             // It's a 32bit OS/2 executable
    1730 
    1731             // the number of exported entry points is not stored
    1732             // in the executable header; we have to count them in
    1733             // the entry table
    1734 
    1735             ENSURE(ScanLXEntryTable(pExec, NULL, &cFunctions));
    1736 
    1737             // we now have the number of exported entries; let us
    1738             // build them
    1739 
    1740             if (cFunctions)
    1741             {
    1742                 ULONG cb = sizeof(FSYSFUNCTION) * cFunctions;
    1743 
    1744                 paFunctions = (PFSYSFUNCTION)malloc(cb);
    1745                 if (!paFunctions)
    1746                     ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY);
    1747 
    1748                 // we rescan the entry table (the cost is not as bad
    1749                 // as it may seem, due to disk caching)
    1750 
    1751                 ENSURE_SAFE(ScanLXEntryTable(pExec, paFunctions, NULL));
    1752 
    1753                 // we now scan the resident name table entries
    1754 
    1755                 ENSURE_SAFE(DosSetFilePtr(hfExe,
    1756                                           pExec->pLXHeader->ulResdNameTblOfs
    1757                                             + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller]
    1758                                           FILE_BEGIN,
    1759                                           &ulDummy));
    1760 
    1761                 ENSURE_SAFE(ScanNameTable(pExec, cFunctions, paFunctions));
    1762 
    1763                 // we now scan the non-resident name table entries,
    1764                 // whose offset is _from the begining of the file_
    1765 
    1766                 ENSURE_SAFE(DosSetFilePtr(hfExe,
    1767                                           pExec->pLXHeader->ulNonResdNameTblOfs,
    1768                                           FILE_BEGIN,
    1769                                           &ulDummy));
    1770 
    1771                 ENSURE_SAFE(ScanNameTable(pExec, cFunctions, paFunctions));
    1772             } // end if (cFunctions)
    1773         }
    1774         else if (pExec->ulExeFormat == EXEFORMAT_NE)
    1775         {
    1776             // it's a "new" segmented 16bit executable
    1777 
    1778             // here too the number of exported entry points
    1779             // is not stored in the executable header; we
    1780             // have to count them in the entry table
    1781 
    1782             ENSURE(ScanNEEntryTable(pExec, NULL, &cFunctions));
    1783 
    1784             // we now have the number of exported entries; let us
    1785             // build them
    1786 
    1787             if (cFunctions)
    1788             {
    1789                 // USHORT usOrdinal = 1;
    1790                        // usCurrent = 0;
    1791 
    1792                 paFunctions = (PFSYSFUNCTION)malloc(sizeof(FSYSFUNCTION) * cFunctions);
    1793                 if (!paFunctions)
    1794                     ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY);
    1795 
    1796                 // we rescan the entry table (the cost is not as bad
    1797                 // as it may seem, due to disk caching)
    1798 
    1799                 ENSURE_SAFE(ScanNEEntryTable(pExec, paFunctions, NULL));
    1800 
    1801                 // we now scan the resident name table entries
    1802 
    1803                 ENSURE_SAFE(DosSetFilePtr(hfExe,
    1804                                           pExec->pNEHeader->usResdNameTblOfs
    1805                                             + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller]
    1806                                           FILE_BEGIN,
    1807                                           &ulDummy));
    1808 
    1809                 ENSURE_SAFE(ScanNameTable(pExec, cFunctions, paFunctions));
    1810 
    1811                 // we now scan the non-resident name table entries,
    1812                 // whose offset is _from the begining of the file_
    1813 
    1814                 ENSURE_SAFE(DosSetFilePtr(hfExe,
    1815                                           pExec->pNEHeader->ulNonResdTblOfs,
    1816                                           FILE_BEGIN,
    1817                                           &ulDummy));
    1818 
    1819                 ENSURE_SAFE(ScanNameTable(pExec, cFunctions, paFunctions));
    1820             }
    1821         }
    1822         else
    1823             ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller]
    1824 
    1825         // no error: output data
    1826         *ppaFunctions = paFunctions;
    1827         *pcFunctions = cFunctions;
    1828 
    1829         ENSURE_FINALLY;
    1830             // if we had an error above, clean up
    1831             free(paFunctions);
    1832         ENSURE_END;
    1833     }
    1834     else
    1835         ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller]
    1836 
    1837     ENSURE_OK;
    1838 }
    1839 
    1840 /*
    1841  *@@ doshExecFreeExportedFunctions:
    1842  *      frees resources allocated by doshExecQueryExportedFunctions.
    1843  *
    1844  *@@added V0.9.9 (2001-03-11)
    1845  */
    1846 
    1847 APIRET doshExecFreeExportedFunctions(PFSYSFUNCTION paFunctions)
    1848 {
    1849     free(paFunctions);
    1850 
    1851     return (NO_ERROR);
    1852 }
    1853 
    1854 /*
    1855  *@@ doshExecQueryResources:
    1856  *      returns an array of FSYSRESOURCE structures describing all
    1857  *      available resources in the module.
    1858  *
    1859  *      *pcResources receives the no. of items in the array
    1860  *      (not the array size!). Use doshExecFreeResources to clean up.
    1861  *
    1862  *      This returns a standard OS/2 error code, which might be
    1863  *      any of the codes returned by DosSetFilePtr and DosRead.
    1864  *      In addition, this may return:
    1865  *
    1866  *      --  ERROR_NOT_ENOUGH_MEMORY
    1867  *
    1868  *      --  ERROR_INVALID_EXE_SIGNATURE: exe is in a format other
    1869  *          than LX or NE, which is not understood by this function.
    1870  *
    1871  *      Even if NO_ERROR is returned, the array pointer might still
    1872  *      be NULL if the module contains no such data.
    1873  *
    1874  *@@added V0.9.7 (2000-12-18) [lafaix]
    1875  *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET
    1876  *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support
    1877  *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support
    1878  */
    1879 
    1880 APIRET doshExecQueryResources(PEXECUTABLE pExec,     // in: executable from doshExecOpen
    1881                               PFSYSRESOURCE *ppaResources,   // out: res's array
    1882                               PULONG pcResources)    // out: array item count
    1883 {
    1884     if (    (pExec)
    1885          && (    (pExec->ulOS == EXEOS_OS2)
    1886               || (pExec->ulOS == EXEOS_WIN16)
    1887               || (pExec->ulOS == EXEOS_WIN386)
    1888             )
    1889        )
    1890     {
    1891         ENSURE_BEGIN;
    1892         ULONG           cResources = 0;
    1893         PFSYSRESOURCE   paResources = NULL;
    1894 
    1895         HFILE hfExe = pExec->pFile->hf;
    1896         ULONG           ulNewHeaderOfs = 0; // V0.9.12 (2001-05-03) [umoeller]
    1897 
    1898         if (pExec->pDosExeHeader)
    1899             // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller]
    1900             ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs;
    1901 
    1902         if (pExec->ulExeFormat == EXEFORMAT_LX)
    1903         {
    1904             // 32-bit OS/2 executable:
    1905             PLXHEADER pLXHeader = pExec->pLXHeader;
    1906             if (cResources = pLXHeader->ulResTblCnt)
    1907             {
    1908                 #pragma pack(1)     // V0.9.9 (2001-04-02) [umoeller]
    1909                 struct rsrc32               // Resource Table Entry
    1910                 {
    1911                     unsigned short  type;   // Resource type
    1912                     unsigned short  name;   // Resource name
    1913                     unsigned long   cb;     // Resource size
    1914                     unsigned short  obj;    // Object number
    1915                     unsigned long   offset; // Offset within object
    1916                 } rs;
    1917 
    1918                 struct o32_obj                    // Flat .EXE object table entry
    1919                 {
    1920                     unsigned long   o32_size;     // Object virtual size
    1921                     unsigned long   o32_base;     // Object base virtual address
    1922                     unsigned long   o32_flags;    // Attribute flags
    1923                     unsigned long   o32_pagemap;  // Object page map index
    1924                     unsigned long   o32_mapsize;  // Number of entries in object page map
    1925                     unsigned long   o32_reserved; // Reserved
    1926                 } ot;
    1927                 #pragma pack() // V0.9.9 (2001-04-03) [umoeller]
    1928 
    1929                 ULONG cb = sizeof(FSYSRESOURCE) * cResources;
    1930                 ULONG ulDummy;
    1931                 int i;
    1932                 ULONG ulCurOfs;
    1933 
    1934                 paResources = (PFSYSRESOURCE)malloc(cb);
    1935                 if (!paResources)
    1936                     ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY);
    1937 
    1938                 memset(paResources, 0, cb); // V0.9.9 (2001-04-03) [umoeller]
    1939 
    1940                 ENSURE_SAFE(DosSetFilePtr(hfExe,
    1941                                           pLXHeader->ulResTblOfs
    1942                                             + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller]
    1943                                           FILE_BEGIN,
    1944                                           &ulDummy));
    1945 
    1946                 for (i = 0; i < cResources; i++)
    1947                 {
    1948                     ENSURE_SAFE(DosRead(hfExe, &rs, 14, &ulDummy));
    1949 
    1950                     paResources[i].ulID = rs.name;
    1951                     paResources[i].ulType = rs.type;
    1952                     paResources[i].ulSize = rs.cb;
    1953                     paResources[i].ulFlag = rs.obj; // Temp storage for Object
    1954                                                     // number.  Will be filled
    1955                                                     // with resource flag
    1956                                                     // later.
    1957                 }
    1958 
    1959                 for (i = 0; i < cResources; i++)
    1960                 {
    1961                     ULONG ulOfsThis =   pLXHeader->ulObjTblOfs
    1962                                       + ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller]
    1963                                       + (   sizeof(ot)
    1964                                           * (paResources[i].ulFlag - 1));
    1965 
    1966                     ENSURE_SAFE(DosSetFilePtr(hfExe,
    1967                                               ulOfsThis,
    1968                                               FILE_BEGIN,
    1969                                               &ulDummy));
    1970 
    1971                     ENSURE_SAFE(DosRead(hfExe, &ot, sizeof(ot), &ulDummy));
    1972 
    1973                     paResources[i].ulFlag  = ((ot.o32_flags & OBJWRITE)
    1974                                                     ? 0
    1975                                                     : RNPURE);
    1976                     paResources[i].ulFlag |= ((ot.o32_flags & OBJDISCARD)
    1977                                                     ? 4096
    1978                                                     : 0);
    1979                     paResources[i].ulFlag |= ((ot.o32_flags & OBJSHARED)
    1980                                                     ? RNMOVE
    1981                                                     : 0);
    1982                     paResources[i].ulFlag |= ((ot.o32_flags & OBJPRELOAD)
    1983                                                     ? RNPRELOAD
    1984                                                     : 0);
    1985                 } // end for
    1986             } // end if (cResources)
    1987         } // end if (pExec->ulExeFormat == EXEFORMAT_LX)
    1988         else if (pExec->ulExeFormat == EXEFORMAT_NE)
    1989         {
    1990             PNEHEADER pNEHeader = pExec->pNEHeader;
    1991 
    1992             if (pExec->ulOS == EXEOS_OS2)
    1993             {
    1994                 // 16-bit OS/2 executable:
    1995                 cResources = pNEHeader->usResSegmCount;
    1996 
    1997                 if (cResources)
    1998                 {
    1999                     #pragma pack(1)     // V0.9.9 (2001-04-02) [umoeller]
    2000                     struct {unsigned short type; unsigned short name;} rti;
    2001                     struct new_seg                          // New .EXE segment table entry
    2002                     {
    2003                         unsigned short      ns_sector;      // File sector of start of segment
    2004                         unsigned short      ns_cbseg;       // Number of bytes in file
    2005                         unsigned short      ns_flags;       // Attribute flags
    2006                         unsigned short      ns_minalloc;    // Minimum allocation in bytes
    2007                     } ns;
    2008                     #pragma pack()
    2009 
    2010                     ULONG cb = sizeof(FSYSRESOURCE) * cResources;
    2011                     ULONG ulDummy;
    2012                     int i;
    2013 
    2014                     paResources = (PFSYSRESOURCE)malloc(cb);
    2015                     if (!paResources)
    2016                         ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY);
    2017 
    2018                     memset(paResources, 0, cb);     // V0.9.9 (2001-04-03) [umoeller]
    2019 
    2020                     // we first read the resources IDs and types
    2021 
    2022                     ENSURE_SAFE(DosSetFilePtr(hfExe,
    2023                                               pNEHeader->usResTblOfs
    2024                                                 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller]
    2025                                               FILE_BEGIN,
    2026                                               &ulDummy));
    2027 
    2028                     for (i = 0; i < cResources; i++)
    2029                     {
    2030                         ENSURE_SAFE(DosRead(hfExe, &rti, sizeof(rti), &ulDummy));
    2031 
    2032                         paResources[i].ulID = rti.name;
    2033                         paResources[i].ulType = rti.type;
    2034                     }
    2035 
    2036                     // we then read their sizes and flags
    2037 
    2038                     for (i = 0; i < cResources; i++)
    2039                     {
    2040                         ENSURE_SAFE(DosSetFilePtr(hfExe,
    2041                                                   ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller]
    2042                                                     + pNEHeader->usSegTblOfs
    2043                                                     + (sizeof(ns)
    2044                                                     * (  pNEHeader->usSegTblEntries
    2045                                                        - pNEHeader->usResSegmCount
    2046                                                        + i)),
    2047                                                     FILE_BEGIN,
    2048                                                     &ulDummy));
    2049 
    2050                         ENSURE_SAFE(DosRead(hfExe, &ns, sizeof(ns), &ulDummy));
    2051 
    2052                         paResources[i].ulSize = ns.ns_cbseg;
    2053 
    2054                         paResources[i].ulFlag  = (ns.ns_flags & OBJPRELOAD) ? RNPRELOAD : 0;
    2055                         paResources[i].ulFlag |= (ns.ns_flags & OBJSHARED) ? RNPURE : 0;
    2056                         paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? RNMOVE : 0;
    2057                         paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? 4096 : 0;
    2058                     }
    2059                 } // end if (cResources)
    2060             }
    2061             else
    2062             {
    2063                 // 16-bit Windows executable
    2064                 USHORT usAlignShift;
    2065                 ULONG  ulDummy;
    2066 
    2067                 ENSURE(DosSetFilePtr(hfExe,
    2068                                      pNEHeader->usResTblOfs
    2069                                        + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller]
    2070                                      FILE_BEGIN,
    2071                                      &ulDummy));
    2072 
    2073                 ENSURE(DosRead(hfExe,
    2074                                &usAlignShift,
    2075                                sizeof(usAlignShift),
    2076                                &ulDummy));
    2077 
    2078                 while (TRUE)
    2079                 {
    2080                     USHORT usTypeID;
    2081                     USHORT usCount;
    2082 
    2083                     ENSURE(DosRead(hfExe,
    2084                                    &usTypeID,
    2085                                    sizeof(usTypeID),
    2086                                    &ulDummy));
    2087 
    2088                     if (usTypeID == 0)
    2089                         break;
    2090 
    2091                     ENSURE(DosRead(hfExe,
    2092                                    &usCount,
    2093                                    sizeof(usCount),
    2094                                    &ulDummy));
    2095 
    2096                     ENSURE(DosSetFilePtr(hfExe,
    2097                                          sizeof(ULONG),
    2098                                          FILE_CURRENT,
    2099                                          &ulDummy));
    2100 
    2101                     cResources += usCount;
    2102 
    2103                     // first pass, skip NAMEINFO table
    2104                     ENSURE(DosSetFilePtr(hfExe,
    2105                                          usCount*6*sizeof(USHORT),
    2106                                          FILE_CURRENT,
    2107                                          &ulDummy));
    2108                 }
    2109 
    2110                 if (cResources)
    2111                 {
    2112                     USHORT usCurrent = 0;
    2113                     ULONG cb = sizeof(FSYSRESOURCE) * cResources;
    2114 
    2115                     paResources = (PFSYSRESOURCE)malloc(cb);
    2116                     if (!paResources)
    2117                         ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY);
    2118 
    2119                     memset(paResources, 0, cb);
    2120 
    2121                     ENSURE_SAFE(DosSetFilePtr(hfExe,
    2122                                               pNEHeader->usResTblOfs
    2123                                                 + ulNewHeaderOfs,
    2124                                               FILE_BEGIN,
    2125                                               &ulDummy));
    2126 
    2127                     ENSURE_SAFE(DosRead(hfExe,
    2128                                         &usAlignShift,
    2129                                         sizeof(usAlignShift),
    2130                                         &ulDummy));
    2131 
    2132                     while (TRUE)
    2133                     {
    2134                         USHORT usTypeID;
    2135                         USHORT usCount;
    2136                         int i;
    2137 
    2138                         ENSURE_SAFE(DosRead(hfExe,
    2139                                             &usTypeID,
    2140                                             sizeof(usTypeID),
    2141                                             &ulDummy));
    2142 
    2143                         if (usTypeID == 0)
    2144                             break;
    2145 
    2146                         ENSURE_SAFE(DosRead(hfExe,
    2147                                             &usCount,
    2148                                             sizeof(usCount),
    2149                                             &ulDummy));
    2150 
    2151                         ENSURE_SAFE(DosSetFilePtr(hfExe,
    2152                                                   sizeof(ULONG),
    2153                                                   FILE_CURRENT,
    2154                                                   &ulDummy));
    2155 
    2156                         // second pass, read NAMEINFO table
    2157                         for (i = 0; i < usCount; i++)
    2158                         {
    2159                             USHORT usLength,
    2160                                    usFlags,
    2161                                    usID;
    2162 
    2163                             ENSURE_SAFE(DosSetFilePtr(hfExe,
    2164                                                       sizeof(USHORT),
    2165                                                       FILE_CURRENT,
    2166                                                       &ulDummy));
    2167 
    2168                             ENSURE_SAFE(DosRead(hfExe,
    2169                                                 &usLength,
    2170                                                 sizeof(USHORT),
    2171                                                 &ulDummy));
    2172                             ENSURE_SAFE(DosRead(hfExe,
    2173                                                 &usFlags,
    2174                                                 sizeof(USHORT),
    2175                                                 &ulDummy));
    2176                             ENSURE_SAFE(DosRead(hfExe,
    2177                                                 &usID,
    2178                                                 sizeof(USHORT),
    2179                                                 &ulDummy));
    2180 
    2181                             ENSURE_SAFE(DosSetFilePtr(hfExe,
    2182                                                       2*sizeof(USHORT),
    2183                                                       FILE_CURRENT,
    2184                                                       &ulDummy));
    2185 
    2186                             // !!! strings ids and types not handled yet
    2187                             // !!! 15th bit is used to denotes strings
    2188                             // !!! offsets [lafaix]
    2189                             paResources[usCurrent].ulType = usTypeID ^ 0x8000;
    2190                             paResources[usCurrent].ulID = usID ^ 0x8000;
    2191                             paResources[usCurrent].ulSize = usLength << usAlignShift;
    2192                             paResources[usCurrent].ulFlag = usFlags & 0x70;
    2193 
    2194                             usCurrent++;
    2195                         }
    2196                     }
    2197                 }
    2198             }
    2199         } // end else if (pExec->ulExeFormat == EXEFORMAT_NE)
    2200         else
    2201             ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller]
    2202 
    2203         *ppaResources = paResources;
    2204         *pcResources = cResources;
    2205 
    2206         ENSURE_FINALLY;
    2207             // if we had an error above, clean up
    2208             free(paResources);
    2209         ENSURE_END;
    2210     }
    2211     else
    2212         ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller]
    2213 
    2214     ENSURE_OK;
    2215 }
    2216 
    2217 /*
    2218  *@@ doshExecFreeResources:
    2219  *      frees resources allocated by doshExecQueryResources.
    2220  *
    2221  *@@added V0.9.7 (2000-12-18) [lafaix]
    2222  */
    2223 
    2224 APIRET doshExecFreeResources(PFSYSRESOURCE paResources)
    2225 {
    2226     free(paResources);
    2227     return (NO_ERROR);
    2228 }
    2229 
    2230 /*
    2231  *@@ doshLoadLXMaps:
    2232  *      loads the three main LX maps into the given
    2233  *      EXECUTABLE structure.
    2234  *
    2235  *      This loads:
    2236  *
    2237  *      1)  the LX resource table;
    2238  *
    2239  *      2)  the LX object table;
    2240  *
    2241  *      3)  the LX object _page_ table (object map).
    2242  *
    2243  *      Note that this is not automatically called
    2244  *      by doshExecOpen to save time, since the LX
    2245  *      maps are not needed for all the other exe
    2246  *      functions.
    2247  *
    2248  *      This returns:
    2249  *
    2250  *      --  NO_ERROR: all three LX maps were loaded,
    2251  *          and pExec->fLXMapsLoaded was set to TRUE.
    2252  *
    2253  *      --  ERROR_INVALID_PARAMETER
    2254  *
    2255  *      --  ERROR_INVALID_EXE_SIGNATURE: pExec does
    2256  *          not specify an LX executable.
    2257  *
    2258  *      --  ERROR_NO_DATA: at least one of the structs
    2259  *          does not exist.
    2260  *
    2261  *      --  ERROR_NOT_ENOUGH_MEMORY
    2262  *
    2263  *      plus the error codes of doshReadAt.
    2264  *
    2265  *      Call doshFreeLXMaps to clean up explicitly, but
    2266  *      that func automatically gets called by doshExecClose.
    2267  *
    2268  *@@added V0.9.16 (2001-12-08) [umoeller]
    2269  */
    2270 
    2271 APIRET doshLoadLXMaps(PEXECUTABLE pExec)
    2272 {
    2273     APIRET arc;
    2274 
    2275     PLXHEADER pLXHeader;
    2276 
    2277     if (!pExec)
    2278         arc = ERROR_INVALID_PARAMETER;
    2279     else if (pExec->fLXMapsLoaded)
    2280         // already loaded:
    2281         arc = NO_ERROR;
    2282     else if (    (pExec->ulExeFormat != EXEFORMAT_LX)
    2283               || (!(pLXHeader = pExec->pLXHeader))
    2284             )
    2285         arc = ERROR_INVALID_EXE_SIGNATURE;
    2286     else
    2287     {
    2288         PXFILE pFile = pExec->pFile;
    2289         ULONG ulNewHeaderOfs = 0;
    2290         ULONG cb;
    2291 
    2292         if (pExec->pDosExeHeader)
    2293             // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller]
    2294             ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs;
    2295 
    2296         // resource table
    2297         if (    (!(arc = doshAllocArray(pLXHeader->ulResTblCnt,
    2298                                         sizeof(RESOURCETABLEENTRY),
    2299                                         (PBYTE*)&pExec->pRsTbl,
    2300                                         &cb)))
    2301              && (!(arc = doshReadAt(pFile,
    2302                                     pLXHeader->ulResTblOfs
    2303                                       + ulNewHeaderOfs,
    2304                                     &cb,
    2305                                     (PBYTE)pExec->pRsTbl)))
    2306             )
    2307         {
    2308             // object table
    2309             if (    (!(arc = doshAllocArray(pLXHeader->ulObjCount,
    2310                                             sizeof(OBJECTTABLEENTRY),
    2311                                             (PBYTE*)&pExec->pObjTbl,
    2312                                             &cb)))
    2313                  && (!(arc = doshReadAt(pFile,
    2314                                         pLXHeader->ulObjTblOfs
    2315                                           + ulNewHeaderOfs,
    2316                                         &cb,
    2317                                         (PBYTE)pExec->pObjTbl)))
    2318                )
    2319             {
    2320                 // object page table
    2321                 if (    (!(arc = doshAllocArray(pLXHeader->ulPageCount,
    2322                                                 sizeof(OBJECTPAGETABLEENTRY),
    2323                                                 (PBYTE*)&pExec->pObjPageTbl,
    2324                                                 &cb)))
    2325                      && (!(arc = doshReadAt(pFile,
    2326                                             pLXHeader->ulObjPageTblOfs
    2327                                               + ulNewHeaderOfs,
    2328                                             &cb,
    2329                                             (PBYTE)pExec->pObjPageTbl)))
    2330                    )
    2331                 {
    2332                 }
    2333             }
    2334         }
    2335 
    2336         if (!arc)
    2337             pExec->fLXMapsLoaded = TRUE;
    2338         else
    2339             doshFreeLXMaps(pExec);
    2340     }
    2341 
    2342     return (arc);
    2343 }
    2344 
    2345 /*
    2346  *@@ doshFreeLXMaps:
    2347  *      frees only the LX maps allocated by doshLoadLXMaps.
    2348  *      This gets called automatically by doshExecClose.
    2349  *
    2350  *@@added V0.9.16 (2001-12-08) [umoeller]
    2351  */
    2352 
    2353 VOID doshFreeLXMaps(PEXECUTABLE pExec)
    2354 {
    2355     FREE(pExec->pRsTbl);
    2356     FREE(pExec->pObjTbl);
    2357     FREE(pExec->pObjPageTbl);
    2358     pExec->fLXMapsLoaded = FALSE;
    2359 }
    2360 
    2361 /*
    2362  *@@ doshLoadOS2NEMaps:
    2363  *
    2364  *      This works only if
    2365  *
    2366  *      --  ulExeFormat == EXEFORMAT_NE and
    2367  *
    2368  *      --  ulOS == EXEOS_OS2,
    2369  *
    2370  *      but not with Win16 NE executables.
    2371  *
    2372  *@@added V0.9.16 (2001-12-08) [umoeller]
    2373  */
    2374 
    2375 APIRET doshLoadOS2NEMaps(PEXECUTABLE pExec)
    2376 {
    2377     APIRET arc;
    2378 
    2379     PNEHEADER pNEHeader;
    2380 
    2381     if (!pExec)
    2382         arc = ERROR_INVALID_PARAMETER;
    2383     else if (pExec->fOS2NEMapsLoaded)
    2384         // already loaded:
    2385         arc = NO_ERROR;
    2386     else if (    (pExec->ulExeFormat != EXEFORMAT_NE)
    2387               || (pExec->ulOS != EXEOS_OS2)
    2388               || (!(pNEHeader = pExec->pNEHeader))
    2389             )
    2390         arc = ERROR_INVALID_EXE_SIGNATURE;
    2391     else
    2392     {
    2393         PXFILE pFile = pExec->pFile;
    2394         ULONG ulNewHeaderOfs = 0;
    2395         ULONG cb;
    2396 
    2397         if (pExec->pDosExeHeader)
    2398             // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller]
    2399             ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs;
    2400 
    2401         // resource table
    2402         if (    (!(arc = doshAllocArray(pNEHeader->usResSegmCount,
    2403                                         sizeof(OS2NERESTBLENTRY),
    2404                                         (PBYTE*)&pExec->paOS2NEResTblEntry,
    2405                                         &cb)))
    2406              && (!(arc = doshReadAt(pFile,
    2407                                     pNEHeader->usResTblOfs
    2408                                       + ulNewHeaderOfs,
    2409                                     &cb,
    2410                                     (PBYTE)pExec->paOS2NEResTblEntry)))
    2411             )
    2412         {
    2413             // resource segments
    2414             if (    (!(arc = doshAllocArray(pNEHeader->usResSegmCount,
    2415                                             sizeof(OS2NESEGMENT),
    2416                                             (PBYTE*)&pExec->paOS2NESegments,
    2417                                             &cb)))
    2418                  && (!(arc = doshReadAt(pFile,
    2419                                         pNEHeader->usResTblOfs
    2420                                           + ulNewHeaderOfs
    2421                                           - cb, // pNEHeader->usResSegmCount * sizeof(struct new_seg)
    2422                                         &cb,
    2423                                         (PBYTE)pExec->paOS2NESegments)))
    2424                 )
    2425             {
    2426             }
    2427         }
    2428 
    2429         if (!arc)
    2430             pExec->fOS2NEMapsLoaded = TRUE;
    2431         else
    2432             doshFreeNEMaps(pExec);
    2433     }
    2434 
    2435     return (arc);
    2436 }
    2437 
    2438 /*
    2439  *@@ doshFreeNEMaps:
    2440  *
    2441  *@@added V0.9.16 (2001-12-08) [umoeller]
    2442  */
    2443 
    2444 VOID doshFreeNEMaps(PEXECUTABLE pExec)
    2445 {
    2446     FREE(pExec->paOS2NEResTblEntry);
    2447     FREE(pExec->paOS2NESegments);
    2448     pExec->fOS2NEMapsLoaded = FALSE;
    2449 }
    2450 
    2451 /*
    2452  *@@ doshExecClose:
    2453  *      this closes an executable opened with doshExecOpen.
    2454  *      Always call this function if NO_ERROR was returned by
    2455  *      doshExecOpen.
    2456  *
    2457  *      This automaticall calls doshFreeLXMaps.
    2458  *
    2459  *@@added V0.9.0 [umoeller]
    2460  *@@changed V0.9.16 (2001-12-08) [umoeller]: fixed memory leaks
    2461  *@@changed V0.9.16 (2001-12-08) [umoeller]: changed prototype to null the pExec ptr
    2462  */
    2463 
    2464 APIRET doshExecClose(PEXECUTABLE *ppExec)
    2465 {
    2466     APIRET arc = NO_ERROR;
    2467     PEXECUTABLE pExec;
    2468     if (    (ppExec)
    2469          && (pExec = *ppExec)
    2470        )
    2471     {
    2472         char **papsz[] =
    2473             {
    2474                 (char**)&pExec->pDosExeHeader,
    2475                 (char**)&pExec->pNEHeader,
    2476                 (char**)&pExec->pLXHeader,
    2477                 (char**)&pExec->pPEHeader,
    2478 
    2479                 &pExec->pszDescription,
    2480                 &pExec->pszVendor,
    2481                 &pExec->pszVersion,
    2482                 &pExec->pszInfo,
    2483 
    2484                 &pExec->pszBuildDateTime,
    2485                 &pExec->pszBuildMachine,
    2486                 &pExec->pszASD,
    2487                 &pExec->pszLanguage,
    2488                 &pExec->pszCountry,
    2489                 &pExec->pszRevision,
    2490                 &pExec->pszUnknown,
    2491                 &pExec->pszFixpak
    2492             };
    2493         ULONG ul;
    2494 
    2495         doshFreeLXMaps(pExec);
    2496         doshFreeNEMaps(pExec);
    2497 
    2498         // fixed the memory leaks with the missing fields,
    2499         // turned this into a loop
    2500         for (ul = 0;
    2501              ul < sizeof(papsz) / sizeof(papsz[0]);
    2502              ul++)
    2503         {
    2504             PSZ pThis;
    2505             if (pThis = *papsz[ul])
    2506             {
    2507                 free(pThis);
    2508                 pThis = NULL;
    2509             }
    2510         }
    2511 
    2512         doshClose(&pExec->pFile);
    2513 
    2514         free(pExec);
    2515         *ppExec = NULL;
    2516     }
    2517     else
    2518         arc = ERROR_INVALID_PARAMETER;
    2519 
    2520     return (arc);
    2521352}
    2522353
  • trunk/src/helpers/gpih.c

    r127 r129  
    7878 *      mentioned in the documentation, so a word is in order here.
    7979 *
    80  *      In general, graphics operations
    81  *      involving device coordinates (such as regions, bit maps and
    82  *      bit blts, and window management) use inclusive-exclusive
    83  *      rectangles.  All other graphics operations, such as GPI
    84  *      functions that define paths, use inclusive-inclusive rectangles.
     80 *      In general, graphics operations involving device coordinates
     81 *      (such as regions, bit maps and bit blts, and window management)
     82 *      use inclusive-exclusive rectangles. In other words, with
     83 *      those rectangles, xRight - xLeft is the same as the width
     84 *      of the rectangle (and yTop - yBottom = height).
     85 *
     86 *      All other graphics operations, such as GPI functions that
     87 *      define paths, use inclusive-inclusive rectangles.
    8588 *
    8689 *      This can be a problem with mixing Win and Gpi functions. For
    8790 *      example, WinQueryWindowRect returns an inclusive-exclusive
    88  *      rectangle (so that the xRight value is the same as the window
    89  *      width -- tested V0.9.7 (2000-12-20) [umoeller]).
     91 *      rectangle (tested V0.9.7 (2000-12-20) [umoeller]).
    9092 *
    9193 *      WinFillRect expects an inclusive-exclusive rectangle, so it
     
    267269 +          GpiCreateLogColorTable(hps, 0, LCOLF_RGB, 0, 0, NULL);
    268270 *
    269  *@@changed V0.9.7 (2001-01-15) [umoeller]: turned macro into function
     271 *@@changed V0.9.7 (2001-01-15) [umoeller]: turned macro into function to reduce fixups
    270272 */
    271273
  • trunk/src/helpers/helpers_pre.in

    r127 r129  
    5959$(OUTPUTDIR)\eah.obj \
    6060$(OUTPUTDIR)\except.obj \
     61$(OUTPUTDIR)\exeh.obj \
    6162$(OUTPUTDIR)\lan.obj \
    6263$(OUTPUTDIR)\level.obj \
  • trunk/src/helpers/tmsgfile.c

    r119 r129  
    154154
    155155    if (!(arc = doshLoadTextFile(pcszMessageFile,
    156                                  &pszContent)))
     156                                 &pszContent,
     157                                 NULL)))
    157158    {
    158159        // file loaded:
  • trunk/src/helpers/winh.c

    r113 r129  
    28662866                        ULONG   ulPP,       // in: PP_* index
    28672867                        BOOL    fInherit,   // in: search parent windows too?
    2868                         LONG    lSysColor)  // in: SYSCLR_* index
     2868                        LONG    lSysColor)  // in: SYSCLR_* index or -1
    28692869{
    28702870    ULONG   ul,
     
    32343234VOID winhSleep(ULONG ulSleep)    // in: sleep time in milliseconds
    32353235{
    3236     HWND hwnd = winhCreateObjectWindow(WC_STATIC, NULL);
    3237     if (hwnd)
     3236    HWND hwnd;
     3237    if (hwnd = winhCreateObjectWindow(WC_STATIC, NULL))
    32383238    {
    32393239        QMSG qmsg;
  • trunk/src/helpers/wphandle.c

    r127 r129  
    375375
    376376                    if (!arc)
    377                         if (treeInsert(ppTree,
    378                                        pcChildren,
    379                                        (TREE*)pNew,
    380                                        treeCompareStrings))
    381                             ; // @@todo if this fails, there are
     377                        if (!treeInsert(ppTree,
     378                                        pcChildren,
     379                                        (TREE*)pNew,
     380                                        treeCompareStrings))
     381                            // store PNODE in hash table
     382                            pHandlesBuf->NodeHashTable[pNode->usHandle] = pNew;
     383                        else
     384                            ;
     385                            // @@todo if this fails, there are
    382386                            // several handles for short name!!!
    383387                            // arc = ERROR_WPH_NODE_TREEINSERT_FAILED;
    384388
    385                     // store PNODE in hash table
    386                     pHandlesBuf->NodeHashTable[pNode->usHandle] = pNew;
     389                    if (arc)
     390                        free(pNew);
     391
    387392                }
    388393
     
    933938                               str.psz,
    934939                               str.ulLength + 1);
     940                xstrClear(&str);
    935941            }
    936942        }
  • trunk/src/helpers/xstring.c

    r121 r129  
    230230}
    231231
     232#ifdef __DEBUG_MALLOC_ENABLED__
     233
     234/*
     235 *@@ xstrInitCopyDebug:
     236 *
     237 *@@added V0.9.16 (2002-01-05) [umoeller]
     238 */
     239
     240void XWPENTRY xstrInitCopyDebug(PXSTRING pxstr,
     241                                const char *pcszSource,
     242                                ULONG ulExtraAllocate,
     243                                const char *file,
     244                                unsigned long line,
     245                                const char *function)
     246{
     247    if (pxstr)
     248    {
     249        memset(pxstr, 0, sizeof(XSTRING));
     250
     251        if (pcszSource)
     252        {
     253            pxstr->ulLength = strlen(pcszSource);
     254
     255            if (pxstr->ulLength)
     256            {
     257                // we do have a source string:
     258                pxstr->cbAllocated = pxstr->ulLength + 1 + ulExtraAllocate;
     259                pxstr->psz = (PSZ)memdMalloc(pxstr->cbAllocated,
     260                                             file,
     261                                             line,
     262                                             function);
     263                // V0.9.16 (2002-01-05) [umoeller]
     264                memcpy(pxstr->psz,
     265                       pcszSource,
     266                       pxstr->ulLength);
     267                pxstr->psz[pxstr->ulLength] = '\0';
     268
     269                pxstr->ulDelta = pxstr->cbAllocated * 10 / 100;
     270            }
     271        }
     272    }
     273}
     274
     275#endif
     276
    232277/*
    233278 *@@ xstrInitCopy:
     
    252297 *@@changed V0.9.7 (2000-12-31) [umoeller]: added ulExtraAllocate
    253298 *@@changed V0.9.9 (2001-03-09) [umoeller]: added ulDelta
     299 *@@changed V0.9.16 (2002-01-05) [umoeller]: use memcpy instead of strcpy
    254300 */
    255301
     
    271317                pxstr->cbAllocated = pxstr->ulLength + 1 + ulExtraAllocate;
    272318                pxstr->psz = (PSZ)malloc(pxstr->cbAllocated);
    273                 strcpy(pxstr->psz, pcszSource);
     319                // V0.9.16 (2002-01-05) [umoeller]
     320                memcpy(pxstr->psz,
     321                       pcszSource,
     322                       pxstr->ulLength);
     323                pxstr->psz[pxstr->ulLength] = '\0';
    274324
    275325                pxstr->ulDelta = pxstr->cbAllocated * 10 / 100;
Note: See TracChangeset for help on using the changeset viewer.