diff options
author | OctaneSnail <os@v12pwr.com> | 2008-12-13 21:54:51 +0300 |
---|---|---|
committer | OctaneSnail <os@v12pwr.com> | 2008-12-13 22:54:08 +0300 |
commit | 0978b5dd252cfdfed9813af201d634aa9e79d949 (patch) | |
tree | 9b1e7b457c1ddca08146682a7a2f1502d836deae | |
parent | 75ed77126304e38d098fc4f5845e552a48999734 (diff) |
Fix handling of archives and media files larger than 4 gigabytes.
Based on a patch from OV2.
-rw-r--r-- | OutputPin.cpp | 14 | ||||
-rw-r--r-- | RAR.cpp | 44 | ||||
-rw-r--r-- | RAR.h | 8 | ||||
-rw-r--r-- | RFS.cpp | 32 | ||||
-rw-r--r-- | RFS.h | 2 | ||||
-rw-r--r-- | Utils.cpp | 4 |
6 files changed, 49 insertions, 55 deletions
diff --git a/OutputPin.cpp b/OutputPin.cpp index acee509..4090a52 100644 --- a/OutputPin.cpp +++ b/OutputPin.cpp @@ -275,7 +275,8 @@ STDMETHODIMP CRFSOutputPin::Request (IMediaSample* pSample, DWORD_PTR dwUser) } LARGE_INTEGER offset; - DWORD to_read, acc = 0, offset2; + DWORD to_read, acc = 0; + LONGLONG offset2; int pos = FindStartPart (llPosition); if (pos == -1) @@ -294,7 +295,7 @@ STDMETHODIMP CRFSOutputPin::Request (IMediaSample* pSample, DWORD_PTR dwUser) FilePart *part = m_file->array + pos; - offset2 = (DWORD) (llPosition - part->in_file_offset); + offset2 = llPosition - part->in_file_offset; offset.QuadPart = part->in_rar_offset + offset2; while (true) @@ -310,7 +311,7 @@ STDMETHODIMP CRFSOutputPin::Request (IMediaSample* pSample, DWORD_PTR dwUser) request->subreqs.InsertLast (sr); request->count ++; - to_read = min (lLength, part->size - offset2); + to_read = min (lLength, (DWORD) (part->size - offset2)); sr->file = part->file; sr->expected = to_read; @@ -552,7 +553,8 @@ HRESULT CRFSOutputPin::SyncRead (LONGLONG llPosition, DWORD lLength, BYTE* pBuff { OVERLAPPED o; LARGE_INTEGER offset; - DWORD to_read, read, acc = 0, offset2; + DWORD to_read, read, acc = 0; + LONGLONG offset2; int pos; #ifdef _DEBUG static int last_pos = -1; @@ -583,7 +585,7 @@ HRESULT CRFSOutputPin::SyncRead (LONGLONG llPosition, DWORD lLength, BYTE* pBuff #endif FilePart *part = m_file->array + pos; - offset2 = (DWORD) (llPosition - part->in_file_offset); + offset2 = llPosition - part->in_file_offset; offset.QuadPart = part->in_rar_offset + offset2; memset (&o, 0, sizeof (o)); @@ -597,7 +599,7 @@ HRESULT CRFSOutputPin::SyncRead (LONGLONG llPosition, DWORD lLength, BYTE* pBuff while (true) { read = 0; - to_read = min (lLength, part->size - offset2); + to_read = min (lLength, (DWORD) (part->size - offset2)); o.Offset = offset.LowPart; o.OffsetHigh = offset.HighPart; @@ -44,7 +44,8 @@ DWORD ReadHeader (HANDLE file, rar_header_t *dest) { fixed_header_t fh; fixed_file_header_t ffh; - DWORD read, acc = 0, dword; + DWORD read, dword; + LONGLONG acc = 0; // Read fixed archive header. READ_ITEM (fh); @@ -56,16 +57,13 @@ DWORD ReadHeader (HANDLE file, rar_header_t *dest) if (fh.flags & LONG_BLOCK) { READ_ITEM (dword); - - if ((MAXDWORD - dword) < fh.size) - { - ErrorMsg (0, L"Variable overflow while reading RAR header."); - return S_FALSE; - } - dest->ch.size = dword + fh.size; + dest->ch.size.QuadPart = (LONGLONG) dword + fh.size; } else - dest->ch.size = fh.size; + { + dest->ch.size.HighPart = 0; + dest->ch.size.LowPart = fh.size; + } switch (fh.type) { @@ -76,7 +74,7 @@ DWORD ReadHeader (HANDLE file, rar_header_t *dest) case HEADER_TYPE_FILE: READ_ITEM (ffh); - dest->fh.low_size = ffh.size; + dest->fh.size.LowPart = ffh.size; dest->fh.os = ffh.os; dest->fh.crc = ffh.crc; dest->fh.timestamp = ffh.timestamp; @@ -87,16 +85,13 @@ DWORD ReadHeader (HANDLE file, rar_header_t *dest) if (fh.flags & LHD_LARGE) { - READ_ITEM (dword); - dest->fh.high_size = dword; - dest->fh.size = ((DWORD64) dword << 32) | ffh.size; - READ_ITEM (dword); + READ_ITEM (dword); // Packed size high dword + dest->ch.size.HighPart += dword; + READ_ITEM (dword); // Unpacked size high dword + dest->fh.size.HighPart = dword; } else - { - dest->fh.high_size = 0; - dest->fh.size = ffh.size; - } + dest->fh.size.HighPart = 0; dest->fh.filename = new char [dest->fh.name_len + 1]; if (!dest->fh.filename) @@ -136,20 +131,21 @@ DWORD ReadHeader (HANDLE file, rar_header_t *dest) } } - if (acc > dest->ch.size) + if (acc > dest->ch.size.QuadPart) { ErrorMsg (0, L"Overrun while reading RAR header."); return S_FALSE; } - if (fh.type != HEADER_TYPE_FILE && acc < dest->ch.size) + if (fh.type != HEADER_TYPE_FILE && acc < dest->ch.size.QuadPart) { - SetFilePointer (file, dest->ch.size - acc, 0, FILE_CURRENT); -// DbgLog ((LOG_TRACE, 2, L"Skipped over %d header bytes.", dest->ch.size - acc)); - dest->bytesRemaining = 0; + LARGE_INTEGER li; + li.QuadPart = dest->ch.size.QuadPart - acc; + SetFilePointerEx (file, li, NULL, FILE_CURRENT); + dest->bytesRemaining.QuadPart = 0; } else - dest->bytesRemaining = dest->ch.size - acc; + dest->bytesRemaining.QuadPart = dest->ch.size.QuadPart - acc; return ERROR_SUCCESS; } @@ -60,7 +60,7 @@ typedef struct WORD crc; BYTE type; WORD flags; - DWORD size; + LARGE_INTEGER size; } common_header_t; typedef struct @@ -71,9 +71,7 @@ typedef struct typedef struct { - DWORD64 size; - DWORD low_size; - DWORD high_size; + LARGE_INTEGER size; DWORD crc; DWORD timestamp; @@ -108,7 +106,7 @@ typedef struct end_header_t eh; }; - DWORD bytesRemaining; + LARGE_INTEGER bytesRemaining; } rar_header_t; DWORD ReadHeader (HANDLE file, rar_header_t *dest); @@ -228,13 +228,12 @@ STDMETHODIMP CRARFileSource::NonDelegatingQueryInterface (REFIID riid, void **pp #define HEADER_SKIP_FILE \ delete [] rh.fh.filename; \ - SetFilePointer (hFile, rh.bytesRemaining, 0, FILE_CURRENT); \ + SetFilePointerEx (hFile, rh.bytesRemaining, NULL, FILE_CURRENT); \ continue; int CRARFileSource::ScanArchive (wchar_t *archive_name, List<File> *file_list, int *ok_files_found) { DWORD dwBytesRead; - DWORD mem_offset = 0; char *filename = NULL; wchar_t *current_rar_filename = NULL, *rar_ext; bool first_archive_file = true; @@ -243,13 +242,14 @@ int CRARFileSource::ScanArchive (wchar_t *archive_name, List<File> *file_list, i BYTE marker [7]; BYTE expected [7] = { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 }; FilePart *new_part, *prev_part; - LONGLONG collect = 0; + LONGLONG collected; DWORD ret; DWORD files = 0, volumes = 0; int volume_digits; File *file = NULL; *ok_files_found = 0; + LARGE_INTEGER zero = {0}; Anchor<File> af (&file); ArrayAnchor<wchar_t> acrf (¤t_rar_filename); @@ -398,13 +398,13 @@ int CRARFileSource::ScanArchive (wchar_t *archive_name, List<File> *file_list, i } if (rh.ch.type != HEADER_TYPE_FILE) { - SetFilePointer (hFile, rh.bytesRemaining, 0, FILE_CURRENT); + SetFilePointerEx (hFile, rh.bytesRemaining, NULL, FILE_CURRENT); DbgLog ((LOG_TRACE, 2,L"Skipping unknown header type %02x.", rh.ch.type)); continue; } - DbgLog ((LOG_TRACE, 2, L"SIZE %d,%d OS %02x CRC %08x TIMESTAMP %08x VERSION %d METHOD %02x LEN %04x ATTRIB %08x", - rh.fh.low_size, rh.fh.high_size, rh.fh.os, rh.fh.crc, rh.fh.timestamp, rh.fh.version, rh.fh.method, rh.fh.name_len, rh.fh.attributes)); + DbgLog ((LOG_TRACE, 2, L"SIZE %08x %08x OS %02x CRC %08x TIMESTAMP %08x VERSION %d METHOD %02x LEN %04x ATTRIB %08x", + rh.fh.size.HighPart, rh.fh.size.LowPart, rh.fh.os, rh.fh.crc, rh.fh.timestamp, rh.fh.version, rh.fh.method, rh.fh.name_len, rh.fh.attributes)); DbgLog ((LOG_TRACE, 2, L"FILENAME \"%S\"", rh.fh.filename)); @@ -437,8 +437,7 @@ int CRARFileSource::ScanArchive (wchar_t *archive_name, List<File> *file_list, i } files ++; - mem_offset = 0; - collect = 0; + collected = 0; ASSERT (!file); @@ -447,7 +446,7 @@ int CRARFileSource::ScanArchive (wchar_t *archive_name, List<File> *file_list, i file->media_type.SetType (&MEDIATYPE_Stream); file->media_type.SetSubtype (&MEDIASUBTYPE_NULL); file->filename = rh.fh.filename; - file->size = rh.fh.size; + file->size = rh.fh.size.QuadPart; filename = rh.fh.filename; if (rh.ch.flags & LHD_PASSWORD) @@ -512,9 +511,9 @@ int CRARFileSource::ScanArchive (wchar_t *archive_name, List<File> *file_list, i } prev_part = new_part; - new_part->in_rar_offset = SetFilePointer (hFile, 0, 0, FILE_CURRENT); - new_part->in_file_offset = mem_offset; - new_part->size = rh.bytesRemaining; + SetFilePointerEx (hFile, zero, (LARGE_INTEGER*) &new_part->in_rar_offset, FILE_CURRENT); + new_part->in_file_offset = collected; + new_part->size = rh.bytesRemaining.QuadPart; new_part->file = CreateFile (current_rar_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (new_part->file == INVALID_HANDLE_VALUE) @@ -524,15 +523,14 @@ int CRARFileSource::ScanArchive (wchar_t *archive_name, List<File> *file_list, i } } - collect += rh.bytesRemaining; - mem_offset += rh.bytesRemaining; - SetFilePointer (hFile, rh.bytesRemaining, 0, FILE_CURRENT); + collected += rh.bytesRemaining.QuadPart; + SetFilePointerEx (hFile, rh.bytesRemaining, NULL, FILE_CURRENT); // Is file complete? if (!(rh.ch.flags & LHD_SPLIT_AFTER)) { - if (!file->unsupported && (file->size != collect || file->size != mem_offset)) - DbgLog ((LOG_TRACE, 2, L"The file is not the sum of it's parts. expected = %d, actual = %d", file->size, collect)); + if (!file->unsupported && file->size != collected) + DbgLog ((LOG_TRACE, 2, L"The file is not the sum of it's parts. expected = %lld, actual = %lld", file->size, collected)); if (file->parts) { @@ -31,7 +31,7 @@ public: LONGLONG in_rar_offset; LONGLONG in_file_offset; - DWORD size; + LONGLONG size; }; class File : public Node<File> @@ -95,8 +95,8 @@ void LogHeader (rar_header_t *rh) int i; WORD flags = rh->ch.flags; - DbgLog ((LOG_TRACE, 2, L"Header CRC %04x TYPE %02x FLAGS %04x SIZE %08x", - rh->ch.crc, rh->ch.type, rh->ch.flags, rh->ch.size)); + DbgLog ((LOG_TRACE, 2, L"Header CRC %04x TYPE %02x FLAGS %04x SIZE %08x %08x", + rh->ch.crc, rh->ch.type, rh->ch.flags, rh->ch.size.HighPart, rh->ch.size.LowPart)); switch (rh->ch.type) { |