Changeset 54 for trunk/src/helpers/dosh2.c
- Timestamp:
- Apr 4, 2001, 4:39:06 PM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/dosh2.c
r52 r54 255 255 BOOL brc = FALSE; 256 256 PSZ pSource = pszSource, 257 pTarget = pszTarget, 258 pszInvalid = (fIsFAT) 259 ? "*<>|+=:;,\"/\\[] " // invalid characters in FAT 260 : "*<>|:\"/\\"; // invalid characters in IFS's 257 pTarget = pszTarget; 258 259 const char *pcszInvalid = (fIsFAT) 260 ? "*<>|+=:;,\"/\\[] " // invalid characters in FAT 261 : "*<>|:\"/\\"; // invalid characters in IFS's 261 262 262 263 for (ul = 0; ul < cbSource; ul++) … … 277 278 } 278 279 // and replace invalid characters 279 if (strchr(p szInvalid, *pSource) == NULL)280 if (strchr(pcszInvalid, *pSource) == NULL) 280 281 *pTarget = *pSource; 281 282 else … … 322 323 * one will change the current drive 323 324 * also, if one is specified. 325 * 326 *@@changed V0.9.9 (2001-04-04) [umoeller]: this returned an error even if none occured, fixed 324 327 */ 325 328 326 329 APIRET doshSetCurrentDir(const char *pcszDir) 327 330 { 328 if (pcszDir) 331 APIRET arc = NO_ERROR; 332 if (!pcszDir) 333 return (ERROR_INVALID_PARAMETER); 329 334 { 330 335 if (*pcszDir != 0) … … 333 338 // drive given: 334 339 CHAR cDrive = toupper(*(pcszDir)); 335 APIRET arc;336 340 // change drive 337 341 arc = DosSetDefaultDisk( (ULONG)(cDrive - 'A' + 1) ); 338 342 // 1 = A:, 2 = B:, ... 339 if (arc != NO_ERROR)340 return (arc);341 343 } 342 344 343 return (DosSetCurrentDir((PSZ)pcszDir));345 arc = DosSetCurrentDir((PSZ)pcszDir); 344 346 } 345 return (ERROR_INVALID_PARAMETER); 347 348 return (arc); // V0.9.9 (2001-04-04) [umoeller] 346 349 } 347 350 … … 775 778 * and a pointer to a new EXECUTABLE structure 776 779 * is stored in *ppExec. Consider this pointer a 777 * handle and pass it to doshExecClose when the 778 * executable is no longer needed to free 779 * resources. 780 * handle and pass it to doshExecClose to clean 781 * up. 780 782 * 781 783 * If NO_ERROR is returned, all the fields through … … 784 786 * call to doshExecQueryBldLevel. 785 787 * 788 * NOTE: If NO_ERROR is returned, the executable 789 * file has been opened by this function. It will 790 * only be closed when you call doshExecClose. 791 * 786 792 * If errors occur, this function returns the 787 793 * following error codes: 794 * 788 795 * -- ERROR_NOT_ENOUGH_MEMORY: malloc() failed. 796 * 789 797 * -- ERROR_INVALID_EXE_SIGNATURE: specified file 790 * has no DOS EXE header. 798 * has no DOS EXE header, or it does, but 799 * the extended header is neither LX nor 800 * NE nor PE. 801 * 791 802 * -- ERROR_INVALID_PARAMETER: ppExec is NULL. 792 803 * … … 802 813 PEXECUTABLE* ppExec) 803 814 { 815 APIRET arc = NO_ERROR; 816 804 817 ULONG ulAction = 0; 805 818 HFILE hFile; 806 APIRET arc = DosOpen((PSZ)pcszExecutable, 807 &hFile, 808 &ulAction, // out: action taken 809 0, // in: new file (ignored for read-mode) 810 0, // in: new file attribs (ignored) 811 // open-flags 812 OPEN_ACTION_FAIL_IF_NEW 813 | OPEN_ACTION_OPEN_IF_EXISTS, 814 // open-mode 815 OPEN_FLAGS_FAIL_ON_ERROR // report errors to caller 816 | OPEN_FLAGS_SEQUENTIAL 817 | OPEN_FLAGS_NOINHERIT 818 | OPEN_SHARE_DENYNONE 819 | OPEN_ACCESS_READONLY, // read-only mode 820 NULL); // no EAs 821 822 if (arc == NO_ERROR) 819 820 if (!ppExec) 821 return (ERROR_INVALID_PARAMETER); 822 823 *ppExec = (PEXECUTABLE)malloc(sizeof(EXECUTABLE)); 824 if (!(*ppExec)) 825 return (ERROR_NOT_ENOUGH_MEMORY); 826 827 memset((*ppExec), 0, sizeof(EXECUTABLE)); 828 829 if (!(arc = DosOpen((PSZ)pcszExecutable, 830 &hFile, 831 &ulAction, // out: action taken 832 0, // in: new file (ignored for read-mode) 833 0, // in: new file attribs (ignored) 834 // open-flags 835 OPEN_ACTION_FAIL_IF_NEW 836 | OPEN_ACTION_OPEN_IF_EXISTS, 837 // open-mode 838 OPEN_FLAGS_FAIL_ON_ERROR // report errors to caller 839 | OPEN_FLAGS_SEQUENTIAL 840 | OPEN_FLAGS_NOINHERIT 841 | OPEN_SHARE_DENYNONE 842 | OPEN_ACCESS_READONLY, // read-only mode 843 NULL))) // no EAs 823 844 { 824 845 // file opened successfully: 825 // create EXECUTABLE structure 826 827 if (ppExec) 828 { 829 *ppExec = (PEXECUTABLE)malloc(sizeof(EXECUTABLE)); 830 if (*ppExec) 846 847 ULONG ulLocal = 0; 848 849 // read old DOS EXE header 850 (*ppExec)->pDosExeHeader = (PDOSEXEHEADER)malloc(sizeof(DOSEXEHEADER)); 851 if (!((*ppExec)->pDosExeHeader)) 852 arc = ERROR_NOT_ENOUGH_MEMORY; 853 else 854 { 855 ULONG ulBytesRead = 0; 856 857 if ( (!(arc = DosSetFilePtr(hFile, 858 0L, 859 FILE_BEGIN, 860 &ulLocal))) // out: new offset 861 && (!(arc = DosRead(hFile, 862 (*ppExec)->pDosExeHeader, 863 sizeof(DOSEXEHEADER), 864 &((*ppExec)->cbDosExeHeader)))) 865 ) 831 866 { 832 ULONG ulLocal = 0; 833 834 memset((*ppExec), 0, sizeof(EXECUTABLE)); 835 836 // read old DOS EXE header 837 (*ppExec)->pDosExeHeader = (PDOSEXEHEADER)malloc(sizeof(DOSEXEHEADER)); 838 if ((*ppExec)->pDosExeHeader == NULL) 839 arc = ERROR_NOT_ENOUGH_MEMORY; 867 // now check if we really have a DOS header 868 if ((*ppExec)->pDosExeHeader->usDosExeID != 0x5a4d) 869 arc = ERROR_INVALID_EXE_SIGNATURE; 840 870 else 841 871 { 842 ULONG ulBytesRead = 0; 843 arc = DosSetFilePtr(hFile, 844 0L, 845 FILE_BEGIN, 846 &ulLocal); // out: new offset 847 arc = DosRead(hFile, 848 (*ppExec)->pDosExeHeader, 849 sizeof(DOSEXEHEADER), 850 &((*ppExec)->cbDosExeHeader)); 851 // now check if we really have a DOS header 852 if ((*ppExec)->pDosExeHeader->usDosExeID != 0x5a4d) 853 arc = ERROR_INVALID_EXE_SIGNATURE; 872 // we have a DOS header: 873 if ((*ppExec)->pDosExeHeader->usRelocTableOfs < 0x40) 874 { 875 // neither LX nor PE nor NE: 876 (*ppExec)->ulOS = EXEOS_DOS3; 877 (*ppExec)->ulExeFormat = EXEFORMAT_OLDDOS; 878 } 854 879 else 855 880 { 856 // we have a DOS header: 857 if ((*ppExec)->pDosExeHeader->usRelocTableOfs < 0x40) 881 // either LX or PE or NE: 882 // read more bytes from position specified in header 883 CHAR achNewHeaderType[2] = ""; 884 885 if ( (!(arc = DosSetFilePtr(hFile, 886 (*ppExec)->pDosExeHeader->ulNewHeaderOfs, 887 FILE_BEGIN, 888 &ulLocal))) 889 // read two chars to find out header type 890 && (!(arc = DosRead(hFile, 891 &achNewHeaderType, 892 sizeof(achNewHeaderType), 893 &ulBytesRead))) 894 ) 858 895 { 859 // not LX or PE or NE: 860 (*ppExec)->ulOS = EXEOS_DOS3; 861 (*ppExec)->ulExeFormat = EXEFORMAT_OLDDOS; 862 } 863 else 864 { 865 // either LX or PE or NE: 866 // read more bytes from position 867 // specified in header 868 arc = DosSetFilePtr(hFile, 869 (*ppExec)->pDosExeHeader->ulNewHeaderOfs, 870 FILE_BEGIN, 871 &ulLocal); 872 873 if (arc == NO_ERROR) 896 PBYTE pbCheckOS = NULL; 897 898 // reset file ptr 899 DosSetFilePtr(hFile, 900 (*ppExec)->pDosExeHeader->ulNewHeaderOfs, 901 FILE_BEGIN, 902 &ulLocal); 903 904 if (memcmp(achNewHeaderType, "NE", 2) == 0) 874 905 { 875 PBYTE pbCheckOS = NULL; 876 877 // read two chars to find out header type 878 CHAR achNewHeaderType[2] = ""; 879 arc = DosRead(hFile, 880 &achNewHeaderType, 881 sizeof(achNewHeaderType), 882 &ulBytesRead); 883 // reset file ptr 884 DosSetFilePtr(hFile, 885 (*ppExec)->pDosExeHeader->ulNewHeaderOfs, 886 FILE_BEGIN, 887 &ulLocal); 888 889 if (memcmp(achNewHeaderType, "NE", 2) == 0) 906 // New Executable: 907 (*ppExec)->ulExeFormat = EXEFORMAT_NE; 908 // allocate NE header 909 (*ppExec)->pNEHeader = (PNEHEADER)malloc(sizeof(NEHEADER)); 910 if (!((*ppExec)->pNEHeader)) 911 arc = ERROR_NOT_ENOUGH_MEMORY; 912 else 913 // read in NE header 914 if (!(arc = DosRead(hFile, 915 (*ppExec)->pNEHeader, 916 sizeof(NEHEADER), 917 &((*ppExec)->cbNEHeader)))) 918 if ((*ppExec)->cbNEHeader == sizeof(NEHEADER)) 919 pbCheckOS = &((*ppExec)->pNEHeader->bTargetOS); 920 } 921 else if ( (memcmp(achNewHeaderType, "LX", 2) == 0) 922 || (memcmp(achNewHeaderType, "LE", 2) == 0) 923 // this is used by SMARTDRV.EXE 924 ) 925 { 926 // OS/2 Linear Executable: 927 (*ppExec)->ulExeFormat = EXEFORMAT_LX; 928 // allocate LX header 929 (*ppExec)->pLXHeader = (PLXHEADER)malloc(sizeof(LXHEADER)); 930 if (!((*ppExec)->pLXHeader)) 931 arc = ERROR_NOT_ENOUGH_MEMORY; 932 else 933 // read in LX header 934 if (!(arc = DosRead(hFile, 935 (*ppExec)->pLXHeader, 936 sizeof(LXHEADER), 937 &((*ppExec)->cbLXHeader)))) 938 if ((*ppExec)->cbLXHeader == sizeof(LXHEADER)) 939 pbCheckOS = (PBYTE)(&((*ppExec)->pLXHeader->usTargetOS)); 940 } 941 else if (memcmp(achNewHeaderType, "PE", 2) == 0) 942 { 943 (*ppExec)->ulExeFormat = EXEFORMAT_PE; 944 (*ppExec)->ulOS = EXEOS_WIN32; 945 (*ppExec)->f32Bits = TRUE; 946 947 // can't parse this yet 948 } 949 else 950 // strange type: 951 arc = ERROR_INVALID_EXE_SIGNATURE; 952 953 if (pbCheckOS) 954 // BYTE to check for operating system 955 // (NE and LX): 956 switch (*pbCheckOS) 890 957 { 891 // New Executable: 892 (*ppExec)->ulExeFormat = EXEFORMAT_NE; 893 // read NE header 894 (*ppExec)->pNEHeader = (PNEHEADER)malloc(sizeof(NEHEADER)); 895 DosRead(hFile, 896 (*ppExec)->pNEHeader, 897 sizeof(NEHEADER), 898 &((*ppExec)->cbNEHeader)); 899 if ((*ppExec)->cbNEHeader == sizeof(NEHEADER)) 900 pbCheckOS = &((*ppExec)->pNEHeader->bTargetOS); 958 case NEOS_OS2: 959 (*ppExec)->ulOS = EXEOS_OS2; 960 if ((*ppExec)->ulExeFormat == EXEFORMAT_LX) 961 (*ppExec)->f32Bits = TRUE; 962 break; 963 964 case NEOS_WIN16: 965 (*ppExec)->ulOS = EXEOS_WIN16; 966 break; 967 968 case NEOS_DOS4: 969 (*ppExec)->ulOS = EXEOS_DOS4; 970 break; 971 972 case NEOS_WIN386: 973 (*ppExec)->ulOS = EXEOS_WIN386; 974 (*ppExec)->f32Bits = TRUE; 975 break; 901 976 } 902 else if ( (memcmp(achNewHeaderType, "LX", 2) == 0) 903 || (memcmp(achNewHeaderType, "LE", 2) == 0) 904 // this is used by SMARTDRV.EXE 905 ) 906 { 907 // OS/2 Linear Executable: 908 (*ppExec)->ulExeFormat = EXEFORMAT_LX; 909 // read LX header 910 (*ppExec)->pLXHeader = (PLXHEADER)malloc(sizeof(LXHEADER)); 911 DosRead(hFile, 912 (*ppExec)->pLXHeader, 913 sizeof(LXHEADER), 914 &((*ppExec)->cbLXHeader)); 915 if ((*ppExec)->cbLXHeader == sizeof(LXHEADER)) 916 pbCheckOS = (PBYTE)(&((*ppExec)->pLXHeader->usTargetOS)); 917 } 918 else if (memcmp(achNewHeaderType, "PE", 2) == 0) 919 { 920 (*ppExec)->ulExeFormat = EXEFORMAT_PE; 921 (*ppExec)->ulOS = EXEOS_WIN32; 922 (*ppExec)->f32Bits = TRUE; 923 } 924 else 925 arc = ERROR_INVALID_EXE_SIGNATURE; 926 927 if (pbCheckOS) 928 // BYTE to check for operating system 929 // (NE and LX): 930 switch (*pbCheckOS) 931 { 932 case NEOS_OS2: 933 (*ppExec)->ulOS = EXEOS_OS2; 934 if ((*ppExec)->ulExeFormat == EXEFORMAT_LX) 935 (*ppExec)->f32Bits = TRUE; 936 break; 937 case NEOS_WIN16: 938 (*ppExec)->ulOS = EXEOS_WIN16; 939 break; 940 case NEOS_DOS4: 941 (*ppExec)->ulOS = EXEOS_DOS4; 942 break; 943 case NEOS_WIN386: 944 (*ppExec)->ulOS = EXEOS_WIN386; 945 (*ppExec)->f32Bits = TRUE; 946 break; 947 } 948 } 949 } 977 } // end if (!(arc = DosSetFilePtr(hFile, 950 978 } 951 952 // store exec's HFILE953 (*ppExec)->hfExe = hFile;954 979 } 955 956 if (arc != NO_ERROR) 957 // error: clean up 958 doshExecClose(*ppExec); 959 960 } // end if (*ppExec) 961 else 962 arc = ERROR_NOT_ENOUGH_MEMORY; 963 } // end if (ppExec) 964 else 965 arc = ERROR_INVALID_PARAMETER; 966 } // end if (arc == NO_ERROR) 980 } // end if (!(arc = DosSetFilePtr(hFile, 981 } // end if (*ppExec)->pDosExeHeader = (PDOSEXEHEADER)malloc(sizeof(DOSEXEHEADER)); 982 983 // store exec's HFILE 984 (*ppExec)->hfExe = hFile; 985 } // end if (!(arc = DosOpen((PSZ)pcszExecutable, 986 987 if (arc != NO_ERROR) 988 // error: clean up 989 doshExecClose(*ppExec); 967 990 968 991 return (arc); … … 999 1022 free(pExec->pszInfo); 1000 1023 1001 DosClose(pExec->hfExe); 1024 if (pExec->hfExe) 1025 arc = DosClose(pExec->hfExe); 1002 1026 1003 1027 free(pExec); … … 1048 1072 * 1049 1073 * This returns the following errors: 1074 * 1050 1075 * -- ERROR_INVALID_PARAMETER: pExec invalid 1076 * 1051 1077 * -- ERROR_INVALID_EXE_SIGNATURE (191): pExec is not in LX or NE format 1078 * 1052 1079 * -- ERROR_INVALID_DATA (13): non-resident name table not found. 1080 * 1053 1081 * -- ERROR_NOT_ENOUGH_MEMORY: malloc() failed. 1054 1082 * … … 1058 1086 *@@changed V0.9.0 (99-10-22) [umoeller]: NE format now supported 1059 1087 *@@changed V0.9.1 (99-12-06): fixed memory leak 1088 *@@changed V0.9.9 (2001-04-04) [umoeller]: added more error checking 1060 1089 */ 1061 1090 … … 1063 1092 { 1064 1093 APIRET arc = NO_ERROR; 1065 PSZ pszNameTable = NULL; 1066 ULONG ulNRNTOfs = 0;1067 1068 do1094 1095 if (!pExec) 1096 arc = ERROR_INVALID_PARAMETER; 1097 else 1069 1098 { 1070 ULONG ulLocal = 0, 1071 ulBytesRead = 0; 1072 PSZ pStartOfAuthor = NULL; 1073 1074 if (pExec == NULL) 1075 { 1076 arc = ERROR_INVALID_PARAMETER; 1077 break; 1078 } 1099 ULONG ulNRNTOfs = 0; 1079 1100 1080 1101 if (pExec->ulExeFormat == EXEFORMAT_LX) … … 1083 1104 // check if we have a non-resident name table 1084 1105 if (pExec->pLXHeader == NULL) 1085 {1086 1106 arc = ERROR_INVALID_DATA; 1087 break; 1088 } 1089 if (pExec->pLXHeader->ulNonResdNameTblOfs == 0) 1090 { 1107 else if (pExec->pLXHeader->ulNonResdNameTblOfs == 0) 1091 1108 arc = ERROR_INVALID_DATA; 1092 break; 1093 } 1094 1095 ulNRNTOfs = pExec->pLXHeader->ulNonResdNameTblOfs; 1109 else 1110 ulNRNTOfs = pExec->pLXHeader->ulNonResdNameTblOfs; 1096 1111 } 1097 1112 else if (pExec->ulExeFormat == EXEFORMAT_NE) … … 1100 1115 // check if we have a non-resident name table 1101 1116 if (pExec->pNEHeader == NULL) 1102 {1103 1117 arc = ERROR_INVALID_DATA; 1104 break; 1105 } 1106 if (pExec->pNEHeader->ulNonResdTblOfs == 0) 1107 { 1118 else if (pExec->pNEHeader->ulNonResdTblOfs == 0) 1108 1119 arc = ERROR_INVALID_DATA; 1109 break; 1110 } 1111 1112 ulNRNTOfs = pExec->pNEHeader->ulNonResdTblOfs; 1120 else 1121 ulNRNTOfs = pExec->pNEHeader->ulNonResdTblOfs; 1113 1122 } 1114 1123 else 1115 {1116 1124 // neither LX nor NE: stop 1117 1125 arc = ERROR_INVALID_EXE_SIGNATURE; 1118 break; 1126 1127 if ( (!arc) 1128 && (ulNRNTOfs) 1129 ) 1130 { 1131 ULONG ulLocal = 0, 1132 ulBytesRead = 0; 1133 1134 // move EXE file pointer to offset of non-resident name table 1135 // (from LX header) 1136 if (!(arc = DosSetFilePtr(pExec->hfExe, // file is still open 1137 ulNRNTOfs, // ofs determined above 1138 FILE_BEGIN, 1139 &ulLocal))) 1140 { 1141 // allocate memory as necessary 1142 PSZ pszNameTable = (PSZ)malloc(2001); // should suffice, because each entry 1143 // may only be 255 bytes in length 1144 if (!pszNameTable) 1145 arc = ERROR_NOT_ENOUGH_MEMORY; 1146 else 1147 { 1148 if (!(arc = DosRead(pExec->hfExe, 1149 pszNameTable, 1150 2000, 1151 &ulBytesRead))) 1152 { 1153 if (*pszNameTable == 0) 1154 // first byte (length byte) is null: 1155 arc = ERROR_INVALID_DATA; 1156 else 1157 { 1158 // now copy the string, which is in Pascal format 1159 pExec->pszDescription = (PSZ)malloc((*pszNameTable) + 1); // addt'l null byte 1160 if (!pExec->pszDescription) 1161 arc = ERROR_NOT_ENOUGH_MEMORY; 1162 else 1163 { 1164 const char *pStartOfAuthor = 0, 1165 *pStartOfVendor = 0; 1166 1167 memcpy(pExec->pszDescription, 1168 pszNameTable + 1, // skip length byte 1169 *pszNameTable); // length byte 1170 // terminate string 1171 *(pExec->pszDescription + (*pszNameTable)) = 0; 1172 1173 // now parse the damn thing: 1174 // @#VENDOR:VERSION#@ DESCRIPTION 1175 // but skip the first byte, which has the string length 1176 pStartOfVendor = strstr(pExec->pszDescription, 1177 "@#"); 1178 if (pStartOfVendor) 1179 { 1180 const char *pStartOfInfo = strstr(pStartOfVendor + 2, 1181 "#@"); 1182 if (pStartOfInfo) 1183 { 1184 PSZ pEndOfVendor = strchr(pStartOfVendor + 2, 1185 ':'); 1186 if (pEndOfVendor) 1187 { 1188 pExec->pszVendor = strhSubstr(pStartOfVendor + 2, 1189 pEndOfVendor); 1190 pExec->pszVersion = strhSubstr(pEndOfVendor + 1, 1191 pStartOfInfo); 1192 // skip "@#" in info string 1193 pStartOfInfo += 2; 1194 // skip leading spaces in info string 1195 while (*pStartOfInfo == ' ') 1196 pStartOfInfo++; 1197 if (*pStartOfInfo) // V0.9.9 (2001-04-04) [umoeller] 1198 // and copy until end of string 1199 pExec->pszInfo = strdup(pStartOfInfo); 1200 } 1201 } 1202 } 1203 } 1204 } 1205 } 1206 1207 free(pszNameTable); 1208 } // end if PSZ pszNameTable = (PSZ)malloc(2001); 1209 } 1119 1210 } 1120 1121 if (ulNRNTOfs == 0) 1122 { 1123 // shouldn't happen 1124 arc = ERROR_INVALID_DATA; 1125 break; 1126 } 1127 1128 // move EXE file pointer to offset of non-resident name table 1129 // (from LX header) 1130 arc = DosSetFilePtr(pExec->hfExe, // file is still open 1131 ulNRNTOfs, // ofs determined above 1132 FILE_BEGIN, 1133 &ulLocal); 1134 if (arc != NO_ERROR) 1135 break; 1136 1137 // allocate memory as necessary 1138 pszNameTable = (PSZ)malloc(2001); // should suffice, because each entry 1139 // may only be 255 bytes in length 1140 if (pszNameTable) 1141 { 1142 arc = DosRead(pExec->hfExe, 1143 pszNameTable, 1144 2000, 1145 &ulBytesRead); 1146 if (arc != NO_ERROR) 1147 break; 1148 if (*pszNameTable == 0) 1211 } // end if (!pExec) 1212 1213 return (arc); 1214 } 1215 1216 /* 1217 *@@ doshExecQueryImportedModules: 1218 * returns an array of FSYSMODULE structure describing all 1219 * imported modules. 1220 * 1221 * *pcModules receives the # of items in the array (not the 1222 * array size!). Use doshFreeImportedModules to clean up. 1223 * 1224 * This returns a standard OS/2 error code, which might be 1225 * any of the codes returned by DosSetFilePtr and DosRead. 1226 * In addition, this may return: 1227 * 1228 * -- ERROR_NOT_ENOUGH_MEMORY 1229 * 1230 * -- ERROR_INVALID_EXE_SIGNATURE: exe is in a format other 1231 * than LX or NE, which is not understood by this function. 1232 * 1233 * Even if NO_ERROR is returned, the array pointer might still 1234 * be NULL if the module contains no such data. 1235 * 1236 *@@added V0.9.9 (2001-03-11) [lafaix] 1237 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1238 */ 1239 1240 APIRET doshExecQueryImportedModules(PEXECUTABLE pExec, 1241 PFSYSMODULE *ppaModules, // out: modules array 1242 PULONG pcModules) // out: array item count 1243 { 1244 APIRET arc = NO_ERROR; 1245 1246 if ( (pExec) 1247 && (pExec->ulOS == EXEOS_OS2) 1248 ) 1249 { 1250 ULONG cModules = 0; 1251 PFSYSMODULE paModules = NULL; 1252 int i; 1253 1254 if (pExec->ulExeFormat == EXEFORMAT_LX) 1255 { 1256 // 32-bit OS/2 executable: 1257 if (cModules = pExec->pLXHeader->ulImportModTblCnt) 1149 1258 { 1150 // first byte (length byte) is null: 1151 arc = ERROR_INVALID_DATA; 1152 free (pszNameTable); // fixed V0.9.1 (99-12-06) 1153 break; 1154 } 1155 1156 // now copy the string, which is in Pascal format 1157 pExec->pszDescription = (PSZ)malloc((*pszNameTable) + 1); // addt'l null byte 1158 memcpy(pExec->pszDescription, 1159 pszNameTable + 1, // skip length byte 1160 *pszNameTable); // length byte 1161 // terminate string 1162 *(pExec->pszDescription + (*pszNameTable)) = 0; 1163 1164 // _Pmpf(("pszDescription: %s", pExec->pszDescription)); 1165 1166 // now parse the damn thing: 1167 // @#AUTHOR:VERSION#@ DESCRIPTION 1168 // but skip the first byte, which has the string length 1169 pStartOfAuthor = strstr(pExec->pszDescription, "@#"); 1170 if (pStartOfAuthor) 1171 { 1172 PSZ pStartOfInfo = strstr(pStartOfAuthor + 2, "#@"); 1173 // _Pmpf(("Testing")); 1174 if (pStartOfInfo) 1259 ULONG cb = sizeof(FSYSMODULE) * cModules; // V0.9.9 (2001-04-03) [umoeller] 1260 1261 paModules = (PFSYSMODULE)malloc(cb); 1262 if (!paModules) 1263 arc = ERROR_NOT_ENOUGH_MEMORY; // V0.9.9 (2001-04-03) [umoeller] 1264 else 1175 1265 { 1176 PSZ pEndOfAuthor = strchr(pStartOfAuthor + 2, ':'); 1177 // _Pmpf(("pStartOfinfo: %s", pStartOfInfo)); 1178 if (pEndOfAuthor) 1266 ULONG ulDummy; 1267 1268 memset(paModules, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 1269 1270 // V0.9.9 (2001-04-03) [umoeller]: 1271 // Martin, I added error checking to all the below 1272 // Dos* calls. You can't just read around a file 1273 // and assume it will always be valid... especially 1274 // if you fill dynamically allocated memory. 1275 1276 if (!(arc = DosSetFilePtr(pExec->hfExe, 1277 pExec->pLXHeader->ulImportModTblOfs 1278 + pExec->pDosExeHeader->ulNewHeaderOfs, 1279 FILE_BEGIN, 1280 &ulDummy))) 1179 1281 { 1180 // _Pmpf(("pEndOfAuthor: %s", pEndOfAuthor)); 1181 pExec->pszVendor = strhSubstr(pStartOfAuthor + 2, pEndOfAuthor); 1182 pExec->pszVersion = strhSubstr(pEndOfAuthor + 1, pStartOfInfo); 1183 // skip "@#" in info string 1184 pStartOfInfo += 2; 1185 // skip leading spaces in info string 1186 while (*pStartOfInfo == ' ') 1187 pStartOfInfo++; 1188 // and copy until end of string 1189 pExec->pszInfo = strdup(pStartOfInfo); 1282 for (i = 0; i < cModules; i++) 1283 { 1284 BYTE bLen = 0; 1285 1286 // reading the length of the module name 1287 if (!(arc = DosRead(pExec->hfExe, 1288 &bLen, 1289 1, 1290 &ulDummy))) 1291 { 1292 // At most 127 bytes 1293 bLen &= 0x7F; 1294 1295 // reading the module name 1296 if (!(arc = DosRead(pExec->hfExe, 1297 paModules[i].achModuleName, 1298 bLen, 1299 &ulDummy))) 1300 // module names are not null terminated, so we must 1301 // do it now 1302 paModules[i].achModuleName[bLen] = 0; 1303 } 1304 1305 if (arc) 1306 break; // V0.9.9 (2001-04-03) [umoeller] 1307 1308 } // end for 1190 1309 } 1191 1310 } 1192 1311 } 1193 1194 free(pszNameTable); 1195 } 1196 else 1197 arc = ERROR_NOT_ENOUGH_MEMORY; 1198 } while (FALSE); 1199 1200 1201 return (arc); 1202 } 1203 1204 /* 1205 *@@ doshExecQueryImportedModules: 1206 * returns an array of FSYSMODULE structure describing all 1207 * imported modules. 1208 * 1209 * *pcModules receives the # of items in the array (not the 1210 * array size!). Use doshFreeImportedModules to clean up. 1211 * 1212 *@@added V0.9.9 (2001-03-11) [lafaix] 1213 */ 1214 1215 PFSYSMODULE doshExecQueryImportedModules(PEXECUTABLE pExec, 1216 PULONG pcModules) 1217 { 1218 ULONG cModules = 0; 1219 PFSYSMODULE paModules = NULL; 1220 int i; 1221 1222 if (pExec) 1223 { 1224 if (pExec->ulOS == EXEOS_OS2) 1225 { 1226 ULONG ulDummy; 1227 1228 if (pExec->ulExeFormat == EXEFORMAT_LX) 1312 } // end LX 1313 else if (pExec->ulExeFormat == EXEFORMAT_NE) 1314 { 1315 // 16-bit OS/2 executable: 1316 if (cModules = pExec->pNEHeader->usModuleTblEntries) 1229 1317 { 1230 // It's a 32bit OS/2 executable 1231 cModules = pExec->pLXHeader->ulImportModTblCnt; 1232 1233 if (cModules) 1318 ULONG cb = sizeof(FSYSMODULE) * cModules; 1319 1320 paModules = (PFSYSMODULE)malloc(cb); 1321 if (!paModules) 1322 arc = ERROR_NOT_ENOUGH_MEMORY; // V0.9.9 (2001-04-03) [umoeller] 1323 else 1234 1324 { 1235 BYTE bLen; 1236 1237 paModules = (PFSYSMODULE)malloc(sizeof(FSYSMODULE) * cModules); 1238 1239 DosSetFilePtr(pExec->hfExe, 1240 pExec->pLXHeader->ulImportModTblOfs 1241 + pExec->pDosExeHeader->ulNewHeaderOfs, 1242 FILE_BEGIN, 1243 &ulDummy); 1244 1245 for (i = 0; i < cModules; i++) 1246 { 1247 // reading the length of the module name 1248 DosRead(pExec->hfExe, 1249 &bLen, 1250 1, 1251 &ulDummy); 1252 1253 // At most 127 bytes 1254 bLen &= 0x7F; 1255 1256 // reading the module name 1257 DosRead(pExec->hfExe, 1258 paModules[i].achModuleName, 1259 bLen, 1260 &ulDummy); 1261 1262 // modules name are not null terminated, so we must 1263 // do it now 1264 paModules[i].achModuleName[bLen] = 0; 1265 } 1266 } 1267 } 1268 else 1269 if (pExec->ulExeFormat == EXEFORMAT_NE) 1270 { 1271 // It's a 16bit OS/2 executable 1272 cModules = pExec->pNEHeader->usModuleTblEntries; 1273 1274 if (cModules) 1275 { 1276 BYTE bLen; 1277 1278 paModules = (PFSYSMODULE)malloc(sizeof(FSYSMODULE) * cModules); 1325 memset(paModules, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 1279 1326 1280 1327 for (i = 0; i < cModules; i ++) 1281 1328 { 1329 BYTE bLen; 1282 1330 USHORT usOfs; 1331 ULONG ulDummy; 1283 1332 1284 1333 // the module reference table contains offsets … … 1287 1336 // then we read the name in the import table 1288 1337 1289 DosSetFilePtr(pExec->hfExe,1290 pExec->pNEHeader->usModRefTblOfs1291 + pExec->pDosExeHeader->ulNewHeaderOfs1292 + sizeof(usOfs) * i,1293 FILE_BEGIN,1294 &ulDummy);1295 1296 DosRead(pExec->hfExe,1297 &usOfs,1298 2,1299 &ulDummy);1300 1301 DosSetFilePtr(pExec->hfExe,1302 pExec->pNEHeader->usImportTblOfs1303 + pExec->pDosExeHeader->ulNewHeaderOfs1304 + usOfs,1305 FILE_BEGIN,1306 &ulDummy);1307 1308 DosRead(pExec->hfExe,1309 &bLen,1310 1,1311 &ulDummy);1312 1313 bLen &= 0x7F;1314 1315 DosRead(pExec->hfExe,1316 paModules[i].achModuleName,1317 bLen,1318 &ulDummy);1319 1320 paModules[i].achModuleName[bLen] = 0;1321 }1322 1338 if ( (!(arc = DosSetFilePtr(pExec->hfExe, 1339 pExec->pNEHeader->usModRefTblOfs 1340 + pExec->pDosExeHeader->ulNewHeaderOfs 1341 + sizeof(usOfs) * i, 1342 FILE_BEGIN, 1343 &ulDummy))) 1344 && (!(arc = DosRead(pExec->hfExe, 1345 &usOfs, 1346 2, 1347 &ulDummy))) 1348 && (!(arc = DosSetFilePtr(pExec->hfExe, 1349 pExec->pNEHeader->usImportTblOfs 1350 + pExec->pDosExeHeader->ulNewHeaderOfs 1351 + usOfs, 1352 FILE_BEGIN, 1353 &ulDummy))) 1354 && (!(arc = DosRead(pExec->hfExe, 1355 &bLen, 1356 1, 1357 &ulDummy))) 1358 ) 1359 { 1360 bLen &= 0x7F; 1361 1362 if (!(arc = DosRead(pExec->hfExe, 1363 paModules[i].achModuleName, 1364 bLen, 1365 &ulDummy))) 1366 paModules[i].achModuleName[bLen] = 0; 1367 } 1368 1369 if (arc) 1370 break; // V0.9.9 (2001-04-03) [umoeller] 1371 } // end for 1323 1372 } 1324 1373 } 1325 1374 } 1375 else 1376 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 1377 1378 if (arc) 1379 { 1380 // if we had an error above, clean up 1381 if (paModules) 1382 free(paModules); 1383 } 1384 else 1385 { 1386 // no error: output data 1387 *ppaModules = paModules; 1326 1388 *pcModules = cModules; 1327 1389 } 1328 1390 } 1329 1330 return (paModules); 1391 else 1392 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 1393 1394 return (arc); 1331 1395 } 1332 1396 … … 1340 1404 APIRET doshExecFreeImportedModules(PFSYSMODULE paModules) 1341 1405 { 1342 free(paModules); 1406 if (paModules) // V0.9.9 (2001-04-04) [umoeller] 1407 free(paModules); 1343 1408 return (NO_ERROR); 1344 1409 } … … 1348 1413 * returns the number of exported entries in the entry table. 1349 1414 * 1415 * If paFunctions is not NULL, then successive entries are 1416 * filled with the found type and ordinal values. 1417 * 1418 *@@added V0.9.9 (2001-03-30) [lafaix] 1419 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1420 */ 1421 1422 APIRET ScanLXEntryTable(PEXECUTABLE pExec, 1423 PFSYSFUNCTION paFunctions, 1424 PULONG pcEntries) // out: entry table entry count; ptr can be NULL 1425 { 1426 APIRET arc = NO_ERROR; 1427 1428 ULONG ulDummy; 1429 1430 if (!(arc = DosSetFilePtr(pExec->hfExe, 1431 pExec->pLXHeader->ulEntryTblOfs 1432 + pExec->pDosExeHeader->ulNewHeaderOfs, 1433 FILE_BEGIN, 1434 &ulDummy))) 1435 { 1436 USHORT usOrdinal = 1, 1437 usCurrent = 0; 1438 int i; 1439 1440 while (!arc) // V0.9.9 (2001-04-03) [umoeller] 1441 { 1442 BYTE bCnt, 1443 bType, 1444 bFlag; 1445 1446 if (!(arc = DosRead(pExec->hfExe, 1447 &bCnt, 1448 1, 1449 &ulDummy))) 1450 { 1451 if (bCnt == 0) 1452 // end of the entry table 1453 break; 1454 1455 if (!(arc = DosRead(pExec->hfExe, 1456 &bType, 1457 1, 1458 &ulDummy))) 1459 { 1460 switch (bType & 0x7F) 1461 { 1462 /* 1463 * unused entries 1464 * 1465 */ 1466 1467 case 0: 1468 usOrdinal += bCnt; 1469 break; 1470 1471 /* 1472 * 16-bit entries 1473 * 1474 * the bundle type is followed by the object number 1475 * and by bCnt bFlag+usOffset entries 1476 * 1477 */ 1478 1479 case 1: 1480 if (!(arc = DosSetFilePtr(pExec->hfExe, 1481 sizeof(USHORT), 1482 FILE_CURRENT, 1483 &ulDummy))) 1484 { 1485 for (i = 0; i < bCnt; i ++) 1486 { 1487 if (!(arc = DosRead(pExec->hfExe, 1488 &bFlag, 1489 1, 1490 &ulDummy))) 1491 { 1492 if (bFlag & 0x01) 1493 { 1494 if (paFunctions) 1495 { 1496 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1497 paFunctions[usCurrent].ulType = 1; 1498 paFunctions[usCurrent].achFunctionName[0] = 0; 1499 } 1500 usCurrent++; 1501 } 1502 1503 usOrdinal++; 1504 1505 arc = DosSetFilePtr(pExec->hfExe, 1506 sizeof(USHORT), 1507 FILE_CURRENT, 1508 &ulDummy); 1509 } 1510 1511 if (arc) 1512 break; // V0.9.9 (2001-04-03) [umoeller] 1513 1514 } // end for 1515 } 1516 break; 1517 1518 /* 1519 * 286 call gate entries 1520 * 1521 * the bundle type is followed by the object number 1522 * and by bCnt bFlag+usOffset+usCallGate entries 1523 * 1524 */ 1525 1526 case 2: 1527 if (!(arc = DosSetFilePtr(pExec->hfExe, 1528 sizeof(USHORT), 1529 FILE_CURRENT, 1530 &ulDummy))) 1531 { 1532 for (i = 0; i < bCnt; i ++) 1533 { 1534 if (!(arc = DosRead(pExec->hfExe, 1535 &bFlag, 1536 1, 1537 &ulDummy))) 1538 { 1539 if (bFlag & 0x01) 1540 { 1541 if (paFunctions) 1542 { 1543 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1544 paFunctions[usCurrent].ulType = 2; 1545 paFunctions[usCurrent].achFunctionName[0] = 0; 1546 } 1547 usCurrent++; 1548 } 1549 1550 usOrdinal++; 1551 1552 arc = DosSetFilePtr(pExec->hfExe, 1553 sizeof(USHORT) + sizeof(USHORT), 1554 FILE_CURRENT, 1555 &ulDummy); 1556 } 1557 1558 if (arc) 1559 break; // V0.9.9 (2001-04-03) [umoeller] 1560 1561 } // end for 1562 } 1563 break; 1564 1565 /* 1566 * 32-bit entries 1567 * 1568 * the bundle type is followed by the object number 1569 * and by bCnt bFlag+ulOffset entries 1570 * 1571 */ 1572 1573 case 3: 1574 if (!(arc = DosSetFilePtr(pExec->hfExe, 1575 sizeof(USHORT), 1576 FILE_CURRENT, 1577 &ulDummy))) 1578 { 1579 for (i = 0; i < bCnt; i ++) 1580 { 1581 if (!(arc = DosRead(pExec->hfExe, 1582 &bFlag, 1583 1, 1584 &ulDummy))) 1585 { 1586 if (bFlag & 0x01) 1587 { 1588 if (paFunctions) 1589 { 1590 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1591 paFunctions[usCurrent].ulType = 3; 1592 paFunctions[usCurrent].achFunctionName[0] = 0; 1593 } 1594 usCurrent++; 1595 } 1596 1597 usOrdinal++; 1598 1599 arc = DosSetFilePtr(pExec->hfExe, 1600 sizeof(ULONG), 1601 FILE_CURRENT, 1602 &ulDummy); 1603 } 1604 1605 if (arc) 1606 break; // V0.9.9 (2001-04-03) [umoeller] 1607 } // end for 1608 } 1609 break; 1610 1611 /* 1612 * forwarder entries 1613 * 1614 * the bundle type is followed by a reserved word 1615 * and by bCnt bFlag+usModOrd+ulOffsOrdNum entries 1616 * 1617 */ 1618 1619 case 4: 1620 if (!(arc = DosSetFilePtr(pExec->hfExe, 1621 sizeof(USHORT), 1622 FILE_CURRENT, 1623 &ulDummy))) 1624 { 1625 for (i = 0; i < bCnt; i ++) 1626 { 1627 if (!(arc = DosSetFilePtr(pExec->hfExe, 1628 sizeof(BYTE) + sizeof(USHORT) + sizeof(ULONG), 1629 FILE_CURRENT, 1630 &ulDummy))) 1631 { 1632 if (paFunctions) 1633 { 1634 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1635 paFunctions[usCurrent].ulType = 4; 1636 paFunctions[usCurrent].achFunctionName[0] = 0; 1637 } 1638 usCurrent++; 1639 1640 usOrdinal++; 1641 } 1642 1643 if (arc) 1644 break; // V0.9.9 (2001-04-03) [umoeller] 1645 } // end for 1646 } 1647 break; 1648 1649 /* 1650 * unknown bundle type 1651 * 1652 * we don't know how to handle this bundle, so we must 1653 * stop parsing the entry table here (as we don't know the 1654 * bundle size); if paFunctions is not null, we fill it with 1655 * informative data 1656 */ 1657 1658 default: 1659 if (paFunctions) 1660 { 1661 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1662 paFunctions[usCurrent].ulType = bType; 1663 sprintf(paFunctions[usCurrent].achFunctionName, 1664 "Unknown bundle type encountered (%d). Aborting entry table scan.", 1665 bType); 1666 1667 arc = ERROR_INVALID_LIST_FORMAT; 1668 // whatever 1669 // V0.9.9 (2001-04-03) [umoeller] 1670 } 1671 1672 usCurrent++; 1673 } // end switch (bType & 0x7F) 1674 } 1675 } 1676 } // end while (!arc) 1677 1678 if (!arc) 1679 if (pcEntries) 1680 *pcEntries = usCurrent; 1681 } 1682 1683 return (arc); 1684 } 1685 1686 /* 1687 *@@ ScanNEEntryTable: 1688 * returns the number of exported entries in the entry table. 1689 * 1350 1690 * if paFunctions is not NULL, then successive entries are 1351 1691 * filled with the found type and ordinal values. 1352 1692 * 1353 1693 *@@added V0.9.9 (2001-03-30) [lafaix] 1354 */ 1355 1356 ULONG ScanLXEntryTable(PEXECUTABLE pExec, 1357 PFSYSFUNCTION paFunctions) 1358 { 1359 USHORT usOrdinal = 1, 1360 usCurrent = 0; 1694 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1695 */ 1696 1697 APIRET ScanNEEntryTable(PEXECUTABLE pExec, 1698 PFSYSFUNCTION paFunctions, 1699 PULONG pcEntries) // out: entry table entry count; ptr can be NULL 1700 { 1701 APIRET arc = NO_ERROR; 1361 1702 ULONG ulDummy; 1362 int i; 1363 1364 DosSetFilePtr(pExec->hfExe, 1365 pExec->pLXHeader->ulEntryTblOfs 1366 + pExec->pDosExeHeader->ulNewHeaderOfs, 1367 FILE_BEGIN, 1368 &ulDummy); 1369 1370 while (TRUE) 1703 1704 if (!(arc = DosSetFilePtr(pExec->hfExe, 1705 pExec->pNEHeader->usEntryTblOfs 1706 + pExec->pDosExeHeader->ulNewHeaderOfs, 1707 FILE_BEGIN, 1708 &ulDummy))) 1371 1709 { 1372 BYTE bCnt, 1373 bType, 1374 bFlag; 1375 1376 DosRead(pExec->hfExe, 1377 &bCnt, 1378 1, 1379 &ulDummy); 1380 1381 if (bCnt == 0) 1382 // end of the entry table 1383 break; 1384 1385 DosRead(pExec->hfExe, 1386 &bType, 1387 1, 1388 &ulDummy); 1389 1390 switch (bType & 0x7F) 1391 { 1392 /* 1393 * unused entries 1394 * 1395 */ 1396 1397 case 0: 1398 usOrdinal += bCnt; 1399 break; 1400 1401 /* 1402 * 16-bit entries 1403 * 1404 * the bundle type is followed by the object number 1405 * and by bCnt bFlag+usOffset entries 1406 * 1407 */ 1408 1409 case 1: 1410 DosSetFilePtr(pExec->hfExe, 1411 sizeof(USHORT), 1412 FILE_CURRENT, 1413 &ulDummy); 1414 1415 for (i = 0; i < bCnt; i ++) 1710 USHORT usOrdinal = 1, 1711 usCurrent = 0; 1712 int i; 1713 1714 while (!arc) // V0.9.9 (2001-04-03) [umoeller] 1715 { 1716 BYTE bCnt, 1717 bType, 1718 bFlag; 1719 1720 if (!(arc = DosRead(pExec->hfExe, 1721 &bCnt, 1722 1, 1723 &ulDummy))) 1724 { 1725 if (bCnt == 0) 1726 // end of the entry table 1727 break; 1728 1729 if (!(arc = DosRead(pExec->hfExe, 1730 &bType, 1731 1, 1732 &ulDummy))) 1416 1733 { 1417 DosRead(pExec->hfExe, 1418 &bFlag, 1419 1, 1420 &ulDummy); 1421 1422 if (bFlag & 0x01) 1734 for (i = 0; i < bCnt; i++) 1423 1735 { 1424 if (paFunctions) 1736 if (!(arc = DosRead(pExec->hfExe, 1737 &bFlag, 1738 1, 1739 &ulDummy))) 1425 1740 { 1426 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1427 paFunctions[usCurrent].ulType = 1; 1428 paFunctions[usCurrent].achFunctionName[0] = 0; 1741 if (bFlag & 0x01) 1742 { 1743 if (paFunctions) 1744 { 1745 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1746 paFunctions[usCurrent].ulType = 1; // 16-bit entry 1747 paFunctions[usCurrent].achFunctionName[0] = 0; 1748 } 1749 usCurrent++; 1750 } 1751 1752 usOrdinal++; 1753 1754 if (bType == 0xFF) 1755 // moveable segment 1756 arc = DosSetFilePtr(pExec->hfExe, 1757 5, 1758 FILE_CURRENT, 1759 &ulDummy); 1760 else 1761 // fixed segment 1762 arc = DosSetFilePtr(pExec->hfExe, 1763 2, 1764 FILE_CURRENT, 1765 &ulDummy); 1429 1766 } 1430 usCurrent++; 1431 } 1432 1433 usOrdinal++; 1434 1435 DosSetFilePtr(pExec->hfExe, 1436 sizeof(USHORT), 1437 FILE_CURRENT, 1438 &ulDummy); 1767 1768 if (arc) 1769 break; // V0.9.9 (2001-04-03) [umoeller] 1770 1771 } // end for 1439 1772 } 1440 break;1441 1442 /*1443 * 286 call gate entries1444 *1445 * the bundle type is followed by the object number1446 * and by bCnt bFlag+usOffset+usCallGate entries1447 *1448 */1449 1450 case 2:1451 DosSetFilePtr(pExec->hfExe,1452 sizeof(USHORT),1453 FILE_CURRENT,1454 &ulDummy);1455 1456 for (i = 0; i < bCnt; i ++)1457 {1458 DosRead(pExec->hfExe,1459 &bFlag,1460 1,1461 &ulDummy);1462 1463 if (bFlag & 0x01)1464 {1465 if (paFunctions)1466 {1467 paFunctions[usCurrent].ulOrdinal = usOrdinal;1468 paFunctions[usCurrent].ulType = 2;1469 paFunctions[usCurrent].achFunctionName[0] = 0;1470 }1471 usCurrent++;1472 }1473 1474 usOrdinal++;1475 1476 DosSetFilePtr(pExec->hfExe,1477 sizeof(USHORT) + sizeof(USHORT),1478 FILE_CURRENT,1479 &ulDummy);1480 }1481 break;1482 1483 /*1484 * 32-bit entries1485 *1486 * the bundle type is followed by the object number1487 * and by bCnt bFlag+ulOffset entries1488 *1489 */1490 1491 case 3:1492 DosSetFilePtr(pExec->hfExe,1493 sizeof(USHORT),1494 FILE_CURRENT,1495 &ulDummy);1496 1497 for (i = 0; i < bCnt; i ++)1498 {1499 DosRead(pExec->hfExe,1500 &bFlag,1501 1,1502 &ulDummy);1503 1504 if (bFlag & 0x01)1505 {1506 if (paFunctions)1507 {1508 paFunctions[usCurrent].ulOrdinal = usOrdinal;1509 paFunctions[usCurrent].ulType = 3;1510 paFunctions[usCurrent].achFunctionName[0] = 0;1511 }1512 usCurrent++;1513 }1514 1515 usOrdinal++;1516 1517 DosSetFilePtr(pExec->hfExe,1518 sizeof(ULONG),1519 FILE_CURRENT,1520 &ulDummy);1521 }1522 break;1523 1524 /*1525 * forwarder entries1526 *1527 * the bundle type is followed by a reserved word1528 * and by bCnt bFlag+usModOrd+ulOffsOrdNum entries1529 *1530 */1531 1532 case 4:1533 DosSetFilePtr(pExec->hfExe,1534 sizeof(USHORT),1535 FILE_CURRENT,1536 &ulDummy);1537 1538 for (i = 0; i < bCnt; i ++)1539 {1540 DosSetFilePtr(pExec->hfExe,1541 sizeof(BYTE) + sizeof(USHORT) + sizeof(ULONG),1542 FILE_CURRENT,1543 &ulDummy);1544 1545 if (paFunctions)1546 {1547 paFunctions[usCurrent].ulOrdinal = usOrdinal;1548 paFunctions[usCurrent].ulType = 4;1549 paFunctions[usCurrent].achFunctionName[0] = 0;1550 }1551 usCurrent++;1552 1553 usOrdinal++;1554 }1555 break;1556 }1557 } // end while (TRUE)1558 1559 return (usCurrent);1560 }1561 1562 /*1563 *@@ ScanNEEntryTable:1564 * returns the number of exported entries in the entry table.1565 *1566 * if paFunctions is not NULL, then successive entries are1567 * filled with the found type and ordinal values.1568 *1569 *@@added V0.9.9 (2001-03-30) [lafaix]1570 */1571 1572 ULONG ScanNEEntryTable(PEXECUTABLE pExec,1573 PFSYSFUNCTION paFunctions)1574 {1575 USHORT usOrdinal = 1,1576 usCurrent = 0;1577 ULONG ulDummy;1578 int i;1579 1580 DosSetFilePtr(pExec->hfExe,1581 pExec->pNEHeader->usEntryTblOfs1582 + pExec->pDosExeHeader->ulNewHeaderOfs,1583 FILE_BEGIN,1584 &ulDummy);1585 1586 while (TRUE)1587 {1588 BYTE bCnt,1589 bType,1590 bFlag;1591 1592 DosRead(pExec->hfExe,1593 &bCnt,1594 1,1595 &ulDummy);1596 1597 if (bCnt == 0)1598 // end of the entry table1599 break;1600 1601 DosRead(pExec->hfExe,1602 &bType,1603 1,1604 &ulDummy);1605 1606 for (i = 0; i < bCnt; i++)1607 {1608 DosRead(pExec->hfExe,1609 &bFlag,1610 1,1611 &ulDummy);1612 1613 if (bFlag & 0x01)1614 {1615 if (paFunctions)1616 {1617 paFunctions[usCurrent].ulOrdinal = usOrdinal;1618 paFunctions[usCurrent].ulType = 1; // 16-bit entry1619 paFunctions[usCurrent].achFunctionName[0] = 0;1620 }1621 usCurrent++;1622 1773 } 1623 1624 usOrdinal++; 1625 1626 if (bType == 0xFF) 1627 // moveable segment 1628 DosSetFilePtr(pExec->hfExe, 1629 5, 1630 FILE_CURRENT, 1631 &ulDummy); 1632 else 1633 // fixed segment 1634 DosSetFilePtr(pExec->hfExe, 1635 2, 1636 FILE_CURRENT, 1637 &ulDummy); 1638 } 1639 } // end while (TRUE) 1640 1641 return (usCurrent); 1774 } // end while (!arc) 1775 1776 if (!arc) 1777 if (pcEntries) 1778 *pcEntries = usCurrent; 1779 } 1780 1781 return (arc); 1782 } 1783 1784 /* 1785 *@@ Compare: 1786 * binary search helper 1787 * 1788 *@@added V0.9.9 (2001-04-01) [lafaix] 1789 */ 1790 1791 int Compare(const void *key, 1792 const void *element) 1793 { 1794 USHORT usOrdinal = *((PUSHORT) key); 1795 PFSYSFUNCTION pFunction = (PFSYSFUNCTION)element; 1796 1797 if (usOrdinal > pFunction->ulOrdinal) 1798 return (1); 1799 else if (usOrdinal < pFunction->ulOrdinal) 1800 return (-1); 1801 else 1802 return (0); 1642 1803 } 1643 1804 … … 1651 1812 * 1652 1813 *@@added V0.9.9 (2001-03-30) [lafaix] 1653 */ 1654 1655 VOID ScanNameTable(PEXECUTABLE pExec, 1656 ULONG cFunctions, 1657 PFSYSFUNCTION paFunctions) 1658 { 1659 USHORT usOrdinal; 1660 ULONG ulDummy; 1661 1662 while (TRUE) 1814 *@@changed V0.9.9 (2001-04-02) [lafaix]: the first entry is special 1815 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1816 */ 1817 1818 APIRET ScanNameTable(PEXECUTABLE pExec, 1819 ULONG cFunctions, 1820 PFSYSFUNCTION paFunctions) 1821 { 1822 APIRET arc = NO_ERROR; 1823 ULONG ulDummy; 1824 1825 USHORT usOrdinal; 1826 PFSYSFUNCTION pFunction; 1827 BOOL bFirst = TRUE; 1828 1829 while (!arc) // V0.9.9 (2001-04-03) [umoeller] 1663 1830 { 1664 1831 BYTE bLen; 1665 CHAR achName[ 128];1832 CHAR achName[256]; 1666 1833 int i; 1667 1834 1668 DosRead(pExec->hfExe, 1669 &bLen, 1670 1, 1671 &ulDummy); 1672 1673 if (bLen == 0) 1674 // end of the name table 1675 break; 1676 1677 bLen &= 0x7F; 1678 1679 DosRead(pExec->hfExe, 1680 &achName, 1681 bLen, 1682 &ulDummy); 1683 achName[bLen] = 0; 1684 1685 DosRead(pExec->hfExe, 1686 &usOrdinal, 1687 sizeof(USHORT), 1688 &ulDummy); 1689 1690 for (i = 0; i < cFunctions; i++) 1691 { 1692 if (paFunctions[i].ulOrdinal == usOrdinal) 1835 if (!(arc = DosRead(pExec->hfExe, 1836 &bLen, 1837 1, 1838 &ulDummy))) 1839 { 1840 if (bLen == 0) 1841 // end of the name table 1842 break; 1843 1844 // the LX docs says that len is limited to 127 (the 8th bit being 1845 // reserved for future use); but does this applies to 16bits 1846 // tables too? 1847 // in any case, we must skip the first entry (module name in the 1848 // resident name table, and module description in non-resident 1849 // name table) 1850 if (bFirst) 1851 bFirst = FALSE; 1852 else 1853 bLen &= 0x7F; 1854 1855 if (!(arc = DosRead(pExec->hfExe, 1856 &achName, 1857 bLen, 1858 &ulDummy))) 1693 1859 { 1694 memcpy(paFunctions[i].achFunctionName, 1695 achName, 1696 bLen+1); 1697 break; 1860 achName[bLen] = 0; 1861 1862 if (!(arc = DosRead(pExec->hfExe, 1863 &usOrdinal, 1864 sizeof(USHORT), 1865 &ulDummy))) 1866 { 1867 if ((pFunction = bsearch(&usOrdinal, 1868 paFunctions, 1869 cFunctions, 1870 sizeof(FSYSFUNCTION), 1871 Compare))) 1872 { 1873 memcpy(pFunction->achFunctionName, 1874 achName, 1875 bLen+1); 1876 } 1877 } 1698 1878 } 1699 1879 } 1700 1880 } 1881 1882 return (arc); 1701 1883 } 1702 1884 … … 1712 1894 * functions. Empty export entries are _not_ included. 1713 1895 * 1896 * This returns a standard OS/2 error code, which might be 1897 * any of the codes returned by DosSetFilePtr and DosRead. 1898 * In addition, this may return: 1899 * 1900 * -- ERROR_NOT_ENOUGH_MEMORY 1901 * 1902 * -- ERROR_INVALID_EXE_SIGNATURE: exe is in a format other 1903 * than LX or NE, which is not understood by this function. 1904 * 1905 * -- If ERROR_INVALID_LIST_FORMAT is returned, the format of an 1906 * export entry wasn't understood here. 1907 * 1908 * Even if NO_ERROR is returned, the array pointer might still 1909 * be NULL if the module contains no such data. 1910 * 1714 1911 *@@added V0.9.9 (2001-03-11) [lafaix] 1715 */ 1716 1717 PFSYSFUNCTION doshExecQueryExportedFunctions(PEXECUTABLE pExec, 1718 PULONG pcFunctions) 1719 { 1720 ULONG cFunctions = 0; 1721 PFSYSFUNCTION paFunctions = NULL; 1722 1723 if (pExec) 1912 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1913 */ 1914 1915 APIRET doshExecQueryExportedFunctions(PEXECUTABLE pExec, 1916 PFSYSFUNCTION *ppaFunctions, // out: functions array 1917 PULONG pcFunctions) // out: array item count 1918 { 1919 APIRET arc = NO_ERROR; 1920 1921 if ( (pExec) 1922 && (pExec->ulOS == EXEOS_OS2) 1923 ) 1724 1924 { 1725 if (pExec->ulOS == EXEOS_OS2) 1726 { 1727 ULONG ulDummy; 1728 1729 if (pExec->ulExeFormat == EXEFORMAT_LX) 1925 ULONG cFunctions = 0; 1926 PFSYSFUNCTION paFunctions = NULL; 1927 1928 ULONG ulDummy; 1929 1930 if (pExec->ulExeFormat == EXEFORMAT_LX) 1931 { 1932 // It's a 32bit OS/2 executable 1933 1934 // the number of exported entry points is not stored 1935 // in the executable header; we have to count them in 1936 // the entry table 1937 1938 if (!(arc = ScanLXEntryTable(pExec, 1939 NULL, 1940 &cFunctions))) 1730 1941 { 1731 // It's a 32bit OS/2 executable1732 1733 // the number of exported entry points is not stored1734 // in the executable header; we have to count them in1735 // the entry table1736 1737 cFunctions = ScanLXEntryTable(pExec, NULL);1738 1739 1942 // we now have the number of exported entries; let us 1740 1943 // build them … … 1742 1945 if (cFunctions) 1743 1946 { 1744 paFunctions = (PFSYSFUNCTION)malloc(sizeof(FSYSFUNCTION) * cFunctions); 1745 1746 // we rescan the entry table (the cost is not as bad 1747 // as it may seem, due to disk caching) 1748 1749 ScanLXEntryTable(pExec, paFunctions); 1750 1751 // we now scan the resident name table entries 1752 DosSetFilePtr(pExec->hfExe, 1753 pExec->pLXHeader->ulResdNameTblOfs 1754 + pExec->pDosExeHeader->ulNewHeaderOfs, 1755 FILE_BEGIN, 1756 &ulDummy); 1757 1758 ScanNameTable(pExec, cFunctions, paFunctions); 1759 1760 // we now scan the non-resident name table entries, 1761 // whose offset is _from the begining of the file_ 1762 DosSetFilePtr(pExec->hfExe, 1763 pExec->pLXHeader->ulNonResdNameTblOfs, 1764 FILE_BEGIN, 1765 &ulDummy); 1766 1767 ScanNameTable(pExec, cFunctions, paFunctions); 1947 ULONG cb = sizeof(FSYSFUNCTION) * cFunctions; 1948 1949 paFunctions = (PFSYSFUNCTION)malloc(cb); 1950 if (!paFunctions) 1951 arc = ERROR_NOT_ENOUGH_MEMORY; // V0.9.9 (2001-04-03) [umoeller] 1952 else 1953 { 1954 // we rescan the entry table (the cost is not as bad 1955 // as it may seem, due to disk caching) 1956 1957 if ( (!(arc = ScanLXEntryTable(pExec, paFunctions, NULL))) 1958 // we now scan the resident name table entries 1959 && (!(arc = DosSetFilePtr(pExec->hfExe, 1960 pExec->pLXHeader->ulResdNameTblOfs 1961 + pExec->pDosExeHeader->ulNewHeaderOfs, 1962 FILE_BEGIN, 1963 &ulDummy))) 1964 && (!(arc = ScanNameTable(pExec, cFunctions, paFunctions))) 1965 // we now scan the non-resident name table entries, 1966 // whose offset is _from the begining of the file_ 1967 && (!(arc = DosSetFilePtr(pExec->hfExe, 1968 pExec->pLXHeader->ulNonResdNameTblOfs, 1969 FILE_BEGIN, 1970 &ulDummy))) 1971 ) 1972 { 1973 arc = ScanNameTable(pExec, cFunctions, paFunctions); 1974 } 1975 } 1768 1976 } // end if (cFunctions) 1769 1977 } 1770 else 1771 if (pExec->ulExeFormat == EXEFORMAT_NE) 1978 } 1979 else if (pExec->ulExeFormat == EXEFORMAT_NE) 1980 { 1981 // It's a 16bit OS/2 executable 1982 1983 // here too the number of exported entry points 1984 // is not stored in the executable header; we 1985 // have to count them in the entry table 1986 1987 if (!(arc = ScanNEEntryTable(pExec, 1988 NULL, 1989 &cFunctions))) 1772 1990 { 1773 // It's a 16bit OS/2 executable1774 1775 // here too the number of exported entry points1776 // is not stored in the executable header; we1777 // have to count them in the entry table1778 1779 cFunctions = ScanNEEntryTable(pExec, NULL);1780 1781 1991 // we now have the number of exported entries; let us 1782 1992 // build them … … 1788 1998 1789 1999 paFunctions = (PFSYSFUNCTION)malloc(sizeof(FSYSFUNCTION) * cFunctions); 1790 1791 // we rescan the entry table (the cost is not as bad 1792 // as it may seem, due to disk caching) 1793 1794 ScanNEEntryTable(pExec, paFunctions); 1795 1796 // we now scan the resident name table entries 1797 DosSetFilePtr(pExec->hfExe, 1798 pExec->pNEHeader->usResdNameTblOfs 1799 + pExec->pDosExeHeader->ulNewHeaderOfs, 1800 FILE_BEGIN, 1801 &ulDummy); 1802 1803 ScanNameTable(pExec, cFunctions, paFunctions); 1804 1805 // we now scan the non-resident name table entries, 1806 // whose offset is _from the begining of the file_ 1807 DosSetFilePtr(pExec->hfExe, 1808 pExec->pNEHeader->ulNonResdTblOfs, 1809 FILE_BEGIN, 1810 &ulDummy); 1811 1812 ScanNameTable(pExec, cFunctions, paFunctions); 2000 if (!paFunctions) 2001 arc = ERROR_NOT_ENOUGH_MEMORY; 2002 else 2003 { 2004 // we rescan the entry table (the cost is not as bad 2005 // as it may seem, due to disk caching) 2006 2007 if ( (!(arc = ScanNEEntryTable(pExec, paFunctions, NULL))) 2008 // we now scan the resident name table entries 2009 && (!(arc = DosSetFilePtr(pExec->hfExe, 2010 pExec->pNEHeader->usResdNameTblOfs 2011 + pExec->pDosExeHeader->ulNewHeaderOfs, 2012 FILE_BEGIN, 2013 &ulDummy))) 2014 && (!(arc = ScanNameTable(pExec, cFunctions, paFunctions))) 2015 // we now scan the non-resident name table entries, 2016 // whose offset is _from the begining of the file_ 2017 && (!(arc = DosSetFilePtr(pExec->hfExe, 2018 pExec->pNEHeader->ulNonResdTblOfs, 2019 FILE_BEGIN, 2020 &ulDummy))) 2021 ) 2022 { 2023 arc = ScanNameTable(pExec, cFunctions, paFunctions); 2024 } 2025 } 1813 2026 } 1814 2027 } 1815 2028 } 2029 else 2030 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 2031 2032 if (arc) // V0.9.9 (2001-04-03) [umoeller] 2033 { 2034 // if we had an error above, clean up 2035 if (paFunctions) 2036 free(paFunctions); 2037 } 2038 else 2039 { 2040 // no error: output data 2041 *ppaFunctions = paFunctions; 1816 2042 *pcFunctions = cFunctions; 1817 2043 } 1818 2044 } 1819 1820 return (paFunctions); 2045 else 2046 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 2047 2048 return (arc); 1821 2049 } 1822 2050 … … 1830 2058 APIRET doshExecFreeExportedFunctions(PFSYSFUNCTION paFunctions) 1831 2059 { 1832 free(paFunctions); 2060 if (paFunctions) // V0.9.9 (2001-04-04) [umoeller] 2061 free(paFunctions); 1833 2062 return (NO_ERROR); 1834 2063 } … … 1842 2071 * (not the array size!). Use doshExecFreeResources to clean up. 1843 2072 * 2073 * This returns a standard OS/2 error code, which might be 2074 * any of the codes returned by DosSetFilePtr and DosRead. 2075 * In addition, this may return: 2076 * 2077 * -- ERROR_NOT_ENOUGH_MEMORY 2078 * 2079 * -- ERROR_INVALID_EXE_SIGNATURE: exe is in a format other 2080 * than LX or NE, which is not understood by this function. 2081 * 2082 * Even if NO_ERROR is returned, the array pointer might still 2083 * be NULL if the module contains no such data. 2084 * 1844 2085 *@@added V0.9.7 (2000-12-18) [lafaix] 1845 */ 1846 1847 PFSYSRESOURCE doshExecQueryResources(PEXECUTABLE pExec, PULONG pcResources) 1848 { 1849 ULONG cResources = 0; 1850 PFSYSRESOURCE paResources = NULL; 1851 int i; 1852 1853 if (pExec) 2086 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 2087 */ 2088 2089 APIRET doshExecQueryResources(PEXECUTABLE pExec, // in: executable from doshExecOpen 2090 PFSYSRESOURCE *ppaResources, // out: res's array 2091 PULONG pcResources) // out: array item count 2092 { 2093 APIRET arc = NO_ERROR; 2094 2095 if ( (pExec) 2096 && (pExec->ulOS == EXEOS_OS2) 2097 ) 1854 2098 { 1855 if (pExec->ulOS == EXEOS_OS2) 1856 { 1857 ULONG ulDummy; 1858 1859 if (pExec->ulExeFormat == EXEFORMAT_LX) 2099 ULONG cResources = 0; 2100 PFSYSRESOURCE paResources = NULL; 2101 2102 if (pExec->ulExeFormat == EXEFORMAT_LX) 2103 { 2104 // 32-bit OS/2 executable: 2105 if (cResources = pExec->pLXHeader->ulResTblCnt) 1860 2106 { 1861 // It's a 32bit OS/2 executable 1862 cResources = pExec->pLXHeader->ulResTblCnt; 1863 1864 if (cResources) 2107 ULONG cb = sizeof(FSYSRESOURCE) * cResources; 2108 paResources = (PFSYSRESOURCE)malloc(cb); 2109 if (!paResources) 2110 arc = ERROR_NOT_ENOUGH_MEMORY; 2111 else 1865 2112 { 1866 struct rsrc32 /* Resource Table Entry */ 2113 ULONG ulDummy; 2114 2115 memset(paResources, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 2116 2117 // V0.9.9 (2001-04-03) [umoeller]: 2118 // Martin, I added error checking to all the below 2119 // Dos* calls. You can't just read around a file 2120 // and assume it will always be valid... especially 2121 // if you fill dynamically allocated memory. 2122 if (!(arc = DosSetFilePtr(pExec->hfExe, 2123 pExec->pLXHeader->ulResTblOfs 2124 + pExec->pDosExeHeader->ulNewHeaderOfs, 2125 FILE_BEGIN, 2126 &ulDummy))) 1867 2127 { 1868 unsigned short type; /* Resource type */ 1869 unsigned short name; /* Resource name */ 1870 unsigned long cb; /* Resource size */ 1871 unsigned short obj; /* Object number */ 1872 unsigned long offset; /* Offset within object */ 1873 } rs; 1874 1875 struct o32_obj /* Flat .EXE object table entry */ 2128 int i; 2129 2130 // V0.9.9 (2001-04-03) [umoeller]: 2131 // Besides, packing was missing. 2132 #pragma pack(1) // V0.9.9 (2001-04-02) [umoeller] 2133 struct rsrc32 /* Resource Table Entry */ 2134 { 2135 unsigned short type; /* Resource type */ 2136 unsigned short name; /* Resource name */ 2137 unsigned long cb; /* Resource size */ 2138 unsigned short obj; /* Object number */ 2139 unsigned long offset; /* Offset within object */ 2140 } rs; 2141 2142 struct o32_obj /* Flat .EXE object table entry */ 2143 { 2144 unsigned long o32_size; /* Object virtual size */ 2145 unsigned long o32_base; /* Object base virtual address */ 2146 unsigned long o32_flags; /* Attribute flags */ 2147 unsigned long o32_pagemap; /* Object page map index */ 2148 unsigned long o32_mapsize; /* Number of entries in object page map */ 2149 unsigned long o32_reserved; /* Reserved */ 2150 } ot; 2151 #pragma pack() // V0.9.9 (2001-04-03) [umoeller] 2152 2153 for (i = 0; i < cResources; i++) 2154 { 2155 arc = DosRead(pExec->hfExe, 2156 &rs, 2157 14, 2158 &ulDummy); 2159 if (arc) 2160 break; // V0.9.9 (2001-04-03) [umoeller] 2161 else 2162 { 2163 paResources[i].ulID = rs.name; 2164 paResources[i].ulType = rs.type; 2165 paResources[i].ulSize = rs.cb; 2166 paResources[i].ulFlag = rs.obj; // Temp storage for Object 2167 // number. Will be filled 2168 // with resource flag 2169 // later. 2170 } 2171 } 2172 2173 if (!arc) // V0.9.9 (2001-04-03) [umoeller] 2174 { 2175 for (i = 0; i < cResources; i++) 2176 { 2177 ULONG ulOfsThis 2178 = pExec->pLXHeader->ulObjTblOfs 2179 + pExec->pDosExeHeader->ulNewHeaderOfs 2180 + ( sizeof(ot) 2181 * (paResources[i].ulFlag - 1)); 2182 2183 if (!(arc = DosSetFilePtr(pExec->hfExe, 2184 ulOfsThis, 2185 FILE_BEGIN, 2186 &ulDummy))) 2187 { 2188 if (!(arc = DosRead(pExec->hfExe, 2189 &ot, 2190 sizeof(ot), 2191 &ulDummy))) 2192 { 2193 paResources[i].ulFlag = ((ot.o32_flags & OBJWRITE) 2194 ? 0 2195 : RNPURE); 2196 paResources[i].ulFlag |= ((ot.o32_flags & OBJDISCARD) 2197 ? 4096 2198 : 0); 2199 paResources[i].ulFlag |= ((ot.o32_flags & OBJSHARED) 2200 ? RNMOVE 2201 : 0); 2202 paResources[i].ulFlag |= ((ot.o32_flags & OBJPRELOAD) 2203 ? RNPRELOAD 2204 : 0); 2205 } 2206 } 2207 2208 if (arc) 2209 break; // V0.9.9 (2001-04-03) [umoeller] 2210 } // end for 2211 } 2212 } // end if !DosSetFilePtr(pExec->hfExe, 2213 } // end if paResources = (PFSYSRESOURCE)malloc(sizeof(FSYSRESOURCE) * cResources); 2214 } // end if (cResources) 2215 } // end if (pExec->ulExeFormat == EXEFORMAT_LX) 2216 else if (pExec->ulExeFormat == EXEFORMAT_NE) 2217 { 2218 // 16-bit OS/2 executable: 2219 if (cResources = pExec->pNEHeader->usResSegmCount) 2220 { 2221 #pragma pack(1) // V0.9.9 (2001-04-02) [umoeller] 2222 struct {unsigned short type; unsigned short name;} rti; 2223 struct new_seg /* New .EXE segment table entry */ 2224 { 2225 unsigned short ns_sector; /* File sector of start of segment */ 2226 unsigned short ns_cbseg; /* Number of bytes in file */ 2227 unsigned short ns_flags; /* Attribute flags */ 2228 unsigned short ns_minalloc; /* Minimum allocation in bytes */ 2229 } ns; 2230 #pragma pack() 2231 2232 ULONG cb = sizeof(FSYSRESOURCE) * cResources; 2233 2234 paResources = (PFSYSRESOURCE)malloc(cb); 2235 if (!paResources) 2236 arc = ERROR_NOT_ENOUGH_MEMORY; 2237 else 2238 { 2239 ULONG ulDummy; 2240 2241 memset(paResources, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 2242 2243 // we first read the resources IDs and types 2244 if (!(arc = DosSetFilePtr(pExec->hfExe, 2245 pExec->pNEHeader->usResTblOfs 2246 + pExec->pDosExeHeader->ulNewHeaderOfs, 2247 FILE_BEGIN, 2248 &ulDummy))) 1876 2249 { 1877 unsigned long o32_size; /* Object virtual size */ 1878 unsigned long o32_base; /* Object base virtual address */ 1879 unsigned long o32_flags; /* Attribute flags */ 1880 unsigned long o32_pagemap; /* Object page map index */ 1881 unsigned long o32_mapsize; /* Number of entries in object page map */ 1882 unsigned long o32_reserved; /* Reserved */ 1883 } ot; 1884 1885 paResources = (PFSYSRESOURCE)malloc(sizeof(FSYSRESOURCE) * cResources); 1886 1887 DosSetFilePtr(pExec->hfExe, 1888 pExec->pLXHeader->ulResTblOfs 1889 + pExec->pDosExeHeader->ulNewHeaderOfs, 1890 FILE_BEGIN, 1891 &ulDummy); 1892 1893 for (i = 0; i < cResources; i++) 1894 { 1895 DosRead(pExec->hfExe, &rs, 14, &ulDummy); 1896 paResources[i].ulID = rs.name; 1897 paResources[i].ulType = rs.type; 1898 paResources[i].ulSize = rs.cb; 1899 paResources[i].ulFlag = rs.obj; // Temp storage for Object 1900 // number. Will be filled 1901 // with resource flag 1902 // later. 1903 } 1904 1905 for (i = 0; i < cResources; i++) 1906 { 1907 DosSetFilePtr(pExec->hfExe, 1908 pExec->pLXHeader->ulObjTblOfs 1909 + pExec->pDosExeHeader->ulNewHeaderOfs 1910 + ( sizeof(ot) 1911 * (paResources[i].ulFlag - 1)), 1912 FILE_BEGIN, 1913 &ulDummy); 1914 DosRead(pExec->hfExe, &ot, sizeof(ot), &ulDummy); 1915 1916 paResources[i].ulFlag = (ot.o32_flags & OBJWRITE) ? 0 : RNPURE; 1917 paResources[i].ulFlag |= (ot.o32_flags & OBJDISCARD) ? 4096 : 0; 1918 paResources[i].ulFlag |= (ot.o32_flags & OBJSHARED) ? RNMOVE : 0; 1919 paResources[i].ulFlag |= (ot.o32_flags & OBJPRELOAD) ? RNPRELOAD : 0; 1920 } 1921 } 1922 } 1923 else 1924 if (pExec->ulExeFormat == EXEFORMAT_NE) 1925 { 1926 // It's a 16bit OS/2 executable 1927 cResources = pExec->pNEHeader->usResSegmCount; 1928 1929 if (cResources) 1930 { 1931 struct {unsigned short type; unsigned short name;} rti; 1932 struct new_seg /* New .EXE segment table entry */ 1933 { 1934 unsigned short ns_sector; /* File sector of start of segment */ 1935 unsigned short ns_cbseg; /* Number of bytes in file */ 1936 unsigned short ns_flags; /* Attribute flags */ 1937 unsigned short ns_minalloc; /* Minimum allocation in bytes */ 1938 } ns; 1939 1940 paResources = (PFSYSRESOURCE)malloc(sizeof(FSYSRESOURCE) * cResources); 1941 1942 // We first read the resources IDs and types 1943 DosSetFilePtr(pExec->hfExe, 1944 pExec->pNEHeader->usResTblOfs 1945 + pExec->pDosExeHeader->ulNewHeaderOfs, 1946 FILE_BEGIN, 1947 &ulDummy); 1948 1949 for (i = 0; i < cResources; i++) 1950 { 1951 DosRead(pExec->hfExe, &rti, sizeof(rti), &ulDummy); 1952 paResources[i].ulID = rti.name; 1953 paResources[i].ulType = rti.type; 1954 } 1955 1956 // And we then read their sizes and flags 1957 for (i = 0; i < cResources; i++) 1958 { 1959 DosSetFilePtr(pExec->hfExe, 1960 pExec->pDosExeHeader->ulNewHeaderOfs 1961 + pExec->pNEHeader->usSegTblOfs 1962 + (sizeof(ns) 1963 * ( pExec->pNEHeader->usSegTblEntries 1964 - pExec->pNEHeader->usResSegmCount 1965 + i)), 1966 FILE_BEGIN, 1967 &ulDummy); 1968 DosRead(pExec->hfExe, &ns, sizeof(ns), &ulDummy); 1969 1970 paResources[i].ulSize = ns.ns_cbseg; 1971 1972 paResources[i].ulFlag = (ns.ns_flags & OBJPRELOAD) ? RNPRELOAD : 0; 1973 paResources[i].ulFlag |= (ns.ns_flags & OBJSHARED) ? RNPURE : 0; 1974 paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? RNMOVE : 0; 1975 paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? 4096 : 0; 1976 } 1977 } 1978 } 1979 2250 int i; 2251 2252 for (i = 0; i < cResources; i++) 2253 { 2254 arc = DosRead(pExec->hfExe, &rti, sizeof(rti), &ulDummy); 2255 if (arc) 2256 break; 2257 else 2258 { 2259 paResources[i].ulID = rti.name; 2260 paResources[i].ulType = rti.type; 2261 } 2262 } 2263 2264 if (!arc) 2265 { 2266 // we then read their sizes and flags 2267 for (i = 0; i < cResources; i++) 2268 { 2269 if (!(arc = DosSetFilePtr(pExec->hfExe, 2270 pExec->pDosExeHeader->ulNewHeaderOfs 2271 + pExec->pNEHeader->usSegTblOfs 2272 + (sizeof(ns) 2273 * ( pExec->pNEHeader->usSegTblEntries 2274 - pExec->pNEHeader->usResSegmCount 2275 + i)), 2276 FILE_BEGIN, 2277 &ulDummy))) 2278 { 2279 if (!(arc = DosRead(pExec->hfExe, 2280 &ns, 2281 sizeof(ns), 2282 &ulDummy))) 2283 { 2284 paResources[i].ulSize = ns.ns_cbseg; 2285 2286 paResources[i].ulFlag = (ns.ns_flags & OBJPRELOAD) ? RNPRELOAD : 0; 2287 paResources[i].ulFlag |= (ns.ns_flags & OBJSHARED) ? RNPURE : 0; 2288 paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? RNMOVE : 0; 2289 paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? 4096 : 0; 2290 } 2291 } 2292 2293 if (arc) 2294 break; // V0.9.9 (2001-04-04) [umoeller] 2295 } // end for 2296 } 2297 } // end if !arc = DosSetFilePtr(pExec->hfExe, 2298 } // end if paResources = (PFSYSRESOURCE)malloc(sizeof(FSYSRESOURCE) * cResources); 2299 } // end if (cResources) 2300 } // end else if (pExec->ulExeFormat == EXEFORMAT_NE) 2301 else 2302 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 2303 2304 if (arc) // V0.9.9 (2001-04-03) [umoeller] 2305 { 2306 // if we had an error above, clean up 2307 if (paResources) 2308 free(paResources); 2309 } 2310 else 2311 { 2312 // no error: output data 2313 *ppaResources = paResources; 1980 2314 *pcResources = cResources; 1981 2315 } 1982 2316 } 1983 1984 return (paResources); 2317 else 2318 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 2319 2320 return (arc); 1985 2321 } 1986 2322 … … 1994 2330 APIRET doshExecFreeResources(PFSYSRESOURCE paResources) 1995 2331 { 1996 free(paResources); 2332 if (paResources) // V0.9.9 (2001-04-04) [umoeller] 2333 free(paResources); 1997 2334 return (NO_ERROR); 1998 2335 } … … 2038 2375 * 2039 2376 *@@added V0.9.0 [umoeller] 2377 *@@changed V0.9.9 (2001-04-04) [umoeller]: added more error checking 2040 2378 */ 2041 2379 … … 2046 2384 USHORT sector) 2047 2385 { 2048 UINT arc; 2049 HFILE dh = 0; 2050 char dn[256]; 2051 // char ms[256]; 2052 2053 sprintf( dn, "%u:", disk ); 2054 arc = DosPhysicalDisk(INFO_GETIOCTLHANDLE, &dh, 2, dn, 3); 2055 2056 if (arc) 2057 // error: 2058 return (arc); 2059 else 2386 APIRET arc; 2387 HFILE dh = 0; 2388 char dn[256]; 2389 2390 sprintf(dn, "%u:", disk); 2391 if (!(arc = DosPhysicalDisk(INFO_GETIOCTLHANDLE, &dh, 2, dn, 3))) 2060 2392 { 2061 2393 TRACKLAYOUT DiskIOParm; … … 2076 2408 buff , IOCtlDataLength, &IOCtlDataLength); 2077 2409 2078 if(arc)2079 {2080 // error:2081 DosPhysicalDisk(INFO_FREEIOCTLHANDLE, 0, 0, &dh, 2);2082 return (arc);2083 }2084 2085 2410 DosPhysicalDisk(INFO_FREEIOCTLHANDLE, 0, 0, &dh, 2); 2086 2411 } 2087 return (NO_ERROR); 2412 2413 return (arc); 2088 2414 } 2089 2415 … … 2221 2547 */ 2222 2548 2223 c har* doshType2FSName(unsigned char bFSType) // in: FS type2549 const char* doshType2FSName(unsigned char bFSType) // in: FS type 2224 2550 { 2225 2551 PSZ zFSName = NULL; … … 2459 2785 static USHORT GetCyl(USHORT rBeginSecCyl) 2460 2786 { 2461 return ( (rBeginSecCyl & 0x00C0) << 2) +2462 ((rBeginSecCyl & 0xFF00) >> 8);2787 return ( (rBeginSecCyl & 0x00C0) << 2) 2788 + ((rBeginSecCyl & 0xFF00) >> 8); 2463 2789 } 2464 2790 … … 2557 2883 UINT iDisk) // in: system's physical disk count 2558 2884 { 2559 APIRET arc = NO_ERROR; 2560 MBR_INFO MBoot; // Master Boot 2561 SYS_INFO MName[32]; // Name Space from Boot Manager 2562 USHORT i; 2563 2564 memset(&MName, 0, sizeof(MName)); 2565 2566 if (BmInfo) 2885 APIRET arc = NO_ERROR; 2886 2887 if (!BmInfo) 2888 arc = ERROR_INVALID_PARAMETER; 2889 else 2567 2890 { 2891 SYS_INFO MName[32]; // Name Space from Boot Manager 2892 memset(&MName, 0, sizeof(MName)); 2893 2568 2894 // read boot manager name table 2569 if ((arc = doshReadSector(BmDisk, &MName, BmInfo->bBeginHead, 2570 GetCyl(BmInfo->rBeginSecCyl), 2571 GetSec(BmInfo->rBeginSecCyl) + 3))) 2572 return (arc); 2573 } 2574 2575 // read master boot record 2576 if ((arc = doshReadSector(iDisk, &MBoot, 0, 0, 1))) 2577 return (arc); 2578 2579 for (i = 0; 2580 i < 4; // there can be only four primary partitions 2581 i++) 2582 { 2583 // skip unused partition, BootManager or Extended partition 2584 if ( (MBoot.sPrtnInfo[i].bFileSysCode) // skip unused 2585 && (MBoot.sPrtnInfo[i].bFileSysCode != PAR_BOOTMANAGER) // skip boot manager 2586 && (MBoot.sPrtnInfo[i].bFileSysCode != PAR_EXTENDED) // skip extended 2587 ) 2588 { 2589 BOOL fBootable = ( (BmInfo) 2590 && (MName[(iDisk-1) * 4 + i].bootable & 0x01) 2591 ); 2592 // store this partition 2593 if ((arc = AppendPartition(pppiFirst, 2594 pppiThis, 2595 posCount, 2596 iDisk, 2597 (fBootable) 2598 ? (char*)&MName[(iDisk - 1) * 4 + i].name 2599 : "", 2600 *pcLetter, 2601 MBoot.sPrtnInfo[i].bFileSysCode, 2602 TRUE, // primary 2603 fBootable, 2604 MBoot.sPrtnInfo[i].lTotalSects))) 2605 return (arc); 2895 if (!(arc = doshReadSector(BmDisk, 2896 &MName, 2897 BmInfo->bBeginHead, 2898 GetCyl(BmInfo->rBeginSecCyl), 2899 GetSec(BmInfo->rBeginSecCyl) + 3))) 2900 { 2901 MBR_INFO MBoot; // Master Boot 2902 USHORT i; 2903 2904 // read master boot record of this disk 2905 if (!(arc = doshReadSector(iDisk, &MBoot, 0, 0, 1))) 2906 { 2907 for (i = 0; 2908 i < 4; // there can be only four primary partitions 2909 i++) 2910 { 2911 // skip unused partition, BootManager or Extended partition 2912 if ( (MBoot.sPrtnInfo[i].bFileSysCode) // skip unused 2913 && (MBoot.sPrtnInfo[i].bFileSysCode != PAR_BOOTMANAGER) // skip boot manager 2914 && (MBoot.sPrtnInfo[i].bFileSysCode != PAR_EXTENDED) // skip extended 2915 ) 2916 { 2917 BOOL fBootable = ( (BmInfo) 2918 && (MName[(iDisk-1) * 4 + i].bootable & 0x01) 2919 ); 2920 // store this partition 2921 if ((arc = AppendPartition(pppiFirst, 2922 pppiThis, 2923 posCount, 2924 iDisk, 2925 (fBootable) 2926 ? (char*)&MName[(iDisk - 1) * 4 + i].name 2927 : "", 2928 *pcLetter, 2929 MBoot.sPrtnInfo[i].bFileSysCode, 2930 TRUE, // primary 2931 fBootable, 2932 MBoot.sPrtnInfo[i].lTotalSects))) 2933 return (arc); 2934 } 2935 } 2936 } 2606 2937 } 2607 2938 } 2608 return (NO_ERROR); 2939 2940 return (arc); 2609 2941 } 2610 2942 … … 2634 2966 USHORT i; 2635 2967 2636 if ((arc = doshReadSector(PrDisk, &MBoot, PrInfo->bBeginHead, 2968 if ((arc = doshReadSector(PrDisk, 2969 &MBoot, 2970 PrInfo->bBeginHead, 2637 2971 GetCyl(PrInfo->rBeginSecCyl), 2638 2972 GetSec(PrInfo->rBeginSecCyl)))) … … 2692 3026 return (arc); 2693 3027 } 2694 2695 /* // if BootManager installed and partition is bootable2696 if (BmInfo)2697 {2698 if (MBoot.sBmNames[i].bootable & 0x01)2699 {2700 }2701 }2702 2703 // if BootManager not installed2704 else2705 {2706 if (arc = AppendPartition(pppiFirst,2707 pppiThis,2708 posCount,2709 PrDisk,2710 "",2711 *pcLetter,2712 MBoot.sPrtnInfo[i].bFileSysCode,2713 FALSE,2714 MBoot.sPrtnInfo[i].lTotalSects))2715 return (arc);2716 } */2717 3028 } 2718 3029 … … 2795 3106 * If an error != NO_ERROR is returned, *pusContext 2796 3107 * will be set to one of the following: 3108 * 2797 3109 * -- 1: boot manager not found 3110 * 2798 3111 * -- 2: primary partitions error 3112 * 2799 3113 * -- 3: secondary partitions error 2800 3114 * … … 2832 3146 // on each disk, read primary partitions 2833 3147 for (i = 1; i <= cDisks; i++) 3148 { 2834 3149 if ((arc = GetPrimaryPartitions(&pPartitionInfos, 2835 3150 &ppiTemp, … … 2843 3158 return (arc); 2844 3159 } 3160 } 2845 3161 2846 3162 if (usBmDisk) … … 2850 3166 // with logical drives 2851 3167 for (i = 1; i <= cDisks; i++) 3168 { 2852 3169 if ((arc = GetExtendedPartition(&pPartitionInfos, 2853 3170 &ppiTemp, … … 2856 3173 &BmInfo, 2857 3174 i))) 2858 { 2859 *pusContext = 3; 2860 return (arc); 3175 { 3176 *pusContext = 3; 3177 return (arc); 3178 } 2861 3179 } 2862 3180 }
Note:
See TracChangeset
for help on using the changeset viewer.