From 899e59ffe3b2160df4719780949f8de0cc4ba8eb Mon Sep 17 00:00:00 2001 From: David Quintana Date: Tue, 29 Oct 2013 15:00:53 +0100 Subject: [PATCH] shlwapi: Test and fix the behaviour of the CopyTo method for file sizes not multiple of the internal buffer size, on SHCreateStreamOnFileEx-returned IStreams. --- dlls/shlwapi/istream.c | 16 ++++++------ dlls/shlwapi/tests/istream.c | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/dlls/shlwapi/istream.c b/dlls/shlwapi/istream.c index 42f47fef02f..044594bf19e 100644 --- a/dlls/shlwapi/istream.c +++ b/dlls/shlwapi/istream.c @@ -231,22 +231,22 @@ static HRESULT WINAPI IStream_fnCopyTo(IStream *iface, IStream* pstm, ULARGE_INT ulSize = cb.QuadPart; while (ulSize) { - ULONG ulLeft, ulAmt; + ULONG ulLeft, ulRead, ulWritten; ulLeft = ulSize > sizeof(copyBuff) ? sizeof(copyBuff) : ulSize; /* Read */ - hRet = IStream_fnRead(iface, copyBuff, ulLeft, &ulAmt); - if (pcbRead) - pcbRead->QuadPart += ulAmt; - if (FAILED(hRet) || ulAmt != ulLeft) + hRet = IStream_fnRead(iface, copyBuff, ulLeft, &ulRead); + if (FAILED(hRet) || ulRead == 0) break; + if (pcbRead) + pcbRead->QuadPart += ulRead; /* Write */ - hRet = IStream_fnWrite(pstm, copyBuff, ulLeft, &ulAmt); + hRet = IStream_fnWrite(pstm, copyBuff, ulRead, &ulWritten); if (pcbWritten) - pcbWritten->QuadPart += ulAmt; - if (FAILED(hRet) || ulAmt != ulLeft) + pcbWritten->QuadPart += ulWritten; + if (FAILED(hRet) || ulWritten != ulLeft) break; ulSize -= ulLeft; diff --git a/dlls/shlwapi/tests/istream.c b/dlls/shlwapi/tests/istream.c index 097e70a5627..760b8474e94 100644 --- a/dlls/shlwapi/tests/istream.c +++ b/dlls/shlwapi/tests/istream.c @@ -655,6 +655,52 @@ static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm) } +void test_SHCreateStreamOnFileEx_CopyTo(void) +{ + HRESULT ret; + IStream *src, *dst; + WCHAR tmpPath[MAX_PATH]; + WCHAR srcFileName[MAX_PATH]; + WCHAR dstFileName[MAX_PATH]; + ULARGE_INTEGER count, read, written; + LARGE_INTEGER distance; + static const char srcContents[1]; + static const WCHAR prefix[] = { 'T', 'S', 'T', 0 }; + + GetTempPathW(MAX_PATH, tmpPath); + GetTempFileNameW(tmpPath, prefix, 0, srcFileName); + GetTempFileNameW(tmpPath, prefix, 0, dstFileName); + + ret = pSHCreateStreamOnFileEx(srcFileName, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, FILE_ATTRIBUTE_TEMPORARY, FALSE, NULL, &src); + ok(SUCCEEDED(ret), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret); + + written.QuadPart = 0; + ret = IStream_Write(src, srcContents, sizeof(srcContents), &written.LowPart); + ok(SUCCEEDED(ret), "ISequentialStream_Write failed with ret=0x%08x\n", ret); + + distance.QuadPart = 0; + ret = IStream_Seek(src, distance, STREAM_SEEK_SET, &written); + ok(SUCCEEDED(ret), "ISequentialStream_Seek failed with ret=0x%08x\n", ret); + + ret = pSHCreateStreamOnFileEx(dstFileName, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, FILE_ATTRIBUTE_TEMPORARY, FALSE, NULL, &dst); + ok(SUCCEEDED(ret), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret); + + /* Test using a count larger than the source file, so that the Read operation will fall short */ + count.QuadPart = 2; + + ret = IStream_CopyTo(src, dst, count, &read, &written); + ok(SUCCEEDED(ret), "CopyTo failed with ret=0x%08x\n", ret); + + ok(read.QuadPart == 1, "read does not match size: %d != 1\n", read.LowPart); + ok(written.QuadPart == 1, "written does not match size: %d != 1\n", written.LowPart); + + IStream_Release(dst); + IStream_Release(src); + DeleteFileW( srcFileName ); + DeleteFileW( dstFileName ); +} + + START_TEST(istream) { static const DWORD stgm_access[] = { @@ -712,4 +758,6 @@ START_TEST(istream) } } } + + test_SHCreateStreamOnFileEx_CopyTo(); }