Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- dlls/mfplat/main.c | 38 ++++++++++--- dlls/mfplat/tests/mfplat.c | 111 ++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 9 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index a4fd7329e8..80c1b3e3ba 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -853,7 +853,12 @@ typedef struct _mfbytestream union { IStream *stream; - HANDLE file; + struct + { + HANDLE handle; + LARGE_INTEGER length; + QWORD position; + } file; } u; } mfbytestream;
@@ -907,7 +912,7 @@ static ULONG WINAPI mfbytestream_Release(IMFByteStream *iface)
if (!ref) { - CloseHandle(This->u.file); + CloseHandle(This->u.file.handle); HeapFree(GetProcessHeap(), 0, This); }
@@ -927,18 +932,30 @@ static HRESULT WINAPI mfbytestream_GetLength(IMFByteStream *iface, QWORD *length { mfbytestream *This = impl_from_IMFByteStream(iface);
- FIXME("%p, %p\n", This, length); + TRACE("(%p)->(%p)\n", This, length);
- return E_NOTIMPL; + *length = This->u.file.length.QuadPart; + + return S_OK; }
static HRESULT WINAPI mfbytestream_SetLength(IMFByteStream *iface, QWORD length) { mfbytestream *This = impl_from_IMFByteStream(iface);
- FIXME("%p, %s\n", This, wine_dbgstr_longlong(length)); + TRACE("(%p)->(%s)\n", This, wine_dbgstr_longlong(length));
- return E_NOTIMPL; + if(!SetFilePointer(This->u.file.handle, length, NULL, FILE_BEGIN)) + return E_FAIL; + + if(!SetEndOfFile(This->u.file.handle)) + return E_FAIL; + + if(This->u.file.position) + if(!SetFilePointer(This->u.file.handle, This->u.file.position, NULL, FILE_BEGIN)) + return E_FAIL; + + return S_OK; }
static HRESULT WINAPI mfbytestream_GetCurrentPosition(IMFByteStream *iface, QWORD *position) @@ -1404,7 +1421,14 @@ HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE open init_attribute_object(&object->attributes, 0); object->IMFByteStream_iface.lpVtbl = &mfbytestream_vtbl; object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl; - object->u.file = file; + object->u.file.handle = file; + if(!GetFileSizeEx(file, &object->u.file.length)) + { + CloseHandle(file); + heap_free(object); + return E_FAIL; + } + object->u.file.position = 0;
*bytestream = &object->IMFByteStream_iface;
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 488dbfbce6..712b4abe2c 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -52,6 +52,9 @@ DEFINE_GUID(DUMMY_CLSID, 0x12345678,0x1234,0x1234,0x12,0x13,0x14,0x15,0x16,0x17, DEFINE_GUID(DUMMY_GUID1, 0x12345678,0x1234,0x1234,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21); DEFINE_GUID(DUMMY_GUID2, 0x12345678,0x1234,0x1234,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22);
+static const byte asf_header[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11, + 0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c}; + static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0};
#define CHECK_REF(obj,ref) _check_ref((IUnknown*)obj, ref, __LINE__) @@ -626,7 +629,7 @@ static void test_MFCreateFile(void) hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_APPEND_IF_EXIST, MF_FILEFLAGS_ALLOW_WRITE_SHARING, filename, &bytestream); ok(hr == S_OK, "MFCreateFile failed: 0x%08x.\n", hr); - todo_wine CHECK_BS_LEN(bytestream, file_size); + CHECK_BS_LEN(bytestream, file_size); todo_wine CHECK_BS_POS(bytestream, 0); IMFByteStream_Release(bytestream);
@@ -634,7 +637,7 @@ static void test_MFCreateFile(void) hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_RESET_IF_EXIST, MF_FILEFLAGS_ALLOW_WRITE_SHARING, filename, &bytestream); ok(hr == S_OK, "MFCreateFile failed: 0x%08x.\n", hr); - todo_wine CHECK_BS_LEN(bytestream, 0); + CHECK_BS_LEN(bytestream, 0); todo_wine CHECK_BS_POS(bytestream, 0); IMFByteStream_Release(bytestream); handle = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); @@ -750,6 +753,109 @@ static void test_MFSample(void) IMFSample_Release(sample); }
+static void test_bytestream_from_file(void) +{ + IMFByteStream *bytestream; + HRESULT hr; + HANDLE file; + static WCHAR asffile[] = {'t','e','s','t','.','a','s','f',0}; + byte buffer[1024] = {0}; + byte test_data[] = {0x1,0x2,0x3,0x4}; + ULONG written, read; + QWORD length; + + file = CreateFileW(asffile, GENERIC_READ|GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "File creation failed: 0x%08x.\n", GetLastError()); + WriteFile(file, asf_header, sizeof(asf_header), &written, NULL); + CloseHandle(file); + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, + MF_FILEFLAGS_NONE, asffile, &bytestream); + ok(hr == S_OK, "MFCreateFile failed: 0x%08x.\n", hr); + todo_wine CHECK_BS_POS(bytestream, 0); + CHECK_BS_LEN(bytestream, sizeof(asf_header)); + read = 0; + hr = IMFByteStream_Read(bytestream, buffer, sizeof(buffer), &read); + todo_wine ok(hr == S_OK, "IMFByteStream_Read failed: 0x%08x.\n", hr); + todo_wine ok(read == sizeof(asf_header), "got wrong read length: %d\n", read); + todo_wine ok(!memcmp(buffer, asf_header, sizeof(asf_header)), "got wrong content.\n"); + todo_wine CHECK_BS_POS(bytestream, sizeof(asf_header)); + memset(buffer, 0, sizeof(buffer)); + hr = IMFByteStream_Write(bytestream, asf_header, sizeof(asf_header), &written); + todo_wine ok(hr == E_ACCESSDENIED, "IMFByteStream_Write should fail: 0x%08x.\n", hr); + hr = IMFByteStream_Flush(bytestream); + todo_wine ok(hr == E_ACCESSDENIED, "IMFByteStream_Flush should fail: 0x%08x.\n", hr); + hr = IMFByteStream_SetLength(bytestream, 200); + ok(hr == E_FAIL, "IMFByteStream_SetLength should fail: 0x%08x.\n", hr); + IMFByteStream_Release(bytestream); + + hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_FAIL_IF_NOT_EXIST, + MF_FILEFLAGS_NONE, asffile, &bytestream); + ok(hr == S_OK, "MFCreateFile failed: 0x%08x.\n", hr); + hr = IMFByteStream_Read(bytestream, buffer, sizeof(buffer), &read); + todo_wine ok(hr == E_ACCESSDENIED, "IMFByteStream_Read should fail: 0x%08x.\n", hr); + todo_wine CHECK_BS_POS(bytestream, 0); + written = 0xdeadbeef; + hr = IMFByteStream_Write(bytestream, asf_header, sizeof(asf_header), &written); + todo_wine ok(hr == S_OK, "IMFByteStream_Write failed: 0x%08x.\n", hr); + todo_wine ok(written == sizeof(asf_header), "got wrong written length: %d\n", written); + CHECK_BS_LEN(bytestream, sizeof(asf_header)); + todo_wine CHECK_BS_POS(bytestream, sizeof(asf_header)); + hr = IMFByteStream_Flush(bytestream); + todo_wine ok(hr == S_OK, "IMFByteStream_Flush failed: 0x%08x.\n", hr); + todo_wine CHECK_BS_POS(bytestream, sizeof(asf_header)); + CHECK_BS_LEN(bytestream, sizeof(asf_header)); + + hr = IMFByteStream_SetLength(bytestream, sizeof(asf_header) + 2); + ok(hr == S_OK, "IMFByteStream_SetLength failed: 0x%08x.\n", hr); + length = 0xdeadbeef; + hr = IMFByteStream_GetLength(bytestream, &length); + ok(hr == S_OK, "IMFByteStream_GetLength failed: 0x%08x.\n", hr); + ok(length == sizeof(asf_header) || length == (sizeof(asf_header) + 2) /* xp */, + "got wrong length: %s.\n", wine_dbgstr_longlong(length)); + todo_wine CHECK_BS_POS(bytestream, sizeof(asf_header)); + IMFByteStream_Release(bytestream); + file = CreateFileW(asffile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); + ReadFile(file, buffer, sizeof(buffer), &read, NULL); + ok(read == sizeof(asf_header) + 2, "got wrong read length: %d\n", read); + ok(!memcmp(buffer, asf_header, sizeof(asf_header)), "got wrong content.\n"); + memset(buffer, 0, sizeof(buffer)); + CloseHandle(file); + + hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_APPEND_IF_EXIST, + MF_FILEFLAGS_NONE, asffile, &bytestream); + ok(hr == S_OK, "MFCreateFile failed: 0x%08x.\n", hr); + todo_wine CHECK_BS_POS(bytestream, 0); + CHECK_BS_LEN(bytestream, sizeof(asf_header) + 2); + written = 0xdeadbeef; + hr = IMFByteStream_Write(bytestream, test_data, sizeof(test_data), &written); + todo_wine ok(hr == S_OK, "IMFByteStream_Write failed: 0x%08x.\n", hr); + todo_wine ok(written == sizeof(test_data), "got wrong written length: %d\n", written); + CHECK_BS_LEN(bytestream, sizeof(asf_header) + 2); + todo_wine CHECK_BS_POS(bytestream, sizeof(test_data)); + IMFByteStream_Release(bytestream); + + hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_RESET_IF_EXIST, + MF_FILEFLAGS_NONE, asffile, &bytestream); + ok(hr == S_OK, "MFCreateFile failed: 0x%08x.\n", hr); + todo_wine CHECK_BS_POS(bytestream, 0); + CHECK_BS_LEN(bytestream, 0); + hr = IMFByteStream_SetLength(bytestream, 2000); + ok(hr == S_OK, "IMFByteStream_SetLength failed: 0x%08x.\n", hr); + length = 0xdeadbeef; + hr = IMFByteStream_GetLength(bytestream, &length); + ok(hr == S_OK, "IMFByteStream_GetLength failed: 0x%08x.\n", hr); + ok(length == 0 || length == 2000 /* xp */, "got wrong length: %s.\n", wine_dbgstr_longlong(length)); + todo_wine CHECK_BS_POS(bytestream, 0); + IMFByteStream_Release(bytestream); + + DeleteFileW(asffile); +} + START_TEST(mfplat) { CoInitialize(NULL); @@ -765,6 +871,7 @@ START_TEST(mfplat) test_MFCreateMFByteStreamOnStream(); test_MFCreateMemoryBuffer(); test_source_resolver(); + test_bytestream_from_file();
CoUninitialize(); }