From f9b1044a4a5a4812d45856ca5532fb4af1bbd76f Mon Sep 17 00:00:00 2001 From: shenlei Date: Wed, 30 Sep 2026 12:46:43 +0900 Subject: [PATCH] audit: EterBase CRC32/FileBase/MappedFile mapped, with port.utils checks Co-Authored-By: Claude Opus 5.5 --- audit/history.jsonl | 3 + audit/port-map/EterBase/CRC32.cpp.json | 36 ++++- audit/port-map/EterBase/FileBase.cpp.json | 112 +++++++++++---- audit/port-map/EterBase/MappedFile.cpp.json | 144 +++++++++++++++----- tests/port/port_utils_test.cpp | 75 ++++++++++ 5 files changed, 308 insertions(+), 62 deletions(-) diff --git a/audit/history.jsonl b/audit/history.jsonl index 938894f3..473f757f 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -603,3 +603,6 @@ {"date": "2026-09-30", "unit": "EterPythonLib/PythonGraphic.cpp", "action": "GenScreenShotTag/SaveJPEG PORTED, SaveScreenShot ADAPTED (next-frame readback via ScreenShotHost)", "evidence": "port.screenshot; desktop grp.SaveScreenShot() -> ~/Documents/METIN2/0930_124051.jpg, colours checked"} {"date": "2026-09-30", "unit": "EterBase/error.cpp", "action": "N_A (Win32 SEH crash log)", "evidence": "no reader of ErrorLog.txt in source or root .py"} {"date": "2026-09-30", "unit": "EterPythonLib/PythonGraphic.cpp", "action": "Destroy PORTED, GetD3D ADAPTED, SetOmniLight PORTED, RenderImage/RenderAlphaImage N_A", "evidence": "no callers of RenderImage/RenderAlphaImage; GetD3D covered by port.login_flow resolution check"} +{"date": "2026-09-30", "unit": "EterBase/CRC32.cpp", "action": "GetCaseCRC32 PORTED; GetHFILECRC32/GetFileCRC32/GetFileSize ADAPTED", "evidence": "port.utils CRC32/CFileBase/CMappedFile checks"} +{"date": "2026-09-30", "unit": "EterBase/FileBase.cpp", "action": "all units mapped (FILE* over Win32 HANDLE); stale fstream note corrected", "evidence": "port.utils CRC32/CFileBase/CMappedFile checks"} +{"date": "2026-09-30", "unit": "EterBase/MappedFile.cpp", "action": "Map/Unmap ADAPTED (mmap), rest PORTED verbatim; stale ifstream note corrected", "evidence": "port.utils CRC32/CFileBase/CMappedFile checks"} diff --git a/audit/port-map/EterBase/CRC32.cpp.json b/audit/port-map/EterBase/CRC32.cpp.json index d0a2a9e0..4f0c6f92 100644 --- a/audit/port-map/EterBase/CRC32.cpp.json +++ b/audit/port-map/EterBase/CRC32.cpp.json @@ -13,16 +13,44 @@ "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" }, "GetCaseCRC32": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/CRC32.cpp:GetCaseCRC32" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250 loop (UPPER fold); CRCTable generated from 0xEDB88320, identical to the literal 40250 table." }, "GetHFILECRC32": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterBase/CRC32.cpp:GetHFILECRC32" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 maps the file (CreateFile + CreateFileMapping/MapViewOfFile from offset 0) and CRCs the whole view; the port reads the whole FILE* into a buffer. Invariant: same CRC of the full file, the handle's position is unchanged, 0 when the file cannot be opened." }, "GetFileCRC32": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterBase/CRC32.cpp:GetFileCRC32" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 maps the file (CreateFile + CreateFileMapping/MapViewOfFile from offset 0) and CRCs the whole view; the port reads the whole FILE* into a buffer. Invariant: same CRC of the full file, the handle's position is unchanged, 0 when the file cannot be opened. Callers: GuildMarkUploader/GuildMarkDownloader symbol CRC, root pack CRC report." }, "GetFileSize": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterBase/CRC32.cpp:GetFileSize" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "CreateFile + GetFileSize -> fopen + ftell(SEEK_END); 0 when the file is missing (40250 returns 0 on INVALID_HANDLE_VALUE). Caller: GuildMarkDownloader symbol size." } } } diff --git a/audit/port-map/EterBase/FileBase.cpp.json b/audit/port-map/EterBase/FileBase.cpp.json index 060fae78..915f824d 100644 --- a/audit/port-map/EterBase/FileBase.cpp.json +++ b/audit/port-map/EterBase/FileBase.cpp.json @@ -5,68 +5,134 @@ "contracts": [], "functions": { "CFileBase::CFileBase": { + "status": "PORTED", "impl": [ "src/platform/EterBase/FileBase.cpp:CFileBase::CFileBase" ], - "status": "ADAPTED", - "note": "platform CFileBase over std::fstream; open falls back to a case-insensitive path match (NTFS spelling)", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Same member initialisation." }, "CFileBase::~CFileBase": { + "status": "PORTED", "impl": [ "src/platform/EterBase/FileBase.cpp:CFileBase::~CFileBase" ], - "status": "ADAPTED", - "note": "platform CFileBase over std::fstream; open falls back to a case-insensitive path match (NTFS spelling)", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Same (Destroy)." }, "CFileBase::GetFileName": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/FileBase.cpp:CFileBase::GetFileName" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim (m_filename)." }, "CFileBase::Destroy": { + "status": "PORTED", "impl": [ "src/platform/EterBase/FileBase.cpp:CFileBase::Destroy" ], - "status": "ADAPTED", - "note": "platform CFileBase over std::fstream; open falls back to a case-insensitive path match (NTFS spelling)", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Same (Close, m_dwSize = 0)." }, "CFileBase::Close": { + "status": "ADAPTED", "impl": [ "src/platform/EterBase/FileBase.cpp:CFileBase::Close" ], - "status": "ADAPTED", - "note": "platform CFileBase over std::fstream; open falls back to a case-insensitive path match (NTFS spelling)", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 wraps a Win32 HANDLE; the port keeps a stdio FILE* in m_hFile. CloseHandle -> fclose." }, "CFileBase::Create": { + "status": "ADAPTED", "impl": [ "src/platform/EterBase/FileBase.cpp:CFileBase::Create" ], - "status": "ADAPTED", - "note": "platform CFileBase over std::fstream; open falls back to a case-insensitive path match (NTFS spelling)", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 wraps a Win32 HANDLE; the port keeps a stdio FILE* in m_hFile. CreateFile modes kept: read = OPEN_EXISTING, write = OPEN_ALWAYS read/write (r+b, else w+b: no truncation). On POSIX a missing exact spelling falls back to a case-insensitive per-component match (NTFS names, e.g. pack/Index 'Etc' for ETC.eix)." }, "CFileBase::Size": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/FileBase.cpp:CFileBase::Size" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim (m_dwSize)." }, "CFileBase::SeekCur": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterBase/FileBase.cpp:CFileBase::SeekCur" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 wraps a Win32 HANDLE; the port keeps a stdio FILE* in m_hFile. SetFilePointer(FILE_CURRENT) with a NULL high part takes the DWORD as a signed distance -> fseek(LONG(size), SEEK_CUR)." }, "CFileBase::Seek": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterBase/FileBase.cpp:CFileBase::Seek" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 wraps a Win32 HANDLE; the port keeps a stdio FILE* in m_hFile. Clamp to m_dwSize verbatim; SetFilePointer(FILE_BEGIN) -> fseek(SEEK_SET)." }, "CFileBase::GetPosition": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterBase/FileBase.cpp:CFileBase::GetPosition" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 wraps a Win32 HANDLE; the port keeps a stdio FILE* in m_hFile. SetFilePointer(0, FILE_CURRENT) -> ftell." }, "CFileBase::Write": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterBase/FileBase.cpp:CFileBase::Write" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 wraps a Win32 HANDLE; the port keeps a stdio FILE* in m_hFile. WriteFile -> fwrite (false on a short write), then m_dwSize from the stream size as 40250 re-reads GetFileSize." }, "CFileBase::Read": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterBase/FileBase.cpp:CFileBase::Read" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "40250 wraps a Win32 HANDLE; the port keeps a stdio FILE* in m_hFile. ReadFile succeeds on a short read at end of file; fread + !ferror keeps that." }, "CFileBase::IsNull": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/FileBase.cpp:CFileBase::IsNull" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim (!m_hFile)." } } } diff --git a/audit/port-map/EterBase/MappedFile.cpp.json b/audit/port-map/EterBase/MappedFile.cpp.json index 8ae5a1d0..ced657d2 100644 --- a/audit/port-map/EterBase/MappedFile.cpp.json +++ b/audit/port-map/EterBase/MappedFile.cpp.json @@ -5,100 +5,174 @@ "contracts": [], "functions": { "CMappedFile::CMappedFile": { + "status": "PORTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::CMappedFile" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::~CMappedFile": { + "status": "PORTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::~CMappedFile" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Create": { + "status": "PORTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::Create" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Get": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/MappedFile.cpp:CMappedFile::Get" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Link": { + "status": "PORTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::Link" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::BindLZObject": { + "status": "PORTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::BindLZObject" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::BindLZObjectWithBufferedSize": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/MappedFile.cpp:CMappedFile::BindLZObjectWithBufferedSize" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::AppendDataBlock": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/MappedFile.cpp:CMappedFile::AppendDataBlock" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Destroy": { + "status": "PORTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::Destroy" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Seek": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/MappedFile.cpp:CMappedFile::Seek" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Map": { + "status": "ADAPTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::Map" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "CreateFileMapping/MapViewOfFile -> POSIX mmap of the CFileBase stream (Windows build keeps the Win32 calls), view start aligned down to the page size as 40250 aligns to the allocation granularity; a zero-length view maps 1 byte (mmap rejects 0). Invariant: *dest points at file offset `offset`, Size() == the mapped length, a view past the end returns 0." }, "CMappedFile::GetCurrentSeekPoint": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/MappedFile.cpp:CMappedFile::GetCurrentSeekPoint" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Size": { + "status": "PORTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::Size" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::GetPosition": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/MappedFile.cpp:CMappedFile::GetPosition" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Read": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/MappedFile.cpp:CMappedFile::Read" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::GetSeekPosition": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterBase/MappedFile.cpp:CMappedFile::GetSeekPosition" + ], + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "Verbatim 40250." }, "CMappedFile::Unmap": { + "status": "ADAPTED", "impl": [ "src/platform/EterBase/MappedFile.cpp:CMappedFile::Unmap" ], - "status": "ADAPTED", - "note": "platform CMappedFile: std::ifstream read into an owned buffer instead of CreateFileMapping/MapViewOfFile; same Create/Map/Link/BindLZObject contract", - "test": "tests/port/port_eterpack_test.cpp (103 packs, 54891 entries, first-registered wins, 4 SECURITY rejects)" + "test": [ + "tests/port/port_utils_test.cpp" + ], + "note": "CreateFileMapping/MapViewOfFile -> POSIX mmap of the CFileBase stream (Windows build keeps the Win32 calls), view start aligned down to the page size as 40250 aligns to the allocation granularity; a zero-length view maps 1 byte (mmap rejects 0). Invariant: *dest points at file offset `offset`, Size() == the mapped length, a view past the end returns 0." } } } diff --git a/tests/port/port_utils_test.cpp b/tests/port/port_utils_test.cpp index 9f4dfef5..2b7c9031 100644 --- a/tests/port/port_utils_test.cpp +++ b/tests/port/port_utils_test.cpp @@ -1,11 +1,14 @@ #include "EterBase/StdAfx.h" #include "EterBase/Utils.h" #include "EterBase/FileLoader.h" +#include "EterBase/CRC32.h" +#include "EterBase/MappedFile.h" #include #include #include #include +#include int main() { @@ -88,5 +91,77 @@ int main() check(!disk.Open("/nonexistent/mt_fileloader"), "DiskFileLoader missing"); remove(path); } + + // CRC32: the IEEE check value, GetCaseCRC32 folds ASCII case (effect/sound/tree name keys), and the + // file variants (guild symbol CRC + size, GuildMarkDownloader) CRC the whole file. + { + check(GetCRC32("123456789", 9) == 0xCBF43926u, "GetCRC32 check value"); + check(GetCaseCRC32("D:/Ymir Work/A.MSE", 18) == GetCaseCRC32("d:/ymir work/a.mse", 18), "GetCaseCRC32 case fold"); + check(GetCaseCRC32("abc", 3) == GetCRC32("ABC", 3), "GetCaseCRC32 folds to upper case"); + + char path[] = "/tmp/mt_crc32_XXXXXX"; + int fd = mkstemp(path); + FILE * fp = fdopen(fd, "wb"); + fwrite("123456789", 1, 9, fp); + fclose(fp); + check(GetFileCRC32(path) == 0xCBF43926u, "GetFileCRC32"); + check(GetFileSize(path) == 9, "GetFileSize"); + fp = fopen(path, "rb"); + fseek(fp, 4, SEEK_SET); + check(GetHFILECRC32(fp) == 0xCBF43926u && ftell(fp) == 4, "GetHFILECRC32 whole file, position kept"); + fclose(fp); + check(GetFileCRC32("/nonexistent/mt_crc32") == 0 && GetFileSize("/nonexistent/mt_crc32") == 0, "CRC32 missing file"); + remove(path); + } + + // CFileBase (Win32 HANDLE -> FILE*): write mode opens without truncating and tracks the size, Seek clamps + // to the size, SeekCur takes the DWORD as a signed distance, Read succeeds on a short read. + // CMappedFile: the view at a non-aligned offset, Seek clamps, Read refuses past the end, + // AppendDataBlock re-links onto a copy. + { + char path[] = "/tmp/mt_filebase_XXXXXX"; + close(mkstemp(path)); + { + CFileBase f; + check(f.IsNull(), "CFileBase IsNull before Create"); + check(f.Create(path, CFileBase::FILEMODE_WRITE) && !f.IsNull(), "CFileBase Create write"); + check(strcmp(f.GetFileName(), path) == 0, "CFileBase GetFileName"); + check(f.Write("abcdefgh", 8) && f.Size() == 8 && f.GetPosition() == 8, "CFileBase Write size/position"); + } + { + CFileBase f; + check(f.Create(path, CFileBase::FILEMODE_WRITE) && f.Size() == 8, "CFileBase write mode keeps contents"); + f.Seek(100); + check(f.GetPosition() == 8, "CFileBase Seek clamps to size"); + f.Seek(2); + f.SeekCur(3); + check(f.GetPosition() == 5, "CFileBase SeekCur forward"); + f.SeekCur(DWORD(-2)); + check(f.GetPosition() == 3, "CFileBase SeekCur negative distance"); + char buf[8] = {}; + check(f.Read(buf, 2) && buf[0] == 'd' && buf[1] == 'e', "CFileBase Read"); + check(f.Read(buf, 8), "CFileBase short Read succeeds"); + } + { + CFileBase f; + check(!f.Create("/nonexistent/mt_filebase", CFileBase::FILEMODE_READ) && f.IsNull(), "CFileBase missing file"); + } + { + CMappedFile mf; + const void * view = NULL; + check(mf.Create(path, &view, 3, 4) && memcmp(view, "defg", 4) == 0, "CMappedFile view at offset"); + check(mf.Get() == view && mf.GetPosition() == 3 && mf.Size() == 4, "CMappedFile Get/GetPosition/Size"); + char buf[8] = {}; + check(mf.Read(buf, 3) && memcmp(buf, "def", 3) == 0 && mf.GetSeekPosition() == 3, "CMappedFile Read"); + check(!mf.Read(buf, 2) && mf.GetSeekPosition() == 3, "CMappedFile Read past end"); + check(*mf.GetCurrentSeekPoint() == 'g', "CMappedFile GetCurrentSeekPoint"); + check(mf.Seek(1, CMappedFile::SEEK_TYPE_CURRENT) == 4 && mf.Seek(9, CMappedFile::SEEK_TYPE_CURRENT) == 4, "CMappedFile Seek current clamps"); + check(mf.Seek(1, CMappedFile::SEEK_TYPE_END) == 3 && mf.Seek(1) == 1, "CMappedFile Seek end/begin"); + BYTE * joined = mf.AppendDataBlock("XY", 2); + check(mf.Size() == 6 && memcmp(joined, "defgXY", 6) == 0, "CMappedFile AppendDataBlock"); + check(!mf.Create(path, &view, 6, 4), "CMappedFile view past the end"); + } + remove(path); + } return failures ? 1 : 0; }