diff --git a/dlls/windowscodecs/stream.c b/dlls/windowscodecs/stream.c index 561719da0ee..1ed08f36672 100644 --- a/dlls/windowscodecs/stream.c +++ b/dlls/windowscodecs/stream.c @@ -108,7 +108,7 @@ static HRESULT WINAPI StreamOnMemory_Read(IStream *iface, EnterCriticalSection(&This->lock); uBytesRead = min(cb, This->dwMemsize - This->dwCurPos); - memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead); + memmove(pv, This->pbMemory + This->dwCurPos, uBytesRead); This->dwCurPos += uBytesRead; LeaveCriticalSection(&This->lock); @@ -131,7 +131,7 @@ static HRESULT WINAPI StreamOnMemory_Write(IStream *iface, hr = STG_E_MEDIUMFULL; } else { - memcpy(This->pbMemory + This->dwCurPos, pv, cb); + memmove(This->pbMemory + This->dwCurPos, pv, cb); This->dwCurPos += cb; hr = S_OK; if (pcbWritten) *pcbWritten = cb; diff --git a/dlls/windowscodecs/tests/stream.c b/dlls/windowscodecs/tests/stream.c index d5b2918e9cb..a55b898e27b 100644 --- a/dlls/windowscodecs/tests/stream.c +++ b/dlls/windowscodecs/tests/stream.c @@ -31,8 +31,15 @@ static void test_StreamOnMemory(void) 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, }; + const BYTE CmpMemOverlap[] = { + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + }; + const BYTE ZeroMem[10] = {0}; BYTE Memory[64], MemBuf[64]; - LARGE_INTEGER LargeNull, LargeInt; + LARGE_INTEGER LargeNull, LargeInt, SeekPos; ULARGE_INTEGER uLargeNull, uNewPos; ULONG uBytesRead, uBytesWritten; HRESULT hr; @@ -40,6 +47,7 @@ static void test_StreamOnMemory(void) LargeNull.QuadPart = 0; uLargeNull.QuadPart = 0; + SeekPos.QuadPart = 5; memcpy(Memory, CmpMem, sizeof(CmpMem)); @@ -76,6 +84,19 @@ static void test_StreamOnMemory(void) hr = IWICStream_InitializeFromMemory(pStream, Memory, sizeof(Memory)); ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK); + /* IWICStream does not maintain an independent copy of the backing memory buffer. */ + memcpy(Memory, ZeroMem, sizeof(ZeroMem)); + hr = IWICStream_Read(pStream, MemBuf, sizeof(ZeroMem), &uBytesRead); + ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK); + if(SUCCEEDED(hr)) { + ok(uBytesRead == sizeof(ZeroMem), "Read %u bytes\n", uBytesRead); + ok(memcmp(MemBuf, ZeroMem, sizeof(ZeroMem)) == 0, "Read returned invalid data!\n"); + } + + IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL); + + hr = IWICStream_Write(pStream, CmpMem, sizeof(CmpMem), &uBytesWritten); + ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK); /* Seek */ hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, &uNewPos); @@ -152,6 +173,17 @@ static void test_StreamOnMemory(void) ok(memcmp(Memory, CmpMem, uBytesRead) == 0, "Read returned invalid data!\n"); } + IWICStream_Seek(pStream, SeekPos, STREAM_SEEK_SET, NULL); + + hr = IWICStream_Read(pStream, Memory, 10, &uBytesRead); /* source and dest overlap */ + ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK); + if(SUCCEEDED(hr)) { + ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10); + ok(memcmp(Memory, CmpMemOverlap, uBytesRead) == 0, "Read returned invalid data!\n"); + } + + memcpy(Memory, CmpMem, sizeof(CmpMem)); + IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL); hr = IWICStream_Read(pStream, Memory, sizeof(Memory) + 10, &uBytesRead); /* request too many bytes */ @@ -206,6 +238,22 @@ static void test_StreamOnMemory(void) hr = IWICStream_Write(pStream, MemBuf, 0, &uBytesWritten); ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK); + /* Restore the original contents of the memory stream. */ + hr = IWICStream_Write(pStream, CmpMem, sizeof(CmpMem), &uBytesWritten); + ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK); + + IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL); + + /* Source and destination overlap. */ + hr = IWICStream_Write(pStream, Memory + 5, 10, &uBytesWritten); + ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, S_OK); + if(SUCCEEDED(hr)) { + ok(uBytesWritten == 10, "Wrote %u bytes, expected %u\n", uBytesWritten, 10); + ok(memcmp(CmpMemOverlap, Memory, sizeof(CmpMemOverlap)) == 0, "Wrote returned invalid data!\n"); + } + + IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL); + uBytesWritten = 0xdeadbeef; hr = IWICStream_Write(pStream, NULL, 3, &uBytesWritten); ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);