This function allocates an empty structure for the file stream The stream structure is created as flat block, variable length The file name is placed after the end of the stream structure data
| 1005 | // The stream structure is created as flat block, variable length |
| 1006 | // The file name is placed after the end of the stream structure data |
| 1007 | static TFileStream * AllocateFileStream( |
| 1008 | const TCHAR * szFileName, |
| 1009 | size_t StreamSize, |
| 1010 | DWORD dwStreamFlags) |
| 1011 | { |
| 1012 | TFileStream * pMaster = NULL; |
| 1013 | TFileStream * pStream; |
| 1014 | const TCHAR * szNextFile = szFileName; |
| 1015 | size_t FileNameSize; |
| 1016 | |
| 1017 | // Sanity check |
| 1018 | assert(StreamSize != 0); |
| 1019 | |
| 1020 | // The caller can specify chain of files in the following form: |
| 1021 | // C:\archive.MPQ*http://www.server.com/MPQs/archive-server.MPQ |
| 1022 | // In that case, we use the part after "*" as master file name |
| 1023 | while(szNextFile[0] != 0 && szNextFile[0] != _T('*')) |
| 1024 | szNextFile++; |
| 1025 | FileNameSize = (size_t)((szNextFile - szFileName) * sizeof(TCHAR)); |
| 1026 | |
| 1027 | // If we have a next file, we need to open it as master stream |
| 1028 | // Note that we don't care if the master stream exists or not, |
| 1029 | // If it doesn't, later attempts to read missing file block will fail |
| 1030 | if(szNextFile[0] == _T('*')) |
| 1031 | { |
| 1032 | // Don't allow another master file in the string |
| 1033 | if(_tcschr(szNextFile + 1, _T('*')) != NULL) |
| 1034 | { |
| 1035 | SetLastError(ERROR_INVALID_PARAMETER); |
| 1036 | return NULL; |
| 1037 | } |
| 1038 | |
| 1039 | // Open the master file |
| 1040 | pMaster = FileStream_OpenFile(szNextFile + 1, STREAM_FLAG_READ_ONLY); |
| 1041 | } |
| 1042 | |
| 1043 | // Allocate the stream structure for the given stream type |
| 1044 | pStream = (TFileStream *)STORM_ALLOC(BYTE, StreamSize + FileNameSize + sizeof(TCHAR)); |
| 1045 | if(pStream != NULL) |
| 1046 | { |
| 1047 | // Zero the entire structure |
| 1048 | memset(pStream, 0, StreamSize); |
| 1049 | pStream->pMaster = pMaster; |
| 1050 | pStream->dwFlags = dwStreamFlags; |
| 1051 | |
| 1052 | // Initialize the file name |
| 1053 | pStream->szFileName = (TCHAR *)((BYTE *)pStream + StreamSize); |
| 1054 | memcpy(pStream->szFileName, szFileName, FileNameSize); |
| 1055 | pStream->szFileName[FileNameSize / sizeof(TCHAR)] = 0; |
| 1056 | |
| 1057 | // Initialize the stream functions |
| 1058 | StreamBaseInit[dwStreamFlags & 0x03](pStream); |
| 1059 | } |
| 1060 | |
| 1061 | return pStream; |
| 1062 | } |
| 1063 | |
| 1064 | //----------------------------------------------------------------------------- |
no test coverage detected