Changeset 67
- Timestamp:
- May 3, 2001, 8:01:12 PM (24 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/helpers/dosh.h
r60 r67 481 481 typedef struct _NEHEADER 482 482 { 483 CHAR achNE[2]; // 00: NE483 CHAR achNE[2]; // 00: "NE" magic 484 484 BYTE bLinkerVersion; // 02: linker version 485 485 BYTE bLinkerRevision; // 03: linker revision … … 524 524 typedef struct _LXHEADER 525 525 { 526 CHAR achLX[2]; // 00: LX or LE 527 /* this is "LX" for 32-bit OS/2 programs, but 528 "LE" for MS-DOS progs which use this format 529 (e.g. WINDOWS\SMARTDRV.EXE) */ 526 CHAR achLX[2]; // 00: "LX" or "LE" magic 527 // this is "LX" for 32-bit OS/2 programs, but 528 // "LE" for MS-DOS progs which use this format 529 // (e.g. WINDOWS\SMARTDRV.EXE). IBM says the 530 // LE format was never released and superceded 531 // by LX... I am unsure what the differences are. 530 532 BYTE fByteBigEndian; // 02: byte ordering (1 = big endian) 531 533 BYTE fWordBigEndian; // 03: word ordering (1 = big endian) … … 716 718 doshExecOpen if NO_ERROR is returned. */ 717 719 718 // old DOS EXE header (always valid) 720 // old DOS EXE header; 721 // note: before 0.9.12, this was ALWAYS valid, 722 // but since we support NOSTUB executables now, 723 // there may be situations where this is NULL, 724 // but the other fields are valid! V0.9.12 (2001-05-03) [umoeller] 719 725 PDOSEXEHEADER pDosExeHeader; 720 726 ULONG cbDosExeHeader; … … 742 748 // EXEFORMAT_TEXT_REXX 6 743 749 744 BOOL fLibrary, 745 f32Bits; 750 BOOL fLibrary, // TRUE if this is a DLL 751 f32Bits; // TRUE if this a 32-bits module 752 746 753 ULONG ulOS; 747 // one of: 754 // target operating system as flagged in one of 755 // the EXE headers; one of: 748 756 // EXEOS_DOS3 1 749 757 // EXEOS_DOS4 2 // there is a flag for this in NE … … 751 759 // EXEOS_WIN16 4 752 760 // EXEOS_WIN386 5 // according to IBM, there are flags 753 //// for this both in NE and LX761 // for this both in NE and LX 754 762 // EXEOS_WIN32 6 755 763 -
trunk/src/helpers/dosh2.c
r64 r67 797 797 * -- ERROR_NOT_ENOUGH_MEMORY: malloc() failed. 798 798 * 799 * -- ERROR_INVALID_EXE_SIGNATURE: specified file 800 * has no DOS EXE header, or it does, but 801 * the extended header is neither LX nor 802 * NE nor PE. 799 * -- ERROR_INVALID_EXE_SIGNATURE: unknown 800 * executable type... the given file probably 801 * isn't even an executable. 803 802 * 804 803 * -- ERROR_INVALID_PARAMETER: ppExec is NULL. … … 806 805 * plus those of DosOpen, DosSetFilePtr, and 807 806 * DosRead. 807 * 808 * The following executable types are supported 809 * (see EXECUTABLE for details): 810 * 811 * -- Plain DOS 3.x executable without new header. 812 * 813 * -- New Executable (NE), used by Win16 and 814 * 16-bit OS/2 and still many of today's drivers. 815 * 816 * -- Linear Executable (LX), OS/2 2.x and above. 817 * 818 * -- Portable Executable (PE), used by Win32. 819 * 820 * V0.9.12 adds support for NOSTUB executables, 821 * which are new-style executables (NE or LX) 822 * without a leading DOS header. The executable 823 * then starts directly with the NE or LX header. 824 * I am not sure whether PE supports such things 825 * as well... if so, it should be supported too. 808 826 * 809 827 *@@added V0.9.0 [umoeller] … … 812 830 *@@changed V0.9.10 (2001-04-08) [lafaix]: added PE support 813 831 *@@changed V0.9.10 (2001-04-08) [umoeller]: now setting ppExec only if NO_ERROR is returned 832 *@@changed V0.9.12 (2001-05-03) [umoeller]: added support for NOSTUB newstyle executables 814 833 */ 815 834 … … 870 889 ) 871 890 { 891 ULONG ulNewHeaderOfs = 0; // V0.9.12 (2001-05-03) [umoeller] 892 BOOL fLoadNewHeader = FALSE; 893 872 894 // now check if we really have a DOS header 873 895 if (pExec->pDosExeHeader->usDosExeID != 0x5a4d) 874 arc = ERROR_INVALID_EXE_SIGNATURE; 896 { 897 // arc = ERROR_INVALID_EXE_SIGNATURE; 898 899 // V0.9.12 (2001-05-03) [umoeller] 900 // try loading new header directly; there are 901 // drivers which were built with NOSTUB, and 902 // the exe image starts out with the NE or LX 903 // image directly 904 fLoadNewHeader = TRUE; 905 // ulNewHeaderOfs is 0 now 906 907 // remove the DOS header info, since we have none 908 // V0.9.12 (2001-05-03) [umoeller] 909 free (pExec->pDosExeHeader); 910 pExec->pDosExeHeader = 0; 911 } 875 912 else 876 913 { … … 884 921 else 885 922 { 886 // either LX or PE or NE: 887 // read more bytes from position specified in header 888 CHAR achNewHeaderType[2] = ""; 889 890 if ( (!(arc = DosSetFilePtr(hFile, 891 pExec->pDosExeHeader->ulNewHeaderOfs, 892 FILE_BEGIN, 893 &ulLocal))) 894 // read two chars to find out header type 895 && (!(arc = DosRead(hFile, 896 &achNewHeaderType, 897 sizeof(achNewHeaderType), 898 &ulBytesRead))) 899 ) 923 // we have a new header offset: 924 fLoadNewHeader = TRUE; 925 ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs; 926 } 927 } 928 929 if (fLoadNewHeader) 930 { 931 // either LX or PE or NE: 932 // read in new header... 933 // ulNewHeaderOfs is now either 0 (if no DOS header 934 // was found) or pDosExeHeader->ulNewHeaderOfs 935 // V0.9.12 (2001-05-03) [umoeller] 936 CHAR achNewHeaderType[2] = ""; 937 938 if ( (!(arc = DosSetFilePtr(hFile, 939 ulNewHeaderOfs, 940 FILE_BEGIN, 941 &ulLocal))) 942 // read two chars to find out header type 943 && (!(arc = DosRead(hFile, 944 &achNewHeaderType, 945 sizeof(achNewHeaderType), 946 &ulBytesRead))) 947 ) 948 { 949 PBYTE pbCheckOS = NULL; 950 951 // reset file ptr 952 DosSetFilePtr(hFile, 953 ulNewHeaderOfs, 954 FILE_BEGIN, 955 &ulLocal); 956 957 if (memcmp(achNewHeaderType, "NE", 2) == 0) 900 958 { 901 PBYTE pbCheckOS = NULL; 902 903 // reset file ptr 904 DosSetFilePtr(hFile, 905 pExec->pDosExeHeader->ulNewHeaderOfs, 906 FILE_BEGIN, 907 &ulLocal); 908 909 if (memcmp(achNewHeaderType, "NE", 2) == 0) 959 // New Executable: 960 pExec->ulExeFormat = EXEFORMAT_NE; 961 // allocate NE header 962 pExec->pNEHeader = (PNEHEADER)malloc(sizeof(NEHEADER)); 963 if (!(pExec->pNEHeader)) 964 arc = ERROR_NOT_ENOUGH_MEMORY; 965 else 966 // read in NE header 967 if (!(arc = DosRead(hFile, 968 pExec->pNEHeader, 969 sizeof(NEHEADER), 970 &(pExec->cbNEHeader)))) 971 if (pExec->cbNEHeader == sizeof(NEHEADER)) 972 pbCheckOS = &(pExec->pNEHeader->bTargetOS); 973 } 974 else if ( (memcmp(achNewHeaderType, "LX", 2) == 0) 975 || (memcmp(achNewHeaderType, "LE", 2) == 0) 976 // this is used by SMARTDRV.EXE 977 ) 978 { 979 // OS/2 Linear Executable: 980 pExec->ulExeFormat = EXEFORMAT_LX; 981 // allocate LX header 982 pExec->pLXHeader = (PLXHEADER)malloc(sizeof(LXHEADER)); 983 if (!(pExec->pLXHeader)) 984 arc = ERROR_NOT_ENOUGH_MEMORY; 985 else 986 // read in LX header 987 if (!(arc = DosRead(hFile, 988 pExec->pLXHeader, 989 sizeof(LXHEADER), 990 &(pExec->cbLXHeader)))) 991 if (pExec->cbLXHeader == sizeof(LXHEADER)) 992 pbCheckOS = (PBYTE)(&(pExec->pLXHeader->usTargetOS)); 993 } 994 else if (memcmp(achNewHeaderType, "PE", 2) == 0) 995 { 996 PEHEADER PEHeader = {0}; 997 998 pExec->ulExeFormat = EXEFORMAT_PE; 999 pExec->ulOS = EXEOS_WIN32; 1000 pExec->f32Bits = TRUE; 1001 1002 // V0.9.10 (2001-04-08) [lafaix] 1003 // read in standard PE header 1004 if (!(arc = DosRead(hFile, 1005 &PEHeader, 1006 24, 1007 &ulBytesRead))) 910 1008 { 911 // New Executable: 912 pExec->ulExeFormat = EXEFORMAT_NE; 913 // allocate NE header 914 pExec->pNEHeader = (PNEHEADER)malloc(sizeof(NEHEADER)); 915 if (!(pExec->pNEHeader)) 1009 // allocate PE header 1010 pExec->pPEHeader = (PPEHEADER)malloc(24 + PEHeader.usHeaderSize); 1011 if (!(pExec->pPEHeader)) 916 1012 arc = ERROR_NOT_ENOUGH_MEMORY; 917 1013 else 918 // read in NE header 1014 { 1015 // copy standard PE header 1016 memcpy(pExec->pPEHeader, 1017 &PEHeader, 1018 24); 1019 1020 // read in optional PE header 919 1021 if (!(arc = DosRead(hFile, 920 pExec->pNEHeader, 921 sizeof(NEHEADER), 922 &(pExec->cbNEHeader)))) 923 if (pExec->cbNEHeader == sizeof(NEHEADER)) 924 pbCheckOS = &(pExec->pNEHeader->bTargetOS); 925 } 926 else if ( (memcmp(achNewHeaderType, "LX", 2) == 0) 927 || (memcmp(achNewHeaderType, "LE", 2) == 0) 928 // this is used by SMARTDRV.EXE 929 ) 930 { 931 // OS/2 Linear Executable: 932 pExec->ulExeFormat = EXEFORMAT_LX; 933 // allocate LX header 934 pExec->pLXHeader = (PLXHEADER)malloc(sizeof(LXHEADER)); 935 if (!(pExec->pLXHeader)) 936 arc = ERROR_NOT_ENOUGH_MEMORY; 937 else 938 // read in LX header 939 if (!(arc = DosRead(hFile, 940 pExec->pLXHeader, 941 sizeof(LXHEADER), 942 &(pExec->cbLXHeader)))) 943 if (pExec->cbLXHeader == sizeof(LXHEADER)) 944 pbCheckOS = (PBYTE)(&(pExec->pLXHeader->usTargetOS)); 945 } 946 else if (memcmp(achNewHeaderType, "PE", 2) == 0) 947 { 948 PEHEADER PEHeader = {0}; 949 950 pExec->ulExeFormat = EXEFORMAT_PE; 951 pExec->ulOS = EXEOS_WIN32; 952 pExec->f32Bits = TRUE; 953 954 // V0.9.10 (2001-04-08) [lafaix] 955 // read in standard PE header 956 if (!(arc = DosRead(hFile, 957 &PEHeader, 958 24, 959 &ulBytesRead))) 960 { 961 // allocate PE header 962 pExec->pPEHeader = (PPEHEADER)malloc(24 + PEHeader.usHeaderSize); 963 if (!(pExec->pPEHeader)) 964 arc = ERROR_NOT_ENOUGH_MEMORY; 965 else 966 { 967 // copy standard PE header 968 memcpy(pExec->pPEHeader, 969 &PEHeader, 970 24); 971 972 // read in optional PE header 973 if (!(arc = DosRead(hFile, 974 &(pExec->pPEHeader->usReserved3), 975 PEHeader.usHeaderSize, 976 &(pExec->cbPEHeader)))) 977 pExec->cbPEHeader += 24; 978 } 1022 &(pExec->pPEHeader->usReserved3), 1023 PEHeader.usHeaderSize, 1024 &(pExec->cbPEHeader)))) 1025 pExec->cbPEHeader += 24; 979 1026 } 980 1027 } 981 else 982 // strange type: 983 arc = ERROR_INVALID_EXE_SIGNATURE; 984 985 if (pbCheckOS) 986 // BYTE to check for operating system 987 // (NE and LX): 988 switch (*pbCheckOS) 989 { 990 case NEOS_OS2: 991 pExec->ulOS = EXEOS_OS2; 992 if (pExec->ulExeFormat == EXEFORMAT_LX) 993 pExec->f32Bits = TRUE; 994 break; 995 996 case NEOS_WIN16: 997 pExec->ulOS = EXEOS_WIN16; 998 break; 999 1000 case NEOS_DOS4: 1001 pExec->ulOS = EXEOS_DOS4; 1002 break; 1003 1004 case NEOS_WIN386: 1005 pExec->ulOS = EXEOS_WIN386; 1028 } 1029 else 1030 // strange type: 1031 arc = ERROR_INVALID_EXE_SIGNATURE; 1032 1033 if (pbCheckOS) 1034 // BYTE to check for operating system 1035 // (NE and LX): 1036 switch (*pbCheckOS) 1037 { 1038 case NEOS_OS2: 1039 pExec->ulOS = EXEOS_OS2; 1040 if (pExec->ulExeFormat == EXEFORMAT_LX) 1006 1041 pExec->f32Bits = TRUE; 1007 break; 1008 } 1009 } // end if (!(arc = DosSetFilePtr(hFile, 1010 } 1042 break; 1043 1044 case NEOS_WIN16: 1045 pExec->ulOS = EXEOS_WIN16; 1046 break; 1047 1048 case NEOS_DOS4: 1049 pExec->ulOS = EXEOS_DOS4; 1050 break; 1051 1052 case NEOS_WIN386: 1053 pExec->ulOS = EXEOS_WIN386; 1054 pExec->f32Bits = TRUE; 1055 break; 1056 } 1057 } // end if (!(arc = DosSetFilePtr(hFile, 1011 1058 } 1012 1059 } // end if (!(arc = DosSetFilePtr(hFile, … … 1273 1320 *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support 1274 1321 *@@changed V0.9.10 (2001-04-13) [lafaix]: removed 127 characters limit 1322 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support 1275 1323 */ 1276 1324 … … 1291 1339 int i; 1292 1340 1341 ULONG ulNewHeaderOfs = 0; // V0.9.12 (2001-05-03) [umoeller] 1342 1343 if (pExec->pDosExeHeader) 1344 // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller] 1345 ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs; 1346 1293 1347 if (pExec->ulExeFormat == EXEFORMAT_LX) 1294 1348 { … … 1298 1352 if (cModules) 1299 1353 { 1300 ULONG cb = sizeof(FSYSMODULE) * cModules; // V0.9.9 (2001-04-03) [umoeller]1301 ULONG ulDummy;1354 ULONG cb = sizeof(FSYSMODULE) * cModules; // V0.9.9 (2001-04-03) [umoeller] 1355 ULONG ulDummy; 1302 1356 1303 1357 paModules = (PFSYSMODULE)malloc(cb); … … 1309 1363 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1310 1364 pExec->pLXHeader->ulImportModTblOfs 1311 + pExec->pDosExeHeader->ulNewHeaderOfs,1365 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller] 1312 1366 FILE_BEGIN, 1313 1367 &ulDummy)); … … 1360 1414 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1361 1415 pExec->pNEHeader->usModRefTblOfs 1362 + pExec->pDosExeHeader->ulNewHeaderOfs1416 + ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller] 1363 1417 + sizeof(usOfs) * i, 1364 1418 FILE_BEGIN, … … 1369 1423 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1370 1424 pExec->pNEHeader->usImportTblOfs 1371 + pExec->pDosExeHeader->ulNewHeaderOfs1425 + ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller] 1372 1426 + usOfs, 1373 1427 FILE_BEGIN, … … 1384 1438 } // end for 1385 1439 } 1386 } 1440 } // end NE 1387 1441 else 1388 1442 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller] … … 1426 1480 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1427 1481 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code 1482 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support 1428 1483 */ 1429 1484 … … 1437 1492 int i; 1438 1493 1494 ULONG ulNewHeaderOfs = 0; // V0.9.12 (2001-05-03) [umoeller] 1495 1496 if (pExec->pDosExeHeader) 1497 // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller] 1498 ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs; 1499 1439 1500 ENSURE(DosSetFilePtr(pExec->hfExe, 1440 1501 pExec->pLXHeader->ulEntryTblOfs 1441 + pExec->pDosExeHeader->ulNewHeaderOfs,1502 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller] 1442 1503 FILE_BEGIN, 1443 1504 &ulDummy)); … … 1659 1720 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1660 1721 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code 1722 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support 1661 1723 */ 1662 1724 … … 1670 1732 int i; 1671 1733 1734 ULONG ulNewHeaderOfs = 0; 1735 1736 if (pExec->pDosExeHeader) 1737 // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller] 1738 ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs; 1739 1672 1740 ENSURE(DosSetFilePtr(pExec->hfExe, 1673 1741 pExec->pNEHeader->usEntryTblOfs 1674 + pExec->pDosExeHeader->ulNewHeaderOfs,1742 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller] 1675 1743 FILE_BEGIN, 1676 1744 &ulDummy)); … … 1849 1917 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code 1850 1918 *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support 1919 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support 1851 1920 */ 1852 1921 … … 1868 1937 ULONG ulDummy; 1869 1938 1939 ULONG ulNewHeaderOfs = 0; // V0.9.12 (2001-05-03) [umoeller] 1940 1941 if (pExec->pDosExeHeader) 1942 // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller] 1943 ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs; 1944 1870 1945 if (pExec->ulExeFormat == EXEFORMAT_LX) 1871 1946 { … … 1898 1973 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1899 1974 pExec->pLXHeader->ulResdNameTblOfs 1900 + pExec->pDosExeHeader->ulNewHeaderOfs,1975 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller] 1901 1976 FILE_BEGIN, 1902 1977 &ulDummy)); … … 1946 2021 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1947 2022 pExec->pNEHeader->usResdNameTblOfs 1948 + pExec->pDosExeHeader->ulNewHeaderOfs,2023 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller] 1949 2024 FILE_BEGIN, 1950 2025 &ulDummy)); … … 2018 2093 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 2019 2094 *@@changed V0.9.10 (2001-04-10) [lafaix]: added Win16 and Win386 support 2095 *@@changed V0.9.12 (2001-05-03) [umoeller]: adjusted for new NOSTUB support 2020 2096 */ 2021 2097 … … 2034 2110 ULONG cResources = 0; 2035 2111 PFSYSRESOURCE paResources = NULL; 2112 2113 ULONG ulNewHeaderOfs = 0; // V0.9.12 (2001-05-03) [umoeller] 2114 2115 if (pExec->pDosExeHeader) 2116 // executable has DOS stub: V0.9.12 (2001-05-03) [umoeller] 2117 ulNewHeaderOfs = pExec->pDosExeHeader->ulNewHeaderOfs; 2036 2118 2037 2119 if (pExec->ulExeFormat == EXEFORMAT_LX) … … 2075 2157 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 2076 2158 pExec->pLXHeader->ulResTblOfs 2077 + pExec->pDosExeHeader->ulNewHeaderOfs,2159 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller] 2078 2160 FILE_BEGIN, 2079 2161 &ulDummy)); … … 2095 2177 { 2096 2178 ULONG ulOfsThis = pExec->pLXHeader->ulObjTblOfs 2097 + pExec->pDosExeHeader->ulNewHeaderOfs2179 + ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller] 2098 2180 + ( sizeof(ot) 2099 2181 * (paResources[i].ulFlag - 1)); … … 2155 2237 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 2156 2238 pExec->pNEHeader->usResTblOfs 2157 + pExec->pDosExeHeader->ulNewHeaderOfs,2239 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller] 2158 2240 FILE_BEGIN, 2159 2241 &ulDummy)); … … 2172 2254 { 2173 2255 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 2174 pExec->pDosExeHeader->ulNewHeaderOfs2256 ulNewHeaderOfs // V0.9.12 (2001-05-03) [umoeller] 2175 2257 + pExec->pNEHeader->usSegTblOfs 2176 2258 + (sizeof(ns) … … 2200 2282 ENSURE(DosSetFilePtr(pExec->hfExe, 2201 2283 pExec->pNEHeader->usResTblOfs 2202 + pExec->pDosExeHeader->ulNewHeaderOfs,2284 + ulNewHeaderOfs, // V0.9.12 (2001-05-03) [umoeller] 2203 2285 FILE_BEGIN, 2204 2286 &ulDummy)); … … 2254 2336 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 2255 2337 pExec->pNEHeader->usResTblOfs 2256 + pExec->pDosExeHeader->ulNewHeaderOfs,2338 + ulNewHeaderOfs, 2257 2339 FILE_BEGIN, 2258 2340 &ulDummy));
Note:
See TracChangeset
for help on using the changeset viewer.