Changeset 129
- Timestamp:
- Jan 8, 2002, 7:29:57 PM (24 years ago)
- Location:
- trunk
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/helpers/dosh.h
r127 r129 360 360 HFILE hf; 361 361 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 363 366 ULONG cbInitial, // intial file size on open (can be 0 if new) 364 367 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 365 372 } XFILE, *PXFILE; 366 373 … … 399 406 400 407 APIRET doshLoadTextFile(PCSZ pcszFile, 401 PSZ* ppszContent); 408 PSZ* ppszContent, 409 PULONG pcbRead); 402 410 403 411 PSZ doshCreateBackupFileName(const char* pszExisting); … … 463 471 PUSHORT pusReturn); 464 472 465 /********************************************************************466 *467 * Executable helpers468 *469 ********************************************************************/470 471 #pragma pack(1)472 473 /*474 *@@ DOSEXEHEADER:475 * old DOS EXE header at offset 0476 * in any EXE file.477 *478 *@@changed V0.9.7 (2000-12-20) [umoeller]: fixed NE offset479 *@@changed V0.9.9 (2001-04-06) [lafaix]: additional fields defined480 */481 482 typedef struct _DOSEXEHEADER483 {484 USHORT usDosExeID; // 00: DOS exeid (0x5a4d)485 USHORT usFileLenMod512; // 02: filelen mod 512486 USHORT usFileLenDiv512; // 04: filelen div 512487 USHORT usSegFix; // 06: count of segment adds to fix488 USHORT usHdrPargCnt; // 08: size of header in paragrphs489 USHORT usMinAddPargCnt; // 0a: minimum addtl paragraphs count490 USHORT usMaxAddPargCnt; // 0c: max addtl paragraphs count491 USHORT usSSStartup; // 0e: SS at startup492 USHORT usSPStartup; // 10: SP at startup493 USHORT usHdrChecksum; // 12: header checksum494 USHORT usIPStartup; // 14: IP at startup495 USHORT usCodeSegOfs; // 16: code segment offset from EXE start496 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: unused500 USHORT usBehaviorBits; // 20: exe.h says this field contains501 // 'behavior bits'502 USHORT usUnused2; // 22: unused503 USHORT usOEMIdentifier; // 24: OEM identifier504 USHORT usOEMInformation; // 26: OEM information505 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 Lafaix512 // V0.9.7 (2000-12-20) [umoeller]513 } DOSEXEHEADER, *PDOSEXEHEADER;514 515 // NE and LX OS types516 #define NEOS_UNKNOWN 0517 #define NEOS_OS2 1 // Win16 SDK says: "reserved"...518 #define NEOS_WIN16 2519 #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 the526 * EXE file (at DOSEXEHEADER.ulNewHeaderOfs).527 *528 *@@changed V0.9.9 (2001-04-06) [lafaix]: fixed typo in usMoveableEntries529 */530 531 typedef struct _NEHEADER532 {533 CHAR achNE[2]; // 00: "NE" magic ne_magic534 BYTE bLinkerVersion; // 02: linker version ne_ver535 BYTE bLinkerRevision; // 03: linker revision ne_rev536 USHORT usEntryTblOfs; // 04: ofs from this to entrytable ne_enttab537 USHORT usEntryTblLen; // 06: length of entrytable ne_cbenttab538 ULONG ulChecksum; // 08: MS: reserved, OS/2: checksum ne_crc539 USHORT usFlags; // 0c: flags ne_flags540 /*541 #define NENOTP 0x8000 // Not a process == library542 #define NENOTMPSAFE 0x4000 // Process is not multi-processor safe543 // (Win3.1 SDK: "reserved")544 #define NEIERR 0x2000 // Errors in image545 #define NEBOUND 0x0800 // Bound Family/API546 // (Win3.1 SDK: "first segment contains code547 // that loads the application")548 #define NEAPPTYP 0x0700 // Application type mask549 // (Win3.1 SDK: "reserved")550 #define NENOTWINCOMPAT 0x0100 // Not compatible with P.M. Windowing551 // (Win3.1 SDK: "reserved")552 #define NEWINCOMPAT 0x0200 // Compatible with P.M. Windowing553 // (Win3.1 SDK: "reserved")554 #define NEWINAPI 0x0300 // Uses P.M. Windowing API555 // (Win3.1 SDK: "reserved")556 #define NEFLTP 0x0080 // Floating-point instructions557 #define NEI386 0x0040 // 386 instructions558 #define NEI286 0x0020 // 286 instructions559 #define NEI086 0x0010 // 8086 instructions560 #define NEPROT 0x0008 // Runs in protected mode only561 // (Win3.1 SDK: "reserved")562 #define NEPPLI 0x0004 // Per-Process Library Initialization563 // (Win3.1 SDK: "reserved")564 #define NEINST 0x0002 // Instance data565 #define NESOLO 0x0001 // Solo data (single data)566 */567 USHORT usAutoDataSegNo; // 0e: auto-data seg no. ne_autodata568 // (Win3.1 SDK: "0 if both NEINST and NESOLO are cleared")569 USHORT usInitlHeapSize; // 10: initl. heap size ne_heap570 // (Win3.1 SDK: "0 if no local allocation")571 USHORT usInitlStackSize; // 12: initl. stack size ne_stack572 // (Win3.1 SDK: "0 if SS != DS")573 ULONG ulCSIP; // 14: CS:IP ne_csip574 ULONG ulSSSP; // 18: SS:SP ne_sssp575 USHORT usSegTblEntries; // 1c: segment tbl entry count ne_cseg576 USHORT usModuleTblEntries; // 1e: module ref. table entry count ne_cmod577 USHORT usNonResdTblLen; // 20: non-resd. name tbl length ne_cbnrestab578 USHORT usSegTblOfs; // 22: segment tbl ofs ne_segtab579 // (from start of NEHEADER)580 USHORT usResTblOfs; // 24: resource tbl ofs ne_rsrctab581 // (from start of NEHEADER)582 USHORT usResdNameTblOfs; // 26: resd. name tbl ofs ne_restab583 // (from start of NEHEADER)584 USHORT usModRefTblOfs; // 28: module ref. table ofs ne_modtab585 // (from start of NEHEADER)586 USHORT usImportTblOfs; // 2a: import name tbl ofs ne_imptab587 // (from start of NEHEADER)588 ULONG ulNonResdTblOfs; // 2c: non-resd. name tbl ofs ne_nrestab589 // (from start of EXE!)590 USHORT usMoveableEntries; // 30: moveable entry points count ne_cmovent591 USHORT usLogicalSectShift; // 32: logcl. sector shift ne_align592 // (Win3.1 SDK: "typically 4, but default is 9")593 USHORT usResSegmCount; // 34: resource segm. count ne_cres594 BYTE bTargetOS; // 36: target OS (NEOS_* flags) ne_exetyp595 BYTE bFlags2; // 37: addtl. flags ne_flagsothers596 // Win3.1 SDK:597 // bit 1 --> Win2.x, but runs in Win3.x protected mode598 // bit 2 --> Win2.x that supports prop. fonts599 // bit 3 --> exec contains fastload area600 /*601 #define NELONGNAMES 0x01602 #define NEWINISPROT 0x02603 #define NEWINGETPROPFON 0x04604 #define NEWLOAPPL 0x80605 */606 // the following are not listed in newexe.h, but are documented for Win3.x607 USHORT usFastLoadOfs; // 38: fast-load area ofs608 USHORT usFastLoadLen; // 3a: fast-load area length609 USHORT usReserved; // 3c: MS: 'reserved'610 USHORT usReqWinVersion; // 3e: Win-only: min. Win version611 } NEHEADER, *PNEHEADER;612 613 /*614 *@@ LXHEADER:615 * linear executable (LX) header format,616 * which comes after the DOS header in the617 * EXE file (at DOSEXEHEADER.ulNewHeaderOfs).618 *619 *@@changed V0.9.9 (2001-04-06) [lafaix]: fixed auto data object and ulinstanceDemdCnt620 */621 622 typedef struct _LXHEADER623 {624 CHAR achLX[2]; // 00: "LX" or "LE" magic625 // this is "LX" for 32-bit OS/2 programs, but626 // "LE" for MS-DOS progs which use this format627 // (e.g. WINDOWS\SMARTDRV.EXE). IBM says the628 // LE format was never released and superceded629 // 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 level633 USHORT usCPU; // 08: CPU type634 USHORT usTargetOS; // 0a: OS type (NEOS_* flags)635 ULONG ulModuleVersion; // 0c: module version636 ULONG ulFlags; // 10: module flags637 /* #define E32NOTP 0x8000L // Library Module - used as NENOTP638 #define E32NOLOAD 0x2000L // Module not Loadable639 #define E32PMAPI 0x0300L // Uses PM Windowing API640 #define E32PMW 0x0200L // Compatible with PM Windowing641 #define E32NOPMW 0x0100L // Incompatible with PM Windowing642 #define E32NOEXTFIX 0x0020L // NO External Fixups in .EXE643 #define E32NOINTFIX 0x0010L // NO Internal Fixups in .EXE644 #define E32SYSDLL 0x0008L // System DLL, Internal Fixups discarded645 #define E32LIBINIT 0x0004L // Per-Process Library Initialization646 #define E32LIBTERM 0x40000000L // Per-Process Library Termination647 #define E32APPMASK 0x0300L // Application Type Mask648 */649 ULONG ulPageCount; // 14: no. of pages in module650 ULONG ulEIPRelObj; // 18: object to which EIP is relative651 ULONG ulEIPEntryAddr; // 1c: EIP entry addr652 ULONG ulESPObj; // 20: ESP object653 ULONG ulESP; // 24: ESP654 ULONG ulPageSize; // 28: page size (4K)655 ULONG ulPageLeftShift; // 2c: page left-shift656 ULONG ulFixupTblLen; // 30: fixup section total size657 ULONG ulFixupTblChecksum; // 34: fixup section checksum658 ULONG ulLoaderLen; // 38: size req. for loader section659 ULONG ulLoaderChecksum; // 3c: loader section checksum660 ULONG ulObjTblOfs; // 40: object table offset661 ULONG ulObjCount; // 44: object count662 ULONG ulObjPageTblOfs; // 48: object page table ofs663 ULONG ulObjIterPagesOfs; // 4c: object iter pages ofs664 ULONG ulResTblOfs; // 50: resource table ofs665 ULONG ulResTblCnt; // 54: resource entry count666 ULONG ulResdNameTblOfs; // 58: resident name tbl ofs667 ULONG ulEntryTblOfs; // 5c: entry tbl ofs668 ULONG ulModDirectivesOfs; // 60: module directives ofs669 ULONG ulModDirectivesCnt; // 64: module directives count670 ULONG ulFixupPagePageTblOfs;// 68: fixup page tbl ofs671 ULONG ulFixupRecTblOfs; // 6c: fixup record tbl ofs672 ULONG ulImportModTblOfs; // 70: import modl tbl ofs673 ULONG ulImportModTblCnt; // 74: import modl tbl count674 ULONG ulImportProcTblOfs; // 78: import proc tbl ofs675 ULONG ulPerPageCSOfs; // 7c: per page checksum ofs676 ULONG ulDataPagesOfs; // 80: data pages ofs677 ULONG ulPreloadPagesCnt; // 84: preload pages count678 ULONG ulNonResdNameTblOfs; // 88: non-resdnt name tbl ofs679 ULONG ulNonResdNameTblLen; // 8c: non-resdnt name tbl length680 ULONG ulNonResdNameTblCS; // 90: non-res name tbl checksum681 ULONG ulAutoDataSegObj; // 94: auto dataseg object682 ULONG ulDebugOfs; // 98: debug info ofs683 ULONG ulDebugLen; // 9c: debug info length684 ULONG ulInstancePrelCnt; // a0: instance preload count685 ULONG ulInstanceDemdCnt; // a0: instance demand count686 ULONG ulHeapSize16; // a8: heap size (16-bit)687 ULONG ulStackSize; // ac: stack size688 } LXHEADER, *PLXHEADER;689 690 /*691 *@@ PEHEADER:692 * portable executable (PE) header format,693 * which comes after the DOS header in the694 * EXE file (at DOSEXEHEADER.ulNewHeaderOfs).695 *696 *@@added V0.9.10 (2001-04-08) [lafaix]697 */698 699 typedef struct _PEHEADER700 {701 // standard header702 ULONG ulSignature; // 00: 'P', 'E', 0, 0703 USHORT usCPU; // 04: CPU type704 USHORT usObjCount; // 06: number of object entries705 ULONG ulTimeDateStamp; // 08: store the time and date the706 // file was created or modified707 // by the linker708 ULONG ulReserved1; // 0c: reserved709 ULONG ulReserved2; // 10: reserved710 USHORT usHeaderSize; // 14: number of remaining bytes after711 // usImageFlags712 USHORT usImageFlags; // 16: flags bits for the image713 714 // optional header (always present in valid Win32 files)715 USHORT usReserved3; // 18: reserved716 USHORT usLinkerMajor; // 1a: linker major version number717 USHORT usLinkerMinor; // 1c: linker minor version number718 USHORT usReserved4; // 1e: reserved719 ULONG ulReserved5; // 20: reserved720 ULONG ulReserved6; // 24: reserved721 ULONG ulEntryPointRVA; // 28: entry point relative virtual address722 ULONG ulReserved7; // 2c: reserved723 ULONG ulReserved8; // 30: reserved724 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: reserved734 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: reserved744 ULONG ulInterestingRVACount;// 74:745 ULONG aulRVASize[1]; // 78: array of RVA/Size entries746 } PEHEADER, *PPEHEADER;747 748 // additional LX structures749 750 /*751 *@@ RESOURCETABLEENTRY:752 * LX resource table entry.753 *754 *@@added V0.9.16 (2001-12-08) [umoeller]755 */756 757 typedef struct _RESOURCETABLEENTRY // rsrc32758 {759 unsigned short type; // Resource type760 unsigned short name; // Resource name761 unsigned long cb; // Resource size762 unsigned short obj; // Object number763 unsigned long offset; // Offset within object764 } 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_obj774 {775 unsigned long o32_size; // Object virtual size776 unsigned long o32_base; // Object base virtual address777 unsigned long o32_flags; // Attribute flags778 unsigned long o32_pagemap; // Object page map index779 unsigned long o32_mapsize; // Number of entries in object page map780 unsigned long o32_reserved; // Reserved781 } OBJECTTABLEENTRY;782 783 /*784 *@@ OBJECTPAGETABLEENTRY:785 * LX object _page_ table entry, sometimes786 * referred to as map entry.787 *788 *@@added V0.9.16 (2001-12-08) [umoeller]789 */790 791 typedef struct _OBJECTPAGETABLEENTRY // o32_map792 {793 unsigned long o32_pagedataoffset; // file offset of page794 unsigned short o32_pagesize; // # of real bytes of page data795 unsigned short o32_pageflags; // Per-Page attributes796 } 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 _LXITER806 {807 unsigned short LX_nIter; // number of iterations808 unsigned short LX_nBytes; // number of bytes809 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 _OS2NERESTBLENTRY820 {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 entry833 {834 unsigned short ns_sector; // File sector of start of segment835 unsigned short ns_cbseg; // Number of bytes in file836 unsigned short ns_flags; // Attribute flags837 unsigned short ns_minalloc; // Minimum allocation in bytes838 } OS2NESEGMENT, *POS2NESEGMENT;839 840 #pragma pack()841 842 // object/segment flags (in NE and LX)843 #define OBJWRITE 0x0002L // Writeable Object844 #define OBJDISCARD 0x0010L // Object is Discardable845 #define OBJSHARED 0x0020L // Object is Shared846 #define OBJPRELOAD 0x0040L // Object has preload pages847 848 // resource flags849 #define RNMOVE 0x0010 // Moveable resource850 #define RNPURE 0x0020 // Pure (read-only) resource851 #define RNPRELOAD 0x0040 // Preloaded resource852 #define RNDISCARD 0xF000 // Discard priority level for resource853 854 // EXE format855 #define EXEFORMAT_OLDDOS 1856 #define EXEFORMAT_NE 2857 #define EXEFORMAT_PE 3858 #define EXEFORMAT_LX 4859 #define EXEFORMAT_TEXT_BATCH 5860 #define EXEFORMAT_TEXT_CMD 6 // REXX or plain OS/2 batch861 #define EXEFORMAT_COM 7 // added V0.9.16 (2002-01-04) [umoeller]862 863 // target OS (in NE and LX)864 #define EXEOS_DOS3 1865 #define EXEOS_DOS4 2 // there is a flag for this in NE866 #define EXEOS_OS2 3867 #define EXEOS_WIN16 4868 #define EXEOS_WIN386 5 // according to IBM, there are flags869 // for this both in NE and LX870 #define EXEOS_WIN32 6871 872 #ifndef __STRIP_DOWN_EXECUTABLE__873 // for mini stubs in warpin, which has its own874 // implementation of this875 876 /*877 *@@ EXECUTABLE:878 * structure used with all the doshExec*879 * functions.880 */881 882 typedef struct _EXECUTABLE883 {884 // executable opened by doshOpen885 PXFILE pFile;886 887 /* All the following fields are set by888 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_NE899 PNEHEADER pNEHeader;900 ULONG cbNEHeader;901 902 // Linear Executable (LX) header, if ulExeFormat == EXEFORMAT_LX903 PLXHEADER pLXHeader;904 ULONG cbLXHeader;905 906 // Portable Executable (PE) header, if ulExeFormat == EXEFORMAT_PE907 PPEHEADER pPEHeader;908 ULONG cbPEHeader;909 910 // module analysis (always set):911 ULONG ulExeFormat;912 // one of:913 // EXEFORMAT_OLDDOS 1914 // EXEFORMAT_NE 2915 // EXEFORMAT_PE 3916 // EXEFORMAT_LX 4917 // EXEFORMAT_TEXT_BATCH 5918 // EXEFORMAT_TEXT_CMD 6919 // EXEFORMAT_COM 7920 921 BOOL fLibrary, // TRUE if this is a DLL922 f32Bits; // TRUE if this a 32-bits module923 924 ULONG ulOS;925 // target operating system as flagged in one of926 // the EXE headers; one of:927 // EXEOS_DOS3 1928 // EXEOS_DOS4 2 // there is a flag for this in NE929 // EXEOS_OS2 3930 // EXEOS_WIN16 4931 // EXEOS_WIN386 5 // according to IBM, there are flags932 // for this both in NE and LX933 // EXEOS_WIN32 6934 935 /* The following fields are only set after936 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 following949 // 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 doshLoadLXMaps960 BOOL fLXMapsLoaded; // TRUE after doshLoadLXMaps961 RESOURCETABLEENTRY *pRsTbl; // pLXHeader->ulResTblCnt962 OBJECTTABLEENTRY *pObjTbl; // pLXHeader->ulObjCount963 OBJECTPAGETABLEENTRY *pObjPageTbl; // pLXHeader->ulPageCount964 965 // the following fields are set after doshLoadOS2NEMaps966 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 _FSYSMODULE983 {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 _FSYSFUNCTION1000 {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 91013 #define WINRT_BITMAP 21014 #define WINRT_CURSOR 11015 #define WINRT_DIALOG 51016 #define WINRT_FONT 81017 #define WINRT_FONTDIR 71018 #define WINRT_ICON 31019 #define WINRT_MENU 41020 #define WINRT_RCDATA 101021 #define WINRT_STRING 61022 1023 /*1024 *@@ FSYSRESOURCE:1025 *1026 *@@added V0.9.7 (2000-12-18) [lafaix]1027 */1028 1029 typedef struct _FSYSRESOURCE1030 {1031 ULONG ulID; // resource ID1032 ULONG ulType; // resource type1033 ULONG ulSize; // resource size in bytes1034 ULONG ulFlag; // resource flags1035 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 1054 473 APIRET doshSearchPath(PCSZ pcszPath, 1055 474 PCSZ pcszFile, … … 1062 481 PCSZ *papcszExtensions, 1063 482 ULONG cExtensions); 1064 #endif1065 483 1066 484 /******************************************************************** -
trunk/include/helpers/standards.h
r123 r129 106 106 #define ARRAYITEMCOUNT(array) sizeof(array) / sizeof(array[0]) 107 107 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 108 118 #endif 109 119 -
trunk/include/helpers/xstring.h
r113 r129 91 91 typedef XSTRINITSET *PXSTRINITSET; 92 92 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 96 113 97 114 void XWPENTRY xstrClear(PXSTRING pxstr); -
trunk/src/helpers/apps.c
r127 r129 1200 1200 ProgDetails.pszParameters = strParamsPatched.psz; 1201 1201 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: ")); 1210 1210 { 1211 1211 PSZ pszThis = ProgDetails.pszEnvironment; 1212 1212 while (pszThis && *pszThis) 1213 1213 { 1214 _Pmpf((" \"%s\"", pszThis));1214 _Pmpf((" \"%s\"", pszThis)); 1215 1215 pszThis += strlen(pszThis) + 1; 1216 1216 } 1217 1217 } 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:", 1220 1221 ProgDetails.swpInitial.fl, 1221 1222 ProgDetails.swpInitial.x, … … 1223 1224 ProgDetails.swpInitial.cx, 1224 1225 ProgDetails.swpInitial.cy)); 1225 _Pmpf((" behind = %d, hwnd = %d, res1 = %d, res2 = %d",1226 _Pmpf((" behind = %d, hwnd = %d, res1 = %d, res2 = %d", 1226 1227 ProgDetails.swpInitial.hwndInsertBehind, 1227 1228 ProgDetails.swpInitial.hwnd, 1228 1229 ProgDetails.swpInitial.ulReserved1, 1229 1230 ProgDetails.swpInitial.ulReserved2)); 1230 */ 1231 1232 if (pszFailingName) 1233 strhncpy0(pszFailingName, ProgDetails.pszExecutable, cbFailingName); 1231 1234 1232 1235 /* if (WinMessageBox(HWND_DESKTOP, … … 1236 1239 0, 1237 1240 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 */ 1256 1244 { 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! 1261 1258 { 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))) 1263 1267 { 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; 1307 1345 } 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 */ 1338 1347 } 1339 1348 } -
trunk/src/helpers/cnrh.c
r123 r129 168 168 BOOL fDrawLines) // in: if TRUE, we'll draw lines around the columns 169 169 { 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 } 185 188 } 186 189 -
trunk/src/helpers/configsys.c
r123 r129 92 92 93 93 if (!(arc = doshLoadTextFile(pcszFile, 94 ppszContents))) 94 ppszContents, 95 NULL))) 95 96 { 96 97 // convert all \r\n to \n -
trunk/src/helpers/dosh.c
r127 r129 1814 1814 = pFile->cbCurrent 1815 1815 = *pcbFile; 1816 1817 pFile->pszFilename = strdup(pcszFilename); 1816 1818 } 1817 1819 else … … 1878 1880 * method). 1879 1881 * 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 * 1880 1893 *@@added V0.9.13 (2001-06-14) [umoeller] 1881 1894 *@@changed V0.9.16 (2001-12-18) [umoeller]: now with XFILE, and always using FILE_BEGIN … … 1895 1908 *pcb = 0; 1896 1909 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 ) 1901 1920 { 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 } 1907 2034 } 1908 2035 … … 2003 2130 cb, 2004 2131 &cbWritten))) 2132 { 2005 2133 pFile->cbCurrent += cbWritten; 2134 // invalidate the cache 2135 FREE(pFile->pbCache); 2136 } 2006 2137 2007 2138 doshUnlockFile(pFile); … … 2137 2268 *ppFile = NULL; 2138 2269 2270 FREE(pFile->pbCache); 2271 FREE(pFile->pszFilename); 2272 2139 2273 if (pFile->hf) 2140 2274 { … … 2162 2296 * buffer (or NULL upon errors). 2163 2297 * 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 * 2164 2302 * This returns the APIRET of DosOpen and DosRead. 2165 2303 * If any error occured, no buffer was allocated. … … 2168 2306 * 2169 2307 *@@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 2312 APIRET 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 /* 2175 2354 ULONG ulSize, 2176 2355 ulBytesRead = 0, … … 2210 2389 // set output buffer pointer 2211 2390 *ppszContent = pszContent; 2391 2392 if (pcbRead) 2393 *pcbRead = ulBytesRead + 1; 2212 2394 } 2213 2395 … … 2217 2399 DosClose(hFile); 2218 2400 } 2401 */ 2219 2402 2220 2403 return (arc); … … 2819 3002 * versions. I believe it came up with some Warp 4 2820 3003 * 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). 2824 3005 * 2825 3006 * This properly initializes the internal counters … … 2835 3016 * which have exactly cProcessors array items. 2836 3017 * 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 * 2837 3023 * Call doshPerfClose to clean up resources allocated 2838 3024 * by this function. 2839 3025 * 3026 * For more sample code, take a look at the "Pulse" widget 3027 * in the XWorkplace sources (src\xcenter\w_pulse.c). 3028 * 2840 3029 * Example code: 2841 3030 * 2842 3031 + PDOSHPERFSYS pPerf = NULL; 2843 + APIRET arc = doshPerfOpen(&pPerf);2844 + if ( arc == NO_ERROR)3032 + APIRET arc; 3033 + if (!(arc = arc = doshPerfOpen(&pPerf))) 2845 3034 + { 2846 + // this should really be in a timer 3035 + // this should really be in a timer, 3036 + // e.g. once per second 2847 3037 + ULONG ulCPU; 2848 + arc = doshPerfGet(&pPerf); 2849 + // go thru all CPUs 2850 + for (ulCPU = 0; ulCPU < pPerf->cProcessors; ulCPU++) 3038 + if (!(arc = doshPerfGet(&pPerf))) 2851 3039 + { 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 + } 2854 3046 + } 2855 +2856 + ...2857 3047 + 2858 3048 + // clean up … … 3014 3204 3015 3205 // avoid division by zero 3016 double dTimeDelta = (dTime - *pdTimePrevThis);3017 if (dTimeDelta )3206 double dTimeDelta; 3207 if (dTimeDelta = (dTime - *pdTimePrevThis)) 3018 3208 { 3019 3209 pPerfSys->palLoads[ul] … … 3060 3250 { 3061 3251 APIRET arc = NO_ERROR; 3062 PDOSHPERFSYS pPerfSys = *ppPerfSys; 3063 if (!pPerfSys) 3252 PDOSHPERFSYS pPerfSys; 3253 if ( (!ppPerfSys) 3254 || (!(pPerfSys = *ppPerfSys)) 3255 ) 3064 3256 arc = ERROR_INVALID_PARAMETER; 3065 3257 else -
trunk/src/helpers/dosh2.c
r127 r129 350 350 351 351 return (arc); // V0.9.9 (2001-04-04) [umoeller] 352 }353 354 /*355 *@@category: Helpers\Control program helpers\Executable info356 * these functions can retrieve BLDLEVEL information,357 * imported modules information, exported functions information,358 * and resources information from any executable module. See359 * doshExecOpen.360 */361 362 /********************************************************************363 *364 * Executable functions365 *366 ********************************************************************/367 368 /*369 *@@ doshExecOpen:370 * this opens the specified executable file371 * (which can be an .EXE, .COM, .DLL, or372 * driver file) for use with the other373 * doshExec* functions.374 *375 * If no error occurs, NO_ERROR is returned376 * and a pointer to a new EXECUTABLE structure377 * is stored in *ppExec. Consider this pointer a378 * handle and pass it to doshExecClose to clean379 * up.380 *381 * If NO_ERROR is returned, all the fields through382 * ulOS are set in EXECUTABLE. The psz* fields383 * which follow afterwards require an additional384 * call to doshExecQueryBldLevel.385 *386 * NOTE: If NO_ERROR is returned, the executable387 * file has been opened by this function. It will388 * only be closed when you call doshExecClose.389 *390 * If errors occur, this function returns the391 * following error codes:392 *393 * -- ERROR_NOT_ENOUGH_MEMORY: malloc() failed.394 *395 * -- ERROR_INVALID_EXE_SIGNATURE (191): header is396 * neither plain DOS, nor NE, nor LX, nor PE.397 * The given file probably isn't even an398 * executable. This you will get if you399 * pass in COM, BAT, or CMD files.400 *401 * -- ERROR_BAD_EXE_FORMAT (193): header was402 * recognized, but the header data was403 * not understood.404 *405 * -- ERROR_INVALID_PARAMETER: ppExec is NULL.406 *407 * plus those of DosOpen, DosSetFilePtr, and408 * DosRead.409 *410 * The following executable types are supported411 * (see EXECUTABLE for details):412 *413 * -- Plain DOS 3.x executable without new header.414 *415 * -- New Executable (NE), used by Win16 and416 * 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 executable425 * then starts directly with the NE or LX header.426 * I am not sure whether PE supports such things427 * as well... if so, it should be supported too.428 *429 * @@todo:430 *431 * win95 \WINDOWS\extract.exe is NE with a non-standard format432 * win16 \WINDOWS\EXPAND.EXE433 * win16 \WINDOWS\MSD.EXE"434 *435 *@@added V0.9.0 [umoeller]436 *@@changed V0.9.1 (2000-02-13) [umoeller]: fixed 32-bits flag437 *@@changed V0.9.7 (2000-12-20) [lafaix]: fixed ulNewHeaderOfs438 *@@changed V0.9.10 (2001-04-08) [lafaix]: added PE support439 *@@changed V0.9.10 (2001-04-08) [umoeller]: now setting ppExec only if NO_ERROR is returned440 *@@changed V0.9.12 (2001-05-03) [umoeller]: added support for NOSTUB newstyle executables441 *@@changed V0.9.16 (2001-12-08) [umoeller]: now using OPEN_SHARE_DENYWRITE442 *@@changed V0.9.16 (2001-12-08) [umoeller]: fLibrary was never set, works for LX and NE now443 *@@changed V0.9.16 (2001-12-08) [umoeller]: some speed optimizations, changed some return codes444 *@@changed V0.9.16 (2002-01-04) [umoeller]: added fixes for COM, BAT, CMD extensions445 */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 extensions468 // 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 the474 // .COM executable format, so for this one case,475 // let OS/2 determine what we have here476 ULONG ulDosAppType = 0;477 if (!(arc = DosQueryAppType((PSZ)pcszExecutable, &ulDosAppType)))478 {479 if (ulDosAppType & FAPPTYP_DOS) // 0x20480 pExec->ulOS = EXEOS_DOS3;481 else482 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 else498 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 header512 if (!(pExec->pDosExeHeader = (PDOSEXEHEADER)malloc(sizeof(DOSEXEHEADER))))513 arc = ERROR_NOT_ENOUGH_MEMORY;514 else515 {516 pExec->cbDosExeHeader = sizeof(DOSEXEHEADER);517 if (!(arc = doshReadAt(pFile,518 0,519 &pExec->cbDosExeHeader, // in/out520 (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 header526 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 are532 // drivers which were built with NOSTUB, and533 // the exe image starts out with the NE or LX534 // image directly535 fLoadNewHeader = TRUE;536 // ulNewHeaderOfs is 0 now537 538 // remove the DOS header info, since we have none539 // V0.9.12 (2001-05-03) [umoeller]540 FREE(pExec->pDosExeHeader);541 }542 else543 {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 else552 {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 header564 // was found) or pDosExeHeader->ulNewHeaderOfs565 // V0.9.12 (2001-05-03) [umoeller]566 ULONG cbRead;567 PBYTE pbHeader;568 569 // now, we used to read in the first two chars570 // to check out if we have PE or LX or NE and571 // then read the header accordingly... but572 // that wasn't terribly efficient. So load573 // a chunk of data and then do a realloc()574 // instead.575 576 // take the largest of LXHEADER and NEHEADER and PEHEADER577 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 else605 {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.EXE619 )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 else630 {631 pExec->pLXHeader = (PLXHEADER)realloc(pbHeader,632 sizeof(LXHEADER));633 // read in LX header634 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 else652 {653 // PE has a standard header of 24 bytes654 // plus an extended header, so check what655 // we've got656 ULONG cbPE = sizeof(PEHEADER); // 24657 // + ((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, so667 // go for the next chunk, if this is more668 // than we have in PEHEADER669 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 else686 {687 arc = ERROR_BAD_EXE_FORMAT;688 FREE(pExec->pPEHeader);689 }690 }691 else692 _Pmpf((" already got extended header"));693 */694 }695 }696 else697 {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 system706 // (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 up738 doshExecClose(&pExec);739 else740 *ppExec = pExec;741 742 return (arc);743 }744 745 /*746 *@@ ParseBldLevel:747 * called from doshExecQueryBldLevel to parse748 * the BLDLEVEL string.749 *750 * On entry, caller has copied the string into751 * pExec->pszDescription. The string is752 * null-terminated.753 *754 * The BLDLEVEL string comes in two flavors.755 *756 * -- The standard format is:757 *758 + @#VENDOR:VERSION#@DESCRIPTION759 *760 * DESCRIPTION can have leading spaces, but761 * need to have them.762 *763 * -- However, there is an extended version764 * in that the DESCRIPTION field is split765 * up even more. The marker for this seems766 * to be that the description starts out767 * with "##1##".768 *769 + ##1## DATETIME BUILDMACHINE:ASD:LANG:CTRY:REVISION:UNKNOWN:FIXPAK@@DESCRIPTION770 *771 * The problem is that the DATETIME field comes772 * in several flavors. IBM uses things like773 *774 + "Thu Nov 30 15:30:37 2000 BWBLD228"775 *776 * while DANIS506.ADD has777 *778 + "15.12.2000 18:22:57 Nachtigall"779 *780 * Looks like the date/time string is standardized781 * 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 support785 */786 787 VOID ParseBldLevel(PEXECUTABLE pExec)788 {789 const char // *pStartOfAuthor = 0,790 *pStartOfVendor = 0;791 792 // @#VENDOR:VERSION#@ DESCRIPTION793 // but skip the first byte, which has the string length794 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 string811 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 beast819 const char *p = pStartOfInfo + 5;820 821 // get build date/time822 if (strlen(p) > 24)823 {824 // date/time seems to be fixed 24 chars in length825 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-separated835 // strings, first of which is the836 // build machine;837 // skip leading spaces838 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->pszFixpak852 };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 else868 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 else885 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 now904 // -- if we parse the extended DESCRIPTION above,905 // pStartOfInfo points to after @@ now906 // -- if we had an error, pStartOfInfo is NULL907 if (pStartOfInfo)908 {909 // add the regular DESCRIPTION then910 // skip leading spaces in info string911 while (*pStartOfInfo == ' ')912 pStartOfInfo++;913 if (*pStartOfInfo) // V0.9.9 (2001-04-04) [umoeller]914 // and copy until end of string915 pExec->pszInfo = strdup(pStartOfInfo);916 }917 }918 }919 }920 }921 922 /*923 *@@ doshExecQueryBldLevel:924 * this retrieves buildlevel information for an925 * LX or NE executable previously opened with926 * doshExecOpen.927 *928 * BuildLevel information must be contained in the929 * DESCRIPTION field of an executable's module930 * definition (.DEF) file. In order to be readable931 * by BLDLEVEL.EXE (which ships with OS/2), this932 * string must have the following format:933 *934 + Description '@#AUTHOR:VERSION#@ DESCRIPTION'935 *936 * Example:937 *938 + Description '@#Ulrich Mller:0.9.0#@ XWorkplace Sound Support Module'939 *940 * The "Description" entry always ends up as the941 * very first entry in the non-resident name table942 * in LX and NE executables. So this is what we retrieve943 * here.944 *945 * If the first entry in that table exists, NO_ERROR is946 * returned and at least the pszDescription field in947 * EXECUTABLE is set to that information.948 *949 * If that string is in IBM BLDLEVEL format, the string950 * 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 Mller"954 + pszVersion = "0.9.0"955 + pszInfo = "XWorkplace Sound Support Module"956 *957 * If that string is not in BLDLEVEL format, only pszDescription958 * will be set. The other fields remain NULL.959 *960 * This returns the following errors:961 *962 * -- ERROR_INVALID_PARAMETER: pExec invalid963 *964 * -- ERROR_INVALID_EXE_SIGNATURE (191): pExec is not in LX or NE format965 *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 supported974 *@@changed V0.9.1 (99-12-06): fixed memory leak975 *@@changed V0.9.9 (2001-04-04) [umoeller]: added more error checking976 *@@changed V0.9.12 (2001-05-18) [umoeller]: extracted ParseBldLevel977 */978 979 APIRET doshExecQueryBldLevel(PEXECUTABLE pExec)980 {981 APIRET arc = NO_ERROR;982 983 if (!pExec)984 arc = ERROR_INVALID_PARAMETER;985 else986 {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 table995 if (pExec->pLXHeader == NULL)996 arc = ERROR_INVALID_DATA;997 else if (pExec->pLXHeader->ulNonResdNameTblOfs == 0)998 arc = ERROR_INVALID_DATA;999 else1000 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 table1006 if (pExec->pNEHeader == NULL)1007 arc = ERROR_INVALID_DATA;1008 else if (pExec->pNEHeader->ulNonResdTblOfs == 0)1009 arc = ERROR_INVALID_DATA;1010 else1011 ulNRNTOfs = pExec->pNEHeader->ulNonResdTblOfs;1012 }1013 else1014 // neither LX nor NE: stop1015 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 table1025 // (from LX header)1026 if (!(arc = DosSetFilePtr(pFile->hf, // file is still open1027 ulNRNTOfs, // ofs determined above1028 FILE_BEGIN,1029 &ulLocal)))1030 {1031 // allocate memory as necessary1032 PSZ pszNameTable = (PSZ)malloc(2001); // should suffice, because each entry1033 // may only be 255 bytes in length1034 if (!pszNameTable)1035 arc = ERROR_NOT_ENOUGH_MEMORY;1036 else1037 {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 else1047 {1048 // now copy the string, which is in Pascal format1049 pExec->pszDescription = (PSZ)malloc((*pszNameTable) + 1); // addt'l null byte1050 if (!pExec->pszDescription)1051 arc = ERROR_NOT_ENOUGH_MEMORY;1052 else1053 {1054 memcpy(pExec->pszDescription,1055 pszNameTable + 1, // skip length byte1056 *pszNameTable); // length byte1057 // terminate string1058 *(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 all1077 * imported modules.1078 *1079 * *pcModules receives the # of items in the array (not the1080 * array size!). Use doshFreeImportedModules to clean up.1081 *1082 * This returns a standard OS/2 error code, which might be1083 * any of the codes returned by DosSetFilePtr and DosRead.1084 * In addition, this may return:1085 *1086 * -- ERROR_NOT_ENOUGH_MEMORY1087 *1088 * -- ERROR_INVALID_EXE_SIGNATURE: exe is in a format other1089 * than LX or NE, which is not understood by this function.1090 *1091 * Even if NO_ERROR is returned, the array pointer might still1092 * 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 APIRET1096 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code1097 *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support1098 *@@changed V0.9.10 (2001-04-13) [lafaix]: removed 127 characters limit1099 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support1100 */1101 1102 APIRET doshExecQueryImportedModules(PEXECUTABLE pExec,1103 PFSYSMODULE *ppaModules, // out: modules array1104 PULONG pcModules) // out: array item count1105 {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->ulImportModTblOfs1143 + 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 name1152 ENSURE_SAFE(DosRead(hfExe, &bLen, 1, &ulDummy));1153 1154 // reading the module name1155 ENSURE_SAFE(DosRead(hfExe,1156 paModules[i].achModuleName,1157 bLen,1158 &ulDummy));1159 1160 // module names are not null terminated, so we must1161 // do it now1162 paModules[i].achModuleName[bLen] = 0;1163 } // end for1164 }1165 } // end LX1166 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 offsets1188 // relative to the import table; we hence read1189 // the offset in the module reference table, and1190 // then we read the name in the import table1191 1192 ENSURE_SAFE(DosSetFilePtr(hfExe,1193 pExec->pNEHeader->usModRefTblOfs1194 + 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->usImportTblOfs1203 + 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 for1217 }1218 } // end NE1219 else1220 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller]1221 1222 // no error: output data1223 *ppaModules = paModules;1224 *pcModules = cModules;1225 1226 ENSURE_FINALLY;1227 // if we had an error above, clean up1228 free(paModules);1229 ENSURE_END;1230 }1231 else1232 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 are1255 * 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 APIRET1259 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code1260 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support1261 */1262 1263 APIRET ScanLXEntryTable(PEXECUTABLE pExec,1264 PFSYSFUNCTION paFunctions,1265 PULONG pcEntries) // out: entry table entry count; ptr can be NULL1266 {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->ulEntryTblOfs1281 + 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 table1295 break;1296 1297 ENSURE(DosRead(hfExe, &bType, 1, &ulDummy));1298 1299 switch (bType & 0x7F)1300 {1301 /*1302 * unused entries1303 *1304 */1305 1306 case 0:1307 usOrdinal += bCnt;1308 break;1309 1310 /*1311 * 16-bit entries1312 *1313 * the bundle type is followed by the object number1314 * and by bCnt bFlag+usOffset entries1315 *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 for1347 break;1348 1349 /*1350 * 286 call gate entries1351 *1352 * the bundle type is followed by the object number1353 * and by bCnt bFlag+usOffset+usCallGate entries1354 *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 for1386 break;1387 1388 /*1389 * 32-bit entries1390 *1391 * the bundle type is followed by the object number1392 * and by bCnt bFlag+ulOffset entries1393 *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 for1424 break;1425 1426 /*1427 * forwarder entries1428 *1429 * the bundle type is followed by a reserved word1430 * and by bCnt bFlag+usModOrd+ulOffsOrdNum entries1431 *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 for1457 break;1458 1459 /*1460 * unknown bundle type1461 *1462 * we don't know how to handle this bundle, so we must1463 * stop parsing the entry table here (as we don't know the1464 * bundle size); if paFunctions is not null, we fill it with1465 * informative data1466 */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 // whatever1481 // 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 are1496 * 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 APIRET1500 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code1501 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support1502 */1503 1504 APIRET ScanNEEntryTable(PEXECUTABLE pExec,1505 PFSYSFUNCTION paFunctions,1506 PULONG pcEntries) // out: entry table entry count; ptr can be NULL1507 {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->usEntryTblOfs1522 + 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 table1536 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 entry1555 paFunctions[usCurrent].achFunctionName[0] = 0;1556 }1557 usCurrent++;1558 }1559 1560 usOrdinal++;1561 1562 if (bType == 0xFF)1563 {1564 // moveable segment1565 ENSURE(DosSetFilePtr(hfExe,1566 5,1567 FILE_CURRENT,1568 &ulDummy));1569 }1570 else1571 {1572 // fixed segment or constant (0xFE)1573 ENSURE(DosSetFilePtr(hfExe,1574 2,1575 FILE_CURRENT,1576 &ulDummy));1577 }1578 1579 } // end for1580 }1581 else1582 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 helper1594 *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 else1610 return (0);1611 }1612 1613 /*1614 *@@ ScanNameTable:1615 * scans a resident or non-resident name table, and fills the1616 * appropriate paFunctions entries when it encounters exported1617 * 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 special1623 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET1624 *@@changed V0.9.9 (2001-04-05) [lafaix]: removed the 127 char limit1625 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code1626 */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 table1648 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 all1673 * exported functions.1674 *1675 * *pcFunctions receives the # of items in the array (not the1676 * array size!). Use doshFreeExportedFunctions to clean up.1677 *1678 * Note that the returned array only contains entry for exported1679 * functions. Empty export entries are _not_ included.1680 *1681 * This returns a standard OS/2 error code, which might be1682 * any of the codes returned by DosSetFilePtr and DosRead.1683 * In addition, this may return:1684 *1685 * -- ERROR_NOT_ENOUGH_MEMORY1686 *1687 * -- ERROR_INVALID_EXE_SIGNATURE: exe is in a format other1688 * than LX or NE, which is not understood by this function.1689 *1690 * -- If ERROR_INVALID_LIST_FORMAT is returned, the format of an1691 * export entry wasn't understood here.1692 *1693 * Even if NO_ERROR is returned, the array pointer might still1694 * 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 APIRET1698 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code1699 *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support1700 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support1701 */1702 1703 APIRET doshExecQueryExportedFunctions(PEXECUTABLE pExec,1704 PFSYSFUNCTION *ppaFunctions, // out: functions array1705 PULONG pcFunctions) // out: array item count1706 {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 executable1730 1731 // the number of exported entry points is not stored1732 // in the executable header; we have to count them in1733 // the entry table1734 1735 ENSURE(ScanLXEntryTable(pExec, NULL, &cFunctions));1736 1737 // we now have the number of exported entries; let us1738 // build them1739 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 bad1749 // 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 entries1754 1755 ENSURE_SAFE(DosSetFilePtr(hfExe,1756 pExec->pLXHeader->ulResdNameTblOfs1757 + 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 executable1777 1778 // here too the number of exported entry points1779 // is not stored in the executable header; we1780 // have to count them in the entry table1781 1782 ENSURE(ScanNEEntryTable(pExec, NULL, &cFunctions));1783 1784 // we now have the number of exported entries; let us1785 // build them1786 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 bad1797 // 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 entries1802 1803 ENSURE_SAFE(DosSetFilePtr(hfExe,1804 pExec->pNEHeader->usResdNameTblOfs1805 + 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 else1823 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller]1824 1825 // no error: output data1826 *ppaFunctions = paFunctions;1827 *pcFunctions = cFunctions;1828 1829 ENSURE_FINALLY;1830 // if we had an error above, clean up1831 free(paFunctions);1832 ENSURE_END;1833 }1834 else1835 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 all1857 * available resources in the module.1858 *1859 * *pcResources receives the no. of items in the array1860 * (not the array size!). Use doshExecFreeResources to clean up.1861 *1862 * This returns a standard OS/2 error code, which might be1863 * any of the codes returned by DosSetFilePtr and DosRead.1864 * In addition, this may return:1865 *1866 * -- ERROR_NOT_ENOUGH_MEMORY1867 *1868 * -- ERROR_INVALID_EXE_SIGNATURE: exe is in a format other1869 * than LX or NE, which is not understood by this function.1870 *1871 * Even if NO_ERROR is returned, the array pointer might still1872 * 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 APIRET1876 *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support1877 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support1878 */1879 1880 APIRET doshExecQueryResources(PEXECUTABLE pExec, // in: executable from doshExecOpen1881 PFSYSRESOURCE *ppaResources, // out: res's array1882 PULONG pcResources) // out: array item count1883 {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 Entry1910 {1911 unsigned short type; // Resource type1912 unsigned short name; // Resource name1913 unsigned long cb; // Resource size1914 unsigned short obj; // Object number1915 unsigned long offset; // Offset within object1916 } rs;1917 1918 struct o32_obj // Flat .EXE object table entry1919 {1920 unsigned long o32_size; // Object virtual size1921 unsigned long o32_base; // Object base virtual address1922 unsigned long o32_flags; // Attribute flags1923 unsigned long o32_pagemap; // Object page map index1924 unsigned long o32_mapsize; // Number of entries in object page map1925 unsigned long o32_reserved; // Reserved1926 } 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->ulResTblOfs1942 + 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 Object1954 // number. Will be filled1955 // with resource flag1956 // later.1957 }1958 1959 for (i = 0; i < cResources; i++)1960 {1961 ULONG ulOfsThis = pLXHeader->ulObjTblOfs1962 + 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 ? 01975 : RNPURE);1976 paResources[i].ulFlag |= ((ot.o32_flags & OBJDISCARD)1977 ? 40961978 : 0);1979 paResources[i].ulFlag |= ((ot.o32_flags & OBJSHARED)1980 ? RNMOVE1981 : 0);1982 paResources[i].ulFlag |= ((ot.o32_flags & OBJPRELOAD)1983 ? RNPRELOAD1984 : 0);1985 } // end for1986 } // 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 entry2002 {2003 unsigned short ns_sector; // File sector of start of segment2004 unsigned short ns_cbseg; // Number of bytes in file2005 unsigned short ns_flags; // Attribute flags2006 unsigned short ns_minalloc; // Minimum allocation in bytes2007 } 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 types2021 2022 ENSURE_SAFE(DosSetFilePtr(hfExe,2023 pNEHeader->usResTblOfs2024 + 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 flags2037 2038 for (i = 0; i < cResources; i++)2039 {2040 ENSURE_SAFE(DosSetFilePtr(hfExe,2041 ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller]2042 + pNEHeader->usSegTblOfs2043 + (sizeof(ns)2044 * ( pNEHeader->usSegTblEntries2045 - pNEHeader->usResSegmCount2046 + 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 else2062 {2063 // 16-bit Windows executable2064 USHORT usAlignShift;2065 ULONG ulDummy;2066 2067 ENSURE(DosSetFilePtr(hfExe,2068 pNEHeader->usResTblOfs2069 + 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 table2104 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->usResTblOfs2123 + 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 table2157 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 yet2187 // !!! 15th bit is used to denotes strings2188 // !!! 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 else2201 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 up2208 free(paResources);2209 ENSURE_END;2210 }2211 else2212 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 given2233 * 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 called2244 * by doshExecOpen to save time, since the LX2245 * maps are not needed for all the other exe2246 * 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_PARAMETER2254 *2255 * -- ERROR_INVALID_EXE_SIGNATURE: pExec does2256 * not specify an LX executable.2257 *2258 * -- ERROR_NO_DATA: at least one of the structs2259 * does not exist.2260 *2261 * -- ERROR_NOT_ENOUGH_MEMORY2262 *2263 * plus the error codes of doshReadAt.2264 *2265 * Call doshFreeLXMaps to clean up explicitly, but2266 * 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 else2287 {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 table2297 if ( (!(arc = doshAllocArray(pLXHeader->ulResTblCnt,2298 sizeof(RESOURCETABLEENTRY),2299 (PBYTE*)&pExec->pRsTbl,2300 &cb)))2301 && (!(arc = doshReadAt(pFile,2302 pLXHeader->ulResTblOfs2303 + ulNewHeaderOfs,2304 &cb,2305 (PBYTE)pExec->pRsTbl)))2306 )2307 {2308 // object table2309 if ( (!(arc = doshAllocArray(pLXHeader->ulObjCount,2310 sizeof(OBJECTTABLEENTRY),2311 (PBYTE*)&pExec->pObjTbl,2312 &cb)))2313 && (!(arc = doshReadAt(pFile,2314 pLXHeader->ulObjTblOfs2315 + ulNewHeaderOfs,2316 &cb,2317 (PBYTE)pExec->pObjTbl)))2318 )2319 {2320 // object page table2321 if ( (!(arc = doshAllocArray(pLXHeader->ulPageCount,2322 sizeof(OBJECTPAGETABLEENTRY),2323 (PBYTE*)&pExec->pObjPageTbl,2324 &cb)))2325 && (!(arc = doshReadAt(pFile,2326 pLXHeader->ulObjPageTblOfs2327 + ulNewHeaderOfs,2328 &cb,2329 (PBYTE)pExec->pObjPageTbl)))2330 )2331 {2332 }2333 }2334 }2335 2336 if (!arc)2337 pExec->fLXMapsLoaded = TRUE;2338 else2339 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 if2365 *2366 * -- ulExeFormat == EXEFORMAT_NE and2367 *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 else2392 {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 table2402 if ( (!(arc = doshAllocArray(pNEHeader->usResSegmCount,2403 sizeof(OS2NERESTBLENTRY),2404 (PBYTE*)&pExec->paOS2NEResTblEntry,2405 &cb)))2406 && (!(arc = doshReadAt(pFile,2407 pNEHeader->usResTblOfs2408 + ulNewHeaderOfs,2409 &cb,2410 (PBYTE)pExec->paOS2NEResTblEntry)))2411 )2412 {2413 // resource segments2414 if ( (!(arc = doshAllocArray(pNEHeader->usResSegmCount,2415 sizeof(OS2NESEGMENT),2416 (PBYTE*)&pExec->paOS2NESegments,2417 &cb)))2418 && (!(arc = doshReadAt(pFile,2419 pNEHeader->usResTblOfs2420 + ulNewHeaderOfs2421 - 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 else2432 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 by2455 * 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 leaks2461 *@@changed V0.9.16 (2001-12-08) [umoeller]: changed prototype to null the pExec ptr2462 */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->pszFixpak2492 };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 loop2500 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 else2518 arc = ERROR_INVALID_PARAMETER;2519 2520 return (arc);2521 352 } 2522 353 -
trunk/src/helpers/gpih.c
r127 r129 78 78 * mentioned in the documentation, so a word is in order here. 79 79 * 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. 85 88 * 86 89 * This can be a problem with mixing Win and Gpi functions. For 87 90 * 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]). 90 92 * 91 93 * WinFillRect expects an inclusive-exclusive rectangle, so it … … 267 269 + GpiCreateLogColorTable(hps, 0, LCOLF_RGB, 0, 0, NULL); 268 270 * 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 270 272 */ 271 273 -
trunk/src/helpers/helpers_pre.in
r127 r129 59 59 $(OUTPUTDIR)\eah.obj \ 60 60 $(OUTPUTDIR)\except.obj \ 61 $(OUTPUTDIR)\exeh.obj \ 61 62 $(OUTPUTDIR)\lan.obj \ 62 63 $(OUTPUTDIR)\level.obj \ -
trunk/src/helpers/tmsgfile.c
r119 r129 154 154 155 155 if (!(arc = doshLoadTextFile(pcszMessageFile, 156 &pszContent))) 156 &pszContent, 157 NULL))) 157 158 { 158 159 // file loaded: -
trunk/src/helpers/winh.c
r113 r129 2866 2866 ULONG ulPP, // in: PP_* index 2867 2867 BOOL fInherit, // in: search parent windows too? 2868 LONG lSysColor) // in: SYSCLR_* index 2868 LONG lSysColor) // in: SYSCLR_* index or -1 2869 2869 { 2870 2870 ULONG ul, … … 3234 3234 VOID winhSleep(ULONG ulSleep) // in: sleep time in milliseconds 3235 3235 { 3236 HWND hwnd = winhCreateObjectWindow(WC_STATIC, NULL);3237 if (hwnd )3236 HWND hwnd; 3237 if (hwnd = winhCreateObjectWindow(WC_STATIC, NULL)) 3238 3238 { 3239 3239 QMSG qmsg; -
trunk/src/helpers/wphandle.c
r127 r129 375 375 376 376 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 382 386 // several handles for short name!!! 383 387 // arc = ERROR_WPH_NODE_TREEINSERT_FAILED; 384 388 385 // store PNODE in hash table 386 pHandlesBuf->NodeHashTable[pNode->usHandle] = pNew; 389 if (arc) 390 free(pNew); 391 387 392 } 388 393 … … 933 938 str.psz, 934 939 str.ulLength + 1); 940 xstrClear(&str); 935 941 } 936 942 } -
trunk/src/helpers/xstring.c
r121 r129 230 230 } 231 231 232 #ifdef __DEBUG_MALLOC_ENABLED__ 233 234 /* 235 *@@ xstrInitCopyDebug: 236 * 237 *@@added V0.9.16 (2002-01-05) [umoeller] 238 */ 239 240 void 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 232 277 /* 233 278 *@@ xstrInitCopy: … … 252 297 *@@changed V0.9.7 (2000-12-31) [umoeller]: added ulExtraAllocate 253 298 *@@changed V0.9.9 (2001-03-09) [umoeller]: added ulDelta 299 *@@changed V0.9.16 (2002-01-05) [umoeller]: use memcpy instead of strcpy 254 300 */ 255 301 … … 271 317 pxstr->cbAllocated = pxstr->ulLength + 1 + ulExtraAllocate; 272 318 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'; 274 324 275 325 pxstr->ulDelta = pxstr->cbAllocated * 10 / 100;
Note:
See TracChangeset
for help on using the changeset viewer.