[PATCH v5 1/3] mfplat: Implement MFCreateFile().
Jactry Zeng
jzeng at codeweavers.com
Thu Feb 7 07:43:04 CST 2019
Superseded patch 157922 to 157924.
ChangeLog:
v5:
- Fix crash when calling MFCreateMFByteStreamOnStream() on Windows.
Thanks Alistair for pointing out!
v4:
- Fix test failure on Windows XP and Vista.
Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
dlls/mfplat/Makefile.in | 2 +-
dlls/mfplat/main.c | 69 +++++++++++++++-----------
dlls/mfplat/tests/mfplat.c | 99 +++++++++++++++++++++++++++++++++-----
3 files changed, 127 insertions(+), 43 deletions(-)
diff --git a/dlls/mfplat/Makefile.in b/dlls/mfplat/Makefile.in
index 76843f5f25..5d9c8eb4c6 100644
--- a/dlls/mfplat/Makefile.in
+++ b/dlls/mfplat/Makefile.in
@@ -1,6 +1,6 @@
MODULE = mfplat.dll
IMPORTLIB = mfplat
-IMPORTS = advapi32 ole32
+IMPORTS = advapi32 ole32 shlwapi
C_SRCS = \
main.c
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index c7c346512f..8aab65c28d 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -31,6 +31,7 @@
#include "mfapi.h"
#include "mfidl.h"
#include "mferror.h"
+#include "shlwapi.h"
#include "wine/heap.h"
#include "wine/debug.h"
@@ -849,6 +850,7 @@ typedef struct _mfbytestream
{
mfattributes attributes;
IMFByteStream IMFByteStream_iface;
+ IStream *stream;
} mfbytestream;
static inline mfbytestream *impl_from_IMFByteStream(IMFByteStream *iface)
@@ -901,6 +903,7 @@ static ULONG WINAPI mfbytestream_Release(IMFByteStream *iface)
if (!ref)
{
+ IStream_Release(This->stream);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -1144,6 +1147,8 @@ HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **byt
init_attribute_object(&object->attributes, 0);
object->IMFByteStream_iface.lpVtbl = &mfbytestream_vtbl;
object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
+ object->stream = stream;
+ IStream_AddRef(object->stream);
*bytestream = &object->IMFByteStream_iface;
@@ -1154,60 +1159,65 @@ HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE open
LPCWSTR url, IMFByteStream **bytestream)
{
mfbytestream *object;
- DWORD fileaccessmode = 0;
- DWORD filesharemode = FILE_SHARE_READ;
- DWORD filecreation_disposition = 0;
- DWORD fileattributes = 0;
- HANDLE file;
+ DWORD mode = STGM_SHARE_DENY_WRITE;
+ DWORD attributes = FILE_ATTRIBUTE_NORMAL;
+ BOOL create = FALSE, reset = FALSE;
+ IStream *stream = NULL;
+ HRESULT hres;
- FIXME("(%d, %d, %d, %s, %p): stub\n", accessmode, openmode, flags, debugstr_w(url), bytestream);
+ TRACE("(%d, %d, %d, %s, %p)\n", accessmode, openmode, flags, debugstr_w(url), bytestream);
switch (accessmode)
{
case MF_ACCESSMODE_READ:
- fileaccessmode = GENERIC_READ;
+ mode |= STGM_READ;
break;
case MF_ACCESSMODE_WRITE:
- fileaccessmode = GENERIC_WRITE;
+ mode |= STGM_WRITE;
break;
case MF_ACCESSMODE_READWRITE:
- fileaccessmode = GENERIC_READ | GENERIC_WRITE;
+ mode |= STGM_READWRITE;
break;
}
switch (openmode)
{
- case MF_OPENMODE_FAIL_IF_NOT_EXIST:
- filecreation_disposition = OPEN_EXISTING;
- break;
- case MF_OPENMODE_FAIL_IF_EXIST:
- filecreation_disposition = CREATE_NEW;
- break;
case MF_OPENMODE_RESET_IF_EXIST:
- filecreation_disposition = TRUNCATE_EXISTING;
+ if (accessmode == MF_ACCESSMODE_READ)
+ return E_INVALIDARG;
+ reset = TRUE;
+ mode |= STGM_FAILIFTHERE;
break;
case MF_OPENMODE_APPEND_IF_EXIST:
- filecreation_disposition = OPEN_ALWAYS;
- fileaccessmode |= FILE_APPEND_DATA;
+ if (GetFileAttributesW(url) == INVALID_FILE_ATTRIBUTES)
+ create = TRUE;
+ case MF_OPENMODE_FAIL_IF_NOT_EXIST:
+ mode |= STGM_FAILIFTHERE;
+ break;
+ case MF_OPENMODE_FAIL_IF_EXIST:
+ mode |= STGM_FAILIFTHERE;
+ create = TRUE;
break;
case MF_OPENMODE_DELETE_IF_EXIST:
- filecreation_disposition = CREATE_ALWAYS;
+ mode |= STGM_CREATE;
break;
}
if (flags & MF_FILEFLAGS_NOBUFFERING)
- fileattributes |= FILE_FLAG_NO_BUFFERING;
-
- /* Open HANDLE to file */
- file = CreateFileW(url, fileaccessmode, filesharemode, NULL,
- filecreation_disposition, fileattributes, 0);
-
- if(file == INVALID_HANDLE_VALUE)
- return HRESULT_FROM_WIN32(GetLastError());
+ attributes |= FILE_FLAG_NO_BUFFERING;
+ if ((flags & MF_FILEFLAGS_ALLOW_WRITE_SHARING) && (accessmode == MF_ACCESSMODE_READ))
+ mode &= ~STGM_SHARE_DENY_WRITE;
- /* Close the file again, since we don't do anything with it yet */
- CloseHandle(file);
+ hres = SHCreateStreamOnFileEx(url, mode, attributes, create, NULL, &stream);
+ if(FAILED(hres))
+ return hres;
+ if (reset)
+ {
+ ULARGE_INTEGER zero;
+ zero.QuadPart = 0;
+ IStream_SetSize(stream, zero);
+ }
object = heap_alloc( sizeof(*object) );
if(!object)
return E_OUTOFMEMORY;
@@ -1215,6 +1225,7 @@ 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->stream = stream;
*bytestream = &object->IMFByteStream_iface;
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 3fa59f4816..a4f11da36e 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -54,6 +54,48 @@ DEFINE_GUID(DUMMY_GUID2, 0x12345678,0x1234,0x1234,0x22,0x22,0x22,0x22,0x22,0x22,
static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0};
+#define CHECK_REF(obj,ref) _check_ref((IUnknown*)obj, ref, __LINE__)
+static void _check_ref(IUnknown* obj, ULONG ref, int line)
+{
+ ULONG rc;
+ IUnknown_AddRef(obj);
+ rc = IUnknown_Release(obj);
+ ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
+}
+
+#define CHECK_BS_POS(obj,pos) _check_bs_pos(obj, pos, __LINE__)
+static void _check_bs_pos(IMFByteStream* obj, QWORD pos, int line)
+{
+ QWORD position = 0xdeadbeef;
+ HRESULT hr;
+ hr = IMFByteStream_GetCurrentPosition(obj, &position);
+ ok_(__FILE__,line)(hr == S_OK, "IMFByteStream_GetCurrentPosition failed: 0x%08x.\n", hr);
+ ok_(__FILE__,line)(position == pos, "got wrong position: %s.\n",
+ wine_dbgstr_longlong(position));
+}
+
+#define CHECK_BS_LEN(obj,len) _check_bs_len(obj, len, __LINE__)
+static void _check_bs_len(IMFByteStream* obj, QWORD len, int line)
+{
+ QWORD length = 0xdeadbeef;
+ HRESULT hr;
+ hr = IMFByteStream_GetLength(obj, &length);
+ ok_(__FILE__,line)(hr == S_OK, "IMFByteStream_GetLength failed: 0x%08x.\n", hr);
+ ok_(__FILE__,line)(length == len, "got wrong length: %s.\n",
+ wine_dbgstr_longlong(length));
+}
+
+#define CHECK_FILE_SIZE(filename,exp_size) _check_file_size(filename, exp_size, __LINE__)
+static void _check_file_size(const WCHAR *filename, LONG exp_size, int line)
+{
+ HANDLE handle;
+ DWORD file_size = 0xdeadbeef;
+ handle = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
+ file_size = GetFileSize(handle, NULL);
+ ok_(__FILE__,line)(file_size == exp_size, "got wrong file size: %d.\n", file_size);
+ CloseHandle(handle);
+}
+
static WCHAR *load_resource(const WCHAR *name)
{
static WCHAR pathW[MAX_PATH];
@@ -450,8 +492,10 @@ static void test_MFCreateMFByteStreamOnStream(void)
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
+ CHECK_REF(stream, 1);
hr = pMFCreateMFByteStreamOnStream(stream, &bytestream);
ok(hr == S_OK, "got 0x%08x\n", hr);
+ CHECK_REF(stream, 2);
hr = IMFByteStream_QueryInterface(bytestream, &IID_IUnknown,
(void **)&unknown);
@@ -509,7 +553,8 @@ static void test_MFCreateFile(void)
IMFAttributes *attributes = NULL;
HRESULT hr;
WCHAR *filename;
-
+ LONG file_size;
+ HANDLE handle;
static const WCHAR newfilename[] = {'n','e','w','.','m','p','4',0};
filename = load_resource(mp4file);
@@ -534,13 +579,11 @@ static void test_MFCreateFile(void)
hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_FAIL_IF_NOT_EXIST,
MF_FILEFLAGS_NONE, filename, &bytestream2);
- todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
- if (hr == S_OK) IMFByteStream_Release(bytestream2);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
hr = MFCreateFile(MF_ACCESSMODE_READWRITE, MF_OPENMODE_FAIL_IF_NOT_EXIST,
MF_FILEFLAGS_NONE, filename, &bytestream2);
- todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
- if (hr == S_OK) IMFByteStream_Release(bytestream2);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
IMFByteStream_Release(bytestream);
@@ -558,18 +601,15 @@ static void test_MFCreateFile(void)
hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST,
MF_FILEFLAGS_NONE, newfilename, &bytestream2);
- todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
- if (hr == S_OK) IMFByteStream_Release(bytestream2);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_FAIL_IF_NOT_EXIST,
MF_FILEFLAGS_NONE, newfilename, &bytestream2);
- todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
- if (hr == S_OK) IMFByteStream_Release(bytestream2);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_FAIL_IF_NOT_EXIST,
MF_FILEFLAGS_ALLOW_WRITE_SHARING, newfilename, &bytestream2);
- todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
- if (hr == S_OK) IMFByteStream_Release(bytestream2);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
IMFByteStream_Release(bytestream);
@@ -580,10 +620,43 @@ static void test_MFCreateFile(void)
/* Opening the file again fails even though MF_FILEFLAGS_ALLOW_WRITE_SHARING is set. */
hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_FAIL_IF_NOT_EXIST,
MF_FILEFLAGS_ALLOW_WRITE_SHARING, newfilename, &bytestream2);
- todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
- if (hr == S_OK) IMFByteStream_Release(bytestream2);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "got 0x%08x\n", hr);
+ hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST,
+ MF_FILEFLAGS_ALLOW_WRITE_SHARING, newfilename, &bytestream2);
+ ok(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) /* xp and vista */,
+ "MFCreateFile failed: 0x%08x.\n", hr);
+ if(hr == S_OK)
+ IMFByteStream_Release(bytestream2);
+ IMFByteStream_Release(bytestream);
+
+ /* test MF_OPENMODE_APPEND_IF_EXIST */
+ handle = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(handle != INVALID_HANDLE_VALUE, "File creation failed: 0x%08x.\n", GetLastError());
+ file_size = GetFileSize(handle, NULL);
+ CloseHandle(handle);
+ 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);
+ todo_wine CHECK_BS_POS(bytestream, 0);
+ IMFByteStream_Release(bytestream);
+ CHECK_FILE_SIZE(filename, file_size);
+
+ /* test MF_OPENMODE_RESET_IF_EXIST with read-only mode */
+ hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_RESET_IF_EXIST,
+ MF_FILEFLAGS_ALLOW_WRITE_SHARING, filename, &bytestream);
+ ok(hr == E_INVALIDARG, "MFCreateFile should fail: 0x%08x.\n", hr);
+ CHECK_FILE_SIZE(filename, file_size);
+
+ /* test MF_OPENMODE_RESET_IF_EXIST */
+ hr = MFCreateFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_RESET_IF_EXIST,
+ MF_FILEFLAGS_NONE, filename, &bytestream);
+ ok(hr == S_OK, "MFCreateFile failed: 0x%08x.\n", hr);
+ todo_wine CHECK_BS_LEN(bytestream, 0);
+ todo_wine CHECK_BS_POS(bytestream, 0);
IMFByteStream_Release(bytestream);
+ CHECK_FILE_SIZE(filename, 0);
MFShutdown();
--
2.20.1
More information about the wine-devel
mailing list