Compare commits

...

88 commits

Author SHA1 Message Date
Alistair Leslie-Hughes
c9d3eea192 Merge branch 'user32_msgbox' into 'master'
user32/msgbox: Support WM_COPY Message

See merge request wine/wine!5247
2024-11-18 05:51:28 +00:00
Rémi Bernon
ae6366b33c winex11: Introduce a new window_update_client_config helper. 2024-11-15 19:08:41 +01:00
Rémi Bernon
d9cf4678a1 winex11: Introduce a new window_update_client_state helper. 2024-11-15 19:08:41 +01:00
Rémi Bernon
da936bcf35 winex11: Use the new window state tracker to get WM_STATE value. 2024-11-15 19:08:40 +01:00
Rémi Bernon
e75192fe72 winex11: Use the new window state tracker to get _NET_WM_STATE value. 2024-11-15 19:08:40 +01:00
Rémi Bernon
0dc7e40468 winex11: Ignore focus changes during WM_STATE transitions.
When WM_STATE is being quickly updated, and depending on the WM we might
receive transient focus changes, which will disrupt the Win32 state and
make us randomly lose focus.

Ignore them instead, when a window is being shown, and wait for WM_STATE
to be updated and stable. We will eventually receive a WM_TAKE_FOCUS /
FocusIn event *after* a window has been shown.

When a window is hidden or minimized, we will receive the FocusOut event
during the WM_STATE transition, and can safely handle it in this case,
as we should have done all the Win32 side effects and have changed the
foreground window already.

When there's no window state change pending, the focus change event is
unexpected, coming from the user or WM, and we handle it normally.
2024-11-15 19:08:20 +01:00
Biswapriyo Nath
700ee59470 include: Add UI Automation Annotation Type ID definitions.
Required for c7ba4a9640
2024-11-15 19:08:10 +01:00
Marc-Aurel Zent
c76a192bf6 winex11: Include kbd.h instead of ime.h. 2024-11-15 19:07:58 +01:00
Marc-Aurel Zent
9acdc03128 include: Add Japanese IME virtual key codes to kbd.h. 2024-11-15 19:07:57 +01:00
Hans Leidekker
8b121591be wininet: Use InternetTimeToSystemTimeW() to convert header values.
The current code calls mktime() which interprets its argument as local time while these
values are assumed to be in UTC.
2024-11-15 19:07:26 +01:00
Hans Leidekker
5a23afb34d wininet: Accept UTC as the equivalent of GMT.
Based on a patch by Etaash Mathamsetty.
2024-11-15 19:07:24 +01:00
Nikolay Sivov
6a01532899 comctl32/listview: Send LVN_HOTTRACK in response to mouse moves.
It's worth noting that comctl32 v6 have hottracking notifications enabled
by default, there is no need to set any extended styles.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
2024-11-15 19:07:06 +01:00
Nikolay Sivov
e5b0ead2b5 comctl32/listview: Initialize hot cursor handle.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
2024-11-15 19:07:04 +01:00
Eric Pouech
b9c06c4474 dbghelp: Fill-in data in SymSrvGetFileIndexIndo if BAD_EXE_FORMAT.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-15 16:25:10 +01:00
Eric Pouech
a57eedec86 dbghelp/tests: Improve SymSrvGetFileIndexInfo tests.
Esp. the failures with ERROR_BAD_EXE_FORMAT still fill all the fields
in the returned structure.

Add more flexibility to .dbg file creation (optional DEBUG_DIRECTORY).

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-15 16:25:10 +01:00
Eric Pouech
9212706ede dbghelp: Only WARN on stripped PE images.
When stripping, binutils' objcopy also sets the flag, yet
without stripping into a .DBG file.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-15 16:25:10 +01:00
Eric Pouech
40b314cf34 dbghelp: Don't try to load PDB for a RSDS debug directory in .buildid section.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-15 16:25:10 +01:00
Brendan Shanks
aa24458086 Add .gitattributes file to mark generated files. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
576d7e24cd server: Use an explicit struct instead of a typedef for async I/O data. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
305ec347dc server: Use an explicit struct instead of a typedef for user APCs. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
4c0103e58c server: Use an explicit union instead of a typedef for APC results. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
1137a10ef7 server: Use an explicit union instead of a typedef for APC calls. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
eae7db4fa4 server: Simplify updating the protocol version. 2024-11-15 16:25:09 +01:00
Alexandre Julliard
75e2ec479b server: Move the generated part of trace.c to a separate header. 2024-11-15 16:25:09 +01:00
Alexandre Julliard
45953cdbec server: Move the generated part of request.h to a separate header. 2024-11-15 16:25:09 +01:00
Alexandre Julliard
126c54cd25 server: Print a warning if page size isn't 4k. 2024-11-15 16:25:09 +01:00
Rémi Bernon
ab40b7fd86 winex11: Always generate ConfigureNotify events for embedded windows.
We won't receive a ConfigureNotify event if the embedded window has been
reparented without moving or resizing it. Top-level windows always
receive synthetic ConfigureNotify from the window manager.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370
2024-11-14 21:56:33 +01:00
Rémi Bernon
0bd49a68dc winex11: Generate ConfigureNotify events for the children tree.
When an ancestor window is moved.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370
2024-11-14 21:56:33 +01:00
Rémi Bernon
50683f7b32 winex11: Avoid overriding previously received ConfigureNotify events.
The X event merging logic removes events from the queue in advance, and
putting a dummy ConfigureNotify back in the queue will override any
previously received event.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370
2024-11-14 21:56:33 +01:00
Rémi Bernon
48bb5f90a2 winex11: Retrieve the HWND for the host window's child window.
Instead of the host window itself, which will never have one.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370
2024-11-14 21:56:33 +01:00
Rémi Bernon
7352196f6a winex11: Introduce a new host_window_send_configure_events helper.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370
2024-11-14 21:56:33 +01:00
Rémi Bernon
4eefc0b9a9 winex11: Reset the window relative position when it gets reparented.
Instead of keeping the same offset as from the previous window parent,
which may cause offsets to stack up with embedded windows.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370
2024-11-14 21:56:33 +01:00
Rémi Bernon
51f6839395 winex11: Reset embedded window position to 0x0 before docking it.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370
2024-11-14 21:56:33 +01:00
Zhiyi Zhang
b240f8ea93 ntdll: Implement NtSetIoCompletionEx(). 2024-11-14 21:56:33 +01:00
Zhiyi Zhang
54b9f68b8e ntdll/tests: Add NtSetIoCompletionEx() tests. 2024-11-14 21:56:33 +01:00
Nikolay Sivov
5a7a4b7f1a dwrite/layout: Skip to the next typography range when current one has no features.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57407
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
2024-11-14 21:56:33 +01:00
Paul Gofman
698ab75a59 server: Don't update cursor pos in set_window_pos() if window wasn't moved.
Fixes a regression introduced by commit db9a4bc66a.
2024-11-14 21:56:33 +01:00
Alexandre Julliard
8e2442584c ntdll/tests: Fix a test failure on 64-bit Windows. 2024-11-14 21:56:33 +01:00
Alexandre Julliard
6d1df55bf3 ntdll: Always return 0 length on failure in SystemFirmwareTableInformation. 2024-11-14 21:56:33 +01:00
Alexandre Julliard
9f8ef43991 rundll32: Restart itself if the dll is for a different architecture.
Based on the corresponding code in regsvr32.
2024-11-14 21:56:33 +01:00
Alexandre Julliard
5c597119a0 rundll32: Rewrite command line parsing.
Windows doesn't do any fancy unescaping.
2024-11-14 11:54:35 +01:00
Alexandre Julliard
c20bf25556 rundll32: Use crt allocation functions. 2024-11-14 11:53:03 +01:00
Alexandre Julliard
194ada7583 rundll32: Don't bother cleaning up at process exit. 2024-11-14 11:52:26 +01:00
Jacek Caban
8a87ce3c4f configure: Use -fms-hotpatch when available.
On Clang, this flag serves as a replacement for the __ms_hook_prologue__ attribute.
2024-11-14 11:10:28 +01:00
Jacek Caban
f47da4307f winegcc: Pass -fms-hotpatch to the linker.
The -fms-hotpatch flag is relevant for both the compiler and the linker.
2024-11-14 11:10:28 +01:00
Jacek Caban
0f84798246 configure: Use -ffunction-sections for PE targets. 2024-11-14 11:10:28 +01:00
Aurimas Fišeras
0eda6a76c7 po: Update Lithuanian translation. 2024-11-14 11:06:38 +01:00
Gabriel Ivăncescu
38f1ce3210 mshtml: Forward deletion for GLOBAL_SCRIPTVAR to the script's object.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-13 23:14:48 +01:00
Gabriel Ivăncescu
9b264c948f mshtml: Check if window global prop still exists before returning its id.
We have to introduce special handling for jscript, as it's probably integrated
on native mshtml.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-13 23:14:47 +01:00
Gabriel Ivăncescu
055bf9f5a2 mshtml: Override window's element prop directly rather than using GLOBAL_DISPEXVAR.
When GLOBAL_DISPEXVAR is used, we store the id of the dynamic prop and
invoke it using the same id. But this is not the case if we have a jsdisp,
which is redirected from InvokeEx and results in an invalid id.

The actual way this works on native (in IE9+) is that element/frame props
are special and not part of the window object at all. They're actually
looked up after the prototype is, in a special way, but that requires a
revamp. Storing over it just creates an actual prop on the window (which
is what we are doing here).

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-13 23:14:36 +01:00
Gabriel Ivăncescu
18aefb5dcf mshtml: Use BSTR to store global prop's name.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-13 23:14:36 +01:00
Gabriel Ivăncescu
85331da430 jscript: Add basic semi-stub implementation of GetMemberProperties.
Also add tests for GetMemberName and DeleteMemberBy* which we did not have.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-13 23:14:35 +01:00
Gabriel Ivăncescu
5947a66f4c mshtml: Throw invalid action for IE8 window prop deletion.
Instead of E_NOTIMPL.

We can't use the dispex's delete because it also applies to dynamic and
builtin props and it also happens too late when deleting by name (after
looking it up), where existing tests show it doesn't look up the dispid
at all.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-13 23:14:33 +01:00
Gabriel Ivăncescu
12755eeb1c mshtml: Reset builtin function props to their default values when deleted.
The previous tests bailed out too early on IE8, and did not test builtin
props. Also added todos for tests that we did not even test because of
returning early.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
2024-11-13 23:14:30 +01:00
Rémi Bernon
e3258e7620 winex11: Simplify the control flow in ConfigureNotify handlers. 2024-11-13 20:27:15 +01:00
Rémi Bernon
968ab4e79a winex11: Simplify the control flow in WM_STATE handlers. 2024-11-13 20:27:15 +01:00
Rémi Bernon
b1dd7da806 winex11: Avoid updating _NET_WM_STATE on iconic windows.
This tends to trigger window mapping with some window managers.
2024-11-13 20:27:13 +01:00
Rémi Bernon
199274d420 winex11: Avoid requesting unnecessary window config changes. 2024-11-13 20:27:13 +01:00
Rémi Bernon
7ac35f13cb winex11: Avoid requesting unnecessary _NET_WM_STATE changes. 2024-11-13 20:27:13 +01:00
Elizabeth Figura
1f42d452aa wined3d: Initialize max_blend_stages in the SPIRV fragment pipe. 2024-11-13 20:26:42 +01:00
Elizabeth Figura
96c37c23f6 wined3d: Clear caps to zero in shader caps query functions. 2024-11-13 20:26:42 +01:00
Elizabeth Figura
f588fec26c wined3d: Rewrite the comment in compute_texture_matrix().
Make the function easier to understand, and use language that's a little less
GL-centric.
2024-11-13 20:26:40 +01:00
Elizabeth Figura
70258a160f wined3d: Calculate the texture matrix solely from the vertex declaration. 2024-11-13 20:26:40 +01:00
Elizabeth Figura
b02b73673b wined3d: Do not clamp fog in the VS.
NVidia and WARP clamp before interpolation in the oFog case; AMD clamps only
after interpolation (which we also do).

On the other hand, test_fog() proves that clamping should not be done before
interpolation in the FFP case, for any driver.

In order to emulate an FFP vertex shader with a real compiled shader, we need to
avoid clamping before interpolation, choosing the AMD behaviour here.
2024-11-13 20:26:35 +01:00
John Chadwick
a5de8d85d3 winex11: Remove stub tablet_get_packet wow64 thunk.
The previous commit ensures that the WTPACKET fields align between
32-bit and 64-bit architectures, so now we can use the same
tablet_get_packet without needing another thunk.
2024-11-13 18:48:42 +01:00
John Chadwick
5b10f924fa wintab32: Align WTPACKET for 32/64-bit archs.
WTPACKET's structure is never directly exposed via the API; it's
internal to Wine. The HCTX value is only used on the wintab32 side,
not the driver side, and it is used as an integer rather than a
pointer, so this should be safe to do.

This eliminates the need to have a wow64 thunk for tablet_get_packet.
2024-11-13 18:48:42 +01:00
Etaash Mathamsetty
ea3c73b12d explorer: Enable the Wayland driver. 2024-11-13 18:48:42 +01:00
Alistair Leslie-Hughes
a93623eced user32: Implement GetDpiAwarenessContextForProcess.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57169
2024-11-13 18:48:42 +01:00
Marc-Aurel Zent
194901b592 winemac.drv: Add additional French symbol vkeys mappings. 2024-11-13 18:48:42 +01:00
Marc-Aurel Zent
484c43c9e9 winemac.drv: Add Mac virtual key code information to the German layout. 2024-11-13 18:48:42 +01:00
Marc-Aurel Zent
1125bb8f71 winemac.drv: Allow symbol vkeys to match on Mac virtual key codes. 2024-11-13 18:48:42 +01:00
Piotr Caban
19018abf86 wine.inf: Set MountMgr service start option to SERVICE_BOOT_START.
This matches with native. It's needed to ensure that mountmgr is started
before other services that use functionality provided by it. Fixes
Autodesk Desktop Licensing Service that uses GetVolumeInformationByHandleW.
2024-11-13 18:48:42 +01:00
Piotr Caban
32be056558 services: Sort services start order by start type. 2024-11-13 18:48:42 +01:00
Zhiyi Zhang
e3db89aa9d urlmon/tests: Test flags for getting properties. 2024-11-13 18:48:42 +01:00
Zhiyi Zhang
61d8e74e72 urlmon: Support Uri_DISPLAY_IDN_HOST.
Uri_DISPLAY_IDN_HOST makes the hostname in Uri_PROPERTY_ABSOLUTE_URI, Uri_PROPERTY_DOMAIN and
Uri_PROPERTY_HOST appear in punycode or Unicode as it would appear in the Uri_PROPERTY_DISPLAY_URI
property. IDNs appears in Unicode on some Windows version and in punycode on others. Wine chose to
display Unicode for Uri_PROPERTY_DISPLAY_URI. So no need to add special handling for
Uri_DISPLAY_IDN_HOST at the moment because they already display in Unicode.
2024-11-13 18:48:42 +01:00
Zhiyi Zhang
427f8fae20 urlmon: Support Uri_PUNYCODE_IDN_HOST. 2024-11-13 18:48:42 +01:00
Zhiyi Zhang
71b4377e68 urlmon: Support Uri_DISPLAY_NO_FRAGMENT. 2024-11-13 18:48:42 +01:00
Zhiyi Zhang
a7b1e5d5dc urlmon: Support Uri_HOST_IDN. 2024-11-13 18:48:42 +01:00
Alexandre Julliard
dd6e73428d fluidsynth: Import upstream release 2.4.0. 2024-11-13 18:48:42 +01:00
Alexandre Julliard
3181ae039e mpg123: Import upstream release 1.32.9. 2024-11-13 15:05:23 +01:00
Alexandre Julliard
786cf5a20b nls: Update locale data to CLDR version 46. 2024-11-13 15:05:23 +01:00
Alexandre Julliard
9accb76341 tools: Download all Unicode data files before generating anything. 2024-11-13 15:05:23 +01:00
Alexandre Julliard
6208d61055 kernelbase: Implement EnumSystemFirmwareTables(). 2024-11-13 15:05:23 +01:00
Alexandre Julliard
966cec7a63 ntdll: Implement BIOS table enumeration.
Based on a patch by Dāvis Mosāns.
2024-11-13 15:05:16 +01:00
Alexandre Julliard
23db166ec8 kernel32/tests: Add some tests for EnumSystemFirmwareTables(). 2024-11-13 10:46:14 +01:00
Bernhard Übelacker
6dd7cd59d9 kernel32/tests: Remove todo_wine from now succeeding heap test.
This is a followup to commit d78cbe84e5.
2024-11-13 09:46:13 +01:00
Alistair Leslie-Hughes
083102cd83 user32/msgbox: Use a windows hook to trap Ctrl+C 2024-03-24 12:58:48 +11:00
Alistair Leslie-Hughes
375ff622d1 user32/msgbox: Support WM_COPY Message
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=17205

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
2024-03-24 12:56:42 +11:00
121 changed files with 10342 additions and 8292 deletions

64
.gitattributes vendored Normal file
View file

@ -0,0 +1,64 @@
[attr]generated gitlab-generated linguist-generated=true
# generated by autotools
configure generated
include/config.h.in generated
# generated by dlls/dsound/make_fir
dlls/dsound/fir.h generated
# generated by dlls/opencl/make_opencl
dlls/opencl/opencl.spec generated
dlls/opencl/opencl_types.h generated
dlls/opencl/pe_thunks.c generated
dlls/opencl/unix_thunks.c generated
dlls/opencl/unixlib.h generated
# generated by dlls/opengl32/make_opengl
dlls/opengl32/opengl32.spec generated
dlls/opengl32/thunks.c generated
dlls/opengl32/unix_thunks.c generated
dlls/opengl32/unixlib.h generated
include/wine/wgl.h generated
include/wine/wgl_driver.h generated
# generated by dlls/winevulkan/make_vulkan
dlls/vulkan-1/vulkan-1.spec generated
dlls/winevulkan/loader_thunks.c generated
dlls/winevulkan/loader_thunks.h generated
dlls/winevulkan/vulkan_thunks.c generated
dlls/winevulkan/vulkan_thunks.h generated
dlls/winevulkan/winevulkan.json generated
dlls/winevulkan/winevulkan.spec generated
include/wine/vulkan.h generated
include/wine/vulkan_driver.h generated
# generated by tools/make_requests
include/wine/server_protocol.h generated
server/request_handlers.h generated
server/request_trace.h generated
# generated by tools/make_specfiles
dlls/ntdll/ntsyscalls.h generated
dlls/win32u/win32syscalls.h generated
# generated by tools/make_unicode
dlls/dwrite/bracket.c generated
dlls/dwrite/direction.c generated
dlls/dwrite/linebreak.c generated
dlls/dwrite/mirror.c generated
dlls/dwrite/scripts.c generated
dlls/dwrite/scripts.h generated
dlls/dwrite/shapers/arabic_table.c generated
dlls/gdi32/uniscribe/bracket.c generated
dlls/gdi32/uniscribe/direction.c generated
dlls/gdi32/uniscribe/indicsyllable.c generated
dlls/gdi32/uniscribe/linebreak.c generated
dlls/gdi32/uniscribe/mirror.c generated
dlls/gdi32/uniscribe/shaping.c generated
dlls/kernelbase/kernelbase.rgs generated
dlls/tzres/tzres.rc generated
dlls/win32u/vertical.c generated
dlls/wineps.drv/direction.c generated
dlls/wineps.drv/vertical.c generated
nls/*.nls generated

3
aclocal.m4 vendored
View file

@ -198,6 +198,9 @@ ac_wine_try_cflags_saved_exeext=$ac_exeext
CFLAGS="$CFLAGS -nostdlib -nodefaultlibs $1" CFLAGS="$CFLAGS -nostdlib -nodefaultlibs $1"
ac_exeext=".exe" ac_exeext=".exe"
AC_LINK_IFELSE([AC_LANG_SOURCE([[void *__os_arm64x_dispatch_ret = 0; AC_LINK_IFELSE([AC_LANG_SOURCE([[void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; }]])], int __cdecl mainCRTStartup(void) { return 0; }]])],
[AS_VAR_SET(ac_var,yes)], [AS_VAR_SET(ac_var,no)]) [AS_VAR_SET(ac_var,yes)], [AS_VAR_SET(ac_var,no)])
CFLAGS=$ac_wine_try_cflags_saved CFLAGS=$ac_wine_try_cflags_saved

185
configure generated vendored
View file

@ -10407,6 +10407,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10444,6 +10447,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10660,6 +10666,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10696,6 +10705,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10732,6 +10744,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10768,6 +10783,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10804,6 +10822,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10840,6 +10861,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10876,6 +10900,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10912,6 +10939,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10948,6 +10978,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -10984,6 +11017,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11020,6 +11056,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11056,6 +11095,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11092,6 +11134,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11128,6 +11173,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11164,6 +11212,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11200,6 +11251,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11236,6 +11290,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11272,6 +11329,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11308,6 +11368,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11344,6 +11407,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11380,6 +11446,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11403,6 +11472,86 @@ then :
as_fn_append ${wine_arch}_EXTRACFLAGS " -Wenum-conversion" as_fn_append ${wine_arch}_EXTRACFLAGS " -Wenum-conversion"
fi } ;; fi } ;;
esac esac
fi }
{ as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-ffunction-sections" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -ffunction-sections" >&5
printf %s "checking whether $CC supports -ffunction-sections... " >&6; }
if eval test \${$as_ac_var+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_wine_try_cflags_saved=$CFLAGS
ac_wine_try_cflags_saved_exeext=$ac_exeext
CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -ffunction-sections"
ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
eval "$as_ac_var=yes"
else case e in #(
e) eval "$as_ac_var=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$ac_wine_try_cflags_saved
ac_exeext=$ac_wine_try_cflags_saved_exeext ;;
esac
fi
eval ac_res=\$$as_ac_var
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
if eval test \"x\$"$as_ac_var"\" = x"yes"
then :
as_fn_append ${wine_arch}_EXTRACFLAGS " -ffunction-sections"
fi }
{ as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-fms-hotpatch -DMIN_CLANG_VERSION=18" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -fms-hotpatch -DMIN_CLANG_VERSION=18" >&5
printf %s "checking whether $CC supports -fms-hotpatch -DMIN_CLANG_VERSION=18... " >&6; }
if eval test \${$as_ac_var+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_wine_try_cflags_saved=$CFLAGS
ac_wine_try_cflags_saved_exeext=$ac_exeext
CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -fms-hotpatch -DMIN_CLANG_VERSION=18"
ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
eval "$as_ac_var=yes"
else case e in #(
e) eval "$as_ac_var=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$ac_wine_try_cflags_saved
ac_exeext=$ac_wine_try_cflags_saved_exeext ;;
esac
fi
eval ac_res=\$$as_ac_var
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
if eval test \"x\$"$as_ac_var"\" = x"yes"
then :
as_fn_append ${wine_arch}_EXTRACFLAGS " -fms-hotpatch"
as_fn_append ${wine_arch}_LDFLAGS " -fms-hotpatch"
fi } fi }
{ as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-flarge-source-files -Wmisleading-indentation" | sed "$as_sed_sh"` { as_ac_var=`printf "%s\n" "ac_cv_${wine_arch}_cflags_-flarge-source-files -Wmisleading-indentation" | sed "$as_sed_sh"`
@ -11419,6 +11568,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11457,6 +11609,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11493,6 +11648,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11529,6 +11687,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11565,6 +11726,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11601,6 +11765,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11637,6 +11804,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11673,6 +11843,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11732,6 +11905,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11768,6 +11944,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11808,6 +11987,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"
@ -11844,6 +12026,9 @@ ac_exeext=".exe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
void *__os_arm64x_dispatch_ret = 0; void *__os_arm64x_dispatch_ret = 0;
#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION
#error Too old clang version
#endif
int __cdecl mainCRTStartup(void) { return 0; } int __cdecl mainCRTStartup(void) { return 0; }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO" if ac_fn_c_try_link "$LINENO"

View file

@ -961,6 +961,12 @@ This is an error since --enable-archs=$wine_arch was requested.])])
WINE_TRY_PE_CFLAGS([-Wlogical-op]) WINE_TRY_PE_CFLAGS([-Wlogical-op])
WINE_TRY_PE_CFLAGS([-Wabsolute-value]) WINE_TRY_PE_CFLAGS([-Wabsolute-value])
WINE_TRY_PE_CFLAGS([-Wenum-enum-conversion],[:],WINE_TRY_PE_CFLAGS([-Wenum-conversion])) WINE_TRY_PE_CFLAGS([-Wenum-enum-conversion],[:],WINE_TRY_PE_CFLAGS([-Wenum-conversion]))
WINE_TRY_PE_CFLAGS([-ffunction-sections])
dnl clang had broken -fms-hotpatch support before version 18 (https://github.com/llvm/llvm-project/pull/77245)
WINE_TRY_PE_CFLAGS([-fms-hotpatch -DMIN_CLANG_VERSION=18],
[AS_VAR_APPEND([${wine_arch}_EXTRACFLAGS],[" -fms-hotpatch"])
AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" -fms-hotpatch"])])
dnl GCC can't handle large files when -Wmisleading-indentation is enabled (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89549) dnl GCC can't handle large files when -Wmisleading-indentation is enabled (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89549)
WINE_TRY_PE_CFLAGS([-flarge-source-files -Wmisleading-indentation],[AS_VAR_APPEND(${wine_arch}_EXTRACFLAGS,[" -Wno-misleading-indentation"])]) WINE_TRY_PE_CFLAGS([-flarge-source-files -Wmisleading-indentation],[AS_VAR_APPEND(${wine_arch}_EXTRACFLAGS,[" -Wno-misleading-indentation"])])

View file

@ -4150,6 +4150,7 @@ static LRESULT LISTVIEW_MouseMove(LISTVIEW_INFO *infoPtr, WORD fwKeys, INT x, IN
/* see if we are supposed to be tracking mouse hovering */ /* see if we are supposed to be tracking mouse hovering */
if (LISTVIEW_IsHotTracking(infoPtr)) { if (LISTVIEW_IsHotTracking(infoPtr)) {
TRACKMOUSEEVENT trackinfo; TRACKMOUSEEVENT trackinfo;
NMLISTVIEW nmlv = { 0 };
DWORD flags; DWORD flags;
trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
@ -4170,6 +4171,15 @@ static LRESULT LISTVIEW_MouseMove(LISTVIEW_INFO *infoPtr, WORD fwKeys, INT x, IN
/* call TRACKMOUSEEVENT so we receive WM_MOUSEHOVER messages */ /* call TRACKMOUSEEVENT so we receive WM_MOUSEHOVER messages */
_TrackMouseEvent(&trackinfo); _TrackMouseEvent(&trackinfo);
} }
ht.pt = pt;
LISTVIEW_HitTest(infoPtr, &ht, TRUE, TRUE);
nmlv.iItem = ht.iItem;
nmlv.iSubItem = ht.iSubItem;
nmlv.ptAction = pt;
notify_listview(infoPtr, LVN_HOTTRACK, &nmlv);
} }
return 0; return 0;
@ -9585,6 +9595,7 @@ static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, const CREATESTRUCTW *
infoPtr->iVersion = COMCTL32_VERSION; infoPtr->iVersion = COMCTL32_VERSION;
infoPtr->colRectsDirty = FALSE; infoPtr->colRectsDirty = FALSE;
infoPtr->selected_column = -1; infoPtr->selected_column = -1;
infoPtr->hHotCursor = LoadCursorW(NULL, (LPWSTR)IDC_HAND);
/* get default font (icon title) */ /* get default font (icon title) */
SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0); SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);

View file

@ -7255,6 +7255,19 @@ static void test_LVM_GETNEXTITEM(void)
DestroyWindow(hwnd); DestroyWindow(hwnd);
} }
static void test_LVM_GETHOTCURSOR(void)
{
HCURSOR cursor;
HWND hwnd;
hwnd = create_listview_control(LVS_REPORT);
cursor = (HCURSOR)SendMessageA(hwnd, LVM_GETHOTCURSOR, 0, 0);
ok(!!cursor, "Unexpected cursor %p.\n", cursor);
DestroyWindow(hwnd);
}
START_TEST(listview) START_TEST(listview)
{ {
ULONG_PTR ctx_cookie; ULONG_PTR ctx_cookie;
@ -7322,6 +7335,7 @@ START_TEST(listview)
test_LVM_SETBKIMAGE(FALSE); test_LVM_SETBKIMAGE(FALSE);
test_custom_sort(); test_custom_sort();
test_LVM_GETNEXTITEM(); test_LVM_GETNEXTITEM();
test_LVM_GETHOTCURSOR();
if (!load_v6_module(&ctx_cookie, &hCtx)) if (!load_v6_module(&ctx_cookie, &hCtx))
{ {
@ -7372,6 +7386,7 @@ START_TEST(listview)
test_LVM_GETNEXTITEMINDEX(); test_LVM_GETNEXTITEMINDEX();
test_LVM_GETNEXTITEM(); test_LVM_GETNEXTITEM();
test_LVM_SETBKIMAGE(TRUE); test_LVM_SETBKIMAGE(TRUE);
test_LVM_GETHOTCURSOR();
unload_v6_module(ctx_cookie, hCtx); unload_v6_module(ctx_cookie, hCtx);

View file

@ -4379,7 +4379,13 @@ static BOOL codeview_process_info(const struct process *pcs,
TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n", TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n",
wine_dbgstr_guid(&rsds->guid), rsds->age, debugstr_a(rsds->name)); wine_dbgstr_guid(&rsds->guid), rsds->age, debugstr_a(rsds->name));
ret = pdb_process_file(pcs, msc_dbg, rsds->name, &rsds->guid, 0, rsds->age); /* gcc/mingw and clang can emit build-id information, but with an empty PDB filename.
* Don't search for the .pdb file in that case.
*/
if (rsds->name[0])
ret = pdb_process_file(pcs, msc_dbg, rsds->name, &rsds->guid, 0, rsds->age);
else
ret = TRUE;
break; break;
} }
default: default:
@ -4487,7 +4493,7 @@ typedef struct _FPO_DATA
__ENDTRY __ENDTRY
/* we haven't found yet any debug information, fallback to unmatched pdb */ /* we haven't found yet any debug information, fallback to unmatched pdb */
if (module->module.SymType == SymDeferred) if (!ret && module->module.SymType == SymDeferred)
{ {
SYMSRV_INDEX_INFOW info = {.sizeofstruct = sizeof(info)}; SYMSRV_INDEX_INFOW info = {.sizeofstruct = sizeof(info)};
char buffer[MAX_PATH]; char buffer[MAX_PATH];
@ -4549,38 +4555,35 @@ DWORD msc_get_file_indexinfo(void* image, const IMAGE_DEBUG_DIRECTORY* debug_dir
num_misc_records++; num_misc_records++;
} }
} }
return info->stripped && !num_misc_records ? ERROR_BAD_EXE_FORMAT : ERROR_SUCCESS; return (!num_dir || (info->stripped && !num_misc_records)) ? ERROR_BAD_EXE_FORMAT : ERROR_SUCCESS;
} }
DWORD dbg_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info) DWORD dbg_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info)
{ {
const IMAGE_SEPARATE_DEBUG_HEADER *header; const IMAGE_SEPARATE_DEBUG_HEADER *header;
IMAGE_DEBUG_DIRECTORY *dbg;
DWORD num_directories; DWORD num_directories;
if (size < sizeof(*header)) return ERROR_BAD_EXE_FORMAT; if (size < sizeof(*header)) return ERROR_BAD_FORMAT;
header = image; header = image;
if (header->Signature != 0x4944 /* DI */ || if (header->Signature != 0x4944 /* DI */ ||
size < sizeof(*header) + header->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + header->ExportedNamesSize + header->DebugDirectorySize) size < sizeof(*header) + header->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + header->ExportedNamesSize + header->DebugDirectorySize)
return ERROR_BAD_EXE_FORMAT; return ERROR_BAD_FORMAT;
info->size = header->SizeOfImage;
/* seems to use header's timestamp, not debug_directory one */
info->timestamp = header->TimeDateStamp;
info->stripped = FALSE; /* FIXME */
/* header is followed by: /* header is followed by:
* - header->NumberOfSections of IMAGE_SECTION_HEADER * - header->NumberOfSections of IMAGE_SECTION_HEADER
* - header->ExportedNameSize * - header->ExportedNameSize
* - then num_directories of IMAGE_DEBUG_DIRECTORY * - then num_directories of IMAGE_DEBUG_DIRECTORY
*/ */
dbg = (IMAGE_DEBUG_DIRECTORY*)((char*)(header + 1) +
header->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
header->ExportedNamesSize);
num_directories = header->DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY); num_directories = header->DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY);
if (!num_directories) return ERROR_BAD_EXE_FORMAT; return msc_get_file_indexinfo(image, dbg, num_directories, info);
info->age = 0;
memset(&info->guid, 0, sizeof(info->guid));
info->sig = 0;
info->dbgfile[0] = L'\0';
info->pdbfile[0] = L'\0';
info->size = header->SizeOfImage;
/* seems to use header's timestamp, not debug_directory one */
info->timestamp = header->TimeDateStamp;
info->stripped = FALSE; /* FIXME */
return ERROR_SUCCESS;
} }

View file

@ -832,7 +832,7 @@ BOOL WINAPI SymSrvGetFileIndexInfoW(const WCHAR *file, SYMSRV_INDEX_INFOW* info,
if (hMap) CloseHandle(hMap); if (hMap) CloseHandle(hMap);
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
if (ret == ERROR_SUCCESS) wcscpy(info->file, file_name(file)); /* overflow? */ if (ret == ERROR_SUCCESS || ret == ERROR_BAD_EXE_FORMAT) wcscpy(info->file, file_name(file)); /* overflow? */
SetLastError(ret); SetLastError(ret);
return ret == ERROR_SUCCESS; return ret == ERROR_SUCCESS;
} }

View file

@ -656,8 +656,8 @@ static BOOL pe_load_msc_debug_info(const struct process* pcs, struct module* mod
if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC || if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC ||
misc->DataType != IMAGE_DEBUG_MISC_EXENAME) misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
{ {
ERR("-Debug info stripped, but no .DBG file in module %s\n", WARN("-Debug info stripped, but no .DBG file in module %s\n",
debugstr_w(module->modulename)); debugstr_w(module->modulename));
} }
else else
{ {
@ -1019,7 +1019,7 @@ DWORD pe_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info)
if (!(nthdr = RtlImageNtHeader(image))) return ERROR_BAD_FORMAT; if (!(nthdr = RtlImageNtHeader(image))) return ERROR_BAD_FORMAT;
dbg = RtlImageDirectoryEntryToData(image, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &dirsize); dbg = RtlImageDirectoryEntryToData(image, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &dirsize);
if (!dbg || dirsize < sizeof(dbg)) return ERROR_BAD_EXE_FORMAT; if (!dbg) dirsize = 0;
/* fill in information from NT header */ /* fill in information from NT header */
info->timestamp = nthdr->FileHeader.TimeDateStamp; info->timestamp = nthdr->FileHeader.TimeDateStamp;

View file

@ -671,20 +671,22 @@ static BOOL create_test_pdb_ds(const WCHAR* pdb_name, const GUID* guid, DWORD ag
return TRUE; return TRUE;
} }
static BOOL create_test_dbg(const WCHAR* dbg_name, WORD machine, DWORD timestamp, DWORD size) static BOOL create_test_dbg(const WCHAR* dbg_name, WORD machine, DWORD charac, DWORD timestamp, DWORD size, struct debug_directory_blob *blob)
{ {
HANDLE hfile; HANDLE hfile;
/* minimalistic .dbg made of a header and a DEBUG_DIRECTORY without any data */ /* minimalistic .dbg made of a header and a DEBUG_DIRECTORY without any data */
const IMAGE_SEPARATE_DEBUG_HEADER header = {.Signature = 0x4944 /* DI */, IMAGE_SEPARATE_DEBUG_HEADER header =
.Flags = 0, .Machine = machine, .Characteristics = 0x010E, .TimeDateStamp = timestamp, {
.Signature = 0x4944 /* DI */,
.Flags = 0, .Machine = machine, .Characteristics = charac, .TimeDateStamp = timestamp,
.CheckSum = 0, .ImageBase = 0x00040000, .SizeOfImage = size, .NumberOfSections = 0, .CheckSum = 0, .ImageBase = 0x00040000, .SizeOfImage = size, .NumberOfSections = 0,
.ExportedNamesSize = 0, .DebugDirectorySize = sizeof(IMAGE_DEBUG_DIRECTORY)}; .ExportedNamesSize = 0, .DebugDirectorySize = 0
const IMAGE_DEBUG_DIRECTORY debug_dir = {.Characteristics = 0, .TimeDateStamp = timestamp + 1, };
.MajorVersion = 0, .MinorVersion = 0, .Type = IMAGE_DEBUG_TYPE_CODEVIEW, DWORD where, expected_size;
.SizeOfData = 0, .AddressOfRawData = 0,
.PointerToRawData = sizeof(header) + header.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + if (blob)
header.DebugDirectorySize}; header.DebugDirectorySize = sizeof(IMAGE_DEBUG_DIRECTORY);
hfile = CreateFileW(dbg_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0); hfile = CreateFileW(dbg_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0);
ok(hfile != INVALID_HANDLE_VALUE, "failed to create %ls err %lu\n", dbg_name, GetLastError()); ok(hfile != INVALID_HANDLE_VALUE, "failed to create %ls err %lu\n", dbg_name, GetLastError());
@ -692,8 +694,18 @@ static BOOL create_test_dbg(const WCHAR* dbg_name, WORD machine, DWORD timestamp
check_write_file(hfile, &header, sizeof(header)); check_write_file(hfile, &header, sizeof(header));
/* FIXME: 0 sections... as header.NumberOfSections */ /* FIXME: 0 sections... as header.NumberOfSections */
check_write_file(hfile, &debug_dir, sizeof(debug_dir)); if (blob)
ok(SetFilePointer(hfile, 0, NULL, FILE_CURRENT) == debug_dir.PointerToRawData, "mismatch\n"); {
where = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
blob->debug_directory.PointerToRawData = (blob->debug_directory.SizeOfData) ?
where + sizeof(IMAGE_DEBUG_DIRECTORY) : 0;
check_write_file(hfile, &blob->debug_directory, sizeof(IMAGE_DEBUG_DIRECTORY));
check_write_file(hfile, blob->content, blob->debug_directory.SizeOfData);
}
expected_size = sizeof(header) + header.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
if (blob)
expected_size += sizeof(IMAGE_DEBUG_DIRECTORY) + blob->debug_directory.SizeOfData;
ok(SetFilePointer(hfile, 0, NULL, FILE_CURRENT) == expected_size, "Incorrect file length\n");
CloseHandle(hfile); CloseHandle(hfile);
return TRUE; return TRUE;
@ -725,16 +737,16 @@ static void test_srvgetindexes_pe(void)
DWORD sig; DWORD sig;
WCHAR pdb_name[16]; WCHAR pdb_name[16];
WCHAR dbg_name[16]; WCHAR dbg_name[16];
BOOL in_error; DWORD last_error;
} }
indexes[] = indexes[] =
{ {
/* error cases */ /* error cases */
/* 0 */{0, {-1, -1, -1}, .in_error = TRUE}, /* 0 */{0, {-1, -1, -1}, 0, &null_guid, 0, .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_DEBUG_STRIPPED, { 0, -1, -1}, .in_error = TRUE}, {IMAGE_FILE_DEBUG_STRIPPED, { 0, -1, -1}, 0, &null_guid, 0, .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_DEBUG_STRIPPED, { 1, -1, -1}, .in_error = TRUE}, {IMAGE_FILE_DEBUG_STRIPPED, { 1, -1, -1}, 123, &null_guid, 0xaaaabbbb, .pdb_name = L"pdbjg.pdb", .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_DEBUG_STRIPPED, { 2, -1, -1}, .in_error = TRUE}, {IMAGE_FILE_DEBUG_STRIPPED, { 2, -1, -1}, 124, &guid1, 0, .pdb_name = L"pdbds.pdb", .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_DEBUG_STRIPPED, {-1, -1, -1}, .in_error = TRUE}, /* not 100% logical ! */ {IMAGE_FILE_DEBUG_STRIPPED, {-1, -1, -1}, 0, &null_guid, 0, .last_error = ERROR_BAD_EXE_FORMAT}, /* not 100% logical ! */
/* success */ /* success */
/* 5 */{0, { 0, -1, -1}, 0, &null_guid, 0 }, /* 5 */{0, { 0, -1, -1}, 0, &null_guid, 0 },
{0, { 1, -1, -1}, 123, &null_guid, 0xaaaabbbb, .pdb_name = L"pdbjg.pdb"}, {0, { 1, -1, -1}, 123, &null_guid, 0xaaaabbbb, .pdb_name = L"pdbjg.pdb"},
@ -796,16 +808,16 @@ static void test_srvgetindexes_pe(void)
memset(&ssii, 0xa5, sizeof(ssii)); memset(&ssii, 0xa5, sizeof(ssii));
ssii.sizeofstruct = sizeof(ssii); ssii.sizeofstruct = sizeof(ssii);
ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0); ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0);
if (indexes[i].in_error) if (indexes[i].last_error)
{ {
ok(!ret, "SymSrvGetFileIndexInfo should have failed\n"); ok(!ret, "SymSrvGetFileIndexInfo should have failed\n");
ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Mismatch in GetLastError: %lu\n", GetLastError()); ok(GetLastError() == indexes[i].last_error, "Mismatch in GetLastError: %lu\n", GetLastError());
} }
else else
{
ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError()); ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError());
if (ret || indexes[i].last_error == ERROR_BAD_EXE_FORMAT)
ok(ssii.age == indexes[i].age, "Mismatch in age: %lx\n", ssii.age); {
ok(ssii.age == indexes[i].age, "Mismatch in age: %lu\n", ssii.age);
ok(IsEqualGUID(&ssii.guid, indexes[i].guid), ok(IsEqualGUID(&ssii.guid, indexes[i].guid),
"Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid)); "Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid));
@ -882,48 +894,69 @@ static void test_srvgetindexes_dbg(void)
WCHAR filename[128]; WCHAR filename[128];
SYMSRV_INDEX_INFOW ssii; SYMSRV_INDEX_INFOW ssii;
BOOL ret; BOOL ret;
struct debug_directory_blob *blob_refs[1];
static struct static struct
{ {
/* input parameters */ /* input parameters */
WORD machine; WORD machine;
DWORD timestamp; DWORD characteristics;
DWORD imagesize; DWORD timestamp;
DWORD imagesize;
int blob;
/* output parameters */
DWORD age;
const GUID *guid;
WCHAR pdbname[16];
WCHAR dbgname[16];
DWORD last_error;
} }
indexes[] = indexes[] =
{ {
{IMAGE_FILE_MACHINE_I386, 0x1234, 0x00560000}, {IMAGE_FILE_MACHINE_I386, 0, 0x1234, 0x00560000, -1, 0, &null_guid, .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_MACHINE_AMD64, 0x1235, 0x00570000}, {IMAGE_FILE_MACHINE_AMD64, 0, 0x1235, 0x00570000, -1, 0, &null_guid, .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_MACHINE_I386, 0, 0x1234, 0x00560000, 0, 123, &guid1, .pdbname=L"foo.pdb"},
{IMAGE_FILE_MACHINE_AMD64, 0, 0x1235, 0x00570000, 0, 123, &guid1, .pdbname=L"foo.pdb"},
}; };
blob_refs[0] = make_pdb_ds_blob(0x1226, &guid1, 123, "foo.pdb");
for (i = 0; i < ARRAY_SIZE(indexes); i++) for (i = 0; i < ARRAY_SIZE(indexes); i++)
{ {
winetest_push_context("dbg#%02u", i); winetest_push_context("dbg#%02u", i);
/* create dll */ /* create dll */
swprintf(filename, ARRAY_SIZE(filename), L"winetest%02u.dbg", i); swprintf(filename, ARRAY_SIZE(filename), L"winetest%02u.dbg", i);
ret = create_test_dbg(filename, indexes[i].machine, indexes[i].timestamp, indexes[i].imagesize); ret = create_test_dbg(filename, indexes[i].machine, indexes[i].characteristics,
indexes[i].timestamp, indexes[i].imagesize,
indexes[i].blob == -1 ? NULL : blob_refs[indexes[i].blob]);
ok(ret, "Couldn't create dbg file %ls\n", filename); ok(ret, "Couldn't create dbg file %ls\n", filename);
memset(&ssii, 0x45, sizeof(ssii)); memset(&ssii, 0x45, sizeof(ssii));
ssii.sizeofstruct = sizeof(ssii); ssii.sizeofstruct = sizeof(ssii);
ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0); ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0);
ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError()); if (indexes[i].last_error)
{
ok(!ret, "SymSrvGetFileIndexInfo should have\n");
ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Unexpected last error: %lu\n", GetLastError());
}
else
ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError());
ok(ssii.age == 0, "Mismatch in age: %lx\n", ssii.age); ok(ssii.age == indexes[i].age, "Mismatch in age: %lx\n", ssii.age);
ok(!memcmp(&ssii.guid, &null_guid, sizeof(GUID)), ok(IsEqualGUID(&ssii.guid, indexes[i].guid),
"Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid)); "Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid));
ok(ssii.sig == 0, "Mismatch in sig: %lx\n", ssii.sig); ok(ssii.sig == 0, "Mismatch in sig: %lx\n", ssii.sig);
ok(ssii.size == indexes[i].imagesize, "Mismatch in size: %lx\n", ssii.size); ok(ssii.size == indexes[i].imagesize, "Mismatch in size: %lx\n", ssii.size);
ok(!ssii.stripped, "Mismatch in stripped: %x\n", ssii.stripped); ok(!ssii.stripped, "Mismatch in stripped: %x\n", ssii.stripped);
ok(ssii.timestamp == indexes[i].timestamp, "Mismatch in timestamp: %lx\n", ssii.timestamp); ok(ssii.timestamp == indexes[i].timestamp, "Mismatch in timestamp: %lx\n", ssii.timestamp);
ok(!wcscmp(ssii.file, filename), "Mismatch in file: %ls\n", ssii.file); ok(!wcscmp(ssii.file, filename), "Mismatch in file: %ls\n", ssii.file);
ok(!ssii.pdbfile[0], "Mismatch in pdbfile: %ls\n", ssii.pdbfile); ok(!wcscmp(ssii.pdbfile, indexes[i].pdbname), "Mismatch in pdbfile: %ls\n", ssii.pdbfile);
ok(!ssii.dbgfile[0], "Mismatch in dbgfile: %ls\n", ssii.dbgfile); ok(!wcscmp(ssii.dbgfile, indexes[i].dbgname), "Mismatch in dbgfile: %ls\n", ssii.dbgfile);
DeleteFileW(filename); DeleteFileW(filename);
winetest_pop_context(); winetest_pop_context();
} }
for (i = 0; i < ARRAY_SIZE(blob_refs); i++) free(blob_refs[i]);
} }
static void make_path(WCHAR file[MAX_PATH], const WCHAR* topdir, const WCHAR* subdir, const WCHAR* base) static void make_path(WCHAR file[MAX_PATH], const WCHAR* topdir, const WCHAR* subdir, const WCHAR* base)
@ -1533,7 +1566,8 @@ static void test_load_modules_path(void)
if (test_files[val].guid) if (test_files[val].guid)
create_test_pdb_ds(filename, test_files[val].guid, test_files[val].age_or_timestamp); create_test_pdb_ds(filename, test_files[val].guid, test_files[val].age_or_timestamp);
else else
create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64 /* FIXME */, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000); /*create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64, 0x10E, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000, blob); */
ok(0, "not supported yet\n");
} }
else ok(0, "Unrecognized file reference %c\n", *ptr); else ok(0, "Unrecognized file reference %c\n", *ptr);
} }
@ -1754,7 +1788,7 @@ static void test_load_modules_details(void)
if (test_files[val].guid) if (test_files[val].guid)
create_test_pdb_ds(filename, test_files[val].guid, test_files[val].age_or_timestamp); create_test_pdb_ds(filename, test_files[val].guid, test_files[val].age_or_timestamp);
else else
create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64 /* FIXME */, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000); create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64 /* FIXME */, 0x10E, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000, NULL);
} }
else ok(0, "Unrecognized file reference %c\n", *ptr); else ok(0, "Unrecognized file reference %c\n", *ptr);
} }

View file

@ -897,7 +897,7 @@ static HRESULT layout_shape_get_user_features(const struct dwrite_textlayout *la
feature_count = IDWriteTypography_GetFontFeatureCount(typography); feature_count = IDWriteTypography_GetFontFeatureCount(typography);
if (!feature_count) if (!feature_count)
{ {
i = range->h.range.length - i + 1; i = range->h.range.startPosition + range->h.range.length;
continue; continue;
} }

View file

@ -656,7 +656,13 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val)
TRACE("no prop_put\n"); TRACE("no prop_put\n");
return S_OK; return S_OK;
} }
return This->builtin_info->prop_put(This, prop->u.id, val); hres = This->builtin_info->prop_put(This, prop->u.id, val);
if(hres != S_FALSE)
return hres;
prop->type = PROP_JSVAL;
prop->flags = PROPF_ENUMERABLE | PROPF_CONFIGURABLE | PROPF_WRITABLE;
prop->u.val = jsval_undefined();
break;
default: default:
ERR("type %d\n", prop->type); ERR("type %d\n", prop->type);
return E_FAIL; return E_FAIL;
@ -2322,8 +2328,21 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IWineJSDispatch *iface, DI
static HRESULT WINAPI DispatchEx_GetMemberProperties(IWineJSDispatch *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) static HRESULT WINAPI DispatchEx_GetMemberProperties(IWineJSDispatch *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
{ {
jsdisp_t *This = impl_from_IWineJSDispatch(iface); jsdisp_t *This = impl_from_IWineJSDispatch(iface);
FIXME("(%p)->(%lx %lx %p)\n", This, id, grfdexFetch, pgrfdex); dispex_prop_t *prop;
return E_NOTIMPL;
TRACE("(%p)->(%lx %lx %p)\n", This, id, grfdexFetch, pgrfdex);
prop = get_prop(This, id);
if(!prop)
return DISP_E_MEMBERNOTFOUND;
*pgrfdex = 0;
if(grfdexFetch) {
FIXME("unimplemented flags %08lx\n", grfdexFetch);
return E_NOTIMPL;
}
return S_OK;
} }
static HRESULT WINAPI DispatchEx_GetMemberName(IWineJSDispatch *iface, DISPID id, BSTR *pbstrName) static HRESULT WINAPI DispatchEx_GetMemberName(IWineJSDispatch *iface, DISPID id, BSTR *pbstrName)

View file

@ -3641,6 +3641,85 @@ static void test_invokeex(void)
IActiveScript_Release(script); IActiveScript_Release(script);
} }
static void test_members(void)
{
DISPID func_id, prop_id;
IActiveScript *script;
IDispatchEx *dispex;
DWORD propflags;
HRESULT hres;
VARIANT v;
BSTR str;
hres = parse_script_expr(L"var o = { func: function() {}, prop: 1 }; o", &v, &script);
ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex);
ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
VariantClear(&v);
str = SysAllocString(L"func");
hres = IDispatchEx_GetDispID(dispex, str, 0, &func_id);
SysFreeString(str);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
str = SysAllocString(L"prop");
hres = IDispatchEx_GetDispID(dispex, str, 0, &prop_id);
SysFreeString(str);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
hres = IDispatchEx_GetMemberName(dispex, func_id, &str);
ok(hres == S_OK, "GetMemberName failed: %08lx\n", hres);
ok(!wcscmp(str, L"func"), "GetMemberName returned %s\n", wine_dbgstr_w(str));
SysFreeString(str);
hres = IDispatchEx_GetMemberName(dispex, prop_id, &str);
ok(hres == S_OK, "GetMemberName failed: %08lx\n", hres);
ok(!wcscmp(str, L"prop"), "GetMemberName returned %s\n", wine_dbgstr_w(str));
SysFreeString(str);
propflags = 0xdeadbeef;
hres = IDispatchEx_GetMemberProperties(dispex, func_id, 0, &propflags);
ok(hres == S_OK, "GetMemberProperties failed: %08lx\n", hres);
ok(propflags == 0, "propflags = %08lx", propflags);
propflags = 0xdeadbeef;
hres = IDispatchEx_GetMemberProperties(dispex, prop_id, 0, &propflags);
ok(hres == S_OK, "GetMemberProperties failed: %08lx\n", hres);
ok(propflags == 0, "propflags = %08lx", propflags);
hres = IDispatchEx_DeleteMemberByDispID(dispex, func_id);
ok(hres == S_OK, "DeleteMemberByDispID failed: %08lx\n", hres);
hres = IDispatchEx_GetMemberName(dispex, func_id, &str);
ok(hres == DISP_E_MEMBERNOTFOUND, "GetMemberName failed: %08lx\n", hres);
hres = IDispatchEx_GetMemberProperties(dispex, func_id, 0, &propflags);
ok(hres == DISP_E_MEMBERNOTFOUND, "GetMemberProperties failed: %08lx\n", hres);
hres = IDispatchEx_GetMemberName(dispex, prop_id, &str);
ok(hres == S_OK, "GetMemberName failed: %08lx\n", hres);
ok(!wcscmp(str, L"prop"), "GetMemberName returned %s\n", wine_dbgstr_w(str));
SysFreeString(str);
propflags = 0xdeadbeef;
hres = IDispatchEx_GetMemberProperties(dispex, prop_id, 0, &propflags);
ok(hres == S_OK, "GetMemberProperties failed: %08lx\n", hres);
ok(propflags == 0, "propflags = %08lx", propflags);
str = SysAllocString(L"prop");
hres = IDispatchEx_DeleteMemberByName(dispex, str, 0);
ok(hres == S_OK, "DeleteMemberByName failed: %08lx\n", hres);
SysFreeString(str);
hres = IDispatchEx_GetMemberName(dispex, prop_id, &str);
ok(hres == DISP_E_MEMBERNOTFOUND, "GetMemberName failed: %08lx\n", hres);
hres = IDispatchEx_GetMemberProperties(dispex, prop_id, 0, &propflags);
ok(hres == DISP_E_MEMBERNOTFOUND, "GetMemberProperties failed: %08lx\n", hres);
IDispatchEx_Release(dispex);
IActiveScript_Release(script);
}
static void test_destructors(void) static void test_destructors(void)
{ {
static const WCHAR cyclic_refs[] = L"(function() {\n" static const WCHAR cyclic_refs[] = L"(function() {\n"
@ -4299,6 +4378,7 @@ static BOOL run_tests(void)
test_script_exprs(); test_script_exprs();
test_invokeex(); test_invokeex();
test_members();
test_destructors(); test_destructors();
test_eval(); test_eval();
test_error_reports(); test_error_reports();

View file

@ -217,7 +217,6 @@ static void test_HeapCreate(void)
count = GetProcessHeaps( ARRAY_SIZE(heaps), heaps ); count = GetProcessHeaps( ARRAY_SIZE(heaps), heaps );
ok( count == heap_count + 2, "GetProcessHeaps returned %lu\n", count ); ok( count == heap_count + 2, "GetProcessHeaps returned %lu\n", count );
ok( heaps[0] == GetProcessHeap(), "got wrong heap\n" ); ok( heaps[0] == GetProcessHeap(), "got wrong heap\n" );
todo_wine
ok( heaps[heap_count + 0] == heap, "got wrong heap\n" ); ok( heaps[heap_count + 0] == heap, "got wrong heap\n" );
todo_wine todo_wine
ok( heaps[heap_count + 1] == heap1, "got wrong heap\n" ); ok( heaps[heap_count + 1] == heap1, "got wrong heap\n" );

View file

@ -18,12 +18,15 @@
* 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/test.h" #include "wine/test.h"
#include "winbase.h" #include "winbase.h"
#include "winternl.h" #include "winternl.h"
#include "appmodel.h" #include "appmodel.h"
static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *); static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *);
static UINT (WINAPI * pEnumSystemFirmwareTables)(DWORD, void *, DWORD);
static UINT (WINAPI * pGetSystemFirmwareTable)(DWORD, DWORD, void *, DWORD); static UINT (WINAPI * pGetSystemFirmwareTable)(DWORD, DWORD, void *, DWORD);
static LONG (WINAPI * pPackageIdFromFullName)(const WCHAR *, UINT32, UINT32 *, BYTE *); static LONG (WINAPI * pPackageIdFromFullName)(const WCHAR *, UINT32, UINT32 *, BYTE *);
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, void *, ULONG, ULONG *); static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, void *, ULONG, ULONG *);
@ -44,6 +47,7 @@ static void init_function_pointers(void)
hmod = GetModuleHandleA("kernel32.dll"); hmod = GetModuleHandleA("kernel32.dll");
GET_PROC(GetProductInfo); GET_PROC(GetProductInfo);
GET_PROC(EnumSystemFirmwareTables);
GET_PROC(GetSystemFirmwareTable); GET_PROC(GetSystemFirmwareTable);
GET_PROC(PackageIdFromFullName); GET_PROC(PackageIdFromFullName);
@ -701,17 +705,18 @@ static void test_VerifyVersionInfo(void)
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError()); ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
} }
static void test_GetSystemFirmwareTable(void) static void test_SystemFirmwareTable(void)
{ {
static const ULONG min_sfti_len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer); static const ULONG min_sfti_len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
ULONG expected_len; ULONG expected_len;
UINT len; UINT len;
NTSTATUS status;
SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti; SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti;
UCHAR *smbios_table; UCHAR *smbios_table;
if (!pGetSystemFirmwareTable) if (!pGetSystemFirmwareTable || !pEnumSystemFirmwareTables)
{ {
win_skip("GetSystemFirmwareTable not available\n"); win_skip("SystemFirmwareTable functions not available\n");
return; return;
} }
@ -720,18 +725,21 @@ static void test_GetSystemFirmwareTable(void)
sfti->ProviderSignature = RSMB; sfti->ProviderSignature = RSMB;
sfti->Action = SystemFirmwareTable_Get; sfti->Action = SystemFirmwareTable_Get;
sfti->TableID = 0; sfti->TableID = 0;
pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, min_sfti_len, &expected_len); status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, min_sfti_len, &expected_len);
if (expected_len == 0) /* xp, 2003 */ if (expected_len == 0) /* xp, 2003 */
{ {
win_skip("SystemFirmwareTableInformation is not available\n"); win_skip("SystemFirmwareTableInformation is not available\n");
HeapFree(GetProcessHeap(), 0, sfti); HeapFree(GetProcessHeap(), 0, sfti);
return; return;
} }
ok( status == STATUS_BUFFER_TOO_SMALL, "NtQuerySystemInformation failed %lx\n", status );
sfti = HeapReAlloc(GetProcessHeap(), 0, sfti, expected_len); sfti = HeapReAlloc(GetProcessHeap(), 0, sfti, expected_len);
ok(!!sfti, "Failed to allocate memory\n"); status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, expected_len, &expected_len);
pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, expected_len, &expected_len); ok( !status, "NtQuerySystemInformation failed %lx\n", status );
expected_len -= min_sfti_len; expected_len -= min_sfti_len;
ok( sfti->TableBufferLength == expected_len, "wrong len %lu/%lx\n",
sfti->TableBufferLength, expected_len );
len = pGetSystemFirmwareTable(RSMB, 0, NULL, 0); len = pGetSystemFirmwareTable(RSMB, 0, NULL, 0);
ok(len == expected_len, "Expected length %lu, got %u\n", expected_len, len); ok(len == expected_len, "Expected length %lu, got %u\n", expected_len, len);
@ -744,9 +752,27 @@ static void test_GetSystemFirmwareTable(void)
sfti->TableBuffer[3], sfti->TableBuffer[4], sfti->TableBuffer[5], sfti->TableBuffer[3], sfti->TableBuffer[4], sfti->TableBuffer[5],
smbios_table[0], smbios_table[1], smbios_table[2], smbios_table[0], smbios_table[1], smbios_table[2],
smbios_table[3], smbios_table[4], smbios_table[5]); smbios_table[3], smbios_table[4], smbios_table[5]);
HeapFree(GetProcessHeap(), 0, smbios_table);
sfti->Action = SystemFirmwareTable_Enumerate;
status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, min_sfti_len, &expected_len);
ok( status == STATUS_BUFFER_TOO_SMALL, "NtQuerySystemInformation failed %lx\n", status );
sfti = HeapReAlloc(GetProcessHeap(), 0, sfti, expected_len);
status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, expected_len, &expected_len);
ok( !status, "NtQuerySystemInformation failed %lx\n", status );
ok( expected_len == min_sfti_len + sizeof(UINT), "wrong len %lu\n", expected_len );
ok( sfti->TableBufferLength == sizeof(UINT), "wrong len %lu\n", sfti->TableBufferLength );
ok( *(UINT *)sfti->TableBuffer == 0, "wrong table id %x\n", *(UINT *)sfti->TableBuffer );
len = pEnumSystemFirmwareTables( RSMB, NULL, 0 );
ok( len == sizeof(UINT), "wrong len %u\n", len );
smbios_table = malloc( len );
len = pEnumSystemFirmwareTables( RSMB, smbios_table, len );
ok( len == sizeof(UINT), "wrong len %u\n", len );
ok( *(UINT *)smbios_table == 0, "wrong table id %x\n", *(UINT *)smbios_table );
free( smbios_table );
HeapFree(GetProcessHeap(), 0, sfti); HeapFree(GetProcessHeap(), 0, sfti);
HeapFree(GetProcessHeap(), 0, smbios_table);
} }
static const struct static const struct
@ -1100,6 +1126,6 @@ START_TEST(version)
test_GetVersionEx(); test_GetVersionEx();
test_VerifyVersionInfo(); test_VerifyVersionInfo();
test_pe_os_version(); test_pe_os_version();
test_GetSystemFirmwareTable(); test_SystemFirmwareTable();
test_PackageIdFromFullName(); test_PackageIdFromFullName();
} }

View file

@ -1785,27 +1785,12 @@ BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
* Firmware functions * Firmware functions
***********************************************************************/ ***********************************************************************/
static UINT get_firmware_table( DWORD provider, SYSTEM_FIRMWARE_TABLE_ACTION action, DWORD id,
/*********************************************************************** void *buffer, DWORD size )
* EnumSystemFirmwareTable (kernelbase.@)
*/
UINT WINAPI EnumSystemFirmwareTables( DWORD provider, void *buffer, DWORD size )
{
FIXME( "(0x%08lx, %p, %ld)\n", provider, buffer, size );
return 0;
}
/***********************************************************************
* GetSystemFirmwareTable (kernelbase.@)
*/
UINT WINAPI GetSystemFirmwareTable( DWORD provider, DWORD id, void *buffer, DWORD size )
{ {
SYSTEM_FIRMWARE_TABLE_INFORMATION *info; SYSTEM_FIRMWARE_TABLE_INFORMATION *info;
ULONG buffer_size = offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer ) + size; ULONG buffer_size = offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer ) + size;
TRACE( "(0x%08lx, 0x%08lx, %p, %ld)\n", provider, id, buffer, size );
if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, buffer_size ))) if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, buffer_size )))
{ {
SetLastError( ERROR_OUTOFMEMORY ); SetLastError( ERROR_OUTOFMEMORY );
@ -1813,7 +1798,7 @@ UINT WINAPI GetSystemFirmwareTable( DWORD provider, DWORD id, void *buffer, DWOR
} }
info->ProviderSignature = provider; info->ProviderSignature = provider;
info->Action = SystemFirmwareTable_Get; info->Action = action;
info->TableID = id; info->TableID = id;
set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation, set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation,
@ -1824,3 +1809,23 @@ UINT WINAPI GetSystemFirmwareTable( DWORD provider, DWORD id, void *buffer, DWOR
HeapFree( GetProcessHeap(), 0, info ); HeapFree( GetProcessHeap(), 0, info );
return buffer_size; return buffer_size;
} }
/***********************************************************************
* EnumSystemFirmwareTables (kernelbase.@)
*/
UINT WINAPI EnumSystemFirmwareTables( DWORD provider, void *buffer, DWORD size )
{
TRACE( "(0x%08lx, %p, %ld)\n", provider, buffer, size );
return get_firmware_table( provider, SystemFirmwareTable_Enumerate, 0, buffer, size );
}
/***********************************************************************
* GetSystemFirmwareTable (kernelbase.@)
*/
UINT WINAPI GetSystemFirmwareTable( DWORD provider, DWORD id, void *buffer, DWORD size )
{
TRACE( "(0x%08lx, 0x%08lx, %p, %ld)\n", provider, id, buffer, size );
return get_firmware_table( provider, SystemFirmwareTable_Get, id, buffer, size );
}

View file

@ -1764,6 +1764,26 @@ HRESULT dispex_call_builtin(DispatchEx *dispex, DISPID id, DISPPARAMS *dp,
return call_builtin_function(dispex, func, dp, res, ei, caller); return call_builtin_function(dispex, func, dp, res, ei, caller);
} }
static VARIANT_BOOL reset_builtin_func(DispatchEx *dispex, func_info_t *func)
{
func_obj_entry_t *entry;
if(!dispex->dynamic_data || !dispex->dynamic_data->func_disps ||
!dispex->dynamic_data->func_disps[func->func_disp_idx].func_obj)
return VARIANT_FALSE;
entry = dispex->dynamic_data->func_disps + func->func_disp_idx;
if(V_VT(&entry->val) == VT_DISPATCH &&
V_DISPATCH(&entry->val) == (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface)
return VARIANT_FALSE;
VariantClear(&entry->val);
V_VT(&entry->val) = VT_DISPATCH;
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface;
IDispatch_AddRef(V_DISPATCH(&entry->val));
return VARIANT_TRUE;
}
HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
{ {
switch(get_dispid_type(id)) { switch(get_dispid_type(id)) {
@ -1793,26 +1813,7 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
/* For builtin functions, we set their value to the original function. */ /* For builtin functions, we set their value to the original function. */
if(func->func_disp_idx >= 0) { if(func->func_disp_idx >= 0) {
func_obj_entry_t *entry; *success = reset_builtin_func(This, func);
if(!This->dynamic_data || !This->dynamic_data->func_disps
|| !This->dynamic_data->func_disps[func->func_disp_idx].func_obj) {
*success = VARIANT_FALSE;
return S_OK;
}
entry = This->dynamic_data->func_disps + func->func_disp_idx;
if(V_VT(&entry->val) == VT_DISPATCH
&& V_DISPATCH(&entry->val) == (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface) {
*success = VARIANT_FALSE;
return S_OK;
}
VariantClear(&entry->val);
V_VT(&entry->val) = VT_DISPATCH;
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface;
IDispatch_AddRef(V_DISPATCH(&entry->val));
*success = VARIANT_TRUE;
return S_OK; return S_OK;
} }
*success = VARIANT_TRUE; *success = VARIANT_TRUE;
@ -2304,7 +2305,8 @@ static HRESULT dispex_prop_delete(DispatchEx *dispex, DISPID id)
return E_NOTIMPL; return E_NOTIMPL;
} }
if(is_dynamic_dispid(id)) { switch(get_dispid_type(id)) {
case DISPEXPROP_DYNAMIC: {
DWORD idx = id - DISPID_DYNPROP_0; DWORD idx = id - DISPID_DYNPROP_0;
dynamic_prop_t *prop; dynamic_prop_t *prop;
@ -2316,6 +2318,24 @@ static HRESULT dispex_prop_delete(DispatchEx *dispex, DISPID id)
prop->flags |= DYNPROP_DELETED; prop->flags |= DYNPROP_DELETED;
return S_OK; return S_OK;
} }
case DISPEXPROP_BUILTIN: {
func_info_t *func;
HRESULT hres;
if(!ensure_real_info(dispex))
return E_OUTOFMEMORY;
hres = get_builtin_func(dispex->info, id, &func);
if(FAILED(hres))
return hres;
if(func->func_disp_idx >= 0)
reset_builtin_func(dispex, func);
return S_OK;
}
default:
break;
}
return S_OK; return S_OK;
} }

View file

@ -48,6 +48,7 @@ IDispatch *script_parse_event(HTMLInnerWindow*,LPCWSTR);
HRESULT exec_script(HTMLInnerWindow*,const WCHAR*,const WCHAR*,VARIANT*); HRESULT exec_script(HTMLInnerWindow*,const WCHAR*,const WCHAR*,VARIANT*);
void update_browser_script_mode(GeckoBrowser*,IUri*); 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*);
IDispatch *get_script_disp(ScriptHost*); IDispatch *get_script_disp(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

@ -3302,7 +3302,7 @@ static global_prop_t *alloc_global_prop(HTMLInnerWindow *This, global_prop_type_
This->global_prop_size = new_size; This->global_prop_size = new_size;
} }
This->global_props[This->global_prop_cnt].name = wcsdup(name); This->global_props[This->global_prop_cnt].name = SysAllocString(name);
if(!This->global_props[This->global_prop_cnt].name) if(!This->global_props[This->global_prop_cnt].name)
return NULL; return NULL;
@ -3324,8 +3324,10 @@ HRESULT search_window_props(HTMLInnerWindow *This, const WCHAR *name, DWORD grfd
for(i=0; i < This->global_prop_cnt; i++) { for(i=0; i < This->global_prop_cnt; i++) {
/* FIXME: case sensitivity */ /* FIXME: case sensitivity */
if(!wcscmp(This->global_props[i].name, name)) { if(!wcscmp(This->global_props[i].name, name)) {
*pid = MSHTML_DISPID_CUSTOM_MIN+i; HRESULT hres = global_prop_still_exists(This, &This->global_props[i]);
return S_OK; if(hres == S_OK)
*pid = MSHTML_DISPID_CUSTOM_MIN + i;
return (hres == DISP_E_MEMBERNOTFOUND) ? DISP_E_UNKNOWNNAME : hres;
} }
} }
@ -3364,18 +3366,34 @@ static HRESULT WINAPI WindowDispEx_InvokeEx(IWineJSDispatchHost *iface, DISPID i
static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IWineJSDispatchHost *iface, BSTR bstrName, DWORD grfdex) static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IWineJSDispatchHost *iface, BSTR bstrName, DWORD grfdex)
{ {
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
compat_mode_t compat_mode = dispex_compat_mode(&This->base.inner_window->event_target.dispex);
TRACE("(%p)->(%s %lx)\n", This, debugstr_w(bstrName), grfdex); TRACE("(%p)->(%s %lx)\n", This, debugstr_w(bstrName), grfdex);
if(compat_mode < COMPAT_MODE_IE8) {
/* Not implemented by IE */
return E_NOTIMPL;
}
if(compat_mode == COMPAT_MODE_IE8)
return MSHTML_E_INVALID_ACTION;
return IWineJSDispatchHost_DeleteMemberByName(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, bstrName, grfdex); return IWineJSDispatchHost_DeleteMemberByName(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, bstrName, grfdex);
} }
static HRESULT WINAPI WindowDispEx_DeleteMemberByDispID(IWineJSDispatchHost *iface, DISPID id) static HRESULT WINAPI WindowDispEx_DeleteMemberByDispID(IWineJSDispatchHost *iface, DISPID id)
{ {
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
compat_mode_t compat_mode = dispex_compat_mode(&This->base.inner_window->event_target.dispex);
TRACE("(%p)->(%lx)\n", This, id); TRACE("(%p)->(%lx)\n", This, id);
if(compat_mode < COMPAT_MODE_IE8) {
/* Not implemented by IE */
return E_NOTIMPL;
}
if(compat_mode == COMPAT_MODE_IE8)
return MSHTML_E_INVALID_ACTION;
return IWineJSDispatchHost_DeleteMemberByDispID(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id); return IWineJSDispatchHost_DeleteMemberByDispID(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id);
} }
@ -3763,7 +3781,7 @@ static void HTMLWindow_destructor(DispatchEx *dispex)
VariantClear(&This->performance); VariantClear(&This->performance);
for(i = 0; i < This->global_prop_cnt; i++) for(i = 0; i < This->global_prop_cnt; i++)
free(This->global_props[i].name); SysFreeString(This->global_props[i].name);
free(This->global_props); free(This->global_props);
if(This->mon) if(This->mon)
@ -3910,6 +3928,9 @@ HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags,
case DISPATCH_PROPERTYPUT: { case DISPATCH_PROPERTYPUT: {
DISPID dispex_id; DISPID dispex_id;
if(This->event_target.dispex.jsdisp)
return S_FALSE;
hres = dispex_get_dynid(&This->event_target.dispex, prop->name, TRUE, &dispex_id); hres = dispex_get_dynid(&This->event_target.dispex, prop->name, TRUE, &dispex_id);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -3953,6 +3974,44 @@ HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags,
return hres; return hres;
} }
static HRESULT HTMLWindow_delete(DispatchEx *dispex, DISPID id)
{
HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN;
global_prop_t *prop;
HRESULT hres = S_OK;
if(idx >= This->global_prop_cnt)
return DISP_E_MEMBERNOTFOUND;
prop = This->global_props + idx;
switch(prop->type) {
case GLOBAL_SCRIPTVAR: {
IDispatchEx *iface;
IDispatch *disp;
disp = get_script_disp(prop->script_host);
if(!disp)
return E_UNEXPECTED;
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&iface);
if(SUCCEEDED(hres)) {
hres = IDispatchEx_DeleteMemberByDispID(iface, prop->id);
IDispatchEx_Release(iface);
}else {
WARN("No IDispatchEx, so can't delete\n");
hres = S_OK;
}
IDispatch_Release(disp);
break;
}
default:
break;
}
return hres;
}
static HRESULT HTMLWindow_next_dispid(DispatchEx *dispex, DISPID id, DISPID *pid) static HRESULT HTMLWindow_next_dispid(DispatchEx *dispex, DISPID id, DISPID *pid)
{ {
DWORD idx = (id == DISPID_STARTENUM) ? 0 : id - MSHTML_DISPID_CUSTOM_MIN + 1; DWORD idx = (id == DISPID_STARTENUM) ? 0 : id - MSHTML_DISPID_CUSTOM_MIN + 1;
@ -4179,6 +4238,7 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = {
.lookup_dispid = HTMLWindow_lookup_dispid, .lookup_dispid = HTMLWindow_lookup_dispid,
.find_dispid = HTMLWindow_find_dispid, .find_dispid = HTMLWindow_find_dispid,
.invoke = HTMLWindow_invoke, .invoke = HTMLWindow_invoke,
.delete = HTMLWindow_delete,
.next_dispid = HTMLWindow_next_dispid, .next_dispid = HTMLWindow_next_dispid,
.get_prop_desc = HTMLWindow_get_prop_desc, .get_prop_desc = HTMLWindow_get_prop_desc,
.get_script_global = HTMLWindow_get_script_global, .get_script_global = HTMLWindow_get_script_global,

View file

@ -656,7 +656,7 @@ typedef enum {
typedef struct { typedef struct {
global_prop_type_t type; global_prop_type_t type;
WCHAR *name; BSTR name;
ScriptHost *script_host; ScriptHost *script_host;
DISPID id; DISPID id;
} global_prop_t; } global_prop_t;

View file

@ -85,6 +85,7 @@ struct ScriptHost {
SCRIPTSTATE script_state; SCRIPTSTATE script_state;
HTMLInnerWindow *window; HTMLInnerWindow *window;
IDispatchEx *script_dispex;
GUID guid; GUID guid;
struct list entry; struct list entry;
@ -255,6 +256,18 @@ static BOOL init_script_engine(ScriptHost *script_host, IActiveScript *script)
if(is_second_init) if(is_second_init)
set_script_prop(first_host->script, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var); set_script_prop(first_host->script, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var);
} }
if(IsEqualGUID(&script_host->guid, &CLSID_JScript)) {
IDispatch *script_disp;
hres = IActiveScript_GetScriptDispatch(script, NULL, &script_disp);
if(FAILED(hres))
WARN("GetScriptDispatch failed: %08lx\n", hres);
else {
IDispatch_QueryInterface(script_disp, &IID_IDispatchEx, (void**)&script_host->script_dispex);
IDispatch_Release(script_disp);
}
}
}else { }else {
WARN("AddNamedItem failed: %08lx\n", hres); WARN("AddNamedItem failed: %08lx\n", hres);
} }
@ -288,6 +301,8 @@ static void release_script_engine(ScriptHost *This)
unlink_ref(&This->parse); unlink_ref(&This->parse);
} }
if(This->script_dispex)
IDispatchEx_Release(This->script_dispex);
IActiveScript_Release(This->script); IActiveScript_Release(This->script);
This->script = NULL; This->script = NULL;
This->script_state = SCRIPTSTATE_UNINITIALIZED; This->script_state = SCRIPTSTATE_UNINITIALIZED;
@ -1825,6 +1840,48 @@ BOOL find_global_prop(HTMLInnerWindow *window, const WCHAR *name, DWORD flags, S
return FALSE; return FALSE;
} }
HRESULT global_prop_still_exists(HTMLInnerWindow *window, global_prop_t *prop)
{
HRESULT hres;
switch(prop->type) {
case GLOBAL_SCRIPTVAR: {
DWORD properties;
if(!prop->script_host->script)
return E_UNEXPECTED;
if(!prop->script_host->script_dispex)
return S_OK;
return IDispatchEx_GetMemberProperties(prop->script_host->script_dispex, prop->id, 0, &properties);
}
case GLOBAL_ELEMENTVAR: {
IHTMLElement *elem;
hres = IHTMLDocument3_getElementById(&window->doc->IHTMLDocument3_iface, prop->name, &elem);
if(FAILED(hres))
return hres;
if(!elem)
return DISP_E_MEMBERNOTFOUND;
IHTMLElement_Release(elem);
return S_OK;
}
case GLOBAL_FRAMEVAR: {
HTMLOuterWindow *frame;
hres = get_frame_by_name(window->base.outer_window, prop->name, FALSE, &frame);
if(FAILED(hres))
return hres;
return frame ? S_OK : DISP_E_MEMBERNOTFOUND;
}
default:
break;
}
return S_OK;
}
static BOOL is_jscript_available(void) static BOOL is_jscript_available(void)
{ {
static BOOL available, checked; static BOOL available, checked;

View file

@ -1301,7 +1301,7 @@ sync_test("navigator", function() {
sync_test("delete_prop", function() { sync_test("delete_prop", function() {
var v = document.documentMode; var v = document.documentMode;
var obj = document.createElement("div"), r, obj2; var obj = document.createElement("div"), r, obj2, func, prop;
obj.prop1 = true; obj.prop1 = true;
r = false; r = false;
@ -1317,6 +1317,40 @@ sync_test("delete_prop", function() {
ok(!r, "got an unexpected exception"); ok(!r, "got an unexpected exception");
ok(!("prop1" in obj), "prop1 is still in obj"); ok(!("prop1" in obj), "prop1 is still in obj");
/* builtin properties don't throw any exception, but are not really deleted */
r = (delete obj.tagName);
ok(r, "delete returned " + r);
ok("tagName" in obj, "tagName deleted from obj");
ok(obj.tagName === "DIV", "tagName = " + obj.tagName);
prop = obj.id;
r = (delete obj.id);
ok(r, "delete returned " + r);
ok("id" in obj, "id deleted from obj");
ok(obj.id === prop, "id = " + obj.id);
obj.id = "1234";
ok(obj.id === "1234", "id after set to 1234 = " + obj.id);
r = (delete obj.id);
ok(r, "delete returned " + r);
ok("id" in obj, "id deleted from obj");
ok(obj.id === "1234", "id = " + obj.id);
/* builtin functions get reset to their original values */
func = function() { }
prop = obj.setAttribute;
r = (delete obj.setAttribute);
ok(r, "delete returned " + r);
ok("setAttribute" in obj, "setAttribute deleted from obj");
ok(obj.setAttribute === prop, "setAttribute = " + obj.setAttribute);
obj.setAttribute = func;
ok(obj.setAttribute === func, "setAttribute after set to func = " + obj.setAttribute);
r = (delete obj.setAttribute);
ok(r, "delete returned " + r);
ok("setAttribute" in obj, "setAttribute deleted from obj");
ok(obj.setAttribute === prop, "setAttribute = " + obj.setAttribute);
/* again, this time prop1 does not exist */ /* again, this time prop1 does not exist */
r = false; r = false;
try { try {
@ -1326,7 +1360,6 @@ sync_test("delete_prop", function() {
} }
if(v < 9) { if(v < 9) {
ok(r, "did not get an expected exception"); ok(r, "did not get an expected exception");
return;
}else { }else {
ok(!r, "got an unexpected exception"); ok(!r, "got an unexpected exception");
ok(!("prop1" in obj), "prop1 is still in obj"); ok(!("prop1" in obj), "prop1 is still in obj");
@ -1337,12 +1370,6 @@ sync_test("delete_prop", function() {
ok("className" in obj, "className deleted from obj"); ok("className" in obj, "className deleted from obj");
ok(obj.className === "", "className = " + obj.className); ok(obj.className === "", "className = " + obj.className);
/* builtin propertiles don't throw any exception, but are not really deleted */
r = (delete obj.tagName);
ok(r, "delete returned " + r);
ok("tagName" in obj, "tagName deleted from obj");
ok(obj.tagName === "DIV", "tagName = " + obj.tagName);
obj = document.querySelectorAll("*"); obj = document.querySelectorAll("*");
ok("0" in obj, "0 is not in obj"); ok("0" in obj, "0 is not in obj");
obj2 = obj[0]; obj2 = obj[0];
@ -1353,12 +1380,27 @@ sync_test("delete_prop", function() {
/* test window object and its global scope handling */ /* test window object and its global scope handling */
obj = window; obj = window;
ok("encodeURIComponent" in obj, "encodeURIComponent not in obj");
try {
prop = window.encodeURIComponent;
r = (delete window.encodeURIComponent);
ok(v >= 9, "did not get an expect exception deleting encodeURIComponent");
ok(r, "delete returned " + r);
ok(!("encodeURIComponent" in obj), "encodeURIComponent is still in obj");
window.encodeURIComponent = prop;
}catch(ex) {
ok(v < 9, "expected exception deleting encodeURIComponent");
ok(ex.number === 0xa01bd - 0x80000000, "deleting encodeURIComponent threw " + ex.number);
ok("encodeURIComponent" in obj, "encodeURIComponent is not in obj");
}
obj.globalprop1 = true; obj.globalprop1 = true;
ok(globalprop1, "globalprop1 = " + globalprop1); ok(globalprop1, "globalprop1 = " + globalprop1);
r = false; r = false;
try { try {
delete obj.globalprop1; delete obj.globalprop1;
}catch(ex) { }catch(ex) {
ok(ex.number === 0xa01bd - 0x80000000, "deleting globalprop1 threw " + ex.number);
r = true; r = true;
} }
if(v < 9) { if(v < 9) {
@ -1374,13 +1416,13 @@ sync_test("delete_prop", function() {
try { try {
delete obj.globalprop2; delete obj.globalprop2;
}catch(ex) { }catch(ex) {
ok(ex.number === 0xa01bd - 0x80000000, "deleting globalprop2 threw " + ex.number);
r = true; r = true;
} }
if(v < 9) { if(v < 9) {
ok(r, "did not get an expected globalprop2 exception"); ok(r, "did not get an expected globalprop2 exception");
}else { }else {
ok(!r, "got an unexpected exception"); ok(!r, "got an unexpected exception");
todo_wine.
ok(!("globalprop2" in obj), "globalprop2 is still in obj"); ok(!("globalprop2" in obj), "globalprop2 is still in obj");
} }
@ -1390,6 +1432,7 @@ sync_test("delete_prop", function() {
try { try {
delete globalprop3; delete globalprop3;
}catch(ex) { }catch(ex) {
ok(ex.number === 0xa01bd - 0x80000000, "deleting globalprop3 threw " + ex.number);
r = true; r = true;
} }
if(v < 9) { if(v < 9) {
@ -1404,8 +1447,88 @@ sync_test("delete_prop", function() {
ok(obj.globalprop4, "globalprop4 = " + globalprop4); ok(obj.globalprop4, "globalprop4 = " + globalprop4);
r = (delete globalprop4); r = (delete globalprop4);
ok(r, "delete returned " + r); ok(r, "delete returned " + r);
todo_wine.
ok(!("globalprop4" in obj), "globalprop4 is still in obj"); ok(!("globalprop4" in obj), "globalprop4 is still in obj");
globalprop5 = true;
ok(obj.globalprop5, "globalprop5 = " + globalprop5);
try {
r = (delete window.globalprop5);
ok(v >= 9, "did not get an expected exception deleting globalprop5");
ok(r, "delete returned " + r);
ok(!("globalprop5" in obj), "globalprop5 is still in obj");
}catch(ex) {
ok(v < 9, "expected exception deleting globalprop5");
ok(ex.number === 0xa01bd - 0x80000000, "deleting globalprop5 threw " + ex.number);
ok("globalprop5" in obj, "globalprop5 is not in obj");
}
document.body.innerHTML = '<div id="winetest"/>';
ok("winetest" in obj, "winetest not in obj");
try {
r = (delete window.winetest);
ok(v >= 9, "did not get an expected exception deleting winetest");
ok(r, "delete returned " + r);
}catch(ex) {
ok(v < 9, "expected exception deleting winetest");
ok(ex.number === 0xa01bd - 0x80000000, "deleting winetest threw " + ex.number);
}
ok("winetest" in obj, "winetest is not in obj");
document.body.innerHTML = "";
ok(!("winetest" in obj), "winetest is still in obj");
document.body.innerHTML = '<div id="foobar"/>';
ok("foobar" in obj, "foobar not in obj");
window.foobar = "1234";
ok(obj.foobar === "1234", "foobar = " + obj.foobar);
document.body.innerHTML = "";
ok("foobar" in obj, "foobar is not in obj");
ok(obj.foobar === "1234", "foobar = " + obj.foobar);
try {
r = (delete window.foobar);
ok(v >= 9, "did not get an expected exception deleting foobar");
ok(r, "delete returned " + r);
ok(!("foobar" in obj), "foobar is still in obj");
}catch(ex) {
ok(v < 9, "expected exception deleting foobar");
ok(ex.number === 0xa01bd - 0x80000000, "deleting foobar threw " + ex.number);
ok("foobar" in obj, "foobar is not in obj");
}
document.body.innerHTML = '<div id="barfoo"/>';
ok("barfoo" in obj, "barfoo not in obj");
window.barfoo = "5678";
ok(obj.barfoo === "5678", "barfoo = " + obj.barfoo);
try {
r = (delete window.barfoo);
ok(v >= 9, "did not get an expected exception deleting barfoo");
ok(r, "delete returned " + r);
ok(obj.barfoo !== "5678", "barfoo is still 5678");
}catch(ex) {
ok(v < 9, "expected exception deleting barfoo");
ok(ex.number === 0xa01bd - 0x80000000, "deleting barfoo threw " + ex.number);
ok(obj.barfoo === "5678", "barfoo = " + obj.barfoo);
}
ok("barfoo" in obj, "barfoo is not in obj");
document.body.innerHTML = "";
if(v < 9)
ok("barfoo" in obj, "barfoo is not in obj");
else
ok(!("barfoo" in obj), "barfoo is still in obj");
document.body.innerHTML = '<iframe id="testwine"/>';
ok("testwine" in obj, "testwine not in obj");
try {
r = (delete window.testwine);
ok(v >= 9, "did not get an expected exception deleting testwine");
ok(r, "delete returned " + r);
}catch(ex) {
ok(v < 9, "expected exception deleting testwine");
ok(ex.number === 0xa01bd - 0x80000000, "deleting testwine threw " + ex.number);
}
ok("testwine" in obj, "testwine is not in obj");
document.body.innerHTML = "";
ok(!("testwine" in obj), "testwine is still in obj");
}); });
sync_test("detached arguments", function() { sync_test("detached arguments", function() {

View file

@ -400,6 +400,7 @@
@ stdcall -syscall NtSetInformationVirtualMemory(long long ptr ptr ptr long) @ stdcall -syscall NtSetInformationVirtualMemory(long long ptr ptr ptr long)
@ stdcall -syscall NtSetIntervalProfile(long long) @ stdcall -syscall NtSetIntervalProfile(long long)
@ stdcall -syscall NtSetIoCompletion(ptr long long long long) @ stdcall -syscall NtSetIoCompletion(ptr long long long long)
@ stdcall -syscall NtSetIoCompletionEx(ptr ptr long long long long)
@ stdcall -syscall NtSetLdtEntries(long int64 long int64) @ stdcall -syscall NtSetLdtEntries(long int64 long int64)
# @ stub NtSetLowEventPair # @ stub NtSetLowEventPair
# @ stub NtSetLowWaitHighEventPair # @ stub NtSetLowWaitHighEventPair
@ -1460,6 +1461,7 @@
@ stdcall -private -syscall ZwSetInformationVirtualMemory(long long ptr ptr ptr long) NtSetInformationVirtualMemory @ stdcall -private -syscall ZwSetInformationVirtualMemory(long long ptr ptr ptr long) NtSetInformationVirtualMemory
@ stdcall -private -syscall ZwSetIntervalProfile(long long) NtSetIntervalProfile @ stdcall -private -syscall ZwSetIntervalProfile(long long) NtSetIntervalProfile
@ stdcall -private -syscall ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion @ stdcall -private -syscall ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion
@ stdcall -private -syscall ZwSetIoCompletionEx(ptr ptr long long long long) NtSetIoCompletionEx
@ stdcall -private -syscall ZwSetLdtEntries(long int64 long int64) NtSetLdtEntries @ stdcall -private -syscall ZwSetLdtEntries(long int64 long int64) NtSetLdtEntries
# @ stub ZwSetLowEventPair # @ stub ZwSetLowEventPair
# @ stub ZwSetLowWaitHighEventPair # @ stub ZwSetLowWaitHighEventPair

158
dlls/ntdll/ntsyscalls.h generated
View file

@ -203,48 +203,49 @@
SYSCALL_ENTRY( 0x00c7, NtSetInformationVirtualMemory, 24 ) \ SYSCALL_ENTRY( 0x00c7, NtSetInformationVirtualMemory, 24 ) \
SYSCALL_ENTRY( 0x00c8, NtSetIntervalProfile, 8 ) \ SYSCALL_ENTRY( 0x00c8, NtSetIntervalProfile, 8 ) \
SYSCALL_ENTRY( 0x00c9, NtSetIoCompletion, 20 ) \ SYSCALL_ENTRY( 0x00c9, NtSetIoCompletion, 20 ) \
SYSCALL_ENTRY( 0x00ca, NtSetLdtEntries, 24 ) \ SYSCALL_ENTRY( 0x00ca, NtSetIoCompletionEx, 24 ) \
SYSCALL_ENTRY( 0x00cb, NtSetSecurityObject, 12 ) \ SYSCALL_ENTRY( 0x00cb, NtSetLdtEntries, 24 ) \
SYSCALL_ENTRY( 0x00cc, NtSetSystemInformation, 12 ) \ SYSCALL_ENTRY( 0x00cc, NtSetSecurityObject, 12 ) \
SYSCALL_ENTRY( 0x00cd, NtSetSystemTime, 8 ) \ SYSCALL_ENTRY( 0x00cd, NtSetSystemInformation, 12 ) \
SYSCALL_ENTRY( 0x00ce, NtSetThreadExecutionState, 8 ) \ SYSCALL_ENTRY( 0x00ce, NtSetSystemTime, 8 ) \
SYSCALL_ENTRY( 0x00cf, NtSetTimer, 28 ) \ SYSCALL_ENTRY( 0x00cf, NtSetThreadExecutionState, 8 ) \
SYSCALL_ENTRY( 0x00d0, NtSetTimerResolution, 12 ) \ SYSCALL_ENTRY( 0x00d0, NtSetTimer, 28 ) \
SYSCALL_ENTRY( 0x00d1, NtSetValueKey, 24 ) \ SYSCALL_ENTRY( 0x00d1, NtSetTimerResolution, 12 ) \
SYSCALL_ENTRY( 0x00d2, NtSetVolumeInformationFile, 20 ) \ SYSCALL_ENTRY( 0x00d2, NtSetValueKey, 24 ) \
SYSCALL_ENTRY( 0x00d3, NtShutdownSystem, 4 ) \ SYSCALL_ENTRY( 0x00d3, NtSetVolumeInformationFile, 20 ) \
SYSCALL_ENTRY( 0x00d4, NtSignalAndWaitForSingleObject, 16 ) \ SYSCALL_ENTRY( 0x00d4, NtShutdownSystem, 4 ) \
SYSCALL_ENTRY( 0x00d5, NtSuspendProcess, 4 ) \ SYSCALL_ENTRY( 0x00d5, NtSignalAndWaitForSingleObject, 16 ) \
SYSCALL_ENTRY( 0x00d6, NtSuspendThread, 8 ) \ SYSCALL_ENTRY( 0x00d6, NtSuspendProcess, 4 ) \
SYSCALL_ENTRY( 0x00d7, NtSystemDebugControl, 24 ) \ SYSCALL_ENTRY( 0x00d7, NtSuspendThread, 8 ) \
SYSCALL_ENTRY( 0x00d8, NtTerminateJobObject, 8 ) \ SYSCALL_ENTRY( 0x00d8, NtSystemDebugControl, 24 ) \
SYSCALL_ENTRY( 0x00d9, NtTerminateProcess, 8 ) \ SYSCALL_ENTRY( 0x00d9, NtTerminateJobObject, 8 ) \
SYSCALL_ENTRY( 0x00da, NtTerminateThread, 8 ) \ SYSCALL_ENTRY( 0x00da, NtTerminateProcess, 8 ) \
SYSCALL_ENTRY( 0x00db, NtTestAlert, 0 ) \ SYSCALL_ENTRY( 0x00db, NtTerminateThread, 8 ) \
SYSCALL_ENTRY( 0x00dc, NtTraceControl, 24 ) \ SYSCALL_ENTRY( 0x00dc, NtTestAlert, 0 ) \
SYSCALL_ENTRY( 0x00dd, NtUnloadDriver, 4 ) \ SYSCALL_ENTRY( 0x00dd, NtTraceControl, 24 ) \
SYSCALL_ENTRY( 0x00de, NtUnloadKey, 4 ) \ SYSCALL_ENTRY( 0x00de, NtUnloadDriver, 4 ) \
SYSCALL_ENTRY( 0x00df, NtUnlockFile, 20 ) \ SYSCALL_ENTRY( 0x00df, NtUnloadKey, 4 ) \
SYSCALL_ENTRY( 0x00e0, NtUnlockVirtualMemory, 16 ) \ SYSCALL_ENTRY( 0x00e0, NtUnlockFile, 20 ) \
SYSCALL_ENTRY( 0x00e1, NtUnmapViewOfSection, 8 ) \ SYSCALL_ENTRY( 0x00e1, NtUnlockVirtualMemory, 16 ) \
SYSCALL_ENTRY( 0x00e2, NtUnmapViewOfSectionEx, 12 ) \ SYSCALL_ENTRY( 0x00e2, NtUnmapViewOfSection, 8 ) \
SYSCALL_ENTRY( 0x00e3, NtWaitForAlertByThreadId, 8 ) \ SYSCALL_ENTRY( 0x00e3, NtUnmapViewOfSectionEx, 12 ) \
SYSCALL_ENTRY( 0x00e4, NtWaitForDebugEvent, 16 ) \ SYSCALL_ENTRY( 0x00e4, NtWaitForAlertByThreadId, 8 ) \
SYSCALL_ENTRY( 0x00e5, NtWaitForKeyedEvent, 16 ) \ SYSCALL_ENTRY( 0x00e5, NtWaitForDebugEvent, 16 ) \
SYSCALL_ENTRY( 0x00e6, NtWaitForMultipleObjects, 20 ) \ SYSCALL_ENTRY( 0x00e6, NtWaitForKeyedEvent, 16 ) \
SYSCALL_ENTRY( 0x00e7, NtWaitForSingleObject, 12 ) \ SYSCALL_ENTRY( 0x00e7, NtWaitForMultipleObjects, 20 ) \
SYSCALL_ENTRY( 0x00e8, NtWow64AllocateVirtualMemory64, 28 ) \ SYSCALL_ENTRY( 0x00e8, NtWaitForSingleObject, 12 ) \
SYSCALL_ENTRY( 0x00e9, NtWow64GetNativeSystemInformation, 16 ) \ SYSCALL_ENTRY( 0x00e9, NtWow64AllocateVirtualMemory64, 28 ) \
SYSCALL_ENTRY( 0x00ea, NtWow64IsProcessorFeaturePresent, 4 ) \ SYSCALL_ENTRY( 0x00ea, NtWow64GetNativeSystemInformation, 16 ) \
SYSCALL_ENTRY( 0x00eb, NtWow64QueryInformationProcess64, 20 ) \ SYSCALL_ENTRY( 0x00eb, NtWow64IsProcessorFeaturePresent, 4 ) \
SYSCALL_ENTRY( 0x00ec, NtWow64ReadVirtualMemory64, 28 ) \ SYSCALL_ENTRY( 0x00ec, NtWow64QueryInformationProcess64, 20 ) \
SYSCALL_ENTRY( 0x00ed, NtWow64WriteVirtualMemory64, 28 ) \ SYSCALL_ENTRY( 0x00ed, NtWow64ReadVirtualMemory64, 28 ) \
SYSCALL_ENTRY( 0x00ee, NtWriteFile, 36 ) \ SYSCALL_ENTRY( 0x00ee, NtWow64WriteVirtualMemory64, 28 ) \
SYSCALL_ENTRY( 0x00ef, NtWriteFileGather, 36 ) \ SYSCALL_ENTRY( 0x00ef, NtWriteFile, 36 ) \
SYSCALL_ENTRY( 0x00f0, NtWriteVirtualMemory, 20 ) \ SYSCALL_ENTRY( 0x00f0, NtWriteFileGather, 36 ) \
SYSCALL_ENTRY( 0x00f1, NtYieldExecution, 0 ) \ SYSCALL_ENTRY( 0x00f1, NtWriteVirtualMemory, 20 ) \
SYSCALL_ENTRY( 0x00f2, wine_nt_to_unix_file_name, 16 ) \ SYSCALL_ENTRY( 0x00f2, NtYieldExecution, 0 ) \
SYSCALL_ENTRY( 0x00f3, wine_unix_to_nt_file_name, 12 ) SYSCALL_ENTRY( 0x00f3, wine_nt_to_unix_file_name, 16 ) \
SYSCALL_ENTRY( 0x00f4, wine_unix_to_nt_file_name, 12 )
#define ALL_SYSCALLS64 \ #define ALL_SYSCALLS64 \
SYSCALL_ENTRY( 0x0000, NtAcceptConnectPort, 48 ) \ SYSCALL_ENTRY( 0x0000, NtAcceptConnectPort, 48 ) \
@ -449,39 +450,40 @@
SYSCALL_ENTRY( 0x00c7, NtSetInformationVirtualMemory, 48 ) \ SYSCALL_ENTRY( 0x00c7, NtSetInformationVirtualMemory, 48 ) \
SYSCALL_ENTRY( 0x00c8, NtSetIntervalProfile, 16 ) \ SYSCALL_ENTRY( 0x00c8, NtSetIntervalProfile, 16 ) \
SYSCALL_ENTRY( 0x00c9, NtSetIoCompletion, 40 ) \ SYSCALL_ENTRY( 0x00c9, NtSetIoCompletion, 40 ) \
SYSCALL_ENTRY( 0x00ca, NtSetLdtEntries, 32 ) \ SYSCALL_ENTRY( 0x00ca, NtSetIoCompletionEx, 48 ) \
SYSCALL_ENTRY( 0x00cb, NtSetSecurityObject, 24 ) \ SYSCALL_ENTRY( 0x00cb, NtSetLdtEntries, 32 ) \
SYSCALL_ENTRY( 0x00cc, NtSetSystemInformation, 24 ) \ SYSCALL_ENTRY( 0x00cc, NtSetSecurityObject, 24 ) \
SYSCALL_ENTRY( 0x00cd, NtSetSystemTime, 16 ) \ SYSCALL_ENTRY( 0x00cd, NtSetSystemInformation, 24 ) \
SYSCALL_ENTRY( 0x00ce, NtSetThreadExecutionState, 16 ) \ SYSCALL_ENTRY( 0x00ce, NtSetSystemTime, 16 ) \
SYSCALL_ENTRY( 0x00cf, NtSetTimer, 56 ) \ SYSCALL_ENTRY( 0x00cf, NtSetThreadExecutionState, 16 ) \
SYSCALL_ENTRY( 0x00d0, NtSetTimerResolution, 24 ) \ SYSCALL_ENTRY( 0x00d0, NtSetTimer, 56 ) \
SYSCALL_ENTRY( 0x00d1, NtSetValueKey, 48 ) \ SYSCALL_ENTRY( 0x00d1, NtSetTimerResolution, 24 ) \
SYSCALL_ENTRY( 0x00d2, NtSetVolumeInformationFile, 40 ) \ SYSCALL_ENTRY( 0x00d2, NtSetValueKey, 48 ) \
SYSCALL_ENTRY( 0x00d3, NtShutdownSystem, 8 ) \ SYSCALL_ENTRY( 0x00d3, NtSetVolumeInformationFile, 40 ) \
SYSCALL_ENTRY( 0x00d4, NtSignalAndWaitForSingleObject, 32 ) \ SYSCALL_ENTRY( 0x00d4, NtShutdownSystem, 8 ) \
SYSCALL_ENTRY( 0x00d5, NtSuspendProcess, 8 ) \ SYSCALL_ENTRY( 0x00d5, NtSignalAndWaitForSingleObject, 32 ) \
SYSCALL_ENTRY( 0x00d6, NtSuspendThread, 16 ) \ SYSCALL_ENTRY( 0x00d6, NtSuspendProcess, 8 ) \
SYSCALL_ENTRY( 0x00d7, NtSystemDebugControl, 48 ) \ SYSCALL_ENTRY( 0x00d7, NtSuspendThread, 16 ) \
SYSCALL_ENTRY( 0x00d8, NtTerminateJobObject, 16 ) \ SYSCALL_ENTRY( 0x00d8, NtSystemDebugControl, 48 ) \
SYSCALL_ENTRY( 0x00d9, NtTerminateProcess, 16 ) \ SYSCALL_ENTRY( 0x00d9, NtTerminateJobObject, 16 ) \
SYSCALL_ENTRY( 0x00da, NtTerminateThread, 16 ) \ SYSCALL_ENTRY( 0x00da, NtTerminateProcess, 16 ) \
SYSCALL_ENTRY( 0x00db, NtTestAlert, 0 ) \ SYSCALL_ENTRY( 0x00db, NtTerminateThread, 16 ) \
SYSCALL_ENTRY( 0x00dc, NtTraceControl, 48 ) \ SYSCALL_ENTRY( 0x00dc, NtTestAlert, 0 ) \
SYSCALL_ENTRY( 0x00dd, NtUnloadDriver, 8 ) \ SYSCALL_ENTRY( 0x00dd, NtTraceControl, 48 ) \
SYSCALL_ENTRY( 0x00de, NtUnloadKey, 8 ) \ SYSCALL_ENTRY( 0x00de, NtUnloadDriver, 8 ) \
SYSCALL_ENTRY( 0x00df, NtUnlockFile, 40 ) \ SYSCALL_ENTRY( 0x00df, NtUnloadKey, 8 ) \
SYSCALL_ENTRY( 0x00e0, NtUnlockVirtualMemory, 32 ) \ SYSCALL_ENTRY( 0x00e0, NtUnlockFile, 40 ) \
SYSCALL_ENTRY( 0x00e1, NtUnmapViewOfSection, 16 ) \ SYSCALL_ENTRY( 0x00e1, NtUnlockVirtualMemory, 32 ) \
SYSCALL_ENTRY( 0x00e2, NtUnmapViewOfSectionEx, 24 ) \ SYSCALL_ENTRY( 0x00e2, NtUnmapViewOfSection, 16 ) \
SYSCALL_ENTRY( 0x00e3, NtWaitForAlertByThreadId, 16 ) \ SYSCALL_ENTRY( 0x00e3, NtUnmapViewOfSectionEx, 24 ) \
SYSCALL_ENTRY( 0x00e4, NtWaitForDebugEvent, 32 ) \ SYSCALL_ENTRY( 0x00e4, NtWaitForAlertByThreadId, 16 ) \
SYSCALL_ENTRY( 0x00e5, NtWaitForKeyedEvent, 32 ) \ SYSCALL_ENTRY( 0x00e5, NtWaitForDebugEvent, 32 ) \
SYSCALL_ENTRY( 0x00e6, NtWaitForMultipleObjects, 40 ) \ SYSCALL_ENTRY( 0x00e6, NtWaitForKeyedEvent, 32 ) \
SYSCALL_ENTRY( 0x00e7, NtWaitForSingleObject, 24 ) \ SYSCALL_ENTRY( 0x00e7, NtWaitForMultipleObjects, 40 ) \
SYSCALL_ENTRY( 0x00e8, NtWriteFile, 72 ) \ SYSCALL_ENTRY( 0x00e8, NtWaitForSingleObject, 24 ) \
SYSCALL_ENTRY( 0x00e9, NtWriteFileGather, 72 ) \ SYSCALL_ENTRY( 0x00e9, NtWriteFile, 72 ) \
SYSCALL_ENTRY( 0x00ea, NtWriteVirtualMemory, 40 ) \ SYSCALL_ENTRY( 0x00ea, NtWriteFileGather, 72 ) \
SYSCALL_ENTRY( 0x00eb, NtYieldExecution, 0 ) \ SYSCALL_ENTRY( 0x00eb, NtWriteVirtualMemory, 40 ) \
SYSCALL_ENTRY( 0x00ec, wine_nt_to_unix_file_name, 32 ) \ SYSCALL_ENTRY( 0x00ec, NtYieldExecution, 0 ) \
SYSCALL_ENTRY( 0x00ed, wine_unix_to_nt_file_name, 24 ) SYSCALL_ENTRY( 0x00ed, wine_nt_to_unix_file_name, 32 ) \
SYSCALL_ENTRY( 0x00ee, wine_unix_to_nt_file_name, 24 )

View file

@ -443,6 +443,7 @@ DEFINE_SYSCALL(NtSetInformationToken, (HANDLE token, TOKEN_INFORMATION_CLASS cla
DEFINE_SYSCALL(NtSetInformationVirtualMemory, (HANDLE process, VIRTUAL_MEMORY_INFORMATION_CLASS info_class, ULONG_PTR count, PMEMORY_RANGE_ENTRY addresses, PVOID ptr, ULONG size)) DEFINE_SYSCALL(NtSetInformationVirtualMemory, (HANDLE process, VIRTUAL_MEMORY_INFORMATION_CLASS info_class, ULONG_PTR count, PMEMORY_RANGE_ENTRY addresses, PVOID ptr, ULONG size))
DEFINE_SYSCALL(NtSetIntervalProfile, (ULONG interval, KPROFILE_SOURCE source)) DEFINE_SYSCALL(NtSetIntervalProfile, (ULONG interval, KPROFILE_SOURCE source))
DEFINE_SYSCALL(NtSetIoCompletion, (HANDLE handle, ULONG_PTR key, ULONG_PTR value, NTSTATUS status, SIZE_T count)) DEFINE_SYSCALL(NtSetIoCompletion, (HANDLE handle, ULONG_PTR key, ULONG_PTR value, NTSTATUS status, SIZE_T count))
DEFINE_SYSCALL(NtSetIoCompletionEx, (HANDLE completion_handle, HANDLE completion_reserve_handle, ULONG_PTR key, ULONG_PTR value, NTSTATUS status, SIZE_T count))
DEFINE_SYSCALL(NtSetLdtEntries, (ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2)) DEFINE_SYSCALL(NtSetLdtEntries, (ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2))
DEFINE_SYSCALL(NtSetSecurityObject, (HANDLE handle, SECURITY_INFORMATION info, PSECURITY_DESCRIPTOR descr)) DEFINE_SYSCALL(NtSetSecurityObject, (HANDLE handle, SECURITY_INFORMATION info, PSECURITY_DESCRIPTOR descr))
DEFINE_SYSCALL(NtSetSystemInformation, (SYSTEM_INFORMATION_CLASS class, void *info, ULONG length)) DEFINE_SYSCALL(NtSetSystemInformation, (SYSTEM_INFORMATION_CLASS class, void *info, ULONG length))

View file

@ -51,6 +51,7 @@ static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* ); static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * ); static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
static NTSTATUS (WINAPI *pNtAllocateReserveObject)( HANDLE *, const OBJECT_ATTRIBUTES *, MEMORY_RESERVE_OBJECT_TYPE );
static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
ULONG, ULONG, ULONG, PLARGE_INTEGER ); ULONG, ULONG, ULONG, PLARGE_INTEGER );
static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG); static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
@ -76,6 +77,7 @@ static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION
static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER); static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
static NTSTATUS (WINAPI *pNtRemoveIoCompletionEx)(HANDLE,FILE_IO_COMPLETION_INFORMATION*,ULONG,ULONG*,LARGE_INTEGER*,BOOLEAN); static NTSTATUS (WINAPI *pNtRemoveIoCompletionEx)(HANDLE,FILE_IO_COMPLETION_INFORMATION*,ULONG,ULONG*,LARGE_INTEGER*,BOOLEAN);
static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T); static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
static NTSTATUS (WINAPI *pNtSetIoCompletionEx)(HANDLE, HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
static NTSTATUS (WINAPI *pNtQueryAttributesFile)(const OBJECT_ATTRIBUTES*,FILE_BASIC_INFORMATION*); static NTSTATUS (WINAPI *pNtQueryAttributesFile)(const OBJECT_ATTRIBUTES*,FILE_BASIC_INFORMATION*);
static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
@ -5932,6 +5934,62 @@ static void test_reparse_points(void)
CloseHandle( handle ); CloseHandle( handle );
} }
static void test_set_io_completion_ex(void)
{
HANDLE completion, completion_reserve, apc_reserve;
LARGE_INTEGER timeout = {{0}};
IO_STATUS_BLOCK iosb;
ULONG_PTR key, value;
NTSTATUS status;
SIZE_T size = 3;
if (!pNtSetIoCompletionEx || !pNtAllocateReserveObject)
{
win_skip("NtSetIoCompletionEx() or NtAllocateReserveObject() is unavailable.\n");
return;
}
if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
status = pNtCreateIoCompletion(&completion, IO_COMPLETION_ALL_ACCESS, NULL, 0);
ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status);
status = pNtAllocateReserveObject(&completion_reserve, NULL, MemoryReserveObjectTypeIoCompletion);
ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status);
status = pNtAllocateReserveObject(&apc_reserve, NULL, MemoryReserveObjectTypeUserApc);
ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status);
/* Parameter checks */
status = pNtSetIoCompletionEx(NULL, completion_reserve, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size);
ok(status == STATUS_INVALID_HANDLE, "Got unexpected status %#lx.\n", status);
status = pNtSetIoCompletionEx(INVALID_HANDLE_VALUE, completion_reserve, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size);
ok(status == STATUS_OBJECT_TYPE_MISMATCH, "Got unexpected status %#lx.\n", status);
status = pNtSetIoCompletionEx(completion, NULL, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size);
ok(status == STATUS_INVALID_HANDLE, "Got unexpected status %#lx.\n", status);
status = pNtSetIoCompletionEx(completion, INVALID_HANDLE_VALUE, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size);
ok(status == STATUS_OBJECT_TYPE_MISMATCH, "Got unexpected status %#lx.\n", status);
status = pNtSetIoCompletionEx(completion, apc_reserve, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size);
ok(status == STATUS_OBJECT_TYPE_MISMATCH, "Got unexpected status %#lx.\n", status);
/* Normal call */
status = pNtSetIoCompletionEx(completion, completion_reserve, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size);
ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status);
status = pNtRemoveIoCompletion(completion, &key, &value, &iosb, &timeout);
ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status);
ok(key == CKEY_FIRST, "Invalid completion key: %#Ix\n", key);
ok(iosb.Information == size, "Invalid iosb.Information: %Iu\n", iosb.Information);
ok(iosb.Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid iosb.Status: %#lx\n", iosb.Status);
ok(value == CVALUE_FIRST, "Invalid completion value: %#Ix\n", value);
CloseHandle(apc_reserve);
CloseHandle(completion_reserve);
CloseHandle(completion);
}
START_TEST(file) START_TEST(file)
{ {
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
@ -5949,6 +6007,7 @@ START_TEST(file)
pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString"); pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U"); pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx"); pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
pNtAllocateReserveObject= (void *)GetProcAddress(hntdll, "NtAllocateReserveObject");
pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile"); pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile"); pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile"); pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
@ -5965,6 +6024,7 @@ START_TEST(file)
pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion"); pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
pNtRemoveIoCompletionEx = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletionEx"); pNtRemoveIoCompletionEx = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletionEx");
pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion"); pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
pNtSetIoCompletionEx = (void *)GetProcAddress(hntdll, "NtSetIoCompletionEx");
pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile"); pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
pNtQueryAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryAttributesFile"); pNtQueryAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryAttributesFile");
pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile"); pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
@ -5983,6 +6043,7 @@ START_TEST(file)
append_file_test(); append_file_test();
nt_mailslot_test(); nt_mailslot_test();
test_set_io_completion(); test_set_io_completion();
test_set_io_completion_ex();
test_file_io_completion(); test_file_io_completion();
test_file_basic_information(); test_file_basic_information();
test_file_all_information(); test_file_all_information();

View file

@ -4052,10 +4052,9 @@ static void test_user_procs(void)
status = pRtlInitializeNtUserPfn( dummy, size_A, dummy + 1, size_W, dummy + 2, size_workers ); status = pRtlInitializeNtUserPfn( dummy, size_A, dummy + 1, size_W, dummy + 2, size_workers );
if (!status) break; if (!status) break;
ok( status == STATUS_INVALID_PARAMETER, "RtlInitializeNtUserPfn failed %lx\n", status ); ok( status == STATUS_INVALID_PARAMETER, "RtlInitializeNtUserPfn failed %lx\n", status );
status = pRtlResetNtUserPfn();
ok( status == STATUS_INVALID_PARAMETER, "RtlResetNtUserPfn failed %lx\n", status );
} }
trace( "got sizes %lx %lx %lx\n", size_A, size_W, size_workers ); trace( "got sizes %lx %lx %lx\n", size_A, size_W, size_workers );
if (!size_workers) return; /* something went wrong */
ok( !memcmp( ptrs, ptr_A, size_A ), "pointers changed by init\n" ); ok( !memcmp( ptrs, ptr_A, size_A ), "pointers changed by init\n" );
/* can't set twice without a reset */ /* can't set twice without a reset */

View file

@ -354,7 +354,7 @@ static int wait_select_reply( void *cookie )
/*********************************************************************** /***********************************************************************
* invoke_user_apc * invoke_user_apc
*/ */
static NTSTATUS invoke_user_apc( CONTEXT *context, const user_apc_t *apc, NTSTATUS status ) static NTSTATUS invoke_user_apc( CONTEXT *context, const struct user_apc *apc, NTSTATUS status )
{ {
return call_user_apc_dispatcher( context, apc->args[0], apc->args[1], apc->args[2], return call_user_apc_dispatcher( context, apc->args[0], apc->args[1], apc->args[2],
wine_server_get_ptr( apc->func ), status ); wine_server_get_ptr( apc->func ), status );
@ -364,7 +364,7 @@ static NTSTATUS invoke_user_apc( CONTEXT *context, const user_apc_t *apc, NTSTAT
/*********************************************************************** /***********************************************************************
* invoke_system_apc * invoke_system_apc
*/ */
static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOOL self ) static void invoke_system_apc( const union apc_call *call, union apc_result *result, BOOL self )
{ {
SIZE_T size, bits; SIZE_T size, bits;
void *addr; void *addr;
@ -688,19 +688,19 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO
* 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 select_op_t *select_op, data_size_t size, UINT flags,
timeout_t abs_timeout, context_t *context, user_apc_t *user_apc ) timeout_t abs_timeout, context_t *context, struct user_apc *user_apc )
{ {
unsigned int ret; unsigned int ret;
int cookie; int cookie;
obj_handle_t apc_handle = 0; obj_handle_t apc_handle = 0;
BOOL suspend_context = !!context; BOOL suspend_context = !!context;
apc_result_t result; union apc_result result;
sigset_t old_set; sigset_t old_set;
int signaled; int signaled;
data_size_t reply_size; data_size_t reply_size;
struct struct
{ {
apc_call_t call; union apc_call call;
context_t context[2]; context_t context[2];
} reply_data; } reply_data;
@ -768,7 +768,7 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f
{ {
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE; timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
unsigned int ret; unsigned int ret;
user_apc_t apc; struct user_apc apc;
if (abs_timeout < 0) if (abs_timeout < 0)
{ {
@ -794,7 +794,7 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f
*/ */
NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable ) NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable )
{ {
user_apc_t apc; struct user_apc apc;
NTSTATUS status; NTSTATUS status;
if (alertable) if (alertable)
@ -811,7 +811,7 @@ NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable )
*/ */
NTSTATUS WINAPI NtTestAlert(void) NTSTATUS WINAPI NtTestAlert(void)
{ {
user_apc_t apc; struct user_apc apc;
NTSTATUS status; NTSTATUS status;
status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, &apc ); status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, &apc );
@ -823,7 +823,7 @@ NTSTATUS WINAPI NtTestAlert(void)
/*********************************************************************** /***********************************************************************
* server_queue_process_apc * server_queue_process_apc
*/ */
unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result ) unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, union apc_result *result )
{ {
for (;;) for (;;)
{ {
@ -1759,8 +1759,8 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE
if ((options & DUPLICATE_CLOSE_SOURCE) && source_process != NtCurrentProcess()) if ((options & DUPLICATE_CLOSE_SOURCE) && source_process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );

View file

@ -1992,6 +1992,35 @@ NTSTATUS WINAPI NtSetIoCompletion( HANDLE handle, ULONG_PTR key, ULONG_PTR value
return ret; return ret;
} }
/***********************************************************************
* NtSetIoCompletionEx (NTDLL.@)
*
* completion_reserve_handle is a handle allocated by NtAllocateReserveObject() for pre-allocating
* memory for completion objects to deal with low-memory situations. It's not in use for now.
*/
NTSTATUS WINAPI NtSetIoCompletionEx( HANDLE completion_handle, HANDLE completion_reserve_handle,
ULONG_PTR key, ULONG_PTR value, NTSTATUS status, SIZE_T count )
{
unsigned int ret;
TRACE( "(%p, %p, %lx, %lx, %x, %lx)\n", completion_handle, completion_reserve_handle,
key, value, (int)status, count );
if (!completion_reserve_handle) return STATUS_INVALID_HANDLE;
SERVER_START_REQ( add_completion )
{
req->handle = wine_server_obj_handle( completion_handle );
req->ckey = key;
req->cvalue = value;
req->status = status;
req->information = count;
req->reserve_handle = wine_server_obj_handle( completion_reserve_handle );
ret = wine_server_call( req );
}
SERVER_END_REQ;
return ret;
}
/*********************************************************************** /***********************************************************************
* NtRemoveIoCompletion (NTDLL.@) * NtRemoveIoCompletion (NTDLL.@)

View file

@ -2131,6 +2131,26 @@ static struct smbios_prologue *create_smbios_data(void)
#endif #endif
static NTSTATUS enum_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULONG available_len,
ULONG *required_len )
{
ULONG len;
switch (sfti->ProviderSignature)
{
case RSMB:
sfti->TableBufferLength = len = sizeof(UINT);
*required_len = offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer[len] );
if (available_len < *required_len) return STATUS_BUFFER_TOO_SMALL;
*(UINT *)sfti->TableBuffer = 0;
return STATUS_SUCCESS;
default:
FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION provider %08x\n", (unsigned int)sfti->ProviderSignature);
return STATUS_NOT_IMPLEMENTED;
}
}
static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULONG available_len, static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULONG available_len,
ULONG *required_len ) ULONG *required_len )
{ {
@ -3459,14 +3479,17 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
ret = STATUS_INFO_LENGTH_MISMATCH; ret = STATUS_INFO_LENGTH_MISMATCH;
break; break;
} }
len = 0;
switch (sfti->Action) switch (sfti->Action)
{ {
case SystemFirmwareTable_Enumerate:
ret = enum_firmware_info(sfti, size, &len);
break;
case SystemFirmwareTable_Get: case SystemFirmwareTable_Get:
ret = get_firmware_info(sfti, size, &len); ret = get_firmware_info(sfti, size, &len);
break; break;
default: default:
len = 0;
ret = STATUS_NOT_IMPLEMENTED; ret = STATUS_NOT_IMPLEMENTED;
FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION action %d\n", sfti->Action); FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION action %d\n", sfti->Action);
} }

View file

@ -1323,8 +1323,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -1712,7 +1712,7 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1
ULONG_PTR arg2, ULONG_PTR arg3 ) ULONG_PTR arg2, ULONG_PTR arg3 )
{ {
unsigned int ret; unsigned int ret;
apc_call_t call; union apc_call call;
SERVER_START_REQ( queue_apc ) SERVER_START_REQ( queue_apc )
{ {

View file

@ -209,11 +209,11 @@ 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 select_op_t *select_op, data_size_t size, UINT flags,
timeout_t abs_timeout, context_t *context, user_apc_t *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 select_op_t *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 apc_call_t *call, extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call,
apc_result_t *result ); union apc_result *result );
extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
int *needs_close, enum server_fd_type *type, unsigned int *options ); int *needs_close, enum server_fd_type *type, unsigned int *options );
extern void wine_server_send_fd( int fd ); extern void wine_server_send_fd( int fd );
@ -436,10 +436,10 @@ static inline void mutex_unlock( pthread_mutex_t *mutex )
if (!process_exiting) pthread_mutex_unlock( mutex ); if (!process_exiting) pthread_mutex_unlock( mutex );
} }
static inline async_data_t server_async( HANDLE handle, struct async_fileio *user, HANDLE event, static inline struct async_data server_async( HANDLE handle, struct async_fileio *user, HANDLE event,
PIO_APC_ROUTINE apc, void *apc_context, client_ptr_t iosb ) PIO_APC_ROUTINE apc, void *apc_context, client_ptr_t iosb )
{ {
async_data_t async; struct async_data async;
async.handle = wine_server_obj_handle( handle ); async.handle = wine_server_obj_handle( handle );
async.user = wine_server_client_ptr( user ); async.user = wine_server_client_ptr( user );
async.iosb = iosb; async.iosb = iosb;

View file

@ -4671,8 +4671,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
unsigned int status; unsigned int status;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -4817,8 +4817,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -4864,8 +4864,8 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -4962,8 +4962,8 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -5146,8 +5146,8 @@ static unsigned int get_basic_memory_info( HANDLE process, LPCVOID addr,
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -5559,8 +5559,8 @@ NTSTATUS WINAPI NtLockVirtualMemory( HANDLE process, PVOID *addr, SIZE_T *size,
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -5596,8 +5596,8 @@ NTSTATUS WINAPI NtUnlockVirtualMemory( HANDLE process, PVOID *addr, SIZE_T *size
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -5672,8 +5672,8 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -5744,8 +5744,8 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -5788,8 +5788,8 @@ static NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr, ULONG flags )
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -5973,8 +5973,8 @@ NTSTATUS WINAPI NtFlushVirtualMemory( HANDLE process, LPCVOID *addr_ptr,
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );
@ -6359,8 +6359,8 @@ NTSTATUS WINAPI NtWow64AllocateVirtualMemory64( HANDLE process, ULONG64 *ret, UL
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
apc_call_t call; union apc_call call;
apc_result_t result; union apc_result result;
memset( &call, 0, sizeof(call) ); memset( &call, 0, sizeof(call) );

View file

@ -1525,6 +1525,7 @@
@ stdcall -private ZwSetInformationToken(long long ptr long) NtSetInformationToken @ stdcall -private ZwSetInformationToken(long long ptr long) NtSetInformationToken
@ stdcall -private ZwSetIntervalProfile(long long) NtSetIntervalProfile @ stdcall -private ZwSetIntervalProfile(long long) NtSetIntervalProfile
@ stdcall -private ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion @ stdcall -private ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion
@ stdcall -private ZwSetIoCompletionEx(ptr ptr long long long long) NtSetIoCompletionEx
@ stdcall -private ZwSetSecurityObject(long long ptr) NtSetSecurityObject @ stdcall -private ZwSetSecurityObject(long long ptr) NtSetSecurityObject
@ stdcall -private ZwSetSystemInformation(long ptr long) NtSetSystemInformation @ stdcall -private ZwSetSystemInformation(long ptr long) NtSetSystemInformation
@ stdcall -private ZwSetSystemTime(ptr ptr) NtSetSystemTime @ stdcall -private ZwSetSystemTime(ptr ptr) NtSetSystemTime

File diff suppressed because it is too large Load diff

View file

@ -525,11 +525,19 @@ void find_domain_name(const WCHAR *host, DWORD host_len,
return; return;
} }
} else if(last_tld-host < 3) } else if(last_tld-host < 3)
/* Anything less than 3 characters is considered part {
/* Anything less than 3 ASCII characters is considered part
* of the TLD name. * of the TLD name.
* Ex: ak.uk -> Has no domain name. * Ex: ak.uk -> Has no domain name.
*/ */
return; for(p = host; p < last_tld; p++) {
if(!is_ascii(*p))
break;
}
if(p == last_tld)
return;
}
/* Otherwise the domain name is the whole host name. */ /* Otherwise the domain name is the whole host name. */
*domain_start = 0; *domain_start = 0;
@ -1339,11 +1347,21 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD extras) {
/* If the host is empty, then it's an unknown host type. */ /* If the host is empty, then it's an unknown host type. */
if(data->host_len == 0 || is_res) if(data->host_len == 0 || is_res)
data->host_type = Uri_HOST_UNKNOWN; data->host_type = Uri_HOST_UNKNOWN;
else else {
unsigned int i;
data->host_type = Uri_HOST_DNS; data->host_type = Uri_HOST_DNS;
TRACE("(%p %p %lx): Parsed reg-name. host=%s len=%ld\n", ptr, data, extras, for(i = 0; i < data->host_len; i++) {
debugstr_wn(data->host, data->host_len), data->host_len); if(!is_ascii(data->host[i])) {
data->host_type = Uri_HOST_IDN;
break;
}
}
}
TRACE("(%p %p %lx): Parsed reg-name. host=%s len=%ld type=%d\n", ptr, data, extras,
debugstr_wn(data->host, data->host_len), data->host_len, data->host_type);
return TRUE; return TRUE;
} }
@ -2276,6 +2294,13 @@ static BOOL canonicalize_host(const parse_data *data, Uri *uri, DWORD flags, BOO
uri->host_type = Uri_HOST_IPV6; uri->host_type = Uri_HOST_IPV6;
break; break;
case Uri_HOST_IDN:
uri->host_type = Uri_HOST_IDN;
if(!canonicalize_reg_name(data, uri, flags, computeOnly))
return FALSE;
break;
case Uri_HOST_UNKNOWN: case Uri_HOST_UNKNOWN:
if(data->host_len > 0 || data->scheme_type != URL_SCHEME_FILE) { if(data->host_len > 0 || data->scheme_type != URL_SCHEME_FILE) {
uri->host_start = uri->canon_len; uri->host_start = uri->canon_len;
@ -3873,17 +3898,37 @@ static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BST
return E_INVALIDARG; return E_INVALIDARG;
} }
/* Don't have support for flags yet. */ if(dwFlags != 0 && dwFlags != Uri_DISPLAY_NO_FRAGMENT && dwFlags != Uri_PUNYCODE_IDN_HOST
if(dwFlags) { && dwFlags != Uri_DISPLAY_IDN_HOST)
FIXME("(%p)->(%d %p %lx)\n", This, uriProp, pbstrProperty, dwFlags); return E_INVALIDARG;
return E_NOTIMPL;
} if((dwFlags == Uri_DISPLAY_NO_FRAGMENT && uriProp != Uri_PROPERTY_DISPLAY_URI)
|| (dwFlags == Uri_PUNYCODE_IDN_HOST && uriProp != Uri_PROPERTY_ABSOLUTE_URI
&& uriProp != Uri_PROPERTY_DOMAIN && uriProp != Uri_PROPERTY_HOST)
|| (dwFlags == Uri_DISPLAY_IDN_HOST && uriProp != Uri_PROPERTY_ABSOLUTE_URI
&& uriProp != Uri_PROPERTY_DOMAIN && uriProp != Uri_PROPERTY_HOST))
return E_INVALIDARG;
switch(uriProp) { switch(uriProp) {
case Uri_PROPERTY_ABSOLUTE_URI: case Uri_PROPERTY_ABSOLUTE_URI:
if(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI) { if(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI) {
*pbstrProperty = SysAllocStringLen(NULL, 0); *pbstrProperty = SysAllocStringLen(NULL, 0);
hres = S_FALSE; hres = S_FALSE;
}
/* Uri_PUNYCODE_IDN_HOST doesn't remove user info containing only "@" and ":@" */
else if (dwFlags == Uri_PUNYCODE_IDN_HOST && This->host_type == Uri_HOST_IDN && This->host_start > -1) {
unsigned int punycode_host_len;
punycode_host_len = IdnToAscii(0, This->canon_uri+This->host_start, This->host_len, NULL, 0);
*pbstrProperty = SysAllocStringLen(NULL, This->canon_len-This->host_len+punycode_host_len);
hres = S_OK;
if(*pbstrProperty) {
memcpy(*pbstrProperty, This->canon_uri, This->host_start*sizeof(WCHAR));
IdnToAscii(0, This->canon_uri+This->host_start, This->host_len, *pbstrProperty+This->host_start, punycode_host_len);
memcpy(*pbstrProperty+This->host_start+punycode_host_len,
This->canon_uri+This->host_start+This->host_len,
(This->canon_len-This->host_start-This->host_len)*sizeof(WCHAR));
}
} else { } else {
if(This->scheme_type != URL_SCHEME_UNKNOWN && This->userinfo_start > -1) { if(This->scheme_type != URL_SCHEME_UNKNOWN && This->userinfo_start > -1) {
if(This->userinfo_len == 0) { if(This->userinfo_len == 0) {
@ -3944,18 +3989,32 @@ static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BST
* scheme types. * scheme types.
*/ */
if(This->scheme_type != URL_SCHEME_UNKNOWN && This->userinfo_start > -1) { if(This->scheme_type != URL_SCHEME_UNKNOWN && This->userinfo_start > -1) {
*pbstrProperty = SysAllocStringLen(NULL, This->canon_len-This->userinfo_len); unsigned int length = This->canon_len-This->userinfo_len;
/* Skip fragment if Uri_DISPLAY_NO_FRAGMENT is specified */
if(dwFlags == Uri_DISPLAY_NO_FRAGMENT && This->fragment_start > -1)
length -= This->fragment_len;
*pbstrProperty = SysAllocStringLen(NULL, length);
if(*pbstrProperty) { if(*pbstrProperty) {
/* Copy everything before the userinfo over. */ /* Copy everything before the userinfo over. */
memcpy(*pbstrProperty, This->canon_uri, This->userinfo_start*sizeof(WCHAR)); memcpy(*pbstrProperty, This->canon_uri, This->userinfo_start*sizeof(WCHAR));
/* Copy everything after the userinfo over. */ /* Copy everything after the userinfo over. */
length -= This->userinfo_start+1;
memcpy(*pbstrProperty+This->userinfo_start, memcpy(*pbstrProperty+This->userinfo_start,
This->canon_uri+This->userinfo_start+This->userinfo_len+1, This->canon_uri+This->userinfo_start+This->userinfo_len+1, length*sizeof(WCHAR));
(This->canon_len-(This->userinfo_start+This->userinfo_len+1))*sizeof(WCHAR));
} }
} else } else {
*pbstrProperty = SysAllocString(This->canon_uri); unsigned int length = This->canon_len;
/* Skip fragment if Uri_DISPLAY_NO_FRAGMENT is specified */
if(dwFlags == Uri_DISPLAY_NO_FRAGMENT && This->fragment_start > -1)
length -= This->fragment_len;
*pbstrProperty = SysAllocStringLen(This->canon_uri, length);
}
if(!(*pbstrProperty)) if(!(*pbstrProperty))
hres = E_OUTOFMEMORY; hres = E_OUTOFMEMORY;
@ -3965,8 +4024,20 @@ static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BST
break; break;
case Uri_PROPERTY_DOMAIN: case Uri_PROPERTY_DOMAIN:
if(This->domain_offset > -1) { if(This->domain_offset > -1) {
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start+This->domain_offset, if(dwFlags == Uri_PUNYCODE_IDN_HOST && This->host_type == Uri_HOST_IDN) {
This->host_len-This->domain_offset); unsigned int punycode_length;
punycode_length = IdnToAscii(0, This->canon_uri+This->host_start+This->domain_offset,
This->host_len-This->domain_offset, NULL, 0);
*pbstrProperty = SysAllocStringLen(NULL, punycode_length);
if (*pbstrProperty)
IdnToAscii(0, This->canon_uri+This->host_start+This->domain_offset,
This->host_len-This->domain_offset, *pbstrProperty, punycode_length);
} else {
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start+This->domain_offset,
This->host_len-This->domain_offset);
}
hres = S_OK; hres = S_OK;
} else { } else {
*pbstrProperty = SysAllocStringLen(NULL, 0); *pbstrProperty = SysAllocStringLen(NULL, 0);
@ -4009,6 +4080,14 @@ static HRESULT WINAPI Uri_GetPropertyBSTR(IUri *iface, Uri_PROPERTY uriProp, BST
/* The '[' and ']' aren't included for IPv6 addresses. */ /* The '[' and ']' aren't included for IPv6 addresses. */
if(This->host_type == Uri_HOST_IPV6) if(This->host_type == Uri_HOST_IPV6)
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start+1, This->host_len-2); *pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start+1, This->host_len-2);
else if(dwFlags == Uri_PUNYCODE_IDN_HOST && This->host_type == Uri_HOST_IDN) {
unsigned int punycode_length;
punycode_length = IdnToAscii(0, This->canon_uri+This->host_start, This->host_len, NULL, 0);
*pbstrProperty = SysAllocStringLen(NULL, punycode_length);
if (*pbstrProperty)
IdnToAscii(0, This->canon_uri+This->host_start, This->host_len, *pbstrProperty, punycode_length);
}
else else
*pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start, This->host_len); *pbstrProperty = SysAllocStringLen(This->canon_uri+This->host_start, This->host_len);
@ -4156,10 +4235,10 @@ static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, D
if(uriProp > Uri_PROPERTY_STRING_LAST) if(uriProp > Uri_PROPERTY_STRING_LAST)
return E_INVALIDARG; return E_INVALIDARG;
/* Don't have support for flags yet. */ if(dwFlags != 0 && dwFlags != Uri_DISPLAY_NO_FRAGMENT && dwFlags != Uri_PUNYCODE_IDN_HOST
if(dwFlags) { && dwFlags != Uri_DISPLAY_IDN_HOST) {
FIXME("(%p)->(%d %p %lx)\n", This, uriProp, pcchProperty, dwFlags); *pcchProperty = 0;
return E_NOTIMPL; return E_INVALIDARG;
} }
switch(uriProp) { switch(uriProp) {
@ -4167,6 +4246,12 @@ static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, D
if(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI) { if(This->display_modifiers & URI_DISPLAY_NO_ABSOLUTE_URI) {
*pcchProperty = 0; *pcchProperty = 0;
hres = S_FALSE; hres = S_FALSE;
}
/* Uri_PUNYCODE_IDN_HOST doesn't remove user info containing only "@" and ":@" */
else if(dwFlags == Uri_PUNYCODE_IDN_HOST && This->host_type == Uri_HOST_IDN && This->host_start > -1) {
unsigned int punycode_host_len = IdnToAscii(0, This->canon_uri+This->host_start, This->host_len, NULL, 0);
*pcchProperty = This->canon_len - This->host_len + punycode_host_len;
hres = S_OK;
} else { } else {
if(This->scheme_type != URL_SCHEME_UNKNOWN) { if(This->scheme_type != URL_SCHEME_UNKNOWN) {
if(This->userinfo_start > -1 && This->userinfo_len == 0) if(This->userinfo_start > -1 && This->userinfo_len == 0)
@ -4201,11 +4286,18 @@ static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, D
else else
*pcchProperty = This->canon_len; *pcchProperty = This->canon_len;
if(dwFlags == Uri_DISPLAY_NO_FRAGMENT && This->fragment_start > -1)
*pcchProperty -= This->fragment_len;
hres = S_OK; hres = S_OK;
break; break;
case Uri_PROPERTY_DOMAIN: case Uri_PROPERTY_DOMAIN:
if(This->domain_offset > -1) if(This->domain_offset > -1) {
*pcchProperty = This->host_len - This->domain_offset; if(dwFlags == Uri_PUNYCODE_IDN_HOST && This->host_type == Uri_HOST_IDN)
*pcchProperty = IdnToAscii(0, This->canon_uri+This->host_start+This->domain_offset, This->host_len-This->domain_offset, NULL, 0);
else
*pcchProperty = This->host_len - This->domain_offset;
}
else else
*pcchProperty = 0; *pcchProperty = 0;
@ -4231,6 +4323,8 @@ static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, D
/* '[' and ']' aren't included in the length. */ /* '[' and ']' aren't included in the length. */
if(This->host_type == Uri_HOST_IPV6) if(This->host_type == Uri_HOST_IPV6)
*pcchProperty -= 2; *pcchProperty -= 2;
else if(dwFlags == Uri_PUNYCODE_IDN_HOST && This->host_type == Uri_HOST_IDN && This->host_start > -1)
*pcchProperty = IdnToAscii(0, This->canon_uri+This->host_start, This->host_len, NULL, 0);
hres = (This->host_start > -1) ? S_OK : S_FALSE; hres = (This->host_start > -1) ? S_OK : S_FALSE;
break; break;
@ -4274,6 +4368,16 @@ static HRESULT WINAPI Uri_GetPropertyLength(IUri *iface, Uri_PROPERTY uriProp, D
hres = E_NOTIMPL; hres = E_NOTIMPL;
} }
if(hres == S_OK
&& ((dwFlags == Uri_DISPLAY_NO_FRAGMENT && uriProp != Uri_PROPERTY_DISPLAY_URI)
|| (dwFlags == Uri_PUNYCODE_IDN_HOST && uriProp != Uri_PROPERTY_ABSOLUTE_URI
&& uriProp != Uri_PROPERTY_DOMAIN && uriProp != Uri_PROPERTY_HOST)
|| (dwFlags == Uri_DISPLAY_IDN_HOST && uriProp != Uri_PROPERTY_ABSOLUTE_URI
&& uriProp != Uri_PROPERTY_DOMAIN && uriProp != Uri_PROPERTY_HOST))) {
*pcchProperty = 0;
hres = E_INVALIDARG;
}
return hres; return hres;
} }

View file

@ -41,6 +41,11 @@ struct ThreadWindows
HWND *handles; HWND *handles;
}; };
/* Index the order the buttons need to appear to an ID* constant */
static const int buttonOrder[10] = { IDYES, IDNO, IDOK, IDABORT, IDRETRY,
IDCANCEL, IDIGNORE, IDTRYAGAIN,
IDCONTINUE, IDHELP };
static BOOL CALLBACK MSGBOX_EnumProc(HWND hwnd, LPARAM lParam) static BOOL CALLBACK MSGBOX_EnumProc(HWND hwnd, LPARAM lParam)
{ {
struct ThreadWindows *threadWindows = (struct ThreadWindows *)lParam; struct ThreadWindows *threadWindows = (struct ThreadWindows *)lParam;
@ -74,11 +79,6 @@ static void MSGBOX_OnInit(HWND hwnd, LPMSGBOXPARAMSW lpmb)
WCHAR *buffer = NULL; WCHAR *buffer = NULL;
const WCHAR *ptr; const WCHAR *ptr;
/* Index the order the buttons need to appear to an ID* constant */
static const int buttonOrder[10] = { IDYES, IDNO, IDOK, IDABORT, IDRETRY,
IDCANCEL, IDIGNORE, IDTRYAGAIN,
IDCONTINUE, IDHELP };
nclm.cbSize = sizeof(nclm); nclm.cbSize = sizeof(nclm);
SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0); SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
@ -320,6 +320,95 @@ static void MSGBOX_OnInit(HWND hwnd, LPMSGBOXPARAMSW lpmb)
HeapFree( GetProcessHeap(), 0, buffer ); HeapFree( GetProcessHeap(), 0, buffer );
} }
static void MSGBOX_CopyToClipbaord( HWND hwnd )
{
int i;
static const WCHAR line[] = L"---------------------------\r\n";
static const WCHAR carriage[] = L"\r\n";
static const WCHAR spaces[] = L" ";
int lenTitle = GetWindowTextLengthW(hwnd) + 1;
int lenMsg = GetWindowTextLengthW(GetDlgItem(hwnd, MSGBOX_IDTEXT)) + 1;
HGLOBAL hMem;
WCHAR *data;
/*
---------------------------
Dialog Title
---------------------------
Dialog Message
---------------------------
Button(s) Text. OK
---------------------------
*/
int len = ((wcslen(carriage) * 3) + (wcslen(line) * 4) + lenTitle + lenMsg) * sizeof(WCHAR);
WCHAR *text = malloc(len);
if (!text)
return;
lstrcpyW(text, line);
if (!GetWindowTextW(hwnd, text + lstrlenW(text), lenTitle))
{
free(text);
return;
}
lstrcatW(text, carriage);
lstrcatW(text, line);
GetWindowTextW(GetDlgItem(hwnd, MSGBOX_IDTEXT), text + lstrlenW(text), lenMsg);
lstrcatW(text, carriage);
lstrcatW(text, line);
for (i = 0; i < ARRAY_SIZE(buttonOrder); i++)
{
HWND hItem = GetDlgItem(hwnd, buttonOrder[i]);
if (GetWindowLongW(hItem, GWL_STYLE) & WS_VISIBLE)
{
WCHAR buffer[1024] = {0};
int j = 0, k = lstrlenW(text);
GetWindowTextW(hItem, buffer, 1024);
while(buffer[j] != 0)
{
if(buffer[j] != '&')
text[k++] = buffer[j];
j++;
}
text[k] = 0;
lstrcatW(text, spaces);
}
}
lstrcatW(text, carriage);
lstrcatW(text, line);
hMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, len);
data = GlobalLock(hMem);
lstrcpyW(data, text);
GlobalUnlock(hMem);
OpenClipboard(hwnd);
NtUserEmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hMem);
NtUserCloseClipboard();
free(text);
}
HHOOK msghook_handle;
LRESULT CALLBACK msg_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
{
MSG *msg = (MSG *)lParam;
if (nCode == MSGF_DIALOGBOX && msg->message == WM_KEYUP)
{
if ( (msg->wParam == 'C' || msg->wParam == 'c') && (NtUserGetKeyState(VK_CONTROL) & 0x8000))
{
MSGBOX_CopyToClipbaord(GetParent(msg->hwnd));
}
}
return NtUserCallNextHookEx(msghook_handle, nCode, wParam, lParam);
}
/************************************************************************** /**************************************************************************
* MSGBOX_DlgProc * MSGBOX_DlgProc
@ -336,9 +425,18 @@ static INT_PTR CALLBACK MSGBOX_DlgProc( HWND hwnd, UINT message,
SetWindowContextHelpId(hwnd, mbp->dwContextHelpId); SetWindowContextHelpId(hwnd, mbp->dwContextHelpId);
MSGBOX_OnInit(hwnd, mbp); MSGBOX_OnInit(hwnd, mbp);
SetPropA(hwnd, "WINE_MSGBOX_HELPCALLBACK", mbp->lpfnMsgBoxCallback); SetPropA(hwnd, "WINE_MSGBOX_HELPCALLBACK", mbp->lpfnMsgBoxCallback);
msghook_handle = SetWindowsHookExA(WH_MSGFILTER, msg_hook_proc, NULL, GetCurrentThreadId());
break; break;
} }
case WM_COPY:
MSGBOX_CopyToClipbaord(hwnd);
break;
case WM_DESTROY:
NtUserUnhookWindowsHookEx(msghook_handle);
break;
case WM_COMMAND: case WM_COMMAND:
switch (LOWORD(wParam)) switch (LOWORD(wParam))
{ {

View file

@ -6187,6 +6187,13 @@ static const struct message WmMove_mouse[] = {
{ 0 } { 0 }
}; };
static const struct message WmMove_mouse2[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
{ WM_GETTEXT, sent|optional },
{ WM_GETMINMAXINFO, sent|defwinproc },
{ 0 }
};
static void test_setwindowpos(void) static void test_setwindowpos(void)
{ {
HWND hwnd; HWND hwnd;
@ -6253,6 +6260,11 @@ static void test_setwindowpos(void)
ok(res == TRUE, "SetWindowPos expected TRUE, got %Id.\n", res); ok(res == TRUE, "SetWindowPos expected TRUE, got %Id.\n", res);
flush_events(); flush_events();
ok_sequence(WmMove_mouse, "MouseMove", FALSE); ok_sequence(WmMove_mouse, "MouseMove", FALSE);
/* if the window and client rects were not changed WM_MOUSEMOVE is not sent. */
res = SetWindowPos( hwnd, 0, 205, 205, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE );
ok(res == TRUE, "SetWindowPos expected TRUE, got %Id.\n", res);
flush_events();
ok_sequence(WmMove_mouse2, "MouseMove2", FALSE);
ignore_mouse_messages = TRUE; ignore_mouse_messages = TRUE;
DestroyWindow(hwnd); DestroyWindow(hwnd);

View file

@ -558,7 +558,7 @@
@ stdcall GetDlgItemTextA(long long ptr long) @ stdcall GetDlgItemTextA(long long ptr long)
@ stdcall GetDlgItemTextW(long long ptr long) @ stdcall GetDlgItemTextW(long long ptr long)
@ stdcall GetDoubleClickTime() NtUserGetDoubleClickTime @ stdcall GetDoubleClickTime() NtUserGetDoubleClickTime
# @ stub GetDpiAwarenessContextForProcess @ stdcall GetDpiAwarenessContextForProcess(ptr)
@ stdcall GetDpiForMonitorInternal(long long ptr ptr) NtUserGetDpiForMonitor @ stdcall GetDpiForMonitorInternal(long long ptr ptr) NtUserGetDpiForMonitor
@ stdcall GetDpiForSystem() @ stdcall GetDpiForSystem()
@ stdcall GetDpiForWindow(long) @ stdcall GetDpiForWindow(long)

View file

@ -615,6 +615,13 @@ DPI_AWARENESS_CONTEXT WINAPI GetWindowDpiAwarenessContext( HWND hwnd )
return LongToHandle( NtUserGetWindowDpiAwarenessContext( hwnd ) ); return LongToHandle( NtUserGetWindowDpiAwarenessContext( hwnd ) );
} }
/***********************************************************************
* GetDpiAwarenessContextForProcess (USER32.@)
*/
DPI_AWARENESS_CONTEXT WINAPI GetDpiAwarenessContextForProcess(HANDLE process)
{
return LongToHandle( NtUserGetProcessDpiAwarenessContext( process ) );
}
/*********************************************************************** /***********************************************************************
* GetWindowDpiHostingBehavior (USER32.@) * GetWindowDpiHostingBehavior (USER32.@)

View file

@ -7366,7 +7366,7 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl
} }
else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG)) else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
{ {
shader_addline(buffer, "%s = clamp(outputs[%u].%c, 0.0, 1.0);\n", shader_addline(buffer, "%s = outputs[%u].%c;\n",
legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord", legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord",
output->register_idx, reg_mask[1]); output->register_idx, reg_mask[1]);
} }
@ -11402,6 +11402,8 @@ static void shader_glsl_get_caps(const struct wined3d_adapter *adapter, struct s
TRACE("Shader model %u.\n", shader_model); TRACE("Shader model %u.\n", shader_model);
memset(caps, 0, sizeof(*caps));
caps->vs_version = min(wined3d_settings.max_sm_vs, shader_model); caps->vs_version = min(wined3d_settings.max_sm_vs, shader_model);
caps->hs_version = min(wined3d_settings.max_sm_hs, shader_model); caps->hs_version = min(wined3d_settings.max_sm_hs, shader_model);
caps->ds_version = min(wined3d_settings.max_sm_ds, shader_model); caps->ds_version = min(wined3d_settings.max_sm_ds, shader_model);
@ -11743,6 +11745,8 @@ static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_adapter *adapter,
{ {
const struct wined3d_gl_info *gl_info = &wined3d_adapter_gl_const(adapter)->gl_info; const struct wined3d_gl_info *gl_info = &wined3d_adapter_gl_const(adapter)->gl_info;
memset(caps, 0, sizeof(*caps));
caps->emulated_flatshading = !needs_legacy_glsl_syntax(gl_info); caps->emulated_flatshading = !needs_legacy_glsl_syntax(gl_info);
caps->max_active_lights = WINED3D_MAX_ACTIVE_LIGHTS; caps->max_active_lights = WINED3D_MAX_ACTIVE_LIGHTS;
caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS; caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS;

View file

@ -1065,6 +1065,8 @@ static void shader_spirv_init_context_state(struct wined3d_context *context)
static void shader_spirv_get_caps(const struct wined3d_adapter *adapter, struct shader_caps *caps) static void shader_spirv_get_caps(const struct wined3d_adapter *adapter, struct shader_caps *caps)
{ {
memset(caps, 0, sizeof(*caps));
caps->vs_version = min(wined3d_settings.max_sm_vs, 5); caps->vs_version = min(wined3d_settings.max_sm_vs, 5);
caps->hs_version = min(wined3d_settings.max_sm_hs, 5); caps->hs_version = min(wined3d_settings.max_sm_hs, 5);
caps->ds_version = min(wined3d_settings.max_sm_ds, 5); caps->ds_version = min(wined3d_settings.max_sm_ds, 5);
@ -1196,6 +1198,7 @@ static void spirv_fragment_pipe_vk_fp_disable(const struct wined3d_context *cont
static void spirv_fragment_pipe_vk_fp_get_caps(const struct wined3d_adapter *adapter, struct fragment_caps *caps) static void spirv_fragment_pipe_vk_fp_get_caps(const struct wined3d_adapter *adapter, struct fragment_caps *caps)
{ {
memset(caps, 0, sizeof(*caps)); memset(caps, 0, sizeof(*caps));
caps->max_blend_stages = WINED3D_MAX_FFP_TEXTURES;
} }
static unsigned int spirv_fragment_pipe_vk_fp_get_emul_mask(const struct wined3d_adapter *adapter) static unsigned int spirv_fragment_pipe_vk_fp_get_emul_mask(const struct wined3d_adapter *adapter)

View file

@ -3697,14 +3697,9 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device,
if (changed->texture_matrices) if (changed->texture_matrices)
{ {
struct wined3d_ffp_vs_constants constants; struct wined3d_ffp_vs_constants constants;
struct wined3d_stream_info si;
/* FIXME: This is a bit fragile. Ideally we should be calculating
* stream info from the stateblock state. */
wined3d_stream_info_from_declaration(&si, context->state, &device->adapter->d3d_info);
for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i)
get_texture_matrix(&si, state, i, &constants.texture_matrices[i]); get_texture_matrix(state, i, &constants.texture_matrices[i]);
wined3d_device_context_push_constants(context, wined3d_device_context_push_constants(context,
WINED3D_PUSH_CONSTANTS_VS_FFP, WINED3D_SHADER_CONST_FFP_TEXMATRIX, WINED3D_PUSH_CONSTANTS_VS_FFP, WINED3D_SHADER_CONST_FFP_TEXMATRIX,
offsetof(struct wined3d_ffp_vs_constants, texture_matrices), offsetof(struct wined3d_ffp_vs_constants, texture_matrices),

View file

@ -5608,38 +5608,43 @@ static void compute_texture_matrix(const struct wined3d_matrix *matrix, uint32_t
mat = *matrix; mat = *matrix;
/* Under Direct3D the R/Z coord can be used for translation, under /* When less than 4 components are provided for an attribute, the remaining
* OpenGL we use the Q coord instead. */ * components are filled with (..., 0, 0, 1). This is the case when using
* shaders in Direct3D as well as in GL and Vulkan.
*
* However, when using the Direct3D fixed function vertex pipeline, the
* texture coordinates transformed by texture matrices effectively have
* 1 in the first "default" component and 0 in the others (e.g. for
* R32_FLOAT the coordinates are (..., 1, 0, 0).
*
* We could approximate this by modifying the shader, but modifying uniforms
* is generally cheaper, so instead we change the matrix, copying the 2nd or
* 3rd column to the 4th. That is, whichever coefficients expect a value of
* 1 will instead be used as the coefficients for the 4th column, which
* actually has a value of 1. The coefficients for other columns don't need
* to be modified, since the corresponding texcoord components are zero. */
if (!(flags & WINED3D_TTFF_PROJECTED) && !calculated_coords) if (!(flags & WINED3D_TTFF_PROJECTED) && !calculated_coords)
{ {
switch (format_id) switch (format_id)
{ {
/* Direct3D passes the default 1.0 in the 2nd coord, while GL
* passes it in the 4th. Swap 2nd and 4th coord. No need to
* store the value of mat._41 in mat._21 because the input
* value to the transformation will be 0, so the matrix value
* is irrelevant. */
case WINED3DFMT_R32_FLOAT: case WINED3DFMT_R32_FLOAT:
mat._41 = mat._21; mat._41 = mat._21;
mat._42 = mat._22; mat._42 = mat._22;
mat._43 = mat._23; mat._43 = mat._23;
mat._44 = mat._24; mat._44 = mat._24;
break; break;
/* See above, just 3rd and 4th coord. */
case WINED3DFMT_R32G32_FLOAT: case WINED3DFMT_R32G32_FLOAT:
mat._41 = mat._31; mat._41 = mat._31;
mat._42 = mat._32; mat._42 = mat._32;
mat._43 = mat._33; mat._43 = mat._33;
mat._44 = mat._34; mat._44 = mat._34;
break; break;
case WINED3DFMT_R32G32B32_FLOAT: /* Opengl defaults match dx defaults */
case WINED3DFMT_R32G32B32A32_FLOAT: /* No defaults apply, all app defined */
/* This is to prevent swapping the matrix lines and put the default 4th coord = 1.0 case WINED3DFMT_R32G32B32_FLOAT:
* into a bad place. The division elimination below will apply to make sure the case WINED3DFMT_R32G32B32A32_FLOAT:
* 1.0 doesn't do anything bad. The caller will set this value if the stride is 0 case WINED3DFMT_UNKNOWN:
*/
case WINED3DFMT_UNKNOWN: /* No texture coords, 0/0/0/1 defaults are passed */
break; break;
default: default:
FIXME("Unexpected fixed function texture coord input\n"); FIXME("Unexpected fixed function texture coord input\n");
@ -5649,23 +5654,29 @@ static void compute_texture_matrix(const struct wined3d_matrix *matrix, uint32_t
*out_matrix = mat; *out_matrix = mat;
} }
void get_texture_matrix(const struct wined3d_stream_info *si, static enum wined3d_format_id get_texcoord_format(const struct wined3d_vertex_declaration *decl, unsigned int index)
const struct wined3d_stateblock_state *state, const unsigned int tex, struct wined3d_matrix *mat) {
for (unsigned int i = 0; i < decl->element_count; ++i)
{
if (decl->elements[i].usage == WINED3D_DECL_USAGE_TEXCOORD
&& decl->elements[i].usage_idx == index)
return decl->elements[i].format->id;
}
return WINED3DFMT_UNKNOWN;
}
void get_texture_matrix(const struct wined3d_stateblock_state *state,
const unsigned int tex, struct wined3d_matrix *mat)
{ {
BOOL generated = (state->texture_states[tex][WINED3D_TSS_TEXCOORD_INDEX] & 0xffff0000) BOOL generated = (state->texture_states[tex][WINED3D_TSS_TEXCOORD_INDEX] & 0xffff0000)
!= WINED3DTSS_TCI_PASSTHRU; != WINED3DTSS_TCI_PASSTHRU;
unsigned int coord_idx = min(state->texture_states[tex][WINED3D_TSS_TEXCOORD_INDEX] & 0x0000ffff, unsigned int coord_idx = min(state->texture_states[tex][WINED3D_TSS_TEXCOORD_INDEX] & 0x0000ffff,
WINED3D_MAX_FFP_TEXTURES - 1); WINED3D_MAX_FFP_TEXTURES - 1);
enum wined3d_format_id attribute_format;
if (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx)))
attribute_format = si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->id;
else
attribute_format = WINED3DFMT_UNKNOWN;
compute_texture_matrix(&state->transforms[WINED3D_TS_TEXTURE0 + tex], compute_texture_matrix(&state->transforms[WINED3D_TS_TEXTURE0 + tex],
state->texture_states[tex][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS], state->texture_states[tex][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS],
generated, attribute_format, mat); generated, get_texcoord_format(state->vertex_declaration, coord_idx), mat);
} }
void get_pointsize_minmax(const struct wined3d_context *context, const struct wined3d_state *state, void get_pointsize_minmax(const struct wined3d_context *context, const struct wined3d_state *state,

View file

@ -4376,8 +4376,8 @@ static inline BOOL shader_sampler_is_shadow(const struct wined3d_shader *shader,
void get_identity_matrix(struct wined3d_matrix *mat); void get_identity_matrix(struct wined3d_matrix *mat);
void get_modelview_matrix(const struct wined3d_stateblock_state *state, unsigned int index, struct wined3d_matrix *mat); void get_modelview_matrix(const struct wined3d_stateblock_state *state, unsigned int index, struct wined3d_matrix *mat);
void get_texture_matrix(const struct wined3d_stream_info *si, void get_texture_matrix(const struct wined3d_stateblock_state *state,
const struct wined3d_stateblock_state *state, const unsigned int tex, struct wined3d_matrix *mat); const unsigned int tex, struct wined3d_matrix *mat);
void get_pointsize_minmax(const struct wined3d_context *context, const struct wined3d_state *state, void get_pointsize_minmax(const struct wined3d_context *context, const struct wined3d_state *state,
float *out_min, float *out_max); float *out_min, float *out_max);
void get_fog_start_end(const struct wined3d_context *context, const struct wined3d_state *state, void get_fog_start_end(const struct wined3d_context *context, const struct wined3d_state *state,

View file

@ -696,57 +696,72 @@ void macdrv_compute_keyboard_layout(struct macdrv_thread_data *thread_data)
static const struct { static const struct {
WCHAR wchar; WCHAR wchar;
DWORD vkey; DWORD vkey;
/* Mac virtual key code that must match wchar under the current layout.
* A value of -1 means match-any.
* TODO: replace -1 with the actual mac virtual key codes for all mappings
* and their respective layouts to avoid false matches, when possible. */
int mac_keyc;
} symbol_vkeys[] = { } symbol_vkeys[] = {
{ '-', VK_OEM_MINUS }, { '-', VK_OEM_PLUS, kVK_ANSI_Equal },
{ '+', VK_OEM_PLUS }, { '-', VK_OEM_MINUS, -1 },
{ '_', VK_OEM_MINUS }, { '+', VK_OEM_PLUS, -1 },
{ ',', VK_OEM_COMMA }, { '_', VK_OEM_MINUS, -1 },
{ '.', VK_OEM_PERIOD }, { ',', VK_OEM_COMMA, -1 },
{ '=', VK_OEM_PLUS }, { '.', VK_OEM_PERIOD, -1 },
{ '>', VK_OEM_PERIOD }, { '=', VK_OEM_8, kVK_ANSI_Slash },
{ '<', VK_OEM_COMMA }, { '=', VK_OEM_PLUS, -1 },
{ '|', VK_OEM_5 }, { '!', VK_OEM_8, kVK_ANSI_Slash },
{ '\\', VK_OEM_5 }, { 0x00F9, VK_OEM_3, kVK_ANSI_Quote }, /* 0x00F9 is French U accent grave */
{ '`', VK_OEM_3 }, { '$', VK_OEM_1, kVK_ANSI_RightBracket },
{ '[', VK_OEM_4 }, { ':', VK_OEM_2, kVK_ANSI_Period },
{ '~', VK_OEM_3 }, { '*', VK_OEM_5, kVK_ANSI_Backslash },
{ 0x00DF, VK_OEM_4 }, /* 0x00DF is ESZETT */ { '`', VK_OEM_5, kVK_ANSI_Backslash },
{ 0x00FC, VK_OEM_1 }, /* 0x00FC is German U Umlaut */ { ';', VK_OEM_PERIOD, kVK_ANSI_Comma },
{ 0x00F6, VK_OEM_3 }, /* 0x00F6 is German O Umlaut */ { ')', VK_OEM_4, kVK_ANSI_Minus },
{ 0x00E4, VK_OEM_7 }, /* 0x00B4 is German A Umlaut */ { '>', VK_OEM_PERIOD, -1 },
{ '?', VK_OEM_2 }, { '<', VK_OEM_COMMA, -1 },
{ ']', VK_OEM_6 }, { '|', VK_OEM_5, -1 },
{ '/', VK_OEM_2 }, { '\\', VK_OEM_5, -1 },
{ ':', VK_OEM_1 }, { '`', VK_OEM_3, -1 },
{ '}', VK_OEM_6 }, { '[', VK_OEM_4, -1 },
{ '{', VK_OEM_4 }, { '~', VK_OEM_3, -1 },
{ ';', VK_OEM_1 }, { 0x00DF, VK_OEM_4, kVK_ANSI_Minus }, /* 0x00DF is ESZETT */
{ '\'', VK_OEM_7 }, { 0x00FC, VK_OEM_1, kVK_ANSI_LeftBracket }, /* 0x00FC is German U Umlaut */
{ ':', VK_OEM_PERIOD }, { 0x00F6, VK_OEM_3, kVK_ANSI_Semicolon }, /* 0x00F6 is German O Umlaut */
{ ';', VK_OEM_COMMA }, { 0x00E4, VK_OEM_7, kVK_ANSI_Quote }, /* 0x00B4 is German A Umlaut */
{ '"', VK_OEM_7 }, { '?', VK_OEM_2, -1 },
{ 0x00B4, VK_OEM_4 }, /* 0x00B4 is ACUTE ACCENT */ { ']', VK_OEM_6, -1 },
{ '\'', VK_OEM_2 }, { '/', VK_OEM_2, -1 },
{ 0x00A7, VK_OEM_5 }, /* 0x00A7 is SECTION SIGN */ { ':', VK_OEM_1, -1 },
{ '*', VK_OEM_PLUS }, { '}', VK_OEM_6, -1 },
{ 0x00B4, VK_OEM_7 }, { '{', VK_OEM_4, },
{ '`', VK_OEM_4 }, { ';', VK_OEM_1, -1 },
{ '[', VK_OEM_6 }, { '\'', VK_OEM_7, -1 },
{ '/', VK_OEM_5 }, { ':', VK_OEM_PERIOD, -1 },
{ '^', VK_OEM_6 }, { ';', VK_OEM_COMMA, -1 },
{ '*', VK_OEM_2 }, { '"', VK_OEM_7, -1 },
{ '{', VK_OEM_6 }, { 0x00B4, VK_OEM_4, kVK_ANSI_Equal }, /* 0x00B4 is ACUTE ACCENT */
{ 0x00B4, VK_OEM_6 }, { '\'', VK_OEM_2, -1 },
{ '~', VK_OEM_1 }, { 0x00A7, VK_OEM_5, -1 }, /* 0x00A7 is SECTION SIGN */
{ '?', VK_OEM_PLUS }, { '*', VK_OEM_PLUS, -1 },
{ '?', VK_OEM_4 }, { 0x00B4, VK_OEM_7, -1 },
{ 0x00B4, VK_OEM_3 }, { '`', VK_OEM_4, -1 },
{ '?', VK_OEM_COMMA }, { '[', VK_OEM_6, -1 },
{ '~', VK_OEM_PLUS }, { '/', VK_OEM_5, -1 },
{ ']', VK_OEM_4 }, { '^', VK_OEM_6, -1 },
{ '\'', VK_OEM_3 }, { '*', VK_OEM_2, -1 },
{ 0x00A7, VK_OEM_7 }, { '{', VK_OEM_6, -1 },
{ '<', VK_OEM_102 }, { 0x00B4, VK_OEM_6, -1 },
{ '~', VK_OEM_1, -1 },
{ '?', VK_OEM_PLUS, -1 },
{ '?', VK_OEM_4, -1 },
{ 0x00B4, VK_OEM_3, -1 },
{ '?', VK_OEM_COMMA, -1 },
{ '~', VK_OEM_PLUS, -1 },
{ ']', VK_OEM_4, -1 },
{ '\'', VK_OEM_3, -1 },
{ 0x00A7, VK_OEM_7, -1 },
{ '<', VK_OEM_102, -1 },
}; };
int i; int i;
@ -915,6 +930,8 @@ void macdrv_compute_keyboard_layout(struct macdrv_thread_data *thread_data)
if (!thread_data->keyc2scan[keyc]) continue; /* not a known Mac key code */ if (!thread_data->keyc2scan[keyc]) continue; /* not a known Mac key code */
if (thread_data->keyc2vkey[keyc] || !map[keyc][combo][0]) if (thread_data->keyc2vkey[keyc] || !map[keyc][combo][0])
continue; continue;
if (symbol_vkeys[i].mac_keyc != -1 && symbol_vkeys[i].mac_keyc != keyc)
continue;
if (char_matches_string(symbol_vkeys[i].wchar, map[keyc][combo], collatorRef)) if (char_matches_string(symbol_vkeys[i].wchar, map[keyc][combo], collatorRef))
{ {

View file

@ -171,13 +171,49 @@ static inline void free_event_data( XEvent *event )
#endif #endif
} }
static BOOL host_window_filter_event( XEvent *event ) static void host_window_send_configure_events( struct host_window *win, Display *display, unsigned long serial, XEvent *previous )
{
XConfigureEvent configure = {.type = ConfigureNotify, .serial = serial, .display = display};
unsigned int i;
for (i = 0; i < win->children_count; i++)
{
RECT rect = win->children[i].rect;
struct x11drv_win_data *data;
HWND hwnd;
configure.event = win->children[i].window;
configure.window = configure.event;
configure.x = rect.left;
configure.y = rect.top;
configure.width = rect.right - rect.left;
configure.height = rect.bottom - rect.top;
configure.send_event = 0;
/* Only send a fake event if we're not expecting one from a state/config request.
* We may know what was requested, but not what the WM will decide to reply, and our
* fake event might trigger some undesired changes before the real ConfigureNotify.
*/
if (!XFindContext( configure.display, configure.window, winContext, (char **)&hwnd ) &&
(data = get_win_data( hwnd )))
{
/* embedded windows won't receive synthetic ConfigureNotify and are positioned by the WM */
BOOL has_serial = !data->embedded && (data->wm_state_serial || data->configure_serial);
release_win_data( data );
if (has_serial) continue;
}
if (previous->type == ConfigureNotify && previous->xconfigure.window == configure.window) continue;
TRACE( "generating ConfigureNotify for window %p/%lx, rect %s\n", hwnd, configure.window, wine_dbgstr_rect(&rect) );
XPutBackEvent( configure.display, (XEvent *)&configure );
}
}
static BOOL host_window_filter_event( XEvent *event, XEvent *previous )
{ {
struct host_window *win; struct host_window *win;
RECT old_rect;
if (!(win = get_host_window( event->xany.window, FALSE ))) return FALSE; if (!(win = get_host_window( event->xany.window, FALSE ))) return FALSE;
old_rect = win->rect;
switch (event->type) switch (event->type)
{ {
@ -190,6 +226,7 @@ static BOOL host_window_filter_event( XEvent *event )
XReparentEvent *reparent = (XReparentEvent *)event; XReparentEvent *reparent = (XReparentEvent *)event;
TRACE( "host window %p/%lx ReparentNotify, parent %lx\n", win, win->window, reparent->parent ); TRACE( "host window %p/%lx ReparentNotify, parent %lx\n", win, win->window, reparent->parent );
host_window_set_parent( win, reparent->parent ); host_window_set_parent( win, reparent->parent );
host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous );
break; break;
} }
case GravityNotify: case GravityNotify:
@ -198,6 +235,7 @@ static BOOL host_window_filter_event( XEvent *event )
OffsetRect( &win->rect, gravity->x - win->rect.left, gravity->y - win->rect.top ); OffsetRect( &win->rect, gravity->x - win->rect.left, gravity->y - win->rect.top );
if (win->parent) win->rect = host_window_configure_child( win->parent, win->window, win->rect, FALSE ); if (win->parent) win->rect = host_window_configure_child( win->parent, win->window, win->rect, FALSE );
TRACE( "host window %p/%lx GravityNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); TRACE( "host window %p/%lx GravityNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) );
host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous );
break; break;
} }
case ConfigureNotify: case ConfigureNotify:
@ -206,44 +244,11 @@ static BOOL host_window_filter_event( XEvent *event )
SetRect( &win->rect, configure->x, configure->y, configure->x + configure->width, configure->y + configure->height ); SetRect( &win->rect, configure->x, configure->y, configure->x + configure->width, configure->y + configure->height );
if (win->parent) win->rect = host_window_configure_child( win->parent, win->window, win->rect, configure->send_event ); if (win->parent) win->rect = host_window_configure_child( win->parent, win->window, win->rect, configure->send_event );
TRACE( "host window %p/%lx ConfigureNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); TRACE( "host window %p/%lx ConfigureNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) );
host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous );
break; break;
} }
} }
if (old_rect.left != win->rect.left || old_rect.top != win->rect.top)
{
XConfigureEvent configure = {.type = ConfigureNotify, .serial = event->xany.serial, .display = event->xany.display};
unsigned int i;
for (i = 0; i < win->children_count; i++)
{
RECT rect = win->children[i].rect;
struct x11drv_win_data *data;
BOOL has_serial;
HWND hwnd;
/* Only send a fake event if we're not expecting one from a state/config request.
* We may know what was requested, but not what the WM will decide to reply, and our
* fake event might trigger some undesired changes before the real ConfigureNotify.
*/
if (XFindContext( event->xany.display, event->xany.window, winContext, (char **)&hwnd )) continue;
if (!(data = get_win_data( hwnd ))) continue;
has_serial = data->wm_state_serial || data->configure_serial;
release_win_data( data );
if (has_serial) continue;
configure.event = win->children[i].window;
configure.window = configure.event;
configure.x = rect.left;
configure.y = rect.top;
configure.width = rect.right - rect.left;
configure.height = rect.bottom - rect.top;
configure.send_event = 0;
XPutBackEvent( configure.display, (XEvent *)&configure );
}
}
return TRUE; return TRUE;
} }
@ -521,7 +526,7 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X
continue; /* filtered, ignore it */ continue; /* filtered, ignore it */
} }
if (host_window_filter_event( &event )) continue; if (host_window_filter_event( &event, &prev_event )) continue;
get_event_data( &event ); get_event_data( &event );
if (prev_event.type) action = merge_events( &prev_event, &event ); if (prev_event.type) action = merge_events( &prev_event, &event );
@ -756,12 +761,20 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
} }
else if (protocol == x11drv_atom(WM_TAKE_FOCUS)) else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
{ {
HWND last_focus = x11drv_thread_data()->last_focus; HWND last_focus = x11drv_thread_data()->last_focus, foreground = NtUserGetForegroundWindow();
TRACE( "got take focus msg for %p, enabled=%d, visible=%d (style %08x), focus=%p, active=%p, fg=%p, last=%p\n", if (window_has_pending_wm_state( hwnd, -1 ))
hwnd, NtUserIsWindowEnabled(hwnd), NtUserIsWindowVisible(hwnd), {
(int)NtUserGetWindowLongW(hwnd, GWL_STYLE), WARN( "Ignoring window %p/%lx WM_TAKE_FOCUS serial %lu, event_time %ld, foreground %p during WM_STATE change\n",
get_focus(), get_active_window(), NtUserGetForegroundWindow(), last_focus ); hwnd, event->window, event->serial, event_time, foreground );
return;
}
TRACE( "window %p/%lx WM_TAKE_FOCUS serial %lu, event_time %ld, foreground %p\n", hwnd, event->window,
event->serial, event_time, foreground );
TRACE( " enabled %u, visible %u, style %#x, focus %p, active %p, last %p\n",
NtUserIsWindowEnabled( hwnd ), NtUserIsWindowVisible( hwnd ), (int)NtUserGetWindowLongW( hwnd, GWL_STYLE ),
get_focus(), get_active_window(), last_focus );
if (can_activate_window(hwnd)) if (can_activate_window(hwnd))
{ {
@ -778,7 +791,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
} }
else if (hwnd == NtUserGetDesktopWindow()) else if (hwnd == NtUserGetDesktopWindow())
{ {
hwnd = NtUserGetForegroundWindow(); hwnd = foreground;
if (!hwnd) hwnd = last_focus; if (!hwnd) hwnd = last_focus;
if (!hwnd) hwnd = NtUserGetDesktopWindow(); if (!hwnd) hwnd = NtUserGetDesktopWindow();
set_focus( event->display, hwnd, event_time ); set_focus( event->display, hwnd, event_time );
@ -840,14 +853,23 @@ BOOL is_current_process_focused(void)
*/ */
static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev ) static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev )
{ {
HWND foreground = NtUserGetForegroundWindow();
XFocusChangeEvent *event = &xev->xfocus; XFocusChangeEvent *event = &xev->xfocus;
BOOL was_grabbed; BOOL was_grabbed;
if (event->detail == NotifyPointer) return FALSE;
if (!hwnd) return FALSE; if (!hwnd) return FALSE;
TRACE( "win %p xwin %lx detail=%s mode=%s\n", hwnd, event->window, focus_details[event->detail], focus_modes[event->mode] ); if (window_has_pending_wm_state( hwnd, -1 ))
{
WARN( "Ignoring window %p/%lx FocusIn serial %lu, detail %s, mode %s, foreground %p during WM_STATE change\n",
hwnd, event->window, event->serial, focus_details[event->detail], focus_modes[event->mode], foreground );
return FALSE;
}
TRACE( "window %p/%lx FocusIn serial %lu, detail %s, mode %s, foreground %p\n", hwnd, event->window,
event->serial, focus_details[event->detail], focus_modes[event->mode], foreground );
if (event->detail == NotifyPointer) return FALSE;
/* when focusing in the virtual desktop window, re-apply the cursor clipping rect */ /* when focusing in the virtual desktop window, re-apply the cursor clipping rect */
if (is_virtual_desktop() && hwnd == NtUserGetDesktopWindow()) reapply_cursor_clipping(); if (is_virtual_desktop() && hwnd == NtUserGetDesktopWindow()) reapply_cursor_clipping();
if (hwnd == NtUserGetDesktopWindow()) return FALSE; if (hwnd == NtUserGetDesktopWindow()) return FALSE;
@ -916,10 +938,9 @@ static void focus_out( Display *display , HWND hwnd )
*/ */
static BOOL X11DRV_FocusOut( HWND hwnd, XEvent *xev ) static BOOL X11DRV_FocusOut( HWND hwnd, XEvent *xev )
{ {
HWND foreground = NtUserGetForegroundWindow();
XFocusChangeEvent *event = &xev->xfocus; XFocusChangeEvent *event = &xev->xfocus;
TRACE( "win %p xwin %lx detail=%s mode=%s\n", hwnd, event->window, focus_details[event->detail], focus_modes[event->mode] );
if (event->detail == NotifyPointer) if (event->detail == NotifyPointer)
{ {
if (!hwnd && event->window == x11drv_thread_data()->clip_window) if (!hwnd && event->window == x11drv_thread_data()->clip_window)
@ -933,6 +954,16 @@ static BOOL X11DRV_FocusOut( HWND hwnd, XEvent *xev )
} }
if (!hwnd) return FALSE; if (!hwnd) return FALSE;
if (window_has_pending_wm_state( hwnd, NormalState )) /* ignore FocusOut only if the window is being shown */
{
WARN( "Ignoring window %p/%lx FocusOut serial %lu, detail %s, mode %s, foreground %p during WM_STATE change\n",
hwnd, event->window, event->serial, focus_details[event->detail], focus_modes[event->mode], foreground );
return FALSE;
}
TRACE( "window %p/%lx FocusOut serial %lu, detail %s, mode %s, foreground %p\n", hwnd, event->window,
event->serial, focus_details[event->detail], focus_modes[event->mode], foreground );
/* in virtual desktop mode or when keyboard is grabbed, release any cursor grab but keep the clipping rect */ /* in virtual desktop mode or when keyboard is grabbed, release any cursor grab but keep the clipping rect */
keyboard_grabbed = event->mode == NotifyGrab || event->mode == NotifyWhileGrabbed; keyboard_grabbed = event->mode == NotifyGrab || event->mode == NotifyWhileGrabbed;
if (is_virtual_desktop() || keyboard_grabbed) ungrab_clipping_window(); if (is_virtual_desktop() || keyboard_grabbed) ungrab_clipping_window();
@ -1073,9 +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 flags; UINT config_cmd;
int cx, cy, x, y;
DWORD style;
if (!hwnd) return FALSE; if (!hwnd) return FALSE;
if (!(data = get_win_data( hwnd ))) return FALSE; if (!(data = get_win_data( hwnd ))) return FALSE;
@ -1094,80 +1123,17 @@ 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 );
if (!data->mapped || data->iconic) goto done; config_cmd = window_update_client_config( data );
if (!data->whole_window || !data->managed) goto done; rect = window_rect_from_visible( &data->rects, data->current_state.rect );
if (data->configure_serial && (long)(data->configure_serial - event->serial) > 0)
{
TRACE( "win %p/%lx event %d,%d,%dx%d ignoring old serial %lu/%lu\n",
hwnd, data->whole_window, event->x, event->y, event->width, event->height,
event->serial, data->configure_serial );
goto done;
}
rect = window_rect_from_visible( &data->rects, rect );
TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n",
hwnd, data->whole_window, (int)rect.left, (int)rect.top,
(int)(rect.right-rect.left), (int)(rect.bottom-rect.top),
event->x, event->y, event->width, event->height );
/* Compare what has changed */
x = rect.left;
y = rect.top;
cx = rect.right - rect.left;
cy = rect.bottom - rect.top;
flags = SWP_NOACTIVATE | SWP_NOZORDER;
if (!data->whole_window) flags |= SWP_NOCOPYBITS; /* we can't copy bits of foreign windows */
if (data->rects.window.left == x && data->rects.window.top == y) flags |= SWP_NOMOVE;
else
TRACE( "%p moving from (%d,%d) to (%d,%d)\n",
hwnd, (int)data->rects.window.left, (int)data->rects.window.top, x, y );
if ((data->rects.window.right - data->rects.window.left == cx &&
data->rects.window.bottom - data->rects.window.top == cy) ||
IsRectEmpty( &data->rects.window ))
flags |= SWP_NOSIZE;
else
TRACE( "%p resizing from (%dx%d) to (%dx%d)\n",
hwnd, (int)(data->rects.window.right - data->rects.window.left),
(int)(data->rects.window.bottom - data->rects.window.top), cx, cy );
style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE );
if ((style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen)
{
data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window );
if ((data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)))
{
if (!(style & WS_MAXIMIZE))
{
TRACE( "win %p/%lx is maximized\n", data->hwnd, data->whole_window );
release_win_data( data );
send_message( data->hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0 );
return TRUE;
}
}
else if (style & WS_MAXIMIZE)
{
TRACE( "window %p/%lx is no longer maximized\n", data->hwnd, data->whole_window );
release_win_data( data );
send_message( data->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0 );
return TRUE;
}
}
if ((flags & (SWP_NOSIZE | SWP_NOMOVE)) != (SWP_NOSIZE | SWP_NOMOVE))
{
release_win_data( data );
NtUserSetRawWindowPos( hwnd, rect, flags, FALSE );
return TRUE;
}
done:
release_win_data( data ); release_win_data( data );
return FALSE;
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 );
}
return !!config_cmd;
} }
@ -1230,7 +1196,7 @@ static int get_window_xembed_info( Display *display, Window window )
static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL update_window ) static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL update_window )
{ {
struct x11drv_win_data *data; struct x11drv_win_data *data;
UINT style, value = 0; UINT value = 0, state_cmd = 0;
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 );
@ -1251,61 +1217,20 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat
TRACE( "%p/%lx: new WM_STATE %d from %d\n", TRACE( "%p/%lx: new WM_STATE %d from %d\n",
data->hwnd, data->whole_window, new_state, old_state ); data->hwnd, data->whole_window, new_state, old_state );
data->wm_state = new_state; data->wm_state = new_state;
/* ignore the initial state transition out of withdrawn state */
/* metacity does Withdrawn->NormalState->IconicState when mapping an iconic window */
if (!old_state) goto done;
} }
} }
break; break;
} }
if (!update_window || !data->managed || !data->mapped) goto done; if (update_window) state_cmd = window_update_client_state( data );
style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE );
if (data->iconic && data->wm_state == NormalState) /* restore window */
{
data->iconic = FALSE;
data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window );
if ((style & WS_CAPTION) == WS_CAPTION && (data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)))
{
if ((style & WS_MAXIMIZEBOX) && !(style & WS_DISABLED))
{
TRACE( "restoring to max %p/%lx\n", data->hwnd, data->whole_window );
release_win_data( data );
send_message( hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0 );
return;
}
TRACE( "not restoring to max win %p/%lx style %08x\n", data->hwnd, data->whole_window, style );
}
else
{
if (style & (WS_MINIMIZE | WS_MAXIMIZE))
{
TRACE( "restoring win %p/%lx\n", data->hwnd, data->whole_window );
release_win_data( data );
if ((style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE))
NtUserSetActiveWindow( hwnd );
send_message( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0 );
return;
}
TRACE( "not restoring win %p/%lx style %08x\n", data->hwnd, data->whole_window, style );
}
}
else if (!data->iconic && data->wm_state == IconicState)
{
data->iconic = TRUE;
if ((style & WS_MINIMIZEBOX) && !(style & WS_DISABLED))
{
TRACE( "minimizing win %p/%lx\n", data->hwnd, data->whole_window );
release_win_data( data );
send_message( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
return;
}
TRACE( "not minimizing win %p/%lx style %08x\n", data->hwnd, data->whole_window, style );
}
done:
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 );
}
} }
static void handle_xembed_info_notify( HWND hwnd, XPropertyEvent *event ) static void handle_xembed_info_notify( HWND hwnd, XPropertyEvent *event )

View file

@ -46,7 +46,7 @@
#include "winuser.h" #include "winuser.h"
#include "winreg.h" #include "winreg.h"
#include "winnls.h" #include "winnls.h"
#include "ime.h" #include "kbd.h"
#include "wine/server.h" #include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"

View file

@ -1160,7 +1160,7 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data )
long monitors[4]; long monitors[4];
XEvent xev; XEvent xev;
if (!(data->net_wm_state & (1 << NET_WM_STATE_FULLSCREEN)) || is_virtual_desktop() if (!(data->pending_state.net_wm_state & (1 << NET_WM_STATE_FULLSCREEN)) || is_virtual_desktop()
|| NtUserGetWindowLongW( data->hwnd, GWL_STYLE ) & WS_MINIMIZE) || NtUserGetWindowLongW( data->hwnd, GWL_STYLE ) & WS_MINIMIZE)
return; return;
@ -1211,10 +1211,12 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data )
static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_state ) static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_state )
{ {
UINT i, count; UINT i, count, old_state = data->pending_state.net_wm_state;
if (!data->whole_window) return; /* no window, nothing to update */ if (!data->whole_window) return; /* no window, 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->mapped) /* set the _NET_WM_STATE atom directly */ if (!data->mapped) /* set the _NET_WM_STATE atom directly */
{ {
Atom atoms[NB_NET_WM_STATES + 1]; Atom atoms[NB_NET_WM_STATES + 1];
@ -1250,6 +1252,8 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat
for (i = 0; i < NB_NET_WM_STATES; i++) for (i = 0; i < NB_NET_WM_STATES; i++)
{ {
if (!((old_state ^ new_state) & (1 << i))) continue;
xev.xclient.data.l[0] = (new_state & (1 << i)) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; xev.xclient.data.l[0] = (new_state & (1 << i)) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
xev.xclient.data.l[1] = X11DRV_Atoms[net_wm_state_atoms[i] - FIRST_XATOM]; xev.xclient.data.l[1] = X11DRV_Atoms[net_wm_state_atoms[i] - FIRST_XATOM];
xev.xclient.data.l[2] = ((net_wm_state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) ? xev.xclient.data.l[2] = ((net_wm_state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) ?
@ -1268,9 +1272,11 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat
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 )
{ {
UINT style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ), mask = 0; UINT style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ), mask = 0;
const RECT *old_rect = &data->pending_state.rect;
XWindowChanges changes; XWindowChanges changes;
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 */
/* resizing a managed maximized window is not allowed */ /* resizing a managed maximized window is not allowed */
if (!(style & WS_MAXIMIZE) || !data->managed) if (!(style & WS_MAXIMIZE) || !data->managed)
@ -1322,7 +1328,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->net_wm_state & ((1 << NET_WM_STATE_FULLSCREEN)|(1 << NET_WM_STATE_MAXIMIZED)); new_state |= data->pending_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)
@ -1346,7 +1352,6 @@ static void update_net_wm_states( struct x11drv_win_data *data )
} }
window_set_net_wm_state( data, new_state ); window_set_net_wm_state( data, new_state );
data->net_wm_state = new_state;
update_net_wm_fullscreen_monitors( data ); update_net_wm_fullscreen_monitors( data );
} }
@ -1412,8 +1417,8 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state )
data->pending_state.wm_state = new_state; data->pending_state.wm_state = new_state;
data->wm_state_serial = NextRequest( data->display ); data->wm_state_serial = NextRequest( data->display );
TRACE( "window %p/%lx, requesting WM_STATE %#x -> %#x serial %lu\n", data->hwnd, data->whole_window, TRACE( "window %p/%lx, requesting WM_STATE %#x -> %#x serial %lu, foreground %p\n", data->hwnd, data->whole_window,
old_state, new_state, data->wm_state_serial ); old_state, new_state, data->wm_state_serial, NtUserGetForegroundWindow() );
switch (MAKELONG(old_state, new_state)) switch (MAKELONG(old_state, new_state))
{ {
@ -1484,11 +1489,87 @@ static void unmap_window( HWND hwnd )
TRACE( "win %p/%lx\n", data->hwnd, data->whole_window ); TRACE( "win %p/%lx\n", data->hwnd, data->whole_window );
window_set_wm_state( data, WithdrawnState ); window_set_wm_state( data, WithdrawnState );
data->mapped = FALSE; data->mapped = FALSE;
data->net_wm_state = 0;
} }
release_win_data( data ); release_win_data( data );
} }
UINT window_update_client_state( struct x11drv_win_data *data )
{
UINT old_style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE );
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->iconic && data->current_state.wm_state == NormalState) /* restore window */
{
data->iconic = FALSE;
if ((old_style & WS_CAPTION) == WS_CAPTION && (data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)))
{
if ((old_style & WS_MAXIMIZEBOX) && !(old_style & WS_DISABLED))
{
TRACE( "restoring to max %p/%lx\n", data->hwnd, data->whole_window );
return SC_MAXIMIZE;
}
}
else if (old_style & (WS_MINIMIZE | WS_MAXIMIZE))
{
BOOL activate = (old_style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE);
TRACE( "restoring win %p/%lx\n", data->hwnd, data->whole_window );
return MAKELONG(SC_RESTORE, activate);
}
}
else if (!data->iconic && data->current_state.wm_state == IconicState)
{
data->iconic = TRUE;
if ((old_style & WS_MINIMIZEBOX) && !(old_style & WS_DISABLED))
{
TRACE( "minimizing win %p/%lx\n", data->hwnd, data->whole_window );
return SC_MINIMIZE;
}
}
return 0;
}
UINT window_update_client_config( struct x11drv_win_data *data )
{
UINT old_style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ), flags;
RECT rect, old_rect = data->rects.window, new_rect;
if (!data->managed) return 0; /* unmanaged windows are managed by the Win32 side */
if (!data->mapped) return 0; /* ignore config changes on invisible windows */
if (data->iconic) return 0; /* ignore config changes on minimized windows */
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 ((data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) && !(old_style & WS_MAXIMIZE))
{
TRACE( "window %p/%lx is maximized\n", data->hwnd, data->whole_window );
return SC_MAXIMIZE;
}
if (!(data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) && (old_style & WS_MAXIMIZE))
{
TRACE( "window %p/%lx is no longer maximized\n", data->hwnd, data->whole_window );
return SC_RESTORE;
}
}
flags = SWP_NOACTIVATE | SWP_NOZORDER;
rect = new_rect = window_rect_from_visible( &data->rects, data->current_state.rect );
if (new_rect.left == old_rect.left && new_rect.top == old_rect.top) flags |= SWP_NOMOVE;
else OffsetRect( &rect, old_rect.left - new_rect.left, old_rect.top - new_rect.top );
if (rect.right == old_rect.right && rect.bottom == old_rect.bottom) flags |= SWP_NOSIZE;
else if (IsRectEmpty( &rect )) flags |= SWP_NOSIZE;
if ((flags & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE)) return 0;
TRACE( "window %p/%lx config changed %s -> %s, flags %#x\n", data->hwnd, data->whole_window,
wine_dbgstr_rect(&old_rect), wine_dbgstr_rect(&new_rect), flags );
return MAKELONG(SC_MOVE, flags);
}
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 *pending = &data->pending_state.wm_state, *current = &data->current_state.wm_state;
@ -1587,6 +1668,19 @@ void window_configure_notify( struct x11drv_win_data *data, unsigned long serial
*expect_serial = 0; *expect_serial = 0;
} }
BOOL window_has_pending_wm_state( HWND hwnd, UINT state )
{
struct x11drv_win_data *data;
BOOL pending;
if (!(data = get_win_data( hwnd ))) return FALSE;
if (state != -1 && data->pending_state.wm_state != state) pending = FALSE;
else pending = !!data->wm_state_serial;
release_win_data( data );
return pending;
}
/*********************************************************************** /***********************************************************************
* make_window_embedded * make_window_embedded
*/ */
@ -1594,7 +1688,6 @@ void make_window_embedded( struct x11drv_win_data *data )
{ {
/* the window cannot be mapped before being embedded */ /* the window cannot be mapped before being embedded */
window_set_wm_state( data, WithdrawnState ); window_set_wm_state( data, WithdrawnState );
data->net_wm_state = 0;
data->embedded = TRUE; data->embedded = TRUE;
data->managed = TRUE; data->managed = TRUE;
sync_window_style( data ); sync_window_style( data );
@ -2006,7 +2099,6 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des
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->wm_state = WithdrawnState;
data->net_wm_state = 0;
data->mapped = FALSE; data->mapped = FALSE;
memset( &data->pending_state, 0, sizeof(data->pending_state) ); memset( &data->pending_state, 0, sizeof(data->pending_state) );
@ -2314,7 +2406,12 @@ void set_window_parent( struct x11drv_win_data *data, Window parent )
if (!data->whole_window) return; /* only keep track of parent if we have a toplevel */ if (!data->whole_window) return; /* only keep track of parent if we have a toplevel */
TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, parent ); TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, parent );
host_window_reparent( &data->parent, parent, data->whole_window ); host_window_reparent( &data->parent, parent, data->whole_window );
if (data->parent) host_window_configure_child( data->parent, data->whole_window, data->rects.visible, TRUE ); if (data->parent)
{
RECT rect = data->rects.visible;
OffsetRect( &rect, -rect.left, -rect.top );
host_window_configure_child( data->parent, data->whole_window, rect, TRUE );
}
data->parent_invalid = 0; data->parent_invalid = 0;
} }
@ -2468,6 +2565,7 @@ BOOL X11DRV_SystrayDockInsert( HWND hwnd, UINT cx, UINT cy, void *icon )
window = data->whole_window; window = data->whole_window;
release_win_data( data ); release_win_data( data );
NtUserSetWindowPos( hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOZORDER );
NtUserShowWindow( hwnd, SW_SHOWNA ); NtUserShowWindow( hwnd, SW_SHOWNA );
TRACE_(systray)( "icon window %p/%lx\n", hwnd, window ); TRACE_(systray)( "icon window %p/%lx\n", hwnd, window );

View file

@ -236,7 +236,7 @@ typedef struct tagWTI_DEVICES_INFO
#define CSR_TYPE_OTHER 0x000 #define CSR_TYPE_OTHER 0x000
typedef struct tagWTPACKET { typedef struct tagWTPACKET {
HCTX pkContext; UINT pkContext;
UINT pkStatus; UINT pkStatus;
LONG pkTime; LONG pkTime;
WTPKT pkChanged; WTPKT pkChanged;

View file

@ -634,7 +634,6 @@ struct x11drv_win_data
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 */ int wm_state; /* current value of the WM_STATE property */
DWORD net_wm_state; /* bit mask of active x11drv_net_wm_state values */
Window embedder; /* window id of embedder */ Window embedder; /* window id of embedder */
Pixmap icon_pixmap; Pixmap icon_pixmap;
Pixmap icon_mask; Pixmap icon_mask;
@ -659,9 +658,13 @@ extern void set_gl_drawable_parent( HWND hwnd, HWND parent );
extern void destroy_gl_drawable( HWND hwnd ); extern void destroy_gl_drawable( HWND hwnd );
extern void destroy_vk_surface( HWND hwnd ); extern void destroy_vk_surface( HWND hwnd );
extern BOOL window_has_pending_wm_state( HWND hwnd, UINT state );
extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ); extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value );
extern void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ); extern void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value );
extern void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *rect ); extern void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *rect );
extern UINT window_update_client_state( 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 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 );

View file

@ -811,12 +811,6 @@ C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
#ifdef _WIN64 #ifdef _WIN64
static NTSTATUS x11drv_wow64_tablet_get_packet( void *arg )
{
FIXME( "%p\n", arg );
return 0;
}
static NTSTATUS x11drv_wow64_tablet_info( void *arg ) static NTSTATUS x11drv_wow64_tablet_info( void *arg )
{ {
struct struct
@ -837,7 +831,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
{ {
x11drv_init, x11drv_init,
x11drv_tablet_attach_queue, x11drv_tablet_attach_queue,
x11drv_wow64_tablet_get_packet, x11drv_tablet_get_packet,
x11drv_wow64_tablet_info, x11drv_wow64_tablet_info,
x11drv_tablet_load_info, x11drv_tablet_load_info,
}; };

View file

@ -3886,26 +3886,23 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel,
} }
else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer) else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer)
{ {
time_t tmpTime; SYSTEMTIME st;
struct tm tmpTM;
SYSTEMTIME *STHook;
tmpTime = ConvertTimeString(lphttpHdr->lpszValue); if (!InternetTimeToSystemTimeW(lphttpHdr->lpszValue, &st, 0))
{
tmpTM = *gmtime(&tmpTime); LeaveCriticalSection( &request->headers_section );
STHook = (SYSTEMTIME *)lpBuffer; return ERROR_HTTP_INVALID_HEADER;
STHook->wDay = tmpTM.tm_mday; }
STHook->wHour = tmpTM.tm_hour; if (*lpdwBufferLength < sizeof(st))
STHook->wMilliseconds = 0; {
STHook->wMinute = tmpTM.tm_min; *lpdwBufferLength = sizeof(st);
STHook->wDayOfWeek = tmpTM.tm_wday; LeaveCriticalSection( &request->headers_section );
STHook->wMonth = tmpTM.tm_mon + 1; return ERROR_INSUFFICIENT_BUFFER;
STHook->wSecond = tmpTM.tm_sec; }
STHook->wYear = 1900+tmpTM.tm_year; TRACE(" returning time: %04u/%02u/%02u - %u - %02u:%02u:%02u.%02u\n",
st.wYear, st.wMonth, st.wDay, st.wDayOfWeek, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
TRACE(" returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n", memcpy(lpBuffer, &st, sizeof(st));
STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek, *lpdwBufferLength = sizeof(st);
STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds);
} }
else if (lphttpHdr->lpszValue) else if (lphttpHdr->lpszValue)
{ {
@ -4521,7 +4518,7 @@ static BOOL HTTP_ParseDateAsAsctime(LPCWSTR value, FILETIME *ft)
/* asctime() doesn't report a timezone, but some web servers do, so accept /* asctime() doesn't report a timezone, but some web servers do, so accept
* with or without GMT. * with or without GMT.
*/ */
if (*ptr && wcscmp(ptr, L"GMT")) if (*ptr && (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC")))
{ {
ERR("unexpected timezone %s\n", debugstr_w(ptr)); ERR("unexpected timezone %s\n", debugstr_w(ptr));
return FALSE; return FALSE;
@ -4598,7 +4595,7 @@ static BOOL HTTP_ParseRfc1123Date(LPCWSTR value, FILETIME *ft)
while (iswspace(*ptr)) while (iswspace(*ptr))
ptr++; ptr++;
if (wcscmp(ptr, L"GMT")) if (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC"))
{ {
ERR("unexpected time zone %s\n", debugstr_w(ptr)); ERR("unexpected time zone %s\n", debugstr_w(ptr));
return FALSE; return FALSE;
@ -4715,7 +4712,7 @@ static BOOL HTTP_ParseRfc850Date(LPCWSTR value, FILETIME *ft)
while (iswspace(*ptr)) while (iswspace(*ptr))
ptr++; ptr++;
if (wcscmp(ptr, L"GMT")) if (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC"))
{ {
ERR("unexpected time zone %s\n", debugstr_w(ptr)); ERR("unexpected time zone %s\n", debugstr_w(ptr));
return FALSE; return FALSE;

View file

@ -2412,6 +2412,7 @@ static const char okmsg2[] =
"Content-Length: 0\r\n" "Content-Length: 0\r\n"
"Set-Cookie: one\r\n" "Set-Cookie: one\r\n"
"Set-Cookie: two\r\n" "Set-Cookie: two\r\n"
"Last-Modified: Mon, 01 Dec 2008 13:44:34 UTC\r\n"
"\r\n"; "\r\n";
static DWORD64 content_length; static DWORD64 content_length;
@ -4566,9 +4567,11 @@ static void test_head_request(int port)
static void test_HttpQueryInfo(int port) static void test_HttpQueryInfo(int port)
{ {
static const SYSTEMTIME expect = {2008, 12, 1, 1, 13, 44, 34};
test_request_t req; test_request_t req;
DWORD size, index, error; DWORD size, index, error;
char buffer[1024]; char buffer[1024];
SYSTEMTIME st;
BOOL ret; BOOL ret;
open_simple_request(&req, "localhost", port, NULL, "/testD"); open_simple_request(&req, "localhost", port, NULL, "/testD");
@ -4589,9 +4592,27 @@ static void test_HttpQueryInfo(int port)
ok(index == 1, "expected 1 got %lu\n", index); ok(index == 1, "expected 1 got %lu\n", index);
index = 0; index = 0;
size = sizeof(buffer); size = 0;
ret = HttpQueryInfoA(req.request, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, buffer, &size, &index); ret = HttpQueryInfoA(req.request, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, &st, &size, &index);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
ok(size == sizeof(st), "got %lu\n", size);
index = 0;
size = sizeof(st) + 1;
memset(&st, 0, sizeof(st));
ret = HttpQueryInfoA(req.request, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, &st, &size, &index);
ok(ret, "HttpQueryInfo failed %lu\n", GetLastError()); ok(ret, "HttpQueryInfo failed %lu\n", GetLastError());
ok(!memcmp(&st, &expect, sizeof(st)), "wrong time\n");
ok(size == sizeof(st), "got %lu\n", size);
ok(index == 1, "expected 1 got %lu\n", index);
index = 0;
size = sizeof(st);
memset(&st, 0, sizeof(st));
ret = HttpQueryInfoA(req.request, HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME, &st, &size, &index);
ok(ret, "HttpQueryInfo failed %lu\n", GetLastError());
ok(!memcmp(&st, &expect, sizeof(st)), "wrong time\n");
ok(size == sizeof(st), "got %lu\n", size);
ok(index == 1, "expected 1 got %lu\n", index); ok(index == 1, "expected 1 got %lu\n", index);
index = 0; index = 0;

View file

@ -1116,9 +1116,11 @@ static void test_InternetTimeToSystemTime(void)
test_data[] = test_data[] =
{ {
{ "Fri, 07 Jan 2005 12:06:35 GMT", &expect1, TRUE }, { "Fri, 07 Jan 2005 12:06:35 GMT", &expect1, TRUE },
{ "Fri, 07 Jan 2005 12:06:35 UTC", &expect1, TRUE },
{ " fri, 7 jan 2005 12 06 35", &expect1, TRUE }, { " fri, 7 jan 2005 12 06 35", &expect1, TRUE },
{ "Fri, 07-01-2005 12:06:35", &expect1, TRUE }, { "Fri, 07-01-2005 12:06:35", &expect1, TRUE },
{ "5, 07-01-2005 12:06:35 GMT", &expect1, TRUE }, { "5, 07-01-2005 12:06:35 GMT", &expect1, TRUE },
{ "5, 07-01-2005 12:06:35 UTC", &expect1, TRUE },
{ "5, 07-01-2005 12:06:35 GMT;", &expect1, TRUE }, { "5, 07-01-2005 12:06:35 GMT;", &expect1, TRUE },
{ "5, 07-01-2005 12:06:35 GMT123", &expect1, TRUE }, { "5, 07-01-2005 12:06:35 GMT123", &expect1, TRUE },
{ "2, 11 01 2022 11 13 05", &expect2, TRUE }, { "2, 11 01 2022 11 13 05", &expect2, TRUE },
@ -1126,6 +1128,9 @@ static void test_InternetTimeToSystemTime(void)
{ "2, 11*01/2022 11+13=05", &expect2, TRUE }, { "2, 11*01/2022 11+13=05", &expect2, TRUE },
{ "2, 11-Jan-2022 11:13:05", &expect2, TRUE }, { "2, 11-Jan-2022 11:13:05", &expect2, TRUE },
{ "Fr", NULL, FALSE }, { "Fr", NULL, FALSE },
{ "Fri Jan 7 12:06:35 2005", &expect1, TRUE, TRUE },
{ "Fri Jan 7 12:06:35 2005 GMT", &expect1, TRUE, TRUE },
{ "Fri Jan 7 12:06:35 2005 UTC", &expect1, TRUE, TRUE },
}; };
ret = pInternetTimeToSystemTimeA(NULL, NULL, 0); ret = pInternetTimeToSystemTimeA(NULL, NULL, 0);

View file

@ -39,92 +39,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(wininet); WINE_DEFAULT_DEBUG_CHANNEL(wininet);
#define TIME_STRING_LEN 30
time_t ConvertTimeString(LPCWSTR asctime)
{
WCHAR tmpChar[TIME_STRING_LEN];
WCHAR *tmpChar2;
struct tm t;
int timelen = lstrlenW(asctime);
if(!timelen)
return 0;
/* FIXME: the atoiWs below rely on that tmpChar is \0 padded */
memset( tmpChar, 0, sizeof(tmpChar) );
lstrcpynW(tmpChar, asctime, TIME_STRING_LEN);
/* Assert that the string is the expected length */
if (lstrlenW(asctime) >= TIME_STRING_LEN) FIXME("\n");
/* Convert a time such as 'Mon, 15 Nov 1999 16:09:35 GMT' into a SYSTEMTIME structure
* We assume the time is in this format
* and divide it into easy to swallow chunks
*/
tmpChar[3]='\0';
tmpChar[7]='\0';
tmpChar[11]='\0';
tmpChar[16]='\0';
tmpChar[19]='\0';
tmpChar[22]='\0';
tmpChar[25]='\0';
memset( &t, 0, sizeof(t) );
t.tm_year = wcstol(tmpChar+12, NULL, 10) - 1900;
t.tm_mday = wcstol(tmpChar+5, NULL, 10);
t.tm_hour = wcstol(tmpChar+17, NULL, 10);
t.tm_min = wcstol(tmpChar+20, NULL, 10);
t.tm_sec = wcstol(tmpChar+23, NULL, 10);
/* and month */
tmpChar2 = tmpChar + 8;
switch(tmpChar2[2])
{
case 'n':
if(tmpChar2[1]=='a')
t.tm_mon = 0;
else
t.tm_mon = 5;
break;
case 'b':
t.tm_mon = 1;
break;
case 'r':
if(tmpChar2[1]=='a')
t.tm_mon = 2;
else
t.tm_mon = 3;
break;
case 'y':
t.tm_mon = 4;
break;
case 'l':
t.tm_mon = 6;
break;
case 'g':
t.tm_mon = 7;
break;
case 'p':
t.tm_mon = 8;
break;
case 't':
t.tm_mon = 9;
break;
case 'v':
t.tm_mon = 10;
break;
case 'c':
t.tm_mon = 11;
break;
default:
FIXME("\n");
}
return mktime(&t);
}
BOOL GetAddress(const WCHAR *name, INTERNET_PORT port, struct sockaddr *psa, int *sa_len, char *addr_str) BOOL GetAddress(const WCHAR *name, INTERNET_PORT port, struct sockaddr *psa, int *sa_len, char *addr_str)
{ {
ADDRINFOW *res, hints; ADDRINFOW *res, hints;

View file

@ -102,7 +102,7 @@ static const char* DUMPBITS(int x)
static inline void DUMPPACKET(WTPACKET packet) static inline void DUMPPACKET(WTPACKET packet)
{ {
TRACE("pkContext: %p pkStatus: 0x%x pkTime : 0x%lx pkChanged: 0x%lx pkSerialNumber: 0x%x pkCursor : %i pkButtons: %lx pkX: %li pkY: %li pkZ: %li pkNormalPressure: %i pkTangentPressure: %i pkOrientation: (%i,%i,%i) pkRotation: (%i,%i,%i)\n", TRACE("pkContext: 0x%x pkStatus: 0x%x pkTime : 0x%lx pkChanged: 0x%lx pkSerialNumber: 0x%x pkCursor : %i pkButtons: %lx pkX: %li pkY: %li pkZ: %li pkNormalPressure: %i pkTangentPressure: %i pkOrientation: (%i,%i,%i) pkRotation: (%i,%i,%i)\n",
packet.pkContext, packet.pkStatus, packet.pkTime, packet.pkChanged, packet.pkSerialNumber, packet.pkContext, packet.pkStatus, packet.pkTime, packet.pkChanged, packet.pkSerialNumber,
packet.pkCursor, packet.pkButtons, packet.pkX, packet.pkY, packet.pkZ, packet.pkCursor, packet.pkButtons, packet.pkX, packet.pkY, packet.pkZ,
packet.pkNormalPressure, packet.pkTangentPressure, packet.pkNormalPressure, packet.pkTangentPressure,
@ -205,7 +205,7 @@ LPOPENCONTEXT AddPacketToContextQueue(LPWTPACKET packet, HWND hwnd)
tgt = ptr->PacketsQueued; tgt = ptr->PacketsQueued;
packet->pkContext = ptr->handle; packet->pkContext = HandleToULong(ptr->handle);
/* translate packet data to the context */ /* translate packet data to the context */
packet->pkChanged = packet->pkChanged & ptr->context.lcPktData; packet->pkChanged = packet->pkChanged & ptr->context.lcPktData;
@ -296,12 +296,15 @@ static LPVOID TABLET_CopyPacketData(LPOPENCONTEXT context, LPVOID lpPkt,
LPWTPACKET wtp) LPWTPACKET wtp)
{ {
LPBYTE ptr; LPBYTE ptr;
HCTX ctx;
ptr = lpPkt; ptr = lpPkt;
TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData)); TRACE("Packet Bits %s\n",DUMPBITS(context->context.lcPktData));
ctx = ULongToHandle(wtp->pkContext);
if (context->context.lcPktData & PK_CONTEXT) if (context->context.lcPktData & PK_CONTEXT)
ptr+=CopyTabletData(ptr,&wtp->pkContext,sizeof(HCTX)); ptr+=CopyTabletData(ptr,&ctx,sizeof(HCTX));
if (context->context.lcPktData & PK_STATUS) if (context->context.lcPktData & PK_STATUS)
ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT)); ptr+=CopyTabletData(ptr,&wtp->pkStatus,sizeof(UINT));
if (context->context.lcPktData & PK_TIME) if (context->context.lcPktData & PK_TIME)

View file

@ -117,7 +117,7 @@ typedef struct tagWTI_EXTENSIONS_INFO
} WTI_EXTENSIONS_INFO, *LPWTI_EXTENSIONS_INFO; } WTI_EXTENSIONS_INFO, *LPWTI_EXTENSIONS_INFO;
typedef struct tagWTPACKET { typedef struct tagWTPACKET {
HCTX pkContext; UINT pkContext;
UINT pkStatus; UINT pkStatus;
LONG pkTime; LONG pkTime;
WTPKT pkChanged; WTPKT pkChanged;

View file

@ -1449,6 +1449,22 @@ NTSTATUS WINAPI wow64_NtSetIoCompletion( UINT *args )
} }
/**********************************************************************
* wow64_NtSetIoCompletionEx
*/
NTSTATUS WINAPI wow64_NtSetIoCompletionEx( UINT *args )
{
HANDLE completion_handle = get_handle( &args );
HANDLE completion_reserve_handle = get_handle( &args );
ULONG_PTR key = get_ulong( &args );
ULONG_PTR value = get_ulong( &args );
NTSTATUS status = get_ulong( &args );
SIZE_T count = get_ulong( &args );
return NtSetIoCompletionEx( completion_handle, completion_reserve_handle, key, value, status, count );
}
/********************************************************************** /**********************************************************************
* wow64_NtSetTimer * wow64_NtSetTimer
*/ */

View file

@ -343,4 +343,19 @@ typedef struct tagKbdLayer
#error "Unsupported KBD_TYPE" #error "Unsupported KBD_TYPE"
#endif #endif
#define VK_DBE_ALPHANUMERIC 0x0f0
#define VK_DBE_KATAKANA 0x0f1
#define VK_DBE_HIRAGANA 0x0f2
#define VK_DBE_SBCSCHAR 0x0f3
#define VK_DBE_DBCSCHAR 0x0f4
#define VK_DBE_ROMAN 0x0f5
#define VK_DBE_NOROMAN 0x0f6
#define VK_DBE_ENTERWORDREGISTERMODE 0x0f7
#define VK_DBE_ENTERIMECONFIGMODE 0x0f8
#define VK_DBE_FLUSHSTRING 0x0f9
#define VK_DBE_CODEINPUT 0x0fa
#define VK_DBE_NOCODEINPUT 0x0fb
#define VK_DBE_DETERMINESTRING 0x0fc
#define VK_DBE_ENTERDLGCONVERSIONMODE 0x0fd
#endif /* __WINE_KBD_H */ #endif /* __WINE_KBD_H */

View file

@ -430,6 +430,36 @@ library UIAutomationClient {
const long UIA_AppBarControlTypeId = 50040; const long UIA_AppBarControlTypeId = 50040;
} }
[dllname("<no entry points>")]
module UIA_AnnotationTypes
{
const long AnnotationType_Unknown = 60000;
const long AnnotationType_SpellingError = 60001;
const long AnnotationType_GrammarError = 60002;
const long AnnotationType_Comment = 60003;
const long AnnotationType_FormulaError = 60004;
const long AnnotationType_TrackChanges = 60005;
const long AnnotationType_Header = 60006;
const long AnnotationType_Footer = 60007;
const long AnnotationType_Highlighted = 60008;
const long AnnotationType_Endnote = 60009;
const long AnnotationType_Footnote = 60010;
const long AnnotationType_InsertionChange = 60011;
const long AnnotationType_DeletionChange = 60012;
const long AnnotationType_MoveChange = 60013;
const long AnnotationType_FormatChange = 60014;
const long AnnotationType_UnsyncedChange = 60015;
const long AnnotationType_EditingLockedChange = 60016;
const long AnnotationType_ExternalChange = 60017;
const long AnnotationType_ConflictingChange = 60018;
const long AnnotationType_Author = 60019;
const long AnnotationType_AdvancedProofingIssue = 60020;
const long AnnotationType_DataValidationError = 60021;
const long AnnotationType_CircularReferenceError = 60022;
const long AnnotationType_Mathematics = 60023;
const long AnnotationType_Sensitive = 60024;
}
[dllname("<no entry points>")] [dllname("<no entry points>")]
module UIA_LandmarkTypeIds module UIA_LandmarkTypeIds
{ {

View file

@ -260,7 +260,7 @@ typedef struct
} rectangle_t; } rectangle_t;
typedef struct struct async_data
{ {
obj_handle_t handle; obj_handle_t handle;
obj_handle_t event; obj_handle_t event;
@ -268,7 +268,7 @@ typedef struct
client_ptr_t user; client_ptr_t user;
client_ptr_t apc; client_ptr_t apc;
apc_param_t apc_context; apc_param_t apc_context;
} async_data_t; };
@ -488,18 +488,18 @@ enum apc_type
APC_DUP_HANDLE APC_DUP_HANDLE
}; };
typedef struct struct user_apc
{ {
enum apc_type type; enum apc_type type;
int __pad; int __pad;
client_ptr_t func; client_ptr_t func;
apc_param_t args[3]; apc_param_t args[3];
} user_apc_t; };
typedef union union apc_call
{ {
enum apc_type type; enum apc_type type;
user_apc_t user; struct user_apc user;
struct struct
{ {
enum apc_type type; enum apc_type type;
@ -620,9 +620,9 @@ typedef union
unsigned int attributes; unsigned int attributes;
unsigned int options; unsigned int options;
} dup_handle; } dup_handle;
} apc_call_t; };
typedef union union apc_result
{ {
enum apc_type type; enum apc_type type;
struct struct
@ -732,7 +732,7 @@ typedef union
enum apc_type type; enum apc_type type;
unsigned int status; unsigned int status;
} break_process; } break_process;
} apc_result_t; };
enum irp_type enum irp_type
{ {
@ -1343,7 +1343,7 @@ struct get_apc_result_request
struct get_apc_result_reply struct get_apc_result_reply
{ {
struct reply_header __header; struct reply_header __header;
apc_result_t result; union apc_result result;
}; };
@ -1829,7 +1829,7 @@ struct flush_request
{ {
struct request_header __header; struct request_header __header;
char __pad_12[4]; char __pad_12[4];
async_data_t async; struct async_data async;
}; };
struct flush_reply struct flush_reply
{ {
@ -1857,7 +1857,7 @@ struct get_volume_info_request
{ {
struct request_header __header; struct request_header __header;
obj_handle_t handle; obj_handle_t handle;
async_data_t async; struct async_data async;
unsigned int info_class; unsigned int info_class;
char __pad_60[4]; char __pad_60[4];
}; };
@ -1906,7 +1906,7 @@ struct recv_socket_request
{ {
struct request_header __header; struct request_header __header;
int oob; int oob;
async_data_t async; struct async_data async;
int force_async; int force_async;
char __pad_60[4]; char __pad_60[4];
}; };
@ -1925,7 +1925,7 @@ struct send_socket_request
{ {
struct request_header __header; struct request_header __header;
unsigned int flags; unsigned int flags;
async_data_t async; struct async_data async;
}; };
struct send_socket_reply struct send_socket_reply
{ {
@ -2016,7 +2016,7 @@ struct read_directory_changes_request
unsigned int filter; unsigned int filter;
int subtree; int subtree;
int want_data; int want_data;
async_data_t async; struct async_data async;
}; };
struct read_directory_changes_reply struct read_directory_changes_reply
{ {
@ -3152,7 +3152,7 @@ struct register_async_request
{ {
struct request_header __header; struct request_header __header;
int type; int type;
async_data_t async; struct async_data async;
int count; int count;
char __pad_60[4]; char __pad_60[4];
}; };
@ -3216,7 +3216,7 @@ struct read_request
{ {
struct request_header __header; struct request_header __header;
char __pad_12[4]; char __pad_12[4];
async_data_t async; struct async_data async;
file_pos_t pos; file_pos_t pos;
}; };
struct read_reply struct read_reply
@ -3233,7 +3233,7 @@ struct write_request
{ {
struct request_header __header; struct request_header __header;
char __pad_12[4]; char __pad_12[4];
async_data_t async; struct async_data async;
file_pos_t pos; file_pos_t pos;
/* VARARG(data,bytes); */ /* VARARG(data,bytes); */
}; };
@ -3252,7 +3252,7 @@ struct ioctl_request
{ {
struct request_header __header; struct request_header __header;
ioctl_code_t code; ioctl_code_t code;
async_data_t async; struct async_data async;
/* VARARG(in_data,bytes); */ /* VARARG(in_data,bytes); */
}; };
struct ioctl_reply struct ioctl_reply
@ -5412,8 +5412,8 @@ struct add_completion_request
apc_param_t ckey; apc_param_t ckey;
apc_param_t cvalue; apc_param_t cvalue;
apc_param_t information; apc_param_t information;
obj_handle_t reserve_handle;
unsigned int status; unsigned int status;
char __pad_44[4];
}; };
struct add_completion_reply struct add_completion_reply
{ {
@ -6758,10 +6758,6 @@ union generic_reply
struct set_keyboard_repeat_reply set_keyboard_repeat_reply; struct set_keyboard_repeat_reply set_keyboard_repeat_reply;
}; };
/* ### protocol_version begin ### */ #define SERVER_PROTOCOL_VERSION 848
#define SERVER_PROTOCOL_VERSION 847
/* ### protocol_version end ### */
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View file

@ -4675,6 +4675,7 @@ NTSYSAPI NTSTATUS WINAPI NtSetInformationToken(HANDLE,TOKEN_INFORMATION_CLASS,P
NTSYSAPI NTSTATUS WINAPI NtSetInformationVirtualMemory(HANDLE,VIRTUAL_MEMORY_INFORMATION_CLASS,ULONG_PTR,PMEMORY_RANGE_ENTRY,PVOID,ULONG); NTSYSAPI NTSTATUS WINAPI NtSetInformationVirtualMemory(HANDLE,VIRTUAL_MEMORY_INFORMATION_CLASS,ULONG_PTR,PMEMORY_RANGE_ENTRY,PVOID,ULONG);
NTSYSAPI NTSTATUS WINAPI NtSetIntervalProfile(ULONG,KPROFILE_SOURCE); NTSYSAPI NTSTATUS WINAPI NtSetIntervalProfile(ULONG,KPROFILE_SOURCE);
NTSYSAPI NTSTATUS WINAPI NtSetIoCompletion(HANDLE,ULONG_PTR,ULONG_PTR,NTSTATUS,SIZE_T); NTSYSAPI NTSTATUS WINAPI NtSetIoCompletion(HANDLE,ULONG_PTR,ULONG_PTR,NTSTATUS,SIZE_T);
NTSYSAPI NTSTATUS WINAPI NtSetIoCompletionEx(HANDLE,HANDLE,ULONG_PTR,ULONG_PTR,NTSTATUS,SIZE_T);
NTSYSAPI NTSTATUS WINAPI NtSetLdtEntries(ULONG,LDT_ENTRY,ULONG,LDT_ENTRY); NTSYSAPI NTSTATUS WINAPI NtSetLdtEntries(ULONG,LDT_ENTRY,ULONG,LDT_ENTRY);
NTSYSAPI NTSTATUS WINAPI NtSetLowEventPair(HANDLE); NTSYSAPI NTSTATUS WINAPI NtSetLowEventPair(HANDLE);
NTSYSAPI NTSTATUS WINAPI NtSetLowWaitHighEventPair(HANDLE); NTSYSAPI NTSTATUS WINAPI NtSetLowWaitHighEventPair(HANDLE);

View file

@ -40,8 +40,11 @@ summary of contributions.
changes and bug fixes and got the synthesizer to actually work. Most changes and bug fixes and got the synthesizer to actually work. Most
importantly, he used it on stage to make music. importantly, he used it on stage to make music.
* S. Christian Collins did much testing of FluidSynth in regards to * S. Christian Collins provided many tests and fixes on EMU10K1
EMU10K1 compatibility and provided many synthesis fixes in that regard. compatibility. He also supplied reference chorus and reverb settings for
developing the default ones.
* Alberto Salvia Novella developed the default chorus and reverb settings.
* Stephane Letz from Grame wrote most of the MidiShare driver, all of * Stephane Letz from Grame wrote most of the MidiShare driver, all of
the PortAudio driver, ported iiwusynth to MacOS X, and sent in many the PortAudio driver, ported iiwusynth to MacOS X, and sent in many

View file

@ -57,6 +57,15 @@ enum fluid_mod_flags
FLUID_MOD_SIN = 0x80, /**< Custom non-standard sinus mapping function */ FLUID_MOD_SIN = 0x80, /**< Custom non-standard sinus mapping function */
}; };
/**
* Transform types for the SoundFont2 modulators as defined by SoundFont 2.04 section 8.3.
*/
enum fluid_mod_transforms
{
FLUID_MOD_TRANSFORM_LINEAR = 0, /**< Linear: directly add the computed value to summing node */
FLUID_MOD_TRANSFORM_ABS = 2 /**< Abs: add the absolute value of the computed to summing node */
};
/** /**
* General controller (if #FLUID_MOD_GC in flags). This * General controller (if #FLUID_MOD_GC in flags). This
* corresponds to SoundFont 2.04 PDF section 8.2.1 * corresponds to SoundFont 2.04 PDF section 8.2.1
@ -83,6 +92,7 @@ FLUIDSYNTH_API void fluid_mod_set_source1(fluid_mod_t *mod, int src, int flags);
FLUIDSYNTH_API void fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags); FLUIDSYNTH_API void fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags);
FLUIDSYNTH_API void fluid_mod_set_dest(fluid_mod_t *mod, int dst); FLUIDSYNTH_API void fluid_mod_set_dest(fluid_mod_t *mod, int dst);
FLUIDSYNTH_API void fluid_mod_set_amount(fluid_mod_t *mod, double amount); FLUIDSYNTH_API void fluid_mod_set_amount(fluid_mod_t *mod, double amount);
FLUIDSYNTH_API void fluid_mod_set_transform(fluid_mod_t *mod, int type);
FLUIDSYNTH_API int fluid_mod_get_source1(const fluid_mod_t *mod); FLUIDSYNTH_API int fluid_mod_get_source1(const fluid_mod_t *mod);
FLUIDSYNTH_API int fluid_mod_get_flags1(const fluid_mod_t *mod); FLUIDSYNTH_API int fluid_mod_get_flags1(const fluid_mod_t *mod);
@ -90,6 +100,7 @@ FLUIDSYNTH_API int fluid_mod_get_source2(const fluid_mod_t *mod);
FLUIDSYNTH_API int fluid_mod_get_flags2(const fluid_mod_t *mod); FLUIDSYNTH_API int fluid_mod_get_flags2(const fluid_mod_t *mod);
FLUIDSYNTH_API int fluid_mod_get_dest(const fluid_mod_t *mod); FLUIDSYNTH_API int fluid_mod_get_dest(const fluid_mod_t *mod);
FLUIDSYNTH_API double fluid_mod_get_amount(const fluid_mod_t *mod); FLUIDSYNTH_API double fluid_mod_get_amount(const fluid_mod_t *mod);
FLUIDSYNTH_API int fluid_mod_get_transform(fluid_mod_t *mod);
FLUIDSYNTH_API int fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2); FLUIDSYNTH_API int fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2);
FLUIDSYNTH_API int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl); FLUIDSYNTH_API int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl);

View file

@ -357,8 +357,13 @@ fluid_midi_file_read_mthd(fluid_midi_file *mf)
} }
mf->type = mthd[9]; mf->type = mthd[9];
mf->ntracks = (unsigned) mthd[11]; if(!(mf->type == 0 || mf->type == 1))
mf->ntracks += (unsigned int)(mthd[10]) << 16; {
FLUID_LOG(FLUID_ERR,
"Sorry, but MIDI Format %d is not supported by this player", mf->type);
return FLUID_FAILED;
}
mf->ntracks = (signed)((unsigned)(mthd[10]) << 8 | (unsigned) mthd[11]);
if((signed char)mthd[12] < 0) if((signed char)mthd[12] < 0)
{ {
@ -1062,7 +1067,7 @@ fluid_midi_file_get_division(fluid_midi_file *midifile)
* @return New MIDI event structure or NULL when out of memory. * @return New MIDI event structure or NULL when out of memory.
*/ */
fluid_midi_event_t * fluid_midi_event_t *
new_fluid_midi_event() new_fluid_midi_event(void)
{ {
fluid_midi_event_t *evt; fluid_midi_event_t *evt;
evt = FLUID_NEW(fluid_midi_event_t); evt = FLUID_NEW(fluid_midi_event_t);
@ -2696,7 +2701,7 @@ int fluid_player_get_midi_tempo(fluid_player_t *player)
* new_fluid_midi_parser * new_fluid_midi_parser
*/ */
fluid_midi_parser_t * fluid_midi_parser_t *
new_fluid_midi_parser() new_fluid_midi_parser(void)
{ {
fluid_midi_parser_t *parser; fluid_midi_parser_t *parser;
parser = FLUID_NEW(fluid_midi_parser_t); parser = FLUID_NEW(fluid_midi_parser_t);

View file

@ -65,7 +65,6 @@ fluid_iir_filter_apply(fluid_iir_filter_t *iir_filter,
fluid_real_t dsp_a2 = iir_filter->a2; fluid_real_t dsp_a2 = iir_filter->a2;
fluid_real_t dsp_b02 = iir_filter->b02; fluid_real_t dsp_b02 = iir_filter->b02;
fluid_real_t dsp_b1 = iir_filter->b1; fluid_real_t dsp_b1 = iir_filter->b1;
int dsp_filter_coeff_incr_count = iir_filter->filter_coeff_incr_count;
fluid_real_t dsp_centernode; fluid_real_t dsp_centernode;
int dsp_i; int dsp_i;
@ -83,51 +82,18 @@ fluid_iir_filter_apply(fluid_iir_filter_t *iir_filter,
* doesn't change. * doesn't change.
*/ */
if(dsp_filter_coeff_incr_count > 0) for(dsp_i = 0; dsp_i < count; dsp_i++)
{ {
fluid_real_t dsp_a1_incr = iir_filter->a1_incr; /* The filter is implemented in Direct-II form. */
fluid_real_t dsp_a2_incr = iir_filter->a2_incr; dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
fluid_real_t dsp_b02_incr = iir_filter->b02_incr; dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
fluid_real_t dsp_b1_incr = iir_filter->b1_incr; dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode;
/* Alternatively, it could be implemented in Transposed Direct Form II */
/* Increment is added to each filter coefficient filter_coeff_incr_count times. */ // fluid_real_t dsp_input = dsp_buf[dsp_i];
for(dsp_i = 0; dsp_i < count; dsp_i++) // dsp_buf[dsp_i] = dsp_b02 * dsp_input + dsp_hist1;
{ // dsp_hist1 = dsp_b1 * dsp_input - dsp_a1 * dsp_buf[dsp_i] + dsp_hist2;
/* The filter is implemented in Direct-II form. */ // dsp_hist2 = dsp_b02 * dsp_input - dsp_a2 * dsp_buf[dsp_i];
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode;
if(dsp_filter_coeff_incr_count-- > 0)
{
fluid_real_t old_b02 = dsp_b02;
dsp_a1 += dsp_a1_incr;
dsp_a2 += dsp_a2_incr;
dsp_b02 += dsp_b02_incr;
dsp_b1 += dsp_b1_incr;
/* Compensate history to avoid the filter going havoc with large frequency changes */
if(iir_filter->compensate_incr && FLUID_FABS(dsp_b02) > 0.001f)
{
fluid_real_t compensate = old_b02 / dsp_b02;
dsp_hist1 *= compensate;
dsp_hist2 *= compensate;
}
}
} /* for dsp_i */
}
else /* The filter parameters are constant. This is duplicated to save time. */
{
for(dsp_i = 0; dsp_i < count; dsp_i++)
{
/* The filter is implemented in Direct-II form. */
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode;
}
} }
iir_filter->hist1 = dsp_hist1; iir_filter->hist1 = dsp_hist1;
@ -136,7 +102,6 @@ fluid_iir_filter_apply(fluid_iir_filter_t *iir_filter,
iir_filter->a2 = dsp_a2; iir_filter->a2 = dsp_a2;
iir_filter->b02 = dsp_b02; iir_filter->b02 = dsp_b02;
iir_filter->b1 = dsp_b1; iir_filter->b1 = dsp_b1;
iir_filter->filter_coeff_incr_count = dsp_filter_coeff_incr_count;
fluid_check_fpe("voice_filter"); fluid_check_fpe("voice_filter");
} }
@ -320,47 +285,11 @@ fluid_iir_filter_calculate_coefficients(fluid_iir_filter_t *iir_filter,
return; return;
} }
iir_filter->compensate_incr = 0; iir_filter->a1 = a1_temp;
iir_filter->a2 = a2_temp;
if(iir_filter->filter_startup || (transition_samples == 0)) iir_filter->b02 = b02_temp;
{ iir_filter->b1 = b1_temp;
/* The filter is calculated, because the voice was started up. iir_filter->filter_startup = 0;
* In this case set the filter coefficients without delay.
*/
iir_filter->a1 = a1_temp;
iir_filter->a2 = a2_temp;
iir_filter->b02 = b02_temp;
iir_filter->b1 = b1_temp;
iir_filter->filter_coeff_incr_count = 0;
iir_filter->filter_startup = 0;
// printf("Setting initial filter coefficients.\n");
}
else
{
/* The filter frequency is changed. Calculate an increment
* factor, so that the new setting is reached after one buffer
* length. x_incr is added to the current value FLUID_BUFSIZE
* times. The length is arbitrarily chosen. Longer than one
* buffer will sacrifice some performance, though. Note: If
* the filter is still too 'grainy', then increase this number
* at will.
*/
iir_filter->a1_incr = (a1_temp - iir_filter->a1) / transition_samples;
iir_filter->a2_incr = (a2_temp - iir_filter->a2) / transition_samples;
iir_filter->b02_incr = (b02_temp - iir_filter->b02) / transition_samples;
iir_filter->b1_incr = (b1_temp - iir_filter->b1) / transition_samples;
if(FLUID_FABS(iir_filter->b02) > 0.0001f)
{
fluid_real_t quota = b02_temp / iir_filter->b02;
iir_filter->compensate_incr = quota < 0.5f || quota > 2.f;
}
/* Have to add the increments filter_coeff_incr_count times. */
iir_filter->filter_coeff_incr_count = transition_samples;
}
fluid_check_fpe("voice_write filter calculation"); fluid_check_fpe("voice_write filter calculation");
} }
@ -376,9 +305,6 @@ void fluid_iir_filter_calc(fluid_iir_filter_t *iir_filter,
/* calculate the frequency of the resonant filter in Hz */ /* calculate the frequency of the resonant filter in Hz */
fres = fluid_ct2hz(iir_filter->fres + fres_mod); fres = fluid_ct2hz(iir_filter->fres + fres_mod);
/* FIXME - Still potential for a click during turn on, can we interpolate
between 20khz cutoff and 0 Q? */
/* I removed the optimization of turning the filter off when the /* I removed the optimization of turning the filter off when the
* resonance frequency is above the maximum frequency. Instead, the * resonance frequency is above the maximum frequency. Instead, the
* filter frequency is set to a maximum of 0.45 times the sampling * filter frequency is set to a maximum of 0.45 times the sampling
@ -398,6 +324,7 @@ void fluid_iir_filter_calc(fluid_iir_filter_t *iir_filter,
fres = 5.f; fres = 5.f;
} }
// FLUID_LOG(FLUID_INFO, "%f + %f cents = %f cents = %f Hz | Q: %f", iir_filter->fres, fres_mod, iir_filter->fres + fres_mod, fres, iir_filter->q_lin);
/* if filter enabled and there is a significant frequency change.. */ /* if filter enabled and there is a significant frequency change.. */
if(iir_filter->type != FLUID_IIR_DISABLED && FLUID_FABS(fres - iir_filter->last_fres) > 0.01f) if(iir_filter->type != FLUID_IIR_DISABLED && FLUID_FABS(fres - iir_filter->last_fres) > 0.01f)
{ {

View file

@ -53,12 +53,6 @@ struct _fluid_iir_filter_t
fluid_real_t a1; /* a0 / a0 */ fluid_real_t a1; /* a0 / a0 */
fluid_real_t a2; /* a1 / a0 */ fluid_real_t a2; /* a1 / a0 */
fluid_real_t b02_incr;
fluid_real_t b1_incr;
fluid_real_t a1_incr;
fluid_real_t a2_incr;
int filter_coeff_incr_count;
int compensate_incr; /* Flag: If set, must compensate history */
fluid_real_t hist1, hist2; /* Sample history for the IIR filter */ fluid_real_t hist1, hist2; /* Sample history for the IIR filter */
int filter_startup; /* Flag: If set, the filter will be set directly. int filter_startup; /* Flag: If set, the filter will be set directly.
Else it changes smoothly. */ Else it changes smoothly. */

View file

@ -354,11 +354,13 @@ fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf)
/******************* amplitude **********************/ /******************* amplitude **********************/
count = fluid_rvoice_calc_amp(voice); count = fluid_rvoice_calc_amp(voice);
if(count == 0)
if(count <= 0)
{ {
return count; /* return -1 if voice is quiet, 0 if voice has finished */ // Voice has finished, remove from dsp loop
return 0;
} }
// else if count is negative, still process the voice
/******************* phase **********************/ /******************* phase **********************/
@ -420,6 +422,14 @@ fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf)
voice->dsp.phase_incr = 1; voice->dsp.phase_incr = 1;
} }
/* loop mode release? if not in release, the voice is silent
* note: this intentionally processes the volenv before returning silence,
* since that's what polyphone does (PR #1400) */
if(voice->dsp.samplemode == FLUID_START_ON_RELEASE && fluid_adsr_env_get_section(&voice->envlfo.volenv) < FLUID_VOICE_ENVRELEASE)
{
return -1;
}
/* voice is currently looping? */ /* voice is currently looping? */
is_looping = voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE is_looping = voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE
|| (voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE || (voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE
@ -431,6 +441,19 @@ fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf)
* Depending on the position in the loop and the loop size, this * Depending on the position in the loop and the loop size, this
* may require several runs. */ * may require several runs. */
if(count < 0)
{
// The voice is quite, i.e. either in delay phase or zero volume.
// We need to update the rvoice's dsp phase, as the delay phase shall not "postpone" the sound, rather
// it should be played silently, see https://github.com/FluidSynth/fluidsynth/issues/1312
//
// Currently, this does access the sample buffers, which is redundant and could be optimized away.
// On the other hand, entering this if-clause is not supposed to happen often.
//
// Also note, that we're returning directly without running the IIR filter below.
return fluid_rvoice_dsp_interpolate_none(&voice->dsp, dsp_buf, is_looping);
}
switch(voice->dsp.interp_method) switch(voice->dsp.interp_method)
{ {
case FLUID_INTERP_NONE: case FLUID_INTERP_NONE:
@ -455,6 +478,7 @@ fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf)
if(count == 0) if(count == 0)
{ {
// voice has finished
return count; return count;
} }

View file

@ -45,7 +45,7 @@ enum fluid_loop
{ {
FLUID_UNLOOPED = 0, FLUID_UNLOOPED = 0,
FLUID_LOOP_DURING_RELEASE = 1, FLUID_LOOP_DURING_RELEASE = 1,
FLUID_NOTUSED = 2, FLUID_START_ON_RELEASE = 2, /* this is a looping mode introduced by Polyphone, see #1398 for more info */
FLUID_LOOP_UNTIL_RELEASE = 3 FLUID_LOOP_UNTIL_RELEASE = 3
}; };

View file

@ -954,7 +954,6 @@ fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int c
for(i = 0; i < GEN_LAST; i++) for(i = 0; i < GEN_LAST; i++)
{ {
/* SF 2.01 section 9.4 'bullet' 4: /* SF 2.01 section 9.4 'bullet' 4:
* *
* A generator in a local instrument zone supersedes a * A generator in a local instrument zone supersedes a
@ -977,7 +976,6 @@ fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int c
* Do nothing, leave it at the default. * Do nothing, leave it at the default.
*/ */
} }
} /* for all generators */ } /* for all generators */
/* Adds instrument zone modulators (global and local) to the voice.*/ /* Adds instrument zone modulators (global and local) to the voice.*/
@ -991,7 +989,7 @@ fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int c
for(i = 0; i < GEN_LAST; i++) for(i = 0; i < GEN_LAST; i++)
{ {
fluid_real_t awe_val;
/* SF 2.01 section 8.5 page 58: If some generators are /* SF 2.01 section 8.5 page 58: If some generators are
encountered at preset level, they should be ignored. encountered at preset level, they should be ignored.
However this check is not necessary when the soundfont However this check is not necessary when the soundfont
@ -1026,6 +1024,12 @@ fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int c
* Do nothing, leave it unchanged. * Do nothing, leave it unchanged.
*/ */
} }
/* ...unless the default value has been overridden by an AWE32 NRPN */
if (fluid_channel_get_override_gen_default(synth->channel[chan], i, &awe_val))
{
fluid_voice_gen_set(voice, i, awe_val);
}
} /* for all generators */ } /* for all generators */
/* Adds preset zone modulators (global and local) to the voice.*/ /* Adds preset zone modulators (global and local) to the voice.*/
@ -1614,18 +1618,6 @@ fluid_zone_mod_import_sfont(char *zone_name, fluid_mod_t **mod, SFZone *sfzone)
mod_dest->amount = 0; mod_dest->amount = 0;
} }
/* Note: When primary source input (src1) is set to General Controller 'No Controller',
output will be forced to 0.0 at synthesis time (see fluid_mod_get_value()).
That means that the minimum value of the modulator will be always 0.0.
We need to force amount value to 0 to ensure a correct evaluation of the minimum
value later (see fluid_voice_get_lower_boundary_for_attenuation()).
*/
if(((mod_dest->flags1 & FLUID_MOD_CC) == FLUID_MOD_GC) &&
(mod_dest->src1 == FLUID_MOD_NONE))
{
mod_dest->amount = 0;
}
/* *** Dest *** */ /* *** Dest *** */
mod_dest->dest = mod_src->dest; /* index of controlled generator */ mod_dest->dest = mod_src->dest; /* index of controlled generator */
@ -1636,25 +1628,20 @@ fluid_zone_mod_import_sfont(char *zone_name, fluid_mod_t **mod, SFZone *sfzone)
* Deactivate the modulator by setting the amount to 0. */ * Deactivate the modulator by setting the amount to 0. */
mod_dest->amount = 0; mod_dest->amount = 0;
} }
/* Note: When secondary source input (src2) is set to General Controller 'No Controller',
output will be forced to +1.0 at synthesis time (see fluid_mod_get_value()).
That means that this source will behave unipolar only. We need to force the
unipolar flag to ensure to ensure a correct evaluation of the minimum
value later (see fluid_voice_get_lower_boundary_for_attenuation()).
*/
if(((mod_dest->flags2 & FLUID_MOD_CC) == FLUID_MOD_GC) &&
(mod_dest->src2 == FLUID_MOD_NONE))
{
mod_dest->flags2 &= ~FLUID_MOD_BIPOLAR;
}
/* *** Transform *** */ /**
/* SF2.01 only uses the 'linear' transform (0). * *** Transform Type ***
* Deactivate the modulator by setting the amount to 0 in any other case. * Only 2 types of transform are defined in the sf2 specification.
*/ */
if(mod_src->trans != 0) if(mod_src->trans != FLUID_MOD_TRANSFORM_LINEAR && mod_src->trans != FLUID_MOD_TRANSFORM_ABS)
{ {
/* disable the modulator as the transform is invalid */
mod_dest->amount = 0; mod_dest->amount = 0;
mod_dest->trans = FLUID_MOD_TRANSFORM_LINEAR;
}
else
{
mod_dest->trans = mod_src->trans;
} }
/* Store the new modulator in the zone The order of modulators /* Store the new modulator in the zone The order of modulators

View file

@ -66,7 +66,7 @@ struct _fluid_zone_range_t
}; };
/* Stored on a preset zone to keep track of the inst zones that could start a voice /* Stored on a preset zone to keep track of the inst zones that could start a voice
* and their combined preset zone/instument zone ranges */ * and their combined preset zone/instrument zone ranges */
struct _fluid_voice_zone_t struct _fluid_voice_zone_t
{ {
fluid_inst_zone_t *inst_zone; fluid_inst_zone_t *inst_zone;

View file

@ -2500,6 +2500,12 @@ static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigne
goto error_exit; goto error_exit;
} }
// Avoid clipping for loud samples, see
// https://github.com/FluidSynth/fluidsynth/issues/1380
// and
// https://github.com/libsndfile/libsndfile/issues/194
sf_command(sndfile, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
/* Automatically decompresses the Ogg Vorbis data to 16-bit PCM */ /* Automatically decompresses the Ogg Vorbis data to 16-bit PCM */
if(sf_readf_short(sndfile, wav_data, sfinfo.frames) < sfinfo.frames) if(sf_readf_short(sndfile, wav_data, sfinfo.frames) < sfinfo.frames)
{ {

View file

@ -128,7 +128,12 @@ fluid_channel_init_ctrl(fluid_channel_t *chan, int is_all_ctrl_off)
for(i = 0; i < GEN_LAST; i++) for(i = 0; i < GEN_LAST; i++)
{ {
chan->gen[i] = 0.0f; chan->gen[i] = 0.0f;
chan->override_gen_default[i].flags = GEN_UNUSED;
chan->override_gen_default[i].val = 0.0f;
} }
// Not all MIDIs initialize the IIR filter coefficient, e.g. Uplift.mid.
// A default value is not documented, hence I'm assuming zero here.
chan->awe32_filter_coeff = 0;
if(is_all_ctrl_off) if(is_all_ctrl_off)
{ {
@ -730,3 +735,20 @@ void fluid_channel_cc_breath_note_on_off(fluid_channel_t *chan, int value)
chan->previous_cc_breath = value; chan->previous_cc_breath = value;
} }
int fluid_channel_get_override_gen_default(fluid_channel_t *chan, int gen, fluid_real_t* val)
{
if(chan->override_gen_default[gen].flags != GEN_UNUSED)
{
*val = chan->override_gen_default[gen].val;
return TRUE;
}
return FALSE;
}
void fluid_channel_set_override_gen_default(fluid_channel_t *chan, int gen, fluid_real_t val)
{
chan->override_gen_default[gen].flags = GEN_SET;
chan->override_gen_default[gen].val = val;
}

View file

@ -24,6 +24,7 @@
#include "fluidsynth_priv.h" #include "fluidsynth_priv.h"
#include "fluid_midi.h" #include "fluid_midi.h"
#include "fluid_tuning.h" #include "fluid_tuning.h"
#include "fluid_gen.h"
/* The mononophonic list is part of the legato detector for monophonic mode */ /* The mononophonic list is part of the legato detector for monophonic mode */
/* see fluid_synth_monopoly.c about a description of the legato detector device */ /* see fluid_synth_monopoly.c about a description of the legato detector device */
@ -124,11 +125,20 @@ struct _fluid_channel_t
enum fluid_gen_type nrpn_select; /* Generator ID of SoundFont NRPN message */ enum fluid_gen_type nrpn_select; /* Generator ID of SoundFont NRPN message */
char nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */ char nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */
char awe32_filter_coeff;
/* The values of the generators, set by NRPN messages, or by /* The values of the generators, set by NRPN messages, or by
* fluid_synth_set_gen(), are cached in the channel so they can be * fluid_synth_set_gen(), are cached in the channel so they can be
* applied to future notes. They are copied to a voice's generators * applied to future notes. They are copied to a voice's generators
* in fluid_voice_init(), which calls fluid_gen_init(). */ * in fluid_voice_init(), which calls fluid_gen_init(). */
fluid_real_t gen[GEN_LAST]; fluid_real_t gen[GEN_LAST];
/* Same for AWE32 NRPNs, however they override the gen's default values */
struct
{
enum fluid_gen_flags flags;
fluid_real_t val;
} override_gen_default[GEN_LAST];
}; };
fluid_channel_t *new_fluid_channel(fluid_synth_t *synth, int num); fluid_channel_t *new_fluid_channel(fluid_synth_t *synth, int num);
@ -272,5 +282,7 @@ void fluid_channel_invalid_prev_note_staccato(fluid_channel_t *chan);
void fluid_channel_cc_legato(fluid_channel_t *chan, int value); void fluid_channel_cc_legato(fluid_channel_t *chan, int value);
void fluid_channel_cc_breath_note_on_off(fluid_channel_t *chan, int value); void fluid_channel_cc_breath_note_on_off(fluid_channel_t *chan, int value);
int fluid_channel_get_override_gen_default(fluid_channel_t *chan, int gen, fluid_real_t *val);
void fluid_channel_set_override_gen_default(fluid_channel_t *chan, int gen, fluid_real_t val);
#endif /* _FLUID_CHAN_H */ #endif /* _FLUID_CHAN_H */

View file

@ -39,6 +39,7 @@ fluid_mod_clone(fluid_mod_t *mod, const fluid_mod_t *src)
mod->src2 = src->src2; mod->src2 = src->src2;
mod->flags2 = src->flags2; mod->flags2 = src->flags2;
mod->amount = src->amount; mod->amount = src->amount;
mod->trans = src->trans;
} }
/** /**
@ -97,6 +98,24 @@ fluid_mod_set_amount(fluid_mod_t *mod, double amount)
mod->amount = (double) amount; mod->amount = (double) amount;
} }
/**
* Set the transform type of a modulator.
*
* @param mod The modulator instance
* @param type Transform type, see #fluid_mod_transforms
*/
void
fluid_mod_set_transform(fluid_mod_t *mod, int type)
{
unsigned char flag = (unsigned char) type;
if(flag != FLUID_MOD_TRANSFORM_LINEAR && flag != FLUID_MOD_TRANSFORM_ABS)
{
FLUID_LOG(FLUID_ERR, "fluid_mod_set_transform() called with invalid transform type %d", type);
return;
}
mod->trans = flag;
}
/** /**
* Get the primary source value from a modulator. * Get the primary source value from a modulator.
* *
@ -169,6 +188,18 @@ fluid_mod_get_amount(const fluid_mod_t *mod)
return (double) mod->amount; return (double) mod->amount;
} }
/**
* Get the transform type of a modulator.
*
* @param mod The modulator instance
* @param type Transform type, see #fluid_mod_transforms
*/
int
fluid_mod_get_transform(fluid_mod_t *mod)
{
return (int) mod->trans;
}
/* /*
* retrieves the initial value from the given source of the modulator * retrieves the initial value from the given source of the modulator
*/ */
@ -188,7 +219,7 @@ fluid_mod_get_source_value(const unsigned char mod_src,
if(mod_src == PORTAMENTO_CTRL) if(mod_src == PORTAMENTO_CTRL)
{ {
// an invalid portamento fromkey should be treated as 0 when it's actually used for moulating // an invalid portamento fromkey should be treated as 0 when it's actually used for modulating
if(!fluid_channel_is_valid_note(val)) if(!fluid_channel_is_valid_note(val))
{ {
val = 0; val = 0;
@ -240,7 +271,7 @@ fluid_mod_get_source_value(const unsigned char mod_src,
/** /**
* transforms the initial value retrieved by \c fluid_mod_get_source_value into [0.0;1.0] * transforms the initial value retrieved by \c fluid_mod_get_source_value into [0.0;1.0]
*/ */
static fluid_real_t fluid_real_t
fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, const fluid_real_t range) fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, const fluid_real_t range)
{ {
/* normalized value, i.e. usually in the range [0;1] */ /* normalized value, i.e. usually in the range [0;1] */
@ -365,23 +396,18 @@ fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, cons
* *
* Output = Transform(Amount * Map(primary source input) * Map(secondary source input)) * Output = Transform(Amount * Map(primary source input) * Map(secondary source input))
* *
* Notes: * Note:
* 1)fluid_mod_get_value, ignores the Transform operator. The result is: * fluid_mod_get_value ignores the Transform operator. The result is:
* *
* Output = Amount * Map(primary source input) * Map(secondary source input) * Output = Amount * Map(primary source input) * Map(secondary source input)
*
* 2)When primary source input (src1) is set to General Controller 'No Controller',
* output is forced to 0.
*
* 3)When secondary source input (src2) is set to General Controller 'No Controller',
* output is forced to +1.0
*/ */
fluid_real_t fluid_real_t
fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice) fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice)
{ {
extern fluid_mod_t default_vel2filter_mod; extern fluid_mod_t default_vel2filter_mod;
fluid_real_t v1 = 0.0, v2 = 1.0; fluid_real_t v1, v2;
fluid_real_t final_value;
/* The wording of the default modulators refers to a range of 127/128. /* The wording of the default modulators refers to a range of 127/128.
* And the table in section 9.5.3 suggests, that this mapping should be applied * And the table in section 9.5.3 suggests, that this mapping should be applied
* to all unipolar and bipolar mappings respectively. * to all unipolar and bipolar mappings respectively.
@ -419,59 +445,42 @@ fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice)
* */ * */
if(fluid_mod_test_identity(mod, &default_vel2filter_mod)) if(fluid_mod_test_identity(mod, &default_vel2filter_mod))
{ {
// S. Christian Collins' mod, to stop forcing velocity based filtering
/* /*
if (voice->vel < 64){ if (voice->vel < 64){
return (fluid_real_t) mod->amount / 2.0; return (fluid_real_t) mod->amount / 2.0;
} else { } else {
return (fluid_real_t) mod->amount * (127 - voice->vel) / 127; return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
} }
return (fluid_real_t) mod->amount / 2.0;
*/ */
return 0; // (fluid_real_t) mod->amount / 2.0; // S. Christian Collins' mod, to stop forcing velocity based filtering
return 0;
} }
// end S. Christian Collins' mod /* Get the initial value of the first source.
*
* Even if the src is FLUID_MOD_NONE, the value has to be transformed, see #1389
*/
v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, voice);
/* get the initial value of the first source */ /* transform the input value */
if(mod->src1 > 0) v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1);
{
v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, voice);
/* transform the input value */
v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1);
}
/* When primary source input (src1) is set to General Controller 'No Controller',
output is forced to 0.0
*/
else
{
return 0.0;
}
/* no need to go further */
if(v1 == 0.0f)
{
return 0.0f;
}
/* get the second input source */ /* get the second input source */
if(mod->src2 > 0) v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, voice);
{
v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, voice);
/* transform the second input value */ /* transform the second input value */
v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2); v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2);
}
/* When secondary source input (src2) is set to General Controller 'No Controller',
output is forced to +1.0
*/
else
{
v2 = 1.0f;
}
/* it's as simple as that: */ /* it indeed is as simple as that: */
return (fluid_real_t) mod->amount * v1 * v2; final_value = (fluid_real_t) mod->amount * v1 * v2;
/* check for absolute value transform */
if(mod->trans == FLUID_MOD_TRANSFORM_ABS)
{
final_value = FLUID_FABS(final_value);
}
return final_value;
} }
/** /**
@ -480,7 +489,7 @@ fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice)
* @return New allocated modulator or NULL if out of memory * @return New allocated modulator or NULL if out of memory
*/ */
fluid_mod_t * fluid_mod_t *
new_fluid_mod() new_fluid_mod(void)
{ {
fluid_mod_t *mod = FLUID_NEW(fluid_mod_t); fluid_mod_t *mod = FLUID_NEW(fluid_mod_t);
@ -489,7 +498,8 @@ new_fluid_mod()
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
// for the sake of backward compatibility
mod->trans = FLUID_MOD_TRANSFORM_LINEAR;
return mod; return mod;
} }
@ -511,7 +521,7 @@ delete_fluid_mod(fluid_mod_t *mod)
* *
* Useful in low latency scenarios e.g. to allocate a modulator on the stack. * Useful in low latency scenarios e.g. to allocate a modulator on the stack.
*/ */
size_t fluid_mod_sizeof() size_t fluid_mod_sizeof(void)
{ {
return sizeof(fluid_mod_t); return sizeof(fluid_mod_t);
} }

View file

@ -34,6 +34,7 @@ struct _fluid_mod_t
unsigned char flags1; /**< Source controller 1 flags */ unsigned char flags1; /**< Source controller 1 flags */
unsigned char src2; /**< Source controller 2 */ unsigned char src2; /**< Source controller 2 */
unsigned char flags2; /**< Source controller 2 flags */ unsigned char flags2; /**< Source controller 2 flags */
unsigned char trans; /**< Output transform flag */
double amount; /**< Multiplier amount */ double amount; /**< Multiplier amount */
/* The 'next' field allows to link modulators into a list. It is /* The 'next' field allows to link modulators into a list. It is
* not used in fluid_voice.c, there each voice allocates memory for a * not used in fluid_voice.c, there each voice allocates memory for a
@ -45,6 +46,8 @@ struct _fluid_mod_t
fluid_real_t fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice); fluid_real_t fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice);
int fluid_mod_check_sources(const fluid_mod_t *mod, char *name); int fluid_mod_check_sources(const fluid_mod_t *mod, char *name);
fluid_real_t fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, const fluid_real_t range);
#ifdef DEBUG #ifdef DEBUG
void fluid_dump_modulator(fluid_mod_t *mod); void fluid_dump_modulator(fluid_mod_t *mod);

View file

@ -129,6 +129,7 @@ static void fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id);
static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels); static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels);
static void fluid_synth_process_awe32_nrpn_LOCAL(fluid_synth_t *synth, int chan, int gen, int data, int data_lsb);
/* Callback handlers for real-time settings */ /* Callback handlers for real-time settings */
static void fluid_synth_handle_gain(void *data, const char *name, double value); static void fluid_synth_handle_gain(void *data, const char *name, double value);
@ -229,7 +230,7 @@ void fluid_synth_settings(fluid_settings_t *settings)
fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0); fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0);
fluid_settings_register_int(settings, "synth.effects-groups", 1, 1, 128, 0); fluid_settings_register_int(settings, "synth.effects-groups", 1, 1, 128, 0);
fluid_settings_register_num(settings, "synth.sample-rate", 44100.0, 8000.0, 96000.0, 0); fluid_settings_register_num(settings, "synth.sample-rate", 44100.0, 8000.0, 96000.0, 0);
fluid_settings_register_int(settings, "synth.device-id", 0, 0, 127, 0); fluid_settings_register_int(settings, "synth.device-id", 16, 0, 127, 0);
#ifdef ENABLE_MIXER_THREADS #ifdef ENABLE_MIXER_THREADS
fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0); fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0);
#else #else
@ -1600,7 +1601,7 @@ fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val)
/* chan is enabled */ /* chan is enabled */
if(synth->verbose) if(synth->verbose)
{ {
FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val); FLUID_LOG(FLUID_INFO, "cc\t\t%d\t%d\t%d", chan, num, val);
} }
fluid_channel_set_cc(channel, num, val); fluid_channel_set_cc(channel, num, val);
@ -1634,7 +1635,7 @@ fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val)
{ {
if(synth->verbose) if(synth->verbose)
{ {
FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", i, num, val); FLUID_LOG(FLUID_INFO, "cc\t\t%d\t%d\t%d", i, num, val);
} }
fluid_channel_set_cc(synth->channel[i], num, val); fluid_channel_set_cc(synth->channel[i], num, val);
@ -1840,6 +1841,26 @@ fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
chan->nrpn_select = 0; /* Reset to 0 */ chan->nrpn_select = 0; /* Reset to 0 */
} }
else if(fluid_channel_get_cc(chan, NRPN_MSB) == 127) // indicates AWE32 NRPNs
{
// ALTITUDE.MID also manipulates AWE32 NRPNs by only using DATA LSB events - seems to be legal
if(fluid_channel_get_cc(chan, NRPN_MSB) == 127) // indicates AWE32 NRPNs
{
int gen = fluid_channel_get_cc(chan, NRPN_LSB);
if(synth->verbose)
{
FLUID_LOG(FLUID_INFO, "AWE32 NRPN RAW: Chan %d, Gen %d, data %d | 0x%X, MSB: %d, LSB: %d", channum, gen, data, data, msb_value, lsb_value);
}
if(gen <= 26) // Effect 26 (reverb) is the last effect to select
{
fluid_synth_process_awe32_nrpn_LOCAL(synth, channum, gen, data, lsb_value);
}
else
{
FLUID_LOG(FLUID_INFO, "Ignoring unknown AWE32 NRPN targetting effect %d", gen);
}
}
}
} }
else if(fluid_channel_get_cc(chan, RPN_MSB) == 0) /* RPN is active: MSB = 0? */ else if(fluid_channel_get_cc(chan, RPN_MSB) == 0) /* RPN is active: MSB = 0? */
{ {
@ -2859,7 +2880,7 @@ fluid_synth_pitch_bend(fluid_synth_t *synth, int chan, int val)
if(synth->verbose) if(synth->verbose)
{ {
FLUID_LOG(FLUID_INFO, "pitchb\t%d\t%d", chan, val); FLUID_LOG(FLUID_INFO, "pitchb\t\t%d\t%d", chan, val);
} }
fluid_channel_set_pitch_bend(synth->channel[chan], val); fluid_channel_set_pitch_bend(synth->channel[chan], val);
@ -3091,7 +3112,7 @@ fluid_synth_program_change(fluid_synth_t *synth, int chan, int prognum)
if(synth->verbose) if(synth->verbose)
{ {
FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum); FLUID_LOG(FLUID_INFO, "prog\t\t%d\t%d\t%d", chan, banknum, prognum);
} }
/* I think this is a hack for MIDI files that do bank changes in GM mode. /* I think this is a hack for MIDI files that do bank changes in GM mode.
@ -6852,15 +6873,30 @@ fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth, int chan,
&& (fluid_voice_get_key(voice) == key) && (fluid_voice_get_key(voice) == key)
&& (fluid_voice_get_id(voice) != synth->noteid)) && (fluid_voice_get_id(voice) != synth->noteid))
{ {
enum fluid_midi_channel_type type = synth->channel[chan]->channel_type;
/* Id of voices that was sustained by sostenuto */ /* Id of voices that was sustained by sostenuto */
if(fluid_voice_is_sostenuto(voice)) if(fluid_voice_is_sostenuto(voice))
{ {
synth->storeid = fluid_voice_get_id(voice); synth->storeid = fluid_voice_get_id(voice);
} }
/* Force the voice into release stage except if pedaling switch(type)
(sostenuto or sustain) is active */ {
fluid_voice_noteoff(voice); case CHANNEL_TYPE_DRUM:
/* release the voice, this should make riding hi-hats or snares sound more
* realistic (Discussion #1196) */
fluid_voice_off(voice);
break;
case CHANNEL_TYPE_MELODIC:
/* Force the voice into release stage except if pedaling (sostenuto or sustain) is active.
* This gives a more realistic sound to pianos and possibly other instruments (see PR #905). */
fluid_voice_noteoff(voice);
break;
default:
FLUID_LOG(FLUID_ERR, "This should never happen: unknown channel type %d", (int)type);
break;
}
} }
} }
} }
@ -7572,6 +7608,272 @@ fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan, int param, float value
} }
} }
// The "SB AWE32 Developer's Information Pack" provides a lookup table for the filter resonance.
// Instead of a single Q value, a high and low Q value is given. This suggests a variable-Q filter design, which is
// incompatible to fluidsynth's IIR filter. Therefore we need to somehow derive a single Q value.
// Options are:
// * mean
// * geometric distance (sqrt(q_lo * q_hi))
// * either q_lo or q_hi
// * linear interpolation between low and high fc
// * log interpolation between low and high fc
static fluid_real_t
calc_awe32_filter_q(int data, fluid_real_t* fc)
{
typedef struct
{
fluid_real_t fc_lo;
fluid_real_t fc_hi;
fluid_real_t q_lo;
fluid_real_t q_hi;
fluid_real_t dc_atten;
} awe32_q;
// Q in dB
static const awe32_q awe32_q_table[] =
{
{92, 22000, 5.f, 0.f, -0.0f }, /* coef 0 */
{93, 8500, 6.f, 0.5f, -0.5f }, /* coef 1 */
{94, 8300, 8.f, 1.f, -1.2f }, /* coef 2 */
{95, 8200, 10.f, 2.f, -1.8f }, /* coef 3 */
{96, 8100, 11.f, 3.f, -2.5f }, /* coef 4 */
{97, 8000, 13.f, 4.f, -3.3f }, /* coef 5 */
{98, 7900, 14.f, 5.f, -4.1f }, /* coef 6 */
{99, 7800, 16.f, 6.f, -5.5f}, /* coef 7 */
{100, 7700, 17.f, 7.f, -6.0f }, /* coef 8 */
{100, 7500, 19.f, 9.f, -6.6f }, /* coef 9 */
{100, 7400, 20.f, 10.f, -7.2f }, /* coef 10 */
{100, 7300, 22.f, 11.f, -7.9f }, /* coef 11 */
{100, 7200, 23.f, 13.f, -8.5f }, /* coef 12 */
{100, 7100, 25.f, 15.f, -9.3f }, /* coef 13 */
{100, 7100, 26.f, 16.f, -10.1f },/* coef 14 */
{100, 7000, 28.f, 18.f, -11.0f}, /* coef 15 */
};
const awe32_q* tab;
fluid_real_t alpha;
fluid_clip(data, 0, 127);
data /= 8;
tab = &awe32_q_table[data];
fluid_clip(*fc, tab->fc_lo, tab->fc_hi);
alpha = (*fc - tab->fc_lo) / (tab->fc_hi - tab->fc_lo);
// linearly interpolate between high and low Q
return 10 * /* cB */ (tab->q_lo * (1.0f - alpha) + tab->q_hi * alpha);
// alternatively: log interpolation
// return 10 * /* cB */ FLUID_POW(tab->q_hi, alpha) * FLUID_POW(tab->q_lo, 1.0f - alpha);
}
/**
* This implementation is based on "Frequently Asked Questions for SB AWE32" http://archive.gamedev.net/archive/reference/articles/article445.html
* as well as on the "SB AWE32 Developer's Information Pack" https://github.com/user-attachments/files/15757220/adip301.pdf
*
* @param gen the AWE32 effect or generator to manipulate
* @param data the composed value of DATA_MSB and DATA_LSB
*/
static void fluid_synth_process_awe32_nrpn_LOCAL(fluid_synth_t *synth, int chan, int gen, int data, int data_lsb)
{
static const enum fluid_gen_type awe32_to_sf2_gen[] =
{
// assuming LFO1 maps to MODLFO and LFO2 maps to VIBLFO
// observe how nicely most of the AWE32 generators here match up with the order of SF2 generators in fluid_gen_type
GEN_MODLFODELAY, /**< Modulation LFO delay */
GEN_MODLFOFREQ, /**< Modulation LFO frequency */
GEN_VIBLFODELAY, /**< Vibrato LFO delay */
GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */
GEN_MODENVDELAY, /**< Modulation envelope delay */
GEN_MODENVATTACK, /**< Modulation envelope attack */
GEN_MODENVHOLD, /**< Modulation envelope hold */
GEN_MODENVDECAY, /**< Modulation envelope decay */
GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */
GEN_MODENVRELEASE, /**< Modulation envelope release */
GEN_VOLENVDELAY, /**< Volume envelope delay */
GEN_VOLENVATTACK, /**< Volume envelope attack */
GEN_VOLENVHOLD, /**< Volume envelope hold */
GEN_VOLENVDECAY, /**< Volume envelope decay */
GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */
GEN_VOLENVRELEASE, /**< Volume envelope release */
GEN_PITCH, /**< Initial Pitch */
GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */
GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */
GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */
GEN_MODLFOTOVOL, /**< Modulation LFO to volume */
GEN_FILTERFC, /**< Filter cutoff */
GEN_FILTERQ, /**< Filter Q */
GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */
GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */
GEN_CHORUSSEND, /**< Chorus send amount */
GEN_REVERBSEND, /**< Reverb send amount */
};
enum fluid_gen_type sf2_gen = awe32_to_sf2_gen[gen];
int is_realtime = FALSE, i, coef;
fluid_real_t converted_sf2_generator_value, q;
// The AWE32 NRPN docs say that a value of 8192 is considered to be the middle, i.e. zero.
// However, it looks like for those generators which work in range [0,127], the AWE32 only inspects the DATA_LSB, i.e. and not doing this subtraction. Found while investigating Uplift.mid.
data -= 8192;
switch(sf2_gen)
{
case GEN_MODLFODELAY:
case GEN_VIBLFODELAY:
case GEN_MODENVDELAY:
case GEN_VOLENVDELAY:
fluid_clip(data, 0, 5900);
converted_sf2_generator_value = fluid_sec2tc(data * (fluid_real_t)(4.0 / 1000.0));
break;
case GEN_MODLFOFREQ:
case GEN_VIBLFOFREQ:
fluid_clip(data_lsb, 0, 127);
converted_sf2_generator_value = fluid_hz2ct(data_lsb * (fluid_real_t)0.084 /* Hz */);
is_realtime = TRUE;
break;
case GEN_MODENVATTACK:
case GEN_VOLENVATTACK:
fluid_clip(data, 0, 5940);
converted_sf2_generator_value = fluid_sec2tc(data * (fluid_real_t)(1.0 / 1000.0));
break;
case GEN_MODENVHOLD:
case GEN_VOLENVHOLD:
fluid_clip(data, 0, 8191);
converted_sf2_generator_value = fluid_sec2tc(data * (fluid_real_t)(1.0 / 1000.0));
break;
case GEN_MODENVDECAY:
case GEN_MODENVRELEASE:
case GEN_VOLENVDECAY:
case GEN_VOLENVRELEASE:
fluid_clip(data, 0, 5940);
converted_sf2_generator_value = fluid_sec2tc(data * (fluid_real_t)(4.0 / 1000.0));
break;
case GEN_MODENVSUSTAIN:
case GEN_VOLENVSUSTAIN:
fluid_clip(data_lsb, 0, 127);
converted_sf2_generator_value = data_lsb * (fluid_real_t)(0.75 /* dB */ * 10) /* cB */;
break;
case GEN_PITCH:
converted_sf2_generator_value = data + 8192;
// This has the side effect of manipulating the modulation state of the channel's pitchwheel, but
// I'll buy it, since pitch bend is not a regular SF2 generator and we do a bit of magic there to
// make it work
fluid_synth_pitch_bend(synth, chan, converted_sf2_generator_value);
return;
case GEN_MODLFOTOPITCH:
case GEN_VIBLFOTOPITCH:
is_realtime = TRUE;
/* fallthrough */
case GEN_MODENVTOPITCH:
fluid_clip(data, -127, 127);
converted_sf2_generator_value = data * (fluid_real_t)9.375 /* cents */;
break;
case GEN_MODLFOTOVOL:
fluid_clip(data_lsb, 0, 127);
converted_sf2_generator_value = data_lsb * (fluid_real_t)(0.1875 /* dB */ * 10.0) /* cB */;
is_realtime = TRUE;
break;
case GEN_FILTERFC:
fluid_clip(data_lsb, 0, 127);
// Yes, DO NOT use data here, Uplift.mid doesn't set MSB=64, therefore we would always get a negative value after subtracting 8192.
// Since Uplift.mid sounds fine on hardware though, it seems like AWE32 only inspects DATA_LSB in this case.
// conversion continues below!
converted_sf2_generator_value = (data_lsb * 62 /* Hz */);
FLUID_LOG(FLUID_DBG, "AWE32 IIR Fc: %f Hz",converted_sf2_generator_value);
is_realtime = TRUE;
break;
case GEN_FILTERQ:
FLUID_LOG(FLUID_DBG, "AWE32 IIR Q Tab: %d",data_lsb);
synth->channel[chan]->awe32_filter_coeff = data_lsb;
return;
case GEN_MODLFOTOFILTERFC:
fluid_clip(data, -64, 63);
converted_sf2_generator_value = data * (fluid_real_t)56.25 /* cents */;
FLUID_LOG(FLUID_DBG, "AWE32 MOD LFO TO FILTER Fc: %f cents", converted_sf2_generator_value);
is_realtime = TRUE;
// not supported, as this modulates the "phase" rather than the filters cutoff frequency
return;
case GEN_MODENVTOFILTERFC:
fluid_clip(data, -127, 127);
converted_sf2_generator_value = data * (fluid_real_t)56.25 /* cents */;
FLUID_LOG(FLUID_DBG, "AWE32 MOD ENV TO FILTER Fc: %f cents", converted_sf2_generator_value);
// not supported, as this modulates the "phase" rather than the filters cutoff frequency
return;
case GEN_REVERBSEND:
fluid_clip(data, 0, 255);
/* transform the input value */
converted_sf2_generator_value = fluid_mod_transform_source_value(data, default_reverb_mod.flags1, 256);
FLUID_LOG(FLUID_DBG, "AWE32 Reverb: %f", converted_sf2_generator_value);
converted_sf2_generator_value*= fluid_mod_get_amount(&default_reverb_mod);
break;
case GEN_CHORUSSEND:
fluid_clip(data, 0, 255);
/* transform the input value */
converted_sf2_generator_value = fluid_mod_transform_source_value(data, default_chorus_mod.flags1, 256);
FLUID_LOG(FLUID_DBG, "AWE32 Chorus: %f", converted_sf2_generator_value);
converted_sf2_generator_value*= fluid_mod_get_amount(&default_chorus_mod);
break;
default:
// should not happen
FLUID_LOG(FLUID_WARN, "AWE32 NPRN %d conversion not implemented", gen);
return;
}
coef = synth->channel[chan]->awe32_filter_coeff;
if(sf2_gen == GEN_FILTERFC)
{
// The cutoff at fc seems to be very steep for SoundBlaster! hardware. Listening tests have shown that lowering the cutoff frequency by 1000Hz gives a closer signal to the SB! hardware filter...
converted_sf2_generator_value -= 1000;
q = calc_awe32_filter_q(coef, &converted_sf2_generator_value);
FLUID_LOG(FLUID_DBG, "AWE32 IIR Fc (corrected): %f Hz", converted_sf2_generator_value);
FLUID_LOG(FLUID_DBG, "AWE32 IIR Q: %f cB", q);
converted_sf2_generator_value = fluid_hz2ct(converted_sf2_generator_value /* Hz */);
// Safe the "true initial Q"
fluid_channel_set_override_gen_default(synth->channel[chan], GEN_FILTERQ, q);
}
fluid_channel_set_override_gen_default(synth->channel[chan], sf2_gen, converted_sf2_generator_value);
for (i = 0; is_realtime && i < synth->polyphony; i++)
{
fluid_voice_t* voice = synth->voice[i];
if (fluid_voice_is_playing(voice) && fluid_voice_get_channel(voice) == chan)
{
// sets the adjusted generator
fluid_voice_gen_set(voice, sf2_gen, converted_sf2_generator_value);
fluid_voice_update_param(voice, sf2_gen);
FLUID_LOG(FLUID_DBG, "AWE32 Realtime: adjusting voice id %d, generator %d, chan %d", fluid_voice_get_id(voice), sf2_gen, chan);
if(sf2_gen == GEN_FILTERFC)
{
// also sets the calculated Q
fluid_voice_gen_set(voice, GEN_FILTERQ, q);
fluid_voice_update_param(voice, GEN_FILTERQ);
}
}
}
}
/** /**
* Retrieve the generator NRPN offset assigned to a MIDI channel. * Retrieve the generator NRPN offset assigned to a MIDI channel.
* *

View file

@ -41,21 +41,21 @@
* *
* DEFINES * DEFINES
*/ */
#define FLUID_NUM_PROGRAMS 128 #define FLUID_NUM_PROGRAMS 128
#define DRUM_INST_BANK 128 #define DRUM_INST_BANK 128
#define FLUID_UNSET_PROGRAM 128 /* Program number used to unset a preset */ #define FLUID_UNSET_PROGRAM 128 /* Program number used to unset a preset */
#define FLUID_REVERB_DEFAULT_ROOMSIZE 0.2f /**< Default reverb room size */ #define FLUID_REVERB_DEFAULT_DAMP 0.3f /**< Default reverb damping */
#define FLUID_REVERB_DEFAULT_DAMP 0.0f /**< Default reverb damping */ #define FLUID_REVERB_DEFAULT_LEVEL 0.7f /**< Default reverb level */
#define FLUID_REVERB_DEFAULT_WIDTH 0.5f /**< Default reverb width */ #define FLUID_REVERB_DEFAULT_ROOMSIZE 0.5f /**< Default reverb room size */
#define FLUID_REVERB_DEFAULT_LEVEL 0.9f /**< Default reverb level */ #define FLUID_REVERB_DEFAULT_WIDTH 0.8f /**< Default reverb width */
#define FLUID_CHORUS_DEFAULT_N 3 /**< Default chorus voice count */ #define FLUID_CHORUS_DEFAULT_DEPTH 4.25f /**< Default chorus depth */
#define FLUID_CHORUS_DEFAULT_LEVEL 2.0f /**< Default chorus level */ #define FLUID_CHORUS_DEFAULT_LEVEL 0.6f /**< Default chorus level */
#define FLUID_CHORUS_DEFAULT_SPEED 0.3f /**< Default chorus speed */ #define FLUID_CHORUS_DEFAULT_N 3 /**< Default chorus voice count */
#define FLUID_CHORUS_DEFAULT_DEPTH 8.0f /**< Default chorus depth */ #define FLUID_CHORUS_DEFAULT_SPEED 0.2f /**< Default chorus speed */
#define FLUID_CHORUS_DEFAULT_TYPE FLUID_CHORUS_MOD_SINE /**< Default chorus waveform type */ #define FLUID_CHORUS_DEFAULT_TYPE FLUID_CHORUS_MOD_SINE /**< Default chorus waveform type */
/*************************************************************** /***************************************************************
* *

View file

@ -1791,7 +1791,7 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice)
3)absolute value of amount. 3)absolute value of amount.
When at least one source mapping is bipolar: When at least one source mapping is bipolar:
min_val is -|amount| regardless the sign of amount. min_val is -|amount| regardless the sign of amount.
When both sources mapping are unipolar: When both sources mapping are unipolar:
min_val is -|amount|, if amount is negative. min_val is -|amount|, if amount is negative.
min_val is 0, if amount is positive min_val is 0, if amount is positive
@ -1834,9 +1834,6 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice)
return lower_bound; return lower_bound;
} }
int fluid_voice_set_param(fluid_voice_t *voice, int gen, fluid_real_t nrpn_value) int fluid_voice_set_param(fluid_voice_t *voice, int gen, fluid_real_t nrpn_value)
{ {
voice->gen[gen].nrpn = nrpn_value; voice->gen[gen].nrpn = nrpn_value;

View file

@ -111,9 +111,20 @@ fluid_cb2amp(fluid_real_t cb)
*/ */
/* minimum attenuation: 0 dB */ /* minimum attenuation: 0 dB */
if(cb < 0) if(FLUID_UNLIKELY(cb < 0))
{ {
return 1.0; /* Issue #1374: it seems that by using modLfoToVolEnv, the attenuation can become negative and
* therefore the signal needs to be amplified.
* In such a rare case, calculate the attenuation on the fly.
*
* This behavior is backed by the spec saying:
* modLfoToVolume: "A positive number indicates a positive LFO excursion increases volume;
* a negative number indicates a positive excursion decreases volume.
* [...] For example, a value of 100 indicates that the volume will first rise ten dB, then fall ten dB."
*
* And in order to rise, a negative attenuation must be permitted.
*/
return FLUID_POW(10.0f, cb / -200.0f);
} }
if(cb >= FLUID_CB_AMP_SIZE) if(cb >= FLUID_CB_AMP_SIZE)
@ -150,7 +161,7 @@ fluid_tc2sec_delay(fluid_real_t tc)
tc = (fluid_real_t) 5000.0f; tc = (fluid_real_t) 5000.0f;
} }
return FLUID_POW(2.f, tc / 1200.f); return fluid_tc2sec(tc);
} }
/* /*
@ -178,7 +189,7 @@ fluid_tc2sec_attack(fluid_real_t tc)
tc = (fluid_real_t) 8000.f; tc = (fluid_real_t) 8000.f;
}; };
return FLUID_POW(2.f, tc / 1200.f); return fluid_tc2sec(tc);
} }
/* /*
@ -191,6 +202,29 @@ fluid_tc2sec(fluid_real_t tc)
return FLUID_POW(2.f, tc / 1200.f); return FLUID_POW(2.f, tc / 1200.f);
} }
/*
* fluid_sec2tc
*
* seconds to timecents
*/
fluid_real_t
fluid_sec2tc(fluid_real_t sec)
{
fluid_real_t res;
if(sec < 0)
{
// would require a complex solution of fluid_tc2sec(), but this is real-only
return -32768.f;
}
res = (1200.f / M_LN2) * FLUID_LOGF(sec);
if(res < -32768.f)
{
res = -32768.f;
}
return res;
}
/* /*
* fluid_tc2sec_release * fluid_tc2sec_release
*/ */
@ -216,20 +250,21 @@ fluid_tc2sec_release(fluid_real_t tc)
tc = (fluid_real_t) 8000.f; tc = (fluid_real_t) 8000.f;
}; };
return FLUID_POW(2.f, tc / 1200.f); return fluid_tc2sec(tc);
}
/**
* The inverse operation, converting from Hertz to cents
*/
fluid_real_t fluid_hz2ct(fluid_real_t f)
{
return 6900.f + (1200.f / FLUID_M_LN2) * FLUID_LOGF(f / 440.0f);
} }
/* /*
* fluid_act2hz * fluid_act2hz
* *
* Convert from absolute cents to Hertz * Convert from absolute cents to Hertz
*
* The inverse operation, converting from Hertz to cents, was unused and implemented as
*
fluid_hz2ct(fluid_real_t f)
{
return 6900.f + (1200.f / FLUID_M_LN2) * FLUID_LOGF(f / 440.0f));
}
*/ */
double double
fluid_act2hz(double c) fluid_act2hz(double c)

View file

@ -27,10 +27,12 @@
fluid_real_t fluid_ct2hz_real(fluid_real_t cents); fluid_real_t fluid_ct2hz_real(fluid_real_t cents);
fluid_real_t fluid_ct2hz(fluid_real_t cents); fluid_real_t fluid_ct2hz(fluid_real_t cents);
fluid_real_t fluid_cb2amp(fluid_real_t cb); fluid_real_t fluid_cb2amp(fluid_real_t cb);
fluid_real_t fluid_sec2tc(fluid_real_t sec);
fluid_real_t fluid_tc2sec(fluid_real_t tc); fluid_real_t fluid_tc2sec(fluid_real_t tc);
fluid_real_t fluid_tc2sec_delay(fluid_real_t tc); fluid_real_t fluid_tc2sec_delay(fluid_real_t tc);
fluid_real_t fluid_tc2sec_attack(fluid_real_t tc); fluid_real_t fluid_tc2sec_attack(fluid_real_t tc);
fluid_real_t fluid_tc2sec_release(fluid_real_t tc); fluid_real_t fluid_tc2sec_release(fluid_real_t tc);
fluid_real_t fluid_hz2ct(fluid_real_t f);
double fluid_act2hz(double c); double fluid_act2hz(double c);
fluid_real_t fluid_pan(fluid_real_t c, int left); fluid_real_t fluid_pan(fluid_real_t c, int left);
fluid_real_t fluid_balance(fluid_real_t balance, int left); fluid_real_t fluid_balance(fluid_real_t balance, int left);

View file

@ -30,6 +30,7 @@ The creator: Michael Hipp (email: hippm@informatik.uni-tuebingen.de - please bot
Contributions/ideas Thomas Orgis era (includes backports from mhipp trunk): Contributions/ideas Thomas Orgis era (includes backports from mhipp trunk):
Bill Roberts <bill.roberts@arm.com>: PAC/BTI for aarch64
Dave Yeo <dave.r.yeo@gmail.com>: continued OS/2 fixing Dave Yeo <dave.r.yeo@gmail.com>: continued OS/2 fixing
madebr and manx: github mirror and CI madebr and manx: github mirror and CI
Vitaly Kirsanov <krokoziabla@gmail.com>: ports/cmake (optional CMake build) Vitaly Kirsanov <krokoziabla@gmail.com>: ports/cmake (optional CMake build)

View file

@ -38,6 +38,9 @@
/* Define if FIFO support is enabled. */ /* Define if FIFO support is enabled. */
#define FIFO 1 #define FIFO 1
/* System setup enforces 64 bit offsets where 32 bit would be native. */
/* #undef FORCED_OFF_64 */
/* Define if frame index should be used. */ /* Define if frame index should be used. */
#define FRAME_INDEX 1 #define FRAME_INDEX 1
@ -436,7 +439,7 @@
#define PACKAGE_NAME "mpg123" #define PACKAGE_NAME "mpg123"
/* Define to the full name and version of this package. */ /* Define to the full name and version of this package. */
#define PACKAGE_STRING "mpg123 1.32.7" #define PACKAGE_STRING "mpg123 1.32.9"
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "mpg123" #define PACKAGE_TARNAME "mpg123"
@ -445,7 +448,7 @@
#define PACKAGE_URL "" #define PACKAGE_URL ""
/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "1.32.7" #define PACKAGE_VERSION "1.32.9"
/* Define to only include portable library API (no off_t, no internal I/O). */ /* Define to only include portable library API (no off_t, no internal I/O). */
/* #undef PORTABLE_API */ /* #undef PORTABLE_API */
@ -477,7 +480,7 @@
/* #undef USE_YASM_FOR_AVX */ /* #undef USE_YASM_FOR_AVX */
/* Version number of package */ /* Version number of package */
#define VERSION "1.32.7" #define VERSION "1.32.9"
/* Define to use Win32 named pipes */ /* Define to use Win32 named pipes */
#define WANT_WIN32_FIFO 1 #define WANT_WIN32_FIFO 1

View file

@ -88,7 +88,7 @@ int INT123_compat_open(const char *filename, int flags)
open_fallback: open_fallback:
#endif #endif
#if (defined(WIN32) && !defined (__CYGWIN__)) #if defined(MPG123_COMPAT_MSVCRT_IO)
/* MSDN says POSIX function is deprecated beginning in Visual C++ 2005 */ /* MSDN says POSIX function is deprecated beginning in Visual C++ 2005 */
/* Try plain old _open(), if it fails, do nothing */ /* Try plain old _open(), if it fails, do nothing */
ret = _open(filename, flags|_O_BINARY, _S_IREAD | _S_IWRITE); ret = _open(filename, flags|_O_BINARY, _S_IREAD | _S_IWRITE);
@ -138,12 +138,16 @@ fopen_ok:
FILE* INT123_compat_fdopen(int fd, const char *mode) FILE* INT123_compat_fdopen(int fd, const char *mode)
{ {
#if defined(MPG123_COMPAT_MSVCRT_IO)
return _fdopen(fd, mode);
#else
return fdopen(fd, mode); return fdopen(fd, mode);
#endif
} }
int INT123_compat_close(int infd) int INT123_compat_close(int infd)
{ {
#if (defined(WIN32) && !defined (__CYGWIN__)) /* MSDN says POSIX function is deprecated beginning in Visual C++ 2005 */ #if defined(MPG123_COMPAT_MSVCRT_IO)
return _close(infd); return _close(infd);
#else #else
return close(infd); return close(infd);

View file

@ -110,7 +110,42 @@
typedef unsigned char byte; typedef unsigned char byte;
#if (defined(_UCRT) || defined(_MSC_VER) || (defined(__MINGW32__) || defined(__MINGW64__)) || (defined(__WATCOMC__) && defined(__NT__))) && !defined(__CYGWIN__)
#define MPG123_COMPAT_MSVCRT_IO
#endif
#if defined(MPG123_COMPAT_MSVCRT_IO)
#if defined(_UCRT)
// needs to get checked separately from MSVC and MinGW becuase it is also used by native Clang on Windows
#ifndef MPG123_COMPAT_MSVCRT_IO_64
#define MPG123_COMPAT_MSVCRT_IO_64
#endif
#endif
#if defined(_MSC_VER) #if defined(_MSC_VER)
#if (_MSC_VER >= 1200)
// >= VC6
#ifndef MPG123_COMPAT_MSVCRT_IO_64
#define MPG123_COMPAT_MSVCRT_IO_64
#endif
#endif
#endif
#if defined(__MINGW32__) || defined(__MINGW64__)
#if (defined(__MSVCRT__) || defined(_UCRT)) && !defined(__CRTDLL__)
#ifndef MPG123_COMPAT_MSVCRT_IO_64
#define MPG123_COMPAT_MSVCRT_IO_64
#endif
#endif
#endif
#if defined(__WATCOMC__) && defined(__NT__)
#if (__WATCOMC__ >= 1100)
#ifndef MPG123_COMPAT_MSVCRT_IO_64
#define MPG123_COMPAT_MSVCRT_IO_64
#endif
#endif
#endif
#endif
#if defined(HAVE__SETMODE) || defined(HAVE_SETMODE) || defined(MPG123_COMPAT_MSVCRT_IO)
// For _setmode(), at least. // For _setmode(), at least.
#include <io.h> #include <io.h>
#endif #endif

View file

@ -19,7 +19,7 @@
*/ */
#define MPG123_API_VERSION 48 #define MPG123_API_VERSION 48
/** library patch level at client build time */ /** library patch level at client build time */
#define MPG123_PATCHLEVEL 2 #define MPG123_PATCHLEVEL 3
#ifndef MPG123_EXPORT #ifndef MPG123_EXPORT
/** Defines needed for MS Visual Studio(tm) DLL builds. /** Defines needed for MS Visual Studio(tm) DLL builds.

View file

@ -511,6 +511,7 @@ static void frame_fixed_reset(mpg123_handle *fr)
{ {
frame_icy_reset(fr); frame_icy_reset(fr);
INT123_open_bad(fr); INT123_open_bad(fr);
memset(&(fr->hdr), 0, sizeof(fr->hdr));
fr->to_decode = FALSE; fr->to_decode = FALSE;
fr->to_ignore = FALSE; fr->to_ignore = FALSE;
fr->metaflags = 0; fr->metaflags = 0;
@ -524,15 +525,12 @@ static void frame_fixed_reset(mpg123_handle *fr)
fr->clip = 0; fr->clip = 0;
fr->oldhead = 0; fr->oldhead = 0;
fr->firsthead = 0; fr->firsthead = 0;
fr->lay = 0;
fr->vbr = MPG123_CBR; fr->vbr = MPG123_CBR;
fr->abr_rate = 0; fr->abr_rate = 0;
fr->track_frames = 0; fr->track_frames = 0;
fr->track_samples = -1; fr->track_samples = -1;
fr->framesize=0;
fr->mean_frames = 0; fr->mean_frames = 0;
fr->mean_framesize = 0; fr->mean_framesize = 0;
fr->freesize = 0;
fr->lastscale = -1; fr->lastscale = -1;
fr->rva.level[0] = -1; fr->rva.level[0] = -1;
fr->rva.level[1] = -1; fr->rva.level[1] = -1;
@ -567,8 +565,7 @@ static void frame_fixed_reset(mpg123_handle *fr)
fr->icy.next = 0; fr->icy.next = 0;
#endif #endif
fr->halfphase = 0; /* here or indeed only on first-time init? */ fr->halfphase = 0; /* here or indeed only on first-time init? */
fr->error_protection = 0; fr->hdr.freeformat_framesize = fr->p.freeformat_framesize;
fr->freeformat_framesize = fr->p.freeformat_framesize;
fr->enc_delay = -1; fr->enc_delay = -1;
fr->enc_padding = -1; fr->enc_padding = -1;
memset(fr->id3buf, 0, sizeof(fr->id3buf)); memset(fr->id3buf, 0, sizeof(fr->id3buf));
@ -627,7 +624,7 @@ int attribute_align_arg mpg123_framedata(mpg123_handle *mh, unsigned long *heade
if(header != NULL) *header = mh->oldhead; if(header != NULL) *header = mh->oldhead;
if(bodydata != NULL) *bodydata = mh->bsbuf; if(bodydata != NULL) *bodydata = mh->bsbuf;
if(bodybytes != NULL) *bodybytes = mh->framesize; if(bodybytes != NULL) *bodybytes = mh->hdr.framesize;
return MPG123_OK; return MPG123_OK;
} }
@ -900,9 +897,9 @@ static int64_t ignoreframe(mpg123_handle *fr)
{ {
int64_t preshift = fr->p.preframes; int64_t preshift = fr->p.preframes;
/* Layer 3 _really_ needs at least one frame before. */ /* Layer 3 _really_ needs at least one frame before. */
if(fr->lay==3 && preshift < 1) preshift = 1; if(fr->hdr.lay==3 && preshift < 1) preshift = 1;
/* Layer 1 & 2 reall do not need more than 2. */ /* Layer 1 & 2 reall do not need more than 2. */
if(fr->lay!=3 && preshift > 2) preshift = 2; if(fr->hdr.lay!=3 && preshift > 2) preshift = 2;
return fr->firstframe - preshift; return fr->firstframe - preshift;
} }
@ -949,7 +946,7 @@ void INT123_frame_set_frameseek(mpg123_handle *fr, int64_t fe)
void INT123_frame_skip(mpg123_handle *fr) void INT123_frame_skip(mpg123_handle *fr)
{ {
#ifndef NO_LAYER3 #ifndef NO_LAYER3
if(fr->lay == 3) INT123_set_pointer(fr, 1, 512); if(fr->hdr.lay == 3) INT123_set_pointer(fr, 1, 512);
#endif #endif
} }

View file

@ -96,6 +96,33 @@ enum frame_state_flags
,FRAME_DECODER_LIVE = 0x8 /**< 1000 Decoder can be used. */ ,FRAME_DECODER_LIVE = 0x8 /**< 1000 Decoder can be used. */
}; };
// separate frame header structure for safe decoding of headers without
// modifying the main frame struct before we are sure that we can read a
// frame into it
struct frame_header
{
int lay;
// lots of flags that could share storage, should reform that
int lsf; /* 0: MPEG 1.0; 1: MPEG 2.0/2.5 -- both used as bool and array index! */
int mpeg25;
int error_protection;
int bitrate_index;
int sampling_frequency;
int padding;
int extension;
int mode;
int mode_ext;
int copyright;
int original;
int emphasis;
// Even 16 bit int is enough for MAXFRAMESIZE
int framesize; /* computed framesize */
int freeformat;
int freeformat_framesize;
// Derived from header and checked against the above.
int ssize;
};
/* There is a lot to condense here... many ints can be merged as flags; though the main space is still consumed by buffers. */ /* There is a lot to condense here... many ints can be merged as flags; though the main space is still consumed by buffers. */
struct mpg123_handle_struct struct mpg123_handle_struct
{ {
@ -197,26 +224,12 @@ struct mpg123_handle_struct
int single; int single;
int II_sblimit; int II_sblimit;
int down_sample_sblimit; int down_sample_sblimit;
int lsf; /* 0: MPEG 1.0; 1: MPEG 2.0/2.5 -- both used as bool and array index! */
/* Many flags in disguise as integers... wasting bytes. */ /* Many flags in disguise as integers... wasting bytes. */
int mpeg25;
int down_sample; int down_sample;
int header_change; int header_change;
int lay; struct frame_header hdr;
long spf; /* cached count of samples per frame */ long spf; /* cached count of samples per frame */
int (*do_layer)(mpg123_handle *); int (*do_layer)(mpg123_handle *);
int error_protection;
int bitrate_index;
int sampling_frequency;
int padding;
int extension;
int mode;
int mode_ext;
int copyright;
int original;
int emphasis;
int framesize; /* computed framesize */
int freesize; /* free format frame size */
enum mpg123_vbr vbr; /* 1 if variable bitrate was detected */ enum mpg123_vbr vbr; /* 1 if variable bitrate was detected */
int64_t num; /* frame offset ... */ int64_t num; /* frame offset ... */
int64_t input_offset; /* byte offset of this frame in input stream */ int64_t input_offset; /* byte offset of this frame in input stream */
@ -225,8 +238,6 @@ struct mpg123_handle_struct
int state_flags; int state_flags;
char silent_resync; /* Do not complain for the next n resyncs. */ char silent_resync; /* Do not complain for the next n resyncs. */
unsigned char* xing_toc; /* The seek TOC from Xing header. */ unsigned char* xing_toc; /* The seek TOC from Xing header. */
int freeformat;
long freeformat_framesize;
/* bitstream info; bsi */ /* bitstream info; bsi */
int bitindex; int bitindex;
@ -253,7 +264,6 @@ struct mpg123_handle_struct
double mean_framesize; double mean_framesize;
int64_t mean_frames; int64_t mean_frames;
int fsizeold; int fsizeold;
int ssize;
unsigned int bitreservoir; unsigned int bitreservoir;
unsigned char bsspace[2][MAXFRAMESIZE+512+4]; /* MAXFRAMESIZE */ unsigned char bsspace[2][MAXFRAMESIZE+512+4]; /* MAXFRAMESIZE */
unsigned char *bsbuf; unsigned char *bsbuf;

View file

@ -217,7 +217,7 @@ int INT123_do_layer1(mpg123_handle *fr)
real (*fraction)[SBLIMIT] = fr->layer1.fraction; /* fraction[2][SBLIMIT] */ real (*fraction)[SBLIMIT] = fr->layer1.fraction; /* fraction[2][SBLIMIT] */
int single = fr->single; int single = fr->single;
fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext<<2)+4 : 32; fr->jsbound = (fr->hdr.mode == MPG_MD_JOINT_STEREO) ? (fr->hdr.mode_ext<<2)+4 : 32;
if(stereo == 1 || single == SINGLE_MIX) /* I don't see mixing handled here */ if(stereo == 1 || single == SINGLE_MIX) /* I don't see mixing handled here */
single = SINGLE_LEFT; single = SINGLE_LEFT;

View file

@ -313,10 +313,10 @@ static void II_select_table(mpg123_handle *fr)
const struct al_table *tables[5] = { alloc_0, alloc_1, alloc_2, alloc_3 , alloc_4 }; const struct al_table *tables[5] = { alloc_0, alloc_1, alloc_2, alloc_3 , alloc_4 };
const int sblims[5] = { 27 , 30 , 8, 12 , 30 }; const int sblims[5] = { 27 , 30 , 8, 12 , 30 };
if(fr->sampling_frequency >= 3) /* Or equivalent: (fr->lsf == 1) */ if(fr->hdr.sampling_frequency >= 3) /* Or equivalent: (fr->lsf == 1) */
table = 4; table = 4;
else else
table = translate[fr->sampling_frequency][2-fr->stereo][fr->bitrate_index]; table = translate[fr->hdr.sampling_frequency][2-fr->stereo][fr->hdr.bitrate_index];
sblim = sblims[table]; sblim = sblims[table];
fr->alloc = tables[table]; fr->alloc = tables[table];
@ -337,7 +337,7 @@ int INT123_do_layer2(mpg123_handle *fr)
int single = fr->single; int single = fr->single;
II_select_table(fr); II_select_table(fr);
fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext<<2)+4 : fr->II_sblimit; fr->jsbound = (fr->hdr.mode == MPG_MD_JOINT_STEREO) ? (fr->hdr.mode_ext<<2)+4 : fr->II_sblimit;
if(fr->jsbound > fr->II_sblimit) if(fr->jsbound > fr->II_sblimit)
{ {

View file

@ -135,16 +135,16 @@ static int III_get_side_info(mpg123_handle *fr, struct III_sideinfo *si,int ster
int powdiff = (single == SINGLE_MIX) ? 4 : 0; int powdiff = (single == SINGLE_MIX) ? 4 : 0;
const int tabs[2][5] = { { 2,9,5,3,4 } , { 1,8,1,2,9 } }; const int tabs[2][5] = { { 2,9,5,3,4 } , { 1,8,1,2,9 } };
const int *tab = tabs[fr->lsf]; const int *tab = tabs[fr->hdr.lsf];
{ /* First ensure we got enough bits available. */ { /* First ensure we got enough bits available. */
unsigned int needbits = 0; unsigned int needbits = 0;
needbits += tab[1]; /* main_data_begin */ needbits += tab[1]; /* main_data_begin */
needbits += stereo == 1 ? tab[2] : tab[3]; /* private */ needbits += stereo == 1 ? tab[2] : tab[3]; /* private */
if(!fr->lsf) if(!fr->hdr.lsf)
needbits += stereo*4; /* scfsi */ needbits += stereo*4; /* scfsi */
/* For each granule for each channel ... */ /* For each granule for each channel ... */
needbits += tab[0]*stereo*(29+tab[4]+1+22+(!fr->lsf?1:0)+2); needbits += tab[0]*stereo*(29+tab[4]+1+22+(!fr->hdr.lsf?1:0)+2);
if(fr->bits_avail < needbits) \ if(fr->bits_avail < needbits) \
{ {
if(NOQUIET) if(NOQUIET)
@ -162,7 +162,7 @@ static int III_get_side_info(mpg123_handle *fr, struct III_sideinfo *si,int ster
/* overwrite main_data_begin for the really available bit reservoir */ /* overwrite main_data_begin for the really available bit reservoir */
backbits(fr, tab[1]); backbits(fr, tab[1]);
if(fr->lsf == 0) if(fr->hdr.lsf == 0)
{ {
fr->wordpointer[0] = (unsigned char) (fr->bitreservoir >> 1); fr->wordpointer[0] = (unsigned char) (fr->bitreservoir >> 1);
fr->wordpointer[1] = (unsigned char) ((fr->bitreservoir & 1) << 7); fr->wordpointer[1] = (unsigned char) ((fr->bitreservoir & 1) << 7);
@ -171,7 +171,7 @@ static int III_get_side_info(mpg123_handle *fr, struct III_sideinfo *si,int ster
/* zero "side-info" data for a silence-frame /* zero "side-info" data for a silence-frame
without touching audio data used as bit reservoir for following frame */ without touching audio data used as bit reservoir for following frame */
memset(fr->wordpointer+2, 0, fr->ssize-2); memset(fr->wordpointer+2, 0, fr->hdr.ssize-2);
/* reread the new bit reservoir offset */ /* reread the new bit reservoir offset */
si->main_data_begin = getbits(fr, tab[1]); si->main_data_begin = getbits(fr, tab[1]);
@ -179,11 +179,11 @@ static int III_get_side_info(mpg123_handle *fr, struct III_sideinfo *si,int ster
/* Keep track of the available data bytes for the bit reservoir. /* Keep track of the available data bytes for the bit reservoir.
CRC is included in ssize already. */ CRC is included in ssize already. */
fr->bitreservoir = fr->bitreservoir + fr->framesize - fr->ssize; fr->bitreservoir = fr->bitreservoir + fr->hdr.framesize - fr->hdr.ssize;
/* Limit the reservoir to the max for MPEG 1.0 or 2.x . */ /* Limit the reservoir to the max for MPEG 1.0 or 2.x . */
if(fr->bitreservoir > (unsigned int) (fr->lsf == 0 ? 511 : 255)) if(fr->bitreservoir > (unsigned int) (fr->hdr.lsf == 0 ? 511 : 255))
fr->bitreservoir = (fr->lsf == 0 ? 511 : 255); fr->bitreservoir = (fr->hdr.lsf == 0 ? 511 : 255);
/* Now back into less commented territory. It's code. It works. */ /* Now back into less commented territory. It's code. It works. */
@ -192,7 +192,7 @@ static int III_get_side_info(mpg123_handle *fr, struct III_sideinfo *si,int ster
else else
si->private_bits = getbits(fr, tab[3]); si->private_bits = getbits(fr, tab[3]);
if(!fr->lsf) for(ch=0; ch<stereo; ch++) if(!fr->hdr.lsf) for(ch=0; ch<stereo; ch++)
{ {
si->ch[ch].gr[0].scfsi = -1; si->ch[ch].gr[0].scfsi = -1;
si->ch[ch].gr[1].scfsi = getbits(fr, 4); si->ch[ch].gr[1].scfsi = getbits(fr, 4);
@ -257,14 +257,14 @@ static int III_get_side_info(mpg123_handle *fr, struct III_sideinfo *si,int ster
} }
/* region_count/start parameters are implicit in this case. */ /* region_count/start parameters are implicit in this case. */
if( (!fr->lsf || (gr_info->block_type == 2)) && !fr->mpeg25) if( (!fr->hdr.lsf || (gr_info->block_type == 2)) && !fr->hdr.mpeg25)
{ {
gr_info->region1start = 36>>1; gr_info->region1start = 36>>1;
gr_info->region2start = 576>>1; gr_info->region2start = 576>>1;
} }
else else
{ {
if(fr->mpeg25) if(fr->hdr.mpeg25)
{ {
int r0c,r1c; int r0c,r1c;
if((gr_info->block_type == 2) && (!gr_info->mixed_block_flag) ) r0c = 5; if((gr_info->block_type == 2) && (!gr_info->mixed_block_flag) ) r0c = 5;
@ -299,7 +299,7 @@ static int III_get_side_info(mpg123_handle *fr, struct III_sideinfo *si,int ster
gr_info->block_type = 0; gr_info->block_type = 0;
gr_info->mixed_block_flag = 0; gr_info->mixed_block_flag = 0;
} }
if(!fr->lsf) gr_info->preflag = get1bit(fr); if(!fr->hdr.lsf) gr_info->preflag = get1bit(fr);
gr_info->scalefac_scale = get1bit(fr); gr_info->scalefac_scale = get1bit(fr);
gr_info->count1table_select = get1bit(fr); gr_info->count1table_select = get1bit(fr);
@ -1824,7 +1824,7 @@ int INT123_do_layer3(mpg123_handle *fr)
int stereo = fr->stereo; int stereo = fr->stereo;
int single = fr->single; int single = fr->single;
int ms_stereo,i_stereo; int ms_stereo,i_stereo;
int sfreq = fr->sampling_frequency; int sfreq = fr->hdr.sampling_frequency;
int stereo1,granules; int stereo1,granules;
if(stereo == 1) if(stereo == 1)
@ -1837,14 +1837,14 @@ int INT123_do_layer3(mpg123_handle *fr)
else else
stereo1 = 2; stereo1 = 2;
if(fr->mode == MPG_MD_JOINT_STEREO) if(fr->hdr.mode == MPG_MD_JOINT_STEREO)
{ {
ms_stereo = (fr->mode_ext & 0x2)>>1; ms_stereo = (fr->hdr.mode_ext & 0x2)>>1;
i_stereo = fr->mode_ext & 0x1; i_stereo = fr->hdr.mode_ext & 0x1;
} }
else ms_stereo = i_stereo = 0; else ms_stereo = i_stereo = 0;
granules = fr->lsf ? 1 : 2; granules = fr->hdr.lsf ? 1 : 2;
/* quick hack to keep the music playing */ /* quick hack to keep the music playing */
/* after having seen this nasty test file... */ /* after having seen this nasty test file... */
@ -1859,7 +1859,7 @@ int INT123_do_layer3(mpg123_handle *fr)
if(fr->pinfo) if(fr->pinfo)
{ {
fr->pinfo->maindata = sideinfo.main_data_begin; fr->pinfo->maindata = sideinfo.main_data_begin;
fr->pinfo->padding = fr->padding; fr->pinfo->padding = fr->hdr.padding;
} }
#endif #endif
for(gr=0;gr<granules;gr++) for(gr=0;gr<granules;gr++)
@ -1880,7 +1880,7 @@ int INT123_do_layer3(mpg123_handle *fr)
, gr_info->part2_3_length, fr->bits_avail ); , gr_info->part2_3_length, fr->bits_avail );
return clip; return clip;
} }
if(fr->lsf) if(fr->hdr.lsf)
part2bits = III_get_scale_factors_2(fr, scalefacs[0],gr_info,0); part2bits = III_get_scale_factors_2(fr, scalefacs[0],gr_info,0);
else else
part2bits = III_get_scale_factors_1(fr, scalefacs[0],gr_info,0,gr); part2bits = III_get_scale_factors_1(fr, scalefacs[0],gr_info,0,gr);
@ -1920,7 +1920,7 @@ int INT123_do_layer3(mpg123_handle *fr)
{ {
struct gr_info_s *gr_info = &(sideinfo.ch[1].gr[gr]); struct gr_info_s *gr_info = &(sideinfo.ch[1].gr[gr]);
long part2bits; long part2bits;
if(fr->lsf) if(fr->hdr.lsf)
part2bits = III_get_scale_factors_2(fr, scalefacs[1],gr_info,i_stereo); part2bits = III_get_scale_factors_2(fr, scalefacs[1],gr_info,i_stereo);
else else
part2bits = III_get_scale_factors_1(fr, scalefacs[1],gr_info,1,gr); part2bits = III_get_scale_factors_1(fr, scalefacs[1],gr_info,1,gr);
@ -1970,7 +1970,7 @@ int INT123_do_layer3(mpg123_handle *fr)
} }
} }
if(i_stereo) III_i_stereo(hybridIn,scalefacs[1],gr_info,sfreq,ms_stereo,fr->lsf); if(i_stereo) III_i_stereo(hybridIn,scalefacs[1],gr_info,sfreq,ms_stereo,fr->hdr.lsf);
if(ms_stereo || i_stereo || (single == SINGLE_MIX) ) if(ms_stereo || i_stereo || (single == SINGLE_MIX) )
{ {

View file

@ -137,7 +137,11 @@ static void wrap_io_cleanup(void *handle)
if(ioh->my_fd >= 0) if(ioh->my_fd >= 0)
{ {
mdebug("closing my fd %d", ioh->my_fd); mdebug("closing my fd %d", ioh->my_fd);
#if defined(MPG123_COMPAT_MSVCRT_IO)
_close(ioh->my_fd);
#else
close(ioh->my_fd); close(ioh->my_fd);
#endif
ioh->my_fd = -1; ioh->my_fd = -1;
} }
} }
@ -699,6 +703,35 @@ static int64_t wrap_lseek(void *handle, int64_t offset, int whence)
return -1; return -1;
} }
// Defining a wrapper to the native read to be sure the prototype matches.
// There are platforms where it is read(int, void*, unsigned int).
// We know that we read small chunks where the difference does not matter. Could
// apply specific hackery, use a common compat_read() (INT123_unintr_read()?) with system
// specifics.
static mpg123_ssize_t fallback_read(int fd, void *buf, size_t count)
{
#if defined(MPG123_COMPAT_MSVCRT_IO)
if(count > UINT_MAX)
{
errno = EOVERFLOW;
return -1;
}
return _read(fd, buf, (unsigned int)count);
#else
return read(fd, buf, count);
#endif
}
static off_t fallback_lseek(int fd, off_t offset, int whence)
{
#if defined(MPG123_COMPAT_MSVCRT_IO)
// Off_t is 32 bit and does fit into long. We know that.
return _lseek(fd, (long)offset, whence);
#else
return lseek(fd, offset, whence);
#endif
}
// This is assuming an internally opened file, which usually will be // This is assuming an internally opened file, which usually will be
// using 64 bit offsets. It keeps reading on on trivial interruptions. // using 64 bit offsets. It keeps reading on on trivial interruptions.
// I guess any file descriptor that matches the libc should work fine. // I guess any file descriptor that matches the libc should work fine.
@ -730,7 +763,7 @@ static int internal_read64(void *handle, void *buf, size_t bytes, size_t *got_by
} }
#endif #endif
errno = 0; errno = 0;
ptrdiff_t part = read(fd, (char*)buf+got, bytes); ptrdiff_t part = fallback_read(fd, (char*)buf+got, bytes);
if(part > 0) // == 0 is end of file if(part > 0) // == 0 is end of file
{ {
SATURATE_SUB(bytes, part, 0) SATURATE_SUB(bytes, part, 0)
@ -755,13 +788,15 @@ static int64_t internal_lseek64(void *handle, int64_t offset, int whence)
struct wrap_data* ioh = handle; struct wrap_data* ioh = handle;
#ifdef LFS_LARGEFILE_64 #ifdef LFS_LARGEFILE_64
return lseek64(ioh->fd, offset, whence); return lseek64(ioh->fd, offset, whence);
#elif defined(MPG123_COMPAT_MSVCRT_IO_64)
return _lseeki64(ioh->fd, offset, whence);
#else #else
if(offset < OFF_MIN || offset > OFF_MAX) if(offset < OFF_MIN || offset > OFF_MAX)
{ {
errno = EOVERFLOW; errno = EOVERFLOW;
return -1; return -1;
} }
return lseek(ioh->fd, (off_t)offset, whence); return fallback_lseek(ioh->fd, (off_t)offset, whence);
#endif #endif
} }
@ -861,16 +896,6 @@ int INT123_wrap_open(mpg123_handle *mh, void *handle, const char *path, int fd,
// So, native off_t reader replacement. // So, native off_t reader replacement.
// Defining a wrapper to the native read to be sure the prototype matches.
// There are platforms where it is read(int, void*, unsigned int).
// We know that we read small chunks where the difference does not matter. Could
// apply specific hackery, use a common compat_read() (INT123_unintr_read()?) with system
// specifics.
static mpg123_ssize_t fallback_read(int fd, void *buf, size_t count)
{
return read(fd, buf, count);
}
// In forced 64 bit offset mode, the only definitions of these are // In forced 64 bit offset mode, the only definitions of these are
// the _64 ones. // the _64 ones.
#ifdef FORCED_OFF_64 #ifdef FORCED_OFF_64
@ -902,7 +927,7 @@ int attribute_align_arg mpg123_replace_reader(mpg123_handle *mh, mpg123_ssize_t
ioh->iotype = IO_FD; ioh->iotype = IO_FD;
ioh->fd = -1; /* On next mpg123_open_fd(), this gets a value. */ ioh->fd = -1; /* On next mpg123_open_fd(), this gets a value. */
ioh->r_read = r_read != NULL ? r_read : fallback_read; ioh->r_read = r_read != NULL ? r_read : fallback_read;
ioh->r_lseek = r_lseek != NULL ? (void *)r_lseek : (void *)lseek; ioh->r_lseek = r_lseek != NULL ? r_lseek : fallback_lseek;
} }
/* The real reader replacement will happen while opening. */ /* The real reader replacement will happen while opening. */

View file

@ -457,7 +457,7 @@ int attribute_align_arg mpg123_getstate(mpg123_handle *mh, enum mpg123_state key
theval = mh->enc_padding; theval = mh->enc_padding;
break; break;
case MPG123_DEC_DELAY: case MPG123_DEC_DELAY:
theval = mh->lay == 3 ? GAPLESS_DELAY : -1; theval = mh->hdr.lay == 3 ? GAPLESS_DELAY : -1;
break; break;
default: default:
mh->err = MPG123_BAD_KEY; mh->err = MPG123_BAD_KEY;
@ -1241,10 +1241,10 @@ static int init_track(mpg123_handle *mh)
b = init_track(mh); \ b = init_track(mh); \
if(b < 0) return b; \ if(b < 0) return b; \
\ \
mi->version = mh->mpeg25 ? MPG123_2_5 : (mh->lsf ? MPG123_2_0 : MPG123_1_0); \ mi->version = mh->hdr.mpeg25 ? MPG123_2_5 : (mh->hdr.lsf ? MPG123_2_0 : MPG123_1_0); \
mi->layer = mh->lay; \ mi->layer = mh->hdr.lay; \
mi->rate = INT123_frame_freq(mh); \ mi->rate = INT123_frame_freq(mh); \
switch(mh->mode) \ switch(mh->hdr.mode) \
{ \ { \
case 0: mi->mode = MPG123_M_STEREO; break; \ case 0: mi->mode = MPG123_M_STEREO; break; \
case 1: mi->mode = MPG123_M_JOINT; break; \ case 1: mi->mode = MPG123_M_JOINT; break; \
@ -1252,14 +1252,14 @@ static int init_track(mpg123_handle *mh)
case 3: mi->mode = MPG123_M_MONO; break; \ case 3: mi->mode = MPG123_M_MONO; break; \
default: mi->mode = 0; /* Nothing good to do here. */ \ default: mi->mode = 0; /* Nothing good to do here. */ \
} \ } \
mi->mode_ext = mh->mode_ext; \ mi->mode_ext = mh->hdr.mode_ext; \
mi->framesize = mh->framesize+4; /* Include header. */ \ mi->framesize = mh->hdr.framesize+4; /* Include header. */ \
mi->flags = 0; \ mi->flags = 0; \
if(mh->error_protection) mi->flags |= MPG123_CRC; \ if(mh->hdr.error_protection) mi->flags |= MPG123_CRC; \
if(mh->copyright) mi->flags |= MPG123_COPYRIGHT; \ if(mh->hdr.copyright) mi->flags |= MPG123_COPYRIGHT; \
if(mh->extension) mi->flags |= MPG123_PRIVATE; \ if(mh->hdr.extension) mi->flags |= MPG123_PRIVATE; \
if(mh->original) mi->flags |= MPG123_ORIGINAL; \ if(mh->hdr.original) mi->flags |= MPG123_ORIGINAL; \
mi->emphasis = mh->emphasis; \ mi->emphasis = mh->hdr.emphasis; \
mi->bitrate = INT123_frame_bitrate(mh); \ mi->bitrate = INT123_frame_bitrate(mh); \
mi->abr_rate = mh->abr_rate; \ mi->abr_rate = mh->abr_rate; \
mi->vbr = mh->vbr; \ mi->vbr = mh->vbr; \

View file

@ -63,9 +63,10 @@ static const int tabsel_123[2][3][16] =
static const long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 }; static const long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 };
static int decode_header(mpg123_handle *fr,unsigned long newhead, int *freeformat_count); static int decode_header(mpg123_handle *fr, struct frame_header *hdr, unsigned long newhead, int *freeformat_count);
static int skip_junk(mpg123_handle *fr, unsigned long *newheadp, long *headcount); static void apply_header(mpg123_handle *fr, struct frame_header *hdr);
static int do_readahead(mpg123_handle *fr, unsigned long newhead); static int skip_junk(mpg123_handle *fr, unsigned long *newheadp, long *headcount, struct frame_header *nhdr);
static int do_readahead(mpg123_handle *fr, struct frame_header *nhdr, unsigned long newhead);
static int wetwork(mpg123_handle *fr, unsigned long *newheadp); static int wetwork(mpg123_handle *fr, unsigned long *newheadp);
/* These two are to be replaced by one function that gives all the frame parameters (for outsiders).*/ /* These two are to be replaced by one function that gives all the frame parameters (for outsiders).*/
@ -73,12 +74,12 @@ static int wetwork(mpg123_handle *fr, unsigned long *newheadp);
int INT123_frame_bitrate(mpg123_handle *fr) int INT123_frame_bitrate(mpg123_handle *fr)
{ {
return tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index]; return tabsel_123[fr->hdr.lsf][fr->hdr.lay-1][fr->hdr.bitrate_index];
} }
long INT123_frame_freq(mpg123_handle *fr) long INT123_frame_freq(mpg123_handle *fr)
{ {
return freqs[fr->sampling_frequency]; return freqs[fr->hdr.sampling_frequency];
} }
/* compiler is smart enought to inline this one or should I really do it as macro...? */ /* compiler is smart enought to inline this one or should I really do it as macro...? */
@ -141,8 +142,8 @@ static int check_lame_tag(mpg123_handle *fr)
Mono 17 9 Mono 17 9
*/ */
int lame_offset = (fr->stereo == 2) int lame_offset = (fr->stereo == 2)
? (fr->lsf ? 17 : 32) ? (fr->hdr.lsf ? 17 : 32)
: (fr->lsf ? 9 : 17); : (fr->hdr.lsf ? 9 : 17);
if(fr->p.flags & MPG123_IGNORE_INFOFRAME) goto check_lame_tag_no; if(fr->p.flags & MPG123_IGNORE_INFOFRAME) goto check_lame_tag_no;
@ -154,7 +155,7 @@ static int check_lame_tag(mpg123_handle *fr)
for the actual data, have to check if each byte of information is present. for the actual data, have to check if each byte of information is present.
But: 4 B Info/Xing + 4 B flags is bare minimum. But: 4 B Info/Xing + 4 B flags is bare minimum.
*/ */
if(fr->framesize < lame_offset+8) goto check_lame_tag_no; if(fr->hdr.framesize < lame_offset+8) goto check_lame_tag_no;
/* only search for tag when all zero before it (apart from checksum) */ /* only search for tag when all zero before it (apart from checksum) */
for(i=2; i < lame_offset; ++i) if(fr->bsbuf[i] != 0) goto check_lame_tag_no; for(i=2; i < lame_offset; ++i) if(fr->bsbuf[i] != 0) goto check_lame_tag_no;
@ -190,7 +191,7 @@ static int check_lame_tag(mpg123_handle *fr)
/* From now on, I have to carefully check if the announced data is actually /* From now on, I have to carefully check if the announced data is actually
there! I'm always returning 'yes', though. */ there! I'm always returning 'yes', though. */
#define check_bytes_left(n) if(fr->framesize < lame_offset+n) \ #define check_bytes_left(n) if(fr->hdr.framesize < lame_offset+n) \
goto check_lame_tag_yes goto check_lame_tag_yes
if(xing_flags & 1) /* total bitstream frames */ if(xing_flags & 1) /* total bitstream frames */
{ {
@ -443,10 +444,10 @@ static int head_compatible(unsigned long fred, unsigned long bret)
static void halfspeed_prepare(mpg123_handle *fr) static void halfspeed_prepare(mpg123_handle *fr)
{ {
/* save for repetition */ /* save for repetition */
if(fr->p.halfspeed && fr->lay == 3) if(fr->p.halfspeed && fr->hdr.lay == 3)
{ {
debug("halfspeed - reusing old bsbuf "); debug("halfspeed - reusing old bsbuf ");
memcpy (fr->ssave, fr->bsbuf, fr->ssize); memcpy (fr->ssave, fr->bsbuf, fr->hdr.ssize);
} }
} }
@ -462,8 +463,8 @@ static int halfspeed_do(mpg123_handle *fr)
fr->to_decode = fr->to_ignore = TRUE; fr->to_decode = fr->to_ignore = TRUE;
--fr->halfphase; --fr->halfphase;
INT123_set_pointer(fr, 0, 0); INT123_set_pointer(fr, 0, 0);
if(fr->lay == 3) memcpy (fr->bsbuf, fr->ssave, fr->ssize); if(fr->hdr.lay == 3) memcpy (fr->bsbuf, fr->ssave, fr->hdr.ssize);
if(fr->error_protection) fr->crc = getbits(fr, 16); /* skip crc */ if(fr->hdr.error_protection) fr->crc = getbits(fr, 16); /* skip crc */
return 1; return 1;
} }
else else
@ -496,10 +497,11 @@ int INT123_read_frame(mpg123_handle *fr)
/* TODO: rework this thing */ /* TODO: rework this thing */
int freeformat_count = 0; int freeformat_count = 0;
unsigned long newhead; unsigned long newhead;
// Start with current frame header state as copy for roll-back ability.
struct frame_header nhdr = fr->hdr;
int64_t framepos; int64_t framepos;
int ret; int ret;
/* stuff that needs resetting if complete frame reading fails */ /* stuff that needs resetting if complete frame reading fails */
int oldsize = fr->framesize;
int oldphase = fr->halfphase; int oldphase = fr->halfphase;
/* The counter for the search-first-header loop. /* The counter for the search-first-header loop.
@ -507,11 +509,12 @@ int INT123_read_frame(mpg123_handle *fr)
when repeatedly headers are found that do not have valid followup headers. */ when repeatedly headers are found that do not have valid followup headers. */
long headcount = 0; long headcount = 0;
fr->fsizeold=fr->framesize; /* for Layer3 */ fr->fsizeold=fr->hdr.framesize; /* for Layer3 */
if(halfspeed_do(fr) == 1) return 1; if(halfspeed_do(fr) == 1) return 1;
/* From now on, old frame data is tainted by parsing attempts. */ /* From now on, old frame data is tainted by parsing attempts. */
// Handling premature effects of decode_header now, more decoupling would be welcome.
fr->to_decode = fr->to_ignore = FALSE; fr->to_decode = fr->to_ignore = FALSE;
if( fr->p.flags & MPG123_NO_FRANKENSTEIN && if( fr->p.flags & MPG123_NO_FRANKENSTEIN &&
@ -540,13 +543,13 @@ init_resync:
#ifdef SKIP_JUNK #ifdef SKIP_JUNK
if(!fr->firsthead && !head_check(newhead)) if(!fr->firsthead && !head_check(newhead))
{ {
ret = skip_junk(fr, &newhead, &headcount); ret = skip_junk(fr, &newhead, &headcount, &nhdr);
JUMP_CONCLUSION(ret); JUMP_CONCLUSION(ret);
} }
#endif #endif
ret = head_check(newhead); ret = head_check(newhead);
if(ret) ret = decode_header(fr, newhead, &freeformat_count); if(ret) ret = decode_header(fr, &nhdr, newhead, &freeformat_count);
JUMP_CONCLUSION(ret); /* That only continues for ret == PARSE_BAD or PARSE_GOOD. */ JUMP_CONCLUSION(ret); /* That only continues for ret == PARSE_BAD or PARSE_GOOD. */
if(ret == PARSE_BAD) if(ret == PARSE_BAD)
@ -561,7 +564,7 @@ init_resync:
{ {
ret = fr->p.flags & MPG123_NO_READAHEAD ret = fr->p.flags & MPG123_NO_READAHEAD
? PARSE_GOOD ? PARSE_GOOD
: do_readahead(fr, newhead); : do_readahead(fr, &nhdr, newhead);
/* readahead can fail mit NEED_MORE, in which case we must also make the just read header available again for next go */ /* readahead can fail mit NEED_MORE, in which case we must also make the just read header available again for next go */
if(ret < 0) fr->rd->back_bytes(fr, 4); if(ret < 0) fr->rd->back_bytes(fr, 4);
JUMP_CONCLUSION(ret); JUMP_CONCLUSION(ret);
@ -585,8 +588,8 @@ init_resync:
{ {
unsigned char *newbuf = fr->bsspace[fr->bsnum]+512; unsigned char *newbuf = fr->bsspace[fr->bsnum]+512;
/* read main data into memory */ /* read main data into memory */
debug2("read frame body of %i at %"PRIi64, fr->framesize, framepos+4); debug2("read frame body of %i at %"PRIi64, nhdr.framesize, framepos+4);
if((ret=fr->rd->read_frame_body(fr,newbuf,fr->framesize))<0) if((ret=fr->rd->read_frame_body(fr,newbuf,nhdr.framesize))<0)
{ {
/* if failed: flip back */ /* if failed: flip back */
debug1("%s", ret == MPG123_NEED_MORE ? "need more" : "read error"); debug1("%s", ret == MPG123_NEED_MORE ? "need more" : "read error");
@ -597,6 +600,10 @@ init_resync:
} }
fr->bsnum = (fr->bsnum + 1) & 1; fr->bsnum = (fr->bsnum + 1) & 1;
// We read the frame body, time to apply the matching header.
// Even if erroring out later, the header state needs to match the body.
apply_header(fr, &nhdr);
if(!fr->firsthead) if(!fr->firsthead)
{ {
fr->firsthead = newhead; /* _now_ it's time to store it... the first real header */ fr->firsthead = newhead; /* _now_ it's time to store it... the first real header */
@ -608,7 +615,7 @@ init_resync:
fr->audio_start = framepos; fr->audio_start = framepos;
/* Only check for LAME tag at beginning of whole stream /* Only check for LAME tag at beginning of whole stream
... when there indeed is one in between, it's the user's problem. */ ... when there indeed is one in between, it's the user's problem. */
if(fr->lay == 3 && check_lame_tag(fr) == 1) if(fr->hdr.lay == 3 && check_lame_tag(fr) == 1)
{ /* ...in practice, Xing/LAME tags are layer 3 only. */ { /* ...in practice, Xing/LAME tags are layer 3 only. */
if(fr->rd->forget != NULL) fr->rd->forget(fr); if(fr->rd->forget != NULL) fr->rd->forget(fr);
@ -624,6 +631,8 @@ init_resync:
INT123_set_pointer(fr, 0, 0); INT123_set_pointer(fr, 0, 0);
// No use of nhdr from here on. It is fr->hdr now!
/* Question: How bad does the floating point value get with repeated recomputation? /* Question: How bad does the floating point value get with repeated recomputation?
Also, considering that we can play the file or parts of many times. */ Also, considering that we can play the file or parts of many times. */
if(++fr->mean_frames != 0) if(++fr->mean_frames != 0)
@ -631,7 +640,7 @@ init_resync:
fr->mean_framesize = ((fr->mean_frames-1)*fr->mean_framesize+INT123_compute_bpf(fr)) / fr->mean_frames ; fr->mean_framesize = ((fr->mean_frames-1)*fr->mean_framesize+INT123_compute_bpf(fr)) / fr->mean_frames ;
} }
++fr->num; /* 0 for first frame! */ ++fr->num; /* 0 for first frame! */
debug4("Frame %"PRIi64" %08lx %i, next filepos=%"PRIi64, fr->num, newhead, fr->framesize, fr->rd->tell(fr)); debug4("Frame %"PRIi64" %08lx %i, next filepos=%"PRIi64, fr->num, newhead, fr->hdr.framesize, fr->rd->tell(fr));
if(!(fr->state_flags & FRAME_FRANKENSTEIN) && ( if(!(fr->state_flags & FRAME_FRANKENSTEIN) && (
(fr->track_frames > 0 && fr->num >= fr->track_frames) (fr->track_frames > 0 && fr->num >= fr->track_frames)
#ifdef GAPLESS #ifdef GAPLESS
@ -665,7 +674,7 @@ init_resync:
if(fr->rd->forget != NULL) fr->rd->forget(fr); if(fr->rd->forget != NULL) fr->rd->forget(fr);
fr->to_decode = fr->to_ignore = TRUE; fr->to_decode = fr->to_ignore = TRUE;
if(fr->error_protection) fr->crc = getbits(fr, 16); /* skip crc */ if(fr->hdr.error_protection) fr->crc = getbits(fr, 16); /* skip crc */
/* /*
Let's check for header change after deciding that the new one is good Let's check for header change after deciding that the new one is good
@ -712,7 +721,6 @@ read_frame_bad:
fr->silent_resync = 0; fr->silent_resync = 0;
if(fr->err == MPG123_OK) fr->err = MPG123_ERR_READER; if(fr->err == MPG123_OK) fr->err = MPG123_ERR_READER;
fr->framesize = oldsize;
fr->halfphase = oldphase; fr->halfphase = oldphase;
/* That return code might be inherited from some feeder action, or reader error. */ /* That return code might be inherited from some feeder action, or reader error. */
return ret; return ret;
@ -726,9 +734,9 @@ read_frame_bad:
* <0: error codes, possibly from feeder buffer (NEED_MORE) * <0: error codes, possibly from feeder buffer (NEED_MORE)
* PARSE_BAD: cannot get the framesize for some reason and shall silentry try the next possible header (if this is no free format stream after all...) * PARSE_BAD: cannot get the framesize for some reason and shall silentry try the next possible header (if this is no free format stream after all...)
*/ */
static int guess_freeformat_framesize(mpg123_handle *fr, unsigned long oldhead) static int guess_freeformat_framesize(mpg123_handle *fr, unsigned long oldhead, int *framesize)
{ {
long i; int i;
int ret; int ret;
unsigned long head; unsigned long head;
if(!(fr->rdat.flags & (READER_SEEKABLE|READER_BUFFERED))) if(!(fr->rdat.flags & (READER_SEEKABLE|READER_BUFFERED)))
@ -749,7 +757,7 @@ static int guess_freeformat_framesize(mpg123_handle *fr, unsigned long oldhead)
if((head & HDR_SAMEMASK) == (oldhead & HDR_SAMEMASK)) if((head & HDR_SAMEMASK) == (oldhead & HDR_SAMEMASK))
{ {
fr->rd->back_bytes(fr,i+1); fr->rd->back_bytes(fr,i+1);
fr->framesize = i-3; *framesize = i-3;
return PARSE_GOOD; /* Success! */ return PARSE_GOOD; /* Success! */
} }
} }
@ -766,8 +774,13 @@ static int guess_freeformat_framesize(mpg123_handle *fr, unsigned long oldhead)
* 0: no valid header * 0: no valid header
* <0: some error * <0: some error
* You are required to do a head_check() before calling! * You are required to do a head_check() before calling!
*
* This now only operates on a frame header struct, not the full frame structure.
* The scope is limited to parsing header information and determining the size of
* the frame body to read. Everything else belongs into a later stage of applying
* header information to the main decoder frame structure.
*/ */
static int decode_header(mpg123_handle *fr,unsigned long newhead, int *freeformat_count) static int decode_header(mpg123_handle *fr, struct frame_header *fh, unsigned long newhead, int *freeformat_count)
{ {
#ifdef DEBUG /* Do not waste cycles checking the header twice all the time. */ #ifdef DEBUG /* Do not waste cycles checking the header twice all the time. */
if(!head_check(newhead)) if(!head_check(newhead))
@ -778,43 +791,42 @@ static int decode_header(mpg123_handle *fr,unsigned long newhead, int *freeforma
/* For some reason, the layer and sampling freq settings used to be wrapped /* For some reason, the layer and sampling freq settings used to be wrapped
in a weird conditional including MPG123_NO_RESYNC. What was I thinking? in a weird conditional including MPG123_NO_RESYNC. What was I thinking?
This information has to be consistent. */ This information has to be consistent. */
fr->lay = 4 - HDR_LAYER_VAL(newhead); fh->lay = 4 - HDR_LAYER_VAL(newhead);
if(HDR_VERSION_VAL(newhead) & 0x2) if(HDR_VERSION_VAL(newhead) & 0x2)
{ {
fr->lsf = (HDR_VERSION_VAL(newhead) & 0x1) ? 0 : 1; fh->lsf = (HDR_VERSION_VAL(newhead) & 0x1) ? 0 : 1;
fr->mpeg25 = 0; fh->mpeg25 = 0;
fr->sampling_frequency = HDR_SAMPLERATE_VAL(newhead) + (fr->lsf*3); fh->sampling_frequency = HDR_SAMPLERATE_VAL(newhead) + (fh->lsf*3);
} }
else else
{ {
fr->lsf = 1; fh->lsf = 1;
fr->mpeg25 = 1; fh->mpeg25 = 1;
fr->sampling_frequency = 6 + HDR_SAMPLERATE_VAL(newhead); fh->sampling_frequency = 6 + HDR_SAMPLERATE_VAL(newhead);
} }
#ifdef DEBUG #ifdef DEBUG
/* seen a file where this varies (old lame tag without crc, track with crc) */ /* seen a file where this varies (old lame tag without crc, track with crc) */
if((HDR_CRC_VAL(newhead)^0x1) != fr->error_protection) debug("changed crc bit!"); if((HDR_CRC_VAL(newhead)^0x1) != fh->error_protection) debug("changed crc bit!");
#endif #endif
fr->error_protection = HDR_CRC_VAL(newhead)^0x1; fh->error_protection = HDR_CRC_VAL(newhead)^0x1;
fr->bitrate_index = HDR_BITRATE_VAL(newhead); fh->bitrate_index = HDR_BITRATE_VAL(newhead);
fr->padding = HDR_PADDING_VAL(newhead); fh->padding = HDR_PADDING_VAL(newhead);
fr->extension = HDR_PRIVATE_VAL(newhead); fh->extension = HDR_PRIVATE_VAL(newhead);
fr->mode = HDR_CHANNEL_VAL(newhead); fh->mode = HDR_CHANNEL_VAL(newhead);
fr->mode_ext = HDR_CHANEX_VAL(newhead); fh->mode_ext = HDR_CHANEX_VAL(newhead);
fr->copyright = HDR_COPYRIGHT_VAL(newhead); fh->copyright = HDR_COPYRIGHT_VAL(newhead);
fr->original = HDR_ORIGINAL_VAL(newhead); fh->original = HDR_ORIGINAL_VAL(newhead);
fr->emphasis = HDR_EMPHASIS_VAL(newhead); fh->emphasis = HDR_EMPHASIS_VAL(newhead);
fr->freeformat = !(newhead & HDR_BITRATE); fh->freeformat = !(newhead & HDR_BITRATE);
fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2;
/* we can't use tabsel_123 for freeformat, so trying to guess framesize... */ /* we can't use tabsel_123 for freeformat, so trying to guess framesize... */
if(fr->freeformat) if(fh->freeformat)
{ {
/* when we first encounter the frame with freeformat, guess framesize */ /* when we first encounter the frame with freeformat, guess framesize */
if(fr->freeformat_framesize < 0) if(fh->freeformat_framesize < 0)
{ {
int ret; int ret;
if(fr->p.flags & MPG123_NO_READAHEAD) if(fr->p.flags & MPG123_NO_READAHEAD)
@ -829,12 +841,12 @@ static int decode_header(mpg123_handle *fr,unsigned long newhead, int *freeforma
if(VERBOSE3) error("You fooled me too often. Refusing to guess free format frame size _again_."); if(VERBOSE3) error("You fooled me too often. Refusing to guess free format frame size _again_.");
return PARSE_BAD; return PARSE_BAD;
} }
ret = guess_freeformat_framesize(fr, newhead); ret = guess_freeformat_framesize(fr, newhead, &(fh->framesize));
if(ret == PARSE_GOOD) if(ret == PARSE_GOOD)
{ {
fr->freeformat_framesize = fr->framesize - fr->padding; fh->freeformat_framesize = fh->framesize - fh->padding;
if(VERBOSE2) if(VERBOSE2)
fprintf(stderr, "Note: free format frame size %li\n", fr->freeformat_framesize); fprintf(stderr, "Note: free format frame size %i\n", fh->freeformat_framesize);
} }
else else
{ {
@ -849,81 +861,109 @@ static int decode_header(mpg123_handle *fr,unsigned long newhead, int *freeforma
/* freeformat should be CBR, so the same framesize can be used at the 2nd reading or later */ /* freeformat should be CBR, so the same framesize can be used at the 2nd reading or later */
else else
{ {
fr->framesize = fr->freeformat_framesize + fr->padding; fh->framesize = fh->freeformat_framesize + fh->padding;
} }
} }
switch(fh->lay)
{
#ifndef NO_LAYER1
case 1:
if(!fh->freeformat)
{
long fs = (long) tabsel_123[fh->lsf][0][fh->bitrate_index] * 12000;
fs /= freqs[fh->sampling_frequency];
fs = ((fs+fh->padding)<<2)-4;
fh->framesize = (int)fs;
}
break;
#endif
#ifndef NO_LAYER2
case 2:
if(!fh->freeformat)
{
debug2("bitrate index: %i (%i)", fh->bitrate_index, tabsel_123[fh->lsf][1][fh->bitrate_index] );
long fs = (long) tabsel_123[fh->lsf][1][fh->bitrate_index] * 144000;
fs /= freqs[fh->sampling_frequency];
fs += fh->padding - 4;
fh->framesize = (int)fs;
}
break;
#endif
#ifndef NO_LAYER3
case 3:
if(fh->lsf)
fh->ssize = (fh->mode == MPG_MD_MONO) ? 9 : 17;
else
fh->ssize = (fh->mode == MPG_MD_MONO) ? 17 : 32;
switch(fr->lay) if(fh->error_protection)
fh->ssize += 2;
if(!fh->freeformat)
{
long fs = (long) tabsel_123[fh->lsf][2][fh->bitrate_index] * 144000;
fs /= freqs[fh->sampling_frequency]<<(fh->lsf);
fs += fh->padding - 4;
fh->framesize = fs;
}
if(fh->framesize < fh->ssize)
{
if(NOQUIET)
error2( "Frame smaller than mandatory side info (%i < %i)!"
, fh->framesize, fh->ssize );
return PARSE_BAD;
}
break;
#endif
default:
if(NOQUIET) error1("Layer type %i not supported in this build!", fh->lay);
return PARSE_BAD;
}
if (fh->framesize > MAXFRAMESIZE)
{
if(NOQUIET) error1("Frame size too big: %d", fh->framesize+4-fh->padding);
return PARSE_BAD;
}
return PARSE_GOOD;
}
// Apply decoded header structure to frame struct, including
// main decoder function pointer.
static void apply_header(mpg123_handle *fr, struct frame_header *hdr)
{
// copy the whole struct, do some postprocessing
fr->hdr = *hdr;
fr->stereo = (fr->hdr.mode == MPG_MD_MONO) ? 1 : 2;
switch(fr->hdr.lay)
{ {
#ifndef NO_LAYER1 #ifndef NO_LAYER1
case 1: case 1:
fr->spf = 384; fr->spf = 384;
fr->do_layer = INT123_do_layer1; fr->do_layer = INT123_do_layer1;
if(!fr->freeformat)
{
long fs = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000;
fs /= freqs[fr->sampling_frequency];
fs = ((fs+fr->padding)<<2)-4;
fr->framesize = (int)fs;
}
break; break;
#endif #endif
#ifndef NO_LAYER2 #ifndef NO_LAYER2
case 2: case 2:
fr->spf = 1152; fr->spf = 1152;
fr->do_layer = INT123_do_layer2; fr->do_layer = INT123_do_layer2;
if(!fr->freeformat)
{
debug2("bitrate index: %i (%i)", fr->bitrate_index, tabsel_123[fr->lsf][1][fr->bitrate_index] );
long fs = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000;
fs /= freqs[fr->sampling_frequency];
fs += fr->padding - 4;
fr->framesize = (int)fs;
}
break; break;
#endif #endif
#ifndef NO_LAYER3 #ifndef NO_LAYER3
case 3: case 3:
fr->spf = fr->lsf ? 576 : 1152; /* MPEG 2.5 implies LSF.*/ fr->spf = fr->hdr.lsf ? 576 : 1152; /* MPEG 2.5 implies LSF.*/
fr->do_layer = INT123_do_layer3; fr->do_layer = INT123_do_layer3;
if(fr->lsf) #endif
fr->ssize = (fr->stereo == 1) ? 9 : 17;
else
fr->ssize = (fr->stereo == 1) ? 17 : 32;
if(fr->error_protection)
fr->ssize += 2;
if(!fr->freeformat)
{
long fs = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000;
fs /= freqs[fr->sampling_frequency]<<(fr->lsf);
fs += fr->padding - 4;
fr->framesize = fs;
}
if(fr->framesize < fr->ssize)
{
if(NOQUIET)
error2( "Frame smaller than mandatory side info (%i < %i)!"
, fr->framesize, fr->ssize );
return PARSE_BAD;
}
break; break;
#endif
default: default:
if(NOQUIET) error1("Layer type %i not supported in this build!", fr->lay); // No error checking/message here, been done in decode_header().
fr->spf = 0;
return PARSE_BAD; fr->do_layer = NULL;
} }
if (fr->framesize > MAXFRAMESIZE)
{
if(NOQUIET) error1("Frame size too big: %d", fr->framesize+4-fr->padding);
return PARSE_BAD;
}
return PARSE_GOOD;
} }
/* Prepare for bit reading. Two stages: /* Prepare for bit reading. Two stages:
0. Layers 1 and 2, side info for layer 3 0. Layers 1 and 2, side info for layer 3
1. Second call for possible bit reservoir for layer 3 part 2,3. 1. Second call for possible bit reservoir for layer 3 part 2,3.
@ -935,26 +975,26 @@ static int decode_header(mpg123_handle *fr,unsigned long newhead, int *freeforma
void INT123_set_pointer(mpg123_handle *fr, int part2, long backstep) void INT123_set_pointer(mpg123_handle *fr, int part2, long backstep)
{ {
fr->bitindex = 0; fr->bitindex = 0;
if(fr->lay == 3) if(fr->hdr.lay == 3)
{ {
if(part2) if(part2)
{ {
fr->wordpointer = fr->bsbuf + fr->ssize - backstep; fr->wordpointer = fr->bsbuf + fr->hdr.ssize - backstep;
if(backstep) if(backstep)
memcpy( fr->wordpointer, fr->bsbufold+fr->fsizeold-backstep memcpy( fr->wordpointer, fr->bsbufold+fr->fsizeold-backstep
, backstep ); , backstep );
fr->bits_avail = (long)(fr->framesize - fr->ssize + backstep)*8; fr->bits_avail = (long)(fr->hdr.framesize - fr->hdr.ssize + backstep)*8;
} }
else else
{ {
fr->wordpointer = fr->bsbuf; fr->wordpointer = fr->bsbuf;
fr->bits_avail = fr->ssize*8; fr->bits_avail = fr->hdr.ssize*8;
} }
} }
else else
{ {
fr->wordpointer = fr->bsbuf; fr->wordpointer = fr->bsbuf;
fr->bits_avail = fr->framesize*8; fr->bits_avail = fr->hdr.framesize*8;
} }
} }
@ -962,7 +1002,7 @@ void INT123_set_pointer(mpg123_handle *fr, int part2, long backstep)
double INT123_compute_bpf(mpg123_handle *fr) double INT123_compute_bpf(mpg123_handle *fr)
{ {
return (fr->framesize > 0) ? fr->framesize + 4.0 : 1.0; return (fr->hdr.framesize > 0) ? fr->hdr.framesize + 4.0 : 1.0;
} }
int attribute_align_arg mpg123_spf(mpg123_handle *mh) int attribute_align_arg mpg123_spf(mpg123_handle *mh)
@ -978,8 +1018,8 @@ double attribute_align_arg mpg123_tpf(mpg123_handle *fr)
double tpf; double tpf;
if(fr == NULL || !fr->firsthead) return MPG123_ERR; if(fr == NULL || !fr->firsthead) return MPG123_ERR;
tpf = (double) bs[fr->lay]; tpf = (double) bs[fr->hdr.lay];
tpf /= freqs[fr->sampling_frequency] << (fr->lsf); tpf /= freqs[fr->hdr.sampling_frequency] << (fr->hdr.lsf);
return tpf; return tpf;
} }
@ -1046,7 +1086,7 @@ int attribute_align_arg mpg123_position64(mpg123_handle *fr, int64_t no, int64_t
} }
/* first attempt of read ahead check to find the real first header; cannot believe what junk is out there! */ /* first attempt of read ahead check to find the real first header; cannot believe what junk is out there! */
static int do_readahead(mpg123_handle *fr, unsigned long newhead) static int do_readahead(mpg123_handle *fr, struct frame_header *nhdr, unsigned long newhead)
{ {
unsigned long nexthead = 0; unsigned long nexthead = 0;
int hd = 0; int hd = 0;
@ -1058,9 +1098,9 @@ static int do_readahead(mpg123_handle *fr, unsigned long newhead)
start = fr->rd->tell(fr); start = fr->rd->tell(fr);
debug2("doing ahead check with BPF %d at %"PRIi64, fr->framesize+4, start); debug2("doing ahead check with BPF %d at %"PRIi64, nhdr->framesize+4, start);
/* step framesize bytes forward and read next possible header*/ /* step framesize bytes forward and read next possible header*/
if((oret=fr->rd->skip_bytes(fr, fr->framesize))<0) if((oret=fr->rd->skip_bytes(fr, nhdr->framesize))<0)
{ {
if(oret==READER_ERROR && NOQUIET) error("cannot seek!"); if(oret==READER_ERROR && NOQUIET) error("cannot seek!");
@ -1195,7 +1235,7 @@ static int forget_head_shift(mpg123_handle *fr, unsigned long *newheadp, int for
} }
/* watch out for junk/tags on beginning of stream by invalid header */ /* watch out for junk/tags on beginning of stream by invalid header */
static int skip_junk(mpg123_handle *fr, unsigned long *newheadp, long *headcount) static int skip_junk(mpg123_handle *fr, unsigned long *newheadp, long *headcount, struct frame_header *nhdr)
{ {
int ret; int ret;
int freeformat_count = 0; int freeformat_count = 0;
@ -1251,7 +1291,7 @@ static int skip_junk(mpg123_handle *fr, unsigned long *newheadp, long *headcount
if(++forgetcount > FORGET_INTERVAL) forgetcount = 0; if(++forgetcount > FORGET_INTERVAL) forgetcount = 0;
if((ret=forget_head_shift(fr, &newhead, !forgetcount))<=0) return ret; if((ret=forget_head_shift(fr, &newhead, !forgetcount))<=0) return ret;
if(head_check(newhead) && (ret=decode_header(fr, newhead, &freeformat_count))) break; if(head_check(newhead) && (ret=decode_header(fr, nhdr, newhead, &freeformat_count))) break;
} while(1); } while(1);
if(ret<0) return ret; if(ret<0) return ret;

View file

@ -16,7 +16,7 @@
// only single spaces as separator to ease parsing by build scripts // only single spaces as separator to ease parsing by build scripts
#define MPG123_MAJOR 1 #define MPG123_MAJOR 1
#define MPG123_MINOR 32 #define MPG123_MINOR 32
#define MPG123_PATCH 7 #define MPG123_PATCH 9
// Don't get too wild with that to avoid confusing m4. No brackets. // Don't get too wild with that to avoid confusing m4. No brackets.
// Also, it should fit well into a sane file name for the tarball. // Also, it should fit well into a sane file name for the tarball.
#define MPG123_SUFFIX "" #define MPG123_SUFFIX ""

View file

@ -2338,7 +2338,7 @@ Description="Device mounting service"
DisplayName="Mount Manager" DisplayName="Mount Manager"
ServiceBinary="%12%\mountmgr.sys" ServiceBinary="%12%\mountmgr.sys"
ServiceType=1 ServiceType=1
StartType=2 StartType=0
ErrorControl=1 ErrorControl=1
LoadOrderGroup="System Bus Extender" LoadOrderGroup="System Bus Extender"

BIN
nls/locale.nls generated

Binary file not shown.

View file

@ -5,7 +5,7 @@ msgstr ""
"Project-Id-Version: Wine\n" "Project-Id-Version: Wine\n"
"Report-Msgid-Bugs-To: https://bugs.winehq.org\n" "Report-Msgid-Bugs-To: https://bugs.winehq.org\n"
"POT-Creation-Date: N/A\n" "POT-Creation-Date: N/A\n"
"PO-Revision-Date: 2024-11-08 00:18+0200\n" "PO-Revision-Date: 2024-11-13 23:36+0200\n"
"Last-Translator: Aurimas Fišeras <aurimas@members.fsf.org>\n" "Last-Translator: Aurimas Fišeras <aurimas@members.fsf.org>\n"
"Language-Team: Lithuanian <komp_lt@konf.lt>\n" "Language-Team: Lithuanian <komp_lt@konf.lt>\n"
"Language: lt\n" "Language: lt\n"
@ -3166,7 +3166,7 @@ msgstr "&Atkurti"
#: dlls/desk.cpl/desk.rc:42 #: dlls/desk.cpl/desk.rc:42
msgid "Emulate display mode changes (requires restart)" msgid "Emulate display mode changes (requires restart)"
msgstr "" msgstr "Emuliuoti rodymo veiksenos pakeitimus (reikia perleisti)"
#: dlls/desk.cpl/desk.rc:29 #: dlls/desk.cpl/desk.rc:29
msgid "Display Settings" msgid "Display Settings"

View file

@ -39,7 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(explorer);
#define DESKTOP_CLASS_ATOM ((LPCWSTR)MAKEINTATOM(32769)) #define DESKTOP_CLASS_ATOM ((LPCWSTR)MAKEINTATOM(32769))
#define DESKTOP_ALL_ACCESS 0x01ff #define DESKTOP_ALL_ACCESS 0x01ff
static const WCHAR default_driver[] = {'m','a','c',',','x','1','1',0}; static const WCHAR default_driver[] = L"mac,x11,wayland";
static BOOL using_root = TRUE; static BOOL using_root = TRUE;

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