Wine-Devel
Threads by month
- ----- 2026 -----
- 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
- 8 participants
- 84547 discussions
July 31, 2020
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/d3dx11_43/async.c | 31 +++++-
dlls/d3dx11_43/tests/d3dx11.c | 203 ++++++++++++++++++++++++++++++++++
2 files changed, 228 insertions(+), 6 deletions(-)
diff --git a/dlls/d3dx11_43/async.c b/dlls/d3dx11_43/async.c
index cde87cec60..f9d9d0cf9e 100644
--- a/dlls/d3dx11_43/async.c
+++ b/dlls/d3dx11_43/async.c
@@ -236,24 +236,43 @@ HRESULT WINAPI D3DX11CompileFromFileA(const char *filename, const D3D10_SHADER_M
ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags,
ID3DX11ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult)
{
- FIXME("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, "
- "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p stub.\n",
+ WCHAR filename_w[MAX_PATH];
+ DWORD len;
+
+ TRACE("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, "
+ "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p.\n",
debugstr_a(filename), defines, include, debugstr_a(entry_point), debugstr_a(target),
sflags, eflags, pump, shader, error_messages, hresult);
- return E_NOTIMPL;
+ len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
+ MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
+
+ return D3DX11CompileFromFileW(filename_w, defines, include, entry_point, target,
+ sflags, eflags, pump, shader, error_messages, hresult);
}
HRESULT WINAPI D3DX11CompileFromFileW(const WCHAR *filename, const D3D10_SHADER_MACRO *defines,
ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags,
ID3DX11ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult)
{
- FIXME("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, "
- "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p stub.\n",
+ HRESULT hr;
+
+ TRACE("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, "
+ "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p.\n",
debugstr_w(filename), defines, include, debugstr_a(entry_point), debugstr_a(target),
sflags, eflags, pump, shader, error_messages, hresult);
- return E_NOTIMPL;
+ if (pump)
+ FIXME("Unimplemented ID3DX11ThreadPump handling.\n");
+
+ if (!include)
+ include = D3D_COMPILE_STANDARD_FILE_INCLUDE;
+
+ hr = D3DCompileFromFile(filename, defines, include, entry_point, target, sflags, eflags, shader, error_messages);
+ if (hresult)
+ *hresult = hr;
+
+ return hr;
}
HRESULT WINAPI D3DX11CreateAsyncMemoryLoader(const void *data, SIZE_T data_size, ID3DX11DataLoader **loader)
diff --git a/dlls/d3dx11_43/tests/d3dx11.c b/dlls/d3dx11_43/tests/d3dx11.c
index f7ced893b0..90d3417299 100644
--- a/dlls/d3dx11_43/tests/d3dx11.c
+++ b/dlls/d3dx11_43/tests/d3dx11.c
@@ -22,6 +22,63 @@
#include "d3dx11.h"
#include "wine/test.h"
+static WCHAR temp_dir[MAX_PATH];
+
+static BOOL create_file(const WCHAR *filename, const char *data, const unsigned int size, WCHAR *out_path)
+{
+ WCHAR path[MAX_PATH];
+ DWORD written;
+ HANDLE file;
+
+ if (!temp_dir[0])
+ GetTempPathW(ARRAY_SIZE(temp_dir), temp_dir);
+ lstrcpyW(path, temp_dir);
+ lstrcatW(path, filename);
+
+ file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (WriteFile(file, data, size, &written, NULL))
+ {
+ CloseHandle(file);
+
+ if (out_path)
+ lstrcpyW(out_path, path);
+ return TRUE;
+ }
+
+ CloseHandle(file);
+ return FALSE;
+}
+
+static void delete_file(const WCHAR *filename)
+{
+ WCHAR path[MAX_PATH];
+
+ lstrcpyW(path, temp_dir);
+ lstrcatW(path, filename);
+ DeleteFileW(path);
+}
+
+static BOOL create_directory(const WCHAR *dir)
+{
+ WCHAR path[MAX_PATH];
+
+ lstrcpyW(path, temp_dir);
+ lstrcatW(path, dir);
+ return CreateDirectoryW(path, NULL);
+}
+
+static void delete_directory(const WCHAR *dir)
+{
+ WCHAR path[MAX_PATH];
+
+ lstrcpyW(path, temp_dir);
+ lstrcatW(path, dir);
+ RemoveDirectoryW(path);
+}
+
static void test_D3DX11CreateAsyncMemoryLoader(void)
{
ID3DX11DataLoader *loader;
@@ -205,9 +262,155 @@ static void test_D3DX11CreateAsyncResourceLoader(void)
ok(hr == D3DX11_ERR_INVALID_DATA, "Got unexpected hr %#x.\n", hr);
}
+static HRESULT WINAPI test_d3dinclude_open(ID3DInclude *iface, D3D_INCLUDE_TYPE include_type,
+ const char *filename, const void *parent_data, const void **data, UINT *bytes)
+{
+ static const char include1[] =
+ "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n";
+ static const char include2[] =
+ "#include \"include1.h\"\n"
+ "float4 light_color = LIGHT;\n";
+ char *buffer;
+
+ trace("filename %s.\n", filename);
+ trace("parent_data %p: %s.\n", parent_data, parent_data ? (char *)parent_data : "(null)");
+
+ if (!strcmp(filename, "include1.h"))
+ {
+ buffer = HeapAlloc(GetProcessHeap(), 0, strlen(include1));
+ CopyMemory(buffer, include1, strlen(include1));
+ *bytes = strlen(include1);
+ ok(include_type == D3D_INCLUDE_LOCAL, "Wrong include type %d.\n", include_type);
+ ok(parent_data != NULL && !strncmp(include2, parent_data, strlen(include2)),
+ "Wrong parent_data value.\n");
+ }
+ else if (!strcmp(filename, "include\\include2.h"))
+ {
+ buffer = HeapAlloc(GetProcessHeap(), 0, strlen(include2));
+ CopyMemory(buffer, include2, strlen(include2));
+ *bytes = strlen(include2);
+ ok(!parent_data, "Wrong parent_data value.\n");
+ ok(include_type == D3D_INCLUDE_LOCAL, "Wrong include type %d.\n", include_type);
+ }
+ else
+ {
+ ok(0, "Unexpected #include for file %s.\n", filename);
+ return E_INVALIDARG;
+ }
+
+ *data = buffer;
+ return S_OK;
+}
+
+static HRESULT WINAPI test_d3dinclude_close(ID3DInclude *iface, const void *data)
+{
+ HeapFree(GetProcessHeap(), 0, (void *)data);
+ return S_OK;
+}
+
+static const struct ID3DIncludeVtbl test_d3dinclude_vtbl =
+{
+ test_d3dinclude_open,
+ test_d3dinclude_close
+};
+
+struct test_d3dinclude
+{
+ ID3DInclude ID3DInclude_iface;
+};
+
+static void test_D3DX11CompileFromFile(void)
+{
+ WCHAR filename[MAX_PATH], directory[MAX_PATH];
+ ID3D10Blob *blob = NULL, *errors = NULL;
+ struct test_d3dinclude include;
+ CHAR filename_a[MAX_PATH];
+ HRESULT hr, result;
+ DWORD len;
+ static const char ps_code[] =
+ "#include \"include\\include2.h\"\n"
+ "\n"
+ "float4 main() : COLOR\n"
+ "{\n"
+ " return light_color;\n"
+ "}";
+ static const char include1[] =
+ "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n";
+ static const char include1_wrong[] =
+ "#define LIGHT nope\n";
+ static const char include2[] =
+ "#include \"include1.h\"\n"
+ "float4 light_color = LIGHT;\n";
+
+ include.ID3DInclude_iface.lpVtbl = &test_d3dinclude_vtbl;
+
+ create_file(L"source.ps", ps_code, strlen(ps_code), filename);
+ create_directory(L"include");
+ create_file(L"include\\include1.h", include1_wrong, strlen(include1_wrong), NULL);
+ create_file(L"include1.h", include1, strlen(include1), NULL);
+ create_file(L"include\\include2.h", include2, strlen(include2), NULL);
+
+ hr = D3DX11CompileFromFileW(filename, NULL, &include.ID3DInclude_iface, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result);
+ todo_wine ok(hr == S_OK && hr == result, "Got hr %#x, result %#x.\n", hr, result);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ /* Windows always seems to resolve includes from the initial file location
+ * instead of using the immediate parent, as it would be the case for
+ * standard C preprocessor includes. */
+ hr = D3DX11CompileFromFileW(filename, NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result);
+ todo_wine ok(hr == S_OK && hr == result, "Got hr %#x, result %#x.\n", hr, result);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
+ WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
+ hr = D3DX11CompileFromFileA(filename_a, NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result);
+ todo_wine ok(hr == S_OK && hr == result, "Got hr %#x, result %#x.\n", hr, result);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ GetCurrentDirectoryW(MAX_PATH, directory);
+ SetCurrentDirectoryW(temp_dir);
+
+ hr = D3DX11CompileFromFileW(L"source.ps", NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result);
+ todo_wine ok(hr == S_OK && hr == result, "Got hr %#x, result %#x.\n", hr, result);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ SetCurrentDirectoryW(directory);
+
+ delete_file(L"source.ps");
+ delete_file(L"include\\include1.h");
+ delete_file(L"include1.h");
+ delete_file(L"include\\include2.h");
+ delete_directory(L"include");
+}
+
START_TEST(d3dx11)
{
test_D3DX11CreateAsyncMemoryLoader();
test_D3DX11CreateAsyncFileLoader();
test_D3DX11CreateAsyncResourceLoader();
+ test_D3DX11CompileFromFile();
}
--
2.27.0
1
0
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/d3dcompiler_43/compiler.c | 47 ++++++++++++++++++++++---
dlls/d3dcompiler_43/tests/hlsl_d3d9.c | 49 +++++++++++++++++++++++++++
2 files changed, 92 insertions(+), 4 deletions(-)
diff --git a/dlls/d3dcompiler_43/compiler.c b/dlls/d3dcompiler_43/compiler.c
index b3dd39a6f2..41bd01849a 100644
--- a/dlls/d3dcompiler_43/compiler.c
+++ b/dlls/d3dcompiler_43/compiler.c
@@ -1003,13 +1003,52 @@ HRESULT WINAPI D3DDisassemble(const void *data, SIZE_T size, UINT flags, const c
return E_NOTIMPL;
}
-HRESULT WINAPI D3DCompileFromFile(const WCHAR *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *includes,
+HRESULT WINAPI D3DCompileFromFile(const WCHAR *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
const char *entrypoint, const char *target, UINT flags1, UINT flags2, ID3DBlob **code, ID3DBlob **errors)
{
- FIXME("filename %s, defines %p, includes %p, entrypoint %s, target %s, flags1 %x, flags2 %x, code %p, errors %p\n",
- debugstr_w(filename), defines, includes, debugstr_a(entrypoint), debugstr_a(target), flags1, flags2, code, errors);
+ CHAR filename_a[MAX_PATH], *source = NULL;
+ SIZE_T source_size;
+ DWORD read_size;
+ HANDLE file;
+ HRESULT hr;
+ ULONG len;
- return E_NOTIMPL;
+ TRACE("filename %s, defines %p, include %p, entrypoint %s, target %s, flags1 %x, flags2 %x, code %p, errors %p.\n",
+ debugstr_w(filename), defines, include, debugstr_a(entrypoint), debugstr_a(target), flags1, flags2, code, errors);
+
+ file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file == INVALID_HANDLE_VALUE)
+ return HRESULT_FROM_WIN32(GetLastError());
+
+ source_size = GetFileSize(file, NULL);
+ if (source_size == INVALID_FILE_SIZE)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto end;
+ }
+
+ if (!(source = heap_alloc(source_size)))
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ if (!ReadFile(file, source, source_size, &read_size, NULL) || (read_size != source_size))
+ {
+ WARN("Failed to read file contents.\n");
+ hr = E_FAIL;
+ goto end;
+ }
+
+ len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
+ WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
+
+ hr = D3DCompile(source, source_size, filename_a, defines, include, entrypoint, target, flags1, flags2, code, errors);
+
+end:
+ heap_free(source);
+ CloseHandle(file);
+ return hr;
}
HRESULT WINAPI D3DLoadModule(const void *data, SIZE_T size, ID3D11Module **module)
diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
index cf13574c52..0614edf988 100644
--- a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
+++ b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
@@ -28,6 +28,8 @@ static pD3DCompile ppD3DCompile;
static HRESULT (WINAPI *pD3DCompile2)(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines,
ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, UINT secondary_flags,
const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader, ID3DBlob **error_messages);
+static HRESULT (WINAPI *pD3DCompileFromFile)(const WCHAR *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *includes,
+ const char *entrypoint, const char *target, UINT flags1, UINT flags2, ID3DBlob **code, ID3DBlob **errors);
static HRESULT (WINAPI *pD3DXGetShaderConstantTable)(const DWORD *byte_code, ID3DXConstantTable **constant_table);
struct vec2
@@ -1330,6 +1332,7 @@ static BOOL load_d3dcompiler(void)
#if D3D_COMPILER_VERSION == 47
if (!(module = LoadLibraryA("d3dcompiler_47.dll"))) return FALSE;
pD3DCompile2 = (void*)GetProcAddress(module, "D3DCompile2");
+ pD3DCompileFromFile = (void*)GetProcAddress(module, "D3DCompileFromFile");
#else
if (!(module = LoadLibraryA("d3dcompiler_43.dll"))) return FALSE;
#endif
@@ -1491,6 +1494,42 @@ static void test_d3dcompile(void)
blob = NULL;
}
+ hr = pD3DCompileFromFile(L"nonexistent", NULL, NULL, "main", "vs_2_0", 0, 0, &blob, &errors);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Got hr %#x.\n", hr);
+ ok(!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+
+ hr = pD3DCompileFromFile(filename, NULL, NULL, "main", "ps_2_0", 0, 0, &blob, &errors);
+ ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+ ok(!blob, "Got unexpected blob.\n");
+ ok(!!errors, "Got unexpected errors.\n");
+ trace("%s.\n", (char *)ID3D10Blob_GetBufferPointer(errors));
+ ID3D10Blob_Release(errors);
+ errors = NULL;
+
+ hr = pD3DCompileFromFile(filename, NULL, &include.ID3DInclude_iface, "main", "ps_2_0", 0, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ /* Windows always seems to resolve includes from the initial file location
+ * instead of using the immediate parent, as it would be the case for
+ * standard C preprocessor includes. */
+ hr = pD3DCompileFromFile(filename, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "ps_2_0", 0, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
GetCurrentDirectoryW(MAX_PATH, directory);
SetCurrentDirectoryW(temp_dir);
@@ -1516,6 +1555,16 @@ static void test_d3dcompile(void)
blob = NULL;
}
+ hr = pD3DCompileFromFile(L"source.ps", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "ps_2_0", 0, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
SetCurrentDirectoryW(directory);
cleanup:
--
2.27.0
1
0
[PATCH 1/3] d3dcompiler: Add D3D_COMPILE_STANDARD_FILE_INCLUDE support for D3DCompile2().
by Jactry Zeng July 31, 2020
by Jactry Zeng July 31, 2020
July 31, 2020
This patch includes some improvements from Matteo.
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/d3dcompiler_43/compiler.c | 82 +++++++++
dlls/d3dcompiler_43/tests/hlsl_d3d9.c | 250 ++++++++++++++++++++++++++
include/d3dcompiler.h | 2 +
3 files changed, 334 insertions(+)
diff --git a/dlls/d3dcompiler_43/compiler.c b/dlls/d3dcompiler_43/compiler.c
index c400b83d8d..b3dd39a6f2 100644
--- a/dlls/d3dcompiler_43/compiler.c
+++ b/dlls/d3dcompiler_43/compiler.c
@@ -829,12 +829,88 @@ static HRESULT compile_shader(const char *preproc_shader, const char *target, co
return hr;
}
+static HRESULT WINAPI d3dcompiler_include_from_file_open(ID3DInclude *iface, D3D_INCLUDE_TYPE include_type,
+ const char *filename, const void *parent_data, const void **data, UINT *bytes)
+{
+ char *fullpath = NULL, *buffer = NULL, current_dir[MAX_PATH + 1];
+ const char *initial_dir;
+ SIZE_T size;
+ HANDLE file;
+ ULONG read;
+ DWORD len;
+
+ if ((initial_dir = strrchr(initial_filename, '\\')))
+ {
+ len = initial_dir - initial_filename + 1;
+ initial_dir = initial_filename;
+ }
+ else
+ {
+ len = GetCurrentDirectoryA(MAX_PATH, current_dir);
+ current_dir[len] = '\\';
+ len++;
+ initial_dir = current_dir;
+ }
+ fullpath = heap_alloc(len + strlen(filename) + 1);
+ if (!fullpath)
+ return E_OUTOFMEMORY;
+ memcpy(fullpath, initial_dir, len);
+ strcpy(fullpath + len, filename);
+
+ file = CreateFileA(fullpath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ goto error;
+
+ TRACE("Include file found at %s.\n", debugstr_a(fullpath));
+
+ size = GetFileSize(file, NULL);
+ if (size == INVALID_FILE_SIZE)
+ goto error;
+ buffer = heap_alloc(size);
+ if (!buffer)
+ goto error;
+ if (!ReadFile(file, buffer, size, &read, NULL) || read != size)
+ goto error;
+
+ *bytes = size;
+ *data = buffer;
+
+ heap_free(fullpath);
+ CloseHandle(file);
+ return S_OK;
+
+error:
+ heap_free(fullpath);
+ heap_free(buffer);
+ CloseHandle(file);
+ WARN("Returning E_FAIL.\n");
+ return E_FAIL;
+}
+
+static HRESULT WINAPI d3dcompiler_include_from_file_close(ID3DInclude *iface, const void *data)
+{
+ heap_free((void *)data);
+ return S_OK;
+}
+
+const struct ID3DIncludeVtbl d3dcompiler_include_from_file_vtbl =
+{
+ d3dcompiler_include_from_file_open,
+ d3dcompiler_include_from_file_close
+};
+
+struct d3dcompiler_include_from_file
+{
+ ID3DInclude ID3DInclude_iface;
+};
+
HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filename,
const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
const char *target, UINT sflags, UINT eflags, UINT secondary_flags,
const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader,
ID3DBlob **error_messages)
{
+ struct d3dcompiler_include_from_file include_from_file;
HRESULT hr;
TRACE("data %p, data_size %lu, filename %s, defines %p, include %p, entrypoint %s, "
@@ -850,6 +926,12 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen
if (shader) *shader = NULL;
if (error_messages) *error_messages = NULL;
+ if (include == D3D_COMPILE_STANDARD_FILE_INCLUDE)
+ {
+ include_from_file.ID3DInclude_iface.lpVtbl = &d3dcompiler_include_from_file_vtbl;
+ include = &include_from_file.ID3DInclude_iface;
+ }
+
EnterCriticalSection(&wpp_mutex);
hr = preprocess_shader(data, data_size, filename, defines, include, error_messages);
diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
index ed148ff112..cf13574c52 100644
--- a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
+++ b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
@@ -25,6 +25,9 @@
static pD3DCompile ppD3DCompile;
+static HRESULT (WINAPI *pD3DCompile2)(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines,
+ ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, UINT secondary_flags,
+ const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader, ID3DBlob **error_messages);
static HRESULT (WINAPI *pD3DXGetShaderConstantTable)(const DWORD *byte_code, ID3DXConstantTable **constant_table);
struct vec2
@@ -37,6 +40,63 @@ struct vec4
float x, y, z, w;
};
+static WCHAR temp_dir[MAX_PATH];
+
+static BOOL create_file(const WCHAR *filename, const char *data, const unsigned int size, WCHAR *out_path)
+{
+ WCHAR path[MAX_PATH];
+ DWORD written;
+ HANDLE file;
+
+ if (!temp_dir[0])
+ GetTempPathW(ARRAY_SIZE(temp_dir), temp_dir);
+ lstrcpyW(path, temp_dir);
+ lstrcatW(path, filename);
+
+ file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (WriteFile(file, data, size, &written, NULL))
+ {
+ CloseHandle(file);
+
+ if (out_path)
+ lstrcpyW(out_path, path);
+ return TRUE;
+ }
+
+ CloseHandle(file);
+ return FALSE;
+}
+
+static void delete_file(const WCHAR *filename)
+{
+ WCHAR path[MAX_PATH];
+
+ lstrcpyW(path, temp_dir);
+ lstrcatW(path, filename);
+ DeleteFileW(path);
+}
+
+static BOOL create_directory(const WCHAR *dir)
+{
+ WCHAR path[MAX_PATH];
+
+ lstrcpyW(path, temp_dir);
+ lstrcatW(path, dir);
+ return CreateDirectoryW(path, NULL);
+}
+
+static void delete_directory(const WCHAR *dir)
+{
+ WCHAR path[MAX_PATH];
+
+ lstrcpyW(path, temp_dir);
+ lstrcatW(path, dir);
+ RemoveDirectoryW(path);
+}
+
#define compile_shader(a, b) compile_shader_(__LINE__, a, b)
static ID3D10Blob *compile_shader_(unsigned int line, const char *source, const char *target)
{
@@ -1269,6 +1329,7 @@ static BOOL load_d3dcompiler(void)
#if D3D_COMPILER_VERSION == 47
if (!(module = LoadLibraryA("d3dcompiler_47.dll"))) return FALSE;
+ pD3DCompile2 = (void*)GetProcAddress(module, "D3DCompile2");
#else
if (!(module = LoadLibraryA("d3dcompiler_43.dll"))) return FALSE;
#endif
@@ -1277,6 +1338,194 @@ static BOOL load_d3dcompiler(void)
return TRUE;
}
+static HRESULT WINAPI test_d3dinclude_open(ID3DInclude *iface, D3D_INCLUDE_TYPE include_type,
+ const char *filename, const void *parent_data, const void **data, UINT *bytes)
+{
+ static const char include1[] =
+ "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n";
+ static const char include2[] =
+ "#include \"include1.h\"\n"
+ "float4 light_color = LIGHT;\n";
+ char *buffer;
+
+ trace("filename %s.\n", filename);
+ trace("parent_data %p: %s.\n", parent_data, parent_data ? (char *)parent_data : "(null)");
+
+ if (!strcmp(filename, "include1.h"))
+ {
+ buffer = HeapAlloc(GetProcessHeap(), 0, strlen(include1));
+ CopyMemory(buffer, include1, strlen(include1));
+ *bytes = strlen(include1);
+ ok(include_type == D3D_INCLUDE_LOCAL, "Wrong include type %d.\n", include_type);
+ ok(parent_data != NULL && !strncmp(include2, parent_data, strlen(include2)),
+ "Wrong parent_data value.\n");
+ }
+ else if (!strcmp(filename, "include\\include2.h"))
+ {
+ buffer = HeapAlloc(GetProcessHeap(), 0, strlen(include2));
+ CopyMemory(buffer, include2, strlen(include2));
+ *bytes = strlen(include2);
+ ok(!parent_data, "Wrong parent_data value.\n");
+ ok(include_type == D3D_INCLUDE_LOCAL, "Wrong include type %d.\n", include_type);
+ }
+ else
+ {
+ ok(0, "Unexpected #include for file %s.\n", filename);
+ return D3DERR_INVALIDCALL;
+ }
+
+ *data = buffer;
+ return S_OK;
+}
+
+static HRESULT WINAPI test_d3dinclude_close(ID3DInclude *iface, const void *data)
+{
+ HeapFree(GetProcessHeap(), 0, (void *)data);
+ return S_OK;
+}
+
+static const struct ID3DIncludeVtbl test_d3dinclude_vtbl =
+{
+ test_d3dinclude_open,
+ test_d3dinclude_close
+};
+
+struct test_d3dinclude
+{
+ ID3DInclude ID3DInclude_iface;
+};
+
+static void test_d3dcompile(void)
+{
+ WCHAR filename[MAX_PATH], directory[MAX_PATH];
+ ID3D10Blob *blob = NULL, *errors = NULL;
+ struct test_d3dinclude include;
+ CHAR filename_a[MAX_PATH];
+ HRESULT hr;
+ DWORD len;
+ static const char ps_code[] =
+ "#include \"include\\include2.h\"\n"
+ "\n"
+ "float4 main() : COLOR\n"
+ "{\n"
+ " return light_color;\n"
+ "}";
+ static const char include1[] =
+ "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n";
+ static const char include1_wrong[] =
+ "#define LIGHT nope\n";
+ static const char include2[] =
+ "#include \"include1.h\"\n"
+ "float4 light_color = LIGHT;\n";
+
+ include.ID3DInclude_iface.lpVtbl = &test_d3dinclude_vtbl;
+
+ create_file(L"source.ps", ps_code, strlen(ps_code), filename);
+ create_directory(L"include");
+ create_file(L"include\\include1.h", include1_wrong, strlen(include1_wrong), NULL);
+ create_file(L"include1.h", include1, strlen(include1), NULL);
+ create_file(L"include\\include2.h", include2, strlen(include2), NULL);
+
+ len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
+ WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
+
+ hr = ppD3DCompile(ps_code, sizeof(ps_code), filename_a, NULL, &include.ID3DInclude_iface, "main", "ps_2_0", 0, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ /* Also skip tests of D3D_COMPILE_STANDARD_FILE_INCLUDE for D3DCompile() from
+ * d3dcompiler_43 or eailier since they crash on Windows. */
+ if (!pD3DCompile2)
+ {
+ skip("D3DCompile2() isn't supported.\n");
+ goto cleanup;
+ }
+
+ hr = ppD3DCompile(ps_code, sizeof(ps_code), NULL, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main", "ps_2_0", 0, 0, &blob, &errors);
+ ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+ ok(!blob, "Got unexpected blob.\n");
+ ok(!!errors, "Got unexpected errors.\n");
+ ID3D10Blob_Release(errors);
+ errors = NULL;
+
+ /* Windows always seems to resolve includes from the initial file location
+ * instead of using the immediate parent, as it would be the case for
+ * standard C preprocessor includes. */
+ hr = ppD3DCompile(ps_code, sizeof(ps_code), filename_a, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main", "ps_2_0", 0, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ hr = pD3DCompile2(ps_code, sizeof(ps_code), filename_a, NULL, &include.ID3DInclude_iface,
+ "main", "ps_2_0", 0, 0, 0, NULL, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ hr = pD3DCompile2(ps_code, sizeof(ps_code), filename_a, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main", "ps_2_0", 0, 0, 0, NULL, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ GetCurrentDirectoryW(MAX_PATH, directory);
+ SetCurrentDirectoryW(temp_dir);
+
+ hr = ppD3DCompile(ps_code, sizeof(ps_code), "source.ps", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main", "ps_2_0", 0, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ hr = pD3DCompile2(ps_code, sizeof(ps_code), "source.ps", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main", "ps_2_0", 0, 0, 0, NULL, 0, &blob, &errors);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(!!blob, "Got unexpected blob.\n");
+ ok(!errors, "Got unexpected errors.\n");
+ if (blob)
+ {
+ ID3D10Blob_Release(blob);
+ blob = NULL;
+ }
+
+ SetCurrentDirectoryW(directory);
+
+cleanup:
+ delete_file(L"source.ps");
+ delete_file(L"include\\include1.h");
+ delete_file(L"include1.h");
+ delete_file(L"include\\include2.h");
+ delete_directory(L"include");
+}
+
START_TEST(hlsl_d3d9)
{
HMODULE mod;
@@ -1309,4 +1558,5 @@ START_TEST(hlsl_d3d9)
test_constant_table();
test_fail();
+ test_d3dcompile();
}
diff --git a/include/d3dcompiler.h b/include/d3dcompiler.h
index bd1b3d1d44..b892950aa7 100644
--- a/include/d3dcompiler.h
+++ b/include/d3dcompiler.h
@@ -81,6 +81,8 @@ static const WCHAR D3DCOMPILER_DLL_W[] = {'d','3','d','c','o','m','p','i','l','e
#define D3D_DISASM_INSTRUCTION_ONLY 0x00000040
#define D3D_DISASM_PRINT_HEX_LITERALS 0x00000080
+#define D3D_COMPILE_STANDARD_FILE_INCLUDE ((ID3DInclude *)(UINT_PTR)1)
+
HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename,
const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
--
2.27.0
1
0
From: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
v2: Pass the buffer/expected size to stream_chunk_get_data()
dlls/dmime/timesigtrack.c | 54 +++++++++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/dlls/dmime/timesigtrack.c b/dlls/dmime/timesigtrack.c
index 697b3e3593b..a85f134e0f1 100644
--- a/dlls/dmime/timesigtrack.c
+++ b/dlls/dmime/timesigtrack.c
@@ -37,6 +37,11 @@ static inline IDirectMusicTimeSigTrack *impl_from_IDirectMusicTrack(IDirectMusic
return CONTAINING_RECORD(iface, IDirectMusicTimeSigTrack, IDirectMusicTrack_iface);
}
+static inline IDirectMusicTimeSigTrack *impl_from_IPersistStream(IPersistStream *iface)
+{
+ return CONTAINING_RECORD(iface, IDirectMusicTimeSigTrack, dmobj.IPersistStream_iface);
+}
+
static HRESULT WINAPI IDirectMusicTrackImpl_QueryInterface(IDirectMusicTrack *iface, REFIID riid,
void **ret_iface)
{
@@ -207,10 +212,55 @@ static const IDirectMusicTrackVtbl dmtack_vtbl = {
IDirectMusicTrackImpl_Clone
};
+
+static HRESULT parse_timetrack_list(IDirectMusicTimeSigTrack *This, IStream *stream,
+ struct chunk_entry *timesig)
+{
+ HRESULT hr;
+ struct chunk_entry chunk = {.parent = timesig};
+ DMUS_IO_TIMESIGNATURE_ITEM item;
+
+ TRACE("Parsing segment form in %p: %s\n", stream, debugstr_chunk(timesig));
+
+ while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
+ if (chunk.id != DMUS_FOURCC_TIMESIGNATURE_TRACK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &item, sizeof(item)))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+
+ TRACE("Found DMUS_IO_TIMESIGNATURE_ITEM\n");
+ TRACE(" - lTime %d\n", item.lTime);
+ TRACE(" - bBeatsPerMeasure %d\n", item.bBeatsPerMeasure);
+ TRACE(" - bBeat %d\n", item.bBeat);
+ TRACE(" - wGridsPerBeat %d\n", item.wGridsPerBeat);
+ }
+
+ return SUCCEEDED(hr) ? S_OK : hr;
+}
+
static HRESULT WINAPI time_IPersistStream_Load(IPersistStream *iface, IStream *stream)
{
- FIXME(": Loading not implemented yet\n");
- return S_OK;
+ IDirectMusicTimeSigTrack *This = impl_from_IPersistStream(iface);
+ HRESULT hr;
+ struct chunk_entry chunk = {0};
+
+ TRACE("%p, %p\n", This, stream);
+
+ if (!stream)
+ return E_POINTER;
+
+ if ((hr = stream_get_chunk(stream, &chunk) != S_OK))
+ return hr;
+
+ if (chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_TIMESIGTRACK_LIST)
+ hr = parse_timetrack_list(This, stream, &chunk);
+ else
+ hr = DMUS_E_UNSUPPORTED_STREAM;
+
+ return hr;
}
static const IPersistStreamVtbl persiststream_vtbl = {
--
2.26.2
2
1
July 30, 2020
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
I know of no application yet that requires this behaviour, or in fact even tries
to query file/object information from a device file. These tests are rather
meant to illustrate how ObjectNameInformation is implemented for files, which in
turn may help to inform our implementation for server-based objects such as
regular files and named pipes.
dlls/ntoskrnl.exe/tests/driver.c | 120 +++++++++++++++++++++++++++--
dlls/ntoskrnl.exe/tests/ntoskrnl.c | 114 +++++++++++++++++++++++++++
2 files changed, 226 insertions(+), 8 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 0671a56efc7..d3f62879a40 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -37,6 +37,19 @@
#include "utils.h"
+/* memcmp() isn't exported from ntoskrnl on i386 */
+static int kmemcmp( const void *ptr1, const void *ptr2, size_t n )
+{
+ const unsigned char *p1, *p2;
+
+ for (p1 = ptr1, p2 = ptr2; n; n--, p1++, p2++)
+ {
+ if (*p1 < *p2) return -1;
+ if (*p1 > *p2) return 1;
+ }
+ return 0;
+}
+
static const WCHAR device_name[] = {'\\','D','e','v','i','c','e',
'\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
static const WCHAR upper_name[] = {'\\','D','e','v','i','c','e',
@@ -55,6 +68,13 @@ static PETHREAD create_irp_thread;
NTSTATUS WINAPI ZwQueryInformationProcess(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*);
+struct file_context
+{
+ DWORD id;
+ ULONG namelen;
+ WCHAR name[10];
+};
+
static void *get_proc_address(const char *name)
{
UNICODE_STRING name_u;
@@ -2175,15 +2195,15 @@ static NTSTATUS get_fscontext(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *inf
{
ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
char *buffer = irp->AssociatedIrp.SystemBuffer;
- DWORD *context = stack->FileObject->FsContext;
+ struct file_context *context = stack->FileObject->FsContext;
- if (!buffer || !context)
+ if (!buffer)
return STATUS_ACCESS_VIOLATION;
if (length < sizeof(DWORD))
return STATUS_BUFFER_TOO_SMALL;
- *(DWORD*)buffer = *context;
+ *(DWORD*)buffer = context->id;
*info = sizeof(DWORD);
return STATUS_SUCCESS;
}
@@ -2271,13 +2291,21 @@ static NTSTATUS test_completion_ioctl(DEVICE_OBJECT *device, IRP *irp)
static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp)
{
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
- DWORD *context = ExAllocatePool(PagedPool, sizeof(*context));
+ struct file_context *context = ExAllocatePool(PagedPool, sizeof(*context));
- last_created_file = irpsp->FileObject;
- ++create_count;
- if (context)
- *context = create_count;
+ if (!context)
+ {
+ irp->IoStatus.Status = STATUS_NO_MEMORY;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return STATUS_NO_MEMORY;
+ }
+
+ context->id = ++create_count;
+ context->namelen = min(irpsp->FileObject->FileName.Length, sizeof(context->name));
+ memcpy(context->name, irpsp->FileObject->FileName.Buffer, context->namelen);
irpsp->FileObject->FsContext = context;
+
+ last_created_file = irpsp->FileObject;
create_caller_thread = KeGetCurrentThread();
create_irp_thread = irp->Tail.Overlay.Thread;
@@ -2356,6 +2384,81 @@ static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp)
return STATUS_PENDING;
}
+static BOOL compare_file_name(const struct file_context *context, const WCHAR *expect)
+{
+ return context->namelen == wcslen(expect) * sizeof(WCHAR)
+ && !kmemcmp(context->name, expect, context->namelen);
+}
+
+static NTSTATUS WINAPI driver_QueryInformation(DEVICE_OBJECT *device, IRP *irp)
+{
+ IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
+ NTSTATUS ret;
+
+ switch (stack->Parameters.QueryFile.FileInformationClass)
+ {
+ case FileNameInformation:
+ {
+ const struct file_context *context = stack->FileObject->FsContext;
+ FILE_NAME_INFORMATION *info = irp->AssociatedIrp.SystemBuffer;
+ ULONG len;
+
+ if (stack->Parameters.QueryFile.Length < sizeof(*info))
+ {
+ ret = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ if (compare_file_name(context, L"\\notimpl"))
+ {
+ ret = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ else if (compare_file_name(context, L""))
+ {
+ ret = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+ else if (compare_file_name(context, L"\\badparam"))
+ {
+ ret = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ else if (compare_file_name(context, L"\\genfail"))
+ {
+ ret = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ else if (compare_file_name(context, L"\\badtype"))
+ {
+ ret = STATUS_OBJECT_TYPE_MISMATCH;
+ break;
+ }
+
+ len = stack->Parameters.QueryFile.Length - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
+ if (len < context->namelen)
+ ret = STATUS_BUFFER_OVERFLOW;
+ else
+ {
+ len = context->namelen;
+ ret = STATUS_SUCCESS;
+ }
+ irp->IoStatus.Information = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + len;
+ info->FileNameLength = context->namelen;
+ memcpy(info->FileName, context->name, len);
+ break;
+ }
+
+ default:
+ ret = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+
+ irp->IoStatus.Status = ret;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return ret;
+}
+
static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp)
{
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
@@ -2400,6 +2503,7 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
driver->MajorFunction[IRP_MJ_CREATE] = driver_Create;
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_IoControl;
driver->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = driver_FlushBuffers;
+ driver->MajorFunction[IRP_MJ_QUERY_INFORMATION] = driver_QueryInformation;
driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close;
RtlInitUnicodeString(&nameW, IoDriverObjectTypeW);
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index b4ef9d0dcb7..61b1e401c56 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -493,6 +493,119 @@ static void test_return_status(void)
ok(ret_size == 3, "got size %u\n", ret_size);
}
+static BOOL compare_unicode_string(const WCHAR *buffer, ULONG len, const WCHAR *expect)
+{
+ return len == wcslen(expect) * sizeof(WCHAR) && !memcmp(buffer, expect, len);
+}
+
+static void test_object_info(void)
+{
+ char buffer[200];
+ OBJECT_NAME_INFORMATION *name_info = (OBJECT_NAME_INFORMATION *)buffer;
+ OBJECT_TYPE_INFORMATION *type_info = (OBJECT_TYPE_INFORMATION *)buffer;
+ FILE_NAME_INFORMATION *file_info = (FILE_NAME_INFORMATION *)buffer;
+ HANDLE file;
+ NTSTATUS status;
+ IO_STATUS_BLOCK io;
+ ULONG size;
+
+ status = NtQueryObject(device, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ todo_wine ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ status = NtQueryObject(device, ObjectTypeInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(type_info->TypeName.Buffer, type_info->TypeName.Length, L"File"),
+ "wrong name %s\n", debugstr_wn(type_info->TypeName.Buffer, type_info->TypeName.Length / sizeof(WCHAR)));
+
+ status = NtQueryInformationFile(device, &io, buffer, sizeof(buffer), FileNameInformation);
+ todo_wine ok(status == STATUS_INVALID_DEVICE_REQUEST, "got %#x\n", status);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\subfile", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ todo_wine ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+ if (file == INVALID_HANDLE_VALUE) return;
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), &size);
+ ok(!status, "got %#x\n", status);
+ ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
+ ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver\\subfile"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ status = NtQueryObject(file, ObjectNameInformation, buffer, size - 2, &size);
+ ok(status == STATUS_BUFFER_OVERFLOW, "got %#x\n", status);
+ ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
+ ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver\\subfil"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(*name_info), &size);
+ ok(status == STATUS_BUFFER_OVERFLOW, "got %#x\n", status);
+ ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
+
+ status = NtQueryObject(file, ObjectTypeInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(type_info->TypeName.Buffer, type_info->TypeName.Length, L"File"),
+ "wrong name %s\n", debugstr_wn(type_info->TypeName.Buffer, type_info->TypeName.Length / sizeof(WCHAR)));
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(file_info->FileName, file_info->FileNameLength, L"\\subfile"),
+ "wrong name %s\n", debugstr_wn(file_info->FileName, file_info->FileNameLength / sizeof(WCHAR)));
+
+ CloseHandle(file);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\notimpl", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(status == STATUS_NOT_IMPLEMENTED, "got %#x\n", status);
+
+ CloseHandle(file);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\badparam", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(status == STATUS_INVALID_PARAMETER, "got %#x\n", status);
+
+ CloseHandle(file);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\genfail", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(status == STATUS_UNSUCCESSFUL, "got %#x\n", status);
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(status == STATUS_UNSUCCESSFUL, "got %#x\n", status);
+
+ CloseHandle(file);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\badtype", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(status == STATUS_OBJECT_TYPE_MISMATCH, "got %#x\n", status);
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(status == STATUS_OBJECT_TYPE_MISMATCH, "got %#x\n", status);
+
+ CloseHandle(file);
+}
+
static void test_driver3(void)
{
char filename[MAX_PATH];
@@ -644,6 +757,7 @@ START_TEST(ntoskrnl)
test_load_driver(service2);
test_file_handles();
test_return_status();
+ test_object_info();
/* We need a separate ioctl to call IoDetachDevice(); calling it in the
* driver unload routine causes a live-lock. */
--
2.27.0
1
1
[PATCH v2] amstream: Return correct media type info when enumerating AMAudioStream media types.
by Gijs Vermeulen July 30, 2020
by Gijs Vermeulen July 30, 2020
July 30, 2020
Signed-off-by: Gijs Vermeulen <gijsvrm(a)gmail.com>
---
dlls/amstream/audiostream.c | 21 ++++++++++++++++++++-
dlls/amstream/tests/amstream.c | 11 ++++++-----
2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/dlls/amstream/audiostream.c b/dlls/amstream/audiostream.c
index 072850aae7..dc6c810d19 100644
--- a/dlls/amstream/audiostream.c
+++ b/dlls/amstream/audiostream.c
@@ -837,6 +837,17 @@ static HRESULT WINAPI enum_media_types_Next(IEnumMediaTypes *iface, ULONG count,
{
struct enum_media_types *enum_media_types = impl_from_IEnumMediaTypes(iface);
+ static const WAVEFORMATEX wfx =
+ {
+ .wFormatTag = WAVE_FORMAT_PCM,
+ .nChannels = 1,
+ .nSamplesPerSec = 11025,
+ .nAvgBytesPerSec = 11025 * 2,
+ .nBlockAlign = 2,
+ .wBitsPerSample = 16,
+ .cbSize = 0,
+ };
+
TRACE("iface %p, count %u, mts %p, ret_count %p.\n", iface, count, mts, ret_count);
if (!ret_count)
@@ -847,7 +858,15 @@ static HRESULT WINAPI enum_media_types_Next(IEnumMediaTypes *iface, ULONG count,
mts[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
memset(mts[0], 0, sizeof(AM_MEDIA_TYPE));
mts[0]->majortype = MEDIATYPE_Audio;
- mts[0]->subtype = MEDIASUBTYPE_PCM;
+ mts[0]->subtype = GUID_NULL;
+ mts[0]->bFixedSizeSamples = TRUE;
+ mts[0]->bTemporalCompression = FALSE;
+ mts[0]->lSampleSize = 2;
+ mts[0]->formattype = FORMAT_WaveFormatEx;
+ mts[0]->cbFormat = sizeof(WAVEFORMATEX);
+ mts[0]->pbFormat = CoTaskMemAlloc(sizeof(WAVEFORMATEX));
+ memcpy(mts[0]->pbFormat, &wfx, sizeof(WAVEFORMATEX));
+
++enum_media_types->index;
*ret_count = 1;
return count == 1 ? S_OK : S_FALSE;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c
index 130f9f0e0e..cf66538a7a 100644
--- a/dlls/amstream/tests/amstream.c
+++ b/dlls/amstream/tests/amstream.c
@@ -2515,20 +2515,21 @@ static void test_media_types(void)
ok(count == 1, "Got count %u.\n", count);
ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Audio), "Got major type %s\n",
wine_dbgstr_guid(&pmt->majortype));
- todo_wine ok(IsEqualGUID(&pmt->subtype, &GUID_NULL), "Got subtype %s\n",
+ ok(IsEqualGUID(&pmt->subtype, &GUID_NULL), "Got subtype %s\n",
wine_dbgstr_guid(&pmt->subtype));
- todo_wine ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples);
+ ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples);
ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression);
- todo_wine ok(pmt->lSampleSize == 2, "Got sample size %u.\n", pmt->lSampleSize);
- todo_wine ok(IsEqualGUID(&pmt->formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n",
+ ok(pmt->lSampleSize == 2, "Got sample size %u.\n", pmt->lSampleSize);
+ ok(IsEqualGUID(&pmt->formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n",
wine_dbgstr_guid(&pmt->formattype));
ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk);
- todo_wine ok(pmt->cbFormat == sizeof(WAVEFORMATEX), "Got format size %u.\n", pmt->cbFormat);
+ ok(pmt->cbFormat == sizeof(WAVEFORMATEX), "Got format size %u.\n", pmt->cbFormat);
ok(!memcmp(pmt->pbFormat, &expect_wfx, pmt->cbFormat), "Format blocks didn't match.\n");
hr = IPin_QueryAccept(pin, pmt);
ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+ CoTaskMemFree(pmt->pbFormat);
CoTaskMemFree(pmt);
hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
--
2.27.0
2
1
July 30, 2020
Many Windows games do not expect that maxImageCount can be set to 0.
A value of 0 means that there is no limit on the number of images.
Nvidia reports 8 on Windows, AMD 16.
Based on a patch by Józef Kucia.
Signed-off-by: Georg Lehmann <dadschoorse(a)gmail.com>
---
dlls/winevulkan/make_vulkan | 4 ++--
dlls/winevulkan/vulkan.c | 41 +++++++++++++++++++++++++++++++++
dlls/winevulkan/vulkan_thunks.c | 8 ++-----
dlls/winevulkan/vulkan_thunks.h | 4 ++++
4 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index fc0e2182dd..6a039bd268 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -183,12 +183,12 @@ FUNCTION_OVERRIDES = {
# VK_KHR_surface
"vkDestroySurfaceKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
"vkGetPhysicalDeviceSurfaceSupportKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
- "vkGetPhysicalDeviceSurfaceCapabilitiesKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
+ "vkGetPhysicalDeviceSurfaceCapabilitiesKHR" : {"dispatch" : True, "driver" : True, "thunk" : False, "private_thunk" : True},
"vkGetPhysicalDeviceSurfaceFormatsKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
"vkGetPhysicalDeviceSurfacePresentModesKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
# VK_KHR_get_surface_capabilities2
- "vkGetPhysicalDeviceSurfaceCapabilities2KHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
+ "vkGetPhysicalDeviceSurfaceCapabilities2KHR" : {"dispatch" : True, "driver" : True, "thunk" : False, "private_thunk" : True},
"vkGetPhysicalDeviceSurfaceFormats2KHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
# VK_KHR_win32_surface
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index be614f1cef..1e83defa18 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -1555,6 +1555,47 @@ void WINAPI wine_vkGetPrivateDataEXT(VkDevice device, VkObjectType object_type,
device->funcs.p_vkGetPrivateDataEXT(device->device, object_type, object_handle, private_data_slot, data);
}
+static inline void adjust_max_image_count(VkSurfaceCapabilitiesKHR* capabilities)
+{
+ /* Many Windows games do not expect that maxImageCount can be set to 0.
+ * A value of 0 means that there is no limit on the number of images.
+ * Nvidia reports 8 on Windows, AMD 16.*/
+ if (!capabilities->maxImageCount)
+ {
+ capabilities->maxImageCount = 16;
+ }
+}
+
+VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev,
+ VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *capabilities)
+{
+ VkResult res;
+
+ TRACE("%p, 0x%s, %p\n", phys_dev, wine_dbgstr_longlong(surface), capabilities);
+
+ res = thunk_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, surface, capabilities);
+
+ if (res == VK_SUCCESS)
+ adjust_max_image_count(capabilities);
+
+ return res;
+}
+
+VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev,
+ const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, VkSurfaceCapabilities2KHR *capabilities)
+{
+ VkResult res;
+
+ TRACE("%p, %p, %p\n", phys_dev, surface_info, capabilities);
+
+ res = thunk_vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev, surface_info, capabilities);
+
+ if (res == VK_SUCCESS)
+ adjust_max_image_count(&capabilities->surfaceCapabilities);
+
+ return res;
+}
+
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
{
TRACE("%p, %u, %p\n", hinst, reason, reserved);
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c
index fcefa6a767..4f75a4ec7c 100644
--- a/dlls/winevulkan/vulkan_thunks.c
+++ b/dlls/winevulkan/vulkan_thunks.c
@@ -4998,26 +4998,22 @@ static VkResult WINAPI wine_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesC
return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(physicalDevice->phys_dev, pCombinationCount, pCombinations);
}
-VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
+VkResult thunk_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
{
#if defined(USE_STRUCT_CONVERSION)
VkResult result;
VkPhysicalDeviceSurfaceInfo2KHR_host pSurfaceInfo_host;
- TRACE("%p, %p, %p\n", physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
-
convert_VkPhysicalDeviceSurfaceInfo2KHR_win_to_host(pSurfaceInfo, &pSurfaceInfo_host);
result = physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice->phys_dev, &pSurfaceInfo_host, pSurfaceCapabilities);
return result;
#else
- TRACE("%p, %p, %p\n", physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice->phys_dev, pSurfaceInfo, pSurfaceCapabilities);
#endif
}
-VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
+VkResult thunk_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
{
- TRACE("%p, 0x%s, %p\n", physicalDevice, wine_dbgstr_longlong(surface), pSurfaceCapabilities);
return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice->phys_dev, surface, pSurfaceCapabilities);
}
diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h
index f2d650decf..d35e8c4269 100644
--- a/dlls/winevulkan/vulkan_thunks.h
+++ b/dlls/winevulkan/vulkan_thunks.h
@@ -42,6 +42,8 @@ VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice
VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN;
void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties);
void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN;
+VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkSurfaceCapabilities2KHR *pSurfaceCapabilities);
+VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities);
void WINAPI wine_vkGetPrivateDataEXT(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlotEXT privateDataSlot, uint64_t *pData) DECLSPEC_HIDDEN;
VkResult WINAPI wine_vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence);
VkResult WINAPI wine_vkSetPrivateDataEXT(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlotEXT privateDataSlot, uint64_t data) DECLSPEC_HIDDEN;
@@ -51,6 +53,8 @@ VkResult thunk_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physic
VkResult thunk_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN;
void thunk_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN;
void thunk_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN;
+VkResult thunk_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkSurfaceCapabilities2KHR *pSurfaceCapabilities) DECLSPEC_HIDDEN;
+VkResult thunk_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) DECLSPEC_HIDDEN;
typedef struct VkAcquireNextImageInfoKHR_host
{
--
2.28.0
3
2
July 30, 2020
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
I know of no application yet that requires this behaviour, or in fact even tries
to query file/object information from a device file. These tests are rather
meant to illustrate how ObjectNameInformation is implemented for files, which in
turn may help to inform our implementation for server-based objects such as
regular files and named pipes.
dlls/ntoskrnl.exe/tests/driver.c | 120 +++++++++++++++++++++++++++--
dlls/ntoskrnl.exe/tests/ntoskrnl.c | 114 +++++++++++++++++++++++++++
2 files changed, 226 insertions(+), 8 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 0671a56efc7..d3f62879a40 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -37,6 +37,19 @@
#include "utils.h"
+/* memcmp() isn't exported from ntoskrnl on i386 */
+static int kmemcmp( const void *ptr1, const void *ptr2, size_t n )
+{
+ const unsigned char *p1, *p2;
+
+ for (p1 = ptr1, p2 = ptr2; n; n--, p1++, p2++)
+ {
+ if (*p1 < *p2) return -1;
+ if (*p1 > *p2) return 1;
+ }
+ return 0;
+}
+
static const WCHAR device_name[] = {'\\','D','e','v','i','c','e',
'\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
static const WCHAR upper_name[] = {'\\','D','e','v','i','c','e',
@@ -55,6 +68,13 @@ static PETHREAD create_irp_thread;
NTSTATUS WINAPI ZwQueryInformationProcess(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*);
+struct file_context
+{
+ DWORD id;
+ ULONG namelen;
+ WCHAR name[10];
+};
+
static void *get_proc_address(const char *name)
{
UNICODE_STRING name_u;
@@ -2175,15 +2195,15 @@ static NTSTATUS get_fscontext(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *inf
{
ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
char *buffer = irp->AssociatedIrp.SystemBuffer;
- DWORD *context = stack->FileObject->FsContext;
+ struct file_context *context = stack->FileObject->FsContext;
- if (!buffer || !context)
+ if (!buffer)
return STATUS_ACCESS_VIOLATION;
if (length < sizeof(DWORD))
return STATUS_BUFFER_TOO_SMALL;
- *(DWORD*)buffer = *context;
+ *(DWORD*)buffer = context->id;
*info = sizeof(DWORD);
return STATUS_SUCCESS;
}
@@ -2271,13 +2291,21 @@ static NTSTATUS test_completion_ioctl(DEVICE_OBJECT *device, IRP *irp)
static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp)
{
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
- DWORD *context = ExAllocatePool(PagedPool, sizeof(*context));
+ struct file_context *context = ExAllocatePool(PagedPool, sizeof(*context));
- last_created_file = irpsp->FileObject;
- ++create_count;
- if (context)
- *context = create_count;
+ if (!context)
+ {
+ irp->IoStatus.Status = STATUS_NO_MEMORY;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return STATUS_NO_MEMORY;
+ }
+
+ context->id = ++create_count;
+ context->namelen = min(irpsp->FileObject->FileName.Length, sizeof(context->name));
+ memcpy(context->name, irpsp->FileObject->FileName.Buffer, context->namelen);
irpsp->FileObject->FsContext = context;
+
+ last_created_file = irpsp->FileObject;
create_caller_thread = KeGetCurrentThread();
create_irp_thread = irp->Tail.Overlay.Thread;
@@ -2356,6 +2384,81 @@ static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp)
return STATUS_PENDING;
}
+static BOOL compare_file_name(const struct file_context *context, const WCHAR *expect)
+{
+ return context->namelen == wcslen(expect) * sizeof(WCHAR)
+ && !kmemcmp(context->name, expect, context->namelen);
+}
+
+static NTSTATUS WINAPI driver_QueryInformation(DEVICE_OBJECT *device, IRP *irp)
+{
+ IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
+ NTSTATUS ret;
+
+ switch (stack->Parameters.QueryFile.FileInformationClass)
+ {
+ case FileNameInformation:
+ {
+ const struct file_context *context = stack->FileObject->FsContext;
+ FILE_NAME_INFORMATION *info = irp->AssociatedIrp.SystemBuffer;
+ ULONG len;
+
+ if (stack->Parameters.QueryFile.Length < sizeof(*info))
+ {
+ ret = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ if (compare_file_name(context, L"\\notimpl"))
+ {
+ ret = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ else if (compare_file_name(context, L""))
+ {
+ ret = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+ else if (compare_file_name(context, L"\\badparam"))
+ {
+ ret = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ else if (compare_file_name(context, L"\\genfail"))
+ {
+ ret = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ else if (compare_file_name(context, L"\\badtype"))
+ {
+ ret = STATUS_OBJECT_TYPE_MISMATCH;
+ break;
+ }
+
+ len = stack->Parameters.QueryFile.Length - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
+ if (len < context->namelen)
+ ret = STATUS_BUFFER_OVERFLOW;
+ else
+ {
+ len = context->namelen;
+ ret = STATUS_SUCCESS;
+ }
+ irp->IoStatus.Information = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + len;
+ info->FileNameLength = context->namelen;
+ memcpy(info->FileName, context->name, len);
+ break;
+ }
+
+ default:
+ ret = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+
+ irp->IoStatus.Status = ret;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return ret;
+}
+
static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp)
{
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
@@ -2400,6 +2503,7 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
driver->MajorFunction[IRP_MJ_CREATE] = driver_Create;
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_IoControl;
driver->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = driver_FlushBuffers;
+ driver->MajorFunction[IRP_MJ_QUERY_INFORMATION] = driver_QueryInformation;
driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close;
RtlInitUnicodeString(&nameW, IoDriverObjectTypeW);
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index b4ef9d0dcb7..61b1e401c56 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -493,6 +493,119 @@ static void test_return_status(void)
ok(ret_size == 3, "got size %u\n", ret_size);
}
+static BOOL compare_unicode_string(const WCHAR *buffer, ULONG len, const WCHAR *expect)
+{
+ return len == wcslen(expect) * sizeof(WCHAR) && !memcmp(buffer, expect, len);
+}
+
+static void test_object_info(void)
+{
+ char buffer[200];
+ OBJECT_NAME_INFORMATION *name_info = (OBJECT_NAME_INFORMATION *)buffer;
+ OBJECT_TYPE_INFORMATION *type_info = (OBJECT_TYPE_INFORMATION *)buffer;
+ FILE_NAME_INFORMATION *file_info = (FILE_NAME_INFORMATION *)buffer;
+ HANDLE file;
+ NTSTATUS status;
+ IO_STATUS_BLOCK io;
+ ULONG size;
+
+ status = NtQueryObject(device, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ todo_wine ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ status = NtQueryObject(device, ObjectTypeInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(type_info->TypeName.Buffer, type_info->TypeName.Length, L"File"),
+ "wrong name %s\n", debugstr_wn(type_info->TypeName.Buffer, type_info->TypeName.Length / sizeof(WCHAR)));
+
+ status = NtQueryInformationFile(device, &io, buffer, sizeof(buffer), FileNameInformation);
+ todo_wine ok(status == STATUS_INVALID_DEVICE_REQUEST, "got %#x\n", status);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\subfile", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ todo_wine ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+ if (file == INVALID_HANDLE_VALUE) return;
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), &size);
+ ok(!status, "got %#x\n", status);
+ ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
+ ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver\\subfile"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ status = NtQueryObject(file, ObjectNameInformation, buffer, size - 2, &size);
+ ok(status == STATUS_BUFFER_OVERFLOW, "got %#x\n", status);
+ ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
+ ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver\\subfil"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(*name_info), &size);
+ ok(status == STATUS_BUFFER_OVERFLOW, "got %#x\n", status);
+ ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
+
+ status = NtQueryObject(file, ObjectTypeInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(type_info->TypeName.Buffer, type_info->TypeName.Length, L"File"),
+ "wrong name %s\n", debugstr_wn(type_info->TypeName.Buffer, type_info->TypeName.Length / sizeof(WCHAR)));
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(file_info->FileName, file_info->FileNameLength, L"\\subfile"),
+ "wrong name %s\n", debugstr_wn(file_info->FileName, file_info->FileNameLength / sizeof(WCHAR)));
+
+ CloseHandle(file);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\notimpl", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(status == STATUS_NOT_IMPLEMENTED, "got %#x\n", status);
+
+ CloseHandle(file);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\badparam", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(!status, "got %#x\n", status);
+ ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
+ "wrong name %s\n", debugstr_w(name_info->Name.Buffer));
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(status == STATUS_INVALID_PARAMETER, "got %#x\n", status);
+
+ CloseHandle(file);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\genfail", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(status == STATUS_UNSUCCESSFUL, "got %#x\n", status);
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(status == STATUS_UNSUCCESSFUL, "got %#x\n", status);
+
+ CloseHandle(file);
+
+ file = CreateFileA("\\\\.\\WineTestDriver\\badtype", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
+
+ status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
+ ok(status == STATUS_OBJECT_TYPE_MISMATCH, "got %#x\n", status);
+
+ status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
+ ok(status == STATUS_OBJECT_TYPE_MISMATCH, "got %#x\n", status);
+
+ CloseHandle(file);
+}
+
static void test_driver3(void)
{
char filename[MAX_PATH];
@@ -644,6 +757,7 @@ START_TEST(ntoskrnl)
test_load_driver(service2);
test_file_handles();
test_return_status();
+ test_object_info();
/* We need a separate ioctl to call IoDetachDevice(); calling it in the
* driver unload routine causes a live-lock. */
--
2.27.0
2
2
July 30, 2020
Signed-off-by: Gijs Vermeulen <gijsvrm(a)gmail.com>
---
dlls/amstream/tests/amstream.c | 326 +++++++++++++++++++++++----------
1 file changed, 225 insertions(+), 101 deletions(-)
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c
index 130f9f0e0e..17ff110f11 100644
--- a/dlls/amstream/tests/amstream.c
+++ b/dlls/amstream/tests/amstream.c
@@ -2542,106 +2542,6 @@ static void test_media_types(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
-static void test_IDirectDrawStreamSample(void)
-{
- IDirectDrawMediaStream *ddraw_stream = NULL;
- IDirectDrawStreamSample *sample = NULL;
- IDirectDrawSurface *surface, *surface2;
- IMediaStream *stream2, *stream = NULL;
- DDSURFACEDESC desc = { sizeof(desc) };
- IAMMultiMediaStream *mmstream;
- IDirectDrawSurface7 *surface7;
- HRESULT hr;
- RECT rect;
-
- if (!(mmstream = create_ammultimediastream()))
- return;
- if (!create_directdraw())
- {
- IAMMultiMediaStream_Release(mmstream);
- return;
- }
-
- hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
- ok(hr == S_OK, "got 0x%08x\n", hr);
-
- hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown*)pdd7, &MSPID_PrimaryVideo, 0, NULL);
- ok(hr == S_OK, "got 0x%08x\n", hr);
-
- hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryVideo, &stream);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- if (FAILED(hr)) goto error;
-
- hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- if (FAILED(hr)) goto error;
-
- hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
- ok(hr == S_OK, "got 0x%08x\n", hr);
-
- surface = NULL;
- hr = IDirectDrawStreamSample_GetSurface(sample, &surface, &rect);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- ok(surface != NULL, "got %p\n", surface);
-
- /* Crashes on native. */
- if (0)
- {
- hr = IDirectDrawStreamSample_GetMediaStream(sample, NULL);
- ok(hr == E_POINTER, "Got hr %#x.\n", hr);
- }
-
- hr = IDirectDrawStreamSample_GetMediaStream(sample, &stream2);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(stream2 == stream, "Expected stream %p, got %p.\n", stream, stream2);
- IMediaStream_Release(stream2);
-
- hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- IDirectDrawSurface7_Release(surface7);
-
- hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- ok(desc.dwWidth == 100, "width %d\n", desc.dwWidth);
- ok(desc.dwHeight == 100, "height %d\n", desc.dwHeight);
- ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "format flags %08x\n", desc.ddpfPixelFormat.dwFlags);
- ok(desc.ddpfPixelFormat.dwRGBBitCount, "dwRGBBitCount %d\n", desc.ddpfPixelFormat.dwRGBBitCount);
- IDirectDrawSurface_Release(surface);
- IDirectDrawStreamSample_Release(sample);
-
- hr = IDirectDrawSurface7_QueryInterface(pdds7, &IID_IDirectDrawSurface, (void **)&surface);
- ok(hr == S_OK, "got 0x%08x\n", hr);
-
- EXPECT_REF(surface, 1);
- hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- EXPECT_REF(surface, 2);
-
- surface2 = NULL;
- SetRectEmpty(&rect);
- hr = IDirectDrawStreamSample_GetSurface(sample, &surface2, &rect);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- ok(surface == surface2, "got %p\n", surface2);
- ok(rect.right > 0 && rect.bottom > 0, "got %d, %d\n", rect.right, rect.bottom);
- EXPECT_REF(surface, 3);
- IDirectDrawSurface_Release(surface2);
-
- hr = IDirectDrawStreamSample_GetSurface(sample, NULL, NULL);
- ok(hr == S_OK, "got 0x%08x\n", hr);
-
- IDirectDrawStreamSample_Release(sample);
- IDirectDrawSurface_Release(surface);
-
-error:
- if (ddraw_stream)
- IDirectDrawMediaStream_Release(ddraw_stream);
- if (stream)
- IMediaStream_Release(stream);
-
- release_directdraw();
- IAMMultiMediaStream_Release(mmstream);
-}
-
static IUnknown *create_audio_data(void)
{
IUnknown *audio_data = NULL;
@@ -5727,6 +5627,227 @@ static void test_audiostreamsample_get_audio_data(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static void test_ddrawstream_create_sample(void)
+{
+ IAMMultiMediaStream *mmstream = create_ammultimediastream();
+ IDirectDrawMediaStream *ddraw_stream;
+ IDirectDrawStreamSample *sample;
+ IDirectDrawSurface *surface;
+ IMediaStream *stream;
+ IDirectDraw *ddraw;
+ DDSURFACEDESC desc;
+ HRESULT hr;
+ RECT rect;
+ ULONG ref;
+
+ hr = DirectDrawCreate(NULL, &ddraw, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ /* Crashes on native. */
+ if (0)
+ {
+ hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, NULL);
+ ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ }
+
+ SetRectEmpty(&rect);
+ hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, &rect, 0, &sample);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ EXPECT_REF(stream, 3);
+ hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine EXPECT_REF(stream, 4);
+ IDirectDrawStreamSample_Release(sample);
+ EXPECT_REF(stream, 3);
+
+ memset(&desc, 0, sizeof(desc));
+ desc.dwSize = sizeof(desc);
+ desc.dwFlags = DDSD_CAPS;
+ desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ EXPECT_REF(surface, 1);
+ hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ EXPECT_REF(surface, 2);
+ IDirectDrawStreamSample_Release(sample);
+ EXPECT_REF(surface, 1);
+
+ hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IDirectDrawMediaStream_Release(ddraw_stream);
+ ref = IDirectDrawStreamSample_Release(sample);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IDirectDrawSurface_Release(surface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IDirectDraw_Release(ddraw);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
+static void test_ddrawstreamsample_get_media_stream(void)
+{
+ IAMMultiMediaStream *mmstream = create_ammultimediastream();
+ IDirectDrawMediaStream *ddraw_stream;
+ IDirectDrawStreamSample *sample;
+ IMediaStream *stream, *stream2;
+ IDirectDraw *ddraw;
+ HRESULT hr;
+ ULONG ref;
+
+ hr = DirectDrawCreate(NULL, &ddraw, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ /* Crashes on native. */
+ if (0)
+ {
+ hr = IDirectDrawStreamSample_GetMediaStream(sample, NULL);
+ ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+ }
+
+ todo_wine EXPECT_REF(stream, 4);
+ hr = IDirectDrawStreamSample_GetMediaStream(sample, &stream2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(stream2 == stream, "Expected stream %p, got %p.\n", stream, stream2);
+ todo_wine EXPECT_REF(stream, 5);
+ IMediaStream_Release(stream2);
+ todo_wine EXPECT_REF(stream, 4);
+
+ IDirectDrawMediaStream_Release(ddraw_stream);
+ ref = IDirectDrawStreamSample_Release(sample);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IDirectDraw_Release(ddraw);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
+static void test_ddrawstreamsample_get_surface(void)
+{
+ IAMMultiMediaStream *mmstream = create_ammultimediastream();
+ IDirectDrawSurface *surface, *surface2;
+ DDSURFACEDESC desc = { sizeof(desc) };
+ IDirectDrawMediaStream *ddraw_stream;
+ IDirectDrawStreamSample *sample;
+ IMediaStream *stream;
+ IDirectDraw *ddraw;
+ HRESULT hr;
+ RECT rect;
+ ULONG ref;
+
+ hr = DirectDrawCreate(NULL, &ddraw, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IDirectDraw_SetCooperativeLevel(ddraw, GetDesktopWindow(), DDSCL_NORMAL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IDirectDrawStreamSample_GetSurface(sample, NULL, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IDirectDrawStreamSample_GetSurface(sample, NULL, &rect);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IDirectDrawStreamSample_GetSurface(sample, &surface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(surface != NULL, "Expected non-NULL surface.\n");
+ IDirectDrawSurface_Release(surface);
+
+ surface = NULL;
+ hr = IDirectDrawStreamSample_GetSurface(sample, &surface, &rect);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(surface != NULL, "Expected non-NULL surface.\n");
+
+ hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(desc.dwWidth == 100, "Expected width 100, got %d.\n", desc.dwWidth);
+ ok(desc.dwHeight == 100, "Expected height 100, got %d.\n", desc.dwHeight);
+ ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Expected format flags DDPF_RGB, got %#x.\n", desc.ddpfPixelFormat.dwFlags);
+ ok(desc.ddpfPixelFormat.dwRGBBitCount, "Expected non-zero RGB bit count.\n");
+ IDirectDrawSurface_Release(surface);
+ IDirectDrawStreamSample_Release(sample);
+
+ memset(&desc, 0, sizeof(desc));
+ desc.dwSize = sizeof(desc);
+ desc.dwFlags = DDSD_CAPS;
+ desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ EXPECT_REF(surface, 1);
+ hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ EXPECT_REF(surface, 2);
+
+ surface2 = NULL;
+ SetRectEmpty(&rect);
+ hr = IDirectDrawStreamSample_GetSurface(sample, &surface2, &rect);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(surface2 == surface, "Expected surface %p, got %p.\n", surface, surface2);
+ ok(rect.right > 0 && rect.bottom > 0, "Got rect %d, %d.\n", rect.right, rect.bottom);
+ EXPECT_REF(surface, 3);
+ IDirectDrawSurface_Release(surface2);
+ EXPECT_REF(surface, 2);
+
+ IDirectDrawMediaStream_Release(ddraw_stream);
+ ref = IDirectDrawStreamSample_Release(sample);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IDirectDrawSurface_Release(surface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IMediaStream_Release(stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IDirectDraw_Release(ddraw);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
START_TEST(amstream)
{
const WCHAR *test_avi_path;
@@ -5743,7 +5864,6 @@ START_TEST(amstream)
test_set_state();
test_enum_media_types();
test_media_types();
- test_IDirectDrawStreamSample();
test_avi_path = load_resource(L"test.avi");
@@ -5779,6 +5899,10 @@ START_TEST(amstream)
test_ddrawstream_initialize();
test_ddrawstream_getsetdirectdraw();
test_ddrawstream_receive_connection();
+ test_ddrawstream_create_sample();
+
+ test_ddrawstreamsample_get_media_stream();
+ test_ddrawstreamsample_get_surface();
test_ammediastream_join_am_multi_media_stream();
test_ammediastream_join_filter();
--
2.27.0
1
2
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/kernel32/tests/console.c | 106 ++++++++++++++++++++++++++++++++++
1 file changed, 106 insertions(+)
2
1