1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

Compare commits

...

124 Commits

Author SHA1 Message Date
KREYREN
e828bdc018
Merge 51561300b2 into f9af971bd7 2024-06-25 00:34:57 +02:00
Santino Mazza
f9af971bd7 mshtml: Implement MarkupServices_ParseString. 2024-06-24 20:57:04 +02:00
Santino Mazza
f9a8f2f1a3 mshtml: Implement MarkupServices_CreateMarkupContainer. 2024-06-24 20:57:04 +02:00
Santino Mazza
e2100e3f1e mshtml/tests: Test for IMarkupServices. 2024-06-24 20:57:04 +02:00
Ilia Docin
ac4e478015 sane.ds: Add SANE option settable flag support. 2024-06-24 20:56:47 +02:00
Zhiyi Zhang
d1a62e862e include: Add some windows.applicationmodel definitions. 2024-06-24 17:13:05 +02:00
Zhiyi Zhang
c165459699 include: Add some windows.ui.core definitions. 2024-06-24 17:13:05 +02:00
Zhiyi Zhang
425ef9cb23 include: Add windows.ui.input.idl. 2024-06-24 17:13:05 +02:00
Zhiyi Zhang
cd8306db83 include: Add windows.devices.input.idl. 2024-06-24 17:13:05 +02:00
Zhiyi Zhang
d010f52241 include: Add some windows.system definitions. 2024-06-24 17:13:05 +02:00
Zhiyi Zhang
b80657c0a5 include: Add some windows.foundation definitions. 2024-06-24 17:13:05 +02:00
Zhiyi Zhang
cbf1310f87 rometadata: Add initial dll. 2024-06-24 17:13:05 +02:00
Alistair Leslie-Hughes
c483e5d456 msado15: Implement _Recordset get/put MaxRecords. 2024-06-24 17:13:05 +02:00
Alistair Leslie-Hughes
794e1f1884 msado15: Implement _Recordset get/put CacheSize. 2024-06-24 17:13:05 +02:00
Torge Matthies
9dd9c455d3 winegstreamer: Handle Gstreamer pipeline flushes gracefully in the media source.
If a GST_EVENT_FLUSH_START event is received between the calls from PE code to wg_parser_stream_get_buffer
and wg_parser_stream_copy_buffer, the latter function will return an error, resulting in the sample request being
dropped without having delivered a sample.

If wg_parser_stream_copy_buffer returns an error, retry the whole wait_on_sample procedure.

Flushes can be triggered by seek operations.
2024-06-24 17:13:05 +02:00
Torge Matthies
62d8d3415c winegstreamer: Ignore an assert in wg_parser.
This gets hit when a wg_parser receives GST_EVENT_FLUSH_START between the wg_parser_stream_get_buffer function return
and the wg_parser_stream_release_buffer call. In this case the NULL buffer can be ignored, it does no harm and there
is no memory leak from this.
2024-06-24 17:13:05 +02:00
Torge Matthies
215478fc46 winegstreamer: Don't only accept segment events when streams are enabled.
I don't know why this was done previously but this just creates a race condition, with no to me apparent benefit.
2024-06-24 17:13:05 +02:00
Torge Matthies
490d8ed663 winegstreamer: Fix race between wg_parser_stream_en/disable and GST_EVENT_FLUSH_START/STOP. 2024-06-24 17:13:05 +02:00
Alexandre Julliard
7c0aa6fd8c makefiles: Generate rules to build makedep. 2024-06-24 17:13:05 +02:00
Alexandre Julliard
0fb9e616bc makefiles: Hardcode the dll directory.
It's Wine-specific anyway.
2024-06-24 15:21:42 +02:00
Alexandre Julliard
f0ee51026b makefiles: Hardcode the nls directory.
It's Wine-specific anyway.
2024-06-24 13:47:08 +02:00
Alexandre Julliard
13159b0767 makefiles: Hardcode the fonts directory.
It's Wine-specific anyway.
2024-06-24 13:46:40 +02:00
Alexandre Julliard
58de2dec08 makedep: Add a helper to get a root-relative directory path. 2024-06-24 13:39:49 +02:00
Rémi Bernon
ef7f9fed60 winewayland: Move window surface creation functions to window_surface.c. 2024-06-24 13:25:28 +02:00
Rémi Bernon
834da273c1 winemac: Move window surface creation functions to surface.c. 2024-06-24 13:25:28 +02:00
Rémi Bernon
e9ca13a6f7 winex11: Move window surface creation functions to bitblt.c. 2024-06-24 13:25:28 +02:00
Eric Pouech
2f5456316c cmd: Move depth count inside builder.
(and temporarly using parenthesis count to store curDepth).

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-24 13:24:06 +02:00
Eric Pouech
fc4b9c645a cmd: Fix a couple of issues wrt. variable expansion.
Ensure expansion at parse time is only done once.
Simply handleExpansion() code.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-24 13:24:05 +02:00
Eric Pouech
3a8aad4834 cmd: Move prompt handling into line reading.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-24 13:24:04 +02:00
Eric Pouech
f45588c57f cmd: Remove unrelated parameter to WCMD_show_prompt.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-24 13:24:03 +02:00
Eric Pouech
8ad0923515 cmd: Factorize code for reading a new line for parser.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-24 13:24:02 +02:00
Davide Beatrici
b34b5d84a6 mmdevapi: Implement IAudioClient3_GetCurrentSharedModeEnginePeriod. 2024-06-24 13:23:31 +02:00
Davide Beatrici
235d527fa5 mmdevapi: Complete IAudioClient3_GetSharedModeEnginePeriod. 2024-06-24 13:23:31 +02:00
Davide Beatrici
9d046996cb mmdevapi: Complete IAudioClient3_InitializeSharedAudioStream. 2024-06-24 13:23:31 +02:00
Davide Beatrici
73a501ab46 mmdevapi: Introduce helper stream_init(). 2024-06-24 13:23:31 +02:00
Davide Beatrici
5dcb879df1 mmdevapi: Return errors early in adjust_timing(). 2024-06-24 13:23:31 +02:00
Alex Henrie
7053e0f641 ntdll: Don't special-case default values in RtlQueryRegistryValues.
Additional tests reveal that RTL_QUERY_REGISTRY_DIRECT does work with
non-string default values, it just requires a pointer to the value and
it doesn't infer the size automatically. That means that the same code
can be used to handle both default and non-default values.
2024-06-24 13:23:19 +02:00
Aida Jonikienė
5eafe53e54 ntdll: Fix params_mask type in NtRaiseHardError().
Real-world app testing reveals that parameter isn't used as a
pointer (so change it to an integer).
2024-06-24 13:22:53 +02:00
Elizabeth Figura
0db0f6180d ntdll: Use file_complete_async() in NtFsControlFile(). 2024-06-24 13:19:57 +02:00
Elizabeth Figura
0a42bd290d ntdll: Use file_complete_async() in serial_DeviceIoControl().
Thereby also handling completion and APCs.
2024-06-24 13:19:56 +02:00
Elizabeth Figura
c133f14fe6 ntdll: Use file_complete_async() in cdrom_DeviceIoControl().
Thereby also handling completion and APCs.
2024-06-24 13:19:54 +02:00
Elizabeth Figura
d140164d76 ntdll: Use file_complete_async() in tape_DeviceIoControl().
Thereby also handling completion and APCs.
2024-06-24 13:19:52 +02:00
Elizabeth Figura
7e3293107f ntdll: Move complete_async() to file.c and use it in NtWriteFileGather(). 2024-06-24 13:19:52 +02:00
Elizabeth Figura
8fee7e8b7c ntdll: Do not queue an IOCP packet in complete_async() if an APC routine is specified. 2024-06-24 13:19:52 +02:00
Vijay Kiran Kamuju
2a6e7ab4ed ntdll: Add stub RtlNumberGenericTableElementsAvl function.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56839
2024-06-24 13:19:21 +02:00
Vijay Kiran Kamuju
1d58a4674c ntdll: Add stub RtlEnumerateGenericTableWithoutSplayingAvl function.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56839
2024-06-24 13:19:19 +02:00
Vijay Kiran Kamuju
32e2ede0df ntdll: Fix RtlEnumerateGenericTableWithoutSplaying function parameters. 2024-06-24 13:19:17 +02:00
Fabian Maurer
6c5d17af07 wow64: In wow64_NtSetInformationToken forward TokenIntegrityLevel.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56725
2024-06-21 22:59:40 +02:00
Piotr Caban
08c0978f0b kernel32/tests: Test GetFileMUIInfo on language resource file. 2024-06-21 22:59:40 +02:00
Piotr Caban
fe6af4fb9e kernel32/tests: Add GetFileMUIInfo tests. 2024-06-21 22:59:40 +02:00
Piotr Caban
f477eca789 kernelbase: Add GetFileMUIInfo implementation. 2024-06-21 22:59:40 +02:00
Alistair Leslie-Hughes
4aab3e42c1 odbccp32: SQLConfigDataSource/W fix crash with passed NULL attribute parameter. 2024-06-21 22:59:40 +02:00
Alistair Leslie-Hughes
6dca99a713 odbccp32: Look at the Setup key to find the driver of ODBC config functions.
We need to look at the Setup key for the driver, as it can be different
compare to the actually driver.

For example, mysql uses the same Setup file to configure both the Ascii/Unicode
vession but has a different file for the actual ODBC functions.
2024-06-21 22:59:40 +02:00
Eric Pouech
bd36ac98c0 cmd: Expand delayed variables in IF operands.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-21 22:59:40 +02:00
Eric Pouech
01d0027739 cmd/tests: Add tests for delayed substitution in IF command.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-21 22:59:40 +02:00
Eric Pouech
411cce36b1 cmd: Introduce return code to indicate abort of current instruction.
Use that return code for WCMD_exit() and WCMD_goto().

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-21 22:59:40 +02:00
Eric Pouech
844d6b553a cmd: Use kernel32's error codes instead of literals.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-21 22:59:40 +02:00
Eric Pouech
2ec70835fc cmd: Introduce token-based syntax parser for building command nodes.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-21 22:59:40 +02:00
Rémi Bernon
9a7408e771 win32u: Use the shared data if possible for NtUserGetAsyncKeyState.
Based on a patch by Huw Davies.
2024-06-21 22:59:39 +02:00
Rémi Bernon
2eeb4d5192 server: Move the desktop keystate to shared memory.
Based on a patch by Huw Davies.
2024-06-21 22:59:39 +02:00
Rémi Bernon
d5b4458c8d server: Use separate functions to update the desktop and input keystates.
Based on a patch by Huw Davies.
2024-06-21 22:59:39 +02:00
Rémi Bernon
534aff4a63 server: Use a separate variable to determine the message on Alt release.
Based on a patch by Huw Davies.
2024-06-21 22:59:39 +02:00
Rémi Bernon
5b013260d1 win32u: Use the shared memory for get_clip_cursor. 2024-06-21 22:59:39 +02:00
Rémi Bernon
472ce7fd1d server: Get rid of the global cursor structure.
Based on a patch by Huw Davies.
2024-06-21 22:59:39 +02:00
Rémi Bernon
496f663157 server: Store the cursor clip rect in the shared data.
Based on a patch by Huw Davies.
2024-06-21 22:59:39 +02:00
Rémi Bernon
33a9097bb4 server: Mark block as writable in mark_block_uninitialized.
Before writing to it, it may have been marked as noaccess before
in free_shared_object.
2024-06-21 22:59:39 +02:00
Alex Henrie
c77a217d34 ntdll: Fix type and size of expanded strings in RtlQueryRegistryValues. 2024-06-21 22:59:39 +02:00
Alex Henrie
7dad7e87a9 ntdll: Don't write partial strings with RTL_QUERY_REGISTRY_DIRECT.
The new tests revealed only one case where too-small buffers were not
already being handled correctly.
2024-06-21 22:59:39 +02:00
Elizabeth Figura
1dee9881e2 ntdll: Do not fill the IOSB in NtFsControlFile() on failure. 2024-06-21 22:59:39 +02:00
Elizabeth Figura
86be09ac0b ntdll: Do not fill the IOSB or signal completion on failure in tape_DeviceIoControl().
We should never fill the IOSB or signal completion for NT_ERROR conditions.
2024-06-21 22:59:39 +02:00
Elizabeth Figura
98b99b6569 ntdll: Do not fill the IOSB or signal completion on failure in serial_DeviceIoControl().
We should never fill the IOSB or signal completion for NT_ERROR conditions.
2024-06-21 22:59:39 +02:00
Elizabeth Figura
5f76f07bff ntdll: Do not fill the IOSB or signal completion on failure in cdrom_DeviceIoControl().
Synchronous NT_ERROR conditions should not touch the IOSB or signal completion.
2024-06-21 22:59:39 +02:00
Elizabeth Figura
0e928ccaea ntdll: Remove the redundant filling of the IOSB in NtDeviceIoControlFile(). 2024-06-21 22:59:39 +02:00
Alexandre Julliard
b2017a48dc ntdll: Move the IP string conversion functions to rtlstr.c. 2024-06-21 22:59:39 +02:00
Alexandre Julliard
0051e102cc ntdll: Move RtlIsProcessorFeaturePresent implementation to the CPU backends. 2024-06-21 22:59:39 +02:00
Alexandre Julliard
7f53949a49 ntdll: Export a proper function for RtlGetNativeSystemInformation.
It will need custom handling on ARM64EC.
2024-06-21 22:59:39 +02:00
Alexandre Julliard
7830153c38 ntdll: Simplify preloader execution using HAVE_WINE_PRELOADER. 2024-06-21 22:59:36 +02:00
Brendan Shanks
7b82f507bd loader: Use zerofill sections instead of preloader on macOS when building with Xcode 15.3.
Xcode 15.3 adds a new linker flag ('-no_huge') which allows the loader
to use zero-fill sections to reserve the areas currently being
reserved by the preloader.

This means the preloader is no longer needed (a good thing, since it's
heavily dependent on private APIs).

The preloader will still be used when Xcode <15.3 is being used, or when
building for i386 (32-bit for 10.14 and earlier).
2024-06-21 17:33:24 +02:00
Brendan Shanks
5da03c7a60 configure: Define HAVE_WINE_PRELOADER when the preloader is being built. 2024-06-21 17:33:24 +02:00
Brendan Shanks
266e95a21b configure: Rename wine_can_build_preloader to wine_use_preloader, and also use it for Linux. 2024-06-21 17:33:24 +02:00
Brendan Shanks
9669cd56f4 configure: Remove warning when not using preloader on macOS. 2024-06-21 17:33:24 +02:00
Brendan Shanks
1f79e7697b configure: Don't build wineloader on macOS with '-pie'.
This is already the default for all Mac binaries targeting 10.7 or
later.
2024-06-21 17:33:24 +02:00
Rémi Bernon
f5a739ce62 include: Define frexpf as inline function in more cases. 2024-06-21 14:11:54 +02:00
Rémi Bernon
dea96222b4 include: Add a couple of CRT function declarations. 2024-06-21 14:11:54 +02:00
Zhiyi Zhang
53d03fb0a5 kernel32: Add AppPolicyGetWindowingModel(). 2024-06-21 14:11:54 +02:00
Arkadiusz Hiler
5a903c0f1a apisetschema: Add api-ms-win-appmodel-runtime-internal-l1-1-1. 2024-06-21 10:51:08 +02:00
Arkadiusz Hiler
2030973a3f bcp47langs: Add stub dll. 2024-06-21 10:51:08 +02:00
Zhiyi Zhang
2804012993 profapi: Add stub dll. 2024-06-21 10:47:56 +02:00
Biswapriyo Nath
4792d3dd2d include: Add Windows.Graphics.Capture.Direct3D11CaptureFramePool runtimeclass. 2024-06-21 10:47:38 +02:00
Biswapriyo Nath
ffe88e3b0d include: Add Windows.Graphics.Capture.Direct3D11CaptureFrame runtimeclass. 2024-06-21 10:47:38 +02:00
Biswapriyo Nath
68b62ecdc9 include: Add Windows.Graphics.Capture.GraphicsCaptureItem runtimeclass. 2024-06-21 10:47:38 +02:00
Biswapriyo Nath
657cc2a9f6 include: Add windows.graphics.idl file. 2024-06-21 10:47:37 +02:00
Biswapriyo Nath
0525a996a4 include: Add Windows.Graphics.Capture.IGraphicsCaptureSession3 definition. 2024-06-21 10:47:37 +02:00
Biswapriyo Nath
9954c6b7fb include: Add Windows.Graphics.Capture.IGraphicsCaptureSession2 definition. 2024-06-21 10:47:35 +02:00
Rémi Bernon
8c64979dcb winex11: Create a global vulkan instance for xrandr. 2024-06-20 23:03:26 +02:00
Rémi Bernon
6e526d19f7 win32u: Remove now unused vulkan_funcs in d3dkmt.c. 2024-06-20 23:03:26 +02:00
Jacek Caban
ec17fc4ca3 mshtml: Add support for using apply on builtin function objects.
Based on patch by Gabriel Ivăncescu.
2024-06-20 23:03:26 +02:00
Jacek Caban
7b95b93c42 mshtml: Add support for using call on builtin function objects.
Based on patch by Gabriel Ivăncescu.
2024-06-20 23:03:26 +02:00
Jacek Caban
005e164751 mshtml: Rename builtin function helpers. 2024-06-20 23:03:26 +02:00
Jacek Caban
bea627b646 mshtml: Introduce IWineJSDispatchHost interface.
Based on patch by Gabriel Ivăncescu.
2024-06-20 23:03:26 +02:00
Rémi Bernon
81eafa9b78 win32u: Use the desktop shared data for GetCursorPos.
Based on a patch by Huw Davies.
2024-06-20 23:03:26 +02:00
Rémi Bernon
5488d99b3e server: Move the last cursor time to the desktop session object.
Based on a patch by Huw Davies.
2024-06-20 23:03:26 +02:00
Rémi Bernon
728049d6fa server: Move the cursor position to the desktop session object.
Based on a patch by Huw Davies.
2024-06-20 23:03:26 +02:00
Rémi Bernon
eb63ac74dc win32u: Open the desktop shared object in NtUserSetThreadDesktop. 2024-06-20 23:03:26 +02:00
Rémi Bernon
20f4c9af0f server: Return the desktop object locator in (get|set)_thread_desktop. 2024-06-20 23:03:26 +02:00
Rémi Bernon
1e10e3a1c0 server: Allocate shared session object for desktops. 2024-06-20 23:03:26 +02:00
Rémi Bernon
f82b1c1fcf include: Add ReadNoFence64 inline helpers. 2024-06-20 23:03:26 +02:00
Rémi Bernon
fac940dfac server: Create a global session shared mapping. 2024-06-20 23:03:26 +02:00
Eric Pouech
96d682e5f7 cmd: Test input has been read before using it.
This let confirmations fail when reading from NUL
(instead of looping forever).

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-20 23:03:26 +02:00
Eric Pouech
96762f12e7 cmd: Remove old FOR loop related code.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-20 23:03:26 +02:00
Eric Pouech
f98077591f cmd: Fix delayed expansion in FOR loop on file sets.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-20 23:03:26 +02:00
Eric Pouech
0ca28d3a70 cmd: Split parsing from executing FOR loops for file walking.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-20 23:03:26 +02:00
Alexandre Julliard
6e82d33eb7 ntdll: Don't set the TEB ExceptionList to -1 on 64-bit.
The tests show that it should be zero.
2024-06-20 23:03:26 +02:00
Alexandre Julliard
0d5936563d ntdll: Fix the fake 32-bit %cs value on ARM64EC. 2024-06-20 23:03:26 +02:00
Alexandre Julliard
b7a3023ca1 ntdll: Send cross-process notification in memory functions on ARM64EC.
Copied from the corresponding code in wow64.dll.
2024-06-20 23:03:26 +02:00
Alexandre Julliard
9f8d4d0b0a ntdll: Add helper macros to define syscalls on ARM64EC. 2024-06-20 23:03:26 +02:00
Ziqing Hui
417b4cb453 winegstreamer: Implement stubs for h264 encoder. 2024-06-20 11:16:46 +02:00
Ziqing Hui
9dfc402cc3 mf/tests: Add tests for H264 encoder types. 2024-06-20 11:16:46 +02:00
Elizabeth Figura
85fd5e283a maintainers: Remove myself as a winegstreamer maintainer. 2024-06-20 11:15:57 +02:00
Alex Henrie
867af68b17 ntdll: Fix handling of non-string types with RTL_QUERY_REGISTRY_DIRECT. 2024-06-20 11:14:07 +02:00
Brendan Shanks
802a52cb1b ntdll: Make __wine_syscall_dispatcher_return a separate function to fix Xcode 16 build errors.
LLVM no longer allows non-private labels to appear between
.cfi_startproc/endproc when targeting Mach-O.
For consistency, also modify ARM and i386.
2024-06-20 11:13:44 +02:00
Jacob Hrbek
51561300b2 adapted ptr 2019-10-06 12:41:41 +02:00
Jacob Hrbek
bf9f100d62 removed additional space 2019-10-06 07:50:46 +02:00
Jacob Hrbek
a18d9f55c5 MmGetPhysicalAddress: Attempt to implement MmGetPhysicalAddress
DO-NOT-MERGE: review prior to merge since i don't know what am i doing..

Signed-off-by: Jacob Hrbek <kreyren@rixotstudio.cz>
2019-10-06 04:56:46 +02:00
198 changed files with 8368 additions and 4331 deletions

View File

@ -158,7 +158,7 @@ M: Marcus Meissner <marcus@jet.franken.de>
F: dlls/gphoto2.ds/
GStreamer multimedia backend
M: Elizabeth Figura <zfigura@codeweavers.com>
P: Elizabeth Figura <zfigura@codeweavers.com>
P: Rémi Bernon <rbernon@codeweavers.com>
F: dlls/winegstreamer/

99
configure vendored
View File

@ -868,9 +868,6 @@ CFLAGS
CC
SET_MAKE
srcdir
nlsdir
fontdir
dlldir
host_os
host_vendor
host_cpu
@ -1006,6 +1003,7 @@ enable_authz
enable_avicap32
enable_avifil32
enable_avrt
enable_bcp47langs
enable_bcrypt
enable_bcryptprimitives
enable_bluetoothapis
@ -1369,6 +1367,7 @@ enable_pidgen
enable_powrprof
enable_printui
enable_prntvpt
enable_profapi
enable_propsys
enable_psapi
enable_pstorec
@ -1388,6 +1387,7 @@ enable_regapi
enable_resutils
enable_riched20
enable_riched32
enable_rometadata
enable_rpcrt4
enable_rsabase
enable_rsaenh
@ -4674,12 +4674,6 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
dlldir=\${libdir}/wine
fontdir=\${datadir}/wine/fonts
nlsdir=\${datadir}/wine/nls
@ -6474,7 +6468,7 @@ MAKEDEP=$wine_makedep
RUNTESTFLAGS="-q -P wine"
SED_CMD="LC_ALL=C sed -e 's,@bindir@,\${bindir},g' -e 's,@dlldir@,\${dlldir},g' -e 's,@PACKAGE_STRING@,$PACKAGE_STRING,g' -e 's,@PACKAGE_VERSION@,$PACKAGE_VERSION,g'"
SED_CMD="LC_ALL=C sed -e 's,@bindir@,\${bindir},g' -e 's,@PACKAGE_STRING@,$PACKAGE_STRING,g' -e 's,@PACKAGE_VERSION@,$PACKAGE_VERSION,g'"
if test -n "$host_alias" -a "$host_alias" != "$build_alias"
@ -9529,14 +9523,47 @@ fi
SYSTEMCONFIGURATION_LIBS="-framework SystemConfiguration"
WINELOADER_LDFLAGS="-Wl,-pie,-segalign,0x1000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
WINELOADER_LDFLAGS="-Wl,-segalign,0x1000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
case $HOST_ARCH in
i386|x86_64) wine_can_build_preloader=yes ;;
*) wine_can_build_preloader=no ;;
i386) wine_use_preloader=yes ;;
x86_64)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -Wl,-no_huge" >&5
printf %s "checking whether the compiler supports -Wl,-no_huge... " >&6; }
if test ${ac_cv_cflags__Wl__no_huge+y}
then :
printf %s "(cached) " >&6
else $as_nop
ac_wine_try_cflags_saved=$CFLAGS
CFLAGS="$CFLAGS -Wl,-no_huge"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(int argc, char **argv) { return 0; }
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_cflags__Wl__no_huge=yes
else $as_nop
ac_cv_cflags__Wl__no_huge=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$ac_wine_try_cflags_saved
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cflags__Wl__no_huge" >&5
printf "%s\n" "$ac_cv_cflags__Wl__no_huge" >&6; }
if test "x$ac_cv_cflags__Wl__no_huge" = xyes
then :
wine_use_preloader=no
WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-no_pie,-image_base,0x200000000,-no_huge,-no_fixup_chains,-segalign,0x1000,-segaddr,WINE_RESERVE,0x1000,-segaddr,WINE_TOP_DOWN,0x7ff000000000"
else $as_nop
wine_use_preloader=yes
fi
;;
*) wine_use_preloader=no ;;
esac
if test "$wine_can_build_preloader" = "yes"
if test "$wine_use_preloader" = "yes"
then
WINEPRELOADER_LDFLAGS="-nostartfiles -nodefaultlibs -e _start -ldylib1.o -mmacosx-version-min=10.7 -Wl,-no_new_main,-segalign,0x1000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -Wl,-no_pie" >&5
@ -9576,8 +9603,6 @@ fi
;;
esac
WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -mmacosx-version-min=10.7"
else
as_fn_append wine_warnings "|can't build Wine preloader; many programs won't work"
fi
if test "x$with_coreaudio" != "xno";
@ -20448,19 +20473,20 @@ case $host_os in
linux*)
if test $HOST_ARCH != unknown
then
test "$wine_binary" = wine || as_fn_append CONFIGURE_TARGETS " loader/wine-preloader"
WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
fi
;;
darwin*|macosx*)
if test "$wine_can_build_preloader" = "yes"
then
test "$wine_binary" = wine || as_fn_append CONFIGURE_TARGETS " loader/wine-preloader"
WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
wine_use_preloader=yes
fi
;;
esac
if test "$wine_use_preloader" = "yes"
then
test "$wine_binary" = wine || as_fn_append CONFIGURE_TARGETS " loader/wine-preloader"
WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
printf "%s\n" "#define HAVE_WINE_PRELOADER 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
printf %s "checking for library containing dlopen... " >&6; }
@ -21951,6 +21977,7 @@ wine_fn_config_makefile dlls/avifil32 enable_avifil32
wine_fn_config_makefile dlls/avifil32/tests enable_tests
wine_fn_config_makefile dlls/avifile.dll16 enable_win16
wine_fn_config_makefile dlls/avrt enable_avrt
wine_fn_config_makefile dlls/bcp47langs enable_bcp47langs
wine_fn_config_makefile dlls/bcrypt enable_bcrypt
wine_fn_config_makefile dlls/bcrypt/tests enable_tests
wine_fn_config_makefile dlls/bcryptprimitives enable_bcryptprimitives
@ -22517,6 +22544,7 @@ wine_fn_config_makefile dlls/powrprof enable_powrprof
wine_fn_config_makefile dlls/printui enable_printui
wine_fn_config_makefile dlls/prntvpt enable_prntvpt
wine_fn_config_makefile dlls/prntvpt/tests enable_tests
wine_fn_config_makefile dlls/profapi enable_profapi
wine_fn_config_makefile dlls/propsys enable_propsys
wine_fn_config_makefile dlls/propsys/tests enable_tests
wine_fn_config_makefile dlls/psapi enable_psapi
@ -22550,6 +22578,8 @@ wine_fn_config_makefile dlls/riched20 enable_riched20
wine_fn_config_makefile dlls/riched20/tests enable_tests
wine_fn_config_makefile dlls/riched32 enable_riched32
wine_fn_config_makefile dlls/riched32/tests enable_tests
wine_fn_config_makefile dlls/rometadata enable_rometadata
wine_fn_config_makefile dlls/rometadata/tests enable_tests
wine_fn_config_makefile dlls/rpcrt4 enable_rpcrt4
wine_fn_config_makefile dlls/rpcrt4/tests enable_tests
wine_fn_config_makefile dlls/rsabase enable_rsabase
@ -23073,7 +23103,6 @@ test "$wine_binary" = wine || as_fn_append CONFIGURE_TARGETS " loader/wine"
if test "x$enable_tools" != xno
then
as_fn_append CONFIGURE_TARGETS " tools/makedep$ac_exeext"
ac_config_commands="$ac_config_commands tools/makedep"
fi
@ -23115,18 +23144,6 @@ include/stamp-h.in: configure.ac aclocal.m4
@echo timestamp > \$@"
fi
if test "x$enable_tools" != xno
then
as_fn_append wine_rules "
tools/makedep$ac_exeext: ${wine_srcdir}tools/makedep.c include/config.h config.status
@./config.status tools/makedep
Makefile: tools/makedep$ac_exeext"
else
as_fn_append wine_rules "
\$(MAKEDEP):
@echo \"You need to run make in $toolsdir first\" && false"
fi
if test -n "$with_wine64"
then
@ -23878,7 +23895,8 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
wine_fn_output_makedep ()
{
as_dir=tools; as_fn_mkdir_p
$CC -I${wine_srcdir}tools -Iinclude -I${wine_srcdir}include -D__WINESRC__ -DWINE_UNIX_LIB $EXTRACFLAGS $CPPFLAGS $CFLAGS -o tools/makedep$ac_exeext ${wine_srcdir}tools/makedep.c $LDFLAGS
$CC -c -I${wine_srcdir}tools -Iinclude -I${wine_srcdir}include -D__WINESRC__ -DWINE_UNIX_LIB $EXTRACFLAGS $CPPFLAGS $CFLAGS -o tools/makedep.o ${wine_srcdir}tools/makedep.c
$CC -o tools/makedep$ac_exeext tools/makedep.o $LDFLAGS
}
wine_fn_output_makefile ()
{
@ -23945,9 +23963,6 @@ host = $host
host_cpu = $host_cpu
host_vendor = $host_vendor
host_os = $host_os
dlldir = $dlldir
fontdir = $fontdir
nlsdir = $nlsdir
srcdir = $srcdir
SET_MAKE = $SET_MAKE
CC = $CC

View File

@ -91,9 +91,6 @@ AC_ARG_WITH(wine64, AS_HELP_STRING([--with-wine64=DIR],[use the 64-bit Wine i
AC_CANONICAL_HOST
AC_SUBST(dlldir,[\${libdir}/wine])
AC_SUBST(fontdir,[\${datadir}/wine/fonts])
AC_SUBST(nlsdir,[\${datadir}/wine/nls])
AC_SUBST(srcdir)
dnl **** Check for some programs ****
@ -198,7 +195,7 @@ fi
AC_SUBST(toolsdir,[$wine_cv_toolsdir])
AC_SUBST(MAKEDEP,[$wine_makedep])
AC_SUBST(RUNTESTFLAGS,["-q -P wine"])
AC_SUBST(SED_CMD,["LC_ALL=C sed -e 's,@bindir@,\${bindir},g' -e 's,@dlldir@,\${dlldir},g' -e 's,@PACKAGE_STRING@,$PACKAGE_STRING,g' -e 's,@PACKAGE_VERSION@,$PACKAGE_VERSION,g'"])
AC_SUBST(SED_CMD,["LC_ALL=C sed -e 's,@bindir@,\${bindir},g' -e 's,@PACKAGE_STRING@,$PACKAGE_STRING,g' -e 's,@PACKAGE_VERSION@,$PACKAGE_VERSION,g'"])
if test -n "$host_alias" -a "$host_alias" != "$build_alias"
then
@ -637,14 +634,21 @@ case $host_os in
AC_SUBST(SECURITY_LIBS,"-framework Security -framework CoreFoundation")
AC_SUBST(SYSTEMCONFIGURATION_LIBS,"-framework SystemConfiguration")
WINELOADER_LDFLAGS="-Wl,-pie,-segalign,0x1000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
WINELOADER_LDFLAGS="-Wl,-segalign,0x1000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
case $HOST_ARCH in
i386|x86_64) wine_can_build_preloader=yes ;;
*) wine_can_build_preloader=no ;;
i386) wine_use_preloader=yes ;;
x86_64)
dnl If the -no_huge linker option is present (added in Xcode 15.3), use zerofill sections instead of the preloader
WINE_TRY_CFLAGS([-Wl,-no_huge],
[wine_use_preloader=no
WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-no_pie,-image_base,0x200000000,-no_huge,-no_fixup_chains,-segalign,0x1000,-segaddr,WINE_RESERVE,0x1000,-segaddr,WINE_TOP_DOWN,0x7ff000000000"],
[wine_use_preloader=yes])
;;
*) wine_use_preloader=no ;;
esac
if test "$wine_can_build_preloader" = "yes"
if test "$wine_use_preloader" = "yes"
then
WINEPRELOADER_LDFLAGS="-nostartfiles -nodefaultlibs -e _start -ldylib1.o -mmacosx-version-min=10.7 -Wl,-no_new_main,-segalign,0x1000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
WINE_TRY_CFLAGS([-Wl,-no_pie],
@ -659,8 +663,6 @@ case $host_os in
esac
dnl If preloader is used, the loader needs to be an LC_UNIXTHREAD binary to avoid AppKit/Core Animation problems.
WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -mmacosx-version-min=10.7"
else
WINE_WARNING([can't build Wine preloader; many programs won't work])
fi
if test "x$with_coreaudio" != "xno";
@ -2035,19 +2037,18 @@ case $host_os in
linux*)
if test $HOST_ARCH != unknown
then
test "$wine_binary" = wine || WINE_IGNORE_FILE(loader/wine-preloader)
WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
fi
;;
darwin*|macosx*)
if test "$wine_can_build_preloader" = "yes"
then
test "$wine_binary" = wine || WINE_IGNORE_FILE(loader/wine-preloader)
WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
wine_use_preloader=yes
fi
;;
esac
if test "$wine_use_preloader" = "yes"
then
test "$wine_binary" = wine || WINE_IGNORE_FILE(loader/wine-preloader)
WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
AC_DEFINE(HAVE_WINE_PRELOADER, 1, [Define to 1 if the Wine preloader is being used.])
fi
dnl **** Check for functions ****
dnl Check for -ldl
@ -2459,6 +2460,7 @@ WINE_CONFIG_MAKEFILE(dlls/avifil32)
WINE_CONFIG_MAKEFILE(dlls/avifil32/tests)
WINE_CONFIG_MAKEFILE(dlls/avifile.dll16,enable_win16)
WINE_CONFIG_MAKEFILE(dlls/avrt)
WINE_CONFIG_MAKEFILE(dlls/bcp47langs)
WINE_CONFIG_MAKEFILE(dlls/bcrypt)
WINE_CONFIG_MAKEFILE(dlls/bcrypt/tests)
WINE_CONFIG_MAKEFILE(dlls/bcryptprimitives)
@ -3025,6 +3027,7 @@ WINE_CONFIG_MAKEFILE(dlls/powrprof)
WINE_CONFIG_MAKEFILE(dlls/printui)
WINE_CONFIG_MAKEFILE(dlls/prntvpt)
WINE_CONFIG_MAKEFILE(dlls/prntvpt/tests)
WINE_CONFIG_MAKEFILE(dlls/profapi)
WINE_CONFIG_MAKEFILE(dlls/propsys)
WINE_CONFIG_MAKEFILE(dlls/propsys/tests)
WINE_CONFIG_MAKEFILE(dlls/psapi)
@ -3058,6 +3061,8 @@ WINE_CONFIG_MAKEFILE(dlls/riched20)
WINE_CONFIG_MAKEFILE(dlls/riched20/tests)
WINE_CONFIG_MAKEFILE(dlls/riched32)
WINE_CONFIG_MAKEFILE(dlls/riched32/tests)
WINE_CONFIG_MAKEFILE(dlls/rometadata)
WINE_CONFIG_MAKEFILE(dlls/rometadata/tests)
WINE_CONFIG_MAKEFILE(dlls/rpcrt4)
WINE_CONFIG_MAKEFILE(dlls/rpcrt4/tests)
WINE_CONFIG_MAKEFILE(dlls/rsabase)
@ -3583,12 +3588,12 @@ test "$wine_binary" = wine || WINE_IGNORE_FILE(loader/wine)
if test "x$enable_tools" != xno
then
WINE_IGNORE_FILE(tools/makedep$ac_exeext)
AC_CONFIG_COMMANDS([tools/makedep],[wine_fn_output_makedep || AS_EXIT],
[wine_fn_output_makedep ()
{
AS_MKDIR_P(tools)
$CC -I${wine_srcdir}tools -Iinclude -I${wine_srcdir}include -D__WINESRC__ -DWINE_UNIX_LIB $EXTRACFLAGS $CPPFLAGS $CFLAGS -o tools/makedep$ac_exeext ${wine_srcdir}tools/makedep.c $LDFLAGS
$CC -c -I${wine_srcdir}tools -Iinclude -I${wine_srcdir}include -D__WINESRC__ -DWINE_UNIX_LIB $EXTRACFLAGS $CPPFLAGS $CFLAGS -o tools/makedep.o ${wine_srcdir}tools/makedep.c
$CC -o tools/makedep$ac_exeext tools/makedep.o $LDFLAGS
}])
fi
@ -3652,18 +3657,6 @@ include/stamp-h.in: configure.ac aclocal.m4
@echo timestamp > \$[@]])
fi
if test "x$enable_tools" != xno
then
WINE_APPEND_RULE(
[tools/makedep$ac_exeext: ${wine_srcdir}tools/makedep.c include/config.h config.status
@./config.status tools/makedep
Makefile: tools/makedep$ac_exeext])
else
WINE_APPEND_RULE(
[\$(MAKEDEP):
@echo \"You need to run make in $toolsdir first\" && false])
fi
dnl Rules for wineloader
if test -n "$with_wine64"

View File

@ -1,3 +1,4 @@
apiset api-ms-win-appmodel-runtime-internal-l1-1-1 = kernelbase.dll
apiset api-ms-win-appmodel-runtime-l1-1-2 = kernelbase.dll
apiset api-ms-win-base-bootconfig-l1-1-0 = advapi32.dll
apiset api-ms-win-base-util-l1-1-0 = advapi32.dll

View File

@ -0,0 +1,2 @@
MODULE = bcp47langs.dll
IMPORTLIB = bcp47langs

View File

@ -0,0 +1,71 @@
1 stub GetUnIsoRegionCode
@ stub AppendUserLanguageInputMethods
@ stub AppendUserLanguageInternal
@ stub AppendUserLanguages
@ stub Bcp47BufferFromLcid
@ stub Bcp47FindClosestLanguage
@ stub Bcp47FromCompactTagInternal
@ stub Bcp47FromHkl
@ stub Bcp47FromLcid
@ stub Bcp47GetAbbreviation
@ stub Bcp47GetDirectionality
@ stub Bcp47GetDistance
@ stub Bcp47GetExtensionSingletons
@ stub Bcp47GetExtensionSubstring
@ stub Bcp47GetIsoLanguageCode
@ stub Bcp47GetIsoScriptCode
@ stub Bcp47GetLanguageName
@ stub Bcp47GetMuiForm
@ stub Bcp47GetNeutralForm
@ stub Bcp47GetNlsForm
@ stub Bcp47GetSubtagMapInternal
@ stub Bcp47GetUnIsoRegionCode
@ stub Bcp47IsWellFormed
@ stub Bcp47Normalize
@ stub ClearApplicationLanguageOverride
@ stub ClearApplicationManifestLanguages
@ stub ClearHttpAcceptLanguageOptOut
@ stub ClearUserDisplayLanguageOverride
@ stub ClearUserLocaleFromLanguageProfileOptOut
@ stub CompactTagFromBcp47Internal
@ stub DllGetActivationFactory
@ stub DllGetClassObject
@ stub GetApplicationLanguageOverride
@ stub GetApplicationLanguages
@ stub GetApplicationManifestLanguages
@ stub GetAppropriateUserLocaleForUserLanguages
@ stub GetAppropriateUserPreferredAndDisplayLanguagesForUser
@ stub GetClosestMatchingUserLanguage
@ stub GetDisplayLanguagesForAllUsers
@ stub GetFontFallbackLanguageList
@ stub GetHttpAcceptLanguageOptOut
@ stub GetInputMethodOverrideForUser
@ stub GetPendingUserDisplayLanguage
@ stub GetRelevantLocalesFromLanguageTags
@ stub GetSerializedUserLanguageProfile
@ stub GetSerializedUserLanguagesForUser
@ stub GetStartingUserDisplayLanguage
@ stub GetUserDisplayLanguageOverride
@ stub GetUserLanguageInputMethods
@ stub GetUserLanguageInputMethodsForUser
@ stub GetUserLanguages
@ stub GetUserLanguagesForAllUsers
@ stub GetUserLanguagesForUser
@ stub GetUserLocaleFromLanguageProfileOptOut
@ stub IsTransientLcid
@ stub LanguageListAsMuiForm
@ stub LcidFromBcp47
@ stub RemoveInputsForAllLanguagesInternal
@ stub RemoveUserLanguageInputMethods
@ stub ResolveLanguages
@ stub SetApplicationLanguageOverride
@ stub SetApplicationManifestLanguages
@ stub SetHttpAcceptLanguageOptOut
@ stub SetInputMethodOverride
@ stub SetPreviousUserDisplayLanguages
@ stub SetStartingUserDisplayLanguage
@ stub SetUserDisplayLanguageOverride
@ stub SetUserLanguageInputMethods
@ stub SetUserLanguagesInternal
@ stub SetUserLanguagesInternalCore
@ stub SetUserLocaleFromLanguageProfileOptOut

View File

@ -158,6 +158,7 @@
@ stdcall ApplicationRecoveryFinished(long)
@ stdcall ApplicationRecoveryInProgress(ptr)
@ stdcall AppPolicyGetMediaFoundationCodecLoading(ptr ptr) kernelbase.AppPolicyGetMediaFoundationCodecLoading
@ stdcall AppPolicyGetWindowingModel(ptr ptr) kernelbase.AppPolicyGetWindowingModel
@ stdcall -import AreFileApisANSI()
@ stdcall AssignProcessToJobObject(ptr ptr)
@ stdcall -import AttachConsole(long)

View File

@ -520,6 +520,298 @@ static void test_internal_structure(void)
ok( EndUpdateResourceW( res, TRUE ), "EndUpdateResourceW failed\n");
}
static const struct
{
IMAGE_DOS_HEADER dos;
IMAGE_NT_HEADERS nt;
IMAGE_SECTION_HEADER section;
} dll_image =
{
{ IMAGE_DOS_SIGNATURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 }, 0, 0, { 0 },
sizeof(IMAGE_DOS_HEADER) },
{
IMAGE_NT_SIGNATURE, /* Signature */
{
#if defined __i386__
IMAGE_FILE_MACHINE_I386, /* Machine */
#elif defined __x86_64__
IMAGE_FILE_MACHINE_AMD64, /* Machine */
#elif defined __arm__
IMAGE_FILE_MACHINE_ARMNT, /* Machine */
#elif defined __aarch64__
IMAGE_FILE_MACHINE_ARM64, /* Machine */
#else
# error You must specify the machine type
#endif
1, /* NumberOfSections */
0, /* TimeDateStamp */
0, /* PointerToSymbolTable */
0, /* NumberOfSymbols */
sizeof(IMAGE_OPTIONAL_HEADER), /* SizeOfOptionalHeader */
IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL /* Characteristics */
},
{ IMAGE_NT_OPTIONAL_HDR_MAGIC, /* Magic */
1, /* MajorLinkerVersion */
0, /* MinorLinkerVersion */
0, /* SizeOfCode */
0, /* SizeOfInitializedData */
0, /* SizeOfUninitializedData */
0, /* AddressOfEntryPoint */
0x1000, /* BaseOfCode */
#ifndef _WIN64
0, /* BaseOfData */
#endif
0x10000000, /* ImageBase */
0x1000, /* SectionAlignment */
0x1000, /* FileAlignment */
4, /* MajorOperatingSystemVersion */
0, /* MinorOperatingSystemVersion */
1, /* MajorImageVersion */
0, /* MinorImageVersion */
4, /* MajorSubsystemVersion */
0, /* MinorSubsystemVersion */
0, /* Win32VersionValue */
0x3000, /* SizeOfImage */
sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS),
0, /* CheckSum */
IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | IMAGE_DLLCHARACTERISTICS_NX_COMPAT, /* DllCharacteristics */
0, /* SizeOfStackReserve */
0, /* SizeOfStackCommit */
0, /* SizeOfHeapReserve */
0, /* SizeOfHeapCommit */
0, /* LoaderFlags */
IMAGE_FILE_RESOURCE_DIRECTORY + 1, /* NumberOfRvaAndSizes */
{ { 0 }, { 0 }, { 0x1000, 0x1000 } } /* DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */
}
},
{ ".rsrc\0\0", { 0 }, 0x1000, 0x1000, 0, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ }
};
static void create_test_dll( const WCHAR *name )
{
DWORD dummy;
HANDLE handle = CreateFileW( name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0 );
ok( handle != INVALID_HANDLE_VALUE, "failed to create file err %lu\n", GetLastError() );
WriteFile( handle, &dll_image, sizeof(dll_image), &dummy, NULL );
SetFilePointer( handle, dll_image.nt.OptionalHeader.SizeOfImage, NULL, FILE_BEGIN );
SetEndOfFile( handle );
CloseHandle( handle );
}
static struct mui_res
{
DWORD signature;
DWORD size;
DWORD version;
DWORD path_type;
DWORD file_type;
DWORD system_attributes;
DWORD fallback_location;
BYTE service_checksum[16];
BYTE checksum[16];
DWORD unk1[2];
DWORD mui_path_off;
DWORD mui_path_size;
DWORD unk2[2];
DWORD ln_type_name_off;
DWORD ln_type_name_size;
DWORD ln_type_id_off;
DWORD ln_type_id_size;
DWORD mui_type_name_off;
DWORD mui_type_name_size;
DWORD mui_type_id_off;
DWORD mui_type_id_size;
DWORD lang_off;
DWORD lang_size;
DWORD fallback_lang_off;
DWORD fallback_lang_size;
WCHAR ln_type_names[8];
DWORD ln_type_ids[1];
WCHAR mui_type_names[8];
DWORD mui_type_ids[1];
WCHAR lang[8];
WCHAR fallback_lang[8];
} ln_mui_res = {
0xfecdfecd, sizeof(ln_mui_res), 0x10000, 0,
MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN >> 1,
0, 0, {'s','c'}, {'c'}, {0}, 0, 0, {0},
offsetof(struct mui_res, ln_type_names), sizeof(L"MUI\0"),
offsetof(struct mui_res, ln_type_ids), sizeof(ln_mui_res.ln_type_ids),
offsetof(struct mui_res, mui_type_names), sizeof(L"MUI\0"),
offsetof(struct mui_res, mui_type_ids), sizeof(ln_mui_res.mui_type_ids), 0, 0,
offsetof(struct mui_res, fallback_lang), sizeof(L"en-US"),
{'M','U','I',0,0}, {RT_CURSOR}, {'M','U','I',0,0}, {RT_STRING}, {0}, {'e','n','-','U','S',0},
}, en_mui_res = {
0xfecdfecd, sizeof(ln_mui_res), 0x10000, 0,
MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI >> 1,
0, 0, {'s','c'}, {'c'}, {0}, 0, 0, {0},
offsetof(struct mui_res, ln_type_names), sizeof(L"MUI\0"),
offsetof(struct mui_res, ln_type_ids), sizeof(ln_mui_res.ln_type_ids),
0, 0, 0, 0, offsetof(struct mui_res, lang), sizeof(L"en-US"), 0, 0,
{'M','U','I',0,0}, {RT_STRING}, {0}, {0}, {'e','n','-','U','S',0}
};
static void test_mui(void)
{
static const WCHAR ln_dll[] = L"test_mui.dll";
static const WCHAR en_dll[] = L"en-US\\test_mui.dll.mui";
static const BYTE zeros[16] = { 0 };
BYTE buf[1024];
FILEMUIINFO *info = (FILEMUIINFO *)buf;
const WCHAR *str;
DWORD size, *id;
HANDLE res;
BOOL r;
size = 0;
r = GetFileMUIInfo( 0, ln_dll, NULL, &size);
ok( !r, "GetFileMUIInfo succeeded\n" );
ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError() = %ld\n", GetLastError() );
create_test_dll( ln_dll );
CreateDirectoryW( L"en-US", NULL );
create_test_dll( en_dll );
size = 0;
r = GetFileMUIInfo( 0, ln_dll, NULL, &size );
ok( r, "GetFileMUIInfo failed: %ld\n", GetLastError() );
ok( size == sizeof(*info), "unexpected size: %ld\n", size );
memset( buf, 0xfe, sizeof(buf) );
size = sizeof(buf);
info->dwSize = sizeof(buf);
info->dwVersion = 0;
r = GetFileMUIInfo( 0, ln_dll, info, &size );
ok( !r, "GetFileMUIInfo succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError() = %ld\n", GetLastError() );
ok( !size, "size = %ld\n", size );
size = sizeof(buf);
info->dwVersion = MUI_FILEINFO_VERSION;
r = GetFileMUIInfo( 0, ln_dll, info, &size );
ok( r, "GetFileMUIInfo failed: %ld\n", GetLastError() );
ok( info->dwSize == sizeof(buf), "dwSize = %ld\n", info->dwSize );
ok( info->dwVersion == MUI_FILEINFO_VERSION, "dwVersion = %ld\n", info->dwVersion );
ok( info->dwFileType == MUI_FILETYPE_NOT_LANGUAGE_NEUTRAL, "dwFileType = %ld\n", info->dwFileType );
ok( !memcmp(info->pChecksum, zeros, sizeof(info->pChecksum)), "pChecksum = %s\n",
wine_dbgstr_an((char *)info->pChecksum, sizeof(info->pChecksum)) );
ok( !memcmp(info->pServiceChecksum, zeros, sizeof(info->pServiceChecksum)), "pServiceChecksum = %s\n",
wine_dbgstr_an((char *)info->pServiceChecksum, sizeof(info->pServiceChecksum)) );
ok( !info->dwLanguageNameOffset, "dwLanguageNameOffset = %ld\n", info->dwLanguageNameOffset );
ok( !info->dwTypeIDMainSize, "dwTypeIDMainSize = %ld\n", info->dwTypeIDMainSize );
ok( !info->dwTypeIDMainOffset, "dwTypeIDMainOffset = %ld\n", info->dwTypeIDMainOffset );
ok( !info->dwTypeNameMainOffset, "dwTypeNameMainOffset = %ld\n", info->dwTypeNameMainOffset );
ok( !info->dwTypeIDMUISize, "dwTypeIDMUISize = %ld\n", info->dwTypeIDMUISize );
ok( !info->dwTypeIDMUIOffset, "dwTypeIDMUIOffset = %ld\n", info->dwTypeIDMUIOffset );
ok( !info->dwTypeNameMUIOffset, "dwTypeNameMUIOffset = %ld\n", info->dwTypeNameMUIOffset );
ok( !memcmp(info->abBuffer, zeros, sizeof(info->abBuffer)), "abBuffer = %s\n",
wine_dbgstr_an((char *)info->abBuffer, sizeof(info->abBuffer)) );
res = BeginUpdateResourceW( ln_dll, TRUE );
ok( res != NULL, "BeginUpdateResourceW failed: %ld\n", GetLastError() );
r = UpdateResourceW( res, L"MUI", MAKEINTRESOURCEW(1), 0, &ln_mui_res, 4 );
ok( r, "UpdateResource failed: %ld\n", GetLastError() );
ok( EndUpdateResourceW( res, FALSE ), "EndUpdateResourceW failed: %ld\n", GetLastError() );
size = 0;
r = GetFileMUIInfo( MUI_QUERY_TYPE | MUI_QUERY_CHECKSUM | MUI_QUERY_LANGUAGE_NAME
| MUI_QUERY_RESOURCE_TYPES, ln_dll, NULL, &size );
ok( !r, "GetFileMUIInfo succeeded\n" );
ok( GetLastError() == ERROR_BAD_EXE_FORMAT, "GetLastError() = %ld\n", GetLastError() );
res = BeginUpdateResourceW( ln_dll, TRUE );
ok( res != NULL, "BeginUpdateResourceW failed: %ld\n", GetLastError() );
r = UpdateResourceW( res, L"MUI", MAKEINTRESOURCEW(1), 0, &ln_mui_res, sizeof(ln_mui_res) );
ok( r, "UpdateResource failed: %ld\n", GetLastError() );
ok( EndUpdateResourceW( res, FALSE ), "EndUpdateResourceW failed: %ld\n", GetLastError() );
size = 0;
r = GetFileMUIInfo( MUI_QUERY_TYPE | MUI_QUERY_CHECKSUM | MUI_QUERY_LANGUAGE_NAME
| MUI_QUERY_RESOURCE_TYPES, ln_dll, NULL, &size );
ok( !r, "GetFileMUIInfo succeeded\n" );
ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() = %ld\n", GetLastError() );
ok( size, "size was not set\n" );
memset( buf, 0xfe, sizeof(buf) );
size = sizeof(buf);
info->dwSize = sizeof(buf);
info->dwVersion = MUI_FILEINFO_VERSION;
r = GetFileMUIInfo( MUI_QUERY_TYPE | MUI_QUERY_CHECKSUM | MUI_QUERY_LANGUAGE_NAME
| MUI_QUERY_RESOURCE_TYPES, ln_dll, info, &size );
ok( r, "GetFileMUIInfo failed: %ld\n", GetLastError() );
ok( info->dwSize == sizeof(buf), "dwSize = %ld\n", info->dwSize );
ok( info->dwVersion == MUI_FILEINFO_VERSION, "dwVersion = %ld\n", info->dwVersion );
ok( info->dwFileType == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN, "dwFileType = %ld\n", info->dwFileType );
ok( info->pChecksum[0] == 'c', "pChecksum = %s\n",
wine_dbgstr_an((char *)info->pChecksum, sizeof(info->pChecksum)) );
ok( info->pServiceChecksum[0] == 's', "pServiceChecksum = %s\n",
wine_dbgstr_an((char *)info->pServiceChecksum, sizeof(info->pServiceChecksum)) );
ok( info->dwLanguageNameOffset == 72, "dwLanguageNameOffset = %ld\n", info->dwLanguageNameOffset );
str = (WCHAR *)(buf + info->dwLanguageNameOffset);
ok( !wcscmp(str, L"en-US"), "language name = %s\n", wine_dbgstr_w(str) );
ok( info->dwTypeIDMainSize == 1, "dwTypeIDMainSize = %ld\n", info->dwTypeIDMainSize );
ok( info->dwTypeIDMainOffset == 84, "dwTypeIDMainOffset = %ld\n", info->dwTypeIDMainOffset );
id = (DWORD *)(buf + info->dwTypeIDMainOffset);
ok( id[0] == RT_CURSOR, "type ID main[0] = %ld\n", id[0] );
ok( info->dwTypeNameMainOffset == 88, "dwTypeNameMainOffset = %ld\n", info->dwTypeNameMainOffset );
str = (WCHAR *)(buf + info->dwTypeNameMainOffset);
ok( !wcscmp(str, L"MUI"), "type name main[0] = %s\n", wine_dbgstr_w(str) );
str += wcslen(str) + 1;
ok( !str[0], "string list is not NULL terminated: %s\n", wine_dbgstr_w(str) );
ok( info->dwTypeIDMUISize == 1, "dwTypeIDMUISize = %ld\n", info->dwTypeIDMUISize );
ok( info->dwTypeIDMUIOffset == 98, "dwTypeIDMUIOffset = %ld\n", info->dwTypeIDMUIOffset );
id = (DWORD *)(buf + info->dwTypeIDMUIOffset);
ok( id[0] == RT_STRING, "type ID MUI[0] = %ld\n", id[0] );
ok( info->dwTypeNameMUIOffset == 102, "dwTypeNameMUIOffset = %ld\n", info->dwTypeNameMUIOffset );
str = (WCHAR *)(buf + info->dwTypeNameMUIOffset);
ok( !wcscmp(str, L"MUI"), "type name MUI[0] = %s\n", wine_dbgstr_w(str) );
str += wcslen(str) + 1;
ok( !str[0], "string list is not NULL terminated: %s\n", wine_dbgstr_w(str) );
res = BeginUpdateResourceW( en_dll, TRUE );
ok( res != NULL, "BeginUpdateResourceW failed: %ld\n", GetLastError() );
r = UpdateResourceW( res, L"MUI", MAKEINTRESOURCEW(1), 0, &en_mui_res, sizeof(en_mui_res) );
ok( r, "UpdateResource failed: %ld\n", GetLastError() );
ok( EndUpdateResourceW( res, FALSE ), "EndUpdateResourceW failed: %ld\n", GetLastError() );
memset( buf, 0xfe, sizeof(buf) );
size = sizeof(buf);
info->dwSize = sizeof(buf);
info->dwVersion = MUI_FILEINFO_VERSION;
r = GetFileMUIInfo( MUI_QUERY_TYPE | MUI_QUERY_CHECKSUM | MUI_QUERY_LANGUAGE_NAME
| MUI_QUERY_RESOURCE_TYPES, en_dll, info, &size );
ok( r, "GetFileMUIInfo failed: %ld\n", GetLastError() );
ok( info->dwSize == sizeof(buf), "dwSize = %ld\n", info->dwSize );
ok( info->dwVersion == MUI_FILEINFO_VERSION, "dwVersion = %ld\n", info->dwVersion );
ok( info->dwFileType == MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI, "dwFileType = %ld\n", info->dwFileType );
ok( info->pChecksum[0] == 'c', "pChecksum = %s\n",
wine_dbgstr_an((char *)info->pChecksum, sizeof(info->pChecksum)) );
ok( info->pServiceChecksum[0] == 's', "pServiceChecksum = %s\n",
wine_dbgstr_an((char *)info->pServiceChecksum, sizeof(info->pServiceChecksum)) );
ok( info->dwLanguageNameOffset == 72, "dwLanguageNameOffset = %ld\n", info->dwLanguageNameOffset );
str = (WCHAR *)(buf + info->dwLanguageNameOffset);
ok( !wcscmp(str, L"en-US"), "language name = %s\n", wine_dbgstr_w(str) );
ok( !info->dwTypeIDMainSize, "dwTypeIDMainSize = %ld\n", info->dwTypeIDMainSize );
ok( !info->dwTypeIDMainOffset, "dwTypeIDMainOffset = %ld\n", info->dwTypeIDMainOffset );
ok( !info->dwTypeNameMainOffset, "dwTypeNameMainOffset = %ld\n", info->dwTypeNameMainOffset );
ok( info->dwTypeIDMUISize == 1, "dwTypeIDMUISize = %ld\n", info->dwTypeIDMUISize );
ok( info->dwTypeIDMUIOffset == 84, "dwTypeIDMUIOffset = %ld\n", info->dwTypeIDMUIOffset );
id = (DWORD *)(buf + info->dwTypeIDMUIOffset);
ok( id[0] == RT_STRING, "type ID MUI[0] = %ld\n", id[0] );
ok( info->dwTypeNameMUIOffset == 88, "dwTypeNameMUIOffset = %ld\n", info->dwTypeNameMUIOffset );
str = (WCHAR *)(buf + info->dwTypeNameMUIOffset);
ok( !wcscmp(str, L"MUI"), "type name MUI[0] = %s\n", wine_dbgstr_w(str) );
str += wcslen(str) + 1;
ok( !str[0], "string list is not NULL terminated: %s\n", wine_dbgstr_w(str) );
DeleteFileW( ln_dll );
DeleteFileW( en_dll );
RemoveDirectoryW( L"en-US" );
}
START_TEST(resource)
{
DWORD i;
@ -552,4 +844,5 @@ START_TEST(resource)
DeleteFileA( filename );
}
test_find_resource();
test_mui();
}

View File

@ -5719,15 +5719,221 @@ done:
}
#define MUI_SIGNATURE 0xfecdfecd
struct mui_resource
{
DWORD signature;
DWORD size;
DWORD version;
DWORD path_type;
DWORD file_type;
DWORD system_attributes;
DWORD fallback_location;
BYTE service_checksum[16];
BYTE checksum[16];
DWORD unk1[2];
DWORD mui_path_off;
DWORD mui_path_size;
DWORD unk2[2];
DWORD ln_type_name_off;
DWORD ln_type_name_size;
DWORD ln_type_id_off;
DWORD ln_type_id_size;
DWORD mui_type_name_off;
DWORD mui_type_name_size;
DWORD mui_type_id_off;
DWORD mui_type_id_size;
DWORD lang_off;
DWORD lang_size;
DWORD fallback_lang_off;
DWORD fallback_lang_size;
};
static BOOL validate_mui_resource(struct mui_resource *mui, DWORD size)
{
if (size >= sizeof(DWORD) && mui->signature != MUI_SIGNATURE)
{
SetLastError(ERROR_MUI_INVALID_RC_CONFIG);
return FALSE;
}
size = min( size, mui->size );
if (size < sizeof(*mui) ||
mui->ln_type_name_off >= size || mui->ln_type_name_size > size - mui->ln_type_name_off ||
mui->ln_type_id_off >= size || mui->ln_type_id_size > size - mui->ln_type_id_off ||
mui->mui_type_name_off >= size || mui->mui_type_name_size > size - mui->mui_type_name_off ||
mui->mui_type_id_off >= size || mui->mui_type_id_size > size - mui->mui_type_id_off ||
mui->lang_off >= size || mui->lang_size > size - mui->lang_off ||
mui->fallback_lang_off >= size || mui->fallback_lang_size > size - mui->fallback_lang_off)
{
SetLastError(ERROR_BAD_EXE_FORMAT);
return FALSE;
}
return TRUE;
}
/******************************************************************************
* GetFileMUIInfo (kernelbase.@)
*/
BOOL WINAPI /* DECLSPEC_HOTPATCH */ GetFileMUIInfo( DWORD flags, const WCHAR *path,
FILEMUIINFO *info, DWORD *size )
BOOL WINAPI DECLSPEC_HOTPATCH GetFileMUIInfo( DWORD flags, const WCHAR *path,
FILEMUIINFO *info, DWORD *size )
{
FIXME( "stub: %lu, %s, %p, %p\n", flags, debugstr_w(path), info, size );
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
DWORD off, mui_size, type = MUI_FILETYPE_NOT_LANGUAGE_NEUTRAL;
struct mui_resource *mui = NULL;
HMODULE hmod;
HRSRC hrsrc;
TRACE( "%lu, %s, %p, %p\n", flags, debugstr_w(path), info, size );
if (!path || !size || (*size && !info) ||
(info && (*size < sizeof(*info) || info->dwSize != *size ||
info->dwVersion != MUI_FILEINFO_VERSION)))
{
if (size) *size = 0;
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (!flags) flags = MUI_QUERY_TYPE | MUI_QUERY_CHECKSUM;
hmod = LoadLibraryExW( path, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE );
if (!hmod) return FALSE;
hrsrc = FindResourceW( hmod, MAKEINTRESOURCEW(1), L"MUI" );
if (hrsrc)
{
mui = LockResource( LoadResource(hmod, hrsrc) );
if (mui) mui_size = SizeofResource( hmod, hrsrc );
if (!mui || !validate_mui_resource( mui, mui_size ))
{
FreeLibrary( hmod );
return FALSE;
}
if (mui->file_type & (MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN >> 1))
type = MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN;
else if (mui->file_type & (MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI >> 1))
type = MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI;
}
if (type == MUI_FILETYPE_NOT_LANGUAGE_NEUTRAL)
{
FreeLibrary( hmod );
if (!info)
{
*size = sizeof(*info);
return TRUE;
}
if (info->dwSize < sizeof(*info))
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
memset( info, 0, sizeof(*info) );
info->dwSize = *size;
info->dwVersion = MUI_FILEINFO_VERSION;
if (flags & MUI_QUERY_TYPE) info->dwFileType = type;
return TRUE;
}
off = offsetof(FILEMUIINFO, abBuffer);
if (flags & MUI_QUERY_LANGUAGE_NAME)
{
off += type == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN ?
mui->fallback_lang_size : mui->lang_size;
}
if (flags & MUI_QUERY_RESOURCE_TYPES)
{
if (type == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN)
off += mui->ln_type_name_size + mui->ln_type_id_size;
off += mui->mui_type_name_size + mui->mui_type_id_size;
}
if (off < sizeof(*info)) off = sizeof(*info);
if (!info || info->dwSize < off)
{
FreeLibrary( hmod );
*size = off;
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
off = 0;
memset( info, 0, sizeof(*info) );
info->dwSize = *size;
info->dwVersion = MUI_FILEINFO_VERSION;
if (flags & MUI_QUERY_TYPE) info->dwFileType = type;
if (flags & MUI_QUERY_CHECKSUM)
{
memcpy( info->pChecksum, mui->checksum, sizeof(info->pChecksum) );
memcpy( info->pServiceChecksum, mui->service_checksum, sizeof(info->pServiceChecksum) );
}
if (flags & MUI_QUERY_LANGUAGE_NAME)
{
if (type == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN && mui->fallback_lang_off)
{
info->dwLanguageNameOffset = offsetof(FILEMUIINFO, abBuffer);
memcpy(info->abBuffer, ((BYTE *)mui) + mui->fallback_lang_off,
mui->fallback_lang_size);
off += mui->fallback_lang_size;
}
if (type == MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI && mui->lang_off)
{
info->dwLanguageNameOffset = offsetof(FILEMUIINFO, abBuffer);
memcpy(info->abBuffer, ((BYTE *)mui) + mui->lang_off, mui->lang_size);
off += mui->lang_size;
}
}
if (flags & MUI_QUERY_RESOURCE_TYPES && type & MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN)
{
if (mui->ln_type_id_size && mui->ln_type_id_off)
{
info->dwTypeIDMainSize = mui->ln_type_id_size / sizeof(DWORD);
info->dwTypeIDMainOffset = offsetof(FILEMUIINFO, abBuffer[off]);
memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->ln_type_id_off, mui->ln_type_id_size);
off += mui->ln_type_id_size;
}
if (mui->ln_type_name_off)
{
info->dwTypeNameMainOffset = offsetof(FILEMUIINFO, abBuffer[off]);
memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->ln_type_name_off, mui->ln_type_name_size);
off += mui->ln_type_name_size;
}
if (mui->mui_type_id_size && mui->mui_type_id_off)
{
info->dwTypeIDMUISize = mui->mui_type_id_size / sizeof(DWORD);
info->dwTypeIDMUIOffset = offsetof(FILEMUIINFO, abBuffer[off]);
memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->mui_type_id_off, mui->mui_type_id_size);
off += mui->mui_type_id_size;
}
if (mui->mui_type_name_off)
{
info->dwTypeNameMUIOffset = offsetof(FILEMUIINFO, abBuffer[off]);
memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->mui_type_name_off, mui->mui_type_name_size);
off += mui->mui_type_name_size;
}
}
else if(flags & MUI_QUERY_RESOURCE_TYPES)
{
if (mui->ln_type_id_size && mui->ln_type_id_off)
{
info->dwTypeIDMUISize = mui->ln_type_id_size / sizeof(DWORD);
info->dwTypeIDMUIOffset = offsetof(FILEMUIINFO, abBuffer[off]);
memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->ln_type_id_off, mui->ln_type_id_size);
off += mui->ln_type_id_size;
}
if (mui->ln_type_name_off)
{
info->dwTypeNameMUIOffset = offsetof(FILEMUIINFO, abBuffer[off]);
memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->ln_type_name_off, mui->ln_type_name_size);
off += mui->ln_type_name_size;
}
}
FreeLibrary( hmod );
return TRUE;
}

View File

@ -694,8 +694,9 @@ static void check_mft_set_input_type_required_(int line, IMFTransform *transform
ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
}
#define check_mft_set_input_type(a, b) check_mft_set_input_type_(__LINE__, a, b, FALSE)
static void check_mft_set_input_type_(int line, IMFTransform *transform, const struct attribute_desc *attributes, BOOL todo)
#define check_mft_set_input_type(a, b, c) check_mft_set_input_type_(__LINE__, a, b, c, FALSE)
static void check_mft_set_input_type_(int line, IMFTransform *transform, const struct attribute_desc *attributes,
HRESULT expect_hr, BOOL todo)
{
IMFMediaType *media_type;
HRESULT hr;
@ -705,10 +706,10 @@ static void check_mft_set_input_type_(int line, IMFTransform *transform, const s
init_media_type(media_type, attributes, -1);
hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr);
ok_(__FILE__, line)(hr == expect_hr, "SetInputType returned %#lx.\n", hr);
hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
todo_wine_if(todo)
ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr);
ok_(__FILE__, line)(hr == expect_hr, "SetInputType returned %#lx.\n", hr);
IMFMediaType_Release(media_type);
}
@ -2154,7 +2155,7 @@ static void test_aac_encoder(void)
check_mft_get_output_current_type(transform, expect_output_type_desc);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type(transform, expect_input_type_desc);
check_mft_get_input_stream_info(transform, S_OK, &input_info);
@ -2412,7 +2413,7 @@ static void test_aac_decoder_subtype(const struct attribute_desc *input_type_des
check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type(transform, input_type_desc);
/* check new output media types */
@ -2920,7 +2921,7 @@ static void test_wma_encoder(void)
check_mft_get_output_current_type(transform, expect_output_type_desc);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type(transform, expect_input_type_desc);
check_mft_get_input_stream_info(transform, S_OK, &input_info);
@ -3235,7 +3236,7 @@ static void test_wma_decoder(void)
check_mft_get_output_current_type_(__LINE__, transform, NULL, TRUE, FALSE);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, TRUE, FALSE);
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
@ -3809,6 +3810,32 @@ static void test_h264_encoder(void)
{.subtype = &MFVideoFormat_H264},
},
};
static const media_type_desc default_outputs[] =
{
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
},
};
static const media_type_desc default_inputs[] =
{
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
},
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
},
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
},
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
},
};
static const struct attribute_desc expect_transform_attributes[] =
{
ATTR_UINT32(MFT_ENCODER_SUPPORTS_CONFIG_EVENT, 1),
@ -3854,9 +3881,11 @@ static void test_h264_encoder(void)
static const MFT_OUTPUT_STREAM_INFO expect_output_info = {.cbSize = 0x8000};
MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_H264};
MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_NV12};
IMFMediaType *media_type;
IMFTransform *transform;
HRESULT hr;
ULONG ret;
DWORD i;
hr = CoInitialize(NULL);
ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
@ -3874,7 +3903,10 @@ static void test_h264_encoder(void)
check_mft_get_info(class_id, &expect_mft_info);
hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
todo_wine
ok(hr == S_OK, "CoCreateInstance returned %#lx.\n", hr);
if (hr != S_OK)
goto failed;
check_interface(transform, &IID_IMFTransform, TRUE);
check_interface(transform, &IID_IMediaObject, FALSE);
@ -3885,17 +3917,49 @@ static void test_h264_encoder(void)
check_mft_get_input_stream_info(transform, S_OK, NULL);
check_mft_get_output_stream_info(transform, S_OK, NULL);
/* No input type is available before an output type is set. */
hr = IMFTransform_GetInputAvailableType(transform, 0, 0, &media_type);
ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputAvailableType returned %#lx\n", hr);
check_mft_set_input_type(transform, input_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
check_mft_get_input_current_type(transform, NULL);
/* Check available output types. */
i = -1;
while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
{
winetest_push_context("out %lu", i);
ok(hr == S_OK, "GetOutputAvailableType returned %#lx.\n", hr);
check_media_type(media_type, default_outputs[i], -1);
ret = IMFMediaType_Release(media_type);
ok(ret == 0, "Release returned %lu\n", ret);
winetest_pop_context();
}
ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx.\n", hr);
ok(i == ARRAY_SIZE(default_outputs), "%lu output media types.\n", i);
check_mft_set_output_type_required(transform, output_type_desc);
check_mft_set_output_type(transform, output_type_desc, S_OK);
check_mft_get_output_current_type(transform, expect_output_type_desc);
check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
/* Input types can now be enumerated. */
i = -1;
while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
{
winetest_push_context("out %lu", i);
ok(hr == S_OK, "IMFTransform_GetInputAvailableType returned %#lx\n", hr);
check_media_type(media_type, default_inputs[i], -1);
ret = IMFMediaType_Release(media_type);
ok(ret == 0, "Release returned %lu\n", ret);
winetest_pop_context();
}
ok(hr == MF_E_NO_MORE_TYPES, "IMFTransform_GetInputAvailableType returned %#lx\n", hr);
ok(i == ARRAY_SIZE(default_inputs), "%lu input media types\n", i);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type(transform, expect_input_type_desc);
check_mft_get_output_current_type(transform, expect_output_type_desc);
check_mft_get_input_stream_info(transform, S_OK, NULL);
check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
ret = IMFTransform_Release(transform);
ok(ret == 0, "Release returned %lu\n", ret);
@ -4294,7 +4358,7 @@ static void test_h264_decoder(void)
ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
check_mft_get_input_stream_info(transform, S_OK, &input_info);
@ -4971,7 +5035,7 @@ static void test_audio_convert(void)
check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
@ -5446,7 +5510,7 @@ static void test_wmv_encoder(void)
check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
check_mft_set_output_type_required(transform, output_type_desc);
@ -6034,7 +6098,7 @@ static void test_wmv_decoder(void)
check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
i = -1;
@ -7159,7 +7223,7 @@ static void test_color_convert(void)
ok(i == 20, "%lu input media types\n", i);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type_(__LINE__, transform, expect_input_type_desc, FALSE, TRUE);
for (i = 0; i < ARRAY_SIZE(color_conversion_tests); i++)
@ -7939,7 +8003,7 @@ static void test_video_processor(void)
ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
/* MFVideoFormat_ABGR32 isn't supported by the video processor in non-D3D mode */
check_mft_set_input_type(transform, nv12_default_stride);
check_mft_set_input_type(transform, nv12_default_stride, S_OK);
hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
ok(hr == S_OK, "got %#lx\n", hr);
@ -7961,7 +8025,7 @@ static void test_video_processor(void)
winetest_push_context("transform #%lu", i);
check_mft_set_input_type_required(transform, test->input_type_desc);
check_mft_set_input_type(transform, test->input_type_desc);
check_mft_set_input_type(transform, test->input_type_desc, S_OK);
check_mft_get_input_current_type(transform, test->input_type_desc);
if (i >= 15)
@ -8111,13 +8175,13 @@ skip_test:
&IID_IMFTransform, (void **)&transform);
ok(hr == S_OK, "got hr %#lx\n", hr);
check_mft_set_input_type(transform, nv12_no_aperture);
check_mft_set_input_type(transform, nv12_no_aperture, S_OK);
check_mft_get_input_current_type(transform, nv12_no_aperture);
check_mft_set_output_type(transform, rgb32_no_aperture, S_OK);
check_mft_get_output_current_type(transform, rgb32_no_aperture);
check_mft_set_input_type_(__LINE__, transform, nv12_with_aperture, TRUE);
check_mft_set_input_type_(__LINE__, transform, nv12_with_aperture, S_OK, TRUE);
check_mft_get_input_current_type_(__LINE__, transform, nv12_with_aperture, TRUE, FALSE);
/* output type is the same as before */
@ -8376,7 +8440,7 @@ static void test_mp3_decoder(void)
check_mft_get_output_current_type(transform, NULL);
check_mft_set_input_type_required(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc);
check_mft_set_input_type(transform, input_type_desc, S_OK);
check_mft_get_input_current_type(transform, expect_input_type_desc);
check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
@ -9427,7 +9491,7 @@ static void test_video_processor_with_dxgi_manager(void)
/* check RGB32 output aperture cropping with D3D buffers */
check_mft_set_input_type(transform, nv12_with_aperture);
check_mft_set_input_type(transform, nv12_with_aperture, S_OK);
check_mft_set_output_type_(__LINE__, transform, rgb32_no_aperture, S_OK, TRUE);
load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
@ -9495,7 +9559,7 @@ static void test_video_processor_with_dxgi_manager(void)
skip_rgb32:
/* check ABGR32 output with D3D buffers */
check_mft_set_input_type(transform, nv12_with_aperture);
check_mft_set_input_type(transform, nv12_with_aperture, S_OK);
check_mft_set_output_type_(__LINE__, transform, abgr32_no_aperture, S_OK, TRUE);
load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);

View File

@ -117,7 +117,7 @@ static HRESULT get_periods(struct audio_client *client,
return params.result;
}
static HRESULT adjust_timing(struct audio_client *client,
static HRESULT adjust_timing(struct audio_client *client, const BOOLEAN force_def_period,
REFERENCE_TIME *duration, REFERENCE_TIME *period,
const AUDCLNT_SHAREMODE mode, const DWORD flags,
const WAVEFORMATEX *fmt)
@ -133,28 +133,31 @@ static HRESULT adjust_timing(struct audio_client *client,
TRACE("Device periods: %lu default and %lu minimum\n", (ULONG)def_period, (ULONG)min_period);
if (mode == AUDCLNT_SHAREMODE_SHARED) {
*period = def_period;
if (*period == 0 || force_def_period)
*period = def_period;
else if (*period < min_period)
return AUDCLNT_E_INVALID_DEVICE_PERIOD;
if (*duration < 3 * *period)
*duration = 3 * *period;
} else {
const WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE *)fmt;
if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
(fmtex->dwChannelMask == 0 || fmtex->dwChannelMask & SPEAKER_RESERVED))
hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
return AUDCLNT_E_UNSUPPORTED_FORMAT;
else {
if (*period == 0)
*period = def_period;
if (*period < min_period || *period > 5000000)
hr = AUDCLNT_E_INVALID_DEVICE_PERIOD;
return AUDCLNT_E_INVALID_DEVICE_PERIOD;
else if (*duration > 20000000) /* The smaller the period, the lower this limit. */
hr = AUDCLNT_E_BUFFER_SIZE_ERROR;
return AUDCLNT_E_BUFFER_SIZE_ERROR;
else if (flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) {
if (*duration != *period)
hr = AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL;
return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL;
FIXME("EXCLUSIVE mode with EVENTCALLBACK\n");
hr = AUDCLNT_E_DEVICE_IN_USE;
return AUDCLNT_E_DEVICE_IN_USE;
} else if (*duration < 8 * *period)
*duration = 8 * *period; /* May grow above 2s. */
}
@ -355,6 +358,100 @@ skip:
return wcsdup(name);
}
static HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_period,
const AUDCLNT_SHAREMODE mode, const DWORD flags,
REFERENCE_TIME duration, REFERENCE_TIME period,
const WAVEFORMATEX *fmt, const GUID *sessionguid)
{
struct create_stream_params params;
UINT32 i, channel_count;
stream_handle stream;
WCHAR *name;
if (!fmt)
return E_POINTER;
dump_fmt(fmt);
if (mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
return E_INVALIDARG;
if (flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS |
AUDCLNT_STREAMFLAGS_LOOPBACK |
AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
AUDCLNT_STREAMFLAGS_NOPERSIST |
AUDCLNT_STREAMFLAGS_RATEADJUST |
AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED |
AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE |
AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED |
AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY |
AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM)) {
FIXME("Unknown flags: %08lx\n", flags);
return E_INVALIDARG;
}
if (FAILED(params.result = adjust_timing(client, force_def_period, &duration, &period, mode, flags, fmt)))
return params.result;
sessions_lock();
if (client->stream) {
sessions_unlock();
return AUDCLNT_E_ALREADY_INITIALIZED;
}
if (FAILED(params.result = main_loop_start())) {
sessions_unlock();
return params.result;
}
params.name = name = get_application_name();
params.device = client->device_name;
params.flow = client->dataflow;
params.share = mode;
params.flags = flags;
params.duration = duration;
params.period = period;
params.fmt = fmt;
params.channel_count = &channel_count;
params.stream = &stream;
wine_unix_call(create_stream, &params);
free(name);
if (FAILED(params.result)) {
sessions_unlock();
return params.result;
}
if (!(client->vols = malloc(channel_count * sizeof(*client->vols)))) {
params.result = E_OUTOFMEMORY;
goto exit;
}
for (i = 0; i < channel_count; i++)
client->vols[i] = 1.f;
params.result = get_audio_session(sessionguid, client->parent, channel_count, &client->session);
exit:
if (FAILED(params.result)) {
stream_release(stream, NULL);
free(client->vols);
client->vols = NULL;
} else {
list_add_tail(&client->session->clients, &client->entry);
client->stream = stream;
client->channel_count = channel_count;
set_stream_volumes(client);
}
sessions_unlock();
return params.result;
}
static HRESULT WINAPI capture_QueryInterface(IAudioCaptureClient *iface, REFIID riid, void **ppv)
{
struct audio_client *This = impl_from_IAudioCaptureClient(iface);
@ -537,97 +634,12 @@ static HRESULT WINAPI client_Initialize(IAudioClient3 *iface, AUDCLNT_SHAREMODE
const WAVEFORMATEX *fmt, const GUID *sessionguid)
{
struct audio_client *This = impl_from_IAudioClient3(iface);
struct create_stream_params params;
UINT32 i, channel_count;
stream_handle stream;
WCHAR *name;
TRACE("(%p)->(%x, %lx, %s, %s, %p, %s)\n", This, mode, flags, wine_dbgstr_longlong(duration),
wine_dbgstr_longlong(period), fmt,
debugstr_guid(sessionguid));
if (!fmt)
return E_POINTER;
dump_fmt(fmt);
if (mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
return E_INVALIDARG;
if (flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS |
AUDCLNT_STREAMFLAGS_LOOPBACK |
AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
AUDCLNT_STREAMFLAGS_NOPERSIST |
AUDCLNT_STREAMFLAGS_RATEADJUST |
AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED |
AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE |
AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED |
AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY |
AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM)) {
FIXME("Unknown flags: %08lx\n", flags);
return E_INVALIDARG;
}
if (FAILED(params.result = adjust_timing(This, &duration, &period, mode, flags, fmt)))
return params.result;
sessions_lock();
if (This->stream) {
sessions_unlock();
return AUDCLNT_E_ALREADY_INITIALIZED;
}
if (FAILED(params.result = main_loop_start())) {
sessions_unlock();
return params.result;
}
params.name = name = get_application_name();
params.device = This->device_name;
params.flow = This->dataflow;
params.share = mode;
params.flags = flags;
params.duration = duration;
params.period = period;
params.fmt = fmt;
params.channel_count = &channel_count;
params.stream = &stream;
wine_unix_call(create_stream, &params);
free(name);
if (FAILED(params.result)) {
sessions_unlock();
return params.result;
}
if (!(This->vols = malloc(channel_count * sizeof(*This->vols)))) {
params.result = E_OUTOFMEMORY;
goto exit;
}
for (i = 0; i < channel_count; i++)
This->vols[i] = 1.f;
params.result = get_audio_session(sessionguid, This->parent, channel_count, &This->session);
exit:
if (FAILED(params.result)) {
stream_release(stream, NULL);
free(This->vols);
This->vols = NULL;
} else {
list_add_tail(&This->session->clients, &This->entry);
This->stream = stream;
This->channel_count = channel_count;
set_stream_volumes(This);
}
sessions_unlock();
return params.result;
return stream_init(This, TRUE, mode, flags, duration, period, fmt, sessionguid);
}
static HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *out)
@ -990,17 +1002,23 @@ static HRESULT WINAPI client_GetSharedModeEnginePeriod(IAudioClient3 *iface,
UINT32 *max_period_frames)
{
struct audio_client *This = impl_from_IAudioClient3(iface);
FIXME("(%p)->(%p, %p, %p, %p, %p) - partial stub\n",
REFERENCE_TIME def_period, min_period;
HRESULT hr;
TRACE("(%p)->(%p, %p, %p, %p, %p)\n",
This, format, default_period_frames,
unit_period_frames, min_period_frames,
max_period_frames);
*default_period_frames =
*min_period_frames =
*max_period_frames =
format->nSamplesPerSec / 100; /* ~10ms */
*unit_period_frames = 1;
return S_OK;
if (FAILED(hr = get_periods(This, &def_period, &min_period)))
return hr;
*default_period_frames = def_period * format->nSamplesPerSec / (REFERENCE_TIME)10000000;
*min_period_frames = min_period * format->nSamplesPerSec / (REFERENCE_TIME)10000000;
*max_period_frames = *default_period_frames;
*unit_period_frames = 1;
return hr;
}
static HRESULT WINAPI client_GetCurrentSharedModeEnginePeriod(IAudioClient3 *iface,
@ -1008,8 +1026,18 @@ static HRESULT WINAPI client_GetCurrentSharedModeEnginePeriod(IAudioClient3 *ifa
UINT32 *cur_period_frames)
{
struct audio_client *This = impl_from_IAudioClient3(iface);
FIXME("(%p)->(%p, %p) - stub\n", This, cur_format, cur_period_frames);
return E_NOTIMPL;
UINT32 dummy;
HRESULT hr;
TRACE("(%p)->(%p, %p)\n", This, cur_format, cur_period_frames);
if (!cur_format || !cur_period_frames)
return E_POINTER;
if (FAILED(hr = client_GetMixFormat(iface, cur_format)))
return hr;
return client_GetSharedModeEnginePeriod(iface, *cur_format, cur_period_frames, &dummy, &dummy, &dummy);
}
static HRESULT WINAPI client_InitializeSharedAudioStream(IAudioClient3 *iface, DWORD flags,
@ -1018,14 +1046,16 @@ static HRESULT WINAPI client_InitializeSharedAudioStream(IAudioClient3 *iface, D
const GUID *session_guid)
{
struct audio_client *This = impl_from_IAudioClient3(iface);
REFERENCE_TIME duration;
FIXME("(%p)->(0x%lx, %u, %p, %s) - partial stub\n", This, flags, period_frames, format, debugstr_guid(session_guid));
REFERENCE_TIME period;
TRACE("(%p)->(0x%lx, %u, %p, %s)\n", This, flags, period_frames, format, debugstr_guid(session_guid));
if (!format)
return E_POINTER;
duration = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec;
return client_Initialize(iface, AUDCLNT_SHAREMODE_SHARED, flags, duration, 0, format, session_guid);
period = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec;
return stream_init(This, FALSE, AUDCLNT_SHAREMODE_SHARED, flags, 0, period, format, session_guid);
}
const IAudioClient3Vtbl AudioClient3_Vtbl =

View File

@ -50,6 +50,8 @@ struct recordset
CursorTypeEnum cursor_type;
IRowset *row_set;
EditModeEnum editmode;
LONG cache_size;
ADO_LONGPTR max_records;
VARIANT filter;
DBTYPE *columntypes;
@ -1449,14 +1451,20 @@ static HRESULT WINAPI recordset_put_Bookmark( _Recordset *iface, VARIANT bookmar
static HRESULT WINAPI recordset_get_CacheSize( _Recordset *iface, LONG *size )
{
FIXME( "%p, %p\n", iface, size );
return E_NOTIMPL;
struct recordset *recordset = impl_from_Recordset( iface );
TRACE( "%p, %p\n", iface, size );
*size = recordset->cache_size;
return S_OK;
}
static HRESULT WINAPI recordset_put_CacheSize( _Recordset *iface, LONG size )
{
FIXME( "%p, %ld\n", iface, size );
return E_NOTIMPL;
struct recordset *recordset = impl_from_Recordset( iface );
TRACE( "%p, %ld\n", iface, size );
recordset->cache_size = size;
return S_OK;
}
static HRESULT WINAPI recordset_get_CursorType( _Recordset *iface, CursorTypeEnum *cursor_type )
@ -1525,14 +1533,20 @@ static HRESULT WINAPI recordset_put_LockType( _Recordset *iface, LockTypeEnum lo
static HRESULT WINAPI recordset_get_MaxRecords( _Recordset *iface, ADO_LONGPTR *max_records )
{
FIXME( "%p, %p\n", iface, max_records );
return E_NOTIMPL;
struct recordset *recordset = impl_from_Recordset( iface );
TRACE( "%p, %p\n", iface, max_records );
*max_records = recordset->max_records;
return S_OK;
}
static HRESULT WINAPI recordset_put_MaxRecords( _Recordset *iface, ADO_LONGPTR max_records )
{
FIXME( "%p, %Id\n", iface, max_records );
return E_NOTIMPL;
struct recordset *recordset = impl_from_Recordset( iface );
TRACE( "%p, %Id\n", iface, max_records );
recordset->max_records = max_records;
return S_OK;
}
static HRESULT WINAPI recordset_get_RecordCount( _Recordset *iface, ADO_LONGPTR *count )
@ -2792,6 +2806,8 @@ HRESULT Recordset_create( void **obj )
recordset->cursor_type = adOpenForwardOnly;
recordset->row_set = NULL;
recordset->editmode = adEditNone;
recordset->cache_size = 1;
recordset->max_records = 0;
VariantInit( &recordset->filter );
recordset->columntypes = NULL;
recordset->haccessors = NULL;

View File

@ -53,7 +53,7 @@ static void test_Recordset(void)
Properties *props;
Property *prop;
LONG count, state;
ADO_LONGPTR rec_count;
ADO_LONGPTR rec_count, max_records;
VARIANT missing, val, index;
CursorLocationEnum location;
CursorTypeEnum cursor;
@ -61,6 +61,7 @@ static void test_Recordset(void)
HRESULT hr;
VARIANT bookmark, filter, active;
EditModeEnum editmode;
LONG cache_size;
hr = CoCreateInstance( &CLSID_Recordset, NULL, CLSCTX_INPROC_SERVER, &IID__Recordset, (void **)&recordset );
ok( hr == S_OK, "got %08lx\n", hr );
@ -111,6 +112,36 @@ static void test_Recordset(void)
ok( hr == S_OK, "got %08lx\n", hr );
ok( cursor == adOpenForwardOnly, "got %d\n", cursor );
cache_size = 0;
hr = _Recordset_get_CacheSize( recordset, &cache_size );
ok( hr == S_OK, "got %08lx\n", hr );
ok( cache_size == 1, "got %ld\n", cache_size );
hr = _Recordset_put_CacheSize( recordset, 5 );
ok( hr == S_OK, "got %08lx\n", hr );
hr = _Recordset_get_CacheSize( recordset, &cache_size );
ok( hr == S_OK, "got %08lx\n", hr );
ok( cache_size == 5, "got %ld\n", cache_size );
hr = _Recordset_put_CacheSize( recordset, 1 );
ok( hr == S_OK, "got %08lx\n", hr );
max_records = 0;
hr = _Recordset_get_MaxRecords( recordset, &max_records );
ok( hr == S_OK, "got %08lx\n", hr );
ok( max_records == 0, "got %Id\n", max_records );
hr = _Recordset_put_MaxRecords( recordset, 5 );
ok( hr == S_OK, "got %08lx\n", hr );
hr = _Recordset_get_MaxRecords( recordset, &max_records );
ok( hr == S_OK, "got %08lx\n", hr );
ok( max_records == 5, "got %Id\n", max_records );
hr = _Recordset_put_MaxRecords( recordset, 0 );
ok( hr == S_OK, "got %08lx\n", hr );
editmode = -1;
hr = _Recordset_get_EditMode( recordset, &editmode );
ok( hr == MAKE_ADO_HRESULT( adErrObjectClosed ), "got %08lx\n", hr );

View File

@ -787,7 +787,7 @@ static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags,
return hres;
}
hres = IDispatchEx_QueryInterface(&This->IDispatchEx_iface, tid_ids[func->tid], (void**)&unk);
hres = IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface, tid_ids[func->tid], (void**)&unk);
if(FAILED(hres)) {
ERR("Could not get iface %s: %08lx\n", debugstr_mshtml_guid(tid_ids[func->tid]), hres);
return E_FAIL;
@ -799,6 +799,138 @@ static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags,
return hres;
}
static HRESULT get_disp_prop(IDispatchEx *dispex, const WCHAR *name, LCID lcid, VARIANT *res,
EXCEPINFO *ei, IServiceProvider *caller)
{
DISPPARAMS dp = { 0 };
DISPID dispid;
HRESULT hres;
BSTR bstr;
if(!(bstr = SysAllocString(name)))
return E_OUTOFMEMORY;
hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid);
SysFreeString(bstr);
if(SUCCEEDED(hres))
hres = IDispatchEx_InvokeEx(dispex, dispid, lcid, DISPATCH_PROPERTYGET, &dp, res, ei, caller);
return hres;
}
static HRESULT function_apply(func_disp_t *func, DISPPARAMS *dp, LCID lcid, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
{
IWineJSDispatchHost *this_iface;
DISPPARAMS params = { 0 };
IDispatchEx *array = NULL;
UINT argc = 0;
VARIANT *arg;
HRESULT hres;
arg = dp->rgvarg + dp->cArgs - 1;
if(dp->cArgs < 1 || V_VT(arg) != VT_DISPATCH || !V_DISPATCH(arg))
return CTL_E_ILLEGALFUNCTIONCALL;
hres = IDispatch_QueryInterface(V_DISPATCH(arg), &IID_IWineJSDispatchHost, (void**)&this_iface);
if(FAILED(hres))
return CTL_E_ILLEGALFUNCTIONCALL;
if(dp->cArgs >= 2) {
VARIANT length;
arg--;
if(V_VT(arg) != VT_DISPATCH) {
hres = CTL_E_ILLEGALFUNCTIONCALL;
goto fail;
}
/* FIXME: Native checks if it's an acual JS array. */
hres = IDispatch_QueryInterface(V_DISPATCH(arg), &IID_IDispatchEx, (void**)&array);
if(FAILED(hres))
goto fail;
V_VT(&length) = VT_EMPTY;
hres = get_disp_prop(array, L"length", lcid, &length, ei, caller);
if(FAILED(hres)) {
if(hres == DISP_E_UNKNOWNNAME)
hres = CTL_E_ILLEGALFUNCTIONCALL;
goto fail;
}
if(V_VT(&length) != VT_I4) {
VARIANT tmp = length;
hres = change_type(&length, &tmp, VT_I4, caller);
if(FAILED(hres)) {
hres = CTL_E_ILLEGALFUNCTIONCALL;
goto fail;
}
}
if(V_I4(&length) < 0) {
hres = CTL_E_ILLEGALFUNCTIONCALL;
goto fail;
}
params.cArgs = V_I4(&length);
/* alloc new params */
if(params.cArgs) {
if(!(params.rgvarg = malloc(params.cArgs * sizeof(VARIANTARG)))) {
hres = E_OUTOFMEMORY;
goto fail;
}
for(argc = 0; argc < params.cArgs; argc++) {
WCHAR buf[12];
arg = params.rgvarg + params.cArgs - argc - 1;
swprintf(buf, ARRAY_SIZE(buf), L"%u", argc);
hres = get_disp_prop(array, buf, lcid, arg, ei, caller);
if(FAILED(hres)) {
if(hres == DISP_E_UNKNOWNNAME) {
V_VT(arg) = VT_EMPTY;
continue;
}
goto fail;
}
}
}
}
hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, &params, res, ei, caller);
fail:
while(argc--)
VariantClear(&params.rgvarg[params.cArgs - argc - 1]);
free(params.rgvarg);
if(array)
IDispatchEx_Release(array);
IWineJSDispatchHost_Release(this_iface);
return hres == E_UNEXPECTED ? CTL_E_ILLEGALFUNCTIONCALL : hres;
}
static HRESULT function_call(func_disp_t *func, DISPPARAMS *dp, LCID lcid, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
{
DISPPARAMS params = { dp->rgvarg, NULL, dp->cArgs - 1, 0 };
IWineJSDispatchHost *this_iface;
VARIANT *arg;
HRESULT hres;
arg = dp->rgvarg + dp->cArgs - 1;
if(dp->cArgs < 1 || V_VT(arg) != VT_DISPATCH || !V_DISPATCH(arg))
return CTL_E_ILLEGALFUNCTIONCALL;
hres = IDispatch_QueryInterface(V_DISPATCH(arg), &IID_IWineJSDispatchHost, (void**)&this_iface);
if(FAILED(hres))
return CTL_E_ILLEGALFUNCTIONCALL;
hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, &params, res, ei, caller);
IWineJSDispatchHost_Release(this_iface);
return (hres == E_UNEXPECTED) ? CTL_E_ILLEGALFUNCTIONCALL : hres;
}
static const struct {
const WCHAR *name;
HRESULT (*invoke)(func_disp_t*,DISPPARAMS*,LCID,VARIANT*,EXCEPINFO*,IServiceProvider*);
} function_props[] = {
{ L"apply", function_apply },
{ L"call", function_call }
};
static inline func_disp_t *impl_from_DispatchEx(DispatchEx *iface)
{
return CONTAINING_RECORD(iface, func_disp_t, dispex);
@ -866,9 +998,58 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
return hres;
}
static HRESULT function_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
{
DWORD i;
for(i = 0; i < ARRAY_SIZE(function_props); i++) {
if((flags & fdexNameCaseInsensitive) ? wcsicmp(name, function_props[i].name) : wcscmp(name, function_props[i].name))
continue;
*dispid = MSHTML_DISPID_CUSTOM_MIN + i;
return S_OK;
}
return DISP_E_UNKNOWNNAME;
}
static HRESULT function_get_name(DispatchEx *dispex, DISPID id, BSTR *name)
{
DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN;
if(idx >= ARRAY_SIZE(function_props))
return DISP_E_MEMBERNOTFOUND;
return (*name = SysAllocString(function_props[idx].name)) ? S_OK : E_OUTOFMEMORY;
}
static HRESULT function_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
{
func_disp_t *This = impl_from_DispatchEx(dispex);
DWORD idx = id - MSHTML_DISPID_CUSTOM_MIN;
if(idx >= ARRAY_SIZE(function_props))
return DISP_E_MEMBERNOTFOUND;
switch(flags) {
case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
if(!res)
return E_INVALIDARG;
/* fall through */
case DISPATCH_METHOD:
return function_props[idx].invoke(This, params, lcid, res, ei, caller);
default:
return MSHTML_E_INVALID_PROPERTY;
}
return S_OK;
}
static const dispex_static_data_vtbl_t function_dispex_vtbl = {
.destructor = function_destructor,
.value = function_value,
.get_dispid = function_get_dispid,
.get_name = function_get_name,
.invoke = function_invoke
};
static const tid_t function_iface_tids[] = {0};
@ -916,7 +1097,7 @@ static HRESULT invoke_disp_value(DispatchEx *This, IDispatch *func_disp, LCID lc
memcpy(new_dp.rgvarg+1, dp->rgvarg, dp->cArgs*sizeof(VARIANTARG));
V_VT(new_dp.rgvarg) = VT_DISPATCH;
V_DISPATCH(new_dp.rgvarg) = (IDispatch*)&This->IDispatchEx_iface;
V_DISPATCH(new_dp.rgvarg) = (IDispatch*)&This->IWineJSDispatchHost_iface;
hres = IDispatch_QueryInterface(func_disp, &IID_IDispatchEx, (void**)&dispex);
TRACE(">>>\n");
@ -957,9 +1138,9 @@ static HRESULT get_func_obj_entry(DispatchEx *This, func_info_t *func, func_obj_
if(!entry->func_obj)
return E_OUTOFMEMORY;
IDispatchEx_AddRef(&entry->func_obj->dispex.IDispatchEx_iface);
IWineJSDispatchHost_AddRef(&entry->func_obj->dispex.IWineJSDispatchHost_iface);
V_VT(&entry->val) = VT_DISPATCH;
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface;
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface;
}
*ret = entry;
@ -1082,7 +1263,7 @@ static HRESULT builtin_propget(DispatchEx *This, func_info_t *func, DISPPARAMS *
assert(func->get_vtbl_off);
hres = IDispatchEx_QueryInterface(&This->IDispatchEx_iface, tid_ids[func->tid], (void**)&iface);
hres = IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface, tid_ids[func->tid], (void**)&iface);
if(SUCCEEDED(hres)) {
switch(func->prop_vt) {
#define CASE_VT(vt,type,access) \
@ -1139,7 +1320,7 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS *
v = &tmpv;
}
hres = IDispatchEx_QueryInterface(&This->IDispatchEx_iface, tid_ids[func->tid], (void**)&iface);
hres = IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface, tid_ids[func->tid], (void**)&iface);
if(SUCCEEDED(hres)) {
switch(func->prop_vt) {
#define CASE_VT(vt,type,access) \
@ -1161,8 +1342,8 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS *
return hres;
}
static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp,
VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
static HRESULT call_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp,
VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
{
VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres;
unsigned i, nconv = 0;
@ -1183,7 +1364,7 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP
return E_INVALIDARG;
}
hres = IDispatchEx_QueryInterface(&This->IDispatchEx_iface, tid_ids[func->tid], (void**)&iface);
hres = IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface, tid_ids[func->tid], (void**)&iface);
if(FAILED(hres))
return hres;
@ -1268,7 +1449,7 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP
return V_ERROR(&vhres);
}
static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
EXCEPINFO *ei, IServiceProvider *caller)
{
HRESULT hres;
@ -1288,7 +1469,7 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags,
return E_NOTIMPL;
}
if((IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface != V_DISPATCH(&entry->val)) {
if((IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface != V_DISPATCH(&entry->val)) {
if(!V_DISPATCH(&entry->val)) {
FIXME("Calling null\n");
return E_FAIL;
@ -1299,7 +1480,7 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags,
}
}
hres = invoke_builtin_function(This, func, dp, res, ei, caller);
hres = call_builtin_function(This, func, dp, res, ei, caller);
break;
case DISPATCH_PROPERTYGET: {
func_obj_entry_t *entry;
@ -1365,7 +1546,7 @@ static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD
return hres;
if(func->func_disp_idx >= 0)
return function_invoke(This, func, flags, dp, res, ei, caller);
return invoke_builtin_function(This, func, flags, dp, res, ei, caller);
if(func->hook) {
hres = func->hook(This, flags, dp, res, ei, caller);
@ -1422,7 +1603,7 @@ HRESULT dispex_call_builtin(DispatchEx *dispex, DISPID id, DISPPARAMS *dp,
if(FAILED(hres))
return hres;
return invoke_builtin_function(dispex, func, dp, res, ei, caller);
return call_builtin_function(dispex, func, dp, res, ei, caller);
}
HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
@ -1464,14 +1645,14 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
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.IDispatchEx_iface) {
&& 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.IDispatchEx_iface;
V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface;
IDispatch_AddRef(V_DISPATCH(&entry->val));
*success = VARIANT_TRUE;
return S_OK;
@ -1549,14 +1730,14 @@ static BOOL ensure_real_info(DispatchEx *dispex)
return dispex->info != NULL;
}
static inline DispatchEx *impl_from_IDispatchEx(IDispatchEx *iface)
static inline DispatchEx *impl_from_IWineJSDispatchHost(IWineJSDispatchHost *iface)
{
return CONTAINING_RECORD(iface, DispatchEx, IDispatchEx_iface);
return CONTAINING_RECORD(iface, DispatchEx, IWineJSDispatchHost_iface);
}
static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
static HRESULT WINAPI DispatchEx_QueryInterface(IWineJSDispatchHost *iface, REFIID riid, void **ppv)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
TRACE("%s (%p)->(%s %p)\n", This->info->desc->name, This, debugstr_mshtml_guid(riid), ppv);
@ -1567,12 +1748,14 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid,
}
if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IDispatchEx, riid))
*ppv = &This->IDispatchEx_iface;
*ppv = &This->IWineJSDispatchHost_iface;
else if(IsEqualGUID(&IID_IWineJSDispatchHost, riid))
*ppv = &This->IWineJSDispatchHost_iface;
else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
*ppv = &dispex_ccp;
return S_OK;
}else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
*ppv = &This->IDispatchEx_iface;
*ppv = &This->IWineJSDispatchHost_iface;
return S_OK;
}else if(IsEqualGUID(&IID_IDispatchJS, riid) ||
IsEqualGUID(&IID_UndocumentedScriptIface, riid) ||
@ -1587,24 +1770,24 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid,
}
ret:
IDispatchEx_AddRef(&This->IDispatchEx_iface);
IWineJSDispatchHost_AddRef(&This->IWineJSDispatchHost_iface);
return S_OK;
}
static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
static ULONG WINAPI DispatchEx_AddRef(IWineJSDispatchHost *iface)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->IDispatchEx_iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->IWineJSDispatchHost_iface);
TRACE("%s (%p) ref=%ld\n", This->info->desc->name, This, ref);
return ref;
}
static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
static ULONG WINAPI DispatchEx_Release(IWineJSDispatchHost *iface)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IDispatchEx_iface, &dispex_ccp);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IWineJSDispatchHost_iface, &dispex_ccp);
TRACE("%s (%p) ref=%ld\n", This->info->desc->name, This, ref);
@ -1612,17 +1795,17 @@ static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
* an extra care for objects that need an immediate clean up. See Gecko's
* NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE for details. */
if(!ref && This->info->desc->vtbl->last_release) {
ccref_incr(&This->ccref, (nsISupports*)&This->IDispatchEx_iface);
ccref_incr(&This->ccref, (nsISupports*)&This->IWineJSDispatchHost_iface);
This->info->desc->vtbl->last_release(This);
ccref_decr(&This->ccref, (nsISupports*)&This->IDispatchEx_iface, &dispex_ccp);
ccref_decr(&This->ccref, (nsISupports*)&This->IWineJSDispatchHost_iface, &dispex_ccp);
}
return ref;
}
static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IWineJSDispatchHost *iface, UINT *pctinfo)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
TRACE("%s (%p)->(%p)\n", This->info->desc->name, This, pctinfo);
@ -1630,10 +1813,10 @@ static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pcti
return S_OK;
}
static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
LCID lcid, ITypeInfo **ppTInfo)
static HRESULT WINAPI DispatchEx_GetTypeInfo(IWineJSDispatchHost *iface, UINT iTInfo,
LCID lcid, ITypeInfo **ppTInfo)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
HRESULT hres;
TRACE("%s (%p)->(%u %lu %p)\n", This->info->desc->name, This, iTInfo, lcid, ppTInfo);
@ -1646,11 +1829,11 @@ static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
return S_OK;
}
static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID *rgDispId)
static HRESULT WINAPI DispatchEx_GetIDsOfNames(IWineJSDispatchHost *iface, REFIID riid,
LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID *rgDispId)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
HRESULT hres = S_OK;
TRACE("%s (%p)->(%s %p %u %lu %p)\n", This->info->desc->name, This, debugstr_guid(riid), rgszNames,
@ -1658,27 +1841,27 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
/* Native ignores all cNames > 1, and doesn't even fill them */
if(cNames)
hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[0], 0, rgDispId);
hres = IWineJSDispatchHost_GetDispID(&This->IWineJSDispatchHost_iface, rgszNames[0], 0, rgDispId);
return hres;
}
static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
static HRESULT WINAPI DispatchEx_Invoke(IWineJSDispatchHost *iface, DISPID dispIdMember,
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
TRACE("%s (%p)->(%ld %s %ld %d %p %p %p %p)\n", This->info->desc->name, This, dispIdMember,
debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags, pDispParams,
return IWineJSDispatchHost_InvokeEx(&This->IWineJSDispatchHost_iface, dispIdMember, lcid, wFlags, pDispParams,
pVarResult, pExcepInfo, NULL);
}
static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
static HRESULT WINAPI DispatchEx_GetDispID(IWineJSDispatchHost *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
dynamic_prop_t *dprop = NULL;
HRESULT hres;
@ -1711,10 +1894,10 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
return S_OK;
}
static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
static HRESULT WINAPI DispatchEx_InvokeEx(IWineJSDispatchHost *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
HRESULT hres;
TRACE("%s (%p)->(%lx %lx %x %p %p %p %p)\n", This->info->desc->name, This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
@ -1803,9 +1986,9 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
}
}
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR name, DWORD grfdex)
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IWineJSDispatchHost *iface, BSTR name, DWORD grfdex)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
DISPID id;
HRESULT hres;
@ -1814,7 +1997,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR nam
if(dispex_compat_mode(This) < COMPAT_MODE_IE8 && !This->info->desc->vtbl->delete)
return E_NOTIMPL;
hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, name, grfdex & ~fdexNameEnsure, &id);
hres = IWineJSDispatchHost_GetDispID(&This->IWineJSDispatchHost_iface, name, grfdex & ~fdexNameEnsure, &id);
if(FAILED(hres)) {
compat_mode_t compat_mode = dispex_compat_mode(This);
TRACE("property %s not found\n", debugstr_w(name));
@ -1822,12 +2005,12 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR nam
compat_mode < COMPAT_MODE_IE9 ? hres : S_OK;
}
return IDispatchEx_DeleteMemberByDispID(&This->IDispatchEx_iface, id);
return IWineJSDispatchHost_DeleteMemberByDispID(&This->IWineJSDispatchHost_iface, id);
}
static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IWineJSDispatchHost *iface, DISPID id)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
TRACE("%s (%p)->(%lx)\n", This->info->desc->name, This, id);
@ -1855,16 +2038,16 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID
return S_OK;
}
static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
static HRESULT WINAPI DispatchEx_GetMemberProperties(IWineJSDispatchHost *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
FIXME("%s (%p)->(%lx %lx %p)\n", This->info->desc->name, This, id, grfdexFetch, pgrfdex);
return E_NOTIMPL;
}
static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
static HRESULT WINAPI DispatchEx_GetMemberName(IWineJSDispatchHost *iface, DISPID id, BSTR *pbstrName)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
func_info_t *func;
HRESULT hres;
@ -1917,9 +2100,9 @@ static HRESULT next_dynamic_id(DispatchEx *dispex, DWORD idx, DISPID *ret_id)
return S_OK;
}
static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
static HRESULT WINAPI DispatchEx_GetNextDispID(IWineJSDispatchHost *iface, DWORD grfdex, DISPID id, DISPID *pid)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
func_info_t *func;
HRESULT hres;
@ -1971,14 +2154,31 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex,
return S_FALSE;
}
static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IWineJSDispatchHost *iface, IUnknown **ppunk)
{
DispatchEx *This = impl_from_IDispatchEx(iface);
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
FIXME("%s (%p)->(%p)\n", This->info->desc->name, This, ppunk);
return E_NOTIMPL;
}
static IDispatchExVtbl DispatchExVtbl = {
static HRESULT WINAPI DispatchEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret,
EXCEPINFO *ei, IServiceProvider *caller)
{
DispatchEx *This = impl_from_IWineJSDispatchHost(iface);
func_info_t *func;
HRESULT hres;
TRACE("%s (%p)->(%lx %x %p %p %p %p)\n", This->info->desc->name, This, id, iid, dp, ret, ei, caller);
hres = get_builtin_func(This->info, id, &func);
if(FAILED(hres))
return hres;
if(func->tid != iid || func->func_disp_idx < 0)
return E_UNEXPECTED;
return call_builtin_function(This, func, dp, ret, ei, caller);
}
static IWineJSDispatchHostVtbl JSDispatchHostVtbl = {
DispatchEx_QueryInterface,
DispatchEx_AddRef,
DispatchEx_Release,
@ -1993,12 +2193,13 @@ static IDispatchExVtbl DispatchExVtbl = {
DispatchEx_GetMemberProperties,
DispatchEx_GetMemberName,
DispatchEx_GetNextDispID,
DispatchEx_GetNameSpaceParent
DispatchEx_GetNameSpaceParent,
DispatchEx_CallFunction,
};
static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
{
DispatchEx *This = impl_from_IDispatchEx(p);
DispatchEx *This = impl_from_IWineJSDispatchHost(p);
dynamic_prop_t *prop;
describe_cc_node(&This->ccref, This->info->desc->name, cb);
@ -2018,7 +2219,7 @@ static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTrave
for(iter = This->dynamic_data->func_disps; iter < end; iter++) {
if(!iter->func_obj)
continue;
note_cc_edge((nsISupports*)&iter->func_obj->dispex.IDispatchEx_iface, "func_obj", cb);
note_cc_edge((nsISupports*)&iter->func_obj->dispex.IWineJSDispatchHost_iface, "func_obj", cb);
traverse_variant(&iter->val, "func_val", cb);
}
}
@ -2045,7 +2246,7 @@ void dispex_props_unlink(DispatchEx *This)
if(!iter->func_obj)
continue;
iter->func_obj->obj = NULL;
IDispatchEx_Release(&iter->func_obj->dispex.IDispatchEx_iface);
IWineJSDispatchHost_Release(&iter->func_obj->dispex.IWineJSDispatchHost_iface);
VariantClear(&iter->val);
}
@ -2056,7 +2257,7 @@ void dispex_props_unlink(DispatchEx *This)
static nsresult NSAPI dispex_unlink(void *p)
{
DispatchEx *This = impl_from_IDispatchEx(p);
DispatchEx *This = impl_from_IWineJSDispatchHost(p);
if(This->info->desc->vtbl->unlink)
This->info->desc->vtbl->unlink(This);
@ -2067,7 +2268,7 @@ static nsresult NSAPI dispex_unlink(void *p)
static void NSAPI dispex_delete_cycle_collectable(void *p)
{
DispatchEx *This = impl_from_IDispatchEx(p);
DispatchEx *This = impl_from_IWineJSDispatchHost(p);
dynamic_prop_t *prop;
if(This->info->desc->vtbl->unlink)
@ -2089,7 +2290,7 @@ static void NSAPI dispex_delete_cycle_collectable(void *p)
for(iter = This->dynamic_data->func_disps; iter < This->dynamic_data->func_disps + This->info->func_disp_cnt; iter++) {
if(iter->func_obj) {
iter->func_obj->obj = NULL;
IDispatchEx_Release(&iter->func_obj->dispex.IDispatchEx_iface);
IWineJSDispatchHost_Release(&iter->func_obj->dispex.IWineJSDispatchHost_iface);
}
VariantClear(&iter->val);
}
@ -2122,7 +2323,7 @@ void init_dispatch(DispatchEx *dispex, dispex_static_data_t *data, compat_mode_t
{
assert(compat_mode < COMPAT_MODE_CNT);
dispex->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
dispex->IWineJSDispatchHost_iface.lpVtbl = &JSDispatchHostVtbl;
dispex->dynamic_data = NULL;
ccref_init(&dispex->ccref, 1);

View File

@ -55,7 +55,7 @@ static HRESULT WINAPI HTMLDOMAttribute_get_nodeName(IHTMLDOMAttribute *iface, BS
return *p ? S_OK : E_OUTOFMEMORY;
}
return IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, p);
return IWineJSDispatchHost_GetMemberName(&This->elem->node.event_target.dispex.IWineJSDispatchHost_iface, This->dispid, p);
}
static HRESULT WINAPI HTMLDOMAttribute_put_nodeValue(IHTMLDOMAttribute *iface, VARIANT v)
@ -73,7 +73,7 @@ static HRESULT WINAPI HTMLDOMAttribute_put_nodeValue(IHTMLDOMAttribute *iface, V
memset(&ei, 0, sizeof(ei));
return IDispatchEx_InvokeEx(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, LOCALE_SYSTEM_DEFAULT,
return IWineJSDispatchHost_InvokeEx(&This->elem->node.event_target.dispex.IWineJSDispatchHost_iface, This->dispid, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUT, &dp, &ret, &ei, NULL);
}
@ -110,7 +110,7 @@ static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, V
return S_OK;
}
hres = IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, &name);
hres = IWineJSDispatchHost_GetMemberName(&This->elem->node.event_target.dispex.IWineJSDispatchHost_iface, This->dispid, &name);
if(FAILED(hres))
return hres;

View File

@ -4739,8 +4739,18 @@ static HRESULT WINAPI MarkupServices_CreateMarkupPointer(IMarkupServices *iface,
static HRESULT WINAPI MarkupServices_CreateMarkupContainer(IMarkupServices *iface, IMarkupContainer **ppMarkupContainer)
{
HTMLDocumentNode *This = impl_from_IMarkupServices(iface);
FIXME("(%p)->(%p)\n", This, ppMarkupContainer);
return E_NOTIMPL;
IHTMLDocument2 *frag;
HRESULT hres;
TRACE("(%p)->(%p)\n", This, ppMarkupContainer);
hres = IHTMLDocument3_createDocumentFragment(&This->IHTMLDocument3_iface, &frag);
if(FAILED(hres))
return hres;
IHTMLDocument2_QueryInterface(frag, &IID_IMarkupContainer, (void**)ppMarkupContainer);
IHTMLDocument2_Release(frag);
return S_OK;
}
static HRESULT WINAPI MarkupServices_CreateElement(IMarkupServices *iface,
@ -4813,9 +4823,53 @@ static HRESULT WINAPI MarkupServices_ParseString(IMarkupServices *iface,
OLECHAR *pchHTML, DWORD dwFlags, IMarkupContainer **ppContainerResult,
IMarkupPointer *pPointerStart, IMarkupPointer *pPointerFinish)
{
HRESULT hres;
IMarkupContainer *container;
IHTMLDocument2 *doc;
IHTMLDOMNode *node, *html_node, *new_html_node = NULL;
IHTMLElement *html, *body;
HTMLDocumentNode *This = impl_from_IMarkupServices(iface);
FIXME("(%p)->(%s,%lx,%p,%p,%p)\n", This, debugstr_w(pchHTML), dwFlags, ppContainerResult, pPointerStart, pPointerFinish);
return E_NOTIMPL;
TRACE("(%p)->(%s,%lx,%p,%p,%p)\n", This, debugstr_w(pchHTML), dwFlags, ppContainerResult, pPointerStart, pPointerFinish);
if(dwFlags != 0)
FIXME("flags %lx not implemented.\n", dwFlags);
if(pPointerStart || pPointerFinish) {
FIXME("Pointers not implemented.\n");
return E_NOTIMPL;
}
hres = IMarkupServices_CreateMarkupContainer(iface, &container);
if(FAILED(hres))
return hres;
IMarkupContainer_QueryInterface(container, &IID_IHTMLDocument2, (void**)&doc);
IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDOMNode, (void**)&node);
IHTMLDocument2_createElement(&This->IHTMLDocument2_iface, (BSTR)L"html", &html);
IHTMLElement_put_innerHTML(html, (BSTR)L"<head><title></title></head><body></body>");
IHTMLElement_QueryInterface(html, &IID_IHTMLDOMNode, (void**)&html_node);
IHTMLElement_Release(html);
IHTMLDOMNode_appendChild(node, html_node, &new_html_node);
IHTMLDOMNode_Release(node);
IHTMLDOMNode_Release(html_node);
IHTMLDOMNode_Release(new_html_node);
IHTMLDocument2_get_body(doc, &body);
hres = IHTMLElement_put_innerHTML(body, pchHTML);
if (FAILED(hres))
{
ERR("Failed put_innerHTML hr %#lx\n", hres);
IMarkupContainer_Release(container);
container = NULL;
}
IHTMLDocument2_Release(doc);
IHTMLElement_Release(body);
*ppContainerResult = container;
return hres;
}
static HRESULT WINAPI MarkupServices_ParseGlobal(IMarkupServices *iface,
@ -5529,8 +5583,8 @@ static HRESULT HTMLDocumentNode_location_hook(DispatchEx *dispex, WORD flags, DI
if(!This->window->base.outer_window)
return E_FAIL;
return IDispatchEx_InvokeEx(&This->window->event_target.dispex.IDispatchEx_iface, DISPID_IHTMLWINDOW2_LOCATION,
0, flags, dp, res, ei, caller);
return IWineJSDispatchHost_InvokeEx(&This->window->event_target.dispex.IWineJSDispatchHost_iface,
DISPID_IHTMLWINDOW2_LOCATION, 0, flags, dp, res, ei, caller);
}
static HRESULT HTMLDocumentNode_pre_handle_event(DispatchEx* dispex, DOMEvent *event)

View File

@ -1170,7 +1170,7 @@ static HRESULT set_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, V
return S_OK;
}
return IDispatchEx_InvokeEx(&elem->node.event_target.dispex.IDispatchEx_iface, dispid,
return IWineJSDispatchHost_InvokeEx(&elem->node.event_target.dispex.IWineJSDispatchHost_iface, dispid,
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL);
}
@ -1189,7 +1189,7 @@ static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttr
TRACE("(%p)->(%s %s %08lx)\n", This, debugstr_w(strAttributeName), debugstr_variant(&AttributeValue), lFlags);
if(compat_mode < COMPAT_MODE_IE9 || !This->dom_element) {
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, translate_attr_name(strAttributeName, compat_mode),
hres = IWineJSDispatchHost_GetDispID(&This->node.event_target.dispex.IWineJSDispatchHost_iface, translate_attr_name(strAttributeName, compat_mode),
(lFlags&ATTRFLAG_CASESENSITIVE ? fdexNameCaseSensitive : fdexNameCaseInsensitive) | fdexNameEnsure, &dispid);
if(FAILED(hres))
return hres;
@ -1241,7 +1241,7 @@ HRESULT get_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, VARIANT
DISPPARAMS dispParams = {NULL, NULL, 0, 0};
EXCEPINFO excep;
return IDispatchEx_InvokeEx(&elem->node.event_target.dispex.IDispatchEx_iface, dispid, LOCALE_SYSTEM_DEFAULT,
return IWineJSDispatchHost_InvokeEx(&elem->node.event_target.dispex.IWineJSDispatchHost_iface, dispid, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &dispParams, ret, &excep, NULL);
}
@ -1288,7 +1288,7 @@ static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttr
FIXME("Unsupported flags %lx\n", lFlags);
if(compat_mode < COMPAT_MODE_IE9 || !This->dom_element) {
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, translate_attr_name(strAttributeName, compat_mode),
hres = IWineJSDispatchHost_GetDispID(&This->node.event_target.dispex.IWineJSDispatchHost_iface, translate_attr_name(strAttributeName, compat_mode),
lFlags&ATTRFLAG_CASESENSITIVE ? fdexNameCaseSensitive : fdexNameCaseInsensitive, &dispid);
if(FAILED(hres)) {
V_VT(AttributeValue) = VT_NULL;
@ -1336,7 +1336,7 @@ static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strA
TRACE("(%p)->(%s %lx %p)\n", This, debugstr_w(strAttributeName), lFlags, pfSuccess);
if(compat_mode < COMPAT_MODE_IE9 || !This->dom_element) {
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, translate_attr_name(strAttributeName, compat_mode),
hres = IWineJSDispatchHost_GetDispID(&This->node.event_target.dispex.IWineJSDispatchHost_iface, translate_attr_name(strAttributeName, compat_mode),
lFlags&ATTRFLAG_CASESENSITIVE ? fdexNameCaseSensitive : fdexNameCaseInsensitive, &id);
if(hres == DISP_E_UNKNOWNNAME) {
*pfSuccess = VARIANT_FALSE;
@ -2483,7 +2483,7 @@ static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
if(!String)
return E_INVALIDARG;
hres = IDispatchEx_InvokeEx(&This->node.event_target.dispex.IDispatchEx_iface, DISPID_VALUE,
hres = IWineJSDispatchHost_InvokeEx(&This->node.event_target.dispex.IWineJSDispatchHost_iface, DISPID_VALUE,
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, NULL, &var, NULL, NULL);
if(SUCCEEDED(hres)) {
assert(V_VT(&var) == VT_BSTR);
@ -4429,7 +4429,7 @@ static HRESULT WINAPI HTMLElement4_setAttributeNode(IHTMLElement4 *iface, IHTMLD
return E_INVALIDARG;
}
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface,
hres = IWineJSDispatchHost_GetDispID(&This->node.event_target.dispex.IWineJSDispatchHost_iface,
attr->name, fdexNameCaseInsensitive|fdexNameEnsure, &dispid);
if(FAILED(hres))
return hres;
@ -6399,7 +6399,7 @@ HRESULT HTMLElement_populate_props(DispatchEx *dispex)
continue;
}
hres = IDispatchEx_GetDispID(&dispex->IDispatchEx_iface, name, fdexNameCaseInsensitive, &id);
hres = IWineJSDispatchHost_GetDispID(&dispex->IWineJSDispatchHost_iface, name, fdexNameCaseInsensitive, &id);
if(hres != DISP_E_UNKNOWNNAME) {
nsIDOMAttr_Release(attr);
SysFreeString(name);
@ -7544,7 +7544,7 @@ static HRESULT create_filters_collection(compat_mode_t compat_mode, IHTMLFilters
static HRESULT get_attr_dispid_by_relative_idx(HTMLAttributeCollection *This, LONG *idx, DISPID start, DISPID *dispid)
{
IDispatchEx *dispex = &This->elem->node.event_target.dispex.IDispatchEx_iface;
IWineJSDispatchHost *dispex = &This->elem->node.event_target.dispex.IWineJSDispatchHost_iface;
DISPID id = start;
LONG len = -1;
HRESULT hres;
@ -7552,7 +7552,7 @@ static HRESULT get_attr_dispid_by_relative_idx(HTMLAttributeCollection *This, LO
FIXME("filter non-enumerable attributes out\n");
while(1) {
hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, id, &id);
hres = IWineJSDispatchHost_GetNextDispID(dispex, fdexEnumAll, id, &id);
if(FAILED(hres))
return hres;
else if(hres == S_FALSE)
@ -7593,7 +7593,7 @@ static inline HRESULT get_attr_dispid_by_name(HTMLAttributeCollection *This, BST
}
}
hres = IDispatchEx_GetDispID(&This->elem->node.event_target.dispex.IDispatchEx_iface,
hres = IWineJSDispatchHost_GetDispID(&This->elem->node.event_target.dispex.IWineJSDispatchHost_iface,
name, fdexNameCaseInsensitive, id);
return hres;
}

View File

@ -315,7 +315,7 @@ static BOOL is_elem_name(HTMLElement *elem, LPCWSTR name)
static HRESULT get_item_idx(HTMLElementCollection *This, UINT idx, IDispatch **ret)
{
if(idx < This->len) {
*ret = (IDispatch*)&This->elems[idx]->node.event_target.dispex.IDispatchEx_iface;
*ret = (IDispatch*)&This->elems[idx]->node.event_target.dispex.IWineJSDispatchHost_iface;
IDispatch_AddRef(*ret);
}

View File

@ -2056,7 +2056,7 @@ static HRESULT WINAPI DOMEvent_get_srcElement(IDOMEvent *iface, IHTMLElement **p
TRACE("(%p)->(%p)\n", This, p);
if(This->target)
IDispatchEx_QueryInterface(&This->target->dispex.IDispatchEx_iface, &IID_IHTMLElement, (void**)p);
IWineJSDispatchHost_QueryInterface(&This->target->dispex.IWineJSDispatchHost_iface, &IID_IHTMLElement, (void**)p);
else
*p = NULL;
return S_OK;
@ -4167,7 +4167,7 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp
skip_onevent_listener = TRUE;
V_VT(&arg) = VT_DISPATCH;
V_DISPATCH(&arg) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
V_DISPATCH(&arg) = (IDispatch*)&event_target->dispex.IWineJSDispatchHost_iface;
V_VT(&v) = VT_EMPTY;
if(vtbl->get_dispatch_this)
V_DISPATCH(&arg) = vtbl->get_dispatch_this(&event_target->dispex);
@ -4249,7 +4249,7 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp
DISPPARAMS dp = {args, &named_arg, 2, 1};
V_VT(args) = VT_DISPATCH;
V_DISPATCH(args) = (IDispatch*)&event_target->dispex.IDispatchEx_iface;
V_DISPATCH(args) = (IDispatch*)&event_target->dispex.IWineJSDispatchHost_iface;
if(vtbl->get_dispatch_this)
V_DISPATCH(args) = vtbl->get_dispatch_this(&event_target->dispex);
IDispatch_AddRef(V_DISPATCH(args));

View File

@ -893,7 +893,7 @@ static HRESULT HTMLFrameElement_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
return E_FAIL;
}
return IDispatchEx_InvokeEx(&This->framebase.content_window->IDispatchEx_iface, id, lcid,
return IWineJSDispatchHost_InvokeEx(&This->framebase.content_window->IWineJSDispatchHost_iface, id, lcid,
flags, params, res, ei, caller);
}
@ -1330,7 +1330,7 @@ static HRESULT HTMLIFrame_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD
return E_FAIL;
}
return IDispatchEx_InvokeEx(&This->framebase.content_window->IDispatchEx_iface, id, lcid,
return IWineJSDispatchHost_InvokeEx(&This->framebase.content_window->IWineJSDispatchHost_iface, id, lcid,
flags, params, res, ei, caller);
}

View File

@ -2917,7 +2917,7 @@ static HRESULT WINAPI HTMLStyle_removeAttribute(IHTMLStyle *iface, BSTR strAttri
DISPID dispid;
unsigned i;
hres = IDispatchEx_GetDispID(&This->css_style.dispex.IDispatchEx_iface, strAttributeName,
hres = IWineJSDispatchHost_GetDispID(&This->css_style.dispex.IWineJSDispatchHost_iface, strAttributeName,
(lFlags&1) ? fdexNameCaseSensitive : fdexNameCaseInsensitive, &dispid);
if(hres != S_OK) {
*pfSuccess = VARIANT_FALSE;

View File

@ -211,8 +211,8 @@ static HRESULT WINAPI outer_window_QueryInterface(IHTMLWindow2 *iface, REFIID ri
}else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
*ppv = &This->base.IHTMLWindow2_iface;
return S_OK;
}else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
*ppv = &This->IDispatchEx_iface;
}else if(IsEqualGUID(&IID_IDispatchEx, riid) || IsEqualGUID(&IID_IWineJSDispatchHost, riid)) {
*ppv = &This->IWineJSDispatchHost_iface;
}else if(IsEqualGUID(&IID_IEventTarget, riid)) {
if(!This->base.inner_window->doc || This->base.inner_window->doc->document_mode < COMPAT_MODE_IE9)
return E_NOINTERFACE;
@ -3277,34 +3277,34 @@ static const IWineHTMLWindowCompatPrivateVtbl WineHTMLWindowCompatPrivateVtbl =
window_compat_private_get_performance,
};
static inline HTMLOuterWindow *impl_from_IDispatchEx(IDispatchEx *iface)
static inline HTMLOuterWindow *impl_from_IWineJSDispatchHost(IWineJSDispatchHost *iface)
{
return CONTAINING_RECORD(iface, HTMLOuterWindow, IDispatchEx_iface);
return CONTAINING_RECORD(iface, HTMLOuterWindow, IWineJSDispatchHost_iface);
}
static HRESULT WINAPI WindowDispEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
static HRESULT WINAPI WindowDispEx_QueryInterface(IWineJSDispatchHost *iface, REFIID riid, void **ppv)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
return IHTMLWindow2_QueryInterface(&This->base.IHTMLWindow2_iface, riid, ppv);
}
static ULONG WINAPI WindowDispEx_AddRef(IDispatchEx *iface)
static ULONG WINAPI WindowDispEx_AddRef(IWineJSDispatchHost *iface)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
return IHTMLWindow2_AddRef(&This->base.IHTMLWindow2_iface);
}
static ULONG WINAPI WindowDispEx_Release(IDispatchEx *iface)
static ULONG WINAPI WindowDispEx_Release(IWineJSDispatchHost *iface)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
return IHTMLWindow2_Release(&This->base.IHTMLWindow2_iface);
}
DISPEX_IDISPATCH_NOUNK_IMPL(WindowDispEx, IDispatchEx,
impl_from_IDispatchEx(iface)->base.inner_window->event_target.dispex)
DISPEX_IDISPATCH_NOUNK_IMPL(WindowDispEx, IWineJSDispatchHost,
impl_from_IWineJSDispatchHost(iface)->base.inner_window->event_target.dispex)
static global_prop_t *alloc_global_prop(HTMLInnerWindow *This, global_prop_type_t type, BSTR name)
{
@ -3369,69 +3369,70 @@ HRESULT search_window_props(HTMLInnerWindow *This, BSTR bstrName, DWORD grfdex,
return DISP_E_UNKNOWNNAME;
}
static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
static HRESULT WINAPI WindowDispEx_GetDispID(IWineJSDispatchHost *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
return IDispatchEx_GetDispID(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, bstrName, grfdex, pid);
return IWineJSDispatchHost_GetDispID(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, bstrName, grfdex, pid);
}
static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
static HRESULT WINAPI WindowDispEx_InvokeEx(IWineJSDispatchHost *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
return IDispatchEx_InvokeEx(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
return IWineJSDispatchHost_InvokeEx(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id, lcid, wFlags,
pdp, pvarRes, pei, pspCaller);
}
static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IWineJSDispatchHost *iface, BSTR bstrName, DWORD grfdex)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
TRACE("(%p)->(%s %lx)\n", This, debugstr_w(bstrName), grfdex);
return IDispatchEx_DeleteMemberByName(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, bstrName, grfdex);
return IWineJSDispatchHost_DeleteMemberByName(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, bstrName, grfdex);
}
static HRESULT WINAPI WindowDispEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
static HRESULT WINAPI WindowDispEx_DeleteMemberByDispID(IWineJSDispatchHost *iface, DISPID id)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
TRACE("(%p)->(%lx)\n", This, id);
return IDispatchEx_DeleteMemberByDispID(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, id);
return IWineJSDispatchHost_DeleteMemberByDispID(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id);
}
static HRESULT WINAPI WindowDispEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
static HRESULT WINAPI WindowDispEx_GetMemberProperties(IWineJSDispatchHost *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
TRACE("(%p)->(%lx %lx %p)\n", This, id, grfdexFetch, pgrfdex);
return IDispatchEx_GetMemberProperties(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, id, grfdexFetch,
return IWineJSDispatchHost_GetMemberProperties(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id, grfdexFetch,
pgrfdex);
}
static HRESULT WINAPI WindowDispEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
static HRESULT WINAPI WindowDispEx_GetMemberName(IWineJSDispatchHost *iface, DISPID id, BSTR *pbstrName)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
TRACE("(%p)->(%lx %p)\n", This, id, pbstrName);
return IDispatchEx_GetMemberName(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, id, pbstrName);
return IWineJSDispatchHost_GetMemberName(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id, pbstrName);
}
static HRESULT WINAPI WindowDispEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
static HRESULT WINAPI WindowDispEx_GetNextDispID(IWineJSDispatchHost *iface, DWORD grfdex, DISPID id, DISPID *pid)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
TRACE("(%p)->(%lx %lx %p)\n", This, grfdex, id, pid);
return IDispatchEx_GetNextDispID(&This->base.inner_window->event_target.dispex.IDispatchEx_iface, grfdex, id, pid);
return IWineJSDispatchHost_GetNextDispID(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, grfdex, id, pid);
}
static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IWineJSDispatchHost *iface, IUnknown **ppunk)
{
HTMLOuterWindow *This = impl_from_IDispatchEx(iface);
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
TRACE("(%p)->(%p)\n", This, ppunk);
@ -3439,7 +3440,16 @@ static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IDispatchEx *iface, IUnkno
return S_OK;
}
static const IDispatchExVtbl WindowDispExVtbl = {
static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret,
EXCEPINFO *ei, IServiceProvider *caller)
{
HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
return IWineJSDispatchHost_CallFunction(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface,
id, iid, dp, ret, ei, caller);
}
static const IWineJSDispatchHostVtbl WindowDispExVtbl = {
WindowDispEx_QueryInterface,
WindowDispEx_AddRef,
WindowDispEx_Release,
@ -3454,7 +3464,8 @@ static const IDispatchExVtbl WindowDispExVtbl = {
WindowDispEx_GetMemberProperties,
WindowDispEx_GetMemberName,
WindowDispEx_GetNextDispID,
WindowDispEx_GetNameSpaceParent
WindowDispEx_GetNameSpaceParent,
WindowDispEx_CallFunction,
};
static inline HTMLOuterWindow *impl_from_IEventTarget(IEventTarget *iface)
@ -3810,7 +3821,7 @@ static HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD
prop->type = GLOBAL_DISPEXVAR;
prop->id = dispex_id;
return IDispatchEx_InvokeEx(&This->event_target.dispex.IDispatchEx_iface, dispex_id, 0, flags, params, res, ei, caller);
return IWineJSDispatchHost_InvokeEx(&This->event_target.dispex.IWineJSDispatchHost_iface, dispex_id, 0, flags, params, res, ei, caller);
}
default:
FIXME("Not supported flags: %x\n", flags);
@ -3838,7 +3849,7 @@ static HRESULT HTMLWindow_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD
return E_NOTIMPL;
}
case GLOBAL_DISPEXVAR:
return IDispatchEx_InvokeEx(&This->event_target.dispex.IDispatchEx_iface, prop->id, 0, flags, params, res, ei, caller);
return IWineJSDispatchHost_InvokeEx(&This->event_target.dispex.IWineJSDispatchHost_iface, prop->id, 0, flags, params, res, ei, caller);
default:
ERR("invalid type %d\n", prop->type);
hres = DISP_E_MEMBERNOTFOUND;
@ -3901,7 +3912,7 @@ static HRESULT IHTMLWindow2_location_hook(DispatchEx *dispex, WORD flags, DISPPA
if(FAILED(hres))
return hres;
hres = IDispatchEx_InvokeEx(&location->dispex.IDispatchEx_iface, DISPID_VALUE, 0, flags, dp, res, ei, caller);
hres = IWineJSDispatchHost_InvokeEx(&location->dispex.IWineJSDispatchHost_iface, DISPID_VALUE, 0, flags, dp, res, ei, caller);
IHTMLLocation_Release(&location->IHTMLLocation_iface);
return hres;
}
@ -4204,7 +4215,7 @@ HRESULT create_outer_window(GeckoBrowser *browser, mozIDOMWindowProxy *mozwindow
if(!window)
return E_OUTOFMEMORY;
window->base.IHTMLWindow2_iface.lpVtbl = &outer_window_HTMLWindow2Vtbl;
window->IDispatchEx_iface.lpVtbl = &WindowDispExVtbl;
window->IWineJSDispatchHost_iface.lpVtbl = &WindowDispExVtbl;
window->IEventTarget_iface.lpVtbl = &EventTargetVtbl;
window->base.outer_window = window;

View File

@ -413,7 +413,7 @@ typedef struct {
} dispex_hook_t;
struct DispatchEx {
IDispatchEx IDispatchEx_iface;
IWineJSDispatchHost IWineJSDispatchHost_iface;
nsCycleCollectingAutoRefCnt ccref;
@ -424,38 +424,38 @@ struct DispatchEx {
#define DISPEX_IDISPATCH_NOUNK_IMPL(prefix, iface_name, dispex) \
static HRESULT WINAPI prefix##_GetTypeInfoCount(iface_name *iface, UINT *count) \
{ \
return IDispatchEx_GetTypeInfoCount(&(dispex).IDispatchEx_iface, count); \
return IWineJSDispatchHost_GetTypeInfoCount(&(dispex).IWineJSDispatchHost_iface, count); \
} \
static HRESULT WINAPI prefix##_GetTypeInfo(iface_name *iface, \
UINT index, LCID lcid, ITypeInfo **ret) \
{ \
return IDispatchEx_GetTypeInfo(&(dispex).IDispatchEx_iface, index, lcid, ret); \
return IWineJSDispatchHost_GetTypeInfo(&(dispex).IWineJSDispatchHost_iface, index, lcid, ret); \
} \
static HRESULT WINAPI prefix##_GetIDsOfNames(iface_name *iface, REFIID riid, \
LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) \
{ \
return IDispatchEx_GetIDsOfNames(&(dispex).IDispatchEx_iface, \
return IWineJSDispatchHost_GetIDsOfNames(&(dispex).IWineJSDispatchHost_iface, \
riid, names, count, lcid, dispid); \
} \
static HRESULT WINAPI prefix##_Invoke(iface_name *iface, DISPID dispid, REFIID riid, \
LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, UINT *err) \
{ \
return IDispatchEx_Invoke(&(dispex).IDispatchEx_iface, dispid, \
return IWineJSDispatchHost_Invoke(&(dispex).IWineJSDispatchHost_iface, dispid, \
riid, lcid, flags, params, res, ei, err); \
}
#define DISPEX_IDISPATCH_IMPL(prefix, iface_name, dispex) \
static HRESULT WINAPI prefix##_QueryInterface(iface_name *iface, REFIID riid, void **ppv) \
{ \
return IDispatchEx_QueryInterface(&(dispex).IDispatchEx_iface, riid, ppv); \
return IWineJSDispatchHost_QueryInterface(&(dispex).IWineJSDispatchHost_iface, riid, ppv); \
} \
static ULONG WINAPI prefix##_AddRef(iface_name *iface) \
{ \
return IDispatchEx_AddRef(&(dispex).IDispatchEx_iface); \
return IWineJSDispatchHost_AddRef(&(dispex).IWineJSDispatchHost_iface); \
} \
static ULONG WINAPI prefix##_Release(iface_name *iface) \
{ \
return IDispatchEx_Release(&(dispex).IDispatchEx_iface); \
return IWineJSDispatchHost_Release(&(dispex).IWineJSDispatchHost_iface); \
} \
DISPEX_IDISPATCH_NOUNK_IMPL(prefix, iface_name, dispex)
@ -594,7 +594,7 @@ struct HTMLWindow {
struct HTMLOuterWindow {
HTMLWindow base;
IEventTarget IEventTarget_iface;
IDispatchEx IDispatchEx_iface;
IWineJSDispatchHost IWineJSDispatchHost_iface;
nsCycleCollectingAutoRefCnt ccref;
LONG task_magic;

View File

@ -258,3 +258,13 @@ interface IWineXMLHttpRequestPrivate : IDispatch
}
} /* library MSHTML_private */
[
object,
uuid(d359f2fe-5531-741b-a41a-5cf92edc971b),
local
]
interface IWineJSDispatchHost : IDispatchEx
{
HRESULT CallFunction(DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller);
}

View File

@ -1301,6 +1301,6 @@ HRESULT create_mutation_observer_ctor(compat_mode_t compat_mode, IDispatch **ret
init_dispatch(&obj->dispex, &mutation_observer_ctor_dispex, compat_mode);
*ret = (IDispatch *)&obj->dispex.IDispatchEx_iface;
*ret = (IDispatch *)&obj->dispex.IWineJSDispatchHost_iface;
return S_OK;
}

View File

@ -3542,7 +3542,7 @@ static HRESULT WINAPI DocObjDispatchEx_GetDispID(IDispatchEx *iface, BSTR name,
{
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
return IDispatchEx_GetDispID(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, name, grfdex, pid);
return IWineJSDispatchHost_GetDispID(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, name, grfdex, pid);
}
static HRESULT WINAPI DocObjDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
@ -3550,29 +3550,29 @@ static HRESULT WINAPI DocObjDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, L
{
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
return IDispatchEx_InvokeEx(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, id, lcid,
wFlags, pdp, pvarRes, pei, pspCaller);
return IWineJSDispatchHost_InvokeEx(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, id, lcid,
wFlags, pdp, pvarRes, pei, pspCaller);
}
static HRESULT WINAPI DocObjDispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
{
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
return IDispatchEx_DeleteMemberByName(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, bstrName, grfdex);
return IWineJSDispatchHost_DeleteMemberByName(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, bstrName, grfdex);
}
static HRESULT WINAPI DocObjDispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
{
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
return IDispatchEx_DeleteMemberByDispID(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, id);
return IWineJSDispatchHost_DeleteMemberByDispID(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, id);
}
static HRESULT WINAPI DocObjDispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
{
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
return IDispatchEx_GetMemberProperties(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, id, grfdexFetch,
return IWineJSDispatchHost_GetMemberProperties(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, id, grfdexFetch,
pgrfdex);
}
@ -3580,21 +3580,21 @@ static HRESULT WINAPI DocObjDispatchEx_GetMemberName(IDispatchEx *iface, DISPID
{
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
return IDispatchEx_GetMemberName(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, id, name);
return IWineJSDispatchHost_GetMemberName(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, id, name);
}
static HRESULT WINAPI DocObjDispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
{
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
return IDispatchEx_GetNextDispID(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, grfdex, id, pid);
return IWineJSDispatchHost_GetNextDispID(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, grfdex, id, pid);
}
static HRESULT WINAPI DocObjDispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
{
HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
return IDispatchEx_GetNameSpaceParent(&This->doc_node->node.event_target.dispex.IDispatchEx_iface, ppunk);
return IWineJSDispatchHost_GetNameSpaceParent(&This->doc_node->node.event_target.dispex.IWineJSDispatchHost_iface, ppunk);
}
static const IDispatchExVtbl DocObjDispatchExVtbl = {

View File

@ -2313,7 +2313,7 @@ static nsresult NSAPI media_query_list_callback_HandleChange(nsIDOMMediaQueryLis
DISPPARAMS dp = { args, NULL, 1, 0 };
V_VT(args) = VT_DISPATCH;
V_DISPATCH(args) = (IDispatch*)&media_query_list->dispex.IDispatchEx_iface;
V_DISPATCH(args) = (IDispatch*)&media_query_list->dispex.IWineJSDispatchHost_iface;
V_VT(&v) = VT_EMPTY;
TRACE("%p >>>\n", media_query_list);

View File

@ -1573,7 +1573,7 @@ static EventTarget *find_event_target(HTMLDocumentNode *doc, HTMLScriptElement *
}else if(!wcscmp(target_id, L"window")) {
if(doc->window) {
event_target = &doc->window->event_target;
IDispatchEx_AddRef(&event_target->dispex.IDispatchEx_iface);
IWineJSDispatchHost_AddRef(&event_target->dispex.IWineJSDispatchHost_iface);
}
}else {
HTMLElement *target_elem;
@ -1731,14 +1731,14 @@ void bind_event_scripts(HTMLDocumentNode *doc)
if(event_disp) {
event_target = find_event_target(doc, script_elem);
if(event_target) {
hres = IDispatchEx_QueryInterface(&event_target->dispex.IDispatchEx_iface, &IID_HTMLPluginContainer,
hres = IWineJSDispatchHost_QueryInterface(&event_target->dispex.IWineJSDispatchHost_iface, &IID_HTMLPluginContainer,
(void**)&plugin_container);
if(SUCCEEDED(hres))
bind_activex_event(doc, plugin_container, event, event_disp);
else
bind_target_event(doc, event_target, event, event_disp);
IDispatchEx_Release(&event_target->dispex.IDispatchEx_iface);
IWineJSDispatchHost_Release(&event_target->dispex.IWineJSDispatchHost_iface);
if(plugin_container)
node_release(&plugin_container->element.node);
}

View File

@ -352,6 +352,73 @@ sync_test("builtin_toString", function() {
}
});
sync_test("builtin_obj", function() {
var v = document.documentMode;
var f = document.createElement;
var e;
if(v < 9) {
ok(!(window instanceof Object), "window instance of Object");
ok(!(document instanceof Object), "document instance of Object");
ok(!("arguments" in f), "arguments in f");
ok(!("length" in f), "length in f");
e = 0;
try {
f.toString();
}catch(ex) {
e = ex.number;
}
ok(e === 0xa01b6 - 0x80000000, "[f.toString] e = " + e);
try {
window.toString.call(null);
ok(false, "expected exception calling window.toString with null context");
}catch(ex) {}
}
e = 0;
try {
f.call(Object, "div");
}catch(ex) {
e = ex.number;
}
todo_wine_if(v >= 9).
ok(e === (v < 9 ? 0xa0005 : 0x0ffff) - 0x80000000, "[f.call(Object, 'div')] e = " + e);
e = 0;
try {
f.call(null, "div");
}catch(ex) {
e = ex.number;
}
todo_wine_if(v >= 9).
ok(e === (v < 9 ? 0xa0005 : 0x0ffff) - 0x80000000, "[f.call(null, 'div')] e = " + e);
var elem1 = f.call(document, "div");
var elem2 = f.call(document, "br");
document.body.appendChild(elem1);
document.body.appendChild(elem2);
elem1.onclick = function() { ok(false, "unexpected elem1.onclick"); };
var clicked = false;
elem2.onclick = function() { clicked = true; };
elem1.click.call(elem2);
ok(clicked === true, "elem2.onclick not called");
elem1 = f.apply(document, ["div"]);
elem2 = f.apply(document, ["br"]);
document.body.appendChild(elem1);
document.body.appendChild(elem2);
elem1.onclick = function() { ok(false, "unexpected elem1.onclick"); };
clicked = false;
elem2.onclick = function() { clicked = true; };
elem1.click.apply(elem2);
ok(clicked === true, "elem2.onclick not called");
try {
elem1.click.apply(elem2, { length: -1 });
ok(false, "exception expected");
}catch(ex) {}
});
sync_test("elem_props", function() {
var elem = document.documentElement;

View File

@ -8358,6 +8358,121 @@ static void test_MHTMLDocument(void)
release_document(doc);
}
static LONG get_document_elements_count(IHTMLDocument2 *doc)
{
LONG elements_count;
IHTMLElementCollection *elements = NULL;
IHTMLDocument2_get_all(doc, &elements);
IHTMLElementCollection_get_length(elements, &elements_count);
IHTMLElementCollection_Release(elements);
return elements_count;
}
static void test_MarkupContainer(IMarkupServices *markup_services)
{
IHTMLDOMNode *doc_node;
IHTMLDocument2 *markup_container_doc;
ITargetContainer *target_container_doc;
IInternetSecurityManager *sec_manager;
IMarkupContainer *container = NULL;
ICustomDoc *custom_doc;
IHTMLLocation *location = NULL;
IHTMLElement *body = NULL;
LONG elements_count;
HRESULT hres;
hres = IMarkupServices_CreateMarkupContainer(markup_services, &container);
ok(hres == S_OK, "got 0x%08lx\n", hres);
ok(container != NULL, "MarkupContainer is null.\n");
if (!container) return;
hres = IMarkupContainer_QueryInterface(container, &IID_IHTMLDocument2, (void**)&markup_container_doc);
ok(hres == S_OK, "got 0x%08lx\n", hres);
hres = IHTMLDocument2_get_location(markup_container_doc, &location);
ok(hres == E_UNEXPECTED, "expected E_UNEXPECTED, got 0x%08lx\n", hres);
ok(location == NULL, "expected null location\n");
hres = IHTMLDocument2_get_body(markup_container_doc, &body);
ok(hres == S_OK, "got 0x%08lx\n", hres);
ok(body == NULL, "expected null body\n");
elements_count = get_document_elements_count(markup_container_doc);
ok(elements_count == 0, "expected document to not have elements\n");
hres = IMarkupContainer_QueryInterface(container, &IID_IHTMLDOMNode, (void**)&doc_node);
todo_wine ok(hres == E_NOINTERFACE, "expected to fail with E_NOINTERFACE got 0x%08lx\n", hres);
hres = IHTMLDocument2_QueryInterface(markup_container_doc, &IID_IInternetSecurityManager, (void**)&sec_manager);
ok(hres == E_NOINTERFACE, "expected to fail with E_NOINTERFACE got 0x%08lx\n", hres);
hres = IHTMLDocument2_QueryInterface(markup_container_doc, &IID_ITargetContainer, (void**)&target_container_doc);
ok(hres == E_NOINTERFACE, "expected to fail with E_NOINTERFACE got 0x%08lx\n", hres);
hres = IHTMLDocument2_QueryInterface(markup_container_doc, &IID_ICustomDoc, (void**)&custom_doc);
ok(hres == E_NOINTERFACE, "expected to fail with E_NOINTERFACE got 0x%08lx\n", hres);
IHTMLDocument2_Release(markup_container_doc);
IMarkupContainer_Release(container);
}
static void test_MarkupServices_ParseString(IMarkupServices *markup_services, IHTMLDocument2 *doc)
{
HRESULT hres;
LONG document_elements_count, markup_container_elements_count;
IHTMLElement *body;
BSTR inner_text;
IHTMLDocument2 *markup_container_doc = NULL;
IMarkupContainer *markup_container = NULL;
hres = IMarkupServices_ParseString(markup_services, (OLECHAR*)L"<div>Hello World</div>", 0, &markup_container, NULL, NULL);
ok(hres == S_OK, "got 0x%08lx\n", hres);
ok(markup_container != NULL, "MarkupContainer is null.\n");
if (!markup_container) return;
hres = IMarkupContainer_QueryInterface(markup_container, &IID_IHTMLDocument2, (void**)&markup_container_doc);
ok(hres == S_OK, "failed to query interface of MarkupContainer 0x%08lx\n", hres);
markup_container_elements_count = get_document_elements_count(markup_container_doc);
ok(markup_container_elements_count == 5, "expected markup container to have 5 elements but got %ld\n",
markup_container_elements_count);
document_elements_count = get_document_elements_count(doc);
ok(document_elements_count != markup_container_elements_count,
"expected document to not have the same elements count of the markup container %ld == %ld\n",
document_elements_count, markup_container_elements_count);
hres = IHTMLDocument2_get_body(markup_container_doc, &body);
ok(hres == S_OK, "got 0x%08lx\n", hres);
ok(body != NULL, "got null body\n");
hres = IHTMLElement_get_innerText(body, &inner_text);
ok(hres == S_OK, "failed to get inner text error 0x%08lx\n", hres);
ok(inner_text != NULL, "got a null pointer for inner text\n");
ok(!wcscmp(inner_text, L"Hello World"), "strings don't match, got %ls\n", inner_text);
SysFreeString(inner_text);
IHTMLElement_Release(body);
IHTMLDocument2_Release(markup_container_doc);
IMarkupContainer_Release(markup_container);
}
static void test_MarkupServices(IHTMLDocument2 *doc)
{
HRESULT hres;
IMarkupServices *markup_services = NULL;
hres = IHTMLDocument2_QueryInterface(doc, &IID_IMarkupServices, (void**)&markup_services);
ok(hres == S_OK, "got 0x%08lx\n", hres);
test_MarkupContainer(markup_services);
test_MarkupServices_ParseString(markup_services, doc);
IMarkupServices_Release(markup_services);
}
static void test_HTMLDocument_hlink(DWORD status)
{
IHTMLDocument2 *doc;
@ -8524,6 +8639,7 @@ static void test_HTMLDocument_http(BOOL with_wbapp)
test_travellog(doc);
test_binding_ui((IUnknown*)doc);
test_doc_domain(doc);
test_MarkupServices(doc);
nav_url = nav_serv_url = L"http://test.winehq.org/tests/winehq_snapshot/"; /* for valid prev nav_url */
if(support_wbapp) {

View File

@ -76,5 +76,5 @@ EXTRA_OBJS = unix/version.o
unix_loader_EXTRADEFS = \
-DBINDIR=\"${bindir}\" \
-DSYSTEMDLLPATH=\"${system_dllpath}\" \
-DDLL_TO_BINDIR=\"`${MAKEDEP} -R ${dlldir} ${bindir}`\" \
-DDLL_TO_BINDIR=\"`${MAKEDEP} -R ${libdir}/wine ${bindir}`\" \
-DBIN_TO_DATADIR=\"`${MAKEDEP} -R ${bindir} ${datadir}/wine`\"

View File

@ -340,7 +340,7 @@
@ stdcall -syscall NtQueueApcThread(long ptr long long long)
@ stdcall -syscall NtQueueApcThreadEx(long long ptr long long long)
@ stdcall -syscall NtRaiseException(ptr ptr long)
@ stdcall -syscall NtRaiseHardError(long long ptr ptr long ptr)
@ stdcall -syscall NtRaiseHardError(long long long ptr long ptr)
@ stdcall -syscall NtReadFile(long long ptr ptr ptr ptr long ptr ptr)
@ stdcall -syscall NtReadFileScatter(long long ptr ptr ptr ptr long ptr ptr)
# @ stub NtReadRequestData
@ -650,7 +650,7 @@
# @ stub RtlEnumerateGenericTableAvl
# @ stub RtlEnumerateGenericTableLikeADirectory
@ stdcall RtlEnumerateGenericTableWithoutSplaying(ptr ptr)
# @ stub RtlEnumerateGenericTableWithoutSplayingAvl
@ stdcall RtlEnumerateGenericTableWithoutSplayingAvl(ptr ptr)
@ stub RtlEnumerateProperties
@ stdcall RtlEqualComputerName(ptr ptr)
@ stdcall RtlEqualDomainName(ptr ptr)
@ -743,8 +743,7 @@
# @ stub RtlGetLengthWithoutTrailingPathSeperators
@ stdcall RtlGetLocaleFileMappingAddress(ptr ptr ptr)
@ stdcall RtlGetLongestNtPathLength()
@ stdcall -syscall -arch=win32 RtlGetNativeSystemInformation(long ptr long ptr) NtWow64GetNativeSystemInformation
@ stdcall -syscall -arch=win64 RtlGetNativeSystemInformation(long ptr long ptr) NtQuerySystemInformation
@ stdcall RtlGetNativeSystemInformation(long ptr long ptr)
# @ stub RtlGetNextRange
@ stdcall RtlGetNtGlobalFlags()
@ stdcall RtlGetNtProductType(ptr)
@ -899,7 +898,7 @@
@ stdcall RtlNtStatusToDosError(long)
@ stdcall RtlNtStatusToDosErrorNoTeb(long)
@ stdcall RtlNumberGenericTableElements(ptr)
# @ stub RtlNumberGenericTableElementsAvl
@ stdcall RtlNumberGenericTableElementsAvl(ptr)
@ stdcall RtlNumberOfClearBits(ptr)
@ stdcall RtlNumberOfSetBits(ptr)
@ stdcall RtlOemStringToUnicodeSize(ptr)
@ -1390,7 +1389,7 @@
@ stdcall -private -syscall ZwQueueApcThread(long ptr long long long) NtQueueApcThread
@ stdcall -private -syscall ZwQueueApcThreadEx(long long ptr long long long) NtQueueApcThreadEx
@ stdcall -private -syscall ZwRaiseException(ptr ptr long) NtRaiseException
@ stdcall -private -syscall ZwRaiseHardError(long long ptr ptr long ptr) NtRaiseHardError
@ stdcall -private -syscall ZwRaiseHardError(long long long ptr long ptr) NtRaiseHardError
@ stdcall -private -syscall ZwReadFile(long long ptr ptr ptr ptr long ptr ptr) NtReadFile
@ stdcall -private -syscall ZwReadFileScatter(long long ptr ptr ptr ptr long ptr ptr) NtReadFileScatter
# @ stub ZwReadRequestData

View File

@ -249,7 +249,7 @@ NTSTATUS WINAPI RtlWow64GetThreadSelectorEntry( HANDLE handle, THREAD_DESCRIPTOR
{
/* hardcoded values */
#ifdef __arm64ec__
context.SegCs = 0x33;
context.SegCs = 0x23;
context.SegSs = 0x2b;
context.SegFs = 0x53;
#elif defined(__x86_64__)

View File

@ -243,58 +243,59 @@ static NTSTATUS RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo,
PRTL_QUERY_REGISTRY_TABLE pQuery, PVOID pContext, PVOID pEnvironment)
{
PUNICODE_STRING str = pQuery->EntryContext;
ULONG type, len, offset, count, res;
UNICODE_STRING src, dst;
WCHAR *data, *wstr;
LONG *bin;
ULONG offset;
PWSTR wstr;
DWORD res;
NTSTATUS status = STATUS_SUCCESS;
ULONG len;
if (pInfo == NULL)
if (pInfo)
{
ULONG default_size = pQuery->DefaultLength;
if (!default_size && pQuery->DefaultType == REG_SZ && pQuery->DefaultData)
default_size = (wcslen(pQuery->DefaultData) + 1) * sizeof(WCHAR);
if (pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT)
{
if (pQuery->QueryRoutine)
return STATUS_INVALID_PARAMETER;
if (pQuery->DefaultType == REG_SZ || pQuery->DefaultType == REG_EXPAND_SZ ||
pQuery->DefaultType == REG_MULTI_SZ || pQuery->DefaultType == REG_LINK)
{
if (!pQuery->DefaultData)
return STATUS_DATA_OVERRUN;
if (str->MaximumLength < default_size)
return STATUS_BUFFER_TOO_SMALL;
memcpy(str->Buffer, pQuery->DefaultData, default_size);
str->Length = default_size - sizeof(WCHAR);
}
return STATUS_SUCCESS;
}
else if (pQuery->QueryRoutine)
{
status = pQuery->QueryRoutine(pQuery->Name, pQuery->DefaultType, pQuery->DefaultData,
default_size, pContext, pQuery->EntryContext);
}
return status;
type = pInfo->Type;
data = (WCHAR*)((char*)pInfo + pInfo->DataOffset);
len = pInfo->DataLength;
}
else
{
type = pQuery->DefaultType;
data = pQuery->DefaultData;
len = pQuery->DefaultLength;
if (!data)
return STATUS_DATA_OVERRUN;
if (!len)
{
switch (type)
{
case REG_SZ:
case REG_EXPAND_SZ:
case REG_LINK:
len = (wcslen(data) + 1) * sizeof(WCHAR);
break;
case REG_MULTI_SZ:
for (wstr = data; *wstr; wstr += count)
{
count = wcslen(wstr) + 1;
len += count * sizeof(WCHAR);
}
break;
}
}
}
len = pInfo->DataLength;
if (pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT)
{
if (pQuery->QueryRoutine)
return STATUS_INVALID_PARAMETER;
switch(pInfo->Type)
switch (type)
{
case REG_EXPAND_SZ:
if (!(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
{
RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
RtlInitUnicodeString(&src, data);
res = 0;
dst.MaximumLength = 0;
RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
@ -307,12 +308,12 @@ static NTSTATUS RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo,
case REG_SZ:
case REG_LINK:
if (str->Buffer == NULL)
RtlCreateUnicodeString(str, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
RtlCreateUnicodeString(str, data);
else
{
if (str->MaximumLength < len)
return STATUS_BUFFER_TOO_SMALL;
memcpy(str->Buffer, (char*)pInfo + pInfo->DataOffset, len);
memcpy(str->Buffer, data, len);
str->Length = len - sizeof(WCHAR);
}
break;
@ -327,48 +328,45 @@ static NTSTATUS RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo,
str->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, len);
str->MaximumLength = len;
}
len = min(len, str->MaximumLength);
else if (str->MaximumLength < len)
return STATUS_BUFFER_TOO_SMALL;
len -= sizeof(WCHAR);
memcpy(str->Buffer, ((CHAR*)pInfo) + pInfo->DataOffset, len);
memcpy(str->Buffer, data, len);
str->Buffer[len / sizeof(WCHAR)] = 0;
str->Length = len;
break;
default:
bin = pQuery->EntryContext;
if (pInfo->DataLength <= sizeof(ULONG))
memcpy(bin, ((CHAR*)pInfo) + pInfo->DataOffset,
pInfo->DataLength);
if (len <= sizeof(ULONG))
memcpy(bin, data, len);
else
{
if (bin[0] <= sizeof(ULONG))
if (bin[0] < 0)
{
memcpy(&bin[1], ((CHAR*)pInfo) + pInfo->DataOffset,
min(-bin[0], pInfo->DataLength));
if (len <= -bin[0])
memcpy(bin, data, len);
}
else
else if (len <= bin[0])
{
len = min(bin[0], pInfo->DataLength);
bin[1] = len;
bin[2] = pInfo->Type;
memcpy(&bin[3], ((CHAR*)pInfo) + pInfo->DataOffset, len);
bin[0] = len;
bin[1] = type;
memcpy(bin + 2, data, len);
}
}
break;
}
break;
}
}
else if (pQuery->QueryRoutine)
{
if((pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND) ||
(pInfo->Type != REG_EXPAND_SZ && pInfo->Type != REG_MULTI_SZ))
(type != REG_EXPAND_SZ && type != REG_MULTI_SZ))
{
status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type,
((CHAR*)pInfo) + pInfo->DataOffset, pInfo->DataLength,
pContext, pQuery->EntryContext);
status = pQuery->QueryRoutine(pQuery->Name, type, data, len, pContext, pQuery->EntryContext);
}
else if (pInfo->Type == REG_EXPAND_SZ)
else if (type == REG_EXPAND_SZ)
{
RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
RtlInitUnicodeString(&src, data);
res = 0;
dst.MaximumLength = 0;
RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
@ -376,17 +374,16 @@ static NTSTATUS RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo,
dst.MaximumLength = res;
dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR));
RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer,
dst.Length, pContext, pQuery->EntryContext);
status = pQuery->QueryRoutine(pQuery->Name, REG_SZ, dst.Buffer, res, pContext, pQuery->EntryContext);
RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer);
}
else /* REG_MULTI_SZ */
{
for (offset = 0; offset < pInfo->DataLength; offset += len)
for (offset = 0; offset < len; offset += count)
{
wstr = (WCHAR*)((char*)pInfo + pInfo->DataOffset + offset);
len = (wcslen(wstr) + 1) * sizeof(WCHAR);
status = pQuery->QueryRoutine(pQuery->Name, REG_SZ, wstr, len, pContext, pQuery->EntryContext);
wstr = (WCHAR*)((char*)data + offset);
count = (wcslen(wstr) + 1) * sizeof(WCHAR);
status = pQuery->QueryRoutine(pQuery->Name, REG_SZ, wstr, count, pContext, pQuery->EntryContext);
if (status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
return status;
}

View File

@ -27,22 +27,16 @@
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "winsock2.h"
#include "windef.h"
#include "winternl.h"
#include "wine/debug.h"
#include "wine/exception.h"
#include "ntdll_misc.h"
#include "in6addr.h"
#include "ddk/ntddk.h"
#include "ddk/ntifs.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
WINE_DECLARE_DEBUG_CHANNEL(debugstr);
#define htons(x) RtlUshortByteSwap(x)
#define ntohs(x) RtlUshortByteSwap(x)
/* CRC polynomial 0xedb88320 */
static const DWORD CRC_table[256] =
{
@ -91,16 +85,6 @@ static const DWORD CRC_table[256] =
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
static const int hex_table[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2F */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3F */
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5F */
-1, 10, 11, 12, 13, 14, 15 /* 0x60-0x66 */
};
static LONG WINAPI debug_exception_handler( EXCEPTION_POINTERS *eptr )
{
@ -207,7 +191,7 @@ void WINAPI RtlInitializeGenericTable(RTL_GENERIC_TABLE *table, PRTL_GENERIC_COM
/******************************************************************************
* RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
*/
void * WINAPI RtlEnumerateGenericTableWithoutSplaying(RTL_GENERIC_TABLE *table, void *previous)
void * WINAPI RtlEnumerateGenericTableWithoutSplaying(RTL_GENERIC_TABLE *table, PVOID *previous)
{
static int warn_once;
@ -419,632 +403,6 @@ ULONG WINAPI RtlRandomEx( ULONG *seed )
return RtlRandom( seed );
}
static BOOL parse_ipv4_component(const WCHAR **str, BOOL strict, ULONG *value)
{
int base = 10, d;
WCHAR c;
ULONG cur_value, prev_value = 0;
BOOL success = FALSE;
if (**str == '.')
{
*str += 1;
return FALSE;
}
if ((*str)[0] == '0')
{
if ((*str)[1] == 'x' || (*str)[1] == 'X')
{
*str += 2;
if (strict) return FALSE;
base = 16;
}
else if ((*str)[1] >= '0' && (*str)[1] <= '9')
{
*str += 1;
if (strict) return FALSE;
base = 8;
}
}
for (cur_value = 0; **str; *str += 1)
{
c = **str;
if (c >= ARRAY_SIZE(hex_table)) break;
d = hex_table[c];
if (d == -1 || d >= base) break;
cur_value = cur_value * base + d;
success = TRUE;
if (cur_value < prev_value) return FALSE; /* overflow */
prev_value = cur_value;
}
if (success) *value = cur_value;
return success;
}
static NTSTATUS ipv4_string_to_address(const WCHAR *str, BOOL strict,
const WCHAR **terminator, IN_ADDR *address, USHORT *port)
{
ULONG fields[4];
int n = 0;
for (;;)
{
if (!parse_ipv4_component(&str, strict, &fields[n]))
goto error;
n++;
if (*str != '.')
break;
if (n == 4)
goto error;
str++;
}
if (strict && n < 4)
goto error;
switch (n)
{
case 4:
if (fields[0] > 0xFF || fields[1] > 0xFF || fields[2] > 0xFF || fields[3] > 0xFF)
goto error;
address->S_un.S_un_b.s_b1 = fields[0];
address->S_un.S_un_b.s_b2 = fields[1];
address->S_un.S_un_b.s_b3 = fields[2];
address->S_un.S_un_b.s_b4 = fields[3];
break;
case 3:
if (fields[0] > 0xFF || fields[1] > 0xFF || fields[2] > 0xFFFF)
goto error;
address->S_un.S_un_b.s_b1 = fields[0];
address->S_un.S_un_b.s_b2 = fields[1];
address->S_un.S_un_b.s_b3 = (fields[2] & 0xFF00) >> 8;
address->S_un.S_un_b.s_b4 = (fields[2] & 0x00FF);
break;
case 2:
if (fields[0] > 0xFF || fields[1] > 0xFFFFFF)
goto error;
address->S_un.S_un_b.s_b1 = fields[0];
address->S_un.S_un_b.s_b2 = (fields[1] & 0xFF0000) >> 16;
address->S_un.S_un_b.s_b3 = (fields[1] & 0x00FF00) >> 8;
address->S_un.S_un_b.s_b4 = (fields[1] & 0x0000FF);
break;
case 1:
address->S_un.S_un_b.s_b1 = (fields[0] & 0xFF000000) >> 24;
address->S_un.S_un_b.s_b2 = (fields[0] & 0x00FF0000) >> 16;
address->S_un.S_un_b.s_b3 = (fields[0] & 0x0000FF00) >> 8;
address->S_un.S_un_b.s_b4 = (fields[0] & 0x000000FF);
break;
default:
goto error;
}
if (terminator) *terminator = str;
if (*str == ':')
{
str++;
if (!parse_ipv4_component(&str, FALSE, &fields[0]))
goto error;
if (!fields[0] || fields[0] > 0xFFFF || *str)
goto error;
if (port)
{
*port = htons(fields[0]);
if (terminator) *terminator = str;
}
}
if (!terminator && *str)
return STATUS_INVALID_PARAMETER;
return STATUS_SUCCESS;
error:
if (terminator) *terminator = str;
return STATUS_INVALID_PARAMETER;
}
/***********************************************************************
* RtlIpv4StringToAddressExW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4StringToAddressExW(const WCHAR *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
{
TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, address, port);
if (!str || !address || !port) return STATUS_INVALID_PARAMETER;
return ipv4_string_to_address(str, strict, NULL, address, port);
}
/***********************************************************************
* RtlIpv4StringToAddressW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4StringToAddressW(const WCHAR *str, BOOLEAN strict, const WCHAR **terminator, IN_ADDR *address)
{
TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, terminator, address);
return ipv4_string_to_address(str, strict, terminator, address, NULL);
}
/***********************************************************************
* RtlIpv4StringToAddressExA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4StringToAddressExA(const char *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
{
WCHAR wstr[32];
TRACE("(%s, %u, %p, %p)\n", debugstr_a(str), strict, address, port);
if (!str || !address || !port)
return STATUS_INVALID_PARAMETER;
RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
wstr[ARRAY_SIZE(wstr) - 1] = 0;
return ipv4_string_to_address(wstr, strict, NULL, address, port);
}
/***********************************************************************
* RtlIpv4StringToAddressA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4StringToAddressA(const char *str, BOOLEAN strict, const char **terminator, IN_ADDR *address)
{
WCHAR wstr[32];
const WCHAR *wterminator;
NTSTATUS ret;
TRACE("(%s, %u, %p, %p)\n", debugstr_a(str), strict, terminator, address);
RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
wstr[ARRAY_SIZE(wstr) - 1] = 0;
ret = ipv4_string_to_address(wstr, strict, &wterminator, address, NULL);
if (terminator) *terminator = str + (wterminator - wstr);
return ret;
}
static BOOL parse_ipv6_component(const WCHAR **str, int base, ULONG *value)
{
WCHAR *terminator;
if (**str >= ARRAY_SIZE(hex_table) || hex_table[**str] == -1) return FALSE;
*value = min(wcstoul(*str, &terminator, base), 0x7FFFFFFF);
if (*terminator == '0') terminator++; /* "0x" but nothing valid after */
else if (terminator == *str) return FALSE;
*str = terminator;
return TRUE;
}
static NTSTATUS ipv6_string_to_address(const WCHAR *str, BOOL ex,
const WCHAR **terminator, IN6_ADDR *address, ULONG *scope, USHORT *port)
{
BOOL expecting_port = FALSE, has_0x = FALSE, too_big = FALSE;
int n_bytes = 0, n_ipv4_bytes = 0, gap = -1;
ULONG ip_component, scope_component = 0, port_component = 0;
const WCHAR *prev_str;
if (str[0] == '[')
{
if (!ex) goto error;
expecting_port = TRUE;
str++;
}
if (str[0] == ':')
{
if (str[1] != ':') goto error;
str++;
address->u.Word[0] = 0;
}
for (;;)
{
if (!n_ipv4_bytes && *str == ':')
{
/* double colon */
if (gap != -1) goto error;
str++;
prev_str = str;
gap = n_bytes;
if (n_bytes == 14 || !parse_ipv6_component(&str, 16, &ip_component)) break;
str = prev_str;
}
else
{
prev_str = str;
}
if (!n_ipv4_bytes && n_bytes <= (gap != -1 ? 10 : 12))
{
if (parse_ipv6_component(&str, 10, &ip_component) && *str == '.')
n_ipv4_bytes = 1;
str = prev_str;
}
if (n_ipv4_bytes)
{
/* IPv4 component */
if (!parse_ipv6_component(&str, 10, &ip_component)) goto error;
if (str - prev_str > 3 || ip_component > 255)
{
too_big = TRUE;
}
else
{
if (*str != '.' && (n_ipv4_bytes < 4 || (n_bytes < 15 && gap == -1))) goto error;
address->u.Byte[n_bytes] = ip_component;
n_bytes++;
}
if (n_ipv4_bytes == 4 || *str != '.') break;
n_ipv4_bytes++;
}
else
{
/* IPv6 component */
if (!parse_ipv6_component(&str, 16, &ip_component)) goto error;
if (prev_str[0] == '0' && (prev_str[1] == 'x' || prev_str[1] == 'X'))
{
/* Windows "feature": the last IPv6 component can start with "0x" and be longer than 4 digits */
if (terminator) *terminator = prev_str + 1; /* Windows says that the "x" is the terminator */
if (n_bytes < 14 && gap == -1) return STATUS_INVALID_PARAMETER;
address->u.Word[n_bytes/2] = htons(ip_component);
n_bytes += 2;
has_0x = TRUE;
goto fill_gap;
}
if (*str != ':' && n_bytes < 14 && gap == -1) goto error;
if (str - prev_str > 4)
too_big = TRUE;
else
address->u.Word[n_bytes/2] = htons(ip_component);
n_bytes += 2;
if (*str != ':' || (gap != -1 && str[1] == ':')) break;
}
if (n_bytes == (gap != -1 ? 14 : 16)) break;
if (too_big) return STATUS_INVALID_PARAMETER;
str++;
}
if (terminator) *terminator = str;
if (too_big) return STATUS_INVALID_PARAMETER;
fill_gap:
if (gap == -1)
{
if (n_bytes < 16) goto error;
}
else
{
memmove(address->u.Byte + 16 - (n_bytes - gap), address->u.Byte + gap, n_bytes - gap);
memset(address->u.Byte + gap, 0, 16 - n_bytes);
}
if (ex)
{
if (has_0x) goto error;
if (*str == '%')
{
str++;
if (!parse_ipv4_component(&str, TRUE, &scope_component)) goto error;
}
if (expecting_port)
{
if (*str != ']') goto error;
str++;
if (*str == ':')
{
str++;
if (!parse_ipv4_component(&str, FALSE, &port_component)) goto error;
if (!port_component || port_component > 0xFFFF || *str) goto error;
port_component = htons(port_component);
}
}
}
if (!terminator && *str) return STATUS_INVALID_PARAMETER;
if (scope) *scope = scope_component;
if (port) *port = port_component;
return STATUS_SUCCESS;
error:
if (terminator) *terminator = str;
return STATUS_INVALID_PARAMETER;
}
/***********************************************************************
* RtlIpv6StringToAddressExW [NTDLL.@]
*/
NTSTATUS NTAPI RtlIpv6StringToAddressExW(const WCHAR *str, IN6_ADDR *address, ULONG *scope, USHORT *port)
{
TRACE("(%s, %p, %p, %p)\n", debugstr_w(str), address, scope, port);
if (!str || !address || !scope || !port) return STATUS_INVALID_PARAMETER;
return ipv6_string_to_address(str, TRUE, NULL, address, scope, port);
}
/***********************************************************************
* RtlIpv6StringToAddressW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6StringToAddressW(const WCHAR *str, const WCHAR **terminator, IN6_ADDR *address)
{
TRACE("(%s, %p, %p)\n", debugstr_w(str), terminator, address);
return ipv6_string_to_address(str, FALSE, terminator, address, NULL, NULL);
}
/***********************************************************************
* RtlIpv6StringToAddressExA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6StringToAddressExA(const char *str, IN6_ADDR *address, ULONG *scope, USHORT *port)
{
WCHAR wstr[128];
TRACE("(%s, %p, %p, %p)\n", debugstr_a(str), address, scope, port);
if (!str || !address || !scope || !port)
return STATUS_INVALID_PARAMETER;
RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
wstr[ARRAY_SIZE(wstr) - 1] = 0;
return ipv6_string_to_address(wstr, TRUE, NULL, address, scope, port);
}
/***********************************************************************
* RtlIpv6StringToAddressA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6StringToAddressA(const char *str, const char **terminator, IN6_ADDR *address)
{
WCHAR wstr[128];
const WCHAR *wterminator = NULL;
NTSTATUS ret;
TRACE("(%s, %p, %p)\n", debugstr_a(str), terminator, address);
RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
wstr[ARRAY_SIZE(wstr) - 1] = 0;
ret = ipv6_string_to_address(wstr, FALSE, &wterminator, address, NULL, NULL);
if (terminator && wterminator) *terminator = str + (wterminator - wstr);
return ret;
}
/***********************************************************************
* RtlIpv4AddressToStringExW [NTDLL.@]
*
* Convert the given ipv4 address and optional the port to a string
*
* PARAMS
* pin [I] PTR to the ip address to convert (network byte order)
* port [I] optional port to convert (network byte order)
* buffer [O] destination buffer for the result
* psize [IO] PTR to available/used size of the destination buffer
*
* RETURNS
* Success: STATUS_SUCCESS
* Failure: STATUS_INVALID_PARAMETER
*
*/
NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
{
WCHAR tmp_ip[32];
ULONG needed;
if (!pin || !buffer || !psize)
return STATUS_INVALID_PARAMETER;
TRACE("(%p:0x%lx, %d, %p, %p:%ld)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
needed = swprintf(tmp_ip, ARRAY_SIZE(tmp_ip), L"%u.%u.%u.%u",
pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
if (port) needed += swprintf(tmp_ip + needed, ARRAY_SIZE(tmp_ip) - needed, L":%u", ntohs(port));
if (*psize > needed) {
*psize = needed + 1;
wcscpy(buffer, tmp_ip);
return STATUS_SUCCESS;
}
*psize = needed + 1;
return STATUS_INVALID_PARAMETER;
}
/***********************************************************************
* RtlIpv4AddressToStringExA [NTDLL.@]
*
* Convert the given ipv4 address and optional the port to a string
*
* See RtlIpv4AddressToStringExW
*/
NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
{
CHAR tmp_ip[32];
ULONG needed;
if (!pin || !buffer || !psize)
return STATUS_INVALID_PARAMETER;
TRACE("(%p:0x%lx, %d, %p, %p:%ld)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
needed = sprintf(tmp_ip, "%u.%u.%u.%u",
pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
if (*psize > needed) {
*psize = needed + 1;
strcpy(buffer, tmp_ip);
return STATUS_SUCCESS;
}
*psize = needed + 1;
return STATUS_INVALID_PARAMETER;
}
/***********************************************************************
* RtlIpv4AddressToStringW [NTDLL.@]
*
* Convert the given ipv4 address to a string
*
* PARAMS
* pin [I] PTR to the ip address to convert (network byte order)
* buffer [O] destination buffer for the result (at least 16 character)
*
* RETURNS
* PTR to the 0 character at the end of the converted string
*
*/
WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
{
ULONG size = 16;
if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
return buffer + size - 1;
}
/***********************************************************************
* RtlIpv4AddressToStringA [NTDLL.@]
*
* Convert the given ipv4 address to a string
*
* See RtlIpv4AddressToStringW
*/
CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
{
ULONG size = 16;
if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
return buffer + size - 1;
}
static BOOL is_ipv4_in_ipv6(const IN6_ADDR *address)
{
if (address->s6_words[5] == htons(0x5efe) && (address->s6_words[4] & ~htons(0x200)) == 0)
return TRUE;
if (*(UINT64 *)address != 0)
return FALSE;
if (address->s6_words[4] != 0 && address->s6_words[4] != 0xffff)
return FALSE;
if (address->s6_words[4] == 0 && address->s6_words[5] != 0 && address->s6_words[5] != 0xffff)
return FALSE;
if (address->s6_words[4] == 0xffff && address->s6_words[5] != 0)
return FALSE;
if (address->s6_words[6] == 0)
return FALSE;
return TRUE;
}
/***********************************************************************
* RtlIpv6AddressToStringExA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6AddressToStringExA(const IN6_ADDR *address, ULONG scope, USHORT port, char *str, ULONG *size)
{
char buffer[64], *p = buffer;
int i, len, gap = -1, gap_len = 1, ipv6_end = 8;
ULONG needed;
NTSTATUS ret;
TRACE("(%p %lu %u %p %p)\n", address, scope, port, str, size);
if (!address || !str || !size)
return STATUS_INVALID_PARAMETER;
if (is_ipv4_in_ipv6(address))
ipv6_end = 6;
for (i = 0; i < ipv6_end; i++)
{
len = 0;
while (!address->s6_words[i] && i < ipv6_end)
{
i++;
len++;
}
if (len > gap_len)
{
gap = i - len;
gap_len = len;
}
}
if (port) p += sprintf(p, "[");
i = 0;
while (i < ipv6_end)
{
if (i == gap)
{
p += sprintf(p, ":");
i += gap_len;
if (i == ipv6_end) p += sprintf(p, ":");
continue;
}
if (i > 0) p += sprintf(p, ":");
p += sprintf(p, "%x", ntohs(address->s6_words[i]));
i++;
}
if (ipv6_end == 6)
{
if (p[-1] != ':') p += sprintf(p, ":");
p = RtlIpv4AddressToStringA((IN_ADDR *)(address->s6_words + 6), p);
}
if (scope) p += sprintf(p, "%%%lu", scope);
if (port) p += sprintf(p, "]:%u", ntohs(port));
needed = p - buffer + 1;
if (*size >= needed)
{
strcpy(str, buffer);
ret = STATUS_SUCCESS;
}
else
{
ret = STATUS_INVALID_PARAMETER;
}
*size = needed;
return ret;
}
/***********************************************************************
* RtlIpv6AddressToStringA [NTDLL.@]
*/
char * WINAPI RtlIpv6AddressToStringA(const IN6_ADDR *address, char *str)
{
ULONG size = 46;
if (!address || !str) return str - 1;
str[45] = 0; /* this byte is set even though the string is always shorter */
RtlIpv6AddressToStringExA(address, 0, 0, str, &size);
return str + size - 1;
}
/***********************************************************************
* RtlIpv6AddressToStringExW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6AddressToStringExW(const IN6_ADDR *address, ULONG scope, USHORT port, WCHAR *str, ULONG *size)
{
char cstr[64];
NTSTATUS ret = RtlIpv6AddressToStringExA(address, scope, port, cstr, size);
if (ret == STATUS_SUCCESS) RtlMultiByteToUnicodeN(str, *size * sizeof(WCHAR), NULL, cstr, *size);
return ret;
}
/***********************************************************************
* RtlIpv6AddressToStringW [NTDLL.@]
*/
WCHAR * WINAPI RtlIpv6AddressToStringW(const IN6_ADDR *address, WCHAR *str)
{
ULONG size = 46;
if (!address || !str) return str;
str[45] = 0; /* this word is set even though the string is always shorter */
if (RtlIpv6AddressToStringExW(address, 0, 0, str, &size) != STATUS_SUCCESS)
return str;
return str + size - 1;
}
/***********************************************************************
* get_pointer_obfuscator (internal)
*/
@ -1421,40 +779,6 @@ void WINAPI RtlGetCurrentProcessorNumberEx(PROCESSOR_NUMBER *processor)
processor->Reserved = 0;
}
/***********************************************************************
* RtlIsProcessorFeaturePresent [NTDLL.@]
*/
BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature )
{
#ifdef __aarch64__
static const ULONGLONG arm64_features =
(1ull << PF_COMPARE_EXCHANGE_DOUBLE) |
(1ull << PF_NX_ENABLED) |
(1ull << PF_ARM_VFP_32_REGISTERS_AVAILABLE) |
(1ull << PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_SECOND_LEVEL_ADDRESS_TRANSLATION) |
(1ull << PF_FASTFAIL_AVAILABLE) |
(1ull << PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE) |
(1ull << PF_ARM_64BIT_LOADSTORE_ATOMIC) |
(1ull << PF_ARM_EXTERNAL_CACHE_AVAILABLE) |
(1ull << PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V8_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE);
return (feature < PROCESSOR_FEATURE_MAX && (arm64_features & (1ull << feature)) &&
user_shared_data->ProcessorFeatures[feature]);
#elif defined _WIN64
return feature < PROCESSOR_FEATURE_MAX && user_shared_data->ProcessorFeatures[feature];
#else
return NtWow64IsProcessorFeaturePresent( feature );
#endif
}
/***********************************************************************
* RtlInitializeGenericTableAvl (NTDLL.@)
*/
@ -1464,6 +788,27 @@ void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE table, PRTL_AVL_COMPARE_
FIXME("%p %p %p %p %p: stub\n", table, compare, allocate, free, context);
}
/******************************************************************************
* RtlEnumerateGenericTableWithoutSplayingAvl (NTDLL.@)
*/
void * WINAPI RtlEnumerateGenericTableWithoutSplayingAvl(RTL_AVL_TABLE *table, PVOID *previous)
{
static int warn_once;
if (!warn_once++)
FIXME("(%p, %p) stub!\n", table, previous);
return NULL;
}
/******************************************************************************
* RtlNumberGenericTableElementsAvl (NTDLL.@)
*/
ULONG WINAPI RtlNumberGenericTableElementsAvl(RTL_AVL_TABLE *table)
{
FIXME("(%p) stub!\n", table);
return 0;
}
/***********************************************************************
* RtlInsertElementGenericTableAvl (NTDLL.@)
*/

View File

@ -27,10 +27,12 @@
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "winsock2.h"
#include "windef.h"
#include "winnt.h"
#include "winternl.h"
#include "ddk/ntddk.h"
#include "in6addr.h"
#include "wine/debug.h"
#include "ntdll_misc.h"
@ -1943,3 +1945,606 @@ NTSTATUS WINAPI RtlFormatMessageEx( const WCHAR *src, ULONG width, BOOLEAN ignor
*retsize = (buffer - start) * sizeof(WCHAR);
return STATUS_SUCCESS;
}
/***********************************************************************
* IP addresses
***********************************************************************/
#define htons(x) RtlUshortByteSwap(x)
#define ntohs(x) RtlUshortByteSwap(x)
static const signed char hex_table[] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2F */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3F */
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5F */
-1, 10, 11, 12, 13, 14, 15 /* 0x60-0x66 */
};
static BOOL parse_ipv4_component(const WCHAR **str, BOOL strict, ULONG *value)
{
int base = 10, d;
WCHAR c;
ULONG cur_value, prev_value = 0;
BOOL success = FALSE;
if (**str == '.')
{
*str += 1;
return FALSE;
}
if ((*str)[0] == '0')
{
if ((*str)[1] == 'x' || (*str)[1] == 'X')
{
*str += 2;
if (strict) return FALSE;
base = 16;
}
else if ((*str)[1] >= '0' && (*str)[1] <= '9')
{
*str += 1;
if (strict) return FALSE;
base = 8;
}
}
for (cur_value = 0; **str; *str += 1)
{
c = **str;
if (c >= ARRAY_SIZE(hex_table)) break;
d = hex_table[c];
if (d == -1 || d >= base) break;
cur_value = cur_value * base + d;
success = TRUE;
if (cur_value < prev_value) return FALSE; /* overflow */
prev_value = cur_value;
}
if (success) *value = cur_value;
return success;
}
static NTSTATUS ipv4_string_to_address(const WCHAR *str, BOOL strict,
const WCHAR **terminator, IN_ADDR *address, USHORT *port)
{
ULONG fields[4];
int n = 0;
for (;;)
{
if (!parse_ipv4_component(&str, strict, &fields[n]))
goto error;
n++;
if (*str != '.')
break;
if (n == 4)
goto error;
str++;
}
if (strict && n < 4)
goto error;
switch (n)
{
case 4:
if (fields[0] > 0xFF || fields[1] > 0xFF || fields[2] > 0xFF || fields[3] > 0xFF)
goto error;
address->S_un.S_un_b.s_b1 = fields[0];
address->S_un.S_un_b.s_b2 = fields[1];
address->S_un.S_un_b.s_b3 = fields[2];
address->S_un.S_un_b.s_b4 = fields[3];
break;
case 3:
if (fields[0] > 0xFF || fields[1] > 0xFF || fields[2] > 0xFFFF)
goto error;
address->S_un.S_un_b.s_b1 = fields[0];
address->S_un.S_un_b.s_b2 = fields[1];
address->S_un.S_un_b.s_b3 = (fields[2] & 0xFF00) >> 8;
address->S_un.S_un_b.s_b4 = (fields[2] & 0x00FF);
break;
case 2:
if (fields[0] > 0xFF || fields[1] > 0xFFFFFF)
goto error;
address->S_un.S_un_b.s_b1 = fields[0];
address->S_un.S_un_b.s_b2 = (fields[1] & 0xFF0000) >> 16;
address->S_un.S_un_b.s_b3 = (fields[1] & 0x00FF00) >> 8;
address->S_un.S_un_b.s_b4 = (fields[1] & 0x0000FF);
break;
case 1:
address->S_un.S_un_b.s_b1 = (fields[0] & 0xFF000000) >> 24;
address->S_un.S_un_b.s_b2 = (fields[0] & 0x00FF0000) >> 16;
address->S_un.S_un_b.s_b3 = (fields[0] & 0x0000FF00) >> 8;
address->S_un.S_un_b.s_b4 = (fields[0] & 0x000000FF);
break;
default:
goto error;
}
if (terminator) *terminator = str;
if (*str == ':')
{
str++;
if (!parse_ipv4_component(&str, FALSE, &fields[0]))
goto error;
if (!fields[0] || fields[0] > 0xFFFF || *str)
goto error;
if (port)
{
*port = htons(fields[0]);
if (terminator) *terminator = str;
}
}
if (!terminator && *str)
return STATUS_INVALID_PARAMETER;
return STATUS_SUCCESS;
error:
if (terminator) *terminator = str;
return STATUS_INVALID_PARAMETER;
}
/***********************************************************************
* RtlIpv4StringToAddressExW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4StringToAddressExW(const WCHAR *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
{
TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, address, port);
if (!str || !address || !port) return STATUS_INVALID_PARAMETER;
return ipv4_string_to_address(str, strict, NULL, address, port);
}
/***********************************************************************
* RtlIpv4StringToAddressW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4StringToAddressW(const WCHAR *str, BOOLEAN strict, const WCHAR **terminator, IN_ADDR *address)
{
TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, terminator, address);
return ipv4_string_to_address(str, strict, terminator, address, NULL);
}
/***********************************************************************
* RtlIpv4StringToAddressExA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4StringToAddressExA(const char *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
{
WCHAR wstr[32];
if (!str) return STATUS_INVALID_PARAMETER;
RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
wstr[ARRAY_SIZE(wstr) - 1] = 0;
return RtlIpv4StringToAddressExW(wstr, strict, address, port);
}
/***********************************************************************
* RtlIpv4StringToAddressA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4StringToAddressA(const char *str, BOOLEAN strict, const char **terminator, IN_ADDR *address)
{
WCHAR wstr[32];
const WCHAR *wterminator;
NTSTATUS ret;
RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
wstr[ARRAY_SIZE(wstr) - 1] = 0;
ret = RtlIpv4StringToAddressW(wstr, strict, &wterminator, address);
if (terminator) *terminator = str + (wterminator - wstr);
return ret;
}
static BOOL parse_ipv6_component(const WCHAR **str, int base, ULONG *value)
{
WCHAR *terminator;
if (**str >= ARRAY_SIZE(hex_table) || hex_table[**str] == -1) return FALSE;
*value = min(wcstoul(*str, &terminator, base), 0x7FFFFFFF);
if (*terminator == '0') terminator++; /* "0x" but nothing valid after */
else if (terminator == *str) return FALSE;
*str = terminator;
return TRUE;
}
static NTSTATUS ipv6_string_to_address(const WCHAR *str, BOOL ex,
const WCHAR **terminator, IN6_ADDR *address, ULONG *scope, USHORT *port)
{
BOOL expecting_port = FALSE, has_0x = FALSE, too_big = FALSE;
int n_bytes = 0, n_ipv4_bytes = 0, gap = -1;
ULONG ip_component, scope_component = 0, port_component = 0;
const WCHAR *prev_str;
if (str[0] == '[')
{
if (!ex) goto error;
expecting_port = TRUE;
str++;
}
if (str[0] == ':')
{
if (str[1] != ':') goto error;
str++;
address->u.Word[0] = 0;
}
for (;;)
{
if (!n_ipv4_bytes && *str == ':')
{
/* double colon */
if (gap != -1) goto error;
str++;
prev_str = str;
gap = n_bytes;
if (n_bytes == 14 || !parse_ipv6_component(&str, 16, &ip_component)) break;
str = prev_str;
}
else
{
prev_str = str;
}
if (!n_ipv4_bytes && n_bytes <= (gap != -1 ? 10 : 12))
{
if (parse_ipv6_component(&str, 10, &ip_component) && *str == '.')
n_ipv4_bytes = 1;
str = prev_str;
}
if (n_ipv4_bytes)
{
/* IPv4 component */
if (!parse_ipv6_component(&str, 10, &ip_component)) goto error;
if (str - prev_str > 3 || ip_component > 255)
{
too_big = TRUE;
}
else
{
if (*str != '.' && (n_ipv4_bytes < 4 || (n_bytes < 15 && gap == -1))) goto error;
address->u.Byte[n_bytes] = ip_component;
n_bytes++;
}
if (n_ipv4_bytes == 4 || *str != '.') break;
n_ipv4_bytes++;
}
else
{
/* IPv6 component */
if (!parse_ipv6_component(&str, 16, &ip_component)) goto error;
if (prev_str[0] == '0' && (prev_str[1] == 'x' || prev_str[1] == 'X'))
{
/* Windows "feature": the last IPv6 component can start with "0x" and be longer than 4 digits */
if (terminator) *terminator = prev_str + 1; /* Windows says that the "x" is the terminator */
if (n_bytes < 14 && gap == -1) return STATUS_INVALID_PARAMETER;
address->u.Word[n_bytes/2] = htons(ip_component);
n_bytes += 2;
has_0x = TRUE;
goto fill_gap;
}
if (*str != ':' && n_bytes < 14 && gap == -1) goto error;
if (str - prev_str > 4)
too_big = TRUE;
else
address->u.Word[n_bytes/2] = htons(ip_component);
n_bytes += 2;
if (*str != ':' || (gap != -1 && str[1] == ':')) break;
}
if (n_bytes == (gap != -1 ? 14 : 16)) break;
if (too_big) return STATUS_INVALID_PARAMETER;
str++;
}
if (terminator) *terminator = str;
if (too_big) return STATUS_INVALID_PARAMETER;
fill_gap:
if (gap == -1)
{
if (n_bytes < 16) goto error;
}
else
{
memmove(address->u.Byte + 16 - (n_bytes - gap), address->u.Byte + gap, n_bytes - gap);
memset(address->u.Byte + gap, 0, 16 - n_bytes);
}
if (ex)
{
if (has_0x) goto error;
if (*str == '%')
{
str++;
if (!parse_ipv4_component(&str, TRUE, &scope_component)) goto error;
}
if (expecting_port)
{
if (*str != ']') goto error;
str++;
if (*str == ':')
{
str++;
if (!parse_ipv4_component(&str, FALSE, &port_component)) goto error;
if (!port_component || port_component > 0xFFFF || *str) goto error;
port_component = htons(port_component);
}
}
}
if (!terminator && *str) return STATUS_INVALID_PARAMETER;
if (scope) *scope = scope_component;
if (port) *port = port_component;
return STATUS_SUCCESS;
error:
if (terminator) *terminator = str;
return STATUS_INVALID_PARAMETER;
}
/***********************************************************************
* RtlIpv6StringToAddressExW [NTDLL.@]
*/
NTSTATUS NTAPI RtlIpv6StringToAddressExW(const WCHAR *str, IN6_ADDR *address, ULONG *scope, USHORT *port)
{
TRACE("(%s, %p, %p, %p)\n", debugstr_w(str), address, scope, port);
if (!str || !address || !scope || !port) return STATUS_INVALID_PARAMETER;
return ipv6_string_to_address(str, TRUE, NULL, address, scope, port);
}
/***********************************************************************
* RtlIpv6StringToAddressW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6StringToAddressW(const WCHAR *str, const WCHAR **terminator, IN6_ADDR *address)
{
TRACE("(%s, %p, %p)\n", debugstr_w(str), terminator, address);
return ipv6_string_to_address(str, FALSE, terminator, address, NULL, NULL);
}
/***********************************************************************
* RtlIpv6StringToAddressExA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6StringToAddressExA(const char *str, IN6_ADDR *address, ULONG *scope, USHORT *port)
{
WCHAR wstr[128];
if (!str) return STATUS_INVALID_PARAMETER;
RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
wstr[ARRAY_SIZE(wstr) - 1] = 0;
return RtlIpv6StringToAddressExW(wstr, address, scope, port);
}
/***********************************************************************
* RtlIpv6StringToAddressA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6StringToAddressA(const char *str, const char **terminator, IN6_ADDR *address)
{
WCHAR wstr[128];
const WCHAR *wterminator = NULL;
NTSTATUS ret;
RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
wstr[ARRAY_SIZE(wstr) - 1] = 0;
ret = RtlIpv6StringToAddressW(wstr, &wterminator, address);
if (terminator && wterminator) *terminator = str + (wterminator - wstr);
return ret;
}
/***********************************************************************
* RtlIpv4AddressToStringExW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
{
WCHAR tmp_ip[32];
ULONG needed;
if (!pin || !buffer || !psize)
return STATUS_INVALID_PARAMETER;
TRACE("(%p:0x%lx, %d, %p, %p:%ld)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
needed = swprintf(tmp_ip, ARRAY_SIZE(tmp_ip), L"%u.%u.%u.%u",
pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
if (port) needed += swprintf(tmp_ip + needed, ARRAY_SIZE(tmp_ip) - needed, L":%u", ntohs(port));
if (*psize > needed) {
*psize = needed + 1;
wcscpy(buffer, tmp_ip);
return STATUS_SUCCESS;
}
*psize = needed + 1;
return STATUS_INVALID_PARAMETER;
}
/***********************************************************************
* RtlIpv4AddressToStringExA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
{
CHAR tmp_ip[32];
ULONG needed;
if (!pin || !buffer || !psize)
return STATUS_INVALID_PARAMETER;
TRACE("(%p:0x%lx, %d, %p, %p:%ld)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
needed = sprintf(tmp_ip, "%u.%u.%u.%u",
pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
if (*psize > needed) {
*psize = needed + 1;
strcpy(buffer, tmp_ip);
return STATUS_SUCCESS;
}
*psize = needed + 1;
return STATUS_INVALID_PARAMETER;
}
/***********************************************************************
* RtlIpv4AddressToStringW [NTDLL.@]
*/
WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
{
ULONG size = 16;
if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
return buffer + size - 1;
}
/***********************************************************************
* RtlIpv4AddressToStringA [NTDLL.@]
*/
CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
{
ULONG size = 16;
if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
return buffer + size - 1;
}
static BOOL is_ipv4_in_ipv6(const IN6_ADDR *address)
{
if (address->s6_words[5] == htons(0x5efe) && (address->s6_words[4] & ~htons(0x200)) == 0)
return TRUE;
if (*(UINT64 *)address != 0)
return FALSE;
if (address->s6_words[4] != 0 && address->s6_words[4] != 0xffff)
return FALSE;
if (address->s6_words[4] == 0 && address->s6_words[5] != 0 && address->s6_words[5] != 0xffff)
return FALSE;
if (address->s6_words[4] == 0xffff && address->s6_words[5] != 0)
return FALSE;
if (address->s6_words[6] == 0)
return FALSE;
return TRUE;
}
/***********************************************************************
* RtlIpv6AddressToStringExA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6AddressToStringExA(const IN6_ADDR *address, ULONG scope, USHORT port,
char *str, ULONG *size)
{
char buffer[64], *p = buffer;
int i, len, gap = -1, gap_len = 1, ipv6_end = 8;
ULONG needed;
NTSTATUS ret;
TRACE("(%p %lu %u %p %p)\n", address, scope, port, str, size);
if (!address || !str || !size)
return STATUS_INVALID_PARAMETER;
if (is_ipv4_in_ipv6(address))
ipv6_end = 6;
for (i = 0; i < ipv6_end; i++)
{
len = 0;
while (!address->s6_words[i] && i < ipv6_end)
{
i++;
len++;
}
if (len > gap_len)
{
gap = i - len;
gap_len = len;
}
}
if (port) p += sprintf(p, "[");
i = 0;
while (i < ipv6_end)
{
if (i == gap)
{
p += sprintf(p, ":");
i += gap_len;
if (i == ipv6_end) p += sprintf(p, ":");
continue;
}
if (i > 0) p += sprintf(p, ":");
p += sprintf(p, "%x", ntohs(address->s6_words[i]));
i++;
}
if (ipv6_end == 6)
{
if (p[-1] != ':') p += sprintf(p, ":");
p = RtlIpv4AddressToStringA((IN_ADDR *)(address->s6_words + 6), p);
}
if (scope) p += sprintf(p, "%%%lu", scope);
if (port) p += sprintf(p, "]:%u", ntohs(port));
needed = p - buffer + 1;
if (*size >= needed)
{
strcpy(str, buffer);
ret = STATUS_SUCCESS;
}
else
{
ret = STATUS_INVALID_PARAMETER;
}
*size = needed;
return ret;
}
/***********************************************************************
* RtlIpv6AddressToStringA [NTDLL.@]
*/
char * WINAPI RtlIpv6AddressToStringA(const IN6_ADDR *address, char *str)
{
ULONG size = 46;
if (!address || !str) return str - 1;
str[45] = 0; /* this byte is set even though the string is always shorter */
RtlIpv6AddressToStringExA(address, 0, 0, str, &size);
return str + size - 1;
}
/***********************************************************************
* RtlIpv6AddressToStringExW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6AddressToStringExW(const IN6_ADDR *address, ULONG scope, USHORT port,
WCHAR *str, ULONG *size)
{
char cstr[64];
NTSTATUS ret = RtlIpv6AddressToStringExA(address, scope, port, cstr, size);
if (ret == STATUS_SUCCESS) RtlMultiByteToUnicodeN(str, *size * sizeof(WCHAR), NULL, cstr, *size);
return ret;
}
/***********************************************************************
* RtlIpv6AddressToStringW [NTDLL.@]
*/
WCHAR * WINAPI RtlIpv6AddressToStringW(const IN6_ADDR *address, WCHAR *str)
{
ULONG size = 46;
if (!address || !str) return str;
str[45] = 0; /* this word is set even though the string is always shorter */
if (RtlIpv6AddressToStringExW(address, 0, 0, str, &size) != STATUS_SUCCESS)
return str;
return str + size - 1;
}

View File

@ -556,6 +556,25 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
}
/*************************************************************************
* RtlGetNativeSystemInformation (NTDLL.@)
*/
NTSTATUS WINAPI RtlGetNativeSystemInformation( SYSTEM_INFORMATION_CLASS class,
void *info, ULONG size, ULONG *ret_size )
{
return NtWow64GetNativeSystemInformation( class, info, size, ret_size );
}
/***********************************************************************
* RtlIsProcessorFeaturePresent [NTDLL.@]
*/
BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature )
{
return NtWow64IsProcessorFeaturePresent( feature );
}
/*************************************************************************
* RtlWalkFrameChain (NTDLL.@)
*/

View File

@ -31,6 +31,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winternl.h"
#include "ddk/wdm.h"
#include "wine/exception.h"
#include "ntdll_misc.h"
#include "wine/debug.h"
@ -590,6 +591,45 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
}
/*************************************************************************
* RtlGetNativeSystemInformation (NTDLL.@)
*/
NTSTATUS WINAPI RtlGetNativeSystemInformation( SYSTEM_INFORMATION_CLASS class,
void *info, ULONG size, ULONG *ret_size )
{
return NtQuerySystemInformation( class, info, size, ret_size );
}
/***********************************************************************
* RtlIsProcessorFeaturePresent [NTDLL.@]
*/
BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature )
{
static const ULONGLONG arm64_features =
(1ull << PF_COMPARE_EXCHANGE_DOUBLE) |
(1ull << PF_NX_ENABLED) |
(1ull << PF_ARM_VFP_32_REGISTERS_AVAILABLE) |
(1ull << PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_SECOND_LEVEL_ADDRESS_TRANSLATION) |
(1ull << PF_FASTFAIL_AVAILABLE) |
(1ull << PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE) |
(1ull << PF_ARM_64BIT_LOADSTORE_ATOMIC) |
(1ull << PF_ARM_EXTERNAL_CACHE_AVAILABLE) |
(1ull << PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V8_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE) |
(1ull << PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE);
return (feature < PROCESSOR_FEATURE_MAX && (arm64_features & (1ull << feature)) &&
user_shared_data->ProcessorFeatures[feature]);
}
/*************************************************************************
* RtlWalkFrameChain (NTDLL.@)
*/

File diff suppressed because it is too large Load Diff

View File

@ -451,6 +451,25 @@ __ASM_STDCALL_FUNC( RtlRaiseException, 4,
"ret $4" ) /* actually never returns */
/*************************************************************************
* RtlGetNativeSystemInformation (NTDLL.@)
*/
NTSTATUS WINAPI RtlGetNativeSystemInformation( SYSTEM_INFORMATION_CLASS class,
void *info, ULONG size, ULONG *ret_size )
{
return NtWow64GetNativeSystemInformation( class, info, size, ret_size );
}
/***********************************************************************
* RtlIsProcessorFeaturePresent [NTDLL.@]
*/
BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature )
{
return NtWow64IsProcessorFeaturePresent( feature );
}
/*************************************************************************
* RtlWalkFrameChain (NTDLL.@)
*/

View File

@ -32,6 +32,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winternl.h"
#include "ddk/wdm.h"
#include "wine/exception.h"
#include "wine/list.h"
#include "ntdll_misc.h"
@ -792,6 +793,25 @@ __ASM_GLOBAL_FUNC( RtlRaiseException,
"call " __ASM_NAME("RtlRaiseStatus") /* does not return */ );
/*************************************************************************
* RtlGetNativeSystemInformation (NTDLL.@)
*/
NTSTATUS WINAPI RtlGetNativeSystemInformation( SYSTEM_INFORMATION_CLASS class,
void *info, ULONG size, ULONG *ret_size )
{
return NtQuerySystemInformation( class, info, size, ret_size );
}
/***********************************************************************
* RtlIsProcessorFeaturePresent [NTDLL.@]
*/
BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature )
{
return feature < PROCESSOR_FEATURE_MAX && user_shared_data->ProcessorFeatures[feature];
}
/*************************************************************************
* RtlWalkFrameChain (NTDLL.@)
*/

View File

@ -2553,6 +2553,7 @@ struct query_reg_values_test
ULONG expected_type;
const WCHAR *expected_data;
ULONG expected_data_size;
ULONG size_limit;
};
static unsigned int query_routine_calls;
@ -2623,7 +2624,25 @@ static NTSTATUS WINAPI query_routine(const WCHAR *value_name, ULONG value_type,
return STATUS_SUCCESS;
}
static UNICODE_STRING query_reg_values_direct_str;
static WCHAR query_reg_values_direct_str_buf[32];
static UNICODE_STRING query_reg_values_direct_str = {0, 0, query_reg_values_direct_str_buf};
static ULONG query_reg_values_direct_int;
static union
{
ULONG size;
char data[32];
}
query_reg_values_direct_sized;
static struct
{
ULONG size;
ULONG type;
char data[32];
}
query_reg_values_direct_typed;
static struct query_reg_values_test query_reg_values_tests[] =
{
@ -2644,7 +2663,7 @@ static struct query_reg_values_test query_reg_values_tests[] =
/* The query routine is called for every value in current key */
{
{{ query_routine }},
STATUS_SUCCESS, 4, SKIP_NAME_CHECK | SKIP_DATA_CHECK
STATUS_SUCCESS, 6, SKIP_NAME_CHECK | SKIP_DATA_CHECK
},
/* NOVALUE is ignored when the name is not null */
{
@ -2671,12 +2690,41 @@ static struct query_reg_values_test query_reg_values_tests[] =
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"WindowsDrive", &query_reg_values_direct_str }},
STATUS_SUCCESS, 0, 0, REG_SZ, L"C:"
STATUS_SUCCESS, 0, 0, REG_NONE, L"C:"
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"WindowsDrive", &query_reg_values_direct_str }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\x2323", 0, 2 * sizeof(WCHAR)
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND, (WCHAR*)L"WindowsDrive",
&query_reg_values_direct_str }},
STATUS_SUCCESS, 0, 0, REG_SZ, L"%SYSTEMDRIVE%"
STATUS_SUCCESS, 0, 0, REG_NONE, L"%SYSTEMDRIVE%"
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND, (WCHAR*)L"WindowsDrive",
&query_reg_values_direct_str }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\x2323", 0, 2 * sizeof(WCHAR)
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife32", &query_reg_values_direct_int }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\x2a"
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife64", &query_reg_values_direct_sized }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\x2a\0\0", sizeof(UINT64)
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife64", &query_reg_values_direct_sized }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\xff", 1, 1
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife64", &query_reg_values_direct_typed }},
STATUS_SUCCESS, 0, 0, REG_QWORD, L"\x2a\0\0", sizeof(UINT64)
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"MeaningOfLife64", &query_reg_values_direct_typed }},
STATUS_SUCCESS, 0, 0, 0x23, L"\x23", 1, 1
},
/* DIRECT on a multi-string crashes on Windows without NOEXPAND */
/* {
@ -2686,7 +2734,12 @@ static struct query_reg_values_test query_reg_values_tests[] =
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND, (WCHAR*)L"CapitalsOfEurope",
&query_reg_values_direct_str }},
STATUS_SUCCESS, 0, 0, REG_SZ, L"Brussels\0Paris\0%PATH%\0", sizeof(L"Brussels\0Paris\0%PATH%\0")
STATUS_SUCCESS, 0, 0, REG_NONE, L"Brussels\0Paris\0%PATH%\0", sizeof(L"Brussels\0Paris\0%PATH%\0")
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND, (WCHAR*)L"CapitalsOfEurope",
&query_reg_values_direct_str }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\x2323", 0, 2 * sizeof(WCHAR)
},
/* DIRECT with a null buffer crashes on Windows */
/* {
@ -2730,11 +2783,11 @@ static struct query_reg_values_test query_reg_values_tests[] =
},
{
{{ query_routine, 0, (WCHAR*)L"I don't exist", NULL, REG_EXPAND_SZ, (WCHAR*)L"%SYSTEMDRIVE%" }},
STATUS_SUCCESS, 1, WINE_TODO_TYPE | WINE_TODO_SIZE, REG_SZ, L"C:"
STATUS_SUCCESS, 1, 0, REG_SZ, L"C:"
},
{
{{ query_routine, 0, (WCHAR*)L"I don't exist", NULL, REG_MULTI_SZ, (WCHAR*)L"Brussels\0Paris\0%PATH%\0" }},
STATUS_SUCCESS, 3, EXPECT_DEFAULT_DATA | SPLIT_MULTI | WINE_TODO_CALLS | WINE_TODO_TYPE | WINE_TODO_SIZE
STATUS_SUCCESS, 3, EXPECT_DEFAULT_DATA | SPLIT_MULTI
},
{
{{ query_routine, 0, (WCHAR*)L"I don't exist", NULL, REG_DWORD, (WCHAR*)0xdeadbeef }},
@ -2752,19 +2805,74 @@ static struct query_reg_values_test query_reg_values_tests[] =
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_str, REG_EXPAND_SZ, (WCHAR*)L"%SYSTEMDRIVE%" }},
STATUS_SUCCESS, 0, WINE_TODO_SIZE | WINE_TODO_DATA, REG_EXPAND_SZ, L"C:"
&query_reg_values_direct_str, REG_SZ, (WCHAR*)L"%SYSTEMDRIVE%" }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\x2323", 0, 2 * sizeof(WCHAR)
},
/* DIRECT with a multi-string default value crashes on Windows */
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_str, REG_EXPAND_SZ, (WCHAR*)L"%SYSTEMDRIVE%" }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"C:"
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_str, REG_EXPAND_SZ, (WCHAR*)L"%SYSTEMDRIVE%" }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\x2323", 0, 2 * sizeof(WCHAR)
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_int, REG_DWORD, (WCHAR*)0xdeadbeef }},
STATUS_SUCCESS, 0
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_int, REG_DWORD, (WCHAR*)L"\x2a", sizeof(DWORD) }},
STATUS_SUCCESS, 0, EXPECT_DEFAULT_DATA
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_sized, REG_DWORD, (WCHAR*)L"Some default", sizeof(L"Some default") }},
STATUS_SUCCESS, 0, EXPECT_DEFAULT_DATA
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_sized, REG_DWORD, (WCHAR*)L"Some default", sizeof(L"Some default") }},
STATUS_SUCCESS, 0, 0, REG_NONE, L"\xff", 1, 1
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_typed, REG_NONE, (WCHAR*)L"Some default", sizeof(L"Some default") }},
STATUS_SUCCESS, 0, WINE_TODO_TYPE | WINE_TODO_SIZE, 0x23, NULL, -1
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_typed, REG_QWORD, (WCHAR*)L"Some default", sizeof(L"Some default") }},
STATUS_SUCCESS, 0, WINE_TODO_TYPE | WINE_TODO_SIZE, 0x23, NULL, -1
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_typed, REG_QWORD, (WCHAR*)L"\x2a\0\0", sizeof(UINT64) }},
STATUS_SUCCESS, 0, EXPECT_DEFAULT_DATA
},
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_typed, REG_QWORD, (WCHAR*)L"\x2a\0\0", sizeof(UINT64) }},
STATUS_SUCCESS, 0, 0, 0x23, L"\x23", 1, 1
},
/* DIRECT with a multi-string default value crashes on Windows without NOEXPAND */
/* {
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_str, REG_MULTI_SZ, (WCHAR*)L"A\0B\0C\0", sizeof(L"A\0B\0C\0") }},
STATUS_SUCCESS, EXPECT_DEFAULT_DATA
STATUS_SUCCESS, 0, EXPECT_DEFAULT_DATA
}, */
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND, (WCHAR*)L"I don't exist",
&query_reg_values_direct_str, REG_MULTI_SZ, (WCHAR*)L"A\0B\0C\0", sizeof(L"A\0B\0C\0") }},
STATUS_SUCCESS, 0, EXPECT_DEFAULT_DATA | WINE_TODO_SIZE
},
/* The default value is not used if it is not valid */
{
{{ query_routine, 0, (WCHAR*)L"I don't exist", NULL, REG_SZ }},
STATUS_DATA_OVERRUN, 0, EXPECT_DEFAULT_DATA | WINE_TODO_RET | WINE_TODO_CALLS
STATUS_DATA_OVERRUN, 0, EXPECT_DEFAULT_DATA
},
{
{{ query_routine, 0, (WCHAR*)L"I don't exist", NULL, REG_NONE, (WCHAR*)L"Some default" }},
@ -2780,12 +2888,6 @@ static struct query_reg_values_test query_reg_values_tests[] =
&query_reg_values_direct_str, REG_NONE, (WCHAR*)L"Some default" }},
STATUS_SUCCESS, 0, 0, REG_NONE, NULL, -1
},
/* DIRECT additionally requires the default value to be a string */
{
{{ NULL, RTL_QUERY_REGISTRY_DIRECT, (WCHAR*)L"I don't exist",
&query_reg_values_direct_str, REG_DWORD, (WCHAR*)0xdeadbeef }},
STATUS_SUCCESS, 0, 0, REG_NONE, NULL, -1
},
/* REQUIRED fails if the value doesn't exist and there is no default */
{
{{ query_routine, RTL_QUERY_REGISTRY_REQUIRED, (WCHAR*)L"I don't exist",
@ -2800,7 +2902,7 @@ static struct query_reg_values_test query_reg_values_tests[] =
/* DELETE deletes the value after reading it */
{
{{ query_routine, RTL_QUERY_REGISTRY_DELETE, (WCHAR*)L"WindowsDrive" }},
STATUS_SUCCESS, 1, WINE_TODO_TYPE | WINE_TODO_SIZE, REG_SZ, L"C:"
STATUS_SUCCESS, 1, 0, REG_SZ, L"C:"
},
{
{{ query_routine, 0, (WCHAR*)L"I don't exist", NULL, REG_SZ, (WCHAR*)L"Some default" }},
@ -2821,13 +2923,17 @@ static void test_RtlQueryRegistryValues(void)
L"Brussels\0Paris\0%PATH%", sizeof(L"Brussels\0Paris\0%PATH%"));
ok(status == ERROR_SUCCESS, "Failed to create registry value CapitalsOfEurope: %lu\n", status);
status = RegSetKeyValueW(HKEY_CURRENT_USER, L"WineTest\\subkey", L"Color", REG_SZ,
(void*)L"Yellow", sizeof(L"Yellow"));
ok(status == ERROR_SUCCESS, "Failed to create registry value Color: %lu\n", status);
status = RegSetKeyValueW(HKEY_CURRENT_USER, L"WineTest", L"MeaningOfLife32", REG_DWORD,
L"\x2a", sizeof(DWORD));
ok(status == ERROR_SUCCESS, "Failed to create registry value MeaningOfLife32: %lu\n", status);
query_reg_values_direct_str.MaximumLength = 32 * sizeof(WCHAR);
query_reg_values_direct_str.Buffer = pRtlAllocateHeap(GetProcessHeap(), 0,
query_reg_values_direct_str.MaximumLength);
status = RegSetKeyValueW(HKEY_CURRENT_USER, L"WineTest", L"MeaningOfLife64", REG_QWORD,
L"\x2a\0\0", sizeof(UINT64));
ok(status == ERROR_SUCCESS, "Failed to create registry value MeaningOfLife64: %lu\n", status);
status = RegSetKeyValueW(HKEY_CURRENT_USER, L"WineTest\\subkey", L"Color", REG_SZ,
L"Yellow", sizeof(L"Yellow"));
ok(status == ERROR_SUCCESS, "Failed to create registry value Color: %lu\n", status);
for (i = 0; i < ARRAY_SIZE(query_reg_values_tests); i++)
{
@ -2846,9 +2952,26 @@ static void test_RtlQueryRegistryValues(void)
}
query_routine_calls = 0;
query_reg_values_direct_str.Length = query_reg_values_direct_str.MaximumLength - sizeof(WCHAR);
query_reg_values_direct_str.MaximumLength = test->size_limit ? test->size_limit
: sizeof(query_reg_values_direct_str_buf);
if (query_reg_values_direct_str.MaximumLength >= sizeof(WCHAR))
query_reg_values_direct_str.Length = query_reg_values_direct_str.MaximumLength - sizeof(WCHAR);
else
query_reg_values_direct_str.Length = 0;
memset(query_reg_values_direct_str.Buffer, 0x23, query_reg_values_direct_str.Length);
query_reg_values_direct_str.Buffer[query_reg_values_direct_str.Length] = 0;
query_reg_values_direct_str.Buffer[query_reg_values_direct_str.Length / sizeof(WCHAR)] = 0;
query_reg_values_direct_int = 1;
memset(query_reg_values_direct_sized.data, 0x23, sizeof(query_reg_values_direct_sized));
query_reg_values_direct_sized.size = test->size_limit ? -test->size_limit
: -(LONG)sizeof(query_reg_values_direct_sized);
query_reg_values_direct_typed.size = test->size_limit ? test->size_limit
: sizeof(query_reg_values_direct_typed.data);
query_reg_values_direct_typed.type = 0x23;
memset(query_reg_values_direct_typed.data, 0x23, sizeof(query_reg_values_direct_typed.data));
status = pRtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer, test->query_table, test, NULL);
@ -2877,22 +3000,62 @@ static void test_RtlQueryRegistryValues(void)
expected_size = test->expected_data_size;
}
if (!expected_size && expected_data && (expected_type == REG_SZ || expected_type == REG_EXPAND_SZ))
expected_size = (wcslen(expected_data) + 1) * sizeof(WCHAR);
else if (expected_size == -1)
expected_size = query_reg_values_direct_str.MaximumLength;
todo_wine_if(test->flags & WINE_TODO_SIZE)
ok(query_reg_values_direct_str.Length + sizeof(WCHAR) == expected_size,
"Expected size %lu, got %Iu\n", expected_size,
query_reg_values_direct_str.Length + sizeof(WCHAR));
if (expected_data)
if (query->EntryContext == &query_reg_values_direct_str)
{
todo_wine_if(test->flags & WINE_TODO_DATA)
ok(!memcmp(query_reg_values_direct_str.Buffer, expected_data, expected_size),
"Expected data %s, got %s\n", debugstr_w(expected_data),
debugstr_w(query_reg_values_direct_str.Buffer));
if (!expected_size && expected_data)
expected_size = (wcslen(expected_data) + 1) * sizeof(WCHAR);
else if (expected_size == -1)
expected_size = query_reg_values_direct_str.MaximumLength;
todo_wine_if(test->flags & WINE_TODO_SIZE)
ok(query_reg_values_direct_str.Length + sizeof(WCHAR) == expected_size,
"Expected size %lu, got %Iu\n", expected_size,
query_reg_values_direct_str.Length + sizeof(WCHAR));
if (expected_data)
{
todo_wine_if(test->flags & WINE_TODO_DATA)
ok(!memcmp(query_reg_values_direct_str.Buffer, expected_data, expected_size),
"Expected data %s, got %s\n", debugstr_w(expected_data),
debugstr_w(query_reg_values_direct_str.Buffer));
}
}
else if (query->EntryContext == &query_reg_values_direct_int)
{
if (expected_data)
{
ok(!memcmp(&query_reg_values_direct_int, expected_data, expected_size),
"Data does not match\n");
}
else
{
ok(query_reg_values_direct_int == 1,
"Expected data to not change, got %lu\n", query_reg_values_direct_int);
}
}
else if (query->EntryContext == &query_reg_values_direct_sized)
{
ok(!memcmp(query_reg_values_direct_sized.data, expected_data, expected_size),
"Data does not match\n");
}
else if (query->EntryContext == &query_reg_values_direct_typed)
{
if (expected_size == -1)
expected_size = sizeof(query_reg_values_direct_typed.data);
todo_wine_if(test->flags & WINE_TODO_SIZE)
ok(query_reg_values_direct_typed.size == expected_size,
"Expected size %lu, got %lu\n", expected_size, query_reg_values_direct_typed.size);
todo_wine_if(test->flags & WINE_TODO_TYPE)
ok(query_reg_values_direct_typed.type == expected_type,
"Expected type %lu, got %lu\n", expected_type, query_reg_values_direct_typed.type);
if (expected_data)
{
ok(!memcmp(query_reg_values_direct_typed.data, expected_data, expected_size),
"Data does not match\n");
}
}
}
}
@ -2902,8 +3065,6 @@ static void test_RtlQueryRegistryValues(void)
status = RegDeleteKeyValueW(HKEY_CURRENT_USER, L"WineTest", L"WindowsDrive");
ok(status == ERROR_FILE_NOT_FOUND, "Registry value WindowsDrive should have been deleted already\n");
pRtlFreeHeap(GetProcessHeap(), 0, query_reg_values_direct_str.Buffer);
}
START_TEST(reg)

View File

@ -2822,18 +2822,13 @@ NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc
TRACE( "%p %s %p %d %p %d %p\n", device, iocodex(code), in_buffer, in_size, out_buffer, out_size, io );
io->Information = 0;
if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )))
{
if (status == STATUS_BAD_DEVICE_TYPE) return status; /* no associated fd */
goto error;
}
return status;
if ((status = CDROM_Open(fd, &dev)))
{
if (needs_close) close( fd );
goto error;
return status;
}
#ifdef __APPLE__
@ -2847,16 +2842,13 @@ NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc
* Also for some reason it wants the fd to be closed before we even
* open the parent if we're trying to eject the disk.
*/
if ((status = get_parent_device( fd, name, sizeof(name) ))) goto error;
if ((status = get_parent_device( fd, name, sizeof(name) ))) return status;
if (code == IOCTL_STORAGE_EJECT_MEDIA)
NtClose( device );
if (needs_close) close( fd );
TRACE("opening parent %s\n", name );
if ((fd = open( name, O_RDONLY )) == -1)
{
status = errno_to_status( errno );
goto error;
}
return errno_to_status( errno );
needs_close = 1;
}
#endif
@ -3117,13 +3109,10 @@ NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc
break;
default:
if (needs_close) close( fd );
return STATUS_NOT_SUPPORTED;
status = STATUS_NOT_SUPPORTED;
}
if (needs_close) close( fd );
error:
io->Status = status;
io->Information = sz;
if (event) NtSetEvent(event, NULL);
if (!NT_ERROR(status))
file_complete_async( device, event, apc, apc_user, io, status, sz );
return status;
}

View File

@ -5470,7 +5470,7 @@ static unsigned int register_async_file_read( HANDLE handle, HANDLE event,
return status;
}
void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info, BOOL async )
static void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info, BOOL async )
{
SERVER_START_REQ( add_fd_completion )
{
@ -5484,6 +5484,20 @@ void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info
SERVER_END_REQ;
}
/* complete async file I/O, signaling completion in all ways necessary */
void file_complete_async( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information )
{
ULONG_PTR iosb_ptr = iosb_client_ptr(io);
io->Status = status;
io->Information = information;
if (event) NtSetEvent( event, NULL );
if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, (ULONG_PTR)apc_user, iosb_ptr, 0 );
else if (apc_user) add_completion( handle, (ULONG_PTR)apc_user, status, information, FALSE );
}
static unsigned int set_pending_write( HANDLE device )
{
unsigned int status;
@ -6019,10 +6033,7 @@ NTSTATUS WINAPI NtWriteFileGather( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
int result, unix_handle, needs_close;
unsigned int options, status;
UINT pos = 0, total = 0;
client_ptr_t iosb_ptr = iosb_client_ptr(io);
enum server_fd_type type;
ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
BOOL send_completion = FALSE;
TRACE( "(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
file, event, apc, apc_user, io, segments, (int)length, offset, key );
@ -6074,24 +6085,18 @@ NTSTATUS WINAPI NtWriteFileGather( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
}
}
send_completion = cvalue != 0;
done:
if (needs_close) close( unix_handle );
if (status == STATUS_SUCCESS)
{
io->Status = status;
io->Information = total;
file_complete_async( file, event, apc, apc_user, io, status, total );
TRACE("= SUCCESS (%u)\n", total);
if (event) NtSetEvent( event, NULL );
if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, (ULONG_PTR)apc_user, iosb_ptr, 0 );
}
else
{
TRACE("= 0x%08x\n", status);
if (status != STATUS_PENDING && event) NtResetEvent( event, NULL );
}
if (send_completion) add_completion( file, cvalue, status, total, FALSE );
return status;
}
@ -6120,7 +6125,6 @@ NTSTATUS WINAPI NtDeviceIoControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUT
case FILE_DEVICE_BEEP:
case FILE_DEVICE_NETWORK:
status = sock_ioctl( handle, event, apc, apc_context, io, code, in_buffer, in_size, out_buffer, out_size );
if (status != STATUS_NOT_SUPPORTED && status != STATUS_BAD_DEVICE_TYPE) return status;
break;
case FILE_DEVICE_DISK:
case FILE_DEVICE_CD_ROM:
@ -6143,8 +6147,6 @@ NTSTATUS WINAPI NtDeviceIoControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUT
if (status == STATUS_NOT_SUPPORTED || status == STATUS_BAD_DEVICE_TYPE)
return server_ioctl_file( handle, event, apc, apc_context, io, code,
in_buffer, in_size, out_buffer, out_size );
if (status != STATUS_PENDING && !NT_ERROR(status)) io->Status = status;
return status;
}
@ -6180,6 +6182,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
IO_STATUS_BLOCK *io, ULONG code, void *in_buffer, ULONG in_size,
void *out_buffer, ULONG out_size )
{
ULONG_PTR size = 0;
NTSTATUS status;
TRACE( "(%p,%p,%p,%p,%p,0x%08x,%p,0x%08x,%p,0x%08x)\n",
@ -6223,19 +6226,17 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
buffer->StartingVcn.QuadPart = 1;
buffer->Extents[0].NextVcn.QuadPart = 0;
buffer->Extents[0].Lcn.QuadPart = 0;
io->Information = sizeof(RETRIEVAL_POINTERS_BUFFER);
size = sizeof(RETRIEVAL_POINTERS_BUFFER);
status = STATUS_SUCCESS;
}
else
{
io->Information = 0;
status = STATUS_BUFFER_TOO_SMALL;
}
break;
}
case FSCTL_GET_REPARSE_POINT:
io->Information = 0;
if (out_buffer && out_size)
{
FIXME("FSCTL_GET_REPARSE_POINT semi-stub\n");
@ -6250,7 +6251,6 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
int fd, needs_close;
struct stat st;
io->Information = 0;
if (out_size >= sizeof(*info))
{
status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL );
@ -6260,7 +6260,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
memset( info, 0, sizeof(*info) );
memcpy( info->ObjectId, &st.st_dev, sizeof(st.st_dev) );
memcpy( info->ObjectId + 8, &st.st_ino, sizeof(st.st_ino) );
io->Information = sizeof(*info);
size = sizeof(*info);
}
else status = STATUS_BUFFER_TOO_SMALL;
break;
@ -6268,7 +6268,6 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
case FSCTL_SET_SPARSE:
TRACE("FSCTL_SET_SPARSE: Ignoring request\n");
io->Information = 0;
status = STATUS_SUCCESS;
break;
default:
@ -6276,7 +6275,8 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
in_buffer, in_size, out_buffer, out_size );
}
if (status != STATUS_PENDING) io->Status = status;
if (!NT_ERROR(status) && status != STATUS_PENDING)
file_complete_async( handle, event, apc, apc_context, io, status, size );
return status;
}

View File

@ -147,12 +147,6 @@ SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4] =
static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
#endif
#if defined(linux) || defined(__APPLE__)
static const BOOL use_preloader = TRUE;
#else
static const BOOL use_preloader = FALSE;
#endif
static const char *bin_dir;
static const char *dll_dir;
static const char *ntdll_dir;
@ -500,31 +494,30 @@ char *get_alternate_wineloader( WORD machine )
static void preloader_exec( char **argv )
{
if (use_preloader)
{
static const char *preloader = "wine-preloader";
char *p;
#ifdef HAVE_WINE_PRELOADER
static const char *preloader = "wine-preloader";
char *p;
if (!(p = strrchr( argv[1], '/' ))) p = argv[1];
else p++;
if (!(p = strrchr( argv[1], '/' ))) p = argv[1];
else p++;
if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader";
argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 );
memcpy( argv[0], argv[1], p - argv[1] );
strcpy( argv[0] + (p - argv[1]), preloader );
if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader";
argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 );
memcpy( argv[0], argv[1], p - argv[1] );
strcpy( argv[0] + (p - argv[1]), preloader );
#ifdef __APPLE__
{
posix_spawnattr_t attr;
posix_spawnattr_init( &attr );
posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() );
posix_spawnattr_destroy( &attr );
}
#endif
execv( argv[0], argv );
free( argv[0] );
{
posix_spawnattr_t attr;
posix_spawnattr_init( &attr );
posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() );
posix_spawnattr_destroy( &attr );
}
#endif
execv( argv[0], argv );
free( argv[0] );
#endif
execv( argv[1], argv + 1 );
}
@ -2035,18 +2028,7 @@ static void apple_main_thread(void)
#endif /* __APPLE__ */
#ifdef __ANDROID__
static int pre_exec(void)
{
#if defined(__i386__) || defined(__x86_64__)
return 1; /* we have a preloader */
#else
return 0; /* no exec needed */
#endif
}
#elif defined(__linux__) && (defined(__i386__) || defined(__arm__))
#if defined(__linux__) && !defined(__ANDROID__) && (defined(__i386__) || defined(__arm__))
static void check_vmsplit( void *stack )
{
@ -2067,20 +2049,6 @@ static int pre_exec(void)
return 1; /* we have a preloader on x86/arm */
}
#elif defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__))
static int pre_exec(void)
{
return 1; /* we have a preloader on x86-64/arm64 */
}
#elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
static int pre_exec(void)
{
return 1; /* we have a preloader */
}
#elif (defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__))
static int pre_exec(void)
@ -2097,7 +2065,11 @@ static int pre_exec(void)
static int pre_exec(void)
{
#ifdef HAVE_WINE_PRELOADER
return 1; /* we have a preloader */
#else
return 0; /* no exec needed */
#endif
}
#endif

View File

@ -1261,14 +1261,12 @@ NTSTATUS serial_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE ap
return STATUS_NOT_SUPPORTED;
}
io->Information = 0;
if ((status = server_get_unix_fd( device, access, &fd, &needs_close, &type, NULL ))) goto error;
if ((status = server_get_unix_fd( device, access, &fd, &needs_close, &type, NULL )))
return status;
if (type != FD_TYPE_SERIAL)
{
if (needs_close) close( fd );
status = STATUS_OBJECT_TYPE_MISMATCH;
goto error;
return STATUS_OBJECT_TYPE_MISMATCH;
}
switch (code)
@ -1455,11 +1453,11 @@ NTSTATUS serial_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE ap
status = STATUS_INVALID_PARAMETER;
break;
}
if (needs_close) close( fd );
error:
io->Status = status;
io->Information = sz;
if (event) NtSetEvent(event, NULL);
if (!NT_ERROR(status))
file_complete_async( device, event, apc, apc_user, io, status, sz );
return status;
}

View File

@ -1252,9 +1252,9 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
"5:\tmovw r0, #0x000d\n\t" /* STATUS_INVALID_PARAMETER */
"movt r0, #0xc000\n\t"
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n"
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher_return,
"mov r8, r0\n\t"
"mov r0, r1\n\t"
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )

View File

@ -1607,9 +1607,9 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
"ret x16\n"
"4:\tmov x0, #0xc0000000\n\t" /* STATUS_INVALID_PARAMETER */
"movk x0, #0x000d\n\t"
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n"
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher_return,
"mov sp, x0\n\t"
"mov x0, x1\n\t"
"b " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )

View File

@ -2768,10 +2768,9 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
__ASM_CFI("\t.cfi_restore_state\n")
"6:\tmovl $0xc000000d,%eax\n\t" /* STATUS_INVALID_PARAMETER */
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n"
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher_return,
"movl 8(%esp),%eax\n\t"
"movl 4(%esp),%esp\n\t"
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )

View File

@ -2876,9 +2876,9 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
__ASM_CFI("\t.cfi_restore_state\n")
"5:\tmovl $0xc000000d,%eax\n\t" /* STATUS_INVALID_PARAMETER */
"movq %rsp,%rcx\n\t"
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") "\n\t"
".globl " __ASM_NAME("__wine_syscall_dispatcher_return") "\n"
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
"jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_return") )
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher_return,
"movq %rdi,%rcx\n\t"
"movl 0xb0(%rcx),%r14d\n\t" /* frame->syscall_flags */
"movq %rsi,%rax\n\t"

View File

@ -1425,18 +1425,6 @@ static NTSTATUS sock_transmit( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc,
return status;
}
static void complete_async( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information )
{
ULONG_PTR iosb_ptr = iosb_client_ptr(io);
io->Status = status;
io->Information = information;
if (event) NtSetEvent( event, NULL );
if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, (ULONG_PTR)apc_user, iosb_ptr, 0 );
if (apc_user) add_completion( handle, (ULONG_PTR)apc_user, status, information, FALSE );
}
static NTSTATUS do_getsockopt( HANDLE handle, IO_STATUS_BLOCK *io, int level,
int option, void *out_buffer, ULONG out_size )
@ -1563,7 +1551,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
}
SERVER_END_REQ;
complete_async( handle, event, apc, apc_user, io, status, 0 );
file_complete_async( handle, event, apc, apc_user, io, status, 0 );
return status;
}
@ -1710,7 +1698,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
return STATUS_BUFFER_TOO_SMALL;
status = *(NTSTATUS *)in_buffer;
complete_async( handle, event, apc, apc_user, io, status, 0 );
file_complete_async( handle, event, apc, apc_user, io, status, 0 );
return status;
}
@ -1736,7 +1724,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
{
*(int *)out_buffer = 0;
if (needs_close) close( fd );
complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
return STATUS_SUCCESS;
}
}
@ -1749,7 +1737,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
}
*(int *)out_buffer = value;
if (needs_close) close( fd );
complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
return STATUS_SUCCESS;
}
@ -1788,7 +1776,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
*(int *)out_buffer = !value;
}
if (needs_close) close( fd );
complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
return STATUS_SUCCESS;
}
@ -1815,7 +1803,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
if (out_size < ret_size)
{
freeifaddrs( ifaddrs );
complete_async( handle, event, apc, apc_user, io, STATUS_BUFFER_TOO_SMALL, 0 );
file_complete_async( handle, event, apc, apc_user, io, STATUS_BUFFER_TOO_SMALL, 0 );
return STATUS_PENDING;
}
@ -1865,7 +1853,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
}
freeifaddrs( ifaddrs );
complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, ret_size );
file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, ret_size );
return STATUS_PENDING;
#else
FIXME( "Interface list queries are currently not supported on this platform.\n" );
@ -1920,7 +1908,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
}
if (needs_close) close( fd );
complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 );
return STATUS_SUCCESS;
}

View File

@ -4073,10 +4073,10 @@ NTSTATUS WINAPI NtDisplayString( UNICODE_STRING *string )
* NtRaiseHardError (NTDLL.@)
*/
NTSTATUS WINAPI NtRaiseHardError( NTSTATUS status, ULONG count,
UNICODE_STRING *params_mask, void **params,
ULONG params_mask, void **params,
HARDERROR_RESPONSE_OPTION option, HARDERROR_RESPONSE *response )
{
FIXME( "%08x stub\n", (int)status );
FIXME( "%#08x %u %#x %p %u %p: stub\n", (int)status, (int)count, (int)params_mask, params, option, response );
return STATUS_NOT_IMPLEMENTED;
}

View File

@ -528,9 +528,8 @@ NTSTATUS tape_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc,
TRACE( "%p %s %p %d %p %d %p\n", device, io2str(code),
in_buffer, in_size, out_buffer, out_size, io );
io->Information = 0;
if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL ))) goto error;
if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )))
return status;
switch (code)
{
@ -580,9 +579,7 @@ NTSTATUS tape_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc,
if (needs_close) close( fd );
error:
io->Status = status;
io->Information = sz;
if (event) NtSetEvent( event, NULL );
if (!NT_ERROR(status))
file_complete_async( device, event, apc, apc_user, io, status, sz );
return status;
}

View File

@ -342,7 +342,8 @@ extern NTSTATUS open_unix_file( HANDLE *handle, const char *unix_name, ACCESS_MA
extern NTSTATUS get_device_info( int fd, struct _FILE_FS_DEVICE_INFORMATION *info );
extern void init_files(void);
extern void init_cpu_info(void);
extern void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info, BOOL async );
extern void file_complete_async( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information );
extern void set_async_direct_result( HANDLE *async_handle, NTSTATUS status, ULONG_PTR information, BOOL mark_pending );
extern NTSTATUS unixcall_wine_dbg_write( void *args );

View File

@ -3621,6 +3621,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
if (is_wow) teb64->WowTebOffset = teb_offset;
#else
teb = (TEB *)teb32;
teb32->Tib.ExceptionList = ~0u;
teb64->Peb = PtrToUlong( (char *)peb - page_size );
teb64->Tib.Self = PtrToUlong( teb64 );
teb64->Tib.ExceptionList = PtrToUlong( teb32 );
@ -3639,7 +3640,6 @@ static TEB *init_teb( void *ptr, BOOL is_wow )
#endif
teb->Peb = peb;
teb->Tib.Self = &teb->Tib;
teb->Tib.ExceptionList = (void *)~0ul;
teb->Tib.StackBase = (void *)~0ul;
teb->ActivationContextStackPointer = &teb->ActivationContextStack;
InitializeListHead( &teb->ActivationContextStack.FrameListCache );

View File

@ -3407,6 +3407,16 @@ PVOID WINAPI MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName)
return pFunc;
}
/***********************************************************************
* MmGetPhysicalAddress (NTOSKRNL.EXE.@)
*/
PHYSICAL_ADDRESS WINAPI MmGetPhysicalAddress(PVOID BaseAddress)
{
FIXME("stub\n");
return (PHYSICAL_ADDRESS) VirtualAddress;
}
/***********************************************************************
* MmIsThisAnNtAsSystem (NTOSKRNL.EXE.@)
*/

View File

@ -1072,7 +1072,7 @@
@ stub RtlEnumerateGenericTableAvl
@ stub RtlEnumerateGenericTableLikeADirectory
@ stdcall RtlEnumerateGenericTableWithoutSplaying(ptr ptr)
@ stub RtlEnumerateGenericTableWithoutSplayingAvl
@ stdcall RtlEnumerateGenericTableWithoutSplayingAvl(ptr ptr)
@ stdcall RtlEqualLuid(ptr ptr)
@ stdcall RtlEqualSid(ptr ptr)
@ stdcall RtlEqualString(ptr ptr long)
@ -1214,7 +1214,7 @@
@ stdcall RtlNtStatusToDosError(long)
@ stdcall RtlNtStatusToDosErrorNoTeb(long)
@ stdcall RtlNumberGenericTableElements(ptr)
@ stub RtlNumberGenericTableElementsAvl
@ stdcall RtlNumberGenericTableElementsAvl(ptr)
@ stdcall RtlNumberOfClearBits(ptr)
@ stdcall RtlNumberOfSetBits(ptr)
@ stub RtlOemStringToCountedUnicodeString

View File

@ -223,7 +223,6 @@ static BOOL SQLInstall_narrow(int mode, LPSTR buffer, LPCWSTR str, WORD str_leng
static HMODULE load_config_driver(const WCHAR *driver)
{
static WCHAR reg_driver[] = {'d','r','i','v','e','r',0};
long ret;
HMODULE hmod;
WCHAR *filename = NULL;
@ -236,7 +235,7 @@ static HMODULE load_config_driver(const WCHAR *driver)
if ((ret = RegOpenKeyW(hkey, driver, &hkeydriver)) == ERROR_SUCCESS)
{
ret = RegGetValueW(hkeydriver, NULL, reg_driver, RRF_RT_REG_SZ, &type, NULL, &size);
ret = RegGetValueW(hkeydriver, NULL, L"Setup", RRF_RT_REG_SZ, &type, NULL, &size);
if(ret != ERROR_SUCCESS || type != REG_SZ)
{
RegCloseKey(hkeydriver);
@ -255,7 +254,7 @@ static HMODULE load_config_driver(const WCHAR *driver)
return NULL;
}
ret = RegGetValueW(hkeydriver, NULL, reg_driver, RRF_RT_REG_SZ, &type, filename, &size);
ret = RegGetValueW(hkeydriver, NULL, L"Setup", RRF_RT_REG_SZ, &type, filename, &size);
RegCloseKey(hkeydriver);
}
@ -373,7 +372,7 @@ BOOL WINAPI SQLConfigDataSourceW(HWND hwnd, WORD request, LPCWSTR driver, LPCWST
WORD mapped_request;
TRACE("%p, %d, %s, %s\n", hwnd, request, debugstr_w(driver), debugstr_w(attributes));
if (TRACE_ON(odbc))
if (TRACE_ON(odbc) && attributes)
{
const WCHAR *p;
for (p = attributes; *p; p += lstrlenW(p) + 1)
@ -418,7 +417,7 @@ BOOL WINAPI SQLConfigDataSource(HWND hwnd, WORD request, LPCSTR driver, LPCSTR a
TRACE("%p, %d, %s, %s\n", hwnd, request, debugstr_a(driver), debugstr_a(attributes));
if (TRACE_ON(odbc))
if (TRACE_ON(odbc) && attributes)
{
const char *p;
for (p = attributes; *p; p += lstrlenA(p) + 1)

2
dlls/profapi/Makefile.in Normal file
View File

@ -0,0 +1,2 @@
MODULE = profapi.dll
IMPORTLIB = profapi

17
dlls/profapi/profapi.spec Normal file
View File

@ -0,0 +1,17 @@
101 stub -noname @
102 stub -noname @
103 stub -noname @
104 stub -noname @
105 stub -noname @
106 stub -noname @
107 stub -noname @
108 stub -noname @
109 stub -noname @
110 stub -noname @
111 stub -noname @
112 stub -noname @
113 stub -noname @
114 stub -noname @
115 stub -noname @
116 stub -noname @
117 stub -noname @

View File

@ -0,0 +1,6 @@
MODULE = rometadata.dll
IMPORTLIB = rometadata
IMPORTS = combase
SOURCES = \
main.c

194
dlls/rometadata/main.c Normal file
View File

@ -0,0 +1,194 @@
/*
* Copyright 2024 Zhiyi Zhang for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "initguid.h"
#include "objbase.h"
#include "cor.h"
#include "rometadata.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(rometadata);
struct metadata_dispenser
{
IMetaDataDispenserEx IMetaDataDispenserEx_iface;
LONG refcount;
};
static inline struct metadata_dispenser *impl_from_IMetaDataDispenserEx(IMetaDataDispenserEx *iface)
{
return CONTAINING_RECORD(iface, struct metadata_dispenser, IMetaDataDispenserEx_iface);
}
static HRESULT WINAPI MetaDataDispenser_QueryInterface(IMetaDataDispenserEx *iface, REFIID riid, void **obj)
{
TRACE("%p %s %p\n", iface, debugstr_guid(riid), obj);
if (IsEqualGUID(riid, &IID_IMetaDataDispenserEx)
|| IsEqualGUID(riid, &IID_IMetaDataDispenser)
|| IsEqualGUID(riid, &IID_IUnknown))
{
*obj = iface;
IMetaDataDispenserEx_AddRef(iface);
return S_OK;
}
FIXME("Unsupported interface %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI MetaDataDispenser_AddRef(IMetaDataDispenserEx *iface)
{
struct metadata_dispenser *this = impl_from_IMetaDataDispenserEx(iface);
ULONG ref = InterlockedIncrement(&this->refcount);
TRACE("%p ref=%lu\n", this, ref);
return ref;
}
static ULONG WINAPI MetaDataDispenser_Release(IMetaDataDispenserEx *iface)
{
struct metadata_dispenser *this = impl_from_IMetaDataDispenserEx(iface);
ULONG ref = InterlockedDecrement(&this->refcount);
TRACE("%p ref=%lu\n", this, ref);
if (ref == 0)
free(this);
return ref;
}
static HRESULT WINAPI MetaDataDispenser_DefineScope(IMetaDataDispenserEx *iface, REFCLSID rclsid,
DWORD create_flags, REFIID riid, IUnknown **obj)
{
FIXME("%p %s %lx %s %p\n", iface, debugstr_guid(rclsid), create_flags, debugstr_guid(riid),
obj);
return E_NOTIMPL;
}
static HRESULT WINAPI MetaDataDispenser_OpenScope(IMetaDataDispenserEx *iface, const WCHAR *scope,
DWORD open_flags, REFIID riid, IUnknown **obj)
{
FIXME("%p %s %lx %s %p\n", iface, debugstr_w(scope), open_flags, debugstr_guid(riid), obj);
return E_NOTIMPL;
}
static HRESULT WINAPI MetaDataDispenser_OpenScopeOnMemory(IMetaDataDispenserEx *iface, const void *data,
ULONG data_size, DWORD open_flags, REFIID riid,
IUnknown **obj)
{
FIXME("%p %p %lu %lx %s %p\n", iface, data, data_size, open_flags, debugstr_guid(riid), obj);
return E_NOTIMPL;
}
static HRESULT WINAPI MetaDataDispenser_SetOption(IMetaDataDispenserEx *iface, REFGUID option_id, const VARIANT *value)
{
FIXME("%p %s %p\n", iface, debugstr_guid(option_id), debugstr_variant(value));
return E_NOTIMPL;
}
static HRESULT WINAPI MetaDataDispenser_GetOption(IMetaDataDispenserEx *iface, REFGUID optionid, VARIANT *value)
{
FIXME("%p %s %s\n", iface, debugstr_guid(optionid), debugstr_variant(value));
return E_NOTIMPL;
}
static HRESULT WINAPI MetaDataDispenser_OpenScopeOnITypeInfo(IMetaDataDispenserEx *iface, ITypeInfo *type_info,
DWORD open_flags, REFIID riid, IUnknown **obj)
{
FIXME("%p %p %lu %s %p\n", iface, type_info, open_flags, debugstr_guid(riid), obj);
return E_NOTIMPL;
}
static HRESULT WINAPI MetaDataDispenser_GetCORSystemDirectory(IMetaDataDispenserEx *iface, WCHAR *buffer,
DWORD buffer_size, DWORD *return_length)
{
FIXME("%p %p %lu %p\n", iface, buffer, buffer_size, return_length);
return E_NOTIMPL;
}
static HRESULT WINAPI MetaDataDispenser_FindAssembly(IMetaDataDispenserEx *iface, const WCHAR *app_base,
const WCHAR *private_bin, const WCHAR *global_bin,
const WCHAR *assembly_name, WCHAR *name, ULONG name_size,
ULONG *return_length)
{
FIXME("%p %s %s %s %s %p %lu %p\n", iface, debugstr_w(app_base), debugstr_w(private_bin),
debugstr_w(global_bin), debugstr_w(assembly_name), name, name_size, return_length);
return E_NOTIMPL;
}
static HRESULT WINAPI MetaDataDispenser_FindAssemblyModule(IMetaDataDispenserEx *iface, const WCHAR *app_base,
const WCHAR *private_bin, const WCHAR *global_bin,
const WCHAR *assembly_name, const WCHAR *module_name,
WCHAR *name, ULONG name_size, ULONG *return_length)
{
FIXME("%p %s %s %s %s %s %p %lu %p\n", iface, debugstr_w(app_base), debugstr_w(private_bin),
debugstr_w(global_bin), debugstr_w(assembly_name), debugstr_w(module_name), name, name_size, return_length);
return E_NOTIMPL;
}
static const struct IMetaDataDispenserExVtbl MetaDataDispenserExVtbl =
{
MetaDataDispenser_QueryInterface,
MetaDataDispenser_AddRef,
MetaDataDispenser_Release,
MetaDataDispenser_DefineScope,
MetaDataDispenser_OpenScope,
MetaDataDispenser_OpenScopeOnMemory,
MetaDataDispenser_SetOption,
MetaDataDispenser_GetOption,
MetaDataDispenser_OpenScopeOnITypeInfo,
MetaDataDispenser_GetCORSystemDirectory,
MetaDataDispenser_FindAssembly,
MetaDataDispenser_FindAssemblyModule
};
STDAPI MetaDataGetDispenser(REFCLSID rclsid, REFIID riid, void **obj)
{
struct metadata_dispenser *dispenser;
HRESULT hr;
TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), obj);
if (!IsEqualGUID(rclsid, &CLSID_CorMetaDataDispenser))
return CLASS_E_CLASSNOTAVAILABLE;
dispenser = malloc(sizeof(*dispenser));
if (!dispenser)
return E_OUTOFMEMORY;
dispenser->IMetaDataDispenserEx_iface.lpVtbl = &MetaDataDispenserExVtbl;
dispenser->refcount = 1;
hr = IMetaDataDispenserEx_QueryInterface(&dispenser->IMetaDataDispenserEx_iface, riid, obj);
IMetaDataDispenserEx_Release(&dispenser->IMetaDataDispenserEx_iface);
return hr;
}
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
{
TRACE("inst %p, reason %lu, reserved %p.\n", inst, reason, reserved);
if (reason == DLL_PROCESS_ATTACH)
DisableThreadLibraryCalls(inst);
return TRUE;
}

View File

@ -0,0 +1 @@
@ stdcall MetaDataGetDispenser(ptr ptr ptr)

View File

@ -0,0 +1,5 @@
TESTDLL = rometadata.dll
IMPORTS = combase rometadata
SOURCES = \
rometadata.c

View File

@ -0,0 +1,70 @@
/*
* Copyright 2024 Zhiyi Zhang for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <windows.h>
#include "initguid.h"
#include "cor.h"
#include "roapi.h"
#include "rometadata.h"
#include "wine/test.h"
DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
static void test_MetaDataGetDispenser(void)
{
IMetaDataDispenserEx *dispenser_ex;
IMetaDataDispenser *dispenser;
IUnknown *unknown;
HRESULT hr;
/* Invalid parameters */
hr = MetaDataGetDispenser(&CLSID_NULL, &IID_IMetaDataDispenser, (void **)&dispenser);
ok(hr == CLASS_E_CLASSNOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
hr = MetaDataGetDispenser(&CLSID_CorMetaDataDispenser, &IID_NULL, (void **)&dispenser);
ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
/* Normal calls */
hr = MetaDataGetDispenser(&CLSID_CorMetaDataDispenser, &IID_IUnknown, (void **)&unknown);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
IUnknown_Release(unknown);
hr = MetaDataGetDispenser(&CLSID_CorMetaDataDispenser, &IID_IMetaDataDispenser, (void **)&dispenser);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
IMetaDataDispenser_Release(dispenser);
hr = MetaDataGetDispenser(&CLSID_CorMetaDataDispenser, &IID_IMetaDataDispenserEx, (void **)&dispenser_ex);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
IMetaDataDispenserEx_Release(dispenser_ex);
}
START_TEST(rometadata)
{
HRESULT hr;
hr = RoInitialize(RO_INIT_MULTITHREADED);
ok(hr == S_OK, "RoInitialize failed, hr %#lx\n", hr);
test_MetaDataGetDispenser();
RoUninitialize();
}

View File

@ -59,6 +59,7 @@ TW_UINT16 sane_option_set_int(const char *option_name, int val, BOOL *needs_relo
{
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_INT, &opt);
if (!opt.is_settable) return TWCC_OPERATIONERROR;
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, &val, needs_reload );
return rc;
@ -77,6 +78,7 @@ TW_UINT16 sane_option_set_bool(const char *option_name, int val )
{
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_BOOL, &opt);
if (!opt.is_settable) return TWCC_OPERATIONERROR;
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, &val, NULL );
return rc;
@ -102,6 +104,7 @@ TW_UINT16 sane_option_set_str(const char *option_name, char *val, BOOL *needs_re
{
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option(option_name, TYPE_STRING, &opt);
if (!opt.is_settable) return TWCC_OPERATIONERROR;
if (rc == TWCC_SUCCESS) rc = sane_option_set_value( opt.optno, val, needs_reload );
return rc;

View File

@ -159,6 +159,7 @@ static void map_descr( struct option_descriptor *descr, const SANE_Option_Descri
descr->constraint_type = map_constraint_type( opt->constraint_type );
descr->size = opt->size;
descr->is_active = SANE_OPTION_IS_ACTIVE( opt->cap );
descr->is_settable = SANE_OPTION_IS_SETTABLE( opt->cap );
if (opt->title) len = ntdll_umbstowcs( opt->title, strlen(opt->title),
descr->title, ARRAY_SIZE(descr->title) );
descr->title[len] = 0;

View File

@ -39,6 +39,7 @@ struct option_descriptor
int optno;
int size;
int is_active;
int is_settable;
enum { TYPE_BOOL, TYPE_INT, TYPE_FIXED, TYPE_STRING, TYPE_BUTTON, TYPE_GROUP } type;
enum { UNIT_NONE, UNIT_PIXEL, UNIT_BIT, UNIT_MM, UNIT_DPI, UNIT_PERCENT, UNIT_MICROSECOND } unit;
enum { CONSTRAINT_NONE, CONSTRAINT_RANGE, CONSTRAINT_WORD_LIST, CONSTRAINT_STRING_LIST } constraint_type;

View File

@ -56,5 +56,3 @@ SOURCES = \
vulkan.c \
window.c \
winstation.c
font_EXTRADEFS = -DWINE_FONT_DIR=\"`${MAKEDEP} -R ${datadir}/wine ${fontdir}`\"

View File

@ -65,7 +65,6 @@ static PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryPro
static PFN_vkGetPhysicalDeviceMemoryProperties pvkGetPhysicalDeviceMemoryProperties;
static PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
static PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
static const struct vulkan_funcs *vulkan_funcs;
static void d3dkmt_init_vulkan(void)
{
@ -94,7 +93,6 @@ static void d3dkmt_init_vulkan(void)
if ((vr = p_vkCreateInstance( &create_info, NULL, &d3dkmt_vk_instance )))
{
WARN( "Failed to create a Vulkan instance, vr %d.\n", vr );
vulkan_funcs = NULL;
return;
}
@ -104,7 +102,7 @@ static void d3dkmt_init_vulkan(void)
{ \
WARN( "Failed to load " #f ".\n" ); \
p_vkDestroyInstance( d3dkmt_vk_instance, NULL ); \
vulkan_funcs = NULL; \
d3dkmt_vk_instance = NULL; \
return; \
}
LOAD_VK_FUNC( vkEnumeratePhysicalDevices )
@ -118,7 +116,7 @@ static BOOL d3dkmt_use_vulkan(void)
{
static pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once( &once, d3dkmt_init_vulkan );
return !!vulkan_funcs;
return !!d3dkmt_vk_instance;
}
/* d3dkmt_lock must be held */

View File

@ -462,10 +462,6 @@ static const struct nls_update_font_list
static pthread_mutex_t font_lock = PTHREAD_MUTEX_INITIALIZER;
#ifndef WINE_FONT_DIR
#define WINE_FONT_DIR "fonts"
#endif
#ifdef WORDS_BIGENDIAN
#define GET_BE_WORD(x) (x)
#define GET_BE_DWORD(x) (x)
@ -476,20 +472,12 @@ static pthread_mutex_t font_lock = PTHREAD_MUTEX_INITIALIZER;
static void get_fonts_data_dir_path( const WCHAR *file, WCHAR *path )
{
const char *dir;
const char *dir = ntdll_get_build_dir();
ULONG len = MAX_PATH;
if ((dir = ntdll_get_data_dir()))
{
wine_unix_to_nt_file_name( dir, path, &len );
asciiz_to_unicode( path + len - 1, "\\" WINE_FONT_DIR "\\" );
}
else if ((dir = ntdll_get_build_dir()))
{
wine_unix_to_nt_file_name( dir, path, &len );
asciiz_to_unicode( path + len - 1, "\\fonts\\" );
}
if (!dir) dir = ntdll_get_data_dir();
wine_unix_to_nt_file_name( dir, path, &len );
asciiz_to_unicode( path + len - 1, "\\fonts\\" );
if (file) lstrcatW( path, file );
}

View File

@ -345,8 +345,6 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz
if (params != info) free( params );
}
if (info->id == WH_KEYBOARD_LL || info->id == WH_MOUSE_LL)
InterlockedIncrement( &global_key_state_counter ); /* force refreshing the key state cache */
return ret;
}

View File

@ -406,7 +406,6 @@ static const KBDTABLES kbdus_tables =
static LONG clipping_cursor; /* clipping thread counter */
LONG global_key_state_counter = 0;
BOOL grab_pointer = TRUE;
BOOL grab_fullscreen = FALSE;
@ -740,22 +739,22 @@ BOOL WINAPI NtUserSetCursorPos( INT x, INT y )
*/
BOOL get_cursor_pos( POINT *pt )
{
struct object_lock lock = OBJECT_LOCK_INIT;
const desktop_shm_t *desktop_shm;
BOOL ret;
DWORD last_change;
DWORD last_change = 0;
NTSTATUS status;
UINT dpi;
if (!pt) return FALSE;
SERVER_START_REQ( set_cursor )
while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING)
{
if ((ret = !wine_server_call( req )))
{
pt->x = reply->new_x;
pt->y = reply->new_y;
last_change = reply->last_change;
}
pt->x = desktop_shm->cursor.x;
pt->y = desktop_shm->cursor.y;
last_change = desktop_shm->cursor.last_change;
}
SERVER_END_REQ;
ret = !status;
/* query new position from graphics driver if we haven't updated recently */
if (ret && NtGetTickCount() - last_change > 100) ret = user_driver->pGetCursorPos( pt );
@ -810,52 +809,31 @@ static void check_for_events( UINT flags )
*/
SHORT WINAPI NtUserGetAsyncKeyState( INT key )
{
struct user_key_state_info *key_state_info = get_user_thread_info()->key_state;
INT counter = global_key_state_counter;
BYTE prev_key_state;
SHORT ret;
const desktop_shm_t *desktop_shm;
struct object_lock lock = OBJECT_LOCK_INIT;
NTSTATUS status;
BYTE state = 0;
SHORT ret = 0;
if (key < 0 || key >= 256) return 0;
check_for_events( QS_INPUT );
if (key_state_info && !(key_state_info->state[key] & 0xc0) &&
key_state_info->counter == counter && NtGetTickCount() - key_state_info->time < 50)
{
/* use cached value */
return 0;
}
else if (!key_state_info)
{
key_state_info = calloc( 1, sizeof(*key_state_info) );
get_user_thread_info()->key_state = key_state_info;
}
while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING)
state = desktop_shm->keystate[key];
ret = 0;
if (status) return 0;
if (!(state & 0x40)) return (state & 0x80) << 8;
/* Need to make a server call to reset the last pressed bit */
SERVER_START_REQ( get_key_state )
{
req->async = 1;
req->key = key;
if (key_state_info)
{
prev_key_state = key_state_info->state[key];
wine_server_set_reply( req, key_state_info->state, sizeof(key_state_info->state) );
}
if (!wine_server_call( req ))
{
if (reply->state & 0x40) ret |= 0x0001;
if (reply->state & 0x80) ret |= 0x8000;
if (key_state_info)
{
/* force refreshing the key state cache - some multithreaded programs
* (like Adobe Photoshop CS5) expect that changes to the async key state
* are also immediately available in other threads. */
if (prev_key_state != key_state_info->state[key])
counter = InterlockedIncrement( &global_key_state_counter );
key_state_info->time = NtGetTickCount();
key_state_info->counter = counter;
}
}
}
SERVER_END_REQ;
@ -2555,24 +2533,21 @@ BOOL WINAPI NtUserGetPointerInfoList( UINT32 id, POINTER_INPUT_TYPE type, UINT_P
BOOL get_clip_cursor( RECT *rect, UINT dpi )
{
BOOL ret;
struct object_lock lock = OBJECT_LOCK_INIT;
const desktop_shm_t *desktop_shm;
NTSTATUS status;
if (!rect) return FALSE;
SERVER_START_REQ( set_cursor )
{
req->flags = 0;
if ((ret = !wine_server_call( req )))
*rect = wine_server_get_rect( reply->new_clip );
}
SERVER_END_REQ;
while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING)
*rect = wine_server_get_rect( desktop_shm->cursor.clip );
if (ret)
if (!status)
{
HMONITOR monitor = monitor_from_rect( rect, MONITOR_DEFAULTTOPRIMARY, 0 );
*rect = map_dpi_rect( *rect, get_monitor_dpi( monitor ), dpi );
}
return ret;
return !status;
}
BOOL process_wine_clipcursor( HWND hwnd, UINT flags, BOOL reset )

View File

@ -3469,7 +3469,7 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA
struct send_message_info info;
int prev_x, prev_y, new_x, new_y;
NTSTATUS ret;
BOOL wait, affects_key_state = FALSE;
BOOL wait;
info.type = MSG_HARDWARE;
info.dest_tid = 0;
@ -3495,10 +3495,6 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA
req->input.mouse.flags = input->mi.dwFlags;
req->input.mouse.time = input->mi.time;
req->input.mouse.info = input->mi.dwExtraInfo;
affects_key_state = !!(input->mi.dwFlags & (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP |
MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP |
MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP |
MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP));
break;
case INPUT_KEYBOARD:
if (input->ki.dwFlags & KEYEVENTF_SCANCODE)
@ -3523,7 +3519,6 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA
req->input.kbd.flags = input->ki.dwFlags & ~KEYEVENTF_SCANCODE;
req->input.kbd.time = input->ki.time;
req->input.kbd.info = input->ki.dwExtraInfo;
affects_key_state = TRUE;
break;
case INPUT_HARDWARE:
req->input.hw.msg = input->hi.uMsg;
@ -3553,13 +3548,8 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA
}
SERVER_END_REQ;
if (!ret)
{
if (affects_key_state)
InterlockedIncrement( &global_key_state_counter ); /* force refreshing the key state cache */
if ((flags & SEND_HWMSG_INJECTED) && (prev_x != new_x || prev_y != new_y))
user_driver->pSetCursorPos( new_x, new_y );
}
if (!ret && (flags & SEND_HWMSG_INJECTED) && (prev_x != new_x || prev_y != new_y))
user_driver->pSetCursorPos( new_x, new_y );
if (wait)
{

View File

@ -116,7 +116,6 @@ struct user_thread_info
HHOOK hook; /* Current hook */
UINT active_hooks; /* Bitmap of active hooks */
struct received_message_info *receive_info; /* Message being currently received */
struct user_key_state_info *key_state; /* Cache of global key state */
struct imm_thread_data *imm_thread_data; /* IMM thread data */
HKL kbd_layout; /* Current keyboard layout */
UINT kbd_layout_id; /* Current keyboard layout ID */
@ -124,6 +123,7 @@ struct user_thread_info
UINT spy_indent; /* Current spy indent */
BOOL clipping_cursor; /* thread is currently clipping */
DWORD clipping_reset; /* time when clipping was last reset */
struct session_thread_data *session_data; /* shared session thread data */
};
C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) );
@ -133,13 +133,6 @@ static inline struct user_thread_info *get_user_thread_info(void)
return CONTAINING_RECORD( NtUserGetThreadInfo(), struct user_thread_info, client_info );
}
struct user_key_state_info
{
UINT time; /* Time of last key state refresh */
INT counter; /* Counter to invalidate the key state */
BYTE state[256]; /* State for each key */
};
struct hook_extra_info
{
HHOOK handle;

View File

@ -6334,12 +6334,11 @@ static void thread_detach(void)
destroy_thread_windows();
user_driver->pThreadDetach();
free( thread_info->key_state );
thread_info->key_state = 0;
free( thread_info->rawinput );
cleanup_imm_thread();
NtClose( thread_info->server_queue );
free( thread_info->session_data );
exiting_thread_id = 0;
}

View File

@ -90,7 +90,6 @@ extern void unregister_imm_window( HWND hwnd );
extern BOOL grab_pointer;
extern BOOL grab_fullscreen;
extern BOOL destroy_caret(void);
extern LONG global_key_state_counter;
extern HWND get_active_window(void);
extern HWND get_capture(void);
extern BOOL get_cursor_pos( POINT *pt );
@ -205,6 +204,22 @@ extern void free_vulkan_gpu( struct vulkan_gpu *gpu );
extern BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid );
/* winstation.c */
struct object_lock
{
UINT64 id;
UINT64 seq;
};
#define OBJECT_LOCK_INIT {0}
/* Get shared session object's data pointer, must be called in a loop while STATUS_PENDING
* is returned, lock must be initialized with OBJECT_LOCK_INIT.
*
* The data read from the objects may be transient and no logic should be executed based
* on it, within the loop, or after, unless the function has returned STATUS_SUCCESS.
*/
extern NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm );
extern BOOL is_virtual_desktop(void);
/* window.c */

View File

@ -22,9 +22,14 @@
#pragma makedep unix
#endif
#include <assert.h>
#include <stdarg.h>
#include <stddef.h>
#include <pthread.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "ntuser.h"
@ -40,6 +45,180 @@ WINE_DECLARE_DEBUG_CHANNEL(win);
#define DESKTOP_ALL_ACCESS 0x01ff
struct session_thread_data
{
const shared_object_t *shared_desktop; /* thread desktop shared session cached object */
};
struct session_block
{
struct list entry; /* entry in the session block list */
const char *data; /* base pointer for the mmaped data */
SIZE_T offset; /* offset of data in the session shared mapping */
SIZE_T size; /* size of the mmaped data */
};
static pthread_mutex_t session_lock = PTHREAD_MUTEX_INITIALIZER;
static struct list session_blocks = LIST_INIT(session_blocks);
static struct session_thread_data *get_session_thread_data(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
if (!thread_info->session_data) thread_info->session_data = calloc(1, sizeof(*thread_info->session_data));
return thread_info->session_data;
}
#if defined(__i386__) || defined(__x86_64__)
/* this prevents compilers from incorrectly reordering non-volatile reads (e.g., memcpy) from shared memory */
#define __SHARED_READ_FENCE do { __asm__ __volatile__( "" ::: "memory" ); } while (0)
#else
#define __SHARED_READ_FENCE __atomic_thread_fence( __ATOMIC_ACQUIRE )
#endif
static void shared_object_acquire_seqlock( const shared_object_t *object, UINT64 *seq )
{
while ((*seq = ReadNoFence64( &object->seq )) & 1) YieldProcessor();
__SHARED_READ_FENCE;
}
static BOOL shared_object_release_seqlock( const shared_object_t *object, UINT64 seq )
{
__SHARED_READ_FENCE;
return ReadNoFence64( &object->seq ) == seq;
}
static object_id_t shared_object_get_id( const shared_object_t *object )
{
struct object_lock lock = OBJECT_LOCK_INIT;
do
{
shared_object_acquire_seqlock( object, &lock.seq );
lock.id = object->id;
} while (!shared_object_release_seqlock( object, lock.seq ));
return lock.id;
}
static NTSTATUS map_shared_session_block( SIZE_T offset, SIZE_T size, struct session_block **ret )
{
static const WCHAR nameW[] =
{
'\\','K','e','r','n','e','l','O','b','j','e','c','t','s','\\',
'_','_','w','i','n','e','_','s','e','s','s','i','o','n',0
};
UNICODE_STRING name = RTL_CONSTANT_STRING( nameW );
LARGE_INTEGER off = {.QuadPart = offset - (offset % system_info.AllocationGranularity)};
struct session_block *block;
OBJECT_ATTRIBUTES attr;
unsigned int status;
HANDLE handle;
assert( offset + size > offset );
if (!(block = calloc( 1, sizeof(*block) ))) return STATUS_NO_MEMORY;
InitializeObjectAttributes( &attr, &name, 0, NULL, NULL );
if ((status = NtOpenSection( &handle, SECTION_MAP_READ, &attr )))
WARN( "Failed to open shared session section, status %#x\n", status );
else
{
if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), (void **)&block->data, 0, 0,
&off, &block->size, ViewUnmap, 0, PAGE_READONLY )))
WARN( "Failed to map shared session block, status %#x\n", status );
else
{
list_add_tail( &session_blocks, &block->entry );
block->offset = off.QuadPart;
assert( block->offset + block->size > block->offset );
}
NtClose( handle );
}
if (status) free( block );
else *ret = block;
return status;
}
static NTSTATUS find_shared_session_block( SIZE_T offset, SIZE_T size, struct session_block **ret )
{
struct session_block *block;
UINT status;
assert( offset + size > offset );
pthread_mutex_lock( &session_lock );
LIST_FOR_EACH_ENTRY( block, &session_blocks, struct session_block, entry )
{
if (block->offset < offset && offset + size <= block->offset + block->size)
{
*ret = block;
pthread_mutex_unlock( &session_lock );
return STATUS_SUCCESS;
}
}
if ((status = map_shared_session_block( offset, size, ret )))
{
WARN( "Failed to map session block for offset %s, size %s, status %#x\n",
wine_dbgstr_longlong(offset), wine_dbgstr_longlong(size), status );
}
pthread_mutex_unlock( &session_lock );
return status;
}
static const shared_object_t *find_shared_session_object( obj_locator_t locator )
{
const shared_object_t *object;
struct session_block *block;
NTSTATUS status;
if (locator.id && !(status = find_shared_session_block( locator.offset, sizeof(*object), &block )))
{
object = (const shared_object_t *)(block->data + locator.offset - block->offset);
if (locator.id == shared_object_get_id( object )) return object;
WARN( "Session object id doesn't match expected id %s\n", wine_dbgstr_longlong(locator.id) );
}
return NULL;
}
NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm )
{
struct session_thread_data *data = get_session_thread_data();
const shared_object_t *object;
TRACE( "lock %p, desktop_shm %p\n", lock, desktop_shm );
if (!(object = data->shared_desktop))
{
obj_locator_t locator;
SERVER_START_REQ( get_thread_desktop )
{
req->tid = GetCurrentThreadId();
wine_server_call( req );
locator = reply->locator;
}
SERVER_END_REQ;
data->shared_desktop = find_shared_session_object( locator );
if (!(object = data->shared_desktop)) return STATUS_INVALID_HANDLE;
memset( lock, 0, sizeof(*lock) );
}
if (!lock->id || !shared_object_release_seqlock( object, lock->seq ))
{
shared_object_acquire_seqlock( object, &lock->seq );
*desktop_shm = &object->shm.desktop;
lock->id = object->id;
return STATUS_PENDING;
}
return STATUS_SUCCESS;
}
BOOL is_virtual_desktop(void)
{
HANDLE desktop = NtUserGetThreadDesktop( GetCurrentThreadId() );
@ -249,21 +428,22 @@ HDESK WINAPI NtUserGetThreadDesktop( DWORD thread )
BOOL WINAPI NtUserSetThreadDesktop( HDESK handle )
{
BOOL ret, was_virtual_desktop = is_virtual_desktop();
obj_locator_t locator;
SERVER_START_REQ( set_thread_desktop )
{
req->handle = wine_server_obj_handle( handle );
ret = !wine_server_call_err( req );
locator = reply->locator;
}
SERVER_END_REQ;
if (ret) /* reset the desktop windows */
{
struct user_thread_info *thread_info = get_user_thread_info();
struct user_key_state_info *key_state_info = thread_info->key_state;
get_session_thread_data()->shared_desktop = find_shared_session_object( locator );
thread_info->client_info.top_window = 0;
thread_info->client_info.msg_window = 0;
if (key_state_info) key_state_info->time = 0;
if (was_virtual_desktop != is_virtual_desktop()) update_display_cache( FALSE );
}
return ret;

View File

@ -29,5 +29,8 @@ import "windows.storage.idl";
import "windows.system.idl";
#define DO_NO_IMPORTS
#define _WINDOWS_APPLICATIONMODEL
#include "windows.applicationmodel.core.idl"
#include "windows.applicationmodel.idl"
#include "windows.applicationmodel.activation.idl"
#include "windows.applicationmodel.background.idl"

View File

@ -19,6 +19,7 @@ SOURCES = \
rsrc.rc \
unixlib.c \
video_decoder.c \
video_encoder.c \
video_processor.c \
wg_allocator.c \
wg_format.c \

View File

@ -167,6 +167,8 @@ HRESULT aac_decoder_create(REFIID riid, void **ret);
HRESULT h264_decoder_create(REFIID riid, void **ret);
HRESULT video_processor_create(REFIID riid, void **ret);
HRESULT h264_encoder_create(REFIID riid, void **ret);
extern const GUID MFAudioFormat_RAW_AAC;
#endif /* __GST_PRIVATE_INCLUDED__ */

View File

@ -728,6 +728,7 @@ static HRESULT media_stream_send_sample(struct media_stream *stream, const struc
if (!wg_parser_stream_copy_buffer(stream->wg_stream, data, 0, wg_buffer->size))
{
hr = S_FALSE;
wg_parser_stream_release_buffer(stream->wg_stream);
IMFMediaBuffer_Unlock(buffer);
goto out;
@ -789,8 +790,12 @@ static HRESULT wait_on_sample(struct media_stream *stream, IUnknown *token)
TRACE("%p, %p\n", stream, token);
if (wg_parser_stream_get_buffer(source->wg_parser, stream->wg_stream, &buffer))
return media_stream_send_sample(stream, &buffer, token);
while (wg_parser_stream_get_buffer(source->wg_parser, stream->wg_stream, &buffer))
{
HRESULT hr = media_stream_send_sample(stream, &buffer, token);
if (hr != S_FALSE)
return hr;
}
return media_stream_send_eos(source, stream);
}

View File

@ -133,6 +133,7 @@ class_objects[] =
{ &CLSID_GStreamerByteStreamHandler, &gstreamer_byte_stream_handler_create },
{ &CLSID_MSAACDecMFT, &aac_decoder_create },
{ &CLSID_MSH264DecoderMFT, &h264_decoder_create },
{ &CLSID_MSH264EncoderMFT, &h264_encoder_create },
};
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
@ -208,6 +209,18 @@ HRESULT mfplat_DllRegisterServer(void)
{MFMediaType_Video, MFVideoFormat_YUY2},
};
MFT_REGISTER_TYPE_INFO h264_encoder_input_types[] =
{
{MFMediaType_Video, MFVideoFormat_IYUV},
{MFMediaType_Video, MFVideoFormat_YV12},
{MFMediaType_Video, MFVideoFormat_NV12},
{MFMediaType_Video, MFVideoFormat_YUY2},
};
MFT_REGISTER_TYPE_INFO h264_encoder_output_types[] =
{
{MFMediaType_Video, MFVideoFormat_H264},
};
MFT_REGISTER_TYPE_INFO video_processor_input_types[] =
{
{MFMediaType_Video, MFVideoFormat_IYUV},
@ -371,6 +384,16 @@ HRESULT mfplat_DllRegisterServer(void)
ARRAY_SIZE(h264_decoder_output_types),
h264_decoder_output_types,
},
{
CLSID_MSH264EncoderMFT,
MFT_CATEGORY_VIDEO_ENCODER,
L"H264 Encoder MFT",
MFT_ENUM_FLAG_SYNCMFT,
ARRAY_SIZE(h264_encoder_input_types),
h264_encoder_input_types,
ARRAY_SIZE(h264_encoder_output_types),
h264_encoder_output_types,
},
{
CLSID_WMVDecoderMFT,
MFT_CATEGORY_VIDEO_DECODER,

View File

@ -0,0 +1,338 @@
/* Generic Video Encoder Transform
*
* Copyright 2024 Ziqing Hui for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "gst_private.h"
#include "mfapi.h"
#include "mferror.h"
#include "mfobjects.h"
#include "mftransform.h"
#include "mediaerr.h"
#include "wmcodecdsp.h"
#include "wine/debug.h"
#include "initguid.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
WINE_DECLARE_DEBUG_CHANNEL(winediag);
struct video_encoder
{
IMFTransform IMFTransform_iface;
LONG refcount;
IMFAttributes *attributes;
};
static inline struct video_encoder *impl_from_IMFTransform(IMFTransform *iface)
{
return CONTAINING_RECORD(iface, struct video_encoder, IMFTransform_iface);
}
static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out)
{
struct video_encoder *encoder = impl_from_IMFTransform(iface);
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
if (IsEqualGUID(iid, &IID_IMFTransform) || IsEqualGUID(iid, &IID_IUnknown))
*out = &encoder->IMFTransform_iface;
else
{
*out = NULL;
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown *)*out);
return S_OK;
}
static ULONG WINAPI transform_AddRef(IMFTransform *iface)
{
struct video_encoder *encoder = impl_from_IMFTransform(iface);
ULONG refcount = InterlockedIncrement(&encoder->refcount);
TRACE("iface %p increasing refcount to %lu.\n", encoder, refcount);
return refcount;
}
static ULONG WINAPI transform_Release(IMFTransform *iface)
{
struct video_encoder *encoder = impl_from_IMFTransform(iface);
ULONG refcount = InterlockedDecrement(&encoder->refcount);
TRACE("iface %p decreasing refcount to %lu.\n", encoder, refcount);
if (!refcount)
{
IMFAttributes_Release(encoder->attributes);
free(encoder);
}
return refcount;
}
static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
{
TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
iface, input_minimum, input_maximum, output_minimum, output_maximum);
*input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
return S_OK;
}
static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
{
TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs);
*inputs = *outputs = 1;
return S_OK;
}
static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
DWORD output_size, DWORD *outputs)
{
FIXME("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface,
input_size, inputs, output_size, outputs);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
{
FIXME("iface %p, id %#lx, info %p.\n", iface, id, info);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
{
FIXME("iface %p, id %#lx, info %p.\n", iface, id, info);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
{
struct video_encoder *encoder = impl_from_IMFTransform(iface);
TRACE("iface %p, attributes %p.\n", iface, attributes);
if (!attributes)
return E_POINTER;
IMFAttributes_AddRef((*attributes = encoder->attributes));
return S_OK;
}
static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
{
FIXME("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
{
FIXME("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id)
{
FIXME("iface %p, id %#lx.\n", iface, id);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
{
FIXME("iface %p, streams %lu, ids %p.\n", iface, streams, ids);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
FIXME("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id,
DWORD index, IMFMediaType **type)
{
FIXME("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
FIXME("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
FIXME("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
{
FIXME("iface %p, id %#lx, type %p\n", iface, id, type);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
{
FIXME("iface %p, id %#lx, type %p\n", iface, id, type);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
{
FIXME("iface %p, id %#lx, flags %p.\n", iface, id, flags);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags)
{
FIXME("iface %p, flags %p stub!\n", iface, flags);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
{
FIXME("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
{
FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
{
FIXME("iface %p, message %#x, param %Ix.\n", iface, message, param);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
{
FIXME("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags);
return E_NOTIMPL;
}
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
return E_NOTIMPL;
}
static const IMFTransformVtbl transform_vtbl =
{
transform_QueryInterface,
transform_AddRef,
transform_Release,
transform_GetStreamLimits,
transform_GetStreamCount,
transform_GetStreamIDs,
transform_GetInputStreamInfo,
transform_GetOutputStreamInfo,
transform_GetAttributes,
transform_GetInputStreamAttributes,
transform_GetOutputStreamAttributes,
transform_DeleteInputStream,
transform_AddInputStreams,
transform_GetInputAvailableType,
transform_GetOutputAvailableType,
transform_SetInputType,
transform_SetOutputType,
transform_GetInputCurrentType,
transform_GetOutputCurrentType,
transform_GetInputStatus,
transform_GetOutputStatus,
transform_SetOutputBounds,
transform_ProcessEvent,
transform_ProcessMessage,
transform_ProcessInput,
transform_ProcessOutput,
};
static HRESULT video_encoder_create(struct video_encoder **out)
{
struct video_encoder *encoder;
HRESULT hr;
if (!(encoder = calloc(1, sizeof(*encoder))))
return E_OUTOFMEMORY;
encoder->IMFTransform_iface.lpVtbl = &transform_vtbl;
encoder->refcount = 1;
if (FAILED(hr = MFCreateAttributes(&encoder->attributes, 16)))
goto failed;
if (FAILED(hr = IMFAttributes_SetUINT32(encoder->attributes, &MFT_ENCODER_SUPPORTS_CONFIG_EVENT, TRUE)))
goto failed;
*out = encoder;
TRACE("Created video encoder %p\n", encoder);
return S_OK;
failed:
if (encoder->attributes)
IMFAttributes_Release(encoder->attributes);
free(encoder);
return hr;
}
HRESULT h264_encoder_create(REFIID riid, void **out)
{
const MFVIDEOFORMAT input_format =
{
.dwSize = sizeof(MFVIDEOFORMAT),
.videoInfo = {.dwWidth = 1920, .dwHeight = 1080},
.guidFormat = MFVideoFormat_NV12,
};
const MFVIDEOFORMAT output_format =
{
.dwSize = sizeof(MFVIDEOFORMAT),
.videoInfo = {.dwWidth = 1920, .dwHeight = 1080},
.guidFormat = MFVideoFormat_H264,
};
struct video_encoder *encoder;
HRESULT hr;
TRACE("riid %s, out %p.\n", debugstr_guid(riid), out);
if (FAILED(hr = check_video_transform_support(&input_format, &output_format)))
{
ERR_(winediag)("GStreamer doesn't support H.264 encoding, please install appropriate plugins\n");
return hr;
}
if (FAILED(hr = video_encoder_create(&encoder)))
return hr;
TRACE("Created h264 encoder transform %p.\n", &encoder->IMFTransform_iface);
hr = IMFTransform_QueryInterface(&encoder->IMFTransform_iface, riid, out);
IMFTransform_Release(&encoder->IMFTransform_iface);
return hr;
}

View File

@ -412,11 +412,12 @@ static NTSTATUS wg_parser_stream_release_buffer(void *args)
pthread_mutex_lock(&parser->mutex);
assert(stream->buffer);
gst_buffer_unmap(stream->buffer, &stream->map_info);
gst_buffer_unref(stream->buffer);
stream->buffer = NULL;
if (stream->buffer)
{
gst_buffer_unmap(stream->buffer, &stream->map_info);
gst_buffer_unref(stream->buffer);
stream->buffer = NULL;
}
pthread_mutex_unlock(&parser->mutex);
pthread_cond_signal(&stream->event_empty_cond);
@ -576,24 +577,20 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
switch (event->type)
{
case GST_EVENT_SEGMENT:
pthread_mutex_lock(&parser->mutex);
if (stream->enabled)
{
const GstSegment *segment;
gst_event_parse_segment(event, &segment);
if (segment->format != GST_FORMAT_TIME)
{
const GstSegment *segment;
gst_event_parse_segment(event, &segment);
if (segment->format != GST_FORMAT_TIME)
{
pthread_mutex_unlock(&parser->mutex);
GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(segment->format));
break;
}
gst_segment_copy_into(segment, &stream->segment);
GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(segment->format));
break;
}
pthread_mutex_lock(&parser->mutex);
gst_segment_copy_into(segment, &stream->segment);
pthread_mutex_unlock(&parser->mutex);
break;
}
case GST_EVENT_EOS:
pthread_mutex_lock(&parser->mutex);
@ -608,17 +605,14 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
case GST_EVENT_FLUSH_START:
pthread_mutex_lock(&parser->mutex);
if (stream->enabled)
{
stream->flushing = true;
pthread_cond_signal(&stream->event_empty_cond);
stream->flushing = true;
pthread_cond_signal(&stream->event_empty_cond);
if (stream->buffer)
{
gst_buffer_unmap(stream->buffer, &stream->map_info);
gst_buffer_unref(stream->buffer);
stream->buffer = NULL;
}
if (stream->buffer)
{
gst_buffer_unmap(stream->buffer, &stream->map_info);
gst_buffer_unref(stream->buffer);
stream->buffer = NULL;
}
pthread_mutex_unlock(&parser->mutex);
@ -636,8 +630,7 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
pthread_mutex_lock(&parser->mutex);
stream->eos = false;
if (stream->enabled)
stream->flushing = false;
stream->flushing = false;
pthread_mutex_unlock(&parser->mutex);
break;

View File

@ -107,6 +107,12 @@ coclass CWMVDecMediaObject {}
]
coclass CMSH264DecoderMFT {}
[
threading(both),
uuid(6ca50344-051a-4ded-9779-a43305165e35)
]
coclass CMSH264EncoderMFT {}
[
threading(both),
uuid(f447b69e-1884-4a7e-8055-346f74d6edb3)

View File

@ -207,10 +207,7 @@ extern BOOL macdrv_SystemParametersInfo(UINT action, UINT int_param, void *ptr_p
extern macdrv_window macdrv_get_cocoa_window(HWND hwnd, BOOL require_on_screen);
extern RGNDATA *get_region_data(HRGN hrgn, HDC hdc_lptodp);
extern void activate_on_following_focus(void);
extern struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect,
struct window_surface *old_surface, BOOL use_alpha);
extern void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha);
extern void surface_clip_to_visible_rect(struct window_surface *window_surface, const RECT *visible_rect);
extern void macdrv_handle_event(const macdrv_event *event);

View File

@ -127,8 +127,8 @@ static struct macdrv_window_surface *get_mac_surface(struct window_surface *surf
/***********************************************************************
* create_surface
*/
struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect,
struct window_surface *old_surface, BOOL use_alpha)
static struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect,
struct window_surface *old_surface, BOOL use_alpha)
{
struct macdrv_window_surface *surface;
int width = rect->right - rect->left, height = rect->bottom - rect->top;
@ -265,7 +265,7 @@ done:
* Intersect the accumulated drawn region with a new visible rect,
* effectively discarding stale drawing in the surface slack area.
*/
void surface_clip_to_visible_rect(struct window_surface *window_surface, const RECT *visible_rect)
static void surface_clip_to_visible_rect(struct window_surface *window_surface, const RECT *visible_rect)
{
struct macdrv_window_surface *surface = get_mac_surface(window_surface);
RECT rect = *visible_rect;
@ -277,3 +277,95 @@ void surface_clip_to_visible_rect(struct window_surface *window_surface, const R
intersect_rect(&window_surface->bounds, &window_surface->bounds, &rect);
window_surface_unlock(window_surface);
}
static inline RECT get_surface_rect(const RECT *visible_rect)
{
RECT rect = *visible_rect;
OffsetRect(&rect, -visible_rect->left, -visible_rect->top);
rect.left &= ~127;
rect.top &= ~127;
rect.right = max(rect.left + 128, (rect.right + 127) & ~127);
rect.bottom = max(rect.top + 128, (rect.bottom + 127) & ~127);
return rect;
}
/***********************************************************************
* CreateWindowSurface (MACDRV.@)
*/
BOOL macdrv_CreateWindowSurface(HWND hwnd, UINT swp_flags, const RECT *visible_rect, struct window_surface **surface)
{
struct macdrv_win_data *data;
DWORD style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
RECT surface_rect;
TRACE("hwnd %p, swp_flags %08x, visible %s, surface %p\n", hwnd, swp_flags, wine_dbgstr_rect(visible_rect), surface);
if (!(data = get_win_data(hwnd))) return TRUE; /* use default surface */
if (*surface) window_surface_release(*surface);
*surface = NULL;
surface_rect = get_surface_rect(visible_rect);
if (data->surface)
{
if (EqualRect(&data->surface->rect, &surface_rect))
{
/* existing surface is good enough */
surface_clip_to_visible_rect(data->surface, visible_rect);
window_surface_add_ref(data->surface);
*surface = data->surface;
goto done;
}
}
else if (!(swp_flags & SWP_SHOWWINDOW) && !(style & WS_VISIBLE)) goto done;
*surface = create_surface(data->hwnd, data->cocoa_window, &surface_rect, data->surface, FALSE);
done:
release_win_data(data);
return TRUE;
}
/***********************************************************************
* CreateLayeredWindow (MACDRV.@)
*/
BOOL macdrv_CreateLayeredWindow(HWND hwnd, const RECT *window_rect, COLORREF color_key,
struct window_surface **window_surface)
{
struct window_surface *surface;
struct macdrv_win_data *data;
RECT rect;
if (!(data = get_win_data(hwnd))) return FALSE;
data->layered = TRUE;
data->ulw_layered = TRUE;
rect = *window_rect;
OffsetRect(&rect, -window_rect->left, -window_rect->top);
surface = data->surface;
if (!surface || !EqualRect(&surface->rect, &rect))
{
data->surface = create_surface(data->hwnd, data->cocoa_window, &rect, NULL, TRUE);
macdrv_set_window_surface(data->cocoa_window, data->surface);
if (surface) window_surface_release(surface);
surface = data->surface;
if (data->unminimized_surface)
{
window_surface_release(data->unminimized_surface);
data->unminimized_surface = NULL;
}
}
else set_surface_use_alpha(surface, TRUE);
if ((*window_surface = surface)) window_surface_add_ref(surface);
release_win_data(data);
return TRUE;
}

View File

@ -1890,46 +1890,6 @@ done:
}
/***********************************************************************
* CreateLayeredWindow (MACDRV.@)
*/
BOOL macdrv_CreateLayeredWindow(HWND hwnd, const RECT *window_rect, COLORREF color_key,
struct window_surface **window_surface)
{
struct window_surface *surface;
struct macdrv_win_data *data;
RECT rect;
if (!(data = get_win_data(hwnd))) return FALSE;
data->layered = TRUE;
data->ulw_layered = TRUE;
rect = *window_rect;
OffsetRect(&rect, -window_rect->left, -window_rect->top);
surface = data->surface;
if (!surface || !EqualRect(&surface->rect, &rect))
{
data->surface = create_surface(data->hwnd, data->cocoa_window, &rect, NULL, TRUE);
macdrv_set_window_surface(data->cocoa_window, data->surface);
if (surface) window_surface_release(surface);
surface = data->surface;
if (data->unminimized_surface)
{
window_surface_release(data->unminimized_surface);
data->unminimized_surface = NULL;
}
}
else set_surface_use_alpha(surface, TRUE);
if ((*window_surface = surface)) window_surface_add_ref(surface);
release_win_data(data);
return TRUE;
}
/***********************************************************************
* UpdateLayeredWindow (MACDRV.@)
*/
@ -1984,19 +1944,6 @@ LRESULT macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
}
static inline RECT get_surface_rect(const RECT *visible_rect)
{
RECT rect = *visible_rect;
OffsetRect(&rect, -visible_rect->left, -visible_rect->top);
rect.left &= ~127;
rect.top &= ~127;
rect.right = max(rect.left + 128, (rect.right + 127) & ~127);
rect.bottom = max(rect.top + 128, (rect.bottom + 127) & ~127);
return rect;
}
/***********************************************************************
* WindowPosChanging (MACDRV.@)
*/
@ -2028,44 +1975,6 @@ done:
}
/***********************************************************************
* CreateWindowSurface (MACDRV.@)
*/
BOOL macdrv_CreateWindowSurface(HWND hwnd, UINT swp_flags, const RECT *visible_rect, struct window_surface **surface)
{
struct macdrv_win_data *data;
DWORD style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
RECT surface_rect;
TRACE("hwnd %p, swp_flags %08x, visible %s, surface %p\n", hwnd, swp_flags, wine_dbgstr_rect(visible_rect), surface);
if (!(data = get_win_data(hwnd))) return TRUE; /* use default surface */
if (*surface) window_surface_release(*surface);
*surface = NULL;
surface_rect = get_surface_rect(visible_rect);
if (data->surface)
{
if (EqualRect(&data->surface->rect, &surface_rect))
{
/* existing surface is good enough */
surface_clip_to_visible_rect(data->surface, visible_rect);
window_surface_add_ref(data->surface);
*surface = data->surface;
goto done;
}
}
else if (!(swp_flags & SWP_SHOWWINDOW) && !(style & WS_VISIBLE)) goto done;
*surface = create_surface(data->hwnd, data->cocoa_window, &surface_rect, data->surface, FALSE);
done:
release_win_data(data);
return TRUE;
}
/***********************************************************************
* WindowPosChanged (MACDRV.@)
*/

View File

@ -272,11 +272,34 @@ void wayland_shm_buffer_unref(struct wayland_shm_buffer *shm_buffer);
* Wayland window surface
*/
struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect);
void wayland_window_surface_update_wayland_surface(struct window_surface *surface,
struct wayland_surface *wayland_surface);
void wayland_window_flush(HWND hwnd);
/**********************************************************************
* Wayland Window
*/
/* private window data */
struct wayland_win_data
{
struct rb_entry entry;
/* hwnd that this private data belongs to */
HWND hwnd;
/* wayland surface (if any) for this window */
struct wayland_surface *wayland_surface;
/* wine window_surface backing this window */
struct window_surface *window_surface;
/* USER window rectangle relative to win32 parent window client area */
RECT window_rect;
/* USER client rectangle relative to win32 parent window client area */
RECT client_rect;
BOOL managed;
};
struct wayland_win_data *wayland_win_data_get(HWND hwnd);
void wayland_win_data_release(struct wayland_win_data *data);
/**********************************************************************
* Wayland Keyboard
*/

View File

@ -56,23 +56,6 @@ static BOOL set_window_pos(HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy,
}
/* private window data */
struct wayland_win_data
{
struct rb_entry entry;
/* hwnd that this private data belongs to */
HWND hwnd;
/* wayland surface (if any) for this window */
struct wayland_surface *wayland_surface;
/* wine window_surface backing this window */
struct window_surface *window_surface;
/* USER window rectangle relative to win32 parent window client area */
RECT window_rect;
/* USER client rectangle relative to win32 parent window client area */
RECT client_rect;
BOOL managed;
};
static int wayland_win_data_cmp_rb(const void *key,
const struct rb_entry *entry)
{
@ -153,7 +136,7 @@ static void wayland_win_data_destroy(struct wayland_win_data *data)
*
* Lock and return the data structure associated with a window.
*/
static struct wayland_win_data *wayland_win_data_get(HWND hwnd)
struct wayland_win_data *wayland_win_data_get(HWND hwnd)
{
struct rb_entry *rb_entry;
@ -172,7 +155,7 @@ static struct wayland_win_data *wayland_win_data_get(HWND hwnd)
*
* Release the data returned by wayland_win_data_get.
*/
static void wayland_win_data_release(struct wayland_win_data *data)
void wayland_win_data_release(struct wayland_win_data *data)
{
assert(data);
pthread_mutex_unlock(&win_data_mutex);
@ -471,42 +454,6 @@ done:
}
/***********************************************************************
* WAYLAND_CreateWindowSurface
*/
BOOL WAYLAND_CreateWindowSurface(HWND hwnd, UINT swp_flags, const RECT *visible_rect, struct window_surface **surface)
{
struct wayland_win_data *data;
RECT surface_rect;
TRACE("hwnd %p, swp_flags %08x, visible %s, surface %p\n", hwnd, swp_flags, wine_dbgstr_rect(visible_rect), surface);
if (!(data = wayland_win_data_get(hwnd))) return TRUE; /* use default surface */
/* Release the dummy surface wine provides for toplevels. */
if (*surface) window_surface_release(*surface);
*surface = NULL;
surface_rect = *visible_rect;
OffsetRect(&surface_rect, -surface_rect.left, -surface_rect.top);
/* Check if we can reuse our current window surface. */
if (data->window_surface &&
EqualRect(&data->window_surface->rect, &surface_rect))
{
window_surface_add_ref(data->window_surface);
*surface = data->window_surface;
TRACE("reusing surface %p\n", *surface);
goto done;
}
*surface = wayland_window_surface_create(data->hwnd, &surface_rect);
done:
wayland_win_data_release(data);
return TRUE;
}
/***********************************************************************
* WAYLAND_WindowPosChanged
*/

View File

@ -449,7 +449,7 @@ static const struct window_surface_funcs wayland_window_surface_funcs =
/***********************************************************************
* wayland_window_surface_create
*/
struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect)
static struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect)
{
char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
BITMAPINFO *info = (BITMAPINFO *)buffer;
@ -516,3 +516,40 @@ void wayland_window_surface_update_wayland_surface(struct window_surface *window
window_surface_unlock(window_surface);
}
/***********************************************************************
* WAYLAND_CreateWindowSurface
*/
BOOL WAYLAND_CreateWindowSurface(HWND hwnd, UINT swp_flags, const RECT *visible_rect, struct window_surface **surface)
{
struct wayland_win_data *data;
RECT surface_rect;
TRACE("hwnd %p, swp_flags %08x, visible %s, surface %p\n", hwnd, swp_flags, wine_dbgstr_rect(visible_rect), surface);
if (!(data = wayland_win_data_get(hwnd))) return TRUE; /* use default surface */
/* Release the dummy surface wine provides for toplevels. */
if (*surface) window_surface_release(*surface);
*surface = NULL;
surface_rect = *visible_rect;
OffsetRect(&surface_rect, -surface_rect.left, -surface_rect.top);
/* Check if we can reuse our current window surface. */
if (data->window_surface &&
EqualRect(&data->window_surface->rect, &surface_rect))
{
window_surface_add_ref(data->window_surface);
*surface = data->window_surface;
TRACE("reusing surface %p\n", *surface);
goto done;
}
*surface = wayland_window_surface_create(data->hwnd, &surface_rect);
done:
wayland_win_data_release(data);
return TRUE;
}

View File

@ -2054,8 +2054,8 @@ static const struct window_surface_funcs x11drv_surface_funcs =
/***********************************************************************
* create_surface
*/
struct window_surface *create_surface( HWND hwnd, Window window, const XVisualInfo *vis, const RECT *rect,
COLORREF color_key, BOOL use_alpha )
static struct window_surface *create_surface( HWND hwnd, Window window, const XVisualInfo *vis, const RECT *rect,
COLORREF color_key, BOOL use_alpha )
{
const XPixmapFormatValues *format = pixmap_formats[vis->depth];
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
@ -2182,3 +2182,99 @@ HRGN expose_surface( struct window_surface *window_surface, const RECT *rect )
window_surface_unlock( window_surface );
return region;
}
BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rect )
{
*surface_rect = NtUserGetVirtualScreenRect();
if (!intersect_rect( surface_rect, surface_rect, visible_rect )) return FALSE;
OffsetRect( surface_rect, -visible_rect->left, -visible_rect->top );
surface_rect->left &= ~31;
surface_rect->top &= ~31;
surface_rect->right = max( surface_rect->left + 32, (surface_rect->right + 31) & ~31 );
surface_rect->bottom = max( surface_rect->top + 32, (surface_rect->bottom + 31) & ~31 );
return TRUE;
}
/***********************************************************************
* CreateWindowSurface (X11DRV.@)
*/
BOOL X11DRV_CreateWindowSurface( HWND hwnd, UINT swp_flags, const RECT *visible_rect, struct window_surface **surface )
{
struct x11drv_win_data *data;
RECT surface_rect;
DWORD flags;
COLORREF key;
BOOL layered = NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED;
TRACE( "hwnd %p, swp_flags %08x, visible %s, surface %p\n", hwnd, swp_flags, wine_dbgstr_rect( visible_rect ), surface );
if (!(data = get_win_data( hwnd ))) return TRUE; /* use default surface */
if (*surface) window_surface_release( *surface );
*surface = NULL; /* indicate that we want to draw directly to the window */
if (data->embedded) goto done; /* draw directly to the window */
if (data->whole_window == root_window) goto done; /* draw directly to the window */
if (data->client_window) goto done; /* draw directly to the window */
if (!client_side_graphics && !layered) goto done; /* draw directly to the window */
if (!get_surface_rect( visible_rect, &surface_rect )) goto done;
if (data->surface)
{
if (EqualRect( &data->surface->rect, &surface_rect ))
{
/* existing surface is good enough */
window_surface_add_ref( data->surface );
*surface = data->surface;
goto done;
}
}
else if (!(swp_flags & SWP_SHOWWINDOW) && !(NtUserGetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) goto done;
if (!layered || !NtUserGetLayeredWindowAttributes( hwnd, &key, NULL, &flags ) || !(flags & LWA_COLORKEY))
key = CLR_INVALID;
*surface = create_surface( data->hwnd, data->whole_window, &data->vis, &surface_rect, key, FALSE );
done:
release_win_data( data );
return TRUE;
}
/*****************************************************************************
* CreateLayeredWindow (X11DRV.@)
*/
BOOL X11DRV_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key,
struct window_surface **window_surface )
{
struct window_surface *surface;
struct x11drv_win_data *data;
RECT rect;
if (!(data = get_win_data( hwnd ))) return FALSE;
data->layered = TRUE;
if (!data->embedded && argb_visual.visualid) set_window_visual( data, &argb_visual, TRUE );
rect = *window_rect;
OffsetRect( &rect, -window_rect->left, -window_rect->top );
surface = data->surface;
if (!surface || !EqualRect( &surface->rect, &rect ))
{
data->surface = create_surface( data->hwnd, data->whole_window, &data->vis, &rect,
color_key, data->use_alpha );
if (surface) window_surface_release( surface );
surface = data->surface;
}
else set_surface_color_key( surface, color_key );
if ((*window_surface = surface)) window_surface_add_ref( surface );
release_win_data( data );
return TRUE;
}

View File

@ -2576,20 +2576,6 @@ done:
}
static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rect )
{
*surface_rect = NtUserGetVirtualScreenRect();
if (!intersect_rect( surface_rect, surface_rect, visible_rect )) return FALSE;
OffsetRect( surface_rect, -visible_rect->left, -visible_rect->top );
surface_rect->left &= ~31;
surface_rect->top &= ~31;
surface_rect->right = max( surface_rect->left + 32, (surface_rect->right + 31) & ~31 );
surface_rect->bottom = max( surface_rect->top + 32, (surface_rect->bottom + 31) & ~31 );
return TRUE;
}
/***********************************************************************
* WindowPosChanging (X11DRV.@)
*/
@ -2626,53 +2612,6 @@ done:
}
/***********************************************************************
* CreateWindowSurface (X11DRV.@)
*/
BOOL X11DRV_CreateWindowSurface( HWND hwnd, UINT swp_flags, const RECT *visible_rect, struct window_surface **surface )
{
struct x11drv_win_data *data;
RECT surface_rect;
DWORD flags;
COLORREF key;
BOOL layered = NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED;
TRACE( "hwnd %p, swp_flags %08x, visible %s, surface %p\n", hwnd, swp_flags, wine_dbgstr_rect( visible_rect ), surface );
if (!(data = get_win_data( hwnd ))) return TRUE; /* use default surface */
if (*surface) window_surface_release( *surface );
*surface = NULL; /* indicate that we want to draw directly to the window */
if (data->embedded) goto done; /* draw directly to the window */
if (data->whole_window == root_window) goto done; /* draw directly to the window */
if (data->client_window) goto done; /* draw directly to the window */
if (!client_side_graphics && !layered) goto done; /* draw directly to the window */
if (!get_surface_rect( visible_rect, &surface_rect )) goto done;
if (data->surface)
{
if (EqualRect( &data->surface->rect, &surface_rect ))
{
/* existing surface is good enough */
window_surface_add_ref( data->surface );
*surface = data->surface;
goto done;
}
}
else if (!(swp_flags & SWP_SHOWWINDOW) && !(NtUserGetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) goto done;
if (!layered || !NtUserGetLayeredWindowAttributes( hwnd, &key, NULL, &flags ) || !(flags & LWA_COLORKEY))
key = CLR_INVALID;
*surface = create_surface( data->hwnd, data->whole_window, &data->vis, &surface_rect, key, FALSE );
done:
release_win_data( data );
return TRUE;
}
/***********************************************************************
* WindowPosChanged (X11DRV.@)
*/
@ -2983,41 +2922,6 @@ void X11DRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWO
}
/*****************************************************************************
* CreateLayeredWindow (X11DRV.@)
*/
BOOL X11DRV_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key,
struct window_surface **window_surface )
{
struct window_surface *surface;
struct x11drv_win_data *data;
RECT rect;
if (!(data = get_win_data( hwnd ))) return FALSE;
data->layered = TRUE;
if (!data->embedded && argb_visual.visualid) set_window_visual( data, &argb_visual, TRUE );
rect = *window_rect;
OffsetRect( &rect, -window_rect->left, -window_rect->top );
surface = data->surface;
if (!surface || !EqualRect( &surface->rect, &rect ))
{
data->surface = create_surface( data->hwnd, data->whole_window, &data->vis, &rect,
color_key, data->use_alpha );
if (surface) window_surface_release( surface );
surface = data->surface;
}
else set_surface_color_key( surface, color_key );
if ((*window_surface = surface)) window_surface_add_ref( surface );
release_win_data( data );
return TRUE;
}
/***********************************************************************
* UpdateLayeredWindow (X11DRV.@)
*/

View File

@ -266,8 +266,6 @@ extern Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const B
const struct gdi_image_bits *bits, UINT coloruse );
extern DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis,
BITMAPINFO *info, struct gdi_image_bits *bits );
extern struct window_surface *create_surface( HWND hwnd, Window window, const XVisualInfo *vis, const RECT *rect,
COLORREF color_key, BOOL use_alpha );
extern void set_surface_color_key( struct window_surface *window_surface, COLORREF color_key );
extern HRGN expose_surface( struct window_surface *window_surface, const RECT *rect );
@ -687,6 +685,7 @@ typedef int (*x11drv_error_callback)( Display *display, XErrorEvent *event, void
extern void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg );
extern int X11DRV_check_error(void);
extern BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rect );
extern void X11DRV_X_to_window_rect( struct x11drv_win_data *data, RECT *rect, int x, int y, int cx, int cy );
extern POINT virtual_screen_to_root( INT x, INT y );
extern POINT root_to_virtual_screen( INT x, INT y );

View File

@ -48,9 +48,14 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
#include "wine/vulkan.h"
#include "wine/vulkan_driver.h"
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR)
static void *xrandr_handle;
static void *vulkan_handle;
static void *(*p_vkGetInstanceProcAddr)(VkInstance, const char *);
static VkInstance vk_instance; /* Vulkan instance for XRandR functions */
static VkResult (*p_vkGetRandROutputDisplayEXT)( VkPhysicalDevice, Display *, RROutput, VkDisplayKHR * );
static PFN_vkGetPhysicalDeviceProperties2KHR p_vkGetPhysicalDeviceProperties2KHR;
static PFN_vkEnumeratePhysicalDevices p_vkEnumeratePhysicalDevices;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f;
MAKE_FUNCPTR(XRRConfigCurrentConfiguration)
@ -140,8 +145,31 @@ sym_not_found:
#ifdef SONAME_LIBVULKAN
static void *vulkan_handle;
static void *(*p_vkGetInstanceProcAddr)(VkInstance, const char *);
static void vulkan_init_once(void)
{
static const char *extensions[] =
{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
"VK_EXT_acquire_xlib_display",
"VK_EXT_direct_mode_display",
"VK_KHR_display",
VK_KHR_SURFACE_EXTENSION_NAME,
};
VkInstanceCreateInfo create_info =
{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.ppEnabledExtensionNames = extensions,
.enabledExtensionCount = ARRAY_SIZE(extensions),
};
PFN_vkDestroyInstance p_vkDestroyInstance;
PFN_vkCreateInstance p_vkCreateInstance;
VkResult vr;
if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW )))
{
ERR( "Failed to load %s\n", SONAME_LIBVULKAN );
@ -153,12 +181,33 @@ static void vulkan_init_once(void)
{ \
ERR( "Failed to find " #f "\n" ); \
dlclose( vulkan_handle ); \
vulkan_handle = NULL; \
return; \
}
LOAD_FUNCPTR( vkGetInstanceProcAddr );
#undef LOAD_FUNCPTR
p_vkCreateInstance = p_vkGetInstanceProcAddr( NULL, "vkCreateInstance" );
if ((vr = p_vkCreateInstance( &create_info, NULL, &vk_instance )))
{
WARN( "Failed to create a Vulkan instance, vr %d.\n", vr );
return;
}
p_vkDestroyInstance = p_vkGetInstanceProcAddr( vk_instance, "vkDestroyInstance" );
#define LOAD_VK_FUNC(f) \
if (!(p_##f = (void *)p_vkGetInstanceProcAddr( vk_instance, #f ))) \
{ \
WARN("Failed to load " #f ".\n"); \
p_vkDestroyInstance( vk_instance, NULL ); \
vk_instance = NULL; \
return; \
}
LOAD_VK_FUNC( vkEnumeratePhysicalDevices )
LOAD_VK_FUNC( vkGetPhysicalDeviceProperties2KHR )
LOAD_VK_FUNC( vkGetRandROutputDisplayEXT )
#undef LOAD_VK_FUNC
}
#else /* SONAME_LIBVULKAN */
@ -174,7 +223,7 @@ static BOOL vulkan_init(void)
{
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
pthread_once( &init_once, vulkan_init_once );
return !!vulkan_handle;
return !!vk_instance;
}
static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
@ -668,65 +717,20 @@ static BOOL is_crtc_primary( RECT primary, const XRRCrtcInfo *crtc )
crtc->y + crtc->height == primary.bottom;
}
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR)
static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRProviderInfo *provider_info,
struct x11drv_gpu *prev_gpus, int prev_gpu_count )
{
static const char *extensions[] =
{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
"VK_EXT_acquire_xlib_display",
"VK_EXT_direct_mode_display",
"VK_KHR_display",
VK_KHR_SURFACE_EXTENSION_NAME,
};
VkResult (*pvkGetRandROutputDisplayEXT)( VkPhysicalDevice, Display *, RROutput, VkDisplayKHR * );
PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
uint32_t device_count, device_idx, output_idx, i;
PFN_vkDestroyInstance pvkDestroyInstance = NULL;
VkPhysicalDevice *vk_physical_devices = NULL;
VkPhysicalDeviceProperties2 properties2;
PFN_vkCreateInstance pvkCreateInstance;
VkInstanceCreateInfo create_info;
VkPhysicalDeviceIDProperties id;
VkInstance vk_instance = NULL;
VkDisplayKHR vk_display;
BOOL ret = FALSE;
VkResult vr;
if (!vulkan_init()) goto done;
memset( &create_info, 0, sizeof(create_info) );
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.enabledExtensionCount = ARRAY_SIZE(extensions);
create_info.ppEnabledExtensionNames = extensions;
#define LOAD_VK_FUNC(f) \
if (!(p##f = (void *)p_vkGetInstanceProcAddr( vk_instance, #f ))) \
{ \
WARN("Failed to load " #f ".\n"); \
goto done; \
}
LOAD_VK_FUNC( vkCreateInstance )
vr = pvkCreateInstance( &create_info, NULL, &vk_instance );
if (vr != VK_SUCCESS)
{
WARN( "Failed to create a Vulkan instance, vr %d.\n", vr );
goto done;
}
LOAD_VK_FUNC(vkEnumeratePhysicalDevices)
LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR)
LOAD_VK_FUNC(vkGetRandROutputDisplayEXT)
LOAD_VK_FUNC(vkDestroyInstance)
#undef LOAD_VK_FUNC
vr = pvkEnumeratePhysicalDevices( vk_instance, &device_count, NULL );
vr = p_vkEnumeratePhysicalDevices( vk_instance, &device_count, NULL );
if (vr != VK_SUCCESS || !device_count)
{
WARN("No Vulkan device found, vr %d, device_count %d.\n", vr, device_count);
@ -736,7 +740,7 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
if (!(vk_physical_devices = calloc( device_count, sizeof(*vk_physical_devices) )))
goto done;
vr = pvkEnumeratePhysicalDevices( vk_instance, &device_count, vk_physical_devices );
vr = p_vkEnumeratePhysicalDevices( vk_instance, &device_count, vk_physical_devices );
if (vr != VK_SUCCESS)
{
WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr);
@ -749,8 +753,8 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
{
for (output_idx = 0; output_idx < provider_info->noutputs; ++output_idx)
{
vr = pvkGetRandROutputDisplayEXT( vk_physical_devices[device_idx], gdi_display,
provider_info->outputs[output_idx], &vk_display );
vr = p_vkGetRandROutputDisplayEXT( vk_physical_devices[device_idx], gdi_display,
provider_info->outputs[output_idx], &vk_display );
if (vr != VK_SUCCESS || vk_display == VK_NULL_HANDLE)
continue;
@ -759,7 +763,7 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties2.pNext = &id;
pvkGetPhysicalDeviceProperties2KHR( vk_physical_devices[device_idx], &properties2 );
p_vkGetPhysicalDeviceProperties2KHR( vk_physical_devices[device_idx], &properties2 );
for (i = 0; i < prev_gpu_count; ++i)
{
if (!memcmp( &prev_gpus[i].vulkan_uuid, &id.deviceUUID, sizeof(id.deviceUUID) ))
@ -788,7 +792,6 @@ static BOOL get_gpu_properties_from_vulkan( struct x11drv_gpu *gpu, const XRRPro
done:
free( vk_physical_devices );
if (vk_instance && pvkDestroyInstance) pvkDestroyInstance( vk_instance, NULL );
return ret;
}

View File

@ -521,6 +521,18 @@ NTSTATUS WINAPI wow64_NtSetInformationToken( UINT *args )
switch (class)
{
case TokenIntegrityLevel: /* TOKEN_MANDATORY_LABEL */
if (len >= sizeof(TOKEN_MANDATORY_LABEL32))
{
TOKEN_MANDATORY_LABEL32 *label32 = ptr;
TOKEN_MANDATORY_LABEL label;
label.Label.Sid = ULongToPtr( label32->Label.Sid );
label.Label.Attributes = label32->Label.Attributes;
return NtSetInformationToken( handle, class, &label, sizeof(label) );
}
else return STATUS_INFO_LENGTH_MISMATCH;
case TokenSessionId: /* ULONG */
return NtSetInformationToken( handle, class, ptr, len );

View File

@ -367,6 +367,11 @@ typedef struct
DWORD Attributes;
} SID_AND_ATTRIBUTES32;
typedef struct
{
SID_AND_ATTRIBUTES32 Label;
} TOKEN_MANDATORY_LABEL32;
typedef struct
{
ULONG DefaultDacl;

View File

@ -662,6 +662,7 @@ SOURCES = \
rmxftmpl.x \
roapi.h \
roerrorapi.h \
rometadata.h \
rometadataresolution.h \
roparameterizediid.idl \
row.idl \
@ -825,12 +826,15 @@ SOURCES = \
windef.h \
windns.h \
windot11.h \
windows.applicationmodel.activation.idl \
windows.applicationmodel.background.idl \
windows.applicationmodel.core.idl \
windows.applicationmodel.idl \
windows.devices.bluetooth.idl \
windows.devices.enumeration.idl \
windows.devices.geolocation.idl \
windows.devices.haptics.idl \
windows.devices.input.idl \
windows.devices.power.idl \
windows.devices.radios.idl \
windows.devices.usb.idl \
@ -849,6 +853,7 @@ SOURCES = \
windows.graphics.directx.idl \
windows.graphics.effects.idl \
windows.graphics.holographic.idl \
windows.graphics.idl \
windows.graphics.imaging.idl \
windows.h \
windows.management.deployment.idl \
@ -885,6 +890,7 @@ SOURCES = \
windows.ui.composition.interop.idl \
windows.ui.core.idl \
windows.ui.idl \
windows.ui.input.idl \
windows.ui.viewmanagement.idl \
windows.ui.xaml.hosting.desktopwindowxamlsource.idl \
windowscontracts.idl \

View File

@ -642,6 +642,9 @@
/* Define to 1 if you have the <valgrind/valgrind.h> header file. */
#undef HAVE_VALGRIND_VALGRIND_H
/* Define to 1 if the Wine preloader is being used. */
#undef HAVE_WINE_PRELOADER
/* Define to 1 if you have the <X11/extensions/shape.h> header file. */
#undef HAVE_X11_EXTENSIONS_SHAPE_H

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