| 929 | }; |
| 930 | |
| 931 | int STORMAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer) |
| 932 | { |
| 933 | unsigned char * pbWorkBuffer = NULL; |
| 934 | unsigned char * pbOutBuffer = (unsigned char *)pvOutBuffer; |
| 935 | unsigned char * pbInBuffer = (unsigned char *)pvInBuffer; |
| 936 | unsigned char * pbOutput = (unsigned char *)pvOutBuffer; |
| 937 | unsigned char * pbInput; |
| 938 | unsigned uCompressionMask; // Decompressions applied to the data |
| 939 | unsigned uCompressionCopy; // Decompressions applied to the data |
| 940 | int cbOutBuffer = *pcbOutBuffer; // Current size of the output buffer |
| 941 | int cbInLength; // Current size of the input buffer |
| 942 | int nCompressCount = 0; // Number of compressions to be applied |
| 943 | int nCompressIndex = 0; |
| 944 | int nResult = 1; |
| 945 | |
| 946 | // Verify buffer sizes |
| 947 | if(cbOutBuffer < cbInBuffer || cbInBuffer < 1) |
| 948 | return 0; |
| 949 | |
| 950 | // If the input length is the same as output length, do nothing. |
| 951 | if(cbOutBuffer == cbInBuffer) |
| 952 | { |
| 953 | // If the buffers are equal, don't copy anything. |
| 954 | if(pvInBuffer != pvOutBuffer) |
| 955 | memcpy(pvOutBuffer, pvInBuffer, cbInBuffer); |
| 956 | return 1; |
| 957 | } |
| 958 | |
| 959 | // Get applied compression types and decrement data length |
| 960 | uCompressionMask = uCompressionCopy = (unsigned char)*pbInBuffer++; |
| 961 | cbInBuffer--; |
| 962 | |
| 963 | // Get current compressed data and length of it |
| 964 | pbInput = pbInBuffer; |
| 965 | cbInLength = cbInBuffer; |
| 966 | |
| 967 | // This compression function doesn't support LZMA |
| 968 | assert(uCompressionMask != MPQ_COMPRESSION_LZMA); |
| 969 | |
| 970 | // Parse the compression mask |
| 971 | for(size_t i = 0; i < (sizeof(dcmp_table) / sizeof(TDecompressTable)); i++) |
| 972 | { |
| 973 | // If the mask agrees, insert the compression function to the array |
| 974 | if(uCompressionMask & dcmp_table[i].uMask) |
| 975 | { |
| 976 | uCompressionCopy &= ~dcmp_table[i].uMask; |
| 977 | nCompressCount++; |
| 978 | } |
| 979 | } |
| 980 | |
| 981 | // If at least one of the compressions remaing unknown, return an error |
| 982 | if(nCompressCount == 0 || uCompressionCopy != 0) |
| 983 | { |
| 984 | SetLastError(ERROR_NOT_SUPPORTED); |
| 985 | return 0; |
| 986 | } |
| 987 | |
| 988 | // If there is more than one compression, we have to allocate extra buffer |
no test coverage detected