Compare commits

...

77 commits

Author SHA1 Message Date
Aida Jonikienė
3721f40152 Merge branch 'mr/sdl-hide' into 'master'
ntdll: Add some SDL variables to the special variables list.

See merge request wine/wine!5231
2024-11-19 22:26:52 +00:00
Vibhav Pant
044527c671 setupapi: Implement SetupDiGetDevicePropertyKeys. 2024-11-19 23:16:17 +01:00
Vibhav Pant
b6d427cae7 setupapi/tests: Add tests for SetupDiGetDevicePropertyKeys. 2024-11-19 23:16:17 +01:00
Vibhav Pant
d23d2847c5 setupapi: Add stub for SetupDiGetDevicePropertyKeys. 2024-11-19 23:16:17 +01:00
Jacek Caban
6927ccf6cc ntdll: Use proper format string for ULONG type. 2024-11-19 23:16:17 +01:00
Jacek Caban
34dce6335a configure: Preserve original CFLAGS when adding LLVM flags.
Ensure that the specified CROSSCFLAGS (or its default value) is applied consistently during
toolchain checks. Also fixes debug format recognition.

The regression was introduced in commit 471d7178ae.
2024-11-19 21:11:54 +01:00
Charlotte Pabst
005c8b8b9d jscript/tests: Add tests for star and opt operators in global regex. 2024-11-19 21:11:54 +01:00
Charlotte Pabst
1365b27a6b jscript: Handle star and opt operators while matching global regex properly.
Before this fix, the regex engine would run into an infinite loop and OOM when encountering a
quantifier allowing a zero amount of items in a REG_GLOB regex.
2024-11-19 21:11:54 +01:00
Rémi Bernon
721b7f5df6 evr: Use D3DCREATE_MULTITHREADED device creation flag. 2024-11-19 21:11:54 +01:00
Rémi Bernon
7b58ce5a02 d3d9/tests: Flush events after minimizing and restoring focus window.
Minimizing the window might trigger a focus change to the dummy window,
while restoring and setting foreground should change the foreground
back to the focus window.

However, the X window manager will instead send WM_TAKE_FOCUS event to
the dummy window and to the focus window concurrently, and the dummy
window might reply to it *after* we've restored the foreground to the
focus window. This will later cause the device window to fail to get
foreground, and the tests to randomly fail.
2024-11-19 21:11:54 +01:00
Matteo Bruni
8923eb51ea wined3d: Allow reusing current GL context without a current RT.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57411
2024-11-19 21:11:54 +01:00
Haoyang Chen
5b4237d2be wined3d: Fix a memory leak. 2024-11-19 21:11:54 +01:00
Elizabeth Figura
a50dd3392b wined3d: Beginnings of an HLSL FFP vertex shader implementation. 2024-11-19 21:11:54 +01:00
Elizabeth Figura
eaef138dce wined3d: Use the FFP HLSL pipeline for pretransformed draws as well. 2024-11-19 21:11:54 +01:00
Elizabeth Figura
ff43072059 wined3d: Allow using the HLSL FFP replacement with GL.
This will allow us to replace the GLSL FFP pipes, and is useful for testing
the FFP HLSL backend before the Vulkan backend is mature enough in other
respects.

This patch introduces the d3d setting "ffp_hlsl", set to a DWORD value.
It is disabled by default, and only has an effect on the GL renderer.
2024-11-19 21:11:54 +01:00
Elizabeth Figura
3251015e68 wined3d: Account for HLSL FFP shaders in find_ps_compile_args().
In most cases, it is possible to construct a D3D shader which behaves
identically to a given FFP pipeline.

There are two exceptions, related to fog and texture transforms, where the FFP
pipeline has special behaviour that cannot be emulated with shaders, and we
handle those here by checking whether our shader is actually an FFP replacement
shader.
2024-11-19 21:11:54 +01:00
Elizabeth Figura
04450b6e07 wined3d: Create stub FFP vertex shaders. 2024-11-19 21:11:54 +01:00
Elizabeth Figura
484c6f9af1 wined3d: Create stub FFP pixel shaders.
We only compute ffp_frag_settings and stash that in the shader byte_code.
The HLSL shader will be compiled to sm2 bytecode on the CS side, and then parsed
and interpreted by the shader backend (and all other code) as if it were a real
shader.

In theory, we could take the extra step of retrieving the settings from this
shader in the GLSL backend, instead of from the current state.
This however requires changing a number of places which currently check
"state->shader[WINED3D_SHADER_TYPE_PIXEL]" to also check "is_ffp_ps", and it
also means we need to handle some more states (shade mode, fog, etc.) as part of
ffp_frag_settings. Both of these will go away as soon as the GLSL backend can
simply consume the generated HLSL shader.
2024-11-19 21:11:54 +01:00
Elizabeth Figura
2eb7397e23 wined3d: Move shader parsing to shader_set_function().
The idea is that we will have wined3d_shader objects that represent shaders
not yet in d3d form (specifically, in HLSL form or containing only an FFP
settings struct.) Hence we need to make it possible to delay d3d shader parsing,
but still keep the rest of shader_init().
2024-11-19 21:11:54 +01:00
Elizabeth Figura
d2bed27bfe wined3d: Move shader_trace(). 2024-11-19 21:11:54 +01:00
Fabian Maurer
c2b9d2102e ieframe: Add IERefreshElevationPolicy stub.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57343
2024-11-19 15:49:21 +01:00
Alexandre Julliard
94ab547404 user32: Don't use server data types in clipboard.c. 2024-11-19 15:49:21 +01:00
Alexandre Julliard
95bab1b106 user32: Move support for posting a DDE message to win32u. 2024-11-19 15:49:21 +01:00
Alexandre Julliard
c66b27557d user32: Move PostQuitMessage() implementation to win32u. 2024-11-19 14:48:33 +01:00
Alexandre Julliard
babb7fbc62 win32u: Implement NtUserBuildNameList(). 2024-11-19 13:24:02 +01:00
Alexandre Julliard
fcb7160816 win32u: Implement NtUserBuildPropList(). 2024-11-19 12:59:31 +01:00
Anton Baskanov
e72bd3a7a0 dplayx: Send ADDPLAYERTOGROUP in AddPlayerToGroup(). 2024-11-19 10:36:10 +01:00
Anton Baskanov
28581f00d6 dplayx: Queue DPSYS_ADDPLAYERTOGROUP in DP_AddPlayerToGroup(). 2024-11-19 10:36:10 +01:00
Anton Baskanov
f37853f532 dplayx/tests: Test client side of AddPlayerToGroup() separately. 2024-11-19 10:36:10 +01:00
Anton Baskanov
7ec576a7bd dplayx: Add group players from SUPERENUMPLAYERSREPLY to the group. 2024-11-19 10:36:10 +01:00
Anton Baskanov
91e5057906 dplayx: Factor out a function for adding player to a group. 2024-11-19 10:36:10 +01:00
Anton Baskanov
434b5a148c dplayx: Always set the data size in GetGroupData(). 2024-11-19 10:36:10 +01:00
Anton Baskanov
924a8e0d69 dplayx: Respect enumeration flags in EnumGroups(). 2024-11-19 10:36:10 +01:00
Fabian Maurer
30c7900c40 msi: Make MsiGetSummaryInformationW open database as direct instead of transacted.
This fixes MsiSummaryInfoPersist not saving data to disk

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55859
2024-11-19 10:35:30 +01:00
Fabian Maurer
2b78570297 msi/tests: Add more tests for MsiSummaryInfoPersist. 2024-11-19 10:35:27 +01:00
Paul Gofman
eea781a03b opengl: Avoid infinite recursion in bezier_approximate() in case of degraded curve. 2024-11-19 10:34:01 +01:00
Gerald Pfeifer
245dfb801e dpwsockx: Don't use true as a variable name.
Revision 78bdd23406 (Oct 13 2023) introduced "true" as a variable name
in DPWSCB_EnumSessions.

This is a reserved identifier in C++ and recent versions of C and with
GCC 15 going to move to -std=gnu23 (so essentically C23) we'd break.
2024-11-19 10:33:37 +01:00
Vitor Ramos
6301854fd7 include: Use enum for PATHCCH_ options.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
2024-11-19 10:33:09 +01:00
Vitor Ramos
e0773560ef include: Add cpp header guard to the pathcch.h.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
2024-11-19 10:33:07 +01:00
Gabriel Ivăncescu
67c1c3c255 mshtml: Use actual referenced prop flags for window script props.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-18 22:42:00 +01:00
Gabriel Ivăncescu
c4630993fb jscript: Make most builtin global objects configurable.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-18 22:42:00 +01:00
Gabriel Ivăncescu
10cf578898 jscript: Delete external props before redefining them.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-18 22:42:00 +01:00
Fabian Maurer
12925e9113 net: Correct error code for stopping non existing service.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55859
2024-11-18 21:39:32 +01:00
Fabian Maurer
bce1213281 net/tests: Add test for stopping non existing service. 2024-11-18 21:39:32 +01:00
Rémi Bernon
0cda918561 winex11: Request window state updates asynchronously. 2024-11-18 21:38:16 +01:00
Rémi Bernon
d8b5a3ae12 winex11: Update the window client config on window state changes. 2024-11-18 21:38:16 +01:00
Rémi Bernon
03738c3f22 winex11: Wait for pending ConfigureNotify before updating the client state. 2024-11-18 21:38:16 +01:00
Rémi Bernon
8bbc193178 winex11: Wait for pending _NET_WM_STATE before updating the client state. 2024-11-18 21:38:16 +01:00
Rémi Bernon
03457ece24 winex11: Don't expect WM_STATE events on override-redirect windows. 2024-11-18 21:38:16 +01:00
Rémi Bernon
be6902d072 winex11: Listen to PropertyNotify events on the virtual desktop window.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57423
2024-11-18 21:38:16 +01:00
Rémi Bernon
6ac127ebc6 dinput: Only call SetCursorPos if ClipCursor fails.
Fixes mouse sometimes jumping around in Mechwarrior Online on
KDE/Wayland.
2024-11-18 21:36:52 +01:00
Rémi Bernon
b1e54a5f04 dinput: Assume that clipping the cursor uses the requested rectangle. 2024-11-18 21:36:51 +01:00
Anton Baskanov
3f7c85f7a3 dplayx: Add groups from SUPERENUMPLAYERSREPLY to the session. 2024-11-18 21:36:41 +01:00
Anton Baskanov
0eb2f18166 dplayx: Inform the SP about group creation in DP_CreateGroup(). 2024-11-18 21:36:41 +01:00
Anton Baskanov
18a7362940 dplayx: Return HRESULT from DP_CreateGroup(). 2024-11-18 21:36:41 +01:00
Anton Baskanov
be022f350d dplayx: Set group data in DP_CreateGroup(). 2024-11-18 21:36:41 +01:00
Anton Baskanov
1b9b7a5e65 dplayx: Add group to the parent group in DP_CreateGroup(). 2024-11-18 21:36:41 +01:00
Anton Baskanov
46b79b1856 dplayx/tests: Check that groups from SUPERENUMPLAYERSREPLY are added to the session. 2024-11-18 21:36:40 +01:00
Anton Baskanov
696ef034db dplayx/tests: Add missing pragma pack directives. 2024-11-18 21:36:40 +01:00
Alexandre Julliard
ac1ff67cfd server: Use an explicit union instead of a typedef for select operations. 2024-11-18 21:35:50 +01:00
Alexandre Julliard
ab399468c2 server: Use an explicit union instead of a typedef for IRP params. 2024-11-18 21:34:40 +01:00
Alexandre Julliard
6f5e34ad14 server: Use an explicit union instead of a typedef for debug event data. 2024-11-18 21:33:42 +01:00
Alexandre Julliard
180ba49cee server: Use an explicit union instead of a typedef for hardware input. 2024-11-18 21:32:53 +01:00
Alexandre Julliard
ce946e57db server: Use an explicit union instead of a typedef for message data. 2024-11-18 21:29:14 +01:00
Eric Pouech
446f3b207f dbghelp: Implement SymRefreshModuleList().
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-18 11:54:35 +01:00
Eric Pouech
90ffd6c7dc dbghelp/tests: Add tests for SymRefreshModuleList().
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-18 11:54:35 +01:00
Eric Pouech
3ca383e34e dbghelp/tests: Add retry wrapper around SymRefreshModuleList().
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-18 11:54:35 +01:00
Rémi Bernon
c5a726e8a3 winebus: Enable hidraw by default for various HOTAS controllers.
Based on contributions from Andrew Conrad, Arkadiusz Hiler, Ivo Ivanov,
and Kai Krakow.
2024-11-18 11:53:54 +01:00
Rémi Bernon
a10ea7e662 winebus: Count HID buttons and pass it to is_hidraw_enabled. 2024-11-18 11:53:54 +01:00
Rémi Bernon
b787e0654a winebus: Lookup device HID usage and usage page on the PE side. 2024-11-18 11:53:54 +01:00
Rémi Bernon
29226ef249 winebus: Build HID report descriptors on device creation. 2024-11-18 11:53:54 +01:00
Rémi Bernon
933b885ce7 winebus: Enable all PID effect types for wheel devices.
Forza Horizon 5 doesn't like unsupported racing wheel force feedback
effects and gives up too soon.

On Windows many wheel devices have custom drivers which report support
for all types of force feedback effects.
2024-11-18 11:53:39 +01:00
Rémi Bernon
c3b1f1430c winebus: Always return success from PID effect control.
Forza Horizon 5 doesn't like unsupported racing wheel force feedback
effects.
2024-11-18 11:53:37 +01:00
Zhiyi Zhang
a308076081 wintypes/tests: Add RoParseTypeName() tests. 2024-11-18 11:52:15 +01:00
Zhiyi Zhang
6e79260df0 wintypes: Implement RoParseTypeName(). 2024-11-18 11:52:12 +01:00
Aida Jonikienė
446328b50f ntdll: Add SDL audio driver variables to the special variables list.
This has the same issue as the video driver variable (but on a smaller
scale because games more rarely use SDL for audio).
2024-07-23 13:25:42 +03:00
Aida Jonikienė
a4b434226b ntdll: Add SDL video driver variables to the special variables list.
Overriding the SDL_VIDEODRIVER variable (for Wayland support as an example)
on the Linux side can lead to some games under Wine failing to load (so treat
that variable as special).
2024-07-23 13:22:32 +03:00
110 changed files with 3936 additions and 1543 deletions

3
configure generated vendored
View file

@ -10483,7 +10483,7 @@ fi }
eval "${wine_arch}_DELAYLOADFLAG=\"-Wl,-delayload,\"" eval "${wine_arch}_DELAYLOADFLAG=\"-Wl,-delayload,\""
as_fn_append ${wine_arch}_EXTRACFLAGS " $llvm_extra_cflags" as_fn_append ${wine_arch}_EXTRACFLAGS " $llvm_extra_cflags"
as_fn_append ${wine_arch}_LDFLAGS " $llvm_extra_ldflags" as_fn_append ${wine_arch}_LDFLAGS " $llvm_extra_ldflags"
CFLAGS="$llvm_extra_cflags $llvm_cflags" CFLAGS="$CFLAGS $llvm_extra_cflags $llvm_cflags"
else else
as_wine_cv_crosscc=`printf "%s\n" "wine_cv_${wine_arch}_crosscc" | sed "$as_sed_sh"` as_wine_cv_crosscc=`printf "%s\n" "wine_cv_${wine_arch}_crosscc" | sed "$as_sed_sh"`
@ -23070,6 +23070,7 @@ wine_fn_config_makefile programs/msidb enable_msidb
wine_fn_config_makefile programs/msiexec enable_msiexec wine_fn_config_makefile programs/msiexec enable_msiexec
wine_fn_config_makefile programs/msinfo32 enable_msinfo32 wine_fn_config_makefile programs/msinfo32 enable_msinfo32
wine_fn_config_makefile programs/net enable_net wine_fn_config_makefile programs/net enable_net
wine_fn_config_makefile programs/net/tests enable_tests
wine_fn_config_makefile programs/netsh enable_netsh wine_fn_config_makefile programs/netsh enable_netsh
wine_fn_config_makefile programs/netstat enable_netstat wine_fn_config_makefile programs/netstat enable_netstat
wine_fn_config_makefile programs/ngen enable_ngen wine_fn_config_makefile programs/ngen enable_ngen

View file

@ -879,7 +879,7 @@ do
AS_VAR_SET([${wine_arch}_DELAYLOADFLAG],["-Wl,-delayload,"]) AS_VAR_SET([${wine_arch}_DELAYLOADFLAG],["-Wl,-delayload,"])
AS_VAR_APPEND([${wine_arch}_EXTRACFLAGS],[" $llvm_extra_cflags"]) AS_VAR_APPEND([${wine_arch}_EXTRACFLAGS],[" $llvm_extra_cflags"])
AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" $llvm_extra_ldflags"]) AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" $llvm_extra_ldflags"])
CFLAGS="$llvm_extra_cflags $llvm_cflags" CFLAGS="$CFLAGS $llvm_extra_cflags $llvm_cflags"
else else
AS_VAR_PUSHDEF([wine_cv_crosscc], [wine_cv_${wine_arch}_crosscc]) AS_VAR_PUSHDEF([wine_cv_crosscc], [wine_cv_${wine_arch}_crosscc])
AC_CACHE_CHECK([whether $CC works], wine_cv_crosscc, AC_CACHE_CHECK([whether $CC works], wine_cv_crosscc,
@ -3468,6 +3468,7 @@ WINE_CONFIG_MAKEFILE(programs/msidb)
WINE_CONFIG_MAKEFILE(programs/msiexec) WINE_CONFIG_MAKEFILE(programs/msiexec)
WINE_CONFIG_MAKEFILE(programs/msinfo32) WINE_CONFIG_MAKEFILE(programs/msinfo32)
WINE_CONFIG_MAKEFILE(programs/net) WINE_CONFIG_MAKEFILE(programs/net)
WINE_CONFIG_MAKEFILE(programs/net/tests)
WINE_CONFIG_MAKEFILE(programs/netsh) WINE_CONFIG_MAKEFILE(programs/netsh)
WINE_CONFIG_MAKEFILE(programs/netstat) WINE_CONFIG_MAKEFILE(programs/netstat)
WINE_CONFIG_MAKEFILE(programs/ngen) WINE_CONFIG_MAKEFILE(programs/ngen)

View file

@ -3145,7 +3145,9 @@ static void test_wndproc(void)
* immediately restores the device on activation. There are plenty of WM_WINDOWPOSCHANGED * immediately restores the device on activation. There are plenty of WM_WINDOWPOSCHANGED
* messages that are generated by ShowWindow, so testing for their absence is pointless. */ * messages that are generated by ShowWindow, so testing for their absence is pointless. */
ShowWindow(focus_window, SW_MINIMIZE); ShowWindow(focus_window, SW_MINIMIZE);
flush_events();
ShowWindow(focus_window, SW_RESTORE); ShowWindow(focus_window, SW_RESTORE);
flush_events();
SetForegroundWindow(focus_window); SetForegroundWindow(focus_window);
flush_events(); flush_events();

View file

@ -300,20 +300,6 @@ BOOL WINAPI SymGetSearchPath(HANDLE hProcess, PSTR szSearchPath,
return ret; return ret;
} }
/******************************************************************
* invade_process
*
* SymInitialize helper: loads in dbghelp all known (and loaded modules)
* this assumes that hProcess is a handle on a valid process
*/
static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOID user)
{
HANDLE hProcess = user;
SymLoadModuleExW(hProcess, 0, name, NULL, base, size, NULL, 0);
return TRUE;
}
const WCHAR *process_getenv(const struct process *process, const WCHAR *name) const WCHAR *process_getenv(const struct process *process, const WCHAR *name)
{ {
size_t name_len; size_t name_len;
@ -432,7 +418,10 @@ static BOOL check_live_target(struct process* pcs, BOOL wow64, BOOL child_wow64)
TRACE("got debug info address %#I64x from PEB %p\n", base, pbi.PebBaseAddress); TRACE("got debug info address %#I64x from PEB %p\n", base, pbi.PebBaseAddress);
if (!elf_read_wine_loader_dbg_info(pcs, base) && !macho_read_wine_loader_dbg_info(pcs, base)) if (!elf_read_wine_loader_dbg_info(pcs, base) && !macho_read_wine_loader_dbg_info(pcs, base))
{
WARN("couldn't load process debug info at %#I64x\n", base); WARN("couldn't load process debug info at %#I64x\n", base);
pcs->loader = &empty_loader_ops;
}
return TRUE; return TRUE;
} }
@ -510,8 +499,9 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP
if (check_live_target(pcs, wow64, child_wow64)) if (check_live_target(pcs, wow64, child_wow64))
{ {
if (fInvadeProcess) if (fInvadeProcess)
EnumerateLoadedModulesW64(hProcess, process_invade_cb, hProcess); module_refresh_list(pcs);
if (pcs->loader) pcs->loader->synchronize_module_list(pcs); else
pcs->loader->synchronize_module_list(pcs);
} }
else if (fInvadeProcess) else if (fInvadeProcess)
{ {

View file

@ -743,6 +743,7 @@ extern BOOL module_remove(struct process* pcs,
extern void module_set_module(struct module* module, const WCHAR* name); extern void module_set_module(struct module* module, const WCHAR* name);
extern WCHAR* get_wine_loader_name(struct process *pcs) __WINE_DEALLOC(HeapFree, 3) __WINE_MALLOC; extern WCHAR* get_wine_loader_name(struct process *pcs) __WINE_DEALLOC(HeapFree, 3) __WINE_MALLOC;
extern BOOL module_is_wine_host(const WCHAR* module_name, const WCHAR* ext); extern BOOL module_is_wine_host(const WCHAR* module_name, const WCHAR* ext);
extern BOOL module_refresh_list(struct process *pcs);
/* msc.c */ /* msc.c */
extern BOOL pe_load_debug_directory(const struct process* pcs, extern BOOL pe_load_debug_directory(const struct process* pcs,

View file

@ -1785,7 +1785,6 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr)
{ {
ERR("Unable to access ELF libraries (outside 32bit limit)\n"); ERR("Unable to access ELF libraries (outside 32bit limit)\n");
module_remove(pcs, elf_info.module); module_remove(pcs, elf_info.module);
pcs->loader = &empty_loader_ops;
return FALSE; return FALSE;
} }
TRACE("Found ELF debug header %#I64x\n", elf_info.dbg_hdr_addr); TRACE("Found ELF debug header %#I64x\n", elf_info.dbg_hdr_addr);

View file

@ -24,6 +24,8 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h" #include "dbghelp_private.h"
#include "image_private.h" #include "image_private.h"
#include "psapi.h" #include "psapi.h"
@ -1317,7 +1319,11 @@ BOOL WINAPI EnumerateLoadedModulesW64(HANDLE process,
size_t sysdir_len = 0, wowdir_len = 0; size_t sysdir_len = 0, wowdir_len = 0;
/* process might not be a handle to a live process */ /* process might not be a handle to a live process */
if (!IsWow64Process2(process, &pcs_machine, &native_machine)) return FALSE; if (!IsWow64Process2(process, &pcs_machine, &native_machine))
{
SetLastError(STATUS_INVALID_CID);
return FALSE;
}
with_32bit_modules = sizeof(void*) > sizeof(int) && with_32bit_modules = sizeof(void*) > sizeof(int) &&
pcs_machine != IMAGE_FILE_MACHINE_UNKNOWN && pcs_machine != IMAGE_FILE_MACHINE_UNKNOWN &&
(dbghelp_options & SYMOPT_INCLUDE_32BIT_MODULES); (dbghelp_options & SYMOPT_INCLUDE_32BIT_MODULES);
@ -1600,18 +1606,41 @@ void module_reset_debug_info(struct module* module)
module->sources = NULL; module->sources = NULL;
} }
static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOID user)
{
HANDLE hProcess = user;
/* Note: this follows native behavior:
* If a PE module has been unloaded from debuggee, it's not immediately removed
* from module list in dbghelp.
* Removal may eventually happen when loading a another module with SymLoadModule:
* if the module to be loaded overlaps an existing one, SymLoadModule will
* automatically unload the eldest one.
*/
SymLoadModuleExW(hProcess, 0, name, NULL, base, size, NULL, 0);
return TRUE;
}
BOOL module_refresh_list(struct process *pcs)
{
BOOL ret;
ret = pcs->loader->synchronize_module_list(pcs);
ret = EnumerateLoadedModulesW64(pcs->handle, process_invade_cb, pcs->handle) && ret;
return ret;
}
/****************************************************************** /******************************************************************
* SymRefreshModuleList (DBGHELP.@) * SymRefreshModuleList (DBGHELP.@)
*/ */
BOOL WINAPI SymRefreshModuleList(HANDLE hProcess) BOOL WINAPI SymRefreshModuleList(HANDLE hProcess)
{ {
struct process* pcs; struct process *pcs;
TRACE("(%p)\n", hProcess); TRACE("(%p)\n", hProcess);
if (!(pcs = process_find_by_handle(hProcess))) return FALSE; if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
return module_refresh_list(pcs);
return pcs->loader->synchronize_module_list(pcs);
} }
/*********************************************************************** /***********************************************************************

View file

@ -372,6 +372,29 @@ static unsigned get_native_module_count(HANDLE proc)
return count; return count;
} }
struct module_present
{
const WCHAR* module_name;
BOOL found;
};
static BOOL CALLBACK is_module_present_cb(const WCHAR* name, DWORD64 base, void* usr)
{
struct module_present* present = usr;
if (!wcsicmp(name, present->module_name))
{
present->found = TRUE;
return FALSE;
}
return TRUE;
}
static BOOL is_module_present(HANDLE proc, const WCHAR* module_name)
{
struct module_present present = { .module_name = module_name };
return SymEnumerateModulesW64(proc, is_module_present_cb, &present) && present.found;
}
struct nth_module struct nth_module
{ {
HANDLE proc; HANDLE proc;
@ -424,6 +447,28 @@ static BOOL wrapper_EnumerateLoadedModulesW64(HANDLE proc, PENUMLOADED_MODULES_C
return ret; return ret;
} }
/* wrapper around SymRefreshModuleList which sometimes fails (it's very likely implemented on top
* of EnumerateLoadedModulesW64 on native too)
*/
static BOOL wrapper_SymRefreshModuleList(HANDLE proc)
{
BOOL ret;
int retry;
int retry_count = !strcmp(winetest_platform, "wine") ? 1 : 5;
for (retry = retry_count - 1; retry >= 0; retry--)
{
ret = SymRefreshModuleList(proc);
if (ret || (GetLastError() != STATUS_INFO_LENGTH_MISMATCH && GetLastError() == STATUS_PARTIAL_COPY))
break;
Sleep(10);
}
if (retry + 1 < retry_count)
trace("used wrapper retry: ret=%d retry=%d top=%d\n", ret, retry, retry_count);
return ret;
}
static BOOL test_modules(void) static BOOL test_modules(void)
{ {
BOOL ret; BOOL ret;
@ -492,6 +537,7 @@ static BOOL test_modules(void)
ret = SymRefreshModuleList(dummy); ret = SymRefreshModuleList(dummy);
ok(!ret, "SymRefreshModuleList should have failed\n"); ok(!ret, "SymRefreshModuleList should have failed\n");
ok(GetLastError() == STATUS_INVALID_CID, "Unexpected last error %lx\n", GetLastError());
count = get_module_count(dummy); count = get_module_count(dummy);
ok(count == 0, "Unexpected count (%u instead of 0)\n", count); ok(count == 0, "Unexpected count (%u instead of 0)\n", count);
@ -825,6 +871,11 @@ static void test_loaded_modules(void)
ok(ret, "got error %lu\n", GetLastError()); ok(ret, "got error %lu\n", GetLastError());
strcat(buffer, "\\msinfo32.exe"); strcat(buffer, "\\msinfo32.exe");
/* testing invalid process handle */
ret = wrapper_EnumerateLoadedModulesW64((HANDLE)(ULONG_PTR)0xffffffc0, NULL, FALSE);
ok(!ret, "EnumerateLoadedModulesW64 should have failed\n");
ok(GetLastError() == STATUS_INVALID_CID, "Unexpected last error %lx\n", GetLastError());
/* testing with child process of different machines */ /* testing with child process of different machines */
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
ok(ret, "CreateProcess failed: %lu\n", GetLastError()); ok(ret, "CreateProcess failed: %lu\n", GetLastError());
@ -885,9 +936,10 @@ static void test_loaded_modules(void)
pcskind = get_process_kind(pi.hProcess); pcskind = get_process_kind(pi.hProcess);
ret = SymRefreshModuleList(pi.hProcess); ret = wrapper_SymRefreshModuleList(pi.hProcess);
todo_wine_if(pcskind == PCSKIND_WOW64) ok(ret || broken(GetLastError() == STATUS_PARTIAL_COPY /* Win11 in some cases */ ||
ok(ret || broken(GetLastError() == STATUS_PARTIAL_COPY /* Win11 in some cases */), "SymRefreshModuleList failed: %lu\n", GetLastError()); GetLastError() == STATUS_INFO_LENGTH_MISMATCH /* Win11 in some cases */),
"SymRefreshModuleList failed: %lx\n", GetLastError());
if (!strcmp(winetest_platform, "wine")) if (!strcmp(winetest_platform, "wine"))
{ {
@ -945,8 +997,8 @@ static void test_loaded_modules(void)
"Wrong directory aggregation count %u %u\n", "Wrong directory aggregation count %u %u\n",
aggregation.count_systemdir, aggregation.count_wowdir); aggregation.count_systemdir, aggregation.count_wowdir);
} }
ret = SymRefreshModuleList(pi.hProcess); ret = wrapper_SymRefreshModuleList(pi.hProcess);
ok(ret, "SymRefreshModuleList failed: %lu\n", GetLastError()); ok(ret, "SymRefreshModuleList failed: %lx\n", GetLastError());
if (!strcmp(winetest_platform, "wine")) if (!strcmp(winetest_platform, "wine"))
{ {
@ -1007,8 +1059,8 @@ static void test_loaded_modules(void)
break; break;
} }
ret = SymRefreshModuleList(pi.hProcess); ret = wrapper_SymRefreshModuleList(pi.hProcess);
ok(ret, "SymRefreshModuleList failed: %lu\n", GetLastError()); ok(ret, "SymRefreshModuleList failed: %lx\n", GetLastError());
if (!strcmp(winetest_platform, "wine")) if (!strcmp(winetest_platform, "wine"))
{ {
@ -1529,6 +1581,75 @@ static void test_function_tables(void)
SymCleanup(GetCurrentProcess()); SymCleanup(GetCurrentProcess());
} }
static void test_refresh_modules(void)
{
BOOL ret;
unsigned count, count_current;
HMODULE hmod;
IMAGEHLP_MODULEW64 module_info = { .SizeOfStruct = sizeof(module_info) };
/* pick a DLL: which isn't already loaded by test, and that will not load other DLLs for deps */
static const WCHAR* unused_dll = L"psapi";
ret = SymInitialize(GetCurrentProcess(), 0, TRUE);
ok(ret, "SymInitialize failed: %lu\n", GetLastError());
count = get_module_count(GetCurrentProcess());
ok(count, "Unexpected module count %u\n", count);
ret = SymCleanup(GetCurrentProcess());
ok(ret, "SymCleanup failed: %lu\n", GetLastError());
ret = SymInitialize(GetCurrentProcess(), 0, FALSE);
ok(ret, "SymInitialize failed: %lu\n", GetLastError());
count_current = get_module_count(GetCurrentProcess());
ok(!count_current, "Unexpected module count %u\n", count_current);
ret = wrapper_SymRefreshModuleList(GetCurrentProcess());
ok(ret, "SymRefreshModuleList failed: %lx\n", GetLastError());
count_current = get_module_count(GetCurrentProcess());
ok(count == count_current, "Unexpected module count %u, %u\n", count, count_current);
hmod = GetModuleHandleW(unused_dll);
ok(hmod == NULL, "Expecting DLL %ls not be loaded\n", unused_dll);
hmod = LoadLibraryW(unused_dll);
ok(hmod != NULL, "LoadLibraryW failed: %lu\n", GetLastError());
count_current = get_module_count(GetCurrentProcess());
ok(count == count_current, "Unexpected module count %u, %u\n", count, count_current);
ret = is_module_present(GetCurrentProcess(), unused_dll);
ok(!ret, "Couldn't find module %ls\n", unused_dll);
ret = wrapper_SymRefreshModuleList(GetCurrentProcess());
ok(ret, "SymRefreshModuleList failed: %lx\n", GetLastError());
count_current = get_module_count(GetCurrentProcess());
ok(count + 1 == count_current, "Unexpected module count %u, %u\n", count, count_current);
ret = is_module_present(GetCurrentProcess(), unused_dll);
ok(ret, "Couldn't find module %ls\n", unused_dll);
ret = FreeLibrary(hmod);
ok(ret, "LoadLibraryW failed: %lu\n", GetLastError());
count_current = get_module_count(GetCurrentProcess());
ok(count + 1 == count_current, "Unexpected module count %u, %u\n", count, count_current);
ret = wrapper_SymRefreshModuleList(GetCurrentProcess());
ok(ret, "SymRefreshModuleList failed: %lx\n", GetLastError());
/* SymRefreshModuleList() doesn't remove the unloaded modules... */
count_current = get_module_count(GetCurrentProcess());
ok(count + 1 == count_current, "Unexpected module count %u != %u\n", count, count_current);
ret = is_module_present(GetCurrentProcess(), unused_dll);
ok(ret, "Couldn't find module %ls\n", unused_dll);
ret = SymCleanup(GetCurrentProcess());
ok(ret, "SymCleanup failed: %lu\n", GetLastError());
}
START_TEST(dbghelp) START_TEST(dbghelp)
{ {
BOOL ret; BOOL ret;
@ -1559,6 +1680,7 @@ START_TEST(dbghelp)
test_modules_overlap(); test_modules_overlap();
test_loaded_modules(); test_loaded_modules();
test_live_modules(); test_live_modules();
test_refresh_modules();
} }
test_function_tables(); test_function_tables();
} }

View file

@ -306,20 +306,13 @@ static void warp_check( struct mouse *impl, BOOL force )
if (force || (impl->need_warp && (now - impl->last_warped > interval))) if (force || (impl->need_warp && (now - impl->last_warped > interval)))
{ {
RECT rect, new_rect;
POINT mapped_center; POINT mapped_center;
RECT rect;
impl->last_warped = now; impl->last_warped = now;
impl->need_warp = FALSE; impl->need_warp = FALSE;
if (!GetClientRect( impl->base.win, &rect )) return; if (!GetClientRect( impl->base.win, &rect )) return;
MapWindowPoints( impl->base.win, 0, (POINT *)&rect, 2 ); MapWindowPoints( impl->base.win, 0, (POINT *)&rect, 2 );
if (!impl->clipped)
{
mapped_center.x = (rect.left + rect.right) / 2;
mapped_center.y = (rect.top + rect.bottom) / 2;
TRACE( "Warping mouse to x %+ld, y %+ld.\n", mapped_center.x, mapped_center.y );
SetCursorPos( mapped_center.x, mapped_center.y );
}
if (impl->base.dwCoopLevel & DISCL_EXCLUSIVE) if (impl->base.dwCoopLevel & DISCL_EXCLUSIVE)
{ {
/* make sure we clip even if the window covers the whole screen */ /* make sure we clip even if the window covers the whole screen */
@ -328,8 +321,14 @@ static void warp_check( struct mouse *impl, BOOL force )
rect.right = min( rect.right, rect.left + GetSystemMetrics( SM_CXVIRTUALSCREEN ) - 2 ); rect.right = min( rect.right, rect.left + GetSystemMetrics( SM_CXVIRTUALSCREEN ) - 2 );
rect.bottom = min( rect.bottom, rect.top + GetSystemMetrics( SM_CYVIRTUALSCREEN ) - 2 ); rect.bottom = min( rect.bottom, rect.top + GetSystemMetrics( SM_CYVIRTUALSCREEN ) - 2 );
TRACE("Clipping mouse to %s\n", wine_dbgstr_rect( &rect )); TRACE("Clipping mouse to %s\n", wine_dbgstr_rect( &rect ));
ClipCursor( &rect ); impl->clipped = ClipCursor( &rect );
impl->clipped = GetClipCursor( &new_rect ) && EqualRect( &rect, &new_rect ); }
if (!impl->clipped)
{
mapped_center.x = (rect.left + rect.right) / 2;
mapped_center.y = (rect.top + rect.bottom) / 2;
TRACE( "Warping mouse to x %+ld, y %+ld.\n", mapped_center.x, mapped_center.y );
SetCursorPos( mapped_center.x, mapped_center.y );
} }
} }
} }

View file

@ -1132,42 +1132,26 @@ static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface,
return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player ); return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
} }
static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group, HRESULT DP_AddPlayerToGroup( IDirectPlayImpl *This, DPID group, DPID player )
DPID player )
{ {
IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); DPMSG_ADDPLAYERTOGROUP addPlayerToGroupMsg;
lpGroupData gdata; lpGroupData gdata;
lpPlayerList plist; lpPlayerList plist;
lpPlayerList newplist; lpPlayerList newplist;
HRESULT hr;
TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, group, player );
if ( This->dp2->connectionInitialized == NO_PROVIDER )
return DPERR_UNINITIALIZED;
EnterCriticalSection( &This->lock );
/* Find the group */ /* Find the group */
if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
{
LeaveCriticalSection( &This->lock );
return DPERR_INVALIDGROUP; return DPERR_INVALIDGROUP;
}
/* Find the player */ /* Find the player */
if ( ( plist = DP_FindPlayer( This, player ) ) == NULL ) if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
{
LeaveCriticalSection( &This->lock );
return DPERR_INVALIDPLAYER; return DPERR_INVALIDPLAYER;
}
/* Create a player list (ie "shortcut" ) */ /* Create a player list (ie "shortcut" ) */
newplist = calloc( 1, sizeof( *newplist ) ); newplist = calloc( 1, sizeof( *newplist ) );
if ( !newplist ) if ( !newplist )
{
LeaveCriticalSection( &This->lock );
return DPERR_CANTADDPLAYER; return DPERR_CANTADDPLAYER;
}
/* Add the shortcut */ /* Add the shortcut */
plist->lpPData->uRef++; plist->lpPData->uRef++;
@ -1187,7 +1171,59 @@ static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DP
data.idGroup = group; data.idGroup = group;
data.lpISP = This->dp2->spData.lpISP; data.lpISP = This->dp2->spData.lpISP;
(*This->dp2->spData.lpCB->AddPlayerToGroup)( &data ); hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
if ( FAILED( hr ) )
{
DPQ_REMOVE( gdata->players, newplist, players );
--plist->lpPData->uRef;
free( newplist );
return hr;
}
}
addPlayerToGroupMsg.dwType = DPSYS_ADDPLAYERTOGROUP;
addPlayerToGroupMsg.dpIdGroup = group;
addPlayerToGroupMsg.dpIdPlayer = player;
hr = DP_QueueMessage( This, DPID_SYSMSG, DPID_ALLPLAYERS, 0, &addPlayerToGroupMsg,
DP_CopyGeneric, sizeof( DPMSG_ADDPLAYERTOGROUP ) );
if ( FAILED( hr ) )
{
if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
{
DPSP_REMOVEPLAYERFROMGROUPDATA data;
data.idPlayer = player;
data.idGroup = group;
data.lpISP = This->dp2->spData.lpISP;
This->dp2->spData.lpCB->RemovePlayerFromGroup( &data );
}
DPQ_REMOVE( gdata->players, newplist, players );
--plist->lpPData->uRef;
free( newplist );
return hr;
}
return DP_OK;
}
static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
DPID player )
{
IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
HRESULT hr;
TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, group, player );
if ( This->dp2->connectionInitialized == NO_PROVIDER )
return DPERR_UNINITIALIZED;
EnterCriticalSection( &This->lock );
hr = DP_AddPlayerToGroup( This, group, player );
if ( FAILED( hr ) )
{
LeaveCriticalSection( &This->lock );
return hr;
} }
/* Inform all other peers of the addition of player to the group. If there are /* Inform all other peers of the addition of player to the group. If there are
@ -1195,20 +1231,11 @@ static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DP
* Also, if this event was the result of another machine sending it to us, * Also, if this event was the result of another machine sending it to us,
* don't bother rebroadcasting it. * don't bother rebroadcasting it.
*/ */
if ( This->dp2->lpSessionDesc && hr = DP_MSG_SendAddPlayerToGroup( This, DPID_ALLPLAYERS, player, group );
( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) if( FAILED( hr ) )
{ {
DPMSG_ADDPLAYERTOGROUP msg; LeaveCriticalSection( &This->lock );
msg.dwType = DPSYS_ADDPLAYERTOGROUP; return hr;
msg.dpIdGroup = group;
msg.dpIdPlayer = player;
/* FIXME: Correct to just use send effectively? */
/* FIXME: Should size include data w/ message or just message "header" */
/* FIXME: Check return code */
IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
0, 0, NULL, NULL );
} }
LeaveCriticalSection( &This->lock ); LeaveCriticalSection( &This->lock );
@ -1281,17 +1308,28 @@ static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
return hr; return hr;
} }
static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName, HRESULT DP_CreateGroup( IDirectPlayImpl *This, void *msgHeader, const DPID *lpid,
DWORD dwFlags, DPID idParent, BOOL bAnsi ) const DPNAME *lpName, void *data, DWORD dataSize, DWORD dwFlags, DPID idParent,
BOOL bAnsi )
{ {
struct GroupList *groupList = NULL;
struct GroupData *parent = NULL;
lpGroupData lpGData; lpGroupData lpGData;
HRESULT hr;
if( DPID_SYSTEM_GROUP != *lpid )
{
parent = DP_FindAnyGroup( This, idParent );
if( !parent )
return DPERR_INVALIDGROUP;
}
/* Allocate the new space and add to end of high level group list */ /* Allocate the new space and add to end of high level group list */
lpGData = calloc( 1, sizeof( *lpGData ) ); lpGData = calloc( 1, sizeof( *lpGData ) );
if( lpGData == NULL ) if( lpGData == NULL )
{ {
return NULL; return DPERR_OUTOFMEMORY;
} }
DPQ_INIT(lpGData->groups); DPQ_INIT(lpGData->groups);
@ -1304,7 +1342,7 @@ static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, cons
if ( !lpGData->name ) if ( !lpGData->name )
{ {
free( lpGData ); free( lpGData );
return NULL; return DPERR_OUTOFMEMORY;
} }
lpGData->nameA = DP_DuplicateName( lpName, TRUE, bAnsi ); lpGData->nameA = DP_DuplicateName( lpName, TRUE, bAnsi );
@ -1312,11 +1350,10 @@ static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, cons
{ {
free( lpGData->name ); free( lpGData->name );
free( lpGData ); free( lpGData );
return NULL; return DPERR_OUTOFMEMORY;
} }
/* FIXME: Should we check that the parent exists? */ lpGData->parent = idParent;
lpGData->parent = idParent;
/* FIXME: Should we validate the dwFlags? */ /* FIXME: Should we validate the dwFlags? */
lpGData->dwFlags = dwFlags; lpGData->dwFlags = dwFlags;
@ -1328,12 +1365,83 @@ static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, cons
free( lpGData->nameA ); free( lpGData->nameA );
free( lpGData->name ); free( lpGData->name );
free( lpGData ); free( lpGData );
return NULL; return DPERR_OUTOFMEMORY;
}
if( DPID_SYSTEM_GROUP == *lpid )
{
This->dp2->lpSysGroup = lpGData;
TRACE( "Inserting system group\n" );
}
else
{
/* Insert into the parent group */
groupList = calloc( 1, sizeof( *groupList ) );
if( !groupList )
{
free( lpGData->nameA );
free( lpGData->name );
free( lpGData );
return DPERR_OUTOFMEMORY;
}
groupList->lpGData = lpGData;
DPQ_INSERT( parent->groups, groupList, groups );
}
/* Something is now referencing this data */
lpGData->uRef++;
DP_SetGroupData( lpGData, DPSET_REMOTE, data, dataSize );
/* FIXME: We should only create the system group if GetCaps returns
* DPCAPS_GROUPOPTIMIZED.
*/
/* Let the SP know that we've created this group */
if( This->dp2->spData.lpCB->CreateGroup )
{
DPSP_CREATEGROUPDATA data;
DWORD dwCreateFlags = 0;
TRACE( "Calling SP CreateGroup\n" );
if( !parent )
dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
if( !msgHeader )
dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
if( dwFlags & DPGROUP_HIDDEN )
dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
data.idGroup = *lpid;
data.dwFlags = dwCreateFlags;
data.lpSPMessageHeader = msgHeader;
data.lpISP = This->dp2->spData.lpISP;
hr = (*This->dp2->spData.lpCB->CreateGroup)( &data );
if( FAILED( hr ) )
{
if( groupList )
{
DPQ_REMOVE( parent->groups, groupList, groups );
free( groupList );
}
else
{
This->dp2->lpSysGroup = NULL;
}
free( lpGData->nameA );
free( lpGData->name );
free( lpGData );
return hr;
}
} }
TRACE( "Created group id 0x%08lx\n", *lpid ); TRACE( "Created group id 0x%08lx\n", *lpid );
return lpGData; return DP_OK;
} }
/* This method assumes that all links to it are already deleted */ /* This method assumes that all links to it are already deleted */
@ -1394,7 +1502,7 @@ static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid )
static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup, static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ) DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
{ {
lpGroupData lpGData; HRESULT hr;
TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n", TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize, This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
@ -1421,61 +1529,12 @@ static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *l
} }
} }
lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags, hr = DP_CreateGroup( This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
DPID_NOPARENT_GROUP, bAnsi ); DPID_NOPARENT_GROUP, bAnsi );
if( lpGData == NULL ) if( FAILED( hr ) )
{ {
return DPERR_CANTADDPLAYER; /* yes player not group */ return hr;
}
if( DPID_SYSTEM_GROUP == *lpidGroup )
{
This->dp2->lpSysGroup = lpGData;
TRACE( "Inserting system group\n" );
}
else
{
/* Insert into the system group */
lpGroupList lpGroup = calloc( 1, sizeof( *lpGroup ) );
lpGroup->lpGData = lpGData;
DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
}
/* Something is now referencing this data */
lpGData->uRef++;
/* Set all the important stuff for the group */
DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
/* FIXME: We should only create the system group if GetCaps returns
* DPCAPS_GROUPOPTIMIZED.
*/
/* Let the SP know that we've created this group */
if( This->dp2->spData.lpCB->CreateGroup )
{
DPSP_CREATEGROUPDATA data;
DWORD dwCreateFlags = 0;
TRACE( "Calling SP CreateGroup\n" );
if( *lpidGroup == DPID_NOPARENT_GROUP )
dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
if( lpMsgHdr == NULL )
dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
if( dwFlags & DPGROUP_HIDDEN )
dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
data.idGroup = *lpidGroup;
data.dwFlags = dwCreateFlags;
data.lpSPMessageHeader = lpMsgHdr;
data.lpISP = This->dp2->spData.lpISP;
(*This->dp2->spData.lpCB->CreateGroup)( &data );
} }
/* Inform all other peers of the creation of a new group. If there are /* Inform all other peers of the creation of a new group. If there are
@ -3046,12 +3105,11 @@ static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID g
src = gdata->lpRemoteData; src = gdata->lpRemoteData;
} }
*size = bufsize;
/* Is the user requesting to know how big a buffer is required? */ /* Is the user requesting to know how big a buffer is required? */
if ( !data || *size < bufsize ) if ( !data || *size < bufsize )
{
*size = bufsize;
return DPERR_BUFFERTOOSMALL; return DPERR_BUFFERTOOSMALL;
}
CopyMemory( data, src, bufsize ); CopyMemory( data, src, bufsize );
@ -4458,9 +4516,7 @@ static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr,
DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags,
BOOL bAnsi ) BOOL bAnsi )
{ {
lpGroupData lpGParentData; HRESULT hr;
lpGroupList lpGList;
lpGroupData lpGData;
TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n", TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
This, idParentGroup, lpidGroup, lpGroupName, lpData, This, idParentGroup, lpidGroup, lpGroupName, lpData,
@ -4471,48 +4527,12 @@ static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr,
return DPERR_UNINITIALIZED; return DPERR_UNINITIALIZED;
} }
/* Verify that the specified parent is valid */ hr = DP_CreateGroup(This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
if( ( lpGParentData = DP_FindAnyGroup(This, idParentGroup ) ) == NULL ) idParentGroup, bAnsi );
return DPERR_INVALIDGROUP;
lpGData = DP_CreateGroup(This, lpidGroup, lpGroupName, dwFlags, idParentGroup, bAnsi ); if( FAILED( hr ) )
if( lpGData == NULL )
{ {
return DPERR_CANTADDPLAYER; /* yes player not group */ return hr;
}
/* Something else is referencing this data */
lpGData->uRef++;
DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
/* The list has now been inserted into the interface group list. We now
need to put a "shortcut" to this group in the parent group */
lpGList = calloc( 1, sizeof( *lpGList ) );
if( lpGList == NULL )
{
FIXME( "Memory leak\n" );
return DPERR_CANTADDPLAYER; /* yes player not group */
}
lpGList->lpGData = lpGData;
DPQ_INSERT( lpGParentData->groups, lpGList, groups );
/* Let the SP know that we've created this group */
if( This->dp2->spData.lpCB->CreateGroup )
{
DPSP_CREATEGROUPDATA data;
TRACE( "Calling SP CreateGroup\n" );
data.idGroup = *lpidGroup;
data.dwFlags = dwFlags;
data.lpSPMessageHeader = lpMsgHdr;
data.lpISP = This->dp2->spData.lpISP;
(*This->dp2->spData.lpCB->CreateGroup)( &data );
} }
/* Inform all other peers of the creation of a new group. If there are /* Inform all other peers of the creation of a new group. If there are
@ -4959,19 +4979,22 @@ static HRESULT DP_IF_EnumGroupsInGroup( IDirectPlayImpl *This, DPID group, GUID
if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL ) if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
return DPERR_INVALIDGROUP; return DPERR_INVALIDGROUP;
if ( DPQ_IS_EMPTY( gdata->groups ) ) for( glist = DPQ_FIRST( gdata->groups ); glist; glist = DPQ_NEXT( glist->groups ) )
return DP_OK;
for( glist = DPQ_FIRST( gdata->groups ); ; glist = DPQ_NEXT( glist->groups ) )
{ {
/* FIXME: Should check flags for match here */ DWORD groupFlags;
if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP,
ansi ? glist->lpGData->nameA : glist->lpGData->name, flags, context ) )
return DP_OK; /* User requested break */
if ( DPQ_IS_ENDOFLIST( glist->groups ) ) if ( (glist->lpGData->dwFlags & flags) != (flags & ~DPENUMGROUPS_REMOTE) )
break; continue;
if ( (glist->lpGData->dwFlags & DPENUMGROUPS_LOCAL) && (flags & DPENUMGROUPS_REMOTE) )
continue;
groupFlags = glist->lpGData->dwFlags;
groupFlags &= ~(DPENUMGROUPS_LOCAL | DPLAYI_GROUP_DPLAYOWNS);
groupFlags |= flags;
if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP,
ansi ? glist->lpGData->nameA : glist->lpGData->name, groupFlags, context ) )
return DP_OK; /* User requested break */
} }
return DP_OK; return DP_OK;

View file

@ -218,6 +218,10 @@ HRESULT DP_HandleGameMessage( IDirectPlayImpl *This, void *messageBody, DWORD me
HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName,
void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags, void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags,
HANDLE hEvent, struct PlayerData **playerData, BOOL bAnsi ); HANDLE hEvent, struct PlayerData **playerData, BOOL bAnsi );
HRESULT DP_CreateGroup( IDirectPlayImpl *This, void *msgHeader, const DPID *lpid,
const DPNAME *lpName, void *data, DWORD dataSize, DWORD dwFlags,
DPID idParent, BOOL bAnsi );
HRESULT DP_AddPlayerToGroup( IDirectPlayImpl *This, DPID group, DPID player );
/* DP SP external interfaces into DirectPlay */ /* DP SP external interfaces into DirectPlay */
extern HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData ); extern HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData );

View file

@ -676,6 +676,42 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer, WC
return hr; return hr;
} }
} }
for( i = 0; i < enumPlayersReply->groupCount; ++i )
{
DPPLAYERINFO playerInfo;
int j;
hr = DP_MSG_ReadSuperPackedPlayer( (char *) enumPlayersReply, &offset, dwMsgSize,
&playerInfo );
if( FAILED( hr ) )
{
free( msgHeader );
free( lpMsg );
return hr;
}
hr = DP_CreateGroup( This, msgHeader, &playerInfo.id, &playerInfo.name,
playerInfo.playerData, playerInfo.playerDataLength,
playerInfo.flags & ~DPLAYI_PLAYER_PLAYERLOCAL, playerInfo.parentId,
FALSE );
if( FAILED( hr ) )
{
free( msgHeader );
free( lpMsg );
return hr;
}
for( j = 0; j < playerInfo.playerCount; ++j )
{
hr = DP_AddPlayerToGroup( This, playerInfo.id, playerInfo.playerIds[ j ] );
if( FAILED( hr ) )
{
free( msgHeader );
free( lpMsg );
return hr;
}
}
}
} }
else if( envelope->wCommandId == DPMSGCMD_GETNAMETABLEREPLY ) else if( envelope->wCommandId == DPMSGCMD_GETNAMETABLEREPLY )
{ {
@ -795,6 +831,49 @@ HRESULT DP_MSG_SendCreatePlayer( IDirectPlayImpl *This, DPID toId, DPID id, DWOR
return DP_OK; return DP_OK;
} }
HRESULT DP_MSG_SendAddPlayerToGroup( IDirectPlayImpl *This, DPID toId, DPID playerId, DPID groupId )
{
DPSP_SENDTOGROUPEXDATA sendData;
DPSP_MSG_ADDPLAYERTOGROUP msg;
SGBUFFER buffers[ 2 ] = { 0 };
HRESULT hr;
msg.envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
msg.envelope.wCommandId = DPMSGCMD_ADDPLAYERTOGROUP;
msg.envelope.wVersion = DPMSGVER_DP6;
msg.toId = 0;
msg.playerId = playerId;
msg.groupId = groupId;
msg.createOffset = 0;
msg.passwordOffset = 0;
buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize;
buffers[ 0 ].pData = NULL;
buffers[ 1 ].len = sizeof( msg );
buffers[ 1 ].pData = (UCHAR *)&msg;
sendData.lpISP = This->dp2->spData.lpISP;
sendData.dwFlags = DPSEND_GUARANTEED;
sendData.idGroupTo = toId;
sendData.idPlayerFrom = This->dp2->systemPlayerId;
sendData.lpSendBuffers = buffers;
sendData.cBuffers = ARRAYSIZE( buffers );
sendData.dwMessageSize = DP_MSG_ComputeMessageSize( sendData.lpSendBuffers, sendData.cBuffers );
sendData.dwPriority = 0;
sendData.dwTimeout = 0;
sendData.lpDPContext = NULL;
sendData.lpdwSPMsgID = NULL;
hr = (*This->dp2->spData.lpCB->SendToGroupEx)( &sendData );
if( FAILED( hr ) )
{
ERR( "SendToGroupEx failed: %s\n", DPLAYX_HresultToString( hr ) );
return hr;
}
return DP_OK;
}
HRESULT DP_MSG_SendPingReply( IDirectPlayImpl *This, DPID toId, DPID fromId, DWORD tickCount ) HRESULT DP_MSG_SendPingReply( IDirectPlayImpl *This, DPID toId, DPID fromId, DWORD tickCount )
{ {
SGBUFFER buffers[ 2 ] = { 0 }; SGBUFFER buffers[ 2 ] = { 0 };

View file

@ -57,6 +57,8 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer, WC
HRESULT DP_MSG_SendCreatePlayer( IDirectPlayImpl *This, DPID toId, DPID id, DWORD flags, HRESULT DP_MSG_SendCreatePlayer( IDirectPlayImpl *This, DPID toId, DPID id, DWORD flags,
DPNAME *name, void *playerData, DWORD playerDataSize, DPNAME *name, void *playerData, DWORD playerDataSize,
DPID systemPlayerId ); DPID systemPlayerId );
HRESULT DP_MSG_SendAddPlayerToGroup( IDirectPlayImpl *This, DPID toId, DPID playerId,
DPID groupId );
HRESULT DP_MSG_SendPingReply( IDirectPlayImpl *This, DPID toId, DPID fromId, DWORD tickCount ); HRESULT DP_MSG_SendPingReply( IDirectPlayImpl *This, DPID toId, DPID fromId, DWORD tickCount );
HRESULT DP_MSG_SendAddForwardAck( IDirectPlayImpl *This, DPID id ); HRESULT DP_MSG_SendAddForwardAck( IDirectPlayImpl *This, DPID id );
@ -103,6 +105,7 @@ typedef struct
#define DPMSGCMD_SYSTEMMESSAGE 10 #define DPMSGCMD_SYSTEMMESSAGE 10
#define DPMSGCMD_DELETEPLAYER 11 #define DPMSGCMD_DELETEPLAYER 11
#define DPMSGCMD_DELETEGROUP 12 #define DPMSGCMD_DELETEGROUP 12
#define DPMSGCMD_ADDPLAYERTOGROUP 13
#define DPMSGCMD_ENUMGROUPS 17 #define DPMSGCMD_ENUMGROUPS 17
@ -231,6 +234,16 @@ typedef struct tagDPMSG_NEWPLAYERIDREPLY
} DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY; } DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY;
typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY; typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY;
typedef struct
{
DPMSG_SENDENVELOPE envelope;
DPID toId;
DPID playerId;
DPID groupId;
DWORD createOffset;
DWORD passwordOffset;
} DPSP_MSG_ADDPLAYERTOGROUP;
typedef struct tagDPMSG_FORWARDADDPLAYER typedef struct tagDPMSG_FORWARDADDPLAYER
{ {
DPMSG_SENDENVELOPE envelope; DPMSG_SENDENVELOPE envelope;

View file

@ -978,6 +978,16 @@ typedef struct
DWORD tickCount; DWORD tickCount;
} Ping; } Ping;
typedef struct
{
MessageHeader header;
DPID toId;
DPID playerId;
DPID groupId;
DWORD createOffset;
DWORD passwordOffset;
} AddPlayerToGroup;
#include "poppack.h" #include "poppack.h"
#define bindUdp( port ) bindUdp_( __LINE__, port ) #define bindUdp( port ) bindUdp_( __LINE__, port )
@ -1224,12 +1234,14 @@ static void checkGameMessage_( int line, GameMessage *message, DPID expectedFrom
static unsigned short receiveEnumSessionsRequest_( int line, SOCKET sock, const GUID *expectedAppGuid, static unsigned short receiveEnumSessionsRequest_( int line, SOCKET sock, const GUID *expectedAppGuid,
const WCHAR *expectedPassword, DWORD expectedFlags ) const WCHAR *expectedPassword, DWORD expectedFlags )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
EnumSessionsRequest request; EnumSessionsRequest request;
WCHAR password[ 256 ]; WCHAR password[ 256 ];
} request; } request;
#include "poppack.h"
DWORD expectedPasswordSize; DWORD expectedPasswordSize;
unsigned short port; unsigned short port;
DWORD expectedSize; DWORD expectedSize;
@ -1267,6 +1279,7 @@ static unsigned short receiveEnumSessionsRequest_( int line, SOCKET sock, const
#define sendEnumSessionsReply( sock, port, dpsd ) sendEnumSessionsReply_( __LINE__, sock, port, dpsd ) #define sendEnumSessionsReply( sock, port, dpsd ) sendEnumSessionsReply_( __LINE__, sock, port, dpsd )
static void sendEnumSessionsReply_( int line, SOCKET sock, unsigned short port, const DPSESSIONDESC2 *dpsd ) static void sendEnumSessionsReply_( int line, SOCKET sock, unsigned short port, const DPSESSIONDESC2 *dpsd )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
@ -1295,6 +1308,7 @@ static void sendEnumSessionsReply_( int line, SOCKET sock, unsigned short port,
.nameOffset = sizeof( reply.reply ), .nameOffset = sizeof( reply.reply ),
}, },
}; };
#include "poppack.h"
DWORD passwordSize; DWORD passwordSize;
int wsResult; int wsResult;
DWORD size; DWORD size;
@ -1314,11 +1328,13 @@ static void sendEnumSessionsReply_( int line, SOCKET sock, unsigned short port,
#define receiveRequestPlayerId( sock, expectedFlags, flagsTodo ) receiveRequestPlayerId_( __LINE__, sock, expectedFlags, flagsTodo ) #define receiveRequestPlayerId( sock, expectedFlags, flagsTodo ) receiveRequestPlayerId_( __LINE__, sock, expectedFlags, flagsTodo )
static unsigned short receiveRequestPlayerId_( int line, SOCKET sock, DWORD expectedFlags ) static unsigned short receiveRequestPlayerId_( int line, SOCKET sock, DWORD expectedFlags )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
RequestPlayerId request; RequestPlayerId request;
} request; } request;
#include "poppack.h"
unsigned short port; unsigned short port;
int wsResult; int wsResult;
@ -1335,6 +1351,7 @@ static unsigned short receiveRequestPlayerId_( int line, SOCKET sock, DWORD expe
#define sendRequestPlayerReply( sock, port, id, result ) sendRequestPlayerReply_( __LINE__, sock, port, id, result ) #define sendRequestPlayerReply( sock, port, id, result ) sendRequestPlayerReply_( __LINE__, sock, port, id, result )
static void sendRequestPlayerReply_( int line, SOCKET sock, unsigned short port, DPID id, HRESULT result ) static void sendRequestPlayerReply_( int line, SOCKET sock, unsigned short port, DPID id, HRESULT result )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
@ -1362,6 +1379,7 @@ static void sendRequestPlayerReply_( int line, SOCKET sock, unsigned short port,
.result = result, .result = result,
}, },
}; };
#include "poppack.h"
int wsResult; int wsResult;
wsResult = send( sock, (char *) &reply, sizeof( reply ), 0 ); wsResult = send( sock, (char *) &reply, sizeof( reply ), 0 );
@ -1374,11 +1392,13 @@ static unsigned short receiveAddForwardRequest_( int line, SOCKET sock, DPID exp
const WCHAR *expectedPassword, DWORD expectedTickCount, const WCHAR *expectedPassword, DWORD expectedTickCount,
unsigned short *udpPort ) unsigned short *udpPort )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
AddForwardRequest request; AddForwardRequest request;
} request; } request;
#include "poppack.h"
DWORD expectedPasswordSize; DWORD expectedPasswordSize;
WCHAR password[ 256 ]; WCHAR password[ 256 ];
unsigned short port; unsigned short port;
@ -1427,25 +1447,53 @@ static void sendSuperEnumPlayersReply_( int line, SOCKET sock, unsigned short tc
{ {
#define SHORT_NAME L"short name" #define SHORT_NAME L"short name"
#define LONG_NAME L"long name" #define LONG_NAME L"long name"
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
SuperEnumPlayersReply reply; SuperEnumPlayersReply reply;
DPSESSIONDESC2 dpsd; DPSESSIONDESC2 dpsd;
WCHAR sessionName[ 256 ]; WCHAR sessionName[ 256 ];
SuperPackedPlayer superPackedPlayer0; struct
BYTE spDataLength0; {
SpData spData0; SuperPackedPlayer superPackedPlayer;
SuperPackedPlayer superPackedPlayer1; BYTE spDataLength;
BYTE spDataLength1; SpData spData;
SpData spData1; } player0;
SuperPackedPlayer superPackedPlayer2; struct
WCHAR shortName[ ARRAYSIZE( SHORT_NAME ) ]; {
WCHAR longName[ ARRAYSIZE( LONG_NAME ) ]; SuperPackedPlayer superPackedPlayer;
BYTE playerDataLength2; BYTE spDataLength;
BYTE playerData[ 4 ]; SpData spData;
BYTE spDataLength2; } player1;
SpData spData2; struct
{
SuperPackedPlayer superPackedPlayer;
WCHAR shortName[ ARRAYSIZE( SHORT_NAME ) ];
WCHAR longName[ ARRAYSIZE( LONG_NAME ) ];
BYTE playerDataLength;
BYTE playerData[ 4 ];
BYTE spDataLength;
SpData spData;
} player2;
struct
{
SuperPackedPlayer superPackedPlayer;
BYTE spDataLength;
SpData spData;
} player3;
struct
{
SuperPackedPlayer superPackedPlayer;
WCHAR shortName[ ARRAYSIZE( SHORT_NAME ) ];
WCHAR longName[ ARRAYSIZE( LONG_NAME ) ];
BYTE playerDataLength;
BYTE playerData[ 4 ];
BYTE spDataLength;
SpData spData;
BYTE playerCount;
DPID playerIds[ 1 ];
} group0;
} reply = } reply =
{ {
.spHeader = .spHeader =
@ -1465,8 +1513,8 @@ static void sendSuperEnumPlayersReply_( int line, SOCKET sock, unsigned short tc
.command = 41, .command = 41,
.version = 14, .version = 14,
}, },
.playerCount = 3, .playerCount = 4,
.groupCount = 0, .groupCount = 1,
.packedOffset = sizeof( reply.reply ) + sizeof( reply.dpsd ) + sizeof( reply.sessionName ), .packedOffset = sizeof( reply.reply ) + sizeof( reply.dpsd ) + sizeof( reply.sessionName ),
.shortcutCount = 0, .shortcutCount = 0,
.descriptionOffset = sizeof( reply.reply ), .descriptionOffset = sizeof( reply.reply ),
@ -1474,77 +1522,143 @@ static void sendSuperEnumPlayersReply_( int line, SOCKET sock, unsigned short tc
.passwordOffset = 0, .passwordOffset = 0,
}, },
.dpsd = *dpsd, .dpsd = *dpsd,
.superPackedPlayer0 = .player0 =
{ {
.size = 16, .superPackedPlayer =
.flags = 0x5,
.id = 0x12345678,
.infoMask = 0x4,
.versionOrSystemPlayerId = 14,
},
.spDataLength0 = sizeof( SpData ),
.spData0 =
{
.tcpAddr =
{ {
.sin_family = AF_INET, .size = 16,
.sin_port = htons( tcpPort ), .flags = 0x5,
.id = 0x12345678,
.infoMask = 0x4,
.versionOrSystemPlayerId = 14,
}, },
.udpAddr = .spDataLength = sizeof( SpData ),
.spData =
{ {
.sin_family = AF_INET, .tcpAddr =
.sin_port = htons( udpPort ), {
.sin_family = AF_INET,
.sin_port = htons( tcpPort ),
},
.udpAddr =
{
.sin_family = AF_INET,
.sin_port = htons( udpPort ),
},
}, },
}, },
.superPackedPlayer1 = .player1 =
{ {
.size = 16, .superPackedPlayer =
.flags = 0xf,
.id = 0x51573,
.infoMask = 0x4,
.versionOrSystemPlayerId = 14,
},
.spDataLength1 = sizeof( SpData ),
.spData1 =
{
.tcpAddr =
{ {
.sin_family = AF_INET, .size = 16,
.sin_port = htons( tcpPort ), .flags = 0xf,
.id = 0x51573,
.infoMask = 0x4,
.versionOrSystemPlayerId = 14,
}, },
.udpAddr = .spDataLength = sizeof( SpData ),
.spData =
{ {
.sin_family = AF_INET, .tcpAddr =
.sin_port = htons( udpPort ), {
.sin_family = AF_INET,
.sin_port = htons( tcpPort ),
},
.udpAddr =
{
.sin_family = AF_INET,
.sin_port = htons( udpPort ),
},
}, },
}, },
.superPackedPlayer2 = .player2 =
{ {
.size = 16, .superPackedPlayer =
.flags = 0x8, {
.id = 0x1337, .size = 16,
.infoMask = 0x17, .flags = 0x8,
.versionOrSystemPlayerId = 0x51573, .id = 0x1337,
.infoMask = 0x17,
.versionOrSystemPlayerId = 0x51573,
},
.shortName = SHORT_NAME,
.longName = LONG_NAME,
.playerDataLength = 4,
.playerData = { 1, 2, 3, 4, },
.spDataLength = sizeof( SpData ),
.spData =
{
.tcpAddr =
{
.sin_family = AF_INET,
.sin_port = htons( tcpPort ),
},
.udpAddr =
{
.sin_family = AF_INET,
.sin_port = htons( udpPort ),
},
},
}, },
.shortName = SHORT_NAME, .player3 =
.longName = LONG_NAME,
.playerDataLength2 = 4,
.playerData = { 1, 2, 3, 4, },
.spDataLength2 = sizeof( SpData ),
.spData2 =
{ {
.tcpAddr = .superPackedPlayer =
{ {
.sin_family = AF_INET, .size = 16,
.sin_port = htons( tcpPort ), .flags = 0x8,
.id = 0xd00de,
.infoMask = 0x4,
.versionOrSystemPlayerId = 0x51573,
}, },
.udpAddr = .spDataLength = sizeof( SpData ),
.spData =
{ {
.sin_family = AF_INET, .tcpAddr =
.sin_port = htons( udpPort ), {
.sin_family = AF_INET,
.sin_port = htons( tcpPort ),
},
.udpAddr =
{
.sin_family = AF_INET,
.sin_port = htons( udpPort ),
},
}, },
}, },
.group0 =
{
.superPackedPlayer =
{
.size = 16,
.flags = 0x48,
.id = 0x5e7,
.infoMask = 0x57,
.versionOrSystemPlayerId = 0x51573,
},
.shortName = SHORT_NAME,
.longName = LONG_NAME,
.playerDataLength = 4,
.playerData = { 1, 2, 3, 4, },
.spDataLength = sizeof( SpData ),
.spData =
{
.tcpAddr =
{
.sin_family = AF_INET,
.sin_port = htons( tcpPort ),
},
.udpAddr =
{
.sin_family = AF_INET,
.sin_port = htons( udpPort ),
},
},
.playerCount = 1,
.playerIds = { 0xd00de, },
},
}; };
#include "poppack.h"
#undef LONG_NAME #undef LONG_NAME
#undef SHORT_NAME #undef SHORT_NAME
int wsResult; int wsResult;
@ -1561,6 +1675,7 @@ static void sendSuperEnumPlayersReply_( int line, SOCKET sock, unsigned short tc
#define sendAddForwardReply( sock, port, result ) sendAddForwardReply_( __LINE__, sock, port, result ) #define sendAddForwardReply( sock, port, result ) sendAddForwardReply_( __LINE__, sock, port, result )
static void sendAddForwardReply_( int line, SOCKET sock, unsigned short port, HRESULT result ) static void sendAddForwardReply_( int line, SOCKET sock, unsigned short port, HRESULT result )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
@ -1587,6 +1702,7 @@ static void sendAddForwardReply_( int line, SOCKET sock, unsigned short port, HR
.result = result, .result = result,
}, },
}; };
#include "poppack.h"
int wsResult; int wsResult;
wsResult = send( sock, (char *) &reply, sizeof( reply ), 0 ); wsResult = send( sock, (char *) &reply, sizeof( reply ), 0 );
@ -1596,6 +1712,7 @@ static void sendAddForwardReply_( int line, SOCKET sock, unsigned short port, HR
#define sendAddForward( sock, port, tcpPort, udpPort ) sendAddForward_( __LINE__, sock, port, tcpPort, udpPort ) #define sendAddForward( sock, port, tcpPort, udpPort ) sendAddForward_( __LINE__, sock, port, tcpPort, udpPort )
static void sendAddForward_( int line, SOCKET sock, unsigned short port, unsigned short tcpPort, unsigned short udpPort ) static void sendAddForward_( int line, SOCKET sock, unsigned short port, unsigned short tcpPort, unsigned short udpPort )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
@ -1653,6 +1770,7 @@ static void sendAddForward_( int line, SOCKET sock, unsigned short port, unsigne
}, },
}, },
}; };
#include "poppack.h"
int wsResult; int wsResult;
@ -1663,11 +1781,13 @@ static void sendAddForward_( int line, SOCKET sock, unsigned short port, unsigne
#define receiveAddForwardAck( sock, expectedPlayerId ) receiveAddForwardAck_( __LINE__, sock, expectedPlayerId ) #define receiveAddForwardAck( sock, expectedPlayerId ) receiveAddForwardAck_( __LINE__, sock, expectedPlayerId )
static unsigned short receiveAddForwardAck_( int line, SOCKET sock, DPID expectedPlayerId ) static unsigned short receiveAddForwardAck_( int line, SOCKET sock, DPID expectedPlayerId )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
AddForwardAck request; AddForwardAck request;
} request; } request;
#include "poppack.h"
unsigned short port; unsigned short port;
int wsResult; int wsResult;
@ -1688,11 +1808,13 @@ static unsigned short receiveCreatePlayer_( int line, SOCKET sock, DPID expected
const WCHAR *expectedShortName, const WCHAR *expectedLongName, const WCHAR *expectedShortName, const WCHAR *expectedLongName,
void *expectedPlayerData, DWORD expectedPlayerDataSize ) void *expectedPlayerData, DWORD expectedPlayerDataSize )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
CreatePlayer request; CreatePlayer request;
} request; } request;
#include "poppack.h"
DWORD expectedShortNameSize; DWORD expectedShortNameSize;
DWORD expectedLongNameSize; DWORD expectedLongNameSize;
WCHAR shortName[ 256 ]; WCHAR shortName[ 256 ];
@ -1775,6 +1897,7 @@ static unsigned short receiveCreatePlayer_( int line, SOCKET sock, DPID expected
static void sendCreatePlayer_( int line, SOCKET sock, unsigned short tcpPort, unsigned short udpPort, static void sendCreatePlayer_( int line, SOCKET sock, unsigned short tcpPort, unsigned short udpPort,
const WCHAR *shortName, const WCHAR *longName, void *playerData, DWORD playerDataSize ) const WCHAR *shortName, const WCHAR *longName, void *playerData, DWORD playerDataSize )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
@ -1820,6 +1943,7 @@ static void sendCreatePlayer_( int line, SOCKET sock, unsigned short tcpPort, un
}, },
}, },
}; };
#include "poppack.h"
SpData spData = { SpData spData = {
.tcpAddr.sin_family = AF_INET, .tcpAddr.sin_family = AF_INET,
.tcpAddr.sin_port = htons( tcpPort ), .tcpAddr.sin_port = htons( tcpPort ),
@ -1877,12 +2001,14 @@ static void sendCreatePlayer_( int line, SOCKET sock, unsigned short tcpPort, un
static unsigned short receiveGuaranteedGameMessage_( int line, SOCKET sock, DPID expectedFromId, DPID expectedToId, static unsigned short receiveGuaranteedGameMessage_( int line, SOCKET sock, DPID expectedFromId, DPID expectedToId,
void *expectedData, DWORD expectedDataSize ) void *expectedData, DWORD expectedDataSize )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
GameMessage request; GameMessage request;
BYTE data[ 256 ]; BYTE data[ 256 ];
} request; } request;
#include "poppack.h"
unsigned short port; unsigned short port;
int wsResult; int wsResult;
@ -1903,11 +2029,13 @@ static unsigned short receiveGuaranteedGameMessage_( int line, SOCKET sock, DPID
static void receiveGameMessage_( int line, SOCKET sock, DPID expectedFromId, DPID expectedToId, void *expectedData, static void receiveGameMessage_( int line, SOCKET sock, DPID expectedFromId, DPID expectedToId, void *expectedData,
DWORD expectedDataSize ) DWORD expectedDataSize )
{ {
#include "pshpack1.h"
struct struct
{ {
GameMessage request; GameMessage request;
BYTE data[ 256 ]; BYTE data[ 256 ];
} request; } request;
#include "poppack.h"
int wsResult; int wsResult;
DWORD expectedSize = sizeof( request.request ) + expectedDataSize; DWORD expectedSize = sizeof( request.request ) + expectedDataSize;
@ -1924,6 +2052,7 @@ static void receiveGameMessage_( int line, SOCKET sock, DPID expectedFromId, DPI
static void sendGuaranteedGameMessage_( int line, SOCKET sock, unsigned short port, DPID fromId, DPID toId, void *data, static void sendGuaranteedGameMessage_( int line, SOCKET sock, unsigned short port, DPID fromId, DPID toId, void *data,
DWORD dataSize ) DWORD dataSize )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
@ -1945,6 +2074,7 @@ static void sendGuaranteedGameMessage_( int line, SOCKET sock, unsigned short po
.toId = toId, .toId = toId,
} }
}; };
#include "poppack.h"
int wsResult; int wsResult;
wsResult = send( sock, (char *) &request, sizeof( request ), 0 ); wsResult = send( sock, (char *) &request, sizeof( request ), 0 );
@ -1958,6 +2088,7 @@ static void sendGuaranteedGameMessage_( int line, SOCKET sock, unsigned short po
sendGameMessage_( __LINE__, sock, fromId, toId, data, dataSize ) sendGameMessage_( __LINE__, sock, fromId, toId, data, dataSize )
static void sendGameMessage_( int line, SOCKET sock, DPID fromId, DPID toId, void *data, DWORD dataSize ) static void sendGameMessage_( int line, SOCKET sock, DPID fromId, DPID toId, void *data, DWORD dataSize )
{ {
#include "pshpack1.h"
struct struct
{ {
GameMessage request; GameMessage request;
@ -1970,6 +2101,7 @@ static void sendGameMessage_( int line, SOCKET sock, DPID fromId, DPID toId, voi
.toId = toId, .toId = toId,
} }
}; };
#include "poppack.h"
int wsResult; int wsResult;
DWORD size; DWORD size;
@ -1985,6 +2117,7 @@ static void sendGameMessage_( int line, SOCKET sock, DPID fromId, DPID toId, voi
sendPing_( __LINE__, sock, port, fromId, tickCount ) sendPing_( __LINE__, sock, port, fromId, tickCount )
static void sendPing_( int line, SOCKET sock, unsigned short port, DPID fromId, DWORD tickCount ) static void sendPing_( int line, SOCKET sock, unsigned short port, DPID fromId, DWORD tickCount )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
@ -2012,6 +2145,7 @@ static void sendPing_( int line, SOCKET sock, unsigned short port, DPID fromId,
.tickCount = tickCount, .tickCount = tickCount,
} }
}; };
#include "poppack.h"
int wsResult; int wsResult;
wsResult = send( sock, (char *) &request, sizeof( request ), 0 ); wsResult = send( sock, (char *) &request, sizeof( request ), 0 );
@ -2022,11 +2156,13 @@ static void sendPing_( int line, SOCKET sock, unsigned short port, DPID fromId,
receivePingReply_( __LINE__, sock, expectedFromId, expectedTickCount ) receivePingReply_( __LINE__, sock, expectedFromId, expectedTickCount )
static unsigned short receivePingReply_( int line, SOCKET sock, DPID expectedFromId, DWORD expectedTickCount ) static unsigned short receivePingReply_( int line, SOCKET sock, DPID expectedFromId, DWORD expectedTickCount )
{ {
#include "pshpack1.h"
struct struct
{ {
SpHeader spHeader; SpHeader spHeader;
Ping request; Ping request;
} request; } request;
#include "poppack.h"
unsigned short port; unsigned short port;
int wsResult; int wsResult;
@ -2042,6 +2178,37 @@ static unsigned short receivePingReply_( int line, SOCKET sock, DPID expectedFro
return port; return port;
} }
#define receiveAddPlayerToGroup( sock, expectedPlayerId, expectedGroupId ) \
receiveAddPlayerToGroup_( __LINE__, sock, expectedPlayerId, expectedGroupId )
static unsigned short receiveAddPlayerToGroup_( int line, SOCKET sock, DPID expectedPlayerId, DPID expectedGroupId )
{
#include "pshpack1.h"
struct
{
SpHeader spHeader;
AddPlayerToGroup request;
} request;
#include "poppack.h"
unsigned short port;
int wsResult;
wsResult = receiveMessage_( line, sock, &request, sizeof( request ) );
ok_( __FILE__, line )( wsResult == sizeof( request ), "recv() returned %d.\n", wsResult );
port = checkSpHeader_( line, &request.spHeader, sizeof( request ) );
checkMessageHeader_( line, &request.request.header, 13 );
ok_( __FILE__, line )( !request.request.toId, "got destination id %#lx.\n", request.request.toId );
ok_( __FILE__, line )( request.request.playerId == expectedPlayerId, "got player id %#lx.\n",
request.request.playerId );
ok_( __FILE__, line )( request.request.groupId == expectedGroupId, "got group id %#lx.\n",
request.request.groupId );
ok_( __FILE__, line )( !request.request.createOffset, "got create offset %lu.\n", request.request.createOffset );
ok_( __FILE__, line )( !request.request.passwordOffset, "got password offset %lu.\n", request.request.passwordOffset );
return port;
}
static void init_TCPIP_provider( IDirectPlay4 *pDP, LPCSTR strIPAddressString, WORD port ) static void init_TCPIP_provider( IDirectPlay4 *pDP, LPCSTR strIPAddressString, WORD port )
{ {
@ -2731,7 +2898,10 @@ static BOOL CALLBACK checkPlayerListCallback( DPID dpid, DWORD playerType, const
memset( &playerData, 0xcc, sizeof( playerData ) ); memset( &playerData, 0xcc, sizeof( playerData ) );
playerDataSize = sizeof( playerData ); playerDataSize = sizeof( playerData );
hr = IDirectPlayX_GetPlayerData( data->dp, dpid, playerData, &playerDataSize, DPGET_REMOTE ); if ( playerType == DPPLAYERTYPE_PLAYER )
hr = IDirectPlayX_GetPlayerData( data->dp, dpid, playerData, &playerDataSize, DPGET_REMOTE );
else
hr = IDirectPlayX_GetGroupData( data->dp, dpid, playerData, &playerDataSize, DPGET_REMOTE );
ok_( __FILE__, data->line )( hr == DP_OK, "GetPlayerData() returned %#lx.\n", hr ); ok_( __FILE__, data->line )( hr == DP_OK, "GetPlayerData() returned %#lx.\n", hr );
ok_( __FILE__, data->line )( playerDataSize == player->expectedPlayerDataSize, ok_( __FILE__, data->line )( playerDataSize == player->expectedPlayerDataSize,
"got player data size %lu.\n", playerDataSize ); "got player data size %lu.\n", playerDataSize );
@ -2740,7 +2910,10 @@ static BOOL CALLBACK checkPlayerListCallback( DPID dpid, DWORD playerType, const
memset( &nameData, 0xcc, sizeof( nameData ) ); memset( &nameData, 0xcc, sizeof( nameData ) );
nameDataSize = sizeof( nameData ); nameDataSize = sizeof( nameData );
hr = IDirectPlayX_GetPlayerName( data->dp, dpid, &nameData, &nameDataSize ); if ( playerType == DPPLAYERTYPE_PLAYER )
hr = IDirectPlayX_GetPlayerName( data->dp, dpid, &nameData, &nameDataSize );
else
hr = IDirectPlayX_GetGroupName( data->dp, dpid, &nameData, &nameDataSize );
ok_( __FILE__, data->line )( hr == DP_OK, "GetPlayerName() returned %#lx.\n", hr ); ok_( __FILE__, data->line )( hr == DP_OK, "GetPlayerName() returned %#lx.\n", hr );
ok_( __FILE__, data->line )( ((DPNAME *) nameData)->dwSize == sizeof( DPNAME ), ok_( __FILE__, data->line )( ((DPNAME *) nameData)->dwSize == sizeof( DPNAME ),
"got name size %lu.\n", ((DPNAME *) nameData)->dwSize ); "got name size %lu.\n", ((DPNAME *) nameData)->dwSize );
@ -2796,7 +2969,8 @@ static BOOL CALLBACK checkPlayerListCallback( DPID dpid, DWORD playerType, const
return TRUE; return TRUE;
} }
#define checkPlayerList( dp, expectedPlayers, expectedPlayerCount ) checkPlayerList_( __LINE__, dp, expectedPlayers, expectedPlayerCount ) #define checkPlayerList( dp, expectedPlayers, expectedPlayerCount ) \
checkPlayerList_( __LINE__, dp, expectedPlayers, expectedPlayerCount )
static void checkPlayerList_( int line, IDirectPlay4 *dp, ExpectedPlayer *expectedPlayers, int expectedPlayerCount ) static void checkPlayerList_( int line, IDirectPlay4 *dp, ExpectedPlayer *expectedPlayers, int expectedPlayerCount )
{ {
CheckPlayerListCallbackData data = { CheckPlayerListCallbackData data = {
@ -2817,6 +2991,51 @@ static void checkPlayerList_( int line, IDirectPlay4 *dp, ExpectedPlayer *expect
data.actualPlayerCount ); data.actualPlayerCount );
} }
#define checkGroupPlayerList( dp, group, expectedPlayers, expectedPlayerCount ) \
checkGroupPlayerList_( __LINE__, dp, group, expectedPlayers, expectedPlayerCount )
static void checkGroupPlayerList_( int line, DPID group, IDirectPlay4 *dp, ExpectedPlayer *expectedPlayers,
int expectedPlayerCount )
{
CheckPlayerListCallbackData data = {
.line = line,
.dp = dp,
.expectedPlayers = expectedPlayers,
.expectedPlayerCount = expectedPlayerCount,
};
HRESULT hr;
hr = IDirectPlayX_EnumGroupPlayers( dp, group, NULL, checkPlayerListCallback, &data, DPENUMPLAYERS_LOCAL );
ok_( __FILE__, line )( hr == DP_OK, "EnumGroupPlayers() returned %#lx.\n", hr );
hr = IDirectPlayX_EnumGroupPlayers( dp, group, NULL, checkPlayerListCallback, &data, DPENUMPLAYERS_REMOTE );
ok_( __FILE__, line )( hr == DP_OK, "EnumGroupPlayers() returned %#lx.\n", hr );
ok_( __FILE__, line )( data.actualPlayerCount == data.expectedPlayerCount, "got player count %d.\n",
data.actualPlayerCount );
}
#define checkGroupList( dp, expectedGroups, expectedGroupCount ) \
checkGroupList_( __LINE__, dp, expectedGroups, expectedGroupCount )
static void checkGroupList_( int line, IDirectPlay4 *dp, ExpectedPlayer *expectedGroups, int expectedGroupCount )
{
CheckPlayerListCallbackData data = {
.line = line,
.dp = dp,
.expectedPlayers = expectedGroups,
.expectedPlayerCount = expectedGroupCount,
};
HRESULT hr;
hr = IDirectPlayX_EnumGroups( dp, NULL, checkPlayerListCallback, &data, DPENUMGROUPS_LOCAL );
ok_( __FILE__, line )( hr == DP_OK, "EnumGroups() returned %#lx.\n", hr );
hr = IDirectPlayX_EnumGroups( dp, NULL, checkPlayerListCallback, &data, DPENUMGROUPS_REMOTE );
ok_( __FILE__, line )( hr == DP_OK, "EnumGroups() returned %#lx.\n", hr );
ok_( __FILE__, line )( data.actualPlayerCount == data.expectedPlayerCount, "got group count %d.\n",
data.actualPlayerCount );
}
#define checkPlayerExists( dp, expectedDpid, expectedPlayerType, expectedShortName, expectedLongName, expectedFlags, \ #define checkPlayerExists( dp, expectedDpid, expectedPlayerType, expectedShortName, expectedLongName, expectedFlags, \
expectedPlayerData, expectedPlayerDataSize ) \ expectedPlayerData, expectedPlayerDataSize ) \
checkPlayerExists_( __LINE__, dp, expectedDpid, expectedPlayerType, expectedShortName, expectedLongName, \ checkPlayerExists_( __LINE__, dp, expectedDpid, expectedPlayerType, expectedShortName, expectedLongName, \
@ -2918,9 +3137,36 @@ static void check_Open_( int line, IDirectPlay4A *dp, DPSESSIONDESC2 *dpsd, cons
.expectedPlayerData = expectedPlayerData, .expectedPlayerData = expectedPlayerData,
.expectedPlayerDataSize = sizeof( expectedPlayerData ), .expectedPlayerDataSize = sizeof( expectedPlayerData ),
}, },
{
.expectedDpid = 0xd00de,
.expectedPlayerType = DPPLAYERTYPE_PLAYER,
.expectedFlags = DPENUMPLAYERS_REMOTE,
},
};
ExpectedPlayer expectedGroups[] =
{
{
.expectedDpid = 0x5e7,
.expectedPlayerType = DPPLAYERTYPE_GROUP,
.expectedShortName = "short name",
.expectedLongName = "long name",
.expectedFlags = DPENUMPLAYERS_REMOTE,
.expectedPlayerData = expectedPlayerData,
.expectedPlayerDataSize = sizeof( expectedPlayerData ),
},
};
ExpectedPlayer expectedGroupPlayers[] =
{
{
.expectedDpid = 0xd00de,
.expectedPlayerType = DPPLAYERTYPE_PLAYER,
.expectedFlags = DPENUMPLAYERS_REMOTE,
},
}; };
checkPlayerList_( line, dp, expectedPlayers, ARRAYSIZE( expectedPlayers ) ); checkPlayerList_( line, dp, expectedPlayers, ARRAYSIZE( expectedPlayers ) );
checkGroupList_( line, dp, expectedGroups, ARRAYSIZE( expectedGroups ) );
checkGroupPlayerList_( line, 0x5e7, dp, expectedGroupPlayers, ARRAYSIZE( expectedGroupPlayers ) );
hr = IDirectPlayX_Close( dp ); hr = IDirectPlayX_Close( dp );
checkHR( DP_OK, hr ); checkHR( DP_OK, hr );
@ -4648,20 +4894,20 @@ static void test_CreatePlayer(void)
/* Player name */ /* Player name */
dpid = 0xdeadbeef; dpid = 0xdeadbeef;
check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 2, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 1 ); check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 2, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 2 );
dpid = 0xdeadbeef; dpid = 0xdeadbeef;
check_CreatePlayer( dp, &dpid, &fullName, 0, DP_OK, 3, recvSock, TRUE, 0x8, L"short player name", check_CreatePlayer( dp, &dpid, &fullName, 0, DP_OK, 3, recvSock, TRUE, 0x8, L"short player name",
"short player name", L"long player name", "long player name", 2 ); "short player name", L"long player name", "long player name", 3 );
name = fullName; name = fullName;
name.dwSize = 1; name.dwSize = 1;
dpid = 0xdeadbeef; dpid = 0xdeadbeef;
check_CreatePlayer( dp, &dpid, &name, 0, DP_OK, 4, recvSock, TRUE, 0x8, L"short player name", "short player name", check_CreatePlayer( dp, &dpid, &name, 0, DP_OK, 4, recvSock, TRUE, 0x8, L"short player name", "short player name",
L"long player name", "long player name", 3 ); L"long player name", "long player name", 4 );
dpid = 0xdeadbeef; dpid = 0xdeadbeef;
check_CreatePlayer( dp, &dpid, &nullName, 0, DP_OK, 5, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 4 ); check_CreatePlayer( dp, &dpid, &nullName, 0, DP_OK, 5, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 5 );
/* Null dpid */ /* Null dpid */
dpid = 0xdeadbeef; dpid = 0xdeadbeef;
@ -4669,11 +4915,11 @@ static void test_CreatePlayer(void)
/* Flags */ /* Flags */
dpid = 0xdeadbeef; dpid = 0xdeadbeef;
check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 6, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 5 ); check_CreatePlayer( dp, &dpid, NULL, 0, DP_OK, 6, recvSock, TRUE, 0x8, NULL, NULL, NULL, NULL, 6 );
dpid = 0xdeadbeef; dpid = 0xdeadbeef;
check_CreatePlayer( dp, &dpid, NULL, DPPLAYER_SPECTATOR, DP_OK, 7, recvSock, TRUE, 0x208, NULL, NULL, NULL, NULL, check_CreatePlayer( dp, &dpid, NULL, DPPLAYER_SPECTATOR, DP_OK, 7, recvSock, TRUE, 0x208, NULL, NULL, NULL, NULL,
6 ); 7 );
closesocket( recvSock ); closesocket( recvSock );
closesocket( sendSock ); closesocket( sendSock );
@ -4920,7 +5166,7 @@ static void test_CREATEPLAYER(void)
checkPlayerExists( dp, 0x07734, DPPLAYERTYPE_PLAYER, "new player short name", "new player long name", checkPlayerExists( dp, 0x07734, DPPLAYERTYPE_PLAYER, "new player short name", "new player long name",
DPENUMPLAYERS_REMOTE, playerData, sizeof( playerData ) ); DPENUMPLAYERS_REMOTE, playerData, sizeof( playerData ) );
dpid = checkCreatePlayerOrGroupMessage( dp, DPPLAYERTYPE_PLAYER, 0x07734, 3, playerData, sizeof( playerData ), dpid = checkCreatePlayerOrGroupMessage( dp, DPPLAYERTYPE_PLAYER, 0x07734, 4, playerData, sizeof( playerData ),
"new player short name", "new player long name", 0, 0 ); "new player short name", "new player long name", 0, 0 );
ok( dpid == 0x11223344, "got destination id %#lx.\n", dpid ); ok( dpid == 0x11223344, "got destination id %#lx.\n", dpid );
@ -7852,7 +8098,7 @@ static void test_Send(void)
createPlayer( dp, 0x07734, NULL, NULL, 0, 0, sendSock, recvSock ); createPlayer( dp, 0x07734, NULL, NULL, 0, 0, sendSock, recvSock );
createPlayer( dp, 0x14, NULL, NULL, 0, 0, sendSock, recvSock ); createPlayer( dp, 0x14, NULL, NULL, 0, 0, sendSock, recvSock );
checkCreatePlayerOrGroupMessage( dp, DPPLAYERTYPE_PLAYER, 0x14, 2, NULL, 0, NULL, NULL, 0, DPPLAYER_LOCAL ); checkCreatePlayerOrGroupMessage( dp, DPPLAYERTYPE_PLAYER, 0x14, 3, NULL, 0, NULL, NULL, 0, DPPLAYER_LOCAL );
hr = IDirectPlayX_Send( dp, 0x07734, 0xdeadbeef, DPSEND_GUARANTEED, data, sizeof( data ) ); hr = IDirectPlayX_Send( dp, 0x07734, 0xdeadbeef, DPSEND_GUARANTEED, data, sizeof( data ) );
todo_wine ok( hr == DPERR_INVALIDPARAM, "got hr %#lx.\n", hr ); todo_wine ok( hr == DPERR_INVALIDPARAM, "got hr %#lx.\n", hr );
@ -8289,7 +8535,7 @@ static void test_Receive(void)
waitResult = WaitForSingleObject( event0, 2000 ); waitResult = WaitForSingleObject( event0, 2000 );
ok( waitResult == WAIT_OBJECT_0, "message wait returned %lu\n", waitResult ); ok( waitResult == WAIT_OBJECT_0, "message wait returned %lu\n", waitResult );
checkCreatePlayerOrGroupMessage( dp, DPPLAYERTYPE_PLAYER, 0x14, 2, NULL, 0, NULL, NULL, 0, DPPLAYER_LOCAL ); checkCreatePlayerOrGroupMessage( dp, DPPLAYERTYPE_PLAYER, 0x14, 3, NULL, 0, NULL, NULL, 0, DPPLAYER_LOCAL );
sendGuaranteedGameMessage( sendSock, 2349, 0x1337, 0x07734, data0, sizeof( data0 ) ); sendGuaranteedGameMessage( sendSock, 2349, 0x1337, 0x07734, data0, sizeof( data0 ) );
sendGuaranteedGameMessage( sendSock, 2349, 0x1337, 0x14, data1, sizeof( data1 ) ); sendGuaranteedGameMessage( sendSock, 2349, 0x1337, 0x14, data1, sizeof( data1 ) );
@ -8793,6 +9039,88 @@ static void test_PING(void)
IDirectPlayX_Release( dp ); IDirectPlayX_Release( dp );
} }
/* AddPlayerToGroup */
#define checkAddPlayerToGroupMessage( dp, expectedGroupId, expectedPlayerId ) \
checkAddPlayerToGroupMessage_( __LINE__, dp, expectedGroupId, expectedPlayerId )
static DPID checkAddPlayerToGroupMessage_( int line, IDirectPlay4 *dp, DPID expectedGroupId, DPID expectedPlayerId )
{
DPMSG_ADDPLAYERTOGROUP *msg;
BYTE msgData[ 256 ];
DWORD msgDataSize;
DPID fromId, toId;
HRESULT hr;
memset( &msgData, 0, sizeof( msgData ) );
msgDataSize = sizeof( msgData );
fromId = 0xdeadbeef;
toId = 0xdeadbeef;
hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize );
ok_( __FILE__, line )( hr == DP_OK, "got hr %#lx.\n", hr );
ok_( __FILE__, line )( fromId == DPID_SYSMSG, "got source id %#lx.\n", fromId );
msg = (DPMSG_ADDPLAYERTOGROUP *) msgData;
ok_( __FILE__, line )( msg->dwType == DPSYS_ADDPLAYERTOGROUP, "got message type %#lx.\n", msg->dwType );
ok_( __FILE__, line )( msg->dpIdGroup == expectedGroupId, "got id %#lx.\n", msg->dpIdGroup );
ok_( __FILE__, line )( msg->dpIdPlayer == expectedPlayerId, "got id %#lx.\n", msg->dpIdPlayer );
return toId;
}
static void test_AddPlayerToGroup(void)
{
DPSESSIONDESC2 appGuidDpsd =
{
.dwSize = sizeof( DPSESSIONDESC2 ),
.guidApplication = appGuid,
.guidInstance = appGuid,
};
DPSESSIONDESC2 serverDpsd =
{
.dwSize = sizeof( DPSESSIONDESC2 ),
.guidApplication = appGuid,
.guidInstance = appGuid,
.lpszSessionName = (WCHAR *) L"normal",
.dwReserved1 = 0xaabbccdd,
};
IDirectPlay4 *dp;
SOCKET sendSock;
SOCKET recvSock;
HRESULT hr;
DPID dpid;
hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectPlay4A, (void **) &dp );
ok( hr == DP_OK, "got hr %#lx.\n", hr );
hr = IDirectPlayX_AddPlayerToGroup( dp, 0x5e7, 0x07734 );
ok( hr == DPERR_UNINITIALIZED, "got hr %#lx.\n", hr );
init_TCPIP_provider( dp, "127.0.0.1", 0 );
joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock, NULL );
hr = IDirectPlayX_AddPlayerToGroup( dp, 0x5e7, 0x07734 );
ok( hr == DPERR_INVALIDPLAYER, "got hr %#lx.\n", hr );
createPlayer( dp, 0x07734, NULL, NULL, 0, 0, sendSock, recvSock );
hr = IDirectPlayX_AddPlayerToGroup( dp, 0x5e7, 0x07734 );
ok( hr == DP_OK, "got hr %#lx.\n", hr );
dpid = checkAddPlayerToGroupMessage( dp, 0x5e7, 0x07734 );
ok( dpid == 0x07734, "got destination id %#lx.\n", dpid );
receiveAddPlayerToGroup( recvSock, 0x07734, 0x5e7 );
checkNoMorePlayerMessages( dp );
checkNoMoreMessages( recvSock );
closesocket( recvSock );
closesocket( sendSock );
IDirectPlayX_Release( dp );
}
/* GetMessageCount */ /* GetMessageCount */
static void test_GetMessageCount(void) static void test_GetMessageCount(void)
@ -10050,6 +10378,7 @@ START_TEST(dplayx)
test_Send(); test_Send();
test_Receive(); test_Receive();
test_PING(); test_PING();
test_AddPlayerToGroup();
if (!winetest_interactive) if (!winetest_interactive)
{ {

View file

@ -516,7 +516,7 @@ static HRESULT WINAPI DPWSCB_EnumSessions( LPDPSP_ENUMSESSIONSDATA data )
DPWS_DATA *dpwsData; DPWS_DATA *dpwsData;
DWORD dpwsDataSize; DWORD dpwsDataSize;
SOCKADDR_IN addr; SOCKADDR_IN addr;
BOOL true = TRUE; BOOL trueflag = TRUE;
SOCKET sock; SOCKET sock;
HRESULT hr; HRESULT hr;
@ -539,8 +539,9 @@ static HRESULT WINAPI DPWSCB_EnumSessions( LPDPSP_ENUMSESSIONSDATA data )
return DPERR_UNAVAILABLE; return DPERR_UNAVAILABLE;
} }
if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char *) &true, if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_BROADCAST,
sizeof( true ) ) ) (const char *) &trueflag,
sizeof( trueflag ) ) )
{ {
ERR( "setsockopt() failed\n" ); ERR( "setsockopt() failed\n" );
closesocket( sock ); closesocket( sock );

View file

@ -2136,7 +2136,7 @@ static HRESULT video_presenter_init_d3d(struct video_presenter *presenter)
present_params.Flags = D3DPRESENTFLAG_VIDEO; present_params.Flags = D3DPRESENTFLAG_VIDEO;
present_params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; present_params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow(), hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow(),
D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_params, &device); D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &present_params, &device);
IDirect3D9_Release(d3d); IDirect3D9_Release(d3d);

View file

@ -2476,6 +2476,7 @@ static void test_presenter_video_window(void)
hr = IDirect3DDevice9_GetCreationParameters(d3d_device, &device_params); hr = IDirect3DDevice9_GetCreationParameters(d3d_device, &device_params);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(device_params.hFocusWindow == GetDesktopWindow(), "Unexpected window %p.\n", device_params.hFocusWindow); ok(device_params.hFocusWindow == GetDesktopWindow(), "Unexpected window %p.\n", device_params.hFocusWindow);
ok(device_params.BehaviorFlags & D3DCREATE_MULTITHREADED, "Unexpected flags %#lx.\n", device_params.BehaviorFlags);
hr = IDirect3DDevice9_GetSwapChain(d3d_device, 0, &swapchain); hr = IDirect3DDevice9_GetSwapChain(d3d_device, 0, &swapchain);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);

View file

@ -875,3 +875,9 @@ void InternetExplorer_WebBrowser_Init(InternetExplorer *This)
This->IExternalConnection_iface.lpVtbl = &ExternalConnectionVtbl; This->IExternalConnection_iface.lpVtbl = &ExternalConnectionVtbl;
This->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; This->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
} }
HRESULT WINAPI IERefreshElevationPolicy(void)
{
FIXME("(): stub\n");
return S_OK;
}

View file

@ -6,5 +6,6 @@
@ stdcall -private DllRegisterServer() @ stdcall -private DllRegisterServer()
@ stdcall -private DllUnregisterServer() @ stdcall -private DllUnregisterServer()
@ stdcall IEGetWriteableHKCU(ptr) @ stdcall IEGetWriteableHKCU(ptr)
@ stdcall IERefreshElevationPolicy()
@ stdcall OpenURL(long long str long) @ stdcall OpenURL(long long str long)
@ stdcall SetQueryNetSessionCount(long) @ stdcall SetQueryNetSessionCount(long)

View file

@ -2388,7 +2388,19 @@ static void WINAPI WineJSDispatch_Free(IWineJSDispatch *iface)
{ {
jsdisp_t *This = impl_from_IWineJSDispatch(iface); jsdisp_t *This = impl_from_IWineJSDispatch(iface);
jsdisp_free(This); jsdisp_free(This);
} }
static HRESULT WINAPI WineJSDispatch_GetPropertyFlags(IWineJSDispatch *iface, DISPID id, UINT32 *ret)
{
jsdisp_t *This = impl_from_IWineJSDispatch(iface);
dispex_prop_t *prop = get_prop(This, id);
if(!prop || prop->type == PROP_DELETED || prop->type == PROP_PROTREF)
return DISP_E_MEMBERNOTFOUND;
*ret = prop->flags & PROPF_PUBLIC_MASK;
return S_OK;
}
static HRESULT WINAPI WineJSDispatch_GetScriptGlobal(IWineJSDispatch *iface, IWineJSDispatchHost **ret) static HRESULT WINAPI WineJSDispatch_GetScriptGlobal(IWineJSDispatch *iface, IWineJSDispatchHost **ret)
{ {
@ -2422,6 +2434,7 @@ static IWineJSDispatchVtbl DispatchExVtbl = {
DispatchEx_GetNextDispID, DispatchEx_GetNextDispID,
DispatchEx_GetNameSpaceParent, DispatchEx_GetNameSpaceParent,
WineJSDispatch_Free, WineJSDispatch_Free,
WineJSDispatch_GetPropertyFlags,
WineJSDispatch_GetScriptGlobal, WineJSDispatch_GetScriptGlobal,
}; };
@ -3282,8 +3295,14 @@ HRESULT jsdisp_define_property(jsdisp_t *obj, const WCHAR *name, property_desc_t
if(desc->explicit_value) { if(desc->explicit_value) {
if(prop->type == PROP_JSVAL) if(prop->type == PROP_JSVAL)
jsval_release(prop->u.val); jsval_release(prop->u.val);
else else {
if(prop->type == PROP_EXTERN && obj->builtin_info->prop_delete) {
hres = obj->builtin_info->prop_delete(obj, prop->u.id);
if(FAILED(hres))
return hres;
}
prop->type = PROP_JSVAL; prop->type = PROP_JSVAL;
}
hres = jsval_copy(desc->value, &prop->u.val); hres = jsval_copy(desc->value, &prop->u.val);
if(FAILED(hres)) { if(FAILED(hres)) {
prop->u.val = jsval_undefined(); prop->u.val = jsval_undefined();

View file

@ -943,7 +943,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Function", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Function", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->function_constr)); jsval_obj(ctx->function_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -952,7 +952,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Object", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Object", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->object_constr)); jsval_obj(ctx->object_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -961,7 +961,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Array", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Array", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->array_constr)); jsval_obj(ctx->array_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -970,7 +970,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Boolean", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Boolean", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->bool_constr)); jsval_obj(ctx->bool_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -979,7 +979,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Date", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Date", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->date_constr)); jsval_obj(ctx->date_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -988,7 +988,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Enumerator", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Enumerator", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->enumerator_constr)); jsval_obj(ctx->enumerator_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -997,42 +997,42 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Error", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Error", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->error_constr)); jsval_obj(ctx->error_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"EvalError", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"EvalError", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->eval_error_constr)); jsval_obj(ctx->eval_error_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"RangeError", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"RangeError", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->range_error_constr)); jsval_obj(ctx->range_error_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"ReferenceError", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"ReferenceError", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->reference_error_constr)); jsval_obj(ctx->reference_error_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"RegExpError", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"RegExpError", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->regexp_error_constr)); jsval_obj(ctx->regexp_error_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"SyntaxError", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"SyntaxError", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->syntax_error_constr)); jsval_obj(ctx->syntax_error_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"TypeError", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"TypeError", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->type_error_constr)); jsval_obj(ctx->type_error_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"URIError", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"URIError", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->uri_error_constr)); jsval_obj(ctx->uri_error_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -1041,7 +1041,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Number", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Number", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->number_constr)); jsval_obj(ctx->number_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -1050,7 +1050,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"RegExp", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"RegExp", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->regexp_constr)); jsval_obj(ctx->regexp_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -1059,7 +1059,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"String", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"String", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->string_constr)); jsval_obj(ctx->string_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -1068,7 +1068,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"VBArray", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"VBArray", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(ctx->vbarray_constr)); jsval_obj(ctx->vbarray_constr));
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -1105,7 +1105,7 @@ HRESULT init_global(script_ctx_t *ctx)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Math", PROPF_WRITABLE, jsval_obj(math)); hres = jsdisp_define_data_property(ctx->global, L"Math", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(math));
jsdisp_release(math); jsdisp_release(math);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -1117,7 +1117,7 @@ HRESULT init_global(script_ctx_t *ctx)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"JSON", PROPF_WRITABLE, jsval_obj(json)); hres = jsdisp_define_data_property(ctx->global, L"JSON", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(json));
jsdisp_release(json); jsdisp_release(json);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -1127,7 +1127,7 @@ HRESULT init_global(script_ctx_t *ctx)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"ActiveXObject", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"ActiveXObject", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(constr)); jsval_obj(constr));
jsdisp_release(constr); jsdisp_release(constr);
if(FAILED(hres)) if(FAILED(hres))

View file

@ -51,6 +51,7 @@ interface IWineJSDispatchHost;
interface IWineJSDispatch : IDispatchEx interface IWineJSDispatch : IDispatchEx
{ {
void Free(); void Free();
HRESULT GetPropertyFlags(DISPID id, UINT32 *ret);
HRESULT GetScriptGlobal(IWineJSDispatchHost **ret); HRESULT GetScriptGlobal(IWineJSDispatchHost **ret);
} }

View file

@ -208,6 +208,9 @@ static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *jsstr,
ret[i].index = result->cp - str - result->match_len; ret[i].index = result->cp - str - result->match_len;
ret[i++].length = result->match_len; ret[i++].length = result->match_len;
if (result->match_len == 0)
result->cp++;
if(!gflag && !(This->jsregexp->flags & REG_GLOB)) { if(!gflag && !(This->jsregexp->flags & REG_GLOB)) {
hres = S_OK; hres = S_OK;
break; break;

View file

@ -903,7 +903,7 @@ HRESULT init_set_constructor(script_ctx_t *ctx)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Set", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Set", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(constructor)); jsval_obj(constructor));
jsdisp_release(constructor); jsdisp_release(constructor);
if(FAILED(hres)) if(FAILED(hres))
@ -918,7 +918,7 @@ HRESULT init_set_constructor(script_ctx_t *ctx)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"Map", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"Map", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(constructor)); jsval_obj(constructor));
jsdisp_release(constructor); jsdisp_release(constructor);
if(FAILED(hres)) if(FAILED(hres))
@ -933,7 +933,7 @@ HRESULT init_set_constructor(script_ctx_t *ctx)
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = jsdisp_define_data_property(ctx->global, L"WeakMap", PROPF_WRITABLE, hres = jsdisp_define_data_property(ctx->global, L"WeakMap", PROPF_CONFIGURABLE | PROPF_WRITABLE,
jsval_obj(constructor)); jsval_obj(constructor));
jsdisp_release(constructor); jsdisp_release(constructor);
return hres; return hres;

View file

@ -174,6 +174,42 @@ ok(m.length === 2, "m.length is not 2");
ok(m["0"] === "aaab", "m[0] is not \"ab\""); ok(m["0"] === "aaab", "m[0] is not \"ab\"");
ok(m["1"] === "ab", "m[1] is not \"ab\""); ok(m["1"] === "ab", "m[1] is not \"ab\"");
m = "".match(/a*/g);
ok(typeof(m) === "object", "typeof m is not object");
ok(m.length === 1, "m.length is not 1");
ok(m["0"] === "", "m[0] is not \"\"");
m = "aaa".match(/a*/g);
ok(typeof(m) === "object", "typeof m is not object");
ok(m.length === 2, "m.length is not 2");
ok(m["0"] === "aaa", "m[0] is not \"aaa\"");
ok(m["1"] === "", "m[1] is not \"\"");
m = "b".match(/a*/g);
ok(typeof(m) === "object", "typeof m is not object");
ok(m.length === 2, "m.length is not 2");
ok(m["0"] === "", "m[0] is not \"\"");
ok(m["1"] === "", "m[1] is not \"\"");
m = "".match(/a?/g);
ok(typeof(m) === "object", "typeof m is not object");
ok(m.length === 1, "m.length is not 1");
ok(m["0"] === "", "m[0] is not \"\"");
m = "aaa".match(/a?/g);
ok(typeof(m) === "object", "typeof m is not object");
ok(m.length === 4, "m.length is not 4");
ok(m["0"] === "a", "m[0] is not \"a\"");
ok(m["1"] === "a", "m[1] is not \"a\"");
ok(m["2"] === "a", "m[2] is not \"a\"");
ok(m["3"] === "", "m[3] is not \"\"");
m = "b".match(/a?/g);
ok(typeof(m) === "object", "typeof m is not object");
ok(m.length === 2, "m.length is not 2");
ok(m["0"] === "", "m[0] is not \"\"");
ok(m["1"] === "", "m[1] is not \"\"");
m = "aaa\\\\cabc".match(/\\/g); m = "aaa\\\\cabc".match(/\\/g);
ok(typeof(m) === "object", "typeof m is not object"); ok(typeof(m) === "object", "typeof m is not object");
ok(m.length === 2, "m.length is not 2"); ok(m.length === 2, "m.length is not 2");

View file

@ -50,5 +50,6 @@ void update_browser_script_mode(GeckoBrowser*,IUri*);
BOOL find_global_prop(HTMLInnerWindow*,const WCHAR*,DWORD,ScriptHost**,DISPID*); BOOL find_global_prop(HTMLInnerWindow*,const WCHAR*,DWORD,ScriptHost**,DISPID*);
HRESULT global_prop_still_exists(HTMLInnerWindow*,global_prop_t*); HRESULT global_prop_still_exists(HTMLInnerWindow*,global_prop_t*);
IDispatch *get_script_disp(ScriptHost*); IDispatch *get_script_disp(ScriptHost*);
IWineJSDispatch *get_script_jsdisp(ScriptHost*);
IActiveScriptSite *get_first_script_site(HTMLInnerWindow*); IActiveScriptSite *get_first_script_site(HTMLInnerWindow*);
void initialize_script_global(HTMLInnerWindow*); void initialize_script_global(HTMLInnerWindow*);

View file

@ -4029,7 +4029,9 @@ static HRESULT HTMLWindow_next_dispid(DispatchEx *dispex, DISPID id, DISPID *pid
HRESULT HTMLWindow_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_info *desc) HRESULT HTMLWindow_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_info *desc)
{ {
HTMLInnerWindow *This = impl_from_DispatchEx(dispex); HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
IWineJSDispatch *jsdisp;
global_prop_t *prop; global_prop_t *prop;
HRESULT hres = S_OK;
if(id - MSHTML_DISPID_CUSTOM_MIN >= This->global_prop_cnt) if(id - MSHTML_DISPID_CUSTOM_MIN >= This->global_prop_cnt)
return DISP_E_MEMBERNOTFOUND; return DISP_E_MEMBERNOTFOUND;
@ -4038,10 +4040,22 @@ HRESULT HTMLWindow_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_
desc->name = prop->name; desc->name = prop->name;
desc->id = id; desc->id = id;
desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE;
if(prop->type == GLOBAL_DISPEXVAR)
desc->flags |= PROPF_ENUMERABLE;
desc->iid = 0; desc->iid = 0;
return S_OK;
switch(prop->type) {
case GLOBAL_SCRIPTVAR: {
if((jsdisp = get_script_jsdisp(prop->script_host)))
hres = IWineJSDispatch_GetPropertyFlags(jsdisp, prop->id, &desc->flags);
break;
}
case GLOBAL_DISPEXVAR:
desc->flags |= PROPF_ENUMERABLE;
break;
default:
break;
}
return hres;
} }
static HTMLInnerWindow *HTMLWindow_get_script_global(DispatchEx *dispex) static HTMLInnerWindow *HTMLWindow_get_script_global(DispatchEx *dispex)

View file

@ -85,7 +85,7 @@ struct ScriptHost {
SCRIPTSTATE script_state; SCRIPTSTATE script_state;
HTMLInnerWindow *window; HTMLInnerWindow *window;
IDispatchEx *script_dispex; IWineJSDispatch *script_jsdisp;
GUID guid; GUID guid;
struct list entry; struct list entry;
@ -264,7 +264,7 @@ static BOOL init_script_engine(ScriptHost *script_host, IActiveScript *script)
if(FAILED(hres)) if(FAILED(hres))
WARN("GetScriptDispatch failed: %08lx\n", hres); WARN("GetScriptDispatch failed: %08lx\n", hres);
else { else {
IDispatch_QueryInterface(script_disp, &IID_IDispatchEx, (void**)&script_host->script_dispex); IDispatch_QueryInterface(script_disp, &IID_IWineJSDispatch, (void**)&script_host->script_jsdisp);
IDispatch_Release(script_disp); IDispatch_Release(script_disp);
} }
} }
@ -301,8 +301,8 @@ static void release_script_engine(ScriptHost *This)
unlink_ref(&This->parse); unlink_ref(&This->parse);
} }
if(This->script_dispex) if(This->script_jsdisp)
IDispatchEx_Release(This->script_dispex); IWineJSDispatch_Release(This->script_jsdisp);
IActiveScript_Release(This->script); IActiveScript_Release(This->script);
This->script = NULL; This->script = NULL;
This->script_state = SCRIPTSTATE_UNINITIALIZED; This->script_state = SCRIPTSTATE_UNINITIALIZED;
@ -1588,6 +1588,11 @@ IDispatch *get_script_disp(ScriptHost *script_host)
return disp; return disp;
} }
IWineJSDispatch *get_script_jsdisp(ScriptHost *script_host)
{
return script_host->script_jsdisp;
}
IActiveScriptSite *get_first_script_site(HTMLInnerWindow *window) IActiveScriptSite *get_first_script_site(HTMLInnerWindow *window)
{ {
if(list_empty(&window->script_hosts)) { if(list_empty(&window->script_hosts)) {
@ -1850,9 +1855,9 @@ HRESULT global_prop_still_exists(HTMLInnerWindow *window, global_prop_t *prop)
if(!prop->script_host->script) if(!prop->script_host->script)
return E_UNEXPECTED; return E_UNEXPECTED;
if(!prop->script_host->script_dispex) if(!prop->script_host->script_jsdisp)
return S_OK; return S_OK;
return IDispatchEx_GetMemberProperties(prop->script_host->script_dispex, prop->id, 0, &properties); return IWineJSDispatch_GetMemberProperties(prop->script_host->script_jsdisp, prop->id, 0, &properties);
} }
case GLOBAL_ELEMENTVAR: { case GLOBAL_ELEMENTVAR: {
IHTMLElement *elem; IHTMLElement *elem;

View file

@ -23,6 +23,7 @@ var JS_E_NUMBER_EXPECTED = 0x800a1389;
var JS_E_FUNCTION_EXPECTED = 0x800a138a; var JS_E_FUNCTION_EXPECTED = 0x800a138a;
var JS_E_DATE_EXPECTED = 0x800a138e; var JS_E_DATE_EXPECTED = 0x800a138e;
var JS_E_OBJECT_EXPECTED = 0x800a138f; var JS_E_OBJECT_EXPECTED = 0x800a138f;
var JS_E_UNDEFINED_VARIABLE = 0x800a1391;
var JS_E_BOOLEAN_EXPECTED = 0x800a1392; var JS_E_BOOLEAN_EXPECTED = 0x800a1392;
var JS_E_VBARRAY_EXPECTED = 0x800a1395; var JS_E_VBARRAY_EXPECTED = 0x800a1395;
var JS_E_ENUMERATOR_EXPECTED = 0x800a1397; var JS_E_ENUMERATOR_EXPECTED = 0x800a1397;
@ -2153,6 +2154,109 @@ sync_test("builtin_context", function() {
ok(obj.length === 1, "obj.length = " + obj.length); ok(obj.length === 1, "obj.length = " + obj.length);
}); });
sync_test("globals override", function() {
wineprop = 1337; /* global */
ok(window.hasOwnProperty("wineprop"), "wineprop not a prop of window");
ok(window.wineprop === 1337, "window.wineprop = " + window.wineprop);
ok(wineprop === 1337, "wineprop = " + wineprop);
var i, desc, r = Object.defineProperty(window, "wineprop", { value: 42, configurable: true });
ok(r === window, "defineProperty(window.wineprop) returned " + r);
ok(window.hasOwnProperty("wineprop"), "wineprop not a prop of window after override");
ok(window.wineprop === 42, "window.wineprop after override = " + window.wineprop);
ok(wineprop === 42, "wineprop after override = " + wineprop);
r = (delete window.wineprop);
ok(r === true, "delete window.wineprop returned " + r);
ok(!("wineprop" in window), "wineprop in window after delete");
/* configurable */
var builtins = [
"ActiveXObject",
"Array",
"ArrayBuffer",
"Boolean",
"CollectGarbage",
"DataView",
"Date",
"decodeURI",
"decodeURIComponent",
"encodeURI",
"encodeURIComponent",
"Enumerator",
"Error",
"escape",
"EvalError",
"Function",
"isFinite",
"isNaN",
"JSON",
"Map",
"Math",
"Number",
"parseFloat",
"parseInt",
"RangeError",
"ReferenceError",
"RegExp",
"ScriptEngine",
"ScriptEngineBuildVersion",
"ScriptEngineMajorVersion",
"ScriptEngineMinorVersion",
"Set",
"String",
"SyntaxError",
"TypeError",
"unescape",
"URIError",
"VBArray",
"WeakMap"
];
for(i = 0; i < builtins.length; i++) {
desc = Object.getOwnPropertyDescriptor(window, builtins[i]);
ok(desc !== undefined, "getOwnPropertyDescriptor('" + builtins[i] + "' returned undefined");
ok(desc.configurable === true, builtins[i] + " not configurable");
ok(desc.enumerable === false, builtins[i] + " is enumerable");
ok(desc.writable === true, builtins[i] + " not writable");
r = Object.defineProperty(window, builtins[i], { value: 12, configurable: true, writable: true });
ok(r === window, "defineProperty('" + builtins[i] + "' returned " + r);
r = Object.getOwnPropertyDescriptor(window, builtins[i]);
ok(r !== undefined, "getOwnPropertyDescriptor('" + builtins[i] + "' after override returned undefined");
ok(r.value === 12, builtins[i] + " value = " + r.value);
r = eval(builtins[i]);
ok(r === window[builtins[i]], "Global " + builtins[i] + " does not match redefined window." + builtins[i]);
r = (delete window[builtins[i]]);
ok(r === true, "delete window." + builtins[i] + " returned " + r);
ok(!(builtins[i] in window), builtins[i] + " in window after delete");
try {
eval(builtins[i]);
ok(false, "expected exception retrieving global " + builtins[i] + " after delete.");
}catch(ex) {
r = ex.number >>> 0;
ok(r === JS_E_UNDEFINED_VARIABLE, "retrieving global " + builtins[i] + " after delete threw " + r);
}
r = Object.defineProperty(window, builtins[i], desc);
ok(r === window, "defineProperty('" + builtins[i] + "' to restore returned " + r);
}
/* non-configurable */
builtins = [
"undefined",
"Infinity",
"NaN"
];
for(i = 0; i < builtins.length; i++) {
desc = Object.getOwnPropertyDescriptor(window, builtins[i]);
ok(desc !== undefined, "getOwnPropertyDescriptor('" + builtins[i] + "' returned undefined");
ok(desc.configurable === false, builtins[i] + " is configurable");
ok(desc.enumerable === false, builtins[i] + " is enumerable");
ok(desc.writable === false, builtins[i] + " is writable");
}
});
sync_test("host this", function() { sync_test("host this", function() {
var tests = [ undefined, null, external.nullDisp, function() {}, [0], "foobar", true, 42, new Number(42), external.testHostContext(true), window, document ]; var tests = [ undefined, null, external.nullDisp, function() {}, [0], "foobar", true, 42, new Number(42), external.testHostContext(true), window, document ];
var i, obj = Object.create(Function.prototype); var i, obj = Object.create(Function.prototype);

View file

@ -515,7 +515,7 @@ UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase, const WCHAR *szDatab
if( szDatabase && szDatabase[0] ) if( szDatabase && szDatabase[0] )
{ {
LPCWSTR persist = uiUpdateCount ? MSIDBOPEN_TRANSACT : MSIDBOPEN_READONLY; LPCWSTR persist = uiUpdateCount ? MSIDBOPEN_DIRECT : MSIDBOPEN_READONLY;
ret = MSI_OpenDatabaseW( szDatabase, persist, &db ); ret = MSI_OpenDatabaseW( szDatabase, persist, &db );
if( ret != ERROR_SUCCESS ) if( ret != ERROR_SUCCESS )

View file

@ -278,6 +278,152 @@ static void test_suminfo(void)
r = MsiCloseHandle(hsuminfo); r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
/* try persisting on transacted msi */
r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb);
ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
r = MsiGetSummaryInformationA(hdb, NULL, 1, &hsuminfo);
ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation wrong error\n");
r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Fabian");
ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n");
r = MsiSummaryInfoPersist(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiSummaryInfoPersist wrong error %u\n", r);
r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiCloseHandle(hdb);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
r = MsiGetSummaryInformationA(hdb, NULL, 1, &hsuminfo);
ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation wrong error\n");
sz = 0x10;
strcpy(buf,"x");
r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_AUTHOR, &type, NULL, NULL, buf, &sz);
ok(r == ERROR_SUCCESS, "MsiSummaryInfoGetPropertyA wrong error\n");
ok(!strcmp(buf,"Mike"), "buffer was wrong: %s\n", buf);
r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiCloseHandle(hdb);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
/* try persisting on transacted msi with commit */
r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb);
ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
r = MsiGetSummaryInformationA(hdb, NULL, 1, &hsuminfo);
ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation wrong error\n");
r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Fabian");
ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n");
r = MsiSummaryInfoPersist(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiSummaryInfoPersist wrong error %u\n", r);
r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiDatabaseCommit(hdb);
ok(r == ERROR_SUCCESS, "MsiDatabaseCommit wrong error %u\n", r);
r = MsiCloseHandle(hdb);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
r = MsiGetSummaryInformationA(hdb, NULL, 1, &hsuminfo);
ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation wrong error\n");
sz = 0x10;
strcpy(buf,"x");
r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_AUTHOR, &type, NULL, NULL, buf, &sz);
ok(r == ERROR_SUCCESS, "MsiSummaryInfoGetPropertyA wrong error\n");
ok(!strcmp(buf,"Fabian"), "buffer was wrong: %s\n", buf);
r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiCloseHandle(hdb);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
/* try persisting on direct msi */
r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
r = MsiGetSummaryInformationA(hdb, NULL, 1, &hsuminfo);
ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation wrong error\n");
r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Fabian2");
ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n");
r = MsiSummaryInfoPersist(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiSummaryInfoPersist wrong error %u\n", r);
r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiCloseHandle(hdb);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
r = MsiGetSummaryInformationA(hdb, NULL, 1, &hsuminfo);
ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation wrong error\n");
sz = 0x10;
strcpy(buf,"x");
r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_AUTHOR, &type, NULL, NULL, buf, &sz);
ok(r == ERROR_SUCCESS, "MsiSummaryInfoGetPropertyA wrong error\n");
ok(!strcmp(buf,"Fabian2"), "buffer was wrong: %s\n", buf);
r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiCloseHandle(hdb);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
/* try persisting on indirectly opened msi */
r = MsiGetSummaryInformationA(0, msifile, 2, &hsuminfo);
ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation wrong error %u\n", r);
r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Fabian3");
ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n");
r = MsiSummaryInfoPersist(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiSummaryInfoPersist wrong error %u\n", r);
r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
r = MsiGetSummaryInformationA(hdb, NULL, 1, &hsuminfo);
ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation wrong error\n");
sz = 0x10;
strcpy(buf,"x");
r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_AUTHOR, &type, NULL, NULL, buf, &sz);
ok(r == ERROR_SUCCESS, "MsiSummaryInfoGetPropertyA wrong error\n");
ok(!strcmp(buf,"Fabian3"), "buffer was wrong: %s\n", buf);
r = MsiCloseHandle(hsuminfo);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiCloseHandle(hdb);
ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
/* Cleanup */
r = DeleteFileA(msifile); r = DeleteFileA(msifile);
ok(r, "DeleteFile failed\n"); ok(r, "DeleteFile failed\n");
} }

View file

@ -786,7 +786,7 @@ static NTSTATUS WINAPI LdrpGetX64Information( ULONG type, void *output, void *ex
*(UINT *)output = 0x27f; /* hard-coded x87 control word */ *(UINT *)output = 0x27f; /* hard-coded x87 control word */
return STATUS_SUCCESS; return STATUS_SUCCESS;
default: default:
FIXME( "not implemented type %u\n", type ); FIXME( "not implemented type %lu\n", type );
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
} }
@ -805,7 +805,7 @@ static NTSTATUS WINAPI LdrpSetX64Information( ULONG type, ULONG_PTR input, void
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
default: default:
FIXME( "not implemented type %u\n", type ); FIXME( "not implemented type %lu\n", type );
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
} }

View file

@ -344,6 +344,10 @@ static BOOL is_special_env_var( const char *var )
STARTS_WITH( var, "TEMP=" ) || STARTS_WITH( var, "TEMP=" ) ||
STARTS_WITH( var, "TMP=" ) || STARTS_WITH( var, "TMP=" ) ||
STARTS_WITH( var, "QT_" ) || STARTS_WITH( var, "QT_" ) ||
STARTS_WITH( var, "SDL_AUDIODRIVER=" ) ||
STARTS_WITH( var, "SDL_AUDIO_DRIVER=" ) ||
STARTS_WITH( var, "SDL_VIDEODRIVER=" ) ||
STARTS_WITH( var, "SDL_VIDEO_DRIVER=" ) ||
STARTS_WITH( var, "VK_" ) || STARTS_WITH( var, "VK_" ) ||
STARTS_WITH( var, "XDG_SESSION_TYPE=" )); STARTS_WITH( var, "XDG_SESSION_TYPE=" ));
} }

View file

@ -687,7 +687,7 @@ static void invoke_system_apc( const union apc_call *call, union apc_result *res
/*********************************************************************** /***********************************************************************
* server_select * server_select
*/ */
unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags, unsigned int server_select( const union select_op *select_op, data_size_t size, UINT flags,
timeout_t abs_timeout, context_t *context, struct user_apc *user_apc ) timeout_t abs_timeout, context_t *context, struct user_apc *user_apc )
{ {
unsigned int ret; unsigned int ret;
@ -740,7 +740,7 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
/* don't signal multiple times */ /* don't signal multiple times */
if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT) if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
size = offsetof( select_op_t, signal_and_wait.signal ); size = offsetof( union select_op, signal_and_wait.signal );
} }
pthread_sigmask( SIG_SETMASK, &old_set, NULL ); pthread_sigmask( SIG_SETMASK, &old_set, NULL );
if (signaled) break; if (signaled) break;
@ -763,7 +763,7 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
/*********************************************************************** /***********************************************************************
* server_wait * server_wait
*/ */
unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags, unsigned int server_wait( const union select_op *select_op, data_size_t size, UINT flags,
const LARGE_INTEGER *timeout ) const LARGE_INTEGER *timeout )
{ {
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE; timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;

View file

@ -993,7 +993,7 @@ NTSTATUS WINAPI NtSetInformationDebugObject( HANDLE handle, DEBUGOBJECTINFOCLASS
/* convert the server event data to an NT state change; helper for NtWaitForDebugEvent */ /* convert the server event data to an NT state change; helper for NtWaitForDebugEvent */
static NTSTATUS event_data_to_state_change( const debug_event_t *data, DBGUI_WAIT_STATE_CHANGE *state ) static NTSTATUS event_data_to_state_change( const union debug_event_data *data, DBGUI_WAIT_STATE_CHANGE *state )
{ {
int i; int i;
@ -1098,7 +1098,7 @@ static NTSTATUS get_image_machine( HANDLE handle, USHORT *machine )
NTSTATUS WINAPI NtWaitForDebugEvent( HANDLE handle, BOOLEAN alertable, LARGE_INTEGER *timeout, NTSTATUS WINAPI NtWaitForDebugEvent( HANDLE handle, BOOLEAN alertable, LARGE_INTEGER *timeout,
DBGUI_WAIT_STATE_CHANGE *state ) DBGUI_WAIT_STATE_CHANGE *state )
{ {
debug_event_t data; union debug_event_data data;
unsigned int ret; unsigned int ret;
BOOL wait = TRUE; BOOL wait = TRUE;
@ -1572,7 +1572,7 @@ NTSTATUS WINAPI NtQueryTimer( HANDLE handle, TIMER_INFORMATION_CLASS class,
NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) BOOLEAN alertable, const LARGE_INTEGER *timeout )
{ {
select_op_t select_op; union select_op select_op;
UINT i, flags = SELECT_INTERRUPTIBLE; UINT i, flags = SELECT_INTERRUPTIBLE;
if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
@ -1580,7 +1580,7 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO
if (alertable) flags |= SELECT_ALERTABLE; if (alertable) flags |= SELECT_ALERTABLE;
select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL;
for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
return server_wait( &select_op, offsetof( select_op_t, wait.handles[count] ), flags, timeout ); return server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout );
} }
@ -1599,7 +1599,7 @@ NTSTATUS WINAPI NtWaitForSingleObject( HANDLE handle, BOOLEAN alertable, const L
NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait, NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) BOOLEAN alertable, const LARGE_INTEGER *timeout )
{ {
select_op_t select_op; union select_op select_op;
UINT flags = SELECT_INTERRUPTIBLE; UINT flags = SELECT_INTERRUPTIBLE;
if (!signal) return STATUS_INVALID_HANDLE; if (!signal) return STATUS_INVALID_HANDLE;
@ -1883,7 +1883,7 @@ NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJE
NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key, NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) BOOLEAN alertable, const LARGE_INTEGER *timeout )
{ {
select_op_t select_op; union select_op select_op;
UINT flags = SELECT_INTERRUPTIBLE; UINT flags = SELECT_INTERRUPTIBLE;
if (!handle) handle = keyed_event; if (!handle) handle = keyed_event;
@ -1902,7 +1902,7 @@ NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key,
NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key, NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) BOOLEAN alertable, const LARGE_INTEGER *timeout )
{ {
select_op_t select_op; union select_op select_op;
UINT flags = SELECT_INTERRUPTIBLE; UINT flags = SELECT_INTERRUPTIBLE;
if (!handle) handle = keyed_event; if (!handle) handle = keyed_event;

View file

@ -1512,7 +1512,7 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c
DWORD i; DWORD i;
obj_handle_t handle = 0; obj_handle_t handle = 0;
client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS]; client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS];
select_op_t select_op; union select_op select_op;
sigset_t old_set; sigset_t old_set;
if (!peb->BeingDebugged) return 0; /* no debugger present */ if (!peb->BeingDebugged) return 0; /* no debugger present */
@ -1545,7 +1545,7 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c
contexts_to_server( server_contexts, context ); contexts_to_server( server_contexts, context );
server_contexts[0].flags |= SERVER_CTX_EXEC_SPACE; server_contexts[0].flags |= SERVER_CTX_EXEC_SPACE;
server_contexts[0].exec_space.space.space = exception ? EXEC_SPACE_EXCEPTION : EXEC_SPACE_SYSCALL; server_contexts[0].exec_space.space.space = exception ? EXEC_SPACE_EXCEPTION : EXEC_SPACE_SYSCALL;
server_select( &select_op, offsetof( select_op_t, wait.handles[1] ), SELECT_INTERRUPTIBLE, server_select( &select_op, offsetof( union select_op, wait.handles[1] ), SELECT_INTERRUPTIBLE,
TIMEOUT_INFINITE, server_contexts, NULL ); TIMEOUT_INFINITE, server_contexts, NULL );
SERVER_START_REQ( get_exception_status ) SERVER_START_REQ( get_exception_status )

View file

@ -208,9 +208,9 @@ extern void start_server( BOOL debug );
extern unsigned int server_call_unlocked( void *req_ptr ); extern unsigned int server_call_unlocked( void *req_ptr );
extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset );
extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset ); extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset );
extern unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags, extern unsigned int server_select( const union select_op *select_op, data_size_t size, UINT flags,
timeout_t abs_timeout, context_t *context, struct user_apc *user_apc ); timeout_t abs_timeout, context_t *context, struct user_apc *user_apc );
extern unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags, extern unsigned int server_wait( const union select_op *select_op, data_size_t size, UINT flags,
const LARGE_INTEGER *timeout ); const LARGE_INTEGER *timeout );
extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call,
union apc_result *result ); union apc_result *result );

View file

@ -506,7 +506,7 @@ static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp,
struct dispatch_context struct dispatch_context
{ {
irp_params_t params; union irp_params params;
HANDLE handle; HANDLE handle;
struct irp_data *irp_data; struct irp_data *irp_data;
ULONG in_size; ULONG in_size;

View file

@ -1176,7 +1176,7 @@ typedef struct _bezier_vector {
GLdouble y; GLdouble y;
} bezier_vector; } bezier_vector;
static double bezier_deviation_squared(const bezier_vector *p) static BOOL bezier_fits_deviation(const bezier_vector *p, FLOAT max_deviation)
{ {
bezier_vector deviation; bezier_vector deviation;
bezier_vector vertex; bezier_vector vertex;
@ -1184,25 +1184,36 @@ static double bezier_deviation_squared(const bezier_vector *p)
double base_length; double base_length;
double dot; double dot;
max_deviation *= max_deviation;
vertex.x = (p[0].x + p[1].x*2 + p[2].x)/4 - p[0].x; vertex.x = (p[0].x + p[1].x*2 + p[2].x)/4 - p[0].x;
vertex.y = (p[0].y + p[1].y*2 + p[2].y)/4 - p[0].y; vertex.y = (p[0].y + p[1].y*2 + p[2].y)/4 - p[0].y;
base.x = p[2].x - p[0].x; base.x = p[2].x - p[0].x;
base.y = p[2].y - p[0].y; base.y = p[2].y - p[0].y;
base_length = sqrt(base.x*base.x + base.y*base.y); base_length = base.x * base.x + base.y * base.y;
base.x /= base_length; if (base_length <= max_deviation)
base.y /= base_length; {
base.x = 0.0;
base.y = 0.0;
}
else
{
base_length = sqrt(base_length);
base.x /= base_length;
base.y /= base_length;
dot = base.x*vertex.x + base.y*vertex.y; dot = base.x*vertex.x + base.y*vertex.y;
dot = min(max(dot, 0.0), base_length); dot = min(max(dot, 0.0), base_length);
base.x *= dot; base.x *= dot;
base.y *= dot; base.y *= dot;
}
deviation.x = vertex.x-base.x; deviation.x = vertex.x-base.x;
deviation.y = vertex.y-base.y; deviation.y = vertex.y-base.y;
return deviation.x*deviation.x + deviation.y*deviation.y; return deviation.x*deviation.x + deviation.y*deviation.y <= max_deviation;
} }
static int bezier_approximate(const bezier_vector *p, bezier_vector *points, FLOAT deviation) static int bezier_approximate(const bezier_vector *p, bezier_vector *points, FLOAT deviation)
@ -1212,7 +1223,7 @@ static int bezier_approximate(const bezier_vector *p, bezier_vector *points, FLO
bezier_vector vertex; bezier_vector vertex;
int total_vertices; int total_vertices;
if(bezier_deviation_squared(p) <= deviation*deviation) if (bezier_fits_deviation(p, deviation))
{ {
if(points) if(points)
*points = p[2]; *points = p[2];

View file

@ -4495,6 +4495,120 @@ static LSTATUS get_device_property(struct device *device, const DEVPROPKEY *prop
return ls; return ls;
} }
BOOL WINAPI SetupDiGetDevicePropertyKeys( HDEVINFO devinfo, PSP_DEVINFO_DATA device_data,
DEVPROPKEY *prop_keys, DWORD prop_keys_len,
DWORD *required_prop_keys, DWORD flags )
{
struct device *device;
DWORD count = 0, i;
HKEY hkey;
LSTATUS ls;
DEVPROPKEY *keys_buf = NULL;
TRACE( "%p, %p, %p, %lu, %p, %#lx\n", devinfo, device_data, prop_keys, prop_keys_len,
required_prop_keys, flags);
if (flags)
{
SetLastError( ERROR_INVALID_FLAGS );
return FALSE;
}
if (!prop_keys && prop_keys_len)
{
SetLastError( ERROR_INVALID_USER_BUFFER );
return FALSE;
}
device = get_device( devinfo, device_data );
if (!device)
return FALSE;
ls = RegOpenKeyExW( device->key, L"Properties", 0, KEY_ENUMERATE_SUB_KEYS, &hkey );
if (ls)
{
SetLastError( ls );
return FALSE;
}
keys_buf = malloc( sizeof( *keys_buf ) * prop_keys_len );
if (!keys_buf && prop_keys_len)
{
RegCloseKey( hkey );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
for (i = 0; ;i++)
{
WCHAR guid_str[39];
HKEY propkey;
DWORD len, j;
GUID prop_guid;
len = ARRAY_SIZE( guid_str );
ls = RegEnumKeyExW( hkey, i, guid_str, &len, NULL, NULL, NULL, NULL );
if (ls)
{
if (ls == ERROR_NO_MORE_ITEMS)
ls = ERROR_SUCCESS;
else
ERR( "Could not enumerate subkeys for device %s: %lu\n",
debugstr_w( device->instanceId ), ls );
break;
}
ls = RegOpenKeyExW( hkey, guid_str, 0, KEY_ENUMERATE_SUB_KEYS, &propkey );
if (ls)
break;
guid_str[37] = 0;
if (UuidFromStringW( &guid_str[1], &prop_guid ))
{
ERR( "Could not parse propkey GUID string %s\n", debugstr_w( &guid_str[1] ) );
RegCloseKey( propkey );
continue;
}
for (j = 0; ;j++)
{
DEVPROPID pid;
WCHAR key_name[6];
len = 5;
ls = RegEnumKeyExW( propkey, j, key_name, &len, NULL, NULL, NULL, NULL );
if (ls)
{
if (ls != ERROR_NO_MORE_ITEMS)
ERR( "Could not enumerate subkeys for device %s under %s: %lu\n", debugstr_w( device->instanceId ),
debugstr_guid( &prop_guid ), ls );
break;
}
swscanf( key_name, L"%04X", &pid );
if (++count <= prop_keys_len)
{
keys_buf[count-1].fmtid = prop_guid;
keys_buf[count-1].pid = pid;
}
}
RegCloseKey( propkey );
}
RegCloseKey( hkey );
if (!ls)
{
if (required_prop_keys)
*required_prop_keys = count;
if (prop_keys_len < count)
{
free( keys_buf );
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
memcpy( prop_keys, keys_buf, count * sizeof( *keys_buf ) );
}
free( keys_buf );
SetLastError( ls );
return !ls;
}
/*********************************************************************** /***********************************************************************
* SetupDiGetDevicePropertyW (SETUPAPI.@) * SetupDiGetDevicePropertyW (SETUPAPI.@)
*/ */

View file

@ -357,6 +357,7 @@
@ stub SetupDiGetDeviceInterfaceAlias @ stub SetupDiGetDeviceInterfaceAlias
@ stdcall SetupDiGetDeviceInterfaceDetailA(long ptr ptr long ptr ptr) @ stdcall SetupDiGetDeviceInterfaceDetailA(long ptr ptr long ptr ptr)
@ stdcall SetupDiGetDeviceInterfaceDetailW(long ptr ptr long ptr ptr) @ stdcall SetupDiGetDeviceInterfaceDetailW(long ptr ptr long ptr ptr)
@ stdcall SetupDiGetDevicePropertyKeys(ptr ptr ptr long ptr long)
@ stdcall SetupDiGetDevicePropertyW(ptr ptr ptr ptr ptr long ptr long) @ stdcall SetupDiGetDevicePropertyW(ptr ptr ptr ptr ptr long ptr long)
@ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr) @ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr)
@ stdcall SetupDiGetDeviceRegistryPropertyW(long ptr long ptr ptr long ptr) @ stdcall SetupDiGetDeviceRegistryPropertyW(long ptr long ptr ptr long ptr)

View file

@ -56,6 +56,7 @@ static HRESULT (WINAPI *pDriverStoreFindDriverPackageA)(const char *inf_path, vo
static BOOL (WINAPI *pSetupDiSetDevicePropertyW)(HDEVINFO, SP_DEVINFO_DATA *, const DEVPROPKEY *, DEVPROPTYPE, const BYTE *, DWORD, DWORD); static BOOL (WINAPI *pSetupDiSetDevicePropertyW)(HDEVINFO, SP_DEVINFO_DATA *, const DEVPROPKEY *, DEVPROPTYPE, const BYTE *, DWORD, DWORD);
static BOOL (WINAPI *pSetupDiGetDevicePropertyW)(HDEVINFO, SP_DEVINFO_DATA *, const DEVPROPKEY *, DEVPROPTYPE *, BYTE *, DWORD, DWORD *, DWORD); static BOOL (WINAPI *pSetupDiGetDevicePropertyW)(HDEVINFO, SP_DEVINFO_DATA *, const DEVPROPKEY *, DEVPROPTYPE *, BYTE *, DWORD, DWORD *, DWORD);
static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(SP_INF_INFORMATION *, UINT, SP_ALTPLATFORM_INFO *, SP_ORIGINAL_FILE_INFO_A *); static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(SP_INF_INFORMATION *, UINT, SP_ALTPLATFORM_INFO *, SP_ORIGINAL_FILE_INFO_A *);
static BOOL (WINAPI *pSetupDiGetDevicePropertyKeys)(HDEVINFO, PSP_DEVINFO_DATA, DEVPROPKEY *,DWORD, DWORD *, DWORD);
static BOOL wow64; static BOOL wow64;
@ -885,6 +886,7 @@ static void test_device_property(void)
hmod = LoadLibraryA("setupapi.dll"); hmod = LoadLibraryA("setupapi.dll");
pSetupDiSetDevicePropertyW = (void *)GetProcAddress(hmod, "SetupDiSetDevicePropertyW"); pSetupDiSetDevicePropertyW = (void *)GetProcAddress(hmod, "SetupDiSetDevicePropertyW");
pSetupDiGetDevicePropertyW = (void *)GetProcAddress(hmod, "SetupDiGetDevicePropertyW"); pSetupDiGetDevicePropertyW = (void *)GetProcAddress(hmod, "SetupDiGetDevicePropertyW");
pSetupDiGetDevicePropertyKeys = (void *)GetProcAddress(hmod, "SetupDiGetDevicePropertyKeys");
if (!pSetupDiSetDevicePropertyW || !pSetupDiGetDevicePropertyW) if (!pSetupDiSetDevicePropertyW || !pSetupDiGetDevicePropertyW)
{ {
@ -1190,6 +1192,86 @@ static void test_device_property(void)
ok(size == sizeof(valueW), "Got size %ld\n", size); ok(size == sizeof(valueW), "Got size %ld\n", size);
ok(!lstrcmpW((WCHAR *)buffer, valueW), "Expect buffer %s, got %s\n", wine_dbgstr_w(valueW), wine_dbgstr_w((WCHAR *)buffer)); ok(!lstrcmpW((WCHAR *)buffer, valueW), "Expect buffer %s, got %s\n", wine_dbgstr_w(valueW), wine_dbgstr_w((WCHAR *)buffer));
if (pSetupDiGetDevicePropertyKeys)
{
DWORD keys_len = 0, n, required_len, expected_keys = 1;
DEVPROPKEY *keys;
ret = pSetupDiGetDevicePropertyKeys(NULL, NULL, NULL, 0, NULL, 0);
ok(!ret, "Expect failure\n");
err = GetLastError();
ok(err == ERROR_INVALID_HANDLE, "Expect last error %#x, got %#lx\n",
ERROR_INVALID_HANDLE, err);
SetLastError(0xdeadbeef);
ret = pSetupDiGetDevicePropertyKeys(set, NULL, NULL, 0, NULL, 0);
ok(!ret, "Expect failure\n");
err = GetLastError();
ok(err == ERROR_INVALID_PARAMETER, "Expect last error %#x, got %#lx\n",
ERROR_INVALID_PARAMETER, err);
SetLastError(0xdeadbeef);
ret = pSetupDiGetDevicePropertyKeys(set, &device_data, NULL, 10, NULL, 0);
ok(!ret, "Expect failure\n");
err = GetLastError();
ok(err == ERROR_INVALID_USER_BUFFER, "Expect last error %#x, got %#lx\n",
ERROR_INVALID_USER_BUFFER, err);
SetLastError(0xdeadbeef);
ret = pSetupDiGetDevicePropertyKeys(set, &device_data, NULL, 0, NULL, 0);
ok(!ret, "Expect failure\n");
err = GetLastError();
ok(err == ERROR_INSUFFICIENT_BUFFER, "Expect last error %#x, got %#lx\n",
ERROR_INSUFFICIENT_BUFFER, err);
SetLastError(0xdeadbeef);
ret = pSetupDiGetDevicePropertyKeys(set, &device_data, NULL, 0, &keys_len, 0xdeadbeef);
ok(!ret, "Expect failure\n");
err = GetLastError();
ok(err == ERROR_INVALID_FLAGS, "Expect last error %#x, got %#lx\n",
ERROR_INVALID_FLAGS, err);
SetLastError(0xdeadbeef);
ret = pSetupDiGetDevicePropertyKeys(set, &device_data, NULL, 0, &keys_len, 0);
ok(!ret, "Expect failure\n");
err = GetLastError();
ok(err == ERROR_INSUFFICIENT_BUFFER, "Expect last error %#x, got %#lx\n",
ERROR_INSUFFICIENT_BUFFER, err);
keys = calloc(keys_len, sizeof(*keys));
ok(keys_len && !!keys, "Failed to allocate buffer\n");
SetLastError(0xdeadbeef);
ret = pSetupDiGetDevicePropertyKeys(set, &device_data, keys, keys_len, &keys_len, 0xdeadbeef);
ok(!ret, "Expect failure\n");
err = GetLastError();
ok(err == ERROR_INVALID_FLAGS, "Expect last error %#x, got %#lx\n",
ERROR_INVALID_FLAGS, err);
required_len = 0xdeadbeef;
ret = SetupDiGetDevicePropertyKeys(set, &device_data, keys, keys_len, &required_len, 0);
ok(ret, "Expect success\n");
err = GetLastError();
ok(!err, "Expect last error %#x, got %#lx\n", ERROR_SUCCESS, err);
ok(keys_len == required_len, "%lu != %lu\n", keys_len, required_len);
ok(keys_len >= expected_keys, "Expected %lu >= %lu\n", keys_len, expected_keys);
keys_len = 0;
if (keys)
{
for (n = 0; n < required_len; n++)
{
if (!memcmp(&keys[n], &DEVPKEY_Device_FriendlyName, sizeof(keys[n])))
keys_len++;
}
}
ok(keys_len == expected_keys, "%lu != %lu\n", keys_len, expected_keys);
free(keys);
}
else
win_skip("SetupDiGetDevicePropertyKeys not available\n");
ret = SetupDiRemoveDevice(set, &device_data); ret = SetupDiRemoveDevice(set, &device_data);
ok(ret, "Got unexpected error %#lx.\n", GetLastError()); ok(ret, "Got unexpected error %#lx.\n", GetLastError());

View file

@ -18,11 +18,12 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "wownt32.h" #include "wownt32.h"
#include "user_private.h" #include "user_private.h"
#include "wine/list.h" #include "wine/list.h"
#include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(win); WINE_DEFAULT_DEBUG_CHANNEL(win);
@ -192,22 +193,16 @@ BOOL16 WINAPI SetProp16( HWND16 hwnd, LPCSTR str, HANDLE16 handle )
*/ */
INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func ) INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
{ {
int ret = -1, i, count, total = 32; int ret = -1, i;
property_data_t *list; struct ntuser_property_list *list;
ULONG count, total = 32;
NTSTATUS status;
while (total) while (total)
{ {
if (!(list = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*list) ))) break; if (!(list = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*list) ))) break;
count = 0; status = NtUserBuildPropList( WIN_Handle32(hwnd), total, list, &count );
SERVER_START_REQ( get_window_properties ) if (!status && count)
{
req->window = wine_server_user_handle( HWND_32(hwnd) );
wine_server_set_reply( req, list, total * sizeof(*list) );
if (!wine_server_call( req )) count = reply->total;
}
SERVER_END_REQ;
if (count && count <= total)
{ {
char string[ATOM_BUFFER_SIZE]; char string[ATOM_BUFFER_SIZE];
SEGPTR segptr = MapLS( string ); SEGPTR segptr = MapLS( string );
@ -239,6 +234,7 @@ INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
break; break;
} }
HeapFree( GetProcessHeap(), 0, list ); HeapFree( GetProcessHeap(), 0, list );
if (status != STATUS_BUFFER_TOO_SMALL) break;
total = count; /* restart with larger buffer */ total = count; /* restart with larger buffer */
} }
return ret; return ret;

View file

@ -29,7 +29,6 @@
#include "winnls.h" #include "winnls.h"
#include "objidl.h" #include "objidl.h"
#include "shlobj.h" #include "shlobj.h"
#include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(clipboard); WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
@ -164,7 +163,7 @@ static HANDLE marshal_data( UINT format, HANDLE handle, size_t *ret_size )
{ {
char *ptr; char *ptr;
if (!(size = GlobalSize( handle ))) return 0; if (!(size = GlobalSize( handle ))) return 0;
if ((data_size_t)size != size) return 0; if ((UINT)size != size) return 0;
if (size < sizeof(WCHAR)) return 0; if (size < sizeof(WCHAR)) return 0;
if (!(ptr = GlobalLock( handle ))) return 0; if (!(ptr = GlobalLock( handle ))) return 0;
/* enforce nul-termination the Windows way: ignoring alignment */ /* enforce nul-termination the Windows way: ignoring alignment */
@ -178,7 +177,7 @@ static HANDLE marshal_data( UINT format, HANDLE handle, size_t *ret_size )
{ {
char *ptr; char *ptr;
if (!(size = GlobalSize( handle ))) return 0; if (!(size = GlobalSize( handle ))) return 0;
if ((data_size_t)size != size) return 0; if ((UINT)size != size) return 0;
if (!(ptr = GlobalLock( handle ))) return 0; if (!(ptr = GlobalLock( handle ))) return 0;
ptr[size - 1] = 0; /* enforce null-termination */ ptr[size - 1] = 0; /* enforce null-termination */
GlobalUnlock( handle ); GlobalUnlock( handle );
@ -187,14 +186,14 @@ static HANDLE marshal_data( UINT format, HANDLE handle, size_t *ret_size )
} }
default: default:
if (!(size = GlobalSize( handle ))) return 0; if (!(size = GlobalSize( handle ))) return 0;
if ((data_size_t)size != size) return 0; if ((UINT)size != size) return 0;
*ret_size = size; *ret_size = size;
return handle; return handle;
} }
} }
/* rebuild the target handle from the data received in GetClipboardData */ /* rebuild the target handle from the data received in GetClipboardData */
static HANDLE unmarshal_data( UINT format, void *data, data_size_t size ) static HANDLE unmarshal_data( UINT format, void *data, UINT size )
{ {
HANDLE handle = GlobalReAlloc( data, size, GMEM_MOVEABLE ); /* release unused space */ HANDLE handle = GlobalReAlloc( data, size, GMEM_MOVEABLE ); /* release unused space */

View file

@ -333,10 +333,9 @@ static HGLOBAL dde_get_pair(HGLOBAL shm)
* *
* Post a DDE message * Post a DDE message
*/ */
NTSTATUS post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid, DWORD type ) NTSTATUS post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid )
{ {
void* ptr = NULL; struct post_dde_message_call_params params = { .dest_tid = dest_tid };
int size = 0;
UINT_PTR uiLo, uiHi; UINT_PTR uiLo, uiHi;
LPARAM lp; LPARAM lp;
HGLOBAL hunlock = 0; HGLOBAL hunlock = 0;
@ -364,8 +363,8 @@ NTSTATUS post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DW
{ {
hpack = pack_ptr( h ); hpack = pack_ptr( h );
/* send back the value of h on the other side */ /* send back the value of h on the other side */
ptr = &hpack; params.ptr = &hpack;
size = sizeof(hpack); params.size = sizeof(hpack);
lp = uiLo; lp = uiLo;
TRACE( "send dde-ack %Ix %08Ix => %p\n", uiLo, uiHi, h ); TRACE( "send dde-ack %Ix %08Ix => %p\n", uiLo, uiHi, h );
} }
@ -382,10 +381,10 @@ NTSTATUS post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DW
case WM_DDE_POKE: case WM_DDE_POKE:
if (uiLo) if (uiLo)
{ {
size = GlobalSize( (HGLOBAL)uiLo ) ; params.size = GlobalSize( (HGLOBAL)uiLo ) ;
if ((msg == WM_DDE_ADVISE && size < sizeof(DDEADVISE)) || if ((msg == WM_DDE_ADVISE && params.size < sizeof(DDEADVISE)) ||
(msg == WM_DDE_DATA && size < FIELD_OFFSET(DDEDATA, Value)) || (msg == WM_DDE_DATA && params.size < FIELD_OFFSET(DDEDATA, Value)) ||
(msg == WM_DDE_POKE && size < FIELD_OFFSET(DDEPOKE, Value))) (msg == WM_DDE_POKE && params.size < FIELD_OFFSET(DDEPOKE, Value)))
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
else if (msg != WM_DDE_DATA) return STATUS_INVALID_PARAMETER; else if (msg != WM_DDE_DATA) return STATUS_INVALID_PARAMETER;
@ -393,23 +392,23 @@ NTSTATUS post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DW
lp = uiHi; lp = uiHi;
if (uiLo) if (uiLo)
{ {
if ((ptr = GlobalLock( (HGLOBAL)uiLo) )) if ((params.ptr = GlobalLock( (HGLOBAL)uiLo) ))
{ {
DDEDATA *dde_data = ptr; DDEDATA *dde_data = params.ptr;
TRACE("unused %d, fResponse %d, fRelease %d, fDeferUpd %d, fAckReq %d, cfFormat %d\n", TRACE("unused %d, fResponse %d, fRelease %d, fDeferUpd %d, fAckReq %d, cfFormat %d\n",
dde_data->unused, dde_data->fResponse, dde_data->fRelease, dde_data->unused, dde_data->fResponse, dde_data->fRelease,
dde_data->reserved, dde_data->fAckReq, dde_data->cfFormat); dde_data->reserved, dde_data->fAckReq, dde_data->cfFormat);
hunlock = (HGLOBAL)uiLo; hunlock = (HGLOBAL)uiLo;
} }
} }
TRACE( "send ddepack %u %Ix\n", size, uiHi ); TRACE( "send ddepack %u %Ix\n", params.size, uiHi );
break; break;
case WM_DDE_EXECUTE: case WM_DDE_EXECUTE:
if (lparam) if (lparam)
{ {
if ((ptr = GlobalLock( (HGLOBAL)lparam) )) if ((params.ptr = GlobalLock( (HGLOBAL)lparam) ))
{ {
size = GlobalSize( (HGLOBAL)lparam ); params.size = GlobalSize( (HGLOBAL)lparam );
/* so that the other side can send it back on ACK */ /* so that the other side can send it back on ACK */
lp = lparam; lp = lparam;
hunlock = (HGLOBAL)lparam; hunlock = (HGLOBAL)lparam;
@ -417,20 +416,9 @@ NTSTATUS post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DW
} }
break; break;
} }
SERVER_START_REQ( send_message )
{ res = NtUserMessageCall( hwnd, msg, wparam, lp, &params, NtUserPostDdeCall, FALSE );
req->id = dest_tid; if (!res) FreeDDElParam( msg, lparam );
req->type = type;
req->flags = 0;
req->win = wine_server_user_handle( hwnd );
req->msg = msg;
req->wparam = wparam;
req->lparam = lp;
req->timeout = TIMEOUT_INFINITE;
if (size) wine_server_add_data( req, ptr, size );
if (!(res = wine_server_call( req ))) FreeDDElParam( msg, lparam );
}
SERVER_END_REQ;
if (hunlock) GlobalUnlock(hunlock); if (hunlock) GlobalUnlock(hunlock);
return res; return res;
@ -746,12 +734,7 @@ BOOL WINAPI PostThreadMessageA( DWORD thread, UINT msg, WPARAM wparam, LPARAM lp
*/ */
void WINAPI PostQuitMessage( INT exit_code ) void WINAPI PostQuitMessage( INT exit_code )
{ {
SERVER_START_REQ( post_quit_message ) NtUserPostQuitMessage( exit_code );
{
req->exit_code = exit_code;
wine_server_call( req );
}
SERVER_END_REQ;
} }
/*********************************************************************** /***********************************************************************

View file

@ -21,11 +21,12 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winnls.h" #include "winnls.h"
#include "ntuser.h" #include "ntuser.h"
#include "wine/server.h"
/* size of buffer needed to store an atom string */ /* size of buffer needed to store an atom string */
#define ATOM_BUFFER_SIZE 256 #define ATOM_BUFFER_SIZE 256
@ -37,30 +38,19 @@
* Retrieve the list of properties of a given window. * Retrieve the list of properties of a given window.
* Returned buffer must be freed by caller. * Returned buffer must be freed by caller.
*/ */
static property_data_t *get_properties( HWND hwnd, int *count ) static struct ntuser_property_list *get_properties( HWND hwnd, ULONG *count )
{ {
property_data_t *data; struct ntuser_property_list *props;
int total = 32; int total = 32;
NTSTATUS status;
while (total) while (total)
{ {
int res = 0; if (!(props = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*props) ))) break;
if (!(data = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*data) ))) break; if (!(status = NtUserBuildPropList( hwnd, total, props, count ))) return props;
*count = 0; HeapFree( GetProcessHeap(), 0, props );
SERVER_START_REQ( get_window_properties ) if (status != STATUS_BUFFER_TOO_SMALL) break;
{ total = *count; /* restart with larger buffer */
req->window = wine_server_user_handle( hwnd );
wine_server_set_reply( req, data, total * sizeof(*data) );
if (!wine_server_call( req )) res = reply->total;
}
SERVER_END_REQ;
if (res && res <= total)
{
*count = res;
return data;
}
HeapFree( GetProcessHeap(), 0, data );
total = res; /* restart with larger buffer */
} }
return NULL; return NULL;
} }
@ -179,8 +169,9 @@ HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
*/ */
INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam) INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
{ {
int ret = -1, i, count; int ret = -1;
property_data_t *list = get_properties( hwnd, &count ); ULONG i, count;
struct ntuser_property_list *list = get_properties( hwnd, &count );
if (list) if (list)
{ {
@ -201,8 +192,9 @@ INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
*/ */
INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam) INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam)
{ {
int ret = -1, i, count; int ret = -1;
property_data_t *list = get_properties( hwnd, &count ); ULONG i, count;
struct ntuser_property_list *list = get_properties( hwnd, &count );
if (list) if (list)
{ {

View file

@ -4067,11 +4067,8 @@ static void test_SetForegroundWindow(HWND hwnd)
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0); if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
/* FIXME: these tests are failing because of a race condition ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow());
* between internal focus state applied immediately and X11 focus ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus());
* message coming late */
todo_wine ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow());
todo_wine ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus());
SetForegroundWindow(hwnd); SetForegroundWindow(hwnd);
check_wnd_state(hwnd, hwnd, hwnd, 0); check_wnd_state(hwnd, hwnd, hwnd, 0);

View file

@ -126,7 +126,7 @@ static NTSTATUS WINAPI User32PostDDEMessage( void *args, ULONG size )
{ {
const struct post_dde_message_params *params = args; const struct post_dde_message_params *params = args;
return post_dde_message( params->hwnd, params->msg, params->wparam, params->lparam, return post_dde_message( params->hwnd, params->msg, params->wparam, params->lparam,
params->dest_tid, params->type ); params->dest_tid );
} }
static NTSTATUS WINAPI User32RenderSsynthesizedFormat( void *args, ULONG size ) static NTSTATUS WINAPI User32RenderSsynthesizedFormat( void *args, ULONG size )

View file

@ -46,8 +46,7 @@ struct wm_char_mapping_data
extern HMODULE user32_module; extern HMODULE user32_module;
extern NTSTATUS post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid, extern NTSTATUS post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid );
DWORD type );
extern BOOL unpack_dde_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, extern BOOL unpack_dde_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
const void *buffer, size_t size ); const void *buffer, size_t size );
extern void free_cached_data( UINT format, HANDLE handle ); extern void free_cached_data( UINT format, HANDLE handle );

View file

@ -30,7 +30,6 @@
#include "winuser.h" #include "winuser.h"
#include "winternl.h" #include "winternl.h"
#include "ddk/wdm.h" #include "ddk/wdm.h"
#include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "user_private.h" #include "user_private.h"
@ -54,6 +53,34 @@ static BOOL CALLBACK enum_names_WtoA( LPWSTR name, LPARAM lparam )
return data->func( buffer, data->lparam ); return data->func( buffer, data->lparam );
} }
static BOOL enum_names( HWINSTA handle, NAMEENUMPROCW func, LPARAM lparam )
{
struct ntuser_name_list *list;
ULONG i, size = offsetof( struct ntuser_name_list, strings[256] );
WCHAR *name;
NTSTATUS status;
BOOL ret = TRUE;
while (size)
{
if (!(list = HeapAlloc( GetProcessHeap(), 0, size ))) break;
if (!(status = NtUserBuildNameList( handle, size, list, &size )))
{
for (i = 0, name = list->strings; ret && i < list->count; i++, name += wcslen( name ) + 1)
ret = func( name, lparam );
}
HeapFree( GetProcessHeap(), 0, list );
if (status != STATUS_BUFFER_TOO_SMALL) break;
}
if (status)
{
SetLastError( RtlNtStatusToDosError( status ) );
return FALSE;
}
return ret;
}
/* return a handle to the directory where window station objects are created */ /* return a handle to the directory where window station objects are created */
static HANDLE get_winstations_dir_handle(void) static HANDLE get_winstations_dir_handle(void)
{ {
@ -194,32 +221,7 @@ BOOL WINAPI EnumWindowStationsA( WINSTAENUMPROCA func, LPARAM lparam )
*/ */
BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam ) BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
{ {
unsigned int index = 0; return enum_names( 0, func, lparam );
WCHAR name[MAX_PATH];
BOOL ret = TRUE;
NTSTATUS status;
while (ret)
{
SERVER_START_REQ( enum_winstation )
{
req->index = index;
wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
status = wine_server_call( req );
name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
index = reply->next;
}
SERVER_END_REQ;
if (status == STATUS_NO_MORE_ENTRIES)
break;
if (status)
{
SetLastError( RtlNtStatusToDosError( status ) );
return FALSE;
}
ret = func( name, lparam );
}
return ret;
} }
@ -327,36 +329,10 @@ BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam
*/ */
BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam ) BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
{ {
unsigned int index = 0;
WCHAR name[MAX_PATH];
BOOL ret = TRUE;
NTSTATUS status;
if (!winsta) if (!winsta)
winsta = NtUserGetProcessWindowStation(); winsta = NtUserGetProcessWindowStation();
while (ret) return enum_names( winsta, func, lparam );
{
SERVER_START_REQ( enum_desktop )
{
req->winstation = wine_server_obj_handle( winsta );
req->index = index;
wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
status = wine_server_call( req );
name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
index = reply->next;
}
SERVER_END_REQ;
if (status == STATUS_NO_MORE_ENTRIES)
break;
if (status)
{
SetLastError( RtlNtStatusToDosError( status ) );
return FALSE;
}
ret = func(name, lparam);
}
return ret;
} }

View file

@ -1133,6 +1133,16 @@ NTSTATUS SYSCALL_API NtUserBuildHwndList( HDESK desktop, ULONG unk2, ULONG unk3,
SYSCALL_FUNC( NtUserBuildHwndList ); SYSCALL_FUNC( NtUserBuildHwndList );
} }
NTSTATUS SYSCALL_API NtUserBuildNameList( HWINSTA winsta, ULONG size, struct ntuser_name_list *buffer, ULONG *ret_size )
{
SYSCALL_FUNC( NtUserBuildNameList );
}
NTSTATUS SYSCALL_API NtUserBuildPropList( HWND hwnd, ULONG count, struct ntuser_property_list *buffer, ULONG *ret_count )
{
SYSCALL_FUNC( NtUserBuildPropList );
}
ULONG_PTR SYSCALL_API NtUserCallHwnd( HWND hwnd, DWORD code ) ULONG_PTR SYSCALL_API NtUserCallHwnd( HWND hwnd, DWORD code )
{ {
SYSCALL_FUNC( NtUserCallHwnd ); SYSCALL_FUNC( NtUserCallHwnd );

View file

@ -34,7 +34,6 @@
#include "dbt.h" #include "dbt.h"
#include "dde.h" #include "dde.h"
#include "immdev.h" #include "immdev.h"
#include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msg); WINE_DEFAULT_DEBUG_CHANNEL(msg);
@ -2729,7 +2728,7 @@ int peek_message( MSG *msg, const struct peek_message_filter *filter )
{ {
NTSTATUS res; NTSTATUS res;
size_t size = 0; size_t size = 0;
const message_data_t *msg_data = buffer; const union message_data *msg_data = buffer;
UINT wake_mask, signal_bits, wake_bits, changed_bits, clear_bits = 0; UINT wake_mask, signal_bits, wake_bits, changed_bits, clear_bits = 0;
/* use the same logic as in server/queue.c get_message */ /* use the same logic as in server/queue.c get_message */
@ -3320,7 +3319,7 @@ BOOL WINAPI NtUserGetMessage( MSG *msg, HWND hwnd, UINT first, UINT last )
static BOOL put_message_in_queue( const struct send_message_info *info, size_t *reply_size ) static BOOL put_message_in_queue( const struct send_message_info *info, size_t *reply_size )
{ {
struct packed_message data; struct packed_message data;
message_data_t msg_data; union message_data msg_data;
unsigned int res; unsigned int res;
int i; int i;
timeout_t timeout = TIMEOUT_INFINITE; timeout_t timeout = TIMEOUT_INFINITE;
@ -3368,7 +3367,6 @@ static BOOL put_message_in_queue( const struct send_message_info *info, size_t *
params.wparam = info->wparam; params.wparam = info->wparam;
params.lparam = info->lparam; params.lparam = info->lparam;
params.dest_tid = info->dest_tid; params.dest_tid = info->dest_tid;
params.type = info->type;
res = KeUserModeCallback( NtUserPostDDEMessage, &params, sizeof(params), &ret_ptr, &ret_len ); res = KeUserModeCallback( NtUserPostDDEMessage, &params, sizeof(params), &ret_ptr, &ret_len );
goto done; goto done;
} }
@ -3396,6 +3394,32 @@ done:
return !res; return !res;
} }
/***********************************************************************
* post_dde_message_call
*/
static NTSTATUS post_dde_message_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
const struct post_dde_message_call_params *params )
{
NTSTATUS status;
SERVER_START_REQ( send_message )
{
req->id = params->dest_tid;
req->type = MSG_POSTED;
req->flags = 0;
req->win = wine_server_user_handle( hwnd );
req->msg = msg;
req->wparam = wparam;
req->lparam = lparam;
req->timeout = TIMEOUT_INFINITE;
wine_server_add_data( req, params->ptr, params->size );
status = wine_server_call( req );
}
SERVER_END_REQ;
return status;
}
/*********************************************************************** /***********************************************************************
* wait_message_reply * wait_message_reply
* *
@ -3649,6 +3673,20 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA
return ret; return ret;
} }
/***********************************************************************
* post_quit_message
*/
BOOL post_quit_message( int exit_code )
{
SERVER_START_REQ( post_quit_message )
{
req->exit_code = exit_code;
wine_server_call( req );
}
SERVER_END_REQ;
return TRUE;
}
/********************************************************************** /**********************************************************************
* NtUserDispatchMessage (win32u.@) * NtUserDispatchMessage (win32u.@)
*/ */
@ -4433,6 +4471,9 @@ LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa
case NtUserDragDropCall: case NtUserDragDropCall:
return drag_drop_call( hwnd, msg, wparam, lparam, result_info ); return drag_drop_call( hwnd, msg, wparam, lparam, result_info );
case NtUserPostDdeCall:
return post_dde_message_call( hwnd, msg, wparam, lparam, result_info );
default: default:
FIXME( "%p %x %lx %lx %p %x %x\n", hwnd, msg, (long)wparam, lparam, result_info, (int)type, ansi ); FIXME( "%p %x %lx %lx %p %x %x\n", hwnd, msg, (long)wparam, lparam, result_info, (int)type, ansi );
} }

View file

@ -7006,6 +7006,9 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
case NtUserCallOneParam_MessageBeep: case NtUserCallOneParam_MessageBeep:
return message_beep( arg ); return message_beep( arg );
case NtUserCallOneParam_PostQuitMessage:
return post_quit_message( arg );
case NtUserCallOneParam_ReplyMessage: case NtUserCallOneParam_ReplyMessage:
return reply_message_result( arg ); return reply_message_result( arg );

View file

@ -120,6 +120,9 @@ static void test_window_props(void)
ATOM atom; ATOM atom;
HWND hwnd; HWND hwnd;
BOOL ret; BOOL ret;
ULONG i, count;
NTSTATUS status;
struct ntuser_property_list *props;
hwnd = CreateWindowExA( 0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL ); hwnd = CreateWindowExA( 0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL );
@ -134,12 +137,40 @@ static void test_window_props(void)
prop = NtUserGetProp( hwnd, UlongToPtr(atom) ); prop = NtUserGetProp( hwnd, UlongToPtr(atom) );
ok( prop == UlongToHandle(0xdeadbeef), "prop = %p\n", prop ); ok( prop == UlongToHandle(0xdeadbeef), "prop = %p\n", prop );
props = malloc( 32 * sizeof(*props) );
count = 0xdead;
status = NtUserBuildPropList( hwnd, 32, NULL, &count );
ok( status == STATUS_INVALID_PARAMETER || status == STATUS_INVALID_HANDLE,
"NtUserBuildPropList failed %lx\n", status );
ok( count == 0xdead, "wrong count %lu\n", count );
status = NtUserBuildPropList( hwnd, 32, props, NULL );
ok( status == STATUS_INVALID_PARAMETER || status == STATUS_INVALID_HANDLE,
"NtUserBuildPropList failed %lx\n", status );
ok( count == 0xdead, "wrong count %lu\n", count );
status = NtUserBuildPropList( hwnd, 32, props, &count );
ok( !status, "NtUserBuildPropList failed %lx\n", status );
ok( count, "wrong count %lu\n", count );
for (i = 0; i < count; i++)
{
if (props[i].data != (INT_PTR)0xdeadbeef) continue;
ok( props[i].atom == atom, "prop = %x / %x\n", props[i].atom, atom );
break;
}
ok( i < count, "property not found\n" );
prop = NtUserRemoveProp( hwnd, UlongToPtr(atom) ); prop = NtUserRemoveProp( hwnd, UlongToPtr(atom) );
ok( prop == UlongToHandle(0xdeadbeef), "prop = %p\n", prop ); ok( prop == UlongToHandle(0xdeadbeef), "prop = %p\n", prop );
prop = GetPropW(hwnd, L"test"); prop = GetPropW(hwnd, L"test");
ok(!prop, "prop = %p\n", prop); ok(!prop, "prop = %p\n", prop);
status = NtUserBuildPropList( hwnd, 32, props, &count );
ok( !status, "NtUserBuildPropList failed %lx\n", status );
for (i = 0; i < count; i++) ok( props[i].atom != atom, "property still exists\n" );
free( props );
GlobalDeleteAtom( atom ); GlobalDeleteAtom( atom );
DestroyWindow( hwnd ); DestroyWindow( hwnd );
} }
@ -532,6 +563,106 @@ static void test_NtUserBuildHwndList(void)
DestroyWindow( hwnd ); DestroyWindow( hwnd );
} }
static BOOL CALLBACK enum_names( LPWSTR name, LPARAM lp )
{
struct ntuser_name_list *buffer = (struct ntuser_name_list *)lp;
WCHAR *p;
UINT i;
for (i = 0, p = buffer->strings; i < buffer->count; i++, p += wcslen(p) + 1)
if (!wcscmp( p, name )) break;
ok( i < buffer->count, "string %s not found\n", debugstr_w(name) );
return TRUE;
}
static void test_NtUserBuildNameList(void)
{
struct ntuser_name_list *buffer;
WCHAR *p;
NTSTATUS status;
ULONG i, count, ret_size, expect, size = offsetof( struct ntuser_name_list, strings[256] );
buffer = malloc( size );
memset( buffer, 0xcc, size );
status = NtUserBuildNameList( 0, size, buffer, &ret_size );
ok( !status, "NtUserBuildNameList failed %lx\n", status );
count = buffer->count;
for (i = 0, p = buffer->strings; i < count; i++)
{
trace( "%lu: %s\n", i, debugstr_w(p) );
p += wcslen(p) + 1;
}
ok( *p == 0, "missing final null\n" );
ok( (char *)(p + 1) == (char *)buffer + buffer->size, "wrong size %lx / %lx\n",
(ULONG)((char *)(p + 1) - (char *)buffer), buffer->size );
ok( ret_size == buffer->size, "wrong ret size %lx / %lx\n", ret_size, buffer->size );
EnumWindowStationsW( enum_names, (LPARAM)buffer );
memset( buffer, 0xcc, size );
status = NtUserBuildNameList( 0, ret_size - sizeof(WCHAR), buffer, &ret_size );
ok( status == STATUS_BUFFER_TOO_SMALL, "NtUserBuildNameList failed %lx\n", status );
p = buffer->strings;
while (*p) p += wcslen(p) + 1;
expect = (char *)(p + 1) - (char *)buffer;
ok( buffer->size == expect, "wrong size %lx / %lx\n", buffer->size, expect );
ok( buffer->count == count, "wrong count %lx / %lx\n", buffer->count, count );
ok( ret_size > expect, "wrong size %lx / %lx\n", ret_size, expect );
memset( buffer, 0xcc, size );
ret_size = 0xdead;
status = NtUserBuildNameList( 0, offsetof( struct ntuser_name_list, strings[3] ), buffer, &ret_size );
ok( status == STATUS_BUFFER_TOO_SMALL, "NtUserBuildNameList failed %lx\n", status );
ok( buffer->size == offsetof( struct ntuser_name_list, strings[1] ), "wrong size %lx\n", buffer->size );
ok( buffer->count == count, "wrong count %lx / %lx\n", buffer->count, count );
ok( buffer->strings[0] == 0, "missing final null\n" );
ok( ret_size > offsetof( struct ntuser_name_list, strings[1] ), "wrong size %lx\n", ret_size );
memset( buffer, 0xcc, size );
ret_size = 0xdead;
status = NtUserBuildNameList( 0, offsetof( struct ntuser_name_list, strings[1] ), buffer, &ret_size );
ok( status == STATUS_INVALID_HANDLE, "NtUserBuildNameList failed %lx\n", status );
ok( buffer->size == 0xcccccccc, "wrong size %lx\n", buffer->size );
ok( buffer->count == 0xcccccccc, "wrong count %lx\n", buffer->count );
ok( ret_size == 0xdead, "wrong size %lx\n", ret_size );
memset( buffer, 0xcc, size );
ret_size = 0xdead;
status = NtUserBuildNameList( 0, offsetof( struct ntuser_name_list, strings ) - 1, buffer, &ret_size );
ok( status == STATUS_INVALID_HANDLE, "NtUserBuildNameList failed %lx\n", status );
ok( buffer->size == 0xcccccccc, "wrong size %lx\n", buffer->size );
ok( buffer->count == 0xcccccccc, "wrong count %lx\n", buffer->count );
ok( ret_size == 0xdead, "wrong size %lx\n", ret_size );
memset( buffer, 0xcc, size );
ret_size = 0xdead;
status = NtUserBuildNameList( 0, 0, NULL, &ret_size );
ok( status == STATUS_INVALID_HANDLE, "NtUserBuildNameList failed %lx\n", status );
ok( buffer->size == 0xcccccccc, "wrong size %lx\n", buffer->size );
ok( buffer->count == 0xcccccccc, "wrong count %lx\n", buffer->count );
ok( ret_size == 0xdead, "wrong size %lx\n", ret_size );
status = NtUserBuildNameList( (HANDLE)0xdeadbeef, 1024, buffer, &ret_size );
ok( status == STATUS_INVALID_HANDLE, "NtUserBuildNameList failed %lx\n", status );
memset( buffer, 0xcc, size );
status = NtUserBuildNameList( GetProcessWindowStation(), size, buffer, &ret_size );
ok( !status, "NtUserBuildNameList failed %lx\n", status );
for (i = 0, p = buffer->strings; i < buffer->count; i++)
{
trace( "%lu: %s\n", i, debugstr_w(p) );
p += wcslen(p) + 1;
}
ok( *p == 0, "missing final null\n" );
ok( (char *)(p + 1) == (char *)buffer + buffer->size, "wrong size %lx / %lx\n",
(ULONG)((char *)(p + 1) - (char *)buffer), buffer->size );
ok( ret_size == buffer->size, "wrong ret size %lx / %lx\n", ret_size, buffer->size );
EnumDesktopsW( GetProcessWindowStation(), enum_names, (LPARAM)buffer );
free( buffer );
}
static void test_cursoricon(void) static void test_cursoricon(void)
{ {
WCHAR module[MAX_PATH], res_buf[MAX_PATH]; WCHAR module[MAX_PATH], res_buf[MAX_PATH];
@ -2195,6 +2326,7 @@ START_TEST(win32u)
test_NtUserCreateInputContext(); test_NtUserCreateInputContext();
test_NtUserBuildHimcList(); test_NtUserBuildHimcList();
test_NtUserBuildHwndList(); test_NtUserBuildHwndList();
test_NtUserBuildNameList();
test_cursoricon(); test_cursoricon();
test_message_call(); test_message_call();
test_window_text(); test_window_text();

View file

@ -206,229 +206,231 @@
SYSCALL_ENTRY( 0x00ca, NtUserBeginPaint, 8 ) \ SYSCALL_ENTRY( 0x00ca, NtUserBeginPaint, 8 ) \
SYSCALL_ENTRY( 0x00cb, NtUserBuildHimcList, 16 ) \ SYSCALL_ENTRY( 0x00cb, NtUserBuildHimcList, 16 ) \
SYSCALL_ENTRY( 0x00cc, NtUserBuildHwndList, 32 ) \ SYSCALL_ENTRY( 0x00cc, NtUserBuildHwndList, 32 ) \
SYSCALL_ENTRY( 0x00cd, NtUserCallHwnd, 8 ) \ SYSCALL_ENTRY( 0x00cd, NtUserBuildNameList, 16 ) \
SYSCALL_ENTRY( 0x00ce, NtUserCallHwndParam, 12 ) \ SYSCALL_ENTRY( 0x00ce, NtUserBuildPropList, 16 ) \
SYSCALL_ENTRY( 0x00cf, NtUserCallMsgFilter, 8 ) \ SYSCALL_ENTRY( 0x00cf, NtUserCallHwnd, 8 ) \
SYSCALL_ENTRY( 0x00d0, NtUserCallNextHookEx, 16 ) \ SYSCALL_ENTRY( 0x00d0, NtUserCallHwndParam, 12 ) \
SYSCALL_ENTRY( 0x00d1, NtUserCallNoParam, 4 ) \ SYSCALL_ENTRY( 0x00d1, NtUserCallMsgFilter, 8 ) \
SYSCALL_ENTRY( 0x00d2, NtUserCallOneParam, 8 ) \ SYSCALL_ENTRY( 0x00d2, NtUserCallNextHookEx, 16 ) \
SYSCALL_ENTRY( 0x00d3, NtUserCallTwoParam, 12 ) \ SYSCALL_ENTRY( 0x00d3, NtUserCallNoParam, 4 ) \
SYSCALL_ENTRY( 0x00d4, NtUserChangeClipboardChain, 8 ) \ SYSCALL_ENTRY( 0x00d4, NtUserCallOneParam, 8 ) \
SYSCALL_ENTRY( 0x00d5, NtUserChangeDisplaySettings, 20 ) \ SYSCALL_ENTRY( 0x00d5, NtUserCallTwoParam, 12 ) \
SYSCALL_ENTRY( 0x00d6, NtUserCheckMenuItem, 12 ) \ SYSCALL_ENTRY( 0x00d6, NtUserChangeClipboardChain, 8 ) \
SYSCALL_ENTRY( 0x00d7, NtUserChildWindowFromPointEx, 16 ) \ SYSCALL_ENTRY( 0x00d7, NtUserChangeDisplaySettings, 20 ) \
SYSCALL_ENTRY( 0x00d8, NtUserClipCursor, 4 ) \ SYSCALL_ENTRY( 0x00d8, NtUserCheckMenuItem, 12 ) \
SYSCALL_ENTRY( 0x00d9, NtUserCloseClipboard, 0 ) \ SYSCALL_ENTRY( 0x00d9, NtUserChildWindowFromPointEx, 16 ) \
SYSCALL_ENTRY( 0x00da, NtUserCloseDesktop, 4 ) \ SYSCALL_ENTRY( 0x00da, NtUserClipCursor, 4 ) \
SYSCALL_ENTRY( 0x00db, NtUserCloseWindowStation, 4 ) \ SYSCALL_ENTRY( 0x00db, NtUserCloseClipboard, 0 ) \
SYSCALL_ENTRY( 0x00dc, NtUserCopyAcceleratorTable, 12 ) \ SYSCALL_ENTRY( 0x00dc, NtUserCloseDesktop, 4 ) \
SYSCALL_ENTRY( 0x00dd, NtUserCountClipboardFormats, 0 ) \ SYSCALL_ENTRY( 0x00dd, NtUserCloseWindowStation, 4 ) \
SYSCALL_ENTRY( 0x00de, NtUserCreateAcceleratorTable, 8 ) \ SYSCALL_ENTRY( 0x00de, NtUserCopyAcceleratorTable, 12 ) \
SYSCALL_ENTRY( 0x00df, NtUserCreateCaret, 16 ) \ SYSCALL_ENTRY( 0x00df, NtUserCountClipboardFormats, 0 ) \
SYSCALL_ENTRY( 0x00e0, NtUserCreateDesktopEx, 24 ) \ SYSCALL_ENTRY( 0x00e0, NtUserCreateAcceleratorTable, 8 ) \
SYSCALL_ENTRY( 0x00e1, NtUserCreateInputContext, 4 ) \ SYSCALL_ENTRY( 0x00e1, NtUserCreateCaret, 16 ) \
SYSCALL_ENTRY( 0x00e2, NtUserCreateWindowEx, 68 ) \ SYSCALL_ENTRY( 0x00e2, NtUserCreateDesktopEx, 24 ) \
SYSCALL_ENTRY( 0x00e3, NtUserCreateWindowStation, 28 ) \ SYSCALL_ENTRY( 0x00e3, NtUserCreateInputContext, 4 ) \
SYSCALL_ENTRY( 0x00e4, NtUserDeferWindowPosAndBand, 40 ) \ SYSCALL_ENTRY( 0x00e4, NtUserCreateWindowEx, 68 ) \
SYSCALL_ENTRY( 0x00e5, NtUserDeleteMenu, 12 ) \ SYSCALL_ENTRY( 0x00e5, NtUserCreateWindowStation, 28 ) \
SYSCALL_ENTRY( 0x00e6, NtUserDestroyAcceleratorTable, 4 ) \ SYSCALL_ENTRY( 0x00e6, NtUserDeferWindowPosAndBand, 40 ) \
SYSCALL_ENTRY( 0x00e7, NtUserDestroyCursor, 8 ) \ SYSCALL_ENTRY( 0x00e7, NtUserDeleteMenu, 12 ) \
SYSCALL_ENTRY( 0x00e8, NtUserDestroyInputContext, 4 ) \ SYSCALL_ENTRY( 0x00e8, NtUserDestroyAcceleratorTable, 4 ) \
SYSCALL_ENTRY( 0x00e9, NtUserDestroyMenu, 4 ) \ SYSCALL_ENTRY( 0x00e9, NtUserDestroyCursor, 8 ) \
SYSCALL_ENTRY( 0x00ea, NtUserDestroyWindow, 4 ) \ SYSCALL_ENTRY( 0x00ea, NtUserDestroyInputContext, 4 ) \
SYSCALL_ENTRY( 0x00eb, NtUserDisableThreadIme, 4 ) \ SYSCALL_ENTRY( 0x00eb, NtUserDestroyMenu, 4 ) \
SYSCALL_ENTRY( 0x00ec, NtUserDispatchMessage, 4 ) \ SYSCALL_ENTRY( 0x00ec, NtUserDestroyWindow, 4 ) \
SYSCALL_ENTRY( 0x00ed, NtUserDisplayConfigGetDeviceInfo, 4 ) \ SYSCALL_ENTRY( 0x00ed, NtUserDisableThreadIme, 4 ) \
SYSCALL_ENTRY( 0x00ee, NtUserDragDetect, 12 ) \ SYSCALL_ENTRY( 0x00ee, NtUserDispatchMessage, 4 ) \
SYSCALL_ENTRY( 0x00ef, NtUserDragObject, 20 ) \ SYSCALL_ENTRY( 0x00ef, NtUserDisplayConfigGetDeviceInfo, 4 ) \
SYSCALL_ENTRY( 0x00f0, NtUserDrawCaptionTemp, 28 ) \ SYSCALL_ENTRY( 0x00f0, NtUserDragDetect, 12 ) \
SYSCALL_ENTRY( 0x00f1, NtUserDrawIconEx, 36 ) \ SYSCALL_ENTRY( 0x00f1, NtUserDragObject, 20 ) \
SYSCALL_ENTRY( 0x00f2, NtUserDrawMenuBarTemp, 20 ) \ SYSCALL_ENTRY( 0x00f2, NtUserDrawCaptionTemp, 28 ) \
SYSCALL_ENTRY( 0x00f3, NtUserEmptyClipboard, 0 ) \ SYSCALL_ENTRY( 0x00f3, NtUserDrawIconEx, 36 ) \
SYSCALL_ENTRY( 0x00f4, NtUserEnableMenuItem, 12 ) \ SYSCALL_ENTRY( 0x00f4, NtUserDrawMenuBarTemp, 20 ) \
SYSCALL_ENTRY( 0x00f5, NtUserEnableMouseInPointer, 4 ) \ SYSCALL_ENTRY( 0x00f5, NtUserEmptyClipboard, 0 ) \
SYSCALL_ENTRY( 0x00f6, NtUserEnableMouseInPointerForThread, 0 ) \ SYSCALL_ENTRY( 0x00f6, NtUserEnableMenuItem, 12 ) \
SYSCALL_ENTRY( 0x00f7, NtUserEnableScrollBar, 12 ) \ SYSCALL_ENTRY( 0x00f7, NtUserEnableMouseInPointer, 4 ) \
SYSCALL_ENTRY( 0x00f8, NtUserEndDeferWindowPosEx, 8 ) \ SYSCALL_ENTRY( 0x00f8, NtUserEnableMouseInPointerForThread, 0 ) \
SYSCALL_ENTRY( 0x00f9, NtUserEndMenu, 0 ) \ SYSCALL_ENTRY( 0x00f9, NtUserEnableScrollBar, 12 ) \
SYSCALL_ENTRY( 0x00fa, NtUserEndPaint, 8 ) \ SYSCALL_ENTRY( 0x00fa, NtUserEndDeferWindowPosEx, 8 ) \
SYSCALL_ENTRY( 0x00fb, NtUserEnumDisplayDevices, 16 ) \ SYSCALL_ENTRY( 0x00fb, NtUserEndMenu, 0 ) \
SYSCALL_ENTRY( 0x00fc, NtUserEnumDisplayMonitors, 16 ) \ SYSCALL_ENTRY( 0x00fc, NtUserEndPaint, 8 ) \
SYSCALL_ENTRY( 0x00fd, NtUserEnumDisplaySettings, 16 ) \ SYSCALL_ENTRY( 0x00fd, NtUserEnumDisplayDevices, 16 ) \
SYSCALL_ENTRY( 0x00fe, NtUserExcludeUpdateRgn, 8 ) \ SYSCALL_ENTRY( 0x00fe, NtUserEnumDisplayMonitors, 16 ) \
SYSCALL_ENTRY( 0x00ff, NtUserFindExistingCursorIcon, 12 ) \ SYSCALL_ENTRY( 0x00ff, NtUserEnumDisplaySettings, 16 ) \
SYSCALL_ENTRY( 0x0100, NtUserFindWindowEx, 20 ) \ SYSCALL_ENTRY( 0x0100, NtUserExcludeUpdateRgn, 8 ) \
SYSCALL_ENTRY( 0x0101, NtUserFlashWindowEx, 4 ) \ SYSCALL_ENTRY( 0x0101, NtUserFindExistingCursorIcon, 12 ) \
SYSCALL_ENTRY( 0x0102, NtUserGetAncestor, 8 ) \ SYSCALL_ENTRY( 0x0102, NtUserFindWindowEx, 20 ) \
SYSCALL_ENTRY( 0x0103, NtUserGetAsyncKeyState, 4 ) \ SYSCALL_ENTRY( 0x0103, NtUserFlashWindowEx, 4 ) \
SYSCALL_ENTRY( 0x0104, NtUserGetAtomName, 8 ) \ SYSCALL_ENTRY( 0x0104, NtUserGetAncestor, 8 ) \
SYSCALL_ENTRY( 0x0105, NtUserGetCaretBlinkTime, 0 ) \ SYSCALL_ENTRY( 0x0105, NtUserGetAsyncKeyState, 4 ) \
SYSCALL_ENTRY( 0x0106, NtUserGetCaretPos, 4 ) \ SYSCALL_ENTRY( 0x0106, NtUserGetAtomName, 8 ) \
SYSCALL_ENTRY( 0x0107, NtUserGetClassInfoEx, 20 ) \ SYSCALL_ENTRY( 0x0107, NtUserGetCaretBlinkTime, 0 ) \
SYSCALL_ENTRY( 0x0108, NtUserGetClassName, 12 ) \ SYSCALL_ENTRY( 0x0108, NtUserGetCaretPos, 4 ) \
SYSCALL_ENTRY( 0x0109, NtUserGetClipboardData, 8 ) \ SYSCALL_ENTRY( 0x0109, NtUserGetClassInfoEx, 20 ) \
SYSCALL_ENTRY( 0x010a, NtUserGetClipboardFormatName, 12 ) \ SYSCALL_ENTRY( 0x010a, NtUserGetClassName, 12 ) \
SYSCALL_ENTRY( 0x010b, NtUserGetClipboardOwner, 0 ) \ SYSCALL_ENTRY( 0x010b, NtUserGetClipboardData, 8 ) \
SYSCALL_ENTRY( 0x010c, NtUserGetClipboardSequenceNumber, 0 ) \ SYSCALL_ENTRY( 0x010c, NtUserGetClipboardFormatName, 12 ) \
SYSCALL_ENTRY( 0x010d, NtUserGetClipboardViewer, 0 ) \ SYSCALL_ENTRY( 0x010d, NtUserGetClipboardOwner, 0 ) \
SYSCALL_ENTRY( 0x010e, NtUserGetCursor, 0 ) \ SYSCALL_ENTRY( 0x010e, NtUserGetClipboardSequenceNumber, 0 ) \
SYSCALL_ENTRY( 0x010f, NtUserGetCursorFrameInfo, 16 ) \ SYSCALL_ENTRY( 0x010f, NtUserGetClipboardViewer, 0 ) \
SYSCALL_ENTRY( 0x0110, NtUserGetCursorInfo, 4 ) \ SYSCALL_ENTRY( 0x0110, NtUserGetCursor, 0 ) \
SYSCALL_ENTRY( 0x0111, NtUserGetDC, 4 ) \ SYSCALL_ENTRY( 0x0111, NtUserGetCursorFrameInfo, 16 ) \
SYSCALL_ENTRY( 0x0112, NtUserGetDCEx, 12 ) \ SYSCALL_ENTRY( 0x0112, NtUserGetCursorInfo, 4 ) \
SYSCALL_ENTRY( 0x0113, NtUserGetDisplayConfigBufferSizes, 12 ) \ SYSCALL_ENTRY( 0x0113, NtUserGetDC, 4 ) \
SYSCALL_ENTRY( 0x0114, NtUserGetDoubleClickTime, 0 ) \ SYSCALL_ENTRY( 0x0114, NtUserGetDCEx, 12 ) \
SYSCALL_ENTRY( 0x0115, NtUserGetDpiForMonitor, 16 ) \ SYSCALL_ENTRY( 0x0115, NtUserGetDisplayConfigBufferSizes, 12 ) \
SYSCALL_ENTRY( 0x0116, NtUserGetForegroundWindow, 0 ) \ SYSCALL_ENTRY( 0x0116, NtUserGetDoubleClickTime, 0 ) \
SYSCALL_ENTRY( 0x0117, NtUserGetGUIThreadInfo, 8 ) \ SYSCALL_ENTRY( 0x0117, NtUserGetDpiForMonitor, 16 ) \
SYSCALL_ENTRY( 0x0118, NtUserGetIconInfo, 24 ) \ SYSCALL_ENTRY( 0x0118, NtUserGetForegroundWindow, 0 ) \
SYSCALL_ENTRY( 0x0119, NtUserGetIconSize, 16 ) \ SYSCALL_ENTRY( 0x0119, NtUserGetGUIThreadInfo, 8 ) \
SYSCALL_ENTRY( 0x011a, NtUserGetInternalWindowPos, 12 ) \ SYSCALL_ENTRY( 0x011a, NtUserGetIconInfo, 24 ) \
SYSCALL_ENTRY( 0x011b, NtUserGetKeyNameText, 12 ) \ SYSCALL_ENTRY( 0x011b, NtUserGetIconSize, 16 ) \
SYSCALL_ENTRY( 0x011c, NtUserGetKeyState, 4 ) \ SYSCALL_ENTRY( 0x011c, NtUserGetInternalWindowPos, 12 ) \
SYSCALL_ENTRY( 0x011d, NtUserGetKeyboardLayout, 4 ) \ SYSCALL_ENTRY( 0x011d, NtUserGetKeyNameText, 12 ) \
SYSCALL_ENTRY( 0x011e, NtUserGetKeyboardLayoutList, 8 ) \ SYSCALL_ENTRY( 0x011e, NtUserGetKeyState, 4 ) \
SYSCALL_ENTRY( 0x011f, NtUserGetKeyboardLayoutName, 4 ) \ SYSCALL_ENTRY( 0x011f, NtUserGetKeyboardLayout, 4 ) \
SYSCALL_ENTRY( 0x0120, NtUserGetKeyboardState, 4 ) \ SYSCALL_ENTRY( 0x0120, NtUserGetKeyboardLayoutList, 8 ) \
SYSCALL_ENTRY( 0x0121, NtUserGetLayeredWindowAttributes, 16 ) \ SYSCALL_ENTRY( 0x0121, NtUserGetKeyboardLayoutName, 4 ) \
SYSCALL_ENTRY( 0x0122, NtUserGetMenuBarInfo, 16 ) \ SYSCALL_ENTRY( 0x0122, NtUserGetKeyboardState, 4 ) \
SYSCALL_ENTRY( 0x0123, NtUserGetMenuItemRect, 16 ) \ SYSCALL_ENTRY( 0x0123, NtUserGetLayeredWindowAttributes, 16 ) \
SYSCALL_ENTRY( 0x0124, NtUserGetMessage, 16 ) \ SYSCALL_ENTRY( 0x0124, NtUserGetMenuBarInfo, 16 ) \
SYSCALL_ENTRY( 0x0125, NtUserGetMouseMovePointsEx, 20 ) \ SYSCALL_ENTRY( 0x0125, NtUserGetMenuItemRect, 16 ) \
SYSCALL_ENTRY( 0x0126, NtUserGetObjectInformation, 20 ) \ SYSCALL_ENTRY( 0x0126, NtUserGetMessage, 16 ) \
SYSCALL_ENTRY( 0x0127, NtUserGetOpenClipboardWindow, 0 ) \ SYSCALL_ENTRY( 0x0127, NtUserGetMouseMovePointsEx, 20 ) \
SYSCALL_ENTRY( 0x0128, NtUserGetPointerInfoList, 32 ) \ SYSCALL_ENTRY( 0x0128, NtUserGetObjectInformation, 20 ) \
SYSCALL_ENTRY( 0x0129, NtUserGetPriorityClipboardFormat, 8 ) \ SYSCALL_ENTRY( 0x0129, NtUserGetOpenClipboardWindow, 0 ) \
SYSCALL_ENTRY( 0x012a, NtUserGetProcessDpiAwarenessContext, 4 ) \ SYSCALL_ENTRY( 0x012a, NtUserGetPointerInfoList, 32 ) \
SYSCALL_ENTRY( 0x012b, NtUserGetProcessWindowStation, 0 ) \ SYSCALL_ENTRY( 0x012b, NtUserGetPriorityClipboardFormat, 8 ) \
SYSCALL_ENTRY( 0x012c, NtUserGetProp, 8 ) \ SYSCALL_ENTRY( 0x012c, NtUserGetProcessDpiAwarenessContext, 4 ) \
SYSCALL_ENTRY( 0x012d, NtUserGetQueueStatus, 4 ) \ SYSCALL_ENTRY( 0x012d, NtUserGetProcessWindowStation, 0 ) \
SYSCALL_ENTRY( 0x012e, NtUserGetRawInputBuffer, 12 ) \ SYSCALL_ENTRY( 0x012e, NtUserGetProp, 8 ) \
SYSCALL_ENTRY( 0x012f, NtUserGetRawInputData, 20 ) \ SYSCALL_ENTRY( 0x012f, NtUserGetQueueStatus, 4 ) \
SYSCALL_ENTRY( 0x0130, NtUserGetRawInputDeviceInfo, 16 ) \ SYSCALL_ENTRY( 0x0130, NtUserGetRawInputBuffer, 12 ) \
SYSCALL_ENTRY( 0x0131, NtUserGetRawInputDeviceList, 12 ) \ SYSCALL_ENTRY( 0x0131, NtUserGetRawInputData, 20 ) \
SYSCALL_ENTRY( 0x0132, NtUserGetRegisteredRawInputDevices, 12 ) \ SYSCALL_ENTRY( 0x0132, NtUserGetRawInputDeviceInfo, 16 ) \
SYSCALL_ENTRY( 0x0133, NtUserGetScrollBarInfo, 12 ) \ SYSCALL_ENTRY( 0x0133, NtUserGetRawInputDeviceList, 12 ) \
SYSCALL_ENTRY( 0x0134, NtUserGetSystemDpiForProcess, 4 ) \ SYSCALL_ENTRY( 0x0134, NtUserGetRegisteredRawInputDevices, 12 ) \
SYSCALL_ENTRY( 0x0135, NtUserGetSystemMenu, 8 ) \ SYSCALL_ENTRY( 0x0135, NtUserGetScrollBarInfo, 12 ) \
SYSCALL_ENTRY( 0x0136, NtUserGetThreadDesktop, 4 ) \ SYSCALL_ENTRY( 0x0136, NtUserGetSystemDpiForProcess, 4 ) \
SYSCALL_ENTRY( 0x0137, NtUserGetTitleBarInfo, 8 ) \ SYSCALL_ENTRY( 0x0137, NtUserGetSystemMenu, 8 ) \
SYSCALL_ENTRY( 0x0138, NtUserGetUpdateRect, 12 ) \ SYSCALL_ENTRY( 0x0138, NtUserGetThreadDesktop, 4 ) \
SYSCALL_ENTRY( 0x0139, NtUserGetUpdateRgn, 12 ) \ SYSCALL_ENTRY( 0x0139, NtUserGetTitleBarInfo, 8 ) \
SYSCALL_ENTRY( 0x013a, NtUserGetUpdatedClipboardFormats, 12 ) \ SYSCALL_ENTRY( 0x013a, NtUserGetUpdateRect, 12 ) \
SYSCALL_ENTRY( 0x013b, NtUserGetWindowDC, 4 ) \ SYSCALL_ENTRY( 0x013b, NtUserGetUpdateRgn, 12 ) \
SYSCALL_ENTRY( 0x013c, NtUserGetWindowPlacement, 8 ) \ SYSCALL_ENTRY( 0x013c, NtUserGetUpdatedClipboardFormats, 12 ) \
SYSCALL_ENTRY( 0x013d, NtUserGetWindowRgnEx, 12 ) \ SYSCALL_ENTRY( 0x013d, NtUserGetWindowDC, 4 ) \
SYSCALL_ENTRY( 0x013e, NtUserHideCaret, 4 ) \ SYSCALL_ENTRY( 0x013e, NtUserGetWindowPlacement, 8 ) \
SYSCALL_ENTRY( 0x013f, NtUserHiliteMenuItem, 16 ) \ SYSCALL_ENTRY( 0x013f, NtUserGetWindowRgnEx, 12 ) \
SYSCALL_ENTRY( 0x0140, NtUserInitializeClientPfnArrays, 16 ) \ SYSCALL_ENTRY( 0x0140, NtUserHideCaret, 4 ) \
SYSCALL_ENTRY( 0x0141, NtUserInternalGetWindowIcon, 8 ) \ SYSCALL_ENTRY( 0x0141, NtUserHiliteMenuItem, 16 ) \
SYSCALL_ENTRY( 0x0142, NtUserInternalGetWindowText, 12 ) \ SYSCALL_ENTRY( 0x0142, NtUserInitializeClientPfnArrays, 16 ) \
SYSCALL_ENTRY( 0x0143, NtUserInvalidateRect, 12 ) \ SYSCALL_ENTRY( 0x0143, NtUserInternalGetWindowIcon, 8 ) \
SYSCALL_ENTRY( 0x0144, NtUserInvalidateRgn, 12 ) \ SYSCALL_ENTRY( 0x0144, NtUserInternalGetWindowText, 12 ) \
SYSCALL_ENTRY( 0x0145, NtUserIsClipboardFormatAvailable, 4 ) \ SYSCALL_ENTRY( 0x0145, NtUserInvalidateRect, 12 ) \
SYSCALL_ENTRY( 0x0146, NtUserIsMouseInPointerEnabled, 0 ) \ SYSCALL_ENTRY( 0x0146, NtUserInvalidateRgn, 12 ) \
SYSCALL_ENTRY( 0x0147, NtUserKillTimer, 8 ) \ SYSCALL_ENTRY( 0x0147, NtUserIsClipboardFormatAvailable, 4 ) \
SYSCALL_ENTRY( 0x0148, NtUserLockWindowUpdate, 4 ) \ SYSCALL_ENTRY( 0x0148, NtUserIsMouseInPointerEnabled, 0 ) \
SYSCALL_ENTRY( 0x0149, NtUserLogicalToPerMonitorDPIPhysicalPoint, 8 ) \ SYSCALL_ENTRY( 0x0149, NtUserKillTimer, 8 ) \
SYSCALL_ENTRY( 0x014a, NtUserMapVirtualKeyEx, 12 ) \ SYSCALL_ENTRY( 0x014a, NtUserLockWindowUpdate, 4 ) \
SYSCALL_ENTRY( 0x014b, NtUserMenuItemFromPoint, 16 ) \ SYSCALL_ENTRY( 0x014b, NtUserLogicalToPerMonitorDPIPhysicalPoint, 8 ) \
SYSCALL_ENTRY( 0x014c, NtUserMessageCall, 28 ) \ SYSCALL_ENTRY( 0x014c, NtUserMapVirtualKeyEx, 12 ) \
SYSCALL_ENTRY( 0x014d, NtUserMoveWindow, 24 ) \ SYSCALL_ENTRY( 0x014d, NtUserMenuItemFromPoint, 16 ) \
SYSCALL_ENTRY( 0x014e, NtUserMsgWaitForMultipleObjectsEx, 20 ) \ SYSCALL_ENTRY( 0x014e, NtUserMessageCall, 28 ) \
SYSCALL_ENTRY( 0x014f, NtUserNotifyIMEStatus, 8 ) \ SYSCALL_ENTRY( 0x014f, NtUserMoveWindow, 24 ) \
SYSCALL_ENTRY( 0x0150, NtUserNotifyWinEvent, 16 ) \ SYSCALL_ENTRY( 0x0150, NtUserMsgWaitForMultipleObjectsEx, 20 ) \
SYSCALL_ENTRY( 0x0151, NtUserOpenClipboard, 8 ) \ SYSCALL_ENTRY( 0x0151, NtUserNotifyIMEStatus, 8 ) \
SYSCALL_ENTRY( 0x0152, NtUserOpenDesktop, 12 ) \ SYSCALL_ENTRY( 0x0152, NtUserNotifyWinEvent, 16 ) \
SYSCALL_ENTRY( 0x0153, NtUserOpenInputDesktop, 12 ) \ SYSCALL_ENTRY( 0x0153, NtUserOpenClipboard, 8 ) \
SYSCALL_ENTRY( 0x0154, NtUserOpenWindowStation, 8 ) \ SYSCALL_ENTRY( 0x0154, NtUserOpenDesktop, 12 ) \
SYSCALL_ENTRY( 0x0155, NtUserPeekMessage, 20 ) \ SYSCALL_ENTRY( 0x0155, NtUserOpenInputDesktop, 12 ) \
SYSCALL_ENTRY( 0x0156, NtUserPerMonitorDPIPhysicalToLogicalPoint, 8 ) \ SYSCALL_ENTRY( 0x0156, NtUserOpenWindowStation, 8 ) \
SYSCALL_ENTRY( 0x0157, NtUserPostMessage, 16 ) \ SYSCALL_ENTRY( 0x0157, NtUserPeekMessage, 20 ) \
SYSCALL_ENTRY( 0x0158, NtUserPostThreadMessage, 16 ) \ SYSCALL_ENTRY( 0x0158, NtUserPerMonitorDPIPhysicalToLogicalPoint, 8 ) \
SYSCALL_ENTRY( 0x0159, NtUserPrintWindow, 12 ) \ SYSCALL_ENTRY( 0x0159, NtUserPostMessage, 16 ) \
SYSCALL_ENTRY( 0x015a, NtUserQueryDisplayConfig, 24 ) \ SYSCALL_ENTRY( 0x015a, NtUserPostThreadMessage, 16 ) \
SYSCALL_ENTRY( 0x015b, NtUserQueryInputContext, 8 ) \ SYSCALL_ENTRY( 0x015b, NtUserPrintWindow, 12 ) \
SYSCALL_ENTRY( 0x015c, NtUserRealChildWindowFromPoint, 12 ) \ SYSCALL_ENTRY( 0x015c, NtUserQueryDisplayConfig, 24 ) \
SYSCALL_ENTRY( 0x015d, NtUserRedrawWindow, 16 ) \ SYSCALL_ENTRY( 0x015d, NtUserQueryInputContext, 8 ) \
SYSCALL_ENTRY( 0x015e, NtUserRegisterClassExWOW, 28 ) \ SYSCALL_ENTRY( 0x015e, NtUserRealChildWindowFromPoint, 12 ) \
SYSCALL_ENTRY( 0x015f, NtUserRegisterHotKey, 16 ) \ SYSCALL_ENTRY( 0x015f, NtUserRedrawWindow, 16 ) \
SYSCALL_ENTRY( 0x0160, NtUserRegisterRawInputDevices, 12 ) \ SYSCALL_ENTRY( 0x0160, NtUserRegisterClassExWOW, 28 ) \
SYSCALL_ENTRY( 0x0161, NtUserRegisterTouchPadCapable, 4 ) \ SYSCALL_ENTRY( 0x0161, NtUserRegisterHotKey, 16 ) \
SYSCALL_ENTRY( 0x0162, NtUserReleaseDC, 8 ) \ SYSCALL_ENTRY( 0x0162, NtUserRegisterRawInputDevices, 12 ) \
SYSCALL_ENTRY( 0x0163, NtUserRemoveClipboardFormatListener, 4 ) \ SYSCALL_ENTRY( 0x0163, NtUserRegisterTouchPadCapable, 4 ) \
SYSCALL_ENTRY( 0x0164, NtUserRemoveMenu, 12 ) \ SYSCALL_ENTRY( 0x0164, NtUserReleaseDC, 8 ) \
SYSCALL_ENTRY( 0x0165, NtUserRemoveProp, 8 ) \ SYSCALL_ENTRY( 0x0165, NtUserRemoveClipboardFormatListener, 4 ) \
SYSCALL_ENTRY( 0x0166, NtUserScrollDC, 28 ) \ SYSCALL_ENTRY( 0x0166, NtUserRemoveMenu, 12 ) \
SYSCALL_ENTRY( 0x0167, NtUserScrollWindowEx, 32 ) \ SYSCALL_ENTRY( 0x0167, NtUserRemoveProp, 8 ) \
SYSCALL_ENTRY( 0x0168, NtUserSelectPalette, 12 ) \ SYSCALL_ENTRY( 0x0168, NtUserScrollDC, 28 ) \
SYSCALL_ENTRY( 0x0169, NtUserSendInput, 12 ) \ SYSCALL_ENTRY( 0x0169, NtUserScrollWindowEx, 32 ) \
SYSCALL_ENTRY( 0x016a, NtUserSetActiveWindow, 4 ) \ SYSCALL_ENTRY( 0x016a, NtUserSelectPalette, 12 ) \
SYSCALL_ENTRY( 0x016b, NtUserSetCapture, 4 ) \ SYSCALL_ENTRY( 0x016b, NtUserSendInput, 12 ) \
SYSCALL_ENTRY( 0x016c, NtUserSetClassLong, 16 ) \ SYSCALL_ENTRY( 0x016c, NtUserSetActiveWindow, 4 ) \
SYSCALL_ENTRY( 0x016d, NtUserSetClassLongPtr, 16 ) \ SYSCALL_ENTRY( 0x016d, NtUserSetCapture, 4 ) \
SYSCALL_ENTRY( 0x016e, NtUserSetClassWord, 12 ) \ SYSCALL_ENTRY( 0x016e, NtUserSetClassLong, 16 ) \
SYSCALL_ENTRY( 0x016f, NtUserSetClipboardData, 12 ) \ SYSCALL_ENTRY( 0x016f, NtUserSetClassLongPtr, 16 ) \
SYSCALL_ENTRY( 0x0170, NtUserSetClipboardViewer, 4 ) \ SYSCALL_ENTRY( 0x0170, NtUserSetClassWord, 12 ) \
SYSCALL_ENTRY( 0x0171, NtUserSetCursor, 4 ) \ SYSCALL_ENTRY( 0x0171, NtUserSetClipboardData, 12 ) \
SYSCALL_ENTRY( 0x0172, NtUserSetCursorIconData, 16 ) \ SYSCALL_ENTRY( 0x0172, NtUserSetClipboardViewer, 4 ) \
SYSCALL_ENTRY( 0x0173, NtUserSetCursorPos, 8 ) \ SYSCALL_ENTRY( 0x0173, NtUserSetCursor, 4 ) \
SYSCALL_ENTRY( 0x0174, NtUserSetFocus, 4 ) \ SYSCALL_ENTRY( 0x0174, NtUserSetCursorIconData, 16 ) \
SYSCALL_ENTRY( 0x0175, NtUserSetInternalWindowPos, 16 ) \ SYSCALL_ENTRY( 0x0175, NtUserSetCursorPos, 8 ) \
SYSCALL_ENTRY( 0x0176, NtUserSetKeyboardState, 4 ) \ SYSCALL_ENTRY( 0x0176, NtUserSetFocus, 4 ) \
SYSCALL_ENTRY( 0x0177, NtUserSetLayeredWindowAttributes, 16 ) \ SYSCALL_ENTRY( 0x0177, NtUserSetInternalWindowPos, 16 ) \
SYSCALL_ENTRY( 0x0178, NtUserSetMenu, 8 ) \ SYSCALL_ENTRY( 0x0178, NtUserSetKeyboardState, 4 ) \
SYSCALL_ENTRY( 0x0179, NtUserSetMenuContextHelpId, 8 ) \ SYSCALL_ENTRY( 0x0179, NtUserSetLayeredWindowAttributes, 16 ) \
SYSCALL_ENTRY( 0x017a, NtUserSetMenuDefaultItem, 12 ) \ SYSCALL_ENTRY( 0x017a, NtUserSetMenu, 8 ) \
SYSCALL_ENTRY( 0x017b, NtUserSetObjectInformation, 16 ) \ SYSCALL_ENTRY( 0x017b, NtUserSetMenuContextHelpId, 8 ) \
SYSCALL_ENTRY( 0x017c, NtUserSetParent, 8 ) \ SYSCALL_ENTRY( 0x017c, NtUserSetMenuDefaultItem, 12 ) \
SYSCALL_ENTRY( 0x017d, NtUserSetProcessDpiAwarenessContext, 8 ) \ SYSCALL_ENTRY( 0x017d, NtUserSetObjectInformation, 16 ) \
SYSCALL_ENTRY( 0x017e, NtUserSetProcessWindowStation, 4 ) \ SYSCALL_ENTRY( 0x017e, NtUserSetParent, 8 ) \
SYSCALL_ENTRY( 0x017f, NtUserSetProp, 12 ) \ SYSCALL_ENTRY( 0x017f, NtUserSetProcessDpiAwarenessContext, 8 ) \
SYSCALL_ENTRY( 0x0180, NtUserSetScrollInfo, 16 ) \ SYSCALL_ENTRY( 0x0180, NtUserSetProcessWindowStation, 4 ) \
SYSCALL_ENTRY( 0x0181, NtUserSetShellWindowEx, 8 ) \ SYSCALL_ENTRY( 0x0181, NtUserSetProp, 12 ) \
SYSCALL_ENTRY( 0x0182, NtUserSetSysColors, 12 ) \ SYSCALL_ENTRY( 0x0182, NtUserSetScrollInfo, 16 ) \
SYSCALL_ENTRY( 0x0183, NtUserSetSystemMenu, 8 ) \ SYSCALL_ENTRY( 0x0183, NtUserSetShellWindowEx, 8 ) \
SYSCALL_ENTRY( 0x0184, NtUserSetSystemTimer, 12 ) \ SYSCALL_ENTRY( 0x0184, NtUserSetSysColors, 12 ) \
SYSCALL_ENTRY( 0x0185, NtUserSetThreadDesktop, 4 ) \ SYSCALL_ENTRY( 0x0185, NtUserSetSystemMenu, 8 ) \
SYSCALL_ENTRY( 0x0186, NtUserSetTimer, 20 ) \ SYSCALL_ENTRY( 0x0186, NtUserSetSystemTimer, 12 ) \
SYSCALL_ENTRY( 0x0187, NtUserSetWinEventHook, 32 ) \ SYSCALL_ENTRY( 0x0187, NtUserSetThreadDesktop, 4 ) \
SYSCALL_ENTRY( 0x0188, NtUserSetWindowLong, 16 ) \ SYSCALL_ENTRY( 0x0188, NtUserSetTimer, 20 ) \
SYSCALL_ENTRY( 0x0189, NtUserSetWindowLongPtr, 16 ) \ SYSCALL_ENTRY( 0x0189, NtUserSetWinEventHook, 32 ) \
SYSCALL_ENTRY( 0x018a, NtUserSetWindowPlacement, 8 ) \ SYSCALL_ENTRY( 0x018a, NtUserSetWindowLong, 16 ) \
SYSCALL_ENTRY( 0x018b, NtUserSetWindowPos, 28 ) \ SYSCALL_ENTRY( 0x018b, NtUserSetWindowLongPtr, 16 ) \
SYSCALL_ENTRY( 0x018c, NtUserSetWindowRgn, 12 ) \ SYSCALL_ENTRY( 0x018c, NtUserSetWindowPlacement, 8 ) \
SYSCALL_ENTRY( 0x018d, NtUserSetWindowWord, 12 ) \ SYSCALL_ENTRY( 0x018d, NtUserSetWindowPos, 28 ) \
SYSCALL_ENTRY( 0x018e, NtUserSetWindowsHookEx, 24 ) \ SYSCALL_ENTRY( 0x018e, NtUserSetWindowRgn, 12 ) \
SYSCALL_ENTRY( 0x018f, NtUserShowCaret, 4 ) \ SYSCALL_ENTRY( 0x018f, NtUserSetWindowWord, 12 ) \
SYSCALL_ENTRY( 0x0190, NtUserShowCursor, 4 ) \ SYSCALL_ENTRY( 0x0190, NtUserSetWindowsHookEx, 24 ) \
SYSCALL_ENTRY( 0x0191, NtUserShowScrollBar, 12 ) \ SYSCALL_ENTRY( 0x0191, NtUserShowCaret, 4 ) \
SYSCALL_ENTRY( 0x0192, NtUserShowWindow, 8 ) \ SYSCALL_ENTRY( 0x0192, NtUserShowCursor, 4 ) \
SYSCALL_ENTRY( 0x0193, NtUserShowWindowAsync, 8 ) \ SYSCALL_ENTRY( 0x0193, NtUserShowScrollBar, 12 ) \
SYSCALL_ENTRY( 0x0194, NtUserSwitchDesktop, 4 ) \ SYSCALL_ENTRY( 0x0194, NtUserShowWindow, 8 ) \
SYSCALL_ENTRY( 0x0195, NtUserSystemParametersInfo, 16 ) \ SYSCALL_ENTRY( 0x0195, NtUserShowWindowAsync, 8 ) \
SYSCALL_ENTRY( 0x0196, NtUserSystemParametersInfoForDpi, 20 ) \ SYSCALL_ENTRY( 0x0196, NtUserSwitchDesktop, 4 ) \
SYSCALL_ENTRY( 0x0197, NtUserThunkedMenuInfo, 8 ) \ SYSCALL_ENTRY( 0x0197, NtUserSystemParametersInfo, 16 ) \
SYSCALL_ENTRY( 0x0198, NtUserThunkedMenuItemInfo, 24 ) \ SYSCALL_ENTRY( 0x0198, NtUserSystemParametersInfoForDpi, 20 ) \
SYSCALL_ENTRY( 0x0199, NtUserToUnicodeEx, 28 ) \ SYSCALL_ENTRY( 0x0199, NtUserThunkedMenuInfo, 8 ) \
SYSCALL_ENTRY( 0x019a, NtUserTrackMouseEvent, 4 ) \ SYSCALL_ENTRY( 0x019a, NtUserThunkedMenuItemInfo, 24 ) \
SYSCALL_ENTRY( 0x019b, NtUserTrackPopupMenuEx, 24 ) \ SYSCALL_ENTRY( 0x019b, NtUserToUnicodeEx, 28 ) \
SYSCALL_ENTRY( 0x019c, NtUserTranslateAccelerator, 12 ) \ SYSCALL_ENTRY( 0x019c, NtUserTrackMouseEvent, 4 ) \
SYSCALL_ENTRY( 0x019d, NtUserTranslateMessage, 8 ) \ SYSCALL_ENTRY( 0x019d, NtUserTrackPopupMenuEx, 24 ) \
SYSCALL_ENTRY( 0x019e, NtUserUnhookWinEvent, 4 ) \ SYSCALL_ENTRY( 0x019e, NtUserTranslateAccelerator, 12 ) \
SYSCALL_ENTRY( 0x019f, NtUserUnhookWindowsHookEx, 4 ) \ SYSCALL_ENTRY( 0x019f, NtUserTranslateMessage, 8 ) \
SYSCALL_ENTRY( 0x01a0, NtUserUnregisterClass, 12 ) \ SYSCALL_ENTRY( 0x01a0, NtUserUnhookWinEvent, 4 ) \
SYSCALL_ENTRY( 0x01a1, NtUserUnregisterHotKey, 8 ) \ SYSCALL_ENTRY( 0x01a1, NtUserUnhookWindowsHookEx, 4 ) \
SYSCALL_ENTRY( 0x01a2, NtUserUpdateInputContext, 12 ) \ SYSCALL_ENTRY( 0x01a2, NtUserUnregisterClass, 12 ) \
SYSCALL_ENTRY( 0x01a3, NtUserUpdateLayeredWindow, 40 ) \ SYSCALL_ENTRY( 0x01a3, NtUserUnregisterHotKey, 8 ) \
SYSCALL_ENTRY( 0x01a4, NtUserValidateRect, 8 ) \ SYSCALL_ENTRY( 0x01a4, NtUserUpdateInputContext, 12 ) \
SYSCALL_ENTRY( 0x01a5, NtUserVkKeyScanEx, 8 ) \ SYSCALL_ENTRY( 0x01a5, NtUserUpdateLayeredWindow, 40 ) \
SYSCALL_ENTRY( 0x01a6, NtUserWaitForInputIdle, 12 ) \ SYSCALL_ENTRY( 0x01a6, NtUserValidateRect, 8 ) \
SYSCALL_ENTRY( 0x01a7, NtUserWaitMessage, 0 ) \ SYSCALL_ENTRY( 0x01a7, NtUserVkKeyScanEx, 8 ) \
SYSCALL_ENTRY( 0x01a8, NtUserWindowFromDC, 4 ) \ SYSCALL_ENTRY( 0x01a8, NtUserWaitForInputIdle, 12 ) \
SYSCALL_ENTRY( 0x01a9, NtUserWindowFromPoint, 8 ) \ SYSCALL_ENTRY( 0x01a9, NtUserWaitMessage, 0 ) \
SYSCALL_ENTRY( 0x01aa, __wine_get_file_outline_text_metric, 16 ) \ SYSCALL_ENTRY( 0x01aa, NtUserWindowFromDC, 4 ) \
SYSCALL_ENTRY( 0x01ab, __wine_get_icm_profile, 16 ) SYSCALL_ENTRY( 0x01ab, NtUserWindowFromPoint, 8 ) \
SYSCALL_ENTRY( 0x01ac, __wine_get_file_outline_text_metric, 16 ) \
SYSCALL_ENTRY( 0x01ad, __wine_get_icm_profile, 16 )
#define ALL_SYSCALLS64 \ #define ALL_SYSCALLS64 \
SYSCALL_ENTRY( 0x0000, NtGdiAbortDoc, 8 ) \ SYSCALL_ENTRY( 0x0000, NtGdiAbortDoc, 8 ) \
@ -636,226 +638,228 @@
SYSCALL_ENTRY( 0x00ca, NtUserBeginPaint, 16 ) \ SYSCALL_ENTRY( 0x00ca, NtUserBeginPaint, 16 ) \
SYSCALL_ENTRY( 0x00cb, NtUserBuildHimcList, 32 ) \ SYSCALL_ENTRY( 0x00cb, NtUserBuildHimcList, 32 ) \
SYSCALL_ENTRY( 0x00cc, NtUserBuildHwndList, 64 ) \ SYSCALL_ENTRY( 0x00cc, NtUserBuildHwndList, 64 ) \
SYSCALL_ENTRY( 0x00cd, NtUserCallHwnd, 16 ) \ SYSCALL_ENTRY( 0x00cd, NtUserBuildNameList, 32 ) \
SYSCALL_ENTRY( 0x00ce, NtUserCallHwndParam, 24 ) \ SYSCALL_ENTRY( 0x00ce, NtUserBuildPropList, 32 ) \
SYSCALL_ENTRY( 0x00cf, NtUserCallMsgFilter, 16 ) \ SYSCALL_ENTRY( 0x00cf, NtUserCallHwnd, 16 ) \
SYSCALL_ENTRY( 0x00d0, NtUserCallNextHookEx, 32 ) \ SYSCALL_ENTRY( 0x00d0, NtUserCallHwndParam, 24 ) \
SYSCALL_ENTRY( 0x00d1, NtUserCallNoParam, 8 ) \ SYSCALL_ENTRY( 0x00d1, NtUserCallMsgFilter, 16 ) \
SYSCALL_ENTRY( 0x00d2, NtUserCallOneParam, 16 ) \ SYSCALL_ENTRY( 0x00d2, NtUserCallNextHookEx, 32 ) \
SYSCALL_ENTRY( 0x00d3, NtUserCallTwoParam, 24 ) \ SYSCALL_ENTRY( 0x00d3, NtUserCallNoParam, 8 ) \
SYSCALL_ENTRY( 0x00d4, NtUserChangeClipboardChain, 16 ) \ SYSCALL_ENTRY( 0x00d4, NtUserCallOneParam, 16 ) \
SYSCALL_ENTRY( 0x00d5, NtUserChangeDisplaySettings, 40 ) \ SYSCALL_ENTRY( 0x00d5, NtUserCallTwoParam, 24 ) \
SYSCALL_ENTRY( 0x00d6, NtUserCheckMenuItem, 24 ) \ SYSCALL_ENTRY( 0x00d6, NtUserChangeClipboardChain, 16 ) \
SYSCALL_ENTRY( 0x00d7, NtUserChildWindowFromPointEx, 32 ) \ SYSCALL_ENTRY( 0x00d7, NtUserChangeDisplaySettings, 40 ) \
SYSCALL_ENTRY( 0x00d8, NtUserClipCursor, 8 ) \ SYSCALL_ENTRY( 0x00d8, NtUserCheckMenuItem, 24 ) \
SYSCALL_ENTRY( 0x00d9, NtUserCloseClipboard, 0 ) \ SYSCALL_ENTRY( 0x00d9, NtUserChildWindowFromPointEx, 32 ) \
SYSCALL_ENTRY( 0x00da, NtUserCloseDesktop, 8 ) \ SYSCALL_ENTRY( 0x00da, NtUserClipCursor, 8 ) \
SYSCALL_ENTRY( 0x00db, NtUserCloseWindowStation, 8 ) \ SYSCALL_ENTRY( 0x00db, NtUserCloseClipboard, 0 ) \
SYSCALL_ENTRY( 0x00dc, NtUserCopyAcceleratorTable, 24 ) \ SYSCALL_ENTRY( 0x00dc, NtUserCloseDesktop, 8 ) \
SYSCALL_ENTRY( 0x00dd, NtUserCountClipboardFormats, 0 ) \ SYSCALL_ENTRY( 0x00dd, NtUserCloseWindowStation, 8 ) \
SYSCALL_ENTRY( 0x00de, NtUserCreateAcceleratorTable, 16 ) \ SYSCALL_ENTRY( 0x00de, NtUserCopyAcceleratorTable, 24 ) \
SYSCALL_ENTRY( 0x00df, NtUserCreateCaret, 32 ) \ SYSCALL_ENTRY( 0x00df, NtUserCountClipboardFormats, 0 ) \
SYSCALL_ENTRY( 0x00e0, NtUserCreateDesktopEx, 48 ) \ SYSCALL_ENTRY( 0x00e0, NtUserCreateAcceleratorTable, 16 ) \
SYSCALL_ENTRY( 0x00e1, NtUserCreateInputContext, 8 ) \ SYSCALL_ENTRY( 0x00e1, NtUserCreateCaret, 32 ) \
SYSCALL_ENTRY( 0x00e2, NtUserCreateWindowEx, 136 ) \ SYSCALL_ENTRY( 0x00e2, NtUserCreateDesktopEx, 48 ) \
SYSCALL_ENTRY( 0x00e3, NtUserCreateWindowStation, 56 ) \ SYSCALL_ENTRY( 0x00e3, NtUserCreateInputContext, 8 ) \
SYSCALL_ENTRY( 0x00e4, NtUserDeferWindowPosAndBand, 80 ) \ SYSCALL_ENTRY( 0x00e4, NtUserCreateWindowEx, 136 ) \
SYSCALL_ENTRY( 0x00e5, NtUserDeleteMenu, 24 ) \ SYSCALL_ENTRY( 0x00e5, NtUserCreateWindowStation, 56 ) \
SYSCALL_ENTRY( 0x00e6, NtUserDestroyAcceleratorTable, 8 ) \ SYSCALL_ENTRY( 0x00e6, NtUserDeferWindowPosAndBand, 80 ) \
SYSCALL_ENTRY( 0x00e7, NtUserDestroyCursor, 16 ) \ SYSCALL_ENTRY( 0x00e7, NtUserDeleteMenu, 24 ) \
SYSCALL_ENTRY( 0x00e8, NtUserDestroyInputContext, 8 ) \ SYSCALL_ENTRY( 0x00e8, NtUserDestroyAcceleratorTable, 8 ) \
SYSCALL_ENTRY( 0x00e9, NtUserDestroyMenu, 8 ) \ SYSCALL_ENTRY( 0x00e9, NtUserDestroyCursor, 16 ) \
SYSCALL_ENTRY( 0x00ea, NtUserDestroyWindow, 8 ) \ SYSCALL_ENTRY( 0x00ea, NtUserDestroyInputContext, 8 ) \
SYSCALL_ENTRY( 0x00eb, NtUserDisableThreadIme, 8 ) \ SYSCALL_ENTRY( 0x00eb, NtUserDestroyMenu, 8 ) \
SYSCALL_ENTRY( 0x00ec, NtUserDispatchMessage, 8 ) \ SYSCALL_ENTRY( 0x00ec, NtUserDestroyWindow, 8 ) \
SYSCALL_ENTRY( 0x00ed, NtUserDisplayConfigGetDeviceInfo, 8 ) \ SYSCALL_ENTRY( 0x00ed, NtUserDisableThreadIme, 8 ) \
SYSCALL_ENTRY( 0x00ee, NtUserDragDetect, 24 ) \ SYSCALL_ENTRY( 0x00ee, NtUserDispatchMessage, 8 ) \
SYSCALL_ENTRY( 0x00ef, NtUserDragObject, 40 ) \ SYSCALL_ENTRY( 0x00ef, NtUserDisplayConfigGetDeviceInfo, 8 ) \
SYSCALL_ENTRY( 0x00f0, NtUserDrawCaptionTemp, 56 ) \ SYSCALL_ENTRY( 0x00f0, NtUserDragDetect, 24 ) \
SYSCALL_ENTRY( 0x00f1, NtUserDrawIconEx, 72 ) \ SYSCALL_ENTRY( 0x00f1, NtUserDragObject, 40 ) \
SYSCALL_ENTRY( 0x00f2, NtUserDrawMenuBarTemp, 40 ) \ SYSCALL_ENTRY( 0x00f2, NtUserDrawCaptionTemp, 56 ) \
SYSCALL_ENTRY( 0x00f3, NtUserEmptyClipboard, 0 ) \ SYSCALL_ENTRY( 0x00f3, NtUserDrawIconEx, 72 ) \
SYSCALL_ENTRY( 0x00f4, NtUserEnableMenuItem, 24 ) \ SYSCALL_ENTRY( 0x00f4, NtUserDrawMenuBarTemp, 40 ) \
SYSCALL_ENTRY( 0x00f5, NtUserEnableMouseInPointer, 8 ) \ SYSCALL_ENTRY( 0x00f5, NtUserEmptyClipboard, 0 ) \
SYSCALL_ENTRY( 0x00f6, NtUserEnableMouseInPointerForThread, 0 ) \ SYSCALL_ENTRY( 0x00f6, NtUserEnableMenuItem, 24 ) \
SYSCALL_ENTRY( 0x00f7, NtUserEnableScrollBar, 24 ) \ SYSCALL_ENTRY( 0x00f7, NtUserEnableMouseInPointer, 8 ) \
SYSCALL_ENTRY( 0x00f8, NtUserEndDeferWindowPosEx, 16 ) \ SYSCALL_ENTRY( 0x00f8, NtUserEnableMouseInPointerForThread, 0 ) \
SYSCALL_ENTRY( 0x00f9, NtUserEndMenu, 0 ) \ SYSCALL_ENTRY( 0x00f9, NtUserEnableScrollBar, 24 ) \
SYSCALL_ENTRY( 0x00fa, NtUserEndPaint, 16 ) \ SYSCALL_ENTRY( 0x00fa, NtUserEndDeferWindowPosEx, 16 ) \
SYSCALL_ENTRY( 0x00fb, NtUserEnumDisplayDevices, 32 ) \ SYSCALL_ENTRY( 0x00fb, NtUserEndMenu, 0 ) \
SYSCALL_ENTRY( 0x00fc, NtUserEnumDisplayMonitors, 32 ) \ SYSCALL_ENTRY( 0x00fc, NtUserEndPaint, 16 ) \
SYSCALL_ENTRY( 0x00fd, NtUserEnumDisplaySettings, 32 ) \ SYSCALL_ENTRY( 0x00fd, NtUserEnumDisplayDevices, 32 ) \
SYSCALL_ENTRY( 0x00fe, NtUserExcludeUpdateRgn, 16 ) \ SYSCALL_ENTRY( 0x00fe, NtUserEnumDisplayMonitors, 32 ) \
SYSCALL_ENTRY( 0x00ff, NtUserFindExistingCursorIcon, 24 ) \ SYSCALL_ENTRY( 0x00ff, NtUserEnumDisplaySettings, 32 ) \
SYSCALL_ENTRY( 0x0100, NtUserFindWindowEx, 40 ) \ SYSCALL_ENTRY( 0x0100, NtUserExcludeUpdateRgn, 16 ) \
SYSCALL_ENTRY( 0x0101, NtUserFlashWindowEx, 8 ) \ SYSCALL_ENTRY( 0x0101, NtUserFindExistingCursorIcon, 24 ) \
SYSCALL_ENTRY( 0x0102, NtUserGetAncestor, 16 ) \ SYSCALL_ENTRY( 0x0102, NtUserFindWindowEx, 40 ) \
SYSCALL_ENTRY( 0x0103, NtUserGetAsyncKeyState, 8 ) \ SYSCALL_ENTRY( 0x0103, NtUserFlashWindowEx, 8 ) \
SYSCALL_ENTRY( 0x0104, NtUserGetAtomName, 16 ) \ SYSCALL_ENTRY( 0x0104, NtUserGetAncestor, 16 ) \
SYSCALL_ENTRY( 0x0105, NtUserGetCaretBlinkTime, 0 ) \ SYSCALL_ENTRY( 0x0105, NtUserGetAsyncKeyState, 8 ) \
SYSCALL_ENTRY( 0x0106, NtUserGetCaretPos, 8 ) \ SYSCALL_ENTRY( 0x0106, NtUserGetAtomName, 16 ) \
SYSCALL_ENTRY( 0x0107, NtUserGetClassInfoEx, 40 ) \ SYSCALL_ENTRY( 0x0107, NtUserGetCaretBlinkTime, 0 ) \
SYSCALL_ENTRY( 0x0108, NtUserGetClassName, 24 ) \ SYSCALL_ENTRY( 0x0108, NtUserGetCaretPos, 8 ) \
SYSCALL_ENTRY( 0x0109, NtUserGetClipboardData, 16 ) \ SYSCALL_ENTRY( 0x0109, NtUserGetClassInfoEx, 40 ) \
SYSCALL_ENTRY( 0x010a, NtUserGetClipboardFormatName, 24 ) \ SYSCALL_ENTRY( 0x010a, NtUserGetClassName, 24 ) \
SYSCALL_ENTRY( 0x010b, NtUserGetClipboardOwner, 0 ) \ SYSCALL_ENTRY( 0x010b, NtUserGetClipboardData, 16 ) \
SYSCALL_ENTRY( 0x010c, NtUserGetClipboardSequenceNumber, 0 ) \ SYSCALL_ENTRY( 0x010c, NtUserGetClipboardFormatName, 24 ) \
SYSCALL_ENTRY( 0x010d, NtUserGetClipboardViewer, 0 ) \ SYSCALL_ENTRY( 0x010d, NtUserGetClipboardOwner, 0 ) \
SYSCALL_ENTRY( 0x010e, NtUserGetCursor, 0 ) \ SYSCALL_ENTRY( 0x010e, NtUserGetClipboardSequenceNumber, 0 ) \
SYSCALL_ENTRY( 0x010f, NtUserGetCursorFrameInfo, 32 ) \ SYSCALL_ENTRY( 0x010f, NtUserGetClipboardViewer, 0 ) \
SYSCALL_ENTRY( 0x0110, NtUserGetCursorInfo, 8 ) \ SYSCALL_ENTRY( 0x0110, NtUserGetCursor, 0 ) \
SYSCALL_ENTRY( 0x0111, NtUserGetDC, 8 ) \ SYSCALL_ENTRY( 0x0111, NtUserGetCursorFrameInfo, 32 ) \
SYSCALL_ENTRY( 0x0112, NtUserGetDCEx, 24 ) \ SYSCALL_ENTRY( 0x0112, NtUserGetCursorInfo, 8 ) \
SYSCALL_ENTRY( 0x0113, NtUserGetDisplayConfigBufferSizes, 24 ) \ SYSCALL_ENTRY( 0x0113, NtUserGetDC, 8 ) \
SYSCALL_ENTRY( 0x0114, NtUserGetDoubleClickTime, 0 ) \ SYSCALL_ENTRY( 0x0114, NtUserGetDCEx, 24 ) \
SYSCALL_ENTRY( 0x0115, NtUserGetDpiForMonitor, 32 ) \ SYSCALL_ENTRY( 0x0115, NtUserGetDisplayConfigBufferSizes, 24 ) \
SYSCALL_ENTRY( 0x0116, NtUserGetForegroundWindow, 0 ) \ SYSCALL_ENTRY( 0x0116, NtUserGetDoubleClickTime, 0 ) \
SYSCALL_ENTRY( 0x0117, NtUserGetGUIThreadInfo, 16 ) \ SYSCALL_ENTRY( 0x0117, NtUserGetDpiForMonitor, 32 ) \
SYSCALL_ENTRY( 0x0118, NtUserGetIconInfo, 48 ) \ SYSCALL_ENTRY( 0x0118, NtUserGetForegroundWindow, 0 ) \
SYSCALL_ENTRY( 0x0119, NtUserGetIconSize, 32 ) \ SYSCALL_ENTRY( 0x0119, NtUserGetGUIThreadInfo, 16 ) \
SYSCALL_ENTRY( 0x011a, NtUserGetInternalWindowPos, 24 ) \ SYSCALL_ENTRY( 0x011a, NtUserGetIconInfo, 48 ) \
SYSCALL_ENTRY( 0x011b, NtUserGetKeyNameText, 24 ) \ SYSCALL_ENTRY( 0x011b, NtUserGetIconSize, 32 ) \
SYSCALL_ENTRY( 0x011c, NtUserGetKeyState, 8 ) \ SYSCALL_ENTRY( 0x011c, NtUserGetInternalWindowPos, 24 ) \
SYSCALL_ENTRY( 0x011d, NtUserGetKeyboardLayout, 8 ) \ SYSCALL_ENTRY( 0x011d, NtUserGetKeyNameText, 24 ) \
SYSCALL_ENTRY( 0x011e, NtUserGetKeyboardLayoutList, 16 ) \ SYSCALL_ENTRY( 0x011e, NtUserGetKeyState, 8 ) \
SYSCALL_ENTRY( 0x011f, NtUserGetKeyboardLayoutName, 8 ) \ SYSCALL_ENTRY( 0x011f, NtUserGetKeyboardLayout, 8 ) \
SYSCALL_ENTRY( 0x0120, NtUserGetKeyboardState, 8 ) \ SYSCALL_ENTRY( 0x0120, NtUserGetKeyboardLayoutList, 16 ) \
SYSCALL_ENTRY( 0x0121, NtUserGetLayeredWindowAttributes, 32 ) \ SYSCALL_ENTRY( 0x0121, NtUserGetKeyboardLayoutName, 8 ) \
SYSCALL_ENTRY( 0x0122, NtUserGetMenuBarInfo, 32 ) \ SYSCALL_ENTRY( 0x0122, NtUserGetKeyboardState, 8 ) \
SYSCALL_ENTRY( 0x0123, NtUserGetMenuItemRect, 32 ) \ SYSCALL_ENTRY( 0x0123, NtUserGetLayeredWindowAttributes, 32 ) \
SYSCALL_ENTRY( 0x0124, NtUserGetMessage, 32 ) \ SYSCALL_ENTRY( 0x0124, NtUserGetMenuBarInfo, 32 ) \
SYSCALL_ENTRY( 0x0125, NtUserGetMouseMovePointsEx, 40 ) \ SYSCALL_ENTRY( 0x0125, NtUserGetMenuItemRect, 32 ) \
SYSCALL_ENTRY( 0x0126, NtUserGetObjectInformation, 40 ) \ SYSCALL_ENTRY( 0x0126, NtUserGetMessage, 32 ) \
SYSCALL_ENTRY( 0x0127, NtUserGetOpenClipboardWindow, 0 ) \ SYSCALL_ENTRY( 0x0127, NtUserGetMouseMovePointsEx, 40 ) \
SYSCALL_ENTRY( 0x0128, NtUserGetPointerInfoList, 64 ) \ SYSCALL_ENTRY( 0x0128, NtUserGetObjectInformation, 40 ) \
SYSCALL_ENTRY( 0x0129, NtUserGetPriorityClipboardFormat, 16 ) \ SYSCALL_ENTRY( 0x0129, NtUserGetOpenClipboardWindow, 0 ) \
SYSCALL_ENTRY( 0x012a, NtUserGetProcessDpiAwarenessContext, 8 ) \ SYSCALL_ENTRY( 0x012a, NtUserGetPointerInfoList, 64 ) \
SYSCALL_ENTRY( 0x012b, NtUserGetProcessWindowStation, 0 ) \ SYSCALL_ENTRY( 0x012b, NtUserGetPriorityClipboardFormat, 16 ) \
SYSCALL_ENTRY( 0x012c, NtUserGetProp, 16 ) \ SYSCALL_ENTRY( 0x012c, NtUserGetProcessDpiAwarenessContext, 8 ) \
SYSCALL_ENTRY( 0x012d, NtUserGetQueueStatus, 8 ) \ SYSCALL_ENTRY( 0x012d, NtUserGetProcessWindowStation, 0 ) \
SYSCALL_ENTRY( 0x012e, NtUserGetRawInputBuffer, 24 ) \ SYSCALL_ENTRY( 0x012e, NtUserGetProp, 16 ) \
SYSCALL_ENTRY( 0x012f, NtUserGetRawInputData, 40 ) \ SYSCALL_ENTRY( 0x012f, NtUserGetQueueStatus, 8 ) \
SYSCALL_ENTRY( 0x0130, NtUserGetRawInputDeviceInfo, 32 ) \ SYSCALL_ENTRY( 0x0130, NtUserGetRawInputBuffer, 24 ) \
SYSCALL_ENTRY( 0x0131, NtUserGetRawInputDeviceList, 24 ) \ SYSCALL_ENTRY( 0x0131, NtUserGetRawInputData, 40 ) \
SYSCALL_ENTRY( 0x0132, NtUserGetRegisteredRawInputDevices, 24 ) \ SYSCALL_ENTRY( 0x0132, NtUserGetRawInputDeviceInfo, 32 ) \
SYSCALL_ENTRY( 0x0133, NtUserGetScrollBarInfo, 24 ) \ SYSCALL_ENTRY( 0x0133, NtUserGetRawInputDeviceList, 24 ) \
SYSCALL_ENTRY( 0x0134, NtUserGetSystemDpiForProcess, 8 ) \ SYSCALL_ENTRY( 0x0134, NtUserGetRegisteredRawInputDevices, 24 ) \
SYSCALL_ENTRY( 0x0135, NtUserGetSystemMenu, 16 ) \ SYSCALL_ENTRY( 0x0135, NtUserGetScrollBarInfo, 24 ) \
SYSCALL_ENTRY( 0x0136, NtUserGetThreadDesktop, 8 ) \ SYSCALL_ENTRY( 0x0136, NtUserGetSystemDpiForProcess, 8 ) \
SYSCALL_ENTRY( 0x0137, NtUserGetTitleBarInfo, 16 ) \ SYSCALL_ENTRY( 0x0137, NtUserGetSystemMenu, 16 ) \
SYSCALL_ENTRY( 0x0138, NtUserGetUpdateRect, 24 ) \ SYSCALL_ENTRY( 0x0138, NtUserGetThreadDesktop, 8 ) \
SYSCALL_ENTRY( 0x0139, NtUserGetUpdateRgn, 24 ) \ SYSCALL_ENTRY( 0x0139, NtUserGetTitleBarInfo, 16 ) \
SYSCALL_ENTRY( 0x013a, NtUserGetUpdatedClipboardFormats, 24 ) \ SYSCALL_ENTRY( 0x013a, NtUserGetUpdateRect, 24 ) \
SYSCALL_ENTRY( 0x013b, NtUserGetWindowDC, 8 ) \ SYSCALL_ENTRY( 0x013b, NtUserGetUpdateRgn, 24 ) \
SYSCALL_ENTRY( 0x013c, NtUserGetWindowPlacement, 16 ) \ SYSCALL_ENTRY( 0x013c, NtUserGetUpdatedClipboardFormats, 24 ) \
SYSCALL_ENTRY( 0x013d, NtUserGetWindowRgnEx, 24 ) \ SYSCALL_ENTRY( 0x013d, NtUserGetWindowDC, 8 ) \
SYSCALL_ENTRY( 0x013e, NtUserHideCaret, 8 ) \ SYSCALL_ENTRY( 0x013e, NtUserGetWindowPlacement, 16 ) \
SYSCALL_ENTRY( 0x013f, NtUserHiliteMenuItem, 32 ) \ SYSCALL_ENTRY( 0x013f, NtUserGetWindowRgnEx, 24 ) \
SYSCALL_ENTRY( 0x0140, NtUserInitializeClientPfnArrays, 32 ) \ SYSCALL_ENTRY( 0x0140, NtUserHideCaret, 8 ) \
SYSCALL_ENTRY( 0x0141, NtUserInternalGetWindowIcon, 16 ) \ SYSCALL_ENTRY( 0x0141, NtUserHiliteMenuItem, 32 ) \
SYSCALL_ENTRY( 0x0142, NtUserInternalGetWindowText, 24 ) \ SYSCALL_ENTRY( 0x0142, NtUserInitializeClientPfnArrays, 32 ) \
SYSCALL_ENTRY( 0x0143, NtUserInvalidateRect, 24 ) \ SYSCALL_ENTRY( 0x0143, NtUserInternalGetWindowIcon, 16 ) \
SYSCALL_ENTRY( 0x0144, NtUserInvalidateRgn, 24 ) \ SYSCALL_ENTRY( 0x0144, NtUserInternalGetWindowText, 24 ) \
SYSCALL_ENTRY( 0x0145, NtUserIsClipboardFormatAvailable, 8 ) \ SYSCALL_ENTRY( 0x0145, NtUserInvalidateRect, 24 ) \
SYSCALL_ENTRY( 0x0146, NtUserIsMouseInPointerEnabled, 0 ) \ SYSCALL_ENTRY( 0x0146, NtUserInvalidateRgn, 24 ) \
SYSCALL_ENTRY( 0x0147, NtUserKillTimer, 16 ) \ SYSCALL_ENTRY( 0x0147, NtUserIsClipboardFormatAvailable, 8 ) \
SYSCALL_ENTRY( 0x0148, NtUserLockWindowUpdate, 8 ) \ SYSCALL_ENTRY( 0x0148, NtUserIsMouseInPointerEnabled, 0 ) \
SYSCALL_ENTRY( 0x0149, NtUserLogicalToPerMonitorDPIPhysicalPoint, 16 ) \ SYSCALL_ENTRY( 0x0149, NtUserKillTimer, 16 ) \
SYSCALL_ENTRY( 0x014a, NtUserMapVirtualKeyEx, 24 ) \ SYSCALL_ENTRY( 0x014a, NtUserLockWindowUpdate, 8 ) \
SYSCALL_ENTRY( 0x014b, NtUserMenuItemFromPoint, 32 ) \ SYSCALL_ENTRY( 0x014b, NtUserLogicalToPerMonitorDPIPhysicalPoint, 16 ) \
SYSCALL_ENTRY( 0x014c, NtUserMessageCall, 56 ) \ SYSCALL_ENTRY( 0x014c, NtUserMapVirtualKeyEx, 24 ) \
SYSCALL_ENTRY( 0x014d, NtUserMoveWindow, 48 ) \ SYSCALL_ENTRY( 0x014d, NtUserMenuItemFromPoint, 32 ) \
SYSCALL_ENTRY( 0x014e, NtUserMsgWaitForMultipleObjectsEx, 40 ) \ SYSCALL_ENTRY( 0x014e, NtUserMessageCall, 56 ) \
SYSCALL_ENTRY( 0x014f, NtUserNotifyIMEStatus, 16 ) \ SYSCALL_ENTRY( 0x014f, NtUserMoveWindow, 48 ) \
SYSCALL_ENTRY( 0x0150, NtUserNotifyWinEvent, 32 ) \ SYSCALL_ENTRY( 0x0150, NtUserMsgWaitForMultipleObjectsEx, 40 ) \
SYSCALL_ENTRY( 0x0151, NtUserOpenClipboard, 16 ) \ SYSCALL_ENTRY( 0x0151, NtUserNotifyIMEStatus, 16 ) \
SYSCALL_ENTRY( 0x0152, NtUserOpenDesktop, 24 ) \ SYSCALL_ENTRY( 0x0152, NtUserNotifyWinEvent, 32 ) \
SYSCALL_ENTRY( 0x0153, NtUserOpenInputDesktop, 24 ) \ SYSCALL_ENTRY( 0x0153, NtUserOpenClipboard, 16 ) \
SYSCALL_ENTRY( 0x0154, NtUserOpenWindowStation, 16 ) \ SYSCALL_ENTRY( 0x0154, NtUserOpenDesktop, 24 ) \
SYSCALL_ENTRY( 0x0155, NtUserPeekMessage, 40 ) \ SYSCALL_ENTRY( 0x0155, NtUserOpenInputDesktop, 24 ) \
SYSCALL_ENTRY( 0x0156, NtUserPerMonitorDPIPhysicalToLogicalPoint, 16 ) \ SYSCALL_ENTRY( 0x0156, NtUserOpenWindowStation, 16 ) \
SYSCALL_ENTRY( 0x0157, NtUserPostMessage, 32 ) \ SYSCALL_ENTRY( 0x0157, NtUserPeekMessage, 40 ) \
SYSCALL_ENTRY( 0x0158, NtUserPostThreadMessage, 32 ) \ SYSCALL_ENTRY( 0x0158, NtUserPerMonitorDPIPhysicalToLogicalPoint, 16 ) \
SYSCALL_ENTRY( 0x0159, NtUserPrintWindow, 24 ) \ SYSCALL_ENTRY( 0x0159, NtUserPostMessage, 32 ) \
SYSCALL_ENTRY( 0x015a, NtUserQueryDisplayConfig, 48 ) \ SYSCALL_ENTRY( 0x015a, NtUserPostThreadMessage, 32 ) \
SYSCALL_ENTRY( 0x015b, NtUserQueryInputContext, 16 ) \ SYSCALL_ENTRY( 0x015b, NtUserPrintWindow, 24 ) \
SYSCALL_ENTRY( 0x015c, NtUserRealChildWindowFromPoint, 24 ) \ SYSCALL_ENTRY( 0x015c, NtUserQueryDisplayConfig, 48 ) \
SYSCALL_ENTRY( 0x015d, NtUserRedrawWindow, 32 ) \ SYSCALL_ENTRY( 0x015d, NtUserQueryInputContext, 16 ) \
SYSCALL_ENTRY( 0x015e, NtUserRegisterClassExWOW, 56 ) \ SYSCALL_ENTRY( 0x015e, NtUserRealChildWindowFromPoint, 24 ) \
SYSCALL_ENTRY( 0x015f, NtUserRegisterHotKey, 32 ) \ SYSCALL_ENTRY( 0x015f, NtUserRedrawWindow, 32 ) \
SYSCALL_ENTRY( 0x0160, NtUserRegisterRawInputDevices, 24 ) \ SYSCALL_ENTRY( 0x0160, NtUserRegisterClassExWOW, 56 ) \
SYSCALL_ENTRY( 0x0161, NtUserRegisterTouchPadCapable, 8 ) \ SYSCALL_ENTRY( 0x0161, NtUserRegisterHotKey, 32 ) \
SYSCALL_ENTRY( 0x0162, NtUserReleaseDC, 16 ) \ SYSCALL_ENTRY( 0x0162, NtUserRegisterRawInputDevices, 24 ) \
SYSCALL_ENTRY( 0x0163, NtUserRemoveClipboardFormatListener, 8 ) \ SYSCALL_ENTRY( 0x0163, NtUserRegisterTouchPadCapable, 8 ) \
SYSCALL_ENTRY( 0x0164, NtUserRemoveMenu, 24 ) \ SYSCALL_ENTRY( 0x0164, NtUserReleaseDC, 16 ) \
SYSCALL_ENTRY( 0x0165, NtUserRemoveProp, 16 ) \ SYSCALL_ENTRY( 0x0165, NtUserRemoveClipboardFormatListener, 8 ) \
SYSCALL_ENTRY( 0x0166, NtUserScrollDC, 56 ) \ SYSCALL_ENTRY( 0x0166, NtUserRemoveMenu, 24 ) \
SYSCALL_ENTRY( 0x0167, NtUserScrollWindowEx, 64 ) \ SYSCALL_ENTRY( 0x0167, NtUserRemoveProp, 16 ) \
SYSCALL_ENTRY( 0x0168, NtUserSelectPalette, 24 ) \ SYSCALL_ENTRY( 0x0168, NtUserScrollDC, 56 ) \
SYSCALL_ENTRY( 0x0169, NtUserSendInput, 24 ) \ SYSCALL_ENTRY( 0x0169, NtUserScrollWindowEx, 64 ) \
SYSCALL_ENTRY( 0x016a, NtUserSetActiveWindow, 8 ) \ SYSCALL_ENTRY( 0x016a, NtUserSelectPalette, 24 ) \
SYSCALL_ENTRY( 0x016b, NtUserSetCapture, 8 ) \ SYSCALL_ENTRY( 0x016b, NtUserSendInput, 24 ) \
SYSCALL_ENTRY( 0x016c, NtUserSetClassLong, 32 ) \ SYSCALL_ENTRY( 0x016c, NtUserSetActiveWindow, 8 ) \
SYSCALL_ENTRY( 0x016d, NtUserSetClassLongPtr, 32 ) \ SYSCALL_ENTRY( 0x016d, NtUserSetCapture, 8 ) \
SYSCALL_ENTRY( 0x016e, NtUserSetClassWord, 24 ) \ SYSCALL_ENTRY( 0x016e, NtUserSetClassLong, 32 ) \
SYSCALL_ENTRY( 0x016f, NtUserSetClipboardData, 24 ) \ SYSCALL_ENTRY( 0x016f, NtUserSetClassLongPtr, 32 ) \
SYSCALL_ENTRY( 0x0170, NtUserSetClipboardViewer, 8 ) \ SYSCALL_ENTRY( 0x0170, NtUserSetClassWord, 24 ) \
SYSCALL_ENTRY( 0x0171, NtUserSetCursor, 8 ) \ SYSCALL_ENTRY( 0x0171, NtUserSetClipboardData, 24 ) \
SYSCALL_ENTRY( 0x0172, NtUserSetCursorIconData, 32 ) \ SYSCALL_ENTRY( 0x0172, NtUserSetClipboardViewer, 8 ) \
SYSCALL_ENTRY( 0x0173, NtUserSetCursorPos, 16 ) \ SYSCALL_ENTRY( 0x0173, NtUserSetCursor, 8 ) \
SYSCALL_ENTRY( 0x0174, NtUserSetFocus, 8 ) \ SYSCALL_ENTRY( 0x0174, NtUserSetCursorIconData, 32 ) \
SYSCALL_ENTRY( 0x0175, NtUserSetInternalWindowPos, 32 ) \ SYSCALL_ENTRY( 0x0175, NtUserSetCursorPos, 16 ) \
SYSCALL_ENTRY( 0x0176, NtUserSetKeyboardState, 8 ) \ SYSCALL_ENTRY( 0x0176, NtUserSetFocus, 8 ) \
SYSCALL_ENTRY( 0x0177, NtUserSetLayeredWindowAttributes, 32 ) \ SYSCALL_ENTRY( 0x0177, NtUserSetInternalWindowPos, 32 ) \
SYSCALL_ENTRY( 0x0178, NtUserSetMenu, 16 ) \ SYSCALL_ENTRY( 0x0178, NtUserSetKeyboardState, 8 ) \
SYSCALL_ENTRY( 0x0179, NtUserSetMenuContextHelpId, 16 ) \ SYSCALL_ENTRY( 0x0179, NtUserSetLayeredWindowAttributes, 32 ) \
SYSCALL_ENTRY( 0x017a, NtUserSetMenuDefaultItem, 24 ) \ SYSCALL_ENTRY( 0x017a, NtUserSetMenu, 16 ) \
SYSCALL_ENTRY( 0x017b, NtUserSetObjectInformation, 32 ) \ SYSCALL_ENTRY( 0x017b, NtUserSetMenuContextHelpId, 16 ) \
SYSCALL_ENTRY( 0x017c, NtUserSetParent, 16 ) \ SYSCALL_ENTRY( 0x017c, NtUserSetMenuDefaultItem, 24 ) \
SYSCALL_ENTRY( 0x017d, NtUserSetProcessDpiAwarenessContext, 16 ) \ SYSCALL_ENTRY( 0x017d, NtUserSetObjectInformation, 32 ) \
SYSCALL_ENTRY( 0x017e, NtUserSetProcessWindowStation, 8 ) \ SYSCALL_ENTRY( 0x017e, NtUserSetParent, 16 ) \
SYSCALL_ENTRY( 0x017f, NtUserSetProp, 24 ) \ SYSCALL_ENTRY( 0x017f, NtUserSetProcessDpiAwarenessContext, 16 ) \
SYSCALL_ENTRY( 0x0180, NtUserSetScrollInfo, 32 ) \ SYSCALL_ENTRY( 0x0180, NtUserSetProcessWindowStation, 8 ) \
SYSCALL_ENTRY( 0x0181, NtUserSetShellWindowEx, 16 ) \ SYSCALL_ENTRY( 0x0181, NtUserSetProp, 24 ) \
SYSCALL_ENTRY( 0x0182, NtUserSetSysColors, 24 ) \ SYSCALL_ENTRY( 0x0182, NtUserSetScrollInfo, 32 ) \
SYSCALL_ENTRY( 0x0183, NtUserSetSystemMenu, 16 ) \ SYSCALL_ENTRY( 0x0183, NtUserSetShellWindowEx, 16 ) \
SYSCALL_ENTRY( 0x0184, NtUserSetSystemTimer, 24 ) \ SYSCALL_ENTRY( 0x0184, NtUserSetSysColors, 24 ) \
SYSCALL_ENTRY( 0x0185, NtUserSetThreadDesktop, 8 ) \ SYSCALL_ENTRY( 0x0185, NtUserSetSystemMenu, 16 ) \
SYSCALL_ENTRY( 0x0186, NtUserSetTimer, 40 ) \ SYSCALL_ENTRY( 0x0186, NtUserSetSystemTimer, 24 ) \
SYSCALL_ENTRY( 0x0187, NtUserSetWinEventHook, 64 ) \ SYSCALL_ENTRY( 0x0187, NtUserSetThreadDesktop, 8 ) \
SYSCALL_ENTRY( 0x0188, NtUserSetWindowLong, 32 ) \ SYSCALL_ENTRY( 0x0188, NtUserSetTimer, 40 ) \
SYSCALL_ENTRY( 0x0189, NtUserSetWindowLongPtr, 32 ) \ SYSCALL_ENTRY( 0x0189, NtUserSetWinEventHook, 64 ) \
SYSCALL_ENTRY( 0x018a, NtUserSetWindowPlacement, 16 ) \ SYSCALL_ENTRY( 0x018a, NtUserSetWindowLong, 32 ) \
SYSCALL_ENTRY( 0x018b, NtUserSetWindowPos, 56 ) \ SYSCALL_ENTRY( 0x018b, NtUserSetWindowLongPtr, 32 ) \
SYSCALL_ENTRY( 0x018c, NtUserSetWindowRgn, 24 ) \ SYSCALL_ENTRY( 0x018c, NtUserSetWindowPlacement, 16 ) \
SYSCALL_ENTRY( 0x018d, NtUserSetWindowWord, 24 ) \ SYSCALL_ENTRY( 0x018d, NtUserSetWindowPos, 56 ) \
SYSCALL_ENTRY( 0x018e, NtUserSetWindowsHookEx, 48 ) \ SYSCALL_ENTRY( 0x018e, NtUserSetWindowRgn, 24 ) \
SYSCALL_ENTRY( 0x018f, NtUserShowCaret, 8 ) \ SYSCALL_ENTRY( 0x018f, NtUserSetWindowWord, 24 ) \
SYSCALL_ENTRY( 0x0190, NtUserShowCursor, 8 ) \ SYSCALL_ENTRY( 0x0190, NtUserSetWindowsHookEx, 48 ) \
SYSCALL_ENTRY( 0x0191, NtUserShowScrollBar, 24 ) \ SYSCALL_ENTRY( 0x0191, NtUserShowCaret, 8 ) \
SYSCALL_ENTRY( 0x0192, NtUserShowWindow, 16 ) \ SYSCALL_ENTRY( 0x0192, NtUserShowCursor, 8 ) \
SYSCALL_ENTRY( 0x0193, NtUserShowWindowAsync, 16 ) \ SYSCALL_ENTRY( 0x0193, NtUserShowScrollBar, 24 ) \
SYSCALL_ENTRY( 0x0194, NtUserSwitchDesktop, 8 ) \ SYSCALL_ENTRY( 0x0194, NtUserShowWindow, 16 ) \
SYSCALL_ENTRY( 0x0195, NtUserSystemParametersInfo, 32 ) \ SYSCALL_ENTRY( 0x0195, NtUserShowWindowAsync, 16 ) \
SYSCALL_ENTRY( 0x0196, NtUserSystemParametersInfoForDpi, 40 ) \ SYSCALL_ENTRY( 0x0196, NtUserSwitchDesktop, 8 ) \
SYSCALL_ENTRY( 0x0197, NtUserThunkedMenuInfo, 16 ) \ SYSCALL_ENTRY( 0x0197, NtUserSystemParametersInfo, 32 ) \
SYSCALL_ENTRY( 0x0198, NtUserThunkedMenuItemInfo, 48 ) \ SYSCALL_ENTRY( 0x0198, NtUserSystemParametersInfoForDpi, 40 ) \
SYSCALL_ENTRY( 0x0199, NtUserToUnicodeEx, 56 ) \ SYSCALL_ENTRY( 0x0199, NtUserThunkedMenuInfo, 16 ) \
SYSCALL_ENTRY( 0x019a, NtUserTrackMouseEvent, 8 ) \ SYSCALL_ENTRY( 0x019a, NtUserThunkedMenuItemInfo, 48 ) \
SYSCALL_ENTRY( 0x019b, NtUserTrackPopupMenuEx, 48 ) \ SYSCALL_ENTRY( 0x019b, NtUserToUnicodeEx, 56 ) \
SYSCALL_ENTRY( 0x019c, NtUserTranslateAccelerator, 24 ) \ SYSCALL_ENTRY( 0x019c, NtUserTrackMouseEvent, 8 ) \
SYSCALL_ENTRY( 0x019d, NtUserTranslateMessage, 16 ) \ SYSCALL_ENTRY( 0x019d, NtUserTrackPopupMenuEx, 48 ) \
SYSCALL_ENTRY( 0x019e, NtUserUnhookWinEvent, 8 ) \ SYSCALL_ENTRY( 0x019e, NtUserTranslateAccelerator, 24 ) \
SYSCALL_ENTRY( 0x019f, NtUserUnhookWindowsHookEx, 8 ) \ SYSCALL_ENTRY( 0x019f, NtUserTranslateMessage, 16 ) \
SYSCALL_ENTRY( 0x01a0, NtUserUnregisterClass, 24 ) \ SYSCALL_ENTRY( 0x01a0, NtUserUnhookWinEvent, 8 ) \
SYSCALL_ENTRY( 0x01a1, NtUserUnregisterHotKey, 16 ) \ SYSCALL_ENTRY( 0x01a1, NtUserUnhookWindowsHookEx, 8 ) \
SYSCALL_ENTRY( 0x01a2, NtUserUpdateInputContext, 24 ) \ SYSCALL_ENTRY( 0x01a2, NtUserUnregisterClass, 24 ) \
SYSCALL_ENTRY( 0x01a3, NtUserUpdateLayeredWindow, 80 ) \ SYSCALL_ENTRY( 0x01a3, NtUserUnregisterHotKey, 16 ) \
SYSCALL_ENTRY( 0x01a4, NtUserValidateRect, 16 ) \ SYSCALL_ENTRY( 0x01a4, NtUserUpdateInputContext, 24 ) \
SYSCALL_ENTRY( 0x01a5, NtUserVkKeyScanEx, 16 ) \ SYSCALL_ENTRY( 0x01a5, NtUserUpdateLayeredWindow, 80 ) \
SYSCALL_ENTRY( 0x01a6, NtUserWaitForInputIdle, 24 ) \ SYSCALL_ENTRY( 0x01a6, NtUserValidateRect, 16 ) \
SYSCALL_ENTRY( 0x01a7, NtUserWaitMessage, 0 ) \ SYSCALL_ENTRY( 0x01a7, NtUserVkKeyScanEx, 16 ) \
SYSCALL_ENTRY( 0x01a8, NtUserWindowFromDC, 8 ) \ SYSCALL_ENTRY( 0x01a8, NtUserWaitForInputIdle, 24 ) \
SYSCALL_ENTRY( 0x01a9, NtUserWindowFromPoint, 16 ) \ SYSCALL_ENTRY( 0x01a9, NtUserWaitMessage, 0 ) \
SYSCALL_ENTRY( 0x01aa, __wine_get_file_outline_text_metric, 32 ) \ SYSCALL_ENTRY( 0x01aa, NtUserWindowFromDC, 8 ) \
SYSCALL_ENTRY( 0x01ab, __wine_get_icm_profile, 32 ) SYSCALL_ENTRY( 0x01ab, NtUserWindowFromPoint, 16 ) \
SYSCALL_ENTRY( 0x01ac, __wine_get_file_outline_text_metric, 32 ) \
SYSCALL_ENTRY( 0x01ad, __wine_get_icm_profile, 32 )

View file

@ -813,8 +813,8 @@
@ stub NtUserBroadcastThemeChangeEvent @ stub NtUserBroadcastThemeChangeEvent
@ stdcall -syscall NtUserBuildHimcList(long long ptr ptr) @ stdcall -syscall NtUserBuildHimcList(long long ptr ptr)
@ stdcall -syscall NtUserBuildHwndList(long long long long long long ptr ptr) @ stdcall -syscall NtUserBuildHwndList(long long long long long long ptr ptr)
@ stub NtUserBuildNameList @ stdcall -syscall NtUserBuildNameList(long long ptr ptr)
@ stub NtUserBuildPropList @ stdcall -syscall NtUserBuildPropList(long long ptr ptr)
@ stub NtUserCalcMenuBar @ stub NtUserCalcMenuBar
@ stub NtUserCalculatePopupWindowPosition @ stub NtUserCalculatePopupWindowPosition
@ stdcall -syscall NtUserCallHwnd(long long) @ stdcall -syscall NtUserCallHwnd(long long)

View file

@ -132,6 +132,7 @@ extern void track_mouse_menu_bar( HWND hwnd, INT ht, int x, int y );
/* message.c */ /* message.c */
extern BOOL kill_system_timer( HWND hwnd, UINT_PTR id ); extern BOOL kill_system_timer( HWND hwnd, UINT_PTR id );
extern BOOL reply_message_result( LRESULT result ); extern BOOL reply_message_result( LRESULT result );
extern BOOL post_quit_message( int exit_code );
extern NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARAM lparam ); extern NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARAM lparam );
extern LRESULT send_internal_message_timeout( DWORD dest_pid, DWORD dest_tid, UINT msg, WPARAM wparam, extern LRESULT send_internal_message_timeout( DWORD dest_pid, DWORD dest_tid, UINT msg, WPARAM wparam,
LPARAM lparam, UINT flags, UINT timeout, LPARAM lparam, UINT flags, UINT timeout,

View file

@ -1561,6 +1561,43 @@ HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str )
return (HANDLE)ret; return (HANDLE)ret;
} }
/***********************************************************************
* NtUserBuildPropList (win32u.@)
*/
NTSTATUS WINAPI NtUserBuildPropList( HWND hwnd, ULONG count, struct ntuser_property_list *buffer, ULONG *ret_count )
{
property_data_t *data;
ULONG i;
NTSTATUS status;
if (!buffer || !ret_count) return STATUS_INVALID_PARAMETER;
if (!(data = malloc( count * sizeof(*data) ))) return STATUS_NO_MEMORY;
SERVER_START_REQ( get_window_properties )
{
req->window = wine_server_user_handle( hwnd );
wine_server_set_reply( req, data, count * sizeof(*data) );
if (!(status = wine_server_call( req )))
{
for (i = 0; i < wine_server_reply_size(reply) / sizeof(*data); i++)
{
buffer[i].data = data[i].data;
buffer[i].atom = data[i].atom;
buffer[i].string = data[i].string;
}
*ret_count = reply->total;
if (reply->total > count) status = STATUS_BUFFER_TOO_SMALL;
}
}
SERVER_END_REQ;
free( data );
return status;
}
static void mirror_rect( const RECT *window_rect, RECT *rect ) static void mirror_rect( const RECT *window_rect, RECT *rect )
{ {
int width = window_rect->right - window_rect->left; int width = window_rect->right - window_rect->left;

View file

@ -602,6 +602,43 @@ BOOL WINAPI NtUserSwitchDesktop( HDESK desktop )
return TRUE; return TRUE;
} }
/******************************************************************************
* NtUserBuildNameList (win32u.@)
*/
NTSTATUS WINAPI NtUserBuildNameList( HWINSTA handle, ULONG size, struct ntuser_name_list *list,
ULONG *ret_size )
{
const ULONG header_size = offsetof( struct ntuser_name_list, strings[1] ); /* header + final null */
WCHAR *buffer;
NTSTATUS status;
ULONG count, result, total;
if (size <= header_size) return STATUS_INVALID_HANDLE;
if (!(buffer = malloc( size - header_size ))) return STATUS_NO_MEMORY;
SERVER_START_REQ( enum_winstation )
{
req->handle = wine_server_obj_handle( handle );
wine_server_set_reply( req, buffer, size - header_size );
status = wine_server_call( req );
result = wine_server_reply_size( reply );
total = reply->total;
count = reply->count;
}
SERVER_END_REQ;
if (!status || status == STATUS_BUFFER_TOO_SMALL)
{
list->size = header_size + result;
list->count = count;
memcpy( list->strings, buffer, result );
list->strings[result / sizeof(WCHAR)] = 0;
*ret_size = header_size + total;
}
return status;
}
/*********************************************************************** /***********************************************************************
* NtUserGetObjectInformation (win32u.@) * NtUserGetObjectInformation (win32u.@)
*/ */

View file

@ -275,10 +275,11 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
.serialnumber = {'0','0','0','0',0}, .serialnumber = {'0','0','0','0',0},
}; };
struct iohid_device *impl; struct iohid_device *impl;
USAGE_AND_PAGE usages;
CFStringRef str; CFStringRef str;
desc.usages.UsagePage = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDPrimaryUsagePageKey))); usages.UsagePage = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDPrimaryUsagePageKey)));
desc.usages.Usage = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDPrimaryUsageKey))); usages.Usage = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDPrimaryUsageKey)));
desc.vid = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDVendorIDKey))); desc.vid = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDVendorIDKey)));
desc.pid = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDProductIDKey))); desc.pid = CFNumberToDWORD(IOHIDDeviceGetProperty(IOHIDDevice, CFSTR(kIOHIDProductIDKey)));
@ -289,8 +290,8 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
desc.is_bluetooth = !CFStringCompare(str, CFSTR(kIOHIDTransportBluetoothValue), 0) || desc.is_bluetooth = !CFStringCompare(str, CFSTR(kIOHIDTransportBluetoothValue), 0) ||
!CFStringCompare(str, CFSTR(kIOHIDTransportBluetoothLowEnergyValue), 0); !CFStringCompare(str, CFSTR(kIOHIDTransportBluetoothLowEnergyValue), 0);
if (desc.usages.UsagePage != HID_USAGE_PAGE_GENERIC || if (usages.UsagePage != HID_USAGE_PAGE_GENERIC ||
!(desc.usages.Usage == HID_USAGE_GENERIC_JOYSTICK || desc.usages.Usage == HID_USAGE_GENERIC_GAMEPAD)) !(usages.Usage == HID_USAGE_GENERIC_JOYSTICK || usages.Usage == HID_USAGE_GENERIC_GAMEPAD))
{ {
/* winebus isn't currently meant to handle anything but these, and /* winebus isn't currently meant to handle anything but these, and
* opening keyboards, mice, or the Touch Bar on older MacBooks triggers * opening keyboards, mice, or the Touch Bar on older MacBooks triggers

View file

@ -198,7 +198,7 @@ static void set_hat_value(struct unix_device *iface, int index, int value)
hid_device_set_hatswitch_y(iface, index, y); hid_device_set_hatswitch_y(iface, index, y);
} }
static BOOL descriptor_add_haptic(struct sdl_device *impl) static BOOL descriptor_add_haptic(struct sdl_device *impl, BOOL force)
{ {
USHORT i, count = 0; USHORT i, count = 0;
USAGE usages[16]; USAGE usages[16];
@ -227,16 +227,16 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl)
if ((impl->effect_support & EFFECT_SUPPORT_PHYSICAL)) if ((impl->effect_support & EFFECT_SUPPORT_PHYSICAL))
{ {
/* SDL_HAPTIC_SQUARE doesn't exist */ /* SDL_HAPTIC_SQUARE doesn't exist */
if (impl->effect_support & SDL_HAPTIC_SINE) usages[count++] = PID_USAGE_ET_SINE; if (force || (impl->effect_support & SDL_HAPTIC_SINE)) usages[count++] = PID_USAGE_ET_SINE;
if (impl->effect_support & SDL_HAPTIC_TRIANGLE) usages[count++] = PID_USAGE_ET_TRIANGLE; if (force || (impl->effect_support & SDL_HAPTIC_TRIANGLE)) usages[count++] = PID_USAGE_ET_TRIANGLE;
if (impl->effect_support & SDL_HAPTIC_SAWTOOTHUP) usages[count++] = PID_USAGE_ET_SAWTOOTH_UP; if (force || (impl->effect_support & SDL_HAPTIC_SAWTOOTHUP)) usages[count++] = PID_USAGE_ET_SAWTOOTH_UP;
if (impl->effect_support & SDL_HAPTIC_SAWTOOTHDOWN) usages[count++] = PID_USAGE_ET_SAWTOOTH_DOWN; if (force || (impl->effect_support & SDL_HAPTIC_SAWTOOTHDOWN)) usages[count++] = PID_USAGE_ET_SAWTOOTH_DOWN;
if (impl->effect_support & SDL_HAPTIC_SPRING) usages[count++] = PID_USAGE_ET_SPRING; if (force || (impl->effect_support & SDL_HAPTIC_SPRING)) usages[count++] = PID_USAGE_ET_SPRING;
if (impl->effect_support & SDL_HAPTIC_DAMPER) usages[count++] = PID_USAGE_ET_DAMPER; if (force || (impl->effect_support & SDL_HAPTIC_DAMPER)) usages[count++] = PID_USAGE_ET_DAMPER;
if (impl->effect_support & SDL_HAPTIC_INERTIA) usages[count++] = PID_USAGE_ET_INERTIA; if (force || (impl->effect_support & SDL_HAPTIC_INERTIA)) usages[count++] = PID_USAGE_ET_INERTIA;
if (impl->effect_support & SDL_HAPTIC_FRICTION) usages[count++] = PID_USAGE_ET_FRICTION; if (force || (impl->effect_support & SDL_HAPTIC_FRICTION)) usages[count++] = PID_USAGE_ET_FRICTION;
if (impl->effect_support & SDL_HAPTIC_CONSTANT) usages[count++] = PID_USAGE_ET_CONSTANT_FORCE; if (force || (impl->effect_support & SDL_HAPTIC_CONSTANT)) usages[count++] = PID_USAGE_ET_CONSTANT_FORCE;
if (impl->effect_support & SDL_HAPTIC_RAMP) usages[count++] = PID_USAGE_ET_RAMP; if (force || (impl->effect_support & SDL_HAPTIC_RAMP)) usages[count++] = PID_USAGE_ET_RAMP;
if (!hid_device_add_physical(&impl->unix_device, usages, count)) if (!hid_device_add_physical(&impl->unix_device, usages, count))
return FALSE; return FALSE;
@ -360,7 +360,7 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface)
if (!hid_device_end_input_report(iface)) if (!hid_device_end_input_report(iface))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
if (!descriptor_add_haptic(impl)) if (!descriptor_add_haptic(impl, physical_usage.Usage == HID_USAGE_SIMULATION_AUTOMOBILE_SIMULATION_DEVICE))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
if (!hid_device_end_report_descriptor(iface)) if (!hid_device_end_report_descriptor(iface))
@ -414,7 +414,7 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface)
if (!hid_device_end_input_report(iface)) if (!hid_device_end_input_report(iface))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
if (!descriptor_add_haptic(impl)) if (!descriptor_add_haptic(impl, FALSE))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
if (!hid_device_end_report_descriptor(iface)) if (!hid_device_end_report_descriptor(iface))
@ -443,17 +443,12 @@ static void sdl_device_destroy(struct unix_device *iface)
static NTSTATUS sdl_device_start(struct unix_device *iface) static NTSTATUS sdl_device_start(struct unix_device *iface)
{ {
struct sdl_device *impl = impl_from_unix_device(iface); struct sdl_device *impl = impl_from_unix_device(iface);
NTSTATUS status;
pthread_mutex_lock(&sdl_cs); pthread_mutex_lock(&sdl_cs);
impl->started = TRUE;
if (impl->sdl_controller) status = build_controller_report_descriptor(iface);
else status = build_joystick_report_descriptor(iface);
impl->started = !status;
pthread_mutex_unlock(&sdl_cs); pthread_mutex_unlock(&sdl_cs);
return status; return STATUS_SUCCESS;
} }
static void sdl_device_stop(struct unix_device *iface) static void sdl_device_stop(struct unix_device *iface)
@ -595,7 +590,7 @@ static NTSTATUS sdl_device_physical_effect_control(struct unix_device *iface, BY
TRACE("iface %p, index %u, control %04x, iterations %u.\n", iface, index, control, iterations); TRACE("iface %p, index %u, control %04x, iterations %u.\n", iface, index, control, iterations);
if (impl->effect_ids[index] < 0) return STATUS_UNSUCCESSFUL; if (id < 0) return STATUS_SUCCESS;
switch (control) switch (control)
{ {
@ -991,8 +986,6 @@ static void sdl_add_device(unsigned int index)
if (controller) if (controller)
{ {
desc.is_gamepad = TRUE; desc.is_gamepad = TRUE;
desc.usages.UsagePage = HID_USAGE_PAGE_GENERIC;
desc.usages.Usage = HID_USAGE_GENERIC_GAMEPAD;
axis_count = 6; axis_count = 6;
} }
else else
@ -1000,12 +993,12 @@ static void sdl_add_device(unsigned int index)
int button_count = pSDL_JoystickNumButtons(joystick); int button_count = pSDL_JoystickNumButtons(joystick);
axis_count = pSDL_JoystickNumAxes(joystick); axis_count = pSDL_JoystickNumAxes(joystick);
desc.is_gamepad = (axis_count == 6 && button_count >= 14); desc.is_gamepad = (axis_count == 6 && button_count >= 14);
desc.usages.UsagePage = HID_USAGE_PAGE_GENERIC;
desc.usages.Usage = HID_USAGE_GENERIC_JOYSTICK;
} }
for (axis_offset = 0; axis_offset < axis_count; axis_offset += (options.split_controllers ? 6 : axis_count)) for (axis_offset = 0; axis_offset < axis_count; axis_offset += (options.split_controllers ? 6 : axis_count))
{ {
NTSTATUS status;
if (!axis_offset) strcpy(buffer, product); if (!axis_offset) strcpy(buffer, product);
else snprintf(buffer, ARRAY_SIZE(buffer), "%s %d", product, axis_offset / 6); else snprintf(buffer, ARRAY_SIZE(buffer), "%s %d", product, axis_offset / 6);
ntdll_umbstowcs(buffer, strlen(buffer) + 1, desc.product, ARRAY_SIZE(desc.product)); ntdll_umbstowcs(buffer, strlen(buffer) + 1, desc.product, ARRAY_SIZE(desc.product));
@ -1019,6 +1012,15 @@ static void sdl_add_device(unsigned int index)
impl->id = id; impl->id = id;
impl->axis_offset = axis_offset; impl->axis_offset = axis_offset;
if (impl->sdl_controller) status = build_controller_report_descriptor(&impl->unix_device);
else status = build_joystick_report_descriptor(&impl->unix_device);
if (status)
{
list_remove(&impl->unix_device.entry);
impl->unix_device.vtbl->destroy(&impl->unix_device);
return;
}
bus_event_queue_device_created(&event_queue, &impl->unix_device, &desc); bus_event_queue_device_created(&event_queue, &impl->unix_device, &desc);
} }
} }

View file

@ -728,12 +728,6 @@ static void lnxev_device_destroy(struct unix_device *iface)
static NTSTATUS lnxev_device_start(struct unix_device *iface) static NTSTATUS lnxev_device_start(struct unix_device *iface)
{ {
struct lnxev_device *impl = lnxev_impl_from_unix_device(iface);
NTSTATUS status;
if ((status = build_report_descriptor(iface, impl->base.udev_device)))
return status;
pthread_mutex_lock(&udev_cs); pthread_mutex_lock(&udev_cs);
start_polling_device(iface); start_polling_device(iface);
pthread_mutex_unlock(&udev_cs); pthread_mutex_unlock(&udev_cs);
@ -1254,7 +1248,6 @@ static void udev_add_device(struct udev_device *dev, int fd)
#ifdef HAS_PROPER_INPUT_HEADER #ifdef HAS_PROPER_INPUT_HEADER
else if (!strcmp(subsystem, "input")) else if (!strcmp(subsystem, "input"))
{ {
const USAGE_AND_PAGE device_usage = *what_am_I(dev, fd);
static const WCHAR evdev[] = {'e','v','d','e','v',0}; static const WCHAR evdev[] = {'e','v','d','e','v',0};
struct input_id device_id = {0}; struct input_id device_id = {0};
char buffer[MAX_PATH]; char buffer[MAX_PATH];
@ -1275,8 +1268,6 @@ static void udev_add_device(struct udev_device *dev, int fd)
if (!desc.serialnumber[0] && ioctl(fd, EVIOCGUNIQ(sizeof(buffer)), buffer) >= 0) if (!desc.serialnumber[0] && ioctl(fd, EVIOCGUNIQ(sizeof(buffer)), buffer) >= 0)
ntdll_umbstowcs(buffer, strlen(buffer) + 1, desc.serialnumber, ARRAY_SIZE(desc.serialnumber)); ntdll_umbstowcs(buffer, strlen(buffer) + 1, desc.serialnumber, ARRAY_SIZE(desc.serialnumber));
desc.usages = device_usage;
} }
#endif #endif
@ -1321,6 +1312,13 @@ static void udev_add_device(struct udev_device *dev, int fd)
strcpy(impl->devnode, devnode); strcpy(impl->devnode, devnode);
impl->device_fd = fd; impl->device_fd = fd;
if (build_report_descriptor(&impl->unix_device, impl->udev_device))
{
list_remove(&impl->unix_device.entry);
impl->unix_device.vtbl->destroy(&impl->unix_device);
return;
}
bus_event_queue_device_created(&event_queue, &impl->unix_device, &desc); bus_event_queue_device_created(&event_queue, &impl->unix_device, &desc);
} }
#endif #endif

View file

@ -417,7 +417,7 @@ static DWORD check_bus_option(const WCHAR *option, DWORD default_value)
return default_value; return default_value;
} }
static BOOL is_hidraw_enabled(WORD vid, WORD pid, const USAGE_AND_PAGE *usages) static BOOL is_hidraw_enabled(WORD vid, WORD pid, const USAGE_AND_PAGE *usages, UINT buttons)
{ {
char buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[1024])]; char buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[1024])];
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
@ -436,6 +436,48 @@ static BOOL is_hidraw_enabled(WORD vid, WORD pid, const USAGE_AND_PAGE *usages)
if (is_dualshock4_gamepad(vid, pid)) prefer_hidraw = TRUE; if (is_dualshock4_gamepad(vid, pid)) prefer_hidraw = TRUE;
if (is_dualsense_gamepad(vid, pid)) prefer_hidraw = TRUE; if (is_dualsense_gamepad(vid, pid)) prefer_hidraw = TRUE;
switch (vid)
{
case 0x044f:
if (pid == 0xb679) prefer_hidraw = TRUE; /* ThrustMaster T-Rudder */
if (pid == 0xb687) prefer_hidraw = TRUE; /* ThrustMaster TWCS Throttle */
if (pid == 0xb10a) prefer_hidraw = TRUE; /* ThrustMaster T.16000M Joystick */
break;
case 0x16d0:
if (pid == 0x0d61) prefer_hidraw = TRUE; /* Simucube 2 Sport */
if (pid == 0x0d60) prefer_hidraw = TRUE; /* Simucube 2 Pro */
if (pid == 0x0d5f) prefer_hidraw = TRUE; /* Simucube 2 Ultimate */
if (pid == 0x0d5a) prefer_hidraw = TRUE; /* Simucube 1 */
break;
case 0x0eb7:
if (pid == 0x183b) prefer_hidraw = TRUE; /* Fanatec ClubSport Pedals v3 */
if (pid == 0x1839) prefer_hidraw = TRUE; /* Fanatec ClubSport Pedals v1/v2 */
break;
case 0x231d:
/* comes with 128 buttons in the default configuration */
if (buttons == 128) prefer_hidraw = TRUE;
/* if customized, less than 128 buttons may be shown, decide by PID */
if (pid == 0x0200) prefer_hidraw = TRUE; /* VKBsim Gladiator EVO Right Grip */
if (pid == 0x0201) prefer_hidraw = TRUE; /* VKBsim Gladiator EVO Left Grip */
if (pid == 0x0126) prefer_hidraw = TRUE; /* VKB-Sim Space Gunfighter */
if (pid == 0x0127) prefer_hidraw = TRUE; /* VKB-Sim Space Gunfighter L */
break;
case 0x3344:
/* comes with 31 buttons in the default configuration, or 128 max */
if ((buttons == 31) || (buttons == 128)) prefer_hidraw = TRUE;
/* users may have configured button limits, usually 32/50/64 */
if ((buttons == 32) || (buttons == 50) || (buttons == 64)) prefer_hidraw = TRUE;
/* if customized, arbitrary amount of buttons may be shown, decide by PID */
if (pid == 0x412f) prefer_hidraw = TRUE; /* Virpil Constellation ALPHA-R */
if (pid == 0x812c) prefer_hidraw = TRUE; /* Virpil Constellation ALPHA-L */
break;
case 0x03eb:
/* users may have configured button limits, usually 32/50/64 */
if ((buttons == 32) || (buttons == 50) || (buttons == 64)) prefer_hidraw = TRUE;
if (pid == 0x2055) prefer_hidraw = TRUE; /* ATMEL/VIRPIL/200325 VPC Throttle MT-50 CM2 */
break;
}
RtlInitUnicodeString(&str, L"EnableHidraw"); RtlInitUnicodeString(&str, L"EnableHidraw");
if (!NtQueryValueKey(driver_key, &str, KeyValuePartialInformation, info, if (!NtQueryValueKey(driver_key, &str, KeyValuePartialInformation, info,
sizeof(buffer) - sizeof(WCHAR), &size)) sizeof(buffer) - sizeof(WCHAR), &size))
@ -684,22 +726,41 @@ static NTSTATUS get_device_descriptors(UINT64 unix_device, BYTE **report_desc, U
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static USAGE_AND_PAGE get_hidraw_device_usages(UINT64 unix_device) static USAGE_AND_PAGE get_device_usages(UINT64 unix_device, UINT *buttons)
{ {
HIDP_DEVICE_DESC device_desc; HIDP_DEVICE_DESC device_desc;
USAGE_AND_PAGE usages = {0}; USAGE_AND_PAGE usages = {0};
UINT report_desc_length; UINT i, count = 0, report_desc_length;
HIDP_BUTTON_CAPS *button_caps;
BYTE *report_desc; BYTE *report_desc;
NTSTATUS status; NTSTATUS status;
HIDP_CAPS caps;
if (!(status = get_device_descriptors(unix_device, &report_desc, &report_desc_length, &device_desc))) if (!(status = get_device_descriptors(unix_device, &report_desc, &report_desc_length, &device_desc)))
{ {
PHIDP_PREPARSED_DATA preparsed = device_desc.CollectionDesc[0].PreparsedData;
usages.UsagePage = device_desc.CollectionDesc[0].UsagePage; usages.UsagePage = device_desc.CollectionDesc[0].UsagePage;
usages.Usage = device_desc.CollectionDesc[0].Usage; usages.Usage = device_desc.CollectionDesc[0].Usage;
if ((status = HidP_GetCaps(preparsed, &caps)) == HIDP_STATUS_SUCCESS &&
(button_caps = malloc(sizeof(*button_caps) * caps.NumberInputButtonCaps)))
{
status = HidP_GetButtonCaps(HidP_Input, button_caps, &caps.NumberInputButtonCaps, preparsed);
if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetButtonCaps returned %#lx\n", status);
else for (i = 0; i < caps.NumberInputButtonCaps; i++)
{
if (button_caps[i].UsagePage != HID_USAGE_PAGE_BUTTON) continue;
if (button_caps[i].IsRange) count = max(count, button_caps[i].Range.UsageMax);
else count = max(count, button_caps[i].NotRange.Usage);
}
free(button_caps);
}
HidP_FreeCollectionDescription(&device_desc); HidP_FreeCollectionDescription(&device_desc);
RtlFreeHeap(GetProcessHeap(), 0, report_desc); RtlFreeHeap(GetProcessHeap(), 0, report_desc);
} }
*buttons = count;
return usages; return usages;
} }
@ -749,18 +810,21 @@ static DWORD CALLBACK bus_main_thread(void *args)
case BUS_EVENT_TYPE_DEVICE_CREATED: case BUS_EVENT_TYPE_DEVICE_CREATED:
{ {
struct device_desc desc = event->device_created.desc; struct device_desc desc = event->device_created.desc;
if (desc.is_hidraw && !desc.usages.UsagePage) desc.usages = get_hidraw_device_usages(event->device); USAGE_AND_PAGE usages;
if (!desc.is_hidraw != !is_hidraw_enabled(desc.vid, desc.pid, &desc.usages)) UINT buttons;
usages = get_device_usages(event->device, &buttons);
if (!desc.is_hidraw != !is_hidraw_enabled(desc.vid, desc.pid, &usages, buttons))
{ {
struct device_remove_params params = {.device = event->device}; struct device_remove_params params = {.device = event->device};
WARN("ignoring %shidraw device %04x:%04x with usages %04x:%04x\n", desc.is_hidraw ? "" : "non-", WARN("ignoring %shidraw device %04x:%04x with usages %04x:%04x\n", desc.is_hidraw ? "" : "non-",
desc.vid, desc.pid, desc.usages.UsagePage, desc.usages.Usage); desc.vid, desc.pid, usages.UsagePage, usages.Usage);
winebus_call(device_remove, &params); winebus_call(device_remove, &params);
break; break;
} }
TRACE("creating %shidraw device %04x:%04x with usages %04x:%04x\n", desc.is_hidraw ? "" : "non-", TRACE("creating %shidraw device %04x:%04x with usages %04x:%04x\n", desc.is_hidraw ? "" : "non-",
desc.vid, desc.pid, desc.usages.UsagePage, desc.usages.Usage); desc.vid, desc.pid, usages.UsagePage, usages.Usage);
device = bus_create_hid_device(&event->device_created.desc, event->device); device = bus_create_hid_device(&event->device_created.desc, event->device);
if (device) IoInvalidateDeviceRelations(bus_pdo, BusRelations); if (device) IoInvalidateDeviceRelations(bus_pdo, BusRelations);

View file

@ -49,14 +49,6 @@ static void mouse_destroy(struct unix_device *iface)
static NTSTATUS mouse_start(struct unix_device *iface) static NTSTATUS mouse_start(struct unix_device *iface)
{ {
const USAGE_AND_PAGE device_usage = {.UsagePage = HID_USAGE_PAGE_GENERIC, .Usage = HID_USAGE_GENERIC_MOUSE};
if (!hid_device_begin_report_descriptor(iface, &device_usage))
return STATUS_NO_MEMORY;
if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, 3))
return STATUS_NO_MEMORY;
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -123,9 +115,21 @@ static const struct device_desc mouse_device_desc =
static NTSTATUS mouse_device_create(void *args) static NTSTATUS mouse_device_create(void *args)
{ {
const USAGE_AND_PAGE device_usage = {.UsagePage = HID_USAGE_PAGE_GENERIC, .Usage = HID_USAGE_GENERIC_MOUSE};
struct device_create_params *params = args; struct device_create_params *params = args;
struct unix_device *iface;
if (!(iface = hid_device_create(&mouse_vtbl, sizeof(struct mouse_device))))
return STATUS_NO_MEMORY;
if (!hid_device_begin_report_descriptor(iface, &device_usage))
return STATUS_NO_MEMORY;
if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, 3))
return STATUS_NO_MEMORY;
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
params->desc = mouse_device_desc; params->desc = mouse_device_desc;
params->device = (UINT_PTR)hid_device_create(&mouse_vtbl, sizeof(struct mouse_device)); params->device = (UINT_PTR)iface;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -140,14 +144,6 @@ static void keyboard_destroy(struct unix_device *iface)
static NTSTATUS keyboard_start(struct unix_device *iface) static NTSTATUS keyboard_start(struct unix_device *iface)
{ {
const USAGE_AND_PAGE device_usage = {.UsagePage = HID_USAGE_PAGE_GENERIC, .Usage = HID_USAGE_GENERIC_KEYBOARD};
if (!hid_device_begin_report_descriptor(iface, &device_usage))
return STATUS_NO_MEMORY;
if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_KEYBOARD, 0, 101))
return STATUS_NO_MEMORY;
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -214,9 +210,21 @@ static const struct device_desc keyboard_device_desc =
static NTSTATUS keyboard_device_create(void *args) static NTSTATUS keyboard_device_create(void *args)
{ {
const USAGE_AND_PAGE device_usage = {.UsagePage = HID_USAGE_PAGE_GENERIC, .Usage = HID_USAGE_GENERIC_KEYBOARD};
struct device_create_params *params = args; struct device_create_params *params = args;
struct unix_device *iface;
if (!(iface = hid_device_create(&keyboard_vtbl, sizeof(struct keyboard_device))))
return STATUS_NO_MEMORY;
if (!hid_device_begin_report_descriptor(iface, &device_usage))
return STATUS_NO_MEMORY;
if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_KEYBOARD, 0, 101))
return STATUS_NO_MEMORY;
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
params->desc = keyboard_device_desc; params->desc = keyboard_device_desc;
params->device = (UINT_PTR)hid_device_create(&keyboard_vtbl, sizeof(struct keyboard_device)); params->device = (UINT_PTR)iface;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -38,7 +38,6 @@ struct device_desc
UINT version; UINT version;
UINT input; UINT input;
UINT uid; UINT uid;
USAGE_AND_PAGE usages;
BOOL is_gamepad; BOOL is_gamepad;
BOOL is_hidraw; BOOL is_hidraw;
BOOL is_bluetooth; BOOL is_bluetooth;
@ -151,8 +150,8 @@ enum unix_funcs
static inline const char *debugstr_device_desc(struct device_desc *desc) static inline const char *debugstr_device_desc(struct device_desc *desc)
{ {
if (!desc) return "(null)"; if (!desc) return "(null)";
return wine_dbg_sprintf("{vid %04x, pid %04x, version %04x, input %d, uid %08x, usage %04x:%04x, is_gamepad %u, is_hidraw %u, is_bluetooth %u}", return wine_dbg_sprintf("{vid %04x, pid %04x, version %04x, input %d, uid %08x, is_gamepad %u, is_hidraw %u, is_bluetooth %u}",
desc->vid, desc->pid, desc->version, desc->input, desc->uid, desc->usages.UsagePage, desc->usages.Usage, desc->vid, desc->pid, desc->version, desc->input, desc->uid,
desc->is_gamepad, desc->is_hidraw, desc->is_bluetooth); desc->is_gamepad, desc->is_hidraw, desc->is_bluetooth);
} }

View file

@ -14,6 +14,7 @@ SOURCES = \
device.c \ device.c \
directx.c \ directx.c \
ffp_gl.c \ ffp_gl.c \
ffp_hlsl.c \
gl_compat.c \ gl_compat.c \
glsl_shader.c \ glsl_shader.c \
palette.c \ palette.c \

View file

@ -4928,6 +4928,7 @@ static void wined3d_adapter_gl_init_d3d_info(struct wined3d_adapter_gl *adapter_
d3d_info->feature_level = feature_level_from_caps(gl_info, &shader_caps, &d3d_info->ffp_fragment_caps); d3d_info->feature_level = feature_level_from_caps(gl_info, &shader_caps, &d3d_info->ffp_fragment_caps);
d3d_info->filling_convention_offset = gl_info->filling_convention_offset; d3d_info->filling_convention_offset = gl_info->filling_convention_offset;
d3d_info->persistent_map = !!gl_info->supported[ARB_BUFFER_STORAGE]; d3d_info->persistent_map = !!gl_info->supported[ARB_BUFFER_STORAGE];
d3d_info->ffp_hlsl = wined3d_settings.ffp_hlsl;
if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB; d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;

View file

@ -2359,6 +2359,7 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_
d3d_info->fences = true; d3d_info->fences = true;
d3d_info->persistent_map = true; d3d_info->persistent_map = true;
d3d_info->gpu_push_constants = true; d3d_info->gpu_push_constants = true;
d3d_info->ffp_hlsl = true;
/* Like GL, Vulkan doesn't explicitly specify a filling convention and only mandates that a /* Like GL, Vulkan doesn't explicitly specify a filling convention and only mandates that a
* shared edge of two adjacent triangles generate a fragment for exactly one of the triangles. * shared edge of two adjacent triangles generate a fragment for exactly one of the triangles.

View file

@ -54,7 +54,7 @@ void wined3d_context_cleanup(struct wined3d_context *context)
* A to avoid breaking caller code. */ * A to avoid breaking caller code. */
void context_restore(struct wined3d_context *context, struct wined3d_texture *texture, unsigned int sub_resource_idx) void context_restore(struct wined3d_context *context, struct wined3d_texture *texture, unsigned int sub_resource_idx)
{ {
if (context->current_rt.texture != texture || context->current_rt.sub_resource_idx != sub_resource_idx) if (texture && (context->current_rt.texture != texture || context->current_rt.sub_resource_idx != sub_resource_idx))
{ {
context_release(context); context_release(context);
context = context_acquire(texture->resource.device, texture, sub_resource_idx); context = context_acquire(texture->resource.device, texture, sub_resource_idx);
@ -161,8 +161,8 @@ void wined3d_stream_info_from_declaration(struct wined3d_stream_info *stream_inf
const struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info) const struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info)
{ {
/* We need to deal with frequency data! */ /* We need to deal with frequency data! */
BOOL use_vshader = use_vs(state) || (d3d_info->ffp_hlsl && state->shader[WINED3D_SHADER_TYPE_VERTEX]);
struct wined3d_vertex_declaration *declaration = state->vertex_declaration; struct wined3d_vertex_declaration *declaration = state->vertex_declaration;
BOOL use_vshader = use_vs(state);
unsigned int i; unsigned int i;
stream_info->use_map = 0; stream_info->use_map = 0;

View file

@ -1286,6 +1286,7 @@ static BOOL wined3d_context_gl_set_gl_context(struct wined3d_context_gl *context
return FALSE; return FALSE;
} }
wined3d_release_dc(context_gl->window, context_gl->dc);
if (!(context_gl->dc = wined3d_device_gl_get_backup_dc(device_gl))) if (!(context_gl->dc = wined3d_device_gl_get_backup_dc(device_gl)))
{ {
wined3d_context_gl_set_current(NULL); wined3d_context_gl_set_current(NULL);
@ -4355,7 +4356,6 @@ struct wined3d_context *wined3d_context_gl_acquire(const struct wined3d_device *
if (!texture) if (!texture)
{ {
if (current_context if (current_context
&& current_context->c.current_rt.texture
&& current_context->c.device == device) && current_context->c.device == device)
{ {
texture = current_context->c.current_rt.texture; texture = current_context->c.current_rt.texture;

View file

@ -2123,15 +2123,23 @@ static void wined3d_cs_exec_push_constants(struct wined3d_cs *cs, const void *da
{ {
const struct wined3d_cs_push_constants *op = data; const struct wined3d_cs_push_constants *op = data;
struct wined3d_device *device = cs->c.device; struct wined3d_device *device = cs->c.device;
unsigned int ffp_start_idx, ffp_end_idx;
unsigned int context_count, i; unsigned int context_count, i;
/* The constant buffers were already updated; this op is just to mark the /* The constant buffers were already updated; this op is just to mark the
* constants as invalid in the device state. */ * constants as invalid in the device state. */
ffp_start_idx = op->start_idx / sizeof(struct wined3d_vec4);
ffp_end_idx = (op->start_idx + op->count + sizeof(struct wined3d_vec4)) / sizeof(struct wined3d_vec4);
if (op->type == WINED3D_PUSH_CONSTANTS_VS_F) if (op->type == WINED3D_PUSH_CONSTANTS_VS_F)
device->shader_backend->shader_update_float_vertex_constants(device, op->start_idx, op->count); device->shader_backend->shader_update_float_vertex_constants(device, op->start_idx, op->count);
else if (op->type == WINED3D_PUSH_CONSTANTS_PS_F) else if (op->type == WINED3D_PUSH_CONSTANTS_PS_F)
device->shader_backend->shader_update_float_pixel_constants(device, op->start_idx, op->count); device->shader_backend->shader_update_float_pixel_constants(device, op->start_idx, op->count);
else if (op->type == WINED3D_PUSH_CONSTANTS_VS_FFP)
device->shader_backend->shader_update_float_vertex_constants(device, ffp_start_idx, ffp_end_idx - ffp_start_idx);
else if (op->type == WINED3D_PUSH_CONSTANTS_PS_FFP)
device->shader_backend->shader_update_float_pixel_constants(device, ffp_start_idx, ffp_end_idx - ffp_start_idx);
for (i = 0, context_count = device->context_count; i < context_count; ++i) for (i = 0, context_count = device->context_count; i < context_count; ++i)
device->contexts[i]->constant_update_mask |= op->update_mask; device->contexts[i]->constant_update_mask |= op->update_mask;

View file

@ -1667,6 +1667,22 @@ static void device_free_depth_stencil_state(struct wine_rb_entry *entry, void *c
wined3d_depth_stencil_state_decref(state); wined3d_depth_stencil_state_decref(state);
} }
static void device_free_ffp_vertex_shader(struct wine_rb_entry *entry, void *context)
{
struct wined3d_ffp_vs *vs = WINE_RB_ENTRY_VALUE(entry, struct wined3d_ffp_vs, entry);
wined3d_shader_decref(vs->shader);
free(vs);
}
static void device_free_ffp_pixel_shader(struct wine_rb_entry *entry, void *context)
{
struct wined3d_ffp_ps *ps = WINE_RB_ENTRY_VALUE(entry, struct wined3d_ffp_ps, entry);
wined3d_shader_decref(ps->shader);
free(ps);
}
void wined3d_device_uninit_3d(struct wined3d_device *device) void wined3d_device_uninit_3d(struct wined3d_device *device)
{ {
struct wined3d_state *state = device->cs->c.state; struct wined3d_state *state = device->cs->c.state;
@ -1714,6 +1730,8 @@ void wined3d_device_uninit_3d(struct wined3d_device *device)
wine_rb_destroy(&device->rasterizer_states, device_free_rasterizer_state, NULL); wine_rb_destroy(&device->rasterizer_states, device_free_rasterizer_state, NULL);
wine_rb_destroy(&device->blend_states, device_free_blend_state, NULL); wine_rb_destroy(&device->blend_states, device_free_blend_state, NULL);
wine_rb_destroy(&device->depth_stencil_states, device_free_depth_stencil_state, NULL); wine_rb_destroy(&device->depth_stencil_states, device_free_depth_stencil_state, NULL);
wine_rb_destroy(&device->ffp_vertex_shaders, device_free_ffp_vertex_shader, NULL);
wine_rb_destroy(&device->ffp_pixel_shaders, device_free_ffp_pixel_shader, NULL);
LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
{ {
@ -5515,6 +5533,8 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined
wine_rb_init(&device->rasterizer_states, wined3d_rasterizer_state_compare); wine_rb_init(&device->rasterizer_states, wined3d_rasterizer_state_compare);
wine_rb_init(&device->blend_states, wined3d_blend_state_compare); wine_rb_init(&device->blend_states, wined3d_blend_state_compare);
wine_rb_init(&device->depth_stencil_states, wined3d_depth_stencil_state_compare); wine_rb_init(&device->depth_stencil_states, wined3d_depth_stencil_state_compare);
wine_rb_init(&device->ffp_vertex_shaders, wined3d_ffp_vertex_program_key_compare);
wine_rb_init(&device->ffp_pixel_shaders, wined3d_ffp_frag_program_key_compare);
if (vertex_pipeline->vp_states && fragment_pipeline->states if (vertex_pipeline->vp_states && fragment_pipeline->states
&& FAILED(hr = compile_state_table(device->state_table, device->multistate_funcs, && FAILED(hr = compile_state_table(device->state_table, device->multistate_funcs,
@ -5527,6 +5547,8 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined
wine_rb_destroy(&device->blend_states, NULL, NULL); wine_rb_destroy(&device->blend_states, NULL, NULL);
wine_rb_destroy(&device->depth_stencil_states, NULL, NULL); wine_rb_destroy(&device->depth_stencil_states, NULL, NULL);
wine_rb_destroy(&device->so_descs, NULL, NULL); wine_rb_destroy(&device->so_descs, NULL, NULL);
wine_rb_destroy(&device->ffp_vertex_shaders, NULL, NULL);
wine_rb_destroy(&device->ffp_pixel_shaders, NULL, NULL);
wined3d_decref(device->wined3d); wined3d_decref(device->wined3d);
return hr; return hr;
} }
@ -5554,6 +5576,8 @@ err:
wine_rb_destroy(&device->blend_states, NULL, NULL); wine_rb_destroy(&device->blend_states, NULL, NULL);
wine_rb_destroy(&device->depth_stencil_states, NULL, NULL); wine_rb_destroy(&device->depth_stencil_states, NULL, NULL);
wine_rb_destroy(&device->so_descs, NULL, NULL); wine_rb_destroy(&device->so_descs, NULL, NULL);
wine_rb_destroy(&device->ffp_vertex_shaders, NULL, NULL);
wine_rb_destroy(&device->ffp_pixel_shaders, NULL, NULL);
wined3d_decref(device->wined3d); wined3d_decref(device->wined3d);
return hr; return hr;
} }

246
dlls/wined3d/ffp_hlsl.c Normal file
View file

@ -0,0 +1,246 @@
/*
* Fixed-function pipeline replacement implemented using HLSL shaders
*
* Copyright 2006 Jason Green
* Copyright 2006-2007 Henri Verbeet
* Copyright 2007-2009,2013 Stefan Dösinger for CodeWeavers
* Copyright 2009-2011 Henri Verbeet for CodeWeavers
* Copyright 2022,2024 Elizabeth Figura for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wined3d_private.h"
#include <vkd3d_shader.h>
WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
static bool ffp_hlsl_generate_vertex_shader(const struct wined3d_ffp_vs_settings *settings,
struct wined3d_string_buffer *buffer)
{
if (settings->lighting)
FIXME("Ignoring lighting.\n");
if (settings->point_size)
FIXME("Ignoring point size.\n");
if (settings->transformed)
FIXME("Ignoring pretransformed vertices.\n");
if (settings->vertexblends)
FIXME("Ignoring vertex blend.\n");
if (settings->normal)
FIXME("Ignoring normals.\n");
if (settings->fog_mode != WINED3D_FFP_VS_FOG_OFF)
FIXME("Ignoring fog.\n");
/* This must be kept in sync with struct wined3d_ffp_vs_constants. */
shader_addline(buffer, "uniform struct\n");
shader_addline(buffer, "{\n");
shader_addline(buffer, " float4x4 modelview_matrices[%u];\n", MAX_VERTEX_BLENDS);
shader_addline(buffer, " float4x4 projection_matrix;\n");
shader_addline(buffer, " float4x4 texture_matrices[%u];\n", WINED3D_MAX_FFP_TEXTURES);
shader_addline(buffer, " float4 point_params;\n");
shader_addline(buffer, " struct\n");
shader_addline(buffer, " {\n");
shader_addline(buffer, " float4 diffuse;\n");
shader_addline(buffer, " float4 ambient;\n");
shader_addline(buffer, " float4 specular;\n");
shader_addline(buffer, " float4 emissive;\n");
shader_addline(buffer, " float power;\n");
shader_addline(buffer, " } material;\n");
shader_addline(buffer, " float4 ambient_colour;\n");
shader_addline(buffer, " struct\n");
shader_addline(buffer, " {\n");
shader_addline(buffer, " float4 diffuse, specular, ambient;\n");
shader_addline(buffer, " float4 position, direction;\n");
shader_addline(buffer, " float4 packed_params;\n");
shader_addline(buffer, " float4 attenuation;\n");
shader_addline(buffer, " } lights[%u];\n", WINED3D_MAX_ACTIVE_LIGHTS);
shader_addline(buffer, "} c;\n");
shader_addline(buffer, "struct input\n");
shader_addline(buffer, "{\n");
shader_addline(buffer, " float4 pos : POSITION;\n");
shader_addline(buffer, " float4 blend_weight : BLENDWEIGHT;\n");
shader_addline(buffer, " uint blend_indices : BLENDINDICES;\n");
shader_addline(buffer, " float3 normal : NORMAL;\n");
shader_addline(buffer, " float point_size : PSIZE;\n");
shader_addline(buffer, " float4 diffuse : COLOR0;\n");
shader_addline(buffer, " float4 specular : COLOR1;\n");
shader_addline(buffer, " float4 texcoord[%u] : TEXCOORD;\n", WINED3D_MAX_FFP_TEXTURES);
shader_addline(buffer, "};\n\n");
shader_addline(buffer, "struct output\n");
shader_addline(buffer, "{\n");
shader_addline(buffer, " float4 pos : POSITION;\n");
shader_addline(buffer, " float4 diffuse : COLOR0;\n");
shader_addline(buffer, " float4 specular : COLOR1;\n");
for (unsigned int i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i)
{
if (((settings->texgen[i] & 0xffff0000) != WINED3DTSS_TCI_PASSTHRU) || (settings->texcoords & (1u << i)))
shader_addline(buffer, " float4 texcoord%u : TEXCOORD%u;\n", i, i);
}
shader_addline(buffer, "};\n\n");
shader_addline(buffer, "void main(in struct input i, out struct output o)\n");
shader_addline(buffer, "{\n");
shader_addline(buffer, " float4 ec_pos = 0.0;\n\n");
shader_addline(buffer, " ec_pos += mul(c.modelview_matrices[0], float4(i.pos.xyz, 1.0));\n\n");
shader_addline(buffer, " o.pos = mul(c.projection_matrix, ec_pos);\n");
shader_addline(buffer, " ec_pos /= ec_pos.w;\n\n");
/* No lighting. */
if (settings->diffuse)
shader_addline(buffer, " o.diffuse = i.diffuse;\n");
else
shader_addline(buffer, " o.diffuse = 1.0;\n");
shader_addline(buffer, " o.specular = i.specular;\n\n");
for (unsigned int i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i)
{
switch (settings->texgen[i] & 0xffff0000)
{
case WINED3DTSS_TCI_PASSTHRU:
if (settings->texcoords & (1u << i))
shader_addline(buffer, " o.texcoord%u = mul(c.texture_matrices[%u], i.texcoord[%u]);\n",
i, i, settings->texgen[i] & 0x0000ffff);
else
continue;
break;
default:
FIXME("Unhandled texgen %#x.\n", settings->texgen[i]);
break;
}
}
switch (settings->fog_mode)
{
case WINED3D_FFP_VS_FOG_OFF:
break;
default:
FIXME("Unhandled fog mode %#x.\n", settings->fog_mode);
break;
}
shader_addline(buffer, "}\n");
return true;
}
static bool ffp_hlsl_generate_pixel_shader(const struct ffp_frag_settings *settings,
struct wined3d_string_buffer *string)
{
FIXME("Not yet implemented.\n");
return false;
}
static bool compile_hlsl_shader(const struct wined3d_string_buffer *hlsl,
struct vkd3d_shader_code *sm1, const char *profile)
{
struct vkd3d_shader_hlsl_source_info hlsl_source_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO};
struct vkd3d_shader_compile_info compile_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO};
char *messages;
int ret;
compile_info.source.code = hlsl->buffer;
compile_info.source.size = hlsl->content_size;
compile_info.source_type = VKD3D_SHADER_SOURCE_HLSL;
compile_info.target_type = VKD3D_SHADER_TARGET_D3D_BYTECODE;
compile_info.log_level = VKD3D_SHADER_LOG_WARNING;
compile_info.next = &hlsl_source_info;
hlsl_source_info.profile = profile;
ret = vkd3d_shader_compile(&compile_info, sm1, &messages);
if (messages && *messages && FIXME_ON(d3d_shader))
{
const char *ptr, *end, *line;
FIXME("Shader log:\n");
ptr = messages;
end = ptr + strlen(ptr);
while ((line = wined3d_get_line(&ptr, end)))
FIXME(" %.*s", (int)(ptr - line), line);
FIXME("\n");
}
vkd3d_shader_free_messages(messages);
if (ret < 0)
{
ERR("Failed to compile HLSL, ret %d.\n", ret);
return false;
}
return true;
}
bool ffp_hlsl_compile_vs(const struct wined3d_ffp_vs_settings *settings, struct wined3d_shader_desc *shader_desc)
{
struct wined3d_string_buffer string;
struct vkd3d_shader_code sm1;
if (!string_buffer_init(&string))
return false;
if (!ffp_hlsl_generate_vertex_shader(settings, &string))
{
string_buffer_free(&string);
return false;
}
if (!compile_hlsl_shader(&string, &sm1, "vs_2_0"))
{
string_buffer_free(&string);
return false;
}
string_buffer_free(&string);
shader_desc->byte_code = sm1.code;
shader_desc->byte_code_size = ~(size_t)0;
return true;
}
bool ffp_hlsl_compile_ps(const struct ffp_frag_settings *settings, struct wined3d_shader_desc *shader_desc)
{
struct wined3d_string_buffer string;
struct vkd3d_shader_code sm1;
if (!string_buffer_init(&string))
return false;
if (!ffp_hlsl_generate_pixel_shader(settings, &string))
{
string_buffer_free(&string);
return false;
}
if (!compile_hlsl_shader(&string, &sm1, "ps_2_0"))
{
string_buffer_free(&string);
return false;
}
string_buffer_free(&string);
shader_desc->byte_code = sm1.code;
shader_desc->byte_code_size = ~(size_t)0;
return true;
}

View file

@ -1735,17 +1735,38 @@ static void shader_glsl_load_constants(struct shader_glsl_priv *priv,
constant_version = prog->constant_version; constant_version = prog->constant_version;
update_mask = context->constant_update_mask & prog->constant_update_mask; update_mask = context->constant_update_mask & prog->constant_update_mask;
if (update_mask & WINED3D_SHADER_CONST_VS_F) if (vshader && vshader->is_ffp_vs)
shader_glsl_load_constants_f(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_F], {
prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version); /* The shader's constant update mask is WINED3D_SHADER_CONST_VS_F.
* This may be set from shader_glsl_update_graphics_program().
* However, we also need to update constants when FFP flags change. */
static const uint32_t vs_update_mask = WINED3D_SHADER_CONST_VS_F
| WINED3D_SHADER_CONST_FFP_LIGHTS
| WINED3D_SHADER_CONST_FFP_MATERIAL
| WINED3D_SHADER_CONST_FFP_MODELVIEW
| WINED3D_SHADER_CONST_FFP_PROJ
| WINED3D_SHADER_CONST_FFP_TEXMATRIX
| WINED3D_SHADER_CONST_FFP_VERTEXBLEND
| WINED3D_SHADER_CONST_VS_POINTSIZE;
if (update_mask & WINED3D_SHADER_CONST_VS_I) if (context->constant_update_mask & vs_update_mask)
shader_glsl_load_constants_i(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_I], shader_glsl_load_constants_f(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_FFP],
prog->vs.uniform_i_locations, vshader->reg_maps.integer_constants); prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version);
}
else
{
if (update_mask & WINED3D_SHADER_CONST_VS_F)
shader_glsl_load_constants_f(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_F],
prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version);
if (update_mask & WINED3D_SHADER_CONST_VS_B) if (update_mask & WINED3D_SHADER_CONST_VS_I)
shader_glsl_load_constants_b(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_B], shader_glsl_load_constants_i(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_I],
prog->vs.uniform_b_locations, vshader->reg_maps.boolean_constants); prog->vs.uniform_i_locations, vshader->reg_maps.integer_constants);
if (update_mask & WINED3D_SHADER_CONST_VS_B)
shader_glsl_load_constants_b(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_B],
prog->vs.uniform_b_locations, vshader->reg_maps.boolean_constants);
}
if (update_mask & WINED3D_SHADER_CONST_VS_CLIP_PLANES) if (update_mask & WINED3D_SHADER_CONST_VS_CLIP_PLANES)
{ {
@ -1890,17 +1911,30 @@ static void shader_glsl_load_constants(struct shader_glsl_priv *priv,
WINED3D_LIGHT_PARALLELPOINT, &constants->light.lights[i], prog); WINED3D_LIGHT_PARALLELPOINT, &constants->light.lights[i], prog);
} }
if (update_mask & WINED3D_SHADER_CONST_PS_F) if (pshader && pshader->is_ffp_ps)
shader_glsl_load_constants_f(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_F], {
prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version); static const uint32_t ps_update_mask = WINED3D_SHADER_CONST_PS_F
| WINED3D_SHADER_CONST_FFP_COLOR_KEY
| WINED3D_SHADER_CONST_FFP_PS;
if (update_mask & WINED3D_SHADER_CONST_PS_I) if (context->constant_update_mask & ps_update_mask)
shader_glsl_load_constants_i(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_I], shader_glsl_load_constants_f(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_FFP],
prog->ps.uniform_i_locations, pshader->reg_maps.integer_constants); prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version);
}
else
{
if (update_mask & WINED3D_SHADER_CONST_PS_F)
shader_glsl_load_constants_f(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_F],
prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version);
if (update_mask & WINED3D_SHADER_CONST_PS_B) if (update_mask & WINED3D_SHADER_CONST_PS_I)
shader_glsl_load_constants_b(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_B], shader_glsl_load_constants_i(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_I],
prog->ps.uniform_b_locations, pshader->reg_maps.boolean_constants); prog->ps.uniform_i_locations, pshader->reg_maps.integer_constants);
if (update_mask & WINED3D_SHADER_CONST_PS_B)
shader_glsl_load_constants_b(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_B],
prog->ps.uniform_b_locations, pshader->reg_maps.boolean_constants);
}
if (update_mask & WINED3D_SHADER_CONST_PS_BUMP_ENV) if (update_mask & WINED3D_SHADER_CONST_PS_BUMP_ENV)
{ {
@ -10391,10 +10425,10 @@ static void set_glsl_shader_program(const struct wined3d_context_gl *context_gl,
vs_id = ctx_data->glsl_program->vs.id; vs_id = ctx_data->glsl_program->vs.id;
vs_list = &ctx_data->glsl_program->vs.shader_entry; vs_list = &ctx_data->glsl_program->vs.shader_entry;
if (use_vs(state)) if (use_vs(state) || d3d_info->ffp_hlsl)
vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX]; vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
} }
else if (use_vs(state)) else if (use_vs(state) || d3d_info->ffp_hlsl)
{ {
struct vs_compile_args vs_compile_args; struct vs_compile_args vs_compile_args;
@ -12113,7 +12147,7 @@ static void glsl_fragment_pipe_fogparams(struct wined3d_context *context,
static void glsl_fragment_pipe_fog(struct wined3d_context *context, static void glsl_fragment_pipe_fog(struct wined3d_context *context,
const struct wined3d_state *state, DWORD state_id) const struct wined3d_state *state, DWORD state_id)
{ {
BOOL use_vshader = use_vs(state); BOOL use_vshader = use_vs(state) && !state->shader[WINED3D_SHADER_TYPE_VERTEX]->is_ffp_vs;
enum fogsource new_source; enum fogsource new_source;
DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART]; DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
DWORD fogend = state->render_states[WINED3D_RS_FOGEND]; DWORD fogend = state->render_states[WINED3D_RS_FOGEND];

View file

@ -2268,7 +2268,55 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
return WINED3D_OK; return WINED3D_OK;
} }
static HRESULT shader_set_function(struct wined3d_shader *shader, static void shader_trace(const void *code, size_t size, enum vkd3d_shader_source_type source_type)
{
struct vkd3d_shader_compile_info info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO};
struct vkd3d_shader_code d3d_asm;
const char *ptr, *end, *line;
char *messages;
int ret;
static const struct vkd3d_shader_compile_option compile_options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_6},
};
info.source.code = code;
info.source.size = size;
info.source_type = source_type;
info.target_type = VKD3D_SHADER_TARGET_D3D_ASM;
info.options = compile_options;
info.option_count = ARRAY_SIZE(compile_options);
info.log_level = VKD3D_SHADER_LOG_WARNING;
ret = vkd3d_shader_compile(&info, &d3d_asm, &messages);
if (messages && *messages && FIXME_ON(d3d_shader))
{
FIXME("Shader log:\n");
ptr = messages;
end = ptr + strlen(ptr);
while ((line = wined3d_get_line(&ptr, end)))
FIXME(" %.*s", (int)(ptr - line), line);
FIXME("\n");
}
vkd3d_shader_free_messages(messages);
if (ret < 0)
{
ERR("Failed to disassemble, ret %d.\n", ret);
return;
}
ptr = d3d_asm.code;
end = ptr + d3d_asm.size;
while ((line = wined3d_get_line(&ptr, end)))
TRACE(" %.*s", (int)(ptr - line), line);
TRACE("\n");
vkd3d_shader_free_shader_code(&d3d_asm);
}
static HRESULT shader_set_function(struct wined3d_shader *shader, const struct wined3d_shader_desc *desc,
enum wined3d_shader_type type, const struct wined3d_stream_output_desc *so_desc, unsigned int float_const_count) enum wined3d_shader_type type, const struct wined3d_stream_output_desc *so_desc, unsigned int float_const_count)
{ {
const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info; const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
@ -2279,8 +2327,88 @@ static HRESULT shader_set_function(struct wined3d_shader *shader,
unsigned int backend_version; unsigned int backend_version;
HRESULT hr; HRESULT hr;
TRACE("shader %p, type %s, float_const_count %u.\n", TRACE("shader %p, byte_code %p, size %#Ix, type %s, float_const_count %u.\n",
shader, debug_shader_type(type), float_const_count); shader, desc->byte_code, desc->byte_code_size, debug_shader_type(type), float_const_count);
if (!desc->byte_code)
return WINED3DERR_INVALIDCALL;
if (desc->byte_code_size == ~(size_t)0)
{
struct wined3d_shader_version shader_version;
const struct wined3d_shader_frontend *fe;
struct wined3d_shader_instruction ins;
const DWORD *ptr;
void *fe_data;
shader->source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE;
if (!(shader->frontend = shader_select_frontend(shader->source_type)))
{
FIXME("Unable to find frontend for shader.\n");
shader_cleanup(shader);
return WINED3DERR_INVALIDCALL;
}
fe = shader->frontend;
if (!(fe_data = fe->shader_init(desc->byte_code, desc->byte_code_size, &shader->output_signature)))
{
WARN("Failed to initialise frontend data.\n");
shader_cleanup(shader);
return WINED3DERR_INVALIDCALL;
}
fe->shader_read_header(fe_data, &ptr, &shader_version);
while (!fe->shader_is_end(fe_data, &ptr))
fe->shader_read_instruction(fe_data, &ptr, &ins);
fe->shader_free(fe_data);
shader->byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr);
if (!(shader->byte_code = malloc(shader->byte_code_size)))
{
shader_cleanup(shader);
return E_OUTOFMEMORY;
}
memcpy(shader->byte_code, desc->byte_code, shader->byte_code_size);
shader->function = shader->byte_code;
shader->functionLength = shader->byte_code_size;
}
else
{
unsigned int max_version;
if (!(shader->byte_code = malloc(desc->byte_code_size)))
{
shader_cleanup(shader);
return E_OUTOFMEMORY;
}
memcpy(shader->byte_code, desc->byte_code, desc->byte_code_size);
shader->byte_code_size = desc->byte_code_size;
max_version = shader_max_version_from_feature_level(shader->device->cs->c.state->feature_level);
if (FAILED(hr = wined3d_shader_extract_from_dxbc(shader, max_version, &shader->source_type)))
{
shader_cleanup(shader);
return hr;
}
if (!(shader->frontend = shader_select_frontend(shader->source_type)))
{
FIXME("Unable to find frontend for shader.\n");
shader_cleanup(shader);
return WINED3DERR_INVALIDCALL;
}
}
if (TRACE_ON(d3d_shader))
{
if (shader->source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE)
shader_trace(shader->function, shader->functionLength, shader->source_type);
else
shader_trace(shader->byte_code, shader->byte_code_size, shader->source_type);
}
if (type == WINED3D_SHADER_TYPE_GEOMETRY) if (type == WINED3D_SHADER_TYPE_GEOMETRY)
{ {
@ -2308,7 +2436,8 @@ static HRESULT shader_set_function(struct wined3d_shader *shader,
WARN("Wrong shader type %s.\n", debug_shader_type(reg_maps->shader_version.type)); WARN("Wrong shader type %s.\n", debug_shader_type(reg_maps->shader_version.type));
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
} }
if (version->major > shader_max_version_from_feature_level(shader->device->cs->c.state->feature_level)) if (!shader->is_ffp_vs && !shader->is_ffp_ps
&& version->major > shader_max_version_from_feature_level(shader->device->cs->c.state->feature_level))
{ {
WARN("Shader version %u not supported by this device.\n", version->major); WARN("Shader version %u not supported by this device.\n", version->major);
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
@ -2421,6 +2550,30 @@ static void wined3d_shader_init_object(void *object)
list_add_head(&device->shaders, &shader->shader_list_entry); list_add_head(&device->shaders, &shader->shader_list_entry);
if (shader->is_ffp_vs)
{
struct wined3d_ffp_vs_settings *settings = shader->byte_code;
struct wined3d_shader_desc desc;
if (!ffp_hlsl_compile_vs(settings, &desc))
return;
free(settings);
shader_set_function(shader, &desc, WINED3D_SHADER_TYPE_VERTEX, NULL,
device->adapter->d3d_info.limits.vs_uniform_count);
}
if (shader->is_ffp_ps)
{
struct ffp_frag_settings *settings = shader->byte_code;
struct wined3d_shader_desc desc;
if (!ffp_hlsl_compile_ps(settings, &desc))
return;
free(settings);
shader_set_function(shader, &desc, WINED3D_SHADER_TYPE_PIXEL, NULL,
device->adapter->d3d_info.limits.ps_uniform_count);
}
device->shader_backend->shader_precompile(device->shader_priv, shader); device->shader_backend->shader_precompile(device->shader_priv, shader);
} }
@ -2548,9 +2701,27 @@ void find_vs_compile_args(const struct wined3d_state *state, const struct wined3
&& state->transforms[WINED3D_TS_PROJECTION]._24 == 0.0f && state->transforms[WINED3D_TS_PROJECTION]._24 == 0.0f
&& state->transforms[WINED3D_TS_PROJECTION]._34 == 0.0f && state->transforms[WINED3D_TS_PROJECTION]._34 == 0.0f
&& state->transforms[WINED3D_TS_PROJECTION]._44 == 1.0f) && state->transforms[WINED3D_TS_PROJECTION]._44 == 1.0f)
args->fog_src = VS_FOG_Z; {
/* Fog source is vertex output Z.
*
* However, if drawing RHW (which means we are using an HLSL
* replacement shader, since we got here), and depth testing is
* disabled, primitives are not supposed to be clipped by the
* viewport. We handle this in the vertex shader by essentially
* flushing output Z to zero.
*
* Fog needs to still read from the original Z, however. In this
* case we read from oFog, which contains the original Z. */
if (state->vertex_declaration->position_transformed)
args->fog_src = VS_FOG_COORD;
else
args->fog_src = VS_FOG_Z;
}
else else
{
args->fog_src = VS_FOG_W; args->fog_src = VS_FOG_W;
}
} }
else else
{ {
@ -2613,71 +2784,9 @@ bool vshader_get_input(const struct wined3d_shader *shader,
return false; return false;
} }
static void shader_trace(const void *code, size_t size, enum vkd3d_shader_source_type source_type) static void shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
void *parent, const struct wined3d_parent_ops *parent_ops)
{ {
struct vkd3d_shader_compile_info info;
struct vkd3d_shader_code d3d_asm;
const char *ptr, *end, *line;
char *messages;
int ret;
static const struct vkd3d_shader_compile_option compile_options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_6},
};
info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;
info.next = NULL;
info.source.code = code;
info.source.size = size;
info.source_type = source_type;
info.target_type = VKD3D_SHADER_TARGET_D3D_ASM;
info.options = compile_options;
info.option_count = ARRAY_SIZE(compile_options);
info.log_level = VKD3D_SHADER_LOG_WARNING;
info.source_name = NULL;
ret = vkd3d_shader_compile(&info, &d3d_asm, &messages);
if (messages && *messages && FIXME_ON(d3d_shader))
{
FIXME("Shader log:\n");
ptr = messages;
end = ptr + strlen(ptr);
while ((line = wined3d_get_line(&ptr, end)))
{
FIXME(" %.*s", (int)(ptr - line), line);
}
FIXME("\n");
}
vkd3d_shader_free_messages(messages);
if (ret < 0)
{
ERR("Failed to disassemble, ret %d.\n", ret);
return;
}
ptr = d3d_asm.code;
end = ptr + d3d_asm.size;
while ((line = wined3d_get_line(&ptr, end)))
{
TRACE(" %.*s", (int)(ptr - line), line);
}
TRACE("\n");
vkd3d_shader_free_shader_code(&d3d_asm);
}
static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
{
HRESULT hr;
TRACE("byte_code %p, byte_code_size %#lx.\n", desc->byte_code, (long)desc->byte_code_size);
if (!desc->byte_code)
return WINED3DERR_INVALIDCALL;
shader->ref = 1; shader->ref = 1;
shader->device = device; shader->device = device;
shader->parent = parent; shader->parent = parent;
@ -2690,87 +2799,6 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
shader->lconst_inf_or_nan = FALSE; shader->lconst_inf_or_nan = FALSE;
list_init(&shader->reg_maps.indexable_temps); list_init(&shader->reg_maps.indexable_temps);
list_init(&shader->shader_list_entry); list_init(&shader->shader_list_entry);
if (desc->byte_code_size == ~(size_t)0)
{
struct wined3d_shader_version shader_version;
const struct wined3d_shader_frontend *fe;
struct wined3d_shader_instruction ins;
const DWORD *ptr;
void *fe_data;
shader->source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE;
if (!(shader->frontend = shader_select_frontend(shader->source_type)))
{
FIXME("Unable to find frontend for shader.\n");
hr = WINED3DERR_INVALIDCALL;
goto fail;
}
fe = shader->frontend;
if (!(fe_data = fe->shader_init(desc->byte_code, desc->byte_code_size, &shader->output_signature)))
{
WARN("Failed to initialise frontend data.\n");
hr = WINED3DERR_INVALIDCALL;
goto fail;
}
fe->shader_read_header(fe_data, &ptr, &shader_version);
while (!fe->shader_is_end(fe_data, &ptr))
fe->shader_read_instruction(fe_data, &ptr, &ins);
fe->shader_free(fe_data);
shader->byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr);
if (!(shader->byte_code = malloc(shader->byte_code_size)))
{
hr = E_OUTOFMEMORY;
goto fail;
}
memcpy(shader->byte_code, desc->byte_code, shader->byte_code_size);
shader->function = shader->byte_code;
shader->functionLength = shader->byte_code_size;
}
else
{
unsigned int max_version;
if (!(shader->byte_code = malloc(desc->byte_code_size)))
{
hr = E_OUTOFMEMORY;
goto fail;
}
memcpy(shader->byte_code, desc->byte_code, desc->byte_code_size);
shader->byte_code_size = desc->byte_code_size;
max_version = shader_max_version_from_feature_level(device->cs->c.state->feature_level);
if (FAILED(hr = wined3d_shader_extract_from_dxbc(shader, max_version, &shader->source_type)))
goto fail;
if (!(shader->frontend = shader_select_frontend(shader->source_type)))
{
FIXME("Unable to find frontend for shader.\n");
hr = WINED3DERR_INVALIDCALL;
goto fail;
}
}
if (TRACE_ON(d3d_shader))
{
if (shader->source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE)
shader_trace(shader->function, shader->functionLength, shader->source_type);
else
shader_trace(shader->byte_code, shader->byte_code_size, shader->source_type);
}
return WINED3D_OK;
fail:
shader_cleanup(shader);
return hr;
} }
static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_device *device, static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
@ -2778,10 +2806,9 @@ static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_
{ {
HRESULT hr; HRESULT hr;
if (FAILED(hr = shader_init(shader, device, desc, parent, parent_ops))) shader_init(shader, device, parent, parent_ops);
return hr;
if (FAILED(hr = shader_set_function(shader, if (FAILED(hr = shader_set_function(shader, desc,
WINED3D_SHADER_TYPE_VERTEX, NULL, device->adapter->d3d_info.limits.vs_uniform_count))) WINED3D_SHADER_TYPE_VERTEX, NULL, device->adapter->d3d_info.limits.vs_uniform_count)))
{ {
shader_cleanup(shader); shader_cleanup(shader);
@ -2797,10 +2824,9 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3
{ {
HRESULT hr; HRESULT hr;
if (FAILED(hr = shader_init(shader, device, desc, parent, parent_ops))) shader_init(shader, device, parent, parent_ops);
return hr;
if (FAILED(hr = shader_set_function(shader, WINED3D_SHADER_TYPE_GEOMETRY, so_desc, 0))) if (FAILED(hr = shader_set_function(shader, desc, WINED3D_SHADER_TYPE_GEOMETRY, so_desc, 0)))
goto fail; goto fail;
return WINED3D_OK; return WINED3D_OK;
@ -2846,6 +2872,7 @@ void find_gs_compile_args(const struct wined3d_state *state, const struct wined3
void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader, void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
BOOL position_transformed, struct ps_compile_args *args, const struct wined3d_context *context) BOOL position_transformed, struct ps_compile_args *args, const struct wined3d_context *context)
{ {
const struct wined3d_shader *vs = state->shader[WINED3D_SHADER_TYPE_VERTEX];
const struct wined3d_d3d_info *d3d_info = context->d3d_info; const struct wined3d_d3d_info *d3d_info = context->d3d_info;
struct wined3d_shader_resource_view *view; struct wined3d_shader_resource_view *view;
struct wined3d_texture *texture; struct wined3d_texture *texture;
@ -2873,7 +2900,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
{ {
uint32_t tex_transform = flags & ~WINED3D_TTFF_PROJECTED; uint32_t tex_transform = flags & ~WINED3D_TTFF_PROJECTED;
if (!state->shader[WINED3D_SHADER_TYPE_VERTEX]) if (!vs || vs->is_ffp_vs)
{ {
enum wined3d_shader_resource_type resource_type = shader->reg_maps.resource_info[i].type; enum wined3d_shader_resource_type resource_type = shader->reg_maps.resource_info[i].type;
unsigned int j; unsigned int j;
@ -3043,7 +3070,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
switch (state->render_states[WINED3D_RS_FOGTABLEMODE]) switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
{ {
case WINED3D_FOG_NONE: case WINED3D_FOG_NONE:
if (position_transformed || use_vs(state)) if (position_transformed || (vs && !vs->is_ffp_vs))
{ {
args->fog = WINED3D_FFP_PS_FOG_LINEAR; args->fog = WINED3D_FFP_PS_FOG_LINEAR;
break; break;
@ -3127,10 +3154,9 @@ static HRESULT pixel_shader_init(struct wined3d_shader *shader, struct wined3d_d
const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
HRESULT hr; HRESULT hr;
if (FAILED(hr = shader_init(shader, device, desc, parent, parent_ops))) shader_init(shader, device, parent, parent_ops);
return hr;
if (FAILED(hr = shader_set_function(shader, if (FAILED(hr = shader_set_function(shader, desc,
WINED3D_SHADER_TYPE_PIXEL, NULL, d3d_info->limits.ps_uniform_count))) WINED3D_SHADER_TYPE_PIXEL, NULL, d3d_info->limits.ps_uniform_count)))
{ {
shader_cleanup(shader); shader_cleanup(shader);
@ -3175,14 +3201,9 @@ HRESULT CDECL wined3d_shader_create_cs(struct wined3d_device *device, const stru
if (!(object = calloc(1, sizeof(*object)))) if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (FAILED(hr = shader_init(object, device, desc, parent, parent_ops))) shader_init(object, device, parent, parent_ops);
{
WARN("Failed to initialize compute shader, hr %#lx.\n", hr);
free(object);
return hr;
}
if (FAILED(hr = shader_set_function(object, WINED3D_SHADER_TYPE_COMPUTE, NULL, 0))) if (FAILED(hr = shader_set_function(object, desc, WINED3D_SHADER_TYPE_COMPUTE, NULL, 0)))
{ {
shader_cleanup(object); shader_cleanup(object);
free(object); free(object);
@ -3209,14 +3230,9 @@ HRESULT CDECL wined3d_shader_create_ds(struct wined3d_device *device, const stru
if (!(object = calloc(1, sizeof(*object)))) if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (FAILED(hr = shader_init(object, device, desc, parent, parent_ops))) shader_init(object, device, parent, parent_ops);
{
WARN("Failed to initialize domain shader, hr %#lx.\n", hr);
free(object);
return hr;
}
if (FAILED(hr = shader_set_function(object, WINED3D_SHADER_TYPE_DOMAIN, NULL, 0))) if (FAILED(hr = shader_set_function(object, desc, WINED3D_SHADER_TYPE_DOMAIN, NULL, 0)))
{ {
shader_cleanup(object); shader_cleanup(object);
free(object); free(object);
@ -3271,14 +3287,9 @@ HRESULT CDECL wined3d_shader_create_hs(struct wined3d_device *device, const stru
if (!(object = calloc(1, sizeof(*object)))) if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (FAILED(hr = shader_init(object, device, desc, parent, parent_ops))) shader_init(object, device, parent, parent_ops);
{
WARN("Failed to initialize hull shader, hr %#lx.\n", hr);
free(object);
return hr;
}
if (FAILED(hr = shader_set_function(object, WINED3D_SHADER_TYPE_HULL, NULL, 0))) if (FAILED(hr = shader_set_function(object, desc, WINED3D_SHADER_TYPE_HULL, NULL, 0)))
{ {
shader_cleanup(object); shader_cleanup(object);
free(object); free(object);
@ -3346,3 +3357,53 @@ HRESULT CDECL wined3d_shader_create_vs(struct wined3d_device *device, const stru
return WINED3D_OK; return WINED3D_OK;
} }
HRESULT wined3d_shader_create_ffp_vs(struct wined3d_device *device,
const struct wined3d_ffp_vs_settings *settings, struct wined3d_shader **shader)
{
struct wined3d_shader *object;
if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY;
shader_init(object, device, NULL, &wined3d_null_parent_ops);
object->is_ffp_vs = true;
if (!(object->byte_code = malloc(sizeof(*settings))))
{
free(object);
return E_OUTOFMEMORY;
}
memcpy(object->byte_code, settings, sizeof(*settings));
wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object);
TRACE("Created FFP vertex shader %p.\n", object);
*shader = object;
return WINED3D_OK;
}
HRESULT wined3d_shader_create_ffp_ps(struct wined3d_device *device,
const struct ffp_frag_settings *settings, struct wined3d_shader **shader)
{
struct wined3d_shader *object;
if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY;
shader_init(object, device, NULL, &wined3d_null_parent_ops);
object->is_ffp_ps = true;
if (!(object->byte_code = malloc(sizeof(*settings))))
{
free(object);
return E_OUTOFMEMORY;
}
memcpy(object->byte_code, settings, sizeof(*settings));
wined3d_cs_init_object(device->cs, wined3d_shader_init_object, object);
TRACE("Created FFP pixel shader %p.\n", object);
*shader = object;
return WINED3D_OK;
}

View file

@ -6,7 +6,7 @@
* Copyright 2005 Oliver Stieber * Copyright 2005 Oliver Stieber
* Copyright 2007 Stefan Dösinger for CodeWeavers * Copyright 2007 Stefan Dösinger for CodeWeavers
* Copyright 2009 Henri Verbeet for CodeWeavers * Copyright 2009 Henri Verbeet for CodeWeavers
* Copyright 2019,2020,2022 Zebediah Figura for CodeWeavers * Copyright 2019,2020,2022-2024 Elizabeth Figura for CodeWeavers
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -1299,6 +1299,7 @@ void CDECL wined3d_stateblock_set_vertex_shader(struct wined3d_stateblock *state
wined3d_shader_decref(stateblock->stateblock_state.vs); wined3d_shader_decref(stateblock->stateblock_state.vs);
stateblock->stateblock_state.vs = shader; stateblock->stateblock_state.vs = shader;
stateblock->changed.vertexShader = TRUE; stateblock->changed.vertexShader = TRUE;
stateblock->changed.ffp_vs_settings = 1;
} }
static void wined3d_bitmap_set_bits(uint32_t *bitmap, unsigned int start, unsigned int count) static void wined3d_bitmap_set_bits(uint32_t *bitmap, unsigned int start, unsigned int count)
@ -1439,6 +1440,7 @@ void CDECL wined3d_stateblock_set_pixel_shader(struct wined3d_stateblock *stateb
wined3d_shader_decref(stateblock->stateblock_state.ps); wined3d_shader_decref(stateblock->stateblock_state.ps);
stateblock->stateblock_state.ps = shader; stateblock->stateblock_state.ps = shader;
stateblock->changed.pixelShader = TRUE; stateblock->changed.pixelShader = TRUE;
stateblock->changed.ffp_ps_settings = 1;
} }
HRESULT CDECL wined3d_stateblock_set_ps_consts_f(struct wined3d_stateblock *stateblock, HRESULT CDECL wined3d_stateblock_set_ps_consts_f(struct wined3d_stateblock *stateblock,
@ -1573,6 +1575,9 @@ void CDECL wined3d_stateblock_set_vertex_declaration(struct wined3d_stateblock *
|| declaration->normal != prev->normal || declaration->point_size != prev->point_size) || declaration->normal != prev->normal || declaration->point_size != prev->point_size)
stateblock->changed.ffp_vs_settings = 1; stateblock->changed.ffp_vs_settings = 1;
} }
if (declaration->position_transformed != prev->position_transformed)
stateblock->changed.ffp_vs_settings = 1;
} }
else else
{ {
@ -2379,10 +2384,10 @@ static void wined3d_stateblock_state_init(struct wined3d_stateblock_state *state
} }
/* FFP push constant buffers do not have a "default" state on the CS side. /* Some states, e.g. FFP push constant buffers, do not have a "default" state
* We need to explicitly invalidate them when initializing the context or * on the CS side. We need to explicitly invalidate them when initializing the
* resetting. */ * context or resetting. */
static void wined3d_stateblock_invalidate_push_constants(struct wined3d_stateblock *stateblock) static void wined3d_stateblock_invalidate_initial_states(struct wined3d_stateblock *stateblock)
{ {
stateblock->changed.ffp_ps_constants = 1; stateblock->changed.ffp_ps_constants = 1;
stateblock->changed.lights = 1; stateblock->changed.lights = 1;
@ -2392,6 +2397,8 @@ static void wined3d_stateblock_invalidate_push_constants(struct wined3d_stateblo
memset(stateblock->changed.transform, 0xff, sizeof(stateblock->changed.transform)); memset(stateblock->changed.transform, 0xff, sizeof(stateblock->changed.transform));
stateblock->changed.modelview_matrices = 1; stateblock->changed.modelview_matrices = 1;
stateblock->changed.point_scale = 1; stateblock->changed.point_scale = 1;
stateblock->changed.ffp_vs_settings = 1;
stateblock->changed.ffp_ps_settings = 1;
} }
static HRESULT stateblock_init(struct wined3d_stateblock *stateblock, const struct wined3d_stateblock *device_state, static HRESULT stateblock_init(struct wined3d_stateblock *stateblock, const struct wined3d_stateblock *device_state,
@ -2409,7 +2416,7 @@ static HRESULT stateblock_init(struct wined3d_stateblock *stateblock, const stru
list_init(&stateblock->changed.changed_lights); list_init(&stateblock->changed.changed_lights);
if (type == WINED3D_SBT_PRIMARY) if (type == WINED3D_SBT_PRIMARY)
wined3d_stateblock_invalidate_push_constants(stateblock); wined3d_stateblock_invalidate_initial_states(stateblock);
if (type == WINED3D_SBT_RECORDED || type == WINED3D_SBT_PRIMARY) if (type == WINED3D_SBT_RECORDED || type == WINED3D_SBT_PRIMARY)
return WINED3D_OK; return WINED3D_OK;
@ -2486,7 +2493,7 @@ void CDECL wined3d_stateblock_reset(struct wined3d_stateblock *stateblock)
memset(&stateblock->stateblock_state, 0, sizeof(stateblock->stateblock_state)); memset(&stateblock->stateblock_state, 0, sizeof(stateblock->stateblock_state));
stateblock->stateblock_state.light_state = &stateblock->light_state; stateblock->stateblock_state.light_state = &stateblock->light_state;
wined3d_stateblock_state_init(&stateblock->stateblock_state, stateblock->device, WINED3D_STATE_INIT_DEFAULT); wined3d_stateblock_state_init(&stateblock->stateblock_state, stateblock->device, WINED3D_STATE_INIT_DEFAULT);
wined3d_stateblock_invalidate_push_constants(stateblock); wined3d_stateblock_invalidate_initial_states(stateblock);
} }
static void wined3d_device_set_base_vertex_index(struct wined3d_device *device, int base_index) static void wined3d_device_set_base_vertex_index(struct wined3d_device *device, int base_index)
@ -2909,6 +2916,65 @@ void CDECL wined3d_stateblock_apply_clear_state(struct wined3d_stateblock *state
wined3d_device_set_render_state(device, WINED3D_RS_SRGBWRITEENABLE, state->rs[WINED3D_RS_SRGBWRITEENABLE]); wined3d_device_set_render_state(device, WINED3D_RS_SRGBWRITEENABLE, state->rs[WINED3D_RS_SRGBWRITEENABLE]);
} }
static struct wined3d_shader *get_ffp_vertex_shader(struct wined3d_device *device, const struct wined3d_state *state)
{
static const struct wined3d_stream_info dummy_stream_info;
struct wined3d_ffp_vs_settings settings;
const struct wine_rb_entry *entry;
struct wined3d_ffp_vs *vs;
/* XXX: wined3d_ffp_get_vs_settings() only needs the stream info for the
* swizzle map, which the HLSL pipeline doesn't use (it will be computed and
* used later as part of struct vs_compile_args).
*
* This is nevertheless janky, and we'd like to get rid of it. Eventually
* once the HLSL backend is used everywhere, we can get rid of the swizzle
* map from wined3d_ffp_vs_settings. */
wined3d_ffp_get_vs_settings(state, &dummy_stream_info, &device->adapter->d3d_info, &settings);
if ((entry = wine_rb_get(&device->ffp_vertex_shaders, &settings)))
return WINE_RB_ENTRY_VALUE(entry, struct wined3d_ffp_vs, entry.entry)->shader;
if (!(vs = malloc(sizeof(*vs))))
return NULL;
vs->entry.settings = settings;
if (FAILED(wined3d_shader_create_ffp_vs(device, &settings, &vs->shader)))
{
free(vs);
return NULL;
}
if (wine_rb_put(&device->ffp_vertex_shaders, &vs->entry.settings, &vs->entry.entry) == -1)
ERR("Failed to insert FFP vertex shader.\n");
return vs->shader;
}
static struct wined3d_shader *get_ffp_pixel_shader(struct wined3d_device *device, const struct wined3d_state *state)
{
struct ffp_frag_settings settings;
const struct ffp_frag_desc *desc;
struct wined3d_ffp_ps *ps;
wined3d_ffp_get_fs_settings(state, &device->adapter->d3d_info, &settings);
if ((desc = find_ffp_frag_shader(&device->ffp_pixel_shaders, &settings)))
return CONTAINING_RECORD(desc, struct wined3d_ffp_ps, entry)->shader;
if (!(ps = malloc(sizeof(*ps))))
return NULL;
ps->entry.settings = settings;
if (FAILED(wined3d_shader_create_ffp_ps(device, &settings, &ps->shader)))
{
free(ps);
return NULL;
}
add_ffp_frag_shader(&device->ffp_pixel_shaders, &ps->entry);
return ps->shader;
}
void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device,
struct wined3d_stateblock *stateblock) struct wined3d_stateblock *stateblock)
{ {
@ -3746,16 +3812,40 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device,
WINED3D_SHADER_CONST_FFP_PS, 0, offsetof(struct wined3d_ffp_ps_constants, color_key), &constants); WINED3D_SHADER_CONST_FFP_PS, 0, offsetof(struct wined3d_ffp_ps_constants, color_key), &constants);
} }
if (changed->ffp_vs_settings && !state->vs) /* XXX: We don't invalidate HLSL shaders for every field contained in
* wined3d_ffp_vs_settings / ffp_frag_settings; only the ones that the HLSL
* FFP pipeline cares about. The rest should eventually be removed from
* those structs and left only in vs_compile_args / ps_compile_args. */
if (changed->ffp_vs_settings
&& (!state->vs || !state->vertex_declaration || state->vertex_declaration->position_transformed))
{ {
/* Force invalidation of the vertex shader. */ if (device->adapter->d3d_info.ffp_hlsl)
wined3d_device_context_emit_set_shader(context, WINED3D_SHADER_TYPE_VERTEX, NULL); {
struct wined3d_shader *shader = get_ffp_vertex_shader(device, device->cs->c.state);
wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_VERTEX, shader);
}
else
{
/* Force invalidation of the vertex shader. */
wined3d_device_context_emit_set_shader(context, WINED3D_SHADER_TYPE_VERTEX, NULL);
}
} }
if (changed->ffp_ps_settings && !state->ps) if (changed->ffp_ps_settings && !state->ps)
{ {
/* Force invalidation of the pixel shader. */ if (device->adapter->d3d_info.ffp_hlsl)
wined3d_device_context_emit_set_shader(context, WINED3D_SHADER_TYPE_PIXEL, NULL); {
struct wined3d_shader *shader = get_ffp_pixel_shader(device, device->cs->c.state);
wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_PIXEL, shader);
}
else
{
/* Force invalidation of the pixel shader. */
wined3d_device_context_emit_set_shader(context, WINED3D_SHADER_TYPE_PIXEL, NULL);
}
} }
assert(list_empty(&stateblock->changed.changed_lights)); assert(list_empty(&stateblock->changed.changed_lights));

View file

@ -352,6 +352,7 @@ void texture2d_read_from_framebuffer(struct wined3d_texture *texture, unsigned i
unsigned int row_pitch, slice_pitch; unsigned int row_pitch, slice_pitch;
unsigned int width, height, level; unsigned int width, height, level;
struct wined3d_bo_address data; struct wined3d_bo_address data;
bool restore_context = false;
unsigned int restore_idx; unsigned int restore_idx;
BYTE *row, *top, *bottom; BYTE *row, *top, *bottom;
BOOL src_is_upside_down; BOOL src_is_upside_down;
@ -369,9 +370,10 @@ void texture2d_read_from_framebuffer(struct wined3d_texture *texture, unsigned i
restore_texture = context->current_rt.texture; restore_texture = context->current_rt.texture;
restore_idx = context->current_rt.sub_resource_idx; restore_idx = context->current_rt.sub_resource_idx;
if (!wined3d_resource_is_offscreen(resource) && (restore_texture != texture || restore_idx != sub_resource_idx)) if (!wined3d_resource_is_offscreen(resource) && (restore_texture != texture || restore_idx != sub_resource_idx))
{
context = context_acquire(device, texture, sub_resource_idx); context = context_acquire(device, texture, sub_resource_idx);
else restore_context = true;
restore_texture = NULL; }
context_gl = wined3d_context_gl(context); context_gl = wined3d_context_gl(context);
gl_info = context_gl->gl_info; gl_info = context_gl->gl_info;
@ -473,7 +475,7 @@ error:
checkGLcall("glBindBuffer"); checkGLcall("glBindBuffer");
} }
if (restore_texture) if (restore_context)
context_restore(context, restore_texture, restore_idx); context_restore(context, restore_texture, restore_idx);
} }

View file

@ -340,12 +340,12 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont
struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location,
const RECT *dst_rect, const struct wined3d_format *resolve_format) const RECT *dst_rect, const struct wined3d_format *resolve_format)
{ {
struct wined3d_texture *required_texture, *restore_texture = NULL, *dst_save_texture = dst_texture; struct wined3d_texture *required_texture, *restore_texture, *dst_save_texture = dst_texture;
unsigned int restore_idx, dst_save_sub_resource_idx = dst_sub_resource_idx; unsigned int restore_idx, dst_save_sub_resource_idx = dst_sub_resource_idx;
bool resolve, scaled_resolve, restore_context = false;
struct wined3d_texture *src_staging_texture = NULL; struct wined3d_texture *src_staging_texture = NULL;
const struct wined3d_gl_info *gl_info; const struct wined3d_gl_info *gl_info;
struct wined3d_context_gl *context_gl; struct wined3d_context_gl *context_gl;
bool resolve, scaled_resolve;
GLenum gl_filter; GLenum gl_filter;
GLenum buffer; GLenum buffer;
RECT s, d; RECT s, d;
@ -490,16 +490,17 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont
restore_texture = context->current_rt.texture; restore_texture = context->current_rt.texture;
restore_idx = context->current_rt.sub_resource_idx; restore_idx = context->current_rt.sub_resource_idx;
if (restore_texture != required_texture) if (restore_texture != required_texture)
{
context = context_acquire(device, required_texture, 0); context = context_acquire(device, required_texture, 0);
else restore_context = true;
restore_texture = NULL; }
context_gl = wined3d_context_gl(context); context_gl = wined3d_context_gl(context);
if (!context_gl->valid) if (!context_gl->valid)
{ {
context_release(context); context_release(context);
WARN("Invalid context, skipping blit.\n"); WARN("Invalid context, skipping blit.\n");
restore_texture = NULL; restore_context = false;
goto done; goto done;
} }
@ -565,7 +566,7 @@ done:
if (src_staging_texture) if (src_staging_texture)
wined3d_texture_decref(src_staging_texture); wined3d_texture_decref(src_staging_texture);
if (restore_texture) if (restore_context)
context_restore(context, restore_texture, restore_idx); context_restore(context, restore_texture, restore_idx);
} }

View file

@ -6448,7 +6448,7 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct
memset(settings, 0, sizeof(*settings)); memset(settings, 0, sizeof(*settings));
if (si->position_transformed) if (vdecl->position_transformed)
{ {
settings->transformed = 1; settings->transformed = 1;
settings->point_size = state->primitive_type == WINED3D_PT_POINTLIST; settings->point_size = state->primitive_type == WINED3D_PT_POINTLIST;

View file

@ -463,6 +463,11 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL)
TRACE("Forcing all constant buffers to be write-mappable.\n"); TRACE("Forcing all constant buffers to be write-mappable.\n");
wined3d_settings.cb_access_map_w = TRUE; wined3d_settings.cb_access_map_w = TRUE;
} }
if (!get_config_key_dword(hkey, appkey, env, "ffp_hlsl", &tmpvalue))
{
ERR_(winediag)("Using the HLSL-based FFP backend.\n");
wined3d_settings.ffp_hlsl = tmpvalue;
}
} }
if (appkey) RegCloseKey( appkey ); if (appkey) RegCloseKey( appkey );

View file

@ -242,6 +242,7 @@ struct wined3d_d3d_info
uint32_t fences : 1; uint32_t fences : 1;
uint32_t persistent_map : 1; uint32_t persistent_map : 1;
uint32_t gpu_push_constants : 1; uint32_t gpu_push_constants : 1;
uint32_t ffp_hlsl : 1;
enum wined3d_feature_level feature_level; enum wined3d_feature_level feature_level;
DWORD multisample_draw_location; DWORD multisample_draw_location;
@ -475,7 +476,6 @@ struct wined3d_settings
char *logo; char *logo;
unsigned int multisample_textures; unsigned int multisample_textures;
unsigned int sample_count; unsigned int sample_count;
BOOL check_float_constants;
unsigned int strict_shader_math; unsigned int strict_shader_math;
unsigned int max_sm_vs; unsigned int max_sm_vs;
unsigned int max_sm_hs; unsigned int max_sm_hs;
@ -485,7 +485,9 @@ struct wined3d_settings
unsigned int max_sm_cs; unsigned int max_sm_cs;
enum wined3d_renderer renderer; enum wined3d_renderer renderer;
enum wined3d_shader_backend shader_backend; enum wined3d_shader_backend shader_backend;
BOOL cb_access_map_w; bool check_float_constants;
bool cb_access_map_w;
bool ffp_hlsl;
}; };
extern struct wined3d_settings wined3d_settings; extern struct wined3d_settings wined3d_settings;
@ -2048,10 +2050,11 @@ void context_state_fb(struct wined3d_context *context,
struct wined3d_light_constants struct wined3d_light_constants
{ {
/* Padding is needed for the HLSL backend. */
struct wined3d_color diffuse, specular, ambient; struct wined3d_color diffuse, specular, ambient;
struct wined3d_vec4 position, direction; struct wined3d_vec4 position, direction;
float range, falloff, cos_half_theta, cos_half_phi; float range, falloff, cos_half_theta, cos_half_phi;
float const_att, linear_att, quad_att; float const_att, linear_att, quad_att, padding;
}; };
/***************************************************************************** /*****************************************************************************
@ -2662,6 +2665,12 @@ struct ffp_frag_desc
int wined3d_ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry); int wined3d_ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry);
int wined3d_ffp_vertex_program_key_compare(const void *key, const struct wine_rb_entry *entry); int wined3d_ffp_vertex_program_key_compare(const void *key, const struct wine_rb_entry *entry);
struct wined3d_ffp_ps
{
struct ffp_frag_desc entry;
struct wined3d_shader *shader;
};
extern const struct wined3d_parent_ops wined3d_null_parent_ops; extern const struct wined3d_parent_ops wined3d_null_parent_ops;
void wined3d_ffp_get_fs_settings(const struct wined3d_state *state, void wined3d_ffp_get_fs_settings(const struct wined3d_state *state,
@ -2724,6 +2733,12 @@ struct wined3d_ffp_vs_desc
struct wined3d_ffp_vs_settings settings; struct wined3d_ffp_vs_settings settings;
}; };
struct wined3d_ffp_vs
{
struct wined3d_ffp_vs_desc entry;
struct wined3d_shader *shader;
};
void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si, void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct wined3d_stream_info *si,
const struct wined3d_d3d_info *d3d_info, struct wined3d_ffp_vs_settings *settings); const struct wined3d_d3d_info *d3d_info, struct wined3d_ffp_vs_settings *settings);
@ -2769,8 +2784,10 @@ struct wined3d_ffp_vs_constants
struct wined3d_ffp_point_constants struct wined3d_ffp_point_constants
{ {
float scale_const, scale_linear, scale_quad; float scale_const, scale_linear, scale_quad;
float padding; /* For the HLSL backend. */
} point; } point;
struct wined3d_material material; struct wined3d_material material;
float padding[3]; /* For the HLSL backend. */
struct wined3d_ffp_light_constants struct wined3d_ffp_light_constants
{ {
struct wined3d_color ambient; struct wined3d_color ambient;
@ -2983,6 +3000,7 @@ struct wined3d_device
struct list shaders; /* a linked list to track shaders (pixel and vertex) */ struct list shaders; /* a linked list to track shaders (pixel and vertex) */
struct wine_rb_tree so_descs; struct wine_rb_tree so_descs;
struct wine_rb_tree samplers, rasterizer_states, blend_states, depth_stencil_states; struct wine_rb_tree samplers, rasterizer_states, blend_states, depth_stencil_states;
struct wine_rb_tree ffp_vertex_shaders, ffp_pixel_shaders;
/* Render Target Support */ /* Render Target Support */
struct wined3d_rendertarget_view *auto_depth_stencil_view; struct wined3d_rendertarget_view *auto_depth_stencil_view;
@ -4206,7 +4224,9 @@ struct wined3d_shader
unsigned int functionLength; unsigned int functionLength;
void *byte_code; void *byte_code;
unsigned int byte_code_size; unsigned int byte_code_size;
BOOL load_local_constsF; bool load_local_constsF;
bool is_ffp_vs;
bool is_ffp_ps;
enum vkd3d_shader_source_type source_type; enum vkd3d_shader_source_type source_type;
const struct wined3d_shader_frontend *frontend; const struct wined3d_shader_frontend *frontend;
void *frontend_data; void *frontend_data;
@ -4244,6 +4264,11 @@ struct wined3d_shader
} u; } u;
}; };
HRESULT wined3d_shader_create_ffp_vs(struct wined3d_device *device,
const struct wined3d_ffp_vs_settings *settings, struct wined3d_shader **shader);
HRESULT wined3d_shader_create_ffp_ps(struct wined3d_device *device,
const struct ffp_frag_settings *settings, struct wined3d_shader **shader);
enum wined3d_shader_resource_type pixelshader_get_resource_type(const struct wined3d_shader_reg_maps *reg_maps, enum wined3d_shader_resource_type pixelshader_get_resource_type(const struct wined3d_shader_reg_maps *reg_maps,
unsigned int resource_idx, DWORD tex_types); unsigned int resource_idx, DWORD tex_types);
void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader, void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
@ -4273,6 +4298,9 @@ BOOL shader_match_semantic(const char *semantic_name, enum wined3d_decl_usage us
enum vkd3d_shader_visibility vkd3d_shader_visibility_from_wined3d(enum wined3d_shader_type shader_type); enum vkd3d_shader_visibility vkd3d_shader_visibility_from_wined3d(enum wined3d_shader_type shader_type);
bool ffp_hlsl_compile_vs(const struct wined3d_ffp_vs_settings *settings, struct wined3d_shader_desc *shader_desc);
bool ffp_hlsl_compile_ps(const struct ffp_frag_settings *settings, struct wined3d_shader_desc *shader_desc);
static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg) static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg)
{ {
switch (reg->type) switch (reg->type)

View file

@ -73,7 +73,8 @@ BOOL X11DRV_CreateDesktop( const WCHAR *name, UINT width, UINT height )
/* Create window */ /* Create window */
win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask |
PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask; PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
PropertyChangeMask;
win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow ); win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow );
if (default_visual.visual != DefaultVisual( display, DefaultScreen(display) )) if (default_visual.visual != DefaultVisual( display, DefaultScreen(display) ))

View file

@ -1104,7 +1104,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
struct x11drv_win_data *data; struct x11drv_win_data *data;
RECT rect; RECT rect;
POINT pos = {event->x, event->y}; POINT pos = {event->x, event->y};
UINT config_cmd; UINT config_cmd, state_cmd;
if (!hwnd) return FALSE; if (!hwnd) return FALSE;
if (!(data = get_win_data( hwnd ))) return FALSE; if (!(data = get_win_data( hwnd ))) return FALSE;
@ -1123,17 +1123,24 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
SetRect( &rect, pos.x, pos.y, pos.x + event->width, pos.y + event->height ); SetRect( &rect, pos.x, pos.y, pos.x + event->width, pos.y + event->height );
window_configure_notify( data, event->serial, &rect ); window_configure_notify( data, event->serial, &rect );
state_cmd = window_update_client_state( data );
config_cmd = window_update_client_config( data ); config_cmd = window_update_client_config( data );
rect = window_rect_from_visible( &data->rects, data->current_state.rect ); rect = window_rect_from_visible( &data->rects, data->current_state.rect );
release_win_data( data ); release_win_data( data );
if (state_cmd)
{
if (LOWORD(state_cmd) == SC_RESTORE && HIWORD(state_cmd)) NtUserSetActiveWindow( hwnd );
send_message( hwnd, WM_SYSCOMMAND, LOWORD(state_cmd), 0 );
}
if (config_cmd) if (config_cmd)
{ {
if (LOWORD(config_cmd) == SC_MOVE) NtUserSetRawWindowPos( hwnd, rect, HIWORD(config_cmd), FALSE ); if (LOWORD(config_cmd) == SC_MOVE) NtUserSetRawWindowPos( hwnd, rect, HIWORD(config_cmd), FALSE );
else send_message( hwnd, WM_SYSCOMMAND, LOWORD(config_cmd), 0 ); else send_message( hwnd, WM_SYSCOMMAND, LOWORD(config_cmd), 0 );
} }
return !!config_cmd; return config_cmd || state_cmd;
} }
@ -1193,36 +1200,19 @@ static int get_window_xembed_info( Display *display, Window window )
* *
* Handle a PropertyNotify for WM_STATE. * Handle a PropertyNotify for WM_STATE.
*/ */
static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL update_window ) static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event )
{ {
struct x11drv_win_data *data; struct x11drv_win_data *data;
UINT value = 0, state_cmd = 0; UINT value = 0, state_cmd = 0, config_cmd = 0;
RECT rect;
if (!(data = get_win_data( hwnd ))) return; if (!(data = get_win_data( hwnd ))) return;
if (event->state == PropertyNewValue) value = get_window_wm_state( event->display, event->window ); if (event->state == PropertyNewValue) value = get_window_wm_state( event->display, event->window );
if (update_window) window_wm_state_notify( data, event->serial, value ); window_wm_state_notify( data, event->serial, value );
switch(event->state) state_cmd = window_update_client_state( data );
{ config_cmd = window_update_client_config( data );
case PropertyDelete: rect = window_rect_from_visible( &data->rects, data->current_state.rect );
TRACE( "%p/%lx: WM_STATE deleted from %d\n", data->hwnd, data->whole_window, data->wm_state );
data->wm_state = WithdrawnState;
break;
case PropertyNewValue:
{
int old_state = data->wm_state;
int new_state = get_window_wm_state( event->display, data->whole_window );
if (new_state != -1 && new_state != data->wm_state)
{
TRACE( "%p/%lx: new WM_STATE %d from %d\n",
data->hwnd, data->whole_window, new_state, old_state );
data->wm_state = new_state;
}
}
break;
}
if (update_window) state_cmd = window_update_client_state( data );
release_win_data( data ); release_win_data( data );
@ -1231,6 +1221,12 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat
if (LOWORD(state_cmd) == SC_RESTORE && HIWORD(state_cmd)) NtUserSetActiveWindow( hwnd ); if (LOWORD(state_cmd) == SC_RESTORE && HIWORD(state_cmd)) NtUserSetActiveWindow( hwnd );
send_message( hwnd, WM_SYSCOMMAND, LOWORD(state_cmd), 0 ); send_message( hwnd, WM_SYSCOMMAND, LOWORD(state_cmd), 0 );
} }
if (config_cmd)
{
if (LOWORD(config_cmd) == SC_MOVE) NtUserSetRawWindowPos( hwnd, rect, HIWORD(config_cmd), FALSE );
else send_message( hwnd, WM_SYSCOMMAND, LOWORD(config_cmd), 0 );
}
} }
static void handle_xembed_info_notify( HWND hwnd, XPropertyEvent *event ) static void handle_xembed_info_notify( HWND hwnd, XPropertyEvent *event )
@ -1247,12 +1243,30 @@ static void handle_xembed_info_notify( HWND hwnd, XPropertyEvent *event )
static void handle_net_wm_state_notify( HWND hwnd, XPropertyEvent *event ) static void handle_net_wm_state_notify( HWND hwnd, XPropertyEvent *event )
{ {
struct x11drv_win_data *data; struct x11drv_win_data *data;
UINT value = 0; UINT value = 0, state_cmd = 0, config_cmd = 0;
RECT rect;
if (!(data = get_win_data( hwnd ))) return; if (!(data = get_win_data( hwnd ))) return;
if (event->state == PropertyNewValue) value = get_window_net_wm_state( event->display, event->window ); if (event->state == PropertyNewValue) value = get_window_net_wm_state( event->display, event->window );
window_net_wm_state_notify( data, event->serial, value ); window_net_wm_state_notify( data, event->serial, value );
state_cmd = window_update_client_state( data );
config_cmd = window_update_client_config( data );
rect = window_rect_from_visible( &data->rects, data->current_state.rect );
release_win_data( data ); release_win_data( data );
if (state_cmd)
{
if (LOWORD(state_cmd) == SC_RESTORE && HIWORD(state_cmd)) NtUserSetActiveWindow( hwnd );
send_message( hwnd, WM_SYSCOMMAND, LOWORD(state_cmd), 0 );
}
if (config_cmd)
{
if (LOWORD(config_cmd) == SC_MOVE) NtUserSetRawWindowPos( hwnd, rect, HIWORD(config_cmd), FALSE );
else send_message( hwnd, WM_SYSCOMMAND, LOWORD(config_cmd), 0 );
}
} }
/*********************************************************************** /***********************************************************************
@ -1263,79 +1277,13 @@ static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *xev )
XPropertyEvent *event = &xev->xproperty; XPropertyEvent *event = &xev->xproperty;
if (!hwnd) return FALSE; if (!hwnd) return FALSE;
if (event->atom == x11drv_atom(WM_STATE)) handle_wm_state_notify( hwnd, event, TRUE ); if (event->atom == x11drv_atom(WM_STATE)) handle_wm_state_notify( hwnd, event );
if (event->atom == x11drv_atom(_XEMBED_INFO)) handle_xembed_info_notify( hwnd, event ); if (event->atom == x11drv_atom(_XEMBED_INFO)) handle_xembed_info_notify( hwnd, event );
if (event->atom == x11drv_atom(_NET_WM_STATE)) handle_net_wm_state_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_WM_STATE)) handle_net_wm_state_notify( hwnd, event );
return TRUE; return TRUE;
} }
/* event filter to wait for a WM_STATE change notification on a window */
static Bool is_wm_state_notify( Display *display, XEvent *event, XPointer arg )
{
if (event->xany.window != (Window)arg) return 0;
return (event->type == DestroyNotify ||
(event->type == PropertyNotify && event->xproperty.atom == x11drv_atom(WM_STATE)));
}
/***********************************************************************
* wait_for_withdrawn_state
*/
void wait_for_withdrawn_state( HWND hwnd, BOOL set )
{
Display *display = thread_display();
struct x11drv_win_data *data;
DWORD end = NtGetTickCount() + 2000;
TRACE( "waiting for window %p to become %swithdrawn\n", hwnd, set ? "" : "not " );
for (;;)
{
XEvent event;
Window window;
int count = 0;
if (!(data = get_win_data( hwnd ))) break;
if (!data->managed || data->embedded || data->display != display) break;
if (!(window = data->whole_window)) break;
if (!data->mapped == !set)
{
TRACE( "window %p/%lx now %smapped\n", hwnd, window, data->mapped ? "" : "un" );
break;
}
if ((data->wm_state == WithdrawnState) != !set)
{
TRACE( "window %p/%lx state now %d\n", hwnd, window, data->wm_state );
break;
}
release_win_data( data );
while (XCheckIfEvent( display, &event, is_wm_state_notify, (char *)window ))
{
count++;
if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */
if (event.type == DestroyNotify) call_event_handler( display, &event );
else handle_wm_state_notify( hwnd, &event.xproperty, FALSE );
}
if (!count)
{
struct pollfd pfd;
int timeout = end - NtGetTickCount();
pfd.fd = ConnectionNumber(display);
pfd.events = POLLIN;
if (timeout <= 0 || poll( &pfd, 1, timeout ) != 1)
{
FIXME( "window %p/%lx wait timed out\n", hwnd, window );
return;
}
}
}
release_win_data( data );
}
/***************************************************************** /*****************************************************************
* SetFocus (X11DRV.@) * SetFocus (X11DRV.@)
* *

View file

@ -1213,7 +1213,10 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat
{ {
UINT i, count, old_state = data->pending_state.net_wm_state; UINT i, count, old_state = data->pending_state.net_wm_state;
data->desired_state.net_wm_state = new_state;
if (!data->whole_window) return; /* no window, nothing to update */ if (!data->whole_window) return; /* no window, nothing to update */
if (data->wm_state_serial) return; /* another WM_STATE update is pending, wait for it to complete */
/* we ignore and override previous _NET_WM_STATE update requests */
if (old_state == new_state) return; /* states are the same, nothing to update */ if (old_state == new_state) return; /* states are the same, nothing to update */
if (data->pending_state.wm_state == IconicState) return; /* window is iconic, don't update its state now */ if (data->pending_state.wm_state == IconicState) return; /* window is iconic, don't update its state now */
@ -1267,6 +1270,8 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat
SubstructureRedirectMask | SubstructureNotifyMask, &xev ); SubstructureRedirectMask | SubstructureNotifyMask, &xev );
} }
} }
XFlush( data->display );
} }
static void window_set_config( struct x11drv_win_data *data, const RECT *new_rect, BOOL above ) static void window_set_config( struct x11drv_win_data *data, const RECT *new_rect, BOOL above )
@ -1275,6 +1280,7 @@ static void window_set_config( struct x11drv_win_data *data, const RECT *new_rec
const RECT *old_rect = &data->pending_state.rect; const RECT *old_rect = &data->pending_state.rect;
XWindowChanges changes; XWindowChanges changes;
data->desired_state.rect = *new_rect;
if (!data->whole_window) return; /* no window, nothing to update */ if (!data->whole_window) return; /* no window, nothing to update */
if (EqualRect( old_rect, new_rect )) return; /* rects are the same, nothing to update */ if (EqualRect( old_rect, new_rect )) return; /* rects are the same, nothing to update */
@ -1328,7 +1334,7 @@ static void update_net_wm_states( struct x11drv_win_data *data )
style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE );
if (style & WS_MINIMIZE) if (style & WS_MINIMIZE)
new_state |= data->pending_state.net_wm_state & ((1 << NET_WM_STATE_FULLSCREEN)|(1 << NET_WM_STATE_MAXIMIZED)); new_state |= data->desired_state.net_wm_state & ((1 << NET_WM_STATE_FULLSCREEN)|(1 << NET_WM_STATE_MAXIMIZED));
if (data->is_fullscreen) if (data->is_fullscreen)
{ {
if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION) if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION)
@ -1412,7 +1418,9 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state )
{ {
UINT old_state = data->pending_state.wm_state; UINT old_state = data->pending_state.wm_state;
data->desired_state.wm_state = new_state;
if (!data->whole_window) return; /* no window, nothing to update */ if (!data->whole_window) return; /* no window, nothing to update */
if (data->wm_state_serial) return; /* another WM_STATE update is pending, wait for it to complete */
if (old_state == new_state) return; /* states are the same, nothing to update */ if (old_state == new_state) return; /* states are the same, nothing to update */
data->pending_state.wm_state = new_state; data->pending_state.wm_state = new_state;
@ -1438,6 +1446,11 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state )
if (!data->embedded) XIconifyWindow( data->display, data->whole_window, data->vis.screen ); if (!data->embedded) XIconifyWindow( data->display, data->whole_window, data->vis.screen );
break; break;
} }
/* override redirect windows won't receive WM_STATE property changes */
if (!data->managed) data->wm_state_serial = 0;
XFlush( data->display );
} }
@ -1449,7 +1462,6 @@ static void map_window( HWND hwnd, DWORD new_style )
struct x11drv_win_data *data; struct x11drv_win_data *data;
make_owner_managed( hwnd ); make_owner_managed( hwnd );
wait_for_withdrawn_state( hwnd, TRUE );
if (!(data = get_win_data( hwnd ))) return; if (!(data = get_win_data( hwnd ))) return;
@ -1463,7 +1475,6 @@ static void map_window( HWND hwnd, DWORD new_style )
sync_window_style( data ); sync_window_style( data );
window_set_wm_state( data, (new_style & WS_MINIMIZE) ? IconicState : NormalState ); window_set_wm_state( data, (new_style & WS_MINIMIZE) ? IconicState : NormalState );
XFlush( data->display );
data->mapped = TRUE; data->mapped = TRUE;
data->iconic = (new_style & WS_MINIMIZE) != 0; data->iconic = (new_style & WS_MINIMIZE) != 0;
@ -1480,8 +1491,6 @@ static void unmap_window( HWND hwnd )
{ {
struct x11drv_win_data *data; struct x11drv_win_data *data;
wait_for_withdrawn_state( hwnd, FALSE );
if (!(data = get_win_data( hwnd ))) return; if (!(data = get_win_data( hwnd ))) return;
if (data->mapped) if (data->mapped)
@ -1500,6 +1509,10 @@ UINT window_update_client_state( struct x11drv_win_data *data )
if (!data->managed) return 0; /* unmanaged windows are managed by the Win32 side */ if (!data->managed) return 0; /* unmanaged windows are managed by the Win32 side */
if (!data->mapped) return 0; /* ignore state changes on invisible windows */ if (!data->mapped) return 0; /* ignore state changes on invisible windows */
if (data->wm_state_serial) return 0; /* another WM_STATE update is pending, wait for it to complete */
if (data->net_wm_state_serial) return 0; /* another _NET_WM_STATE update is pending, wait for it to complete */
if (data->configure_serial) return 0; /* another config update is pending, wait for it to complete */
if (data->iconic && data->current_state.wm_state == NormalState) /* restore window */ if (data->iconic && data->current_state.wm_state == NormalState) /* restore window */
{ {
data->iconic = FALSE; data->iconic = FALSE;
@ -1540,6 +1553,8 @@ UINT window_update_client_config( struct x11drv_win_data *data )
if (!data->mapped) return 0; /* ignore config changes on invisible windows */ if (!data->mapped) return 0; /* ignore config changes on invisible windows */
if (data->iconic) return 0; /* ignore config changes on minimized windows */ if (data->iconic) return 0; /* ignore config changes on minimized windows */
if (data->wm_state_serial) return 0; /* another WM_STATE update is pending, wait for it to complete */
if (data->net_wm_state_serial) return 0; /* another _NET_WM_STATE update is pending, wait for it to complete */
if (data->configure_serial) return 0; /* another config update is pending, wait for it to complete */ if (data->configure_serial) return 0; /* another config update is pending, wait for it to complete */
if ((old_style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen) if ((old_style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen)
@ -1572,7 +1587,7 @@ UINT window_update_client_config( struct x11drv_win_data *data )
void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ) void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value )
{ {
UINT *pending = &data->pending_state.wm_state, *current = &data->current_state.wm_state; UINT *desired = &data->desired_state.wm_state, *pending = &data->pending_state.wm_state, *current = &data->current_state.wm_state;
unsigned long *expect_serial = &data->wm_state_serial; unsigned long *expect_serial = &data->wm_state_serial;
const char *reason = NULL, *expected, *received; const char *reason = NULL, *expected, *received;
@ -1597,16 +1612,20 @@ void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial,
else else
{ {
WARN( "window %p/%lx, %s%s%s\n", data->hwnd, data->whole_window, reason, received, expected ); WARN( "window %p/%lx, %s%s%s\n", data->hwnd, data->whole_window, reason, received, expected );
*pending = value; /* avoid requesting the same state again */ *desired = *pending = value; /* avoid requesting the same state again */
} }
*current = value; *current = value;
*expect_serial = 0; *expect_serial = 0;
/* send any pending changes from the desired state */
window_set_wm_state( data, data->desired_state.wm_state );
window_set_net_wm_state( data, data->desired_state.net_wm_state );
} }
void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ) void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value )
{ {
UINT *pending = &data->pending_state.net_wm_state, *current = &data->current_state.net_wm_state; UINT *desired = &data->desired_state.net_wm_state, *pending = &data->pending_state.net_wm_state, *current = &data->current_state.net_wm_state;
unsigned long *expect_serial = &data->net_wm_state_serial; unsigned long *expect_serial = &data->net_wm_state_serial;
const char *reason = NULL, *expected, *received; const char *reason = NULL, *expected, *received;
@ -1629,16 +1648,20 @@ void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long ser
else else
{ {
WARN( "window %p/%lx, %s%s%s\n", data->hwnd, data->whole_window, reason, received, expected ); WARN( "window %p/%lx, %s%s%s\n", data->hwnd, data->whole_window, reason, received, expected );
*pending = value; /* avoid requesting the same state again */ *desired = *pending = value; /* avoid requesting the same state again */
} }
*current = value; *current = value;
*expect_serial = 0; *expect_serial = 0;
/* send any pending changes from the desired state */
window_set_wm_state( data, data->desired_state.wm_state );
window_set_net_wm_state( data, data->desired_state.net_wm_state );
} }
void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *value ) void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *value )
{ {
RECT *pending = &data->pending_state.rect, *current = &data->current_state.rect; RECT *desired = &data->desired_state.rect, *pending = &data->pending_state.rect, *current = &data->current_state.rect;
unsigned long *expect_serial = &data->configure_serial; unsigned long *expect_serial = &data->configure_serial;
const char *reason = NULL, *expected, *received; const char *reason = NULL, *expected, *received;
@ -1661,7 +1684,7 @@ void window_configure_notify( struct x11drv_win_data *data, unsigned long serial
else else
{ {
WARN( "window %p/%lx, %s%s%s\n", data->hwnd, data->whole_window, reason, received, expected ); WARN( "window %p/%lx, %s%s%s\n", data->hwnd, data->whole_window, reason, received, expected );
*pending = *value; /* avoid requesting the same state again */ *desired = *pending = *value; /* avoid requesting the same state again */
} }
*current = *value; *current = *value;
@ -1674,7 +1697,7 @@ BOOL window_has_pending_wm_state( HWND hwnd, UINT state )
BOOL pending; BOOL pending;
if (!(data = get_win_data( hwnd ))) return FALSE; if (!(data = get_win_data( hwnd ))) return FALSE;
if (state != -1 && data->pending_state.wm_state != state) pending = FALSE; if (state != -1 && data->desired_state.wm_state != state) pending = FALSE;
else pending = !!data->wm_state_serial; else pending = !!data->wm_state_serial;
release_win_data( data ); release_win_data( data );
@ -2044,6 +2067,7 @@ static void create_whole_window( struct x11drv_win_data *data )
if (!data->whole_window) goto done; if (!data->whole_window) goto done;
SetRect( &data->current_state.rect, pos.x, pos.y, pos.x + cx, pos.y + cy ); SetRect( &data->current_state.rect, pos.x, pos.y, pos.x + cx, pos.y + cy );
data->pending_state.rect = data->current_state.rect; data->pending_state.rect = data->current_state.rect;
data->desired_state.rect = data->current_state.rect;
x11drv_xinput2_enable( data->display, data->whole_window ); x11drv_xinput2_enable( data->display, data->whole_window );
set_initial_wm_hints( data->display, data->whole_window ); set_initial_wm_hints( data->display, data->whole_window );
@ -2098,9 +2122,9 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des
if (data->whole_colormap) XFreeColormap( data->display, data->whole_colormap ); if (data->whole_colormap) XFreeColormap( data->display, data->whole_colormap );
data->whole_window = data->client_window = 0; data->whole_window = data->client_window = 0;
data->whole_colormap = 0; data->whole_colormap = 0;
data->wm_state = WithdrawnState;
data->mapped = FALSE; data->mapped = FALSE;
memset( &data->desired_state, 0, sizeof(data->desired_state) );
memset( &data->pending_state, 0, sizeof(data->pending_state) ); memset( &data->pending_state, 0, sizeof(data->pending_state) );
memset( &data->current_state, 0, sizeof(data->current_state) ); memset( &data->current_state, 0, sizeof(data->current_state) );
data->wm_state_serial = 0; data->wm_state_serial = 0;

View file

@ -633,13 +633,13 @@ struct x11drv_win_data
UINT net_wm_fullscreen_monitors_set : 1; /* is _NET_WM_FULLSCREEN_MONITORS set */ UINT net_wm_fullscreen_monitors_set : 1; /* is _NET_WM_FULLSCREEN_MONITORS set */
UINT is_fullscreen : 1; /* is the window visible rect fullscreen */ UINT is_fullscreen : 1; /* is the window visible rect fullscreen */
UINT parent_invalid : 1; /* is the parent host window possibly invalid */ UINT parent_invalid : 1; /* is the parent host window possibly invalid */
int wm_state; /* current value of the WM_STATE property */
Window embedder; /* window id of embedder */ Window embedder; /* window id of embedder */
Pixmap icon_pixmap; Pixmap icon_pixmap;
Pixmap icon_mask; Pixmap icon_mask;
unsigned long *icon_bits; unsigned long *icon_bits;
unsigned int icon_size; unsigned int icon_size;
struct window_state desired_state; /* window state tracking the desired / win32 state */
struct window_state pending_state; /* window state tracking the pending / requested state */ struct window_state pending_state; /* window state tracking the pending / requested state */
struct window_state current_state; /* window state tracking the current X11 state */ struct window_state current_state; /* window state tracking the current X11 state */
unsigned long wm_state_serial; /* serial of last pending WM_STATE request */ unsigned long wm_state_serial; /* serial of last pending WM_STATE request */
@ -665,7 +665,6 @@ extern void window_configure_notify( struct x11drv_win_data *data, unsigned long
extern UINT window_update_client_state( struct x11drv_win_data *data ); extern UINT window_update_client_state( struct x11drv_win_data *data );
extern UINT window_update_client_config( struct x11drv_win_data *data ); extern UINT window_update_client_config( struct x11drv_win_data *data );
extern void wait_for_withdrawn_state( HWND hwnd, BOOL set );
extern Window init_clip_window(void); extern Window init_clip_window(void);
extern void update_user_time( Time time ); extern void update_user_time( Time time );
extern UINT get_window_net_wm_state( Display *display, Window window ); extern UINT get_window_net_wm_state( Display *display, Window window );

View file

@ -1240,3 +1240,211 @@ HRESULT WINAPI RoResolveNamespace(HSTRING name, HSTRING windowsMetaDataDir,
return RO_E_METADATA_NAME_NOT_FOUND; return RO_E_METADATA_NAME_NOT_FOUND;
} }
struct parse_type_context
{
DWORD allocated_parts_count;
DWORD parts_count;
HSTRING *parts;
};
static HRESULT add_part(struct parse_type_context *context, const WCHAR *part, size_t length)
{
DWORD new_parts_count;
HSTRING *new_parts;
HRESULT hr;
if (context->parts_count == context->allocated_parts_count)
{
new_parts_count = context->allocated_parts_count ? context->allocated_parts_count * 2 : 4;
new_parts = CoTaskMemRealloc(context->parts, new_parts_count * sizeof(*context->parts));
if (!new_parts)
return E_OUTOFMEMORY;
context->allocated_parts_count = new_parts_count;
context->parts = new_parts;
}
if (FAILED(hr = WindowsCreateString(part, length, &context->parts[context->parts_count])))
return hr;
context->parts_count++;
return S_OK;
}
static HRESULT parse_part(struct parse_type_context *context, const WCHAR *input, unsigned int length)
{
const WCHAR *start, *end, *ptr;
start = input;
end = start + length;
/* Remove leading spaces */
while (start < end && *start == ' ')
start++;
/* Remove trailing spaces */
while (end - 1 >= start && end[-1] == ' ')
end--;
/* Only contains spaces */
if (start == end)
return RO_E_METADATA_INVALID_TYPE_FORMAT;
/* Has spaces in the middle */
for (ptr = start; ptr < end; ptr++)
{
if (*ptr == ' ')
return RO_E_METADATA_INVALID_TYPE_FORMAT;
}
return add_part(context, start, end - start);
}
static HRESULT parse_type(struct parse_type_context *context, const WCHAR *input, unsigned int length)
{
unsigned int i, parameter_count, nested_level;
const WCHAR *start, *end, *part_start, *ptr;
HRESULT hr;
start = input;
end = start + length;
part_start = start;
ptr = start;
/* Read until the end of input or '`' or '<' or '>' or ',' */
while (ptr < end && *ptr != '`' && *ptr != '<' && *ptr != '>' && *ptr != ',')
ptr++;
/* If the type name has '`' and there are characters before '`' */
if (ptr > start && ptr < end && *ptr == '`')
{
/* Move past the '`' */
ptr++;
/* Read the number of type parameters, expecting '1' to '9' */
if (!(ptr < end && *ptr >= '1' && *ptr <= '9'))
return RO_E_METADATA_INVALID_TYPE_FORMAT;
parameter_count = *ptr - '0';
/* Move past the number of type parameters, expecting '<' */
ptr++;
if (!(ptr < end && *ptr == '<'))
return RO_E_METADATA_INVALID_TYPE_FORMAT;
/* Add the name of parameterized interface, e.g., the "interface`1" in "interface`1<parameter>" */
if (FAILED(hr = parse_part(context, part_start, ptr - part_start)))
return hr;
/* Move past the '<' */
ptr++;
nested_level = 1;
/* Read parameters inside brackets, e.g., the "p1" and "p2" in "interface`2<p1, p2>" */
for (i = 0; i < parameter_count; i++)
{
/* Read a new parameter */
part_start = ptr;
/* Read until ','. The comma must be at the same nested bracket level */
while (ptr < end)
{
if (*ptr == '<')
{
nested_level++;
ptr++;
}
else if (*ptr == '>')
{
/* The last parameter before '>' */
if (i == parameter_count - 1 && nested_level == 1)
{
if (FAILED(hr = parse_type(context, part_start, ptr - part_start)))
return hr;
nested_level--;
ptr++;
/* Finish reading all parameters */
break;
}
nested_level--;
ptr++;
}
else if (*ptr == ',' && nested_level == 1)
{
/* Parse the parameter, which can be another parameterized type */
if (FAILED(hr = parse_type(context, part_start, ptr - part_start)))
return hr;
/* Move past the ',' */
ptr++;
/* Finish reading one parameter */
break;
}
else
{
ptr++;
}
}
}
/* Mismatching brackets or not enough parameters */
if (nested_level != 0 || i != parameter_count)
return RO_E_METADATA_INVALID_TYPE_FORMAT;
/* The remaining characters must be spaces */
while (ptr < end)
{
if (*ptr++ != ' ')
return RO_E_METADATA_INVALID_TYPE_FORMAT;
}
return S_OK;
}
/* Contain invalid '`', '<', '>' or ',' */
else if (ptr != end)
{
return RO_E_METADATA_INVALID_TYPE_FORMAT;
}
/* Non-parameterized */
else
{
return parse_part(context, part_start, ptr - part_start);
}
}
HRESULT WINAPI RoParseTypeName(HSTRING type_name, DWORD *parts_count, HSTRING **parts)
{
struct parse_type_context context = {0};
const WCHAR *input;
unsigned int i;
HRESULT hr;
TRACE("%s %p %p.\n", debugstr_hstring(type_name), parts_count, parts);
/* Empty string */
if (!WindowsGetStringLen(type_name))
return E_INVALIDARG;
input = WindowsGetStringRawBuffer(type_name, NULL);
/* The string has a leading space */
if (input[0] == ' ')
return RO_E_METADATA_INVALID_TYPE_FORMAT;
*parts_count = 0;
*parts = NULL;
if (FAILED(hr = parse_type(&context, input, wcslen(input))))
{
for (i = 0; i < context.parts_count; i++)
WindowsDeleteString(context.parts[i]);
CoTaskMemFree(context.parts);
return hr;
}
*parts_count = context.parts_count;
*parts = context.parts;
return S_OK;
}

View file

@ -814,11 +814,159 @@ static void test_RoResolveNamespace(void)
RoUninitialize(); RoUninitialize();
} }
static void test_RoParseTypeName(void)
{
static const struct
{
const WCHAR *type_name;
HRESULT hr;
DWORD parts_count;
const WCHAR *parts[16];
}
tests[] =
{
/* Invalid type names */
{L"", E_INVALIDARG},
{L" ", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"`", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"<", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L">", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L",", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"<>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"`<>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a b", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a,b", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"1<>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L" a", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L" a ", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a<", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a<>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`<>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`1<>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a<b>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`<b> ", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"`1<b>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L" a`1<b>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`1<b>c", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`1<b,>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`2<b, <c, d>>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`10<b1, b2, b3, b4, b5, b6, b7, b8, b9, b10>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`0xa<b1, b2, b3, b4, b5, b6, b7, b8, b9, b10>", RO_E_METADATA_INVALID_TYPE_FORMAT},
{L"a`a<b1, b2, b3, b4, b5, b6, b7, b8, b9, b10>", RO_E_METADATA_INVALID_TYPE_FORMAT},
/* Valid type names */
{L"1", S_OK, 1, {L"1"}},
{L"a", S_OK, 1, {L"a"}},
{L"-", S_OK, 1, {L"-"}},
{L"a ", S_OK, 1, {L"a"}},
{L"0`1<b>", S_OK, 2, {L"0`1", L"b"}},
{L"a`1<b>", S_OK, 2, {L"a`1", L"b"}},
{L"a`1<b> ", S_OK, 2, {L"a`1", L"b"}},
{L"a`1<b >", S_OK, 2, {L"a`1", L"b"}},
{L"a`1< b>", S_OK, 2, {L"a`1", L"b"}},
{L"a`1< b >", S_OK, 2, {L"a`1", L"b"}},
{L"a`2<b,c>", S_OK, 3, {L"a`2", L"b", L"c"}},
{L"a`2<b, c>", S_OK, 3, {L"a`2", L"b", L"c"}},
{L"a`2<b ,c>", S_OK, 3, {L"a`2", L"b", L"c"}},
{L"a`2<b , c>", S_OK, 3, {L"a`2", L"b", L"c"}},
{L"a`3<b, c, d>", S_OK, 4, {L"a`3", L"b", L"c", L"d"}},
{L"a`1<b`1<c>>", S_OK, 3, {L"a`1", L"b`1", L"c"}},
{L"a`1<b`2<c, d>>", S_OK, 4, {L"a`1", L"b`2", L"c", L"d"}},
{L"a`2<b`2<c, d>, e>", S_OK, 5, {L"a`2", L"b`2", L"c", L"d", L"e"}},
{L"a`2<b, c`2<d, e>>", S_OK, 5, {L"a`2", L"b", L"c`2", L"d", L"e"}},
{L"a`9<b1, b2, b3, b4, b5, b6, b7, b8, b9>", S_OK, 10, {L"a`9", L"b1", L"b2", L"b3", L"b4", L"b5", L"b6", L"b7", L"b8", L"b9"}},
{L"Windows.Foundation.IExtensionInformation", S_OK, 1, {L"Windows.Foundation.IExtensionInformation"}},
{L"Windows.Foundation.IReference`1<Windows.UI.Color>", S_OK, 2, {L"Windows.Foundation.IReference`1", L"Windows.UI.Color"}},
{L"Windows.Foundation.Collections.IIterator`1<Windows.Foundation.Collections.IMapView`2<Windows.Foundation.Collections.IVector`1<String>, String>>",
S_OK, 5, {L"Windows.Foundation.Collections.IIterator`1",
L"Windows.Foundation.Collections.IMapView`2",
L"Windows.Foundation.Collections.IVector`1",
L"String",
L"String"}},
};
HSTRING type_name, *parts;
const WCHAR *buffer;
DWORD parts_count;
unsigned int i, j;
HRESULT hr;
/* Parameter checks */
hr = WindowsCreateString(L"a", 1, &type_name);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = RoParseTypeName(NULL, &parts_count, &parts);
ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
/* Crash on Windows */
if (0)
{
hr = RoParseTypeName(type_name, NULL, &parts);
ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
hr = RoParseTypeName(type_name, &parts_count, NULL);
ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
}
hr = RoParseTypeName(type_name, &parts_count, &parts);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
ok(parts_count == 1, "Got unexpected %ld.\n", parts_count);
hr = WindowsDeleteString(parts[0]);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
CoTaskMemFree(parts);
hr = WindowsDeleteString(type_name);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
/* Parsing checks */
for (i = 0; i < ARRAY_SIZE(tests); i++)
{
winetest_push_context("%s", wine_dbgstr_w(tests[i].type_name));
if (tests[i].type_name)
{
hr = WindowsCreateString(tests[i].type_name, wcslen(tests[i].type_name), &type_name);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
}
else
{
type_name = NULL;
}
parts_count = 0;
hr = RoParseTypeName(type_name, &parts_count, &parts);
ok(hr == tests[i].hr, "Got unexpected hr %#lx.\n", hr);
if (FAILED(hr))
{
hr = WindowsDeleteString(type_name);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
winetest_pop_context();
continue;
}
ok(parts_count == tests[i].parts_count, "Got unexpected %lu.\n", parts_count);
for (j = 0; j < parts_count; j++)
{
winetest_push_context("%s", wine_dbgstr_w(tests[i].parts[j]));
buffer = WindowsGetStringRawBuffer(parts[j], NULL);
ok(!lstrcmpW(tests[i].parts[j], buffer), "Got unexpected %s.\n", wine_dbgstr_w(buffer));
hr = WindowsDeleteString(parts[j]);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
winetest_pop_context();
}
CoTaskMemFree(parts);
hr = WindowsDeleteString(type_name);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
winetest_pop_context();
}
}
START_TEST(wintypes) START_TEST(wintypes)
{ {
IsWow64Process(GetCurrentProcess(), &is_wow64); IsWow64Process(GetCurrentProcess(), &is_wow64);
test_IApiInformationStatics(); test_IApiInformationStatics();
test_IPropertyValueStatics(); test_IPropertyValueStatics();
test_RoParseTypeName();
test_RoResolveNamespace(); test_RoResolveNamespace();
} }

View file

@ -7,5 +7,5 @@
@ stub RoGetMetaDataFile @ stub RoGetMetaDataFile
@ stdcall RoIsApiContractMajorVersionPresent(wstr long ptr) @ stdcall RoIsApiContractMajorVersionPresent(wstr long ptr)
@ stub RoIsApiContractPresent @ stub RoIsApiContractPresent
@ stub RoParseTypeName @ stdcall RoParseTypeName(ptr ptr ptr)
@ stdcall RoResolveNamespace(ptr ptr long ptr ptr ptr ptr ptr) @ stdcall RoResolveNamespace(ptr ptr long ptr ptr ptr ptr ptr)

View file

@ -1395,7 +1395,6 @@ static NTSTATUS WINAPI wow64_NtUserPostDDEMessage( void *arg, ULONG size )
LONG wparam; LONG wparam;
LONG lparam; LONG lparam;
DWORD dest_tid; DWORD dest_tid;
DWORD type;
} params32; } params32;
params32.hwnd = HandleToUlong( params->hwnd ); params32.hwnd = HandleToUlong( params->hwnd );
@ -1403,7 +1402,6 @@ static NTSTATUS WINAPI wow64_NtUserPostDDEMessage( void *arg, ULONG size )
params32.wparam = params->wparam; params32.wparam = params->wparam;
params32.lparam = params->lparam; params32.lparam = params->lparam;
params32.dest_tid = params->dest_tid; params32.dest_tid = params->dest_tid;
params32.type = params->type;
return dispatch_callback( NtUserPostDDEMessage, &params32, sizeof(params32) ); return dispatch_callback( NtUserPostDDEMessage, &params32, sizeof(params32) );
} }
@ -1635,6 +1633,26 @@ NTSTATUS WINAPI wow64_NtUserBuildHwndList( UINT *args )
return status; return status;
} }
NTSTATUS WINAPI wow64_NtUserBuildNameList( UINT *args )
{
HWINSTA handle = get_handle( &args );
ULONG count = get_ulong( &args );
struct ntuser_name_list *props = get_ptr( &args );
ULONG *ret_count = get_ptr( &args );
return NtUserBuildNameList( handle, count, props, ret_count );
}
NTSTATUS WINAPI wow64_NtUserBuildPropList( UINT *args )
{
HWND hwnd = get_handle( &args );
ULONG count = get_ulong( &args );
struct ntuser_property_list *props = get_ptr( &args );
ULONG *ret_count = get_ptr( &args );
return NtUserBuildPropList( hwnd, count, props, ret_count );
}
NTSTATUS WINAPI wow64_NtUserCallHwnd( UINT *args ) NTSTATUS WINAPI wow64_NtUserCallHwnd( UINT *args )
{ {
HWND hwnd = get_handle( &args ); HWND hwnd = get_handle( &args );
@ -3656,6 +3674,22 @@ NTSTATUS WINAPI wow64_NtUserMessageCall( UINT *args )
return status; return status;
} }
return NtUserMessageCall( hwnd, msg, wparam, lparam, result_info, type, ansi ); return NtUserMessageCall( hwnd, msg, wparam, lparam, result_info, type, ansi );
case NtUserPostDdeCall:
{
struct
{
ULONG ptr;
UINT size;
DWORD dest_tid;
} *params32 = result_info;
struct post_dde_message_call_params params;
params.ptr = UlongToPtr(params32->ptr);
params.size = params32->size;
params.dest_tid = params32->dest_tid;
return NtUserMessageCall( hwnd, msg, wparam, lparam, &params, type, ansi );
}
} }
return message_call_32to64( hwnd, msg, wparam, lparam, result_info, type, ansi ); return message_call_32to64( hwnd, msg, wparam, lparam, result_info, type, ansi );

View file

@ -279,7 +279,6 @@ struct post_dde_message_params
WPARAM wparam; WPARAM wparam;
LPARAM lparam; LPARAM lparam;
DWORD dest_tid; DWORD dest_tid;
DWORD type;
}; };
/* NtUserRenderSynthesizedFormat params */ /* NtUserRenderSynthesizedFormat params */
@ -398,6 +397,7 @@ enum
NtUserImeDriverCall = 0x0305, NtUserImeDriverCall = 0x0305,
NtUserSystemTrayCall = 0x0306, NtUserSystemTrayCall = 0x0306,
NtUserDragDropCall = 0x0307, NtUserDragDropCall = 0x0307,
NtUserPostDdeCall = 0x0308,
}; };
/* NtUserThunkedMenuItemInfo codes */ /* NtUserThunkedMenuItemInfo codes */
@ -428,6 +428,13 @@ struct send_message_callback_params
ULONG_PTR data; ULONG_PTR data;
}; };
struct post_dde_message_call_params
{
void *ptr;
UINT size;
DWORD dest_tid;
};
/* color index used to retrieve system 55aa brush */ /* color index used to retrieve system 55aa brush */
#define COLOR_55AA_BRUSH 0x100 #define COLOR_55AA_BRUSH 0x100
@ -661,6 +668,20 @@ enum wine_drag_drop_call
WINE_DRAG_DROP_POST, WINE_DRAG_DROP_POST,
}; };
struct ntuser_property_list
{
UINT64 data;
ATOM atom;
BOOLEAN string; /* Wine extension */
};
struct ntuser_name_list
{
ULONG size;
ULONG count;
WCHAR strings[1];
};
#define WM_SYSTIMER 0x0118 #define WM_SYSTIMER 0x0118
@ -672,6 +693,8 @@ W32KAPI HDC WINAPI NtUserBeginPaint( HWND hwnd, PAINTSTRUCT *ps );
W32KAPI NTSTATUS WINAPI NtUserBuildHimcList( UINT thread_id, UINT count, HIMC *buffer, UINT *size ); W32KAPI NTSTATUS WINAPI NtUserBuildHimcList( UINT thread_id, UINT count, HIMC *buffer, UINT *size );
W32KAPI NTSTATUS WINAPI NtUserBuildHwndList( HDESK desktop, ULONG unk2, ULONG unk3, ULONG unk4, W32KAPI NTSTATUS WINAPI NtUserBuildHwndList( HDESK desktop, ULONG unk2, ULONG unk3, ULONG unk4,
ULONG thread_id, ULONG count, HWND *buffer, ULONG *size ); ULONG thread_id, ULONG count, HWND *buffer, ULONG *size );
W32KAPI NTSTATUS WINAPI NtUserBuildNameList( HWINSTA winsta, ULONG size, struct ntuser_name_list *buffer, ULONG *ret_size );
W32KAPI NTSTATUS WINAPI NtUserBuildPropList( HWND hwnd, ULONG count, struct ntuser_property_list *buffer, ULONG *ret_count );
W32KAPI ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code ); W32KAPI ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code );
W32KAPI ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ); W32KAPI ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code );
W32KAPI LRESULT WINAPI NtUserCallNextHookEx( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ); W32KAPI LRESULT WINAPI NtUserCallNextHookEx( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam );
@ -1019,6 +1042,7 @@ enum
NtUserCallOneParam_GetSystemMetrics, NtUserCallOneParam_GetSystemMetrics,
NtUserCallOneParam_GetVirtualScreenRect, NtUserCallOneParam_GetVirtualScreenRect,
NtUserCallOneParam_MessageBeep, NtUserCallOneParam_MessageBeep,
NtUserCallOneParam_PostQuitMessage,
NtUserCallOneParam_RealizePalette, NtUserCallOneParam_RealizePalette,
NtUserCallOneParam_ReplyMessage, NtUserCallOneParam_ReplyMessage,
NtUserCallOneParam_SetCaretBlinkTime, NtUserCallOneParam_SetCaretBlinkTime,
@ -1125,6 +1149,11 @@ static inline BOOL NtUserMessageBeep( UINT i )
return NtUserCallOneParam( i, NtUserCallOneParam_MessageBeep ); return NtUserCallOneParam( i, NtUserCallOneParam_MessageBeep );
} }
static inline void NtUserPostQuitMessage( INT exit_code )
{
NtUserCallOneParam( exit_code, NtUserCallOneParam_PostQuitMessage );
}
static inline UINT NtUserRealizePalette( HDC hdc ) static inline UINT NtUserRealizePalette( HDC hdc )
{ {
return NtUserCallOneParam( HandleToUlong(hdc), NtUserCallOneParam_RealizePalette ); return NtUserCallOneParam( HandleToUlong(hdc), NtUserCallOneParam_RealizePalette );

View file

@ -16,13 +16,20 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#define PATHCCH_NONE 0x00 #ifdef __cplusplus
#define PATHCCH_ALLOW_LONG_PATHS 0x01 extern "C" {
#define PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS 0x02 #endif
#define PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS 0x04
#define PATHCCH_DO_NOT_NORMALIZE_SEGMENTS 0x08 typedef enum PATHCCH_OPTIONS
#define PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH 0x10 {
#define PATHCCH_ENSURE_TRAILING_SLASH 0x20 PATHCCH_NONE = 0x00,
PATHCCH_ALLOW_LONG_PATHS = 0x01,
PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS = 0x02,
PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS = 0x04,
PATHCCH_DO_NOT_NORMALIZE_SEGMENTS = 0x08,
PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH = 0x10,
PATHCCH_ENSURE_TRAILING_SLASH = 0x20,
} PATHCCH_OPTIONS;
#define PATHCCH_MAX_CCH 0x8000 #define PATHCCH_MAX_CCH 0x8000
@ -48,3 +55,7 @@ WINBASEAPI HRESULT WINAPI PathCchSkipRoot(const WCHAR *path, const WCHAR **root_
WINBASEAPI HRESULT WINAPI PathCchStripPrefix(WCHAR *path, SIZE_T size); WINBASEAPI HRESULT WINAPI PathCchStripPrefix(WCHAR *path, SIZE_T size);
WINBASEAPI HRESULT WINAPI PathCchStripToRoot(WCHAR *path, SIZE_T size); WINBASEAPI HRESULT WINAPI PathCchStripToRoot(WCHAR *path, SIZE_T size);
WINBASEAPI BOOL WINAPI PathIsUNCEx(const WCHAR *path, const WCHAR **server); WINBASEAPI BOOL WINAPI PathIsUNCEx(const WCHAR *path, const WCHAR **server);
#ifdef __cplusplus
}
#endif

View file

@ -23,6 +23,7 @@
#include <hstring.h> #include <hstring.h>
HRESULT WINAPI RoIsApiContractMajorVersionPresent(const WCHAR *, UINT16, BOOL *); HRESULT WINAPI RoIsApiContractMajorVersionPresent(const WCHAR *, UINT16, BOOL *);
HRESULT WINAPI RoParseTypeName(HSTRING, DWORD *, HSTRING **);
HRESULT WINAPI RoResolveNamespace(HSTRING, HSTRING, DWORD, const HSTRING *, DWORD *, HSTRING **, DWORD *, HSTRING **); HRESULT WINAPI RoResolveNamespace(HSTRING, HSTRING, DWORD, const HSTRING *, DWORD *, HSTRING **, DWORD *, HSTRING **);
#endif /* _ROMETADATARESOLUTION_H */ #endif /* _ROMETADATARESOLUTION_H */

View file

@ -1573,6 +1573,7 @@ WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfaceAlias(HDEVINFO, PSP_DEVICE_
WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA); WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA);
WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_W, DWORD, PDWORD, PSP_DEVINFO_DATA); WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_W, DWORD, PDWORD, PSP_DEVINFO_DATA);
#define SetupDiGetDeviceInterfaceDetail WINELIB_NAME_AW(SetupDiGetDeviceInterfaceDetail) #define SetupDiGetDeviceInterfaceDetail WINELIB_NAME_AW(SetupDiGetDeviceInterfaceDetail)
WINSETUPAPI BOOL WINAPI SetupDiGetDevicePropertyKeys(HDEVINFO, PSP_DEVINFO_DATA, DEVPROPKEY *, DWORD, DWORD *, DWORD);
WINSETUPAPI BOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO, PSP_DEVINFO_DATA, const DEVPROPKEY *, DEVPROPTYPE *, BYTE *, DWORD, DWORD *, DWORD); WINSETUPAPI BOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO, PSP_DEVINFO_DATA, const DEVPROPKEY *, DEVPROPTYPE *, BYTE *, DWORD, DWORD *, DWORD);
#define SetupDiGetDeviceProperty WINELIB_NAME_AW(SetupDiGetDeviceProperty) /* note: A function doesn't exist */ #define SetupDiGetDeviceProperty WINELIB_NAME_AW(SetupDiGetDeviceProperty) /* note: A function doesn't exist */
WINSETUPAPI BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD); WINSETUPAPI BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);

View file

@ -57,7 +57,7 @@ struct request_max_size
typedef union union debug_event_data
{ {
int code; int code;
struct struct
@ -109,7 +109,7 @@ typedef union
int __pad; int __pad;
mod_handle_t base; mod_handle_t base;
} unload_dll; } unload_dll;
} debug_event_t; };
enum context_exec_space enum context_exec_space
@ -312,7 +312,7 @@ struct winevent_msg_data
}; };
typedef union union hw_input
{ {
int type; int type;
struct struct
@ -342,15 +342,15 @@ typedef union
lparam_t lparam; lparam_t lparam;
struct hid_input hid; struct hid_input hid;
} hw; } hw;
} hw_input_t; };
typedef union union message_data
{ {
unsigned char bytes[1]; unsigned char bytes[1];
struct hardware_msg_data hardware; struct hardware_msg_data hardware;
struct callback_msg_data callback; struct callback_msg_data callback;
struct winevent_msg_data winevent; struct winevent_msg_data winevent;
} message_data_t; };
struct filesystem_event struct filesystem_event
@ -435,7 +435,7 @@ struct object_type_info
}; };
enum select_op enum select_opcode
{ {
SELECT_NONE, SELECT_NONE,
SELECT_WAIT, SELECT_WAIT,
@ -445,28 +445,28 @@ enum select_op
SELECT_KEYED_EVENT_RELEASE SELECT_KEYED_EVENT_RELEASE
}; };
typedef union union select_op
{ {
enum select_op op; enum select_opcode op;
struct struct
{ {
enum select_op op; enum select_opcode op;
obj_handle_t handles[MAXIMUM_WAIT_OBJECTS]; obj_handle_t handles[MAXIMUM_WAIT_OBJECTS];
int __pad; int __pad;
} wait; } wait;
struct struct
{ {
enum select_op op; enum select_opcode op;
obj_handle_t wait; obj_handle_t wait;
obj_handle_t signal; obj_handle_t signal;
} signal_and_wait; } signal_and_wait;
struct struct
{ {
enum select_op op; enum select_opcode op;
obj_handle_t handle; obj_handle_t handle;
client_ptr_t key; client_ptr_t key;
} keyed_event; } keyed_event;
} select_op_t; };
enum apc_type enum apc_type
{ {
@ -748,7 +748,7 @@ enum irp_type
IRP_CALL_CANCEL IRP_CALL_CANCEL
}; };
typedef union union irp_params
{ {
enum irp_type type; enum irp_type type;
struct struct
@ -816,7 +816,7 @@ typedef union
int __pad; int __pad;
client_ptr_t irp; client_ptr_t irp;
} cancel; } cancel;
} irp_params_t; };
typedef struct typedef struct
@ -2970,7 +2970,7 @@ struct send_hardware_message_request
{ {
struct request_header __header; struct request_header __header;
user_handle_t win; user_handle_t win;
hw_input_t input; union hw_input input;
unsigned int flags; unsigned int flags;
/* VARARG(report,bytes); */ /* VARARG(report,bytes); */
char __pad_60[4]; char __pad_60[4];
@ -3895,14 +3895,14 @@ struct set_process_winstation_reply
struct enum_winstation_request struct enum_winstation_request
{ {
struct request_header __header; struct request_header __header;
unsigned int index; obj_handle_t handle;
}; };
struct enum_winstation_reply struct enum_winstation_reply
{ {
struct reply_header __header; struct reply_header __header;
unsigned int next; data_size_t count;
/* VARARG(name,unicode_str); */ data_size_t total;
char __pad_12[4]; /* VARARG(names,unicode_strings); */
}; };
@ -4011,23 +4011,6 @@ struct set_thread_desktop_reply
struct enum_desktop_request
{
struct request_header __header;
obj_handle_t winstation;
unsigned int index;
char __pad_20[4];
};
struct enum_desktop_reply
{
struct reply_header __header;
unsigned int next;
/* VARARG(name,unicode_str); */
char __pad_12[4];
};
struct set_user_object_info_request struct set_user_object_info_request
{ {
struct request_header __header; struct request_header __header;
@ -5239,7 +5222,7 @@ struct get_next_device_request_request
struct get_next_device_request_reply struct get_next_device_request_reply
{ {
struct reply_header __header; struct reply_header __header;
irp_params_t params; union irp_params params;
obj_handle_t next; obj_handle_t next;
thread_id_t client_tid; thread_id_t client_tid;
client_ptr_t client_thread; client_ptr_t client_thread;
@ -6052,7 +6035,6 @@ enum request
REQ_close_desktop, REQ_close_desktop,
REQ_get_thread_desktop, REQ_get_thread_desktop,
REQ_set_thread_desktop, REQ_set_thread_desktop,
REQ_enum_desktop,
REQ_set_user_object_info, REQ_set_user_object_info,
REQ_register_hotkey, REQ_register_hotkey,
REQ_unregister_hotkey, REQ_unregister_hotkey,
@ -6350,7 +6332,6 @@ union generic_request
struct close_desktop_request close_desktop_request; struct close_desktop_request close_desktop_request;
struct get_thread_desktop_request get_thread_desktop_request; struct get_thread_desktop_request get_thread_desktop_request;
struct set_thread_desktop_request set_thread_desktop_request; struct set_thread_desktop_request set_thread_desktop_request;
struct enum_desktop_request enum_desktop_request;
struct set_user_object_info_request set_user_object_info_request; struct set_user_object_info_request set_user_object_info_request;
struct register_hotkey_request register_hotkey_request; struct register_hotkey_request register_hotkey_request;
struct unregister_hotkey_request unregister_hotkey_request; struct unregister_hotkey_request unregister_hotkey_request;
@ -6646,7 +6627,6 @@ union generic_reply
struct close_desktop_reply close_desktop_reply; struct close_desktop_reply close_desktop_reply;
struct get_thread_desktop_reply get_thread_desktop_reply; struct get_thread_desktop_reply get_thread_desktop_reply;
struct set_thread_desktop_reply set_thread_desktop_reply; struct set_thread_desktop_reply set_thread_desktop_reply;
struct enum_desktop_reply enum_desktop_reply;
struct set_user_object_info_reply set_user_object_info_reply; struct set_user_object_info_reply set_user_object_info_reply;
struct register_hotkey_reply register_hotkey_reply; struct register_hotkey_reply register_hotkey_reply;
struct unregister_hotkey_reply unregister_hotkey_reply; struct unregister_hotkey_reply unregister_hotkey_reply;
@ -6758,6 +6738,6 @@ union generic_reply
struct set_keyboard_repeat_reply set_keyboard_repeat_reply; struct set_keyboard_repeat_reply set_keyboard_repeat_reply;
}; };
#define SERVER_PROTOCOL_VERSION 848 #define SERVER_PROTOCOL_VERSION 849
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View file

@ -365,7 +365,7 @@ int __cdecl wmain(int argc, const WCHAR* argv[])
if(arg_is(argv[2], L"/help")) if(arg_is(argv[2], L"/help"))
output_string(STRING_STOP_USAGE); output_string(STRING_STOP_USAGE);
else if(!net_service(NET_STOP, argv[2])) else if(!net_service(NET_STOP, argv[2]))
return 1; return 2;
} }
else if(arg_is(argv[1], L"use")) else if(arg_is(argv[1], L"use"))
{ {

View file

@ -0,0 +1,4 @@
TESTDLL = net.exe
SOURCES = \
net.c

78
programs/net/tests/net.c Normal file
View file

@ -0,0 +1,78 @@
/*
* Copyright 2024 Fabian Maurer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <windows.h>
#include <stdio.h>
#include "wine/test.h"
static HANDLE nul_file;
#define check_exit_code(x) ok(r == (x), "got exit code %ld, expected %d\n", r, (x))
/* Copied and modified from the reg.exe tests */
#define run_net_exe(c,r) run_net_exe_(__FILE__,__LINE__,c,r)
static BOOL run_net_exe_(const char *file, unsigned line, const char *cmd, DWORD *rc)
{
STARTUPINFOA si = {sizeof(STARTUPINFOA)};
PROCESS_INFORMATION pi;
BOOL bret;
DWORD ret;
char cmdline[256];
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = nul_file;
si.hStdOutput = nul_file;
si.hStdError = nul_file;
strcpy(cmdline, cmd);
if (!CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
return FALSE;
ret = WaitForSingleObject(pi.hProcess, 10000);
if (ret == WAIT_TIMEOUT)
TerminateProcess(pi.hProcess, 1);
bret = GetExitCodeProcess(pi.hProcess, rc);
ok_(__FILE__, line)(bret, "GetExitCodeProcess failed: %ld\n", GetLastError());
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return bret;
}
static void test_stop(void)
{
DWORD r;
/* Stop non existing service */
run_net_exe("net stop non-existing-service", &r);
check_exit_code(2);
}
START_TEST(net)
{
SECURITY_ATTRIBUTES secattr = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
nul_file = CreateFileA("NUL", GENERIC_READ | GENERIC_WRITE, 0, &secattr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
test_stop();
CloseHandle(nul_file);
}

View file

@ -48,7 +48,7 @@ struct debug_event
struct file *file; /* file object for events that need one */ struct file *file; /* file object for events that need one */
enum debug_event_state state; /* event state */ enum debug_event_state state; /* event state */
int status; /* continuation status */ int status; /* continuation status */
debug_event_t data; /* event data */ union debug_event_data data; /* event data */
}; };
static const WCHAR debug_obj_name[] = {'D','e','b','u','g','O','b','j','e','c','t'}; static const WCHAR debug_obj_name[] = {'D','e','b','u','g','O','b','j','e','c','t'};
@ -142,7 +142,7 @@ static client_ptr_t get_teb_user_ptr( struct thread *thread )
static void fill_exception_event( struct debug_event *event, const void *arg ) static void fill_exception_event( struct debug_event *event, const void *arg )
{ {
const debug_event_t *data = arg; const union debug_event_data *data = arg;
event->data.exception = data->exception; event->data.exception = data->exception;
event->data.exception.nb_params = min( event->data.exception.nb_params, EXCEPTION_MAXIMUM_PARAMETERS ); event->data.exception.nb_params = min( event->data.exception.nb_params, EXCEPTION_MAXIMUM_PARAMETERS );
} }
@ -641,7 +641,7 @@ DECL_HANDLER(queue_exception_event)
reply->handle = 0; reply->handle = 0;
if (debug_obj) if (debug_obj)
{ {
debug_event_t data; union debug_event_data data;
struct debug_event *event; struct debug_event *event;
struct thread *thread = current; struct thread *thread = current;

View file

@ -49,7 +49,7 @@ struct irp_call
struct device_file *file; /* file containing this irp */ struct device_file *file; /* file containing this irp */
struct thread *thread; /* thread that queued the irp */ struct thread *thread; /* thread that queued the irp */
struct async *async; /* pending async op */ struct async *async; /* pending async op */
irp_params_t params; /* irp parameters */ union irp_params params; /* irp parameters */
struct iosb *iosb; /* I/O status block */ struct iosb *iosb; /* I/O status block */
int canceled; /* the call was canceled */ int canceled; /* the call was canceled */
client_ptr_t user_ptr; /* client side pointer */ client_ptr_t user_ptr; /* client side pointer */
@ -348,7 +348,8 @@ static void irp_call_destroy( struct object *obj )
if (irp->thread) release_object( irp->thread ); if (irp->thread) release_object( irp->thread );
} }
static struct irp_call *create_irp( struct device_file *file, const irp_params_t *params, struct async *async ) static struct irp_call *create_irp( struct device_file *file, const union irp_params *params,
struct async *async )
{ {
struct irp_call *irp; struct irp_call *irp;
@ -455,7 +456,7 @@ static struct object *device_open_file( struct object *obj, unsigned int access,
if (device->manager) if (device->manager)
{ {
struct irp_call *irp; struct irp_call *irp;
irp_params_t params; union irp_params params;
memset( &params, 0, sizeof(params) ); memset( &params, 0, sizeof(params) );
params.create.type = IRP_CALL_CREATE; params.create.type = IRP_CALL_CREATE;
@ -512,7 +513,7 @@ static int device_file_close_handle( struct object *obj, struct process *process
if (!file->closed && file->device->manager && obj->handle_count == 1) /* last handle */ if (!file->closed && file->device->manager && obj->handle_count == 1) /* last handle */
{ {
struct irp_call *irp; struct irp_call *irp;
irp_params_t params; union irp_params params;
file->closed = 1; file->closed = 1;
memset( &params, 0, sizeof(params) ); memset( &params, 0, sizeof(params) );
@ -542,7 +543,7 @@ static void device_file_destroy( struct object *obj )
release_object( file->device ); release_object( file->device );
} }
static int fill_irp_params( struct device_manager *manager, struct irp_call *irp, irp_params_t *params ) static int fill_irp_params( struct device_manager *manager, struct irp_call *irp, union irp_params *params )
{ {
switch (irp->params.type) switch (irp->params.type)
{ {
@ -595,7 +596,7 @@ static void free_irp_params( struct irp_call *irp )
} }
/* queue an irp to the device */ /* queue an irp to the device */
static void queue_irp( struct device_file *file, const irp_params_t *params, struct async *async ) static void queue_irp( struct device_file *file, const union irp_params *params, struct async *async )
{ {
struct irp_call *irp = create_irp( file, params, async ); struct irp_call *irp = create_irp( file, params, async );
if (!irp) return; if (!irp) return;
@ -615,7 +616,7 @@ static enum server_fd_type device_file_get_fd_type( struct fd *fd )
static void device_file_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class ) static void device_file_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class )
{ {
struct device_file *file = get_fd_user( fd ); struct device_file *file = get_fd_user( fd );
irp_params_t params; union irp_params params;
memset( &params, 0, sizeof(params) ); memset( &params, 0, sizeof(params) );
params.volume.type = IRP_CALL_VOLUME; params.volume.type = IRP_CALL_VOLUME;
@ -626,7 +627,7 @@ static void device_file_get_volume_info( struct fd *fd, struct async *async, uns
static void device_file_read( struct fd *fd, struct async *async, file_pos_t pos ) static void device_file_read( struct fd *fd, struct async *async, file_pos_t pos )
{ {
struct device_file *file = get_fd_user( fd ); struct device_file *file = get_fd_user( fd );
irp_params_t params; union irp_params params;
memset( &params, 0, sizeof(params) ); memset( &params, 0, sizeof(params) );
params.read.type = IRP_CALL_READ; params.read.type = IRP_CALL_READ;
@ -638,7 +639,7 @@ static void device_file_read( struct fd *fd, struct async *async, file_pos_t pos
static void device_file_write( struct fd *fd, struct async *async, file_pos_t pos ) static void device_file_write( struct fd *fd, struct async *async, file_pos_t pos )
{ {
struct device_file *file = get_fd_user( fd ); struct device_file *file = get_fd_user( fd );
irp_params_t params; union irp_params params;
memset( &params, 0, sizeof(params) ); memset( &params, 0, sizeof(params) );
params.write.type = IRP_CALL_WRITE; params.write.type = IRP_CALL_WRITE;
@ -650,7 +651,7 @@ static void device_file_write( struct fd *fd, struct async *async, file_pos_t po
static void device_file_flush( struct fd *fd, struct async *async ) static void device_file_flush( struct fd *fd, struct async *async )
{ {
struct device_file *file = get_fd_user( fd ); struct device_file *file = get_fd_user( fd );
irp_params_t params; union irp_params params;
memset( &params, 0, sizeof(params) ); memset( &params, 0, sizeof(params) );
params.flush.type = IRP_CALL_FLUSH; params.flush.type = IRP_CALL_FLUSH;
@ -660,7 +661,7 @@ static void device_file_flush( struct fd *fd, struct async *async )
static void device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static void device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
struct device_file *file = get_fd_user( fd ); struct device_file *file = get_fd_user( fd );
irp_params_t params; union irp_params params;
memset( &params, 0, sizeof(params) ); memset( &params, 0, sizeof(params) );
params.ioctl.type = IRP_CALL_IOCTL; params.ioctl.type = IRP_CALL_IOCTL;
@ -671,7 +672,7 @@ static void device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *a
static void cancel_irp_call( struct irp_call *irp ) static void cancel_irp_call( struct irp_call *irp )
{ {
struct irp_call *cancel_irp; struct irp_call *cancel_irp;
irp_params_t params; union irp_params params;
irp->canceled = 1; irp->canceled = 1;
if (!irp->user_ptr || !irp->file || !irp->file->device->manager) return; if (!irp->user_ptr || !irp->file || !irp->file->device->manager) return;
@ -842,7 +843,7 @@ void free_kernel_objects( struct object *obj )
{ {
struct kernel_object *kernel_object = LIST_ENTRY( ptr, struct kernel_object, list_entry ); struct kernel_object *kernel_object = LIST_ENTRY( ptr, struct kernel_object, list_entry );
struct irp_call *irp; struct irp_call *irp;
irp_params_t params; union irp_params params;
assert( !kernel_object->owned ); assert( !kernel_object->owned );

View file

@ -248,7 +248,7 @@ static void keyed_event_dump( struct object *obj, int verbose )
fputs( "Keyed event\n", stderr ); fputs( "Keyed event\n", stderr );
} }
static enum select_op matching_op( enum select_op op ) static enum select_opcode matching_op( enum select_opcode op )
{ {
return op ^ (SELECT_KEYED_EVENT_WAIT ^ SELECT_KEYED_EVENT_RELEASE); return op ^ (SELECT_KEYED_EVENT_WAIT ^ SELECT_KEYED_EVENT_RELEASE);
} }
@ -257,7 +257,7 @@ static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *en
{ {
struct wait_queue_entry *ptr; struct wait_queue_entry *ptr;
struct process *process; struct process *process;
enum select_op select_op; enum select_opcode select_op;
assert( obj->ops == &keyed_event_ops ); assert( obj->ops == &keyed_event_ops );

Some files were not shown because too many files have changed in this diff Show more