Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2017
- 68 participants
- 738 messages
[PATCH 2/3] ntdll: Don't return an error when reading past EOF in NtReadFileScatter
by Andrew Eikum
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/kernel32/tests/file.c | 27 ++++++++++++++++++++++++++-
dlls/ntdll/file.c | 8 +++-----
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index 8f5f392822..75b56e5d41 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -4353,7 +4353,7 @@ static void test_WriteFileGather(void)
FILE_SEGMENT_ELEMENT fse[2];
OVERLAPPED ovl, *povl = NULL;
SYSTEM_INFO si;
- LPVOID wbuf = NULL, rbuf1;
+ LPVOID wbuf = NULL, rbuf1, rbuf2;
BOOL br;
ret = GetTempPathA( MAX_PATH, temp_path );
@@ -4378,6 +4378,9 @@ static void test_WriteFileGather(void)
rbuf1 = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
ok( rbuf1 != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
+ rbuf2 = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
+ ok( rbuf2 != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
+
memset( &ovl, 0, sizeof(ovl) );
memset( fse, 0, sizeof(fse) );
memset( wbuf, 0x42, si.dwPageSize );
@@ -4430,11 +4433,33 @@ static void test_WriteFileGather(void)
ok( povl == NULL, "wrong ovl %p\n", povl );
}
+ /* read past EOF */
+ memset( &ovl, 0, sizeof(ovl) );
+ memset( fse, 0, sizeof(fse) );
+ fse[0].Buffer = rbuf1;
+ fse[1].Buffer = rbuf2;
+ memset( rbuf1, 0, si.dwPageSize );
+ memset( rbuf2, 0x17, si.dwPageSize );
+ br = ReadFileScatter( hfile, fse, si.dwPageSize * 2, NULL, &ovl );
+ ok( br == FALSE, "ReadFileScatter should be asynchronous\n" );
+ ok( GetLastError() == ERROR_IO_PENDING, "ReadFileScatter failed err %u\n", GetLastError() );
+
+ ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 );
+ ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError() );
+ ok( povl == &ovl, "wrong ovl %p\n", povl );
+
+ ok( memcmp( rbuf1, wbuf, si.dwPageSize ) == 0,
+ "data was not read into buffer\n" );
+ memset( rbuf1, 0x17, si.dwPageSize );
+ ok( memcmp( rbuf2, rbuf1, si.dwPageSize ) == 0,
+ "data should not have been read into buffer\n" );
+
CloseHandle( hfile );
CloseHandle( hiocp1 );
CloseHandle( hiocp2 );
VirtualFree( wbuf, 0, MEM_RELEASE );
VirtualFree( rbuf1, 0, MEM_RELEASE );
+ VirtualFree( rbuf2, 0, MEM_RELEASE );
DeleteFileA( filename );
}
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 12b1d0f6c5..6c3b571638 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -1070,11 +1070,7 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
status = FILE_GetNtStatus();
break;
}
- if (!result)
- {
- status = STATUS_END_OF_FILE;
- break;
- }
+ if (!result) break;
total += result;
length -= result;
if ((pos += result) == page_size)
@@ -1084,6 +1080,8 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
}
}
+ if (total == 0) status = STATUS_END_OF_FILE;
+
send_completion = cvalue != 0;
error:
--
2.15.0
Nov. 30, 2017
[PATCH 1/3] ntdll: NtReadFileScatter results are reported asynchronously
by Andrew Eikum
This patch sequence fixes Wolfenstein II, Bug 43935.
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/kernel32/tests/file.c | 53 +++++++++++++++++++++++++++++++++++++++-------
dlls/ntdll/file.c | 2 +-
2 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index 0b8cef23f8..8f5f392822 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -4353,7 +4353,8 @@ static void test_WriteFileGather(void)
FILE_SEGMENT_ELEMENT fse[2];
OVERLAPPED ovl, *povl = NULL;
SYSTEM_INFO si;
- LPVOID buf = NULL;
+ LPVOID wbuf = NULL, rbuf1;
+ BOOL br;
ret = GetTempPathA( MAX_PATH, temp_path );
ok( ret != 0, "GetTempPathA error %d\n", GetLastError() );
@@ -4371,12 +4372,16 @@ static void test_WriteFileGather(void)
ok( hiocp2 != 0, "CreateIoCompletionPort failed err %u\n", GetLastError() );
GetSystemInfo( &si );
- buf = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
- ok( buf != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
+ wbuf = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
+ ok( wbuf != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
+
+ rbuf1 = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
+ ok( rbuf1 != NULL, "VirtualAlloc failed err %u\n", GetLastError() );
memset( &ovl, 0, sizeof(ovl) );
memset( fse, 0, sizeof(fse) );
- fse[0].Buffer = buf;
+ memset( wbuf, 0x42, si.dwPageSize );
+ fse[0].Buffer = wbuf;
if (!WriteFileGather( hfile, fse, si.dwPageSize, NULL, &ovl ))
ok( GetLastError() == ERROR_IO_PENDING, "WriteFileGather failed err %u\n", GetLastError() );
@@ -4384,20 +4389,52 @@ static void test_WriteFileGather(void)
ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError());
ok( povl == &ovl, "wrong ovl %p\n", povl );
+ /* read exact size */
memset( &ovl, 0, sizeof(ovl) );
memset( fse, 0, sizeof(fse) );
- fse[0].Buffer = buf;
- if (!ReadFileScatter( hfile, fse, si.dwPageSize, NULL, &ovl ))
- ok( GetLastError() == ERROR_IO_PENDING, "ReadFileScatter failed err %u\n", GetLastError() );
+ fse[0].Buffer = rbuf1;
+ memset( rbuf1, 0, si.dwPageSize );
+ br = ReadFileScatter( hfile, fse, si.dwPageSize, NULL, &ovl );
+ ok( br == FALSE, "ReadFileScatter should be asynchronous\n" );
+ ok( GetLastError() == ERROR_IO_PENDING, "ReadFileScatter failed err %u\n", GetLastError() );
ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 );
ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError());
ok( povl == &ovl, "wrong ovl %p\n", povl );
+ ok( memcmp( rbuf1, wbuf, si.dwPageSize ) == 0,
+ "data was not read into buffer\n" );
+
+ /* start read at EOF */
+ memset( &ovl, 0, sizeof(ovl) );
+ S(U(ovl)).OffsetHigh = 0;
+ S(U(ovl)).Offset = si.dwPageSize;
+ memset( fse, 0, sizeof(fse) );
+ fse[0].Buffer = rbuf1;
+ br = ReadFileScatter( hfile, fse, si.dwPageSize, NULL, &ovl );
+ ok( br == FALSE, "ReadFileScatter should have failed\n" );
+ ok( GetLastError() == ERROR_HANDLE_EOF ||
+ GetLastError() == ERROR_IO_PENDING, "ReadFileScatter gave wrong error %u\n", GetLastError() );
+ if (GetLastError() == ERROR_IO_PENDING)
+ {
+ ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 );
+ ok( !ret, "GetQueuedCompletionStatus should have returned failure\n" );
+ ok( GetLastError() == ERROR_HANDLE_EOF, "Got wrong error: %u\n", GetLastError() );
+ ok( povl == &ovl, "wrong ovl %p\n", povl );
+ }
+ else
+ {
+ ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 100 );
+ ok( !ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError() );
+ ok( GetLastError() == WAIT_TIMEOUT, "GetQueuedCompletionStatus gave wrong error %u\n", GetLastError() );
+ ok( povl == NULL, "wrong ovl %p\n", povl );
+ }
+
CloseHandle( hfile );
CloseHandle( hiocp1 );
CloseHandle( hiocp2 );
- VirtualFree( buf, 0, MEM_RELEASE );
+ VirtualFree( wbuf, 0, MEM_RELEASE );
+ VirtualFree( rbuf1, 0, MEM_RELEASE );
DeleteFileA( filename );
}
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index ca2afa0e89..12b1d0f6c5 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -1105,7 +1105,7 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
if (send_completion) NTDLL_AddCompletion( file, cvalue, status, total );
- return status;
+ return STATUS_PENDING;
}
--
2.15.0
Nov. 30, 2017
[PATCH 2/2] hlink: Better handle the IBrowseContext parameter in IHlink::Navigate().
by Zebediah Figura
Query it for an IHlinkTarget object. Also, use ShellExecute() only if the
parameter is NULL.
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/hlink/link.c | 43 ++++++++++++++++++++++-----------------
dlls/hlink/tests/hlink.c | 53 ++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 69 insertions(+), 27 deletions(-)
diff --git a/dlls/hlink/link.c b/dlls/hlink/link.c
index f5da0b49a7d..983765cefea 100644
--- a/dlls/hlink/link.c
+++ b/dlls/hlink/link.c
@@ -486,25 +486,33 @@ static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
if (SUCCEEDED(r))
{
- IBindCtx *bcxt;
+ IBindCtx *bcxt = NULL;
IUnknown *unk = NULL;
IHlinkTarget *target;
- CreateBindCtx(0, &bcxt);
-
- RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
-
- r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IUnknown, (void**)&unk);
- if (r == S_OK)
- {
- r = IUnknown_QueryInterface(unk, &IID_IHlinkTarget, (void**)&target);
- IUnknown_Release(unk);
- }
- if (r == S_OK)
+ if (phbc)
{
- IHlinkTarget_SetBrowseContext(target, phbc);
- r = IHlinkTarget_Navigate(target, grfHLNF, This->Location);
- IHlinkTarget_Release(target);
+ r = IHlinkBrowseContext_GetObject(phbc, mon, TRUE, &unk);
+ if (r == S_FALSE)
+ {
+ CreateBindCtx(0, &bcxt);
+ RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
+ r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IUnknown, (void**)&unk);
+ }
+ if (r == S_OK)
+ {
+ r = IUnknown_QueryInterface(unk, &IID_IHlinkTarget, (void **)&target);
+ IUnknown_Release(unk);
+ }
+ if (r == S_OK)
+ {
+ if (bcxt) IHlinkTarget_SetBrowseContext(target, phbc);
+ r = IHlinkTarget_Navigate(target, grfHLNF, This->Location);
+ IHlinkTarget_Release(target);
+ }
+
+ RevokeBindStatusCallback(bcxt, pbsc);
+ if (bcxt) IBindCtx_Release(bcxt);
}
else
{
@@ -516,12 +524,9 @@ static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
{
ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
CoTaskMemFree(target);
+ r = DRAGDROP_S_DROP;
}
}
-
- RevokeBindStatusCallback(bcxt, pbsc);
-
- IBindCtx_Release(bcxt);
IMoniker_Release(mon);
}
diff --git a/dlls/hlink/tests/hlink.c b/dlls/hlink/tests/hlink.c
index c19de13ca81..835062433cc 100644
--- a/dlls/hlink/tests/hlink.c
+++ b/dlls/hlink/tests/hlink.c
@@ -73,6 +73,7 @@ DEFINE_EXPECT(HBC_QueryInterface_IUnknown);
DEFINE_EXPECT(HBC_GetObject);
DEFINE_EXPECT(HBC_UpdateHlink);
+DEFINE_EXPECT(HT_QueryInterface_IHlinkTarget);
DEFINE_EXPECT(HT_SetBrowseContext);
DEFINE_EXPECT(HT_GetBrowseContext);
DEFINE_EXPECT(HT_Navigate);
@@ -868,6 +869,8 @@ static HRESULT WINAPI HlinkBrowseContext_Register(IHlinkBrowseContext *iface,
return E_NOTIMPL;
}
+static IUnknown *HBC_object;
+
static IMoniker Moniker;
static HRESULT WINAPI HlinkBrowseContext_GetObject(IHlinkBrowseContext *iface,
IMoniker *pimk, BOOL fBindIfRootRegistered, IUnknown **ppiunk)
@@ -884,8 +887,9 @@ static HRESULT WINAPI HlinkBrowseContext_GetObject(IHlinkBrowseContext *iface,
IBindCtx_Release(bctx);
ok(fBindIfRootRegistered == 1, "fBindIfRootRegistered = %x\n", fBindIfRootRegistered);
- *ppiunk = NULL;
- return S_FALSE;
+
+ *ppiunk = HBC_object;
+ return HBC_object ? S_OK : S_FALSE;
}
static HRESULT WINAPI HlinkBrowseContext_Revoke(IHlinkBrowseContext *iface, DWORD dwRegister)
@@ -995,6 +999,7 @@ static IHlinkBrowseContext HlinkBrowseContext = { &HlinkBrowseContextVtbl };
static HRESULT WINAPI HlinkTarget_QueryInterface(IHlinkTarget *iface, REFIID riid, void **ppv)
{
if(IsEqualGUID(&IID_IHlinkTarget, riid)) {
+ CHECK_EXPECT(HT_QueryInterface_IHlinkTarget);
*ppv = iface;
return S_OK;
}
@@ -2188,6 +2193,8 @@ static void test_Hlink_Navigate(void)
ok(hres == S_OK, "CreateBindCtx failed: %08x\n", hres);
_bctx = pbc;
+ HBC_object = NULL;
+
SET_EXPECT(Reduce);
SET_EXPECT(Enum);
SET_EXPECT(IsSystemMoniker);
@@ -2205,6 +2212,7 @@ static void test_Hlink_Navigate(void)
SET_EXPECT(HBC_GetObject);
SET_EXPECT(Reduce);
SET_EXPECT(BindToObject);
+ SET_EXPECT(HT_QueryInterface_IHlinkTarget);
SET_EXPECT(HT_GetBrowseContext);
SET_EXPECT(HT_SetBrowseContext);
SET_EXPECT(HBC_QueryInterface_IHlinkHistory);
@@ -2213,36 +2221,65 @@ static void test_Hlink_Navigate(void)
hres = IHlink_Navigate(hlink, 0, pbc, NULL, &HlinkBrowseContext);
ok(hres == S_OK, "Navigate failed: %08x\n", hres);
CHECK_CALLED(IsSystemMoniker);
- todo_wine CHECK_CALLED(GetDisplayName);
- todo_wine CHECK_CALLED(HBC_GetObject);
+ CHECK_CALLED(GetDisplayName);
+ CHECK_CALLED(HBC_GetObject);
todo_wine CHECK_CALLED(Reduce);
CHECK_CALLED(BindToObject);
+ CHECK_CALLED(HT_QueryInterface_IHlinkTarget);
todo_wine CHECK_CALLED(HT_GetBrowseContext);
CHECK_CALLED(HT_SetBrowseContext);
todo_wine CHECK_CALLED(HBC_QueryInterface_IHlinkHistory);
CHECK_CALLED(HT_Navigate);
todo_wine CHECK_CALLED(HT_GetFriendlyName);
+ /* Test with valid return from HlinkBrowseContext::GetObject */
+ HBC_object = (IUnknown *)&HlinkTarget;
+
+ SET_EXPECT(IsSystemMoniker);
+ SET_EXPECT(GetDisplayName);
+ SET_EXPECT(HBC_GetObject);
+ SET_EXPECT(HT_QueryInterface_IHlinkTarget);
+ SET_EXPECT(HT_Navigate);
+ SET_EXPECT(HT_GetFriendlyName);
+ hres = IHlink_Navigate(hlink, 0, pbc, NULL, &HlinkBrowseContext);
+ ok(hres == S_OK, "Navigate failed: %08x\n", hres);
+ CHECK_CALLED(IsSystemMoniker);
+ CHECK_CALLED(GetDisplayName);
+ CHECK_CALLED(HBC_GetObject);
+ CHECK_CALLED(HT_QueryInterface_IHlinkTarget);
+ CHECK_CALLED(HT_Navigate);
+ todo_wine CHECK_CALLED(HT_GetFriendlyName);
+
+ HBC_object = NULL;
+
if (0) { /* these currently open a browser window on wine */
/* Test from string */
SET_EXPECT(HBC_GetObject);
hres = HlinkNavigateToStringReference(winehq_404W, NULL, NULL, 0, NULL, 0, pbc, NULL, &HlinkBrowseContext);
todo_wine ok(hres == INET_E_OBJECT_NOT_FOUND, "Expected INET_E_OBJECT_NOT_FOUND, got %08x\n", hres);
- todo_wine CHECK_CALLED(HBC_GetObject);
+ CHECK_CALLED(HBC_GetObject);
/* MSDN claims browse context and bind context can't be null, but they can */
SET_EXPECT(HBC_GetObject);
hres = HlinkNavigateToStringReference(winehq_404W, NULL, NULL, 0, NULL, 0, NULL, NULL, &HlinkBrowseContext);
todo_wine ok(hres == INET_E_OBJECT_NOT_FOUND, "Expected INET_E_OBJECT_NOT_FOUND, got %08x\n", hres);
- todo_wine CHECK_CALLED(HBC_GetObject);
+ CHECK_CALLED(HBC_GetObject);
}
/* these open a browser window, so mark them interactive only */
if (winetest_interactive)
{
/* both parameters null */
+ SET_EXPECT(IsSystemMoniker);
+ SET_EXPECT(GetDisplayName);
+ hres = IHlink_Navigate(hlink, 0, NULL, NULL, NULL);
+ ok(hres == DRAGDROP_S_DROP, "Expected DRAGDROP_S_DROP, got %08x\n", hres);
+ CHECK_CALLED(IsSystemMoniker);
+ CHECK_CALLED(GetDisplayName);
+
+ /* same, from string */
hres = HlinkNavigateToStringReference(winehq_404W, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL);
- todo_wine ok(hres == DRAGDROP_S_DROP, "Expected DRAGDROP_S_DROP, got %08x\n", hres);
+ ok(hres == DRAGDROP_S_DROP, "Expected DRAGDROP_S_DROP, got %08x\n", hres);
/* try basic test with valid URL */
SET_EXPECT(HBC_GetObject);
@@ -2252,7 +2289,7 @@ if (0) { /* these currently open a browser window on wine */
SET_EXPECT(HBC_QueryInterface_IUnknown);
hres = HlinkNavigateToStringReference(winehq_urlW, NULL, NULL, 0, NULL, 0, pbc, NULL, &HlinkBrowseContext);
ok(hres == S_OK, "Expected S_OK, got %08x\n", hres);
- todo_wine CHECK_CALLED(HBC_GetObject);
+ CHECK_CALLED(HBC_GetObject);
todo_wine CHECK_CALLED(HBC_QueryInterface_IHlinkHistory);
todo_wine CHECK_CALLED(HBC_QueryInterface_IMarshal);
todo_wine CHECK_CALLED(HBC_QueryInterface_IdentityUnmarshal);
--
2.15.0
Nov. 30, 2017
[PATCH 1/2] hlink/tests: Add tests for navigating from a string reference.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
v2: use test.winehq.org instead of www.winehq.org
v4: disable failing tests on Wine
dlls/hlink/tests/hlink.c | 79 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 67 insertions(+), 12 deletions(-)
diff --git a/dlls/hlink/tests/hlink.c b/dlls/hlink/tests/hlink.c
index 50f61d57f7e..c19de13ca81 100644
--- a/dlls/hlink/tests/hlink.c
+++ b/dlls/hlink/tests/hlink.c
@@ -67,6 +67,9 @@ DEFINE_EXPECT(GetClassID);
DEFINE_EXPECT(Save);
DEFINE_EXPECT(HBC_QueryInterface_IHlinkHistory);
+DEFINE_EXPECT(HBC_QueryInterface_IMarshal);
+DEFINE_EXPECT(HBC_QueryInterface_IdentityUnmarshal);
+DEFINE_EXPECT(HBC_QueryInterface_IUnknown);
DEFINE_EXPECT(HBC_GetObject);
DEFINE_EXPECT(HBC_UpdateHlink);
@@ -77,8 +80,16 @@ DEFINE_EXPECT(HT_GetFriendlyName);
DEFINE_EXPECT(HLF_UpdateHlink);
+DEFINE_GUID(CLSID_IdentityUnmarshal,0x0000001b,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
DEFINE_GUID(IID_IHlinkHistory,0x79eac9c8,0xbaf9,0x11ce,0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b);
+static const WCHAR winehq_urlW[] =
+ {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',
+ '/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
+static const WCHAR winehq_404W[] =
+ {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',
+ '/','t','e','s','t','s','/','f','a','k','e','u','r','l',0};
+
static void test_HlinkIsShortcut(void)
{
UINT i;
@@ -627,9 +638,6 @@ static void test_HlinkParseDisplayName(void)
IBindCtx *bctx;
HRESULT hres;
- static const WCHAR winehq_urlW[] =
- {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
- '/','s','i','t','e','/','a','b','o','u','t',0};
static const WCHAR invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':',
'2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8',
@@ -829,12 +837,17 @@ static HRESULT WINAPI HlinkBrowseContext_QueryInterface(
{
*ppv = NULL;
- if(IsEqualGUID(&IID_IHlinkHistory, riid)) {
+ if (IsEqualGUID(&IID_IHlinkHistory, riid))
CHECK_EXPECT(HBC_QueryInterface_IHlinkHistory);
- return E_NOINTERFACE;
- }
+ else if (IsEqualGUID(&IID_IMarshal, riid))
+ CHECK_EXPECT2(HBC_QueryInterface_IMarshal);
+ else if (IsEqualGUID(&CLSID_IdentityUnmarshal, riid))
+ CHECK_EXPECT(HBC_QueryInterface_IdentityUnmarshal);
+ else if (IsEqualGUID(&IID_IUnknown, riid))
+ CHECK_EXPECT(HBC_QueryInterface_IUnknown);
+ else
+ ok(0, "unexpected interface: %s\n", wine_dbgstr_guid(riid));
- ok(0, "unexpected interface: %s\n", wine_dbgstr_guid(riid));
return E_NOINTERFACE;
}
@@ -859,9 +872,17 @@ static IMoniker Moniker;
static HRESULT WINAPI HlinkBrowseContext_GetObject(IHlinkBrowseContext *iface,
IMoniker *pimk, BOOL fBindIfRootRegistered, IUnknown **ppiunk)
{
+ IBindCtx *bctx;
+ WCHAR *name;
+
CHECK_EXPECT(HBC_GetObject);
- ok(pimk == &Moniker, "pimk != &Moniker\n");
+ CreateBindCtx(0, &bctx);
+ IMoniker_GetDisplayName(pimk, bctx, NULL, &name);
+ ok(!lstrcmpW(winehq_urlW, name) || !lstrcmpW(winehq_404W, name), "got unexpected url\n");
+ CoTaskMemFree(name);
+ IBindCtx_Release(bctx);
+
ok(fBindIfRootRegistered == 1, "fBindIfRootRegistered = %x\n", fBindIfRootRegistered);
*ppiunk = NULL;
return S_FALSE;
@@ -1205,10 +1226,6 @@ static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther
static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
{
- static const WCHAR winehq_urlW[] =
- {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
- '/','s','i','t','e','/','a','b','o','u','t',0};
-
CHECK_EXPECT2(GetDisplayName);
ok(pbc != NULL, "pbc == NULL\n");
@@ -2206,6 +2223,44 @@ static void test_Hlink_Navigate(void)
CHECK_CALLED(HT_Navigate);
todo_wine CHECK_CALLED(HT_GetFriendlyName);
+if (0) { /* these currently open a browser window on wine */
+ /* Test from string */
+ SET_EXPECT(HBC_GetObject);
+ hres = HlinkNavigateToStringReference(winehq_404W, NULL, NULL, 0, NULL, 0, pbc, NULL, &HlinkBrowseContext);
+ todo_wine ok(hres == INET_E_OBJECT_NOT_FOUND, "Expected INET_E_OBJECT_NOT_FOUND, got %08x\n", hres);
+ todo_wine CHECK_CALLED(HBC_GetObject);
+
+ /* MSDN claims browse context and bind context can't be null, but they can */
+ SET_EXPECT(HBC_GetObject);
+ hres = HlinkNavigateToStringReference(winehq_404W, NULL, NULL, 0, NULL, 0, NULL, NULL, &HlinkBrowseContext);
+ todo_wine ok(hres == INET_E_OBJECT_NOT_FOUND, "Expected INET_E_OBJECT_NOT_FOUND, got %08x\n", hres);
+ todo_wine CHECK_CALLED(HBC_GetObject);
+}
+
+ /* these open a browser window, so mark them interactive only */
+ if (winetest_interactive)
+ {
+ /* both parameters null */
+ hres = HlinkNavigateToStringReference(winehq_404W, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL);
+ todo_wine ok(hres == DRAGDROP_S_DROP, "Expected DRAGDROP_S_DROP, got %08x\n", hres);
+
+ /* try basic test with valid URL */
+ SET_EXPECT(HBC_GetObject);
+ SET_EXPECT(HBC_QueryInterface_IHlinkHistory);
+ SET_EXPECT(HBC_QueryInterface_IMarshal);
+ SET_EXPECT(HBC_QueryInterface_IdentityUnmarshal);
+ SET_EXPECT(HBC_QueryInterface_IUnknown);
+ hres = HlinkNavigateToStringReference(winehq_urlW, NULL, NULL, 0, NULL, 0, pbc, NULL, &HlinkBrowseContext);
+ ok(hres == S_OK, "Expected S_OK, got %08x\n", hres);
+ todo_wine CHECK_CALLED(HBC_GetObject);
+ todo_wine CHECK_CALLED(HBC_QueryInterface_IHlinkHistory);
+ todo_wine CHECK_CALLED(HBC_QueryInterface_IMarshal);
+ todo_wine CHECK_CALLED(HBC_QueryInterface_IdentityUnmarshal);
+ todo_wine CHECK_CALLED(HBC_QueryInterface_IUnknown);
+ }
+ else
+ skip("interactive IHlink_Navigate tests\n");
+
IHlink_Release(hlink);
IBindCtx_Release(pbc);
_bctx = NULL;
--
2.15.0
Nov. 30, 2017
[PATCH 5/5] mshtml: Silence some noisy FIXMEs.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/mshtml/nsio.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
Nov. 30, 2017
[PATCH 4/5] mshtml: Pass listener type as a string to remove_event_listener.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/mshtml/htmlevent.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
Nov. 30, 2017
[PATCH 3/5] mshtml: Pass listener type as a string to get_listener_container.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/mshtml/htmlevent.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)
Nov. 30, 2017
[PATCH 2/5] mshtml: Store listener container type as a string.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/mshtml/htmlevent.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
Nov. 30, 2017
[PATCH 1/5] mshtml: Removed unused impl_from_DispatchEx.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/mshtml/htmlevent.c | 5 -----
1 file changed, 5 deletions(-)
Nov. 30, 2017
[PATCH] xaudio2: Ignore buffers returned from OpenAL after Stop
by Andrew Eikum
For bug 40963.
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/xaudio2_7/tests/xaudio2.c | 78 +++++++++++++++++++++++++++++++++++++++++
dlls/xaudio2_7/xaudio_dll.c | 77 +++++++++++++++++++++++++---------------
dlls/xaudio2_7/xaudio_private.h | 2 +-
3 files changed, 127 insertions(+), 30 deletions(-)
diff --git a/dlls/xaudio2_7/tests/xaudio2.c b/dlls/xaudio2_7/tests/xaudio2.c
index 54176eaf86..ff402f87c4 100644
--- a/dlls/xaudio2_7/tests/xaudio2.c
+++ b/dlls/xaudio2_7/tests/xaudio2.c
@@ -841,6 +841,82 @@ static void test_submix(IXAudio2 *xa)
IXAudio2MasteringVoice_DestroyVoice(master);
}
+static void test_flush(IXAudio2 *xa)
+{
+ HRESULT hr;
+ IXAudio2MasteringVoice *master;
+ IXAudio2SourceVoice *src;
+ WAVEFORMATEX fmt;
+ XAUDIO2_BUFFER buf;
+ XAUDIO2_VOICE_STATE state;
+
+ XA2CALL_0V(StopEngine);
+
+ if(xaudio27)
+ hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL);
+ else
+ hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
+ ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr);
+
+ fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+ fmt.nChannels = 2;
+ fmt.nSamplesPerSec = 44100;
+ fmt.wBitsPerSample = 32;
+ fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
+ fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
+ fmt.cbSize = 0;
+
+ XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, NULL, NULL, NULL);
+ ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
+
+ memset(&buf, 0, sizeof(buf));
+ buf.AudioBytes = 22050 * fmt.nBlockAlign;
+ buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes);
+ fill_buf((float*)buf.pAudioData, &fmt, 440, 22050);
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
+ ok(hr == S_OK, "Start failed: %08x\n", hr);
+
+ XA2CALL_0(StartEngine);
+ ok(hr == S_OK, "StartEngine failed: %08x\n", hr);
+
+ while(1){
+ if(xaudio27)
+ IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state);
+ else
+ IXAudio2SourceVoice_GetState(src, &state, 0);
+ if(state.SamplesPlayed >= 2205)
+ break;
+ Sleep(10);
+ }
+
+ hr = IXAudio2SourceVoice_Stop(src, 0, XAUDIO2_COMMIT_NOW);
+ ok(hr == S_OK, "Stop failed: %08x\n", hr);
+
+ hr = IXAudio2SourceVoice_FlushSourceBuffers(src);
+ ok(hr == S_OK, "FlushSourceBuffers failed: %08x\n", hr);
+
+ hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
+ ok(hr == S_OK, "Start failed: %08x\n", hr);
+
+ Sleep(100);
+
+ hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
+ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
+
+ if(xaudio27){
+ IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src);
+ }else{
+ IXAudio2SourceVoice_DestroyVoice(src);
+ }
+ IXAudio2MasteringVoice_DestroyVoice(master);
+
+ HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData);
+}
+
static UINT32 test_DeviceDetails(IXAudio27 *xa)
{
HRESULT hr;
@@ -1136,6 +1212,7 @@ START_TEST(xaudio2)
test_buffer_callbacks((IXAudio2*)xa27);
test_looping((IXAudio2*)xa27);
test_submix((IXAudio2*)xa27);
+ test_flush((IXAudio2*)xa27);
}else
skip("No audio devices available\n");
@@ -1159,6 +1236,7 @@ START_TEST(xaudio2)
test_buffer_callbacks(xa);
test_looping(xa);
test_submix(xa);
+ test_flush(xa);
}else
skip("No audio devices available\n");
diff --git a/dlls/xaudio2_7/xaudio_dll.c b/dlls/xaudio2_7/xaudio_dll.c
index 13f591630f..8f15ded023 100644
--- a/dlls/xaudio2_7/xaudio_dll.c
+++ b/dlls/xaudio2_7/xaudio_dll.c
@@ -414,6 +414,7 @@ static void WINAPI XA2SRC_DestroyVoice(IXAudio2SourceVoice *iface)
This->nbufs = 0;
This->first_buf = 0;
This->cur_buf = 0;
+ This->abandoned_albufs = 0;
LeaveCriticalSection(&This->lock);
}
@@ -438,11 +439,18 @@ static HRESULT WINAPI XA2SRC_Stop(IXAudio2SourceVoice *iface, UINT32 Flags,
UINT32 OperationSet)
{
XA2SourceImpl *This = impl_from_IXAudio2SourceVoice(iface);
+ ALint bufs;
TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
+ palcSetThreadContext(This->xa2->al_ctx);
+
EnterCriticalSection(&This->lock);
+ alGetSourcei(This->al_src, AL_BUFFERS_QUEUED, &bufs);
+
+ This->abandoned_albufs = bufs;
+
This->running = FALSE;
LeaveCriticalSection(&This->lock);
@@ -2273,44 +2281,53 @@ static void update_source_state(XA2SourceImpl *src)
ALuint al_buffers[XAUDIO2_MAX_QUEUED_BUFFERS];
alSourceUnqueueBuffers(src->al_src, processed, al_buffers);
+
src->first_al_buf += processed;
src->first_al_buf %= XAUDIO2_MAX_QUEUED_BUFFERS;
src->al_bufs_used -= processed;
- for(i = 0; i < processed; ++i){
- ALint bufsize;
+ if(processed > src->abandoned_albufs){
+ for(i = src->abandoned_albufs; i < processed; ++i){
+ ALint bufsize;
- alGetBufferi(al_buffers[i], AL_SIZE, &bufsize);
+ alGetBufferi(al_buffers[i], AL_SIZE, &bufsize);
- src->in_al_bytes -= bufsize;
- src->played_frames += bufsize / src->submit_blocksize;
+ src->in_al_bytes -= bufsize;
+ src->played_frames += bufsize / src->submit_blocksize;
- if(al_buffers[i] == src->buffers[src->first_buf].latest_al_buf){
- DWORD old_buf = src->first_buf;
+ if(al_buffers[i] == src->buffers[src->first_buf].latest_al_buf){
+ DWORD old_buf = src->first_buf;
- src->first_buf++;
- src->first_buf %= XAUDIO2_MAX_QUEUED_BUFFERS;
- src->nbufs--;
+ src->first_buf++;
+ src->first_buf %= XAUDIO2_MAX_QUEUED_BUFFERS;
+ src->nbufs--;
- TRACE("%p: done with buffer %u\n", src, old_buf);
+ TRACE("%p: done with buffer %u\n", src, old_buf);
- if(src->buffers[old_buf].xa2buffer.Flags & XAUDIO2_END_OF_STREAM)
- src->played_frames = 0;
-
- if(src->cb){
- IXAudio2VoiceCallback_OnBufferEnd(src->cb,
- src->buffers[old_buf].xa2buffer.pContext);
if(src->buffers[old_buf].xa2buffer.Flags & XAUDIO2_END_OF_STREAM)
- IXAudio2VoiceCallback_OnStreamEnd(src->cb);
+ src->played_frames = 0;
- if(src->nbufs > 0)
- IXAudio2VoiceCallback_OnBufferStart(src->cb,
- src->buffers[src->first_buf].xa2buffer.pContext);
+ if(src->cb){
+ IXAudio2VoiceCallback_OnBufferEnd(src->cb,
+ src->buffers[old_buf].xa2buffer.pContext);
+ if(src->buffers[old_buf].xa2buffer.Flags & XAUDIO2_END_OF_STREAM)
+ IXAudio2VoiceCallback_OnStreamEnd(src->cb);
+
+ if(src->nbufs > 0)
+ IXAudio2VoiceCallback_OnBufferStart(src->cb,
+ src->buffers[src->first_buf].xa2buffer.pContext);
+ }
}
}
- }
+
+ src->abandoned_albufs = 0;
+ }else
+ src->abandoned_albufs -= processed;
}
+ if(!src->running)
+ return;
+
alGetSourcei(src->al_src, AL_BYTE_OFFSET, &bufpos);
/* maintain IN_AL_PERIODS periods in AL */
@@ -2384,12 +2401,12 @@ static void do_engine_tick(IXAudio2Impl *This)
EnterCriticalSection(&src->lock);
- if(!src->in_use || !src->running){
+ if(!src->in_use){
LeaveCriticalSection(&src->lock);
continue;
}
- if(src->cb){
+ if(src->cb && This->running){
#if XAUDIO2_VER == 0
IXAudio20VoiceCallback_OnVoiceProcessingPassStart((IXAudio20VoiceCallback*)src->cb);
#else
@@ -2403,12 +2420,14 @@ static void do_engine_tick(IXAudio2Impl *This)
update_source_state(src);
- alGetSourcei(src->al_src, AL_SOURCE_STATE, &st);
- if(st != AL_PLAYING)
- alSourcePlay(src->al_src);
+ if(This->running){
+ alGetSourcei(src->al_src, AL_SOURCE_STATE, &st);
+ if(st != AL_PLAYING)
+ alSourcePlay(src->al_src);
- if(src->cb)
- IXAudio2VoiceCallback_OnVoiceProcessingPassEnd(src->cb);
+ if(src->cb)
+ IXAudio2VoiceCallback_OnVoiceProcessingPassEnd(src->cb);
+ }
LeaveCriticalSection(&src->lock);
}
diff --git a/dlls/xaudio2_7/xaudio_private.h b/dlls/xaudio2_7/xaudio_private.h
index f28a0aec47..1a4aa08ce5 100644
--- a/dlls/xaudio2_7/xaudio_private.h
+++ b/dlls/xaudio2_7/xaudio_private.h
@@ -81,7 +81,7 @@ typedef struct _XA2SourceImpl {
/* most cases will only need about 4 AL buffers, but some corner cases
* could require up to MAX_QUEUED_BUFFERS */
ALuint al_bufs[XAUDIO2_MAX_QUEUED_BUFFERS];
- DWORD first_al_buf, al_bufs_used;
+ DWORD first_al_buf, al_bufs_used, abandoned_albufs;
struct list entry;
} XA2SourceImpl;
--
2.15.0
Nov. 30, 2017