diff -Nru wine-development-5.8/ANNOUNCE wine-development-5.9/ANNOUNCE --- wine-development-5.8/ANNOUNCE 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/ANNOUNCE 2020-05-22 18:49:34.000000000 +0000 @@ -1,17 +1,16 @@ -The Wine development release 5.8 is now available. +The Wine development release 5.9 is now available. What's new in this release (see below for details): - - Support for Plug & Play device notifications. - - More support for building with Clang in MSVC mode. - - Still more progress on the WineD3D Vulkan backend. - - Initial implementation of a GIF encoder. - - Vulkan spec update. + - Major progress on the WineD3D Vulkan backend. + - Initial support for splitting dlls into PE and Unix parts. + - Support for generating PDB files when building PE dlls. + - Timestamp updates in the Kernel User Shared Data. - Various bug fixes. The source is available from the following locations: - https://dl.winehq.org/wine/source/5.x/wine-5.8.tar.xz - http://mirrors.ibiblio.org/wine/source/5.x/wine-5.8.tar.xz + https://dl.winehq.org/wine/source/5.x/wine-5.9.tar.xz + http://mirrors.ibiblio.org/wine/source/5.x/wine-5.9.tar.xz Binary packages for various distributions will be available from: @@ -27,444 +26,461 @@ ---------------------------------------------------------------- -Bugs fixed in 5.8 (total 44): +Bugs fixed in 5.9 (total 28): - 17233 Zanzarah game opens a black fullscreen window and then crashes (needs support for IDirectDraw7::EnumSurfaces 'DDENUMSURFACES_CANBECREATED') - 32337 ABBYY FineReader 11 trial version crashes when trying to activate the production (RichEdit control incorrectly returns failure for EM_SETREADONLY) - 34495 Total War: Shogun 2 (Steam): character models are fixed sideways with NVIDIA drivers - 37388 GTA IV fails to launch (using XLiveLess) - 38495 Origin crashes when launching a game - 39534 Bad Mojo Redux crashes on start (ddraw1_vtbl and ddraw_surface1_vtbl need to be writable) - 39649 Anno 1701 doesn't show images in ANNOpedia when anti-aliasing enabled - 40311 Processing of 'DeviceIoControl' calls doesn't corresponds to specification - 40820 Karaoke DVD Burner v1.0 crashes when attempting to 'Create and Burn' (missing 'CLSID_FileWriter', clsid '{8596E5F0-0DA5-11d0-BD21-00A0C911CE86}') - 40894 Warcraft 3: Crash on starting the game - 42313 64-bit Process Hacker 2.39.124 crashes when attempting to inspect any process - 42326 Darsksiders Warmastered Edition crashes on startup - 42555 Units are invisible in Shogun: Total War battle map - 43454 Multiple installers and applications crash on unhandled exception 0x000006ba inside NdrAsyncClientCall (ABBYY FineReader 12 Professional) - 43765 RSpec-Explorer windows are sometimes unresponsive to keyboard and mouse input - 44216 The 4Th coming crashes - 45377 StreetFighter V Arcade Edition (Steam) custom protection scheme requires pids/tids to be multiples of four - 45774 Multiple games and applications show black screen or have broken user interface rendering (Ragnarok Online kRO, Microsoft Expression Design 4) - 45839 Qt 5.8 SDK installer needs 'IFileSystem.MoveFile' method implementation for maintenance tool creation step - 46377 The Bat!: weird behaviour of program icon on the KDE taskbar - 46949 DDraw games using older windowed mode wrappers such as DirectX Windower Embedded v2.3/D3D Windower v1.x crash (ddraw_palette_vtbl and ddraw_surface{1,2,3,4,7}_vtbl need to be writable) - 47621 Command link buttons in task dialog are displayed in wrong style - 47623 Acronis Disk Director 12 installer fails in 'MsiFltSrvInstall64' custom action (Acronis Storage Filter Management Driver 'fltsrv.sys') - 47690 Notepad++ shows no ligatures for Fira Code font, when used with DirectWrite backend - 47999 Gif pictures stored in PE files are not loaded into HTML web pages via Res protocol - 48308 KERNEL32.dll.SetEnvironmentStringsW function needed for GoG Galaxy 2 beta - 48586 d3d tests broke on cw-gtx560-64 due to recent user32/tests changes - 48738 cmd.exe crashes when running certain batch files - 48857 Tokyo Xanadu eX+: game crashes when trying to play videos with builtin quartz - 48920 Can't quit Legends of Runeterra by closing virtual desktop window (stack overflow) (5.6 regression) - 48927 Heap buffer underflow in TiffFrameDecode_ReadTile when decoding 1x1 4bpp RGBA image - 48984 Riot Vanguard (Riot Games) 'vgk.sys' crashes on unimplemented function ntoskrnl.exe.{vswprintf_s,swprintf_s} - 48985 Riot Vanguard (Riot Games) 'vgk.sys' crashes on unimplemented function ntoskrnl.exe.ZwFlushBuffersFile - 48987 Riot Vanguard (Riot Games) 'vgk.sys' crashes on unimplemented function ntoskrnl.exe.{wcscat_s,wcscpy_s} - 49005 Listview header occasionally fails to redraw when list is scrolled vertically - 49011 Multiple games and applications cause wineserver crash in Wine 5.7 - 49034 Enlarge list width in font selection dialog - 49043 iLok License Manager daemon 'LDSvc.exe' crashes on startup (PACE copy protection spuriously fails to get/set thread context of newly created threads) - 49064 Riot Vanguard (Riot Games) v0.3.3 'vgk.sys' crashes on unimplemented function ntoskrnl.exe.RtlDuplicateUnicodeString - 49068 'Access violation in riched20.dll' with certain GOG.com installers - 49086 Blindwrite 7.0 'ezplay.sys' crashes in driver entry point - 49087 Blindwrite 7.0 'ezplay.sys' needs ntoskrnl.exe.RtlCopyMemoryNonTemporal - 49088 Acronis Storage Filter Management Driver 'fltsrv.sys' crashes on unimplemented function 'ntoskrnl.exe.IoIs32bitProcess' - 49090 The Witcher: Enhanced Edition: tooltips, object descriptions are wrongly displayed + 15489 Build should optionally produce .pdb file suitable for use with symbol server + 29168 Multiple games and applications need realtime updates to KSYSTEM_TIME members in KUSER_SHARED_DATA (Star Wars: The Old Republic game client, Blizzard games, GO 1.4+ runtime, Denuvo Anti-Tamper x64 #2) + 29806 Hype The Time Quest: DirectX Media (DXM) v6.0 runtime installer fails (advpack.ExecuteCab should extract the INF from CAB before running the install part) + 30814 Age of Empires II scrolling gets stuck after Alt-Tab away and back + 42125 4k/8k demos often fail with 'Bad EXE Format' or 'error c0000020' due to Crinkler executable file compressor's "optimized" usage of PE header fields (loader compatibility) + 43959 webservices/reader tests fail on arm + 43960 rpcrt4/cstub tests fail on arm + 43962 msvcrt/string tests fail on arm + 44860 4k/8k demos crash due to Crinkler executable file compressor expecting PEB address in %ebx on process entry + 48186 every wine process shows a definite leak in dlls/ntdll/env.c + 48289 Grand Theft Auto 5 crashes after loading (GTA5 expects Vista+ PEB_LDR_DATA structure fields) + 48441 mouse coordinates cannot exceed initial desktop size during startup of wineserver + 48471 Mismatching behavior of GetEnvironmentVariableW for empty / long values + 48490 Restored minimized windows have wrong height + 48775 Microsoft Teams 1.3.x crashes on unimplemented function IPHLPAPI.DLL.NotifyRouteChange2 + 49105 Deus Ex GOTY fails to start with Direct3D renderer + 49115 Hitman (2016) and Hitman 2 (2018) fail to launch in DX11 mode + 49128 Good Company crash on launch + 49130 NVIDIA RTX Voice installer crashes on unimplemented function setupapi.dll.SetupDiGetActualSectionToInstallExW + 49131 wineboot fails to start + 49139 Regression: Wine crashes on startup on FreeBSD >= 5.7 + 49140 Windows 10 SDK installer hangs on startup + 49142 Horizontal mouse scroll events (X11 buttons 6 and 7) should not be translated to back/forward events + 49146 Hearts of Iron IV needs api-ms-win-crt-private-l1-1-0.dll._o_sin + 49173 widl generates invalid code for Gecko's ISimpleDOM.idl + 49175 Duplicated checking canonicalized inside kernelbase/path.c + 49200 Steam hangs after login + 49203 Possible incorrect usage >= instead <= in shlview.c ---------------------------------------------------------------- -Changes since 5.7: +Changes since 5.8: -Alexandre Julliard (40): - ntdll: Avoid using wine_get_config_dir() from libwine. - ntdll: Avoid using wine_get_server_dir() from libwine. - ntdll: Avoid using wine_get_user_name() from libwine. - ntdll: Avoid using wine_get_build/data_dir() from libwine. - ntdll: Avoid using wine_dll_enum_load_path() from libwine. - libwine: Make the various directory functions obsolete. - configure: Check for deprecation warnings from sys/sysctl.h. - ntdll: Add a helper to exec wineserver. - ntdll: Add a helper to exec wineloader. - ntdll: Store the pending free list in the main process heap. - ntdll: Don't use a custom alignment for large heap blocks. - ntdll: Remove VFAT_IOCTL_READDIR_BOTH kernel bugs workarounds. - ntdll: Add a helper for platform-specific threading initialization. - ntdll: Move signal stack size computation to the common code. - ntdll: Move TEB allocation to the common code. - ntdll: Use server_enter_uninterrupted_section() for LDT locking. - ntdll: Get rid of obsolete KERN_THALTSTACK sysctl. - ntdll: Allocate TEBs out of a larger memory block. - ntdll: Remove support for custom virtual memory alignments. - wrc: Remove some dead code. - include: Get rid of BITFIELDS_BIGENDIAN. - include: Get rid of ALLOW_UNALIGNED_ACCESS. - include: Get rid of Mac support in RPC headers. - ntoskrnl: Add missing exports for functions that are already implemented. - gdi32: Return 0 char width for missing glyphs. - include: Use the gcc interlocked functions also on i386 if possible. - ntdll: Use the standard Interlocked* functions. - user32: Use the standard Interlocked* functions. - server: Avoid using interlocked functions. - libport: Get rid of interlocked functions. - kernel32: Move volume functions to kernelbase. - kernel32: Move some file functions to kernelbase. - kernel32: Move Wer* function stubs to kernelbase. - kernel32: Move FlushProcessWriteBuffers() stub to ntdll. - kernel32: Move some stub functions to kernelbase. - kernelbase: Add CopyMemoryNonTemporal export. - kernel32: Move the psapi functions to kernelbase. - api-ms-win-core-windowserrorreporting-l1-1-0: Add WerUnregisterFile(). - kernel32/tests: Use wide character string literals in FormatMessage() tests. - kernel32/tests: Fix some incorrect FormatMessage() tests. - -Alistair Leslie-Hughes (3): - ddraw: Make palette and remaining surface vtbls writable. - dmime: Parse lyric track data. - dmime: Support more common chunks. - -Andrew Eikum (5): - include/xapo.idl: Add XAPO registration flags. - setupapi: Quiet down missing driver debug message. - ntoskrnl: Quiet down failed class installer debug message. - winmm: Accept open handles in wave{In,Out}GetDevCaps. - winmm/tests: Test using a device handle in wave{In,Out}GetDevCaps and wave{In,Out}Open. - -Bernhard Übelacker (3): - cmd: Fix crash in if condition parsing. - cmd/tests: Test that the if command is not influenced by a previous one. - server: Save whole input history line again. +Akihiro Sagawa (3): + po: Update Japanese translation. + winegstreamer: Unref the GstCaps object in init_new_decoded_pad(). + strmbase: Allow NULL pin_get_media_type() callback in source_Connect(). + +Alex Henrie (8): + ntdll: Implement RtlIpv6StringToAddress(Ex)[AW]. + iphlpapi: Implement ParseNetworkString for IPv6 addresses and services. + ws2_32/tests: Put WSAStringToAddress tests in tables. + ws2_32: Reimplement WSAStringToAddress on top of ntdll functions. + ws2_32: Set WSAEINVAL in InetPtonW if the address string is unparsable. + ws2_32: Reimplement inet_pton on top of ntdll functions. + ws2_32/tests: Fix typos in test_WSAStringToAddress. + ws2_32: Don't set output length in WSAStringToAddress on error. + +Alexandre Julliard (54): + ntdll/tests: Enable RtlDowncaseUnicodeString() test. + ntdll: Add a few printf functions. + ntdll: Merge new features from msvcrt's printf implementation. + ntdll: Implement RtlFormatMessage(). + ntdll/tests: Add some printf tests. + ntdll/tests: Add tests for RtlFormatMessage(). + kernelbase: Reimplement FormatMessageA/W using RtlFormatMessage(). + kernel32/tests: Add some tests for FormatMessageA/W buffer sizes. + attrib: FormatMessage() now reports ERROR_NO_WORK_DONE error for empty string. + cmd: FormatMessage() now reports ERROR_NO_WORK_DONE error for empty string. + net: FormatMessage() now reports ERROR_NO_WORK_DONE error for empty string. + reg: FormatMessage() now reports ERROR_NO_WORK_DONE error for empty string. + regedit: FormatMessage() now reports ERROR_NO_WORK_DONE error for empty string. + regsvr32: FormatMessage() now reports ERROR_NO_WORK_DONE error for empty string. + uninstaller: FormatMessage() now reports ERROR_NO_WORK_DONE error for empty string. + xcopy: FormatMessage() now reports ERROR_NO_WORK_DONE error for empty string. + ntdll: Initialize server directory on macOS when sending Mach port. + ntdll: Fix __sync_bool_compare_and_swap() usage. + ntdll: Handle already relocated .dynamic entries. + winegcc: Allow the output file to end in .so. + makefiles: Add support for building Unix .so libraries. + ntdll: Initial version of the ntdll.so Unix library. + ntdll: Allow ntdll.so to be loaded before wine_init() has run. + ntdll: Set up virtual memory layout in the Unix library. + loader: Try to load ntdll.so before libwine initialization. + ntoskrnl.exe: Avoid a few more ntdll forwards. + ntdll: Move the mmap reserved area functions to the Unix library. + ntdll: Store reserved areas in the Unix library. + ntdll: Move the debug functions to the Unix library. + ntdll: Move the Wine version functions to the Unix library. + ntdll: Do the pre-exec checks in the Unix library. + ntdll: Store main() arguments in the Unix library. + ntdll: Move configuration paths setup to the Unix library. + ntdll: Move the wineloader exec support to the Unix library. + ntdll: Don't use libwine during the Unix library initialization. + ntdll: Move the wineserver exec support to the Unix library. + ntdll: Move the Unix codepage initialization to the Unix library. + ntdll: Move setting the process name to the Unix library. + wineboot: Use wide character string literals. + include: Update the KUSER_SHARED_DATA structure. + ntdll: Make the windows directory a global variable. + ntdll: Add some more CPU feature flags. + ntdll: Centralize initialization of the user shared data. + ntdll: Use the user shared data to implement NtGetTickCount(). + ntdll: Use the user shared data to implement RtlQueryUnbiasedInterruptTime(). + kernelbase: Move WaitOnAddress implementation to sync.c. + kernelbase: Use the user shared data to implement GetTickCount(). + kernel32: Use the user shared data to implement GetTickCount(). + kernel32: Move GetProcessTimes() implementation to kernelbase and ntdll. + kernel32: Move GetSystemTimes() implementation to kernelbase. + ntdll: Implement SystemTimeAdjustmentInformation class. + kernel32: Move Get/SetSystemTimeAdjustment to kernelbase. + kernel32: Move the *PreferredUILanguages functions to kernelbase and ntdll. + ntdll: Silence a va_start compiler warning. + +Alistair Leslie-Hughes (2): + shell32: Correct if condition. + loader: http.sys belongs in the driver directory. + +Alon Barzilai (1): + ntdll: Add missing RtlQueryEnvironmentVariable function. + +André Hentschel (1): + ntdll: Fix SystemRecommendedSharedDataAlignment on ARM. + +Aurimas Fišeras (1): + po: Update Lithuanian translation. + +Austin English (1): + mshtml: Mark tests that need wine-gecko as todo on arches without it. Biswapriyo Nath (2): - include: Add d3d11 video processor capability flags. - include/dxgi.idl: Add cpu access flags. + include/dwrite_1.idl: Fix typo in DWRITE_PANOSE_STROKE_VARIATION symbol name. + include/dwrite.idl: Fix typo in DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME member name. + +Brendan Shanks (1): + ntdll: Fix length calculation of generated SMBIOS tables. -Brendan Shanks (8): - include: Add additional DISPLAYCONFIG defines. - user32: Move DisplayConfig stubs together into sysparams.c. - user32/tests: Add QueryDisplayConfig() and DisplayConfigGetDeviceInfo() tests. - user32: Improve QueryDisplayConfig() stub. - user32: Improve DisplayConfigGetDeviceInfo() stub. - include: Add additional DISPLAYCONFIG defines. - user32/tests: Rename DisplayConfig test functions to match style. - user32/tests: Test success for QueryDisplayConfig() and DisplayConfigGetDeviceInfo(). - -Christian Costa (1): - d3dx9/tests: Remove useless '\n' within some ok() messages. - -Derek Lesho (1): - mf: Add missing ::Release of clock timer. - -Dmitry Kislyuk (1): - wshom.ocx: Use wide character string literals. - -Dmitry Timoshkov (3): - windowscodecs: Add initial implementation of the GIF encoder. - windowscodecs: Fix IWICBitmapDecoder::CopyPalette for a not initialized case in the GIF decoder. - windowscodecs/tests: Add the tests for GIF encoder and decoder. - -Fabian Maurer (2): - find.exe/tests: Add test for multiple files at once. - find.exe: Implement file searching. - -Gabriel Ivăncescu (6): - qedit: Check for S_OK when enumerating the splitter pin. - qedit: Check for S_OK when enumerating the source pin. - qedit: Retrieve the pin media type using a helper function. - qedit: Use the pin's media type instead of querying for IFileSourceFilter. - qedit: Implement IMediaDet::get_StreamLength(). - cmd.exe: Don't treat explicit paths as a PATH search list. - -Gijs Vermeulen (3): - wineqtdecoder: Do not use wide string literals to fix warning. - ntdll: Remove unused function fast_wait_cv(). - kernel32: Remove unused functions is_executable() and get_table_entry(). - -Hans Leidekker (3): - msxml3: Update version resource. - msxml6: Update version resource. - msi: Return void from init_automation_object. - -Henri Verbeet (25): - wined3d: Do not flush read-only mappings in wined3d_texture_vk_download_data(). - wined3d: Move device_clear_render_targets() to texture.c. - wined3d: Use the view instead of the texture in is_full_clear(). - wined3d: Create Vulkan image views for rendertarget views. - wined3d: Implement clears in the Vulkan blitter. - wined3d: Implement depth/stencil clears in the Vulkan blitter. - wined3d: Make the adapter responsible for compute dispatch. - wined3d: Make the adapter responsible for draws. - wined3d: Add Vulkan format information for WINED3DFMT_R9G9B9E5_SHAREDEXP. - wined3d: Add Vulkan format information for WINED3DFMT_D32_FLOAT_S8X24_UINT. - wined3d: Add Vulkan format information for WINED3DFMT_R32_FLOAT_X8X24_TYPELESS. - wined3d: Add Vulkan format information for WINED3DFMT_X32_TYPELESS_G8X24_UINT. - wined3d: Add Vulkan format information for WINED3DFMT_D24_UNORM_S8_UINT. - wined3d: Implement WINED3D_MAP_DISCARD support in adapter_vk_map_bo_address(). - wined3d: Use DISCARD maps in wined3d_buffer_vk_upload_ranges() if possible. - wined3d: Create Vulkan image views for shader resource views. - wined3d: Create Vulkan buffer views for shader resource views. - wined3d: Create Vulkan image views for unordered access views. - wined3d: Create Vulkan buffer views for unordered access views. - wined3d: Create Vulkan buffer views for unordered access view counters. - wined3d: Create Vulkan samplers for samplers. - wined3d: Add a swizzle to the Vulkan format information for WINED3DFMT_A8_UNORM. - wined3d: Add Vulkan format information for WINED3DFMT_B8G8R8X8_UNORM. - wined3d: Add Vulkan format information for WINED3DFMT_B8G8R8X8_UNORM_SRGB. - wined3d: Submit the current command buffer in adapter_vk_flush_context(). - -Jacek Caban (39): - server: Fix setting context flags in get_thread_context. - msvcp: Get rid of no longer needed hack. - wine/exception.h: Don't override __attribute__ keyword on clang MSVC target. - wincon.h: Don't use calling convention wrappers on MSVC. - include: Improve _CrtDbgBreak macro. - math.h: Use builtin nan and inf on clang MSVC target. - wine/asm.h: Introduce __ASM_USE_THISCALL_WRAPPER macro. - msvcirt: Use __ASM_USE_THISCALL_WRAPPER macro. - msvcp60: Use __ASM_USE_THISCALL_WRAPPER macro. - msvcp: Use __ASM_USE_THISCALL_WRAPPER macro. - msvcrt: Use __ASM_USE_THISCALL_WRAPPER macro. - riched20/tests: Don't use thiscall wrappers on clang MSVC target. - riched20: Use __ASM_USE_THISCALL_WRAPPER macro. - rpcrt4: Don't use GetExceptionCode outside __except block. - server: Don't try to synchronize system registers on not initialized threads in get_thread_context request. - server: Delay setting system registers until suspending select is waken. - winbase.h: Support using int for LONG in MSVC interlocked functions. - riched20: Include wine/asm.h in editstr.h. - winegcc: Add entry symbol underscore when building linker command. - winegcc: Explicitly pass DLL crt entry point to PE linker when Wine crt is used. - winegcc: Make mingw a separated platform from msvc. - winegcc: Use libgcc only on mingw target. - winegcc: Add support for msvc target. - include: Introduce WINE_USE_LONG macro. - include: Add intrin.h and use it to provide __cpuid implementation. - wineboot: Use __cpuid from intrin.h. - wbemprox: Use __cpuid from intrin.h. - ntdll: Export _chkstk from importlib. - ntoskrnl.exe: Export _chkstk from importlib. - winecrt0: Build exception functions on clang msvc target. - winecrt0: Add _fltused symbol. - configure: Assume that -delayload linker argument is supported when -target argument is used. - configure: Allow specifying default CROSSTARGET as configure argument. - configure: Explicitly specify subsystem when using msvc target. - winebuild: Introduce --safeseh option that allows marking assembly files as SEH compatible. - winegcc: Use --safeseh winebuild option on msvc target. - msdmo: Use proper buffer types in IEnumDMO::Next. - winuser.h: Add touch event flags. - comdlg32: Improve error handling in get_config_key_string. +Charles Davis (8): + wined3d: Have ARB_fbo imply EXT_packed_depth_stencil. + winemac.drv: Use InitOnceExecuteOnce to initialize OpenGL. + preloader: Depend on wine_info.plist. + d3d11: Implement d3d11_immediate_context_FinishCommandList(). + d3d11: Implement d3d11_immediate_context_GetContextFlags(). + wined3d: Introduce wined3d_device_flush(). + d3d11: Implement d3d11_immediate_context_Flush(). + d3d11: Implement d3d10_device_Flush(). + +Connor McAdams (4): + d2d1: Introduce a helper to check for Bézier segments. + d2d1: Introduce a helper to check for split Bézier segments. + d2d1: Allow inserting multiple Bézier control points into a figure at once. + d2d1: Allow appending multiple Bézier control points to a figure at once. + +Damjan Jovanovic (2): + ntdll: Fix ELF initializer address calculations on FreeBSD. + libwine: Add support for mmap at fixed start addresses on FreeBSD. + +Daniel Lehman (1): + vcruntime140_1: Use return address from catch block routine if not provided by catch block info. + +Derek Lesho (2): + mf/samplegrabber: Attach markers to previously queued sample, not the next. + mfreadwrite/reader: Add recognition of ftypemp42 mp4 header. + +Dmitry Timoshkov (5): + server: All fields up to CheckSum are mandatory regardless of SizeOfOptionalHeader value. + ntdll: Don't try to map the PE file past the size of the backing file. + kernel32: On process entry store PEB address in %ebx. + kernel32/tests: Add a PE test image that resembles format of some of 8k demos. + crypt32: pwszContainerName or pwszProvName could be NULL in CRYPT_KEY_PROV_INFO. + +Emilio Cobos Álvarez (2): + widl: Use DECLSPEC_ALIGN in MSVC compatible way for return types too. + api-ms-win-crt-private-l1-1-0: Implement _o__fileno, _o__setmode, _o__wfopen. + +Esme Povirk (7): + joy.cpl: Add a description. + gdiplus: Don't set a palette when loading non-indexed images. + gdiplus: Return an error retrieving the palette for a metafile. + gdiplus: Add tests for image palette size. + gdiplus: Implement GdipGetMetafileDownLevelRasterizationLimit. + gdiplus: Improve GdipSetMetafileDownLevelRasterizationLimit. + maintainers: Changing my name. + +François Gouget (5): + windowscodecs/tests: Fix the spelling of a couple of variable names. + msvcrt: Fix a couple of spelling errors in comments. + wineusb.sys: Fix the spelling of an ERR() message. + winebus.sys: Fix the spelling of HID_USAGE_SIMULATION_ACCELERATOR. + rsaenh: Remove an unnecessary reference to wine-devel. + +Gabriel Ivăncescu (2): + winex11.drv: Use a helper to retrieve the decoration rect for managed windows. + winex11.drv: Fix X11DRV_X_to_window_rect to handle windows smaller than the decoration. + +Gijs Vermeulen (10): + advpack: Extract inf file before installing in ExecuteCab(). + dxgi: Introduce helper to convert between dxgi and wined3d scanline ordering types. + dwrite: Set ret on unimplemented lookup in opentype_layout_apply_gsub_lookup. + include: Fix SetupDiGetActualSectionToInstallExA/W definitions. + setupapi: Add SetupDiGetActualSectionToInstallExA/W. + winemac: Add default case in isMouseMoveEventType. + setupapi: Correct SetupDiGetActualSectionToInstall[Ex]A/W .spec file entries. + advapi32: Set last error directly in GetUserName. + ucrtbase: Add more _o forwards. + ntdll: Fix number of arguments passed to mmap_remove_reserved_area in apple_create_wine_thread. + +Hans Leidekker (4): + wbemprox: Fix allocation size. + crypt32: Recognize 'Microsoft Root Certificate Authority 2010' when verifying the Microsoft root policy. + crypt32: Microsoft root policy does not include the base policy. + wbemprox: Get the operating system serial number from the registry. + +Henri Verbeet (34): + wined3d: Introduce WINED3D_BITMAP_SIZE. + wined3d: Check for a bound compute shader in wined3d_cs_exec_dispatch(). + wined3d: Introduce a SPIR-V shader backend for the Vulkan adapter. + wined3d: Implement adapter_vk_dispatch_compute(). + wined3d: Implement Vulkan constant buffer descriptors. + wined3d: Implement Vulkan image shader resource view descriptors. + wined3d: Implement Vulkan buffer shader resource view descriptors. + wined3d: Implement Vulkan sampler descriptors. + wined3d: Implement Vulkan buffer unordered access view descriptors. + wined3d: Implement Vulkan image unordered access view descriptors. + wined3d: Implement Vulkan unordered access view counter descriptors. + wined3d: Implement Vulkan NULL buffer shader resource view descriptors. + wined3d: Implement Vulkan NULL 1D image shader resource view descriptors. + wined3d: Implement Vulkan NULL 2D image shader resource view descriptors. + wined3d: Reference shader resources in wined3d_context_vk_update_descriptors(). + wined3d: Add a supported extensions array to the wined3d_vk_info structure. + wined3d: Implement Vulkan draws. + wined3d: Implement indirect Vulkan draws. + wined3d: Implement indexed Vulkan draws. + wined3d: Create Vulkan pipeline objects. + wined3d: Bind Vulkan vertex buffers. + wined3d: Implement scissor rectangle support for the Vulkan adapter. + wined3d: Implement blend object support for the Vulkan adapter. + wined3d: Implement rasterisation object support for the Vulkan adapter. + wined3d: Store the wined3d primitive type in the wined3d state structure. + wined3d: Store the wined3d patch vertex count in the wined3d state structure. + wined3d: Implement different primitive topologies for the Vulkan adapter. + wined3d: Implement primitive restart for the Vulkan adapter. + wined3d: Set the correct patch vertex count for the Vulkan adapter. + wined3d: Implement depth tests and writes for the Vulkan adapter. + wined3d: Implement stencil tests for the Vulkan adapter. + wined3d: Implement alpha to coverage multisampling for the Vulkan adapter. + wined3d: Implement vertex attribute divisors for the Vulkan adapter. + wined3d: Move the swapchain fps counter to wined3d_cs_exec_present(). + +Jacek Caban (24): + dbghelp: Use debuggee environment in search_unix_path. + notepad: Use int for point size value. + dmscript: Remove unused function. + winegcc: Introduce --debug-file option for generating separated symbol files. + configure: Allow specifying cross debug format. + makedep: Support split debug for cross compiled modules. + configure: Check if --disable-stdcall-fixup is supported before using it. + makedep: Install also generated typelib for installed idl files. + oleacc.idl: Generate tlb file for importlib. + winnt.h: Add ARRAYSIZE macro. + wine/test.h: Remove NAN and INFINITY macros. + dmusicf.h: Move typedef below enum declarations. + gdiplusenums.h: Remove PaletteFlags. + winegcc: Default to ucrtbase. + configure: Use cross compiler for EXCESS_PRECISION_CFLAGS check when available. + winegcc: Pass only raw compiler and linker arguments in forward mode. + include: Add winapifamily.h file. + include: Avoid redefinition warnings when basetyps.h is used together with winnt.h or objbase.h. + stdlib.h: Remove _strtold declaration. + stdlib.h: Provide strtold as an inline wrapper. + configure: Remove no longer needed -Wno-incompatible-library-redeclaration. + ucrtbase: Use MSVCRT prefix for __stdio_common_vsprintf implementation. + math.h: Provide copysign declaration for ucrt. + math.h: Add scalbn declaration. Jactry Zeng (6): - qcap/videocapture: Store capabilities information. - qcap/videocapture: Use formats from capabilities instead of hard coding. - qcap/videocapture: Remove code for resizing. - qcap/videocapture: Implement IAMStreamConfig::GetNumberOfCapabilities(). - qcap/videocapture: Implement IAMStreamConfig::GetStreamCaps(). - qcap/videocapture: Reimplement source_get_media_type(). - -Jeff Smith (2): - gdiplus/tests: Indicate which encoder failed when attempting to save image. - gdiplus: Include palette when writing PNG indexed formats. - -Liam Middlebrook (1): - winevulkan: Update to VK spec version spec 1.2.139. - -Mas Ahmad Muhammad (1): - comdlg32: Enlarge list area in CHOOSE_FONT window. - -Micah N Gorrell (2): - advapi32: Replace usage of internal SERV_ functions with exported functions. - advapi32: Replace SERV_dup() with strdupAW(). - -Michael Müller (1): - ddraw: Make ddraw1_vtbl and ddraw_surface1_vtbl writable. - -Nikolay Sivov (28): - mfuuid: Add file scheme handler CLSID to static library. - mfplat/tests: Use file scheme handler CLSID from mfuuid. - comctl32/monthcal: Use wide string literals. - comctl32/ipaddress: Use wide string literals. - comctl32/animate: Use wide string literals. - comctl32/rebar: Use wide string literals. - comctl32/datetime: Use wide string literals. - comctl32/syslink: Use wide string literals. - comctl32/datetime: Use designated initializers for constants. - dwrite: Add separate structure for top level gsub/gpos offsets. - dwrite: Initialize GSUB offsets in shaping cache. - dwrite: Add helper functions to collect default GSUB features. - dwrite: Add a helper to collect gsub/gpos lookups. - dwrite: Implement single substitution lookup (GSUB lookup 1). - dwrite: Partially implement chaining contextual substitution (GSUB lookup 6). - comctl32/header: Use wide string literals. - comctl32/propsheet: Use wide string literals. - comctl32/tab: Use wide string literals. - comctl32: Move MRU functions to another file. - dwrite: Enable common positional features for all scripts. - dwrite: Use feature tags directly instead of SDK symbols. - dwrite: Update DWRITE_SHAPING_TEXT_PROPERTIES definition. - dwrite: Enable global directional substitution features. - mf: Fix timer instance leak on error path in SetTimer(). - rtworkq: Invoke cancelled waiting item with RTWQ_E_OPERATION_CANCELLED. - mfplat: Add I420 format support for frame size helpers. - qmgr: Update to IBackgroundCopyJob4. - qmgr: Make SetMaximumDownloadTime() succeed. - -Philip Rebohle (3): - winevulkan: Support struct forward-declarations as base types. - winevulkan: Avoid adding duplicate enum aliases. - winevulkan: Update to VK spec version spec 1.2.140. - -Piotr Caban (5): - msvcrt: Fix overflow checks in parse_double. - msvcrt: Improve string to double conversion accuracy. - msvcrt: Avoid depending on signed variable overflow in parse_double. - msvcrt/tests: Cleanup strtod tests. - msvcrt: Fix 0 parsing in parse_double helper. - -Rémi Bernon (5): - mfplat: Signal synchronous resolver methods on handler failure. - ntdll/tests: Test that ptids are multiples of four. - server: Make sure pids/tids are multiples of four. - user32: Don't read preparsed data on non-HID devices. - devenum: Use free for memory allocated with wcsdup. - -Serge Gautherie (1): - rpcrt4: Remove inexistent CreateServerInterfaceFromStub(). - -Stefan Dösinger (1): - configure: Try -lgnutls as gnutls default lib. - -Vijay Kiran Kamuju (13): - include: Add IWbemRefresher related interfaces. - include: Add dvdif.idl. - include: Add some missing defines to winioctl.h. - include: Add missing GUIDs and CLSIDs to wincodecsdk.idl. - include: Add related ASN1encoding_s and ASN1decoding_s structs. - msasn1: Add ASN1_CreateModule stub implementation. - msasn1/tests: Add initial tests. - msasn1: Implement ASN1_CreateModule function. - msasn1: Implement ASN1_CloseModule function. - msasn1: Add partial implementation of ASN1_CreateEncoder. - msasn1: Add stub for ASN1_CloseEncoder function. - msasn1: Add partial implementation of ASN1_CreateDecoder. - msasn1: Add stub for ASN1_CloseDecoder function. - -Vincent Povirk (1): - gdiplus: Support character offsets in GDI32_GdipDrawDriverString. - -Zebediah Figura (85): - wineusb.sys: Avoid touching the IRP structure after queueing it. - cmd: Use _wsplitpath() from msvcrt. - cmd: Fix the spelling of "tilde". - cmd: Ignore quotes when parsing command line parameters. - wine.inf: Install WMI DLLs in the wbem subdirectory in WoW64 too. - http.sys: Avoid touching the IRP structure after queueing it. - amstream/tests: Remove some no longer necessary callbacks. - wineqtdecoder: Remove some no longer necessary callbacks. - qasf/tests: Remove some no longer necessary callbacks. - winegstreamer: Remove some no longer necessary callbacks. - quartz/tests: Remove some no longer necessary callbacks. - sechost: New stub DLL. - advapi32: Move event tracing APIs to sechost. - ddraw/tests: Test vtbl protection. - quartz: Don't register the DirectSound renderer as a filter for autoplugging. - quartz: Don't register the audio renderer as a filter for autoplugging. - quartz/tests: Relax a test for PresentImage(). - include: Add the missing SetStreamMediaType() method to IVMRImageCompositor9. - advapi32: Make {Lock, Unlock}ServiceDatabase() into a no-op. - services: Make svcctl_{Lock, Unlock}ServiceDatabase() into a no-op. - advapi32: Reimplement EnumServicesStatusW() on top of EnumServicesStatusExW(). - ksproxy.ax: New stub DLL. - quartz/vmr9: Don't expose IVMRSurfaceAllocatorNotify from the VMR9. - quartz/vmr9: Don't expose IVMRSurfaceAllocatorNotify9 from the VMR7. - quartz/vmr9: Don't expose IVMRWindowlessControl from the VMR9. - quartz/vmr9: Don't expose IVMRWindowlessControl9 from the VMR7. - quartz/tests: Expand tests for VMR9 interfaces. - advapi32: Move service functions into sechost. - quartz/vmr9: Remove some dead code. - quartz/vmr9: Support VMR9AllocFlag_3DRenderTarget in IVMRSurfaceAllocatorNotify9::AllocateSurfaceHelper(). - quartz/vmr9: Retrieve a default format if none is given in IVMRSurfaceAllocatorNotify9::AllocateSurfaceHelper(). - quartz/vmr9: Improve tracing in IVMRSurfaceAllocatorNotify9::AllocateSurfaceHelper(). - d3dcompiler: Fix matrix dimension declaration and access. - d3dcompiler: Set the struct base type to HLSL_TYPE_VOID. - d3dcompiler: Respect arrays in struct fields. - d3dcompiler: Set the dimensions for array types. - d3dcompiler: Set the x-dimension for struct types. - quartz/tests: Fix a copy-paste error. - quartz/tests: Add more tests for mixing mode. - quartz/tests: Add some tests for sample presentation time on the VMR9. - quartz/tests: Add some tests for end-of-stream notifications on the VMR9. - quartz/tests: Test current position caching. - d3dcompiler: Add a helper to initialize the hlsl_ir_node structure. - qcap/filewriter: Propagate file I/O failure in file_writer_sink_receive(). - advapi32: Move string SID/SD conversion functions to sechost. - quartz/tests: Add some tests for IVMRWindowlessControl9::SetVideoClippingWindow(). - quartz/vmr9: Validate the window in IVMRWindowlessControl9::SetVideoClippingWindow(). - quartz/vmr9: Forbid setting the video clipping window while connected. - quartz/vmr9: Do not call VMR9_maybe_init() in vmr_start_stream(). - quartz/vmr9: Remove the "force" parameter of VMR9_maybe_init(). - ntoskrnl.exe: Protect relocated pages one at a time. - ntdll: Export RtlCopyMemoryNonTemporal. - ntoskrnl.exe: Implement IoIs32bitProcess(). - quartz/tests: Add tests for the separate reference count of IVMRSurfaceAllocatorNotify9. - quartz/vmr9: Track the IVMRSurfaceAllocatorNotify9 reference count separately. - quartz/vmr9: Call IVMRSurfaceAllocator9::TerminateDevice() when destroying the filter. - quartz/vmr9: Add a stub IVMRMixerBitmap9 interface. - kernel32/tests: Account for unsupported NLSVERSIONINFOEX. - kernel32/tests: Fix failures in test_GetThreadSelectorEntry() on 32-bit machines. - ddraw/tests: Add more tests for EnumSurfaces(). - ddraw: Properly compare DDENUMSURFACES_NOMATCH to TRUE. - ddraw: Implement DDENUMSURFACES_CANBECREATED. - quartz/videorenderer: Factor out get_bitmap_header(). - quartz/videorenderer: Set the source rect at connection time. - quartz/videorenderer: Resize the window in video_renderer_connect(). - quartz/vmr9: Factor out get_bitmap_header(). - quartz/vmr9: Resize the window in vmr_connect(). - sechost: Implement I_ScRegisterDeviceNotification(). - ntoskrnl.exe: Broadcast device notifications to registered handlers. - user32: Implement RegisterDeviceNotification(). - ntoskrnl.exe: Move the BroadcastSystemMessage() call to plugplay_send_event(). - quartz: Rename "baseControlWindow" to "window". - quartz: Retrieve the video format directly from the pin. - quartz: Get rid of the IsDefault*Rect callbacks. - quartz: Move the source and destination rectangles to the BaseControlVideo structure. - quartz: Merge the BaseControlVideo object into the video_window object. - ntdll/tests: Add tests for RtlSetCurrentEnvironment(). - ntdll: Avoid leaking the previous environment in RtlSetCurrentEnvironment(). - kernelbase: Implement SetEnvironmentStrings(). - http.sys: Use a separate file and preprocessor directives to avoid duplication. - quartz: Get rid of the SetDefault*Rect callbacks. - quartz: Get rid of the resize callback. - quartz: Resize the destination rect only if we are using the default destination rect. - quartz: Implement IBasicVideo::IsUsingDefaultSource(). - quartz/tests: Add tests for IBasicVideo. - -Zhiyi Zhang (19): - user32/tests: Flush messages after mode changes. - user32/tests: Fix a ChangeDisplaySettings() test. - user32/tests: Test EnumDisplayMonitors(). - user32: Leave critical section before calling callbacks in EnumDisplayMonitors(). - dxgi/tests: Fix a possible test failure on D3D12. - dxgi/tests: Do not run test_multi_adapter() in parallel with other tests. - dxgi/tests: Test IDXGISwapChain_ResizeTarget() with all outputs. - wined3d: Move device window to the correct output in wined3d_swapchain_state_resize_target(). - wined3d: Fix an uninitialised variable warning. - user32/tests: Add a trailing '\n' to some ok() calls. - user32/tests: Test button styles. - comctl32/tests: Test button styles. - comctl32/button: Do not set BS_PUSHBUTTON and BS_DEFPUSHBUTTON style directly to Split Buttons and Command Links. - user32/tests: Test restoring a full screen window with WS_THICKFRAME style. - winex11.drv: Update _NET_WM_STATE before resizing windows. - dxgi/tests: Add more default full screen swapchain target output tests. - wined3d: Release wined3d mutex if wined3d_swapchain_state_init() failed in wined3d_swapchain_init(). - wined3d: Move device window to the correct output when changing swapchain state to full screen. - dxgi/tests: Add more get swapchain containing output tests. + include: Add some interface definitions for axextend.idl. + qcap/tests: Add interface tests for video capture filter. + qcap/videocapture: Initialize caps struct. + qcap/tests: Correct CLSID in aggregation tests of smart tee filter. + qcap/videocapture: Implement IAMFilterMiscFlags interface. + qcap/videocapture: Implement IAMVideoControl interface. + +Józef Kucia (3): + wined3d: Introduce a (stub) SPIR-V fixed-function vertex pipe implementation. + wined3d: Introduce a (stub) SPIR-V fixed-function fragment pipe implementation. + wined3d: Implement shader_spirv_select(). + +Louis Lenders (3): + iphlpapi: Add stub for NotifyRouteChange2. + setupapi: Add stub for CM_Get_Device_Interface_Alias{A,W}. + shcore: Return S_OK in SetCurrentProcessExplicitAppUserModelID. + +Markus Engel (2): + user32: Force undefined bits in GetKeyState() and GetKeyboardState() to zero. + user32/tests: Add more tests for GetKeyState(). + +Martin Storsjo (5): + ntdll: Fix arm64 unwind across ELF/PE boundaries. + ntdll: Pass a nonnull handler_data when continuing after a collided unwind on arm64. + ntdll: Properly restore x29/x30 for arm64 packed unwind data with local stack. + ucrtbase: Add tests and fix more zero length __stdio_common_vs[w]printf cases. + ucrtbase: Extend the printf tests even further. + +Michael Stefaniuc (1): + dmusic: Remove an unused function. + +Murray Colpman (1): + winex11.drv: Interpret mouse 6/7 as horiz scroll. + +Nikolay Sivov (40): + dxgi: Translate DXGI_USAGE_UNORDERED_ACCESS to corresponding wined3d bind flag. + mf: Add a helper for session commands without parameters. + mf: Add a helper to set closed state for the session. + mf: Add a helper to set paused state for the session. + mf: Move locking from individual command helpers to command callback. + mf: Serialize session commands. + mf: Add internal placeholder command for end-of-presentation. + shlwapi: Forward SHRegDuplicateHKey() to shcore.dll. + shlwapi: Forward SHRegGetPath() to shcore.dll. + shlwapi: Forward SHRegSetPath() to shcore.dll. + shlwapi: Forward SHGetValue() to shcore.dll. + shlwapi: Forward SHQueryInfoKey() to shcore.dll. + shlwapi: Forward SHDeleteValueW() to shcore.dll. + shlwapi: Forward SHSetValue() to shcore.dll. + shlwapi: Forward SHQueryValueExA() to shcore.dll. + mf: Add flags field for additional SAR state. + mf: Avoid unnecessary prerolling calls in SAR. + mf: Preroll on sink start. + mf/sar: Implement sample processing. + mf/sar: Implement stream flushing. + mf/sar: Use MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS attribute to configure audio client. + mf/sar: Use MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID to initialize audio client. + mfreadwrite/reader: Consider end-of-stream state when picking stream for MF_SOURCE_READER_ANY_STREAM requests. + mf/samglegrabber: Dump pending items on shutdown. + mf/samplegrabber: Remove now unnecessary shutdown state check. + mf/samplegrabber: Test shutdown state under the lock for methods that modify item queue. + quartz/dsoundrenderer: Remove dead method call. + dwrite: Remove feature duplicates before applying them. + dwrite: Set feature indices before collecting lookups. + dwrite: Enable 'vert' feature. + dwrite: Append enabled user features that apply to whole text. + dwrite: Keep user features values. + dwrite: Propagate feature mask to lookups collected from it. + dwrite: Keep track of shaping stage feature applies to. + dwrite: Set per-glyph feature mask. + dwrite: Silence warning for name entries with platform 3/encoding 10. + dwrite: Use mirrored character only if font supports it. + mf/topology: Setting tee node input type does not create input stream. + mf/topology: Remove logic already present in stream resize helper. + include: Add IMFTopologyNodeAttributeEditor definition. + +Paul Gofman (4): + wined3d: Allow setting user memory for mipmapped textures in wined3d_texture_update_desc(). + ntoskrnl.exe: Emulate full user shared data area range. + ntoskrnl.exe: Support 'or Ev, Gv' opcode for x86_64. + ntoskrnl.exe: Support 'xor Ev, Gv' opcode for x86_64. + +Philip Rebohle (4): + include: Add IDXGIFactory6. + dxgi: Implement IDXGIFactory6. + include: Add IDXGIFactory7. + dxgi: Add stubs for IDXGIFactory7. + +Piotr Caban (1): + ucrtbase: Add remaining _o_* functions forwards. + +Rémi Bernon (4): + ntdll/tests: Add tests for USD timestamp updates. + ntdll/tests: Add tests for USD memory basic info. + server: Add USD support with timestamp updates. + ntdll: Reduce USD section size to 0x1000. + +Stefan Dösinger (2): + wined3d: Implement Vulkan NULL 3D image shader resource view descriptors. + wined3d: Implement Vulkan NULL cube image shader resource view descriptors. + +Vijay Kiran Kamuju (1): + include: Add new defines and fix struct WNODE_HEADER. + +Vladimir Panteleev (3): + kernelbase: Preserve last error when GetEnvironmentVariableA succeeds. + kernelbase: Don't return ERROR_INSUFFICIENT_BUFFER from GetEnvironmentVariableW. + kernelbase: Fix GetEnvironmentVariableW return for empty variables. + +Zebediah Figura (49): + include: Add dpfilter.h. + quartz/tests: Fix a test failure on 32-bit Windows. + quartz/tests: Add some tests for windowless video size. + quartz: Set VMR9AllocationInfo dimension members to the video dimensions. + quartz: Get rid of the texture drawing path. + quartz/vmr9: Get rid of VMR9_SurfaceAllocator_UpdateDeviceReset(). + quartz/vmr9: Perform image stretching in Present() instead of StretchRect(). + quartz/vmr9: Allow the aspect ratio parameters to be NULL in IVMRWindowlessControl9::GetNativeVideoSize(). + quartz/vmr9: Remove a redundant check from VMR9_SurfaceAllocator_InitializeDevice(). + quartz/vmr9: Rename hWndClippingWindow to clipping_window. + quartz/vmr9: Render to the clipping window in windowless mode. + quartz/vmr9: Destroy the window when set to windowless or renderless mode. + quartz/vmr9: Check for D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES. + quartz/vmr9: Partially implement IVMRFilterConfig9::SetNumberOfStreams(). + quartz/vmr9: Implement IVMRFilterConfig9::GetNumberOfStreams(). + quartz/vmr9: Add IVMRMixerControl9. + quartz/vmr9: Set the stream count to 4 in IVMRWindowlessControl9::SetVideoClippingWindow(). + quartz/vmr9: Allocate the surface array in allocate_surfaces(). + qcap/tests: Get rid of the VFW capture filter tests. + devenum: Use calloc() in enum_moniker_create(). + devenum: Map CLSID_LegacyAmFilterCategory to DMOCATEGORY_AUDIO_DECODER and DMOCATEGORY_VIDEO_DECODER. + devenum: Use wide string literals. + quartz/tests: Fix a crash in test_allocate_surface_helper(). + quartz/tests: Test filter mapper interfaces. + quartz/tests: Fix a leak in test_fm2_enummatchingfilters(). + quartz: Pass the matching filter count to IEnumRegFiltersImpl_Construct(). + devenum: Return filter data for DMO monikers. + quartz/tests: Test enumerating DMOs. + quartz/tests: Fix a crash in test_renderless_formats(). + quartz/tests: Fix a test failure in Windows 7 and higher. + quartz/tests: Relax an intermittently failing test. + quartz/filtergraph: Get rid of tracing for outer IUnknown methods. + shell32/tests: Add more tests for IShellWindows. + explorer: Implement IShellWindows::Register() and IShellWindows::Revoke(). + explorer: Implement IShellWindows::OnNavigate(). + explorer: Implement IShellWindows::FindWindowSW() for non-desktop windows. + explorer: Look for an existing window browsing the given path first. + quartz: Complain louder if a filter reports the wrong state. + quartz: Implement IMediaControl::StopWhenReady(). + ntdll: Remove extraneous newline from debugstr_ObjectAttributes(). + d3dcompiler: Synthesize a variable when subscripting a non-deref node. + d3dcompiler: Synthesize a variable when indexing a non-deref node. + d3dcompiler: Do not store matrix and vector indexes as deref instructions. + include: Add asferr.h. + quartz/tests: Move the test for filter mapper aggregation to filtergraph.c. + quartz: Merge enumregfilters.c into filtermapper.c. + quartz: Merge enummoniker.c into filtermapper.c. + wine.inf: Install some driver libraries in the system32/drivers subdirectory. + ntoskrnl.exe: Protect the two relocated pages independently. + +Zhiyi Zhang (21): + dxgi: Search all adapters for the containing output of a swapchain. + ddraw/tests: Test window position. + d3d8/tests: Test window position. + d3d9/tests: Test window position. + ddraw/tests: Add get display mode tests. + d3d8/tests: Add more get display mode tests. + d3d9/tests: Add more get display mode tests. + winex11.drv: Resize desktop upon display change events. + winex11.drv: Move update_windows_on_desktop_resize(). + dxgi/tests: Test IDXGISwapChain_GetContainingOutput() after Alt+Enter. + d3d8: Store a struct d3d8 in struct d3d8_device. + wined3d: Specify a wined3d output for swapchain creation. + wined3d: Determine output from window position in wined3d_hook_proc(). + wined3d: Get output from swapchain state. + kernelbase: Check NULL canonicalized_len parameter in UrlCanonicalizeW(). + shlwapi/tests: Test NULL UrlCanonicalizeA/W() parameters. + wined3d: Move device window to the correct output when handling WM_ACTIVATEAPP with full screen swapchains. + wined3d: Restore display mode for the previous output before changing to another output. + wined3d: Remove no longer needed output parameter in wined3d_swapchain_state_set_fullscreen(). + dxgi: Remove dxgi_swapchain_set_fullscreen_state(). + wined3d: Remove no longer needed output parameter in wined3d_swapchain_state_resize_target(). Ziqing Hui (3): - windowscodecs: Add stub for DdsFrameDecode. - windowscodecs: Add stub implementation for IWICDdsDecoder. - windowscodecs: Add stub implementation for IWICDdsFrameDecode. + windowscodecs/tests: Add tests for IWICDdsDecoder_GetParameters(). + windowsccodecs: Implement DdsDecoder_Dds_GetParameters(). + windowscodecs/tests: Add tests for DdsDecoder_GetFrame() and DdsFrameDecode_GetSize(). -- Alexandre Julliard diff -Nru wine-development-5.8/AUTHORS wine-development-5.9/AUTHORS --- wine-development-5.8/AUTHORS 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/AUTHORS 2020-05-22 18:49:34.000000000 +0000 @@ -79,6 +79,7 @@ Alfons Hoogervorst Alistair Leslie-Hughes Allan Tong +Alon Barzilai Álvaro Nieto Ambrož Bizjak Américo José Melo @@ -438,6 +439,7 @@ Elias Benali Elias Ross Elie Morisse +Emilio Cobos Álvarez Emmanuel Maillard Enol Puente Enrico Horn @@ -462,6 +464,7 @@ Erik Svendsen Erwin Wolff Eryk Wieliczko +Esme Povirk Ethan Chen Ethan Lee Eugene Mayevski @@ -1030,6 +1033,7 @@ Marko Kreen Marko Nikolic Markus Amsler +Markus Engel Markus Gömmel Markus Heidelberg Markus Hitter @@ -1164,6 +1168,7 @@ Mounir Idrassi Muneyuki Noguchi Murali Pattathe +Murray Colpman Myah Caron Mykola Zadorozhnyy Natanael Copa @@ -1644,7 +1649,6 @@ Vincent Béron Vincent Hardy Vincent Pelletier -Vincent Povirk Vitaliy Margolen Vitaly Budovski Vitaly Lipatov diff -Nru wine-development-5.8/configure.ac wine-development-5.9/configure.ac --- wine-development-5.8/configure.ac 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/configure.ac 2020-05-22 18:49:34.000000000 +0000 @@ -727,7 +727,8 @@ DLLEXT="" dnl Disable stdcall fixups to catch prototype mismatches case $host_cpu in - *i[[3456]]86*) LDDLLFLAGS="-Wl,--disable-stdcall-fixup" ;; + *i[[3456]]86*) WINE_TRY_CFLAGS([-Wl,--disable-stdcall-fixup], + [LDDLLFLAGS="-Wl,--disable-stdcall-fixup"]) ;; esac dnl Disable modules that can't be used on Windows enable_iphlpapi=${enable_iphlpapi:-no} @@ -1077,6 +1078,7 @@ WINE_TRY_CROSSCFLAGS([-fno-strict-aliasing]) dnl clang needs to be told to fail on unknown options WINE_TRY_CROSSCFLAGS([-Werror=unknown-warning-option],[CFLAGS="$CFLAGS -Werror=unknown-warning-option"]) + WINE_TRY_CROSSCFLAGS([-Werror=ignored-optimization-argument],[CFLAGS="$CFLAGS -Werror=ignored-optimization-argument"]) WINE_TRY_CROSSCFLAGS([-Wdeclaration-after-statement]) WINE_TRY_CROSSCFLAGS([-Wempty-body]) WINE_TRY_CROSSCFLAGS([-Wignored-qualifiers]) @@ -1090,8 +1092,6 @@ WINE_TRY_CROSSCFLAGS([-Wwrite-strings]) WINE_TRY_CROSSCFLAGS([-Wpointer-arith]) WINE_TRY_CROSSCFLAGS([-Wlogical-op]) - WINE_TRY_CROSSCFLAGS([-Wincompatible-library-redeclaration], - [EXTRACROSSCFLAGS="$EXTRACROSSCFLAGS -Wno-incompatible-library-redeclaration"]) case $host_cpu in *i[[3456789]]86*) WINE_TRY_CROSSCFLAGS([-fno-omit-frame-pointer]) ;; @@ -1100,13 +1100,25 @@ WINE_TRY_CROSSCFLAGS([-Wnonnull]) ;; esac - dnl Default to dwarf-2 debug info - for ac_flag in $CROSSCFLAGS; do - case $ac_flag in - -g) WINE_TRY_CROSSCFLAGS([-gdwarf-2]) - WINE_TRY_CROSSCFLAGS([-gstrict-dwarf]) ;; - esac - done + dnl Determine debug info format + AC_SUBST(CROSSDEBUG) + if test -z "$CROSSDEBUG" + then + for ac_flag in $CROSSCFLAGS; do + case $ac_flag in + -gdwarf*) CROSSDEBUG=dwarf ;; + -gcodeview) CROSSDEBUG=pdb ;; + -g) CROSSDEBUG=${CROSSDEBUG:-dwarf} ;; + esac + done + fi + case $CROSSDEBUG in + *dwarf) WINE_TRY_CROSSCFLAGS([-gdwarf-2]) + WINE_TRY_CROSSCFLAGS([-gstrict-dwarf]) ;; + pdb) WINE_TRY_CROSSCFLAGS([-gcodeview]) ;; + esac + + WINE_TRY_CROSSCFLAGS([-fexcess-precision=standard],[AC_SUBST(EXCESS_PRECISION_CFLAGS,"-fexcess-precision=standard")]) if test "x$enable_werror" = "xyes" then @@ -2038,7 +2050,6 @@ WINE_TRY_CFLAGS([-fcf-protection=none]) WINE_TRY_CFLAGS([-fno-stack-protector]) WINE_TRY_CFLAGS([-fno-strict-aliasing]) - WINE_TRY_CFLAGS([-fexcess-precision=standard],[AC_SUBST(EXCESS_PRECISION_CFLAGS,"-fexcess-precision=standard")]) WINE_TRY_CFLAGS([-Wdeclaration-after-statement]) WINE_TRY_CFLAGS([-Wempty-body]) WINE_TRY_CFLAGS([-Wignored-qualifiers]) @@ -2051,6 +2062,11 @@ WINE_TRY_CFLAGS([-Wvla]) WINE_TRY_CFLAGS([-Wwrite-strings]) + if test -z "$CROSSTARGET" + then + WINE_TRY_CFLAGS([-fexcess-precision=standard],[AC_SUBST(EXCESS_PRECISION_CFLAGS,"-fexcess-precision=standard")]) + fi + dnl Check for noisy string.h WINE_TRY_CFLAGS([-Wpointer-arith], [saved_string_h_CFLAGS=$CFLAGS @@ -2236,7 +2252,6 @@ inet_addr \ inet_network \ inet_ntop \ - inet_pton \ ) dnl Check for clock_gettime which may be in -lrt diff -Nru wine-development-5.8/debian/changelog wine-development-5.9/debian/changelog --- wine-development-5.8/debian/changelog 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/changelog 2021-05-04 03:47:51.000000000 +0000 @@ -1,3 +1,14 @@ +wine-development (5.9-1) unstable; urgency=medium + + * New upstream release 5.9, released May 22, 2020. + - Major progress on the WineD3D Vulkan backend. + - Initial support for splitting dlls into PE and Unix parts. + - Support for generating PDB files when building PE dlls. + - Timestamp updates in the Kernel User Shared Data. + - Various bug fixes. + + -- Michael Gilbert Tue, 04 May 2021 03:47:51 +0000 + wine-development (5.8-1) unstable; urgency=medium * New upstream release 5.8, released May 8, 2020. diff -Nru wine-development-5.8/debian/libwineVERSION.install wine-development-5.9/debian/libwineVERSION.install --- wine-development-5.8/debian/libwineVERSION.install 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/libwineVERSION.install 2021-05-04 03:47:51.000000000 +0000 @@ -1,5 +1,6 @@ # fake PE files and their corresponding ELF files debian/tmp/usr/lib/*/*/*.*.so +debian/tmp/usr/lib/*/*/ntdll.so debian/tmp/usr/lib/*/*/fakedlls # wine library diff -Nru wine-development-5.8/debian/patches/binary-indep/manpages.patch wine-development-5.9/debian/patches/binary-indep/manpages.patch --- wine-development-5.8/debian/patches/binary-indep/manpages.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/binary-indep/manpages.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/tools/makedep.c +++ b/tools/makedep.c -@@ -3884,6 +3884,7 @@ static void output_sources( struct makef +@@ -3955,6 +3955,7 @@ static void output_sources( struct makef output_filenames_obj_dir( make, make->all_targets ); output( "\n" ); } diff -Nru wine-development-5.8/debian/patches/binary-indep/sfnt2fon.patch wine-development-5.9/debian/patches/binary-indep/sfnt2fon.patch --- wine-development-5.8/debian/patches/binary-indep/sfnt2fon.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/binary-indep/sfnt2fon.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/configure.ac +++ b/configure.ac -@@ -3900,7 +3900,6 @@ WINE_CONFIG_MAKEFILE(dlls/xmllite/tests) +@@ -3915,7 +3915,6 @@ WINE_CONFIG_MAKEFILE(dlls/xmllite/tests) WINE_CONFIG_MAKEFILE(dlls/xolehlp) WINE_CONFIG_MAKEFILE(dlls/xpsprint) WINE_CONFIG_MAKEFILE(dlls/xpssvcs) @@ -11,7 +11,7 @@ WINE_CONFIG_MAKEFILE(include) WINE_CONFIG_MAKEFILE(libs/port) WINE_CONFIG_MAKEFILE(libs/wine) -@@ -4019,7 +4018,6 @@ WINE_CONFIG_MAKEFILE(programs/xcopy) +@@ -4034,7 +4033,6 @@ WINE_CONFIG_MAKEFILE(programs/xcopy) WINE_CONFIG_MAKEFILE(programs/xcopy/tests) WINE_CONFIG_MAKEFILE(server) WINE_CONFIG_MAKEFILE(tools,,[test "x$enable_tools" = xno]) diff -Nru wine-development-5.8/debian/patches/debianization/mingw.patch wine-development-5.9/debian/patches/debianization/mingw.patch --- wine-development-5.8/debian/patches/debianization/mingw.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/debianization/mingw.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/configure.ac +++ b/configure.ac -@@ -1034,12 +1034,11 @@ then +@@ -1035,12 +1035,11 @@ then then ac_save_CC="$CC" saved_CFLAGS=$CFLAGS diff -Nru wine-development-5.8/debian/patches/debianization/wineapploader.patch wine-development-5.9/debian/patches/debianization/wineapploader.patch --- wine-development-5.8/debian/patches/debianization/wineapploader.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/debianization/wineapploader.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/tools/makedep.c +++ b/tools/makedep.c -@@ -3356,11 +3356,6 @@ static void output_module( struct makefi +@@ -3422,11 +3422,6 @@ static void output_module( struct makefi if (spec_file) output_man_pages( make ); diff -Nru wine-development-5.8/debian/patches/disable/line-wrapping.patch wine-development-5.9/debian/patches/disable/line-wrapping.patch --- wine-development-5.8/debian/patches/disable/line-wrapping.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/disable/line-wrapping.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/tools/makedep.c +++ b/tools/makedep.c -@@ -518,7 +518,7 @@ static void strarray_qsort( struct strar +@@ -520,7 +520,7 @@ static void strarray_qsort( struct strar */ static void output_filename( const char *name ) { diff -Nru wine-development-5.8/debian/patches/disable/po-modifications.patch wine-development-5.9/debian/patches/disable/po-modifications.patch --- wine-development-5.8/debian/patches/disable/po-modifications.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/disable/po-modifications.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/tools/makedep.c +++ b/tools/makedep.c -@@ -2631,11 +2631,13 @@ static void output_po_files( const struc +@@ -2652,11 +2652,13 @@ static void output_po_files( const struc } if (linguas.count) { diff -Nru wine-development-5.8/debian/patches/fixes/gstbase.patch wine-development-5.9/debian/patches/fixes/gstbase.patch --- wine-development-5.8/debian/patches/fixes/gstbase.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/fixes/gstbase.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/configure.ac +++ b/configure.ac -@@ -1650,7 +1650,7 @@ WINE_NOTICE_WITH(pulse, [test -z "$PULSE +@@ -1662,7 +1662,7 @@ WINE_NOTICE_WITH(pulse, [test -z "$PULSE dnl **** Check for gstreamer **** if test "x$with_gstreamer" != "xno" then @@ -12,7 +12,7 @@ [ac_gst_incl="" for i in $GSTREAMER_CFLAGS do -@@ -1658,6 +1658,7 @@ then +@@ -1670,6 +1670,7 @@ then -I*) ac_gst_incl="$ac_gst_incl $i";; esac done diff -Nru wine-development-5.8/debian/patches/generate/icons.patch wine-development-5.9/debian/patches/generate/icons.patch --- wine-development-5.8/debian/patches/generate/icons.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/generate/icons.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/tools/makedep.c +++ b/tools/makedep.c -@@ -1556,6 +1556,9 @@ static struct file *open_include_file( c +@@ -1558,6 +1558,9 @@ static struct file *open_include_file( c if (pFile->type == INCL_SYSTEM) return NULL; /* ignore system files we cannot find */ @@ -13,7 +13,7 @@ /* try in src file directory */ if ((file = open_file_same_dir( pFile->included_by, pFile->name, &pFile->filename ))) return file; -@@ -2906,6 +2909,14 @@ static void output_source_svg( struct ma +@@ -2930,6 +2933,14 @@ static void output_source_svg( struct ma if (images[i]) { diff -Nru wine-development-5.8/debian/patches/generate/request.patch wine-development-5.9/debian/patches/generate/request.patch --- wine-development-5.8/debian/patches/generate/request.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/generate/request.patch 2021-05-04 03:47:51.000000000 +0000 @@ -18,7 +18,7 @@ - if (/^\#define SERVER_PROTOCOL_VERSION (\d+)/) { $protocol = $1; last; } - } - close SERVER_PROT; -+ my $protocol = 601; ++ my $protocol = 602; return $protocol; } @@ -54,7 +54,7 @@ DECL_HANDLER(new_process); DECL_HANDLER(exec_process); -@@ -2445,9 +2445,8 @@ C_ASSERT( sizeof(struct suspend_process_ +@@ -2446,9 +2446,8 @@ C_ASSERT( sizeof(struct suspend_process_ C_ASSERT( FIELD_OFFSET(struct resume_process_request, handle) == 12 ); C_ASSERT( sizeof(struct resume_process_request) == 16 ); @@ -80,7 +80,7 @@ static void dump_new_process_request( const struct new_process_request *req ) { -@@ -5663,8 +5664,7 @@ static const struct +@@ -5664,8 +5665,7 @@ static const struct { NULL, 0 } }; diff -Nru wine-development-5.8/debian/patches/generate/vulkan.patch wine-development-5.9/debian/patches/generate/vulkan.patch --- wine-development-5.8/debian/patches/generate/vulkan.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/generate/vulkan.patch 2021-05-04 03:47:51.000000000 +0000 @@ -82,7 +82,7 @@ --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c -@@ -5356,9 +5356,9 @@ const char *wined3d_debug_vkresult(VkRes +@@ -5336,9 +5336,9 @@ const char *wined3d_debug_vkresult(VkRes switch (vr) { #define WINED3D_TO_STR(x) case x: return #x diff -Nru wine-development-5.8/debian/patches/series wine-development-5.9/debian/patches/series --- wine-development-5.8/debian/patches/series 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/series 2021-05-04 03:47:51.000000000 +0000 @@ -42,6 +42,6 @@ warnings/format-overflow.patch warnings/strcpy-overflow.patch warnings/incorrect-bounds.patch -warnings/argument-promotion.patch +# warnings/argument-promotion.patch # probably fixed??? warnings/discarded-qualifiers.patch warnings/uninitialized-variables.patch diff -Nru wine-development-5.8/debian/patches/system/zlib.patch wine-development-5.9/debian/patches/system/zlib.patch --- wine-development-5.8/debian/patches/system/zlib.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/system/zlib.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/tools/makedep.c +++ b/tools/makedep.c -@@ -1554,14 +1554,6 @@ static struct file *open_include_file( c +@@ -1556,14 +1556,6 @@ static struct file *open_include_file( c } } diff -Nru wine-development-5.8/debian/patches/warnings/arm64-excess-precision.patch wine-development-5.9/debian/patches/warnings/arm64-excess-precision.patch --- wine-development-5.8/debian/patches/warnings/arm64-excess-precision.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/warnings/arm64-excess-precision.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,15 +3,14 @@ --- a/configure.ac +++ b/configure.ac -@@ -2039,6 +2039,11 @@ then - WINE_TRY_CFLAGS([-fno-stack-protector]) - WINE_TRY_CFLAGS([-fno-strict-aliasing]) - WINE_TRY_CFLAGS([-fexcess-precision=standard],[AC_SUBST(EXCESS_PRECISION_CFLAGS,"-fexcess-precision=standard")]) +@@ -2067,6 +2067,10 @@ then + WINE_TRY_CFLAGS([-fexcess-precision=standard],[AC_SUBST(EXCESS_PRECISION_CFLAGS,"-fexcess-precision=standard")]) + fi + ++ case $host_cpu in ++ *aarch64*) EXCESS_PRECISION_CFLAGS="" ;; ++ esac + -+case $host_cpu in -+ *aarch64*) EXCESS_PRECISION_CFLAGS="" ;; -+esac -+ - WINE_TRY_CFLAGS([-Wdeclaration-after-statement]) - WINE_TRY_CFLAGS([-Wempty-body]) - WINE_TRY_CFLAGS([-Wignored-qualifiers]) + dnl Check for noisy string.h + WINE_TRY_CFLAGS([-Wpointer-arith], + [saved_string_h_CFLAGS=$CFLAGS diff -Nru wine-development-5.8/debian/patches/warnings/bison.patch wine-development-5.9/debian/patches/warnings/bison.patch --- wine-development-5.8/debian/patches/warnings/bison.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/warnings/bison.patch 2021-05-04 03:47:51.000000000 +0000 @@ -3,7 +3,7 @@ --- a/tools/makedep.c +++ b/tools/makedep.c -@@ -2666,7 +2666,7 @@ static void output_source_y( struct make +@@ -2687,7 +2687,7 @@ static void output_source_y( struct make if (find_include_file( make, header )) { output( "%s: %s\n", obj_dir_path( make, header ), source->filename ); @@ -12,7 +12,7 @@ bison, obj, obj_dir_path( make, obj ), source->filename ); output( "%s.tab.c: %s %s\n", obj_dir_path( make, obj ), source->filename, obj_dir_path( make, header )); -@@ -2674,7 +2674,7 @@ static void output_source_y( struct make +@@ -2695,7 +2695,7 @@ static void output_source_y( struct make } else output( "%s.tab.c: %s\n", obj, source->filename ); diff -Nru wine-development-5.8/debian/patches/warnings/uninitialized-variables.patch wine-development-5.9/debian/patches/warnings/uninitialized-variables.patch --- wine-development-5.8/debian/patches/warnings/uninitialized-variables.patch 2021-05-01 22:38:12.000000000 +0000 +++ wine-development-5.9/debian/patches/warnings/uninitialized-variables.patch 2021-05-04 03:47:51.000000000 +0000 @@ -27,7 +27,7 @@ if (format->type == FORMAT_ARGBF16) --- a/dlls/ntdll/locale.c +++ b/dlls/ntdll/locale.c -@@ -2322,7 +2322,7 @@ NTSTATUS WINAPI RtlIdnToUnicode( DWORD f +@@ -2298,7 +2298,7 @@ NTSTATUS WINAPI RtlIdnToUnicode( DWORD f int i, buflen, start, end, out_label, out = 0; NTSTATUS status; UINT buffer[64]; @@ -93,7 +93,7 @@ if (!desc) return E_INVALIDARG; --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c -@@ -2670,6 +2670,10 @@ static void check_fbo_compat(struct wine +@@ -2651,6 +2651,10 @@ static void check_fbo_compat(struct wine case WINED3D_GL_RES_TYPE_COUNT: color = 0; break; @@ -104,28 +104,6 @@ } checkGLcall("Post-pixelshader blending check"); ---- a/dlls/devenum/createdevenum.c -+++ b/dlls/devenum/createdevenum.c -@@ -374,7 +374,7 @@ static void write_filter_data(IPropertyB - HRESULT hr; - - hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IAMFilterData, (void **)&fildata); -- if (FAILED(hr)) goto cleanup; -+ if (FAILED(hr)) goto cleanup2; - - hr = IAMFilterData_CreateFilterData(fildata, rgf, &data, &size); - if (FAILED(hr)) goto cleanup; -@@ -395,8 +395,9 @@ static void write_filter_data(IPropertyB - if (FAILED(hr)) goto cleanup; - - cleanup: -- VariantClear(&var); - CoTaskMemFree(data); -+cleanup2: -+ VariantClear(&var); - IAMFilterData_Release(fildata); - } - --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -1853,7 +1853,7 @@ BOOL WINAPI SystemParametersInfoW( UINT @@ -242,7 +220,7 @@ if(ts64.tv_sec != (MSVCRT___time32_t)ts64.tv_sec) --- a/dlls/mf/session.c +++ b/dlls/mf/session.c -@@ -551,7 +551,7 @@ static void session_clear_topologies(str +@@ -580,7 +580,7 @@ static void session_clear_topologies(str static void session_set_topo_status(struct media_session *session, HRESULT status, MF_TOPOSTATUS topo_status) { diff -Nru wine-development-5.8/dlls/advapi32/advapi.c wine-development-5.9/dlls/advapi32/advapi.c --- wine-development-5.8/dlls/advapi32/advapi.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/advapi32/advapi.c 2020-05-22 18:49:34.000000000 +0000 @@ -49,6 +49,7 @@ if (!len) return FALSE; if ((ret = (len < *size))) len++; + else SetLastError( ERROR_INSUFFICIENT_BUFFER ); *size = len; return ret; } @@ -64,6 +65,7 @@ if (!len) return FALSE; if ((ret = (len < *size))) len++; + else SetLastError( ERROR_INSUFFICIENT_BUFFER ); *size = len; return ret; } diff -Nru wine-development-5.8/dlls/advapi32/tests/security.c wine-development-5.9/dlls/advapi32/tests/security.c --- wine-development-5.8/dlls/advapi32/tests/security.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/advapi32/tests/security.c 2020-05-22 18:49:34.000000000 +0000 @@ -5099,6 +5099,7 @@ ok(buffer_len == required_len || broken(buffer_len == required_len / sizeof(WCHAR)), /* XP+ */ "Outputted buffer length was %u\n", buffer_len); + ok(GetLastError() == 0xdeadbeef, "Last error was %u\n", GetLastError()); /* Use the reported buffer size from the last GetUserNameA call and pass * a length that is one less than the required value. */ @@ -5168,6 +5169,7 @@ ok(ret == TRUE, "GetUserNameW returned %d, last error %u\n", ret, GetLastError()); ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n"); ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len); + ok(GetLastError() == 0xdeadbeef, "Last error was %u\n", GetLastError()); /* GetUserNameW on XP and newer writes a truncated portion of the username string to the buffer. */ SetLastError(0xdeadbeef); diff -Nru wine-development-5.8/dlls/advpack/install.c wine-development-5.9/dlls/advpack/install.c --- wine-development-5.8/dlls/advpack/install.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/advpack/install.c 2020-05-22 18:49:34.000000000 +0000 @@ -677,8 +677,15 @@ ZeroMemory(&info, sizeof(ADVInfo)); - if (pCab->pszCab && *pCab->pszCab) - FIXME("Cab archive not extracted!\n"); + if ((pCab->pszCab && *pCab->pszCab) && (pCab->pszInf && *pCab->pszInf) && *pCab->szSrcPath) + { + TRACE("pszCab: %s, pszInf: %s, szSrcPath: %s\n", debugstr_w(pCab->pszCab), debugstr_w(pCab->pszInf), + debugstr_w(pCab->szSrcPath)); + + hr = ExtractFilesW(pCab->pszCab, pCab->szSrcPath, 0, pCab->pszInf, NULL, 0); + if (FAILED(hr)) + ERR("Failed to extract .inf file!\n"); + } hr = install_init(pCab->pszInf, pCab->pszSection, pCab->szSrcPath, pCab->dwFlags, &info); if (hr != S_OK) diff -Nru wine-development-5.8/dlls/api-ms-win-crt-convert-l1-1-0/api-ms-win-crt-convert-l1-1-0.spec wine-development-5.9/dlls/api-ms-win-crt-convert-l1-1-0/api-ms-win-crt-convert-l1-1-0.spec --- wine-development-5.8/dlls/api-ms-win-crt-convert-l1-1-0/api-ms-win-crt-convert-l1-1-0.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/api-ms-win-crt-convert-l1-1-0/api-ms-win-crt-convert-l1-1-0.spec 2020-05-22 18:49:34.000000000 +0000 @@ -16,7 +16,7 @@ @ cdecl _fcvt(double long ptr ptr) ucrtbase._fcvt @ cdecl _fcvt_s(ptr long double long ptr ptr) ucrtbase._fcvt_s @ cdecl _gcvt(double long str) ucrtbase._gcvt -@ cdecl _gcvt_s(ptr long double long) ucrtbase._gcvt_s +@ cdecl _gcvt_s(ptr long double long) ucrtbase._gcvt_s @ cdecl _i64toa(int64 ptr long) ucrtbase._i64toa @ cdecl _i64toa_s(int64 ptr long long) ucrtbase._i64toa_s @ cdecl _i64tow(int64 ptr long) ucrtbase._i64tow diff -Nru wine-development-5.8/dlls/api-ms-win-crt-private-l1-1-0/api-ms-win-crt-private-l1-1-0.spec wine-development-5.9/dlls/api-ms-win-crt-private-l1-1-0/api-ms-win-crt-private-l1-1-0.spec --- wine-development-5.8/dlls/api-ms-win-crt-private-l1-1-0/api-ms-win-crt-private-l1-1-0.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/api-ms-win-crt-private-l1-1-0/api-ms-win-crt-private-l1-1-0.spec 2020-05-22 18:49:34.000000000 +0000 @@ -66,313 +66,313 @@ @ cdecl -arch=i386 _local_unwind2(ptr long) ucrtbase._local_unwind2 @ cdecl -arch=i386 _local_unwind4(ptr ptr long) ucrtbase._local_unwind4 @ cdecl -arch=i386 _longjmpex(ptr long) ucrtbase._longjmpex -@ stub _o__CIacos -@ stub _o__CIasin -@ stub _o__CIatan -@ stub _o__CIatan2 -@ stub _o__CIcos -@ stub _o__CIcosh -@ stub _o__CIexp -@ stub _o__CIfmod -@ stub _o__CIlog -@ stub _o__CIlog10 -@ stub _o__CIpow -@ stub _o__CIsin -@ stub _o__CIsinh -@ stub _o__CIsqrt -@ stub _o__CItan -@ stub _o__CItanh -@ stub _o__Getdays -@ stub _o__Getmonths -@ stub _o__Gettnames -@ stub _o__Strftime -@ stub _o__W_Getdays -@ stub _o__W_Getmonths -@ stub _o__W_Gettnames -@ stub _o__Wcsftime -@ stub _o____lc_codepage_func -@ stub _o____lc_collate_cp_func -@ stub _o____lc_locale_name_func -@ stub _o____mb_cur_max_func +@ cdecl -arch=i386 _o__CIacos() ucrtbase._o__CIacos +@ cdecl -arch=i386 _o__CIasin() ucrtbase._o__CIasin +@ cdecl -arch=i386 _o__CIatan() ucrtbase._o__CIatan +@ cdecl -arch=i386 _o__CIatan2() ucrtbase._o__CIatan2 +@ cdecl -arch=i386 _o__CIcos() ucrtbase._o__CIcos +@ cdecl -arch=i386 _o__CIcosh() ucrtbase._o__CIcosh +@ cdecl -arch=i386 _o__CIexp() ucrtbase._o__CIexp +@ cdecl -arch=i386 _o__CIfmod() ucrtbase._o__CIfmod +@ cdecl -arch=i386 _o__CIlog() ucrtbase._o__CIlog +@ cdecl -arch=i386 _o__CIlog10() ucrtbase._o__CIlog10 +@ cdecl -arch=i386 _o__CIpow() ucrtbase._o__CIpow +@ cdecl -arch=i386 _o__CIsin() ucrtbase._o__CIsin +@ cdecl -arch=i386 _o__CIsinh() ucrtbase._o__CIsinh +@ cdecl -arch=i386 _o__CIsqrt() ucrtbase._o__CIsqrt +@ cdecl -arch=i386 _o__CItan() ucrtbase._o__CItan +@ cdecl -arch=i386 _o__CItanh() ucrtbase._o__CItanh +@ cdecl _o__Getdays() ucrtbase._o__Getdays +@ cdecl _o__Getmonths() ucrtbase._o__Getmonths +@ cdecl _o__Gettnames() ucrtbase._o__Gettnames +@ cdecl _o__Strftime(ptr long str ptr ptr) ucrtbase._o__Strftime +@ cdecl _o__W_Getdays() ucrtbase._o__W_Getdays +@ cdecl _o__W_Getmonths() ucrtbase._o__W_Getmonths +@ cdecl _o__W_Gettnames() ucrtbase._o__W_Gettnames +@ cdecl _o__Wcsftime(ptr long wstr ptr ptr) ucrtbase._o__Wcsftime +@ cdecl _o____lc_codepage_func() ucrtbase._o____lc_codepage_func +@ cdecl _o____lc_collate_cp_func() ucrtbase._o____lc_collate_cp_func +@ cdecl _o____lc_locale_name_func() ucrtbase._o____lc_locale_name_func +@ cdecl _o____mb_cur_max_func() ucrtbase._o____mb_cur_max_func @ cdecl _o___acrt_iob_func(long) ucrtbase._o___acrt_iob_func -@ stub _o___conio_common_vcprintf +@ cdecl _o___conio_common_vcprintf(int64 str ptr ptr) ucrtbase._o___conio_common_vcprintf @ stub _o___conio_common_vcprintf_p @ stub _o___conio_common_vcprintf_s @ stub _o___conio_common_vcscanf -@ stub _o___conio_common_vcwprintf +@ cdecl _o___conio_common_vcwprintf(int64 wstr ptr ptr) ucrtbase._o___conio_common_vcwprintf @ stub _o___conio_common_vcwprintf_p @ stub _o___conio_common_vcwprintf_s @ stub _o___conio_common_vcwscanf -@ stub _o___daylight -@ stub _o___dstbias -@ stub _o___fpe_flt_rounds -@ stub _o___libm_sse2_acos -@ stub _o___libm_sse2_acosf -@ stub _o___libm_sse2_asin -@ stub _o___libm_sse2_asinf -@ stub _o___libm_sse2_atan -@ stub _o___libm_sse2_atan2 -@ stub _o___libm_sse2_atanf -@ stub _o___libm_sse2_cos -@ stub _o___libm_sse2_cosf -@ stub _o___libm_sse2_exp -@ stub _o___libm_sse2_expf -@ stub _o___libm_sse2_log -@ stub _o___libm_sse2_log10 -@ stub _o___libm_sse2_log10f -@ stub _o___libm_sse2_logf -@ stub _o___libm_sse2_pow -@ stub _o___libm_sse2_powf -@ stub _o___libm_sse2_sin -@ stub _o___libm_sse2_sinf -@ stub _o___libm_sse2_tan -@ stub _o___libm_sse2_tanf +@ cdecl _o___daylight() ucrtbase._o___daylight +@ cdecl _o___dstbias() ucrtbase._o___dstbias +@ cdecl _o___fpe_flt_rounds() ucrtbase._o___fpe_flt_rounds +@ cdecl -arch=i386 -norelay _o___libm_sse2_acos() ucrtbase._o___libm_sse2_acos +@ cdecl -arch=i386 -norelay _o___libm_sse2_acosf() ucrtbase._o___libm_sse2_acosf +@ cdecl -arch=i386 -norelay _o___libm_sse2_asin() ucrtbase._o___libm_sse2_asin +@ cdecl -arch=i386 -norelay _o___libm_sse2_asinf() ucrtbase._o___libm_sse2_asinf +@ cdecl -arch=i386 -norelay _o___libm_sse2_atan() ucrtbase._o___libm_sse2_atan +@ cdecl -arch=i386 -norelay _o___libm_sse2_atan2() ucrtbase._o___libm_sse2_atan2 +@ cdecl -arch=i386 -norelay _o___libm_sse2_atanf() ucrtbase._o___libm_sse2_atanf +@ cdecl -arch=i386 -norelay _o___libm_sse2_cos() ucrtbase._o___libm_sse2_cos +@ cdecl -arch=i386 -norelay _o___libm_sse2_cosf() ucrtbase._o___libm_sse2_cosf +@ cdecl -arch=i386 -norelay _o___libm_sse2_exp() ucrtbase._o___libm_sse2_exp +@ cdecl -arch=i386 -norelay _o___libm_sse2_expf() ucrtbase._o___libm_sse2_expf +@ cdecl -arch=i386 -norelay _o___libm_sse2_log() ucrtbase._o___libm_sse2_log +@ cdecl -arch=i386 -norelay _o___libm_sse2_log10() ucrtbase._o___libm_sse2_log10 +@ cdecl -arch=i386 -norelay _o___libm_sse2_log10f() ucrtbase._o___libm_sse2_log10f +@ cdecl -arch=i386 -norelay _o___libm_sse2_logf() ucrtbase._o___libm_sse2_logf +@ cdecl -arch=i386 -norelay _o___libm_sse2_pow() ucrtbase._o___libm_sse2_pow +@ cdecl -arch=i386 -norelay _o___libm_sse2_powf() ucrtbase._o___libm_sse2_powf +@ cdecl -arch=i386 -norelay _o___libm_sse2_sin() ucrtbase._o___libm_sse2_sin +@ cdecl -arch=i386 -norelay _o___libm_sse2_sinf() ucrtbase._o___libm_sse2_sinf +@ cdecl -arch=i386 -norelay _o___libm_sse2_tan() ucrtbase._o___libm_sse2_tan +@ cdecl -arch=i386 -norelay _o___libm_sse2_tanf() ucrtbase._o___libm_sse2_tanf @ cdecl _o___p___argc() ucrtbase._o___p___argc -@ stub _o___p___argv +@ cdecl _o___p___argv() ucrtbase._o___p___argv @ cdecl _o___p___wargv() ucrtbase._o___p___wargv -@ stub _o___p__acmdln +@ cdecl _o___p__acmdln() ucrtbase._o___p__acmdln @ cdecl _o___p__commode() ucrtbase._o___p__commode -@ stub _o___p__environ -@ stub _o___p__fmode +@ cdecl _o___p__environ() ucrtbase._o___p__environ +@ cdecl _o___p__fmode() ucrtbase._o___p__fmode @ stub _o___p__mbcasemap -@ stub _o___p__mbctype -@ stub _o___p__pgmptr -@ stub _o___p__wcmdln -@ stub _o___p__wenviron -@ stub _o___p__wpgmptr -@ stub _o___pctype_func +@ cdecl _o___p__mbctype() ucrtbase._o___p__mbctype +@ cdecl _o___p__pgmptr() ucrtbase._o___p__pgmptr +@ cdecl _o___p__wcmdln() ucrtbase._o___p__wcmdln +@ cdecl _o___p__wenviron() ucrtbase._o___p__wenviron +@ cdecl _o___p__wpgmptr() ucrtbase._o___p__wpgmptr +@ cdecl _o___pctype_func() ucrtbase._o___pctype_func @ stub _o___pwctype_func -@ stub _o___std_exception_copy +@ cdecl _o___std_exception_copy(ptr ptr) ucrtbase._o___std_exception_copy @ cdecl _o___std_exception_destroy(ptr) ucrtbase._o___std_exception_destroy @ cdecl _o___std_type_info_destroy_list(ptr) ucrtbase._o___std_type_info_destroy_list -@ stub _o___std_type_info_name +@ cdecl _o___std_type_info_name(ptr ptr) ucrtbase._o___std_type_info_name @ cdecl _o___stdio_common_vfprintf(int64 ptr str ptr ptr) ucrtbase._o___stdio_common_vfprintf @ stub _o___stdio_common_vfprintf_p -@ stub _o___stdio_common_vfprintf_s -@ stub _o___stdio_common_vfscanf +@ cdecl _o___stdio_common_vfprintf_s(int64 ptr str ptr ptr) ucrtbase._o___stdio_common_vfprintf_s +@ cdecl _o___stdio_common_vfscanf(int64 ptr str ptr ptr) ucrtbase._o___stdio_common_vfscanf @ cdecl _o___stdio_common_vfwprintf(int64 ptr wstr ptr ptr) ucrtbase._o___stdio_common_vfwprintf @ stub _o___stdio_common_vfwprintf_p -@ stub _o___stdio_common_vfwprintf_s -@ stub _o___stdio_common_vfwscanf +@ cdecl _o___stdio_common_vfwprintf_s(int64 ptr wstr ptr ptr) ucrtbase._o___stdio_common_vfwprintf_s +@ cdecl _o___stdio_common_vfwscanf(int64 ptr wstr ptr ptr) ucrtbase._o___stdio_common_vfwscanf @ cdecl _o___stdio_common_vsnprintf_s(int64 ptr long long str ptr ptr) ucrtbase._o___stdio_common_vsnprintf_s -@ stub _o___stdio_common_vsnwprintf_s +@ cdecl _o___stdio_common_vsnwprintf_s(int64 ptr long long wstr ptr ptr) ucrtbase._o___stdio_common_vsnwprintf_s @ cdecl _o___stdio_common_vsprintf(int64 ptr long str ptr ptr) ucrtbase._o___stdio_common_vsprintf -@ stub _o___stdio_common_vsprintf_p +@ cdecl _o___stdio_common_vsprintf_p(int64 ptr long str ptr ptr) ucrtbase._o___stdio_common_vsprintf_p @ cdecl _o___stdio_common_vsprintf_s(int64 ptr long str ptr ptr) ucrtbase._o___stdio_common_vsprintf_s -@ stub _o___stdio_common_vsscanf +@ cdecl _o___stdio_common_vsscanf(int64 ptr long str ptr ptr) ucrtbase._o___stdio_common_vsscanf @ cdecl _o___stdio_common_vswprintf(int64 ptr long wstr ptr ptr) ucrtbase._o___stdio_common_vswprintf -@ stub _o___stdio_common_vswprintf_p -@ stub _o___stdio_common_vswprintf_s -@ stub _o___stdio_common_vswscanf -@ stub _o___timezone -@ stub _o___tzname -@ stub _o___wcserror -@ stub _o__access -@ stub _o__access_s -@ stub _o__aligned_free -@ stub _o__aligned_malloc -@ stub _o__aligned_msize -@ stub _o__aligned_offset_malloc -@ stub _o__aligned_offset_realloc +@ cdecl _o___stdio_common_vswprintf_p(int64 ptr long wstr ptr ptr) ucrtbase._o___stdio_common_vswprintf_p +@ cdecl _o___stdio_common_vswprintf_s(int64 ptr long wstr ptr ptr) ucrtbase._o___stdio_common_vswprintf_s +@ cdecl _o___stdio_common_vswscanf(int64 ptr long wstr ptr ptr) ucrtbase._o___stdio_common_vswscanf +@ cdecl _o___timezone() ucrtbase._o___timezone +@ cdecl _o___tzname() ucrtbase._o___tzname +@ cdecl _o___wcserror(wstr) ucrtbase._o___wcserror +@ cdecl _o__access(str long) ucrtbase._o__access +@ cdecl _o__access_s(str long) ucrtbase._o__access_s +@ cdecl _o__aligned_free(ptr) ucrtbase._o__aligned_free +@ cdecl _o__aligned_malloc(long long) ucrtbase._o__aligned_malloc +@ cdecl _o__aligned_msize(ptr long long) ucrtbase._o__aligned_msize +@ cdecl _o__aligned_offset_malloc(long long long) ucrtbase._o__aligned_offset_malloc +@ cdecl _o__aligned_offset_realloc(ptr long long long) ucrtbase._o__aligned_offset_realloc @ stub _o__aligned_offset_recalloc -@ stub _o__aligned_realloc +@ cdecl _o__aligned_realloc(ptr long long) ucrtbase._o__aligned_realloc @ stub _o__aligned_recalloc -@ stub _o__atodbl -@ stub _o__atodbl_l -@ stub _o__atof_l -@ stub _o__atoflt -@ stub _o__atoflt_l -@ stub _o__atoi64 -@ stub _o__atoi64_l -@ stub _o__atoi_l -@ stub _o__atol_l -@ stub _o__atoldbl +@ cdecl _o__atodbl(ptr str) ucrtbase._o__atodbl +@ cdecl _o__atodbl_l(ptr str ptr) ucrtbase._o__atodbl_l +@ cdecl _o__atof_l(str ptr) ucrtbase._o__atof_l +@ cdecl _o__atoflt(ptr str) ucrtbase._o__atoflt +@ cdecl _o__atoflt_l(ptr str ptr) ucrtbase._o__atoflt_l +@ cdecl -ret64 _o__atoi64(str) ucrtbase._o__atoi64 +@ cdecl -ret64 _o__atoi64_l(str ptr) ucrtbase._o__atoi64_l +@ cdecl _o__atoi_l(str ptr) ucrtbase._o__atoi_l +@ cdecl _o__atol_l(str ptr) ucrtbase._o__atol_l +@ cdecl _o__atoldbl(ptr str) ucrtbase._o__atoldbl @ stub _o__atoldbl_l -@ stub _o__atoll_l -@ stub _o__beep -@ stub _o__beginthread -@ stub _o__beginthreadex -@ stub _o__cabs -@ stub _o__callnewh -@ stub _o__calloc_base -@ stub _o__cexit -@ stub _o__cgets +@ cdecl -ret64 _o__atoll_l(str ptr) ucrtbase._o__atoll_l +@ cdecl _o__beep(long long) ucrtbase._o__beep +@ cdecl _o__beginthread(ptr long ptr) ucrtbase._o__beginthread +@ cdecl _o__beginthreadex(ptr long ptr ptr long ptr) ucrtbase._o__beginthreadex +@ cdecl _o__cabs(long) ucrtbase._o__cabs +@ cdecl _o__callnewh(long) ucrtbase._o__callnewh +@ cdecl _o__calloc_base(long long) ucrtbase._o__calloc_base +@ cdecl _o__cexit() ucrtbase._o__cexit +@ cdecl _o__cgets(ptr) ucrtbase._o__cgets @ stub _o__cgets_s @ stub _o__cgetws @ stub _o__cgetws_s -@ stub _o__chdir -@ stub _o__chdrive -@ stub _o__chmod -@ stub _o__chsize -@ stub _o__chsize_s -@ stub _o__close -@ stub _o__commit +@ cdecl _o__chdir(str) ucrtbase._o__chdir +@ cdecl _o__chdrive(long) ucrtbase._o__chdrive +@ cdecl _o__chmod(str long) ucrtbase._o__chmod +@ cdecl _o__chsize(long long) ucrtbase._o__chsize +@ cdecl _o__chsize_s(long int64) ucrtbase._o__chsize_s +@ cdecl _o__close(long) ucrtbase._o__close +@ cdecl _o__commit(long) ucrtbase._o__commit @ cdecl _o__configthreadlocale(long) ucrtbase._o__configthreadlocale -@ stub _o__configure_narrow_argv +@ cdecl _o__configure_narrow_argv(long) ucrtbase._o__configure_narrow_argv @ cdecl _o__configure_wide_argv(long) ucrtbase._o__configure_wide_argv @ cdecl _o__controlfp_s(ptr long long) ucrtbase._o__controlfp_s -@ stub _o__cputs -@ stub _o__cputws -@ stub _o__creat -@ stub _o__create_locale +@ cdecl _o__cputs(str) ucrtbase._o__cputs +@ cdecl _o__cputws(wstr) ucrtbase._o__cputws +@ cdecl _o__creat(str long) ucrtbase._o__creat +@ cdecl _o__create_locale(long str) ucrtbase._o__create_locale @ cdecl _o__crt_atexit(ptr) ucrtbase._o__crt_atexit -@ stub _o__ctime32_s -@ stub _o__ctime64_s -@ stub _o__cwait +@ cdecl _o__ctime32_s(str long ptr) ucrtbase._o__ctime32_s +@ cdecl _o__ctime64_s(str long ptr) ucrtbase._o__ctime64_s +@ cdecl _o__cwait(ptr long long) ucrtbase._o__cwait @ stub _o__d_int -@ stub _o__dclass -@ stub _o__difftime32 -@ stub _o__difftime64 +@ cdecl _o__dclass(double) ucrtbase._o__dclass +@ cdecl _o__difftime32(long long) ucrtbase._o__difftime32 +@ cdecl _o__difftime64(int64 int64) ucrtbase._o__difftime64 @ stub _o__dlog @ stub _o__dnorm -@ stub _o__dpcomp +@ cdecl _o__dpcomp(double double) ucrtbase._o__dpcomp @ stub _o__dpoly @ stub _o__dscale -@ stub _o__dsign +@ cdecl _o__dsign(double) ucrtbase._o__dsign @ stub _o__dsin -@ stub _o__dtest +@ cdecl _o__dtest(ptr) ucrtbase._o__dtest @ stub _o__dunscale -@ stub _o__dup -@ stub _o__dup2 -@ stub _o__dupenv_s -@ stub _o__ecvt -@ stub _o__ecvt_s -@ stub _o__endthread -@ stub _o__endthreadex -@ stub _o__eof +@ cdecl _o__dup(long) ucrtbase._o__dup +@ cdecl _o__dup2(long long) ucrtbase._o__dup2 +@ cdecl _o__dupenv_s(ptr ptr str) ucrtbase._o__dupenv_s +@ cdecl _o__ecvt(double long ptr ptr) ucrtbase._o__ecvt +@ cdecl _o__ecvt_s(str long double long ptr ptr) ucrtbase._o__ecvt_s +@ cdecl _o__endthread() ucrtbase._o__endthread +@ cdecl _o__endthreadex(long) ucrtbase._o__endthreadex +@ cdecl _o__eof(long) ucrtbase._o__eof @ cdecl _o__errno() ucrtbase._o__errno -@ stub _o__except1 +@ cdecl _o__except1(long long double double long ptr) ucrtbase._o__except1 @ cdecl _o__execute_onexit_table(ptr) ucrtbase._o__execute_onexit_table -@ stub _o__execv -@ stub _o__execve -@ stub _o__execvp -@ stub _o__execvpe -@ stub _o__exit -@ stub _o__expand -@ stub _o__fclose_nolock -@ stub _o__fcloseall -@ stub _o__fcvt -@ stub _o__fcvt_s +@ cdecl _o__execv(str ptr) ucrtbase._o__execv +@ cdecl _o__execve(str ptr ptr) ucrtbase._o__execve +@ cdecl _o__execvp(str ptr) ucrtbase._o__execvp +@ cdecl _o__execvpe(str ptr ptr) ucrtbase._o__execvpe +@ cdecl _o__exit(long) ucrtbase._o__exit +@ cdecl _o__expand(ptr long) ucrtbase._o__expand +@ cdecl _o__fclose_nolock(ptr) ucrtbase._o__fclose_nolock +@ cdecl _o__fcloseall() ucrtbase._o__fcloseall +@ cdecl _o__fcvt(double long ptr ptr) ucrtbase._o__fcvt +@ cdecl _o__fcvt_s(ptr long double long ptr ptr) ucrtbase._o__fcvt_s @ stub _o__fd_int -@ stub _o__fdclass +@ cdecl _o__fdclass(float) ucrtbase._o__fdclass @ stub _o__fdexp @ stub _o__fdlog -@ stub _o__fdopen -@ stub _o__fdpcomp +@ cdecl _o__fdopen(long str) ucrtbase._o__fdopen +@ cdecl _o__fdpcomp(float float) ucrtbase._o__fdpcomp @ stub _o__fdpoly @ stub _o__fdscale -@ stub _o__fdsign +@ cdecl _o__fdsign(float) ucrtbase._o__fdsign @ stub _o__fdsin -@ stub _o__fflush_nolock -@ stub _o__fgetc_nolock -@ stub _o__fgetchar -@ stub _o__fgetwc_nolock -@ stub _o__fgetwchar -@ stub _o__filelength -@ stub _o__filelengthi64 -@ stub _o__fileno -@ stub _o__findclose -@ stub _o__findfirst32 +@ cdecl _o__fflush_nolock(ptr) ucrtbase._o__fflush_nolock +@ cdecl _o__fgetc_nolock(ptr) ucrtbase._o__fgetc_nolock +@ cdecl _o__fgetchar() ucrtbase._o__fgetchar +@ cdecl _o__fgetwc_nolock(ptr) ucrtbase._o__fgetwc_nolock +@ cdecl _o__fgetwchar() ucrtbase._o__fgetwchar +@ cdecl _o__filelength(long) ucrtbase._o__filelength +@ cdecl -ret64 _o__filelengthi64(long) ucrtbase._o__filelengthi64 +@ cdecl _o__fileno(ptr) ucrtbase._o__fileno +@ cdecl _o__findclose(long) ucrtbase._o__findclose +@ cdecl _o__findfirst32(str ptr) ucrtbase._o__findfirst32 @ stub _o__findfirst32i64 -@ stub _o__findfirst64 -@ stub _o__findfirst64i32 -@ stub _o__findnext32 +@ cdecl _o__findfirst64(str ptr) ucrtbase._o__findfirst64 +@ cdecl _o__findfirst64i32(str ptr) ucrtbase._o__findfirst64i32 +@ cdecl _o__findnext32(long ptr) ucrtbase._o__findnext32 @ stub _o__findnext32i64 -@ stub _o__findnext64 -@ stub _o__findnext64i32 -@ stub _o__flushall +@ cdecl _o__findnext64(long ptr) ucrtbase._o__findnext64 +@ cdecl _o__findnext64i32(long ptr) ucrtbase._o__findnext64i32 +@ cdecl _o__flushall() ucrtbase._o__flushall @ cdecl _o__fpclass(double) ucrtbase._o__fpclass @ stub _o__fpclassf -@ stub _o__fputc_nolock -@ stub _o__fputchar -@ stub _o__fputwc_nolock -@ stub _o__fputwchar -@ stub _o__fread_nolock -@ stub _o__fread_nolock_s -@ stub _o__free_base -@ stub _o__free_locale -@ stub _o__fseek_nolock -@ stub _o__fseeki64 -@ stub _o__fseeki64_nolock -@ stub _o__fsopen -@ stub _o__fstat32 -@ stub _o__fstat32i64 -@ stub _o__fstat64 -@ stub _o__fstat64i32 -@ stub _o__ftell_nolock -@ stub _o__ftelli64 -@ stub _o__ftelli64_nolock -@ stub _o__ftime32 -@ stub _o__ftime32_s -@ stub _o__ftime64 -@ stub _o__ftime64_s -@ stub _o__fullpath -@ stub _o__futime32 -@ stub _o__futime64 -@ stub _o__fwrite_nolock -@ stub _o__gcvt -@ stub _o__gcvt_s -@ stub _o__get_daylight -@ stub _o__get_doserrno -@ stub _o__get_dstbias -@ stub _o__get_errno -@ stub _o__get_fmode -@ stub _o__get_heap_handle -@ stub _o__get_initial_narrow_environment +@ cdecl _o__fputc_nolock(long ptr) ucrtbase._o__fputc_nolock +@ cdecl _o__fputchar(long) ucrtbase._o__fputchar +@ cdecl _o__fputwc_nolock(long ptr) ucrtbase._o__fputwc_nolock +@ cdecl _o__fputwchar(long) ucrtbase._o__fputwchar +@ cdecl _o__fread_nolock(ptr long long ptr) ucrtbase._o__fread_nolock +@ cdecl _o__fread_nolock_s(ptr long long long ptr) ucrtbase._o__fread_nolock_s +@ cdecl _o__free_base(ptr) ucrtbase._o__free_base +@ cdecl _o__free_locale(ptr) ucrtbase._o__free_locale +@ cdecl _o__fseek_nolock(ptr long long) ucrtbase._o__fseek_nolock +@ cdecl _o__fseeki64(ptr int64 long) ucrtbase._o__fseeki64 +@ cdecl _o__fseeki64_nolock(ptr int64 long) ucrtbase._o__fseeki64_nolock +@ cdecl _o__fsopen(str str long) ucrtbase._o__fsopen +@ cdecl _o__fstat32(long ptr) ucrtbase._o__fstat32 +@ cdecl _o__fstat32i64(long ptr) ucrtbase._o__fstat32i64 +@ cdecl _o__fstat64(long ptr) ucrtbase._o__fstat64 +@ cdecl _o__fstat64i32(long ptr) ucrtbase._o__fstat64i32 +@ cdecl _o__ftell_nolock(ptr) ucrtbase._o__ftell_nolock +@ cdecl -ret64 _o__ftelli64(ptr) ucrtbase._o__ftelli64 +@ cdecl -ret64 _o__ftelli64_nolock(ptr) ucrtbase._o__ftelli64_nolock +@ cdecl _o__ftime32(ptr) ucrtbase._o__ftime32 +@ cdecl _o__ftime32_s(ptr) ucrtbase._o__ftime32_s +@ cdecl _o__ftime64(ptr) ucrtbase._o__ftime64 +@ cdecl _o__ftime64_s(ptr) ucrtbase._o__ftime64_s +@ cdecl _o__fullpath(ptr str long) ucrtbase._o__fullpath +@ cdecl _o__futime32(long ptr) ucrtbase._o__futime32 +@ cdecl _o__futime64(long ptr) ucrtbase._o__futime64 +@ cdecl _o__fwrite_nolock(ptr long long ptr) ucrtbase._o__fwrite_nolock +@ cdecl _o__gcvt(double long str) ucrtbase._o__gcvt +@ cdecl _o__gcvt_s(ptr long double long) ucrtbase._o__gcvt_s +@ cdecl _o__get_daylight(ptr) ucrtbase._o__get_daylight +@ cdecl _o__get_doserrno(ptr) ucrtbase._o__get_doserrno +@ cdecl _o__get_dstbias(ptr) ucrtbase._o__get_dstbias +@ cdecl _o__get_errno(ptr) ucrtbase._o__get_errno +@ cdecl _o__get_fmode(ptr) ucrtbase._o__get_fmode +@ cdecl _o__get_heap_handle() ucrtbase._o__get_heap_handle +@ cdecl _o__get_initial_narrow_environment() ucrtbase._o__get_initial_narrow_environment @ cdecl _o__get_initial_wide_environment() ucrtbase._o__get_initial_wide_environment -@ stub _o__get_invalid_parameter_handler -@ stub _o__get_narrow_winmain_command_line -@ stub _o__get_osfhandle -@ stub _o__get_pgmptr -@ stub _o__get_stream_buffer_pointers -@ stub _o__get_terminate -@ stub _o__get_thread_local_invalid_parameter_handler -@ stub _o__get_timezone -@ stub _o__get_tzname -@ stub _o__get_wide_winmain_command_line -@ stub _o__get_wpgmptr -@ stub _o__getc_nolock -@ stub _o__getch -@ stub _o__getch_nolock -@ stub _o__getche -@ stub _o__getche_nolock -@ stub _o__getcwd -@ stub _o__getdcwd -@ stub _o__getdiskfree -@ stub _o__getdllprocaddr -@ stub _o__getdrive -@ stub _o__getdrives -@ stub _o__getmbcp +@ cdecl _o__get_invalid_parameter_handler() ucrtbase._o__get_invalid_parameter_handler +@ cdecl _o__get_narrow_winmain_command_line() ucrtbase._o__get_narrow_winmain_command_line +@ cdecl _o__get_osfhandle(long) ucrtbase._o__get_osfhandle +@ cdecl _o__get_pgmptr(ptr) ucrtbase._o__get_pgmptr +@ cdecl _o__get_stream_buffer_pointers(ptr ptr ptr ptr) ucrtbase._o__get_stream_buffer_pointers +@ cdecl _o__get_terminate() ucrtbase._o__get_terminate +@ cdecl _o__get_thread_local_invalid_parameter_handler() ucrtbase._o__get_thread_local_invalid_parameter_handler +@ cdecl _o__get_timezone(ptr) ucrtbase._o__get_timezone +@ cdecl _o__get_tzname(ptr str long long) ucrtbase._o__get_tzname +@ cdecl _o__get_wide_winmain_command_line() ucrtbase._o__get_wide_winmain_command_line +@ cdecl _o__get_wpgmptr(ptr) ucrtbase._o__get_wpgmptr +@ cdecl _o__getc_nolock(ptr) ucrtbase._o__getc_nolock +@ cdecl _o__getch() ucrtbase._o__getch +@ cdecl _o__getch_nolock() ucrtbase._o__getch_nolock +@ cdecl _o__getche() ucrtbase._o__getche +@ cdecl _o__getche_nolock() ucrtbase._o__getche_nolock +@ cdecl _o__getcwd(str long) ucrtbase._o__getcwd +@ cdecl _o__getdcwd(long str long) ucrtbase._o__getdcwd +@ cdecl _o__getdiskfree(long ptr) ucrtbase._o__getdiskfree +@ cdecl _o__getdllprocaddr(long str long) ucrtbase._o__getdllprocaddr +@ cdecl _o__getdrive() ucrtbase._o__getdrive +@ cdecl _o__getdrives() ucrtbase._o__getdrives +@ cdecl _o__getmbcp() ucrtbase._o__getmbcp @ stub _o__getsystime -@ stub _o__getw -@ stub _o__getwc_nolock -@ stub _o__getwch -@ stub _o__getwch_nolock -@ stub _o__getwche -@ stub _o__getwche_nolock -@ stub _o__getws +@ cdecl _o__getw(ptr) ucrtbase._o__getw +@ cdecl _o__getwc_nolock(ptr) ucrtbase._o__getwc_nolock +@ cdecl _o__getwch() ucrtbase._o__getwch +@ cdecl _o__getwch_nolock() ucrtbase._o__getwch_nolock +@ cdecl _o__getwche() ucrtbase._o__getwche +@ cdecl _o__getwche_nolock() ucrtbase._o__getwche_nolock +@ cdecl _o__getws(ptr) ucrtbase._o__getws @ stub _o__getws_s -@ stub _o__gmtime32 -@ stub _o__gmtime32_s -@ stub _o__gmtime64 -@ stub _o__gmtime64_s -@ stub _o__heapchk -@ stub _o__heapmin -@ stub _o__hypot -@ stub _o__hypotf -@ stub _o__i64toa -@ stub _o__i64toa_s -@ stub _o__i64tow -@ stub _o__i64tow_s -@ stub _o__initialize_narrow_environment +@ cdecl _o__gmtime32(ptr) ucrtbase._o__gmtime32 +@ cdecl _o__gmtime32_s(ptr ptr) ucrtbase._o__gmtime32_s +@ cdecl _o__gmtime64(ptr) ucrtbase._o__gmtime64 +@ cdecl _o__gmtime64_s(ptr ptr) ucrtbase._o__gmtime64_s +@ cdecl _o__heapchk() ucrtbase._o__heapchk +@ cdecl _o__heapmin() ucrtbase._o__heapmin +@ cdecl _o__hypot(double double) ucrtbase._o__hypot +@ cdecl _o__hypotf(float float) ucrtbase._o__hypotf +@ cdecl _o__i64toa(int64 ptr long) ucrtbase._o__i64toa +@ cdecl _o__i64toa_s(int64 ptr long long) ucrtbase._o__i64toa_s +@ cdecl _o__i64tow(int64 ptr long) ucrtbase._o__i64tow +@ cdecl _o__i64tow_s(int64 ptr long long) ucrtbase._o__i64tow_s +@ cdecl _o__initialize_narrow_environment() ucrtbase._o__initialize_narrow_environment @ cdecl _o__initialize_onexit_table(ptr) ucrtbase._o__initialize_onexit_table @ cdecl _o__initialize_wide_environment() ucrtbase._o__initialize_wide_environment -@ stub _o__invalid_parameter_noinfo -@ stub _o__invalid_parameter_noinfo_noreturn -@ stub _o__isatty -@ stub _o__isctype -@ stub _o__isctype_l -@ stub _o__isleadbyte_l +@ cdecl _o__invalid_parameter_noinfo() ucrtbase._o__invalid_parameter_noinfo +@ cdecl _o__invalid_parameter_noinfo_noreturn() ucrtbase._o__invalid_parameter_noinfo_noreturn +@ cdecl _o__isatty(long) ucrtbase._o__isatty +@ cdecl _o__isctype(long long) ucrtbase._o__isctype +@ cdecl _o__isctype_l(long long ptr) ucrtbase._o__isctype_l +@ cdecl _o__isleadbyte_l(long ptr) ucrtbase._o__isleadbyte_l @ stub _o__ismbbalnum @ stub _o__ismbbalnum_l @ stub _o__ismbbalpha @@ -383,797 +383,797 @@ @ stub _o__ismbbgraph_l @ stub _o__ismbbkalnum @ stub _o__ismbbkalnum_l -@ stub _o__ismbbkana +@ cdecl _o__ismbbkana(long) ucrtbase._o__ismbbkana @ stub _o__ismbbkana_l @ stub _o__ismbbkprint @ stub _o__ismbbkprint_l @ stub _o__ismbbkpunct @ stub _o__ismbbkpunct_l -@ stub _o__ismbblead -@ stub _o__ismbblead_l +@ cdecl _o__ismbblead(long) ucrtbase._o__ismbblead +@ cdecl _o__ismbblead_l(long ptr) ucrtbase._o__ismbblead_l @ stub _o__ismbbprint @ stub _o__ismbbprint_l @ stub _o__ismbbpunct @ stub _o__ismbbpunct_l -@ stub _o__ismbbtrail -@ stub _o__ismbbtrail_l -@ stub _o__ismbcalnum +@ cdecl _o__ismbbtrail(long) ucrtbase._o__ismbbtrail +@ cdecl _o__ismbbtrail_l(long ptr) ucrtbase._o__ismbbtrail_l +@ cdecl _o__ismbcalnum(long) ucrtbase._o__ismbcalnum @ stub _o__ismbcalnum_l -@ stub _o__ismbcalpha +@ cdecl _o__ismbcalpha(long) ucrtbase._o__ismbcalpha @ stub _o__ismbcalpha_l @ stub _o__ismbcblank @ stub _o__ismbcblank_l -@ stub _o__ismbcdigit +@ cdecl _o__ismbcdigit(long) ucrtbase._o__ismbcdigit @ stub _o__ismbcdigit_l -@ stub _o__ismbcgraph +@ cdecl _o__ismbcgraph(long) ucrtbase._o__ismbcgraph @ stub _o__ismbcgraph_l -@ stub _o__ismbchira +@ cdecl _o__ismbchira(long) ucrtbase._o__ismbchira @ stub _o__ismbchira_l -@ stub _o__ismbckata +@ cdecl _o__ismbckata(long) ucrtbase._o__ismbckata @ stub _o__ismbckata_l -@ stub _o__ismbcl0 -@ stub _o__ismbcl0_l -@ stub _o__ismbcl1 -@ stub _o__ismbcl1_l -@ stub _o__ismbcl2 -@ stub _o__ismbcl2_l -@ stub _o__ismbclegal -@ stub _o__ismbclegal_l +@ cdecl _o__ismbcl0(long) ucrtbase._o__ismbcl0 +@ cdecl _o__ismbcl0_l(long ptr) ucrtbase._o__ismbcl0_l +@ cdecl _o__ismbcl1(long) ucrtbase._o__ismbcl1 +@ cdecl _o__ismbcl1_l(long ptr) ucrtbase._o__ismbcl1_l +@ cdecl _o__ismbcl2(long) ucrtbase._o__ismbcl2 +@ cdecl _o__ismbcl2_l(long ptr) ucrtbase._o__ismbcl2_l +@ cdecl _o__ismbclegal(long) ucrtbase._o__ismbclegal +@ cdecl _o__ismbclegal_l(long ptr) ucrtbase._o__ismbclegal_l @ stub _o__ismbclower @ stub _o__ismbclower_l -@ stub _o__ismbcprint +@ cdecl _o__ismbcprint(long) ucrtbase._o__ismbcprint @ stub _o__ismbcprint_l -@ stub _o__ismbcpunct +@ cdecl _o__ismbcpunct(long) ucrtbase._o__ismbcpunct @ stub _o__ismbcpunct_l -@ stub _o__ismbcspace +@ cdecl _o__ismbcspace(long) ucrtbase._o__ismbcspace @ stub _o__ismbcspace_l -@ stub _o__ismbcsymbol +@ cdecl _o__ismbcsymbol(long) ucrtbase._o__ismbcsymbol @ stub _o__ismbcsymbol_l -@ stub _o__ismbcupper +@ cdecl _o__ismbcupper(long) ucrtbase._o__ismbcupper @ stub _o__ismbcupper_l -@ stub _o__ismbslead +@ cdecl _o__ismbslead(ptr ptr) ucrtbase._o__ismbslead @ stub _o__ismbslead_l -@ stub _o__ismbstrail +@ cdecl _o__ismbstrail(ptr ptr) ucrtbase._o__ismbstrail @ stub _o__ismbstrail_l -@ stub _o__iswctype_l -@ stub _o__itoa -@ stub _o__itoa_s -@ stub _o__itow -@ stub _o__itow_s -@ stub _o__j0 -@ stub _o__j1 -@ stub _o__jn -@ stub _o__kbhit +@ cdecl _o__iswctype_l(long long ptr) ucrtbase._o__iswctype_l +@ cdecl _o__itoa(long ptr long) ucrtbase._o__itoa +@ cdecl _o__itoa_s(long ptr long long) ucrtbase._o__itoa_s +@ cdecl _o__itow(long ptr long) ucrtbase._o__itow +@ cdecl _o__itow_s(long ptr long long) ucrtbase._o__itow_s +@ cdecl _o__j0(double) ucrtbase._o__j0 +@ cdecl _o__j1(double) ucrtbase._o__j1 +@ cdecl _o__jn(long double) ucrtbase._o__jn +@ cdecl _o__kbhit() ucrtbase._o__kbhit @ stub _o__ld_int -@ stub _o__ldclass +@ cdecl _o__ldclass(double) ucrtbase._o__ldclass @ stub _o__ldexp @ stub _o__ldlog -@ stub _o__ldpcomp +@ cdecl _o__ldpcomp(double double) ucrtbase._o__ldpcomp @ stub _o__ldpoly @ stub _o__ldscale -@ stub _o__ldsign +@ cdecl _o__ldsign(double) ucrtbase._o__ldsign @ stub _o__ldsin -@ stub _o__ldtest +@ cdecl _o__ldtest(ptr) ucrtbase._o__ldtest @ stub _o__ldunscale -@ stub _o__lfind -@ stub _o__lfind_s -@ stub _o__libm_sse2_acos_precise -@ stub _o__libm_sse2_asin_precise -@ stub _o__libm_sse2_atan_precise -@ stub _o__libm_sse2_cos_precise -@ stub _o__libm_sse2_exp_precise -@ stub _o__libm_sse2_log10_precise -@ stub _o__libm_sse2_log_precise -@ stub _o__libm_sse2_pow_precise -@ stub _o__libm_sse2_sin_precise -@ stub _o__libm_sse2_sqrt_precise -@ stub _o__libm_sse2_tan_precise -@ stub _o__loaddll -@ stub _o__localtime32 -@ stub _o__localtime32_s -@ stub _o__localtime64 -@ stub _o__localtime64_s -@ stub _o__lock_file -@ stub _o__locking -@ stub _o__logb -@ stub _o__logbf -@ stub _o__lsearch +@ cdecl _o__lfind(ptr ptr ptr long ptr) ucrtbase._o__lfind +@ cdecl _o__lfind_s(ptr ptr ptr long ptr ptr) ucrtbase._o__lfind_s +@ cdecl -arch=i386 -norelay _o__libm_sse2_acos_precise() ucrtbase._o__libm_sse2_acos_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_asin_precise() ucrtbase._o__libm_sse2_asin_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_atan_precise() ucrtbase._o__libm_sse2_atan_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_cos_precise() ucrtbase._o__libm_sse2_cos_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_exp_precise() ucrtbase._o__libm_sse2_exp_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_log10_precise() ucrtbase._o__libm_sse2_log10_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_log_precise() ucrtbase._o__libm_sse2_log_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_pow_precise() ucrtbase._o__libm_sse2_pow_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_sin_precise() ucrtbase._o__libm_sse2_sin_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_sqrt_precise() ucrtbase._o__libm_sse2_sqrt_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_tan_precise() ucrtbase._o__libm_sse2_tan_precise +@ cdecl _o__loaddll(str) ucrtbase._o__loaddll +@ cdecl _o__localtime32(ptr) ucrtbase._o__localtime32 +@ cdecl _o__localtime32_s(ptr ptr) ucrtbase._o__localtime32_s +@ cdecl _o__localtime64(ptr) ucrtbase._o__localtime64 +@ cdecl _o__localtime64_s(ptr ptr) ucrtbase._o__localtime64_s +@ cdecl _o__lock_file(ptr) ucrtbase._o__lock_file +@ cdecl _o__locking(long long long) ucrtbase._o__locking +@ cdecl _o__logb(double) ucrtbase._o__logb +@ cdecl -arch=!i386 _o__logbf(float) ucrtbase._o__logbf +@ cdecl _o__lsearch(ptr ptr ptr long ptr) ucrtbase._o__lsearch @ stub _o__lsearch_s -@ stub _o__lseek -@ stub _o__lseeki64 -@ stub _o__ltoa -@ stub _o__ltoa_s -@ stub _o__ltow -@ stub _o__ltow_s -@ stub _o__makepath -@ stub _o__makepath_s -@ stub _o__malloc_base -@ stub _o__mbbtombc +@ cdecl _o__lseek(long long long) ucrtbase._o__lseek +@ cdecl -ret64 _o__lseeki64(long int64 long) ucrtbase._o__lseeki64 +@ cdecl _o__ltoa(long ptr long) ucrtbase._o__ltoa +@ cdecl _o__ltoa_s(long ptr long long) ucrtbase._o__ltoa_s +@ cdecl _o__ltow(long ptr long) ucrtbase._o__ltow +@ cdecl _o__ltow_s(long ptr long long) ucrtbase._o__ltow_s +@ cdecl _o__makepath(ptr str str str str) ucrtbase._o__makepath +@ cdecl _o__makepath_s(ptr long str str str str) ucrtbase._o__makepath_s +@ cdecl _o__malloc_base(long) ucrtbase._o__malloc_base +@ cdecl _o__mbbtombc(long) ucrtbase._o__mbbtombc @ stub _o__mbbtombc_l -@ stub _o__mbbtype +@ cdecl _o__mbbtype(long long) ucrtbase._o__mbbtype @ stub _o__mbbtype_l -@ stub _o__mbccpy -@ stub _o__mbccpy_l -@ stub _o__mbccpy_s -@ stub _o__mbccpy_s_l -@ stub _o__mbcjistojms +@ cdecl _o__mbccpy(ptr ptr) ucrtbase._o__mbccpy +@ cdecl _o__mbccpy_l(ptr ptr ptr) ucrtbase._o__mbccpy_l +@ cdecl _o__mbccpy_s(ptr long ptr ptr) ucrtbase._o__mbccpy_s +@ cdecl _o__mbccpy_s_l(ptr long ptr ptr ptr) ucrtbase._o__mbccpy_s_l +@ cdecl _o__mbcjistojms(long) ucrtbase._o__mbcjistojms @ stub _o__mbcjistojms_l -@ stub _o__mbcjmstojis +@ cdecl _o__mbcjmstojis(long) ucrtbase._o__mbcjmstojis @ stub _o__mbcjmstojis_l -@ stub _o__mbclen +@ cdecl _o__mbclen(ptr) ucrtbase._o__mbclen @ stub _o__mbclen_l -@ stub _o__mbctohira +@ cdecl _o__mbctohira(long) ucrtbase._o__mbctohira @ stub _o__mbctohira_l -@ stub _o__mbctokata +@ cdecl _o__mbctokata(long) ucrtbase._o__mbctokata @ stub _o__mbctokata_l -@ stub _o__mbctolower +@ cdecl _o__mbctolower(long) ucrtbase._o__mbctolower @ stub _o__mbctolower_l -@ stub _o__mbctombb +@ cdecl _o__mbctombb(long) ucrtbase._o__mbctombb @ stub _o__mbctombb_l -@ stub _o__mbctoupper +@ cdecl _o__mbctoupper(long) ucrtbase._o__mbctoupper @ stub _o__mbctoupper_l @ stub _o__mblen_l -@ stub _o__mbsbtype +@ cdecl _o__mbsbtype(str long) ucrtbase._o__mbsbtype @ stub _o__mbsbtype_l -@ stub _o__mbscat_s -@ stub _o__mbscat_s_l -@ stub _o__mbschr +@ cdecl _o__mbscat_s(ptr long str) ucrtbase._o__mbscat_s +@ cdecl _o__mbscat_s_l(ptr long str ptr) ucrtbase._o__mbscat_s_l +@ cdecl _o__mbschr(str long) ucrtbase._o__mbschr @ stub _o__mbschr_l -@ stub _o__mbscmp +@ cdecl _o__mbscmp(str str) ucrtbase._o__mbscmp @ stub _o__mbscmp_l -@ stub _o__mbscoll -@ stub _o__mbscoll_l -@ stub _o__mbscpy_s -@ stub _o__mbscpy_s_l -@ stub _o__mbscspn -@ stub _o__mbscspn_l -@ stub _o__mbsdec +@ cdecl _o__mbscoll(str str) ucrtbase._o__mbscoll +@ cdecl _o__mbscoll_l(str str ptr) ucrtbase._o__mbscoll_l +@ cdecl _o__mbscpy_s(ptr long str) ucrtbase._o__mbscpy_s +@ cdecl _o__mbscpy_s_l(ptr long str ptr) ucrtbase._o__mbscpy_s_l +@ cdecl _o__mbscspn(str str) ucrtbase._o__mbscspn +@ cdecl _o__mbscspn_l(str str ptr) ucrtbase._o__mbscspn_l +@ cdecl _o__mbsdec(ptr ptr) ucrtbase._o__mbsdec @ stub _o__mbsdec_l -@ stub _o__mbsicmp +@ cdecl _o__mbsicmp(str str) ucrtbase._o__mbsicmp @ stub _o__mbsicmp_l -@ stub _o__mbsicoll -@ stub _o__mbsicoll_l -@ stub _o__mbsinc +@ cdecl _o__mbsicoll(str str) ucrtbase._o__mbsicoll +@ cdecl _o__mbsicoll_l(str str ptr) ucrtbase._o__mbsicoll_l +@ cdecl _o__mbsinc(str) ucrtbase._o__mbsinc @ stub _o__mbsinc_l -@ stub _o__mbslen -@ stub _o__mbslen_l -@ stub _o__mbslwr +@ cdecl _o__mbslen(str) ucrtbase._o__mbslen +@ cdecl _o__mbslen_l(str ptr) ucrtbase._o__mbslen_l +@ cdecl _o__mbslwr(str) ucrtbase._o__mbslwr @ stub _o__mbslwr_l -@ stub _o__mbslwr_s +@ cdecl _o__mbslwr_s(str long) ucrtbase._o__mbslwr_s @ stub _o__mbslwr_s_l -@ stub _o__mbsnbcat +@ cdecl _o__mbsnbcat(str str long) ucrtbase._o__mbsnbcat @ stub _o__mbsnbcat_l -@ stub _o__mbsnbcat_s +@ cdecl _o__mbsnbcat_s(str long ptr long) ucrtbase._o__mbsnbcat_s @ stub _o__mbsnbcat_s_l -@ stub _o__mbsnbcmp +@ cdecl _o__mbsnbcmp(str str long) ucrtbase._o__mbsnbcmp @ stub _o__mbsnbcmp_l -@ stub _o__mbsnbcnt +@ cdecl _o__mbsnbcnt(ptr long) ucrtbase._o__mbsnbcnt @ stub _o__mbsnbcnt_l -@ stub _o__mbsnbcoll -@ stub _o__mbsnbcoll_l -@ stub _o__mbsnbcpy +@ cdecl _o__mbsnbcoll(str str long) ucrtbase._o__mbsnbcoll +@ cdecl _o__mbsnbcoll_l(str str long ptr) ucrtbase._o__mbsnbcoll_l +@ cdecl _o__mbsnbcpy(ptr str long) ucrtbase._o__mbsnbcpy @ stub _o__mbsnbcpy_l -@ stub _o__mbsnbcpy_s -@ stub _o__mbsnbcpy_s_l -@ stub _o__mbsnbicmp +@ cdecl _o__mbsnbcpy_s(ptr long str long) ucrtbase._o__mbsnbcpy_s +@ cdecl _o__mbsnbcpy_s_l(ptr long str long ptr) ucrtbase._o__mbsnbcpy_s_l +@ cdecl _o__mbsnbicmp(str str long) ucrtbase._o__mbsnbicmp @ stub _o__mbsnbicmp_l -@ stub _o__mbsnbicoll -@ stub _o__mbsnbicoll_l -@ stub _o__mbsnbset +@ cdecl _o__mbsnbicoll(str str long) ucrtbase._o__mbsnbicoll +@ cdecl _o__mbsnbicoll_l(str str long ptr) ucrtbase._o__mbsnbicoll_l +@ cdecl _o__mbsnbset(ptr long long) ucrtbase._o__mbsnbset @ stub _o__mbsnbset_l @ stub _o__mbsnbset_s @ stub _o__mbsnbset_s_l -@ stub _o__mbsncat +@ cdecl _o__mbsncat(str str long) ucrtbase._o__mbsncat @ stub _o__mbsncat_l @ stub _o__mbsncat_s @ stub _o__mbsncat_s_l -@ stub _o__mbsnccnt +@ cdecl _o__mbsnccnt(str long) ucrtbase._o__mbsnccnt @ stub _o__mbsnccnt_l -@ stub _o__mbsncmp +@ cdecl _o__mbsncmp(str str long) ucrtbase._o__mbsncmp @ stub _o__mbsncmp_l @ stub _o__mbsncoll @ stub _o__mbsncoll_l -@ stub _o__mbsncpy +@ cdecl _o__mbsncpy(ptr str long) ucrtbase._o__mbsncpy @ stub _o__mbsncpy_l @ stub _o__mbsncpy_s @ stub _o__mbsncpy_s_l -@ stub _o__mbsnextc +@ cdecl _o__mbsnextc(str) ucrtbase._o__mbsnextc @ stub _o__mbsnextc_l -@ stub _o__mbsnicmp +@ cdecl _o__mbsnicmp(str str long) ucrtbase._o__mbsnicmp @ stub _o__mbsnicmp_l @ stub _o__mbsnicoll @ stub _o__mbsnicoll_l -@ stub _o__mbsninc +@ cdecl _o__mbsninc(str long) ucrtbase._o__mbsninc @ stub _o__mbsninc_l -@ stub _o__mbsnlen -@ stub _o__mbsnlen_l -@ stub _o__mbsnset +@ cdecl _o__mbsnlen(str long) ucrtbase._o__mbsnlen +@ cdecl _o__mbsnlen_l(str long ptr) ucrtbase._o__mbsnlen_l +@ cdecl _o__mbsnset(ptr long long) ucrtbase._o__mbsnset @ stub _o__mbsnset_l @ stub _o__mbsnset_s @ stub _o__mbsnset_s_l -@ stub _o__mbspbrk +@ cdecl _o__mbspbrk(str str) ucrtbase._o__mbspbrk @ stub _o__mbspbrk_l -@ stub _o__mbsrchr +@ cdecl _o__mbsrchr(str long) ucrtbase._o__mbsrchr @ stub _o__mbsrchr_l -@ stub _o__mbsrev +@ cdecl _o__mbsrev(str) ucrtbase._o__mbsrev @ stub _o__mbsrev_l -@ stub _o__mbsset +@ cdecl _o__mbsset(ptr long) ucrtbase._o__mbsset @ stub _o__mbsset_l @ stub _o__mbsset_s @ stub _o__mbsset_s_l -@ stub _o__mbsspn -@ stub _o__mbsspn_l -@ stub _o__mbsspnp +@ cdecl _o__mbsspn(str str) ucrtbase._o__mbsspn +@ cdecl _o__mbsspn_l(str str ptr) ucrtbase._o__mbsspn_l +@ cdecl _o__mbsspnp(str str) ucrtbase._o__mbsspnp @ stub _o__mbsspnp_l -@ stub _o__mbsstr +@ cdecl _o__mbsstr(str str) ucrtbase._o__mbsstr @ stub _o__mbsstr_l -@ stub _o__mbstok -@ stub _o__mbstok_l -@ stub _o__mbstok_s -@ stub _o__mbstok_s_l -@ stub _o__mbstowcs_l -@ stub _o__mbstowcs_s_l +@ cdecl _o__mbstok(str str) ucrtbase._o__mbstok +@ cdecl _o__mbstok_l(str str ptr) ucrtbase._o__mbstok_l +@ cdecl _o__mbstok_s(str str ptr) ucrtbase._o__mbstok_s +@ cdecl _o__mbstok_s_l(str str ptr ptr) ucrtbase._o__mbstok_s_l +@ cdecl _o__mbstowcs_l(ptr str long ptr) ucrtbase._o__mbstowcs_l +@ cdecl _o__mbstowcs_s_l(ptr ptr long str long ptr) ucrtbase._o__mbstowcs_s_l @ cdecl _o__mbstrlen(str) ucrtbase._o__mbstrlen -@ stub _o__mbstrlen_l +@ cdecl _o__mbstrlen_l(str ptr) ucrtbase._o__mbstrlen_l @ stub _o__mbstrnlen @ stub _o__mbstrnlen_l -@ stub _o__mbsupr +@ cdecl _o__mbsupr(str) ucrtbase._o__mbsupr @ stub _o__mbsupr_l -@ stub _o__mbsupr_s +@ cdecl _o__mbsupr_s(str long) ucrtbase._o__mbsupr_s @ stub _o__mbsupr_s_l -@ stub _o__mbtowc_l -@ stub _o__memicmp -@ stub _o__memicmp_l -@ stub _o__mkdir -@ stub _o__mkgmtime32 -@ stub _o__mkgmtime64 -@ stub _o__mktemp -@ stub _o__mktemp_s -@ stub _o__mktime32 -@ stub _o__mktime64 -@ stub _o__msize -@ stub _o__nextafter -@ stub _o__nextafterf -@ stub _o__open_osfhandle -@ stub _o__pclose -@ stub _o__pipe -@ stub _o__popen -@ stub _o__purecall -@ stub _o__putc_nolock -@ stub _o__putch -@ stub _o__putch_nolock -@ stub _o__putenv -@ stub _o__putenv_s -@ stub _o__putw -@ stub _o__putwc_nolock -@ stub _o__putwch -@ stub _o__putwch_nolock -@ stub _o__putws -@ stub _o__read -@ stub _o__realloc_base -@ stub _o__recalloc +@ cdecl _o__mbtowc_l(ptr str long ptr) ucrtbase._o__mbtowc_l +@ cdecl _o__memicmp(str str long) ucrtbase._o__memicmp +@ cdecl _o__memicmp_l(str str long ptr) ucrtbase._o__memicmp_l +@ cdecl _o__mkdir(str) ucrtbase._o__mkdir +@ cdecl _o__mkgmtime32(ptr) ucrtbase._o__mkgmtime32 +@ cdecl _o__mkgmtime64(ptr) ucrtbase._o__mkgmtime64 +@ cdecl _o__mktemp(str) ucrtbase._o__mktemp +@ cdecl _o__mktemp_s(str long) ucrtbase._o__mktemp_s +@ cdecl _o__mktime32(ptr) ucrtbase._o__mktime32 +@ cdecl _o__mktime64(ptr) ucrtbase._o__mktime64 +@ cdecl _o__msize(ptr) ucrtbase._o__msize +@ cdecl _o__nextafter(double double) ucrtbase._o__nextafter +@ cdecl -arch=x86_64 _o__nextafterf(float float) ucrtbase._o__nextafterf +@ cdecl _o__open_osfhandle(long long) ucrtbase._o__open_osfhandle +@ cdecl _o__pclose(ptr) ucrtbase._o__pclose +@ cdecl _o__pipe(ptr long long) ucrtbase._o__pipe +@ cdecl _o__popen(str str) ucrtbase._o__popen +@ cdecl _o__purecall() ucrtbase._o__purecall +@ cdecl _o__putc_nolock(long ptr) ucrtbase._o__putc_nolock +@ cdecl _o__putch(long) ucrtbase._o__putch +@ cdecl _o__putch_nolock(long) ucrtbase._o__putch_nolock +@ cdecl _o__putenv(str) ucrtbase._o__putenv +@ cdecl _o__putenv_s(str str) ucrtbase._o__putenv_s +@ cdecl _o__putw(long ptr) ucrtbase._o__putw +@ cdecl _o__putwc_nolock(long ptr) ucrtbase._o__putwc_nolock +@ cdecl _o__putwch(long) ucrtbase._o__putwch +@ cdecl _o__putwch_nolock(long) ucrtbase._o__putwch_nolock +@ cdecl _o__putws(wstr) ucrtbase._o__putws +@ cdecl _o__read(long ptr long) ucrtbase._o__read +@ cdecl _o__realloc_base(ptr long) ucrtbase._o__realloc_base +@ cdecl _o__recalloc(ptr long long) ucrtbase._o__recalloc @ cdecl _o__register_onexit_function(ptr ptr) ucrtbase._o__register_onexit_function -@ stub _o__resetstkoflw -@ stub _o__rmdir -@ stub _o__rmtmp -@ stub _o__scalb -@ stub _o__scalbf -@ stub _o__searchenv -@ stub _o__searchenv_s +@ cdecl _o__resetstkoflw() ucrtbase._o__resetstkoflw +@ cdecl _o__rmdir(str) ucrtbase._o__rmdir +@ cdecl _o__rmtmp() ucrtbase._o__rmtmp +@ cdecl _o__scalb(double long) ucrtbase._o__scalb +@ cdecl -arch=x86_64 _o__scalbf(float long) ucrtbase._o__scalbf +@ cdecl _o__searchenv(str str ptr) ucrtbase._o__searchenv +@ cdecl _o__searchenv_s(str str ptr long) ucrtbase._o__searchenv_s @ cdecl _o__seh_filter_dll(long ptr) ucrtbase._o__seh_filter_dll @ cdecl _o__seh_filter_exe(long ptr) ucrtbase._o__seh_filter_exe -@ stub _o__set_abort_behavior +@ cdecl _o__set_abort_behavior(long long) ucrtbase._o__set_abort_behavior @ cdecl _o__set_app_type(long) ucrtbase._o__set_app_type -@ stub _o__set_doserrno -@ stub _o__set_errno +@ cdecl _o__set_doserrno(long) ucrtbase._o__set_doserrno +@ cdecl _o__set_errno(long) ucrtbase._o__set_errno @ cdecl _o__set_fmode(long) ucrtbase._o__set_fmode -@ stub _o__set_invalid_parameter_handler -@ stub _o__set_new_handler +@ cdecl _o__set_invalid_parameter_handler(ptr) ucrtbase._o__set_invalid_parameter_handler +@ cdecl _o__set_new_handler(ptr) ucrtbase._o__set_new_handler @ cdecl _o__set_new_mode(long) ucrtbase._o__set_new_mode -@ stub _o__set_thread_local_invalid_parameter_handler -@ stub _o__seterrormode -@ stub _o__setmbcp -@ stub _o__setmode +@ cdecl _o__set_thread_local_invalid_parameter_handler(ptr) ucrtbase._o__set_thread_local_invalid_parameter_handler +@ cdecl _o__seterrormode(long) ucrtbase._o__seterrormode +@ cdecl _o__setmbcp(long) ucrtbase._o__setmbcp +@ cdecl _o__setmode(long long) ucrtbase._o__setmode @ stub _o__setsystime -@ stub _o__sleep -@ stub _o__sopen -@ stub _o__sopen_dispatch -@ stub _o__sopen_s -@ stub _o__spawnv -@ stub _o__spawnve -@ stub _o__spawnvp -@ stub _o__spawnvpe -@ stub _o__splitpath -@ stub _o__splitpath_s -@ stub _o__stat32 -@ stub _o__stat32i64 -@ stub _o__stat64 -@ stub _o__stat64i32 -@ stub _o__strcoll_l -@ stub _o__strdate -@ stub _o__strdate_s +@ cdecl _o__sleep(long) ucrtbase._o__sleep +@ varargs _o__sopen(str long long) ucrtbase._o__sopen +@ cdecl _o__sopen_dispatch(str long long long ptr long) ucrtbase._o__sopen_dispatch +@ cdecl _o__sopen_s(ptr str long long long) ucrtbase._o__sopen_s +@ cdecl _o__spawnv(long str ptr) ucrtbase._o__spawnv +@ cdecl _o__spawnve(long str ptr ptr) ucrtbase._o__spawnve +@ cdecl _o__spawnvp(long str ptr) ucrtbase._o__spawnvp +@ cdecl _o__spawnvpe(long str ptr ptr) ucrtbase._o__spawnvpe +@ cdecl _o__splitpath(str ptr ptr ptr ptr) ucrtbase._o__splitpath +@ cdecl _o__splitpath_s(str ptr long ptr long ptr long ptr long) ucrtbase._o__splitpath_s +@ cdecl _o__stat32(str ptr) ucrtbase._o__stat32 +@ cdecl _o__stat32i64(str ptr) ucrtbase._o__stat32i64 +@ cdecl _o__stat64(str ptr) ucrtbase._o__stat64 +@ cdecl _o__stat64i32(str ptr) ucrtbase._o__stat64i32 +@ cdecl _o__strcoll_l(str str ptr) ucrtbase._o__strcoll_l +@ cdecl _o__strdate(ptr) ucrtbase._o__strdate +@ cdecl _o__strdate_s(ptr long) ucrtbase._o__strdate_s @ cdecl _o__strdup(str) ucrtbase._o__strdup -@ stub _o__strerror +@ cdecl _o__strerror(long) ucrtbase._o__strerror @ stub _o__strerror_s -@ stub _o__strftime_l +@ cdecl _o__strftime_l(ptr long str ptr ptr) ucrtbase._o__strftime_l @ cdecl _o__stricmp(str str) ucrtbase._o__stricmp -@ stub _o__stricmp_l -@ stub _o__stricoll -@ stub _o__stricoll_l -@ stub _o__strlwr -@ stub _o__strlwr_l -@ stub _o__strlwr_s -@ stub _o__strlwr_s_l -@ stub _o__strncoll -@ stub _o__strncoll_l +@ cdecl _o__stricmp_l(str str ptr) ucrtbase._o__stricmp_l +@ cdecl _o__stricoll(str str) ucrtbase._o__stricoll +@ cdecl _o__stricoll_l(str str ptr) ucrtbase._o__stricoll_l +@ cdecl _o__strlwr(str) ucrtbase._o__strlwr +@ cdecl _o__strlwr_l(str ptr) ucrtbase._o__strlwr_l +@ cdecl _o__strlwr_s(ptr long) ucrtbase._o__strlwr_s +@ cdecl _o__strlwr_s_l(ptr long ptr) ucrtbase._o__strlwr_s_l +@ cdecl _o__strncoll(str str long) ucrtbase._o__strncoll +@ cdecl _o__strncoll_l(str str long ptr) ucrtbase._o__strncoll_l @ cdecl _o__strnicmp(str str long) ucrtbase._o__strnicmp -@ stub _o__strnicmp_l -@ stub _o__strnicoll -@ stub _o__strnicoll_l -@ stub _o__strnset_s +@ cdecl _o__strnicmp_l(str str long ptr) ucrtbase._o__strnicmp_l +@ cdecl _o__strnicoll(str str long) ucrtbase._o__strnicoll +@ cdecl _o__strnicoll_l(str str long ptr) ucrtbase._o__strnicoll_l +@ cdecl _o__strnset_s(str long long long) ucrtbase._o__strnset_s @ stub _o__strset_s -@ stub _o__strtime -@ stub _o__strtime_s -@ stub _o__strtod_l -@ stub _o__strtof_l -@ stub _o__strtoi64 -@ stub _o__strtoi64_l -@ stub _o__strtol_l +@ cdecl _o__strtime(ptr) ucrtbase._o__strtime +@ cdecl _o__strtime_s(ptr long) ucrtbase._o__strtime_s +@ cdecl _o__strtod_l(str ptr ptr) ucrtbase._o__strtod_l +@ cdecl _o__strtof_l(str ptr ptr) ucrtbase._o__strtof_l +@ cdecl -ret64 _o__strtoi64(str ptr long) ucrtbase._o__strtoi64 +@ cdecl -ret64 _o__strtoi64_l(str ptr long ptr) ucrtbase._o__strtoi64_l +@ cdecl _o__strtol_l(str ptr long ptr) ucrtbase._o__strtol_l @ stub _o__strtold_l -@ stub _o__strtoll_l -@ stub _o__strtoui64 -@ stub _o__strtoui64_l -@ stub _o__strtoul_l -@ stub _o__strtoull_l -@ stub _o__strupr -@ stub _o__strupr_l -@ stub _o__strupr_s -@ stub _o__strupr_s_l -@ stub _o__strxfrm_l -@ stub _o__swab -@ stub _o__tell -@ stub _o__telli64 -@ stub _o__timespec32_get -@ stub _o__timespec64_get -@ stub _o__tolower -@ stub _o__tolower_l -@ stub _o__toupper -@ stub _o__toupper_l -@ stub _o__towlower_l -@ stub _o__towupper_l -@ stub _o__tzset -@ stub _o__ui64toa -@ stub _o__ui64toa_s -@ stub _o__ui64tow -@ stub _o__ui64tow_s -@ stub _o__ultoa -@ stub _o__ultoa_s -@ stub _o__ultow -@ stub _o__ultow_s -@ stub _o__umask +@ cdecl -ret64 _o__strtoll_l(str ptr long ptr) ucrtbase._o__strtoll_l +@ cdecl -ret64 _o__strtoui64(str ptr long) ucrtbase._o__strtoui64 +@ cdecl -ret64 _o__strtoui64_l(str ptr long ptr) ucrtbase._o__strtoui64_l +@ cdecl _o__strtoul_l(str ptr long ptr) ucrtbase._o__strtoul_l +@ cdecl -ret64 _o__strtoull_l(str ptr long ptr) ucrtbase._o__strtoull_l +@ cdecl _o__strupr(str) ucrtbase._o__strupr +@ cdecl _o__strupr_l(str ptr) ucrtbase._o__strupr_l +@ cdecl _o__strupr_s(str long) ucrtbase._o__strupr_s +@ cdecl _o__strupr_s_l(str long ptr) ucrtbase._o__strupr_s_l +@ cdecl _o__strxfrm_l(ptr str long ptr) ucrtbase._o__strxfrm_l +@ cdecl _o__swab(str str long) ucrtbase._o__swab +@ cdecl _o__tell(long) ucrtbase._o__tell +@ cdecl -ret64 _o__telli64(long) ucrtbase._o__telli64 +@ cdecl _o__timespec32_get(ptr long) ucrtbase._o__timespec32_get +@ cdecl _o__timespec64_get(ptr long) ucrtbase._o__timespec64_get +@ cdecl _o__tolower(long) ucrtbase._o__tolower +@ cdecl _o__tolower_l(long ptr) ucrtbase._o__tolower_l +@ cdecl _o__toupper(long) ucrtbase._o__toupper +@ cdecl _o__toupper_l(long ptr) ucrtbase._o__toupper_l +@ cdecl _o__towlower_l(long ptr) ucrtbase._o__towlower_l +@ cdecl _o__towupper_l(long ptr) ucrtbase._o__towupper_l +@ cdecl _o__tzset() ucrtbase._o__tzset +@ cdecl _o__ui64toa(int64 ptr long) ucrtbase._o__ui64toa +@ cdecl _o__ui64toa_s(int64 ptr long long) ucrtbase._o__ui64toa_s +@ cdecl _o__ui64tow(int64 ptr long) ucrtbase._o__ui64tow +@ cdecl _o__ui64tow_s(int64 ptr long long) ucrtbase._o__ui64tow_s +@ cdecl _o__ultoa(long ptr long) ucrtbase._o__ultoa +@ cdecl _o__ultoa_s(long ptr long long) ucrtbase._o__ultoa_s +@ cdecl _o__ultow(long ptr long) ucrtbase._o__ultow +@ cdecl _o__ultow_s(long ptr long long) ucrtbase._o__ultow_s +@ cdecl _o__umask(long) ucrtbase._o__umask @ stub _o__umask_s -@ stub _o__ungetc_nolock -@ stub _o__ungetch -@ stub _o__ungetch_nolock -@ stub _o__ungetwc_nolock -@ stub _o__ungetwch -@ stub _o__ungetwch_nolock -@ stub _o__unlink -@ stub _o__unloaddll -@ stub _o__unlock_file -@ stub _o__utime32 -@ stub _o__utime64 -@ stub _o__waccess -@ stub _o__waccess_s -@ stub _o__wasctime -@ stub _o__wasctime_s -@ stub _o__wchdir -@ stub _o__wchmod -@ stub _o__wcreat -@ stub _o__wcreate_locale -@ stub _o__wcscoll_l -@ stub _o__wcsdup -@ stub _o__wcserror -@ stub _o__wcserror_s -@ stub _o__wcsftime_l -@ stub _o__wcsicmp -@ stub _o__wcsicmp_l -@ stub _o__wcsicoll -@ stub _o__wcsicoll_l -@ stub _o__wcslwr -@ stub _o__wcslwr_l -@ stub _o__wcslwr_s -@ stub _o__wcslwr_s_l -@ stub _o__wcsncoll -@ stub _o__wcsncoll_l -@ stub _o__wcsnicmp -@ stub _o__wcsnicmp_l -@ stub _o__wcsnicoll -@ stub _o__wcsnicoll_l -@ stub _o__wcsnset -@ stub _o__wcsnset_s -@ stub _o__wcsset -@ stub _o__wcsset_s -@ stub _o__wcstod_l -@ stub _o__wcstof_l -@ stub _o__wcstoi64 -@ stub _o__wcstoi64_l -@ stub _o__wcstol_l +@ cdecl _o__ungetc_nolock(long ptr) ucrtbase._o__ungetc_nolock +@ cdecl _o__ungetch(long) ucrtbase._o__ungetch +@ cdecl _o__ungetch_nolock(long) ucrtbase._o__ungetch_nolock +@ cdecl _o__ungetwc_nolock(long ptr) ucrtbase._o__ungetwc_nolock +@ cdecl _o__ungetwch(long) ucrtbase._o__ungetwch +@ cdecl _o__ungetwch_nolock(long) ucrtbase._o__ungetwch_nolock +@ cdecl _o__unlink(str) ucrtbase._o__unlink +@ cdecl _o__unloaddll(long) ucrtbase._o__unloaddll +@ cdecl _o__unlock_file(ptr) ucrtbase._o__unlock_file +@ cdecl _o__utime32(str ptr) ucrtbase._o__utime32 +@ cdecl _o__utime64(str ptr) ucrtbase._o__utime64 +@ cdecl _o__waccess(wstr long) ucrtbase._o__waccess +@ cdecl _o__waccess_s(wstr long) ucrtbase._o__waccess_s +@ cdecl _o__wasctime(ptr) ucrtbase._o__wasctime +@ cdecl _o__wasctime_s(ptr long ptr) ucrtbase._o__wasctime_s +@ cdecl _o__wchdir(wstr) ucrtbase._o__wchdir +@ cdecl _o__wchmod(wstr long) ucrtbase._o__wchmod +@ cdecl _o__wcreat(wstr long) ucrtbase._o__wcreat +@ cdecl _o__wcreate_locale(long wstr) ucrtbase._o__wcreate_locale +@ cdecl _o__wcscoll_l(wstr wstr ptr) ucrtbase._o__wcscoll_l +@ cdecl _o__wcsdup(wstr) ucrtbase._o__wcsdup +@ cdecl _o__wcserror(long) ucrtbase._o__wcserror +@ cdecl _o__wcserror_s(ptr long long) ucrtbase._o__wcserror_s +@ cdecl _o__wcsftime_l(ptr long wstr ptr ptr) ucrtbase._o__wcsftime_l +@ cdecl _o__wcsicmp(wstr wstr) ucrtbase._o__wcsicmp +@ cdecl _o__wcsicmp_l(wstr wstr ptr) ucrtbase._o__wcsicmp_l +@ cdecl _o__wcsicoll(wstr wstr) ucrtbase._o__wcsicoll +@ cdecl _o__wcsicoll_l(wstr wstr ptr) ucrtbase._o__wcsicoll_l +@ cdecl _o__wcslwr(wstr) ucrtbase._o__wcslwr +@ cdecl _o__wcslwr_l(wstr ptr) ucrtbase._o__wcslwr_l +@ cdecl _o__wcslwr_s(wstr long) ucrtbase._o__wcslwr_s +@ cdecl _o__wcslwr_s_l(wstr long ptr) ucrtbase._o__wcslwr_s_l +@ cdecl _o__wcsncoll(wstr wstr long) ucrtbase._o__wcsncoll +@ cdecl _o__wcsncoll_l(wstr wstr long ptr) ucrtbase._o__wcsncoll_l +@ cdecl _o__wcsnicmp(wstr wstr long) ucrtbase._o__wcsnicmp +@ cdecl _o__wcsnicmp_l(wstr wstr long ptr) ucrtbase._o__wcsnicmp_l +@ cdecl _o__wcsnicoll(wstr wstr long) ucrtbase._o__wcsnicoll +@ cdecl _o__wcsnicoll_l(wstr wstr long ptr) ucrtbase._o__wcsnicoll_l +@ cdecl _o__wcsnset(wstr long long) ucrtbase._o__wcsnset +@ cdecl _o__wcsnset_s(wstr long long long) ucrtbase._o__wcsnset_s +@ cdecl _o__wcsset(wstr long) ucrtbase._o__wcsset +@ cdecl _o__wcsset_s(wstr long long) ucrtbase._o__wcsset_s +@ cdecl _o__wcstod_l(wstr ptr long) ucrtbase._o__wcstod_l +@ cdecl _o__wcstof_l(wstr ptr ptr) ucrtbase._o__wcstof_l +@ cdecl -ret64 _o__wcstoi64(wstr ptr long) ucrtbase._o__wcstoi64 +@ cdecl -ret64 _o__wcstoi64_l(wstr ptr long ptr) ucrtbase._o__wcstoi64_l +@ cdecl _o__wcstol_l(wstr ptr long ptr) ucrtbase._o__wcstol_l @ stub _o__wcstold_l -@ stub _o__wcstoll_l -@ stub _o__wcstombs_l -@ stub _o__wcstombs_s_l -@ stub _o__wcstoui64 -@ stub _o__wcstoui64_l -@ stub _o__wcstoul_l -@ stub _o__wcstoull_l -@ stub _o__wcsupr -@ stub _o__wcsupr_l -@ stub _o__wcsupr_s -@ stub _o__wcsupr_s_l -@ stub _o__wcsxfrm_l -@ stub _o__wctime32 -@ stub _o__wctime32_s -@ stub _o__wctime64 -@ stub _o__wctime64_s -@ stub _o__wctomb_l -@ stub _o__wctomb_s_l -@ stub _o__wdupenv_s -@ stub _o__wexecv -@ stub _o__wexecve -@ stub _o__wexecvp -@ stub _o__wexecvpe -@ stub _o__wfdopen -@ stub _o__wfindfirst32 +@ cdecl -ret64 _o__wcstoll_l(wstr ptr long ptr) ucrtbase._o__wcstoll_l +@ cdecl _o__wcstombs_l(ptr ptr long ptr) ucrtbase._o__wcstombs_l +@ cdecl _o__wcstombs_s_l(ptr ptr long wstr long ptr) ucrtbase._o__wcstombs_s_l +@ cdecl -ret64 _o__wcstoui64(wstr ptr long) ucrtbase._o__wcstoui64 +@ cdecl -ret64 _o__wcstoui64_l(wstr ptr long ptr) ucrtbase._o__wcstoui64_l +@ cdecl _o__wcstoul_l(wstr ptr long ptr) ucrtbase._o__wcstoul_l +@ cdecl -ret64 _o__wcstoull_l(wstr ptr long ptr) ucrtbase._o__wcstoull_l +@ cdecl _o__wcsupr(wstr) ucrtbase._o__wcsupr +@ cdecl _o__wcsupr_l(wstr ptr) ucrtbase._o__wcsupr_l +@ cdecl _o__wcsupr_s(wstr long) ucrtbase._o__wcsupr_s +@ cdecl _o__wcsupr_s_l(wstr long ptr) ucrtbase._o__wcsupr_s_l +@ cdecl _o__wcsxfrm_l(ptr wstr long ptr) ucrtbase._o__wcsxfrm_l +@ cdecl _o__wctime32(ptr) ucrtbase._o__wctime32 +@ cdecl _o__wctime32_s(ptr long ptr) ucrtbase._o__wctime32_s +@ cdecl _o__wctime64(ptr) ucrtbase._o__wctime64 +@ cdecl _o__wctime64_s(ptr long ptr) ucrtbase._o__wctime64_s +@ cdecl _o__wctomb_l(ptr long ptr) ucrtbase._o__wctomb_l +@ cdecl _o__wctomb_s_l(ptr ptr long long ptr) ucrtbase._o__wctomb_s_l +@ cdecl _o__wdupenv_s(ptr ptr wstr) ucrtbase._o__wdupenv_s +@ cdecl _o__wexecv(wstr ptr) ucrtbase._o__wexecv +@ cdecl _o__wexecve(wstr ptr ptr) ucrtbase._o__wexecve +@ cdecl _o__wexecvp(wstr ptr) ucrtbase._o__wexecvp +@ cdecl _o__wexecvpe(wstr ptr ptr) ucrtbase._o__wexecvpe +@ cdecl _o__wfdopen(long wstr) ucrtbase._o__wfdopen +@ cdecl _o__wfindfirst32(wstr ptr) ucrtbase._o__wfindfirst32 @ stub _o__wfindfirst32i64 -@ stub _o__wfindfirst64 -@ stub _o__wfindfirst64i32 -@ stub _o__wfindnext32 +@ cdecl _o__wfindfirst64(wstr ptr) ucrtbase._o__wfindfirst64 +@ cdecl _o__wfindfirst64i32(wstr ptr) ucrtbase._o__wfindfirst64i32 +@ cdecl _o__wfindnext32(long ptr) ucrtbase._o__wfindnext32 @ stub _o__wfindnext32i64 -@ stub _o__wfindnext64 -@ stub _o__wfindnext64i32 -@ stub _o__wfopen -@ stub _o__wfopen_s -@ stub _o__wfreopen -@ stub _o__wfreopen_s -@ stub _o__wfsopen -@ stub _o__wfullpath -@ stub _o__wgetcwd -@ stub _o__wgetdcwd +@ cdecl _o__wfindnext64(long ptr) ucrtbase._o__wfindnext64 +@ cdecl _o__wfindnext64i32(long ptr) ucrtbase._o__wfindnext64i32 +@ cdecl _o__wfopen(wstr wstr) ucrtbase._o__wfopen +@ cdecl _o__wfopen_s(ptr wstr wstr) ucrtbase._o__wfopen_s +@ cdecl _o__wfreopen(wstr wstr ptr) ucrtbase._o__wfreopen +@ cdecl _o__wfreopen_s(ptr wstr wstr ptr) ucrtbase._o__wfreopen_s +@ cdecl _o__wfsopen(wstr wstr long) ucrtbase._o__wfsopen +@ cdecl _o__wfullpath(ptr wstr long) ucrtbase._o__wfullpath +@ cdecl _o__wgetcwd(wstr long) ucrtbase._o__wgetcwd +@ cdecl _o__wgetdcwd(long wstr long) ucrtbase._o__wgetdcwd @ cdecl _o__wgetenv(wstr) ucrtbase._o__wgetenv -@ stub _o__wgetenv_s -@ stub _o__wmakepath -@ stub _o__wmakepath_s -@ stub _o__wmkdir -@ stub _o__wmktemp -@ stub _o__wmktemp_s -@ stub _o__wperror -@ stub _o__wpopen -@ stub _o__wputenv -@ stub _o__wputenv_s -@ stub _o__wremove -@ stub _o__wrename -@ stub _o__write -@ stub _o__wrmdir -@ stub _o__wsearchenv -@ stub _o__wsearchenv_s +@ cdecl _o__wgetenv_s(ptr ptr long wstr) ucrtbase._o__wgetenv_s +@ cdecl _o__wmakepath(ptr wstr wstr wstr wstr) ucrtbase._o__wmakepath +@ cdecl _o__wmakepath_s(ptr long wstr wstr wstr wstr) ucrtbase._o__wmakepath_s +@ cdecl _o__wmkdir(wstr) ucrtbase._o__wmkdir +@ cdecl _o__wmktemp(wstr) ucrtbase._o__wmktemp +@ cdecl _o__wmktemp_s(wstr long) ucrtbase._o__wmktemp_s +@ cdecl _o__wperror(wstr) ucrtbase._o__wperror +@ cdecl _o__wpopen(wstr wstr) ucrtbase._o__wpopen +@ cdecl _o__wputenv(wstr) ucrtbase._o__wputenv +@ cdecl _o__wputenv_s(wstr wstr) ucrtbase._o__wputenv_s +@ cdecl _o__wremove(wstr) ucrtbase._o__wremove +@ cdecl _o__wrename(wstr wstr) ucrtbase._o__wrename +@ cdecl _o__write(long ptr long) ucrtbase._o__write +@ cdecl _o__wrmdir(wstr) ucrtbase._o__wrmdir +@ cdecl _o__wsearchenv(wstr wstr ptr) ucrtbase._o__wsearchenv +@ cdecl _o__wsearchenv_s(wstr wstr ptr long) ucrtbase._o__wsearchenv_s @ cdecl _o__wsetlocale(long wstr) ucrtbase._o__wsetlocale -@ stub _o__wsopen_dispatch -@ stub _o__wsopen_s -@ stub _o__wspawnv -@ stub _o__wspawnve -@ stub _o__wspawnvp -@ stub _o__wspawnvpe -@ stub _o__wsplitpath -@ stub _o__wsplitpath_s -@ stub _o__wstat32 -@ stub _o__wstat32i64 -@ stub _o__wstat64 -@ stub _o__wstat64i32 -@ stub _o__wstrdate -@ stub _o__wstrdate_s -@ stub _o__wstrtime -@ stub _o__wstrtime_s -@ stub _o__wsystem -@ stub _o__wtmpnam_s -@ stub _o__wtof -@ stub _o__wtof_l -@ stub _o__wtoi -@ stub _o__wtoi64 -@ stub _o__wtoi64_l -@ stub _o__wtoi_l -@ stub _o__wtol -@ stub _o__wtol_l -@ stub _o__wtoll -@ stub _o__wtoll_l -@ stub _o__wunlink -@ stub _o__wutime32 -@ stub _o__wutime64 -@ stub _o__y0 -@ stub _o__y1 -@ stub _o__yn -@ stub _o_abort -@ stub _o_acos -@ stub _o_acosf -@ stub _o_acosh -@ stub _o_acoshf -@ stub _o_acoshl -@ stub _o_asctime -@ stub _o_asctime_s -@ stub _o_asin -@ stub _o_asinf -@ stub _o_asinh -@ stub _o_asinhf -@ stub _o_asinhl -@ stub _o_atan -@ stub _o_atan2 -@ stub _o_atan2f -@ stub _o_atanf -@ stub _o_atanh -@ stub _o_atanhf -@ stub _o_atanhl +@ cdecl _o__wsopen_dispatch(wstr long long long ptr long) ucrtbase._o__wsopen_dispatch +@ cdecl _o__wsopen_s(ptr wstr long long long) ucrtbase._o__wsopen_s +@ cdecl _o__wspawnv(long wstr ptr) ucrtbase._o__wspawnv +@ cdecl _o__wspawnve(long wstr ptr ptr) ucrtbase._o__wspawnve +@ cdecl _o__wspawnvp(long wstr ptr) ucrtbase._o__wspawnvp +@ cdecl _o__wspawnvpe(long wstr ptr ptr) ucrtbase._o__wspawnvpe +@ cdecl _o__wsplitpath(wstr ptr ptr ptr ptr) ucrtbase._o__wsplitpath +@ cdecl _o__wsplitpath_s(wstr ptr long ptr long ptr long ptr long) ucrtbase._o__wsplitpath_s +@ cdecl _o__wstat32(wstr ptr) ucrtbase._o__wstat32 +@ cdecl _o__wstat32i64(wstr ptr) ucrtbase._o__wstat32i64 +@ cdecl _o__wstat64(wstr ptr) ucrtbase._o__wstat64 +@ cdecl _o__wstat64i32(wstr ptr) ucrtbase._o__wstat64i32 +@ cdecl _o__wstrdate(ptr) ucrtbase._o__wstrdate +@ cdecl _o__wstrdate_s(ptr long) ucrtbase._o__wstrdate_s +@ cdecl _o__wstrtime(ptr) ucrtbase._o__wstrtime +@ cdecl _o__wstrtime_s(ptr long) ucrtbase._o__wstrtime_s +@ cdecl _o__wsystem(wstr) ucrtbase._o__wsystem +@ cdecl _o__wtmpnam_s(ptr long) ucrtbase._o__wtmpnam_s +@ cdecl _o__wtof(wstr) ucrtbase._o__wtof +@ cdecl _o__wtof_l(wstr ptr) ucrtbase._o__wtof_l +@ cdecl _o__wtoi(wstr) ucrtbase._o__wtoi +@ cdecl -ret64 _o__wtoi64(wstr) ucrtbase._o__wtoi64 +@ cdecl -ret64 _o__wtoi64_l(wstr ptr) ucrtbase._o__wtoi64_l +@ cdecl _o__wtoi_l(wstr ptr) ucrtbase._o__wtoi_l +@ cdecl _o__wtol(wstr) ucrtbase._o__wtol +@ cdecl _o__wtol_l(wstr ptr) ucrtbase._o__wtol_l +@ cdecl -ret64 _o__wtoll(wstr) ucrtbase._o__wtoll +@ cdecl -ret64 _o__wtoll_l(wstr ptr) ucrtbase._o__wtoll_l +@ cdecl _o__wunlink(wstr) ucrtbase._o__wunlink +@ cdecl _o__wutime32(wstr ptr) ucrtbase._o__wutime32 +@ cdecl _o__wutime64(wstr ptr) ucrtbase._o__wutime64 +@ cdecl _o__y0(double) ucrtbase._o__y0 +@ cdecl _o__y1(double) ucrtbase._o__y1 +@ cdecl _o__yn(long double) ucrtbase._o__yn +@ cdecl _o_abort() ucrtbase._o_abort +@ cdecl _o_acos(double) ucrtbase._o_acos +@ cdecl -arch=!i386 _o_acosf(float) ucrtbase._o_acosf +@ cdecl _o_acosh(double) ucrtbase._o_acosh +@ cdecl _o_acoshf(float) ucrtbase._o_acoshf +@ cdecl _o_acoshl(double) ucrtbase._o_acoshl +@ cdecl _o_asctime(ptr) ucrtbase._o_asctime +@ cdecl _o_asctime_s(ptr long ptr) ucrtbase._o_asctime_s +@ cdecl _o_asin(double) ucrtbase._o_asin +@ cdecl -arch=!i386 _o_asinf(float) ucrtbase._o_asinf +@ cdecl _o_asinh(double) ucrtbase._o_asinh +@ cdecl _o_asinhf(float) ucrtbase._o_asinhf +@ cdecl _o_asinhl(double) ucrtbase._o_asinhl +@ cdecl _o_atan(double) ucrtbase._o_atan +@ cdecl _o_atan2(double double) ucrtbase._o_atan2 +@ cdecl -arch=!i386 _o_atan2f(float float) ucrtbase._o_atan2f +@ cdecl -arch=!i386 _o_atanf(float) ucrtbase._o_atanf +@ cdecl _o_atanh(double) ucrtbase._o_atanh +@ cdecl _o_atanhf(float) ucrtbase._o_atanhf +@ cdecl _o_atanhl(double) ucrtbase._o_atanhl @ cdecl _o_atof(str) ucrtbase._o_atof @ cdecl _o_atoi(str) ucrtbase._o_atoi -@ stub _o_atol -@ stub _o_atoll -@ stub _o_bsearch -@ stub _o_bsearch_s -@ stub _o_btowc +@ cdecl _o_atol(str) ucrtbase._o_atol +@ cdecl -ret64 _o_atoll(str) ucrtbase._o_atoll +@ cdecl _o_bsearch(ptr ptr long long ptr) ucrtbase._o_bsearch +@ cdecl _o_bsearch_s(ptr ptr long long ptr ptr) ucrtbase._o_bsearch_s +@ cdecl _o_btowc(long) ucrtbase._o_btowc @ cdecl _o_calloc(long long) ucrtbase._o_calloc -@ stub _o_cbrt -@ stub _o_cbrtf +@ cdecl _o_cbrt(double) ucrtbase._o_cbrt +@ cdecl _o_cbrtf(float) ucrtbase._o_cbrtf @ cdecl _o_ceil(double) ucrtbase._o_ceil -@ stub _o_ceilf -@ stub _o_clearerr -@ stub _o_clearerr_s -@ stub _o_cos -@ stub _o_cosf -@ stub _o_cosh -@ stub _o_coshf -@ stub _o_erf -@ stub _o_erfc -@ stub _o_erfcf -@ stub _o_erfcl -@ stub _o_erff -@ stub _o_erfl +@ cdecl -arch=!i386 _o_ceilf(float) ucrtbase._o_ceilf +@ cdecl _o_clearerr(ptr) ucrtbase._o_clearerr +@ cdecl _o_clearerr_s(ptr) ucrtbase._o_clearerr_s +@ cdecl _o_cos(double) ucrtbase._o_cos +@ cdecl -arch=!i386 _o_cosf(float) ucrtbase._o_cosf +@ cdecl _o_cosh(double) ucrtbase._o_cosh +@ cdecl -arch=!i386 _o_coshf(float) ucrtbase._o_coshf +@ cdecl _o_erf(double) ucrtbase._o_erf +@ cdecl _o_erfc(double) ucrtbase._o_erfc +@ cdecl _o_erfcf(float) ucrtbase._o_erfcf +@ cdecl _o_erfcl(double) ucrtbase._o_erfcl +@ cdecl _o_erff(float) ucrtbase._o_erff +@ cdecl _o_erfl(double) ucrtbase._o_erfl @ cdecl _o_exit(long) ucrtbase._o_exit -@ stub _o_exp -@ stub _o_exp2 -@ stub _o_exp2f -@ stub _o_exp2l -@ stub _o_expf -@ stub _o_fabs -@ stub _o_fclose -@ stub _o_feof -@ stub _o_ferror -@ stub _o_fflush -@ stub _o_fgetc -@ stub _o_fgetpos -@ stub _o_fgets -@ stub _o_fgetwc -@ stub _o_fgetws +@ cdecl _o_exp(double) ucrtbase._o_exp +@ cdecl _o_exp2(double) ucrtbase._o_exp2 +@ cdecl _o_exp2f(float) ucrtbase._o_exp2f +@ cdecl _o_exp2l(double) ucrtbase._o_exp2l +@ cdecl -arch=!i386 _o_expf(float) ucrtbase._o_expf +@ cdecl _o_fabs(double) ucrtbase._o_fabs +@ cdecl _o_fclose(ptr) ucrtbase._o_fclose +@ cdecl _o_feof(ptr) ucrtbase._o_feof +@ cdecl _o_ferror(ptr) ucrtbase._o_ferror +@ cdecl _o_fflush(ptr) ucrtbase._o_fflush +@ cdecl _o_fgetc(ptr) ucrtbase._o_fgetc +@ cdecl _o_fgetpos(ptr ptr) ucrtbase._o_fgetpos +@ cdecl _o_fgets(ptr long ptr) ucrtbase._o_fgets +@ cdecl _o_fgetwc(ptr) ucrtbase._o_fgetwc +@ cdecl _o_fgetws(ptr long ptr) ucrtbase._o_fgetws @ cdecl _o_floor(double) ucrtbase._o_floor -@ stub _o_floorf -@ stub _o_fma -@ stub _o_fmaf -@ stub _o_fmal +@ cdecl -arch=!i386 _o_floorf(float) ucrtbase._o_floorf +@ cdecl _o_fma(double double double) ucrtbase._o_fma +@ cdecl _o_fmaf(float float float) ucrtbase._o_fmaf +@ cdecl _o_fmal(double double double) ucrtbase._o_fmal @ cdecl _o_fmod(double double) ucrtbase._o_fmod @ cdecl -arch=!i386 _o_fmodf(float float) ucrtbase._o_fmodf -@ stub _o_fopen -@ stub _o_fopen_s -@ stub _o_fputc -@ stub _o_fputs -@ stub _o_fputwc -@ stub _o_fputws -@ stub _o_fread -@ stub _o_fread_s +@ cdecl _o_fopen(str str) ucrtbase._o_fopen +@ cdecl _o_fopen_s(ptr str str) ucrtbase._o_fopen_s +@ cdecl _o_fputc(long ptr) ucrtbase._o_fputc +@ cdecl _o_fputs(str ptr) ucrtbase._o_fputs +@ cdecl _o_fputwc(long ptr) ucrtbase._o_fputwc +@ cdecl _o_fputws(wstr ptr) ucrtbase._o_fputws +@ cdecl _o_fread(ptr long long ptr) ucrtbase._o_fread +@ cdecl _o_fread_s(ptr long long long ptr) ucrtbase._o_fread_s @ cdecl _o_free(ptr) ucrtbase._o_free -@ stub _o_freopen -@ stub _o_freopen_s -@ stub _o_frexp -@ stub _o_fseek -@ stub _o_fsetpos -@ stub _o_ftell -@ stub _o_fwrite -@ stub _o_getc -@ stub _o_getchar +@ cdecl _o_freopen(str str ptr) ucrtbase._o_freopen +@ cdecl _o_freopen_s(ptr str str ptr) ucrtbase._o_freopen_s +@ cdecl _o_frexp(double ptr) ucrtbase._o_frexp +@ cdecl _o_fseek(ptr long long) ucrtbase._o_fseek +@ cdecl _o_fsetpos(ptr ptr) ucrtbase._o_fsetpos +@ cdecl _o_ftell(ptr) ucrtbase._o_ftell +@ cdecl _o_fwrite(ptr long long ptr) ucrtbase._o_fwrite +@ cdecl _o_getc(ptr) ucrtbase._o_getc +@ cdecl _o_getchar() ucrtbase._o_getchar @ cdecl _o_getenv(str) ucrtbase._o_getenv -@ stub _o_getenv_s -@ stub _o_gets -@ stub _o_gets_s -@ stub _o_getwc -@ stub _o_getwchar -@ stub _o_hypot -@ stub _o_is_wctype +@ cdecl _o_getenv_s(ptr ptr long str) ucrtbase._o_getenv_s +@ cdecl _o_gets(str) ucrtbase._o_gets +@ cdecl _o_gets_s(ptr long) ucrtbase._o_gets_s +@ cdecl _o_getwc(ptr) ucrtbase._o_getwc +@ cdecl _o_getwchar() ucrtbase._o_getwchar +@ cdecl _o_hypot(double double) ucrtbase._o_hypot +@ cdecl _o_is_wctype(long long) ucrtbase._o_is_wctype @ cdecl _o_isalnum(long) ucrtbase._o_isalnum @ cdecl _o_isalpha(long) ucrtbase._o_isalpha -@ stub _o_isblank -@ stub _o_iscntrl +@ cdecl _o_isblank(long) ucrtbase._o_isblank +@ cdecl _o_iscntrl(long) ucrtbase._o_iscntrl @ cdecl _o_isdigit(long) ucrtbase._o_isdigit -@ stub _o_isgraph -@ stub _o_isleadbyte -@ stub _o_islower +@ cdecl _o_isgraph(long) ucrtbase._o_isgraph +@ cdecl _o_isleadbyte(long) ucrtbase._o_isleadbyte +@ cdecl _o_islower(long) ucrtbase._o_islower @ cdecl _o_isprint(long) ucrtbase._o_isprint -@ stub _o_ispunct -@ stub _o_isspace -@ stub _o_isupper -@ stub _o_iswalnum -@ stub _o_iswalpha -@ stub _o_iswascii -@ stub _o_iswblank -@ stub _o_iswcntrl -@ stub _o_iswctype -@ stub _o_iswdigit -@ stub _o_iswgraph -@ stub _o_iswlower -@ stub _o_iswprint -@ stub _o_iswpunct -@ stub _o_iswspace -@ stub _o_iswupper -@ stub _o_iswxdigit +@ cdecl _o_ispunct(long) ucrtbase._o_ispunct +@ cdecl _o_isspace(long) ucrtbase._o_isspace +@ cdecl _o_isupper(long) ucrtbase._o_isupper +@ cdecl _o_iswalnum(long) ucrtbase._o_iswalnum +@ cdecl _o_iswalpha(long) ucrtbase._o_iswalpha +@ cdecl _o_iswascii(long) ucrtbase._o_iswascii +@ cdecl _o_iswblank(long) ucrtbase._o_iswblank +@ cdecl _o_iswcntrl(long) ucrtbase._o_iswcntrl +@ cdecl _o_iswctype(long long) ucrtbase._o_iswctype +@ cdecl _o_iswdigit(long) ucrtbase._o_iswdigit +@ cdecl _o_iswgraph(long) ucrtbase._o_iswgraph +@ cdecl _o_iswlower(long) ucrtbase._o_iswlower +@ cdecl _o_iswprint(long) ucrtbase._o_iswprint +@ cdecl _o_iswpunct(long) ucrtbase._o_iswpunct +@ cdecl _o_iswspace(long) ucrtbase._o_iswspace +@ cdecl _o_iswupper(long) ucrtbase._o_iswupper +@ cdecl _o_iswxdigit(long) ucrtbase._o_iswxdigit @ cdecl _o_isxdigit(long) ucrtbase._o_isxdigit -@ stub _o_ldexp -@ stub _o_lgamma -@ stub _o_lgammaf -@ stub _o_lgammal -@ stub _o_llrint -@ stub _o_llrintf -@ stub _o_llrintl -@ stub _o_llround -@ stub _o_llroundf -@ stub _o_llroundl -@ stub _o_localeconv +@ cdecl _o_ldexp(double long) ucrtbase._o_ldexp +@ cdecl _o_lgamma(double) ucrtbase._o_lgamma +@ cdecl _o_lgammaf(float) ucrtbase._o_lgammaf +@ cdecl _o_lgammal(double) ucrtbase._o_lgammal +@ cdecl -ret64 _o_llrint(double) ucrtbase._o_llrint +@ cdecl -ret64 _o_llrintf(float) ucrtbase._o_llrintf +@ cdecl -ret64 _o_llrintl(double) ucrtbase._o_llrintl +@ cdecl -ret64 _o_llround(double) ucrtbase._o_llround +@ cdecl -ret64 _o_llroundf(float) ucrtbase._o_llroundf +@ cdecl -ret64 _o_llroundl(double) ucrtbase._o_llroundl +@ cdecl _o_localeconv() ucrtbase._o_localeconv @ cdecl _o_log(double) ucrtbase._o_log -@ stub _o_log10 -@ stub _o_log10f -@ stub _o_log1p -@ stub _o_log1pf -@ stub _o_log1pl -@ stub _o_log2 -@ stub _o_log2f -@ stub _o_log2l -@ stub _o_logb -@ stub _o_logbf -@ stub _o_logbl -@ stub _o_logf -@ stub _o_lrint -@ stub _o_lrintf -@ stub _o_lrintl -@ stub _o_lround -@ stub _o_lroundf -@ stub _o_lroundl +@ cdecl _o_log10(double) ucrtbase._o_log10 +@ cdecl -arch=!i386 _o_log10f(float) ucrtbase._o_log10f +@ cdecl _o_log1p(double) ucrtbase._o_log1p +@ cdecl _o_log1pf(float) ucrtbase._o_log1pf +@ cdecl _o_log1pl(double) ucrtbase._o_log1pl +@ cdecl _o_log2(double) ucrtbase._o_log2 +@ cdecl _o_log2f(float) ucrtbase._o_log2f +@ cdecl _o_log2l(double) ucrtbase._o_log2l +@ cdecl _o_logb(double) ucrtbase._o_logb +@ cdecl _o_logbf(float) ucrtbase._o_logbf +@ cdecl _o_logbl(double) ucrtbase._o_logbl +@ cdecl -arch=!i386 _o_logf(float) ucrtbase._o_logf +@ cdecl _o_lrint(double) ucrtbase._o_lrint +@ cdecl _o_lrintf(float) ucrtbase._o_lrintf +@ cdecl _o_lrintl(double) ucrtbase._o_lrintl +@ cdecl _o_lround(double) ucrtbase._o_lround +@ cdecl _o_lroundf(float) ucrtbase._o_lroundf +@ cdecl _o_lroundl(double) ucrtbase._o_lroundl @ cdecl _o_malloc(long) ucrtbase._o_malloc -@ stub _o_mblen -@ stub _o_mbrlen +@ cdecl _o_mblen(ptr long) ucrtbase._o_mblen +@ cdecl _o_mbrlen(ptr long ptr) ucrtbase._o_mbrlen @ stub _o_mbrtoc16 @ stub _o_mbrtoc32 -@ stub _o_mbrtowc -@ stub _o_mbsrtowcs -@ stub _o_mbsrtowcs_s -@ stub _o_mbstowcs -@ stub _o_mbstowcs_s -@ stub _o_mbtowc -@ stub _o_memcpy_s +@ cdecl _o_mbrtowc(ptr str long ptr) ucrtbase._o_mbrtowc +@ cdecl _o_mbsrtowcs(ptr ptr long ptr) ucrtbase._o_mbsrtowcs +@ cdecl _o_mbsrtowcs_s(ptr ptr long ptr long ptr) ucrtbase._o_mbsrtowcs_s +@ cdecl _o_mbstowcs(ptr str long) ucrtbase._o_mbstowcs +@ cdecl _o_mbstowcs_s(ptr ptr long str long) ucrtbase._o_mbstowcs_s +@ cdecl _o_mbtowc(ptr str long) ucrtbase._o_mbtowc +@ cdecl _o_memcpy_s(ptr long ptr long) ucrtbase._o_memcpy_s @ cdecl _o_modf(double ptr) ucrtbase._o_modf -@ stub _o_modff -@ stub _o_nan -@ stub _o_nanf -@ stub _o_nanl -@ stub _o_nearbyint -@ stub _o_nearbyintf -@ stub _o_nearbyintl -@ stub _o_nextafter -@ stub _o_nextafterf -@ stub _o_nextafterl -@ stub _o_nexttoward -@ stub _o_nexttowardf -@ stub _o_nexttowardl +@ cdecl -arch=!i386 _o_modff(float ptr) ucrtbase._o_modff +@ cdecl _o_nan(str) ucrtbase._o_nan +@ cdecl _o_nanf(str) ucrtbase._o_nanf +@ cdecl _o_nanl(str) ucrtbase._o_nanl +@ cdecl _o_nearbyint(double) ucrtbase._o_nearbyint +@ cdecl _o_nearbyintf(float) ucrtbase._o_nearbyintf +@ cdecl _o_nearbyintl(double) ucrtbase._o_nearbyintl +@ cdecl _o_nextafter(double double) ucrtbase._o_nextafter +@ cdecl _o_nextafterf(float float) ucrtbase._o_nextafterf +@ cdecl _o_nextafterl(double double) ucrtbase._o_nextafterl +@ cdecl _o_nexttoward(double double) ucrtbase._o_nexttoward +@ cdecl _o_nexttowardf(float double) ucrtbase._o_nexttowardf +@ cdecl _o_nexttowardl(double double) ucrtbase._o_nexttowardl @ cdecl _o_pow(double double) ucrtbase._o_pow -@ stub _o_powf -@ stub _o_putc -@ stub _o_putchar -@ stub _o_puts -@ stub _o_putwc -@ stub _o_putwchar +@ cdecl -arch=!i386 _o_powf(float float) ucrtbase._o_powf +@ cdecl _o_putc(long ptr) ucrtbase._o_putc +@ cdecl _o_putchar(long) ucrtbase._o_putchar +@ cdecl _o_puts(str) ucrtbase._o_puts +@ cdecl _o_putwc(long ptr) ucrtbase._o_putwc +@ cdecl _o_putwchar(long) ucrtbase._o_putwchar @ cdecl _o_qsort(ptr long long ptr) ucrtbase._o_qsort -@ stub _o_qsort_s -@ stub _o_raise -@ stub _o_rand -@ stub _o_rand_s +@ cdecl _o_qsort_s(ptr long long ptr ptr) ucrtbase._o_qsort_s +@ cdecl _o_raise(long) ucrtbase._o_raise +@ cdecl _o_rand() ucrtbase._o_rand +@ cdecl _o_rand_s(ptr) ucrtbase._o_rand_s @ cdecl _o_realloc(ptr long) ucrtbase._o_realloc -@ stub _o_remainder -@ stub _o_remainderf -@ stub _o_remainderl -@ stub _o_remove -@ stub _o_remquo -@ stub _o_remquof -@ stub _o_remquol -@ stub _o_rename -@ stub _o_rewind -@ stub _o_rint -@ stub _o_rintf -@ stub _o_rintl -@ stub _o_round -@ stub _o_roundf -@ stub _o_roundl -@ stub _o_scalbln -@ stub _o_scalblnf -@ stub _o_scalblnl -@ stub _o_scalbn -@ stub _o_scalbnf -@ stub _o_scalbnl -@ stub _o_set_terminate -@ stub _o_setbuf +@ cdecl _o_remainder(double double) ucrtbase._o_remainder +@ cdecl _o_remainderf(float float) ucrtbase._o_remainderf +@ cdecl _o_remainderl(double double) ucrtbase._o_remainderl +@ cdecl _o_remove(str) ucrtbase._o_remove +@ cdecl _o_remquo(double double ptr) ucrtbase._o_remquo +@ cdecl _o_remquof(float float ptr) ucrtbase._o_remquof +@ cdecl _o_remquol(double double ptr) ucrtbase._o_remquol +@ cdecl _o_rename(str str) ucrtbase._o_rename +@ cdecl _o_rewind(ptr) ucrtbase._o_rewind +@ cdecl _o_rint(double) ucrtbase._o_rint +@ cdecl _o_rintf(float) ucrtbase._o_rintf +@ cdecl _o_rintl(double) ucrtbase._o_rintl +@ cdecl _o_round(double) ucrtbase._o_round +@ cdecl _o_roundf(float) ucrtbase._o_roundf +@ cdecl _o_roundl(double) ucrtbase._o_roundl +@ cdecl _o_scalbln(double long) ucrtbase._o_scalbln +@ cdecl _o_scalblnf(float long) ucrtbase._o_scalblnf +@ cdecl _o_scalblnl(double long) ucrtbase._o_scalblnl +@ cdecl _o_scalbn(double long) ucrtbase._o_scalbn +@ cdecl _o_scalbnf(float long) ucrtbase._o_scalbnf +@ cdecl _o_scalbnl(double long) ucrtbase._o_scalbnl +@ cdecl _o_set_terminate(ptr) ucrtbase._o_set_terminate +@ cdecl _o_setbuf(ptr ptr) ucrtbase._o_setbuf @ cdecl _o_setlocale(long str) ucrtbase._o_setlocale -@ stub _o_setvbuf -@ stub _o_sin -@ stub _o_sinf -@ stub _o_sinh -@ stub _o_sinhf +@ cdecl _o_setvbuf(ptr str long long) ucrtbase._o_setvbuf +@ cdecl _o_sin(double) ucrtbase._o_sin +@ cdecl -arch=!i386 _o_sinf(float) ucrtbase._o_sinf +@ cdecl _o_sinh(double) ucrtbase._o_sinh +@ cdecl -arch=!i386 _o_sinhf(float) ucrtbase._o_sinhf @ cdecl _o_sqrt(double) ucrtbase._o_sqrt -@ stub _o_sqrtf -@ stub _o_srand +@ cdecl -arch=!i386 _o_sqrtf(float) ucrtbase._o_sqrtf +@ cdecl _o_srand(long) ucrtbase._o_srand @ cdecl _o_strcat_s(str long str) ucrtbase._o_strcat_s -@ stub _o_strcoll -@ stub _o_strcpy_s -@ stub _o_strerror -@ stub _o_strerror_s -@ stub _o_strftime -@ stub _o_strncat_s -@ stub _o_strncpy_s -@ stub _o_strtod -@ stub _o_strtof -@ stub _o_strtok -@ stub _o_strtok_s -@ stub _o_strtol +@ cdecl _o_strcoll(str str) ucrtbase._o_strcoll +@ cdecl _o_strcpy_s(ptr long str) ucrtbase._o_strcpy_s +@ cdecl _o_strerror(long) ucrtbase._o_strerror +@ cdecl _o_strerror_s(ptr long long) ucrtbase._o_strerror_s +@ cdecl _o_strftime(ptr long str ptr) ucrtbase._o_strftime +@ cdecl _o_strncat_s(str long str long) ucrtbase._o_strncat_s +@ cdecl _o_strncpy_s(ptr long str long) ucrtbase._o_strncpy_s +@ cdecl _o_strtod(str ptr) ucrtbase._o_strtod +@ cdecl _o_strtof(str ptr) ucrtbase._o_strtof +@ cdecl _o_strtok(str str) ucrtbase._o_strtok +@ cdecl _o_strtok_s(ptr str ptr) ucrtbase._o_strtok_s +@ cdecl _o_strtol(str ptr long) ucrtbase._o_strtol @ stub _o_strtold -@ stub _o_strtoll +@ cdecl -ret64 _o_strtoll(str ptr long) ucrtbase._o_strtoll @ cdecl _o_strtoul(str ptr long) ucrtbase._o_strtoul -@ stub _o_strtoull -@ stub _o_system -@ stub _o_tan -@ stub _o_tanf -@ stub _o_tanh -@ stub _o_tanhf -@ stub _o_terminate -@ stub _o_tgamma -@ stub _o_tgammaf -@ stub _o_tgammal -@ stub _o_tmpfile_s -@ stub _o_tmpnam_s +@ cdecl -ret64 _o_strtoull(str ptr long) ucrtbase._o_strtoull +@ cdecl _o_system(str) ucrtbase._o_system +@ cdecl _o_tan(double) ucrtbase._o_tan +@ cdecl -arch=!i386 _o_tanf(float) ucrtbase._o_tanf +@ cdecl _o_tanh(double) ucrtbase._o_tanh +@ cdecl -arch=!i386 _o_tanhf(float) ucrtbase._o_tanhf +@ cdecl _o_terminate() ucrtbase._o_terminate +@ cdecl _o_tgamma(double) ucrtbase._o_tgamma +@ cdecl _o_tgammaf(float) ucrtbase._o_tgammaf +@ cdecl _o_tgammal(double) ucrtbase._o_tgammal +@ cdecl _o_tmpfile_s(ptr) ucrtbase._o_tmpfile_s +@ cdecl _o_tmpnam_s(ptr long) ucrtbase._o_tmpnam_s @ cdecl _o_tolower(long) ucrtbase._o_tolower @ cdecl _o_toupper(long) ucrtbase._o_toupper -@ stub _o_towlower -@ stub _o_towupper -@ stub _o_ungetc -@ stub _o_ungetwc -@ stub _o_wcrtomb -@ stub _o_wcrtomb_s -@ stub _o_wcscat_s -@ stub _o_wcscoll -@ stub _o_wcscpy -@ stub _o_wcscpy_s -@ stub _o_wcsftime -@ stub _o_wcsncat_s -@ stub _o_wcsncpy_s -@ stub _o_wcsrtombs -@ stub _o_wcsrtombs_s -@ stub _o_wcstod -@ stub _o_wcstof -@ stub _o_wcstok -@ stub _o_wcstok_s -@ stub _o_wcstol +@ cdecl _o_towlower(long) ucrtbase._o_towlower +@ cdecl _o_towupper(long) ucrtbase._o_towupper +@ cdecl _o_ungetc(long ptr) ucrtbase._o_ungetc +@ cdecl _o_ungetwc(long ptr) ucrtbase._o_ungetwc +@ cdecl _o_wcrtomb(ptr long ptr) ucrtbase._o_wcrtomb +@ cdecl _o_wcrtomb_s(ptr ptr long long ptr) ucrtbase._o_wcrtomb_s +@ cdecl _o_wcscat_s(wstr long wstr) ucrtbase._o_wcscat_s +@ cdecl _o_wcscoll(wstr wstr) ucrtbase._o_wcscoll +@ cdecl _o_wcscpy(ptr wstr) ucrtbase._o_wcscpy +@ cdecl _o_wcscpy_s(ptr long wstr) ucrtbase._o_wcscpy_s +@ cdecl _o_wcsftime(ptr long wstr ptr) ucrtbase._o_wcsftime +@ cdecl _o_wcsncat_s(wstr long wstr long) ucrtbase._o_wcsncat_s +@ cdecl _o_wcsncpy_s(ptr long wstr long) ucrtbase._o_wcsncpy_s +@ cdecl _o_wcsrtombs(ptr ptr long ptr) ucrtbase._o_wcsrtombs +@ cdecl _o_wcsrtombs_s(ptr ptr long ptr long ptr) ucrtbase._o_wcsrtombs_s +@ cdecl _o_wcstod(wstr ptr) ucrtbase._o_wcstod +@ cdecl _o_wcstof(ptr ptr) ucrtbase._o_wcstof +@ cdecl _o_wcstok(wstr wstr ptr) ucrtbase._o_wcstok +@ cdecl _o_wcstok_s(ptr wstr ptr) ucrtbase._o_wcstok_s +@ cdecl _o_wcstol(wstr ptr long) ucrtbase._o_wcstol @ stub _o_wcstold -@ stub _o_wcstoll -@ stub _o_wcstombs -@ stub _o_wcstombs_s -@ stub _o_wcstoul -@ stub _o_wcstoull -@ stub _o_wctob -@ stub _o_wctomb -@ stub _o_wctomb_s -@ stub _o_wmemcpy_s -@ stub _o_wmemmove_s +@ cdecl -ret64 _o_wcstoll(wstr ptr long) ucrtbase._o_wcstoll +@ cdecl _o_wcstombs(ptr ptr long) ucrtbase._o_wcstombs +@ cdecl _o_wcstombs_s(ptr ptr long wstr long) ucrtbase._o_wcstombs_s +@ cdecl _o_wcstoul(wstr ptr long) ucrtbase._o_wcstoul +@ cdecl -ret64 _o_wcstoull(wstr ptr long) ucrtbase._o_wcstoull +@ cdecl _o_wctob(long) ucrtbase._o_wctob +@ cdecl _o_wctomb(ptr long) ucrtbase._o_wctomb +@ cdecl _o_wctomb_s(ptr ptr long long) ucrtbase._o_wctomb_s +@ cdecl _o_wmemcpy_s(ptr long ptr long) ucrtbase._o_wmemcpy_s +@ cdecl _o_wmemmove_s(ptr long ptr long) ucrtbase._o_wmemmove_s @ cdecl _purecall() ucrtbase._purecall @ stdcall -arch=i386 _seh_longjmp_unwind(ptr) ucrtbase._seh_longjmp_unwind @ stdcall -arch=i386 _seh_longjmp_unwind4(ptr) ucrtbase._seh_longjmp_unwind4 diff -Nru wine-development-5.8/dlls/api-ms-win-downlevel-shlwapi-l2-1-0/api-ms-win-downlevel-shlwapi-l2-1-0.spec wine-development-5.9/dlls/api-ms-win-downlevel-shlwapi-l2-1-0/api-ms-win-downlevel-shlwapi-l2-1-0.spec --- wine-development-5.8/dlls/api-ms-win-downlevel-shlwapi-l2-1-0/api-ms-win-downlevel-shlwapi-l2-1-0.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/api-ms-win-downlevel-shlwapi-l2-1-0/api-ms-win-downlevel-shlwapi-l2-1-0.spec 2020-05-22 18:49:34.000000000 +0000 @@ -23,15 +23,15 @@ @ stdcall SHDeleteEmptyKeyW(long wstr) shlwapi.SHDeleteEmptyKeyW @ stdcall SHDeleteKeyA(long str) shlwapi.SHDeleteKeyA @ stdcall SHDeleteKeyW(long wstr) shlwapi.SHDeleteKeyW -@ stdcall SHDeleteValueA(long str str) shlwapi.SHDeleteValueA +@ stdcall SHDeleteValueA(long str str) shlwapi.SHDeleteValueA @ stdcall SHDeleteValueW(long wstr wstr) shlwapi.SHDeleteValueW @ stdcall SHEnumKeyExA(long long str ptr) shlwapi.SHEnumKeyExA @ stdcall SHEnumKeyExW(long long wstr ptr) shlwapi.SHEnumKeyExW @ stdcall SHEnumValueA(long long str ptr ptr ptr ptr) shlwapi.SHEnumValueA @ stdcall SHEnumValueW(long long wstr ptr ptr ptr ptr) shlwapi.SHEnumValueW @ stdcall SHGetThreadRef(ptr) shlwapi.SHGetThreadRef -@ stdcall SHGetValueA( long str str ptr ptr ptr ) shlwapi.SHGetValueA -@ stdcall SHGetValueW( long wstr wstr ptr ptr ptr ) shlwapi.SHGetValueW +@ stdcall SHGetValueA(long str str ptr ptr ptr) shlwapi.SHGetValueA +@ stdcall SHGetValueW(long wstr wstr ptr ptr ptr) shlwapi.SHGetValueW @ stdcall SHOpenRegStream2A(long str str long) shlwapi.SHOpenRegStream2A @ stdcall SHOpenRegStream2W(long wstr wstr long) shlwapi.SHOpenRegStream2W @ stdcall SHOpenRegStreamA(long str str long) shlwapi.SHOpenRegStreamA @@ -49,7 +49,7 @@ @ stdcall SHRegSetPathW(long wstr wstr wstr long) shlwapi.SHRegSetPathW @ stdcall SHReleaseThreadRef() shlwapi.SHReleaseThreadRef @ stdcall SHSetThreadRef(ptr) shlwapi.SHSetThreadRef -@ stdcall SHSetValueA(long str str long ptr long) shlwapi.SHSetValueA +@ stdcall SHSetValueA(long str str long ptr long) shlwapi.SHSetValueA @ stdcall SHSetValueW(long wstr wstr long ptr long) shlwapi.SHSetValueW @ stdcall SHStrDupW(wstr ptr) shlwapi.SHStrDupW @ stdcall SHUnicodeToAnsi(wstr ptr ptr) shlwapi.SHUnicodeToAnsi diff -Nru wine-development-5.8/dlls/cfgmgr32/cfgmgr32.spec wine-development-5.9/dlls/cfgmgr32/cfgmgr32.spec --- wine-development-5.8/dlls/cfgmgr32/cfgmgr32.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/cfgmgr32/cfgmgr32.spec 2020-05-22 18:49:34.000000000 +0000 @@ -79,8 +79,8 @@ @ stub CM_Get_Device_ID_List_Size_ExW @ stdcall CM_Get_Device_ID_Size(ptr ptr long) setupapi.CM_Get_Device_ID_Size @ stub CM_Get_Device_ID_Size_Ex -@ stub CM_Get_Device_Interface_AliasA -@ stub CM_Get_Device_Interface_AliasW +@ stdcall CM_Get_Device_Interface_AliasA(str ptr ptr ptr long) setupapi.CM_Get_Device_Interface_AliasA +@ stdcall CM_Get_Device_Interface_AliasW(wstr ptr ptr ptr long) setupapi.CM_Get_Device_Interface_AliasW @ stub CM_Get_Device_Interface_Alias_ExA @ stub CM_Get_Device_Interface_Alias_ExW @ stub CM_Get_Device_Interface_ListA diff -Nru wine-development-5.8/dlls/crypt32/cert.c wine-development-5.9/dlls/crypt32/cert.c --- wine-development-5.8/dlls/crypt32/cert.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/crypt32/cert.c 2020-05-22 18:49:34.000000000 +0000 @@ -525,13 +525,19 @@ DWORD i, containerLen, provNameLen; LPBYTE data = (LPBYTE)info + sizeof(CRYPT_KEY_PROV_INFO); - info->pwszContainerName = (LPWSTR)data; - containerLen = (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR); - data += containerLen; + if (info->pwszContainerName) + { + info->pwszContainerName = (LPWSTR)data; + containerLen = (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR); + data += containerLen; + } - info->pwszProvName = (LPWSTR)data; - provNameLen = (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); - data += provNameLen; + if (info->pwszProvName) + { + info->pwszProvName = (LPWSTR)data; + provNameLen = (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); + data += provNameLen; + } if (info->cProvParam) { diff -Nru wine-development-5.8/dlls/crypt32/chain.c wine-development-5.9/dlls/crypt32/chain.c --- wine-development-5.8/dlls/crypt32/chain.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/crypt32/chain.c 2020-05-22 18:49:34.000000000 +0000 @@ -3660,42 +3660,80 @@ 0x60,0x1e,0x7a,0x5b,0x38,0xc8,0x8f,0xbb,0x04,0x26,0x7c,0xd4,0x16,0x40,0xe5, 0xb6,0x6b,0x6c,0xaa,0x86,0xfd,0x00,0xbf,0xce,0xc1,0x35,0x02,0x03,0x01,0x00, 0x01 }; +/* from Microsoft Root Certificate Authority 2010 */ +static BYTE msPubKey4[] = { +0x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xb9,0x08,0x9e,0x28,0xe4,0xe4, +0xec,0x06,0x4e,0x50,0x68,0xb3,0x41,0xc5,0x7b,0xeb,0xae,0xb6,0x8e,0xaf,0x81, +0xba,0x22,0x44,0x1f,0x65,0x34,0x69,0x4c,0xbe,0x70,0x40,0x17,0xf2,0x16,0x7b, +0xe2,0x79,0xfd,0x86,0xed,0x0d,0x39,0xf4,0x1b,0xa8,0xad,0x92,0x90,0x1e,0xcb, +0x3d,0x76,0x8f,0x5a,0xd9,0xb5,0x91,0x10,0x2e,0x3c,0x05,0x8d,0x8a,0x6d,0x24, +0x54,0xe7,0x1f,0xed,0x56,0xad,0x83,0xb4,0x50,0x9c,0x15,0xa5,0x17,0x74,0x88, +0x59,0x20,0xfc,0x08,0xc5,0x84,0x76,0xd3,0x68,0xd4,0x6f,0x28,0x78,0xce,0x5c, +0xb8,0xf3,0x50,0x90,0x44,0xff,0xe3,0x63,0x5f,0xbe,0xa1,0x9a,0x2c,0x96,0x15, +0x04,0xd6,0x07,0xfe,0x1e,0x84,0x21,0xe0,0x42,0x31,0x11,0xc4,0x28,0x36,0x94, +0xcf,0x50,0xa4,0x62,0x9e,0xc9,0xd6,0xab,0x71,0x00,0xb2,0x5b,0x0c,0xe6,0x96, +0xd4,0x0a,0x24,0x96,0xf5,0xff,0xc6,0xd5,0xb7,0x1b,0xd7,0xcb,0xb7,0x21,0x62, +0xaf,0x12,0xdc,0xa1,0x5d,0x37,0xe3,0x1a,0xfb,0x1a,0x46,0x98,0xc0,0x9b,0xc0, +0xe7,0x63,0x1f,0x2a,0x08,0x93,0x02,0x7e,0x1e,0x6a,0x8e,0xf2,0x9f,0x18,0x89, +0xe4,0x22,0x85,0xa2,0xb1,0x84,0x57,0x40,0xff,0xf5,0x0e,0xd8,0x6f,0x9c,0xed, +0xe2,0x45,0x31,0x01,0xcd,0x17,0xe9,0x7f,0xb0,0x81,0x45,0xe3,0xaa,0x21,0x40, +0x26,0xa1,0x72,0xaa,0xa7,0x4f,0x3c,0x01,0x05,0x7e,0xee,0x83,0x58,0xb1,0x5e, +0x06,0x63,0x99,0x62,0x91,0x78,0x82,0xb7,0x0d,0x93,0x0c,0x24,0x6a,0xb4,0x1b, +0xdb,0x27,0xec,0x5f,0x95,0x04,0x3f,0x93,0x4a,0x30,0xf5,0x97,0x18,0xb3,0xa7, +0xf9,0x19,0xa7,0x93,0x33,0x1d,0x01,0xc8,0xdb,0x22,0x52,0x5c,0xd7,0x25,0xc9, +0x46,0xf9,0xa2,0xfb,0x87,0x59,0x43,0xbe,0x9b,0x62,0xb1,0x8d,0x2d,0x86,0x44, +0x1a,0x46,0xac,0x78,0x61,0x7e,0x30,0x09,0xfa,0xae,0x89,0xc4,0x41,0x2a,0x22, +0x66,0x03,0x91,0x39,0x45,0x9c,0xc7,0x8b,0x0c,0xa8,0xca,0x0d,0x2f,0xfb,0x52, +0xea,0x0c,0xf7,0x63,0x33,0x23,0x9d,0xfe,0xb0,0x1f,0xad,0x67,0xd6,0xa7,0x50, +0x03,0xc6,0x04,0x70,0x63,0xb5,0x2c,0xb1,0x86,0x5a,0x43,0xb7,0xfb,0xae,0xf9, +0x6e,0x29,0x6e,0x21,0x21,0x41,0x26,0x06,0x8c,0xc9,0xc3,0xee,0xb0,0xc2,0x85, +0x93,0xa1,0xb9,0x85,0xd9,0xe6,0x32,0x6c,0x4b,0x4c,0x3f,0xd6,0x5d,0xa3,0xe5, +0xb5,0x9d,0x77,0xc3,0x9c,0xc0,0x55,0xb7,0x74,0x00,0xe3,0xb8,0x38,0xab,0x83, +0x97,0x50,0xe1,0x9a,0x42,0x24,0x1d,0xc6,0xc0,0xa3,0x30,0xd1,0x1a,0x5a,0xc8, +0x52,0x34,0xf7,0x73,0xf1,0xc7,0x18,0x1f,0x33,0xad,0x7a,0xec,0xcb,0x41,0x60, +0xf3,0x23,0x94,0x20,0xc2,0x48,0x45,0xac,0x5c,0x51,0xc6,0x2e,0x80,0xc2,0xe2, +0x77,0x15,0xbd,0x85,0x87,0xed,0x36,0x9d,0x96,0x91,0xee,0x00,0xb5,0xa3,0x70, +0xec,0x9f,0xe3,0x8d,0x80,0x68,0x83,0x76,0xba,0xaf,0x5d,0x70,0x52,0x22,0x16, +0xe2,0x66,0xfb,0xba,0xb3,0xc5,0xc2,0xf7,0x3e,0x2f,0x77,0xa6,0xca,0xde,0xc1, +0xa6,0xc6,0x48,0x4c,0xc3,0x37,0x51,0x23,0xd3,0x27,0xd7,0xb8,0x4e,0x70,0x96, +0xf0,0xa1,0x44,0x76,0xaf,0x78,0xcf,0x9a,0xe1,0x66,0x13,0x02,0x03,0x01,0x00, +0x01 }; static BOOL WINAPI verify_ms_root_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus) { - BOOL ret = verify_base_policy(szPolicyOID, pChainContext, pPolicyPara, - pPolicyStatus); + BOOL isMSRoot = FALSE; + + CERT_PUBLIC_KEY_INFO msPubKey = { { 0 } }; + DWORD i; + CRYPT_DATA_BLOB keyBlobs[] = { + { sizeof(msPubKey1), msPubKey1 }, + { sizeof(msPubKey2), msPubKey2 }, + { sizeof(msPubKey3), msPubKey3 }, + { sizeof(msPubKey4), msPubKey4 }, + }; + PCERT_SIMPLE_CHAIN rootChain = + pChainContext->rgpChain[pChainContext->cChain - 1]; + PCCERT_CONTEXT root = + rootChain->rgpElement[rootChain->cElement - 1]->pCertContext; - if (ret && !pPolicyStatus->dwError) + for (i = 0; !isMSRoot && i < ARRAY_SIZE(keyBlobs); i++) { - CERT_PUBLIC_KEY_INFO msPubKey = { { 0 } }; - BOOL isMSRoot = FALSE; - DWORD i; - CRYPT_DATA_BLOB keyBlobs[] = { - { sizeof(msPubKey1), msPubKey1 }, - { sizeof(msPubKey2), msPubKey2 }, - { sizeof(msPubKey3), msPubKey3 }, - }; - PCERT_SIMPLE_CHAIN rootChain = - pChainContext->rgpChain[pChainContext->cChain -1 ]; - PCCERT_CONTEXT root = - rootChain->rgpElement[rootChain->cElement - 1]->pCertContext; - - for (i = 0; !isMSRoot && i < ARRAY_SIZE(keyBlobs); i++) - { - msPubKey.PublicKey.cbData = keyBlobs[i].cbData; - msPubKey.PublicKey.pbData = keyBlobs[i].pbData; - if (CertComparePublicKeyInfo( - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - &root->pCertInfo->SubjectPublicKeyInfo, &msPubKey)) - isMSRoot = TRUE; - } - if (isMSRoot) - pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = 0; + msPubKey.PublicKey.cbData = keyBlobs[i].cbData; + msPubKey.PublicKey.pbData = keyBlobs[i].pbData; + if (CertComparePublicKeyInfo(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + &root->pCertInfo->SubjectPublicKeyInfo, &msPubKey)) isMSRoot = TRUE; } - return ret; + + pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = 0; + + if (isMSRoot) + pPolicyStatus->dwError = 0; + else + pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT; + + return TRUE; } typedef BOOL (WINAPI *CertVerifyCertificateChainPolicyFunc)(LPCSTR szPolicyOID, diff -Nru wine-development-5.8/dlls/crypt32/tests/chain.c wine-development-5.9/dlls/crypt32/tests/chain.c --- wine-development-5.8/dlls/crypt32/tests/chain.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/crypt32/tests/chain.c 2020-05-22 18:49:34.000000000 +0000 @@ -2924,6 +2924,415 @@ 0x43,0x08,0xe5,0x78,0x2b,0x95,0xf3,0x75,0xb6,0x88,0xf0,0x6b,0x5c,0x5b,0x50, 0x04,0x91,0x3b,0x89,0x5a,0x60,0x1f,0xfc,0x36,0x53,0x32,0x36,0x0a,0x4d,0x03, 0x2c,0xd7 }; +/* Microsoft Root Certificate Authority 2010 */ +static const BYTE chain32_1[] = { +0x30,0x82,0x05,0xed,0x30,0x82,0x03,0xd5,0xa0,0x03,0x02,0x01,0x02,0x02,0x10, +0x28,0xcc,0x3a,0x25,0xbf,0xba,0x44,0xac,0x44,0x9a,0x9b,0x58,0x6b,0x43,0x39, +0xaa,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05, +0x00,0x30,0x81,0x88,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, +0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61, +0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55, +0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c, +0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66, +0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x32, +0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73, +0x6f,0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x65,0x72,0x74,0x69,0x66, +0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79, +0x20,0x32,0x30,0x31,0x30,0x30,0x1e,0x17,0x0d,0x31,0x30,0x30,0x36,0x32,0x33, +0x32,0x31,0x35,0x37,0x32,0x34,0x5a,0x17,0x0d,0x33,0x35,0x30,0x36,0x32,0x33, +0x32,0x32,0x30,0x34,0x30,0x31,0x5a,0x30,0x81,0x88,0x31,0x0b,0x30,0x09,0x06, +0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55, +0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31, +0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f, +0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69, +0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61, +0x74,0x69,0x6f,0x6e,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29, +0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20, +0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74, +0x68,0x6f,0x72,0x69,0x74,0x79,0x20,0x32,0x30,0x31,0x30,0x30,0x82,0x02,0x22, +0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00, +0x03,0x82,0x02,0x0f,0x00,0x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xb9, +0x08,0x9e,0x28,0xe4,0xe4,0xec,0x06,0x4e,0x50,0x68,0xb3,0x41,0xc5,0x7b,0xeb, +0xae,0xb6,0x8e,0xaf,0x81,0xba,0x22,0x44,0x1f,0x65,0x34,0x69,0x4c,0xbe,0x70, +0x40,0x17,0xf2,0x16,0x7b,0xe2,0x79,0xfd,0x86,0xed,0x0d,0x39,0xf4,0x1b,0xa8, +0xad,0x92,0x90,0x1e,0xcb,0x3d,0x76,0x8f,0x5a,0xd9,0xb5,0x91,0x10,0x2e,0x3c, +0x05,0x8d,0x8a,0x6d,0x24,0x54,0xe7,0x1f,0xed,0x56,0xad,0x83,0xb4,0x50,0x9c, +0x15,0xa5,0x17,0x74,0x88,0x59,0x20,0xfc,0x08,0xc5,0x84,0x76,0xd3,0x68,0xd4, +0x6f,0x28,0x78,0xce,0x5c,0xb8,0xf3,0x50,0x90,0x44,0xff,0xe3,0x63,0x5f,0xbe, +0xa1,0x9a,0x2c,0x96,0x15,0x04,0xd6,0x07,0xfe,0x1e,0x84,0x21,0xe0,0x42,0x31, +0x11,0xc4,0x28,0x36,0x94,0xcf,0x50,0xa4,0x62,0x9e,0xc9,0xd6,0xab,0x71,0x00, +0xb2,0x5b,0x0c,0xe6,0x96,0xd4,0x0a,0x24,0x96,0xf5,0xff,0xc6,0xd5,0xb7,0x1b, +0xd7,0xcb,0xb7,0x21,0x62,0xaf,0x12,0xdc,0xa1,0x5d,0x37,0xe3,0x1a,0xfb,0x1a, +0x46,0x98,0xc0,0x9b,0xc0,0xe7,0x63,0x1f,0x2a,0x08,0x93,0x02,0x7e,0x1e,0x6a, +0x8e,0xf2,0x9f,0x18,0x89,0xe4,0x22,0x85,0xa2,0xb1,0x84,0x57,0x40,0xff,0xf5, +0x0e,0xd8,0x6f,0x9c,0xed,0xe2,0x45,0x31,0x01,0xcd,0x17,0xe9,0x7f,0xb0,0x81, +0x45,0xe3,0xaa,0x21,0x40,0x26,0xa1,0x72,0xaa,0xa7,0x4f,0x3c,0x01,0x05,0x7e, +0xee,0x83,0x58,0xb1,0x5e,0x06,0x63,0x99,0x62,0x91,0x78,0x82,0xb7,0x0d,0x93, +0x0c,0x24,0x6a,0xb4,0x1b,0xdb,0x27,0xec,0x5f,0x95,0x04,0x3f,0x93,0x4a,0x30, +0xf5,0x97,0x18,0xb3,0xa7,0xf9,0x19,0xa7,0x93,0x33,0x1d,0x01,0xc8,0xdb,0x22, +0x52,0x5c,0xd7,0x25,0xc9,0x46,0xf9,0xa2,0xfb,0x87,0x59,0x43,0xbe,0x9b,0x62, +0xb1,0x8d,0x2d,0x86,0x44,0x1a,0x46,0xac,0x78,0x61,0x7e,0x30,0x09,0xfa,0xae, +0x89,0xc4,0x41,0x2a,0x22,0x66,0x03,0x91,0x39,0x45,0x9c,0xc7,0x8b,0x0c,0xa8, +0xca,0x0d,0x2f,0xfb,0x52,0xea,0x0c,0xf7,0x63,0x33,0x23,0x9d,0xfe,0xb0,0x1f, +0xad,0x67,0xd6,0xa7,0x50,0x03,0xc6,0x04,0x70,0x63,0xb5,0x2c,0xb1,0x86,0x5a, +0x43,0xb7,0xfb,0xae,0xf9,0x6e,0x29,0x6e,0x21,0x21,0x41,0x26,0x06,0x8c,0xc9, +0xc3,0xee,0xb0,0xc2,0x85,0x93,0xa1,0xb9,0x85,0xd9,0xe6,0x32,0x6c,0x4b,0x4c, +0x3f,0xd6,0x5d,0xa3,0xe5,0xb5,0x9d,0x77,0xc3,0x9c,0xc0,0x55,0xb7,0x74,0x00, +0xe3,0xb8,0x38,0xab,0x83,0x97,0x50,0xe1,0x9a,0x42,0x24,0x1d,0xc6,0xc0,0xa3, +0x30,0xd1,0x1a,0x5a,0xc8,0x52,0x34,0xf7,0x73,0xf1,0xc7,0x18,0x1f,0x33,0xad, +0x7a,0xec,0xcb,0x41,0x60,0xf3,0x23,0x94,0x20,0xc2,0x48,0x45,0xac,0x5c,0x51, +0xc6,0x2e,0x80,0xc2,0xe2,0x77,0x15,0xbd,0x85,0x87,0xed,0x36,0x9d,0x96,0x91, +0xee,0x00,0xb5,0xa3,0x70,0xec,0x9f,0xe3,0x8d,0x80,0x68,0x83,0x76,0xba,0xaf, +0x5d,0x70,0x52,0x22,0x16,0xe2,0x66,0xfb,0xba,0xb3,0xc5,0xc2,0xf7,0x3e,0x2f, +0x77,0xa6,0xca,0xde,0xc1,0xa6,0xc6,0x48,0x4c,0xc3,0x37,0x51,0x23,0xd3,0x27, +0xd7,0xb8,0x4e,0x70,0x96,0xf0,0xa1,0x44,0x76,0xaf,0x78,0xcf,0x9a,0xe1,0x66, +0x13,0x02,0x03,0x01,0x00,0x01,0xa3,0x51,0x30,0x4f,0x30,0x0b,0x06,0x03,0x55, +0x1d,0x0f,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13, +0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1d,0x06,0x03,0x55, +0x1d,0x0e,0x04,0x16,0x04,0x14,0xd5,0xf6,0x56,0xcb,0x8f,0xe8,0xa2,0x5c,0x62, +0x68,0xd1,0x3d,0x94,0x90,0x5b,0xd7,0xce,0x9a,0x18,0xc4,0x30,0x10,0x06,0x09, +0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x01,0x04,0x03,0x02,0x01,0x00,0x30, +0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03, +0x82,0x02,0x01,0x00,0xac,0xa5,0x96,0x8c,0xbf,0xbb,0xae,0xa6,0xf6,0xd7,0x71, +0x87,0x43,0x31,0x56,0x88,0xfd,0x1c,0x32,0x71,0x5b,0x35,0xb7,0xd4,0xf0,0x91, +0xf2,0xaf,0x37,0xe2,0x14,0xf1,0xf3,0x02,0x26,0x05,0x3e,0x16,0x14,0x7f,0x14, +0xba,0xb8,0x4f,0xfb,0x89,0xb2,0xb2,0xe7,0xd4,0x09,0xcc,0x6d,0xb9,0x5b,0x3b, +0x64,0x65,0x70,0x66,0xb7,0xf2,0xb1,0x5a,0xdf,0x1a,0x02,0xf3,0xf5,0x51,0xb8, +0x67,0x6d,0x79,0xf3,0xbf,0x56,0x7b,0xe4,0x84,0xb9,0x2b,0x1e,0x9b,0x40,0x9c, +0x26,0x34,0xf9,0x47,0x18,0x98,0x69,0xd8,0x1c,0xd7,0xb6,0xd1,0xbf,0x8f,0x61, +0xc2,0x67,0xc4,0xb5,0xef,0x60,0x43,0x8e,0x10,0x1b,0x36,0x49,0xe4,0x20,0xca, +0xad,0xa7,0xc1,0xb1,0x27,0x65,0x09,0xf8,0xcd,0xf5,0x5b,0x2a,0xd0,0x84,0x33, +0xf3,0xef,0x1f,0xf2,0xf5,0x9c,0x0b,0x58,0x93,0x37,0xa0,0x75,0xa0,0xde,0x72, +0xde,0x6c,0x75,0x2a,0x66,0x22,0xf5,0x8c,0x06,0x30,0x56,0x9f,0x40,0xb9,0x30, +0xaa,0x40,0x77,0x15,0x82,0xd7,0x8b,0xec,0xc0,0xd3,0xb2,0xbd,0x83,0xc5,0x77, +0x0c,0x1e,0xae,0xaf,0x19,0x53,0xa0,0x4d,0x79,0x71,0x9f,0x0f,0xaf,0x30,0xce, +0x67,0xf9,0xd6,0x2c,0xcc,0x22,0x41,0x7a,0x07,0xf2,0x97,0x42,0x18,0xce,0x59, +0x79,0x10,0x55,0xde,0x6f,0x10,0xe4,0xb8,0xda,0x83,0x66,0x40,0x16,0x09,0x68, +0x23,0x5b,0x97,0x2e,0x26,0x9a,0x02,0xbb,0x57,0x8c,0xc5,0xb8,0xba,0x69,0x62, +0x32,0x80,0x89,0x9e,0xa1,0xfd,0xc0,0x92,0x7c,0x7b,0x2b,0x33,0x19,0x84,0x2a, +0x63,0xc5,0x00,0x68,0x62,0xfa,0x9f,0x47,0x8d,0x99,0x7a,0x45,0x3a,0xa7,0xe9, +0xed,0xee,0x69,0x42,0xb5,0xf3,0x81,0x9b,0x47,0x56,0x10,0x7b,0xfc,0x70,0x36, +0x84,0x18,0x73,0xea,0xef,0xf9,0x97,0x4d,0x9e,0x33,0x23,0xdd,0x26,0x0b,0xba, +0x2a,0xb7,0x3f,0x44,0xdc,0x83,0x27,0xff,0xbd,0x61,0x59,0x2b,0x11,0xb7,0xca, +0x4f,0xdb,0xc5,0x8b,0x0c,0x1c,0x31,0xae,0x32,0xf8,0xf8,0xb9,0x42,0xf7,0x7f, +0xdc,0x61,0x9a,0x76,0xb1,0x5a,0x04,0xe1,0x11,0x3d,0x66,0x45,0xb7,0x18,0x71, +0xbe,0xc9,0x24,0x85,0xd6,0xf3,0xd4,0xba,0x41,0x34,0x5d,0x12,0x2d,0x25,0xb9, +0x8d,0xa6,0x13,0x48,0x6d,0x4b,0xb0,0x07,0x7d,0x99,0x93,0x09,0x61,0x81,0x74, +0x57,0x26,0x8a,0xab,0x69,0xe3,0xe4,0xd9,0xc7,0x88,0xcc,0x24,0xd8,0xec,0x52, +0x24,0x5c,0x1e,0xbc,0x91,0x14,0xe2,0x96,0xde,0xeb,0x0a,0xda,0x9e,0xdd,0x5f, +0xb3,0x5b,0xdb,0xd4,0x82,0xec,0xc6,0x20,0x50,0x87,0x25,0x40,0x3a,0xfb,0xc7, +0xee,0xcd,0xfe,0x33,0xe5,0x6e,0xc3,0x84,0x09,0x55,0x03,0x25,0x39,0xc0,0xe9, +0x35,0x5d,0x65,0x31,0xa8,0xf6,0xbf,0xa0,0x09,0xcd,0x29,0xc7,0xb3,0x36,0x32, +0x2e,0xdc,0x95,0xf3,0x83,0xc1,0x5a,0xcf,0x8b,0x8d,0xf6,0xea,0xb3,0x21,0xf8, +0xa4,0xed,0x1e,0x31,0x0e,0xb6,0x4c,0x11,0xab,0x60,0x0b,0xa4,0x12,0x23,0x22, +0x17,0xa3,0x36,0x64,0x82,0x91,0x04,0x12,0xe0,0xab,0x6f,0x1e,0xcb,0x50,0x05, +0x61,0xb4,0x40,0xff,0x59,0x86,0x71,0xd1,0xd5,0x33,0x69,0x7c,0xa9,0x73,0x8a, +0x38,0xd7,0x64,0x0c,0xf1,0x69 }; +/* Microsoft Code Signing PCA 2010 */ +static const BYTE chain32_2[] = { +0x30,0x82,0x06,0x70,0x30,0x82,0x04,0x58,0xa0,0x03,0x02,0x01,0x02,0x02,0x0a, +0x61,0x0c,0x52,0x4c,0x00,0x00,0x00,0x00,0x00,0x03,0x30,0x0d,0x06,0x09,0x2a, +0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x81,0x88,0x31,0x0b, +0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, +0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74, +0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65, +0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13, +0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70, +0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04, +0x03,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x52,0x6f, +0x6f,0x74,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20, +0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x20,0x32,0x30,0x31,0x30,0x30, +0x1e,0x17,0x0d,0x31,0x30,0x30,0x37,0x30,0x36,0x32,0x30,0x34,0x30,0x31,0x37, +0x5a,0x17,0x0d,0x32,0x35,0x30,0x37,0x30,0x36,0x32,0x30,0x35,0x30,0x31,0x37, +0x5a,0x30,0x7e,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, +0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73, +0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04, +0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06, +0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74, +0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x28,0x30, +0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1f,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f, +0x66,0x74,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67, +0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x30,0x30,0x82,0x01,0x22,0x30,0x0d, +0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82, +0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xe9,0x0e,0x64, +0x50,0x79,0x67,0xb5,0xc4,0xe3,0xfd,0x09,0x00,0x4c,0x9e,0x94,0xac,0xf7,0x56, +0x68,0xea,0x44,0xd8,0xcf,0xc5,0x58,0x4f,0xa9,0xa5,0x76,0x7c,0x6d,0x45,0xba, +0xd3,0x39,0x92,0xb4,0xa4,0x1e,0xf9,0xf9,0x65,0x82,0xe4,0x17,0xd2,0x8f,0xfd, +0x44,0x9c,0x08,0xe8,0x65,0x93,0xce,0x2c,0x55,0x84,0xbf,0x7d,0x08,0xe3,0x2e, +0x2b,0xa8,0x41,0x2b,0x18,0xb7,0xa2,0x4b,0x6e,0x49,0x4c,0x6b,0x15,0x07,0xde, +0xd1,0xd2,0xc2,0x89,0x1e,0x71,0x94,0xcd,0xb5,0x7f,0x4b,0xb4,0xaf,0x08,0xd8, +0xcc,0x88,0xd6,0x6b,0x17,0x94,0x3a,0x93,0xce,0x26,0x3f,0xec,0xe6,0xfe,0x34, +0x98,0x57,0xd5,0x1d,0x5d,0x49,0xf6,0xb2,0x2a,0x2e,0xd5,0x85,0xbb,0x59,0x3f, +0xf8,0x90,0xb4,0x2b,0x83,0x74,0xca,0x2b,0xb3,0x3b,0x46,0xe3,0xf0,0x46,0x49, +0xc1,0x17,0x66,0x54,0xc9,0x1c,0xbd,0x1d,0xc4,0x55,0x62,0x57,0x72,0xf8,0x67, +0xb9,0x25,0x20,0x34,0xde,0x5d,0xa6,0xa5,0x95,0x5e,0xab,0x28,0x80,0xcd,0xd5, +0xb2,0x9e,0xe5,0x03,0xb5,0x63,0xd3,0xb2,0x14,0xc8,0xc1,0xc8,0x8a,0x26,0x0a, +0x59,0x7f,0x07,0xec,0xff,0x0e,0xed,0x80,0x12,0x35,0x4c,0x12,0xa6,0xbe,0x52, +0x5b,0xf5,0xa6,0xda,0xe0,0x8b,0x0b,0x48,0x77,0xd6,0x85,0x47,0xd5,0x10,0xb9, +0xc6,0xe8,0xaa,0xee,0x8b,0x6a,0x2d,0x05,0x5c,0x60,0xc6,0xb4,0x2a,0x5b,0x9c, +0x23,0x1c,0x5f,0x45,0xe3,0x1a,0x14,0x1e,0x6f,0x37,0xcb,0x19,0x33,0x80,0x6a, +0x89,0x4d,0xa3,0x6a,0x66,0x63,0x78,0x93,0xd5,0x30,0xcf,0x95,0x1f,0x02,0x03, +0x01,0x00,0x01,0xa3,0x82,0x01,0xe3,0x30,0x82,0x01,0xdf,0x30,0x10,0x06,0x09, +0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x01,0x04,0x03,0x02,0x01,0x00,0x30, +0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xe6,0xfc,0x5f,0x7b,0xbb, +0x22,0x00,0x58,0xe4,0x72,0x4e,0xb5,0xf4,0x21,0x74,0x23,0x32,0xe6,0xef,0xac, +0x30,0x19,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x04,0x0c, +0x1e,0x0a,0x00,0x53,0x00,0x75,0x00,0x62,0x00,0x43,0x00,0x41,0x30,0x0b,0x06, +0x03,0x55,0x1d,0x0f,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0f,0x06,0x03,0x55, +0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1f,0x06, +0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xd5,0xf6,0x56,0xcb,0x8f, +0xe8,0xa2,0x5c,0x62,0x68,0xd1,0x3d,0x94,0x90,0x5b,0xd7,0xce,0x9a,0x18,0xc4, +0x30,0x56,0x06,0x03,0x55,0x1d,0x1f,0x04,0x4f,0x30,0x4d,0x30,0x4b,0xa0,0x49, +0xa0,0x47,0x86,0x45,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e, +0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70, +0x6b,0x69,0x2f,0x63,0x72,0x6c,0x2f,0x70,0x72,0x6f,0x64,0x75,0x63,0x74,0x73, +0x2f,0x4d,0x69,0x63,0x52,0x6f,0x6f,0x43,0x65,0x72,0x41,0x75,0x74,0x5f,0x32, +0x30,0x31,0x30,0x2d,0x30,0x36,0x2d,0x32,0x33,0x2e,0x63,0x72,0x6c,0x30,0x5a, +0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x4e,0x30,0x4c,0x30, +0x4a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x3e,0x68,0x74, +0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73, +0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x2f,0x63,0x65,0x72, +0x74,0x73,0x2f,0x4d,0x69,0x63,0x52,0x6f,0x6f,0x43,0x65,0x72,0x41,0x75,0x74, +0x5f,0x32,0x30,0x31,0x30,0x2d,0x30,0x36,0x2d,0x32,0x33,0x2e,0x63,0x72,0x74, +0x30,0x81,0x9d,0x06,0x03,0x55,0x1d,0x20,0x04,0x81,0x95,0x30,0x81,0x92,0x30, +0x81,0x8f,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x2e,0x03,0x30,0x81, +0x81,0x30,0x3d,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x31, +0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72, +0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x50,0x4b,0x49,0x2f,0x64, +0x6f,0x63,0x73,0x2f,0x43,0x50,0x53,0x2f,0x64,0x65,0x66,0x61,0x75,0x6c,0x74, +0x2e,0x68,0x74,0x6d,0x30,0x40,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02, +0x02,0x30,0x34,0x1e,0x32,0x20,0x1d,0x00,0x4c,0x00,0x65,0x00,0x67,0x00,0x61, +0x00,0x6c,0x00,0x5f,0x00,0x50,0x00,0x6f,0x00,0x6c,0x00,0x69,0x00,0x63,0x00, +0x79,0x00,0x5f,0x00,0x53,0x00,0x74,0x00,0x61,0x00,0x74,0x00,0x65,0x00,0x6d, +0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x2e,0x20,0x1d,0x30,0x0d,0x06,0x09,0x2a, +0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x02,0x01,0x00, +0x1a,0x74,0xef,0x57,0x4f,0x29,0x7b,0xc4,0x16,0x85,0x78,0xb8,0x50,0xd3,0x22, +0xfc,0x09,0x9d,0xac,0x82,0x97,0xf8,0x34,0xff,0x2a,0x2c,0x97,0x95,0x12,0xe5, +0xe4,0xbf,0xcf,0xbf,0x93,0xc8,0xe3,0x34,0xa9,0xdb,0x81,0xb8,0xdc,0x1e,0x00, +0xbe,0xd2,0x35,0x6f,0xaf,0xe5,0x7f,0x79,0x95,0x77,0xe5,0x02,0xd4,0xf1,0xeb, +0xd8,0xcd,0x4e,0x1e,0x1b,0x61,0xa2,0xc2,0x5a,0x23,0x1a,0xf0,0x8c,0xa8,0x62, +0x51,0x45,0x67,0x08,0xe3,0x3f,0x3c,0x1e,0x93,0xf8,0x30,0x85,0x17,0xc8,0x39, +0x40,0xa6,0xd7,0x0e,0xb3,0x21,0x29,0xe5,0xa5,0xa1,0x69,0x8c,0x22,0x93,0xcc, +0x74,0x98,0xe7,0xa1,0x47,0x43,0xf2,0x53,0xac,0xc0,0x0f,0x30,0x69,0x7f,0xfe, +0xd2,0x25,0x20,0x6d,0x6f,0x61,0xd3,0xdf,0x07,0xd5,0xd9,0x72,0x00,0x2c,0x69, +0x86,0x76,0x3d,0x51,0xdb,0xa6,0x39,0x48,0xc9,0x37,0x61,0x6d,0x07,0xdd,0x53, +0x19,0xcb,0xa7,0xd6,0x61,0xc2,0xbf,0xe2,0x83,0xab,0x0f,0xe0,0x6b,0x9b,0x95, +0xd6,0x7d,0x28,0x51,0xb0,0x89,0x4a,0x51,0xa4,0x9a,0x6c,0xc8,0xb7,0x1f,0x4a, +0x1a,0x0e,0x69,0xa9,0xd7,0xdc,0xc1,0x7e,0xd1,0x49,0x70,0xaa,0xb6,0xad,0xbb, +0x72,0x47,0x63,0x17,0xfa,0xa6,0xd6,0xa2,0xa6,0x86,0xec,0xa8,0x10,0x44,0x9b, +0x63,0xb6,0xb2,0x69,0x89,0x06,0xc7,0x46,0x86,0x7a,0x18,0x3f,0xe8,0xc5,0x1d, +0x21,0xd5,0x7b,0xf9,0x02,0x23,0x2d,0xc5,0x41,0xcb,0xbf,0x1d,0x4c,0xc8,0x16, +0xef,0xb1,0x9c,0x7f,0xfc,0x22,0x4b,0x49,0x8a,0x6e,0x15,0xe3,0xa6,0x7f,0x76, +0x5b,0xd1,0x53,0x79,0x91,0x85,0x9d,0xd5,0xd2,0xdb,0x3d,0x73,0x35,0xf3,0x3c, +0xae,0x54,0xb2,0x52,0x47,0x6a,0xc0,0xaa,0x13,0x95,0xd2,0x8e,0x11,0xda,0x99, +0x67,0x5e,0x32,0x8c,0xfb,0x37,0x85,0xd1,0xdc,0x75,0x85,0x9c,0x87,0xc6,0x5a, +0x57,0x85,0xc2,0xbf,0xdd,0x0d,0x8f,0x8c,0x9b,0x2d,0xeb,0xb4,0xee,0xcf,0x27, +0xd3,0xb5,0x5e,0x69,0xfa,0xa4,0x16,0x04,0x01,0xa7,0x24,0x67,0x73,0xcf,0x4d, +0x4f,0xb6,0xde,0x05,0x56,0x97,0x7a,0xf7,0xe9,0x52,0x4d,0xf4,0x77,0x05,0x4f, +0x85,0xc6,0xd8,0x0b,0xf1,0x8e,0xed,0x42,0x09,0xd1,0x0d,0x76,0xe3,0x23,0x56, +0x78,0x22,0x26,0x36,0xbe,0xca,0xb1,0x8c,0x6e,0xaa,0x1d,0xe4,0x85,0xda,0x47, +0x33,0x62,0x8f,0xa4,0xc9,0x91,0x33,0x5f,0x71,0x1e,0x40,0xaf,0x98,0x65,0xc9, +0x22,0xe8,0x42,0x21,0x25,0x8a,0x1c,0x2d,0x60,0xd9,0x37,0x89,0x41,0x89,0x2a, +0x16,0x0f,0xd7,0x61,0x3c,0x94,0x68,0x60,0x52,0xef,0xd6,0x47,0x99,0xa0,0x80, +0x40,0xee,0x15,0x81,0x77,0x3e,0x9c,0xe0,0x53,0x18,0x1a,0x50,0x1d,0x38,0x95, +0x9b,0x1e,0x66,0x33,0x13,0x27,0x39,0x17,0x78,0x87,0x36,0xce,0x4e,0xc3,0x5f, +0xb2,0xf5,0x3d,0x47,0x53,0xb6,0xe0,0xe5,0xdb,0x0b,0x61,0x3d,0x2a,0xd7,0x92, +0x2c,0xce,0x37,0x5a,0x3e,0x40,0x42,0x31,0xa4,0x1f,0x10,0x08,0xc2,0x56,0x9c, +0xbf,0x24,0x5d,0x51,0x02,0x9d,0x6a,0x79,0xd2,0x17,0xd3,0xda,0xc1,0x94,0x8e, +0x07,0x7b,0x25,0x71,0x44,0xab,0x06,0x6a,0xe6,0xd4,0xc6,0xdf,0x23,0x9a,0x96, +0x75,0xc5 }; +/* Microsoft Corporation (expired) */ +static const BYTE chain32_3[] = { +0x30,0x82,0x04,0xfe,0x30,0x82,0x03,0xe6,0xa0,0x03,0x02,0x01,0x02,0x02,0x13, +0x33,0x00,0x00,0x02,0xcf,0x6d,0x2c,0xc5,0x7c,0xaa,0x65,0xa6,0xd8,0x00,0x00, +0x00,0x00,0x02,0xcf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, +0x01,0x0b,0x05,0x00,0x30,0x7e,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06, +0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a, +0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06, +0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e, +0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73, +0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e, +0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1f,0x4d,0x69,0x63,0x72, +0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e, +0x69,0x6e,0x67,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x30,0x30,0x1e,0x17, +0x0d,0x31,0x39,0x30,0x35,0x30,0x32,0x32,0x31,0x32,0x35,0x34,0x32,0x5a,0x17, +0x0d,0x32,0x30,0x30,0x35,0x30,0x32,0x32,0x31,0x32,0x35,0x34,0x32,0x5a,0x30, +0x74,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, +0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69, +0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13, +0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55, +0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43, +0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x1e,0x30,0x1c,0x06, +0x03,0x55,0x04,0x03,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74, +0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x30,0x82,0x01, +0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05, +0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00, +0xb9,0x5a,0xf3,0xb5,0x5d,0x58,0xf9,0x43,0x0f,0x95,0x01,0x79,0xfa,0x74,0xe5, +0xb0,0xca,0xb5,0x38,0xf0,0x92,0xca,0xec,0x9b,0x99,0x42,0x1d,0x3a,0xea,0xb5, +0x8f,0x75,0x75,0x83,0xa9,0x1b,0x36,0xff,0x40,0x96,0x8e,0xd7,0x75,0x0a,0xd1, +0x96,0xae,0xc7,0xb3,0x77,0x12,0x39,0x82,0xd9,0xee,0x48,0x75,0x3d,0x47,0xad, +0x53,0x39,0x3c,0x69,0xd1,0xca,0xd8,0xf0,0x3f,0x21,0x5a,0x4c,0x3a,0xe8,0x28, +0x67,0xc3,0x7d,0x20,0x53,0x4b,0x9c,0x8b,0xbc,0x93,0xf9,0x20,0x46,0xf0,0x50, +0x82,0xca,0x6f,0x6a,0x4e,0x56,0xf1,0xd4,0x43,0xae,0xd8,0xe9,0xdb,0xbe,0x7c, +0x77,0x7d,0x46,0x73,0x03,0x3a,0x64,0xe9,0xf6,0x2d,0xcb,0x25,0x51,0x0d,0x90, +0xc9,0x16,0x59,0x29,0x0c,0x15,0x20,0x63,0xa8,0xb8,0x4f,0x70,0x24,0x9d,0x01, +0xe5,0x69,0x94,0x49,0xc9,0xd6,0x58,0xa8,0x9b,0x89,0xb8,0x2f,0xe0,0x6e,0x1b, +0xa7,0xcc,0x9d,0x75,0x08,0xa6,0xc8,0x31,0x65,0x0f,0xa3,0xed,0xbd,0xd6,0xc6, +0x93,0x8c,0x66,0x22,0xbf,0x48,0x57,0x1d,0x8c,0xa1,0xc1,0xe6,0xad,0x90,0x81, +0x29,0x2b,0x8a,0x62,0xf4,0xc2,0xa1,0xdb,0xc8,0xc1,0x79,0x23,0x74,0x37,0x08, +0x92,0x65,0xe3,0x57,0x01,0xe4,0x4f,0xa1,0x0a,0xf5,0x68,0x96,0xd6,0x09,0x80, +0x4a,0x05,0xdc,0xae,0x30,0xd7,0xb1,0x5a,0xfb,0x1d,0xf9,0x84,0xde,0x92,0xcb, +0xf2,0xc0,0xf8,0xea,0x26,0x6e,0xd3,0x73,0x7e,0xc5,0x66,0xa5,0x05,0xac,0xc4, +0xeb,0x10,0xda,0x0c,0x5c,0x7c,0x36,0x99,0x9c,0x59,0x89,0xc6,0x94,0x47,0xf6, +0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7d,0x30,0x82,0x01,0x79,0x30, +0x1f,0x06,0x03,0x55,0x1d,0x25,0x04,0x18,0x30,0x16,0x06,0x0a,0x2b,0x06,0x01, +0x04,0x01,0x82,0x37,0x3d,0x06,0x01,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07, +0x03,0x03,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0x37,0xf3, +0x4d,0xec,0x4d,0xaf,0x2c,0x04,0x31,0xa9,0x10,0x88,0x0b,0x58,0xc0,0x6f,0x03, +0xbc,0x55,0x08,0x30,0x54,0x06,0x03,0x55,0x1d,0x11,0x04,0x4d,0x30,0x4b,0xa4, +0x49,0x30,0x47,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x0b,0x13,0x24,0x4d, +0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x49,0x72,0x65,0x6c,0x61,0x6e, +0x64,0x20,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x73,0x20,0x4c,0x69, +0x6d,0x69,0x74,0x65,0x64,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x05,0x13, +0x0d,0x32,0x33,0x30,0x38,0x36,0x35,0x2b,0x34,0x35,0x34,0x32,0x34,0x34,0x30, +0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xe6,0xfc,0x5f, +0x7b,0xbb,0x22,0x00,0x58,0xe4,0x72,0x4e,0xb5,0xf4,0x21,0x74,0x23,0x32,0xe6, +0xef,0xac,0x30,0x56,0x06,0x03,0x55,0x1d,0x1f,0x04,0x4f,0x30,0x4d,0x30,0x4b, +0xa0,0x49,0xa0,0x47,0x86,0x45,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72, +0x6c,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d, +0x2f,0x70,0x6b,0x69,0x2f,0x63,0x72,0x6c,0x2f,0x70,0x72,0x6f,0x64,0x75,0x63, +0x74,0x73,0x2f,0x4d,0x69,0x63,0x43,0x6f,0x64,0x53,0x69,0x67,0x50,0x43,0x41, +0x5f,0x32,0x30,0x31,0x30,0x2d,0x30,0x37,0x2d,0x30,0x36,0x2e,0x63,0x72,0x6c, +0x30,0x5a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x4e,0x30, +0x4c,0x30,0x4a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x3e, +0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72, +0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x2f,0x63, +0x65,0x72,0x74,0x73,0x2f,0x4d,0x69,0x63,0x43,0x6f,0x64,0x53,0x69,0x67,0x50, +0x43,0x41,0x5f,0x32,0x30,0x31,0x30,0x2d,0x30,0x37,0x2d,0x30,0x36,0x2e,0x63, +0x72,0x74,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30, +0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05, +0x00,0x03,0x82,0x01,0x01,0x00,0xaa,0x30,0x8f,0x08,0x74,0xb1,0x28,0x88,0x0a, +0x81,0x0c,0xcc,0x38,0xea,0xb1,0xc0,0x47,0x9a,0x7d,0xf3,0x19,0x35,0xa6,0xe8, +0x8b,0xe9,0x16,0x04,0xe4,0xc3,0x32,0xe1,0x29,0xf7,0xcc,0xb8,0xf0,0xc6,0xc3, +0x02,0xd5,0xb0,0x8d,0x0b,0x41,0xfe,0x5c,0xa9,0x03,0x86,0x25,0xf5,0x24,0x9f, +0xb0,0x04,0xc4,0x69,0x0a,0x27,0x94,0x04,0xb2,0x09,0xdc,0x19,0xaf,0xbb,0x01, +0x8b,0x92,0xe4,0xd8,0x72,0x04,0x07,0x72,0x81,0xd3,0x89,0xca,0xd7,0x79,0x98, +0x41,0xe5,0xa0,0x29,0xfb,0x95,0x91,0xd9,0xf8,0x8c,0x40,0x23,0x70,0x9a,0xb2, +0xf6,0xcb,0x0a,0x75,0x0b,0xbd,0x1c,0x72,0xd7,0xff,0x98,0x20,0x01,0xde,0xc0, +0xcd,0xd0,0xd3,0xa5,0xff,0x6b,0x0c,0x8b,0xf9,0x85,0x69,0x22,0x15,0x09,0xd7, +0x4e,0xf2,0xc1,0xe9,0xd4,0x78,0xa7,0xd1,0xe3,0x46,0xf6,0x3d,0xa9,0x06,0x66, +0x11,0xa3,0x9e,0x2f,0xef,0xe6,0xd3,0xc5,0x80,0x29,0xc8,0xfa,0xd3,0xb7,0x98, +0x0d,0xdc,0xa4,0xce,0x84,0x68,0xeb,0x9b,0xfb,0x14,0x83,0x28,0x6d,0x22,0x57, +0x9a,0x46,0xbe,0x37,0x71,0xc4,0xec,0xed,0x38,0x8f,0x4d,0x6e,0x13,0x54,0x39, +0x87,0xc6,0xf4,0x1e,0x41,0xdf,0xba,0x87,0x28,0xda,0xc2,0xc0,0x02,0xa5,0x80, +0x52,0x3c,0xbd,0x9a,0xe2,0x66,0xc0,0x5e,0xc3,0x56,0xe8,0x65,0x1d,0xcc,0xd4, +0xec,0xf5,0x4d,0x05,0xae,0xf3,0x9b,0x96,0x7b,0xf2,0xa9,0x3b,0xae,0xe0,0xbb, +0x3b,0x42,0x9b,0xec,0x20,0xba,0xea,0x1c,0x6d,0xf4,0x6a,0x24,0x8f,0x31,0x01, +0x3c,0x8a,0x0a,0x58,0x61,0x67,0x58 }; +/* Microsoft Root Certificate Authority 2011 */ +static const BYTE chain33_1[] = { +0x30,0x82,0x05,0xed,0x30,0x82,0x03,0xd5,0xa0,0x03,0x02,0x01,0x02,0x02,0x10, +0x3f,0x8b,0xc8,0xb5,0xfc,0x9f,0xb2,0x96,0x43,0xb5,0x69,0xd6,0x6c,0x42,0xe1, +0x44,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05, +0x00,0x30,0x81,0x88,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, +0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61, +0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55, +0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c, +0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66, +0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x32, +0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73, +0x6f,0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x65,0x72,0x74,0x69,0x66, +0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79, +0x20,0x32,0x30,0x31,0x31,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x32,0x32, +0x32,0x32,0x30,0x35,0x32,0x38,0x5a,0x17,0x0d,0x33,0x36,0x30,0x33,0x32,0x32, +0x32,0x32,0x31,0x33,0x30,0x34,0x5a,0x30,0x81,0x88,0x31,0x0b,0x30,0x09,0x06, +0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55, +0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31, +0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f, +0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69, +0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61, +0x74,0x69,0x6f,0x6e,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29, +0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20, +0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74, +0x68,0x6f,0x72,0x69,0x74,0x79,0x20,0x32,0x30,0x31,0x31,0x30,0x82,0x02,0x22, +0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00, +0x03,0x82,0x02,0x0f,0x00,0x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xb2, +0x80,0x41,0xaa,0x35,0x38,0x4d,0x13,0x72,0x32,0x68,0x22,0x4d,0xb8,0xb2,0xf1, +0xff,0xd5,0x52,0xbc,0x6c,0xc7,0xf5,0xd2,0x4a,0x8c,0x36,0xee,0xd1,0xc2,0x5c, +0x7e,0x8c,0x8a,0xae,0xaf,0x13,0x28,0x6f,0xc0,0x73,0xe3,0x3a,0xce,0xd0,0x25, +0xa8,0x5a,0x3a,0x6d,0xef,0xa8,0xb8,0x59,0xab,0x13,0x23,0x68,0xcd,0x0c,0x29, +0x87,0xd1,0x6f,0x80,0x5c,0x8f,0x44,0x7f,0x5d,0x90,0x01,0x52,0x58,0xac,0x51, +0xc5,0x5f,0x2a,0x87,0xdc,0xdc,0xd8,0x0a,0x1d,0xc1,0x03,0xb9,0x7b,0xb0,0x56, +0xe8,0xa3,0xde,0x64,0x61,0xc2,0x9e,0xf8,0xf3,0x7c,0xb9,0xec,0x0d,0xb5,0x54, +0xfe,0x4c,0xb6,0x65,0x4f,0x88,0xf0,0x9c,0x48,0x99,0x0c,0x42,0x0b,0x09,0x7c, +0x31,0x59,0x17,0x79,0x06,0x78,0x28,0x8d,0x89,0x3a,0x4c,0x03,0x25,0xbe,0x71, +0x6a,0x5c,0x0b,0xe7,0x84,0x60,0xa4,0x99,0x22,0xe3,0xd2,0xaf,0x84,0xa4,0xa7, +0xfb,0xd1,0x98,0xed,0x0c,0xa9,0xde,0x94,0x89,0xe1,0x0e,0xa0,0xdc,0xc0,0xce, +0x99,0x3d,0xea,0x08,0x52,0xbb,0x56,0x79,0xe4,0x1f,0x84,0xba,0x1e,0xb8,0xb4, +0xc4,0x49,0x5c,0x4f,0x31,0x4b,0x87,0xdd,0xdd,0x05,0x67,0x26,0x99,0x80,0xe0, +0x71,0x11,0xa3,0xb8,0xa5,0x41,0xe2,0xa4,0x53,0xb9,0xf7,0x32,0x29,0x83,0x0c, +0x13,0xbf,0x36,0x5e,0x04,0xb3,0x4b,0x43,0x47,0x2f,0x6b,0xe2,0x91,0x1e,0xd3, +0x98,0x4f,0xdd,0x42,0x07,0xc8,0xe8,0x1d,0x12,0xfc,0x99,0xa9,0x6b,0x3e,0x92, +0x7e,0xc8,0xd6,0x69,0x3a,0xfc,0x64,0xbd,0xb6,0x09,0x9d,0xca,0xfd,0x0c,0x0b, +0xa2,0x9b,0x77,0x60,0x4b,0x03,0x94,0xa4,0x30,0x69,0x12,0xd6,0x42,0x2d,0xc1, +0x41,0x4c,0xca,0xdc,0xaa,0xfd,0x8f,0x5b,0x83,0x46,0x9a,0xd9,0xfc,0xb1,0xd1, +0xe3,0xb3,0xc9,0x7f,0x48,0x7a,0xcd,0x24,0xf0,0x41,0x8f,0x5c,0x74,0xd0,0xac, +0xb0,0x10,0x20,0x06,0x49,0xb7,0xc7,0x2d,0x21,0xc8,0x57,0xe3,0xd0,0x86,0xf3, +0x03,0x68,0xfb,0xd0,0xce,0x71,0xc1,0x89,0x99,0x4a,0x64,0x01,0x6c,0xfd,0xec, +0x30,0x91,0xcf,0x41,0x3c,0x92,0xc7,0xe5,0xba,0x86,0x1d,0x61,0x84,0xc7,0x5f, +0x83,0x39,0x62,0xae,0xb4,0x92,0x2f,0x47,0xf3,0x0b,0xf8,0x55,0xeb,0xa0,0x1f, +0x59,0xd0,0xbb,0x74,0x9b,0x1e,0xd0,0x76,0xe6,0xf2,0xe9,0x06,0xd7,0x10,0xe8, +0xfa,0x64,0xde,0x69,0xc6,0x35,0x96,0x88,0x02,0xf0,0x46,0xb8,0x3f,0x27,0x99, +0x6f,0xcb,0x71,0x89,0x29,0x35,0xf7,0x48,0x16,0x02,0x35,0x8f,0xd5,0x79,0x7c, +0x4d,0x02,0xcf,0x5f,0xeb,0x8a,0x83,0x4f,0x45,0x71,0x88,0xf9,0xa9,0x0d,0x4e, +0x72,0xe9,0xc2,0x9c,0x07,0xcf,0x49,0x1b,0x4e,0x04,0x0e,0x63,0x51,0x8c,0x5e, +0xd8,0x00,0xc1,0x55,0x2c,0xb6,0xc6,0xe0,0xc2,0x65,0x4e,0xc9,0x34,0x39,0xf5, +0x9c,0xb3,0xc4,0x7e,0xe8,0x61,0x6e,0x13,0x5f,0x15,0xc4,0x5f,0xd9,0x7e,0xed, +0x1d,0xce,0xee,0x44,0xec,0xcb,0x2e,0x86,0xb1,0xec,0x38,0xf6,0x70,0xed,0xab, +0x5c,0x13,0xc1,0xd9,0x0f,0x0d,0xc7,0x80,0xb2,0x55,0xed,0x34,0xf7,0xac,0x9b, +0xe4,0xc3,0xda,0xe7,0x47,0x3c,0xa6,0xb5,0x8f,0x31,0xdf,0xc5,0x4b,0xaf,0xeb, +0xf1,0x02,0x03,0x01,0x00,0x01,0xa3,0x51,0x30,0x4f,0x30,0x0b,0x06,0x03,0x55, +0x1d,0x0f,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13, +0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1d,0x06,0x03,0x55, +0x1d,0x0e,0x04,0x16,0x04,0x14,0x72,0x2d,0x3a,0x02,0x31,0x90,0x43,0xb9,0x14, +0x05,0x4e,0xe1,0xea,0xa7,0xc7,0x31,0xd1,0x23,0x89,0x34,0x30,0x10,0x06,0x09, +0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x01,0x04,0x03,0x02,0x01,0x00,0x30, +0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03, +0x82,0x02,0x01,0x00,0x7f,0x72,0xcf,0x0f,0xb7,0xc5,0x15,0xdb,0x9b,0xc0,0x49, +0xca,0x26,0x5b,0xfe,0x9e,0x13,0xe6,0xd3,0xf0,0xd2,0xdb,0x97,0x5f,0xf2,0x4b, +0x3f,0x4d,0xb3,0xae,0x19,0xae,0xed,0xd7,0x97,0xa0,0xac,0xef,0xa9,0x3a,0xa3, +0xc2,0x41,0xb0,0xe5,0xb8,0x91,0x9e,0x13,0x81,0x24,0x03,0xe6,0x09,0xfd,0x3f, +0x57,0x40,0x39,0x21,0x24,0x56,0xd1,0x10,0x2f,0x4b,0x40,0xa9,0x36,0x86,0x4b, +0xb4,0x53,0x57,0x9a,0xfb,0xf1,0x7e,0x89,0x8f,0x11,0xfe,0x18,0x6c,0x51,0xaa, +0xe8,0xed,0x09,0x95,0xb5,0xe5,0x71,0xc9,0xa1,0xe9,0x87,0x75,0xa6,0x15,0x7f, +0xc9,0x7e,0x37,0x54,0x5e,0x74,0x93,0xc5,0xc3,0x67,0xcc,0x0d,0x4f,0x6b,0xa8, +0x17,0x0c,0x6d,0x08,0x92,0x7e,0x8b,0xdd,0x81,0xaa,0x2d,0x70,0x21,0xc3,0x3d, +0x06,0x14,0xbb,0xbf,0x24,0x5e,0xa7,0x84,0xd7,0x3f,0x0f,0x21,0x22,0xbd,0x4b, +0x00,0x06,0xdb,0x97,0x1c,0xd8,0x5e,0xd4,0xc5,0x0b,0x5c,0x87,0x6e,0x50,0xa4, +0xe8,0xc3,0x38,0xa4,0xfb,0xcb,0x2c,0xc5,0x92,0x66,0x9b,0x85,0x5e,0xcb,0x7a, +0x6c,0x93,0x7c,0x80,0x29,0x58,0x5b,0x57,0xb5,0x40,0x69,0xba,0x08,0x79,0xa6, +0x64,0x62,0x15,0x9d,0x87,0x96,0x45,0xb5,0x66,0x23,0x20,0x03,0x8b,0x1c,0x73, +0xa0,0xd3,0xa2,0x79,0x33,0xe0,0x50,0x59,0x86,0xdb,0x2f,0xe5,0x02,0x25,0xea, +0x73,0x2a,0x9f,0x00,0x14,0xc8,0x36,0xc7,0x92,0x3b,0xe9,0x4e,0x00,0xec,0xd8, +0x56,0x09,0xb9,0x33,0x49,0x12,0xd2,0x54,0x0b,0x01,0xab,0xac,0x47,0xb6,0x91, +0x29,0x7d,0x4c,0xb4,0x75,0x80,0x52,0x01,0xe8,0xca,0x82,0xf6,0x9f,0xcc,0xac, +0x9c,0x8f,0x17,0xea,0x2f,0x26,0xb0,0xab,0x72,0xac,0x0b,0xfe,0x9e,0x51,0x1e, +0xc7,0x43,0x55,0x67,0x4f,0x51,0xb3,0x57,0xd6,0xb6,0xec,0xee,0x52,0xb7,0x3a, +0xe9,0x4e,0xe1,0xd7,0x81,0x88,0xbc,0x4f,0x8e,0x75,0xbb,0x4b,0xa8,0xf0,0x35, +0xaa,0x26,0xd4,0x67,0x67,0x49,0xb2,0x70,0x4c,0x3b,0x93,0xdc,0x1d,0xdf,0x78, +0x90,0x86,0x72,0xb2,0x38,0xa4,0xd1,0xdc,0x92,0x4d,0xc9,0x58,0xeb,0x2b,0x12, +0x5c,0xd4,0x3b,0xae,0x8c,0x6b,0xb0,0x83,0xe5,0x01,0x3f,0xf8,0x09,0x32,0xf6, +0x93,0x35,0x34,0x22,0xaf,0xdd,0x37,0x0d,0x77,0x09,0x80,0x2b,0xcd,0x48,0x00, +0xf1,0x8c,0x99,0x19,0x47,0x05,0x01,0xe9,0xd1,0xbf,0xd1,0x4e,0xd0,0xe6,0x28, +0x43,0x37,0x99,0xa4,0x0a,0x4a,0x08,0xd9,0x9a,0x71,0x73,0xd2,0xaa,0xcd,0x31, +0x13,0x63,0x76,0xa1,0x37,0x6f,0x92,0x38,0x1e,0x7d,0x12,0x3c,0x66,0x32,0xe7, +0xcb,0x6d,0xe1,0xfc,0x52,0x89,0xdd,0xca,0xd6,0x66,0x05,0x9a,0x96,0x61,0xbe, +0xa2,0x28,0xc7,0x1c,0xa3,0xa7,0x36,0x50,0x3c,0x3a,0xa4,0xdf,0x4a,0x6e,0xe6, +0x87,0x3b,0xce,0xeb,0xf0,0xe0,0x81,0x37,0x9d,0x13,0x3c,0x52,0x8e,0xbd,0xb9, +0x1d,0x34,0xc6,0x1d,0xd5,0x0a,0x6a,0x3d,0x98,0x29,0x70,0x8c,0x89,0x2a,0xd1, +0xab,0x82,0x10,0x48,0x1f,0xdc,0xf4,0xef,0xa5,0xc5,0xbb,0x55,0x1a,0x38,0x63, +0x84,0x4e,0xb7,0x6c,0xad,0x95,0x54,0xec,0x65,0x22,0x10,0x49,0x17,0xb8,0xc0, +0x1e,0xc7,0x0f,0xac,0x54,0x47 }; typedef struct _CONST_DATA_BLOB { @@ -3121,6 +3530,8 @@ static SYSTEMTIME oct2016 = { 2016, 10, 6, 1, 0, 0, 0, 0 }; /* Wednesday, Nov 17, 2016 */ static SYSTEMTIME nov2016 = { 2016, 11, 3, 17, 0, 0, 0, 0 }; +/* Thursday, May 14, 2020 */ +static SYSTEMTIME may2020 = { 2020, 5, 4, 14, 0, 0, 0, 0 }; typedef struct _ChainCheck { @@ -3520,6 +3931,14 @@ { sizeof(chain0_0), chain0_0 }, { sizeof(chain31_1), chain31_1 }, }; +static CONST_DATA_BLOB chain32[] = { + { sizeof(chain32_1), chain32_1 }, + { sizeof(chain32_2), chain32_2 }, + { sizeof(chain32_3), chain32_3 }, +}; +static CONST_DATA_BLOB chain33[] = { + { sizeof(chain33_1), chain33_1 }, +}; static CONST_DATA_BLOB selfSignedChain[] = { { sizeof(selfSignedCert), selfSignedCert } }; @@ -4549,6 +4968,20 @@ { 0, 0, -1, -1, NULL }, NULL, 0 }, }; +static const CERT_CHAIN_POLICY_STATUS chain32BrokenStatus = + { 0, CERT_E_UNTRUSTEDROOT, 0, 0, NULL }; + +static const ChainPolicyCheck msRootPolicyCheck[] = { + { { ARRAY_SIZE(chain0), chain0 }, + { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, NULL, TODO_ELEMENTS }, + { { ARRAY_SIZE(selfSignedChain), selfSignedChain }, + { 0, CERT_E_UNTRUSTEDROOT, 0, 0, NULL }, NULL, 0 }, + { { ARRAY_SIZE(chain32), chain32 }, + { 0, 0, 0, 0, NULL }, &chain32BrokenStatus, 0 }, + { { ARRAY_SIZE(chain33), chain33 }, + { 0, CERT_E_UNTRUSTEDROOT, 0, 0, NULL }, NULL, 0 }, +}; + static const char *num_to_str(WORD num) { static char buf[6]; @@ -4906,6 +5339,12 @@ nullTerminatedDomainComponentPolicyCheck, &oct2010, &policyPara); } +static void check_msroot_policy(void) +{ + CHECK_CHAIN_POLICY_STATUS_ARRAY(CERT_CHAIN_POLICY_MICROSOFT_ROOT, NULL, + msRootPolicyCheck, &may2020, NULL); +} + static void testVerifyCertChainPolicy(void) { BOOL ret; @@ -4974,6 +5413,7 @@ check_authenticode_policy(); CHECK_CHAIN_POLICY_STATUS_ARRAY(CERT_CHAIN_POLICY_BASIC_CONSTRAINTS, NULL, basicConstraintsPolicyCheck, &oct2007, NULL); + check_msroot_policy(); } START_TEST(chain) diff -Nru wine-development-5.8/dlls/d2d1/geometry.c wine-development-5.9/dlls/d2d1/geometry.c --- wine-development-5.8/dlls/d2d1/geometry.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d2d1/geometry.c 2020-05-22 18:49:34.000000000 +0000 @@ -409,6 +409,16 @@ d2d_point_scale(p, 1.0f / l); } +static BOOL d2d_vertex_type_is_bezier(enum d2d_vertex_type t) +{ + return (t == D2D_VERTEX_TYPE_BEZIER || t == D2D_VERTEX_TYPE_SPLIT_BEZIER); +} + +static BOOL d2d_vertex_type_is_split_bezier(enum d2d_vertex_type t) +{ + return t == D2D_VERTEX_TYPE_SPLIT_BEZIER; +} + /* This implementation is based on the paper "Adaptive Precision * Floating-Point Arithmetic and Fast Robust Geometric Predicates" and * associated (Public Domain) code by Jonathan Richard Shewchuk. */ @@ -613,33 +623,35 @@ return TRUE; } -static BOOL d2d_figure_insert_bezier_control(struct d2d_figure *figure, size_t idx, const D2D1_POINT_2F *p) +static BOOL d2d_figure_insert_bezier_controls(struct d2d_figure *figure, + size_t idx, size_t count, const D2D1_POINT_2F *p) { if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size, - figure->bezier_control_count + 1, sizeof(*figure->bezier_controls))) + figure->bezier_control_count + count, sizeof(*figure->bezier_controls))) { ERR("Failed to grow bezier controls array.\n"); return FALSE; } - memmove(&figure->bezier_controls[idx + 1], &figure->bezier_controls[idx], + memmove(&figure->bezier_controls[idx + count], &figure->bezier_controls[idx], (figure->bezier_control_count - idx) * sizeof(*figure->bezier_controls)); - figure->bezier_controls[idx] = *p; - ++figure->bezier_control_count; + memcpy(&figure->bezier_controls[idx], p, count * sizeof(*figure->bezier_controls)); + figure->bezier_control_count += count; return TRUE; } -static BOOL d2d_figure_add_bezier_control(struct d2d_figure *figure, const D2D1_POINT_2F *p) +static BOOL d2d_figure_add_bezier_controls(struct d2d_figure *figure, size_t count, const D2D1_POINT_2F *p) { if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size, - figure->bezier_control_count + 1, sizeof(*figure->bezier_controls))) + figure->bezier_control_count + count, sizeof(*figure->bezier_controls))) { ERR("Failed to grow bezier controls array.\n"); return FALSE; } - figure->bezier_controls[figure->bezier_control_count++] = *p; + memcpy(&figure->bezier_controls[figure->bezier_control_count], p, count * sizeof(*figure->bezier_controls)); + figure->bezier_control_count += count; return TRUE; } @@ -1875,7 +1887,7 @@ figure = &geometry->u.path.figures[inter->figure_idx]; vertex_type = figure->vertex_types[inter->vertex_idx + vertex_offset]; - if (vertex_type != D2D_VERTEX_TYPE_BEZIER && vertex_type != D2D_VERTEX_TYPE_SPLIT_BEZIER) + if (!d2d_vertex_type_is_bezier(vertex_type)) { if (!d2d_figure_insert_vertex(&geometry->u.path.figures[inter->figure_idx], inter->vertex_idx + vertex_offset + 1, inter->p)) @@ -1908,7 +1920,7 @@ d2d_point_lerp(&q[1], p[1], p[2], t); figure->bezier_controls[inter->control_idx + control_offset] = q[0]; - if (!(d2d_figure_insert_bezier_control(figure, inter->control_idx + control_offset + 1, &q[1]))) + if (!(d2d_figure_insert_bezier_controls(figure, inter->control_idx + control_offset + 1, 1, &q[1]))) return FALSE; ++control_offset; @@ -1961,9 +1973,9 @@ for (idx_q.vertex_idx = 0; idx_q.vertex_idx < max_q; ++idx_q.vertex_idx) { type_q = figure_q->vertex_types[idx_q.vertex_idx]; - if (type_q == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(type_q)) { - if (type_p == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(type_p)) { if (!d2d_geometry_intersect_bezier_bezier(geometry, &intersections, &idx_p, 0.0f, 1.0f, &idx_q, 0.0f, 1.0f)) @@ -1978,7 +1990,7 @@ } else { - if (type_p == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(type_p)) { if (!d2d_geometry_intersect_bezier_line(geometry, &intersections, &idx_p, &idx_q)) goto done; @@ -1991,7 +2003,7 @@ } } } - if (type_p == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(type_p)) ++idx_p.control_idx; } } @@ -2328,7 +2340,7 @@ if (!i) { prev_type = figure->vertex_types[figure->vertex_count - 1]; - if (prev_type == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(prev_type)) prev = &figure->bezier_controls[figure->bezier_control_count - 1]; else prev = &figure->vertices[figure->vertex_count - 1]; @@ -2336,13 +2348,13 @@ else { prev_type = figure->vertex_types[i - 1]; - if (prev_type == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(prev_type)) prev = &figure->bezier_controls[bezier_idx - 1]; else prev = &figure->vertices[i - 1]; } - if (type == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(type)) next = &figure->bezier_controls[bezier_idx++]; else if (i == figure->vertex_count - 1) next = &figure->vertices[0]; @@ -2372,7 +2384,7 @@ ERR("Failed to add line segment.\n"); return FALSE; } - else if (type == D2D_VERTEX_TYPE_BEZIER) + else if (d2d_vertex_type_is_bezier(type)) { const D2D1_POINT_2F *p2; @@ -2586,7 +2598,7 @@ d2d_rect_get_bezier_bounds(&bezier_bounds, &figure->vertices[figure->vertex_count - 1], &p, &beziers[i].point3); - if (!d2d_figure_add_bezier_control(figure, &p)) + if (!d2d_figure_add_bezier_controls(figure, 1, &p)) { ERR("Failed to add bezier control.\n"); geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR; @@ -2674,8 +2686,7 @@ for (; idx->vertex_idx < figure->vertex_count; ++idx->vertex_idx) { - if (figure->vertex_types[idx->vertex_idx] == D2D_VERTEX_TYPE_BEZIER - || figure->vertex_types[idx->vertex_idx] == D2D_VERTEX_TYPE_SPLIT_BEZIER) + if (d2d_vertex_type_is_bezier(figure->vertex_types[idx->vertex_idx])) return TRUE; } } @@ -2815,7 +2826,7 @@ d2d_point_lerp(&q[2], &q[0], &q[1], 0.5f); figure->bezier_controls[idx->control_idx] = q[0]; - if (!(d2d_figure_insert_bezier_control(figure, idx->control_idx + 1, &q[1]))) + if (!(d2d_figure_insert_bezier_controls(figure, idx->control_idx + 1, 1, &q[1]))) return FALSE; if (!(d2d_figure_insert_vertex(figure, idx->vertex_idx + 1, q[2]))) return FALSE; @@ -3003,7 +3014,7 @@ &beziers[i].point1, &beziers[i].point2); figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER; - if (!d2d_figure_add_bezier_control(figure, &beziers[i].point1)) + if (!d2d_figure_add_bezier_controls(figure, 1, &beziers[i].point1)) { ERR("Failed to add bezier.\n"); geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR; @@ -3198,7 +3209,7 @@ for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j) { if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE - || figure->vertex_types[j] == D2D_VERTEX_TYPE_SPLIT_BEZIER) + || d2d_vertex_type_is_split_bezier(figure->vertex_types[j])) continue; switch (type) @@ -3230,7 +3241,7 @@ type = figure->vertex_types[j]; } - if (type == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(type)) { p1 = figure->original_bezier_controls[bezier_idx++]; d2d_point_transform(&p1, transform, p1.x, p1.y); @@ -3401,7 +3412,7 @@ for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j) { if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE - || figure->vertex_types[j] == D2D_VERTEX_TYPE_SPLIT_BEZIER) + || d2d_vertex_type_is_split_bezier(figure->vertex_types[j])) continue; switch (type) @@ -3436,7 +3447,7 @@ type = figure->vertex_types[j]; } - if (type == D2D_VERTEX_TYPE_BEZIER) + if (d2d_vertex_type_is_bezier(type)) { p1 = figure->original_bezier_controls[bezier_idx++]; if (transform) diff -Nru wine-development-5.8/dlls/d3d11/device.c wine-development-5.9/dlls/d3d11/device.c --- wine-development-5.8/dlls/d3d11/device.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d3d11/device.c 2020-05-22 18:49:34.000000000 +0000 @@ -2396,7 +2396,13 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_Flush(ID3D11DeviceContext1 *iface) { - FIXME("iface %p stub!\n", iface); + struct d3d_device *device = device_from_immediate_ID3D11DeviceContext1(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_device_flush(device->wined3d_device); + wined3d_mutex_unlock(); } static D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE d3d11_immediate_context_GetType(ID3D11DeviceContext1 *iface) @@ -2408,7 +2414,7 @@ static UINT STDMETHODCALLTYPE d3d11_immediate_context_GetContextFlags(ID3D11DeviceContext1 *iface) { - FIXME("iface %p stub!\n", iface); + TRACE("iface %p.\n", iface); return 0; } @@ -2416,9 +2422,9 @@ static HRESULT STDMETHODCALLTYPE d3d11_immediate_context_FinishCommandList(ID3D11DeviceContext1 *iface, BOOL restore, ID3D11CommandList **command_list) { - FIXME("iface %p, restore %#x, command_list %p stub!\n", iface, restore, command_list); + TRACE("iface %p, restore %#x, command_list %p.\n", iface, restore, command_list); - return E_NOTIMPL; + return DXGI_ERROR_INVALID_CALL; } static void STDMETHODCALLTYPE d3d11_immediate_context_CopySubresourceRegion1(ID3D11DeviceContext1 *iface, @@ -5246,7 +5252,13 @@ static void STDMETHODCALLTYPE d3d10_device_Flush(ID3D10Device1 *iface) { - FIXME("iface %p stub!\n", iface); + struct d3d_device *device = impl_from_ID3D10Device(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_device_flush(device->wined3d_device); + wined3d_mutex_unlock(); } static HRESULT STDMETHODCALLTYPE d3d10_device_CreateBuffer(ID3D10Device1 *iface, diff -Nru wine-development-5.8/dlls/d3d11/tests/d3d11.c wine-development-5.9/dlls/d3d11/tests/d3d11.c --- wine-development-5.8/dlls/d3d11/tests/d3d11.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d3d11/tests/d3d11.c 2020-05-22 18:49:34.000000000 +0000 @@ -2147,15 +2147,24 @@ ok(!refcount, "Device has %u references left.\n", refcount); } -static void test_get_immediate_context(void) +static void test_immediate_context(void) { ID3D11DeviceContext *immediate_context, *previous_immediate_context; ULONG expected_refcount, refcount; + ID3D11CommandList *command_list; ID3D11Multithread *multithread; + ID3D11Buffer *buffer[2]; ID3D11Device *device; + unsigned int flags; BOOL enabled; HRESULT hr; + static const unsigned int buffer_contents[] = + { + 0x11111111, 0x22222222, 0x33333333, 0x44444444, + 0x55555555, 0x66666666, 0x77777777, 0x88888888, + }; + if (!(device = create_device(NULL))) { skip("Failed to create device.\n"); @@ -2205,6 +2214,26 @@ ID3D11Multithread_Release(multithread); + ID3D11Device_GetImmediateContext(device, &immediate_context); + + flags = ID3D11DeviceContext_GetContextFlags(immediate_context); + ok(!flags, "Got unexpected flags %#x.\n", flags); + + hr = ID3D11DeviceContext_FinishCommandList(immediate_context, FALSE, &command_list); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); + + buffer[0] = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, 16, &buffer_contents[0]); + buffer[1] = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, 16, &buffer_contents[4]); + + ID3D11DeviceContext_CopyResource(immediate_context, (ID3D11Resource *)buffer[1], (ID3D11Resource *)buffer[0]); + + hr = ID3D11DeviceContext_FinishCommandList(immediate_context, FALSE, &command_list); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); + + ID3D11Buffer_Release(buffer[1]); + ID3D11Buffer_Release(buffer[0]); + ID3D11DeviceContext_Release(immediate_context); + done: refcount = ID3D11DeviceContext_Release(immediate_context); ok(!refcount, "Got unexpected refcount %u.\n", refcount); @@ -30086,7 +30115,7 @@ queue_test(test_create_device); queue_for_each_feature_level(test_device_interfaces); - queue_test(test_get_immediate_context); + queue_test(test_immediate_context); queue_test(test_create_deferred_context); queue_test(test_create_texture1d); queue_test(test_texture1d_interfaces); diff -Nru wine-development-5.8/dlls/d3d8/d3d8_private.h wine-development-5.9/dlls/d3d8/d3d8_private.h --- wine-development-5.8/dlls/d3d8/d3d8_private.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d3d8/d3d8_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -115,7 +115,7 @@ LONG ref; struct wined3d_device *wined3d_device; unsigned int adapter_ordinal; - IDirect3D8 *d3d_parent; + struct d3d8 *d3d_parent; struct d3d8_handle_table handle_table; /* FVF management */ diff -Nru wine-development-5.8/dlls/d3d8/device.c wine-development-5.9/dlls/d3d8/device.c --- wine-development-5.8/dlls/d3d8/device.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d3d8/device.c 2020-05-22 18:49:34.000000000 +0000 @@ -262,8 +262,8 @@ return (enum wined3d_multisample_type)type; } -static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc, - const D3DPRESENT_PARAMETERS *present_parameters) +static BOOL wined3d_swapchain_desc_from_d3d8(struct wined3d_swapchain_desc *swapchain_desc, + struct wined3d_output *output, const D3DPRESENT_PARAMETERS *present_parameters) { if (!present_parameters->SwapEffect || present_parameters->SwapEffect > D3DSWAPEFFECT_COPY_VSYNC) { @@ -293,6 +293,7 @@ return FALSE; } + swapchain_desc->output = output; swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth; swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight; swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat); @@ -609,7 +610,7 @@ if (!ref) { - IDirect3D8 *parent = device->d3d_parent; + IDirect3D8 *parent = &device->d3d_parent->IDirect3D8_iface; unsigned i; TRACE("Releasing wined3d device %p.\n", device->wined3d_device); @@ -705,7 +706,8 @@ if (!d3d8) return D3DERR_INVALIDCALL; - return IDirect3D8_QueryInterface(device->d3d_parent, &IID_IDirect3D8, (void **)d3d8); + return IDirect3D8_QueryInterface(&device->d3d_parent->IDirect3D8_iface, &IID_IDirect3D8, + (void **)d3d8); } static HRESULT WINAPI d3d8_device_GetDeviceCaps(IDirect3DDevice8 *iface, D3DCAPS8 *caps) @@ -791,8 +793,8 @@ return hr; } - if (FAILED(hr = IDirect3D8_GetAdapterDisplayMode(device->d3d_parent, device->adapter_ordinal, - &mode))) + if (FAILED(hr = IDirect3D8_GetAdapterDisplayMode(&device->d3d_parent->IDirect3D8_iface, + device->adapter_ordinal, &mode))) { WARN("Failed to get device display mode, hr %#x.\n", hr); return hr; @@ -845,6 +847,7 @@ struct wined3d_swapchain_desc desc; struct d3d8_swapchain *object; unsigned int swap_interval; + unsigned int output_idx; unsigned int i, count; HRESULT hr; @@ -875,7 +878,9 @@ } wined3d_mutex_unlock(); - if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters)) + output_idx = device->adapter_ordinal; + if (!wined3d_swapchain_desc_from_d3d8(&desc, device->d3d_parent->wined3d_outputs[output_idx], + present_parameters)) return D3DERR_INVALIDCALL; swap_interval = wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval); if (SUCCEEDED(hr = d3d8_swapchain_create(device, &desc, swap_interval, &object))) @@ -940,6 +945,7 @@ struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); struct wined3d_swapchain_desc swapchain_desc; struct d3d8_swapchain *implicit_swapchain; + unsigned int output_idx; HRESULT hr; TRACE("iface %p, present_parameters %p.\n", iface, present_parameters); @@ -949,7 +955,9 @@ WARN("App not active, returning D3DERR_DEVICELOST.\n"); return D3DERR_DEVICELOST; } - if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters)) + output_idx = device->adapter_ordinal; + if (!wined3d_swapchain_desc_from_d3d8(&swapchain_desc, + device->d3d_parent->wined3d_outputs[output_idx], present_parameters)) return D3DERR_INVALIDCALL; swapchain_desc.flags |= WINED3D_SWAPCHAIN_IMPLICIT; @@ -3717,6 +3725,7 @@ struct wined3d_swapchain_desc swapchain_desc; struct wined3d_swapchain *wined3d_swapchain; struct wined3d_adapter *wined3d_adapter; + struct wined3d_output *wined3d_output; struct d3d8_swapchain *d3d_swapchain; struct wined3d_caps caps; unsigned int output_idx; @@ -3749,7 +3758,8 @@ if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu(); wined3d_mutex_lock(); - wined3d_adapter = wined3d_output_get_adapter(parent->wined3d_outputs[output_idx]); + wined3d_output = parent->wined3d_outputs[output_idx]; + wined3d_adapter = wined3d_output_get_adapter(wined3d_output); if (FAILED(hr = wined3d_device_create(wined3d, wined3d_adapter, wined3d_device_type_from_d3d(device_type), focus_window, flags, 4, feature_levels, ARRAY_SIZE(feature_levels), &device->device_parent, &device->wined3d_device))) @@ -3791,7 +3801,7 @@ if (flags & D3DCREATE_MULTITHREADED) wined3d_device_set_multithreaded(device->wined3d_device); - if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, parameters)) + if (!wined3d_swapchain_desc_from_d3d8(&swapchain_desc, wined3d_output, parameters)) { wined3d_device_release_focus_window(device->wined3d_device); wined3d_device_decref(device->wined3d_device); @@ -3835,8 +3845,8 @@ device->implicit_swapchain = wined3d_swapchain; - device->d3d_parent = &parent->IDirect3D8_iface; - IDirect3D8_AddRef(device->d3d_parent); + device->d3d_parent = parent; + IDirect3D8_AddRef(&parent->IDirect3D8_iface); return D3D_OK; diff -Nru wine-development-5.8/dlls/d3d8/tests/device.c wine-development-5.9/dlls/d3d8/tests/device.c --- wine-development-5.8/dlls/d3d8/tests/device.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d3d8/tests/device.c 2020-05-22 18:49:34.000000000 +0000 @@ -9881,13 +9881,20 @@ static void test_get_display_mode(void) { + static const DWORD creation_flags[] = {0, CREATE_DEVICE_FULLSCREEN}; + unsigned int adapter_idx, adapter_count, mode_idx, test_idx; + RECT previous_monitor_rect; + unsigned int width, height; IDirect3DDevice8 *device; + MONITORINFO monitor_info; struct device_desc desc; D3DDISPLAYMODE mode; + HMONITOR monitor; IDirect3D8 *d3d; ULONG refcount; HWND window; HRESULT hr; + BOOL ret; window = create_window(); d3d = Direct3DCreate8(D3D_SDK_VERSION); @@ -9937,8 +9944,104 @@ refcount = IDirect3DDevice8_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); - IDirect3D8_Release(d3d); DestroyWindow(window); + + /* D3D8 uses adapter indices to determine which adapter to use to get the display mode */ + adapter_count = IDirect3D8_GetAdapterCount(d3d); + for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx) + { + if (!adapter_idx) + { + desc.width = 640; + desc.height = 480; + } + else + { + /* Find a mode different than that of the previous adapter, so that tests can be sure + * that they are comparing to the current adapter display mode */ + monitor = IDirect3D8_GetAdapterMonitor(d3d, adapter_idx - 1); + ok(!!monitor, "Adapter %u: GetAdapterMonitor failed.\n", adapter_idx - 1); + monitor_info.cbSize = sizeof(monitor_info); + ret = GetMonitorInfoW(monitor, &monitor_info); + ok(ret, "Adapter %u: GetMonitorInfoW failed, error %#x.\n", adapter_idx - 1, + GetLastError()); + previous_monitor_rect = monitor_info.rcMonitor; + + desc.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left; + desc.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top; + for (mode_idx = 0; SUCCEEDED(IDirect3D8_EnumAdapterModes(d3d, adapter_idx, mode_idx, + &mode)); ++mode_idx) + { + if (mode.Format != D3DFMT_X8R8G8B8) + continue; + if (mode.Width < 640 || mode.Height < 480) + continue; + if (mode.Width != desc.width && mode.Height != desc.height) + break; + } + ok(mode.Width != desc.width && mode.Height != desc.height, + "Adapter %u: Failed to find a different mode than %ux%u.\n", adapter_idx, + desc.width, desc.height); + desc.width = mode.Width; + desc.height = mode.Height; + } + + for (test_idx = 0; test_idx < ARRAY_SIZE(creation_flags); ++test_idx) + { + window = create_window(); + desc.adapter_ordinal = adapter_idx; + desc.device_window = window; + desc.flags = creation_flags[test_idx]; + if (!(device = create_device(d3d, window, &desc))) + { + skip("Adapter %u test %u: Failed to create a D3D device.\n", adapter_idx, test_idx); + DestroyWindow(window); + continue; + } + + monitor = IDirect3D8_GetAdapterMonitor(d3d, adapter_idx); + ok(!!monitor, "Adapter %u test %u: GetAdapterMonitor failed.\n", adapter_idx, test_idx); + monitor_info.cbSize = sizeof(monitor_info); + ret = GetMonitorInfoW(monitor, &monitor_info); + ok(ret, "Adapter %u test %u: GetMonitorInfoW failed, error %#x.\n", adapter_idx, + test_idx, GetLastError()); + width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left; + height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top; + + if (adapter_idx) + { + /* Move the device window to the previous monitor to test that the device window + * position doesn't affect which adapter to use to get the display mode */ + ret = SetWindowPos(window, 0, previous_monitor_rect.left, previous_monitor_rect.top, + 0, 0, SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "Adapter %u test %u: SetWindowPos failed, error %#x.\n", adapter_idx, + test_idx, GetLastError()); + } + + hr = IDirect3D8_GetAdapterDisplayMode(d3d, adapter_idx, &mode); + ok(hr == D3D_OK, "Adapter %u test %u: GetAdapterDisplayMode failed, hr %#x.\n", + adapter_idx, test_idx, hr); + ok(mode.Width == width, "Adapter %u test %u: Expect width %u, got %u.\n", adapter_idx, + test_idx, width, mode.Width); + ok(mode.Height == height, "Adapter %u test %u: Expect height %u, got %u.\n", + adapter_idx, test_idx, height, mode.Height); + + hr = IDirect3DDevice8_GetDisplayMode(device, &mode); + ok(hr == D3D_OK, "Adapter %u test %u: GetDisplayMode failed, hr %#x.\n", adapter_idx, + test_idx, hr); + ok(mode.Width == width, "Adapter %u test %u: Expect width %u, got %u.\n", adapter_idx, + test_idx, width, mode.Width); + ok(mode.Height == height, "Adapter %u test %u: Expect height %u, got %u.\n", + adapter_idx, test_idx, height, mode.Height); + + refcount = IDirect3DDevice8_Release(device); + ok(!refcount, "Adapter %u test %u: Device has %u references left.\n", adapter_idx, + test_idx, refcount); + DestroyWindow(window); + } + } + + IDirect3D8_Release(d3d); } static void test_multi_adapter(void) @@ -10168,6 +10271,87 @@ DestroyWindow(window); } +static void test_window_position(void) +{ + unsigned int adapter_idx, adapter_count; + struct device_desc device_desc; + IDirect3DDevice8 *device; + MONITORINFO monitor_info; + HMONITOR monitor; + RECT window_rect; + IDirect3D8 *d3d; + HWND window; + HRESULT hr; + BOOL ret; + + d3d = Direct3DCreate8(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + + adapter_count = IDirect3D8_GetAdapterCount(d3d); + for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx) + { + monitor = IDirect3D8_GetAdapterMonitor(d3d, adapter_idx); + ok(!!monitor, "Adapter %u: GetAdapterMonitor failed.\n", adapter_idx); + monitor_info.cbSize = sizeof(monitor_info); + ret = GetMonitorInfoW(monitor, &monitor_info); + ok(ret, "Adapter %u: GetMonitorInfoW failed, error %#x.\n", adapter_idx, GetLastError()); + + window = create_window(); + device_desc.adapter_ordinal = adapter_idx; + device_desc.device_window = window; + device_desc.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left; + device_desc.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top; + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + if (!(device = create_device(d3d, window, &device_desc))) + { + skip("Adapter %u: Failed to create a D3D device, skipping tests.\n", adapter_idx); + DestroyWindow(window); + continue; + } + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "Adapter %u: GetWindowRect failed, error %#x.\n", adapter_idx, GetLastError()); + ok(EqualRect(&window_rect, &monitor_info.rcMonitor), + "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx, + wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect)); + + /* Device resets should restore the window rectangle to fit the whole monitor */ + ret = SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "Adapter %u: SetWindowPos failed, error %#x.\n", adapter_idx, GetLastError()); + hr = reset_device(device, &device_desc); + ok(hr == D3D_OK, "Adapter %u: Failed to reset device, hr %#x.\n", adapter_idx, hr); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "Adapter %u: GetWindowRect failed, error %#x.\n", adapter_idx, GetLastError()); + ok(EqualRect(&window_rect, &monitor_info.rcMonitor), + "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx, + wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect)); + + /* Window activation should restore the window rectangle to fit the whole monitor */ + ret = SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "Adapter %u: SetWindowPos failed, error %#x.\n", adapter_idx, GetLastError()); + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Adapter %u: SetForegroundWindow failed, error %#x.\n", adapter_idx, GetLastError()); + flush_events(); + ret = ShowWindow(window, SW_RESTORE); + ok(ret, "Adapter %u: Failed to restore window, error %#x.\n", adapter_idx, GetLastError()); + flush_events(); + ret = SetForegroundWindow(window); + ok(ret, "Adapter %u: SetForegroundWindow failed, error %#x.\n", adapter_idx, GetLastError()); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "Adapter %u: GetWindowRect failed, error %#x.\n", adapter_idx, GetLastError()); + ok(EqualRect(&window_rect, &monitor_info.rcMonitor), + "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx, + wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect)); + + IDirect3DDevice8_Release(device); + DestroyWindow(window); + } + + IDirect3D8_Release(d3d); +} + START_TEST(device) { HMODULE d3d8_handle = GetModuleHandleA("d3d8.dll"); @@ -10287,6 +10471,7 @@ test_multi_adapter(); test_creation_parameters(); test_cursor_clipping(); + test_window_position(); UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL)); } diff -Nru wine-development-5.8/dlls/d3d9/device.c wine-development-5.9/dlls/d3d9/device.c --- wine-development-5.8/dlls/d3d9/device.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d3d9/device.c 2020-05-22 18:49:34.000000000 +0000 @@ -300,8 +300,9 @@ } } -static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc, - const D3DPRESENT_PARAMETERS *present_parameters, BOOL extended) +static BOOL wined3d_swapchain_desc_from_d3d9(struct wined3d_swapchain_desc *swapchain_desc, + struct wined3d_output *output, const D3DPRESENT_PARAMETERS *present_parameters, + BOOL extended) { D3DSWAPEFFECT highest_swapeffect = extended ? D3DSWAPEFFECT_FLIPEX : D3DSWAPEFFECT_COPY; UINT highest_bb_count = extended ? 30 : 3; @@ -332,6 +333,7 @@ return FALSE; } + swapchain_desc->output = output; swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth; swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight; swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat); @@ -887,6 +889,7 @@ struct wined3d_swapchain_desc desc; struct d3d9_swapchain *object; unsigned int swap_interval; + unsigned int output_idx; unsigned int i, count; HRESULT hr; @@ -917,8 +920,9 @@ } wined3d_mutex_unlock(); - if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters, - device->d3d_parent->extended)) + output_idx = device->adapter_ordinal; + if (!wined3d_swapchain_desc_from_d3d9(&desc, device->d3d_parent->wined3d_outputs[output_idx], + present_parameters, device->d3d_parent->extended)) return D3DERR_INVALIDCALL; swap_interval = wined3dswapinterval_from_d3d(present_parameters->PresentationInterval); if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, swap_interval, &object))) @@ -1042,6 +1046,7 @@ struct wined3d_display_mode wined3d_mode; struct wined3d_rendertarget_view *rtv; struct d3d9_swapchain *d3d9_swapchain; + unsigned int output_idx; unsigned int i; HRESULT hr; @@ -1060,7 +1065,9 @@ wined3d_mode.scanline_ordering = wined3d_scanline_ordering_from_d3d(mode->ScanLineOrdering); } - if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters, extended)) + output_idx = device->adapter_ordinal; + if (!wined3d_swapchain_desc_from_d3d9(&swapchain_desc, + device->d3d_parent->wined3d_outputs[output_idx], present_parameters, extended)) return D3DERR_INVALIDCALL; swapchain_desc.flags |= WINED3D_SWAPCHAIN_IMPLICIT; @@ -4763,8 +4770,8 @@ for (i = 0; i < count; ++i) { - if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc[i], ¶meters[i], - parent->extended)) + if (!wined3d_swapchain_desc_from_d3d9(&swapchain_desc[i], + parent->wined3d_outputs[output_idx + i], ¶meters[i], parent->extended)) { wined3d_device_release_focus_window(device->wined3d_device); wined3d_device_decref(device->wined3d_device); diff -Nru wine-development-5.8/dlls/d3d9/tests/device.c wine-development-5.9/dlls/d3d9/tests/device.c --- wine-development-5.8/dlls/d3d9/tests/device.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d3d9/tests/device.c 2020-05-22 18:49:34.000000000 +0000 @@ -13549,14 +13549,21 @@ static void test_get_display_mode(void) { + static const DWORD creation_flags[] = {0, CREATE_DEVICE_FULLSCREEN}; + unsigned int adapter_idx, adapter_count, mode_idx, test_idx; IDirect3DSwapChain9 *swapchain; + RECT previous_monitor_rect; + unsigned int width, height; IDirect3DDevice9 *device; + MONITORINFO monitor_info; struct device_desc desc; D3DDISPLAYMODE mode; + HMONITOR monitor; IDirect3D9 *d3d; ULONG refcount; HWND window; HRESULT hr; + BOOL ret; window = create_window(); d3d = Direct3DCreate9(D3D_SDK_VERSION); @@ -13620,8 +13627,114 @@ refcount = IDirect3DDevice9_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); - IDirect3D9_Release(d3d); DestroyWindow(window); + + /* D3D9 uses adapter indices to determine which adapter to use to get the display mode */ + adapter_count = IDirect3D9_GetAdapterCount(d3d); + for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx) + { + if (!adapter_idx) + { + desc.width = 640; + desc.height = 480; + } + else + { + /* Find a mode different than that of the previous adapter, so that tests can be sure + * that they are comparing to the current adapter display mode */ + monitor = IDirect3D9_GetAdapterMonitor(d3d, adapter_idx - 1); + ok(!!monitor, "Adapter %u: GetAdapterMonitor failed.\n", adapter_idx - 1); + monitor_info.cbSize = sizeof(monitor_info); + ret = GetMonitorInfoW(monitor, &monitor_info); + ok(ret, "Adapter %u: GetMonitorInfoW failed, error %#x.\n", adapter_idx - 1, + GetLastError()); + previous_monitor_rect = monitor_info.rcMonitor; + + desc.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left; + desc.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top; + for (mode_idx = 0; SUCCEEDED(IDirect3D9_EnumAdapterModes(d3d, adapter_idx, + D3DFMT_X8R8G8B8, mode_idx, &mode)); ++mode_idx) + { + if (mode.Width < 640 || mode.Height < 480) + continue; + if (mode.Width != desc.width && mode.Height != desc.height) + break; + } + ok(mode.Width != desc.width && mode.Height != desc.height, + "Adapter %u: Failed to find a different mode than %ux%u.\n", adapter_idx, + desc.width, desc.height); + desc.width = mode.Width; + desc.height = mode.Height; + } + + for (test_idx = 0; test_idx < ARRAY_SIZE(creation_flags); ++test_idx) + { + window = create_window(); + desc.adapter_ordinal = adapter_idx; + desc.device_window = window; + desc.flags = creation_flags[test_idx]; + if (!(device = create_device(d3d, window, &desc))) + { + skip("Adapter %u test %u: Failed to create a D3D device.\n", adapter_idx, test_idx); + DestroyWindow(window); + continue; + } + + monitor = IDirect3D9_GetAdapterMonitor(d3d, adapter_idx); + ok(!!monitor, "Adapter %u test %u: GetAdapterMonitor failed.\n", adapter_idx, test_idx); + monitor_info.cbSize = sizeof(monitor_info); + ret = GetMonitorInfoW(monitor, &monitor_info); + ok(ret, "Adapter %u test %u: GetMonitorInfoW failed, error %#x.\n", adapter_idx, + test_idx, GetLastError()); + width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left; + height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top; + + if (adapter_idx) + { + /* Move the device window to the previous monitor to test that the device window + * position doesn't affect which adapter to use to get the display mode */ + ret = SetWindowPos(window, 0, previous_monitor_rect.left, previous_monitor_rect.top, + 0, 0, SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "Adapter %u test %u: SetWindowPos failed, error %#x.\n", adapter_idx, + test_idx, GetLastError()); + } + + hr = IDirect3D9_GetAdapterDisplayMode(d3d, adapter_idx, &mode); + ok(hr == D3D_OK, "Adapter %u test %u: GetAdapterDisplayMode failed, hr %#x.\n", + adapter_idx, test_idx, hr); + ok(mode.Width == width, "Adapter %u test %u: Expect width %u, got %u.\n", adapter_idx, + test_idx, width, mode.Width); + ok(mode.Height == height, "Adapter %u test %u: Expect height %u, got %u.\n", + adapter_idx, test_idx, height, mode.Height); + + hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode); + ok(hr == D3D_OK, "Adapter %u test %u: GetDisplayMode failed, hr %#x.\n", adapter_idx, + test_idx, hr); + ok(mode.Width == width, "Adapter %u test %u: Expect width %u, got %u.\n", adapter_idx, + test_idx, width, mode.Width); + ok(mode.Height == height, "Adapter %u test %u: Expect height %u, got %u.\n", + adapter_idx, test_idx, height, mode.Height); + + hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain); + ok(hr == D3D_OK, "Adapter %u test %u: GetSwapChain failed, hr %#x.\n", adapter_idx, + test_idx, hr); + hr = IDirect3DSwapChain9_GetDisplayMode(swapchain, &mode); + ok(hr == D3D_OK, "Adapter %u test %u: GetDisplayMode failed, hr %#x.\n", adapter_idx, + test_idx, hr); + ok(mode.Width == width, "Adapter %u test %u: Expect width %u, got %u.\n", adapter_idx, + test_idx, width, mode.Width); + ok(mode.Height == height, "Adapter %u test %u: Expect height %u, got %u.\n", + adapter_idx, test_idx, height, mode.Height); + IDirect3DSwapChain9_Release(swapchain); + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Adapter %u test %u: Device has %u references left.\n", adapter_idx, + test_idx, refcount); + DestroyWindow(window); + } + } + + IDirect3D9_Release(d3d); } static void test_multi_adapter(void) @@ -13909,6 +14022,87 @@ DestroyWindow(window); } +static void test_window_position(void) +{ + unsigned int adapter_idx, adapter_count; + struct device_desc device_desc; + IDirect3DDevice9 *device; + MONITORINFO monitor_info; + HMONITOR monitor; + RECT window_rect; + IDirect3D9 *d3d; + HWND window; + HRESULT hr; + BOOL ret; + + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + + adapter_count = IDirect3D9_GetAdapterCount(d3d); + for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx) + { + monitor = IDirect3D9_GetAdapterMonitor(d3d, adapter_idx); + ok(!!monitor, "Adapter %u: GetAdapterMonitor failed.\n", adapter_idx); + monitor_info.cbSize = sizeof(monitor_info); + ret = GetMonitorInfoW(monitor, &monitor_info); + ok(ret, "Adapter %u: GetMonitorInfoW failed, error %#x.\n", adapter_idx, GetLastError()); + + window = create_window(); + device_desc.adapter_ordinal = adapter_idx; + device_desc.device_window = window; + device_desc.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left; + device_desc.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top; + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + if (!(device = create_device(d3d, window, &device_desc))) + { + skip("Adapter %u: Failed to create a D3D device, skipping tests.\n", adapter_idx); + DestroyWindow(window); + continue; + } + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "Adapter %u: GetWindowRect failed, error %#x.\n", adapter_idx, GetLastError()); + ok(EqualRect(&window_rect, &monitor_info.rcMonitor), + "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx, + wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect)); + + /* Device resets should restore the window rectangle to fit the whole monitor */ + ret = SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "Adapter %u: SetWindowPos failed, error %#x.\n", adapter_idx, GetLastError()); + hr = reset_device(device, &device_desc); + ok(hr == D3D_OK, "Adapter %u: Failed to reset device, hr %#x.\n", adapter_idx, hr); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "Adapter %u: GetWindowRect failed, error %#x.\n", adapter_idx, GetLastError()); + ok(EqualRect(&window_rect, &monitor_info.rcMonitor), + "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx, + wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect)); + + /* Window activation should restore the window rectangle to fit the whole monitor */ + ret = SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "Adapter %u: SetWindowPos failed, error %#x.\n", adapter_idx, GetLastError()); + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Adapter %u: SetForegroundWindow failed, error %#x.\n", adapter_idx, GetLastError()); + flush_events(); + ret = ShowWindow(window, SW_RESTORE); + ok(ret, "Adapter %u: Failed to restore window, error %#x.\n", adapter_idx, GetLastError()); + flush_events(); + ret = SetForegroundWindow(window); + ok(ret, "Adapter %u: SetForegroundWindow failed, error %#x.\n", adapter_idx, GetLastError()); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "Adapter %u: GetWindowRect failed, error %#x.\n", adapter_idx, GetLastError()); + ok(EqualRect(&window_rect, &monitor_info.rcMonitor), + "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx, + wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect)); + + IDirect3DDevice9_Release(device); + DestroyWindow(window); + } + + IDirect3D9_Release(d3d); +} + START_TEST(device) { HMODULE d3d9_handle = GetModuleHandleA("d3d9.dll"); @@ -14043,6 +14237,7 @@ test_shader_validator(); test_creation_parameters(); test_cursor_clipping(); + test_window_position(); UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL)); } diff -Nru wine-development-5.8/dlls/d3dcompiler_43/hlsl.y wine-development-5.9/dlls/d3dcompiler_43/hlsl.y --- wine-development-5.8/dlls/d3dcompiler_43/hlsl.y 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/d3dcompiler_43/hlsl.y 2020-05-22 18:49:34.000000000 +0000 @@ -125,6 +125,11 @@ } } +static BOOL type_is_single_reg(const struct hlsl_type *type) +{ + return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; +} + static BOOL declare_variable(struct hlsl_ir_var *decl, BOOL local) { BOOL ret; @@ -507,6 +512,41 @@ return jump; } +static struct hlsl_ir_var *new_synthetic_var(const char *name, struct hlsl_type *type, + const struct source_location loc) +{ + struct hlsl_ir_var *var; + + if (!(var = d3dcompiler_alloc(sizeof(*var)))) + { + hlsl_ctx.status = PARSE_ERR; + return NULL; + } + + var->name = strdup(name); + var->data_type = type; + var->loc = loc; + list_add_tail(&hlsl_ctx.globals->vars, &var->scope_entry); + return var; +} + +static struct hlsl_ir_assignment *make_simple_assignment(struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs) +{ + struct hlsl_ir_assignment *assign; + + if (!(assign = d3dcompiler_alloc(sizeof(*assign)))) + return NULL; + + init_node(&assign->node, HLSL_IR_ASSIGNMENT, rhs->data_type, rhs->loc); + assign->lhs.type = HLSL_IR_DEREF_VAR; + assign->lhs.v.var = lhs; + assign->rhs = rhs; + if (type_is_single_reg(lhs->data_type)) + assign->writemask = (1 << lhs->data_type->dimx) - 1; + + return assign; +} + static struct hlsl_ir_deref *new_var_deref(struct hlsl_ir_var *var, const struct source_location loc) { struct hlsl_ir_deref *deref = d3dcompiler_alloc(sizeof(*deref)); @@ -522,16 +562,43 @@ return deref; } +static struct hlsl_ir_node *get_var_deref(struct hlsl_ir_node *node) +{ + struct hlsl_ir_assignment *assign; + struct hlsl_ir_deref *deref; + struct hlsl_ir_var *var; + char name[27]; + + if (node->type == HLSL_IR_DEREF) + return node; + + sprintf(name, "", node); + if (!(var = new_synthetic_var(name, node->data_type, node->loc))) + return NULL; + + TRACE("Synthesized variable %p for %s node.\n", var, debug_node_type(node->type)); + + if (!(assign = make_simple_assignment(var, node))) + return NULL; + list_add_after(&node->entry, &assign->node.entry); + + if (!(deref = new_var_deref(var, var->loc))) + return NULL; + list_add_after(&assign->node.entry, &deref->node.entry); + return &deref->node; +} + static struct hlsl_ir_deref *new_record_deref(struct hlsl_ir_node *record, struct hlsl_struct_field *field, const struct source_location loc) { - struct hlsl_ir_deref *deref = d3dcompiler_alloc(sizeof(*deref)); + struct hlsl_ir_deref *deref; - if (!deref) - { - ERR("Out of memory.\n"); + if (!(record = get_var_deref(record))) return NULL; - } + + if (!(deref = d3dcompiler_alloc(sizeof(*deref)))) + return NULL; + init_node(&deref->node, HLSL_IR_DEREF, field->type, loc); deref->src.type = HLSL_IR_DEREF_RECORD; deref->src.v.record.record = record; @@ -539,6 +606,46 @@ return deref; } +static struct hlsl_ir_deref *new_array_deref(struct hlsl_ir_node *array, + struct hlsl_ir_node *index, const struct source_location loc) +{ + const struct hlsl_type *expr_type = array->data_type; + struct hlsl_ir_deref *deref; + struct hlsl_type *data_type; + + TRACE("Array dereference from type %s.\n", debug_hlsl_type(expr_type)); + + if (expr_type->type == HLSL_CLASS_ARRAY) + { + data_type = expr_type->e.array.type; + } + else if (expr_type->type == HLSL_CLASS_MATRIX || expr_type->type == HLSL_CLASS_VECTOR) + { + FIXME("Index of matrix or vector type.\n"); + return NULL; + } + else + { + if (expr_type->type == HLSL_CLASS_SCALAR) + hlsl_report_message(loc, HLSL_LEVEL_ERROR, "array-indexed expression is scalar"); + else + hlsl_report_message(loc, HLSL_LEVEL_ERROR, "expression is not array-indexable"); + return NULL; + } + + if (!(array = get_var_deref(array))) + return NULL; + + if (!(deref = d3dcompiler_alloc(sizeof(*deref)))) + return NULL; + + init_node(&deref->node, HLSL_IR_DEREF, data_type, loc); + deref->src.type = HLSL_IR_DEREF_ARRAY; + deref->src.v.array.array = array; + deref->src.v.array.index = index; + return deref; +} + static void struct_var_initializer(struct list *list, struct hlsl_ir_var *var, struct parse_initializer *initializer) { @@ -2227,37 +2334,7 @@ } | postfix_expr '[' expr ']' { - /* This may be an array dereference or a vector/matrix - * subcomponent access. - * We store it as an array dereference in any case. */ - const struct hlsl_type *expr_type = node_from_list($1)->data_type; struct hlsl_ir_deref *deref; - struct hlsl_type *data_type; - - TRACE("Array dereference from type %s\n", debug_hlsl_type(expr_type)); - - if (expr_type->type == HLSL_CLASS_ARRAY) - { - data_type = expr_type->e.array.type; - } - else if (expr_type->type == HLSL_CLASS_MATRIX) - { - data_type = new_hlsl_type(NULL, HLSL_CLASS_VECTOR, expr_type->base_type, expr_type->dimx, 1); - } - else if (expr_type->type == HLSL_CLASS_VECTOR) - { - data_type = new_hlsl_type(NULL, HLSL_CLASS_SCALAR, expr_type->base_type, 1, 1); - } - else - { - if (expr_type->type == HLSL_CLASS_SCALAR) - hlsl_report_message(get_location(&@2), HLSL_LEVEL_ERROR, "array-indexed expression is scalar"); - else - hlsl_report_message(get_location(&@2), HLSL_LEVEL_ERROR, "expression is not array-indexable"); - free_instr_list($1); - free_instr_list($3); - YYABORT; - } if (node_from_list($3)->data_type->type != HLSL_CLASS_SCALAR) { @@ -2267,17 +2344,12 @@ YYABORT; } - if (!(deref = d3dcompiler_alloc(sizeof(*deref)))) + if (!(deref = new_array_deref(node_from_list($1), node_from_list($3), get_location(&@2)))) { free_instr_list($1); free_instr_list($3); YYABORT; } - init_node(&deref->node, HLSL_IR_DEREF, data_type, get_location(&@2)); - deref->src.type = HLSL_IR_DEREF_ARRAY; - deref->src.v.array.array = node_from_list($1); - deref->src.v.array.index = node_from_list($3); - $$ = append_binop($1, $3, &deref->node); } /* "var_modifiers" doesn't make sense in this case, but it's needed diff -Nru wine-development-5.8/dlls/dbghelp/dbghelp_private.h wine-development-5.9/dlls/dbghelp/dbghelp_private.h --- wine-development-5.8/dlls/dbghelp/dbghelp_private.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dbghelp/dbghelp_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -674,7 +674,7 @@ extern WCHAR *get_dos_file_name(const WCHAR *filename) DECLSPEC_HIDDEN; extern BOOL search_dll_path(const struct process* process, const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) DECLSPEC_HIDDEN; -extern BOOL search_unix_path(const WCHAR *name, const char *path, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) DECLSPEC_HIDDEN; +extern BOOL search_unix_path(const WCHAR *name, const WCHAR *path, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) DECLSPEC_HIDDEN; extern const WCHAR* file_name(const WCHAR* str) DECLSPEC_HIDDEN; extern const char* file_nameA(const char* str) DECLSPEC_HIDDEN; diff -Nru wine-development-5.8/dlls/dbghelp/elf_module.c wine-development-5.9/dlls/dbghelp/elf_module.c --- wine-development-5.8/dlls/dbghelp/elf_module.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dbghelp/elf_module.c 2020-05-22 18:49:34.000000000 +0000 @@ -1435,7 +1435,7 @@ load_elf.dyn_addr = dyn_addr; load_elf.elf_info = elf_info; - ret = search_unix_path(filename, getenv("LD_LIBRARY_PATH"), elf_load_file_cb, &load_elf) + ret = search_unix_path(filename, process_getenv(pcs, L"LD_LIBRARY_PATH"), elf_load_file_cb, &load_elf) || search_dll_path(pcs, filename, elf_load_file_cb, &load_elf); } diff -Nru wine-development-5.8/dlls/dbghelp/macho_module.c wine-development-5.9/dlls/dbghelp/macho_module.c --- wine-development-5.8/dlls/dbghelp/macho_module.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dbghelp/macho_module.c 2020-05-22 18:49:34.000000000 +0000 @@ -1574,7 +1574,7 @@ /* Try DYLD_LIBRARY_PATH first. */ p = file_name(filename); - ret = search_unix_path(p, getenv("DYLD_LIBRARY_PATH"), macho_load_file_cb, &load_params); + ret = search_unix_path(p, process_getenv(pcs, L"DYLD_LIBRARY_PATH"), macho_load_file_cb, &load_params); /* Try the path as given. */ if (!ret) @@ -1582,9 +1582,9 @@ /* Try DYLD_FALLBACK_LIBRARY_PATH, with just the filename (no directories). */ if (!ret) { - const char* fallback = getenv("DYLD_FALLBACK_LIBRARY_PATH"); + const WCHAR* fallback = process_getenv(pcs, L"DYLD_FALLBACK_LIBRARY_PATH"); if (!fallback) - fallback = "/usr/local/lib:/lib:/usr/lib"; + fallback = L"/usr/local/lib:/lib:/usr/lib"; ret = search_unix_path(p, fallback, macho_load_file_cb, &load_params); } if (!ret && p == filename) diff -Nru wine-development-5.8/dlls/dbghelp/path.c wine-development-5.9/dlls/dbghelp/path.c --- wine-development-5.8/dlls/dbghelp/path.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dbghelp/path.c 2020-05-22 18:49:34.000000000 +0000 @@ -779,9 +779,9 @@ return TRUE; } -BOOL search_unix_path(const WCHAR *name, const char *path, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) +BOOL search_unix_path(const WCHAR *name, const WCHAR *path, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) { - const char *iter, *next; + const WCHAR *iter, *next; size_t size, len; WCHAR *dos_path; char *buf; @@ -790,16 +790,16 @@ if (!path) return FALSE; name = file_name(name); - size = WideCharToMultiByte(CP_UNIXCP, 0, name, -1, NULL, 0, NULL, NULL) + strlen(path) + 1; + size = WideCharToMultiByte(CP_UNIXCP, 0, name, -1, NULL, 0, NULL, NULL) + + WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL); if (!(buf = heap_alloc(size))) return FALSE; for (iter = path;; iter = next + 1) { - if (!(next = strchr(iter, ':'))) next = iter + strlen(iter); + if (!(next = wcschr(iter, ':'))) next = iter + lstrlenW(iter); if (*iter == '/') { - len = next - iter; - memcpy(buf, iter, len); + len = WideCharToMultiByte(CP_UNIXCP, 0, iter, next - iter, buf, size, NULL, NULL); if (buf[len - 1] != '/') buf[len++] = '/'; WideCharToMultiByte(CP_UNIXCP, 0, name, -1, buf + len, size - len, NULL, NULL); if ((dos_path = wine_get_dos_file_name(buf))) diff -Nru wine-development-5.8/dlls/ddraw/ddraw.c wine-development-5.9/dlls/ddraw/ddraw.c --- wine-development-5.8/dlls/ddraw/ddraw.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ddraw/ddraw.c 2020-05-22 18:49:34.000000000 +0000 @@ -563,6 +563,7 @@ } memset(&swapchain_desc, 0, sizeof(swapchain_desc)); + swapchain_desc.output = ddraw->wined3d_output; swapchain_desc.backbuffer_width = mode.width; swapchain_desc.backbuffer_height = mode.height; swapchain_desc.backbuffer_format = mode.format_id; diff -Nru wine-development-5.8/dlls/ddraw/tests/ddraw1.c wine-development-5.9/dlls/ddraw/tests/ddraw1.c --- wine-development-5.8/dlls/ddraw/tests/ddraw1.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ddraw/tests/ddraw1.c 2020-05-22 18:49:34.000000000 +0000 @@ -13633,6 +13633,104 @@ DestroyWindow(window); } +static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect, + LPARAM lparam) +{ + RECT primary_rect, window_rect; + IDirectDraw *ddraw; + HWND window; + HRESULT hr; + BOOL ret; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left, + monitor_rect->top, monitor_rect->right - monitor_rect->left, + monitor_rect->bottom - monitor_rect->top, NULL, NULL, NULL, NULL); + ok(!!window, "Failed to create a window.\n"); + flush_events(); + + hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + /* Window activation should restore the window to fit the whole primary monitor */ + ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError()); + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + flush_events(); + ret = ShowWindow(window, SW_RESTORE); + ok(ret, "Failed to restore window, error %#x.\n", GetLastError()); + flush_events(); + ret = SetForegroundWindow(window); + ok(ret, "SetForegroundWindow failed, error %#x.\n", GetLastError()); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + DestroyWindow(window); + IDirectDraw_Release(ddraw); + return TRUE; +} + +static void test_window_position(void) +{ + EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0); +} + +static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect, + LPARAM lparam) +{ + DDSURFACEDESC surface_desc; + IDirectDraw *ddraw; + HWND window; + HRESULT hr; + BOOL ret; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + window = create_window(); + ok(!!window, "Failed to create a window.\n"); + + /* Test that DirectDraw doesn't use the device window to determine which monitor to use */ + ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError()); + + surface_desc.dwSize = sizeof(surface_desc); + hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc); + ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr); + ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %d.\n", + GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth); + ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %d.\n", + GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight); + + DestroyWindow(window); + IDirectDraw_Release(ddraw); + return TRUE; +} + +static void test_get_display_mode(void) +{ + EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0); +} + START_TEST(ddraw1) { DDDEVICEIDENTIFIER identifier; @@ -13747,4 +13845,6 @@ test_d32_support(); test_cursor_clipping(); test_vtbl_protection(); + test_window_position(); + test_get_display_mode(); } diff -Nru wine-development-5.8/dlls/ddraw/tests/ddraw2.c wine-development-5.9/dlls/ddraw/tests/ddraw2.c --- wine-development-5.8/dlls/ddraw/tests/ddraw2.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ddraw/tests/ddraw2.c 2020-05-22 18:49:34.000000000 +0000 @@ -14405,6 +14405,104 @@ DestroyWindow(window); } +static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect, + LPARAM lparam) +{ + RECT primary_rect, window_rect; + IDirectDraw2 *ddraw; + HWND window; + HRESULT hr; + BOOL ret; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left, + monitor_rect->top, monitor_rect->right - monitor_rect->left, + monitor_rect->bottom - monitor_rect->top, NULL, NULL, NULL, NULL); + ok(!!window, "Failed to create a window.\n"); + flush_events(); + + hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + /* Window activation should restore the window to fit the whole primary monitor */ + ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError()); + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + flush_events(); + ret = ShowWindow(window, SW_RESTORE); + ok(ret, "Failed to restore window, error %#x.\n", GetLastError()); + flush_events(); + ret = SetForegroundWindow(window); + ok(ret, "SetForegroundWindow failed, error %#x.\n", GetLastError()); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + DestroyWindow(window); + IDirectDraw2_Release(ddraw); + return TRUE; +} + +static void test_window_position(void) +{ + EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0); +} + +static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect, + LPARAM lparam) +{ + DDSURFACEDESC surface_desc; + IDirectDraw2 *ddraw; + HWND window; + HRESULT hr; + BOOL ret; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + window = create_window(); + ok(!!window, "Failed to create a window.\n"); + + /* Test that DirectDraw doesn't use the device window to determine which monitor to use */ + ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError()); + + surface_desc.dwSize = sizeof(surface_desc); + hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc); + ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr); + ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %d.\n", + GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth); + ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %d.\n", + GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight); + + DestroyWindow(window); + IDirectDraw2_Release(ddraw); + return TRUE; +} + +static void test_get_display_mode(void) +{ + EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0); +} + START_TEST(ddraw2) { DDDEVICEIDENTIFIER identifier; @@ -14525,4 +14623,6 @@ test_caps(); test_d32_support(); test_cursor_clipping(); + test_window_position(); + test_get_display_mode(); } diff -Nru wine-development-5.8/dlls/ddraw/tests/ddraw4.c wine-development-5.9/dlls/ddraw/tests/ddraw4.c --- wine-development-5.8/dlls/ddraw/tests/ddraw4.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ddraw/tests/ddraw4.c 2020-05-22 18:49:34.000000000 +0000 @@ -17432,6 +17432,104 @@ DestroyWindow(window); } +static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect, + LPARAM lparam) +{ + RECT primary_rect, window_rect; + IDirectDraw4 *ddraw; + HWND window; + HRESULT hr; + BOOL ret; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left, + monitor_rect->top, monitor_rect->right - monitor_rect->left, + monitor_rect->bottom - monitor_rect->top, NULL, NULL, NULL, NULL); + ok(!!window, "Failed to create a window.\n"); + flush_events(); + + hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + /* Window activation should restore the window to fit the whole primary monitor */ + ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError()); + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + flush_events(); + ret = ShowWindow(window, SW_RESTORE); + ok(ret, "Failed to restore window, error %#x.\n", GetLastError()); + flush_events(); + ret = SetForegroundWindow(window); + ok(ret, "SetForegroundWindow failed, error %#x.\n", GetLastError()); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + DestroyWindow(window); + IDirectDraw4_Release(ddraw); + return TRUE; +} + +static void test_window_position(void) +{ + EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0); +} + +static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect, + LPARAM lparam) +{ + DDSURFACEDESC2 surface_desc; + IDirectDraw4 *ddraw; + HWND window; + HRESULT hr; + BOOL ret; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + window = create_window(); + ok(!!window, "Failed to create a window.\n"); + + /* Test that DirectDraw doesn't use the device window to determine which monitor to use */ + ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError()); + + surface_desc.dwSize = sizeof(surface_desc); + hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc); + ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr); + ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %d.\n", + GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth); + ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %d.\n", + GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight); + + DestroyWindow(window); + IDirectDraw4_Release(ddraw); + return TRUE; +} + +static void test_get_display_mode(void) +{ + EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0); +} + START_TEST(ddraw4) { DDDEVICEIDENTIFIER identifier; @@ -17568,4 +17666,6 @@ test_d32_support(); test_surface_format_conversion_alpha(); test_cursor_clipping(); + test_window_position(); + test_get_display_mode(); } diff -Nru wine-development-5.8/dlls/ddraw/tests/ddraw7.c wine-development-5.9/dlls/ddraw/tests/ddraw7.c --- wine-development-5.8/dlls/ddraw/tests/ddraw7.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ddraw/tests/ddraw7.c 2020-05-22 18:49:34.000000000 +0000 @@ -7126,6 +7126,64 @@ IDirectDrawSurface7_Release(surface); + /* Test mipmap texture. */ + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT; + ddsd.dwWidth = 8; + ddsd.dwHeight = 8; + U2(ddsd).dwMipMapCount = 3; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + + hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr); + + if (FAILED(hr)) + { + skip("Mipmaps are not supported.\n"); + } + else + { + /* Changing surface desc for mipmap fails even without changing any + * parameters. */ + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr); + IDirectDrawSurface7_Release(surface); + } + + /* Test surface created with DDSD_LPSURFACE. */ + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH; + ddsd.dwWidth = 8; + ddsd.dwHeight = 8; + ddsd.lpSurface = data; + U1(ddsd).lPitch = 8 * 4; + ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = 8; + ddsd.dwHeight = 8; + /* Cannot reset lpSurface. */ + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE | DDSD_PITCH; + ddsd.dwWidth = 4; + ddsd.dwHeight = 4; + ddsd.lpSurface = data; + U1(ddsd).lPitch = 8 * 4; + /* Can change the parameters of surface created with DDSD_LPSURFACE. */ + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + IDirectDrawSurface7_Release(surface); + /* SetSurfaceDesc needs systemmemory surfaces. * * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing @@ -13347,14 +13405,14 @@ surface_desc.dwSize = sizeof(surface_desc); hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc); - ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); width = surface_desc.dwWidth; height = surface_desc.dwHeight; window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, 0, 0, width, height, NULL, NULL, NULL, NULL); hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); - ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); bpp = 0; if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0))) @@ -13367,7 +13425,7 @@ surface_desc.dwSize = sizeof(surface_desc); hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc); - ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width); ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height); ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n", @@ -13379,9 +13437,9 @@ U5(surface_desc).dwBackBufferCount = 1; surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE; hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); - ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc); - ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width); ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height); ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n", @@ -13397,15 +13455,39 @@ surface_desc.dwHeight = height; surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); - ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc); - ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n", U4(surface_desc).ddpfPixelFormat.dwFlags); ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp); IDirectDrawSurface7_Release(surface); + /* Test compatibility mode mipmap texture creation. */ + hr = IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0); + ok(hr == DD_OK || hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr); + if (FAILED(hr)) + { + win_skip("SetDisplayMode failed, skipping test."); + goto done; + } + bpp = 16; + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT | DDSD_PITCH; + U2(surface_desc).dwMipMapCount = 2; + surface_desc.dwWidth = 4; + surface_desc.dwHeight = 4; + U1(surface_desc).lPitch = surface_desc.dwWidth * bpp / 8; + surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_VIDEOMEMORY; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL); + ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Got unexpected hr %#x.\n", hr); + if (surface) + IDirectDrawSurface7_Release(surface); + +done: refcount = IDirectDraw7_Release(ddraw); ok(!refcount, "DirectDraw has %u references left.\n", refcount); DestroyWindow(window); @@ -17667,6 +17749,104 @@ DestroyWindow(window); } +static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect, + LPARAM lparam) +{ + RECT primary_rect, window_rect; + IDirectDraw7 *ddraw; + HWND window; + HRESULT hr; + BOOL ret; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left, + monitor_rect->top, monitor_rect->right - monitor_rect->left, + monitor_rect->bottom - monitor_rect->top, NULL, NULL, NULL, NULL); + ok(!!window, "Failed to create a window.\n"); + flush_events(); + + hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + /* Window activation should restore the window to fit the whole primary monitor */ + ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError()); + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + flush_events(); + ret = ShowWindow(window, SW_RESTORE); + ok(ret, "Failed to restore window, error %#x.\n", GetLastError()); + flush_events(); + ret = SetForegroundWindow(window); + ok(ret, "SetForegroundWindow failed, error %#x.\n", GetLastError()); + flush_events(); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr); + ret = GetWindowRect(window, &window_rect); + ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError()); + ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n", + wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect)); + + DestroyWindow(window); + IDirectDraw7_Release(ddraw); + return TRUE; +} + +static void test_window_position(void) +{ + EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0); +} + +static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect, + LPARAM lparam) +{ + DDSURFACEDESC2 surface_desc; + IDirectDraw7 *ddraw; + HWND window; + HRESULT hr; + BOOL ret; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + window = create_window(); + ok(!!window, "Failed to create a window.\n"); + + /* Test that DirectDraw doesn't use the device window to determine which monitor to use */ + ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError()); + + surface_desc.dwSize = sizeof(surface_desc); + hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc); + ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr); + ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %d.\n", + GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth); + ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %d.\n", + GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight); + + DestroyWindow(window); + IDirectDraw7_Release(ddraw); + return TRUE; +} + +static void test_get_display_mode(void) +{ + EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0); +} + START_TEST(ddraw7) { DDDEVICEIDENTIFIER2 identifier; @@ -17818,4 +17998,6 @@ test_surface_format_conversion_alpha(); test_compressed_surface_stretch(); test_cursor_clipping(); + test_window_position(); + test_get_display_mode(); } diff -Nru wine-development-5.8/dlls/devenum/createdevenum.c wine-development-5.9/dlls/devenum/createdevenum.c --- wine-development-5.8/dlls/devenum/createdevenum.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/devenum/createdevenum.c 2020-05-22 18:49:34.000000000 +0000 @@ -40,17 +40,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(devenum); -static const WCHAR wszFilterKeyName[] = {'F','i','l','t','e','r',0}; -static const WCHAR wszMeritName[] = {'M','e','r','i','t',0}; -static const WCHAR wszPins[] = {'P','i','n','s',0}; -static const WCHAR wszAllowedMany[] = {'A','l','l','o','w','e','d','M','a','n','y',0}; -static const WCHAR wszAllowedZero[] = {'A','l','l','o','w','e','d','Z','e','r','o',0}; -static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0}; -static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0}; -static const WCHAR wszTypes[] = {'T','y','p','e','s',0}; -static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; -static const WCHAR wszFilterData[] = {'F','i','l','t','e','r','D','a','t','a',0}; - static HRESULT WINAPI devenum_factory_QueryInterface(ICreateDevEnum *iface, REFIID riid, void **ppv) { TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); @@ -92,7 +81,6 @@ static HRESULT register_codec(const GUID *class, const WCHAR *name, const GUID *clsid, const WCHAR *friendly_name, IPropertyBag **ret) { - static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','c','m',':',0}; WCHAR guidstr[CHARS_IN_GUID]; IParseDisplayName *parser; IPropertyBag *propbag; @@ -106,17 +94,16 @@ if (FAILED(hr)) return hr; - buffer = heap_alloc((lstrlenW(deviceW) + CHARS_IN_GUID + lstrlenW(name) + 1) * sizeof(WCHAR)); - if (!buffer) + if (!(buffer = heap_alloc((wcslen(L"@device:cm:") + CHARS_IN_GUID + wcslen(name) + 1) * sizeof(WCHAR)))) { IParseDisplayName_Release(parser); return E_OUTOFMEMORY; } - lstrcpyW(buffer, deviceW); - StringFromGUID2(class, buffer + lstrlenW(buffer), CHARS_IN_GUID); - lstrcatW(buffer, backslashW); - lstrcatW(buffer, name); + wcscpy(buffer, L"@device:cm:"); + StringFromGUID2(class, buffer + wcslen(buffer), CHARS_IN_GUID); + wcscat(buffer, L"\\"); + wcscat(buffer, name); IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, &mon); IParseDisplayName_Release(parser); @@ -127,7 +114,7 @@ V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(friendly_name); - hr = IPropertyBag_Write(propbag, wszFriendlyName, &var); + hr = IPropertyBag_Write(propbag, L"FriendlyName", &var); VariantClear(&var); if (FAILED(hr)) { @@ -138,7 +125,7 @@ V_VT(&var) = VT_BSTR; StringFromGUID2(clsid, guidstr, ARRAY_SIZE(guidstr)); V_BSTR(&var) = SysAllocString(guidstr); - hr = IPropertyBag_Write(propbag, clsidW, &var); + hr = IPropertyBag_Write(propbag, L"CLSID", &var); VariantClear(&var); if (FAILED(hr)) { @@ -157,7 +144,7 @@ REGPINTYPES *lpMediaType = NULL; DWORD dwMediaTypeSize = 0; - if (RegOpenKeyExW(hkeyPinKey, wszTypes, 0, KEY_READ, &hkeyTypes) != ERROR_SUCCESS) + if (RegOpenKeyExW(hkeyPinKey, L"Types", 0, KEY_READ, &hkeyTypes) != ERROR_SUCCESS) return ; if (RegQueryInfoKeyW(hkeyTypes, NULL, NULL, NULL, &dwMajorTypes, NULL, NULL, NULL, NULL, NULL, NULL, NULL) @@ -253,7 +240,7 @@ rgf2->u.s2.cPins2 = 0; rgf2->u.s2.rgPins2 = NULL; - if (RegOpenKeyExW(hkeyFilterClass, wszPins, 0, KEY_READ, &hkeyPins) != ERROR_SUCCESS) + if (RegOpenKeyExW(hkeyFilterClass, L"Pins", 0, KEY_READ, &hkeyPins) != ERROR_SUCCESS) return ; if (RegQueryInfoKeyW(hkeyPins, NULL, NULL, NULL, &dwPinsSubkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL) @@ -289,21 +276,21 @@ if (RegOpenKeyExW(hkeyPins, wszPinName, 0, KEY_READ, &hkeyPinKey) != ERROR_SUCCESS) continue; size = sizeof(DWORD); - lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (BYTE *)&value, &size); + lRet = RegQueryValueExW(hkeyPinKey, L"AllowedMany", NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; if (value) rgPin->dwFlags |= REG_PINFLAG_B_MANY; size = sizeof(DWORD); - lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (BYTE *)&value, &size); + lRet = RegQueryValueExW(hkeyPinKey, L"AllowedZero", NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; if (value) rgPin->dwFlags |= REG_PINFLAG_B_ZERO; size = sizeof(DWORD); - lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (BYTE *)&value, &size); + lRet = RegQueryValueExW(hkeyPinKey, L"Direction", NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; if (value) @@ -311,7 +298,7 @@ size = sizeof(DWORD); - lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (BYTE *)&value, &size); + lRet = RegQueryValueExW(hkeyPinKey, L"IsRendered", NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; if (value) @@ -364,40 +351,44 @@ } } -static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf) +HRESULT create_filter_data(VARIANT *var, REGFILTER2 *rgf) { - BYTE *data = NULL, *array; IAMFilterData *fildata; - SAFEARRAYBOUND sabound; - VARIANT var = {}; + BYTE *data = NULL; ULONG size; HRESULT hr; hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IAMFilterData, (void **)&fildata); - if (FAILED(hr)) goto cleanup; + if (FAILED(hr)) + return hr; hr = IAMFilterData_CreateFilterData(fildata, rgf, &data, &size); - if (FAILED(hr)) goto cleanup; - - V_VT(&var) = VT_ARRAY | VT_UI1; - sabound.lLbound = 0; - sabound.cElements = size; - if (!(V_ARRAY(&var) = SafeArrayCreate(VT_UI1, 1, &sabound))) - goto cleanup; - hr = SafeArrayAccessData(V_ARRAY(&var), (void *)&array); - if (FAILED(hr)) goto cleanup; - - memcpy(array, data, size); - hr = SafeArrayUnaccessData(V_ARRAY(&var)); - if (FAILED(hr)) goto cleanup; + IAMFilterData_Release(fildata); + if (FAILED(hr)) + return hr; - hr = IPropertyBag_Write(prop_bag, wszFilterData, &var); - if (FAILED(hr)) goto cleanup; + V_VT(var) = VT_ARRAY | VT_UI1; + if (!(V_ARRAY(var) = SafeArrayCreateVector(VT_UI1, 1, size))) + { + VariantClear(var); + CoTaskMemFree(data); + return E_OUTOFMEMORY; + } -cleanup: - VariantClear(&var); + memcpy(V_ARRAY(var)->pvData, data, size); CoTaskMemFree(data); - IAMFilterData_Release(fildata); + return S_OK; +} + +static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf) +{ + VARIANT var; + + if (SUCCEEDED(create_filter_data(&var, rgf))) + { + IPropertyBag_Write(prop_bag, L"FilterData", &var); + VariantClear(&var); + } } static void register_legacy_filters(void) @@ -407,7 +398,7 @@ LONG lRet; HRESULT hr; - lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilterKeyName, 0, KEY_READ, &hkeyFilter); + lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Filter", 0, KEY_READ, &hkeyFilter); hr = HRESULT_FROM_WIN32(lRet); if (SUCCEEDED(hr)) @@ -437,10 +428,7 @@ if (FAILED(hr)) continue; - lstrcpyW(wszRegKey, clsidW); - lstrcatW(wszRegKey, backslashW); - lstrcatW(wszRegKey, wszFilterSubkeyName); - + swprintf(wszRegKey, ARRAY_SIZE(wszRegKey), L"CLSID\\%s", wszFilterSubkeyName); if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &classkey) != ERROR_SUCCESS) continue; @@ -473,7 +461,7 @@ rgf2.dwMerit = MERIT_NORMAL; len = sizeof(rgf2.dwMerit); - RegQueryValueExW(classkey, wszMeritName, NULL, &Type, (BYTE *)&rgf2.dwMerit, &len); + RegQueryValueExW(classkey, L"Merit", NULL, &Type, (BYTE *)&rgf2.dwMerit, &len); DEVENUM_ReadPins(classkey, &rgf2); @@ -490,9 +478,7 @@ static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, const WCHAR *module, void *context) { - static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','D','i','r','e','c','t','S','o','u','n','d',' ','D','e','v','i','c','e',0}; - static const WCHAR directsoundW[] = {'D','i','r','e','c','t','S','o','u','n','d',':',' ',0}; - static const WCHAR dsguidW[] = {'D','S','G','u','i','d',0}; + static const WCHAR defaultW[] = L"Default DirectSound Device"; IPropertyBag *prop_bag = NULL; REGFILTERPINS2 rgpins = {0}; REGPINTYPES rgtypes = {0}; @@ -503,11 +489,11 @@ if (guid) { - WCHAR *name = heap_alloc(sizeof(defaultW) + lstrlenW(desc) * sizeof(WCHAR)); + WCHAR *name = heap_alloc(sizeof(defaultW) + wcslen(desc) * sizeof(WCHAR)); if (!name) return FALSE; - lstrcpyW(name, directsoundW); - lstrcatW(name, desc); + wcscpy(name, L"DirectSound: "); + wcscat(name, desc); hr = register_codec(&CLSID_AudioRendererCategory, name, &CLSID_DSoundRender, name, &prop_bag); @@ -537,7 +523,7 @@ V_VT(&var) = VT_BSTR; StringFromGUID2(guid ? guid : &GUID_NULL, clsid, CHARS_IN_GUID); if ((V_BSTR(&var) = SysAllocString(clsid))) - hr = IPropertyBag_Write(prop_bag, dsguidW, &var); + hr = IPropertyBag_Write(prop_bag, L"DSGuid", &var); VariantClear(&var); IPropertyBag_Release(prop_bag); @@ -546,8 +532,6 @@ static void register_waveout_devices(void) { - static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','W','a','v','e','O','u','t',' ','D','e','v','i','c','e',0}; - static const WCHAR waveoutidW[] = {'W','a','v','e','O','u','t','I','d',0}; IPropertyBag *prop_bag = NULL; REGFILTERPINS2 rgpins = {0}; REGPINTYPES rgtypes = {0}; @@ -564,7 +548,7 @@ { waveOutGetDevCapsW(i, &caps, sizeof(caps)); - name = (i == -1) ? defaultW : caps.szPname; + name = (i == -1) ? L"Default WaveOut Device" : caps.szPname; hr = register_codec(&CLSID_AudioRendererCategory, name, &CLSID_AudioRender, name, &prop_bag); @@ -587,7 +571,7 @@ /* write WaveOutId */ V_VT(&var) = VT_I4; V_I4(&var) = i; - IPropertyBag_Write(prop_bag, waveoutidW, &var); + IPropertyBag_Write(prop_bag, L"WaveOutId", &var); VariantClear(&var); if (prop_bag) IPropertyBag_Release(prop_bag); @@ -596,7 +580,6 @@ static void register_wavein_devices(void) { - static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0}; IPropertyBag *prop_bag = NULL; REGFILTER2 rgf = {0}; WAVEINCAPSW caps; @@ -624,7 +607,7 @@ /* write WaveInId */ V_VT(&var) = VT_I4; V_I4(&var) = i; - IPropertyBag_Write(prop_bag, waveinidW, &var); + IPropertyBag_Write(prop_bag, L"WaveInId", &var); VariantClear(&var); IPropertyBag_Release(prop_bag); @@ -633,8 +616,6 @@ static void register_midiout_devices(void) { - static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','M','i','d','i','O','u','t',' ','D','e','v','i','c','e',0}; - static const WCHAR midioutidW[] = {'M','i','d','i','O','u','t','I','d',0}; IPropertyBag *prop_bag = NULL; REGFILTERPINS2 rgpins = {0}; REGPINTYPES rgtypes = {0}; @@ -651,7 +632,7 @@ { midiOutGetDevCapsW(i, &caps, sizeof(caps)); - name = (i == -1) ? defaultW : caps.szPname; + name = (i == -1) ? L"Default MidiOut Device" : caps.szPname; hr = register_codec(&CLSID_MidiRendererCategory, name, &CLSID_AVIMIDIRender, name, &prop_bag); @@ -674,7 +655,7 @@ /* write MidiOutId */ V_VT(&var) = VT_I4; V_I4(&var) = i; - IPropertyBag_Write(prop_bag, midioutidW, &var); + IPropertyBag_Write(prop_bag, L"MidiOutId", &var); VariantClear(&var); IPropertyBag_Release(prop_bag); @@ -683,7 +664,6 @@ static void register_vfw_codecs(void) { - static const WCHAR fcchandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0}; REGFILTERPINS2 rgpins[2] = {}; IPropertyBag *prop_bag = NULL; REGPINTYPES rgtypes[2]; @@ -732,7 +712,7 @@ /* write WaveInId */ V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(name); - IPropertyBag_Write(prop_bag, fcchandlerW, &var); + IPropertyBag_Write(prop_bag, L"FccHandler", &var); VariantClear(&var); IPropertyBag_Release(prop_bag); @@ -741,13 +721,12 @@ static void register_avicap_devices(void) { - static const WCHAR vfwindexW[] = {'V','F','W','I','n','d','e','x',0}; - WCHAR name[] = {'v','i','d','e','o','0',0}; WCHAR friendlyname[32], version[32]; IPropertyBag *prop_bag = NULL; REGFILTERPINS2 rgpins = {0}; REGPINTYPES rgtypes; REGFILTER2 rgf; + WCHAR name[6]; VARIANT var; HRESULT hr; int i = 0; @@ -758,7 +737,7 @@ version, ARRAY_SIZE(version))) continue; - name[5] = '0' + i; + swprintf(name, ARRAY_SIZE(name), L"video%d", i); hr = register_codec(&CLSID_VideoInputDeviceCategory, name, &CLSID_VfwCapture, friendlyname, &prop_bag); @@ -780,7 +759,7 @@ /* write VFWIndex */ V_VT(&var) = VT_I4; V_I4(&var) = i; - IPropertyBag_Write(prop_bag, vfwindexW, &var); + IPropertyBag_Write(prop_bag, L"VFWIndex", &var); VariantClear(&var); IPropertyBag_Release(prop_bag); @@ -801,7 +780,7 @@ *out = NULL; - if (!RegOpenKeyW(HKEY_CURRENT_USER, wszActiveMovieKey, &key)) + if (!RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Microsoft\\ActiveMovie\\devenum", &key)) { StringFromGUID2(class, guidstr, ARRAY_SIZE(guidstr)); RegDeleteTreeW(key, guidstr); diff -Nru wine-development-5.8/dlls/devenum/devenum_main.c wine-development-5.9/dlls/devenum/devenum_main.c --- wine-development-5.8/dlls/devenum/devenum_main.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/devenum/devenum_main.c 2020-05-22 18:49:34.000000000 +0000 @@ -162,27 +162,17 @@ &IID_IFilterMapper2, &mapvptr); if (SUCCEEDED(res)) { - static const WCHAR friendlyvidcap[] = {'V','i','d','e','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0}; - static const WCHAR friendlydshow[] = {'D','i','r','e','c','t','S','h','o','w',' ','F','i','l','t','e','r','s',0}; - static const WCHAR friendlyvidcomp[] = {'V','i','d','e','o',' ','C','o','m','p','r','e','s','s','o','r','s',0}; - static const WCHAR friendlyaudcap[] = {'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0}; - static const WCHAR friendlyaudcomp[] = {'A','u','d','i','o',' ','C','o','m','p','r','e','s','s','o','r','s',0}; - static const WCHAR friendlyaudrend[] = {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r','s',0}; - static const WCHAR friendlymidirend[] = {'M','i','d','i',' ','R','e','n','d','e','r','e','r','s',0}; - static const WCHAR friendlyextrend[] = {'E','x','t','e','r','n','a','l',' ','R','e','n','d','e','r','e','r','s',0}; - static const WCHAR friendlydevctrl[] = {'D','e','v','i','c','e',' ','C','o','n','t','r','o','l',' ','F','i','l','t','e','r','s',0}; - pMapper = mapvptr; - IFilterMapper2_CreateCategory(pMapper, &CLSID_VideoInputDeviceCategory, MERIT_DO_NOT_USE, friendlyvidcap); - IFilterMapper2_CreateCategory(pMapper, &CLSID_LegacyAmFilterCategory, MERIT_NORMAL, friendlydshow); - IFilterMapper2_CreateCategory(pMapper, &CLSID_VideoCompressorCategory, MERIT_DO_NOT_USE, friendlyvidcomp); - IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioInputDeviceCategory, MERIT_DO_NOT_USE, friendlyaudcap); - IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioCompressorCategory, MERIT_DO_NOT_USE, friendlyaudcomp); - IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioRendererCategory, MERIT_NORMAL, friendlyaudrend); - IFilterMapper2_CreateCategory(pMapper, &CLSID_MidiRendererCategory, MERIT_NORMAL, friendlymidirend); - IFilterMapper2_CreateCategory(pMapper, &CLSID_TransmitCategory, MERIT_DO_NOT_USE, friendlyextrend); - IFilterMapper2_CreateCategory(pMapper, &CLSID_DeviceControlCategory, MERIT_DO_NOT_USE, friendlydevctrl); + IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioCompressorCategory, MERIT_DO_NOT_USE, L"Audio Compressors"); + IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioInputDeviceCategory, MERIT_DO_NOT_USE, L"Audio Capture Sources"); + IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioRendererCategory, MERIT_NORMAL, L"Audio Renderers"); + IFilterMapper2_CreateCategory(pMapper, &CLSID_DeviceControlCategory, MERIT_DO_NOT_USE, L"Device Control Filters"); + IFilterMapper2_CreateCategory(pMapper, &CLSID_LegacyAmFilterCategory, MERIT_NORMAL, L"DirectShow Filters"); + IFilterMapper2_CreateCategory(pMapper, &CLSID_MidiRendererCategory, MERIT_NORMAL, L"Midi Renderers"); + IFilterMapper2_CreateCategory(pMapper, &CLSID_TransmitCategory, MERIT_DO_NOT_USE, L"External Renderers"); + IFilterMapper2_CreateCategory(pMapper, &CLSID_VideoInputDeviceCategory, MERIT_DO_NOT_USE, L"Video Capture Sources"); + IFilterMapper2_CreateCategory(pMapper, &CLSID_VideoCompressorCategory, MERIT_DO_NOT_USE, L"Video Compressors"); IFilterMapper2_Release(pMapper); } diff -Nru wine-development-5.8/dlls/devenum/devenum_private.h wine-development-5.9/dlls/devenum/devenum_private.h --- wine-development-5.8/dlls/devenum/devenum_private.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/devenum/devenum_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -54,6 +54,7 @@ IPropertyBag IPropertyBag_iface; }; +HRESULT create_filter_data(VARIANT *var, REGFILTER2 *rgf) DECLSPEC_HIDDEN; struct moniker *dmo_moniker_create(const GUID class, const GUID clsid) DECLSPEC_HIDDEN; struct moniker *codec_moniker_create(const GUID *class, const WCHAR *name) DECLSPEC_HIDDEN; struct moniker *filter_moniker_create(const GUID *class, const WCHAR *name) DECLSPEC_HIDDEN; @@ -61,19 +62,3 @@ extern ICreateDevEnum devenum_factory DECLSPEC_HIDDEN; extern IParseDisplayName devenum_parser DECLSPEC_HIDDEN; - -/********************************************************************** - * Global string constant declarations - */ - -static const WCHAR backslashW[] = {'\\',0}; -static const WCHAR clsidW[] = {'C','L','S','I','D',0}; -static const WCHAR instanceW[] = {'\\','I','n','s','t','a','n','c','e',0}; -static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'A','c','t','i','v','e','M','o','v','i','e','\\', - 'd','e','v','e','n','u','m','\\',0}; -static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0}; -static const WCHAR dmoW[] = {'d','m','o',':',0}; -static const WCHAR swW[] = {'s','w',':',0}; -static const WCHAR cmW[] = {'c','m',':',0}; diff -Nru wine-development-5.8/dlls/devenum/mediacatenum.c wine-development-5.9/dlls/devenum/mediacatenum.c --- wine-development-5.8/dlls/devenum/mediacatenum.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/devenum/mediacatenum.c 2020-05-22 18:49:34.000000000 +0000 @@ -28,12 +28,41 @@ WINE_DEFAULT_DEBUG_CHANNEL(devenum); +BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size) +{ + unsigned int max_capacity, new_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~0u / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(8, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = count; + + if (!(new_elements = realloc(*elements, new_capacity * size))) + { + ERR("Failed to allocate memory.\n"); + return FALSE; + } + + *elements = new_elements; + *capacity = new_capacity; + return TRUE; +} + typedef struct { IEnumMoniker IEnumMoniker_iface; CLSID class; LONG ref; - IEnumDMO *dmo_enum; + IEnumDMO *dmo_enum, *dmo_enum2; HKEY sw_key; DWORD sw_index; HKEY cm_key; @@ -106,6 +135,70 @@ } return hr; } + else if (!wcscmp(name, L"FilterData")) + { + REGFILTERPINS2 reg_pins[2] = {{0}}; + REGFILTER2 reg_filter = + { + .dwVersion = 2, + .dwMerit = MERIT_NORMAL + 0x800, + .cPins2 = 2, + .rgPins2 = reg_pins, + }; + + unsigned int count = 1, input_count, output_count, i; + DMO_PARTIAL_MEDIATYPE *types = NULL; + REGPINTYPES *reg_types; + HRESULT hr; + + if (!(types = malloc(2 * count * sizeof(*types)))) + return E_OUTOFMEMORY; + + while ((hr = DMOGetTypes(&moniker->clsid, count, &input_count, types, + count, &output_count, types + count)) == S_FALSE) + { + count *= 2; + if (!(types = realloc(types, count * sizeof(*types)))) + { + free(types); + return E_OUTOFMEMORY; + } + } + if (hr != S_OK) + { + free(types); + return hr; + } + + if (!(reg_types = malloc(2 * count * sizeof(*reg_types)))) + { + free(types); + return hr; + } + + for (i = 0; i < input_count; ++i) + { + reg_types[i].clsMajorType = &types[i].type; + reg_types[i].clsMinorType = &types[i].subtype; + } + for (i = 0; i < output_count; ++i) + { + reg_types[count + i].clsMajorType = &types[count + i].type; + reg_types[count + i].clsMinorType = &types[count + i].subtype; + } + reg_pins[0].cInstances = 1; + reg_pins[0].nMediaTypes = input_count; + reg_pins[0].lpMediaType = reg_types; + reg_pins[1].dwFlags = REG_PINFLAG_B_OUTPUT; + reg_pins[1].cInstances = 1; + reg_pins[1].nMediaTypes = output_count; + reg_pins[1].lpMediaType = reg_types + count; + + hr = create_filter_data(var, ®_filter); + free(reg_types); + free(types); + return hr; + } return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); } @@ -524,7 +617,7 @@ if (SUCCEEDED(IMoniker_GetDisplayName(iface, bind, NULL, &this_name)) && SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker, bind, NULL, &other_name))) { - int result = lstrcmpiW(this_name, other_name); + int result = wcsicmp(this_name, other_name); CoTaskMemFree(this_name); CoTaskMemFree(other_name); if (!result) @@ -603,33 +696,30 @@ if (This->type == DEVICE_DMO) { - buffer = CoTaskMemAlloc((lstrlenW(deviceW) + lstrlenW(dmoW) - + 2 * CHARS_IN_GUID + 1) * sizeof(WCHAR)); + buffer = CoTaskMemAlloc((12 + 2 * CHARS_IN_GUID + 1) * sizeof(WCHAR)); if (!buffer) return E_OUTOFMEMORY; - lstrcpyW(buffer, deviceW); - lstrcatW(buffer, dmoW); - StringFromGUID2(&This->clsid, buffer + lstrlenW(buffer), CHARS_IN_GUID); - StringFromGUID2(&This->class, buffer + lstrlenW(buffer), CHARS_IN_GUID); + wcscpy(buffer, L"@device:dmo:"); + StringFromGUID2(&This->clsid, buffer + wcslen(buffer), CHARS_IN_GUID); + StringFromGUID2(&This->class, buffer + wcslen(buffer), CHARS_IN_GUID); } else { - buffer = CoTaskMemAlloc((lstrlenW(deviceW) + 3 + (This->has_class ? CHARS_IN_GUID : 0) - + lstrlenW(This->name) + 1) * sizeof(WCHAR)); + buffer = CoTaskMemAlloc((11 + (This->has_class ? CHARS_IN_GUID : 0) + + wcslen(This->name) + 1) * sizeof(WCHAR)); if (!buffer) return E_OUTOFMEMORY; - lstrcpyW(buffer, deviceW); if (This->type == DEVICE_FILTER) - lstrcatW(buffer, swW); + wcscpy(buffer, L"@device:sw:"); else if (This->type == DEVICE_CODEC) - lstrcatW(buffer, cmW); + wcscpy(buffer, L"@device:cm:"); if (This->has_class) { - StringFromGUID2(&This->class, buffer + lstrlenW(buffer), CHARS_IN_GUID); - lstrcatW(buffer, backslashW); + StringFromGUID2(&This->class, buffer + wcslen(buffer), CHARS_IN_GUID); + wcscat(buffer, L"\\"); } - lstrcatW(buffer, This->name); + wcscat(buffer, This->name); } *ppszDisplayName = buffer; @@ -786,16 +876,39 @@ if (!ref) { - IEnumDMO_Release(This->dmo_enum); + if (This->dmo_enum) + IEnumDMO_Release(This->dmo_enum); + if (This->dmo_enum2) + IEnumDMO_Release(This->dmo_enum2); RegCloseKey(This->sw_key); RegCloseKey(This->cm_key); - CoTaskMemFree(This); + free(This); DEVENUM_UnlockModule(); return 0; } return ref; } +static struct moniker *get_dmo_moniker(EnumMonikerImpl *enum_moniker) +{ + GUID clsid; + + if (IsEqualGUID(&enum_moniker->class, &CLSID_LegacyAmFilterCategory)) + { + if (enum_moniker->dmo_enum && IEnumDMO_Next(enum_moniker->dmo_enum, 1, &clsid, NULL, NULL) == S_OK) + return dmo_moniker_create(DMOCATEGORY_AUDIO_DECODER, clsid); + if (enum_moniker->dmo_enum2 && IEnumDMO_Next(enum_moniker->dmo_enum2, 1, &clsid, NULL, NULL) == S_OK) + return dmo_moniker_create(DMOCATEGORY_VIDEO_DECODER, clsid); + } + else + { + if (enum_moniker->dmo_enum && IEnumDMO_Next(enum_moniker->dmo_enum, 1, &clsid, NULL, NULL) == S_OK) + return dmo_moniker_create(enum_moniker->class, clsid); + } + + return NULL; +} + static HRESULT WINAPI enum_moniker_Next(IEnumMoniker *iface, ULONG celt, IMoniker **rgelt, ULONG *pceltFetched) { @@ -804,8 +917,6 @@ struct moniker *moniker; LONG res; ULONG fetched = 0; - HRESULT hr; - GUID clsid; HKEY hkey; TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched); @@ -815,10 +926,8 @@ /* FIXME: try PNP devices first */ /* try DMOs */ - if ((hr = IEnumDMO_Next(This->dmo_enum, 1, &clsid, NULL, NULL)) == S_OK) - { - moniker = dmo_moniker_create(This->class, clsid); - } + if ((moniker = get_dmo_moniker(This))) + ; /* try DirectShow filters */ else if (!(res = RegEnumKeyW(This->sw_key, This->sw_index, buffer, ARRAY_SIZE(buffer)))) { @@ -869,7 +978,9 @@ /* FIXME: try PNP devices first */ /* try DMOs */ - if (IEnumDMO_Skip(This->dmo_enum, 1) == S_OK) + if (This->dmo_enum && IEnumDMO_Skip(This->dmo_enum, 1) == S_OK) + ; + else if (This->dmo_enum2 && IEnumDMO_Skip(This->dmo_enum2, 1) == S_OK) ; /* try DirectShow filters */ else if (RegEnumKeyW(This->sw_key, This->sw_index, NULL, 0) != ERROR_NO_MORE_ITEMS) @@ -894,7 +1005,10 @@ TRACE("(%p)->()\n", iface); - IEnumDMO_Reset(This->dmo_enum); + if (This->dmo_enum) + IEnumDMO_Reset(This->dmo_enum); + if (This->dmo_enum2) + IEnumDMO_Reset(This->dmo_enum2); This->sw_index = 0; This->cm_index = 0; @@ -922,41 +1036,43 @@ enum_moniker_Clone, }; -HRESULT enum_moniker_create(REFCLSID class, IEnumMoniker **ppEnumMoniker) +HRESULT enum_moniker_create(REFCLSID class, IEnumMoniker **out) { - EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl)); + EnumMonikerImpl *object; WCHAR buffer[78]; - HRESULT hr; - if (!pEnumMoniker) + if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY; - pEnumMoniker->IEnumMoniker_iface.lpVtbl = &IEnumMoniker_Vtbl; - pEnumMoniker->ref = 1; - pEnumMoniker->sw_index = 0; - pEnumMoniker->cm_index = 0; - pEnumMoniker->class = *class; - - lstrcpyW(buffer, clsidW); - lstrcatW(buffer, backslashW); - StringFromGUID2(class, buffer + lstrlenW(buffer), CHARS_IN_GUID); - lstrcatW(buffer, instanceW); - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->sw_key)) - pEnumMoniker->sw_key = NULL; - - lstrcpyW(buffer, wszActiveMovieKey); - StringFromGUID2(class, buffer + lstrlenW(buffer), CHARS_IN_GUID); - if (RegOpenKeyExW(HKEY_CURRENT_USER, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->cm_key)) - pEnumMoniker->cm_key = NULL; + object->IEnumMoniker_iface.lpVtbl = &IEnumMoniker_Vtbl; + object->ref = 1; + object->class = *class; - hr = DMOEnum(class, 0, 0, NULL, 0, NULL, &pEnumMoniker->dmo_enum); - if (FAILED(hr)) + wcscpy(buffer, L"CLSID\\"); + StringFromGUID2(class, buffer + wcslen(buffer), CHARS_IN_GUID); + wcscat(buffer, L"\\Instance"); + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &object->sw_key)) + object->sw_key = NULL; + + wcscpy(buffer, L"Software\\Microsoft\\ActiveMovie\\devenum\\"); + StringFromGUID2(class, buffer + wcslen(buffer), CHARS_IN_GUID); + if (RegOpenKeyExW(HKEY_CURRENT_USER, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &object->cm_key)) + object->cm_key = NULL; + + if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory)) + { + if (FAILED(DMOEnum(&DMOCATEGORY_AUDIO_DECODER, 0, 0, NULL, 0, NULL, &object->dmo_enum))) + object->dmo_enum = NULL; + if (FAILED(DMOEnum(&DMOCATEGORY_VIDEO_DECODER, 0, 0, NULL, 0, NULL, &object->dmo_enum2))) + object->dmo_enum2 = NULL; + } + else { - IEnumMoniker_Release(&pEnumMoniker->IEnumMoniker_iface); - return hr; + if (FAILED(DMOEnum(class, 0, 0, NULL, 0, NULL, &object->dmo_enum))) + object->dmo_enum = NULL; } - *ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface; + *out = &object->IEnumMoniker_iface; DEVENUM_LockModule(); diff -Nru wine-development-5.8/dlls/devenum/parsedisplayname.c wine-development-5.9/dlls/devenum/parsedisplayname.c --- wine-development-5.8/dlls/devenum/parsedisplayname.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/devenum/parsedisplayname.c 2020-05-22 18:49:34.000000000 +0000 @@ -77,21 +77,21 @@ *ret = NULL; if (eaten) - *eaten = lstrlenW(name); + *eaten = wcslen(name); name = wcschr(name, ':') + 1; - if (!wcsncmp(name, swW, 3)) + if (!wcsncmp(name, L"sw:", 3)) { type = DEVICE_FILTER; name += 3; } - else if (!wcsncmp(name, cmW, 3)) + else if (!wcsncmp(name, L"cm:", 3)) { type = DEVICE_CODEC; name += 3; } - else if (!wcsncmp(name, dmoW, 4)) + else if (!wcsncmp(name, L"dmo:", 4)) { type = DEVICE_DMO; name += 4; diff -Nru wine-development-5.8/dlls/devenum/tests/devenum.c wine-development-5.9/dlls/devenum/tests/devenum.c --- wine-development-5.8/dlls/devenum/tests/devenum.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/devenum/tests/devenum.c 2020-05-22 18:49:34.000000000 +0000 @@ -245,16 +245,18 @@ BOOL found = FALSE; CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (void **)&devenum); - ICreateDevEnum_CreateClassEnumerator(devenum, class, &enum_mon, 0); - while (!found && IEnumMoniker_Next(enum_mon, 1, &mon, NULL) == S_OK) + if (ICreateDevEnum_CreateClassEnumerator(devenum, class, &enum_mon, 0) == S_OK) { - if (IMoniker_IsEqual(mon, needle) == S_OK) - found = TRUE; + while (!found && IEnumMoniker_Next(enum_mon, 1, &mon, NULL) == S_OK) + { + if (IMoniker_IsEqual(mon, needle) == S_OK) + found = TRUE; - IMoniker_Release(mon); - } + IMoniker_Release(mon); + } - IEnumMoniker_Release(enum_mon); + IEnumMoniker_Release(enum_mon); + } ICreateDevEnum_Release(devenum); return found; } @@ -594,7 +596,7 @@ IParseDisplayName_Release(parser); } -static void test_dmo(void) +static void test_dmo(const GUID *dmo_category, const GUID *enum_category) { IParseDisplayName *parser; IPropertyBag *prop_bag; @@ -613,10 +615,10 @@ wcscpy(buffer, L"@device:dmo:"); StringFromGUID2(&CLSID_TestFilter, buffer + wcslen(buffer), CHARS_IN_GUID); - StringFromGUID2(&CLSID_AudioRendererCategory, buffer + wcslen(buffer), CHARS_IN_GUID); + StringFromGUID2(dmo_category, buffer + wcslen(buffer), CHARS_IN_GUID); mon = check_display_name(parser, buffer); - ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "DMO should not be registered\n"); + ok(!find_moniker(enum_category, mon), "DMO should not be registered\n"); hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); ok(hr == S_OK, "got %#x\n", hr); @@ -630,12 +632,12 @@ hr = IPropertyBag_Write(prop_bag, L"FriendlyName", &var); ok(hr == E_ACCESSDENIED, "Write failed: %#x\n", hr); - hr = DMORegister(L"devenum test", &CLSID_TestFilter, &CLSID_AudioRendererCategory, 0, 0, NULL, 0, NULL); + hr = DMORegister(L"devenum test", &CLSID_TestFilter, dmo_category, 0, 0, NULL, 0, NULL); if (hr != E_FAIL) { ok(hr == S_OK, "got %#x\n", hr); - ok(find_moniker(&CLSID_AudioRendererCategory, mon), "DMO should be registered\n"); + ok(find_moniker(enum_category, mon), "DMO should be registered\n"); VariantClear(&var); hr = IPropertyBag_Read(prop_bag, L"FriendlyName", &var, NULL); @@ -652,7 +654,7 @@ hr = IPropertyBag_Read(prop_bag, L"CLSID", &var, NULL); ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "got %#x\n", hr); - hr = DMOUnregister(&CLSID_TestFilter, &CLSID_AudioRendererCategory); + hr = DMOUnregister(&CLSID_TestFilter, dmo_category); ok(hr == S_OK, "got %#x\n", hr); } IPropertyBag_Release(prop_bag); @@ -1168,7 +1170,9 @@ test_register_filter(); test_directshow_filter(); test_codec(); - test_dmo(); + test_dmo(&DMOCATEGORY_AUDIO_DECODER, &CLSID_LegacyAmFilterCategory); + test_dmo(&DMOCATEGORY_VIDEO_DECODER, &CLSID_LegacyAmFilterCategory); + test_dmo(&DMOCATEGORY_VIDEO_DECODER, &DMOCATEGORY_VIDEO_DECODER); test_legacy_filter(); hr = DirectSoundEnumerateW(test_dsound, NULL); diff -Nru wine-development-5.8/dlls/dmscript/script.c wine-development-5.9/dlls/dmscript/script.c --- wine-development-5.8/dlls/dmscript/script.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dmscript/script.c 2020-05-22 18:49:34.000000000 +0000 @@ -199,12 +199,6 @@ IDirectMusicScriptImpl_EnumVariable }; -/* IDirectMusicScriptImpl IDirectMusicObject part: */ -static inline IDirectMusicScriptImpl *impl_from_IDirectMusicObject(IDirectMusicObject *iface) -{ - return CONTAINING_RECORD(iface, IDirectMusicScriptImpl, dmobj.IDirectMusicObject_iface); -} - static HRESULT WINAPI script_IDirectMusicObject_ParseDescriptor(IDirectMusicObject *iface, IStream *stream, DMUS_OBJECTDESC *desc) { diff -Nru wine-development-5.8/dlls/dmusic/collection.c wine-development-5.9/dlls/dmusic/collection.c --- wine-development-5.8/dlls/dmusic/collection.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dmusic/collection.c 2020-05-22 18:49:34.000000000 +0000 @@ -49,11 +49,6 @@ return CONTAINING_RECORD(iface, IDirectMusicCollectionImpl, IDirectMusicCollection_iface); } -static inline struct dmobject *impl_from_IDirectMusicObject(IDirectMusicObject *iface) -{ - return CONTAINING_RECORD(iface, struct dmobject, IDirectMusicObject_iface); -} - static inline IDirectMusicCollectionImpl *impl_from_IPersistStream(IPersistStream *iface) { return CONTAINING_RECORD(iface, IDirectMusicCollectionImpl, dmobj.IPersistStream_iface); diff -Nru wine-development-5.8/dlls/dwrite/analyzer.c wine-development-5.9/dlls/dwrite/analyzer.c --- wine-development-5.8/dlls/dwrite/analyzer.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dwrite/analyzer.c 2020-05-22 18:49:34.000000000 +0000 @@ -280,16 +280,6 @@ return CONTAINING_RECORD(iface, struct dwrite_fontfallback_builder, IDWriteFontFallbackBuilder_iface); } -static inline UINT32 decode_surrogate_pair(const WCHAR *str, UINT32 index, UINT32 end) -{ - if (index < end-1 && IS_SURROGATE_PAIR(str[index], str[index+1])) { - UINT32 ch = 0x10000 + ((str[index] - 0xd800) << 10) + (str[index+1] - 0xdc00); - TRACE("surrogate pair (%x %x) => %x\n", str[index], str[index+1], ch); - return ch; - } - return 0; -} - static inline UINT16 get_char_script(WCHAR c) { UINT16 script = get_table_entry(wine_scripts_table, c); @@ -1059,15 +1049,17 @@ return language; } -static DWRITE_NUMBER_SUBSTITUTION_METHOD get_number_substitutes(IDWriteNumberSubstitution *substitution, WCHAR *digits) +static void get_number_substitutes(IDWriteNumberSubstitution *substitution, BOOL is_rtl, WCHAR *digits) { struct dwrite_numbersubstitution *numbersubst = unsafe_impl_from_IDWriteNumberSubstitution(substitution); DWRITE_NUMBER_SUBSTITUTION_METHOD method; WCHAR isolang[9]; DWORD lctype; + digits[0] = 0; + if (!numbersubst) - return DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE; + return; lctype = numbersubst->ignore_user_override ? LOCALE_NOUSEROVERRIDE : 0; @@ -1096,7 +1088,6 @@ else method = numbersubst->method; - digits[0] = 0; switch (method) { case DWRITE_NUMBER_SUBSTITUTION_METHOD_NATIONAL: @@ -1125,7 +1116,8 @@ method = DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE; } - return method; + if ((method == DWRITE_NUMBER_SUBSTITUTION_METHOD_CONTEXTUAL && !is_rtl) || method == DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE) + digits[0] = 0; } static void analyzer_dump_user_features(DWRITE_TYPOGRAPHIC_FEATURES const **features, @@ -1153,14 +1145,11 @@ DWRITE_SHAPING_GLYPH_PROPERTIES* glyph_props, UINT32* actual_glyph_count) { const struct dwritescript_properties *scriptprops; - DWRITE_NUMBER_SUBSTITUTION_METHOD method; - struct scriptshaping_context context; + struct scriptshaping_context context = { 0 }; struct dwrite_fontface *font_obj; WCHAR digits[NATIVE_DIGITS_LEN]; - unsigned int i, g, script; - BOOL update_cluster; - WCHAR *string; - HRESULT hr = S_OK; + unsigned int script; + HRESULT hr; TRACE("(%s:%u %p %d %d %s %s %p %p %p %u %u %p %p %p %p %p)\n", debugstr_wn(text, length), length, fontface, is_sideways, is_rtl, debugstr_sa_script(analysis->script), debugstr_w(locale), substitution, @@ -1172,78 +1161,11 @@ if (max_glyph_count < length) return E_NOT_SUFFICIENT_BUFFER; - string = heap_calloc(length, sizeof(*string)); - if (!string) - return E_OUTOFMEMORY; - - method = get_number_substitutes(substitution, digits); + get_number_substitutes(substitution, is_rtl, digits); /* FIXME: have the shaping engine set this */ memset(text_props, 0, length * sizeof(*text_props)); - for (i = 0; i < length; i++) { - /* FIXME: set to better values */ - glyph_props[i].justification = text[i] == ' ' ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER; - glyph_props[i].isClusterStart = 1; - glyph_props[i].isDiacritic = 0; - glyph_props[i].isZeroWidthSpace = 0; - glyph_props[i].reserved = 0; - - clustermap[i] = i; - - string[i] = text[i]; - switch (method) - { - case DWRITE_NUMBER_SUBSTITUTION_METHOD_CONTEXTUAL: - if (!is_rtl) - break; - /* fallthrough */ - default: - if (string[i] >= '0' && string[i] <= '9') - string[i] = digits[string[i] - '0']; - break; - case DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE: - ; - } - } - - for (; i < max_glyph_count; i++) { - glyph_props[i].justification = SCRIPT_JUSTIFY_NONE; - glyph_props[i].isClusterStart = 0; - glyph_props[i].isDiacritic = 0; - glyph_props[i].isZeroWidthSpace = 0; - glyph_props[i].reserved = 0; - } - - for (i = 0, g = 0, update_cluster = FALSE; i < length; i++) { - UINT32 codepoint; - - if (!update_cluster) { - codepoint = decode_surrogate_pair(string, i, length); - if (!codepoint) - codepoint = is_rtl ? bidi_get_mirrored_char(string[i]) : string[i]; - else - update_cluster = TRUE; - - hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &glyphs[g]); - if (FAILED(hr)) - goto done; - - g++; - } - else { - INT32 k; - - update_cluster = FALSE; - /* mark surrogate halves with same cluster */ - clustermap[i] = clustermap[i-1]; - /* update following clusters */ - for (k = i + 1; k >= 0 && k < length; k++) - clustermap[k]--; - } - } - *actual_glyph_count = g; - font_obj = unsafe_impl_from_IDWriteFontFace(fontface); context.cache = fontface_get_shaping_cache(font_obj); @@ -1253,19 +1175,26 @@ context.is_sideways = is_sideways; context.u.subst.glyphs = glyphs; context.u.subst.glyph_props = glyph_props; + context.u.subst.clustermap = clustermap; context.u.subst.max_glyph_count = max_glyph_count; - context.glyph_count = g; + context.u.subst.digits = digits; context.language_tag = get_opentype_language(locale); + context.user_features.features = features; + context.user_features.range_lengths = feature_range_lengths; + context.user_features.range_count = feature_ranges; + context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * max_glyph_count); script = analysis->script > Script_LastId ? Script_Unknown : analysis->script; scriptprops = &dwritescripts_properties[script]; hr = shape_get_glyphs(&context, scriptprops->scripttags); if (SUCCEEDED(hr)) + { + *actual_glyph_count = context.glyph_count; hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyphs, *actual_glyph_count, text_props, glyph_props); + } -done: - heap_free(string); + heap_free(context.glyph_infos); return hr; } @@ -1281,6 +1210,7 @@ struct scriptshaping_context context; struct dwrite_fontface *font_obj; unsigned int i, script; + HRESULT hr; TRACE("(%s %p %p %u %p %p %u %p %.2f %d %d %s %s %p %p %u %p %p)\n", debugstr_wn(text, text_len), clustermap, props, text_len, glyphs, glyph_props, glyph_count, fontface, emSize, is_sideways, @@ -1321,8 +1251,16 @@ context.advances = advances; context.offsets = offsets; context.language_tag = get_opentype_language(locale); + context.user_features.features = features; + context.user_features.range_lengths = feature_range_lengths; + context.user_features.range_count = feature_ranges; + context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count); + + hr = shape_get_positions(&context, scriptprops->scripttags); + + heap_free(context.glyph_infos); - return shape_get_positions(&context, scriptprops->scripttags); + return hr; } static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWriteTextAnalyzer2 *iface, @@ -1338,6 +1276,7 @@ DWRITE_MEASURING_MODE measuring_mode; struct dwrite_fontface *font_obj; unsigned int i, script; + HRESULT hr; TRACE("(%s %p %p %u %p %p %u %p %.2f %.2f %p %d %d %d %s %s %p %p %u %p %p)\n", debugstr_wn(text, text_len), clustermap, props, text_len, glyphs, glyph_props, glyph_count, fontface, emSize, ppdip, @@ -1380,8 +1319,16 @@ context.advances = advances; context.offsets = offsets; context.language_tag = get_opentype_language(locale); + context.user_features.features = features; + context.user_features.range_lengths = feature_range_lengths; + context.user_features.range_count = feature_ranges; + context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count); + + hr = shape_get_positions(&context, scriptprops->scripttags); - return shape_get_positions(&context, scriptprops->scripttags); + heap_free(context.glyph_infos); + + return hr; } static HRESULT apply_cluster_spacing(float leading_spacing, float trailing_spacing, float min_advance_width, diff -Nru wine-development-5.8/dlls/dwrite/bidi.c wine-development-5.9/dlls/dwrite/bidi.c --- wine-development-5.8/dlls/dwrite/bidi.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dwrite/bidi.c 2020-05-22 18:49:34.000000000 +0000 @@ -158,13 +158,6 @@ chartype[i] = get_table_entry( bidi_direction_table, string[i] ); } -WCHAR bidi_get_mirrored_char(WCHAR ch) -{ - extern const WCHAR wine_mirror_map[] DECLSPEC_HIDDEN; - WCHAR mirror = get_table_entry( wine_mirror_map, ch ); - return mirror ? mirror : ch; -} - /* RESOLVE EXPLICIT */ static inline UINT8 get_greater_even_level(UINT8 level) diff -Nru wine-development-5.8/dlls/dwrite/dwrite_private.h wine-development-5.9/dlls/dwrite/dwrite_private.h --- wine-development-5.8/dlls/dwrite/dwrite_private.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dwrite/dwrite_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -300,6 +300,8 @@ extern HRESULT create_inmemory_fileloader(IDWriteFontFileLoader**) DECLSPEC_HIDDEN; extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index, IDWriteFontResource **resource) DECLSPEC_HIDDEN; +extern HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints, + UINT32 count, UINT16 *glyphs); struct dwrite_fontface; @@ -378,7 +380,6 @@ /* BiDi helpers */ extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN; -extern WCHAR bidi_get_mirrored_char(WCHAR) DECLSPEC_HIDDEN; /* FreeType integration */ struct dwrite_glyphbitmap @@ -461,6 +462,11 @@ } gdef; }; +struct shaping_glyph_info +{ + unsigned int mask; +}; + struct scriptshaping_context { struct scriptshaping_cache *cache; @@ -482,10 +488,21 @@ { UINT16 *glyphs; DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props; + UINT16 *clustermap; unsigned int max_glyph_count; + const WCHAR *digits; } subst; } u; + struct + { + const DWRITE_TYPOGRAPHIC_FEATURES **features; + const unsigned int *range_lengths; + unsigned int range_count; + } user_features; + unsigned int global_mask; + struct shaping_glyph_info *glyph_infos; + unsigned int glyph_count; float emsize; DWRITE_MEASURING_MODE measuring_mode; @@ -498,6 +515,8 @@ void (*grab_font_table)(void *context, UINT32 table, const BYTE **data, UINT32 *size, void **data_context); void (*release_font_table)(void *context, void *data_context); UINT16 (*get_font_upem)(void *context); + BOOL (*has_glyph)(void *context, unsigned int codepoint); + UINT16 (*get_glyph)(void *context, unsigned int codepoint); }; extern struct scriptshaping_cache *create_scriptshaping_cache(void *context, @@ -505,9 +524,22 @@ extern void release_scriptshaping_cache(struct scriptshaping_cache*) DECLSPEC_HIDDEN; extern struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface) DECLSPEC_HIDDEN; +enum shaping_feature_flags +{ + FEATURE_GLOBAL = 0x1, + FEATURE_GLOBAL_SEARCH = 0x2, +}; + struct shaping_feature { unsigned int tag; + unsigned int index; + unsigned int flags; + unsigned int max_value; + unsigned int default_value; + unsigned int mask; + unsigned int shift; + unsigned int stage; }; struct shaping_features @@ -515,6 +547,7 @@ struct shaping_feature *features; size_t count; size_t capacity; + unsigned int stage; }; extern void opentype_layout_scriptshaping_cache_init(struct scriptshaping_cache *cache) DECLSPEC_HIDDEN; diff -Nru wine-development-5.8/dlls/dwrite/font.c wine-development-5.9/dlls/dwrite/font.c --- wine-development-5.8/dlls/dwrite/font.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dwrite/font.c 2020-05-22 18:49:34.000000000 +0000 @@ -272,11 +272,29 @@ return fontface->metrics.designUnitsPerEm; } +static BOOL dwrite_has_glyph(void *context, unsigned int codepoint) +{ + struct dwrite_fontface *fontface = context; + UINT16 index = 0; + fontface_get_glyphs(fontface, &codepoint, 1, &index); + return !!index; +} + +static UINT16 dwrite_get_glyph(void *context, unsigned int codepoint) +{ + struct dwrite_fontface *fontface = context; + UINT16 index = 0; + fontface_get_glyphs(fontface, &codepoint, 1, &index); + return index; +} + static const struct shaping_font_ops dwrite_font_ops = { dwrite_grab_font_table, dwrite_release_font_table, dwrite_get_font_upem, + dwrite_has_glyph, + dwrite_get_glyph, }; struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface) @@ -714,17 +732,9 @@ return S_OK; } -static HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints, +HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints, UINT32 count, UINT16 *glyphs) { - if (!glyphs) - return E_INVALIDARG; - - if (!codepoints) { - memset(glyphs, 0, count * sizeof(*glyphs)); - return E_INVALIDARG; - } - freetype_get_glyphs(&fontface->IDWriteFontFace5_iface, fontface->charmap, codepoints, count, glyphs); return S_OK; } @@ -736,6 +746,15 @@ TRACE("%p, %p, %u, %p.\n", iface, codepoints, count, glyphs); + if (!glyphs) + return E_INVALIDARG; + + if (!codepoints) + { + memset(glyphs, 0, count * sizeof(*glyphs)); + return E_INVALIDARG; + } + return fontface_get_glyphs(fontface, codepoints, count, glyphs); } @@ -1390,8 +1409,7 @@ TRACE("%p, %#x.\n", iface, ch); index = 0; - if (FAILED(fontface_get_glyphs(fontface, &ch, 1, &index))) - return FALSE; + fontface_get_glyphs(fontface, &ch, 1, &index); return index != 0; } diff -Nru wine-development-5.8/dlls/dwrite/opentype.c wine-development-5.9/dlls/dwrite/opentype.c --- wine-development-5.8/dlls/dwrite/opentype.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dwrite/opentype.c 2020-05-22 18:49:34.000000000 +0000 @@ -778,7 +778,7 @@ enum TT_NAME_WINDOWS_ENCODING_ID { TT_NAME_WINDOWS_ENCODING_SYMBOL = 0, - TT_NAME_WINDOWS_ENCODING_UCS2, + TT_NAME_WINDOWS_ENCODING_UNICODE_BMP, TT_NAME_WINDOWS_ENCODING_SJIS, TT_NAME_WINDOWS_ENCODING_PRC, TT_NAME_WINDOWS_ENCODING_BIG5, @@ -787,7 +787,7 @@ TT_NAME_WINDOWS_ENCODING_RESERVED1, TT_NAME_WINDOWS_ENCODING_RESERVED2, TT_NAME_WINDOWS_ENCODING_RESERVED3, - TT_NAME_WINDOWS_ENCODING_UCS4 + TT_NAME_WINDOWS_ENCODING_UNICODE_FULL }; enum TT_NAME_MAC_ENCODING_ID @@ -1972,7 +1972,8 @@ switch (encoding) { case TT_NAME_WINDOWS_ENCODING_SYMBOL: - case TT_NAME_WINDOWS_ENCODING_UCS2: + case TT_NAME_WINDOWS_ENCODING_UNICODE_BMP: + case TT_NAME_WINDOWS_ENCODING_UNICODE_FULL: break; case TT_NAME_WINDOWS_ENCODING_SJIS: codepage = 932; @@ -3210,6 +3211,36 @@ #endif } +static inline unsigned int dwrite_log2i(unsigned int x) +{ +#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3))) + return __builtin_clz(x) ^ 0x1f; +#else + static const unsigned int l[] = + { + ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + }; + unsigned int i; + + return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x]; +#endif +} + static float opentype_scale_gpos_be_value(WORD value, float emsize, UINT16 upem) { return (short)GET_BE_WORD(value) * emsize / upem; @@ -3333,7 +3364,7 @@ return lookup_offset + subtable_offset; } -struct lookup +struct ot_lookup { unsigned int offset; unsigned int subtable_count; @@ -3406,7 +3437,7 @@ } static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; WORD format, value_format, value_len, coverage; @@ -3469,7 +3500,7 @@ } static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i, first_glyph, second_glyph; @@ -3676,7 +3707,7 @@ } static BOOL opentype_layout_apply_gpos_cursive_attachment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i; @@ -3760,7 +3791,7 @@ } static BOOL opentype_layout_apply_gpos_mark_to_base_attachment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i; @@ -3843,7 +3874,7 @@ } static BOOL opentype_layout_apply_gpos_mark_to_lig_attachment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i; @@ -3889,7 +3920,7 @@ } static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i; @@ -3974,13 +4005,13 @@ } static BOOL opentype_layout_apply_gpos_contextual_positioning(const struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { return FALSE; } static BOOL opentype_layout_apply_gpos_chaining_contextual_positioning(const struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { return FALSE; } @@ -3990,7 +4021,7 @@ struct scriptshaping_cache *cache = context->cache; const struct ot_lookup_table *lookup_table; struct glyph_iterator iter; - struct lookup lookup; + struct ot_lookup lookup; WORD lookup_type; lookup.offset = table_read_be_word(&cache->gpos.table, cache->gpos.lookup_list + @@ -4081,25 +4112,83 @@ } } +struct lookup +{ + unsigned short index; + unsigned int mask; +}; + struct lookups { - int *indexes; + struct lookup *lookups; size_t capacity; size_t count; }; -static int lookups_sorting_compare(const void *left, const void *right) +static int lookups_sorting_compare(const void *a, const void *b) { - return *(int *)left - *(int *)right; + const struct lookup *left = (const struct lookup *)a; + const struct lookup *right = (const struct lookup *)b; + return left->index < right->index ? -1 : left->index > right->index ? 1 : 0; }; +static void opentype_layout_add_lookups(const struct ot_feature_list *feature_list, UINT16 total_lookup_count, + struct ot_gsubgpos_table *table, struct shaping_feature *feature, struct lookups *lookups) +{ + UINT16 feature_offset, lookup_count; + unsigned int i, j; + + /* Feature wasn't found */ + if (feature->index == 0xffff) + return; + + /* FIXME: skip non-global ones for now. */ + if (!(feature->flags & FEATURE_GLOBAL)) + return; + + feature_offset = GET_BE_WORD(feature_list->features[feature->index].offset); + + lookup_count = table_read_be_word(&table->table, table->feature_list + feature_offset + + FIELD_OFFSET(struct ot_feature, lookup_count)); + if (!lookup_count) + return; + + if (!dwrite_array_reserve((void **)&lookups->lookups, &lookups->capacity, lookups->count + lookup_count, + sizeof(*lookups->lookups))) + { + return; + } + + for (i = 0; i < lookup_count; ++i) + { + UINT16 lookup_index = table_read_be_word(&table->table, table->feature_list + feature_offset + + FIELD_OFFSET(struct ot_feature, lookuplist_index[i])); + + if (lookup_index >= total_lookup_count) + continue; + + j = lookups->count; + lookups->lookups[j].index = lookup_index; + lookups->lookups[j].mask = feature->mask; + lookups->count++; + } +} + static void opentype_layout_collect_lookups(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, const struct shaping_features *features, struct ot_gsubgpos_table *table, struct lookups *lookups) { UINT16 table_offset, langsys_offset, script_feature_count, total_feature_count, total_lookup_count; const struct ot_feature_list *feature_list; - unsigned int i, j, l; + unsigned int last_num_lookups = 0, stage; + struct shaping_feature *feature; + unsigned int i, j, next_bit; + unsigned int global_bit_shift = 1; + unsigned int global_bit_mask = 1; + UINT16 feature_index; + + if (!table->table.data) + return; /* ScriptTable offset. */ table_offset = table_read_be_word(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) + @@ -4132,48 +4221,145 @@ if (!feature_list) return; - /* Collect lookups for all given features. */ + context->global_mask = global_bit_mask; + next_bit = global_bit_shift + 1; for (i = 0; i < features->count; ++i) { + unsigned int bits_needed; + BOOL found = FALSE; + + feature = &features->features[i]; + + feature->index = 0xffff; + + if ((feature->flags & FEATURE_GLOBAL) && feature->max_value == 1) + bits_needed = 0; + else + bits_needed = min(8, dwrite_log2i(feature->max_value)); + + if (!feature->max_value || next_bit + bits_needed > 8 * sizeof (feature->mask)) + continue; + for (j = 0; j < script_feature_count; ++j) { - UINT16 feature_index = table_read_be_word(&table->table, table->script_list + table_offset + + feature_index = table_read_be_word(&table->table, table->script_list + table_offset + langsys_offset + FIELD_OFFSET(struct ot_langsys, feature_index[j])); if (feature_index >= total_feature_count) continue; - - if (feature_list->features[feature_index].tag == features->features[i].tag) + if ((found = feature_list->features[feature_index].tag == feature->tag)) { - WORD feature_offset = GET_BE_WORD(feature_list->features[feature_index].offset); - WORD lookup_count; - - lookup_count = table_read_be_word(&table->table, table->feature_list + feature_offset + - FIELD_OFFSET(struct ot_feature, lookup_count)); - if (!lookup_count) - continue; + feature->index = feature_index; + break; + } + } - if (!dwrite_array_reserve((void **)&lookups->indexes, &lookups->capacity, lookups->count + lookup_count, - sizeof(*lookups->indexes))) + if (!found && (features->features[i].flags & FEATURE_GLOBAL_SEARCH)) + { + for (j = 0; j < total_feature_count; ++j) + { + if ((found = (feature_list->features[j].tag == feature->tag))) { - return; + feature->index = j; + break; } + } + } - for (l = 0; l < lookup_count; ++l) - { - UINT16 lookup_index = table_read_be_word(&table->table, table->feature_list + feature_offset + - FIELD_OFFSET(struct ot_feature, lookuplist_index[l])); + if (!found) + continue; + + if (feature->flags & FEATURE_GLOBAL && feature->max_value == 1) + { + feature->shift = global_bit_shift; + feature->mask = global_bit_mask; + } + else + { + feature->shift = next_bit; + feature->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); + next_bit += bits_needed; + context->global_mask |= (feature->default_value << feature->shift) & feature->mask; + } + } + + for (stage = 0; stage <= features->stage; ++stage) + { + for (i = 0; i < features->count; ++i) + { + if (features->features[i].stage == stage) + opentype_layout_add_lookups(feature_list, total_lookup_count, table, &features->features[i], lookups); + } - if (lookup_index >= total_lookup_count) - continue; + /* Sort and merge lookups for current stage. */ + if (last_num_lookups < lookups->count) + { + qsort(lookups->lookups + last_num_lookups, lookups->count - last_num_lookups, sizeof(*lookups->lookups), + lookups_sorting_compare); - lookups->indexes[lookups->count++] = lookup_index; + j = last_num_lookups; + for (i = j + 1; i < lookups->count; ++i) + { + if (lookups->lookups[i].index != lookups->lookups[j].index) + { + lookups->lookups[++j] = lookups->lookups[i]; + } + else + { + lookups->lookups[j].mask |= lookups->lookups[i].mask; } } + lookups->count = j + 1; } + + last_num_lookups = lookups->count; } +} + +static int feature_search_compare(const void *a, const void* b) +{ + unsigned int tag = *(unsigned int *)a; + const struct shaping_feature *feature = b; - /* Sort lookups. */ - qsort(lookups->indexes, lookups->count, sizeof(*lookups->indexes), lookups_sorting_compare); + return tag < feature->tag ? -1 : tag > feature->tag ? 1 : 0; +} + +static unsigned int shaping_features_get_mask(const struct shaping_features *features, unsigned int tag, unsigned int *shift) +{ + struct shaping_feature *feature; + + feature = bsearch(&tag, features->features, features->count, sizeof(*features->features), feature_search_compare); + + if (!feature || feature->index == 0xffff) + return 0; + + if (shift) *shift = feature->shift; + return feature->mask; +} + +static void opentype_layout_set_glyph_masks(struct scriptshaping_context *context, const struct shaping_features *features) +{ + const DWRITE_TYPOGRAPHIC_FEATURES **user_features = context->user_features.features; + unsigned int f, r, g, start_glyph = 0, mask, shift, value; + + for (g = 0; g < context->glyph_count; ++g) + context->glyph_infos[g].mask = context->global_mask; + + /* FIXME: set shaper masks */ + + for (r = 0; r < context->user_features.range_count; ++r) + { + for (f = 0; f < user_features[r]->featureCount; ++f) + { + mask = shaping_features_get_mask(features, user_features[r]->features[f].nameTag, &shift); + if (!mask) + continue; + + value = (user_features[r]->features[f].parameter << shift) & mask; + for (g = 0; g < context->user_features.range_lengths[r]; ++g) + context->glyph_infos[g + start_glyph].mask = (context->glyph_infos[g + start_glyph].mask & ~mask) | value; + start_glyph += context->user_features.range_lengths[r]; + } + } } void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index, @@ -4184,19 +4370,15 @@ opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gpos, &lookups); - for (i = 0; i < lookups.count; ++i) - { - /* Skip duplicates. */ - if (i && lookups.indexes[i] == lookups.indexes[i - 1]) - continue; + opentype_layout_set_glyph_masks(context, features); - opentype_layout_apply_gpos_lookup(context, lookups.indexes[i]); - } + for (i = 0; i < lookups.count; ++i) + opentype_layout_apply_gpos_lookup(context, lookups.lookups[i].index); - heap_free(lookups.indexes); + heap_free(lookups.lookups); } -static BOOL opentype_layout_apply_gsub_single_substitution(struct glyph_iterator *iter, const struct lookup *lookup) +static BOOL opentype_layout_apply_gsub_single_substitution(struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = iter->context->cache; UINT16 format, coverage; @@ -4342,7 +4524,7 @@ opentype_layout_context_gsub_apply_lookup(iter, input_count, lookup_count, lookup_records); } -static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct glyph_iterator *iter, const struct lookup *lookup) +static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = iter->context->cache; UINT16 format, coverage; @@ -4434,7 +4616,7 @@ struct ot_gsubgpos_table *table = &context->cache->gsub; const struct ot_lookup_table *lookup_table; struct glyph_iterator iter; - struct lookup lookup; + struct ot_lookup lookup; WORD lookup_type; lookup.offset = table_read_be_word(&table->table, table->lookup_list + FIELD_OFFSET(struct ot_lookup_list, lookup[lookup_index])); @@ -4478,6 +4660,7 @@ case GSUB_LOOKUP_LIGATURE_SUBST: case GSUB_LOOKUP_CONTEXTUAL_SUBST: case GSUB_LOOKUP_REVERSE_CHAINING_CONTEXTUAL_SUBST: + ret = FALSE; WARN("Unimplemented lookup %d.\n", lookup_type); break; default: @@ -4491,6 +4674,67 @@ } } +static unsigned int unicode_get_mirrored_char(unsigned int codepoint) +{ + extern const WCHAR wine_mirror_map[] DECLSPEC_HIDDEN; + WCHAR mirror; + /* TODO: check if mirroring for higher planes makes sense at all */ + if (codepoint > 0xffff) return codepoint; + mirror = get_table_entry(wine_mirror_map, codepoint); + return mirror ? mirror : codepoint; +} + +static void opentype_get_nominal_glyphs(struct scriptshaping_context *context, const struct shaping_features *features) +{ + unsigned int rtlm_mask = shaping_features_get_mask(features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','m'), NULL); + const struct shaping_font_ops *font = context->cache->font; + UINT16 *clustermap = context->u.subst.clustermap; + const WCHAR *text = context->text; + unsigned int i, g, c, codepoint; + BOOL bmp; + + memset(context->u.subst.glyph_props, 0, context->u.subst.max_glyph_count * sizeof(*context->u.subst.glyph_props)); + + for (i = 0; i < context->length; ++i) + { + g = context->glyph_count; + + if ((bmp = !(IS_HIGH_SURROGATE(text[i]) && (i < context->length - 1) && IS_LOW_SURROGATE(text[i + 1])))) + { + codepoint = text[i]; + } + else + { + codepoint = 0x10000 + ((text[i] - 0xd800) << 10) + (text[i + 1] - 0xdc00); + } + + if (context->is_rtl) + { + c = unicode_get_mirrored_char(codepoint); + if (c != codepoint && font->has_glyph(context->cache->context, c)) + codepoint = c; + else + context->glyph_infos[i].mask |= rtlm_mask; + } + + /* TODO: should this check for glyph availability? */ + if (*context->u.subst.digits && codepoint >= '0' && codepoint <= '9') + codepoint = context->u.subst.digits[codepoint - '0']; + + context->u.subst.glyphs[g] = font->get_glyph(context->cache->context, codepoint); + context->u.subst.glyph_props[g].justification = SCRIPT_JUSTIFY_CHARACTER; + context->u.subst.glyph_props[g].isClusterStart = 1; + context->glyph_count++; + + clustermap[i] = i; + if (!bmp) + { + clustermap[i + 1] = i; + ++i; + } + } +} + HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, const struct shaping_features *features) { @@ -4499,16 +4743,13 @@ opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gsub, &lookups); - for (i = 0; i < lookups.count; ++i) - { - /* Skip duplicates. */ - if (i && lookups.indexes[i] == lookups.indexes[i - 1]) - continue; + opentype_get_nominal_glyphs(context, features); + opentype_layout_set_glyph_masks(context, features); - opentype_layout_apply_gsub_lookup(context, 0, context->glyph_count, lookups.indexes[i]); - } + for (i = 0; i < lookups.count; ++i) + opentype_layout_apply_gsub_lookup(context, 0, context->glyph_count, lookups.lookups[i].index); - heap_free(lookups.indexes); + heap_free(lookups.lookups); return S_OK; } diff -Nru wine-development-5.8/dlls/dwrite/shape.c wine-development-5.9/dlls/dwrite/shape.c --- wine-development-5.8/dlls/dwrite/shape.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dwrite/shape.c 2020-05-22 18:49:34.000000000 +0000 @@ -201,13 +201,77 @@ return 0; } -static void shape_add_feature(struct shaping_features *features, unsigned int tag) +static void shape_add_feature_full(struct shaping_features *features, unsigned int tag, unsigned int flags, unsigned int value) { + unsigned int i = features->count; + if (!dwrite_array_reserve((void **)&features->features, &features->capacity, features->count + 1, sizeof(*features->features))) return; - features->features[features->count++].tag = tag; + features->features[i].tag = tag; + features->features[i].flags = flags; + features->features[i].max_value = value; + features->features[i].default_value = flags & FEATURE_GLOBAL ? value : 0; + features->features[i].stage = features->stage; + features->count++; +} + +static void shape_add_feature(struct shaping_features *features, unsigned int tag) +{ + shape_add_feature_full(features, tag, FEATURE_GLOBAL, 1); +} + +static int features_sorting_compare(const void *a, const void *b) +{ + const struct shaping_feature *left = a, *right = b; + return left->tag != right->tag ? (left->tag < right->tag ? -1 : 1) : 0; +}; + +static void shape_merge_features(struct scriptshaping_context *context, struct shaping_features *features) +{ + const DWRITE_TYPOGRAPHIC_FEATURES **user_features = context->user_features.features; + unsigned int j = 0, i; + + /* For now only consider global, enabled user features. */ + if (user_features && context->user_features.range_lengths) + { + unsigned int flags = context->user_features.range_count == 1 && + context->user_features.range_lengths[0] == context->length ? FEATURE_GLOBAL : 0; + + for (i = 0; i < context->user_features.range_count; ++i) + { + for (j = 0; j < user_features[i]->featureCount; ++j) + shape_add_feature_full(features, user_features[i]->features[j].nameTag, flags, + user_features[i]->features[j].parameter); + } + } + + /* Sort and merge duplicates. */ + qsort(features->features, features->count, sizeof(*features->features), features_sorting_compare); + + for (i = 1; i < features->count; ++i) + { + if (features->features[i].tag != features->features[j].tag) + features->features[++j] = features->features[i]; + else + { + if (features->features[i].flags & FEATURE_GLOBAL) + { + features->features[j].flags |= FEATURE_GLOBAL; + features->features[j].max_value = features->features[i].max_value; + features->features[j].default_value = features->features[i].default_value; + } + else + { + if (features->features[j].flags & FEATURE_GLOBAL) + features->features[j].flags ^= FEATURE_GLOBAL; + features->features[j].max_value = max(features->features[j].max_value, features->features[i].max_value); + } + features->features[j].stage = min(features->features[j].stage, features->features[i].stage); + } + } + features->count = j + 1; } HRESULT shape_get_positions(struct scriptshaping_context *context, const unsigned int *scripts) @@ -239,6 +303,8 @@ shape_add_feature(&features, horizontal_features[i]); } + shape_merge_features(context, &features); + /* Resolve script tag to actually supported script. */ if (cache->gpos.table.data) { @@ -296,15 +362,17 @@ DWRITE_MAKE_OPENTYPE_TAG('l','i','g','a'), DWRITE_MAKE_OPENTYPE_TAG('r','c','l','t'), }; - struct scriptshaping_cache *cache = context->cache; - unsigned int script_index, language_index, script; + unsigned int script_index, language_index; struct shaping_features features = { 0 }; unsigned int i; if (!context->is_sideways) { if (context->is_rtl) + { shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','a')); + shape_add_feature_full(&features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','m'), 0, 1); + } else { shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('l','t','r','a')); @@ -321,15 +389,14 @@ for (i = 0; i < ARRAY_SIZE(horizontal_features); ++i) shape_add_feature(&features, horizontal_features[i]); } + else + shape_add_feature_full(&features, DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t'), FEATURE_GLOBAL | FEATURE_GLOBAL_SEARCH, 1); + + shape_merge_features(context, &features); /* Resolve script tag to actually supported script. */ - if (cache->gsub.table.data) - { - if ((script = shape_get_script_lang_index(context, scripts, MS_GSUB_TAG, &script_index, &language_index))) - { - opentype_layout_apply_gsub_features(context, script_index, language_index, &features); - } - } + shape_get_script_lang_index(context, scripts, MS_GSUB_TAG, &script_index, &language_index); + opentype_layout_apply_gsub_features(context, script_index, language_index, &features); heap_free(features.features); diff -Nru wine-development-5.8/dlls/dxgi/device.c wine-development-5.9/dlls/dxgi/device.c --- wine-development-5.8/dlls/dxgi/device.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dxgi/device.c 2020-05-22 18:49:34.000000000 +0000 @@ -427,13 +427,37 @@ { struct dxgi_device *device = impl_from_IWineDXGISwapChainFactory(iface); struct wined3d_swapchain_desc wined3d_desc; + struct IDXGIOutput *containing_output; struct d3d11_swapchain *object; + struct IDXGIAdapter *adapter; HRESULT hr; TRACE("iface %p, factory %p, window %p, desc %p, fullscreen_desc %p, output %p, swapchain %p.\n", iface, factory, window, desc, fullscreen_desc, output, swapchain); - if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, window, desc, fullscreen_desc))) + if (FAILED(hr = dxgi_get_output_from_window(factory, window, &containing_output))) + { + WARN("Failed to get output from window %p, hr %#x.\n", window, hr); + + /* FIXME: As wined3d only supports one output currently, even if a window is on a + * non-primary output, the swapchain will use the primary output. Keep this behaviour + * until all outputs are correctly enumerated. Otherwise it will create a regression + * for applications that specify a device window on a non-primary output */ + if (FAILED(hr = IDXGIFactory_EnumAdapters(factory, 0, &adapter))) + return hr; + + hr = IDXGIAdapter_EnumOutputs(adapter, 0, &containing_output); + IDXGIAdapter_Release(adapter); + if (FAILED(hr)) + return hr; + + FIXME("Using the primary output for the device window that is on a non-primary output.\n"); + } + + hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, containing_output, window, desc, + fullscreen_desc); + IDXGIOutput_Release(containing_output); + if (FAILED(hr)) return hr; if (!(object = heap_alloc_zero(sizeof(*object)))) @@ -474,7 +498,10 @@ struct d3d11_swapchain *swapchain; struct dxgi_adapter *dxgi_adapter; struct dxgi_factory *dxgi_factory; + struct dxgi_output *dxgi_output; + struct IDXGIOutput *output; void *layer_base; + HWND window; HRESULT hr; if (!(dxgi_factory = unsafe_impl_from_IDXGIFactory(factory))) @@ -530,11 +557,25 @@ return hr; } + window = dxgi_factory_get_device_window(dxgi_factory); + if (FAILED(hr = dxgi_get_output_from_window(factory, window, &output))) + { + ERR("Failed to get output from window %p.\n", window); + wined3d_device_decref(device->wined3d_device); + IUnknown_Release(device->child_layer); + wined3d_private_store_cleanup(&device->private_store); + wined3d_mutex_unlock(); + return hr; + } + dxgi_output = unsafe_impl_from_IDXGIOutput(output); + memset(&swapchain_desc, 0, sizeof(swapchain_desc)); swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD; - swapchain_desc.device_window = dxgi_factory_get_device_window(dxgi_factory); + swapchain_desc.device_window = window; swapchain_desc.windowed = TRUE; swapchain_desc.flags = WINED3D_SWAPCHAIN_IMPLICIT; + swapchain_desc.output = dxgi_output->wined3d_output; + IDXGIOutput_Release(output); if (!(swapchain = heap_alloc_zero(sizeof(*swapchain)))) { diff -Nru wine-development-5.8/dlls/dxgi/dxgi_private.h wine-development-5.9/dlls/dxgi/dxgi_private.h --- wine-development-5.8/dlls/dxgi/dxgi_private.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dxgi/dxgi_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -96,8 +96,10 @@ DXGI_USAGE dxgi_usage_from_wined3d_bind_flags(unsigned int wined3d_bind_flags) DECLSPEC_HIDDEN; unsigned int wined3d_bind_flags_from_dxgi_usage(DXGI_USAGE usage) DECLSPEC_HIDDEN; unsigned int dxgi_swapchain_flags_from_wined3d(unsigned int wined3d_flags) DECLSPEC_HIDDEN; +HRESULT dxgi_get_output_from_window(IDXGIFactory *factory, HWND window, IDXGIOutput **dxgi_output) + DECLSPEC_HIDDEN; HRESULT wined3d_swapchain_desc_from_dxgi(struct wined3d_swapchain_desc *wined3d_desc, - HWND window, const DXGI_SWAP_CHAIN_DESC1 *dxgi_desc, + IDXGIOutput *dxgi_containing_output, HWND window, const DXGI_SWAP_CHAIN_DESC1 *dxgi_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *dxgi_fullscreen_desc) DECLSPEC_HIDDEN; HRESULT dxgi_get_private_data(struct wined3d_private_store *store, diff -Nru wine-development-5.8/dlls/dxgi/factory.c wine-development-5.9/dlls/dxgi/factory.c --- wine-development-5.8/dlls/dxgi/factory.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dxgi/factory.c 2020-05-22 18:49:34.000000000 +0000 @@ -36,6 +36,8 @@ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); if (IsEqualGUID(iid, &IID_IWineDXGIFactory) + || IsEqualGUID(iid, &IID_IDXGIFactory7) + || IsEqualGUID(iid, &IID_IDXGIFactory6) || IsEqualGUID(iid, &IID_IDXGIFactory5) || IsEqualGUID(iid, &IID_IDXGIFactory4) || IsEqualGUID(iid, &IID_IDXGIFactory3) @@ -462,6 +464,42 @@ } } +static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapterByGpuPreference(IWineDXGIFactory *iface, + UINT adapter_idx, DXGI_GPU_PREFERENCE gpu_preference, REFIID iid, void **adapter) +{ + IDXGIAdapter1 *adapter_object; + HRESULT hr; + + TRACE("iface %p, adapter_idx %u, gpu_preference %#x, iid %s, adapter %p.\n", + iface, adapter_idx, gpu_preference, debugstr_guid(iid), adapter); + + if (gpu_preference != DXGI_GPU_PREFERENCE_UNSPECIFIED) + FIXME("Ignoring GPU preference %#x.\n", gpu_preference); + + if (FAILED(hr = dxgi_factory_EnumAdapters1(iface, adapter_idx, &adapter_object))) + return hr; + + hr = IDXGIAdapter1_QueryInterface(adapter_object, iid, adapter); + IDXGIAdapter1_Release(adapter_object); + return hr; +} + +static HRESULT STDMETHODCALLTYPE dxgi_factory_RegisterAdaptersChangedEvent(IWineDXGIFactory *iface, + HANDLE event, DWORD *cookie) +{ + FIXME("iface %p, event %p, cookie %p stub!\n", iface, event, cookie); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE dxgi_factory_UnregisterAdaptersChangedEvent(IWineDXGIFactory *iface, + DWORD cookie) +{ + FIXME("iface %p, cookie %#x stub!\n", iface, cookie); + + return E_NOTIMPL; +} + static const struct IWineDXGIFactoryVtbl dxgi_factory_vtbl = { dxgi_factory_QueryInterface, @@ -498,6 +536,11 @@ dxgi_factory_EnumWarpAdapter, /* IDXIGFactory5 methods */ dxgi_factory_CheckFeatureSupport, + /* IDXGIFactory6 methods */ + dxgi_factory_EnumAdapterByGpuPreference, + /* IDXGIFactory7 methods */ + dxgi_factory_RegisterAdaptersChangedEvent, + dxgi_factory_UnregisterAdaptersChangedEvent, }; struct dxgi_factory *unsafe_impl_from_IDXGIFactory(IDXGIFactory *iface) diff -Nru wine-development-5.8/dlls/dxgi/output.c wine-development-5.9/dlls/dxgi/output.c --- wine-development-5.8/dlls/dxgi/output.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dxgi/output.c 2020-05-22 18:49:34.000000000 +0000 @@ -23,6 +23,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(dxgi); +static inline DXGI_MODE_SCANLINE_ORDER dxgi_mode_scanline_order_from_wined3d(enum wined3d_scanline_ordering ordering) +{ + return (DXGI_MODE_SCANLINE_ORDER)ordering; +} + static void dxgi_mode_from_wined3d(DXGI_MODE_DESC *mode, const struct wined3d_display_mode *wined3d_mode) { mode->Width = wined3d_mode->width; @@ -30,7 +35,7 @@ mode->RefreshRate.Numerator = wined3d_mode->refresh_rate; mode->RefreshRate.Denominator = 1; mode->Format = dxgi_format_from_wined3dformat(wined3d_mode->format_id); - mode->ScanlineOrdering = wined3d_mode->scanline_ordering; + mode->ScanlineOrdering = dxgi_mode_scanline_order_from_wined3d(wined3d_mode->scanline_ordering); mode->Scaling = DXGI_MODE_SCALING_UNSPECIFIED; /* FIXME */ } @@ -41,7 +46,7 @@ mode->RefreshRate.Numerator = wined3d_mode->refresh_rate; mode->RefreshRate.Denominator = 1; mode->Format = dxgi_format_from_wined3dformat(wined3d_mode->format_id); - mode->ScanlineOrdering = wined3d_mode->scanline_ordering; + mode->ScanlineOrdering = dxgi_mode_scanline_order_from_wined3d(wined3d_mode->scanline_ordering); mode->Scaling = DXGI_MODE_SCALING_UNSPECIFIED; /* FIXME */ mode->Stereo = FALSE; /* FIXME */ } diff -Nru wine-development-5.8/dlls/dxgi/swapchain.c wine-development-5.9/dlls/dxgi/swapchain.c --- wine-development-5.8/dlls/dxgi/swapchain.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dxgi/swapchain.c 2020-05-22 18:49:34.000000000 +0000 @@ -111,11 +111,12 @@ return TRUE; } -static HRESULT dxgi_get_output_from_window(IDXGIAdapter *adapter, HWND window, IDXGIOutput **dxgi_output) +HRESULT dxgi_get_output_from_window(IDXGIFactory *factory, HWND window, IDXGIOutput **dxgi_output) { + unsigned int adapter_idx, output_idx; DXGI_OUTPUT_DESC desc; + IDXGIAdapter *adapter; IDXGIOutput *output; - unsigned int index; HMONITOR monitor; HRESULT hr; @@ -125,25 +126,32 @@ return DXGI_ERROR_INVALID_CALL; } - index = 0; - while ((hr = IDXGIAdapter_EnumOutputs(adapter, index, &output)) == S_OK) + for (adapter_idx = 0; SUCCEEDED(hr = IDXGIFactory_EnumAdapters(factory, adapter_idx, &adapter)); + ++adapter_idx) { - if (FAILED(hr = IDXGIOutput_GetDesc(output, &desc))) + for (output_idx = 0; SUCCEEDED(hr = IDXGIAdapter_EnumOutputs(adapter, output_idx, + &output)); ++output_idx) { - WARN("Failed to get output desc %u, hr %#x.\n", index, hr); - ++index; - continue; - } + if (FAILED(hr = IDXGIOutput_GetDesc(output, &desc))) + { + WARN("Adapter %u output %u: Failed to get output desc, hr %#x.\n", adapter_idx, + output_idx, hr); + IDXGIOutput_Release(output); + continue; + } - if (desc.Monitor == monitor) - { - *dxgi_output = output; - return S_OK; - } + if (desc.Monitor == monitor) + { + *dxgi_output = output; + IDXGIAdapter_Release(adapter); + return S_OK; + } - IDXGIOutput_Release(output); - ++index; + IDXGIOutput_Release(output); + } + IDXGIAdapter_Release(adapter); } + if (hr != DXGI_ERROR_NOT_FOUND) WARN("Failed to enumerate outputs, hr %#x.\n", hr); @@ -151,29 +159,10 @@ return DXGI_ERROR_NOT_FOUND; } -static HRESULT dxgi_swapchain_set_fullscreen_state(struct wined3d_swapchain_state *state, - const struct wined3d_swapchain_desc *swapchain_desc, IDXGIOutput *output) -{ - struct dxgi_output *dxgi_output; - HRESULT hr; - - dxgi_output = unsafe_impl_from_IDXGIOutput(output); - - wined3d_mutex_lock(); - hr = wined3d_swapchain_state_set_fullscreen(state, swapchain_desc, - dxgi_output->wined3d_output, NULL); - wined3d_mutex_unlock(); - - return hr; -} - -static HRESULT dxgi_swapchain_resize_target(IDXGISwapChain1 *swapchain, - struct wined3d_swapchain_state *state, const DXGI_MODE_DESC *target_mode_desc) +static HRESULT dxgi_swapchain_resize_target(struct wined3d_swapchain_state *state, + const DXGI_MODE_DESC *target_mode_desc) { struct wined3d_display_mode mode; - struct dxgi_output *dxgi_output; - IDXGIOutput *output; - HRESULT hr; if (!target_mode_desc) { @@ -181,10 +170,6 @@ return DXGI_ERROR_INVALID_CALL; } - if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(swapchain, &output))) - return hr; - dxgi_output = unsafe_impl_from_IDXGIOutput(output); - TRACE("Mode: %s.\n", debug_dxgi_mode(target_mode_desc)); if (target_mode_desc->Scaling) @@ -192,9 +177,7 @@ wined3d_display_mode_from_dxgi(&mode, target_mode_desc); - hr = wined3d_swapchain_state_resize_target(state, dxgi_output->wined3d_output, &mode); - IDXGIOutput_Release(output); - return hr; + return wined3d_swapchain_state_resize_target(state, &mode); } static HWND d3d11_swapchain_get_hwnd(struct d3d11_swapchain *swapchain) @@ -406,6 +389,7 @@ struct d3d11_swapchain *swapchain = d3d11_swapchain_from_IDXGISwapChain1(iface); struct wined3d_swapchain_desc swapchain_desc; struct wined3d_swapchain_state *state; + struct dxgi_output *dxgi_output; HRESULT hr; TRACE("iface %p, fullscreen %#x, target %p.\n", iface, fullscreen, target); @@ -425,12 +409,14 @@ WARN("Failed to get target output for swapchain, hr %#x.\n", hr); return hr; } + dxgi_output = unsafe_impl_from_IDXGIOutput(target); wined3d_mutex_lock(); state = wined3d_swapchain_get_state(swapchain->wined3d_swapchain); wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &swapchain_desc); + swapchain_desc.output = dxgi_output->wined3d_output; swapchain_desc.windowed = !fullscreen; - hr = dxgi_swapchain_set_fullscreen_state(state, &swapchain_desc, target); + hr = wined3d_swapchain_state_set_fullscreen(state, &swapchain_desc, NULL); wined3d_mutex_unlock(); if (FAILED(hr)) { @@ -576,15 +562,13 @@ state = wined3d_swapchain_get_state(swapchain->wined3d_swapchain); - return dxgi_swapchain_resize_target(iface, state, target_mode_desc); + return dxgi_swapchain_resize_target(state, target_mode_desc); } static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetContainingOutput(IDXGISwapChain1 *iface, IDXGIOutput **output) { struct d3d11_swapchain *swapchain = d3d11_swapchain_from_IDXGISwapChain1(iface); - IDXGIAdapter *adapter; - IDXGIDevice *device; - HRESULT hr; + HWND window; TRACE("iface %p, output %p.\n", iface, output); @@ -594,24 +578,14 @@ return S_OK; } - if (SUCCEEDED(hr = d3d11_swapchain_GetDevice(iface, &IID_IDXGIDevice, (void **)&device))) - { - hr = IDXGIDevice_GetAdapter(device, &adapter); - IDXGIDevice_Release(device); - } - - if (SUCCEEDED(hr)) - { - HWND hwnd = d3d11_swapchain_get_hwnd(swapchain); - hr = dxgi_get_output_from_window(adapter, hwnd, output); - IDXGIAdapter_Release(adapter); - } - else + if (!swapchain->factory) { - WARN("Failed to get adapter, hr %#x.\n", hr); + ERR("Implicit swapchain does not store a reference to factory.\n"); + return E_NOINTERFACE; } - return hr; + window = d3d11_swapchain_get_hwnd(swapchain); + return dxgi_get_output_from_window(swapchain->factory, window, output); } static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetFrameStatistics(IDXGISwapChain1 *iface, @@ -898,7 +872,7 @@ goto cleanup; } - if (FAILED(hr = dxgi_swapchain_set_fullscreen_state(state, desc, swapchain->target))) + if (FAILED(hr = wined3d_swapchain_state_set_fullscreen(state, desc, NULL))) { WARN("Failed to set fullscreen state, hr %#x.\n", hr); IDXGIOutput_Release(swapchain->target); @@ -2264,11 +2238,12 @@ return hr; } - if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, window, swapchain_desc, fullscreen_desc))) + if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, target, window, swapchain_desc, + fullscreen_desc))) goto fail; wined3d_mutex_lock(); wined3d_desc.windowed = !fullscreen; - hr = dxgi_swapchain_set_fullscreen_state(swapchain->state, &wined3d_desc, target); + hr = wined3d_swapchain_state_set_fullscreen(swapchain->state, &wined3d_desc, NULL); wined3d_mutex_unlock(); if (FAILED(hr)) goto fail; @@ -2415,7 +2390,7 @@ TRACE("iface %p, target_mode_desc %p.\n", iface, target_mode_desc); - return dxgi_swapchain_resize_target((IDXGISwapChain1 *)iface, swapchain->state, target_mode_desc); + return dxgi_swapchain_resize_target(swapchain->state, target_mode_desc); } static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetContainingOutput(IDXGISwapChain3 *iface, @@ -2423,6 +2398,7 @@ { struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface); IUnknown *device_parent; + IDXGIFactory *factory; IDXGIAdapter *adapter; HRESULT hr; @@ -2436,16 +2412,22 @@ device_parent = vkd3d_get_device_parent(swapchain->device); - if (SUCCEEDED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter))) + if (FAILED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter))) { - hr = dxgi_get_output_from_window(adapter, swapchain->window, output); - IDXGIAdapter_Release(adapter); + WARN("Failed to get adapter, hr %#x.\n", hr); + return hr; } - else + + if (FAILED(hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory))) { - WARN("Failed to get adapter, hr %#x.\n", hr); + WARN("Failed to get factory, hr %#x.\n", hr); + IDXGIAdapter_Release(adapter); + return hr; } + hr = dxgi_get_output_from_window(factory, swapchain->window, output); + IDXGIFactory_Release(factory); + IDXGIAdapter_Release(adapter); return hr; } @@ -2917,13 +2899,13 @@ struct wined3d_swapchain_desc wined3d_desc; VkWin32SurfaceCreateInfoKHR surface_desc; VkPhysicalDevice vk_physical_device; - struct dxgi_adapter *dxgi_adapter; VkFenceCreateInfo fence_desc; uint32_t queue_family_index; VkSurfaceKHR vk_surface; IUnknown *device_parent; VkInstance vk_instance; IDXGIAdapter *adapter; + IDXGIOutput *output; VkBool32 supported; VkDevice vk_device; VkFence vk_fence; @@ -2965,12 +2947,31 @@ device_parent = vkd3d_get_device_parent(device); if (FAILED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter))) return hr; - dxgi_adapter = unsafe_impl_from_IDXGIAdapter(adapter); + + if (FAILED(hr = dxgi_get_output_from_window((IDXGIFactory *)factory, window, &output))) + { + WARN("Failed to get output from window %p, hr %#x.\n", window, hr); + + /* FIXME: As wined3d only supports one output currently, even if a window is on a + * non-primary output, the swapchain will use the primary output. Keep this behaviour + * until all outputs are correctly enumerated. Otherwise it will create a regression + * for applications that specify a device window on a non-primary output */ + if (FAILED(hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output))) + { + IDXGIAdapter_Release(adapter); + return hr; + } + + FIXME("Using the primary output for the device window that is on a non-primary output.\n"); + } IDXGIAdapter_Release(adapter); - if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, window, swapchain_desc, fullscreen_desc))) + + hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, output, window, swapchain_desc, + fullscreen_desc); + IDXGIOutput_Release(output); + if (FAILED(hr)) return hr; - if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window, - dxgi_adapter->factory->wined3d, &swapchain->state))) + if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window, &swapchain->state))) return hr; if (swapchain_desc->BufferUsage && swapchain_desc->BufferUsage != DXGI_USAGE_RENDER_TARGET_OUTPUT) diff -Nru wine-development-5.8/dlls/dxgi/tests/dxgi.c wine-development-5.9/dlls/dxgi/tests/dxgi.c --- wine-development-5.8/dlls/dxgi/tests/dxgi.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dxgi/tests/dxgi.c 2020-05-22 18:49:34.000000000 +0000 @@ -44,6 +44,10 @@ static NTSTATUS (WINAPI *pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER *desc); static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromGdiDisplayName)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *desc); +static HRESULT (WINAPI *pD3D11CreateDevice)(IDXGIAdapter *adapter, D3D_DRIVER_TYPE driver_type, HMODULE swrast, UINT flags, + const D3D_FEATURE_LEVEL *feature_levels, UINT levels, UINT sdk_version, ID3D11Device **device_out, + D3D_FEATURE_LEVEL *obtained_feature_level, ID3D11DeviceContext **immediate_context); + static PFN_D3D12_CREATE_DEVICE pD3D12CreateDevice; static PFN_D3D12_GET_DEBUG_INTERFACE pD3D12GetDebugInterface; @@ -624,6 +628,39 @@ return dxgi_device; } +static IDXGIDevice *create_d3d11_device(void) +{ + static const D3D_FEATURE_LEVEL feature_level[] = + { + D3D_FEATURE_LEVEL_11_0, + }; + unsigned int feature_level_count = ARRAY_SIZE(feature_level); + IDXGIDevice *device = NULL; + ID3D11Device *d3d_device; + HRESULT hr; + + if (!pD3D11CreateDevice) + return NULL; + + hr = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, feature_level, feature_level_count, + D3D11_SDK_VERSION, &d3d_device, NULL, NULL); + if (FAILED(hr)) + hr = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, feature_level, feature_level_count, + D3D11_SDK_VERSION, &d3d_device, NULL, NULL); + if (FAILED(hr)) + hr = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, 0, feature_level, feature_level_count, + D3D11_SDK_VERSION, &d3d_device, NULL, NULL); + + if (SUCCEEDED(hr)) + { + hr = ID3D11Device_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&device); + ok(SUCCEEDED(hr), "Created device does not implement IDXGIDevice.\n"); + ID3D11Device_Release(d3d_device); + } + + return device; +} + static ID3D12Device *create_d3d12_device(void) { IDXGIAdapter *adapter; @@ -1079,6 +1116,7 @@ static void test_create_surface(void) { + ID3D11Texture2D *texture2d; DXGI_SURFACE_DESC desc; IDXGISurface *surface; IDXGIDevice *device; @@ -1109,6 +1147,40 @@ IDXGISurface_Release(surface); refcount = IDXGIDevice_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); + + /* DXGI_USAGE_UNORDERED_ACCESS */ + if (!(device = create_d3d11_device())) + { + skip("Failed to create D3D11 device.\n"); + return; + } + + surface = NULL; + hr = IDXGIDevice_CreateSurface(device, &desc, 1, DXGI_USAGE_UNORDERED_ACCESS, NULL, &surface); + ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr); + + if (surface) + { + ID3D11UnorderedAccessView *uav; + ID3D11Device *d3d_device; + + hr = IDXGISurface_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture2d); + ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr); + + ID3D11Texture2D_GetDevice(texture2d, &d3d_device); + + hr = ID3D11Device_CreateUnorderedAccessView(d3d_device, (ID3D11Resource *)texture2d, NULL, &uav); + ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); + ID3D11UnorderedAccessView_Release(uav); + + ID3D11Device_Release(d3d_device); + ID3D11Texture2D_Release(texture2d); + + IDXGISurface_Release(surface); + } + + refcount = IDXGIDevice_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); } static void test_parents(void) @@ -2023,9 +2095,9 @@ static void test_get_containing_output(void) { unsigned int adapter_idx, output_idx, output_count; + DXGI_OUTPUT_DESC output_desc, output_desc2; DXGI_SWAP_CHAIN_DESC swapchain_desc; IDXGIOutput *output, *output2; - DXGI_OUTPUT_DESC output_desc; MONITORINFOEXW monitor_info; IDXGISwapChain *swapchain; IDXGIFactory *factory; @@ -2297,6 +2369,93 @@ hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); ok(hr == S_OK, "SetFullscreenState failed, hr %#x.\n", hr); + /* Test GetContainingOutput after a full screen swapchain is made windowed by pressing + * Alt+Enter, then move it to another output and use Alt+Enter to enter full screen */ + output = NULL; + output2 = NULL; + for (adapter_idx = 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory, adapter_idx, &adapter)); + ++adapter_idx) + { + for (output_idx = 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter, output_idx, + output ? &output2 : &output)); ++output_idx) + { + if (output2) + break; + } + + IDXGIAdapter_Release(adapter); + if (output2) + break; + } + + if (output && output2) + { + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output); + IDXGIOutput_Release(output); + if (FAILED(hr)) + { + skip("SetFullscreenState failed, hr %#x.\n", hr); + IDXGIOutput_Release(output2); + goto done; + } + + /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to leave full screen on the first output */ + PostMessageA(swapchain_desc.OutputWindow, WM_SYSKEYDOWN, VK_RETURN, + (MapVirtualKeyA(VK_RETURN, MAPVK_VK_TO_VSC) << 16) | 0x20000001); + flush_events(); + hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); + ok(hr == S_OK, "GetFullscreenState failed, hr %#x.\n", hr); + ok(!fullscreen, "Expect swapchain not full screen.\n"); + + /* Move the swapchain output window to the second output */ + hr = IDXGIOutput_GetDesc(output2, &output_desc2); + ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr); + ret = SetWindowPos(swapchain_desc.OutputWindow, 0, output_desc2.DesktopCoordinates.left, + output_desc2.DesktopCoordinates.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + ok(ret, "SetWindowPos failed.\n"); + + /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to enter full screen on the second output */ + PostMessageA(swapchain_desc.OutputWindow, WM_SYSKEYDOWN, VK_RETURN, + (MapVirtualKeyA(VK_RETURN, MAPVK_VK_TO_VSC) << 16) | 0x20000001); + flush_events(); + output = NULL; + hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &output); + ok(hr == S_OK, "GetFullscreenState failed, hr %#x.\n", hr); + ok(fullscreen, "Expect swapchain full screen.\n"); + ok(!!output, "Expect output not NULL.\n"); + hr = IDXGIOutput_GetDesc(output, &output_desc); + ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr); + hr = IDXGIOutput_GetDesc(output2, &output_desc2); + ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr); + todo_wine ok(!lstrcmpW(output_desc.DeviceName, output_desc2.DeviceName), + "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2.DeviceName), + wine_dbgstr_w(output_desc.DeviceName)); + IDXGIOutput_Release(output); + + output = NULL; + hr = IDXGISwapChain_GetContainingOutput(swapchain, &output); + ok(hr == S_OK, "GetContainingOutput failed, hr %#x.\n", hr); + hr = IDXGIOutput_GetDesc(output, &output_desc); + ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr); + hr = IDXGIOutput_GetDesc(output2, &output_desc2); + ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr); + todo_wine ok(!lstrcmpW(output_desc.DeviceName, output_desc2.DeviceName), + "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2.DeviceName), + wine_dbgstr_w(output_desc.DeviceName)); + + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(hr == S_OK, "SetFullscreenState failed, hr %#x.\n", hr); + } + else + { + skip("This test requires two outputs.\n"); + } + + if (output) + IDXGIOutput_Release(output); + if (output2) + IDXGIOutput_Release(output2); + done: refcount = IDXGISwapChain_Release(swapchain); ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount); @@ -6624,7 +6783,7 @@ START_TEST(dxgi) { - HMODULE dxgi_module, d3d12_module, gdi32_module; + HMODULE dxgi_module, d3d11_module, d3d12_module, gdi32_module; BOOL enable_debug_layer = FALSE; unsigned int argc, i; ID3D12Debug *debug; @@ -6639,6 +6798,9 @@ pD3DKMTCloseAdapter = (void *)GetProcAddress(gdi32_module, "D3DKMTCloseAdapter"); pD3DKMTOpenAdapterFromGdiDisplayName = (void *)GetProcAddress(gdi32_module, "D3DKMTOpenAdapterFromGdiDisplayName"); + d3d11_module = LoadLibraryA("d3d11.dll"); + pD3D11CreateDevice = (void *)GetProcAddress(d3d11_module, "D3D11CreateDevice"); + registry_mode.dmSize = sizeof(registry_mode); ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, ®istry_mode), "Failed to get display mode.\n"); diff -Nru wine-development-5.8/dlls/dxgi/utils.c wine-development-5.9/dlls/dxgi/utils.c --- wine-development-5.8/dlls/dxgi/utils.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/dxgi/utils.c 2020-05-22 18:49:34.000000000 +0000 @@ -503,8 +503,10 @@ wined3d_bind_flags |= WINED3D_BIND_SHADER_RESOURCE; if (dxgi_usage & DXGI_USAGE_RENDER_TARGET_OUTPUT) wined3d_bind_flags |= WINED3D_BIND_RENDER_TARGET; + if (dxgi_usage & DXGI_USAGE_UNORDERED_ACCESS) + wined3d_bind_flags |= WINED3D_BIND_UNORDERED_ACCESS; - dxgi_usage &= ~(DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT); + dxgi_usage &= ~(DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_UNORDERED_ACCESS); if (dxgi_usage) FIXME("Unhandled DXGI usage %#x.\n", dxgi_usage); return wined3d_bind_flags; @@ -559,9 +561,12 @@ return wined3d_flags; } -HRESULT wined3d_swapchain_desc_from_dxgi(struct wined3d_swapchain_desc *wined3d_desc, HWND window, - const DXGI_SWAP_CHAIN_DESC1 *dxgi_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *dxgi_fullscreen_desc) +HRESULT wined3d_swapchain_desc_from_dxgi(struct wined3d_swapchain_desc *wined3d_desc, + IDXGIOutput *dxgi_containing_output, HWND window, const DXGI_SWAP_CHAIN_DESC1 *dxgi_desc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *dxgi_fullscreen_desc) { + struct dxgi_output *dxgi_output = unsafe_impl_from_IDXGIOutput(dxgi_containing_output); + if (dxgi_desc->Scaling != DXGI_SCALING_STRETCH) FIXME("Ignoring scaling %#x.\n", dxgi_desc->Scaling); if (dxgi_desc->AlphaMode != DXGI_ALPHA_MODE_IGNORE) @@ -590,6 +595,7 @@ return DXGI_ERROR_INVALID_CALL; } + wined3d_desc->output = dxgi_output->wined3d_output; wined3d_desc->backbuffer_width = dxgi_desc->Width; wined3d_desc->backbuffer_height = dxgi_desc->Height; wined3d_desc->backbuffer_format = wined3dformat_from_dxgi_format(dxgi_desc->Format); diff -Nru wine-development-5.8/dlls/gdiplus/gdiplus_private.h wine-development-5.9/dlls/gdiplus/gdiplus_private.h --- wine-development-5.8/dlls/gdiplus/gdiplus_private.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/gdiplus/gdiplus_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -407,6 +407,7 @@ BOOL auto_frame; /* If true, determine the frame automatically */ GpPointF auto_frame_min, auto_frame_max; DWORD next_object_id; + UINT limit_dpi; /* playback */ GpGraphics *playback_graphics; diff -Nru wine-development-5.8/dlls/gdiplus/gdiplus.spec wine-development-5.9/dlls/gdiplus/gdiplus.spec --- wine-development-5.8/dlls/gdiplus/gdiplus.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/gdiplus/gdiplus.spec 2020-05-22 18:49:34.000000000 +0000 @@ -298,7 +298,7 @@ 298 stdcall GdipGetLogFontA(ptr ptr ptr) 299 stdcall GdipGetLogFontW(ptr ptr ptr) 300 stdcall GdipGetMatrixElements(ptr ptr) -301 stub GdipGetMetafileDownLevelRasterizationLimit +301 stdcall GdipGetMetafileDownLevelRasterizationLimit(ptr ptr) 302 stdcall GdipGetMetafileHeaderFromEmf(ptr ptr) 303 stdcall GdipGetMetafileHeaderFromFile(wstr ptr) 304 stdcall GdipGetMetafileHeaderFromMetafile(ptr ptr) diff -Nru wine-development-5.8/dlls/gdiplus/image.c wine-development-5.9/dlls/gdiplus/image.c --- wine-development-5.8/dlls/gdiplus/image.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/gdiplus/image.c 2020-05-22 18:49:34.000000000 +0000 @@ -58,11 +58,11 @@ { &GUID_WICPixelFormat4bppIndexed, PixelFormat4bppIndexed, WICBitmapPaletteTypeFixedHalftone8 }, { &GUID_WICPixelFormat8bppIndexed, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 }, - { &GUID_WICPixelFormat16bppBGR555, PixelFormat16bppRGB555, WICBitmapPaletteTypeFixedHalftone256 }, - { &GUID_WICPixelFormat24bppBGR, PixelFormat24bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, - { &GUID_WICPixelFormat32bppBGR, PixelFormat32bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, - { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 }, - { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 }, + { &GUID_WICPixelFormat16bppBGR555, PixelFormat16bppRGB555, 0 }, + { &GUID_WICPixelFormat24bppBGR, PixelFormat24bppRGB, 0 }, + { &GUID_WICPixelFormat32bppBGR, PixelFormat32bppRGB, 0 }, + { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, 0 }, + { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, 0 }, { NULL } }; @@ -82,7 +82,7 @@ hr = WINCODEC_ERR_PALETTEUNAVAILABLE; if (frame) hr = IWICBitmapFrameDecode_CopyPalette(frame, wic_palette); - if (hr != S_OK) + if (hr != S_OK && palette_type != 0) { TRACE("using predefined palette %#x\n", palette_type); hr = IWICPalette_InitializePredefined(wic_palette, palette_type, FALSE); @@ -2285,6 +2285,12 @@ if(!image || !size) return InvalidParameter; + if (image->type == ImageTypeMetafile) + { + *size = 0; + return GenericError; + } + if (!image->palette || image->palette->Count == 0) *size = sizeof(ColorPalette); else diff -Nru wine-development-5.8/dlls/gdiplus/metafile.c wine-development-5.9/dlls/gdiplus/metafile.c --- wine-development-5.8/dlls/gdiplus/metafile.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/gdiplus/metafile.c 2020-05-22 18:49:34.000000000 +0000 @@ -810,6 +810,7 @@ (*metafile)->comment_data = NULL; (*metafile)->comment_data_size = 0; (*metafile)->comment_data_length = 0; + (*metafile)->limit_dpi = 96; (*metafile)->hemf = NULL; list_init(&(*metafile)->containers); @@ -4006,11 +4007,38 @@ return Ok; } +GpStatus WINGDIPAPI GdipGetMetafileDownLevelRasterizationLimit(GDIPCONST GpMetafile *metafile, + UINT *limitDpi) +{ + TRACE("(%p,%p)\n", metafile, limitDpi); + + if (!metafile || !limitDpi) + return InvalidParameter; + + if (!metafile->record_dc) + return WrongState; + + *limitDpi = metafile->limit_dpi; + + return Ok; +} + GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpMetafile *metafile, UINT limitDpi) { TRACE("(%p,%u)\n", metafile, limitDpi); + if (limitDpi == 0) + limitDpi = 96; + + if (!metafile || limitDpi < 10) + return InvalidParameter; + + if (!metafile->record_dc) + return WrongState; + + metafile->limit_dpi = limitDpi; + return Ok; } diff -Nru wine-development-5.8/dlls/gdiplus/tests/image.c wine-development-5.9/dlls/gdiplus/tests/image.c --- wine-development-5.8/dlls/gdiplus/tests/image.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/gdiplus/tests/image.c 2020-05-22 18:49:34.000000000 +0000 @@ -3583,20 +3583,22 @@ UINT prop_size2; /* if win7 behaves differently */ UINT prop_id; UINT prop_id2; /* if win7 behaves differently */ + INT palette_size; } td[] = { - { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 }, - { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 }, - { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 }, - { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 }, - { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 } + { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132, 12 }, + { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091, 12 }, + { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0, 12 }, + { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0, 16 }, + { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0, -GenericError } }; GpStatus status; GpImage *image; UINT prop_count, prop_size, i; PROPID prop_id[16] = { 0 }; ImageType image_type; + INT palette_size; union { PropertyItem data; @@ -3617,6 +3619,21 @@ ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n", i, td[i].image_type, image_type); + palette_size = -1; + status = GdipGetImagePaletteSize(image, &palette_size); + if (td[i].palette_size >= 0) + { + ok(status == Ok, "%u: GdipGetImagePaletteSize error %d\n", i, status); + ok(td[i].palette_size == palette_size, "%u: expected palette_size %d, got %d\n", + i, td[i].palette_size, palette_size); + } + else + { + ok(status == -td[i].palette_size, "%u: GdipGetImagePaletteSize returned %d\n", i, status); + ok(palette_size == 0, "%u: expected palette_size 0, got %d\n", + i, palette_size); + } + status = GdipGetPropertyCount(image, &prop_count); ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status); todo_wine_if(td[i].image_data == pngimage || td[i].image_data == jpgimage) diff -Nru wine-development-5.8/dlls/gdiplus/tests/metafile.c wine-development-5.9/dlls/gdiplus/tests/metafile.c --- wine-development-5.8/dlls/gdiplus/tests/metafile.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/gdiplus/tests/metafile.c 2020-05-22 18:49:34.000000000 +0000 @@ -379,6 +379,7 @@ static const GpRectF frame = {0.0, 0.0, 100.0, 100.0}; static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}}; static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0}; + UINT limit_dpi; hdc = CreateCompatibleDC(0); @@ -408,6 +409,42 @@ if (stat != Ok) return; + stat = GdipGetMetafileDownLevelRasterizationLimit(metafile, NULL); + expect(InvalidParameter, stat); + + stat = GdipGetMetafileDownLevelRasterizationLimit(NULL, &limit_dpi); + expect(InvalidParameter, stat); + + limit_dpi = 0xdeadbeef; + stat = GdipGetMetafileDownLevelRasterizationLimit(metafile, &limit_dpi); + expect(Ok, stat); + ok(limit_dpi == 96, "limit_dpi was %d\n", limit_dpi); + + stat = GdipSetMetafileDownLevelRasterizationLimit(metafile, 255); + expect(Ok, stat); + + limit_dpi = 0xdeadbeef; + stat = GdipGetMetafileDownLevelRasterizationLimit(metafile, &limit_dpi); + expect(Ok, stat); + ok(limit_dpi == 255, "limit_dpi was %d\n", limit_dpi); + + stat = GdipSetMetafileDownLevelRasterizationLimit(metafile, 0); + expect(Ok, stat); + + limit_dpi = 0xdeadbeef; + stat = GdipGetMetafileDownLevelRasterizationLimit(metafile, &limit_dpi); + expect(Ok, stat); + ok(limit_dpi == 96, "limit_dpi was %d\n", limit_dpi); + + stat = GdipSetMetafileDownLevelRasterizationLimit(metafile, 1); + expect(InvalidParameter, stat); + + stat = GdipSetMetafileDownLevelRasterizationLimit(metafile, 9); + expect(InvalidParameter, stat); + + stat = GdipSetMetafileDownLevelRasterizationLimit(metafile, 10); + expect(Ok, stat); + stat = GdipGetHemfFromMetafile(metafile, &hemf); expect(InvalidParameter, stat); @@ -420,6 +457,14 @@ stat = GdipDeleteGraphics(graphics); expect(Ok, stat); + limit_dpi = 0xdeadbeef; + stat = GdipGetMetafileDownLevelRasterizationLimit(metafile, &limit_dpi); + expect(WrongState, stat); + expect(0xdeadbeef, limit_dpi); + + stat = GdipSetMetafileDownLevelRasterizationLimit(metafile, 200); + expect(WrongState, stat); + check_metafile(metafile, empty_records, "empty metafile", dst_points, &frame, UnitPixel); sync_metafile(&metafile, "empty.emf"); diff -Nru wine-development-5.8/dlls/iphlpapi/iphlpapi_main.c wine-development-5.9/dlls/iphlpapi/iphlpapi_main.c --- wine-development-5.8/dlls/iphlpapi/iphlpapi_main.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/iphlpapi/iphlpapi_main.c 2020-05-22 18:49:34.000000000 +0000 @@ -2817,6 +2817,18 @@ return NO_ERROR; } +/****************************************************************** + * NotifyRouteChange2 (IPHLPAPI.@) + */ +DWORD WINAPI NotifyRouteChange2(ADDRESS_FAMILY family, PIPFORWARD_CHANGE_CALLBACK callback, VOID* context, + BOOLEAN init_notify, HANDLE* handle) +{ + FIXME("(family %d, callback %p, context %p, init_notify %d, handle %p): stub\n", + family, callback, context, init_notify, handle); + if (handle) *handle = NULL; + return NO_ERROR; +} + /****************************************************************** * NotifyRouteChange (IPHLPAPI.@) @@ -3403,6 +3415,8 @@ NET_ADDRESS_INFO *info, USHORT *port, BYTE *prefix_len) { IN_ADDR temp_addr4; + IN6_ADDR temp_addr6; + ULONG temp_scope; USHORT temp_port = 0; NTSTATUS status; @@ -3443,10 +3457,44 @@ return ERROR_SUCCESS; } } + if (type & NET_STRING_IPV6_ADDRESS) + { + status = RtlIpv6StringToAddressExW(str, &temp_addr6, &temp_scope, &temp_port); + if (SUCCEEDED(status) && !temp_port) + { + if (info) + { + info->Format = NET_ADDRESS_IPV6; + info->u.Ipv6Address.sin6_addr = temp_addr6; + info->u.Ipv6Address.sin6_scope_id = temp_scope; + info->u.Ipv6Address.sin6_port = 0; + } + if (port) *port = 0; + if (prefix_len) *prefix_len = 255; + return ERROR_SUCCESS; + } + } + if (type & NET_STRING_IPV6_SERVICE) + { + status = RtlIpv6StringToAddressExW(str, &temp_addr6, &temp_scope, &temp_port); + if (SUCCEEDED(status) && temp_port) + { + if (info) + { + info->Format = NET_ADDRESS_IPV6; + info->u.Ipv6Address.sin6_addr = temp_addr6; + info->u.Ipv6Address.sin6_scope_id = temp_scope; + info->u.Ipv6Address.sin6_port = temp_port; + } + if (port) *port = ntohs(temp_port); + if (prefix_len) *prefix_len = 255; + return ERROR_SUCCESS; + } + } if (info) info->Format = NET_ADDRESS_FORMAT_UNSPECIFIED; - if (type & ~(NET_STRING_IPV4_ADDRESS|NET_STRING_IPV4_SERVICE)) + if (type & ~(NET_STRING_IPV4_ADDRESS|NET_STRING_IPV4_SERVICE|NET_STRING_IPV6_ADDRESS|NET_STRING_IPV6_SERVICE)) { FIXME("Unimplemented type 0x%x\n", type); return ERROR_NOT_SUPPORTED; diff -Nru wine-development-5.8/dlls/iphlpapi/iphlpapi.spec wine-development-5.9/dlls/iphlpapi/iphlpapi.spec --- wine-development-5.8/dlls/iphlpapi/iphlpapi.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/iphlpapi/iphlpapi.spec 2020-05-22 18:49:34.000000000 +0000 @@ -236,7 +236,7 @@ @ stdcall NotifyAddrChange( ptr ptr ) @ stdcall NotifyIpInterfaceChange( long ptr ptr long ptr ) @ stdcall NotifyRouteChange( ptr ptr ) -#@ stub NotifyRouteChange2 +@ stdcall NotifyRouteChange2( long ptr ptr long ptr ) @ stub NotifyRouteChangeEx #@ stub NotifyStableUnicastIpAddressTable #@ stub NotifyTeredoPortChange diff -Nru wine-development-5.8/dlls/joy.cpl/joy.rc wine-development-5.9/dlls/joy.cpl/joy.rc --- wine-development-5.8/dlls/joy.cpl/joy.rc 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/joy.cpl/joy.rc 2020-05-22 18:49:34.000000000 +0000 @@ -28,6 +28,7 @@ STRINGTABLE BEGIN IDS_CPL_NAME "Game Controllers" + IDS_CPL_INFO "Test and configure game controllers." END IDD_LIST DIALOG 0, 0, 320, 220 diff -Nru wine-development-5.8/dlls/kernel32/format_msg.c wine-development-5.9/dlls/kernel32/format_msg.c --- wine-development-5.8/dlls/kernel32/format_msg.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/format_msg.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,648 +0,0 @@ -/* - * FormatMessage implementation - * - * Copyright 1996 Marcus Meissner - * Copyright 2009 Alexandre Julliard - * - * 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 "config.h" - -#include -#include -#include - -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winternl.h" -#include "winuser.h" -#include "winnls.h" -#include "wine/unicode.h" -#include "kernel_private.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(resource); - -struct format_args -{ - ULONG_PTR *args; - __ms_va_list *list; - int last; -}; - -/* Messages used by FormatMessage - * - * They can be specified either directly or using a message ID and - * loading them from the resource. - * - * The resourcedata has following format: - * start: - * 0: DWORD nrofentries - * nrofentries * subentry: - * 0: DWORD firstentry - * 4: DWORD lastentry - * 8: DWORD offset from start to the stringentries - * - * (lastentry-firstentry) * stringentry: - * 0: WORD len (0 marks end) [ includes the 4 byte header length ] - * 2: WORD flags - * 4: CHAR[len-4] - * (stringentry i of a subentry refers to the ID 'firstentry+i') - * - * Yes, ANSI strings in win32 resources. Go figure. - */ - -/********************************************************************** - * load_message (internal) - */ -static LPWSTR load_message( HMODULE module, UINT id, WORD lang ) -{ - const MESSAGE_RESOURCE_ENTRY *mre; - WCHAR *buffer; - - TRACE("module = %p, id = %08x\n", module, id ); - - if (!module) module = GetModuleHandleW( NULL ); - if (!set_ntstatus( RtlFindMessage( module, RT_MESSAGETABLE, lang, id, &mre ))) return NULL; - - if (mre->Flags & MESSAGE_RESOURCE_UNICODE) - { - int len = (strlenW( (const WCHAR *)mre->Text ) + 1) * sizeof(WCHAR); - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return NULL; - memcpy( buffer, mre->Text, len ); - } - else - { - int len = MultiByteToWideChar( CP_ACP, 0, (const char *)mre->Text, -1, NULL, 0 ); - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL; - MultiByteToWideChar( CP_ACP, 0, (const char*)mre->Text, -1, buffer, len ); - } - TRACE("returning %s\n", wine_dbgstr_w(buffer)); - return buffer; -} - -static LPWSTR search_message( DWORD flags, HMODULE module, UINT id, WORD lang ) -{ - LPWSTR from = NULL; - if (flags & FORMAT_MESSAGE_FROM_HMODULE) - from = load_message( module, id, lang ); - if (!from && (flags & FORMAT_MESSAGE_FROM_SYSTEM)) - { - /* Fold win32 hresult to its embedded error code. */ - if (HRESULT_SEVERITY(id) == SEVERITY_ERROR && - HRESULT_FACILITY(id) == FACILITY_WIN32) - { - id = HRESULT_CODE(id); - } - from = load_message( kernel32_handle, id, lang ); - } - return from; -} - -/********************************************************************** - * get_arg (internal) - */ -static ULONG_PTR get_arg( int nr, DWORD flags, struct format_args *args ) -{ - if (nr == -1) nr = args->last + 1; - if (args->list) - { - if (!args->args) args->args = HeapAlloc( GetProcessHeap(), 0, 99 * sizeof(ULONG_PTR) ); - while (nr > args->last) - args->args[args->last++] = va_arg( *args->list, ULONG_PTR ); - } - if (nr > args->last) args->last = nr; - return args->args[nr - 1]; -} - -/********************************************************************** - * format_insert (internal) - */ -static LPCWSTR format_insert( BOOL unicode_caller, int insert, LPCWSTR format, - DWORD flags, struct format_args *args, - LPWSTR *result ) -{ - static const WCHAR fmt_u[] = {'%','u',0}; - WCHAR *wstring = NULL, *p, fmt[256]; - ULONG_PTR arg; - int size; - - if (*format != '!') /* simple string */ - { - arg = get_arg( insert, flags, args ); - if (unicode_caller || !arg) - { - static const WCHAR nullW[] = {'(','n','u','l','l',')',0}; - const WCHAR *str = (const WCHAR *)arg; - - if (!str) str = nullW; - *result = HeapAlloc( GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR) ); - strcpyW( *result, str ); - } - else - { - const char *str = (const char *)arg; - DWORD length = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); - *result = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, str, -1, *result, length ); - } - return format; - } - - format++; - p = fmt; - *p++ = '%'; - - while (*format == '0' || - *format == '+' || - *format == '-' || - *format == ' ' || - *format == '*' || - *format == '#') - { - if (*format == '*') - { - p += sprintfW( p, fmt_u, get_arg( insert, flags, args )); - insert = -1; - format++; - } - else *p++ = *format++; - } - while (*format >= '0' && *format <= '9') *p++ = *format++; - - if (*format == '.') - { - *p++ = *format++; - if (*format == '*') - { - p += sprintfW( p, fmt_u, get_arg( insert, flags, args )); - insert = -1; - format++; - } - else - while (*format >= '0' && *format <= '9') *p++ = *format++; - } - - /* replicate MS bug: drop an argument when using va_list with width/precision */ - if (insert == -1 && args->list) args->last--; - arg = get_arg( insert, flags, args ); - - /* check for ascii string format */ - if ((format[0] == 'h' && format[1] == 's') || - (format[0] == 'h' && format[1] == 'S') || - (unicode_caller && format[0] == 'S') || - (!unicode_caller && format[0] == 's')) - { - DWORD len = MultiByteToWideChar( CP_ACP, 0, (char *)arg, -1, NULL, 0 ); - wstring = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, (char *)arg, -1, wstring, len ); - arg = (ULONG_PTR)wstring; - *p++ = 's'; - } - /* check for ascii character format */ - else if ((format[0] == 'h' && format[1] == 'c') || - (format[0] == 'h' && format[1] == 'C') || - (unicode_caller && format[0] == 'C') || - (!unicode_caller && format[0] == 'c')) - { - char ch = arg; - wstring = HeapAlloc( GetProcessHeap(), 0, 2 * sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, &ch, 1, wstring, 1 ); - wstring[1] = 0; - arg = (ULONG_PTR)wstring; - *p++ = 's'; - } - /* check for wide string format */ - else if ((format[0] == 'l' && format[1] == 's') || - (format[0] == 'l' && format[1] == 'S') || - (format[0] == 'w' && format[1] == 's') || - (!unicode_caller && format[0] == 'S')) - { - *p++ = 's'; - } - /* check for wide character format */ - else if ((format[0] == 'l' && format[1] == 'c') || - (format[0] == 'l' && format[1] == 'C') || - (format[0] == 'w' && format[1] == 'c') || - (!unicode_caller && format[0] == 'C')) - { - *p++ = 'c'; - } - /* FIXME: handle I64 etc. */ - else while (*format && *format != '!') *p++ = *format++; - - *p = 0; - size = 256; - for (;;) - { - WCHAR *ret = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ); - int needed = snprintfW( ret, size, fmt, arg ); - if (needed == -1 || needed >= size) - { - HeapFree( GetProcessHeap(), 0, ret ); - size = max( needed + 1, size * 2 ); - } - else - { - *result = ret; - break; - } - } - - while (*format && *format != '!') format++; - if (*format == '!') format++; - - HeapFree( GetProcessHeap(), 0, wstring ); - return format; -} - -struct _format_message_data -{ - LPWSTR formatted; - DWORD size; - LPWSTR t; - LPWSTR space; - BOOL inspace; - DWORD width, w; -}; - -static void format_add_char(struct _format_message_data *fmd, WCHAR c) -{ - *fmd->t++ = c; - if (fmd->width && fmd->width != FORMAT_MESSAGE_MAX_WIDTH_MASK) - { - switch (c) { - case '\r': - case '\n': - fmd->space = NULL; - fmd->inspace = FALSE; - fmd->w = 0; - break; - case ' ': - if (!fmd->inspace) - fmd->space = fmd->t - 1; - fmd->inspace = TRUE; - fmd->w++; - break; - default: - fmd->inspace = FALSE; - fmd->w++; - } - if (fmd->w == fmd->width) { - LPWSTR notspace; - if (fmd->space) { - notspace = fmd->space; - while (notspace != fmd->t && *notspace == ' ') - notspace++; - } else - notspace = fmd->space = fmd->t; - fmd->w = fmd->t - notspace; - memmove(fmd->space+2, notspace, fmd->w * sizeof(*fmd->t)); - *fmd->space++ = '\r'; - *fmd->space++ = '\n'; - fmd->t = fmd->space + fmd->w; - fmd->space = NULL; - fmd->inspace = FALSE; - } - } - if ((DWORD)(fmd->t - fmd->formatted) == fmd->size) { - DWORD_PTR ispace = fmd->space - fmd->formatted; - /* Allocate two extra characters so we can insert a '\r\n' in - * the middle of a word. - */ - fmd->formatted = HeapReAlloc(GetProcessHeap(), 0, fmd->formatted, (fmd->size * 2 + 2) * sizeof(WCHAR)); - fmd->t = fmd->formatted + fmd->size; - if (fmd->space) - fmd->space = fmd->formatted + ispace; - fmd->size *= 2; - } -} - -/********************************************************************** - * format_message (internal) - */ -static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr, - struct format_args *format_args ) -{ - struct _format_message_data fmd; - LPCWSTR f; - BOOL eos = FALSE; - - fmd.size = 100; - fmd.formatted = fmd.t = HeapAlloc( GetProcessHeap(), 0, (fmd.size + 2) * sizeof(WCHAR) ); - - fmd.width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK; - fmd.w = 0; - fmd.inspace = FALSE; - fmd.space = NULL; - f = fmtstr; - while (*f && !eos) { - if (*f=='%') { - int insertnr; - WCHAR *str,*x; - - f++; - switch (*f) { - case '1':case '2':case '3':case '4':case '5': - case '6':case '7':case '8':case '9': - if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) - goto ignore_inserts; - else if (((dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->args) || - (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->list)) - { - SetLastError(ERROR_INVALID_PARAMETER); - HeapFree(GetProcessHeap(), 0, fmd.formatted); - return NULL; - } - insertnr = *f-'0'; - switch (f[1]) { - case '0':case '1':case '2':case '3': - case '4':case '5':case '6':case '7': - case '8':case '9': - f++; - insertnr = insertnr*10 + *f-'0'; - f++; - break; - default: - f++; - break; - } - f = format_insert( unicode_caller, insertnr, f, dwFlags, format_args, &str ); - for (x = str; *x; x++) format_add_char(&fmd, *x); - HeapFree( GetProcessHeap(), 0, str ); - break; - case 'n': - format_add_char(&fmd, '\r'); - format_add_char(&fmd, '\n'); - f++; - break; - case 'r': - format_add_char(&fmd, '\r'); - f++; - break; - case 't': - format_add_char(&fmd, '\t'); - f++; - break; - case '0': - eos = TRUE; - f++; - break; - case '\0': - SetLastError(ERROR_INVALID_PARAMETER); - HeapFree(GetProcessHeap(), 0, fmd.formatted); - return NULL; - ignore_inserts: - default: - if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) - format_add_char(&fmd, '%'); - format_add_char(&fmd, *f++); - break; - } - } else { - WCHAR ch = *f; - f++; - if (ch == '\r') { - if (*f == '\n') - f++; - if(fmd.width) - format_add_char(&fmd, ' '); - else - { - format_add_char(&fmd, '\r'); - format_add_char(&fmd, '\n'); - } - } else { - if (ch == '\n') - { - if(fmd.width) - format_add_char(&fmd, ' '); - else - { - format_add_char(&fmd, '\r'); - format_add_char(&fmd, '\n'); - } - } - else - format_add_char(&fmd, ch); - } - } - } - *fmd.t = '\0'; - - return fmd.formatted; -} - -/*********************************************************************** - * FormatMessageA (KERNEL32.@) - */ -DWORD WINAPI FormatMessageA( - DWORD dwFlags, - LPCVOID lpSource, - DWORD dwMessageId, - DWORD dwLanguageId, - LPSTR lpBuffer, - DWORD nSize, - __ms_va_list* args ) -{ - struct format_args format_args; - DWORD ret = 0; - LPWSTR target; - DWORD destlength; - LPWSTR from; - - TRACE("(0x%x,%p,%d,0x%x,%p,%d,%p)\n", - dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args); - - if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) - { - if (!lpBuffer) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - else - *(LPSTR *)lpBuffer = NULL; - } - - if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) - { - format_args.args = (ULONG_PTR *)args; - format_args.list = NULL; - format_args.last = 0; - } - else - { - format_args.args = NULL; - format_args.list = args; - format_args.last = 0; - } - - from = NULL; - if (dwFlags & FORMAT_MESSAGE_FROM_STRING) - { - DWORD length = MultiByteToWideChar(CP_ACP, 0, lpSource, -1, NULL, 0); - from = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) ); - MultiByteToWideChar(CP_ACP, 0, lpSource, -1, from, length); - } - else if (dwFlags & (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM)) - { - from = search_message( dwFlags, (HMODULE)lpSource, dwMessageId, dwLanguageId ); - if (!from) return 0; - } - else - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - target = format_message( FALSE, dwFlags, from, &format_args ); - if (!target) - goto failure; - - TRACE("-- %s\n", debugstr_w(target)); - - /* Only try writing to an output buffer if there are processed characters - * in the temporary output buffer. */ - if (*target) - { - destlength = WideCharToMultiByte(CP_ACP, 0, target, -1, NULL, 0, NULL, NULL); - if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) - { - LPSTR buf = LocalAlloc(LMEM_ZEROINIT, max(nSize, destlength)); - WideCharToMultiByte(CP_ACP, 0, target, -1, buf, destlength, NULL, NULL); - *((LPSTR*)lpBuffer) = buf; - } - else - { - if (nSize < destlength) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - goto failure; - } - WideCharToMultiByte(CP_ACP, 0, target, -1, lpBuffer, destlength, NULL, NULL); - } - ret = destlength - 1; /* null terminator */ - } - -failure: - HeapFree(GetProcessHeap(),0,target); - HeapFree(GetProcessHeap(),0,from); - if (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)) HeapFree( GetProcessHeap(), 0, format_args.args ); - TRACE("-- returning %u\n", ret); - return ret; -} - -/*********************************************************************** - * FormatMessageW (KERNEL32.@) - */ -DWORD WINAPI FormatMessageW( - DWORD dwFlags, - LPCVOID lpSource, - DWORD dwMessageId, - DWORD dwLanguageId, - LPWSTR lpBuffer, - DWORD nSize, - __ms_va_list* args ) -{ - struct format_args format_args; - DWORD ret = 0; - LPWSTR target; - DWORD talloced; - LPWSTR from; - - TRACE("(0x%x,%p,%d,0x%x,%p,%d,%p)\n", - dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args); - - if (!lpBuffer) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) - *(LPWSTR *)lpBuffer = NULL; - - if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) - { - format_args.args = (ULONG_PTR *)args; - format_args.list = NULL; - format_args.last = 0; - } - else - { - format_args.args = NULL; - format_args.list = args; - format_args.last = 0; - } - - from = NULL; - if (dwFlags & FORMAT_MESSAGE_FROM_STRING) { - from = HeapAlloc( GetProcessHeap(), 0, (strlenW(lpSource) + 1) * - sizeof(WCHAR) ); - strcpyW( from, lpSource ); - } - else if (dwFlags & (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM)) - { - from = search_message( dwFlags, (HMODULE)lpSource, dwMessageId, dwLanguageId ); - if (!from) return 0; - } - else - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - target = format_message( TRUE, dwFlags, from, &format_args ); - if (!target) - goto failure; - - talloced = strlenW(target)+1; - TRACE("-- %s\n",debugstr_w(target)); - - /* Only allocate a buffer if there are processed characters in the - * temporary output buffer. If a caller supplies the buffer, then - * a null terminator will be written to it. */ - if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) - { - if (*target) - { - /* nSize is the MINIMUM size */ - *((LPVOID*)lpBuffer) = LocalAlloc(LMEM_ZEROINIT, max(nSize, talloced)*sizeof(WCHAR)); - strcpyW(*(LPWSTR*)lpBuffer, target); - } - } - else - { - if (nSize < talloced) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - goto failure; - } - strcpyW(lpBuffer, target); - } - - ret = talloced - 1; /* null terminator */ -failure: - HeapFree(GetProcessHeap(),0,target); - HeapFree(GetProcessHeap(),0,from); - if (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)) HeapFree( GetProcessHeap(), 0, format_args.args ); - TRACE("-- returning %u\n", ret); - return ret; -} diff -Nru wine-development-5.8/dlls/kernel32/kernel32.spec wine-development-5.9/dlls/kernel32/kernel32.spec --- wine-development-5.8/dlls/kernel32/kernel32.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/kernel32.spec 2020-05-22 18:49:34.000000000 +0000 @@ -522,8 +522,8 @@ @ stdcall -import FlushViewOfFile(ptr long) @ stdcall FoldStringA(long str long ptr long) @ stdcall -import FoldStringW(long wstr long ptr long) -@ stdcall FormatMessageA(long ptr long long ptr long ptr) -@ stdcall FormatMessageW(long ptr long long ptr long ptr) +@ stdcall -import FormatMessageA(long ptr long long ptr long ptr) +@ stdcall -import FormatMessageW(long ptr long long ptr long ptr) @ stdcall FreeConsole() @ stdcall -import FreeEnvironmentStringsA(ptr) @ stdcall -import FreeEnvironmentStringsW(ptr) @@ -761,7 +761,7 @@ @ stdcall -import GetOEMCP() @ stdcall -import GetOverlappedResult(long ptr ptr long) @ stdcall -import GetOverlappedResultEx(long ptr ptr long long) -@ stdcall GetUserPreferredUILanguages(long ptr ptr ptr) +@ stdcall -import GetUserPreferredUILanguages(long ptr ptr ptr) @ stdcall GetPackageFullName(long ptr ptr) kernelbase.GetPackageFullName @ stdcall -import GetPhysicallyInstalledSystemMemory(ptr) @ stdcall -import GetPriorityClass(long) @@ -787,11 +787,11 @@ @ stdcall -import GetProcessIdOfThread(long) @ stdcall GetProcessIoCounters(long ptr) @ stdcall -import GetProcessMitigationPolicy(long long ptr long) -@ stdcall GetProcessPreferredUILanguages(long ptr ptr ptr) +@ stdcall -import GetProcessPreferredUILanguages(long ptr ptr ptr) @ stdcall -import GetProcessPriorityBoost(long ptr) @ stdcall -import GetProcessShutdownParameters(ptr ptr) # @ stub GetProcessorSystemCycleTime -@ stdcall GetProcessTimes(long ptr ptr ptr ptr) +@ stdcall -import GetProcessTimes(long ptr ptr ptr ptr) # @ stub GetProcessUserModeExceptionPolicy @ stdcall GetProcessVersion(long) @ stdcall GetProcessWorkingSetSize(long ptr ptr) @@ -829,13 +829,13 @@ @ stdcall -import GetSystemFirmwareTable(long long ptr long) @ stdcall -import GetSystemInfo(ptr) @ stdcall GetSystemPowerStatus(ptr) -@ stdcall GetSystemPreferredUILanguages(long ptr ptr ptr) +@ stdcall -import GetSystemPreferredUILanguages(long ptr ptr ptr) @ stdcall GetSystemRegistryQuota(ptr ptr) @ stdcall -import GetSystemTime(ptr) -@ stdcall GetSystemTimeAdjustment(ptr ptr ptr) +@ stdcall -import GetSystemTimeAdjustment(ptr ptr ptr) @ stdcall -import GetSystemTimeAsFileTime(ptr) @ stdcall -import GetSystemTimePreciseAsFileTime(ptr) -@ stdcall GetSystemTimes(ptr ptr ptr) +@ stdcall -import GetSystemTimes(ptr ptr ptr) @ stdcall -import GetSystemWindowsDirectoryA(ptr long) @ stdcall -import GetSystemWindowsDirectoryW(ptr long) @ stdcall -import GetSystemWow64DirectoryA(ptr long) @@ -855,7 +855,7 @@ @ stdcall -import GetThreadId(ptr) @ stdcall -import GetThreadIdealProcessorEx(long ptr) @ stdcall -import GetThreadLocale() -@ stdcall GetThreadPreferredUILanguages(long ptr ptr ptr) +@ stdcall -import GetThreadPreferredUILanguages(long ptr ptr ptr) @ stdcall -import GetThreadPriority(long) @ stdcall -import GetThreadPriorityBoost(long ptr) @ stdcall GetThreadSelectorEntry(long long ptr) @@ -1433,7 +1433,7 @@ @ stdcall -import SetProcessAffinityUpdateMode(long long) @ stdcall SetProcessDEPPolicy(long) @ stdcall -import SetProcessMitigationPolicy(long ptr long) -@ stdcall SetProcessPreferredUILanguages(long ptr ptr) +@ stdcall -import SetProcessPreferredUILanguages(long ptr ptr) @ stdcall -import SetProcessPriorityBoost(long long) @ stdcall -import SetProcessShutdownParameters(long long) # @ stub SetProcessUserModeExceptionPolicy @@ -1445,7 +1445,7 @@ @ stdcall -import SetSystemFileCacheSize(long long long) @ stdcall SetSystemPowerState(long long) @ stdcall -import SetSystemTime(ptr) -@ stdcall SetSystemTimeAdjustment(long long) +@ stdcall -import SetSystemTimeAdjustment(long long) @ stdcall SetTapeParameters(ptr long ptr) @ stdcall SetTapePosition(ptr long long long long long) @ stdcall SetTermsrvAppInstallMode(long) @@ -1458,7 +1458,7 @@ @ stdcall -import SetThreadIdealProcessor(long long) @ stdcall -import SetThreadIdealProcessorEx(long ptr ptr) @ stdcall -import SetThreadLocale(long) -@ stdcall SetThreadPreferredUILanguages(long ptr ptr) +@ stdcall -import SetThreadPreferredUILanguages(long ptr ptr) @ stdcall -import SetThreadPriority(long long) @ stdcall -import SetThreadPriorityBoost(long long) @ stdcall -import SetThreadStackGuarantee(ptr) diff -Nru wine-development-5.8/dlls/kernel32/locale.c wine-development-5.9/dlls/kernel32/locale.c --- wine-development-5.8/dlls/kernel32/locale.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/locale.c 2020-05-22 18:49:34.000000000 +0000 @@ -76,139 +76,6 @@ } -static BOOL get_dummy_preferred_ui_language( DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size ) -{ - LCTYPE type; - int lsize; - - FIXME("(0x%x %p %p %p) returning a dummy value (current locale)\n", flags, count, buffer, size); - - if (flags & MUI_LANGUAGE_ID) - type = LOCALE_ILANGUAGE; - else - type = LOCALE_SNAME; - - lsize = GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, type, NULL, 0); - if (!lsize) - { - /* keep last error from callee */ - return FALSE; - } - lsize++; - if (!*size) - { - *size = lsize; - *count = 1; - return TRUE; - } - - if (lsize > *size) - { - *size = lsize; - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - if (!GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, type, buffer, *size)) - { - /* keep last error from callee */ - return FALSE; - } - - buffer[lsize-1] = 0; - *size = lsize; - *count = 1; - TRACE("returned variable content: %d, \"%s\", %d\n", *count, debugstr_w(buffer), *size); - return TRUE; - -} - -/*********************************************************************** - * GetProcessPreferredUILanguages (KERNEL32.@) - */ -BOOL WINAPI GetProcessPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buf, ULONG *size ) -{ - FIXME( "%08x, %p, %p %p\n", flags, count, buf, size ); - return get_dummy_preferred_ui_language( flags, count, buf, size ); -} - -/*********************************************************************** - * GetSystemPreferredUILanguages (KERNEL32.@) - */ -BOOL WINAPI GetSystemPreferredUILanguages(DWORD flags, ULONG* count, WCHAR* buffer, ULONG* size) -{ - if (flags & ~(MUI_LANGUAGE_NAME | MUI_LANGUAGE_ID | MUI_MACHINE_LANGUAGE_SETTINGS)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if ((flags & MUI_LANGUAGE_NAME) && (flags & MUI_LANGUAGE_ID)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if (*size && !buffer) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - return get_dummy_preferred_ui_language( flags, count, buffer, size ); -} - -/*********************************************************************** - * SetProcessPreferredUILanguages (KERNEL32.@) - */ -BOOL WINAPI SetProcessPreferredUILanguages( DWORD flags, PCZZWSTR buffer, PULONG count ) -{ - FIXME("%u, %p, %p\n", flags, buffer, count ); - return TRUE; -} - -/*********************************************************************** - * SetThreadPreferredUILanguages (KERNEL32.@) - */ -BOOL WINAPI SetThreadPreferredUILanguages( DWORD flags, PCZZWSTR buffer, PULONG count ) -{ - FIXME( "%u, %p, %p\n", flags, buffer, count ); - return TRUE; -} - -/*********************************************************************** - * GetThreadPreferredUILanguages (KERNEL32.@) - */ -BOOL WINAPI GetThreadPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buf, ULONG *size ) -{ - FIXME( "%08x, %p, %p %p\n", flags, count, buf, size ); - return get_dummy_preferred_ui_language( flags, count, buf, size ); -} - -/****************************************************************************** - * GetUserPreferredUILanguages (KERNEL32.@) - */ -BOOL WINAPI GetUserPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size ) -{ - TRACE( "%u %p %p %p\n", flags, count, buffer, size ); - - if (flags & ~(MUI_LANGUAGE_NAME | MUI_LANGUAGE_ID)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if ((flags & MUI_LANGUAGE_NAME) && (flags & MUI_LANGUAGE_ID)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if (*size && !buffer) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - return get_dummy_preferred_ui_language( flags, count, buffer, size ); -} - /****************************************************************************** * SetLocaleInfoA [KERNEL32.@] * diff -Nru wine-development-5.8/dlls/kernel32/Makefile.in wine-development-5.9/dlls/kernel32/Makefile.in --- wine-development-5.8/dlls/kernel32/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -16,7 +16,6 @@ editline.c \ environ.c \ file.c \ - format_msg.c \ heap.c \ kernel_main.c \ lcformat.c \ diff -Nru wine-development-5.8/dlls/kernel32/process.c wine-development-5.9/dlls/kernel32/process.c --- wine-development-5.8/dlls/kernel32/process.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/process.c 2020-05-22 18:49:34.000000000 +0000 @@ -94,12 +94,18 @@ __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") "movl %esp,%ebp\n\t" __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") - "pushl 4(%ebp)\n\t" /* deliberately mis-align the stack by 8, Doom 3 needs this */ + "pushl %ebx\n\t" + __ASM_CFI(".cfi_rel_offset %ebx,-4\n\t") + "movl 8(%ebp),%ebx\n\t" + /* deliberately mis-align the stack by 8, Doom 3 needs this */ "pushl 4(%ebp)\n\t" /* Driller expects readable address at this offset */ "pushl 4(%ebp)\n\t" - "pushl 8(%ebp)\n\t" + "pushl %ebx\n\t" "call *12(%ebp)\n\t" - "leave\n\t" + "leal -4(%ebp),%esp\n\t" + "popl %ebx\n\t" + __ASM_CFI(".cfi_same_value %ebx\n\t") + "popl %ebp\n\t" __ASM_CFI(".cfi_def_cfa %esp,4\n\t") __ASM_CFI(".cfi_same_value %ebp\n\t") "ret" ) diff -Nru wine-development-5.8/dlls/kernel32/tests/environ.c wine-development-5.9/dlls/kernel32/tests/environ.c --- wine-development-5.8/dlls/kernel32/tests/environ.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/tests/environ.c 2020-05-22 18:49:34.000000000 +0000 @@ -106,9 +106,12 @@ GetLastError()); /* Try to retrieve the environment variable we just set */ + SetLastError(0xdeadbeef); ret_size = GetEnvironmentVariableA(name, NULL, 0); ok(ret_size == strlen(value) + 1, "should return length with terminating 0 ret_size=%d\n", ret_size); + ok(GetLastError() == 0xdeadbeef, + "should not fail with zero size but GetLastError=%d\n", GetLastError()); lstrcpyA(buf, "foo"); ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value)); @@ -157,14 +160,24 @@ "should not fail with empty value but GetLastError=%d\n", GetLastError()); lstrcpyA(buf, "foo"); - SetLastError(0); + SetLastError(0xdeadbeef); ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1); ok(ret_size == 0 && - ((GetLastError() == 0 && lstrcmpA(buf, "") == 0) || + ((GetLastError() == 0xdeadbeef && lstrcmpA(buf, "") == 0) || (GetLastError() == ERROR_ENVVAR_NOT_FOUND)), "%s should be set to \"\" (NT) or removed (Win9x) but ret_size=%d GetLastError=%d and buf=%s\n", name, ret_size, GetLastError(), buf); + SetLastError(0xdeadbeef); + ret_size = GetEnvironmentVariableA(name, NULL, 0); + ok(ret_size == 1 || + broken(ret_size == 0), /* XP */ + "should return 1 for empty string but ret_size=%d GetLastError=%d\n", + ret_size, GetLastError()); + ok(GetLastError() == 0xdeadbeef || + broken(GetLastError() == ERROR_MORE_DATA), /* XP */ + "should not fail with zero size but GetLastError=%d\n", GetLastError()); + /* Test the limits */ SetLastError(0xdeadbeef); ret_size = GetEnvironmentVariableA(NULL, NULL, 0); @@ -208,10 +221,13 @@ GetLastError()); /* Try to retrieve the environment variable we just set */ + SetLastError(0xdeadbeef); ret_size = GetEnvironmentVariableW(name, NULL, 0); ok(ret_size == lstrlenW(value) + 1, "should return length with terminating 0 ret_size=%d\n", ret_size); + ok(GetLastError() == 0xdeadbeef, + "should not fail with zero size but GetLastError=%d\n", GetLastError()); lstrcpyW(buf, fooW); ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value)); @@ -262,15 +278,25 @@ ok(ret == TRUE, "should not fail with empty value but GetLastError=%d\n", GetLastError()); lstrcpyW(buf, fooW); - SetLastError(0); + SetLastError(0xdeadbeef); ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1); ok(ret_size == 0 && - ((GetLastError() == 0 && lstrcmpW(buf, empty_strW) == 0) || + ((GetLastError() == 0xdeadbeef && lstrcmpW(buf, empty_strW) == 0) || (GetLastError() == ERROR_ENVVAR_NOT_FOUND)), "should be set to \"\" (NT) or removed (Win9x) but ret_size=%d GetLastError=%d\n", ret_size, GetLastError()); ok(lstrcmpW(buf, empty_strW) == 0, "should copy an empty string\n"); + SetLastError(0xdeadbeef); + ret_size = GetEnvironmentVariableW(name, NULL, 0); + ok(ret_size == 1 || + broken(ret_size == 0), /* XP */ + "should return 1 for empty string but ret_size=%d GetLastError=%d\n", + ret_size, GetLastError()); + ok(GetLastError() == 0xdeadbeef || + broken(GetLastError() == ERROR_MORE_DATA), /* XP */ + "should not fail with zero size but GetLastError=%d\n", GetLastError()); + /* Test the limits */ SetLastError(0xdeadbeef); ret_size = GetEnvironmentVariableW(NULL, NULL, 0); diff -Nru wine-development-5.8/dlls/kernel32/tests/format_msg.c wine-development-5.9/dlls/kernel32/tests/format_msg.c --- wine-development-5.8/dlls/kernel32/tests/format_msg.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/tests/format_msg.c 2020-05-22 18:49:34.000000000 +0000 @@ -77,7 +77,7 @@ error = GetLastError(); ok(!lstrcmpW(L"", out), "failed out=%s\n", wine_dbgstr_w(out)); ok(r==0, "succeeded: r=%d\n", r); - ok((error==0xdeadbeef) || (error == ERROR_NO_WORK_DONE), "last error %u\n", error); + ok(error == ERROR_NO_WORK_DONE || broken(error == 0xdeadbeef), "last error %u\n", error); /* format placeholder with no specifier */ SetLastError(0xdeadbeef); @@ -94,8 +94,7 @@ lstrcpyW( out, L"xxxxxx" ); r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, L"test%", 0, 0, out, ARRAY_SIZE(out), NULL); error = GetLastError(); - ok(!lstrcmpW( out, L"xxxxxx" ) || - broken(!lstrcmpW(out, L"testxx")), /* W2K3+ */ + ok(!lstrcmpW(out, L"testxx") || broken(!lstrcmpW( out, L"xxxxxx" )), /* winxp */ "Expected the buffer to be unchanged\n"); ok(r==0, "succeeded: r=%d\n", r); ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error); @@ -359,7 +358,7 @@ r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "", 0, 0, out, ARRAY_SIZE(out), NULL); ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the buffer to be untouched\n"); ok(r==0, "succeeded: r=%d\n", r); - ok((GetLastError()==0xdeadbeef) || (GetLastError() == ERROR_NO_WORK_DONE), + ok(GetLastError() == ERROR_NO_WORK_DONE || broken(GetLastError() == 0xdeadbeef), "last error %u\n", GetLastError()); /* format placeholder with no specifier */ @@ -661,8 +660,8 @@ ARRAY_SIZE(out), NULL); ok(ret == 0, "Expected FormatMessageA to return 0, got %d\n", ret); ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the output buffer to be untouched\n"); - ok((GetLastError() == 0xdeadbeef) || (GetLastError() == ERROR_NO_WORK_DONE), - "Expected GetLastError() to return 0xdeadbeef or ERROR_NO_WORK_DONE, got %u\n", GetLastError()); + ok(GetLastError() == ERROR_NO_WORK_DONE || broken(GetLastError() == 0xdeadbeef), + "Expected GetLastError() to return ERROR_NO_WORK_DONE, got %u\n", GetLastError()); /* Insert sequences are ignored. */ ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test%1%2!*.*s!%99", 0, 0, out, @@ -751,8 +750,8 @@ ARRAY_SIZE(out), NULL); ok(ret == 0, "Expected FormatMessageW to return 0, got %d\n", ret); ok(!lstrcmpW(L"", out), "Expected the output buffer to be the empty string, got %s\n", wine_dbgstr_w(out)); - ok((GetLastError() == 0xdeadbeef) || (GetLastError() == ERROR_NO_WORK_DONE), - "Expected GetLastError() to return 0xdeadbeef or ERROR_NO_WORK_DONE, got %u\n", GetLastError()); + ok(GetLastError() == ERROR_NO_WORK_DONE || broken(GetLastError() == 0xdeadbeef), + "Expected GetLastError() to return ERROR_NO_WORK_DONE, got %u\n", GetLastError()); /* Insert sequences are ignored. */ ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, L"test%1%2!*.*s!%99", 0, 0, out, @@ -1010,7 +1009,7 @@ { static const char init_buf[] = {'x', 'x', 'x', 'x', 'x'}; static const char expected_buf[] = {'x', 'x', 'x', 'x', 'x'}; - DWORD ret; + DWORD ret, size, i; CHAR out[5]; SetLastError(0xdeadbeef); @@ -1042,11 +1041,63 @@ GetLastError()); ok(!memcmp(expected_buf, out, sizeof(expected_buf)), "Expected the buffer to be untouched\n"); + + for (size = 32700; size < 32800; size++) + { + char *tmp = HeapAlloc( GetProcessHeap(), 0, size ); + char *buf = HeapAlloc( GetProcessHeap(), 0, size ); + + for (i = 0; i < size; i++) tmp[i] = 'A' + i % 26; + tmp[size - 1] = 0; + SetLastError( 0xdeadbeef ); + ret = FormatMessageA( FORMAT_MESSAGE_FROM_STRING, tmp, 0, 0, buf, size, NULL ); + if (size < 32768) + { + ok( ret == size - 1, "%u: got %u\n", size, ret ); + ok( !strcmp( tmp, buf ), "wrong buffer\n" ); + } + else + { + ok( ret == 0, "%u: got %u\n", size, ret ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); + } + + SetLastError( 0xdeadbeef ); + ret = doit( FORMAT_MESSAGE_FROM_STRING, "%1", 0, 0, buf, size, tmp ); + if (size < 32768) + { + ok( ret == size - 1, "%u: got %u\n", size, ret ); + ok( !strcmp( tmp, buf ), "wrong buffer\n" ); + } + else + { + ok( ret == 0, "%u: got %u\n", size, ret ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_MORE_DATA), /* winxp */ + "wrong error %u\n", GetLastError() ); + } + HeapFree( GetProcessHeap(), 0, buf ); + + SetLastError( 0xdeadbeef ); + ret = FormatMessageA( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + tmp, 0, 0, (char *)&buf, size, NULL ); + if (size < 32768) + { + ok( ret == size - 1, "%u: got %u\n", size, ret ); + ok( !strcmp( tmp, buf ), "wrong buffer\n" ); + HeapFree( GetProcessHeap(), 0, buf ); + } + else + { + ok( ret == 0, "%u: got %u\n", size, ret ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); + } + HeapFree( GetProcessHeap(), 0, tmp ); + } } static void test_message_insufficient_buffer_wide(void) { - DWORD ret; + DWORD ret, size, i; WCHAR out[8]; SetLastError(0xdeadbeef); @@ -1066,7 +1117,6 @@ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); - todo_wine ok(!memcmp(out, L"\0xxxxx", 6 * sizeof(WCHAR)) || broken(!lstrcmpW( out, L"xxxxxx" )), /* winxp */ "Expected the buffer to be truncated\n"); @@ -1078,10 +1128,31 @@ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); - todo_wine ok(!memcmp(out, L"tes\0xx", 6 * sizeof(WCHAR)) || broken(!lstrcmpW( out, L"xxxxxx" )), /* winxp */ "Expected the buffer to be truncated\n"); + + for (size = 1000; size < 1000000; size += size / 10) + { + WCHAR *tmp = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ); + WCHAR *buf = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ); + for (i = 0; i < size; i++) tmp[i] = 'A' + i % 26; + tmp[size - 1] = 0; + ret = FormatMessageW( FORMAT_MESSAGE_FROM_STRING, tmp, 0, 0, buf, size, NULL ); + ok(ret == size - 1 || broken(!ret), /* winxp */ "got %u\n", ret); + if (!ret) break; + ok( !lstrcmpW( tmp, buf ), "wrong buffer\n" ); + ret = doitW( FORMAT_MESSAGE_FROM_STRING, L"%1", 0, 0, buf, size, tmp ); + ok(ret == size - 1, "got %u\n", ret); + ok( !lstrcmpW( tmp, buf ), "wrong buffer\n" ); + HeapFree( GetProcessHeap(), 0, buf ); + ret = FormatMessageW( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + tmp, 0, 0, (WCHAR *)&buf, size, NULL ); + ok(ret == size - 1, "got %u\n", ret); + ok( !lstrcmpW( tmp, buf ), "wrong buffer\n" ); + HeapFree( GetProcessHeap(), 0, tmp ); + HeapFree( GetProcessHeap(), 0, buf ); + } } static void test_message_null_buffer(void) @@ -1185,8 +1256,8 @@ "", 0, 0, (char *)&buf, 0, NULL); ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret); ok(buf == NULL, "Expected output buffer pointer to be NULL\n"); - ok((GetLastError() == 0xdeadbeef) || (GetLastError() == ERROR_NO_WORK_DONE), - "Expected GetLastError() to return 0xdeadbeef or ERROR_NO_WORK_DONE, got %u\n", GetLastError()); + ok(GetLastError() == ERROR_NO_WORK_DONE || broken(GetLastError() == 0xdeadbeef), + "Expected GetLastError() to return ERROR_NO_WORK_DONE, got %u\n", GetLastError()); buf = (char *)0xdeadbeef; ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, @@ -1279,8 +1350,17 @@ L"", 0, 0, (WCHAR *)&buf, 0, NULL); ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret); ok(buf == NULL, "Expected output buffer pointer to be NULL\n"); - ok((GetLastError() == 0xdeadbeef) || (GetLastError() == ERROR_NO_WORK_DONE), - "Expected GetLastError() to return 0xdeadbeef or ERROR_NO_WORK_DONE, got %u\n", GetLastError()); + ok(GetLastError() == ERROR_NO_WORK_DONE || broken(GetLastError() == 0xdeadbeef), + "Expected GetLastError() to return ERROR_NO_WORK_DONE, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + buf = (WCHAR *)0xdeadbeef; + ret = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, L"%1", + 0, 0, (WCHAR *)&buf, 0, L"" ); + ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret); + ok(buf == NULL, "Expected output buffer pointer to be NULL\n"); + ok(GetLastError() == ERROR_NO_WORK_DONE || broken(GetLastError() == 0xdeadbeef), + "Expected GetLastError() to return ERROR_NO_WORK_DONE, got %u\n", GetLastError()); buf = (WCHAR *)0xdeadbeef; ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, @@ -1637,18 +1717,14 @@ r = doitW(FORMAT_MESSAGE_FROM_STRING, L"%1!I64u!", 0, 0, outW, ARRAY_SIZE(outW), unsigned_tests[i].number); MultiByteToWideChar(CP_ACP, 0, unsigned_tests[i].expected, -1, expW, ARRAY_SIZE(expW)); -todo_wine { ok(!lstrcmpW(outW, expW),"[%d] failed, expected %s, got %s\n", i, unsigned_tests[i].expected, wine_dbgstr_w(outW)); ok(r == unsigned_tests[i].len,"[%d] failed: r=%d\n", i, r); -} r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!I64u!", 0, 0, outA, sizeof(outA), unsigned_tests[i].number); -todo_wine { ok(!strcmp(outA, unsigned_tests[i].expected),"[%d] failed, expected %s, got %s\n", i, unsigned_tests[i].expected, outA); ok(r == unsigned_tests[i].len,"[%d] failed: r=%d\n", i, r); -} } for (i = 0; i < ARRAY_SIZE(signed_tests); i++) @@ -1656,18 +1732,14 @@ r = doitW(FORMAT_MESSAGE_FROM_STRING, L"%1!I64d!", 0, 0, outW, ARRAY_SIZE(outW), signed_tests[i].number); MultiByteToWideChar(CP_ACP, 0, signed_tests[i].expected, -1, expW, ARRAY_SIZE(expW)); -todo_wine { ok(!lstrcmpW(outW, expW),"[%d] failed, expected %s, got %s\n", i, signed_tests[i].expected, wine_dbgstr_w(outW)); ok(r == signed_tests[i].len,"[%d] failed: r=%d\n", i, r); -} r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!I64d!", 0, 0, outA, sizeof(outA), signed_tests[i].number); -todo_wine { ok(!strcmp(outA, signed_tests[i].expected),"[%d] failed, expected %s, got %s\n", i, signed_tests[i].expected, outA); ok(r == signed_tests[i].len,"[%d] failed: r=%d\n", i, r); -} } } diff -Nru wine-development-5.8/dlls/kernel32/tests/loader.c wine-development-5.9/dlls/kernel32/tests/loader.c --- wine-development-5.8/dlls/kernel32/tests/loader.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/tests/loader.c 2020-05-22 18:49:34.000000000 +0000 @@ -228,7 +228,7 @@ { SetLastError(0xdeadbeef); ret = WriteFile(hfile, &nt_header->OptionalHeader, - min(nt_header->FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)), + sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL); ok(ret, "WriteFile error %d\n", GetLastError()); if (nt_header->FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER)) @@ -244,6 +244,8 @@ assert(nt_header->FileHeader.NumberOfSections <= 1); if (nt_header->FileHeader.NumberOfSections) { + SetFilePointer(hfile, dos_size + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + nt_header->FileHeader.SizeOfOptionalHeader, NULL, FILE_BEGIN); + section.SizeOfRawData = 10; if (nt_header->OptionalHeader.SectionAlignment >= page_size) @@ -268,6 +270,17 @@ ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL); ok(ret, "WriteFile error %d\n", GetLastError()); } + + /* Minimal PE image that Windows7+ is able to load: 268 bytes */ + size = GetFileSize(hfile, NULL); + if (size < 268) + { + file_align = 268 - size; + SetLastError(0xdeadbeef); + ret = WriteFile(hfile, filler, file_align, &dummy, NULL); + ok(ret, "WriteFile error %d\n", GetLastError()); + } + size = GetFileSize(hfile, NULL); CloseHandle(hfile); return size; @@ -417,7 +430,8 @@ ok( image.LoaderFlags == (cor_header != NULL), "%u: LoaderFlags wrong %08x\n", id, image.LoaderFlags ); ok( image.ImageFileSize == file_size || broken(!image.ImageFileSize), /* winxpsp1 */ "%u: ImageFileSize wrong %08x / %08x\n", id, image.ImageFileSize, file_size ); - ok( image.CheckSum == nt_header->OptionalHeader.CheckSum, "%u: CheckSum wrong %08x / %08x\n", id, + ok( image.CheckSum == nt_header->OptionalHeader.CheckSum || broken(truncated), + "%u: CheckSum wrong %08x / %08x\n", id, image.CheckSum, nt_header->OptionalHeader.CheckSum ); if (nt_header->OptionalHeader.SizeOfCode || nt_header->OptionalHeader.AddressOfEntryPoint) @@ -768,6 +782,7 @@ /* Mandatory are all fields up to SizeOfHeaders, everything else * is really optional (at least that's true for XP). */ +#if 0 /* 32-bit Windows 8 crashes inside of LoadLibrary */ { sizeof(dos_header), 1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10, @@ -775,6 +790,7 @@ { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT, ERROR_INVALID_ADDRESS, ERROR_NOACCESS } }, +#endif { sizeof(dos_header), 0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200, 0xd0, /* beyond of the end of file */ @@ -843,6 +859,14 @@ 0x40, /* minimal image size that Windows7 accepts */ 0, { ERROR_SUCCESS } + }, + /* the following data mimics the PE image which 8k demos have */ + { 0x04, + 0, 0x08, + 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04, + 0x200000, + 0x40, + { ERROR_SUCCESS } } }; int i; @@ -1077,6 +1101,18 @@ ok(ret, "FreeLibrary error %d\n", GetLastError()); } + SetLastError(0xdeadbeef); + ret = DeleteFileA(dll_name); + ok(ret, "DeleteFile error %d\n", GetLastError()); + + nt_header.OptionalHeader.AddressOfEntryPoint = 0x12345678; + file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name ); + if (!file_size) + { + ok(0, "could not create %s\n", dll_name); + break; + } + query_image_section( i, dll_name, &nt_header, NULL ); } else diff -Nru wine-development-5.8/dlls/kernel32/tests/locale.c wine-development-5.9/dlls/kernel32/tests/locale.c --- wine-development-5.8/dlls/kernel32/tests/locale.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/tests/locale.c 2020-05-22 18:49:34.000000000 +0000 @@ -93,6 +93,9 @@ static NTSTATUS (WINAPI *pNtGetNlsSectionPtr)(ULONG,ULONG,void*,void**,SIZE_T*); static void (WINAPI *pRtlInitCodePageTable)(USHORT*,CPTABLEINFO*); static NTSTATUS (WINAPI *pRtlCustomCPToUnicodeN)(CPTABLEINFO*,WCHAR*,DWORD,DWORD*,const char*,DWORD); +static NTSTATUS (WINAPI *pRtlGetSystemPreferredUILanguages)(DWORD,ULONG,ULONG*,WCHAR*,ULONG*); +static NTSTATUS (WINAPI *pRtlGetThreadPreferredUILanguages)(DWORD,ULONG*,WCHAR*,ULONG*); +static NTSTATUS (WINAPI *pRtlGetUserPreferredUILanguages)(DWORD,ULONG,ULONG*,WCHAR*,ULONG*); static void InitFunctionPointers(void) { @@ -140,6 +143,9 @@ X(NtGetNlsSectionPtr); X(RtlInitCodePageTable); X(RtlCustomCPToUnicodeN); + X(RtlGetSystemPreferredUILanguages); + X(RtlGetThreadPreferredUILanguages); + X(RtlGetUserPreferredUILanguages); #undef X } @@ -5328,10 +5334,10 @@ static void test_GetSystemPreferredUILanguages(void) { BOOL ret; + NTSTATUS status; ULONG count, size, size_id, size_name, size_buffer; WCHAR *buffer; - if (!pGetSystemPreferredUILanguages) { win_skip("GetSystemPreferredUILanguages is not available.\n"); @@ -5482,12 +5488,45 @@ "Expected last two WCHARs being empty, got 0x%x 0x%x\n", buffer[size -2], buffer[size -1]); + /* ntdll version is the same, but apparently takes an extra second parameter */ + count = 0; + size = size_buffer; + memset(buffer, 0x5a, size_buffer * sizeof(WCHAR)); + status = pRtlGetSystemPreferredUILanguages(MUI_LANGUAGE_ID, 0, &count, buffer, &size); + ok(!status, "got %x\n", status); + ok(count, "Expected count > 0\n"); + ok(size % 5 == 1, "Expected size (%d) %% 5 == 1\n", size); + if (ret && size % 5 == 1) + ok(!buffer[size -2] && !buffer[size -1], + "Expected last two WCHARs being empty, got 0x%x 0x%x\n", + buffer[size -2], buffer[size -1]); + + count = 0; + size = size_buffer; + status = pRtlGetSystemPreferredUILanguages(MUI_LANGUAGE_NAME, 0, &count, buffer, &size); + ok(!status, "got %x\n", status); + ok(count, "Expected count > 0\n"); + ok(size % 6 == 1, "Expected size (%d) %% 6 == 1\n", size); + if (ret && size % 5 == 1) + ok(!buffer[size -2] && !buffer[size -1], + "Expected last two WCHARs being empty, got 0x%x 0x%x\n", + buffer[size -2], buffer[size -1]); + + count = 0; + size = 0; + status = pRtlGetSystemPreferredUILanguages(MUI_MACHINE_LANGUAGE_SETTINGS, 0, &count, NULL, &size); + ok(!status, "got %x\n", status); + ok(count, "Expected count > 0\n"); + ok(size % 6 == 1, "Expected size (%d) %% 6 == 1\n", size); + if (ret && size % 6 == 1) + ok(!buffer[size -2] && !buffer[size -1], + "Expected last two WCHARs being empty, got 0x%x 0x%x\n", + buffer[size -2], buffer[size -1]); + size = 0; SetLastError(0xdeadbeef); ret = pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID, &count, buffer, &size); -todo_wine ok(!ret, "Expected GetSystemPreferredUILanguages to fail\n"); -todo_wine ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(size == size_id, "expected %u, got %u\n", size_id, size); @@ -5524,6 +5563,7 @@ static void test_GetThreadPreferredUILanguages(void) { BOOL ret; + NTSTATUS status; ULONG count, size, size_id; WCHAR *buf; @@ -5552,12 +5592,18 @@ ok(size_id, "expected size > 0\n"); ok(size_id <= size, "expected size > 0\n"); + /* ntdll function is the same */ + size_id = count = 0; + status = pRtlGetThreadPreferredUILanguages(MUI_LANGUAGE_ID, &count, NULL, &size_id); + ok(!status, "got %x\n", status); + ok(count, "expected count > 0\n"); + ok(size_id, "expected size > 0\n"); + ok(size_id <= size, "expected size > 0\n"); + size = 0; SetLastError(0xdeadbeef); ret = pGetThreadPreferredUILanguages(MUI_LANGUAGE_ID, &count, buf, &size); -todo_wine ok(!ret, "Expected GetThreadPreferredUILanguages to fail\n"); -todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); ok(size == size_id, "expected %u, got %u\n", size_id, size); @@ -5593,6 +5639,7 @@ static void test_GetUserPreferredUILanguages(void) { BOOL ret; + NTSTATUS status; ULONG count, size, size_id, size_name, size_buffer; WCHAR *buffer; @@ -5653,6 +5700,15 @@ return; } + /* ntdll version is the same, but apparently takes an extra second parameter */ + count = 0; + size_id = 0; + SetLastError(0xdeadbeef); + status = pRtlGetUserPreferredUILanguages(MUI_LANGUAGE_ID, 0, &count, NULL, &size_id); + ok(!status, "got %x\n", status); + ok(count, "Expected count > 0\n"); + ok(size_id % 5 == 1, "Expected size (%d) %% 5 == 1\n", size_id); + buffer = HeapAlloc(GetProcessHeap(), 0, size_buffer * sizeof(WCHAR)); count = 0; diff -Nru wine-development-5.8/dlls/kernel32/time.c wine-development-5.9/dlls/kernel32/time.c --- wine-development-5.8/dlls/kernel32/time.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernel32/time.c 2020-05-22 18:49:34.000000000 +0000 @@ -38,9 +38,6 @@ #elif defined(HAVE_MACHINE_LIMITS_H) #include #endif -#ifdef __APPLE__ -# include -#endif #include "ntstatus.h" #define WIN32_NO_STATUS @@ -49,154 +46,15 @@ #include "winbase.h" #include "winreg.h" #include "winternl.h" +#include "ddk/wdm.h" #include "kernel_private.h" #include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(time); -static inline void longlong_to_filetime( LONGLONG t, FILETIME *ft ) -{ - ft->dwLowDateTime = (DWORD)t; - ft->dwHighDateTime = (DWORD)(t >> 32); -} - -#define TICKSPERSEC 10000000 -#define TICKSPERMSEC 10000 - -/* return a monotonic time counter, in Win32 ticks */ -static inline ULONGLONG monotonic_counter(void) -{ - LARGE_INTEGER counter; - -#ifdef __APPLE__ - static mach_timebase_info_data_t timebase; - - if (!timebase.denom) mach_timebase_info( &timebase ); -#ifdef HAVE_MACH_CONTINUOUS_TIME - if (&mach_continuous_time != NULL) - return mach_continuous_time() * timebase.numer / timebase.denom / 100; -#endif - return mach_absolute_time() * timebase.numer / timebase.denom / 100; -#elif defined(HAVE_CLOCK_GETTIME) - struct timespec ts; -#ifdef CLOCK_MONOTONIC_RAW - if (!clock_gettime( CLOCK_MONOTONIC_RAW, &ts )) - return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; -#endif - if (!clock_gettime( CLOCK_MONOTONIC, &ts )) - return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; -#endif - - NtQueryPerformanceCounter( &counter, NULL ); - return counter.QuadPart; -} - - -/*********************************************************************** - * GetSystemTimeAdjustment (KERNEL32.@) - * - * Get the period between clock interrupts and the amount the clock - * is adjusted each interrupt so as to keep it in sync with an external source. - * - * PARAMS - * lpTimeAdjustment [out] The clock adjustment per interrupt in 100's of nanoseconds. - * lpTimeIncrement [out] The time between clock interrupts in 100's of nanoseconds. - * lpTimeAdjustmentDisabled [out] The clock synchronisation has been disabled. - * - * RETURNS - * TRUE. - * - * BUGS - * Only the special case of disabled time adjustments is supported. - */ -BOOL WINAPI GetSystemTimeAdjustment( PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement, - PBOOL lpTimeAdjustmentDisabled ) -{ - *lpTimeAdjustment = 0; - *lpTimeIncrement = 10000000 / sysconf(_SC_CLK_TCK); - *lpTimeAdjustmentDisabled = TRUE; - return TRUE; -} - - -/*********************************************************************** - * SetSystemTimeAdjustment (KERNEL32.@) - * - * Enables or disables the timing adjustments to the system's clock. - * - * PARAMS - * dwTimeAdjustment [in] Number of units to add per clock interrupt. - * bTimeAdjustmentDisabled [in] Adjustment mode. - * - * RETURNS - * Success: TRUE. - * Failure: FALSE. - */ -BOOL WINAPI SetSystemTimeAdjustment( DWORD dwTimeAdjustment, BOOL bTimeAdjustmentDisabled ) -{ - /* Fake function for now... */ - FIXME("(%08x,%d): stub !\n", dwTimeAdjustment, bTimeAdjustmentDisabled); - return TRUE; -} - -/********************************************************************* - * TIME_ClockTimeToFileTime (olorin@fandra.org, 20-Sep-1998) - * - * Used by GetProcessTimes to convert clock_t into FILETIME. - * - * Differences to UnixTimeToFileTime: - * 1) Divided by CLK_TCK - * 2) Time is relative. There is no 'starting date', so there is - * no need for offset correction, like in UnixTimeToFileTime - */ -static void TIME_ClockTimeToFileTime(clock_t unix_time, LPFILETIME filetime) -{ - long clocksPerSec = sysconf(_SC_CLK_TCK); - ULONGLONG secs = (ULONGLONG)unix_time * 10000000 / clocksPerSec; - filetime->dwLowDateTime = (DWORD)secs; - filetime->dwHighDateTime = (DWORD)(secs >> 32); -} - -/********************************************************************* - * GetProcessTimes (KERNEL32.@) - * - * Get the user and kernel execution times of a process, - * along with the creation and exit times if known. - * - * PARAMS - * hprocess [in] The process to be queried. - * lpCreationTime [out] The creation time of the process. - * lpExitTime [out] The exit time of the process if exited. - * lpKernelTime [out] The time spent in kernel routines in 100's of nanoseconds. - * lpUserTime [out] The time spent in user routines in 100's of nanoseconds. - * - * RETURNS - * TRUE. - * - * NOTES - * olorin@fandra.org: - * Would be nice to subtract the cpu time used by Wine at startup. - * Also, there is a need to separate times used by different applications. - * - * BUGS - * KernelTime and UserTime are always for the current process - */ -BOOL WINAPI GetProcessTimes( HANDLE hprocess, LPFILETIME lpCreationTime, - LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime ) -{ - struct tms tms; - KERNEL_USER_TIMES pti; +static const struct _KUSER_SHARED_DATA *user_shared_data = (struct _KUSER_SHARED_DATA *)0x7ffe0000; - times(&tms); - TIME_ClockTimeToFileTime(tms.tms_utime,lpUserTime); - TIME_ClockTimeToFileTime(tms.tms_stime,lpKernelTime); - if (NtQueryInformationProcess( hprocess, ProcessTimes, &pti, sizeof(pti), NULL)) - return FALSE; - longlong_to_filetime( pti.CreateTime.QuadPart, lpCreationTime ); - longlong_to_filetime( pti.ExitTime.QuadPart, lpExitTime ); - return TRUE; -} /********************************************************************* * GetCalendarInfoA (KERNEL32.@) @@ -318,100 +176,28 @@ return TRUE; } -/********************************************************************* - * GetSystemTimes (KERNEL32.@) - * - * Retrieves system timing information - * - * PARAMS - * lpIdleTime [O] Destination for idle time. - * lpKernelTime [O] Destination for kernel time. - * lpUserTime [O] Destination for user time. - * - * RETURNS - * TRUE if success, FALSE otherwise. - */ -BOOL WINAPI GetSystemTimes(LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime) -{ - LARGE_INTEGER idle_time, kernel_time, user_time; - SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi; - SYSTEM_BASIC_INFORMATION sbi; - ULONG ret_size; - int i; - - TRACE("(%p,%p,%p)\n", lpIdleTime, lpKernelTime, lpUserTime); - - if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation, &sbi, sizeof(sbi), &ret_size ))) - return FALSE; - - sppi = HeapAlloc( GetProcessHeap(), 0, - sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * sbi.NumberOfProcessors); - if (!sppi) - { - SetLastError( ERROR_OUTOFMEMORY ); - return FALSE; - } - - if (!set_ntstatus( NtQuerySystemInformation( SystemProcessorPerformanceInformation, sppi, - sizeof(*sppi) * sbi.NumberOfProcessors, &ret_size ))) - { - HeapFree( GetProcessHeap(), 0, sppi ); - return FALSE; - } - - idle_time.QuadPart = 0; - kernel_time.QuadPart = 0; - user_time.QuadPart = 0; - for (i = 0; i < sbi.NumberOfProcessors; i++) - { - idle_time.QuadPart += sppi[i].IdleTime.QuadPart; - kernel_time.QuadPart += sppi[i].KernelTime.QuadPart; - user_time.QuadPart += sppi[i].UserTime.QuadPart; - } - - if (lpIdleTime) - { - lpIdleTime->dwLowDateTime = idle_time.u.LowPart; - lpIdleTime->dwHighDateTime = idle_time.u.HighPart; - } - if (lpKernelTime) - { - lpKernelTime->dwLowDateTime = kernel_time.u.LowPart; - lpKernelTime->dwHighDateTime = kernel_time.u.HighPart; - } - if (lpUserTime) - { - lpUserTime->dwLowDateTime = user_time.u.LowPart; - lpUserTime->dwHighDateTime = user_time.u.HighPart; - } - - HeapFree( GetProcessHeap(), 0, sppi ); - return TRUE; -} - /****************************************************************************** * GetTickCount64 (KERNEL32.@) */ ULONGLONG WINAPI DECLSPEC_HOTPATCH GetTickCount64(void) { - return monotonic_counter() / TICKSPERMSEC; + ULONG high, low; + + do + { + high = user_shared_data->u.TickCount.High1Time; + low = user_shared_data->u.TickCount.LowPart; + } + while (high != user_shared_data->u.TickCount.High2Time); + /* note: we ignore TickCountMultiplier */ + return (ULONGLONG)high << 32 | low; } /*********************************************************************** * GetTickCount (KERNEL32.@) - * - * Get the number of milliseconds the system has been running. - * - * PARAMS - * None. - * - * RETURNS - * The current tick count. - * - * NOTES - * The value returned will wrap around every 2^32 milliseconds. */ DWORD WINAPI DECLSPEC_HOTPATCH GetTickCount(void) { - return monotonic_counter() / TICKSPERMSEC; + /* note: we ignore TickCountMultiplier */ + return user_shared_data->u.TickCount.LowPart; } diff -Nru wine-development-5.8/dlls/kernelbase/file.c wine-development-5.9/dlls/kernelbase/file.c --- wine-development-5.8/dlls/kernelbase/file.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernelbase/file.c 2020-05-22 18:49:34.000000000 +0000 @@ -3862,6 +3862,23 @@ /*********************************************************************** + * GetSystemTimeAdjustment (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetSystemTimeAdjustment( DWORD *adjust, DWORD *increment, BOOL *disabled ) +{ + SYSTEM_TIME_ADJUSTMENT_QUERY st; + ULONG len; + + if (!set_ntstatus( NtQuerySystemInformation( SystemTimeAdjustmentInformation, &st, sizeof(st), &len ))) + return FALSE; + *adjust = st.TimeAdjustment; + *increment = st.TimeIncrement; + *disabled = st.TimeAdjustmentDisabled; + return TRUE; +} + + +/*********************************************************************** * GetSystemTimeAsFileTime (kernelbase.@) */ void WINAPI DECLSPEC_HOTPATCH GetSystemTimeAsFileTime( FILETIME *time ) @@ -3918,6 +3935,19 @@ } +/*********************************************************************** + * SetSystemTimeAdjustment (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH SetSystemTimeAdjustment( DWORD adjust, BOOL disabled ) +{ + SYSTEM_TIME_ADJUSTMENT st; + + st.TimeAdjustment = adjust; + st.TimeAdjustmentDisabled = disabled; + return set_ntstatus( NtSetSystemInformation( SystemTimeAdjustmentInformation, &st, sizeof(st) )); +} + + /********************************************************************* * SystemTimeToFileTime (kernelbase.@) */ diff -Nru wine-development-5.8/dlls/kernelbase/kernelbase.spec wine-development-5.9/dlls/kernelbase/kernelbase.spec --- wine-development-5.8/dlls/kernelbase/kernelbase.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernelbase/kernelbase.spec 2020-05-22 18:49:34.000000000 +0000 @@ -387,8 +387,8 @@ @ stdcall FoldStringW(long wstr long ptr long) # @ stub ForceSyncFgPolicyInternal # @ stub FormatApplicationUserModelId -@ stdcall FormatMessageA(long ptr long long ptr long ptr) kernel32.FormatMessageA -@ stdcall FormatMessageW(long ptr long long ptr long ptr) kernel32.FormatMessageW +@ stdcall FormatMessageA(long ptr long long ptr long ptr) +@ stdcall FormatMessageW(long ptr long long ptr long ptr) @ stdcall FreeConsole() @ stdcall FreeEnvironmentStringsA(ptr) FreeEnvironmentStringsW @ stdcall FreeEnvironmentStringsW(ptr) @@ -632,10 +632,10 @@ # @ stub GetProcessInformation # @ stub GetProcessMemoryInfo @ stdcall GetProcessMitigationPolicy(long long ptr long) -@ stdcall GetProcessPreferredUILanguages(long ptr ptr ptr) kernel32.GetProcessPreferredUILanguages +@ stdcall GetProcessPreferredUILanguages(long ptr ptr ptr) @ stdcall GetProcessPriorityBoost(long ptr) @ stdcall GetProcessShutdownParameters(ptr ptr) -@ stdcall GetProcessTimes(long ptr ptr ptr ptr) kernel32.GetProcessTimes +@ stdcall GetProcessTimes(long ptr ptr ptr ptr) @ stdcall GetProcessVersion(long) kernel32.GetProcessVersion @ stdcall GetProcessWorkingSetSizeEx(long ptr ptr ptr) # @ stub GetProcessorSystemCycleTime @@ -692,13 +692,13 @@ # @ stub GetSystemMetadataPath # @ stub GetSystemMetadataPathForPackage # @ stub GetSystemMetadataPathForPackageFamily -@ stdcall GetSystemPreferredUILanguages(long ptr ptr ptr) kernel32.GetSystemPreferredUILanguages +@ stdcall GetSystemPreferredUILanguages(long ptr ptr ptr) # @ stub GetSystemStateRootFolder @ stdcall GetSystemTime(ptr) -@ stdcall GetSystemTimeAdjustment(ptr ptr ptr) kernel32.GetSystemTimeAdjustment +@ stdcall GetSystemTimeAdjustment(ptr ptr ptr) @ stdcall GetSystemTimeAsFileTime(ptr) @ stdcall GetSystemTimePreciseAsFileTime(ptr) -@ stdcall GetSystemTimes(ptr ptr ptr) kernel32.GetSystemTimes +@ stdcall GetSystemTimes(ptr ptr ptr) @ stdcall GetSystemWindowsDirectoryA(ptr long) @ stdcall GetSystemWindowsDirectoryW(ptr long) @ stdcall GetSystemWow64Directory2A(ptr long long) @@ -719,14 +719,14 @@ @ stdcall GetThreadIdealProcessorEx(long ptr) # @ stub GetThreadInformation @ stdcall GetThreadLocale() -@ stdcall GetThreadPreferredUILanguages(long ptr ptr ptr) kernel32.GetThreadPreferredUILanguages +@ stdcall GetThreadPreferredUILanguages(long ptr ptr ptr) @ stdcall GetThreadPriority(long) @ stdcall GetThreadPriorityBoost(long ptr) # @ stub GetThreadSelectedCpuSets @ stdcall GetThreadTimes(long ptr ptr ptr ptr) @ stdcall GetThreadUILanguage() -@ stdcall GetTickCount() kernel32.GetTickCount -@ stdcall -ret64 GetTickCount64() kernel32.GetTickCount64 +@ stdcall GetTickCount() +@ stdcall -ret64 GetTickCount64() @ stdcall GetTimeFormatA(long long ptr str ptr long) kernel32.GetTimeFormatA @ stdcall GetTimeFormatEx(wstr long ptr wstr ptr long) kernel32.GetTimeFormatEx @ stdcall GetTimeFormatW(long long ptr wstr ptr long) kernel32.GetTimeFormatW @@ -748,7 +748,7 @@ @ stub GetUserInfoWord # @ stub GetUserOverrideString # @ stub GetUserOverrideWord -@ stdcall GetUserPreferredUILanguages(long ptr ptr ptr) kernel32.GetUserPreferredUILanguages +@ stdcall GetUserPreferredUILanguages(long ptr ptr ptr) @ stdcall GetVersion() @ stdcall GetVersionExA(ptr) @ stdcall GetVersionExW(ptr) @@ -1458,7 +1458,7 @@ # @ stub SetProcessGroupAffinity # @ stub SetProcessInformation @ stdcall SetProcessMitigationPolicy(long ptr long) -@ stdcall SetProcessPreferredUILanguages(long ptr ptr) kernel32.SetProcessPreferredUILanguages +@ stdcall SetProcessPreferredUILanguages(long ptr ptr) @ stdcall SetProcessPriorityBoost(long long) @ stdcall SetProcessShutdownParameters(long long) # @ stub SetProcessValidCallTargets @@ -1477,7 +1477,7 @@ @ stdcall SetStdHandleEx(long long ptr) @ stdcall SetSystemFileCacheSize(long long long) @ stdcall SetSystemTime(ptr) -@ stdcall SetSystemTimeAdjustment(long long) kernel32.SetSystemTimeAdjustment +@ stdcall SetSystemTimeAdjustment(long long) @ stdcall SetThreadContext(long ptr) @ stdcall SetThreadDescription(ptr wstr) @ stdcall SetThreadErrorMode(long ptr) @@ -1486,7 +1486,7 @@ @ stdcall SetThreadIdealProcessorEx(long ptr ptr) # @ stub SetThreadInformation @ stdcall SetThreadLocale(long) -@ stdcall SetThreadPreferredUILanguages(long ptr ptr) kernel32.SetThreadPreferredUILanguages +@ stdcall SetThreadPreferredUILanguages(long ptr ptr) @ stdcall SetThreadPriority(long long) @ stdcall SetThreadPriorityBoost(long long) # @ stub SetThreadSelectedCpuSets diff -Nru wine-development-5.8/dlls/kernelbase/locale.c wine-development-5.9/dlls/kernelbase/locale.c --- wine-development-5.8/dlls/kernelbase/locale.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernelbase/locale.c 2020-05-22 18:49:34.000000000 +0000 @@ -3639,6 +3639,197 @@ } +static const WCHAR *get_message( DWORD flags, const void *src, UINT id, UINT lang, + BOOL ansi, WCHAR **buffer ) +{ + DWORD len; + + if (!(flags & FORMAT_MESSAGE_FROM_STRING)) + { + const MESSAGE_RESOURCE_ENTRY *entry; + NTSTATUS status = STATUS_INVALID_PARAMETER; + + if (flags & FORMAT_MESSAGE_FROM_HMODULE) + { + HMODULE module = (HMODULE)src; + if (!module) module = GetModuleHandleW( 0 ); + status = RtlFindMessage( module, RT_MESSAGETABLE, lang, id, &entry ); + } + if (status && (flags & FORMAT_MESSAGE_FROM_SYSTEM)) + { + /* Fold win32 hresult to its embedded error code. */ + if (HRESULT_SEVERITY(id) == SEVERITY_ERROR && HRESULT_FACILITY(id) == FACILITY_WIN32) + id = HRESULT_CODE( id ); + status = RtlFindMessage( kernel32_handle, RT_MESSAGETABLE, lang, id, &entry ); + } + if (!set_ntstatus( status )) return NULL; + + src = entry->Text; + ansi = !(entry->Flags & MESSAGE_RESOURCE_UNICODE); + } + + if (!ansi) return src; + len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 ); + if (!(*buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL; + MultiByteToWideChar( CP_ACP, 0, src, -1, *buffer, len ); + return *buffer; +} + + +/*********************************************************************** + * FormatMessageA (kernelbase.@) + */ +DWORD WINAPI DECLSPEC_HOTPATCH FormatMessageA( DWORD flags, const void *source, DWORD msgid, DWORD langid, + char *buffer, DWORD size, __ms_va_list *args ) +{ + DWORD ret = 0; + ULONG len, retsize = 0; + ULONG width = (flags & FORMAT_MESSAGE_MAX_WIDTH_MASK); + const WCHAR *src; + WCHAR *result, *message = NULL; + NTSTATUS status; + + TRACE( "(0x%x,%p,%d,0x%x,%p,%d,%p)\n", flags, source, msgid, langid, buffer, size, args ); + + if (flags & FORMAT_MESSAGE_ALLOCATE_BUFFER) + { + if (!buffer) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return 0; + } + *(char **)buffer = NULL; + } + if (size >= 32768) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + if (width == 0xff) width = ~0u; + + if (!(src = get_message( flags, source, msgid, langid, TRUE, &message ))) return 0; + + if (!(result = HeapAlloc( GetProcessHeap(), 0, 65536 ))) + status = STATUS_NO_MEMORY; + else + status = RtlFormatMessage( src, width, !!(flags & FORMAT_MESSAGE_IGNORE_INSERTS), + TRUE, !!(flags & FORMAT_MESSAGE_ARGUMENT_ARRAY), args, + result, 65536, &retsize ); + + HeapFree( GetProcessHeap(), 0, message ); + + if (status == STATUS_BUFFER_OVERFLOW) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + goto done; + } + if (!set_ntstatus( status )) goto done; + + len = WideCharToMultiByte( CP_ACP, 0, result, retsize / sizeof(WCHAR), NULL, 0, NULL, NULL ); + if (len <= 1) + { + SetLastError( ERROR_NO_WORK_DONE ); + goto done; + } + + if (flags & FORMAT_MESSAGE_ALLOCATE_BUFFER) + { + char *buf = LocalAlloc( LMEM_ZEROINIT, max( size, len )); + if (!buf) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + goto done; + } + *(char **)buffer = buf; + WideCharToMultiByte( CP_ACP, 0, result, retsize / sizeof(WCHAR), buf, max( size, len ), NULL, NULL ); + } + else if (len > size) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + goto done; + } + else WideCharToMultiByte( CP_ACP, 0, result, retsize / sizeof(WCHAR), buffer, size, NULL, NULL ); + + ret = len - 1; + +done: + HeapFree( GetProcessHeap(), 0, result ); + return ret; +} + + +/*********************************************************************** + * FormatMessageW (kernelbase.@) + */ +DWORD WINAPI DECLSPEC_HOTPATCH FormatMessageW( DWORD flags, const void *source, DWORD msgid, DWORD langid, + WCHAR *buffer, DWORD size, __ms_va_list *args ) +{ + ULONG retsize = 0; + ULONG width = (flags & FORMAT_MESSAGE_MAX_WIDTH_MASK); + const WCHAR *src; + WCHAR *message = NULL; + NTSTATUS status; + + TRACE( "(0x%x,%p,%d,0x%x,%p,%d,%p)\n", flags, source, msgid, langid, buffer, size, args ); + + if (!buffer) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + if (width == 0xff) width = ~0u; + + if (flags & FORMAT_MESSAGE_ALLOCATE_BUFFER) *(LPWSTR *)buffer = NULL; + + if (!(src = get_message( flags, source, msgid, langid, FALSE, &message ))) return 0; + + if (flags & FORMAT_MESSAGE_ALLOCATE_BUFFER) + { + WCHAR *result; + ULONG alloc = max( size * sizeof(WCHAR), 65536 ); + + for (;;) + { + if (!(result = HeapAlloc( GetProcessHeap(), 0, alloc ))) + { + status = STATUS_NO_MEMORY; + break; + } + status = RtlFormatMessage( src, width, !!(flags & FORMAT_MESSAGE_IGNORE_INSERTS), + FALSE, !!(flags & FORMAT_MESSAGE_ARGUMENT_ARRAY), args, + result, alloc, &retsize ); + if (!status) + { + if (retsize <= sizeof(WCHAR)) HeapFree( GetProcessHeap(), 0, result ); + else *(WCHAR **)buffer = HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, + result, max( retsize, size * sizeof(WCHAR) )); + break; + } + HeapFree( GetProcessHeap(), 0, result ); + if (status != STATUS_BUFFER_OVERFLOW) break; + alloc *= 2; + } + } + else status = RtlFormatMessage( src, width, !!(flags & FORMAT_MESSAGE_IGNORE_INSERTS), + FALSE, !!(flags & FORMAT_MESSAGE_ARGUMENT_ARRAY), args, + buffer, size * sizeof(WCHAR), &retsize ); + + HeapFree( GetProcessHeap(), 0, message ); + + if (status == STATUS_BUFFER_OVERFLOW) + { + if (size) buffer[size - 1] = 0; + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return 0; + } + if (!set_ntstatus( status )) return 0; + if (retsize <= sizeof(WCHAR)) SetLastError( ERROR_NO_WORK_DONE ); + return retsize / sizeof(WCHAR) - 1; +} + + /****************************************************************************** * GetACP (kernelbase.@) */ @@ -4351,6 +4542,16 @@ /*********************************************************************** + * GetProcessPreferredUILanguages (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetProcessPreferredUILanguages( DWORD flags, ULONG *count, + WCHAR *buffer, ULONG *size ) +{ + return set_ntstatus( RtlGetProcessPreferredUILanguages( flags, count, buffer, size )); +} + + +/*********************************************************************** * GetStringTypeA (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH GetStringTypeA( LCID locale, DWORD type, const char *src, int count, @@ -4456,6 +4657,26 @@ /*********************************************************************** + * GetSystemPreferredUILanguages (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetSystemPreferredUILanguages( DWORD flags, ULONG *count, + WCHAR *buffer, ULONG *size ) +{ + return set_ntstatus( RtlGetSystemPreferredUILanguages( flags, 0, count, buffer, size )); +} + + +/*********************************************************************** + * GetThreadPreferredUILanguages (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetThreadPreferredUILanguages( DWORD flags, ULONG *count, + WCHAR *buffer, ULONG *size ) +{ + return set_ntstatus( RtlGetThreadPreferredUILanguages( flags, count, buffer, size )); +} + + +/*********************************************************************** * GetTimeZoneInformation (kernelbase.@) */ DWORD WINAPI DECLSPEC_HOTPATCH GetTimeZoneInformation( TIME_ZONE_INFORMATION *info ) @@ -4618,6 +4839,16 @@ /****************************************************************************** + * GetUserPreferredUILanguages (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetUserPreferredUILanguages( DWORD flags, ULONG *count, + WCHAR *buffer, ULONG *size ) +{ + return set_ntstatus( RtlGetUserPreferredUILanguages( flags, 0, count, buffer, size )); +} + + +/****************************************************************************** * IdnToAscii (kernelbase.@) */ INT WINAPI DECLSPEC_HOTPATCH IdnToAscii( DWORD flags, const WCHAR *src, INT srclen, @@ -5393,6 +5624,24 @@ } +/*********************************************************************** + * SetProcessPreferredUILanguages (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH SetProcessPreferredUILanguages( DWORD flags, PCZZWSTR buffer, ULONG *count ) +{ + return set_ntstatus( RtlSetProcessPreferredUILanguages( flags, buffer, count )); +} + + +/*********************************************************************** + * SetThreadPreferredUILanguages (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH SetThreadPreferredUILanguages( DWORD flags, PCZZWSTR buffer, ULONG *count ) +{ + return set_ntstatus( RtlSetThreadPreferredUILanguages( flags, buffer, count )); +} + + /*********************************************************************** * SetTimeZoneInformation (kernelbase.@) */ diff -Nru wine-development-5.8/dlls/kernelbase/main.c wine-development-5.9/dlls/kernelbase/main.c --- wine-development-5.8/dlls/kernelbase/main.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernelbase/main.c 2020-05-22 18:49:34.000000000 +0000 @@ -200,21 +200,6 @@ return FALSE; } -/*********************************************************************** - * WaitOnAddress (KERNELBASE.@) - */ -BOOL WINAPI WaitOnAddress(volatile void *addr, void *cmp, SIZE_T size, DWORD timeout) -{ - LARGE_INTEGER to; - - if (timeout != INFINITE) - { - to.QuadPart = -(LONGLONG)timeout * 10000; - return set_ntstatus( RtlWaitOnAddress( (const void *)addr, cmp, size, &to )); - } - return set_ntstatus( RtlWaitOnAddress( (const void *)addr, cmp, size, NULL )); -} - HRESULT WINAPI QISearch(void *base, const QITAB *table, REFIID riid, void **obj) { const QITAB *ptr; diff -Nru wine-development-5.8/dlls/kernelbase/path.c wine-development-5.9/dlls/kernelbase/path.c --- wine-development-5.8/dlls/kernelbase/path.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernelbase/path.c 2020-05-22 18:49:34.000000000 +0000 @@ -3521,7 +3521,7 @@ TRACE("%s, %p, %p, %#x\n", wine_dbgstr_w(src_url), canonicalized, canonicalized_len, flags); - if (!src_url || !canonicalized || !canonicalized || !*canonicalized_len) + if (!src_url || !canonicalized || !canonicalized_len || !*canonicalized_len) return E_INVALIDARG; if (!*src_url) diff -Nru wine-development-5.8/dlls/kernelbase/process.c wine-development-5.9/dlls/kernelbase/process.c --- wine-development-5.8/dlls/kernelbase/process.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernelbase/process.c 2020-05-22 18:49:34.000000000 +0000 @@ -791,6 +791,29 @@ } +/********************************************************************* + * GetProcessTimes (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetProcessTimes( HANDLE process, FILETIME *create, FILETIME *exit, + FILETIME *kernel, FILETIME *user ) +{ + KERNEL_USER_TIMES time; + + if (!set_ntstatus( NtQueryInformationProcess( process, ProcessTimes, &time, sizeof(time), NULL ))) + return FALSE; + + create->dwLowDateTime = time.CreateTime.u.LowPart; + create->dwHighDateTime = time.CreateTime.u.HighPart; + exit->dwLowDateTime = time.ExitTime.u.LowPart; + exit->dwHighDateTime = time.ExitTime.u.HighPart; + kernel->dwLowDateTime = time.KernelTime.u.LowPart; + kernel->dwHighDateTime = time.KernelTime.u.HighPart; + user->dwLowDateTime = time.UserTime.u.LowPart; + user->dwHighDateTime = time.UserTime.u.HighPart; + return TRUE; +} + + /*********************************************************************** * GetProcessWorkingSetSizeEx (kernelbase.@) */ @@ -1345,24 +1368,32 @@ */ DWORD WINAPI DECLSPEC_HOTPATCH GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size ) { - UNICODE_STRING us_name; + UNICODE_STRING us_name, us_value; PWSTR valueW; - DWORD ret; + NTSTATUS status; + DWORD len, ret; /* limit the size to sane values */ size = min( size, 32767 ); if (!(valueW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return 0; RtlCreateUnicodeStringFromAsciiz( &us_name, name ); - SetLastError( 0 ); - ret = GetEnvironmentVariableW( us_name.Buffer, valueW, size); - if (ret && ret < size) WideCharToMultiByte( CP_ACP, 0, valueW, ret + 1, value, size, NULL, NULL ); - - /* this is needed to tell, with 0 as a return value, the difference between: - * - an error (GetLastError() != 0) - * - returning an empty string (in this case, we need to update the buffer) - */ - if (ret == 0 && size && GetLastError() == 0) value[0] = 0; + us_value.Length = 0; + us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR); + us_value.Buffer = valueW; + + status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value ); + len = us_value.Length / sizeof(WCHAR); + if (status == STATUS_BUFFER_TOO_SMALL) ret = len + 1; + else if (!set_ntstatus( status )) ret = 0; + else if (!size) ret = len + 1; + else + { + if (len) WideCharToMultiByte( CP_ACP, 0, valueW, len + 1, value, size, NULL, NULL ); + value[len] = 0; + ret = len; + } + RtlFreeUnicodeString( &us_name ); HeapFree( GetProcessHeap(), 0, valueW ); return ret; @@ -1387,8 +1418,10 @@ status = RtlQueryEnvironmentVariable_U( NULL, &us_name, &us_value ); len = us_value.Length / sizeof(WCHAR); - if (!set_ntstatus( status )) return (status == STATUS_BUFFER_TOO_SMALL) ? len + 1 : 0; - if (size) val[len] = 0; + if (status == STATUS_BUFFER_TOO_SMALL) return len + 1; + if (!set_ntstatus( status )) return 0; + if (!size) return len + 1; + val[len] = 0; return len; } diff -Nru wine-development-5.8/dlls/kernelbase/sync.c wine-development-5.9/dlls/kernelbase/sync.c --- wine-development-5.8/dlls/kernelbase/sync.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/kernelbase/sync.c 2020-05-22 18:49:34.000000000 +0000 @@ -42,6 +42,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync); +static const struct _KUSER_SHARED_DATA *user_shared_data = (struct _KUSER_SHARED_DATA *)0x7ffe0000; + /* check if current version is NT or Win95 */ static inline BOOL is_version_nt(void) { @@ -122,6 +124,89 @@ /*********************************************************************** + * Time functions + ***********************************************************************/ + + +/********************************************************************* + * GetSystemTimes (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetSystemTimes( FILETIME *idle, FILETIME *kernel, FILETIME *user ) +{ + LARGE_INTEGER idle_time, kernel_time, user_time; + SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *info; + ULONG ret_size; + DWORD i, cpus = NtCurrentTeb()->Peb->NumberOfProcessors; + + if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) * cpus ))) + { + SetLastError( ERROR_OUTOFMEMORY ); + return FALSE; + } + if (!set_ntstatus( NtQuerySystemInformation( SystemProcessorPerformanceInformation, info, + sizeof(*info) * cpus, &ret_size ))) + { + HeapFree( GetProcessHeap(), 0, info ); + return FALSE; + } + idle_time.QuadPart = 0; + kernel_time.QuadPart = 0; + user_time.QuadPart = 0; + for (i = 0; i < cpus; i++) + { + idle_time.QuadPart += info[i].IdleTime.QuadPart; + kernel_time.QuadPart += info[i].KernelTime.QuadPart; + user_time.QuadPart += info[i].UserTime.QuadPart; + } + if (idle) + { + idle->dwLowDateTime = idle_time.u.LowPart; + idle->dwHighDateTime = idle_time.u.HighPart; + } + if (kernel) + { + kernel->dwLowDateTime = kernel_time.u.LowPart; + kernel->dwHighDateTime = kernel_time.u.HighPart; + } + if (user) + { + user->dwLowDateTime = user_time.u.LowPart; + user->dwHighDateTime = user_time.u.HighPart; + } + HeapFree( GetProcessHeap(), 0, info ); + return TRUE; +} + + +/****************************************************************************** + * GetTickCount (kernelbase.@) + */ +ULONG WINAPI DECLSPEC_HOTPATCH GetTickCount(void) +{ + /* note: we ignore TickCountMultiplier */ + return user_shared_data->u.TickCount.LowPart; +} + + +/****************************************************************************** + * GetTickCount64 (kernelbase.@) + */ +ULONGLONG WINAPI DECLSPEC_HOTPATCH GetTickCount64(void) +{ + ULONG high, low; + + do + { + high = user_shared_data->u.TickCount.High1Time; + low = user_shared_data->u.TickCount.LowPart; + } + while (high != user_shared_data->u.TickCount.High2Time); + /* note: we ignore TickCountMultiplier */ + return (ULONGLONG)high << 32 | low; +} + + +/*********************************************************************** * Waits ***********************************************************************/ @@ -286,6 +371,22 @@ } +/*********************************************************************** + * WaitOnAddress (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH WaitOnAddress( volatile void *addr, void *cmp, SIZE_T size, DWORD timeout ) +{ + LARGE_INTEGER to; + + if (timeout != INFINITE) + { + to.QuadPart = -(LONGLONG)timeout * 10000; + return set_ntstatus( RtlWaitOnAddress( (const void *)addr, cmp, size, &to )); + } + return set_ntstatus( RtlWaitOnAddress( (const void *)addr, cmp, size, NULL )); +} + + /*********************************************************************** * Events ***********************************************************************/ diff -Nru wine-development-5.8/dlls/mf/samplegrabber.c wine-development-5.9/dlls/mf/samplegrabber.c --- wine-development-5.8/dlls/mf/samplegrabber.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mf/samplegrabber.c 2020-05-22 18:49:34.000000000 +0000 @@ -407,12 +407,11 @@ if (!sample) return S_OK; - if (grabber->is_shut_down) - return MF_E_STREAMSINK_REMOVED; - EnterCriticalSection(&grabber->cs); - if (grabber->state == SINK_STATE_RUNNING) + if (grabber->is_shut_down) + hr = MF_E_STREAMSINK_REMOVED; + else if (grabber->state == SINK_STATE_RUNNING) { hr = IMFSample_GetSampleTime(sample, &sampletime); @@ -479,12 +478,11 @@ TRACE("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value); - if (grabber->is_shut_down) - return MF_E_STREAMSINK_REMOVED; - EnterCriticalSection(&grabber->cs); - if (grabber->state == SINK_STATE_RUNNING) + if (grabber->is_shut_down) + hr = MF_E_STREAMSINK_REMOVED; + else if (grabber->state == SINK_STATE_RUNNING) hr = stream_place_marker(grabber, marker_type, context_value); LeaveCriticalSection(&grabber->cs); @@ -708,62 +706,41 @@ return E_NOTIMPL; } -static struct scheduled_item *stream_get_next_item(struct sample_grabber *grabber) -{ - struct scheduled_item *item = NULL; - struct list *e; - - if ((e = list_head(&grabber->items))) - item = LIST_ENTRY(e, struct scheduled_item, entry); - - return item; -} - static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct sample_grabber *grabber = impl_from_IMFAsyncCallback(iface); - struct scheduled_item *item; - BOOL sample_delivered; + BOOL sample_reported = FALSE, sample_delivered = FALSE; + struct scheduled_item *item, *item2; HRESULT hr; EnterCriticalSection(&grabber->cs); - /* Report and schedule next. */ - if (!grabber->is_shut_down && (item = stream_get_next_item(grabber))) + LIST_FOR_EACH_ENTRY_SAFE(item, item2, &grabber->items, struct scheduled_item, entry) { - while (item) + if (item->type == ITEM_TYPE_MARKER) + { + sample_grabber_stream_report_marker(grabber, &item->u.marker.context, S_OK); + stream_release_pending_item(item); + } + else if (item->type == ITEM_TYPE_SAMPLE) { - switch (item->type) + if (!sample_reported) { - case ITEM_TYPE_SAMPLE: - if (FAILED(hr = sample_grabber_report_sample(grabber, item->u.sample, &sample_delivered))) - WARN("Failed to report a sample, hr %#x.\n", hr); - stream_release_pending_item(item); - - /* Schedule next sample, skipping markers. */ - LIST_FOR_EACH_ENTRY(item, &grabber->items, struct scheduled_item, entry) - { - if (item->type == ITEM_TYPE_SAMPLE) - { - if (FAILED(hr = stream_schedule_sample(grabber, item))) - WARN("Failed to schedule a sample, hr %#x.\n", hr); - break; - } - } - - if (sample_delivered) - sample_grabber_stream_request_sample(grabber); - - item = NULL; - break; - case ITEM_TYPE_MARKER: - sample_grabber_stream_report_marker(grabber, &item->u.marker.context, S_OK); - stream_release_pending_item(item); - item = stream_get_next_item(grabber); - break; + if (FAILED(hr = sample_grabber_report_sample(grabber, item->u.sample, &sample_delivered))) + WARN("Failed to report a sample, hr %#x.\n", hr); + stream_release_pending_item(item); + sample_reported = TRUE; + } + else + { + if (FAILED(hr = stream_schedule_sample(grabber, item))) + WARN("Failed to schedule a sample, hr %#x.\n", hr); + break; } } } + if (sample_delivered) + sample_grabber_stream_request_sample(grabber); LeaveCriticalSection(&grabber->cs); @@ -820,11 +797,20 @@ return refcount; } +static void sample_grabber_release_pending_items(struct sample_grabber *grabber) +{ + struct scheduled_item *item, *next_item; + + LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &grabber->items, struct scheduled_item, entry) + { + stream_release_pending_item(item); + } +} + static ULONG WINAPI sample_grabber_sink_Release(IMFMediaSink *iface) { struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); ULONG refcount = InterlockedDecrement(&grabber->refcount); - struct scheduled_item *item, *next_item; TRACE("%p, refcount %u.\n", iface, refcount); @@ -854,10 +840,7 @@ } if (grabber->sample_attributes) IMFAttributes_Release(grabber->sample_attributes); - LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &grabber->items, struct scheduled_item, entry) - { - stream_release_pending_item(item); - } + sample_grabber_release_pending_items(grabber); DeleteCriticalSection(&grabber->cs); heap_free(grabber); } @@ -1049,6 +1032,7 @@ EnterCriticalSection(&grabber->cs); grabber->is_shut_down = TRUE; + sample_grabber_release_pending_items(grabber); if (SUCCEEDED(hr = IMFSampleGrabberSinkCallback_OnShutdown(sample_grabber_get_callback(grabber)))) { sample_grabber_set_presentation_clock(grabber, NULL); diff -Nru wine-development-5.8/dlls/mf/sar.c wine-development-5.9/dlls/mf/sar.c --- wine-development-5.8/dlls/mf/sar.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mf/sar.c 2020-05-22 18:49:34.000000000 +0000 @@ -28,6 +28,7 @@ #include "wine/debug.h" #include "wine/heap.h" +#include "wine/list.h" WINE_DEFAULT_DEBUG_CHANNEL(mfplat); @@ -38,6 +39,38 @@ STREAM_STATE_PAUSED, }; +enum audio_renderer_flags +{ + SAR_SHUT_DOWN = 0x1, + SAR_PREROLLED = 0x2, + SAR_SAMPLE_REQUESTED = 0x4, +}; + +enum queued_object_type +{ + OBJECT_TYPE_SAMPLE, + OBJECT_TYPE_MARKER, +}; + +struct queued_object +{ + struct list entry; + enum queued_object_type type; + union + { + struct + { + IMFSample *sample; + unsigned int frame_offset; + } sample; + struct + { + MFSTREAMSINK_MARKER_TYPE type; + PROPVARIANT context; + } marker; + } u; +}; + struct audio_renderer { IMFMediaSink IMFMediaSink_iface; @@ -50,6 +83,7 @@ IMFSimpleAudioVolume IMFSimpleAudioVolume_iface; IMFAudioStreamVolume IMFAudioStreamVolume_iface; IMFAudioPolicy IMFAudioPolicy_iface; + IMFAsyncCallback render_callback; LONG refcount; IMFMediaEventQueue *event_queue; IMFMediaEventQueue *stream_event_queue; @@ -58,14 +92,39 @@ IMFMediaType *current_media_type; IMMDevice *device; IAudioClient *audio_client; + IAudioRenderClient *audio_render_client; IAudioStreamVolume *stream_volume; ISimpleAudioVolume *audio_volume; + struct + { + unsigned int flags; + GUID session_id; + } stream_config; HANDLE buffer_ready_event; + MFWORKITEM_KEY buffer_ready_key; + unsigned int frame_size; + struct list queue; enum stream_state state; - BOOL is_shut_down; + unsigned int flags; CRITICAL_SECTION cs; }; +static void release_pending_object(struct queued_object *object) +{ + list_remove(&object->entry); + switch (object->type) + { + case OBJECT_TYPE_SAMPLE: + if (object->u.sample.sample) + IMFSample_Release(object->u.sample.sample); + break; + case OBJECT_TYPE_MARKER: + PropVariantClear(&object->u.marker.context); + break; + } + heap_free(object); +} + static struct audio_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface) { return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaSink_iface); @@ -116,6 +175,11 @@ return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaTypeHandler_iface); } +static struct audio_renderer *impl_from_render_callback_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct audio_renderer, render_callback); +} + static HRESULT WINAPI audio_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj) { struct audio_renderer *renderer = impl_from_IMFMediaSink(iface); @@ -165,21 +229,32 @@ static void audio_renderer_release_audio_client(struct audio_renderer *renderer) { + MFCancelWorkItem(renderer->buffer_ready_key); + renderer->buffer_ready_key = 0; if (renderer->audio_client) + { + IAudioClient_Stop(renderer->audio_client); + IAudioClient_Reset(renderer->audio_client); IAudioClient_Release(renderer->audio_client); + } renderer->audio_client = NULL; + if (renderer->audio_render_client) + IAudioRenderClient_Release(renderer->audio_render_client); + renderer->audio_render_client = NULL; if (renderer->stream_volume) IAudioStreamVolume_Release(renderer->stream_volume); renderer->stream_volume = NULL; if (renderer->audio_volume) ISimpleAudioVolume_Release(renderer->audio_volume); renderer->audio_volume = NULL; + renderer->flags &= ~SAR_PREROLLED; } static ULONG WINAPI audio_renderer_sink_Release(IMFMediaSink *iface) { struct audio_renderer *renderer = impl_from_IMFMediaSink(iface); ULONG refcount = InterlockedDecrement(&renderer->refcount); + struct queued_object *obj, *obj2; TRACE("%p, refcount %u.\n", iface, refcount); @@ -197,8 +272,12 @@ IMFMediaType_Release(renderer->media_type); if (renderer->current_media_type) IMFMediaType_Release(renderer->current_media_type); - CloseHandle(renderer->buffer_ready_event); audio_renderer_release_audio_client(renderer); + CloseHandle(renderer->buffer_ready_event); + LIST_FOR_EACH_ENTRY_SAFE(obj, obj2, &renderer->queue, struct queued_object, entry) + { + release_pending_object(obj); + } DeleteCriticalSection(&renderer->cs); heap_free(renderer); } @@ -212,7 +291,7 @@ TRACE("%p, %p.\n", iface, flags); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_SHUTDOWN; *flags = MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL; @@ -227,7 +306,7 @@ TRACE("%p, %#x, %p, %p.\n", iface, stream_sink_id, media_type, stream_sink); - return renderer->is_shut_down ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; + return renderer->flags & SAR_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; } static HRESULT WINAPI audio_renderer_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD stream_sink_id) @@ -236,7 +315,7 @@ TRACE("%p, %#x.\n", iface, stream_sink_id); - return renderer->is_shut_down ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; + return renderer->flags & SAR_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; } static HRESULT WINAPI audio_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count) @@ -248,7 +327,7 @@ if (!count) return E_POINTER; - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_SHUTDOWN; *count = 1; @@ -264,12 +343,9 @@ TRACE("%p, %u, %p.\n", iface, index, stream); - if (renderer->is_shut_down) - return MF_E_SHUTDOWN; - EnterCriticalSection(&renderer->cs); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) hr = MF_E_SHUTDOWN; else if (index > 0) hr = MF_E_INVALIDINDEX; @@ -294,7 +370,7 @@ EnterCriticalSection(&renderer->cs); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) hr = MF_E_SHUTDOWN; else if (stream_sink_id > 0) hr = MF_E_INVALIDSTREAMNUMBER; @@ -333,7 +409,7 @@ EnterCriticalSection(&renderer->cs); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) hr = MF_E_SHUTDOWN; else audio_renderer_set_presentation_clock(renderer, clock); @@ -355,7 +431,7 @@ EnterCriticalSection(&renderer->cs); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) hr = MF_E_SHUTDOWN; else if (renderer->clock) { @@ -376,14 +452,15 @@ TRACE("%p.\n", iface); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_SHUTDOWN; EnterCriticalSection(&renderer->cs); - renderer->is_shut_down = TRUE; + renderer->flags |= SAR_SHUT_DOWN; IMFMediaEventQueue_Shutdown(renderer->event_queue); IMFMediaEventQueue_Shutdown(renderer->stream_event_queue); audio_renderer_set_presentation_clock(renderer, NULL); + audio_renderer_release_audio_client(renderer); LeaveCriticalSection(&renderer->cs); return S_OK; @@ -407,10 +484,14 @@ static void audio_renderer_preroll(struct audio_renderer *renderer) { - int i; + unsigned int i; + + if (renderer->flags & SAR_PREROLLED) + return; for (i = 0; i < 2; ++i) IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); + renderer->flags |= SAR_PREROLLED; } static HRESULT WINAPI audio_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj) @@ -437,7 +518,7 @@ TRACE("%p, %s.\n", iface, debugstr_time(start_time)); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_SHUTDOWN; audio_renderer_preroll(renderer); @@ -559,6 +640,8 @@ hr = MF_E_NOT_INITIALIZED; IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, hr, NULL); + if (SUCCEEDED(hr)) + audio_renderer_preroll(renderer); LeaveCriticalSection(&renderer->cs); return hr; @@ -584,6 +667,7 @@ else WARN("Failed to stop audio client, hr %#x.\n", hr); renderer->state = STREAM_STATE_STOPPED; + renderer->flags &= ~SAR_PREROLLED; } } else @@ -1091,6 +1175,13 @@ else hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, eRender, role, &renderer->device); + /* Configuration attributes to be used later for audio client initialization. */ + if (attributes) + { + IMFAttributes_GetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS, &renderer->stream_config.flags); + IMFAttributes_GetGUID(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID, &renderer->stream_config.session_id); + } + if (FAILED(hr)) hr = MF_E_NO_AUDIO_PLAYBACK_DEVICE; @@ -1145,7 +1236,7 @@ TRACE("%p, %#x, %p.\n", iface, flags, event); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED; return IMFMediaEventQueue_GetEvent(renderer->stream_event_queue, flags, event); @@ -1158,7 +1249,7 @@ TRACE("%p, %p, %p.\n", iface, callback, state); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED; return IMFMediaEventQueue_BeginGetEvent(renderer->stream_event_queue, callback, state); @@ -1171,7 +1262,7 @@ TRACE("%p, %p, %p.\n", iface, result, event); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED; return IMFMediaEventQueue_EndGetEvent(renderer->stream_event_queue, result, event); @@ -1184,7 +1275,7 @@ TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED; return IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, event_type, ext_type, hr, value); @@ -1196,7 +1287,7 @@ TRACE("%p, %p.\n", iface, sink); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED; *sink = &renderer->IMFMediaSink_iface; @@ -1211,7 +1302,7 @@ TRACE("%p, %p.\n", iface, identifier); - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED; *identifier = 0; @@ -1228,7 +1319,7 @@ if (!handler) return E_POINTER; - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED; *handler = &renderer->IMFMediaTypeHandler_iface; @@ -1237,26 +1328,110 @@ return S_OK; } +static HRESULT stream_queue_sample(struct audio_renderer *renderer, IMFSample *sample) +{ + struct queued_object *object; + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->type = OBJECT_TYPE_SAMPLE; + object->u.sample.sample = sample; + IMFSample_AddRef(object->u.sample.sample); + + list_add_tail(&renderer->queue, &object->entry); + + return S_OK; +} + static HRESULT WINAPI audio_renderer_stream_ProcessSample(IMFStreamSink *iface, IMFSample *sample) { - FIXME("%p, %p.\n", iface, sample); + struct audio_renderer *renderer = impl_from_IMFStreamSink(iface); + HRESULT hr = S_OK; - return E_NOTIMPL; + TRACE("%p, %p.\n", iface, sample); + + if (!sample) + return E_POINTER; + + if (renderer->flags & SAR_SHUT_DOWN) + return MF_E_STREAMSINK_REMOVED; + + EnterCriticalSection(&renderer->cs); + if (renderer->state == STREAM_STATE_RUNNING) + hr = stream_queue_sample(renderer, sample); + renderer->flags &= ~SAR_SAMPLE_REQUESTED; + LeaveCriticalSection(&renderer->cs); + + return hr; +} + +static HRESULT stream_place_marker(struct audio_renderer *renderer, MFSTREAMSINK_MARKER_TYPE marker_type, + const PROPVARIANT *context_value) +{ + struct queued_object *marker; + HRESULT hr = S_OK; + + if (!(marker = heap_alloc_zero(sizeof(*marker)))) + return E_OUTOFMEMORY; + + marker->type = OBJECT_TYPE_MARKER; + marker->u.marker.type = marker_type; + PropVariantInit(&marker->u.marker.context); + if (context_value) + hr = PropVariantCopy(&marker->u.marker.context, context_value); + if (SUCCEEDED(hr)) + list_add_tail(&renderer->queue, &marker->entry); + else + release_pending_object(marker); + + return hr; } static HRESULT WINAPI audio_renderer_stream_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type, const PROPVARIANT *marker_value, const PROPVARIANT *context_value) { - FIXME("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value); + struct audio_renderer *renderer = impl_from_IMFStreamSink(iface); + HRESULT hr; - return E_NOTIMPL; + TRACE("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value); + + if (renderer->flags & SAR_SHUT_DOWN) + return MF_E_STREAMSINK_REMOVED; + + EnterCriticalSection(&renderer->cs); + hr = stream_place_marker(renderer, marker_type, context_value); + LeaveCriticalSection(&renderer->cs); + + return hr; } static HRESULT WINAPI audio_renderer_stream_Flush(IMFStreamSink *iface) { - FIXME("%p.\n", iface); + struct audio_renderer *renderer = impl_from_IMFStreamSink(iface); + struct queued_object *obj, *obj2; + HRESULT hr = S_OK; - return E_NOTIMPL; + TRACE("%p.\n", iface); + + EnterCriticalSection(&renderer->cs); + if (renderer->flags & SAR_SHUT_DOWN) + hr = MF_E_STREAMSINK_REMOVED; + else + { + LIST_FOR_EACH_ENTRY_SAFE(obj, obj2, &renderer->queue, struct queued_object, entry) + { + if (obj->type == OBJECT_TYPE_MARKER) + { + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkMarker, + &GUID_NULL, S_OK, &obj->u.marker.context); + } + release_pending_object(obj); + } + } + LeaveCriticalSection(&renderer->cs); + + return hr; } static const IMFStreamSinkVtbl audio_renderer_stream_vtbl = @@ -1339,6 +1514,8 @@ static HRESULT audio_renderer_create_audio_client(struct audio_renderer *renderer) { + IMFAsyncResult *result; + unsigned int flags; WAVEFORMATEX *wfx; HRESULT hr; @@ -1352,8 +1529,6 @@ return hr; } - /* FIXME: use SAR configuration for flags and session id. */ - /* FIXME: for now always use default format. */ if (FAILED(hr = IAudioClient_GetMixFormat(renderer->audio_client, &wfx))) { @@ -1361,8 +1536,15 @@ return hr; } - hr = IAudioClient_Initialize(renderer->audio_client, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - 1000000, 0, wfx, NULL); + renderer->frame_size = wfx->wBitsPerSample * wfx->nChannels / 8; + + flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK; + if (renderer->stream_config.flags & MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_CROSSPROCESS) + flags |= AUDCLNT_STREAMFLAGS_CROSSPROCESS; + if (renderer->stream_config.flags & MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_NOPERSIST) + flags |= AUDCLNT_STREAMFLAGS_NOPERSIST; + hr = IAudioClient_Initialize(renderer->audio_client, AUDCLNT_SHAREMODE_SHARED, flags, 1000000, 0, wfx, + &renderer->stream_config.session_id); CoTaskMemFree(wfx); if (FAILED(hr)) { @@ -1383,12 +1565,26 @@ return hr; } + if (FAILED(hr = IAudioClient_GetService(renderer->audio_client, &IID_IAudioRenderClient, + (void **)&renderer->audio_render_client))) + { + WARN("Failed to get audio render client, hr %#x.\n", hr); + return hr; + } + if (FAILED(hr = IAudioClient_SetEventHandle(renderer->audio_client, renderer->buffer_ready_event))) { WARN("Failed to set event handle, hr %#x.\n", hr); return hr; } + if (SUCCEEDED(hr = MFCreateAsyncResult(NULL, &renderer->render_callback, NULL, &result))) + { + if (FAILED(hr = MFPutWaitingWorkItem(renderer->buffer_ready_event, 0, result, &renderer->buffer_ready_key))) + WARN("Failed to submit wait item, hr %#x.\n", hr); + IMFAsyncResult_Release(result); + } + return hr; } @@ -1462,7 +1658,7 @@ if (!type) return E_POINTER; - if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED; memcpy(type, &MFMediaType_Audio, sizeof(*type)); @@ -1521,6 +1717,121 @@ return hr; } +static HRESULT WINAPI audio_renderer_render_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFAsyncCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFAsyncCallback_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI audio_renderer_render_callback_AddRef(IMFAsyncCallback *iface) +{ + struct audio_renderer *renderer = impl_from_render_callback_IMFAsyncCallback(iface); + return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface); +} + +static ULONG WINAPI audio_renderer_render_callback_Release(IMFAsyncCallback *iface) +{ + struct audio_renderer *renderer = impl_from_render_callback_IMFAsyncCallback(iface); + return IMFMediaSink_Release(&renderer->IMFMediaSink_iface); +} + +static HRESULT WINAPI audio_renderer_render_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI audio_renderer_render_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct audio_renderer *renderer = impl_from_render_callback_IMFAsyncCallback(iface); + unsigned int src_frames, dst_frames, max_frames, src_len; + struct queued_object *obj, *obj2; + BOOL keep_sample = FALSE; + IMFMediaBuffer *buffer; + BYTE *dst, *src; + HRESULT hr; + + EnterCriticalSection(&renderer->cs); + + LIST_FOR_EACH_ENTRY_SAFE(obj, obj2, &renderer->queue, struct queued_object, entry) + { + if (obj->type == OBJECT_TYPE_MARKER) + { + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkMarker, + &GUID_NULL, S_OK, &obj->u.marker.context); + } + else if (obj->type == OBJECT_TYPE_SAMPLE) + { + if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(obj->u.sample.sample, &buffer))) + { + if (SUCCEEDED(IMFMediaBuffer_Lock(buffer, &src, NULL, &src_len))) + { + if ((src_frames = src_len / renderer->frame_size)) + { + if (SUCCEEDED(IAudioClient_GetBufferSize(renderer->audio_client, &max_frames))) + { + src_frames -= obj->u.sample.frame_offset; + dst_frames = min(src_frames, max_frames); + + if (SUCCEEDED(hr = IAudioRenderClient_GetBuffer(renderer->audio_render_client, dst_frames, &dst))) + { + memcpy(dst, src + obj->u.sample.frame_offset * renderer->frame_size, + dst_frames * renderer->frame_size); + + IAudioRenderClient_ReleaseBuffer(renderer->audio_render_client, dst_frames, 0); + + obj->u.sample.frame_offset += dst_frames; + } + + keep_sample = FAILED(hr) || src_frames > max_frames; + } + } + IMFMediaBuffer_Unlock(buffer); + } + IMFMediaBuffer_Release(buffer); + } + } + + if (keep_sample) + break; + + list_remove(&obj->entry); + release_pending_object(obj); + } + + if (list_empty(&renderer->queue) && !(renderer->flags & SAR_SAMPLE_REQUESTED)) + { + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); + renderer->flags |= SAR_SAMPLE_REQUESTED; + } + + if (FAILED(hr = MFPutWaitingWorkItem(renderer->buffer_ready_event, 0, result, &renderer->buffer_ready_key))) + WARN("Failed to submit wait item, hr %#x.\n", hr); + + LeaveCriticalSection(&renderer->cs); + + return S_OK; +} + +static const IMFAsyncCallbackVtbl audio_renderer_render_callback_vtbl = +{ + audio_renderer_render_callback_QueryInterface, + audio_renderer_render_callback_AddRef, + audio_renderer_render_callback_Release, + audio_renderer_render_callback_GetParameters, + audio_renderer_render_callback_Invoke, +}; + static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) { struct audio_renderer *renderer; @@ -1541,9 +1852,11 @@ renderer->IMFSimpleAudioVolume_iface.lpVtbl = &audio_renderer_simple_volume_vtbl; renderer->IMFAudioStreamVolume_iface.lpVtbl = &audio_renderer_stream_volume_vtbl; renderer->IMFAudioPolicy_iface.lpVtbl = &audio_renderer_policy_vtbl; + renderer->render_callback.lpVtbl = &audio_renderer_render_callback_vtbl; renderer->refcount = 1; InitializeCriticalSection(&renderer->cs); renderer->buffer_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + list_init(&renderer->queue); if (FAILED(hr = MFCreateEventQueue(&renderer->event_queue))) goto failed; diff -Nru wine-development-5.8/dlls/mf/session.c wine-development-5.9/dlls/mf/session.c --- wine-development-5.8/dlls/mf/session.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mf/session.c 2020-05-22 18:49:34.000000000 +0000 @@ -43,6 +43,7 @@ SESSION_CMD_START, SESSION_CMD_PAUSE, SESSION_CMD_STOP, + SESSION_CMD_END, /* Internal use only. */ }; struct session_op @@ -63,6 +64,7 @@ PROPVARIANT start_position; } start; } u; + struct list entry; }; struct queued_topology @@ -218,6 +220,7 @@ PROPVARIANT start_position; } presentation; struct list topologies; + struct list commands; enum session_state state; DWORD caps; CRITICAL_SECTION cs; @@ -524,18 +527,44 @@ return session->state == SESSION_STATE_SHUT_DOWN ? MF_E_SHUTDOWN : S_OK; } +static void session_push_back_command(struct media_session *session, enum session_command command) +{ + struct session_op *op; + + if (SUCCEEDED(create_session_op(command, &op))) + list_add_head(&session->commands, &op->entry); +} + static HRESULT session_submit_command(struct media_session *session, struct session_op *op) { HRESULT hr; EnterCriticalSection(&session->cs); if (SUCCEEDED(hr = session_is_shut_down(session))) - hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &session->commands_callback, &op->IUnknown_iface); + { + if (list_empty(&session->commands)) + hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &session->commands_callback, &op->IUnknown_iface); + list_add_tail(&session->commands, &op->entry); + IUnknown_AddRef(&op->IUnknown_iface); + } LeaveCriticalSection(&session->cs); return hr; } +static HRESULT session_submit_simple_command(struct media_session *session, enum session_command command) +{ + struct session_op *op; + HRESULT hr; + + if (FAILED(hr = create_session_op(command, &op))) + return hr; + + hr = session_submit_command(session, op); + IUnknown_Release(&op->IUnknown_iface); + return hr; +} + static void session_clear_topologies(struct media_session *session) { struct queued_topology *ptr, *next; @@ -717,6 +746,7 @@ struct media_source *source, *source2; struct media_sink *sink, *sink2; struct topo_node *node, *node2; + struct session_op *op, *op2; IMFTopology_Clear(session->presentation.current_topology); session->presentation.topo_status = MF_TOPOSTATUS_INVALID; @@ -749,6 +779,12 @@ IMFMediaEventGenerator_Release(sink->event_generator); heap_free(sink); } + + LIST_FOR_EACH_ENTRY_SAFE(op, op2, &session->commands, struct session_op, entry) + { + list_remove(&op->entry); + IUnknown_Release(&op->IUnknown_iface); + } } static void session_start(struct media_session *session, const GUID *time_format, const PROPVARIANT *start_position) @@ -756,8 +792,6 @@ struct media_source *source; HRESULT hr; - EnterCriticalSection(&session->cs); - switch (session->state) { case SESSION_STATE_STOPPED: @@ -795,16 +829,83 @@ default: ; } +} - LeaveCriticalSection(&session->cs); +static void session_command_complete(struct media_session *session) +{ + struct session_op *op; + struct list *e; + + /* Pop current command, submit next. */ + if ((e = list_head(&session->commands))) + { + op = LIST_ENTRY(e, struct session_op, entry); + list_remove(&op->entry); + IUnknown_Release(&op->IUnknown_iface); + } + + if ((e = list_head(&session->commands))) + { + op = LIST_ENTRY(e, struct session_op, entry); + MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &session->commands_callback, &op->IUnknown_iface); + } +} + +static void session_set_started(struct media_session *session) +{ + struct media_source *source; + unsigned int caps, flags; + IMFMediaEvent *event; + + session->state = SESSION_STATE_STARTED; + + caps = session->caps | MFSESSIONCAP_PAUSE; + + LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) + { + if (SUCCEEDED(IMFMediaSource_GetCharacteristics(source->source, &flags))) + { + if (!(flags & MFMEDIASOURCE_CAN_PAUSE)) + { + caps &= ~MFSESSIONCAP_PAUSE; + break; + } + } + } + + session_set_caps(session, caps); + + if (SUCCEEDED(MFCreateMediaEvent(MESessionStarted, &GUID_NULL, S_OK, NULL, &event))) + { + IMFMediaEvent_SetUINT64(event, &MF_EVENT_PRESENTATION_TIME_OFFSET, 0); + IMFMediaEventQueue_QueueEvent(session->event_queue, event); + IMFMediaEvent_Release(event); + } + session_command_complete(session); +} + +static void session_set_paused(struct media_session *session, HRESULT status) +{ + session->state = SESSION_STATE_PAUSED; + if (SUCCEEDED(status)) + session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE); + IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, status, NULL); + session_command_complete(session); +} + +static void session_set_closed(struct media_session *session, HRESULT status) +{ + session->state = SESSION_STATE_CLOSED; + if (SUCCEEDED(status)) + session_set_caps(session, session->caps & ~(MFSESSIONCAP_START | MFSESSIONCAP_SEEK)); + IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionClosed, &GUID_NULL, status, NULL); + session_command_complete(session); } static void session_pause(struct media_session *session) { HRESULT hr; - EnterCriticalSection(&session->cs); - switch (session->state) { case SESSION_STATE_STARTED: @@ -819,12 +920,7 @@ } if (FAILED(hr)) - { - session->state = SESSION_STATE_PAUSED; - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, hr, NULL); - } - - LeaveCriticalSection(&session->cs); + session_set_paused(session, hr); } static void session_set_stopped(struct media_session *session, HRESULT status) @@ -841,13 +937,12 @@ IMFMediaEventQueue_QueueEvent(session->event_queue, event); IMFMediaEvent_Release(event); } + session_command_complete(session); } static void session_stop(struct media_session *session) { - HRESULT hr; - - EnterCriticalSection(&session->cs); + HRESULT hr = MF_E_INVALIDREQUEST; switch (session->state) { @@ -863,13 +958,13 @@ break; case SESSION_STATE_STOPPED: - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionStopped, &GUID_NULL, S_OK, NULL); - break; + hr = S_OK; + /* fallthrough */ default: - ; + IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionStopped, &GUID_NULL, hr, NULL); + session_command_complete(session); + break; } - - LeaveCriticalSection(&session->cs); } static HRESULT session_finalize_sinks(struct media_session *session) @@ -898,11 +993,7 @@ } if (sinks_finalized) - { - session->state = SESSION_STATE_CLOSED; - session_set_caps(session, session->caps & ~(MFSESSIONCAP_START | MFSESSIONCAP_SEEK)); - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionClosed, &GUID_NULL, hr, NULL); - } + session_set_closed(session, hr); return hr; } @@ -911,8 +1002,6 @@ { HRESULT hr = S_OK; - EnterCriticalSection(&session->cs); - switch (session->state) { case SESSION_STATE_STOPPED: @@ -924,20 +1013,13 @@ if (SUCCEEDED(hr = IMFPresentationClock_Stop(session->clock))) session->state = SESSION_STATE_STOPPING_SINKS; break; - case SESSION_STATE_CLOSED: + default: hr = MF_E_INVALIDREQUEST; break; - default: - ; } if (FAILED(hr)) - { - session->state = SESSION_STATE_CLOSED; - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionClosed, &GUID_NULL, hr, NULL); - } - - LeaveCriticalSection(&session->cs); + session_set_closed(session, hr); } static struct media_source *session_get_media_source(struct media_session *session, IMFMediaSource *source) @@ -1314,8 +1396,6 @@ } } - EnterCriticalSection(&session->cs); - if (flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT) { if ((topology && topology == session->presentation.current_topology) || !topology) @@ -1356,8 +1436,6 @@ } } - LeaveCriticalSection(&session->cs); - if (resolved_topology) IMFTopology_Release(resolved_topology); } @@ -1499,18 +1577,10 @@ static HRESULT WINAPI mfsession_ClearTopologies(IMFMediaSession *iface) { struct media_session *session = impl_from_IMFMediaSession(iface); - struct session_op *op; - HRESULT hr; TRACE("%p.\n", iface); - if (FAILED(hr = create_session_op(SESSION_CMD_CLEAR_TOPOLOGIES, &op))) - return hr; - - hr = session_submit_command(session, op); - IUnknown_Release(&op->IUnknown_iface); - - return hr; + return session_submit_simple_command(session, SESSION_CMD_CLEAR_TOPOLOGIES); } static HRESULT WINAPI mfsession_Start(IMFMediaSession *iface, const GUID *format, const PROPVARIANT *start_position) @@ -1541,52 +1611,28 @@ static HRESULT WINAPI mfsession_Pause(IMFMediaSession *iface) { struct media_session *session = impl_from_IMFMediaSession(iface); - struct session_op *op; - HRESULT hr; TRACE("%p.\n", iface); - if (FAILED(hr = create_session_op(SESSION_CMD_PAUSE, &op))) - return hr; - - hr = session_submit_command(session, op); - IUnknown_Release(&op->IUnknown_iface); - - return hr; + return session_submit_simple_command(session, SESSION_CMD_PAUSE); } static HRESULT WINAPI mfsession_Stop(IMFMediaSession *iface) { struct media_session *session = impl_from_IMFMediaSession(iface); - struct session_op *op; - HRESULT hr; TRACE("%p.\n", iface); - if (FAILED(hr = create_session_op(SESSION_CMD_STOP, &op))) - return hr; - - hr = session_submit_command(session, op); - IUnknown_Release(&op->IUnknown_iface); - - return hr; + return session_submit_simple_command(session, SESSION_CMD_STOP); } static HRESULT WINAPI mfsession_Close(IMFMediaSession *iface) { struct media_session *session = impl_from_IMFMediaSession(iface); - struct session_op *op; - HRESULT hr; TRACE("%p.\n", iface); - if (FAILED(hr = create_session_op(SESSION_CMD_CLOSE, &op))) - return hr; - - hr = session_submit_command(session, op); - IUnknown_Release(&op->IUnknown_iface); - - return hr; + return session_submit_simple_command(session, SESSION_CMD_CLOSE); } static HRESULT WINAPI mfsession_Shutdown(IMFMediaSession *iface) @@ -1804,18 +1850,19 @@ struct session_op *op = impl_op_from_IUnknown(IMFAsyncResult_GetStateNoAddRef(result)); struct media_session *session = impl_from_commands_callback_IMFAsyncCallback(iface); + EnterCriticalSection(&session->cs); + switch (op->command) { case SESSION_CMD_CLEAR_TOPOLOGIES: - EnterCriticalSection(&session->cs); session_clear_topologies(session); - LeaveCriticalSection(&session->cs); - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionTopologiesCleared, &GUID_NULL, S_OK, NULL); + session_command_complete(session); break; case SESSION_CMD_SET_TOPOLOGY: session_set_topology(session, op->u.set_topology.flags, op->u.set_topology.topology); + session_command_complete(session); break; case SESSION_CMD_START: session_start(session, &op->u.start.time_format, &op->u.start.start_position); @@ -1833,6 +1880,8 @@ ; } + LeaveCriticalSection(&session->cs); + return S_OK; } @@ -2203,12 +2252,7 @@ if (!session_is_source_nodes_state(session, OBJ_STATE_PAUSED)) break; - session->state = SESSION_STATE_PAUSED; - - session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE); - - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, S_OK, NULL); - + session_set_paused(session, S_OK); break; case SESSION_STATE_STOPPING_SOURCES: if (!session_is_source_nodes_state(session, OBJ_STATE_STOPPED)) @@ -2247,8 +2291,6 @@ { struct media_source *source; enum object_state state; - IMFMediaEvent *event; - DWORD caps, flags; HRESULT hr = S_OK; BOOL changed; @@ -2271,30 +2313,7 @@ if (!session_is_output_nodes_state(session, OBJ_STATE_STARTED)) break; - session->state = SESSION_STATE_STARTED; - - caps = session->caps | MFSESSIONCAP_PAUSE; - - LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) - { - if (SUCCEEDED(IMFMediaSource_GetCharacteristics(source->source, &flags))) - { - if (!(flags & MFMEDIASOURCE_CAN_PAUSE)) - { - caps &= ~MFSESSIONCAP_PAUSE; - break; - } - } - } - - session_set_caps(session, caps); - - if (SUCCEEDED(MFCreateMediaEvent(MESessionStarted, &GUID_NULL, S_OK, NULL, &event))) - { - IMFMediaEvent_SetUINT64(event, &MF_EVENT_PRESENTATION_TIME_OFFSET, 0); - IMFMediaEventQueue_QueueEvent(session->event_queue, event); - IMFMediaEvent_Release(event); - } + session_set_started(session); break; case SESSION_STATE_PAUSING_SINKS: if (!session_is_output_nodes_state(session, OBJ_STATE_PAUSED)) @@ -2309,10 +2328,7 @@ } if (FAILED(hr)) - { - session->state = SESSION_STATE_PAUSED; - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, hr, NULL); - } + session_set_paused(session, hr); break; case SESSION_STATE_STOPPING_SINKS: @@ -2742,8 +2758,9 @@ { if (session_nodes_is_mask_set(session, MF_TOPOLOGY_MAX, SOURCE_FLAG_END_OF_PRESENTATION)) { - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MEEndOfPresentation, &GUID_NULL, S_OK, NULL); session->presentation.flags |= SESSION_FLAG_END_OF_PRESENTATION; + session_push_back_command(session, SESSION_CMD_END); + IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MEEndOfPresentation, &GUID_NULL, S_OK, NULL); } } } @@ -3037,11 +3054,7 @@ { sink->finalized = TRUE; if (sinks_finalized) - { - session->state = SESSION_STATE_CLOSED; - session_set_caps(session, session->caps & ~(MFSESSIONCAP_START | MFSESSIONCAP_SEEK)); - IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionClosed, &GUID_NULL, hr, NULL); - } + session_set_closed(session, hr); } IMFFinalizableMediaSink_Release(fin_sink); } @@ -3254,6 +3267,7 @@ object->sink_finalizer_callback.lpVtbl = &session_sink_finalizer_callback_vtbl; object->refcount = 1; list_init(&object->topologies); + list_init(&object->commands); list_init(&object->presentation.sources); list_init(&object->presentation.sinks); list_init(&object->presentation.nodes); diff -Nru wine-development-5.8/dlls/mf/tests/mf.c wine-development-5.9/dlls/mf/tests/mf.c --- wine-development-5.8/dlls/mf/tests/mf.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mf/tests/mf.c 2020-05-22 18:49:34.000000000 +0000 @@ -114,11 +114,11 @@ static void test_topology(void) { + IMFMediaType *mediatype, *mediatype2, *mediatype3; IMFCollection *collection, *collection2; IUnknown test_unk2 = { &test_unk_vtbl }; IUnknown test_unk = { &test_unk_vtbl }; IMFTopologyNode *node, *node2, *node3; - IMFMediaType *mediatype, *mediatype2; IMFTopology *topology, *topology2; MF_TOPOLOGY_TYPE node_type; UINT32 count, index; @@ -516,6 +516,9 @@ ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n"); IMFMediaType_Release(mediatype2); + hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + hr = IMFTopologyNode_GetInputCount(node, &count); ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); ok(count == 0, "Unexpected count %u.\n", count); @@ -529,6 +532,23 @@ hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype); ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&mediatype2); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + /* Changing output type does not change input type. */ + hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype2); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype3); + ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr); + ok(mediatype3 == mediatype, "Unexpected mediatype instance.\n"); + IMFMediaType_Release(mediatype3); + + IMFMediaType_Release(mediatype2); + hr = IMFTopologyNode_GetInputCount(node, &count); ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); ok(count == 0, "Unexpected count %u.\n", count); @@ -546,6 +566,10 @@ hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype); ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + hr = IMFTopologyNode_GetInputCount(node, &count); + ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr); + ok(count == 4, "Unexpected count %u.\n", count); + hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype); ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); @@ -800,6 +824,70 @@ IMFTopology_Release(topology); } +static void test_topology_tee_node(void) +{ + IMFTopologyNode *src_node, *tee_node; + IMFMediaType *mediatype, *mediatype2; + IMFTopology *topology; + unsigned int count; + HRESULT hr; + + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr); + + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &tee_node); + ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); + ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetInputPrefType(tee_node, 0, mediatype); + ok(hr == S_OK, "Failed to set type, hr %#x.\n", hr); + + /* Even though tee node has only one input and source has only one output, + it's possible to connect to higher inputs/outputs. */ + + /* SRC(0) -> TEE(0) */ + hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 0); + ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputCount(tee_node, &count); + ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr); + ok(count == 1, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_GetInputPrefType(tee_node, 0, &mediatype2); + ok(hr == S_OK, "Failed to get type, hr %#x.\n", hr); + ok(mediatype2 == mediatype, "Unexpected type.\n"); + IMFMediaType_Release(mediatype2); + + /* SRC(0) -> TEE(1) */ + hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 1); + ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputCount(tee_node, &count); + ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr); + ok(count == 2, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_SetInputPrefType(tee_node, 1, mediatype); + ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr); + + /* SRC(1) -> TEE(1) */ + hr = IMFTopologyNode_ConnectOutput(src_node, 1, tee_node, 1); + ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetOutputCount(src_node, &count); + ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr); + ok(count == 2, "Unexpected count %u.\n", count); + + IMFMediaType_Release(mediatype); + IMFTopologyNode_Release(src_node); + IMFTopologyNode_Release(tee_node); + IMFTopology_Release(topology); +} + static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown)) @@ -3725,6 +3813,7 @@ START_TEST(mf) { test_topology(); + test_topology_tee_node(); test_topology_loader(); test_MFGetService(); test_sequencer_source(); diff -Nru wine-development-5.8/dlls/mf/topology.c wine-development-5.9/dlls/mf/topology.c --- wine-development-5.8/dlls/mf/topology.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mf/topology.c 2020-05-22 18:49:34.000000000 +0000 @@ -61,6 +61,7 @@ MF_TOPOLOGY_TYPE node_type; TOPOID id; IUnknown *object; + IMFMediaType *input_type; /* Only for tee nodes. */ struct node_streams inputs; struct node_streams outputs; CRITICAL_SECTION cs; @@ -950,6 +951,8 @@ { if (node->object) IUnknown_Release(node->object); + if (node->input_type) + IMFMediaType_Release(node->input_type); for (i = 0; i < node->inputs.count; ++i) { if (node->inputs.streams[i].preferred_type) @@ -1361,14 +1364,7 @@ TRACE("%p, %p.\n", iface, count); - switch (node->node_type) - { - case MF_TOPOLOGY_TEE_NODE: - *count = 0; - break; - default: - *count = node->inputs.count; - } + *count = node->inputs.count; return S_OK; } @@ -1384,6 +1380,15 @@ return S_OK; } +static void topology_node_set_stream_type(struct node_stream *stream, IMFMediaType *mediatype) +{ + if (stream->preferred_type) + IMFMediaType_Release(stream->preferred_type); + stream->preferred_type = mediatype; + if (stream->preferred_type) + IMFMediaType_AddRef(stream->preferred_type); +} + static HRESULT topology_node_connect_output(struct topology_node *node, DWORD output_index, struct topology_node *connection, DWORD input_index) { @@ -1406,7 +1411,16 @@ hr = topology_node_reserve_streams(&node->outputs, output_index); if (SUCCEEDED(hr)) + { + size_t old_count = connection->inputs.count; hr = topology_node_reserve_streams(&connection->inputs, input_index); + if (SUCCEEDED(hr) && !old_count && connection->input_type) + { + topology_node_set_stream_type(connection->inputs.streams, connection->input_type); + IMFMediaType_Release(connection->input_type); + connection->input_type = NULL; + } + } if (SUCCEEDED(hr)) { @@ -1524,13 +1538,7 @@ if (node->node_type != MF_TOPOLOGY_OUTPUT_NODE) { if (SUCCEEDED(hr = topology_node_reserve_streams(&node->outputs, index))) - { - if (node->outputs.streams[index].preferred_type) - IMFMediaType_Release(node->outputs.streams[index].preferred_type); - node->outputs.streams[index].preferred_type = mediatype; - if (node->outputs.streams[index].preferred_type) - IMFMediaType_AddRef(node->outputs.streams[index].preferred_type); - } + topology_node_set_stream_type(&node->outputs.streams[index], mediatype); } else hr = E_NOTIMPL; @@ -1540,6 +1548,18 @@ return hr; } +static HRESULT topology_node_get_pref_type(struct node_streams *streams, unsigned int index, IMFMediaType **mediatype) +{ + *mediatype = streams->streams[index].preferred_type; + if (*mediatype) + { + IMFMediaType_AddRef(*mediatype); + return S_OK; + } + + return E_FAIL; +} + static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **mediatype) { struct topology_node *node = impl_from_IMFTopologyNode(iface); @@ -1550,13 +1570,7 @@ EnterCriticalSection(&node->cs); if (index < node->outputs.count) - { - *mediatype = node->outputs.streams[index].preferred_type; - if (*mediatype) - IMFMediaType_AddRef(*mediatype); - else - hr = E_FAIL; - } + hr = topology_node_get_pref_type(&node->outputs, index, mediatype); else hr = E_INVALIDARG; @@ -1574,25 +1588,32 @@ EnterCriticalSection(&node->cs); - if (node->node_type != MF_TOPOLOGY_SOURCESTREAM_NODE && !(index > 0 && node->node_type == MF_TOPOLOGY_TEE_NODE)) + switch (node->node_type) { - if (SUCCEEDED(hr = topology_node_reserve_streams(&node->inputs, index))) - { - if (index >= node->inputs.count) + case MF_TOPOLOGY_TEE_NODE: + if (index) { - memset(&node->inputs.streams[node->inputs.count], 0, - (index - node->inputs.count + 1) * sizeof(*node->inputs.streams)); - node->inputs.count = index + 1; + hr = MF_E_INVALIDTYPE; + break; } - if (node->inputs.streams[index].preferred_type) - IMFMediaType_Release(node->inputs.streams[index].preferred_type); - node->inputs.streams[index].preferred_type = mediatype; - if (node->inputs.streams[index].preferred_type) - IMFMediaType_AddRef(node->inputs.streams[index].preferred_type); - } + if (node->inputs.count) + topology_node_set_stream_type(&node->inputs.streams[index], mediatype); + else + { + if (node->input_type) + IMFMediaType_Release(node->input_type); + node->input_type = mediatype; + if (node->input_type) + IMFMediaType_AddRef(node->input_type); + } + break; + case MF_TOPOLOGY_SOURCESTREAM_NODE: + hr = E_NOTIMPL; + break; + default: + if (SUCCEEDED(hr = topology_node_reserve_streams(&node->inputs, index))) + topology_node_set_stream_type(&node->inputs.streams[index], mediatype); } - else - hr = node->node_type == MF_TOPOLOGY_TEE_NODE ? MF_E_INVALIDTYPE : E_NOTIMPL; LeaveCriticalSection(&node->cs); @@ -1610,11 +1631,12 @@ if (index < node->inputs.count) { - *mediatype = node->inputs.streams[index].preferred_type; - if (*mediatype) - IMFMediaType_AddRef(*mediatype); - else - hr = E_FAIL; + hr = topology_node_get_pref_type(&node->inputs, index, mediatype); + } + else if (node->node_type == MF_TOPOLOGY_TEE_NODE && node->input_type) + { + *mediatype = node->input_type; + IMFMediaType_AddRef(*mediatype); } else hr = E_INVALIDARG; diff -Nru wine-development-5.8/dlls/mfreadwrite/reader.c wine-development-5.9/dlls/mfreadwrite/reader.c --- wine-development-5.8/dlls/mfreadwrite/reader.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mfreadwrite/reader.c 2020-05-22 18:49:34.000000000 +0000 @@ -114,6 +114,7 @@ enum media_stream_state state; unsigned int flags; unsigned int requests; + unsigned int responses; }; enum source_reader_async_op @@ -360,6 +361,7 @@ IMFSample_AddRef(response->sample); list_add_tail(&reader->responses, &response->entry); + stream->responses++; if (stream->requests) { @@ -831,6 +833,22 @@ return IMFSourceReader_Release(&reader->IMFSourceReader_iface); } +static struct stream_response * media_stream_detach_response(struct source_reader *reader, struct stream_response *response) +{ + struct media_stream *stream; + + list_remove(&response->entry); + + if (response->stream_index < reader->stream_count) + { + stream = &reader->streams[response->stream_index]; + if (stream->responses) + --stream->responses; + } + + return response; +} + static struct stream_response *media_stream_pop_response(struct source_reader *reader, struct media_stream *stream) { struct stream_response *response; @@ -841,20 +859,13 @@ LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry) { if (response->stream_index == stream->index) - { - list_remove(&response->entry); - return response; - } + return media_stream_detach_response(reader, response); } } else { if ((head = list_head(&reader->responses))) - { - response = LIST_ENTRY(head, struct stream_response, entry); - list_remove(&response->entry); - return response; - } + return media_stream_detach_response(reader, LIST_ENTRY(head, struct stream_response, entry)); } return NULL; @@ -979,20 +990,35 @@ static HRESULT source_reader_get_first_selected_stream(struct source_reader *reader, unsigned int flags, unsigned int *stream_index) { - unsigned int i; - BOOL selected; + unsigned int i, first_selected = ~0u; + BOOL selected, stream_drained; for (i = 0; i < reader->stream_count; ++i) { - source_reader_get_stream_selection(reader, i, &selected); - if (SUCCEEDED(source_reader_get_stream_selection(reader, i, &selected)) && selected && - !(reader->streams[i].flags & flags)) + stream_drained = reader->streams[i].state == STREAM_STATE_EOS && !reader->streams[i].responses; + selected = SUCCEEDED(source_reader_get_stream_selection(reader, i, &selected)) && selected; + + if (selected && !(reader->streams[i].flags & flags)) { - *stream_index = i; - break; + if (first_selected == ~0u) + first_selected = i; + + if (!stream_drained) + { + *stream_index = i; + break; + } } } + /* If all selected streams reached EOS, use first selected. This fallback only applies after reader went through all + selected streams once. */ + if (i == reader->stream_count && first_selected != ~0u && !flags) + { + *stream_index = first_selected; + i = first_selected; + } + return i == reader->stream_count ? MF_E_MEDIA_SOURCE_NO_STREAMS_SELECTED : S_OK; } @@ -1046,7 +1072,7 @@ { continue; } - list_remove(&ptr->entry); + media_stream_detach_response(reader, ptr); source_reader_release_response(ptr); } } @@ -2136,6 +2162,7 @@ static const unsigned char wavmagic[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '}; static const unsigned char wavmask[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; static const unsigned char isommagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm',0x00,0x00,0x00,0x00}; + static const unsigned char mp42magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'm', 'p', '4', '2',0x00,0x00,0x00,0x00}; static const unsigned char mp4mask[] = {0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00}; static const struct stream_content_url_hint { @@ -2148,6 +2175,7 @@ { asfmagic, L".asf" }, { wavmagic, L".wav", wavmask }, { isommagic, L".mp4", mp4mask }, + { mp42magic, L".mp4", mp4mask }, }; unsigned char buffer[4 * sizeof(unsigned int)], pattern[4 * sizeof(unsigned int)]; unsigned int i, j, length = 0, caps = 0; diff -Nru wine-development-5.8/dlls/mshtml/tests/events.c wine-development-5.9/dlls/mshtml/tests/events.c --- wine-development-5.8/dlls/mshtml/tests/events.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mshtml/tests/events.c 2020-05-22 18:49:34.000000000 +0000 @@ -3319,6 +3319,9 @@ hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, (void**)&doc); +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); return SUCCEEDED(hres) ? doc : NULL; } @@ -3489,6 +3492,9 @@ DestroyWindow(container_hwnd); }else { +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif win_skip("Too old IE\n"); } diff -Nru wine-development-5.8/dlls/mshtml/tests/htmldoc.c wine-development-5.9/dlls/mshtml/tests/htmldoc.c --- wine-development-5.8/dlls/mshtml/tests/htmldoc.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mshtml/tests/htmldoc.c 2020-05-22 18:49:34.000000000 +0000 @@ -7290,6 +7290,9 @@ hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, (void**)&doc); +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); if(FAILED(hres)) return NULL; @@ -8774,6 +8777,9 @@ if(!check_ie()) { CoUninitialize(); +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif win_skip("Too old IE\n"); return; } diff -Nru wine-development-5.8/dlls/mshtml/tests/htmllocation.c wine-development-5.9/dlls/mshtml/tests/htmllocation.c --- wine-development-5.8/dlls/mshtml/tests/htmllocation.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mshtml/tests/htmllocation.c 2020-05-22 18:49:34.000000000 +0000 @@ -302,6 +302,9 @@ hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, (void**)&doc); +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif ok(hres == S_OK, "%s: CoCreateInstance failed: 0x%08x\n", test->name, hres); if(FAILED(hres)){ IMoniker_Release(url_mon); diff -Nru wine-development-5.8/dlls/mshtml/tests/script.c wine-development-5.9/dlls/mshtml/tests/script.c --- wine-development-5.8/dlls/mshtml/tests/script.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mshtml/tests/script.c 2020-05-22 18:49:34.000000000 +0000 @@ -1231,6 +1231,9 @@ hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, (void**)&doc); +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); return SUCCEEDED(hres) ? doc : NULL; } @@ -3572,6 +3575,9 @@ skip("IE running in Enhanced Security Configuration\n"); } }else { +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif win_skip("Too old IE.\n"); } diff -Nru wine-development-5.8/dlls/mshtml/tests/style.c wine-development-5.9/dlls/mshtml/tests/style.c --- wine-development-5.8/dlls/mshtml/tests/style.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mshtml/tests/style.c 2020-05-22 18:49:34.000000000 +0000 @@ -3496,6 +3496,9 @@ hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, (void**)&doc); +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); if(FAILED(hres)) return NULL; diff -Nru wine-development-5.8/dlls/mshtml/tests/xmlhttprequest.c wine-development-5.9/dlls/mshtml/tests/xmlhttprequest.c --- wine-development-5.8/dlls/mshtml/tests/xmlhttprequest.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/mshtml/tests/xmlhttprequest.c 2020-05-22 18:49:34.000000000 +0000 @@ -1021,6 +1021,9 @@ hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2, (void**)&doc); +#if !defined(__i386__) && !defined(__x86_64__) + todo_wine +#endif ok(hres == S_OK, "CoCreateInstance failed: 0x%08x\n", hres); hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, diff -Nru wine-development-5.8/dlls/msvcrt/string.c wine-development-5.9/dlls/msvcrt/string.c --- wine-development-5.8/dlls/msvcrt/string.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/msvcrt/string.c 2020-05-22 18:49:34.000000000 +0000 @@ -864,7 +864,7 @@ if(b.data[BNUM_IDX(b.b)]) break; } - /* move decimal point to limb boundry */ + /* move decimal point to limb boundary */ if(limb_digits==dp && b.b==b.e-1) return make_double(sign, 0, b.data[BNUM_IDX(b.e-1)], ROUND_ZERO, err); off = (dp - limb_digits) % LIMB_DIGITS; @@ -893,7 +893,7 @@ } /* Check if fractional part is non-zero */ - /* Caution: it's only correct because bnum_to_mant returns more then 53 bits */ + /* Caution: it's only correct because bnum_to_mant returns more than 53 bits */ for(i=b.e-3; i>=b.b; i--) { if (!b.data[BNUM_IDX(b.b)]) continue; round = ROUND_DOWN; diff -Nru wine-development-5.8/dlls/msvcrt/wcs.c wine-development-5.9/dlls/msvcrt/wcs.c --- wine-development-5.8/dlls/msvcrt/wcs.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/msvcrt/wcs.c 2020-05-22 18:49:34.000000000 +0000 @@ -725,8 +725,8 @@ /********************************************************************* * __stdio_common_vsprintf (UCRTBASE.@) */ -int CDECL __stdio_common_vsprintf( unsigned __int64 options, char *str, MSVCRT_size_t len, const char *format, - MSVCRT__locale_t locale, __ms_va_list valist ) +int CDECL MSVCRT__stdio_common_vsprintf( unsigned __int64 options, char *str, MSVCRT_size_t len, const char *format, + MSVCRT__locale_t locale, __ms_va_list valist ) { static const char nullbyte = '\0'; struct _str_ctx_a ctx = {len, str}; @@ -744,7 +744,9 @@ return ret>len ? -1 : ret; if(ret>=len) { if(len) str[len-1] = 0; - return (options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) ? ret : -2; + if(options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) + return ret; + return len > 0 ? -2 : -1; } return ret; } @@ -1284,7 +1286,9 @@ return ret>len ? -1 : ret; if(ret>=len) { if(len) str[len-1] = 0; - return (options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) ? ret : -2; + if(options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) + return ret; + return len > 0 ? -2 : -1; } return ret; } diff -Nru wine-development-5.8/dlls/ntdll/actctx.c wine-development-5.9/dlls/ntdll/actctx.c --- wine-development-5.8/dlls/ntdll/actctx.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/actctx.c 2020-05-22 18:49:34.000000000 +0000 @@ -3189,11 +3189,11 @@ if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE; if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) + - wcslen(user_shared_data->NtSystemRoot) * sizeof(WCHAR) ))) + wcslen(windows_dir) * sizeof(WCHAR) ))) return STATUS_NO_MEMORY; - wcscpy( path, user_shared_data->NtSystemRoot ); - memcpy( path + wcslen(path), manifest_dirW, sizeof(manifest_dirW) ); + wcscpy( path, windows_dir ); + wcscat( path, manifest_dirW ); if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL )) { diff -Nru wine-development-5.8/dlls/ntdll/debugtools.c wine-development-5.9/dlls/ntdll/debugtools.c --- wine-development-5.8/dlls/ntdll/debugtools.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/debugtools.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,291 +0,0 @@ -/* - * Debugging functions - * - * Copyright 2000 Alexandre Julliard - * - * 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 "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif - -#include "wine/debug.h" -#include "ntdll_misc.h" - -WINE_DECLARE_DEBUG_CHANNEL(pid); -WINE_DECLARE_DEBUG_CHANNEL(timestamp); - -static BOOL init_done; -static struct debug_info initial_info; /* debug info for initial thread */ -static unsigned char default_flags = (1 << __WINE_DBCL_ERR) | (1 << __WINE_DBCL_FIXME); -static int nb_debug_options = -1; -static int options_size; -static struct __wine_debug_channel *debug_options; - -static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" }; - -/* get the debug info pointer for the current thread */ -static inline struct debug_info *get_info(void) -{ - if (!init_done) return &initial_info; - return ntdll_get_thread_data()->debug_info; -} - -/* add a string to the output buffer */ -static int append_output( struct debug_info *info, const char *str, size_t len ) -{ - if (len >= sizeof(info->output) - info->out_pos) - { - fprintf( stderr, "wine_dbg_output: debugstr buffer overflow (contents: '%s')\n", info->output ); - info->out_pos = 0; - abort(); - } - memcpy( info->output + info->out_pos, str, len ); - info->out_pos += len; - return len; -} - -/* add a new debug option at the end of the option list */ -static void add_option( const char *name, unsigned char set, unsigned char clear ) -{ - int min = 0, max = nb_debug_options - 1, pos, res; - - if (!name[0]) /* "all" option */ - { - default_flags = (default_flags & ~clear) | set; - return; - } - if (strlen(name) >= sizeof(debug_options[0].name)) return; - - while (min <= max) - { - pos = (min + max) / 2; - res = strcmp( name, debug_options[pos].name ); - if (!res) - { - debug_options[pos].flags = (debug_options[pos].flags & ~clear) | set; - return; - } - if (res < 0) max = pos - 1; - else min = pos + 1; - } - if (nb_debug_options >= options_size) - { - options_size = max( options_size * 2, 16 ); - debug_options = realloc( debug_options, options_size * sizeof(debug_options[0]) ); - } - - pos = min; - if (pos < nb_debug_options) memmove( &debug_options[pos + 1], &debug_options[pos], - (nb_debug_options - pos) * sizeof(debug_options[0]) ); - strcpy( debug_options[pos].name, name ); - debug_options[pos].flags = (default_flags & ~clear) | set; - nb_debug_options++; -} - -/* parse a set of debugging option specifications and add them to the option list */ -static void parse_options( const char *str ) -{ - char *opt, *next, *options; - unsigned int i; - - if (!(options = strdup(str))) return; - for (opt = options; opt; opt = next) - { - const char *p; - unsigned char set = 0, clear = 0; - - if ((next = strchr( opt, ',' ))) *next++ = 0; - - p = opt + strcspn( opt, "+-" ); - if (!p[0]) p = opt; /* assume it's a debug channel name */ - - if (p > opt) - { - for (i = 0; i < ARRAY_SIZE(debug_classes); i++) - { - int len = strlen(debug_classes[i]); - if (len != (p - opt)) continue; - if (!memcmp( opt, debug_classes[i], len )) /* found it */ - { - if (*p == '+') set |= 1 << i; - else clear |= 1 << i; - break; - } - } - if (i == ARRAY_SIZE(debug_classes)) /* bad class name, skip it */ - continue; - } - else - { - if (*p == '-') clear = ~0; - else set = ~0; - } - if (*p == '+' || *p == '-') p++; - if (!p[0]) continue; - - if (!strcmp( p, "all" )) - default_flags = (default_flags & ~clear) | set; - else - add_option( p, set, clear ); - } - free( options ); -} - -/* print the usage message */ -static void debug_usage(void) -{ - static const char usage[] = - "Syntax of the WINEDEBUG variable:\n" - " WINEDEBUG=[class]+xxx,[class]-yyy,...\n\n" - "Example: WINEDEBUG=+relay,warn-heap\n" - " turns on relay traces, disable heap warnings\n" - "Available message classes: err, warn, fixme, trace\n"; - write( 2, usage, sizeof(usage) - 1 ); - exit(1); -} - -/* initialize all options at startup */ -static void init_options(void) -{ - char *wine_debug = getenv("WINEDEBUG"); - struct stat st1, st2; - - nb_debug_options = 0; - - /* check for stderr pointing to /dev/null */ - if (!fstat( 2, &st1 ) && S_ISCHR(st1.st_mode) && - !stat( "/dev/null", &st2 ) && S_ISCHR(st2.st_mode) && - st1.st_rdev == st2.st_rdev) - { - default_flags = 0; - return; - } - if (!wine_debug) return; - if (!strcmp( wine_debug, "help" )) debug_usage(); - parse_options( wine_debug ); -} - -/*********************************************************************** - * __wine_dbg_get_channel_flags (NTDLL.@) - * - * Get the flags to use for a given channel, possibly setting them too in case of lazy init - */ -unsigned char __cdecl __wine_dbg_get_channel_flags( struct __wine_debug_channel *channel ) -{ - int min, max, pos, res; - - if (nb_debug_options == -1) init_options(); - - min = 0; - max = nb_debug_options - 1; - while (min <= max) - { - pos = (min + max) / 2; - res = strcmp( channel->name, debug_options[pos].name ); - if (!res) return debug_options[pos].flags; - if (res < 0) max = pos - 1; - else min = pos + 1; - } - /* no option for this channel */ - if (channel->flags & (1 << __WINE_DBCL_INIT)) channel->flags = default_flags; - return default_flags; -} - -/*********************************************************************** - * __wine_dbg_strdup (NTDLL.@) - */ -const char * __cdecl __wine_dbg_strdup( const char *str ) -{ - struct debug_info *info = get_info(); - unsigned int pos = info->str_pos; - size_t n = strlen( str ) + 1; - - assert( n <= sizeof(info->strings) ); - if (pos + n > sizeof(info->strings)) pos = 0; - info->str_pos = pos + n; - return memcpy( info->strings + pos, str, n ); -} - -/*********************************************************************** - * __wine_dbg_output (NTDLL.@) - */ -int __cdecl __wine_dbg_output( const char *str ) -{ - struct debug_info *info = get_info(); - const char *end = strrchr( str, '\n' ); - int ret = 0; - - if (end) - { - ret += append_output( info, str, end + 1 - str ); - write( 2, info->output, info->out_pos ); - info->out_pos = 0; - str = end + 1; - } - if (*str) ret += append_output( info, str, strlen( str )); - return ret; -} - -/*********************************************************************** - * __wine_dbg_header (NTDLL.@) - */ -int __cdecl __wine_dbg_header( enum __wine_debug_class cls, struct __wine_debug_channel *channel, - const char *function ) -{ - static const char * const classes[] = { "fixme", "err", "warn", "trace" }; - struct debug_info *info = get_info(); - char buffer[200], *pos = buffer; - - if (!(__wine_dbg_get_channel_flags( channel ) & (1 << cls))) return -1; - - /* only print header if we are at the beginning of the line */ - if (info->out_pos) return 0; - - if (init_done) - { - if (TRACE_ON(timestamp)) - { - ULONG ticks = NtGetTickCount(); - pos += sprintf( pos, "%3u.%03u:", ticks / 1000, ticks % 1000 ); - } - if (TRACE_ON(pid)) pos += sprintf( pos, "%04x:", GetCurrentProcessId() ); - pos += sprintf( pos, "%04x:", GetCurrentThreadId() ); - } - if (function && cls < ARRAY_SIZE( classes )) - snprintf( pos, sizeof(buffer) - (pos - buffer), "%s:%s:%s ", - classes[cls], channel->name, function ); - - return append_output( info, buffer, strlen( buffer )); -} - -/*********************************************************************** - * debug_init - */ -void debug_init(void) -{ - setbuf( stdout, NULL ); - setbuf( stderr, NULL ); - ntdll_get_thread_data()->debug_info = &initial_info; - init_done = TRUE; -} diff -Nru wine-development-5.8/dlls/ntdll/env.c wine-development-5.9/dlls/ntdll/env.c --- wine-development-5.8/dlls/ntdll/env.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/env.c 2020-05-22 18:49:34.000000000 +0000 @@ -50,8 +50,6 @@ static const BOOL is_win64 = (sizeof(void *) > sizeof(int)); -static const WCHAR windows_dir[] = {'C',':','\\','w','i','n','d','o','w','s',0}; - static BOOL first_prefix_start; /* first ever process start in this prefix? */ static inline SIZE_T get_env_length( const WCHAR *env ) @@ -61,13 +59,6 @@ return end + 1 - env; } -#ifdef __APPLE__ -extern char **__wine_get_main_environment(void); -#else -extern char **__wine_main_environ; -static char **__wine_get_main_environment(void) { return __wine_main_environ; } -#endif - /*********************************************************************** * is_special_env_var @@ -391,6 +382,8 @@ const char *p; const char *home = getenv( "HOME" ); const char *name = getenv( "USER" ); + const char **dll_paths; + SIZE_T dll_path_maxlen; WCHAR *val; HANDLE hkey; DWORD i; @@ -411,6 +404,7 @@ set_wine_path_variable( env, winehomedirW, home ); set_wine_path_variable( env, winebuilddirW, build_dir ); set_wine_path_variable( env, wineconfigdirW, config_dir ); + unix_funcs->get_dll_path( &dll_paths, &dll_path_maxlen ); for (i = 0; dll_paths[i]; i++) { NTDLL_swprintf( buf, winedlldirW, i ); @@ -779,8 +773,6 @@ total -= reslen; } wargv[argc] = NULL; - - __wine_main_argc = argc; __wine_main_wargv = wargv; } @@ -990,6 +982,48 @@ return nts; } + +/****************************************************************** + * RtlQueryEnvironmentVariable [NTDLL.@] + */ +NTSTATUS WINAPI RtlQueryEnvironmentVariable( WCHAR *env, const WCHAR *name, SIZE_T namelen, + WCHAR *value, SIZE_T value_length, SIZE_T *return_length ) +{ + NTSTATUS nts = STATUS_VARIABLE_NOT_FOUND; + SIZE_T len = 0; + const WCHAR *var; + + if (!namelen) return nts; + + if (!env) + { + RtlAcquirePebLock(); + var = NtCurrentTeb()->Peb->ProcessParameters->Environment; + } + else var = env; + + var = ENV_FindVariable(var, name, namelen); + if (var != NULL) + { + len = wcslen(var); + if (len <= value_length) + { + memcpy(value, var, min(len + 1, value_length) * sizeof(WCHAR)); + nts = STATUS_SUCCESS; + } + else + { + len++; + nts = STATUS_BUFFER_TOO_SMALL; + } + } + *return_length = len; + + if (!env) RtlReleasePebLock(); + + return nts; +} + /****************************************************************** * RtlSetCurrentEnvironment [NTDLL.@] * @@ -1465,6 +1499,10 @@ startup_info_t *info = NULL; RTL_USER_PROCESS_PARAMETERS *params = NULL; UNICODE_STRING curdir, dllpath, imagepath, cmdline, title, desktop, shellinfo, runtime; + int argc; + char **argv, **envp; + + unix_funcs->get_main_args( &argc, &argv, &envp ); if (!data_size) { @@ -1472,13 +1510,13 @@ WCHAR *env, curdir_buffer[MAX_PATH]; NtCurrentTeb()->Peb->ProcessParameters = &initial_params; - initial_params.Environment = build_initial_environment( __wine_get_main_environment() ); + initial_params.Environment = build_initial_environment( envp ); curdir.Buffer = curdir_buffer; curdir.MaximumLength = sizeof(curdir_buffer); get_current_directory( &curdir ); initial_params.CurrentDirectory.DosPath = curdir; - get_image_path( __wine_main_argv[0], &initial_params.ImagePathName ); - set_library_wargv( __wine_main_argv, &initial_params.ImagePathName ); + get_image_path( argv[0], &initial_params.ImagePathName ); + set_library_wargv( argv, &initial_params.ImagePathName ); build_command_line( __wine_main_wargv, &cmdline ); LdrGetDllPath( initial_params.ImagePathName.Buffer, 0, &load_path, &dummy ); RtlInitUnicodeString( &dllpath, load_path ); @@ -1566,7 +1604,7 @@ else params->Environment[0] = 0; } - set_library_wargv( __wine_main_argv, NULL ); + set_library_wargv( argv, NULL ); done: RtlFreeHeap( GetProcessHeap(), 0, info ); diff -Nru wine-development-5.8/dlls/ntdll/loader.c wine-development-5.9/dlls/ntdll/loader.c --- wine-development-5.8/dlls/ntdll/loader.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/loader.c 2020-05-22 18:49:34.000000000 +0000 @@ -31,10 +31,6 @@ # include #endif -#if defined(__APPLE__) -# include -#endif - #include "ntstatus.h" #define WIN32_NO_STATUS #define NONAMELESSUNION @@ -71,6 +67,10 @@ typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID); typedef void (CALLBACK *LDRENUMPROC)(LDR_DATA_TABLE_ENTRY *, void *, BOOLEAN *); +const struct unix_funcs *unix_funcs = NULL; + +/* windows directory */ +const WCHAR windows_dir[] = {'C',':','\\','w','i','n','d','o','w','s',0}; /* system directory with trailing backslash */ const WCHAR system_dir[] = {'C',':','\\','w','i','n','d','o','w','s','\\', 's','y','s','t','e','m','3','2','\\',0}; @@ -1319,6 +1319,35 @@ } } +#ifdef __FreeBSD__ +/* The PT_LOAD segments are sorted in increasing order, and the first + * starts at the beginning of the ELF file. By parsing the file, we can + * find that first PT_LOAD segment, from which we can find the base + * address it wanted, and knowing mapbase where the binary was actually + * loaded, use them to work out the relocbase offset. */ +static BOOL get_relocbase(caddr_t mapbase, caddr_t *relocbase) +{ + Elf_Half i; +#ifdef _WIN64 + const Elf64_Ehdr *elf_header = (Elf64_Ehdr*) mapbase; +#else + const Elf32_Ehdr *elf_header = (Elf32_Ehdr*) mapbase; +#endif + const Elf_Phdr *prog_header = (const Elf_Phdr *)(mapbase + elf_header->e_phoff); + + for (i = 0; i < elf_header->e_phnum; i++) + { + if (prog_header->p_type == PT_LOAD) + { + caddr_t desired_base = (caddr_t)((prog_header->p_vaddr / prog_header->p_align) * prog_header->p_align); + *relocbase = (caddr_t) (mapbase - desired_base); + return TRUE; + } + prog_header++; + } + return FALSE; +} +#endif /************************************************************************* * call_constructors @@ -1326,11 +1355,12 @@ static void call_constructors( WINE_MODREF *wm ) { #ifdef HAVE_DLINFO - extern char **__wine_main_environ; struct link_map *map; void (*init_func)(int, char **, char **) = NULL; void (**init_array)(int, char **, char **) = NULL; ULONG_PTR i, init_arraysz = 0; + int argc; + char **argv, **envp; #ifdef _WIN64 const Elf64_Dyn *dyn; #else @@ -1340,22 +1370,28 @@ if (dlinfo( wm->so_handle, RTLD_DI_LINKMAP, &map ) == -1) return; for (dyn = map->l_ld; dyn->d_tag; dyn++) { + caddr_t relocbase = (caddr_t)map->l_addr; + +#ifdef __FreeBSD__ /* FreeBSD doesn't relocate l_addr */ + if (!get_relocbase(map->l_addr, &relocbase)) return; +#endif switch (dyn->d_tag) { - case 0x60009990: init_array = (void *)((char *)map->l_addr + dyn->d_un.d_val); break; + case 0x60009990: init_array = (void *)(relocbase + dyn->d_un.d_val); break; case 0x60009991: init_arraysz = dyn->d_un.d_val; break; - case 0x60009992: init_func = (void *)((char *)map->l_addr + dyn->d_un.d_val); break; + case 0x60009992: init_func = (void *)(relocbase + dyn->d_un.d_val); break; } } TRACE( "%s: got init_func %p init_array %p %lu\n", debugstr_us( &wm->ldr.BaseDllName ), init_func, init_array, init_arraysz ); - if (init_func) init_func( __wine_main_argc, __wine_main_argv, __wine_main_environ ); + unix_funcs->get_main_args( &argc, &argv, &envp ); + + if (init_func) init_func( argc, argv, envp ); if (init_array) - for (i = 0; i < init_arraysz / sizeof(*init_array); i++) - init_array[i]( __wine_main_argc, __wine_main_argv, __wine_main_environ ); + for (i = 0; i < init_arraysz / sizeof(*init_array); i++) init_array[i]( argc, argv, envp ); #endif } @@ -1822,186 +1858,6 @@ } -/* adjust an array of pointers to make them into RVAs */ -static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count ) -{ - BYTE **src = array; - DWORD *dst = array; - - for ( ; count; count--, src++, dst++) *dst = *src ? *src - base : 0; -} - -/* fixup an array of RVAs by adding the specified delta */ -static inline void fixup_rva_dwords( DWORD *ptr, int delta, unsigned int count ) -{ - for ( ; count; count--, ptr++) if (*ptr) *ptr += delta; -} - - -/* fixup an array of name/ordinal RVAs by adding the specified delta */ -static inline void fixup_rva_names( UINT_PTR *ptr, int delta ) -{ - for ( ; *ptr; ptr++) if (!(*ptr & IMAGE_ORDINAL_FLAG)) *ptr += delta; -} - - -/* fixup RVAs in the resource directory */ -static void fixup_so_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta ) -{ - IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); - unsigned int i; - - for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++) - { - void *ptr = root + entry->u2.s2.OffsetToDirectory; - if (entry->u2.s2.DataIsDirectory) fixup_so_resources( ptr, root, delta ); - else fixup_rva_dwords( &((IMAGE_RESOURCE_DATA_ENTRY *)ptr)->OffsetToData, delta, 1 ); - } -} - -/************************************************************************* - * map_so_dll - * - * Map a builtin dll in memory and fixup RVAs. - */ -static NTSTATUS map_so_dll( const IMAGE_NT_HEADERS *nt_descr, HMODULE module ) -{ - static const char builtin_signature[32] = "Wine builtin DLL"; - IMAGE_DATA_DIRECTORY *dir; - IMAGE_DOS_HEADER *dos; - IMAGE_NT_HEADERS *nt; - IMAGE_SECTION_HEADER *sec; - BYTE *addr = (BYTE *)module; - DWORD code_start, code_end, data_start, data_end, align_mask; - int delta, nb_sections = 2; /* code + data */ - unsigned int i; - DWORD size = (sizeof(IMAGE_DOS_HEADER) - + sizeof(builtin_signature) - + sizeof(IMAGE_NT_HEADERS) - + nb_sections * sizeof(IMAGE_SECTION_HEADER)); - - if (wine_anon_mmap( addr, size, PROT_READ | PROT_WRITE, MAP_FIXED ) != addr) return STATUS_NO_MEMORY; - - dos = (IMAGE_DOS_HEADER *)addr; - nt = (IMAGE_NT_HEADERS *)((BYTE *)(dos + 1) + sizeof(builtin_signature)); - sec = (IMAGE_SECTION_HEADER *)(nt + 1); - - /* build the DOS and NT headers */ - - dos->e_magic = IMAGE_DOS_SIGNATURE; - dos->e_cblp = 0x90; - dos->e_cp = 3; - dos->e_cparhdr = (sizeof(*dos) + 0xf) / 0x10; - dos->e_minalloc = 0; - dos->e_maxalloc = 0xffff; - dos->e_ss = 0x0000; - dos->e_sp = 0x00b8; - dos->e_lfanew = sizeof(*dos) + sizeof(builtin_signature); - - *nt = *nt_descr; - - delta = (const BYTE *)nt_descr - addr; - align_mask = nt->OptionalHeader.SectionAlignment - 1; - code_start = (size + align_mask) & ~align_mask; - data_start = delta & ~align_mask; -#ifdef __APPLE__ - { - Dl_info dli; - unsigned long data_size; - /* need the mach_header, not the PE header, to give to getsegmentdata(3) */ - dladdr(addr, &dli); - code_end = getsegmentdata(dli.dli_fbase, "__DATA", &data_size) - addr; - data_end = (code_end + data_size + align_mask) & ~align_mask; - } -#else - code_end = data_start; - data_end = (nt->OptionalHeader.SizeOfImage + delta + align_mask) & ~align_mask; -#endif - - fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 ); - - nt->FileHeader.NumberOfSections = nb_sections; - nt->OptionalHeader.BaseOfCode = code_start; -#ifndef _WIN64 - nt->OptionalHeader.BaseOfData = data_start; -#endif - nt->OptionalHeader.SizeOfCode = code_end - code_start; - nt->OptionalHeader.SizeOfInitializedData = data_end - data_start; - nt->OptionalHeader.SizeOfUninitializedData = 0; - nt->OptionalHeader.SizeOfImage = data_end; - nt->OptionalHeader.ImageBase = (ULONG_PTR)addr; - - /* build the code section */ - - memcpy( sec->Name, ".text", sizeof(".text") ); - sec->SizeOfRawData = code_end - code_start; - sec->Misc.VirtualSize = sec->SizeOfRawData; - sec->VirtualAddress = code_start; - sec->PointerToRawData = code_start; - sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ); - sec++; - - /* build the data section */ - - memcpy( sec->Name, ".data", sizeof(".data") ); - sec->SizeOfRawData = data_end - data_start; - sec->Misc.VirtualSize = sec->SizeOfRawData; - sec->VirtualAddress = data_start; - sec->PointerToRawData = data_start; - sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA | - IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ); - sec++; - - for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++) - fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 ); - - /* build the import directory */ - - dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY]; - if (dir->Size) - { - IMAGE_IMPORT_DESCRIPTOR *imports = (IMAGE_IMPORT_DESCRIPTOR *)(addr + dir->VirtualAddress); - - while (imports->Name) - { - fixup_rva_dwords( &imports->u.OriginalFirstThunk, delta, 1 ); - fixup_rva_dwords( &imports->Name, delta, 1 ); - fixup_rva_dwords( &imports->FirstThunk, delta, 1 ); - if (imports->u.OriginalFirstThunk) - fixup_rva_names( (UINT_PTR *)(addr + imports->u.OriginalFirstThunk), delta ); - if (imports->FirstThunk) - fixup_rva_names( (UINT_PTR *)(addr + imports->FirstThunk), delta ); - imports++; - } - } - - /* build the resource directory */ - - dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY]; - if (dir->Size) - { - void *ptr = addr + dir->VirtualAddress; - fixup_so_resources( ptr, ptr, delta ); - } - - /* build the export directory */ - - dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY]; - if (dir->Size) - { - IMAGE_EXPORT_DIRECTORY *exports = (IMAGE_EXPORT_DIRECTORY *)(addr + dir->VirtualAddress); - - fixup_rva_dwords( &exports->Name, delta, 1 ); - fixup_rva_dwords( &exports->AddressOfFunctions, delta, 1 ); - fixup_rva_dwords( &exports->AddressOfNames, delta, 1 ); - fixup_rva_dwords( &exports->AddressOfNameOrdinals, delta, 1 ); - fixup_rva_dwords( (DWORD *)(addr + exports->AddressOfNames), delta, exports->NumberOfNames ); - fixup_rva_ptrs( addr + exports->AddressOfFunctions, addr, exports->NumberOfFunctions ); - } - return STATUS_SUCCESS; -} - - /************************************************************************* * build_so_dll_module * @@ -2719,6 +2575,10 @@ char *ptr, *file; NTSTATUS status = STATUS_DLL_NOT_FOUND; BOOL found_image = FALSE; + const char **dll_paths; + SIZE_T dll_path_maxlen; + + unix_funcs->get_dll_path( &dll_paths, &dll_path_maxlen ); len = wcslen( name ); if (build_dir) maxlen = strlen(build_dir) + sizeof("/programs/") + len; @@ -2847,7 +2707,7 @@ } else { - if ((info.status = map_so_dll( nt, module ))) goto failed; + if ((info.status = unix_funcs->map_so_dll( nt, module ))) goto failed; if ((info.status = build_so_dll_module( load_path, &win_name, module, flags, &info.wm ))) goto failed; TRACE_(loaddll)( "Loaded %s at %p: builtin\n", @@ -3012,7 +2872,7 @@ goto done; } - needed = (wcslen(user_shared_data->NtSystemRoot) * sizeof(WCHAR) + + needed = (wcslen(windows_dir) * sizeof(WCHAR) + sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + nameW.Length + 2*sizeof(WCHAR)); if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed ))) @@ -3020,7 +2880,7 @@ status = STATUS_NO_MEMORY; goto done; } - wcscpy( p, user_shared_data->NtSystemRoot ); + wcscpy( p, windows_dir ); p += wcslen(p); memcpy( p, winsxsW, sizeof(winsxsW) ); p += ARRAY_SIZE( winsxsW ); @@ -4463,6 +4323,33 @@ } +static NTSTATUS load_ntdll_so( HMODULE module, const IMAGE_NT_HEADERS *nt ) +{ + NTSTATUS (__cdecl *init_func)( HMODULE module, const void *ptr_in, void *ptr_out ); + Dl_info info; + char *name; + void *handle; + + if (!dladdr( load_ntdll_so, &info )) + { + fprintf( stderr, "cannot get path to ntdll.dll.so\n" ); + exit(1); + } + name = strdup( info.dli_fname ); + strcpy( name + strlen(name) - strlen(".dll.so"), ".so" ); + if (!(handle = dlopen( name, RTLD_NOW ))) + { + fprintf( stderr, "failed to load %s: %s\n", name, dlerror() ); + exit(1); + } + if (!(init_func = dlsym( handle, "__wine_init_unix_lib" ))) + { + fprintf( stderr, "init func not found in %s\n", name ); + exit(1); + } + return init_func( module, nt, &unix_funcs ); +} + /*********************************************************************** * __wine_process_init */ @@ -4484,8 +4371,13 @@ INITIAL_TEB stack; BOOL suspend; SIZE_T info_size; - TEB *teb = thread_init(); - PEB *peb = teb->Peb; + TEB *teb; + PEB *peb; + + if (!unix_funcs) load_ntdll_so( ntdll_module, &__wine_spec_nt_header ); + + teb = thread_init(); + peb = teb->Peb; /* setup the server connection */ server_init_process(); @@ -4510,7 +4402,6 @@ /* setup the load callback and create ntdll modref */ RtlInitUnicodeString( &nt_name, ntdllW ); - map_so_dll( &__wine_spec_nt_header, ntdll_module ); status = build_so_dll_module( params->DllPath.Buffer, &nt_name, ntdll_module, 0, &wm ); assert( !status ); @@ -4586,3 +4477,13 @@ server_init_process_done(); } + +/*********************************************************************** + * __wine_set_unix_funcs + */ +void CDECL __wine_set_unix_funcs( int version, const struct unix_funcs *funcs ) +{ + assert( version == NTDLL_UNIXLIB_VERSION ); + unix_funcs = funcs; + __wine_process_init(); +} diff -Nru wine-development-5.8/dlls/ntdll/locale.c wine-development-5.9/dlls/ntdll/locale.c --- wine-development-5.8/dlls/ntdll/locale.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/locale.c 2020-05-22 18:49:34.000000000 +0000 @@ -23,7 +23,6 @@ #include "wine/port.h" #include -#include #include #include #include @@ -693,133 +692,11 @@ } -#if !defined(__APPLE__) && !defined(__ANDROID__) /* these platforms always use UTF-8 */ - -/* charset to codepage map, sorted by name */ -static const struct { const char *name; UINT cp; } charset_names[] = -{ - { "ANSIX341968", 20127 }, - { "BIG5", 950 }, - { "BIG5HKSCS", 950 }, - { "CP1250", 1250 }, - { "CP1251", 1251 }, - { "CP1252", 1252 }, - { "CP1253", 1253 }, - { "CP1254", 1254 }, - { "CP1255", 1255 }, - { "CP1256", 1256 }, - { "CP1257", 1257 }, - { "CP1258", 1258 }, - { "CP932", 932 }, - { "CP936", 936 }, - { "CP949", 949 }, - { "CP950", 950 }, - { "EUCJP", 20932 }, - { "EUCKR", 949 }, - { "GB18030", 936 /* 54936 */ }, - { "GB2312", 936 }, - { "GBK", 936 }, - { "IBM037", 37 }, - { "IBM1026", 1026 }, - { "IBM424", 20424 }, - { "IBM437", 437 }, - { "IBM500", 500 }, - { "IBM850", 850 }, - { "IBM852", 852 }, - { "IBM855", 855 }, - { "IBM857", 857 }, - { "IBM860", 860 }, - { "IBM861", 861 }, - { "IBM862", 862 }, - { "IBM863", 863 }, - { "IBM864", 864 }, - { "IBM865", 865 }, - { "IBM866", 866 }, - { "IBM869", 869 }, - { "IBM874", 874 }, - { "IBM875", 875 }, - { "ISO88591", 28591 }, - { "ISO885913", 28603 }, - { "ISO885915", 28605 }, - { "ISO88592", 28592 }, - { "ISO88593", 28593 }, - { "ISO88594", 28594 }, - { "ISO88595", 28595 }, - { "ISO88596", 28596 }, - { "ISO88597", 28597 }, - { "ISO88598", 28598 }, - { "ISO88599", 28599 }, - { "KOI8R", 20866 }, - { "KOI8U", 21866 }, - { "TIS620", 28601 }, - { "UTF8", CP_UTF8 } -}; - -static void load_unix_cptable( unsigned int cp ) -{ - const char *dir = build_dir ? build_dir : data_dir; - struct stat st; - char *name; - USHORT *data; - int fd; - - if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, strlen(dir) + 22 ))) return; - sprintf( name, "%s/nls/c_%03u.nls", dir, cp ); - if ((fd = open( name, O_RDONLY )) != -1) - { - fstat( fd, &st ); - if ((data = RtlAllocateHeap( GetProcessHeap(), 0, st.st_size )) && - st.st_size > 0x10000 && - read( fd, data, st.st_size ) == st.st_size) - { - RtlInitCodePageTable( data, &unix_table ); - } - else - { - RtlFreeHeap( GetProcessHeap(), 0, data ); - } - close( fd ); - } - else ERR( "failed to load %s\n", debugstr_a(name) ); - RtlFreeHeap( GetProcessHeap(), 0, name ); -} - void init_unix_codepage(void) { - char charset_name[16]; - const char *name; - size_t i, j; - int min = 0, max = ARRAY_SIZE(charset_names) - 1; - - setlocale( LC_CTYPE, "" ); - if (!(name = nl_langinfo( CODESET ))) return; - - /* remove punctuation characters from charset name */ - for (i = j = 0; name[i] && j < sizeof(charset_name)-1; i++) - if (isalnum((unsigned char)name[i])) charset_name[j++] = name[i]; - charset_name[j] = 0; - - while (min <= max) - { - int pos = (min + max) / 2; - int res = _strnicmp( charset_names[pos].name, charset_name, -1 ); - if (!res) - { - if (charset_names[pos].cp != CP_UTF8) load_unix_cptable( charset_names[pos].cp ); - return; - } - if (res > 0) max = pos - 1; - else min = pos + 1; - } - ERR( "unrecognized charset '%s'\n", name ); + unix_funcs->get_unix_codepage( &unix_table ); } -#else /* __APPLE__ || __ANDROID__ */ - -void init_unix_codepage(void) { } - -#endif /* __APPLE__ || __ANDROID__ */ - /* Unix format is: lang[_country][.charset][@modifier] * Windows format is: lang[-script][-country][_modifier] */ static LCID unix_locale_to_lcid( const char *unix_name ) @@ -1127,6 +1004,105 @@ return STATUS_SUCCESS; } + +static NTSTATUS get_dummy_preferred_ui_language( DWORD flags, LANGID lang, ULONG *count, + WCHAR *buffer, ULONG *size ) +{ + WCHAR name[LOCALE_NAME_MAX_LENGTH + 2]; + NTSTATUS status; + ULONG len; + + FIXME("(0x%x %p %p %p) returning a dummy value (current locale)\n", flags, count, buffer, size); + + status = load_string( (flags & MUI_LANGUAGE_ID) ? LOCALE_ILANGUAGE : LOCALE_SNAME, + lang, name, ARRAY_SIZE(name) ); + if (status) return status; + + len = wcslen( name ) + 2; + name[len - 1] = 0; + if (buffer) + { + if (len > *size) + { + *size = len; + return STATUS_BUFFER_TOO_SMALL; + } + memcpy( buffer, name, len * sizeof(WCHAR) ); + } + *size = len; + *count = 1; + TRACE("returned variable content: %d, \"%s\", %d\n", *count, debugstr_w(buffer), *size); + return STATUS_SUCCESS; + +} + +/************************************************************************** + * RtlGetProcessPreferredUILanguages (NTDLL.@) + */ +NTSTATUS WINAPI RtlGetProcessPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size ) +{ + FIXME( "%08x, %p, %p %p\n", flags, count, buffer, size ); + return get_dummy_preferred_ui_language( flags, user_ui_language, count, buffer, size ); +} + + +/************************************************************************** + * RtlGetSystemPreferredUILanguages (NTDLL.@) + */ +NTSTATUS WINAPI RtlGetSystemPreferredUILanguages( DWORD flags, ULONG unknown, ULONG *count, + WCHAR *buffer, ULONG *size ) +{ + if (flags & ~(MUI_LANGUAGE_NAME | MUI_LANGUAGE_ID | MUI_MACHINE_LANGUAGE_SETTINGS)) return STATUS_INVALID_PARAMETER; + if ((flags & MUI_LANGUAGE_NAME) && (flags & MUI_LANGUAGE_ID)) return STATUS_INVALID_PARAMETER; + if (*size && !buffer) return STATUS_INVALID_PARAMETER; + + return get_dummy_preferred_ui_language( flags, system_ui_language, count, buffer, size ); +} + + +/************************************************************************** + * RtlGetThreadPreferredUILanguages (NTDLL.@) + */ +NTSTATUS WINAPI RtlGetThreadPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size ) +{ + FIXME( "%08x, %p, %p %p\n", flags, count, buffer, size ); + return get_dummy_preferred_ui_language( flags, user_ui_language, count, buffer, size ); +} + + +/************************************************************************** + * RtlGetUserPreferredUILanguages (NTDLL.@) + */ +NTSTATUS WINAPI RtlGetUserPreferredUILanguages( DWORD flags, ULONG unknown, ULONG *count, + WCHAR *buffer, ULONG *size ) +{ + if (flags & ~(MUI_LANGUAGE_NAME | MUI_LANGUAGE_ID)) return STATUS_INVALID_PARAMETER; + if ((flags & MUI_LANGUAGE_NAME) && (flags & MUI_LANGUAGE_ID)) return STATUS_INVALID_PARAMETER; + if (*size && !buffer) return STATUS_INVALID_PARAMETER; + + return get_dummy_preferred_ui_language( flags, user_ui_language, count, buffer, size ); +} + + +/************************************************************************** + * RtlSetProcessPreferredUILanguages (NTDLL.@) + */ +NTSTATUS WINAPI RtlSetProcessPreferredUILanguages( DWORD flags, PCZZWSTR buffer, ULONG *count ) +{ + FIXME( "%u, %p, %p\n", flags, buffer, count ); + return STATUS_SUCCESS; +} + + +/************************************************************************** + * RtlSetThreadPreferredUILanguages (NTDLL.@) + */ +NTSTATUS WINAPI RtlSetThreadPreferredUILanguages( DWORD flags, PCZZWSTR buffer, ULONG *count ) +{ + FIXME( "%u, %p, %p\n", flags, buffer, count ); + return STATUS_SUCCESS; +} + /************************************************************************** * NtGetNlsSectionPtr (NTDLL.@) diff -Nru wine-development-5.8/dlls/ntdll/Makefile.in wine-development-5.9/dlls/ntdll/Makefile.in --- wine-development-5.8/dlls/ntdll/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -3,7 +3,7 @@ IMPORTLIB = ntdll IMPORTS = winecrt0 EXTRAINCL = $(UNWIND_CFLAGS) -EXTRALIBS = -lwine $(IOKIT_LIBS) $(RT_LIBS) $(PTHREAD_LIBS) $(UNWIND_LIBS) +EXTRALIBS = -lwine $(IOKIT_LIBS) $(COREFOUNDATION_LIBS) $(CORESERVICES_LIBS) $(RT_LIBS) $(PTHREAD_LIBS) $(UNWIND_LIBS) $(I386_LIBS) EXTRADLLFLAGS = -nodefaultlibs -Wl,--image-base,0x7bc00000 C_SRCS = \ @@ -13,7 +13,6 @@ critsection.c \ crypt.c \ debugbuffer.c \ - debugtools.c \ directory.c \ env.c \ error.c \ @@ -51,15 +50,29 @@ thread.c \ threadpool.c \ time.c \ + unix/debug.c \ + unix/loader.c \ + unix/virtual.c \ version.c \ virtual.c \ wcstring.c RC_SRCS = version.rc +EXTRA_OBJS = unix/version.o + server_EXTRADEFS = \ -DBINDIR=\"${bindir}\" \ - -DDLLDIR=\"${dlldir}\" \ -DBIN_TO_DLLDIR=\"`$(MAKEDEP) -R ${bindir} ${dlldir}`\" \ + -DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\" + +unix_loader_EXTRADEFS = \ + -DBINDIR=\"${bindir}\" \ -DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\" \ -DBIN_TO_DATADIR=\"`$(MAKEDEP) -R ${bindir} ${datadir}/wine`\" + +unix/version.c: dummy + version=`(GIT_DIR=$(top_srcdir)/.git git describe HEAD 2>/dev/null || echo "wine-$(PACKAGE_VERSION)") | sed -n -e '$$s/\(.*\)/const char wine_build[] = "\1";/p'` && (echo $$version | cmp -s - $@) || echo $$version >$@ || (rm -f $@ && exit 1) + +dummy: +.PHONY: dummy diff -Nru wine-development-5.8/dlls/ntdll/misc.c wine-development-5.9/dlls/ntdll/misc.c --- wine-development-5.8/dlls/ntdll/misc.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/misc.c 2020-05-22 18:49:34.000000000 +0000 @@ -23,13 +23,9 @@ #include #include -#ifdef HAVE_SYS_UTSNAME_H -#include -#endif #include "ntstatus.h" #define WIN32_NO_STATUS -#include "wine/library.h" #include "wine/debug.h" #include "ntdll_misc.h" #include "wmistr.h" @@ -41,7 +37,7 @@ LPCSTR debugstr_ObjectAttributes(const OBJECT_ATTRIBUTES *oa) { if (!oa) return ""; - return wine_dbg_sprintf( "{name=%s, attr=0x%08x, hRoot=%p, sd=%p}\n", + return wine_dbg_sprintf( "{name=%s, attr=0x%08x, hRoot=%p, sd=%p}", debugstr_us(oa->ObjectName), oa->Attributes, oa->RootDirectory, oa->SecurityDescriptor ); } @@ -57,7 +53,7 @@ */ const char * CDECL NTDLL_wine_get_version(void) { - return wine_get_version(); + return unix_funcs->get_version(); } /********************************************************************* @@ -65,7 +61,7 @@ */ const char * CDECL NTDLL_wine_get_build_id(void) { - return wine_get_build_id(); + return unix_funcs->get_build_id(); } /********************************************************************* @@ -73,21 +69,7 @@ */ void CDECL NTDLL_wine_get_host_version( const char **sysname, const char **release ) { -#ifdef HAVE_SYS_UTSNAME_H - static struct utsname buf; - static BOOL init_done; - - if (!init_done) - { - uname( &buf ); - init_done = TRUE; - } - if (sysname) *sysname = buf.sysname; - if (release) *release = buf.release; -#else - if (sysname) *sysname = ""; - if (release) *release = ""; -#endif + return unix_funcs->get_host_version( sysname, release ); } /********************************************************************* @@ -585,7 +567,7 @@ /****************************************************************************** * EtwTraceMessage (NTDLL.@) */ -ULONG WINAPIV EtwTraceMessage( TRACEHANDLE handle, ULONG flags, LPGUID guid, USHORT number, ... ) +ULONG WINAPIV EtwTraceMessage( TRACEHANDLE handle, ULONG flags, LPGUID guid, /*USHORT*/ ULONG number, ... ) { __ms_va_list valist; ULONG ret; diff -Nru wine-development-5.8/dlls/ntdll/nt.c wine-development-5.9/dlls/ntdll/nt.c --- wine-development-5.8/dlls/ntdll/nt.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/nt.c 2020-05-22 18:49:34.000000000 +0000 @@ -1091,6 +1091,7 @@ if(regs2[3] & (1 << 3 )) info->FeatureSet |= CPU_FEATURE_PSE; if(regs2[3] & (1 << 4 )) info->FeatureSet |= CPU_FEATURE_TSC; + if(regs2[3] & (1 << 6 )) info->FeatureSet |= CPU_FEATURE_PAE; if(regs2[3] & (1 << 8 )) info->FeatureSet |= CPU_FEATURE_CX8; if(regs2[3] & (1 << 11)) info->FeatureSet |= CPU_FEATURE_SEP; if(regs2[3] & (1 << 12)) info->FeatureSet |= CPU_FEATURE_MTRR; @@ -1100,20 +1101,12 @@ if(regs2[3] & (1 << 24)) info->FeatureSet |= CPU_FEATURE_FXSR; if(regs2[3] & (1 << 25)) info->FeatureSet |= CPU_FEATURE_SSE; if(regs2[3] & (1 << 26)) info->FeatureSet |= CPU_FEATURE_SSE2; + if(regs2[2] & (1 << 0 )) info->FeatureSet |= CPU_FEATURE_SSE3; + if(regs2[2] & (1 << 13)) info->FeatureSet |= CPU_FEATURE_CX128; + if(regs2[2] & (1 << 27)) info->FeatureSet |= CPU_FEATURE_XSAVE; - user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = !(regs2[3] & 1); - user_shared_data->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = (regs2[3] >> 4) & 1; - user_shared_data->ProcessorFeatures[PF_PAE_ENABLED] = (regs2[3] >> 6) & 1; - user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = (regs2[3] >> 8) & 1; - user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = (regs2[3] >> 23) & 1; - user_shared_data->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = (regs2[3] >> 25) & 1; - user_shared_data->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = (regs2[3] >> 26) & 1; - user_shared_data->ProcessorFeatures[PF_SSE3_INSTRUCTIONS_AVAILABLE] = regs2[2] & 1; - user_shared_data->ProcessorFeatures[PF_XSAVE_ENABLED] = (regs2[2] >> 27) & 1; - user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE128] = (regs2[2] >> 13) & 1; - - if((regs2[3] & (1 << 26)) && (regs2[3] & (1 << 24))) /* has SSE2 and FXSAVE/FXRSTOR */ - user_shared_data->ProcessorFeatures[PF_SSE_DAZ_MODE_AVAILABLE] = have_sse_daz_mode(); + if((regs2[3] & (1 << 26)) && (regs2[3] & (1 << 24)) && have_sse_daz_mode()) /* has SSE2 and FXSAVE/FXRSTOR */ + info->FeatureSet |= CPU_FEATURE_DAZ; if (regs[1] == AUTH && regs[3] == ENTI && regs[2] == CAMD) { @@ -1130,11 +1123,10 @@ if (regs[0] >= 0x80000001) { do_cpuid(0x80000001, regs2); /* get vendor features */ - user_shared_data->ProcessorFeatures[PF_VIRT_FIRMWARE_ENABLED] = (regs2[2] >> 2) & 1; - user_shared_data->ProcessorFeatures[PF_NX_ENABLED] = (regs2[3] >> 20) & 1; - user_shared_data->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = (regs2[3] >> 31) & 1; - user_shared_data->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = (regs2[3] >> 27) & 1; - if (regs2[3] >> 31) info->FeatureSet |= CPU_FEATURE_3DNOW; + if (regs2[2] & (1 << 2)) info->FeatureSet |= CPU_FEATURE_VIRT; + if (regs2[3] & (1 << 20)) info->FeatureSet |= CPU_FEATURE_NX; + if (regs2[3] & (1 << 27)) info->FeatureSet |= CPU_FEATURE_TSC; + if (regs2[3] & (1u << 31)) info->FeatureSet |= CPU_FEATURE_3DNOW; } } else if (regs[1] == GENU && regs[3] == INEI && regs[2] == NTEL) @@ -1147,15 +1139,15 @@ info->Revision |= ((regs2[0] >> 4 ) & 0xf) << 8; /* model */ info->Revision |= regs2[0] & 0xf; /* stepping */ + if(regs2[2] & (1 << 5)) info->FeatureSet |= CPU_FEATURE_VIRT; if(regs2[3] & (1 << 21)) info->FeatureSet |= CPU_FEATURE_DS; - user_shared_data->ProcessorFeatures[PF_VIRT_FIRMWARE_ENABLED] = (regs2[2] >> 5) & 1; do_cpuid(0x80000000, regs); /* get vendor cpuid level */ if (regs[0] >= 0x80000001) { do_cpuid(0x80000001, regs2); /* get vendor features */ - user_shared_data->ProcessorFeatures[PF_NX_ENABLED] = (regs2[3] >> 20) & 1; - user_shared_data->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = (regs2[3] >> 27) & 1; + if (regs2[3] & (1 << 20)) info->FeatureSet |= CPU_FEATURE_NX; + if (regs2[3] & (1 << 27)) info->FeatureSet |= CPU_FEATURE_TSC; } } else @@ -1178,10 +1170,6 @@ int value; valSize = sizeof(value); - if (sysctlbyname("hw.optional.floatingpoint", &value, &valSize, NULL, 0) == 0) - user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = !value; - - valSize = sizeof(value); if (sysctlbyname("hw.cpusubtype", &value, &valSize, NULL, 0) == 0) { switch (value) @@ -1247,10 +1235,8 @@ } if (!_stricmp(line, "features")) { - if (strstr(value, "vfpv3")) - user_shared_data->ProcessorFeatures[PF_ARM_VFP_32_REGISTERS_AVAILABLE] = TRUE; - if (strstr(value, "neon")) - user_shared_data->ProcessorFeatures[PF_ARM_NEON_INSTRUCTIONS_AVAILABLE] = TRUE; + if (strstr(value, "vfpv3")) info->FeatureSet |= CPU_FEATURE_ARM_VFP_32; + if (strstr(value, "neon")) info->FeatureSet |= CPU_FEATURE_ARM_NEON; continue; } } @@ -1268,12 +1254,10 @@ valsize = sizeof(value); if (!sysctlbyname("hw.floatingpoint", &value, &valsize, NULL, 0)) - user_shared_data->ProcessorFeatures[PF_ARM_VFP_32_REGISTERS_AVAILABLE] = value; + info->FeatureSet |= CPU_FEATURE_ARM_VFP_32; #else FIXME("CPU Feature detection not implemented.\n"); #endif - if (info->Level >= 8) - user_shared_data->ProcessorFeatures[PF_ARM_V8_INSTRUCTIONS_AVAILABLE] = TRUE; info->Architecture = PROCESSOR_ARCHITECTURE_ARM; } @@ -1315,10 +1299,8 @@ } if (!_stricmp(line, "Features")) { - if (strstr(value, "crc32")) - user_shared_data->ProcessorFeatures[PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE] = TRUE; - if (strstr(value, "aes")) - user_shared_data->ProcessorFeatures[PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE] = TRUE; + if (strstr(value, "crc32")) info->FeatureSet |= CPU_FEATURE_ARM_V8_CRC32; + if (strstr(value, "aes")) info->FeatureSet |= CPU_FEATURE_ARM_V8_CRYPTO; continue; } } @@ -1328,7 +1310,6 @@ FIXME("CPU Feature detection not implemented.\n"); #endif info->Level = max(info->Level, 8); - user_shared_data->ProcessorFeatures[PF_ARM_V8_INSTRUCTIONS_AVAILABLE] = TRUE; info->Architecture = PROCESSOR_ARCHITECTURE_ARM64; } @@ -2191,19 +2172,21 @@ *required_len = sizeof(struct smbios_prologue); +#define L(l) (l + (l ? 1 : 0)) *required_len += sizeof(struct smbios_bios); - *required_len += max(bios_vendor_len + bios_version_len + bios_date_len + 4, 2); + *required_len += max(L(bios_vendor_len) + L(bios_version_len) + L(bios_date_len) + 1, 2); *required_len += sizeof(struct smbios_system); - *required_len += max(system_vendor_len + system_product_len + system_version_len + - system_serial_len + system_sku_len + system_family_len + 7, 2); + *required_len += max(L(system_vendor_len) + L(system_product_len) + L(system_version_len) + + L(system_serial_len) + L(system_sku_len) + L(system_family_len) + 1, 2); *required_len += sizeof(struct smbios_board); - *required_len += max(board_vendor_len + board_product_len + board_version_len + board_serial_len + 5, 2); + *required_len += max(L(board_vendor_len) + L(board_product_len) + L(board_version_len) + L(board_serial_len) + 1, 2); *required_len += sizeof(struct smbios_chassis); - *required_len += max(chassis_vendor_len + chassis_version_len + chassis_serial_len + - chassis_asset_tag_len + 5, 2); + *required_len += max(L(chassis_vendor_len) + L(chassis_version_len) + L(chassis_serial_len) + + L(chassis_asset_tag_len) + 1, 2); +#undef L sfti->TableBufferLength = *required_len; @@ -2954,6 +2937,19 @@ FIXME("info_class SYSTEM_INTERRUPT_INFORMATION\n"); } break; + case SystemTimeAdjustmentInformation: + { + SYSTEM_TIME_ADJUSTMENT_QUERY query = { 156250, 156250, TRUE }; + + len = sizeof(query); + if (Length == len) + { + if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; + else memcpy( SystemInformation, &query, len ); + } + else ret = STATUS_INFO_LENGTH_MISMATCH; + } + break; case SystemKernelDebuggerInformation: { SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi; @@ -3032,7 +3028,14 @@ if (Length >= len) { if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; - else *((DWORD *)SystemInformation) = 64; + else + { +#ifdef __arm__ + *((DWORD *)SystemInformation) = 32; +#else + *((DWORD *)SystemInformation) = 64; +#endif + } } else ret = STATUS_INFO_LENGTH_MISMATCH; } diff -Nru wine-development-5.8/dlls/ntdll/ntdll_misc.h wine-development-5.9/dlls/ntdll/ntdll_misc.h --- wine-development-5.8/dlls/ntdll/ntdll_misc.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/ntdll_misc.h 2020-05-22 18:49:34.000000000 +0000 @@ -27,6 +27,7 @@ #include "windef.h" #include "winnt.h" #include "winternl.h" +#include "unixlib.h" #include "wine/server.h" #include "wine/asm.h" @@ -98,7 +99,6 @@ extern void init_unix_codepage(void) DECLSPEC_HIDDEN; extern void init_locale( HMODULE module ) DECLSPEC_HIDDEN; extern void init_user_process_params( SIZE_T data_size ) DECLSPEC_HIDDEN; -extern void init_paths(void) DECLSPEC_HIDDEN; extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN; extern NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS status ) DECLSPEC_HIDDEN; @@ -110,8 +110,6 @@ extern const char *build_dir DECLSPEC_HIDDEN; extern const char *data_dir DECLSPEC_HIDDEN; extern const char *config_dir DECLSPEC_HIDDEN; -extern const char **dll_paths DECLSPEC_HIDDEN; -extern size_t dll_path_maxlen DECLSPEC_HIDDEN; extern timeout_t server_start_time DECLSPEC_HIDDEN; extern unsigned int server_cpus DECLSPEC_HIDDEN; extern BOOL is_wow64 DECLSPEC_HIDDEN; @@ -146,9 +144,11 @@ FARPROC origfun, DWORD ordinal, const WCHAR *user ) DECLSPEC_HIDDEN; extern void RELAY_SetupDLL( HMODULE hmod ) DECLSPEC_HIDDEN; extern void SNOOP_SetupDLL( HMODULE hmod ) DECLSPEC_HIDDEN; +extern const WCHAR windows_dir[] DECLSPEC_HIDDEN; extern const WCHAR system_dir[] DECLSPEC_HIDDEN; extern const WCHAR syswow64_dir[] DECLSPEC_HIDDEN; +extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN; extern void (WINAPI *kernel32_start_process)(LPTHREAD_START_ROUTINE,void*) DECLSPEC_HIDDEN; /* Device IO */ @@ -221,6 +221,7 @@ extern void virtual_fill_image_information( const pe_image_info_t *pe_info, SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; +extern HANDLE user_shared_data_init_done(void) DECLSPEC_HIDDEN; /* completion */ extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue, @@ -324,6 +325,7 @@ LONG __cdecl NTDLL_wcstol( LPCWSTR s, LPWSTR *end, INT base ); ULONG __cdecl NTDLL_wcstoul( LPCWSTR s, LPWSTR *end, INT base ); int WINAPIV NTDLL_swprintf( WCHAR *str, const WCHAR *format, ... ); +int WINAPIV _snwprintf_s( WCHAR *str, SIZE_T size, SIZE_T len, const WCHAR *format, ... ); #define wcsicmp(s1,s2) NTDLL__wcsicmp(s1,s2) #define wcsnicmp(s1,s2,n) NTDLL__wcsnicmp(s1,s2,n) diff -Nru wine-development-5.8/dlls/ntdll/ntdll.spec wine-development-5.9/dlls/ntdll/ntdll.spec --- wine-development-5.8/dlls/ntdll/ntdll.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/ntdll.spec 2020-05-22 18:49:34.000000000 +0000 @@ -667,7 +667,8 @@ @ stub RtlFlushPropertySet # @ stub RtlFlushSecureMemoryCache @ stdcall RtlFormatCurrentUserKeyPath(ptr) -@ stdcall RtlFormatMessage(ptr long long long long ptr ptr long) +@ stdcall RtlFormatMessage(ptr long long long long ptr ptr long ptr) +@ stdcall RtlFormatMessageEx(ptr long long long long ptr ptr long ptr long) @ stdcall RtlFreeAnsiString(ptr) @ stdcall RtlFreeHandle(ptr ptr) @ stdcall RtlFreeHeap(long long ptr) @@ -710,15 +711,19 @@ @ stdcall RtlGetOwnerSecurityDescriptor(ptr ptr ptr) @ stdcall RtlGetProductInfo(long long long long ptr) @ stdcall RtlGetProcessHeaps(long ptr) +@ stdcall RtlGetProcessPreferredUILanguages(long ptr ptr ptr) @ stdcall RtlGetSaclSecurityDescriptor(ptr ptr ptr ptr) @ stdcall RtlGetSearchPath(ptr) # @ stub RtlGetSecurityDescriptorRMControl # @ stub RtlGetSetBootStatusData +@ stdcall RtlGetSystemPreferredUILanguages(long long ptr ptr ptr) @ stdcall -ret64 RtlGetSystemTimePrecise() @ stdcall RtlGetThreadErrorMode() +@ stdcall RtlGetThreadPreferredUILanguages(long ptr ptr ptr) @ stdcall RtlGetUnloadEventTrace() @ stdcall RtlGetUnloadEventTraceEx(ptr ptr ptr) @ stub RtlGetUserInfoHeap +@ stdcall RtlGetUserPreferredUILanguages(long long ptr ptr ptr) @ stdcall RtlGetVersion(ptr) @ stdcall -arch=arm,arm64,x86_64 RtlGrowFunctionTable(ptr long) @ stub RtlGuidToPropertySetName @@ -783,10 +788,10 @@ # @ stub RtlIpv6AddressToStringExA # @ stub RtlIpv6AddressToStringExW # @ stub RtlIpv6AddressToStringW -# @ stub RtlIpv6StringToAddressA -# @ stub RtlIpv6StringToAddressExA +@ stdcall RtlIpv6StringToAddressA(str ptr ptr) +@ stdcall RtlIpv6StringToAddressExA(str ptr ptr ptr) @ stdcall RtlIpv6StringToAddressExW(wstr ptr ptr ptr) -# @ stub RtlIpv6StringToAddressW +@ stdcall RtlIpv6StringToAddressW(wstr ptr ptr) @ stdcall RtlIsActivationContextActive(ptr) @ stdcall RtlIsCriticalSectionLocked(ptr) @ stdcall RtlIsCriticalSectionLockedByThread(ptr) @@ -862,6 +867,7 @@ @ stdcall RtlQueryDepthSList(ptr) @ stdcall RtlQueryDynamicTimeZoneInformation(ptr) @ stdcall RtlQueryEnvironmentVariable_U(ptr ptr ptr) +@ stdcall RtlQueryEnvironmentVariable(ptr ptr long ptr long ptr) @ stdcall RtlQueryHeapInformation(long long ptr long ptr) @ stdcall RtlQueryInformationAcl(ptr ptr long long) @ stdcall RtlQueryInformationActivationContext(long long ptr long ptr long ptr) @@ -940,6 +946,7 @@ # @ stub RtlSetMemoryStreamSize @ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long) # @ stub RtlSetProcessIsCritical +@ stdcall RtlSetProcessPreferredUILanguages(long ptr ptr) @ stub RtlSetProperties @ stub RtlSetPropertyClassId @ stub RtlSetPropertyNames @@ -951,6 +958,7 @@ # @ stub RtlSetSecurityObjectEx @ stdcall RtlSetThreadErrorMode(long ptr) # @ stub RtlSetThreadIsCritical +@ stdcall RtlSetThreadPreferredUILanguages(long ptr ptr) # @ stub RtlSetThreadPoolStartFunc @ stdcall RtlSetTimeZoneInformation(ptr) # @ stub RtlSetTimer @@ -1444,8 +1452,10 @@ @ cdecl _memccpy(ptr ptr long long) @ cdecl _memicmp(str str long) @ varargs _snprintf(ptr long str) NTDLL__snprintf -@ varargs _snprintf_s(ptr long long str) _snprintf_s +@ varargs _snprintf_s(ptr long long str) @ varargs _snwprintf(ptr long wstr) NTDLL__snwprintf +@ varargs _snwprintf_s(ptr long long wstr) +@ varargs _swprintf(ptr wstr) NTDLL_swprintf @ cdecl _splitpath(str ptr ptr ptr ptr) @ cdecl _strcmpi(str str) _stricmp @ cdecl _stricmp(str str) @@ -1459,8 +1469,10 @@ @ cdecl _ultoa(long ptr long) @ cdecl _ultow(long ptr long) @ cdecl -norelay _vsnprintf(ptr long str ptr) NTDLL__vsnprintf -@ cdecl _vsnprintf_s(ptr long str ptr) _vsnprintf_s +@ cdecl _vsnprintf_s(ptr long str ptr) @ cdecl _vsnwprintf(ptr long wstr ptr) NTDLL__vsnwprintf +@ cdecl _vsnwprintf_s(ptr long long wstr ptr) +@ cdecl _vswprintf(ptr wstr ptr) NTDLL__vswprintf @ cdecl _wcsicmp(wstr wstr) NTDLL__wcsicmp @ cdecl _wcslwr(wstr) NTDLL__wcslwr @ cdecl _wcsnicmp(wstr wstr long) NTDLL__wcsnicmp @@ -1506,6 +1518,7 @@ @ cdecl qsort(ptr long long ptr) NTDLL_qsort @ cdecl sin(double) NTDLL_sin @ varargs sprintf(ptr str) NTDLL_sprintf +@ varargs sprintf_s(ptr long str) @ cdecl sqrt(double) NTDLL_sqrt @ varargs sscanf(str str) NTDLL_sscanf @ cdecl strcat(str str) NTDLL_strcat @@ -1525,6 +1538,7 @@ @ cdecl strtol(str ptr long) NTDLL_strtol @ cdecl strtoul(str ptr long) NTDLL_strtoul @ varargs swprintf(ptr wstr) NTDLL_swprintf +@ varargs swprintf_s(ptr long wstr) @ cdecl tan(double) NTDLL_tan @ cdecl tolower(long) NTDLL_tolower @ cdecl toupper(long) NTDLL_toupper @@ -1533,6 +1547,8 @@ @ stdcall vDbgPrintEx(long long str ptr) @ stdcall vDbgPrintExWithPrefix(str long long str ptr) @ cdecl vsprintf(ptr str ptr) NTDLL_vsprintf +@ cdecl vsprintf_s(ptr long str ptr) +@ cdecl vswprintf_s(ptr long wstr ptr) @ cdecl wcscat(wstr wstr) NTDLL_wcscat @ cdecl wcschr(wstr long) NTDLL_wcschr @ cdecl wcscmp(wstr wstr) NTDLL_wcscmp @@ -1564,6 +1580,7 @@ @ cdecl wine_server_release_fd(long long) @ cdecl wine_server_send_fd(long) @ cdecl __wine_make_process_system() +@ cdecl __wine_set_unix_funcs(long ptr) @ extern -arch=i386 __wine_ldt_copy # Debugging diff -Nru wine-development-5.8/dlls/ntdll/printf.c wine-development-5.9/dlls/ntdll/printf.c --- wine-development-5.8/dlls/ntdll/printf.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/printf.c 2020-05-22 18:49:34.000000000 +0000 @@ -55,7 +55,7 @@ { char Sign, LeftAlign, Alternate, PadZero; int FieldLength, Precision; - char IntegerLength, IntegerDouble; + char IntegerLength, IntegerDouble, IntegerNative; char WideString; char Format; } pf_flags; @@ -211,8 +211,15 @@ { int r = 0; - if( len < 0 ) - len = wcslen( str ); + if (len < 0) + { + /* Do not search past the length specified by the precision. */ + if (flags->Precision >= 0) + { + for (len = 0; len < flags->Precision; len++) if (!str[len]) break; + } + else len = wcslen( str ); + } if (flags->Precision >= 0 && flags->Precision < len) len = flags->Precision; @@ -233,8 +240,15 @@ { int r = 0; - if( len < 0 ) - len = strlen( str ); + if (len < 0) + { + /* Do not search past the length specified by the precision. */ + if (flags->Precision >= 0) + { + for (len = 0; len < flags->Precision; len++) if (!str[len]) break; + } + else len = strlen( str ); + } if (flags->Precision >= 0 && flags->Precision < len) len = flags->Precision; @@ -270,80 +284,20 @@ return pf_output_format_W( out, str, len, flags); } -static inline BOOL pf_is_integer_format( char fmt ) -{ - static const char float_fmts[] = "diouxX"; - if (!fmt) - return FALSE; - return strchr( float_fmts, fmt ) != 0; -} - -static inline BOOL pf_is_double_format( char fmt ) -{ - static const char float_fmts[] = "aeEfgG"; - if (!fmt) - return FALSE; - return strchr( float_fmts, fmt ) != 0; -} - -static inline BOOL pf_is_valid_format( char fmt ) -{ - static const char float_fmts[] = "acCdeEfgGinouxX"; - if (!fmt) - return FALSE; - return strchr( float_fmts, fmt ) != 0; -} - -static void pf_rebuild_format_string( char *p, pf_flags *flags ) -{ - *p++ = '%'; - if( flags->Sign ) - *p++ = flags->Sign; - if( flags->LeftAlign ) - *p++ = flags->LeftAlign; - if( flags->Alternate ) - *p++ = flags->Alternate; - if( flags->PadZero ) - *p++ = flags->PadZero; - if( flags->FieldLength ) - { - sprintf(p, "%d", flags->FieldLength); - p += strlen(p); - } - if( flags->Precision >= 0 ) - { - sprintf(p, ".%d", flags->Precision); - p += strlen(p); - } - *p++ = flags->Format; - *p++ = 0; -} - /* pf_integer_conv: prints x to buf, including alternate formats and additional precision digits, but not field characters or the sign */ -static void pf_integer_conv( char *buf, int buf_len, pf_flags *flags, - LONGLONG x ) +static void pf_integer_conv( char *buf, pf_flags *flags, LONGLONG x ) { unsigned int base; const char *digits; - int i, j, k; - char number[40], *tmp = number; - if( buf_len > sizeof number ) - { - if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, buf_len ))) - { - buf[0] = '\0'; - return; - } - } - - base = 10; if( flags->Format == 'o' ) base = 8; else if( flags->Format == 'x' || flags->Format == 'X' ) base = 16; + else + base = 10; if( flags->Format == 'X' ) digits = "0123456789ABCDEFX"; @@ -356,82 +310,44 @@ flags->Sign = '-'; } - /* Do conversion (backwards) */ i = 0; - if( x == 0 && flags->Precision ) - tmp[i++] = '0'; + if( x == 0 ) + { + flags->Alternate = 0; + if( flags->Precision ) + buf[i++] = '0'; + } else while( x != 0 ) { j = (ULONGLONG) x % base; x = (ULONGLONG) x / base; - tmp[i++] = digits[j]; + buf[i++] = digits[j]; } k = flags->Precision - i; while( k-- > 0 ) - tmp[i++] = '0'; + buf[i++] = '0'; if( flags->Alternate ) { if( base == 16 ) { - tmp[i++] = digits[16]; - tmp[i++] = '0'; + buf[i++] = digits[16]; + buf[i++] = '0'; } - else if( base == 8 && tmp[i-1] != '0' ) - tmp[i++] = '0'; + else if( base == 8 && buf[i-1] != '0' ) + buf[i++] = '0'; } - /* Reverse for buf */ - j = 0; - while( i-- > 0 ) - buf[j++] = tmp[i]; - buf[j] = '\0'; - /* Adjust precision so pf_fill won't truncate the number later */ - flags->Precision = strlen( buf ); - - if( tmp != number ) - RtlFreeHeap( GetProcessHeap(), 0, tmp ); - - return; -} - -/* pf_fixup_exponent: convert a string containing a 2 digit exponent - to 3 digits, accounting for padding, in place. Needed to match - the native printf's which always use 3 digits. */ -static void pf_fixup_exponent( char *buf ) -{ - char* tmp = buf; + flags->Precision = i; - while (tmp[0] && NTDLL_tolower(tmp[0]) != 'e') - tmp++; - - if (tmp[0] && (tmp[1] == '+' || tmp[1] == '-') && - isdigit(tmp[2]) && isdigit(tmp[3])) - { - char final; - - if (isdigit(tmp[4])) - return; /* Exponent already 3 digits */ - - /* We have a 2 digit exponent. Prepend '0' to make it 3 */ - tmp += 2; - final = tmp[2]; - tmp[2] = tmp[1]; - tmp[1] = tmp[0]; - tmp[0] = '0'; - if (final == '\0') - { - /* We didn't expand into trailing space, so this string isn't left - * justified. Terminate the string and strip a ' ' at the start of - * the string if there is one (as there may be if the string is - * right justified). - */ - tmp[3] = '\0'; - if (buf[0] == ' ') - memmove(buf, buf + 1, (tmp - buf) + 3); - } - /* Otherwise, we expanded into trailing space -> nothing to do */ + buf[i] = '\0'; + j = 0; + while(--i > j) { + char tmp = buf[j]; + buf[j] = buf[i]; + buf[i] = tmp; + j++; } } @@ -546,7 +462,12 @@ /* deal with integer width modifier */ while( *p ) { - if( *p == 'h' || *p == 'l' || *p == 'L' ) + if (*p == 'l' && *(p+1) == 'l') + { + flags.IntegerDouble++; + p += 2; + } + else if( *p == 'h' || *p == 'l' || *p == 'L' ) { flags.IntegerLength = *p; p++; @@ -573,6 +494,13 @@ } else if( *p == 'w' ) flags.WideString = *p++; + else if ((*p == 'z' || *p == 't') && p[1] && strchr("diouxX", p[1])) + flags.IntegerNative = *p++; + else if (*p == 'j') + { + flags.IntegerDouble++; + p++; + } else if( *p == 'F' ) p++; /* ignore */ else @@ -605,12 +533,13 @@ { char pointer[32]; void *ptr = va_arg( valist, void * ); - + int prec = flags.Precision; + flags.Format = 'X'; + flags.PadZero = '0'; + flags.Precision = 2*sizeof(void*); + pf_integer_conv( pointer, &flags, (ULONG_PTR)ptr ); flags.PadZero = 0; - if( flags.Alternate ) - sprintf(pointer, "0X%0*lX", 2 * (int)sizeof(ptr), (ULONG_PTR)ptr); - else - sprintf(pointer, "%0*lX", 2 * (int)sizeof(ptr), (ULONG_PTR)ptr); + flags.Precision = prec; r = pf_output_format_A( out, pointer, -1, &flags ); } @@ -620,60 +549,30 @@ int *x = va_arg(valist, int *); *x = out->used; } - - /* deal with 64-bit integers */ - else if( pf_is_integer_format( flags.Format ) && flags.IntegerDouble ) + else if( flags.Format && strchr("diouxX", flags.Format )) { char number[40], *x = number; + int max_len; - /* Estimate largest possible required buffer size: - * Chooses the larger of the field or precision - * Includes extra bytes: 1 byte for null, 1 byte for sign, - 4 bytes for exponent, 2 bytes for alternate formats, 1 byte - for a decimal, and 1 byte for an additional float digit. */ - int x_len = ((flags.FieldLength > flags.Precision) ? - flags.FieldLength : flags.Precision) + 10; - - if( x_len >= sizeof number) - if (!(x = RtlAllocateHeap( GetProcessHeap(), 0, x_len ))) - return -1; - - pf_integer_conv( x, x_len, &flags, va_arg(valist, LONGLONG) ); - - r = pf_output_format_A( out, x, -1, &flags ); - if( x != number ) - RtlFreeHeap( GetProcessHeap(), 0, x ); - } - - /* deal with integers and floats using libc's printf */ - else if( pf_is_valid_format( flags.Format ) ) - { - char fmt[20], number[40], *x = number; - - /* Estimate largest possible required buffer size: - * Chooses the larger of the field or precision - * Includes extra bytes: 1 byte for null, 1 byte for sign, - 4 bytes for exponent, 2 bytes for alternate formats, 1 byte - for a decimal, and 1 byte for an additional float digit. */ - int x_len = ((flags.FieldLength > flags.Precision) ? - flags.FieldLength : flags.Precision) + 10; - - if( x_len >= sizeof number) - if (!(x = RtlAllocateHeap( GetProcessHeap(), 0, x_len ))) - return -1; - - pf_rebuild_format_string( fmt, &flags ); - - if( pf_is_double_format( flags.Format ) ) - { - sprintf( x, fmt, va_arg(valist, double) ); - if (NTDLL_tolower(flags.Format) == 'e' || NTDLL_tolower(flags.Format) == 'g') - pf_fixup_exponent( x ); - } + /* 0 padding is added after '0x' if Alternate flag is in use */ + if((flags.Format=='x' || flags.Format=='X') && flags.PadZero && flags.Alternate + && !flags.LeftAlign && flags.Precisionflags.Precision ? flags.FieldLength : flags.Precision) + 10; + if(max_len > ARRAY_SIZE(number)) + if (!(x = RtlAllocateHeap( GetProcessHeap(), 0, max_len ))) return -1; + + if(flags.IntegerDouble || (flags.IntegerNative && sizeof(void*) == 8)) + pf_integer_conv( x, &flags, va_arg(valist, LONGLONG) ); + else if(flags.Format=='d' || flags.Format=='i') + pf_integer_conv( x, &flags, flags.IntegerLength!='h' ? + va_arg(valist, int) : (short)va_arg(valist, int) ); else - sprintf( x, fmt, va_arg(valist, int) ); + pf_integer_conv( x, &flags, flags.IntegerLength!='h' ? + (unsigned int)va_arg(valist, int) : (unsigned short)va_arg(valist, int) ); - r = pf_output_stringA( out, x, -1 ); + r = pf_output_format_A( out, x, -1, &flags ); if( x != number ) RtlFreeHeap( GetProcessHeap(), 0, x ); } @@ -798,6 +697,27 @@ } +/*********************************************************************** + * _vsnwprintf_s (NTDLL.@) + */ +int CDECL _vsnwprintf_s( WCHAR *str, SIZE_T size, SIZE_T len, const WCHAR *format, __ms_va_list args ) +{ + pf_output out; + int r; + + out.unicode = TRUE; + out.buf.W = str; + out.used = 0; + out.len = min( size, len ); + + r = pf_vsnprintf( &out, format, args ); + if (out.used < size) str[out.used] = 0; + else str[0] = 0; + if (r == size) r = -1; + return r; +} + + /********************************************************************* * _snprintf_s (NTDLL.@) */ @@ -814,6 +734,21 @@ /********************************************************************* + * _snwprintf_s (NTDLL.@) + */ +int WINAPIV _snwprintf_s( WCHAR *str, SIZE_T size, SIZE_T len, const WCHAR *format, ... ) +{ + int ret; + __ms_va_list valist; + + __ms_va_start( valist, format ); + ret = _vsnwprintf_s( str, size, len, format, valist ); + __ms_va_end( valist ); + return ret; +} + + +/********************************************************************* * vsprintf (NTDLL.@) */ int CDECL NTDLL_vsprintf( char *str, const char *format, __ms_va_list args ) @@ -823,6 +758,33 @@ /********************************************************************* + * vsprintf_s (NTDLL.@) + */ +int CDECL vsprintf_s( char *str, SIZE_T size, const char *format, __ms_va_list args ) +{ + return _vsnprintf_s( str, size, size, format, args ); +} + + +/********************************************************************* + * _vswprintf (NTDLL.@) + */ +int CDECL NTDLL__vswprintf( WCHAR *str, const WCHAR *format, __ms_va_list args ) +{ + return NTDLL__vsnwprintf( str, size_max, format, args ); +} + + +/********************************************************************* + * vswprintf_s (NTDLL.@) + */ +int CDECL vswprintf_s( WCHAR *str, SIZE_T size, const WCHAR *format, __ms_va_list args ) +{ + return _vsnwprintf_s( str, size, size, format, args ); +} + + +/********************************************************************* * sprintf (NTDLL.@) */ int WINAPIV NTDLL_sprintf( char *str, const char *format, ... ) @@ -837,6 +799,21 @@ } +/********************************************************************* + * sprintf_s (NTDLL.@) + */ +int WINAPIV sprintf_s( char *str, SIZE_T size, const char *format, ... ) +{ + int ret; + __ms_va_list valist; + + __ms_va_start( valist, format ); + ret = vsprintf_s( str, size, format, valist ); + __ms_va_end( valist ); + return ret; +} + + /*********************************************************************** * swprintf (NTDLL.@) */ @@ -850,3 +827,18 @@ __ms_va_end(valist); return ret; } + + +/*********************************************************************** + * swprintf_s (NTDLL.@) + */ +int WINAPIV swprintf_s( WCHAR *str, SIZE_T size, const WCHAR *format, ... ) +{ + int ret; + __ms_va_list valist; + + __ms_va_start(valist, format); + ret = vswprintf_s( str, size, format, valist ); + __ms_va_end(valist); + return ret; +} diff -Nru wine-development-5.8/dlls/ntdll/process.c wine-development-5.9/dlls/ntdll/process.c --- wine-development-5.8/dlls/ntdll/process.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/process.c 2020-05-22 18:49:34.000000000 +0000 @@ -32,6 +32,12 @@ #ifdef HAVE_SYS_SOCKET_H #include #endif +#ifdef HAVE_SYS_TIME_H +# include +#endif +#ifdef HAVE_SYS_TIMES_H +# include +#endif #include #ifdef HAVE_SYS_WAIT_H # include @@ -359,7 +365,7 @@ break; case ProcessTimes: { - KERNEL_USER_TIMES pti; + KERNEL_USER_TIMES pti = {{{0}}}; if (ProcessInformationLength >= sizeof(KERNEL_USER_TIMES)) { @@ -369,8 +375,15 @@ ret = STATUS_INVALID_HANDLE; else { - /* FIXME : User- and KernelTime have to be implemented */ - memset(&pti, 0, sizeof(KERNEL_USER_TIMES)); + long ticks = sysconf(_SC_CLK_TCK); + struct tms tms; + + /* FIXME: user/kernel times only work for current process */ + if (ticks && times( &tms ) != -1) + { + pti.UserTime.QuadPart = (ULONGLONG)tms.tms_utime * 10000000 / ticks; + pti.KernelTime.QuadPart = (ULONGLONG)tms.tms_stime * 10000000 / ticks; + } SERVER_START_REQ(get_process_info) { @@ -1074,6 +1087,7 @@ static NTSTATUS spawn_loader( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd, const char *unixdir, char *winedebug, const pe_image_info_t *pe_info ) { + const int is_child_64bit = (pe_info->cpu == CPU_x86_64 || pe_info->cpu == CPU_ARM64); pid_t pid; int stdin_fd = -1, stdout_fd = -1; char **argv; @@ -1103,7 +1117,8 @@ if (winedebug) putenv( winedebug ); if (unixdir) chdir( unixdir ); - exec_wineloader( argv, socketfd, pe_info ); + unix_funcs->exec_wineloader( argv, socketfd, is_child_64bit, + pe_info->base, pe_info->base + pe_info->map_size ); _exit(1); } @@ -1533,12 +1548,14 @@ if (!status) { + const int is_child_64bit = (pe_info.cpu == CPU_x86_64 || pe_info.cpu == CPU_ARM64); char **argv = build_argv( &strW, 2 ); if (argv) { do { - status = exec_wineloader( argv, socketfd[0], &pe_info ); + status = unix_funcs->exec_wineloader( argv, socketfd[0], is_child_64bit, + pe_info.base, pe_info.base + pe_info.map_size ); } #ifdef __APPLE__ while (errno == ENOTSUP && terminate_main_thread()); diff -Nru wine-development-5.8/dlls/ntdll/resource.c wine-development-5.9/dlls/ntdll/resource.c --- wine-development-5.8/dlls/ntdll/resource.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/resource.c 2020-05-22 18:49:34.000000000 +0000 @@ -419,31 +419,3 @@ } return STATUS_MESSAGE_NOT_FOUND; } - -/********************************************************************** - * RtlFormatMessage (NTDLL.@) - * - * Formats a message (similar to sprintf). - * - * PARAMS - * Message [I] Message to format. - * MaxWidth [I] Maximum width in characters of each output line. - * IgnoreInserts [I] Whether to copy the message without processing inserts. - * Ansi [I] Whether Arguments may have ANSI strings. - * ArgumentsIsArray [I] Whether Arguments is actually an array rather than a va_list *. - * Buffer [O] Buffer to store processed message in. - * BufferSize [I] Size of Buffer (in bytes?). - * - * RETURNS - * NTSTATUS code. - */ -NTSTATUS WINAPI RtlFormatMessage( LPWSTR Message, UCHAR MaxWidth, - BOOLEAN IgnoreInserts, BOOLEAN Ansi, - BOOLEAN ArgumentIsArray, __ms_va_list * Arguments, - LPWSTR Buffer, ULONG BufferSize ) -{ - FIXME("(%s, %u, %s, %s, %s, %p, %p, %d)\n", debugstr_w(Message), - MaxWidth, IgnoreInserts ? "TRUE" : "FALSE", Ansi ? "TRUE" : "FALSE", - ArgumentIsArray ? "TRUE" : "FALSE", Arguments, Buffer, BufferSize); - return STATUS_SUCCESS; -} diff -Nru wine-development-5.8/dlls/ntdll/rtl.c wine-development-5.9/dlls/ntdll/rtl.c --- wine-development-5.8/dlls/ntdll/rtl.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/rtl.c 2020-05-22 18:49:34.000000000 +0000 @@ -97,6 +97,15 @@ 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 */ +}; #if defined(_WIN64) && !defined(_MSC_VER) static inline unsigned char _InterlockedCompareExchange128(__int64 *dest, __int64 xchg_high, __int64 xchg_low, __int64 *compare) @@ -109,7 +118,7 @@ : "m" (dest[0]), "m" (dest[1]), "3" (compare[0]), "4" (compare[1]), "c" (xchg_high), "b" (xchg_low) ); #else - ret = __sync_bool_compare_and_swap( (__int128 *)dest, (__int128 *)compare, + ret = __sync_bool_compare_and_swap( (__int128 *)dest, *(__int128 *)compare, ((__int128)xchg_high << 64) | xchg_low ); #endif return ret; @@ -904,15 +913,6 @@ static BOOL parse_ipv4_component(const WCHAR **str, BOOL strict, ULONG *value) { - 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 */ - }; int base = 10, d; WCHAR c; ULONG cur_value, prev_value = 0; @@ -1092,13 +1092,211 @@ 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++; + /* Windows bug: a double colon at the beginning is treated as 4 bytes of zeros instead of 2 */ + address->u.Word[0] = 0; + n_bytes = 2; + } + + 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) { - FIXME("(%s, %p, %p, %p): stub\n", debugstr_w(str), address, scope, port); - return STATUS_NOT_IMPLEMENTED; + 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[64]; + + 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[64]; + 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; } /*********************************************************************** diff -Nru wine-development-5.8/dlls/ntdll/rtlstr.c wine-development-5.9/dlls/ntdll/rtlstr.c --- wine-development-5.8/dlls/ntdll/rtlstr.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/rtlstr.c 2020-05-22 18:49:34.000000000 +0000 @@ -1707,3 +1707,248 @@ return STATUS_SUCCESS; } + + +/*********************************************************************** + * Message formatting + ***********************************************************************/ + +struct format_message_args +{ + int last; /* last used arg */ + ULONG_PTR *array; /* args array */ + __ms_va_list *list; /* args va_list */ + UINT64 arglist[102]; /* arguments fetched from va_list */ +}; + +static NTSTATUS add_chars( WCHAR **buffer, WCHAR *end, const WCHAR *str, ULONG len ) +{ + if (len > end - *buffer) return STATUS_BUFFER_OVERFLOW; + memcpy( *buffer, str, len * sizeof(WCHAR) ); + *buffer += len; + return STATUS_SUCCESS; +} + +static UINT64 get_arg( int nr, struct format_message_args *args_data, BOOL is64 ) +{ + if (nr == -1) nr = args_data->last + 1; + while (nr > args_data->last) + args_data->arglist[args_data->last++] = is64 ? va_arg( *args_data->list, UINT64 ) + : va_arg( *args_data->list, ULONG_PTR ); + return args_data->arglist[nr - 1]; +} + +static NTSTATUS add_format( WCHAR **buffer, WCHAR *end, const WCHAR **src, int insert, BOOLEAN ansi, + struct format_message_args *args_data ) +{ + static const WCHAR modifiers[] = {'0','1','2','3','4','5','6','7','8','9',' ','+','-','*','#','.',0}; + const WCHAR *format = *src; + WCHAR *p, fmt[32]; + ULONG_PTR args[5] = { 0 }; + BOOL is_64 = FALSE; + UINT64 val; + int len, stars = 0, nb_args = 0; + + p = fmt; + *p++ = '%'; + + if (*format++ == '!') + { + const WCHAR *end = wcschr( format, '!' ); + + if (!end || end - format > ARRAY_SIZE(fmt) - 2) return STATUS_INVALID_PARAMETER; + *src = end + 1; + + while (wcschr( modifiers, *format )) + { + if (*format == '*') stars++; + *p++ = *format++; + } + if (stars > 2) return STATUS_INVALID_PARAMETER; + + switch (*format) + { + case 'c': case 'C': + case 's': case 'S': + if (ansi) *p++ = *format++ ^ ('s' - 'S'); + break; + case 'I': + if (sizeof(void *) == sizeof(int) && format[1] == '6' && format[2] == '4') is_64 = TRUE; + break; + } + while (format != end) *p++ = *format++; + } + else *p++ = ansi ? 'S' : 's'; /* simple string */ + + *p = 0; + if (args_data->list) + { + get_arg( insert - 1, args_data, is_64 ); /* make sure previous args have been fetched */ + while (stars--) + { + args[nb_args++] = get_arg( insert, args_data, FALSE ); + insert = -1; + } + /* replicate MS bug: drop an argument when using va_list with width/precision */ + if (insert == -1) args_data->last--; + val = get_arg( insert, args_data, is_64 ); + args[nb_args++] = val; + args[nb_args] = val >> 32; + } + else if (args_data->array) + { + args[nb_args++] = args_data->array[insert - 1]; + if (args_data->last < insert) args_data->last = insert; + /* replicate MS bug: first arg is considered 64-bit, even if it's actually width or precision */ + if (is_64) nb_args++; + while (stars--) args[nb_args++] = args_data->array[args_data->last++]; + } + else return STATUS_INVALID_PARAMETER; + + len = _snwprintf_s( *buffer, end - *buffer, end - *buffer - 1, fmt, + args[0], args[1], args[2], args[3], args[4] ); + if (len == -1) return STATUS_BUFFER_OVERFLOW; + *buffer += len; + return STATUS_SUCCESS; +} + + +/********************************************************************** + * RtlFormatMessage (NTDLL.@) + */ +NTSTATUS WINAPI RtlFormatMessage( const WCHAR *src, ULONG width, BOOLEAN ignore_inserts, + BOOLEAN ansi, BOOLEAN is_array, __ms_va_list *args, + WCHAR *buffer, ULONG size, ULONG *retsize ) +{ + return RtlFormatMessageEx( src, width, ignore_inserts, ansi, is_array, args, buffer, size, retsize, 0 ); +} + + +/********************************************************************** + * RtlFormatMessageEx (NTDLL.@) + */ +NTSTATUS WINAPI RtlFormatMessageEx( const WCHAR *src, ULONG width, BOOLEAN ignore_inserts, + BOOLEAN ansi, BOOLEAN is_array, __ms_va_list *args, + WCHAR *buffer, ULONG size, ULONG *retsize, ULONG flags ) +{ + static const WCHAR emptyW = 0; + static const WCHAR spaceW = ' '; + static const WCHAR crW = '\r'; + static const WCHAR tabW = '\t'; + static const WCHAR crlfW[] = {'\r','\n'}; + + struct format_message_args args_data; + NTSTATUS status = STATUS_SUCCESS; + + WCHAR *start = buffer; /* start of buffer */ + WCHAR *end = buffer + size / sizeof(WCHAR); /* end of buffer */ + WCHAR *line = buffer; /* start of last line */ + WCHAR *space = NULL; /* last space */ + + if (flags) FIXME( "%s unknown flags %x\n", debugstr_w(src), flags ); + + args_data.last = 0; + args_data.array = is_array ? (ULONG_PTR *)args : NULL; + args_data.list = is_array ? NULL : args; + + for ( ; *src; src++) + { + switch (*src) + { + case '\r': + if (src[1] == '\n') src++; + /* fall through */ + case '\n': + if (!width) + { + status = add_chars( &buffer, end, crlfW, 2 ); + line = buffer; + space = NULL; + break; + } + /* fall through */ + case ' ': + space = buffer; + status = add_chars( &buffer, end, &spaceW, 1 ); + break; + case '\t': + if (space == buffer - 1) space = buffer; + status = add_chars( &buffer, end, &tabW, 1 ); + break; + case '%': + src++; + switch (*src) + { + case 0: + return STATUS_INVALID_PARAMETER; + case 't': + if (!width) + { + status = add_chars( &buffer, end, &tabW, 1 ); + break; + } + /* fall through */ + case 'n': + status = add_chars( &buffer, end, crlfW, 2 ); + line = buffer; + space = NULL; + break; + case 'r': + status = add_chars( &buffer, end, &crW, 1 ); + line = buffer; + space = NULL; + break; + case '0': + while (src[1]) src++; + break; + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + if (!ignore_inserts) + { + int nr = *src++ - '0'; + + if (*src >= '0' && *src <= '9') nr = nr * 10 + *src++ - '0'; + status = add_format( &buffer, end, &src, nr, ansi, &args_data ); + src--; + break; + } + /* fall through */ + default: + if (ignore_inserts) status = add_chars( &buffer, end, src - 1, 2 ); + else status = add_chars( &buffer, end, src, 1 ); + break; + } + break; + default: + status = add_chars( &buffer, end, src, 1 ); + break; + } + + if (status) return status; + + if (width && buffer - line >= width) + { + LONG_PTR diff = 2; + WCHAR *next; + + if (space) /* split line at the last space */ + { + next = space + 1; + while (space > line && (space[-1] == ' ' || space[-1] == '\t')) space--; + diff -= next - space; + } + else space = next = buffer; /* split at the end of the buffer */ + + if (diff > 0 && end - buffer < diff) return STATUS_BUFFER_OVERFLOW; + memmove( space + 2, next, (buffer - next) * sizeof(WCHAR) ); + buffer += diff; + memcpy( space, crlfW, sizeof(crlfW) ); + line = space + 2; + space = NULL; + } + } + + if ((status = add_chars( &buffer, end, &emptyW, 1 ))) return status; + + *retsize = (buffer - start) * sizeof(WCHAR); + return STATUS_SUCCESS; +} diff -Nru wine-development-5.8/dlls/ntdll/server.c wine-development-5.9/dlls/ntdll/server.c --- wine-development-5.8/dlls/ntdll/server.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/server.c 2020-05-22 18:49:34.000000000 +0000 @@ -91,6 +91,7 @@ #include "wine/server.h" #include "wine/debug.h" #include "ntdll_misc.h" +#include "ddk/wdm.h" WINE_DEFAULT_DEBUG_CHANNEL(server); @@ -120,22 +121,12 @@ #error Unsupported CPU #endif -#if defined(linux) || defined(__APPLE__) -static const BOOL use_preloader = TRUE; -#else -static const BOOL use_preloader = FALSE; -#endif - static const BOOL is_win64 = (sizeof(void *) > sizeof(int)); const char *build_dir = NULL; const char *data_dir = NULL; const char *config_dir = NULL; -const char **dll_paths = NULL; -size_t dll_path_maxlen = 0; static const char *server_dir; -static const char *bin_dir; -static const char *argv0; unsigned int server_cpus = 0; BOOL is_wow64 = FALSE; @@ -198,47 +189,6 @@ exit(1); } -/* canonicalize path and return its directory name */ -static char *realpath_dirname( const char *name ) -{ - char *p, *fullpath = realpath( name, NULL ); - - if (fullpath) - { - p = strrchr( fullpath, '/' ); - if (p == fullpath) p++; - if (p) *p = 0; - } - return fullpath; -} - -/* if string ends with tail, remove it */ -static char *remove_tail( const char *str, const char *tail ) -{ - size_t len = strlen( str ); - size_t tail_len = strlen( tail ); - char *ret; - - if (len < tail_len) return NULL; - if (strcmp( str + len - tail_len, tail )) return NULL; - ret = malloc( len - tail_len + 1 ); - memcpy( ret, str, len - tail_len ); - ret[len - tail_len] = 0; - return ret; -} - -/* build a path from the specified dir and name */ -static char *build_path( const char *dir, const char *name ) -{ - size_t len = strlen( dir ); - char *ret = malloc( len + strlen( name ) + 2 ); - - memcpy( ret, dir, len ); - if (len && ret[len - 1] != '/') ret[len++] = '/'; - strcpy( ret + len, name ); - return ret; -} - /*********************************************************************** * server_protocol_error */ @@ -1231,196 +1181,6 @@ /*********************************************************************** - * preloader_exec - */ -static void preloader_exec( char **argv ) -{ - if (use_preloader) - { - static const char *preloader = "wine-preloader"; - char *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 ); - -#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] ); - } - execv( argv[1], argv + 1 ); -} - - -/*********************************************************************** - * exec_wineloader - * - * argv[0] and argv[1] must be reserved for the preloader and loader respectively. - */ -NTSTATUS exec_wineloader( char **argv, int socketfd, const pe_image_info_t *pe_info ) -{ - const int is_child_64bit = (pe_info->cpu == CPU_x86_64 || pe_info->cpu == CPU_ARM64); - const char *path, *loader = argv0; - const char *loader_env = getenv( "WINELOADER" ); - char *p, preloader_reserve[64], socket_env[64]; - ULONGLONG res_start = pe_info->base; - ULONGLONG res_end = pe_info->base + pe_info->map_size; - - if (!is_win64 ^ !is_child_64bit) - { - /* remap WINELOADER to the alternate 32/64-bit version if necessary */ - if (loader_env) - { - int len = strlen( loader_env ); - char *env = malloc( sizeof("WINELOADER=") + len + 2 ); - - if (!env) return STATUS_NO_MEMORY; - strcpy( env, "WINELOADER=" ); - strcat( env, loader_env ); - if (is_child_64bit) - { - strcat( env, "64" ); - } - else - { - len += sizeof("WINELOADER=") - 1; - if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0; - } - loader = env; - putenv( env ); - } - else loader = is_child_64bit ? "wine64" : "wine"; - } - - signal( SIGPIPE, SIG_DFL ); - - sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd ); - sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x", - (ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end ); - - putenv( preloader_reserve ); - putenv( socket_env ); - - if (build_dir) - { - argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" ); - preloader_exec( argv ); - return STATUS_INVALID_IMAGE_FORMAT; - } - - if ((p = strrchr( loader, '/' ))) loader = p + 1; - - argv[1] = build_path( bin_dir, loader ); - preloader_exec( argv ); - - argv[1] = getenv( "WINELOADER" ); - if (argv[1]) preloader_exec( argv ); - - if ((path = getenv( "PATH" ))) - { - for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" )) - { - argv[1] = build_path( p, loader ); - preloader_exec( argv ); - } - } - - argv[1] = build_path( BINDIR, loader ); - preloader_exec( argv ); - return STATUS_INVALID_IMAGE_FORMAT; -} - - -/*********************************************************************** - * exec_wineserver - * - * Exec a new wine server. - */ -static void exec_wineserver( char **argv ) -{ - char *path; - - if (build_dir) - { - if (!is_win64) /* look for 64-bit server */ - { - char *loader = realpath_dirname( build_path( build_dir, "loader/wine64" )); - if (loader) - { - argv[0] = build_path( loader, "../server/wineserver" ); - execv( argv[0], argv ); - } - } - argv[0] = build_path( build_dir, "server/wineserver" ); - execv( argv[0], argv ); - return; - } - - argv[0] = build_path( bin_dir, "wineserver" ); - execv( argv[0], argv ); - - argv[0] = getenv( "WINESERVER" ); - if (argv[0]) execv( argv[0], argv ); - - if ((path = getenv( "PATH" ))) - { - for (path = strtok( strdup( path ), ":" ); path; path = strtok( NULL, ":" )) - { - argv[0] = build_path( path, "wineserver" ); - execvp( argv[0], argv ); - } - } - - argv[0] = build_path( BINDIR, "wineserver" ); - execv( argv[0], argv ); -} - - -/*********************************************************************** - * start_server - * - * Start a new wine server. - */ -static void start_server(void) -{ - static BOOL started; /* we only try once */ - char *argv[3]; - static char debug[] = "-d"; - - if (!started) - { - int status; - int pid = fork(); - if (pid == -1) fatal_perror( "fork" ); - if (!pid) - { - argv[1] = TRACE_ON(server) ? debug : NULL; - argv[2] = NULL; - exec_wineserver( argv ); - fatal_error( "could not exec wineserver\n" ); - } - waitpid( pid, &status, 0 ); - status = WIFEXITED(status) ? WEXITSTATUS(status) : 1; - if (status == 2) return; /* server lock held by someone else, will retry later */ - if (status) exit(status); /* server failed */ - started = TRUE; - } -} - - -/*********************************************************************** * init_server_dir */ static const char *init_server_dir( dev_t dev, ino_t ino ) @@ -1453,106 +1213,6 @@ /*********************************************************************** - * init_config_dir - */ -static const char *init_config_dir(void) -{ - char *p, *dir; - const char *prefix = getenv( "WINEPREFIX" ); - - if (prefix) - { - if (prefix[0] != '/') - fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix ); - dir = strdup( prefix ); - for (p = dir + strlen(dir) - 1; p > dir && *p == '/'; p--) *p = 0; - } - else - { - const char *home = getenv( "HOME" ); - if (!home) - { - struct passwd *pwd = getpwuid( getuid() ); - if (pwd) home = pwd->pw_dir; - } - if (!home) fatal_error( "could not determine your home directory\n" ); - if (home[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home ); - dir = build_path( home, ".wine" ); - } - return dir; -} - - -/*********************************************************************** - * build_dll_path - */ -static void build_dll_path( const char *dll_dir ) -{ - const char *default_dlldir = DLLDIR; - char *p, *path = getenv( "WINEDLLPATH" ); - int i, count = 0; - - if (path) for (p = path, count = 1; *p; p++) if (*p == ':') count++; - - dll_paths = malloc( (count + 2) * sizeof(*dll_paths) ); - count = 0; - - if (!build_dir && dll_dir) dll_paths[count++] = dll_dir; - - if (path) - { - path = strdup(path); - for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" )) dll_paths[count++] = strdup( p ); - free( path ); - } - - if (!build_dir && !dll_dir) dll_paths[count++] = default_dlldir; - - for (i = 0; i < count; i++) dll_path_maxlen = max( dll_path_maxlen, strlen(dll_paths[i]) ); - dll_paths[count] = NULL; -} - - -/*********************************************************************** - * init_paths - */ -void init_paths(void) -{ - const char *dll_dir = NULL; - -#ifdef HAVE_DLADDR - Dl_info info; - - if (dladdr( init_paths, &info ) && info.dli_fname[0] == '/') - dll_dir = realpath_dirname( info.dli_fname ); -#endif - - argv0 = strdup( __wine_main_argv[0] ); - -#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) - bin_dir = realpath_dirname( "/proc/self/exe" ); -#elif defined (__FreeBSD__) || defined(__DragonFly__) - bin_dir = realpath_dirname( "/proc/curproc/file" ); -#else - bin_dir = realpath_dirname( argv0 ); -#endif - - if (dll_dir) build_dir = remove_tail( dll_dir, "/dlls/ntdll" ); - else if (bin_dir) build_dir = remove_tail( bin_dir, "/loader" ); - - if (!build_dir) - { - if (!bin_dir) bin_dir = dll_dir ? build_path( dll_dir, DLL_TO_BINDIR ) : BINDIR; - else if (!dll_dir) dll_dir = build_path( bin_dir, BIN_TO_DLLDIR ); - data_dir = build_path( bin_dir, BIN_TO_DATADIR ); - } - - build_dll_path( dll_dir ); - config_dir = init_config_dir(); -} - - -/*********************************************************************** * setup_config_dir * * Setup the wine configuration dir. @@ -1650,7 +1310,7 @@ if (chdir( server_dir ) == -1) { if (errno != ENOENT) fatal_perror( "chdir to %s", server_dir ); - start_server(); + unix_funcs->start_server( TRACE_ON(server) ); if (chdir( server_dir ) == -1) fatal_perror( "chdir to %s", server_dir ); } @@ -1665,13 +1325,13 @@ if (retry) { usleep( 100000 * retry * retry ); - start_server(); + unix_funcs->start_server( TRACE_ON(server) ); if (lstat( SOCKETNAME, &st ) == -1) continue; /* still no socket, wait a bit more */ } else if (lstat( SOCKETNAME, &st ) == -1) /* check for an already existing socket */ { if (errno != ENOENT) fatal_perror( "lstat %s/%s", server_dir, SOCKETNAME ); - start_server(); + unix_funcs->start_server( TRACE_ON(server) ); if (lstat( SOCKETNAME, &st ) == -1) continue; /* still no socket, wait a bit more */ } @@ -1732,6 +1392,12 @@ if (task_get_bootstrap_port(mach_task_self(), &bootstrap_port) != KERN_SUCCESS) return; + if (!server_dir) + { + struct stat st; + stat( config_dir, &st ); + server_dir = init_server_dir( st.st_dev, st.st_ino ); + } kret = bootstrap_look_up(bootstrap_port, server_dir, &wineserver_port); if (kret != KERN_SUCCESS) fatal_error( "cannot find the server port: 0x%08x\n", kret ); @@ -1863,6 +1529,7 @@ IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); void *entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint; NTSTATUS status; + HANDLE usd_handle = user_shared_data_init_done(); int suspend; #ifdef __APPLE__ @@ -1886,10 +1553,12 @@ #endif req->entry = wine_server_client_ptr( entry ); req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI); + req->usd_handle = wine_server_obj_handle( usd_handle ); status = wine_server_call( req ); suspend = reply->suspend; } SERVER_END_REQ; + NtClose( usd_handle ); assert( !status ); signal_start_process( entry, suspend ); diff -Nru wine-development-5.8/dlls/ntdll/signal_arm64.c wine-development-5.9/dlls/ntdll/signal_arm64.c --- wine-development-5.8/dlls/ntdll/signal_arm64.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/signal_arm64.c 2020-05-22 18:49:34.000000000 +0000 @@ -265,8 +265,7 @@ "stp x23, x24, [x0, #0xc0]\n\t" /* context->X23,X24 */ "stp x25, x26, [x0, #0xd0]\n\t" /* context->X25,X26 */ "stp x27, x28, [x0, #0xe0]\n\t" /* context->X27,X28 */ - "ldp x1, x2, [x29]\n\t" - "stp x1, x2, [x0, #0xf0]\n\t" /* context->Fp,Lr */ + "stp x29, x30, [x0, #0xf0]\n\t" /* context->Fp,Lr */ "add x1, x29, #0x10\n\t" "stp x1, x30, [x0, #0x100]\n\t" /* context->Sp,Pc */ "mov w1, #0x400000\n\t" /* CONTEXT_ARM64 */ @@ -545,7 +544,6 @@ *handler = (void *)info.handler; *handler_data = (void *)info.lsda; *frame = context->Sp; - context->Pc = context->u.s.Lr; unw_get_reg( &cursor, UNW_AARCH64_X0, (unw_word_t *)&context->u.s.X0 ); unw_get_reg( &cursor, UNW_AARCH64_X1, (unw_word_t *)&context->u.s.X1 ); unw_get_reg( &cursor, UNW_AARCH64_X2, (unw_word_t *)&context->u.s.X2 ); @@ -578,6 +576,7 @@ unw_get_reg( &cursor, UNW_AARCH64_X29, (unw_word_t *)&context->u.s.Fp ); unw_get_reg( &cursor, UNW_AARCH64_X30, (unw_word_t *)&context->u.s.Lr ); unw_get_reg( &cursor, UNW_AARCH64_SP, (unw_word_t *)&context->Sp ); + context->Pc = context->u.s.Lr; TRACE( "next function pc=%016lx%s\n", context->Pc, rc ? "" : " (last frame)" ); TRACE(" x0=%016lx x1=%016lx x2=%016lx x3=%016lx\n", @@ -1559,7 +1558,12 @@ if (!skip) { - if (func->u.s.CR == 3) restore_regs( 29, 2, 0, context, ptrs ); + if (func->u.s.CR == 3) + { + DWORD64 *fp = (DWORD64 *) context->u.s.Fp; /* u.X[29] */ + context->u.X[29] = fp[0]; + context->u.X[30] = fp[1]; + } context->Sp += local_size; if (fp_size) restore_fpregs( 8, fp_size / 8, int_size, context, ptrs ); if (func->u.s.CR == 1) restore_regs( 30, 1, int_size - 8, context, ptrs ); @@ -1844,7 +1848,8 @@ dispatch.ContextRecord = context; RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc, dispatch.FunctionEntry, - &new_context, NULL, &frame, NULL ); + &new_context, &dispatch.HandlerData, &frame, + NULL ); rec->ExceptionFlags |= EH_COLLIDED_UNWIND; goto unwind_done; } @@ -1867,7 +1872,8 @@ dispatch.ContextRecord = context; RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc, dispatch.FunctionEntry, - &new_context, NULL, &frame, NULL ); + &new_context, &dispatch.HandlerData, + &frame, NULL ); rec->ExceptionFlags |= EH_COLLIDED_UNWIND; goto unwind_done; } diff -Nru wine-development-5.8/dlls/ntdll/tests/env.c wine-development-5.9/dlls/ntdll/tests/env.c --- wine-development-5.8/dlls/ntdll/tests/env.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/tests/env.c 2020-05-22 18:49:34.000000000 +0000 @@ -27,6 +27,7 @@ static NTSTATUS (WINAPI *pRtlCreateEnvironment)(BOOLEAN, PWSTR*); static NTSTATUS (WINAPI *pRtlDestroyEnvironment)(PWSTR); static NTSTATUS (WINAPI *pRtlQueryEnvironmentVariable_U)(PWSTR, PUNICODE_STRING, PUNICODE_STRING); +static NTSTATUS (WINAPI* pRtlQueryEnvironmentVariable)(WCHAR*, WCHAR*, SIZE_T, WCHAR*, SIZE_T, SIZE_T*); static void (WINAPI *pRtlSetCurrentEnvironment)(PWSTR, PWSTR*); static NTSTATUS (WINAPI *pRtlSetEnvironmentVariable)(PWSTR*, PUNICODE_STRING, PUNICODE_STRING); static NTSTATUS (WINAPI *pRtlExpandEnvironmentStrings_U)(LPWSTR, PUNICODE_STRING, PUNICODE_STRING, PULONG); @@ -95,6 +96,9 @@ UNICODE_STRING name; UNICODE_STRING value; NTSTATUS nts; + SIZE_T name_length; + SIZE_T value_length; + SIZE_T return_length; unsigned int i; for (i = 0; tests[i].var; i++) @@ -130,6 +134,39 @@ break; } } + + if (pRtlQueryEnvironmentVariable) + { + for (i = 0; tests[i].var; i++) + { + const struct test* test = &tests[i]; + name_length = strlen(test->var); + value_length = test->len; + value.Buffer = bv; + bv[test->len] = '@'; + + pRtlMultiByteToUnicodeN(bn, sizeof(bn), NULL, test->var, strlen(test->var) + 1); + nts = pRtlQueryEnvironmentVariable(small_env, bn, name_length, bv, value_length, &return_length); + ok(nts == test->status || (test->alt && nts == test->alt), + "[%d]: Wrong status for '%s', expecting %x got %x\n", + i, test->var, test->status, nts); + if (nts == test->status) switch (nts) + { + case STATUS_SUCCESS: + pRtlMultiByteToUnicodeN(bn, sizeof(bn), NULL, test->val, strlen(test->val) + 1); + ok(return_length == strlen(test->val), "Wrong length %ld for %s\n", + return_length, test->var); + ok(!memcmp(bv, bn, return_length), "Wrong result for %s/%d\n", test->var, test->len); + ok(bv[test->len] == '@', "Writing too far away in the buffer for %s/%d\n", test->var, test->len); + break; + case STATUS_BUFFER_TOO_SMALL: + ok(return_length == (strlen(test->val) + 1), + "Wrong returned length %ld (too small buffer) for %s\n", return_length, test->var); + break; + } + } + } + else win_skip("RtlQueryEnvironmentVariable not available, skipping tests\n"); } static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATUS ret, NTSTATUS alt) @@ -591,6 +628,7 @@ pRtlCreateEnvironment = (void*)GetProcAddress(mod, "RtlCreateEnvironment"); pRtlDestroyEnvironment = (void*)GetProcAddress(mod, "RtlDestroyEnvironment"); pRtlQueryEnvironmentVariable_U = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable_U"); + pRtlQueryEnvironmentVariable = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable"); pRtlSetCurrentEnvironment = (void*)GetProcAddress(mod, "RtlSetCurrentEnvironment"); pRtlSetEnvironmentVariable = (void*)GetProcAddress(mod, "RtlSetEnvironmentVariable"); pRtlExpandEnvironmentStrings_U = (void*)GetProcAddress(mod, "RtlExpandEnvironmentStrings_U"); diff -Nru wine-development-5.8/dlls/ntdll/tests/info.c wine-development-5.9/dlls/ntdll/tests/info.c --- wine-development-5.8/dlls/ntdll/tests/info.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/tests/info.c 2020-05-22 18:49:34.000000000 +0000 @@ -23,6 +23,7 @@ #include static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); +static NTSTATUS (WINAPI * pNtSetSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG); static NTSTATUS (WINAPI * pRtlGetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*); static NTSTATUS (WINAPI * pNtPowerInformation)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG); @@ -76,6 +77,7 @@ } NTDLL_GET_PROC(NtQuerySystemInformation); + NTDLL_GET_PROC(NtSetSystemInformation); NTDLL_GET_PROC(RtlGetNativeSystemInformation); NTDLL_GET_PROC(NtPowerInformation); NTDLL_GET_PROC(NtQueryInformationProcess); @@ -740,6 +742,40 @@ HeapFree( GetProcessHeap(), 0, sii); } +static void test_time_adjustment(void) +{ + SYSTEM_TIME_ADJUSTMENT_QUERY query; + SYSTEM_TIME_ADJUSTMENT adjust; + NTSTATUS status; + ULONG len; + + memset( &query, 0xcc, sizeof(query) ); + status = pNtQuerySystemInformation( SystemTimeAdjustmentInformation, &query, sizeof(query), &len ); + ok( status == STATUS_SUCCESS, "got %08x\n", status ); + ok( len == sizeof(query) || broken(!len) /* winxp */, "wrong len %u\n", len ); + ok( query.TimeAdjustmentDisabled == TRUE || query.TimeAdjustmentDisabled == FALSE, + "wrong value %x\n", query.TimeAdjustmentDisabled ); + + status = pNtQuerySystemInformation( SystemTimeAdjustmentInformation, &query, sizeof(query)-1, &len ); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08x\n", status ); + ok( len == sizeof(query) || broken(!len) /* winxp */, "wrong len %u\n", len ); + + status = pNtQuerySystemInformation( SystemTimeAdjustmentInformation, &query, sizeof(query)+1, &len ); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08x\n", status ); + ok( len == sizeof(query) || broken(!len) /* winxp */, "wrong len %u\n", len ); + + adjust.TimeAdjustment = query.TimeAdjustment; + adjust.TimeAdjustmentDisabled = query.TimeAdjustmentDisabled; + status = pNtSetSystemInformation( SystemTimeAdjustmentInformation, &adjust, sizeof(adjust) ); + ok( status == STATUS_SUCCESS || status == STATUS_PRIVILEGE_NOT_HELD, "got %08x\n", status ); + status = pNtSetSystemInformation( SystemTimeAdjustmentInformation, &adjust, sizeof(adjust)-1 ); + todo_wine + ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08x\n", status ); + status = pNtSetSystemInformation( SystemTimeAdjustmentInformation, &adjust, sizeof(adjust)+1 ); + todo_wine + ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08x\n", status ); +} + static void test_query_kerndebug(void) { NTSTATUS status; @@ -2181,6 +2217,7 @@ MEMORY_BASIC_INFORMATION mbi; char stackbuf[42]; HMODULE module; + void *user_shared_data = (void *)0x7ffe0000; module = GetModuleHandleA( "ntdll.dll" ); trace("Check flags of the PE header of NTDLL.DLL at %p\n", module); @@ -2255,6 +2292,17 @@ } else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */ + trace("Check flags of user shared data at %p\n", user_shared_data); + status = pNtQueryVirtualMemory(NtCurrentProcess(), user_shared_data, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); + ok(readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount); + ok(mbi.AllocationBase == user_shared_data, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, user_shared_data); + ok(mbi.AllocationProtect == PAGE_READONLY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_READONLY); + ok(mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT); + ok(mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x\n", mbi.Protect); + ok(mbi.Type == MEM_PRIVATE, "mbi.Type is 0x%x, expected 0x%x\n", mbi.Type, MEM_PRIVATE); + ok(mbi.RegionSize == 0x1000, "mbi.RegionSize is 0x%lx, expected 0x%x\n", mbi.RegionSize, 0x1000); + /* check error code when addr is higher than working set limit */ status = pNtQueryVirtualMemory(NtCurrentProcess(), (void *)~0, MemoryBasicInformation, &mbi, sizeof(mbi), &readcount); ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got %08x\n", status); @@ -2505,7 +2553,11 @@ status = pNtQuerySystemInformation(SystemRecommendedSharedDataAlignment, &value, sizeof(value), &ReturnLength); ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); ok(sizeof(value) == ReturnLength, "Inconsistent length %u\n", ReturnLength); +#ifdef __arm__ + ok(value == 32, "Expected 32, got %u\n", value); +#else ok(value == 64, "Expected 64, got %u\n", value); +#endif } static void test_thread_lookup(void) @@ -2616,6 +2668,10 @@ trace("Starting test_query_interrupt()\n"); test_query_interrupt(); + /* 0x1c SystemTimeAdjustmentInformation */ + trace("Starting test_time_adjustment()\n"); + test_time_adjustment(); + /* 0x23 SystemKernelDebuggerInformation */ trace("Starting test_query_kerndebug()\n"); test_query_kerndebug(); diff -Nru wine-development-5.8/dlls/ntdll/tests/rtlstr.c wine-development-5.9/dlls/ntdll/tests/rtlstr.c --- wine-development-5.8/dlls/ntdll/tests/rtlstr.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/tests/rtlstr.c 2020-05-22 18:49:34.000000000 +0000 @@ -72,6 +72,7 @@ static NTSTATUS (WINAPI *pRtlHashUnicodeString)(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*); static NTSTATUS (WINAPI *pRtlUnicodeToUTF8N)(CHAR *, ULONG, ULONG *, const WCHAR *, ULONG); static NTSTATUS (WINAPI *pRtlUTF8ToUnicodeN)(WCHAR *, ULONG, ULONG *, const CHAR *, ULONG); +static NTSTATUS (WINAPI *pRtlFormatMessage)(const WCHAR*,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list*,LPWSTR,ULONG,ULONG*); /*static VOID (WINAPI *pRtlFreeOemString)(PSTRING);*/ /*static VOID (WINAPI *pRtlCopyUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *);*/ @@ -144,6 +145,7 @@ pRtlHashUnicodeString = (void*)GetProcAddress(hntdll, "RtlHashUnicodeString"); pRtlUnicodeToUTF8N = (void*)GetProcAddress(hntdll, "RtlUnicodeToUTF8N"); pRtlUTF8ToUnicodeN = (void*)GetProcAddress(hntdll, "RtlUTF8ToUnicodeN"); + pRtlFormatMessage = (void*)GetProcAddress(hntdll, "RtlFormatMessage"); } } @@ -693,6 +695,7 @@ case 0x19d: lower_ch = 0x272; break; case 0x19f: lower_ch = 0x275; break; case 0x1a9: lower_ch = 0x283; break; + case 0x1a6: lower_ch = 0x280; break; case 0x1ae: lower_ch = 0x288; break; case 0x1b1: lower_ch = 0x28a; break; case 0x1b2: lower_ch = 0x28b; break; @@ -701,6 +704,16 @@ case 0x1c7: lower_ch = 0x1c9; break; case 0x1ca: lower_ch = 0x1cc; break; case 0x1f1: lower_ch = 0x1f3; break; + case 0x1f6: lower_ch = 0x195; break; + case 0x1f7: lower_ch = 0x1bf; break; + case 0x220: lower_ch = 0x19e; break; + case 0x23a: lower_ch = 0x2c65; break; + case 0x23d: lower_ch = 0x19a; break; + case 0x23e: lower_ch = 0x2c66; break; + case 0x243: lower_ch = 0x180; break; + case 0x244: lower_ch = 0x289; break; + case 0x245: lower_ch = 0x28c; break; + case 0x37f: lower_ch = 0x3f3; break; case 0x386: lower_ch = 0x3ac; break; case 0x388: lower_ch = 0x3ad; break; case 0x389: lower_ch = 0x3ae; break; @@ -708,6 +721,11 @@ case 0x38c: lower_ch = 0x3cc; break; case 0x38e: lower_ch = 0x3cd; break; case 0x38f: lower_ch = 0x3ce; break; + case 0x3cf: lower_ch = 0x3d7; break; + case 0x3f9: lower_ch = 0x3f2; break; + case 0x3fd: lower_ch = 0x37b; break; + case 0x3fe: lower_ch = 0x37c; break; + case 0x3ff: lower_ch = 0x37d; break; default: lower_ch = ch; break; } /* switch */ } @@ -730,7 +748,8 @@ pRtlDowncaseUnicodeString(&result_str, &source_str, 0); for (i = 0; i <= 1024; i++) { - ok(result_str.Buffer[i] == lower_str.Buffer[i] || result_str.Buffer[i] == source_str.Buffer[i] + 1, + ok(result_str.Buffer[i] == lower_str.Buffer[i] || result_str.Buffer[i] == source_str.Buffer[i] + 1 || + broken( result_str.Buffer[i] == source_str.Buffer[i] ), "RtlDowncaseUnicodeString works wrong: '%c'[=0x%x] is converted to '%c'[=0x%x], expected: '%c'[=0x%x]\n", source_str.Buffer[i], source_str.Buffer[i], result_str.Buffer[i], result_str.Buffer[i], @@ -2592,6 +2611,285 @@ } } +static NTSTATUS WINAPIV fmt( const WCHAR *src, ULONG width, BOOLEAN ignore_inserts, BOOLEAN ansi, + WCHAR *buffer, ULONG size, ULONG *retsize, ... ) +{ + __ms_va_list args; + NTSTATUS status; + + *retsize = 0xdeadbeef; + __ms_va_start( args, retsize ); + status = pRtlFormatMessage( src, width, ignore_inserts, ansi, FALSE, &args, buffer, size, retsize ); + __ms_va_end( args ); + return status; +} + +static void WINAPIV testfmt( const WCHAR *src, const WCHAR *expect, ULONG width, BOOL ansi, ... ) +{ + __ms_va_list args; + NTSTATUS status; + WCHAR buffer[128]; + ULONG size = 0xdeadbeef; + + memset( buffer, 0xcc, sizeof(buffer) ); + __ms_va_start( args, ansi ); + status = pRtlFormatMessage( src, width, FALSE, ansi, FALSE, &args, buffer, sizeof(buffer), &size ); + __ms_va_end( args ); + ok( !status, "%s: failed %x\n", debugstr_w(src), status ); + ok( !lstrcmpW( buffer, expect ), "%s: got %s expected %s\n", debugstr_w(src), + debugstr_w(buffer), debugstr_w(expect) ); + ok( size == (lstrlenW(expect) + 1) * sizeof(WCHAR), "%s: wrong size %u\n", debugstr_w(src), size ); +} + +static void test_RtlFormatMessage(void) +{ + WCHAR buffer[128]; + NTSTATUS status; + ULONG i, size; + + /* basic formats */ + testfmt( L"test", L"test", 0, FALSE ); + testfmt( L"", L"", 0, FALSE ); + testfmt( L"%1", L"test", 0, FALSE, L"test" ); + testfmt( L"%1!s!", L"test", 0, FALSE, L"test" ); + testfmt( L"%1!s!", L"foo", 0, TRUE, "foo" ); + testfmt( L"%1!S!", L"test", 0, FALSE, "test" ); + testfmt( L"%1!S!", L"foo", 0, TRUE, L"foo" ); + testfmt( L"%1!hs!%1!hS!", L"testtest", 0, FALSE, "test" ); + testfmt( L"%1!ls!%1!lS!%1!ws!%1!wS!", L"foofoofoofoo", 0, TRUE, L"foo" ); + testfmt( L"%1!c!", L"a", 0, FALSE, L'a' ); + testfmt( L"%1!c!", L"b", 0, TRUE, 'b' ); + testfmt( L"%1!C!", L"c", 0, FALSE, L'c' ); + testfmt( L"%1!C!", L"d", 0, TRUE, 'd' ); + testfmt( L"%1!hc!", L"e", 0, FALSE, L'e' ); + testfmt( L"%1!hC!", L"f", 0, FALSE, L'f' ); + testfmt( L"%1!lc!", L"g", 0, TRUE, 'g' ); + testfmt( L"%1!lC!", L"h", 0, TRUE, 'h' ); + testfmt( L"%1!wc!", L"i", 0, TRUE, 'i' ); + testfmt( L"%1!wC!", L"j", 0, TRUE, 'j' ); + testfmt( L"%1!04X!", L"BEEF", 0, FALSE, 0xbeef ); + testfmt( L"%1!Saa!", L"testaa", 0, FALSE, "test" ); + testfmt( L"%.%%%Z%n%t%r%!% ", L".%Z\r\n\t\r! ", 0, FALSE ); + testfmt( L"%1!*.*u!,%1!*.*u!", L" 001, 0002", 0, FALSE, 5, 3, 1, 4, 2 ); + testfmt( L"%1!*.*u!,%3!*.*u!", L" 001, 0002", 0, FALSE, 5, 3, 1, 6, 4, 2 ); + testfmt( L"%1", L"(null)", 0, FALSE, NULL ); + testfmt( L"%2", L"(null)", 0, TRUE, "abc", NULL ); + testfmt( L"ab%1!!cd", L"abcd", 0, FALSE, L"hello" ); + testfmt( L"abc%1!#.000000000000000000000000000x!", L"abc0x22", 0, FALSE, 34 ); + testfmt( L"a\r\nb\rc\r\rd\r\r\ne", L"a\r\nb\r\nc\r\n\r\nd\r\n\r\ne", 0, FALSE, NULL ); +#ifdef _WIN64 + testfmt( L"%1!#I64x! %2!x!", L"0x1234 5678", 0, FALSE, (ULONG_PTR)0x1234, 0x5678, 0xbeef ); + testfmt( L"%1!x! %2!#I64x! %3!#I64x! %4!x!", L"dead 0x1111222233334444 0x5555666677778888 beef", + 0, FALSE, 0xdead, 0x1111222233334444ull, 0x5555666677778888ull, 0xbeef ); + testfmt( L"%3!#I64x! %4!#I64x! %3!x! %1!x!", L"0x3 0x4 3 1", 0, FALSE, 0xdead00000001ll, 2, 3ll, 4ll ); + testfmt( L"%2!x! %1!I64x!", L"5678 1234", 0, FALSE, (ULONG_PTR)0x1234, 0x5678, 0xbeef ); + testfmt( L"%2!*.*I64x! %1!u! %4!u! %2!u!", L" 00000000000000d 19 11 17", 0, FALSE, + 19ull, 17ull, 15ull, 13ull, 11ull, 9ull ); + { /* argument array works differently */ + ULONG_PTR args[] = { 19, 17, 15, 13, 11, 9, 7 }; + memset( buffer, 0xcc, sizeof(buffer) ); + status = pRtlFormatMessage( L"%2!*.*I64x! %1!u! %4!u! %2!u!", 0, FALSE, FALSE, TRUE, + (__ms_va_list *)args, buffer, sizeof(buffer), &size ); + ok( !lstrcmpW( buffer, L" 00000000000000d 19 13 17" ), "got %s\n", wine_dbgstr_w(buffer) ); + memset( buffer, 0xcc, sizeof(buffer) ); + status = pRtlFormatMessage( L"%1!I64u! %2!u! %4!.*I64x! %5!I64u!", 0, FALSE, FALSE, TRUE, + (__ms_va_list *)args, buffer, sizeof(buffer), &size ); + ok( !lstrcmpW( buffer, L"19 17 000000000000b 11" ), "got %s\n", wine_dbgstr_w(buffer) ); + } +#else + fmt( L"%1!#I64x! %2!x!", 0, FALSE, FALSE, buffer, sizeof(buffer), &size, 0x1234, 0x5678, 0xbeef ); + if (lstrcmpW( buffer, L"0x567800001234 5678" )) + { + testfmt( L"%1!#I64x! %2!x!", L"0x567800001234 beef", 0, FALSE, 0x1234, 0x5678, 0xbeef ); + testfmt( L"%1!x! %2!#I64x! %3!#I64x! %4!x!", L"dead 0x1111222233334444 0x5555666677778888 beef", + 0, FALSE, 0xdead, 0x1111222233334444ull, 0x5555666677778888ull, 0xbeef ); + testfmt( L"%3!#I64x! %4!#I64x! %3!x! %1!x!", L"0x1111222233334444 0x5555666677778888 33334444 1", + 0, FALSE, 1, 2, 3, 4, 0x33334444, 0x11112222, 0x77778888, 0x55556666, 0xbeef, 0xbee2 ); + testfmt( L"%2!x! %1!I64x!", L"5678 1234", 0, FALSE, 0x1234, 0x5678, 0xbeef ); + testfmt( L"%2!*.*I64x! %1!u! %4!u! %2!u!", L" 000090000000b 19 7 15", 0, FALSE, + 19, 17, 15, 13, 11, 9, 7 ); + { /* argument array works differently */ + ULONG_PTR args[] = { 19, 17, 15, 13, 11, 9, 7 }; + memset( buffer, 0xcc, sizeof(buffer) ); + status = pRtlFormatMessage( L"%2!*.*I64x! %1!u! %4!u! %2!u!", 0, FALSE, FALSE, TRUE, + (__ms_va_list *)args, buffer, sizeof(buffer), &size ); + ok( !lstrcmpW( buffer, L" d0000000f 19 13 17" ), "got %s\n", wine_dbgstr_w(buffer) ); + memset( buffer, 0xcc, sizeof(buffer) ); + status = pRtlFormatMessage( L"%1!I64u! %2!u! %4!.*I64x! %5!I64u!", 0, FALSE, FALSE, TRUE, + (__ms_va_list *)args, buffer, sizeof(buffer), &size ); + ok( !lstrcmpW( buffer, L"19 17 0000b00000000 11" ), "got %s\n", wine_dbgstr_w(buffer) ); + } + } + else win_skip( "I64 support broken\n" ); +#endif + testfmt( L"%1!Ix! %2!QQ!", L"1234 QQ", 0, FALSE, (ULONG_PTR)0x1234 ); + testfmt( L"%1!#llx!%2!#x!%1!#hx!", L"0x1234560x789abc0x3456", 0, FALSE, 0x123456, 0x789abc ); + lstrcpyW( buffer, L"xxxxxxxxxx" ); + fmt( L"ab%0cd", 0, FALSE, FALSE, buffer, sizeof(buffer), &size ); + ok( !memcmp( buffer, L"ab\0xxxxxxx", 10 * sizeof(WCHAR) ), "got %s\n", wine_dbgstr_wn(buffer, 10) ); + + /* max width */ + testfmt( L"%1", L"testing\r\n", 3, FALSE, L"testing" ); + testfmt( L"%1%2%3", L"testing\r\nabcdef\r\nfoobar\r\n", 4, FALSE, L"testing", L"abcdef", L"foobar"); + testfmt( L"%1%2%3%4", L"test\r\nabcd\r\nabcdef\r\n", 4, FALSE, L"test", L"abcd", L"abc", L"def" ); + testfmt( L"%1a\nb%2", L"testing\r\na\r\nbfoo bar\r\n", 3, FALSE, L"testing", L"foo bar" ); + testfmt( L"a%tb%t%t%t%c%r%r%r%r%r%rdefg", L"a\r\nb\r\n\r\n\r\nc\r\r\r\r\r\rdef\r\ng", 3, FALSE ); + testfmt( L"test abcd ", L"test\r\n\r\nabcd\r\n ", 4, FALSE ); + testfmt( L"test abcdef %1 foobar", L"tes\r\nt\r\nabc\r\ndef\r\n\r\nhello\r\nfoo\r\nbar\r\n", 3, FALSE, L"hello" ); + testfmt( L"te st\nabc d\nfoo", L"te st\r\nabc d\r\nfoo", 6, FALSE ); + testfmt( L"te st ab d\nfoo", L"te st\r\n ab\r\n d foo", 7, FALSE ); + testfmt( L"te\tst\t\t\t\tab\t\t\td\nfoo", L"te\tst\t\t\r\n\t\tab\t\t\t\r\nd foo", 7, FALSE ); + testfmt( L"te st\n\n\r\n\nab d\nfoo ", L"te st\r\n ab\r\n d foo\r\n ", 7, FALSE ); + testfmt( L"te st\r\nabc d\n\nfoo\rbar", L"te st abc d foo bar", 0xff, FALSE ); + testfmt( L"te st%r%nabc d%nfoo%rbar", L"te st\r\r\nabc d\r\nfoo\rbar", 0xff, FALSE ); + testfmt( L"\01\02\03\04\a\a\a\a\b\b\b\b\t\t\t\t\v\v\v\v\f\f\f\f\r\r\r\r a", + L"\01\02\r\n\03\04\r\n\a\a\r\n\a\a\r\n\b\b\r\n\b\b\r\n\t\t\r\n\t\t\r\n\v\v\r\n\v\v\r\n\f\f\r\n\f\f\r\n\r\n\r\n\r\n\r\na", 2, FALSE ); + + for (i = 1; i < 0xffff; i++) + { + WCHAR src[] = { i, ' ', i, i, i, i, i, ' ', i, 0 }; + WCHAR expect[16]; + switch (i) + { + case '\t': + lstrcpyW( expect, L"\r\n\r\n\t" ); + break; + case '\r': + case '\n': + case ' ': + lstrcpyW( expect, L"\r\n\r\n " ); + break; + case '%': + lstrcpyW( expect, L" %% \r\nxxxx" ); + break; + default: + swprintf( expect, ARRAY_SIZE(expect), L"%c\r\n%c%c%c%c\r\n%c %c", i, i, i, i, i, i, i ); + break; + } + lstrcpyW( buffer, L"xxxxxxxxxx" ); + fmt( src, 4, FALSE, FALSE, buffer, sizeof(buffer), &size ); + ok( !lstrcmpW( buffer, expect ), "%04x: got %s\n", i, debugstr_w(buffer) ); + } + + /* args are not counted the same way with an argument array */ + { + ULONG_PTR args[] = { 6, 4, 2, 5, 3, 1 }; + memset( buffer, 0xcc, sizeof(buffer) ); + status = pRtlFormatMessage( L"%1!*.*u!,%1!*.*u!", 0, FALSE, FALSE, TRUE, (__ms_va_list *)args, + buffer, sizeof(buffer), &size ); + ok( !lstrcmpW( buffer, L" 0002, 00003" ), "got %s\n", wine_dbgstr_w(buffer) ); + memset( buffer, 0xcc, sizeof(buffer) ); + status = pRtlFormatMessage( L"%1!*.*u!,%4!*.*u!", 0, FALSE, FALSE, TRUE, (__ms_va_list *)args, + buffer, sizeof(buffer), &size ); + ok( !lstrcmpW( buffer, L" 0002, 001" ), "got %s\n", wine_dbgstr_w(buffer) ); + } + + /* buffer overflows */ + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"testing", 0, FALSE, FALSE, buffer, 8, &size ); + ok( status == STATUS_BUFFER_OVERFLOW, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"testxxxxxx" ) || broken(!lstrcmpW( buffer, L"tesxxxxxxx" )), /* winxp */ + "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"%1", 0, FALSE, FALSE, buffer, 8, &size, L"test" ); + ok( status == STATUS_BUFFER_OVERFLOW, "failed %x\n", status ); + ok( !memcmp( buffer, L"tes\0xxxxxx", 10 * sizeof(WCHAR) ) || broken(!lstrcmpW( buffer, L"testxxxxxx" )), /* winxp */ + "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"%1!x!", 0, FALSE, FALSE, buffer, 8, &size, 0x12345678 ); + ok( status == STATUS_BUFFER_OVERFLOW, "failed %x\n", status ); + ok( !memcmp( buffer, L"123\0xxxxxx", 10 * sizeof(WCHAR) ) || broken(!lstrcmpW( buffer, L"1234xxxxxx" )), /* winxp */ + "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"%1!*s!", 0, FALSE, FALSE, buffer, 10, &size, 5, L"abc" ); + ok( status == STATUS_BUFFER_OVERFLOW, "failed %x\n", status ); + ok( !memcmp( buffer, L" ab\0xxxxx", 10 * sizeof(WCHAR) ) || broken(!lstrcmpW( buffer, L" abcxxxxx" )), /* winxp */ + "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"ab%n", 0, FALSE, FALSE, buffer, 6, &size ); + ok( status == STATUS_BUFFER_OVERFLOW, "failed %x\n", status ); + ok( !memcmp( buffer, L"abxxxxxxxx", 10 * sizeof(WCHAR) ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + /* ignore inserts */ + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"%1!x!%r%%%n%t", 0, TRUE, FALSE, buffer, sizeof(buffer), &size ); + ok( !lstrcmpW( buffer, L"%1!x!\r%%\r\n\t" ), "got %s\n", wine_dbgstr_w(buffer) ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"ab%0cd", 0, TRUE, FALSE, buffer, sizeof(buffer), &size ); + ok( !status, "failed %x\n", status ); + ok( !memcmp( buffer, L"ab\0xxxxxxx", 10 * sizeof(WCHAR) ), "got %s\n", wine_dbgstr_wn(buffer, 10) ); + + /* invalid args */ + lstrcpyW( buffer, L"xxxxxxxxxx" ); + size = 0xdeadbeef; + status = pRtlFormatMessage( L"abc%1", 0, FALSE, FALSE, FALSE, NULL, buffer, sizeof(buffer), &size ); + ok( status == STATUS_INVALID_PARAMETER, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"abcxxxxxxx" ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = pRtlFormatMessage( L"abc%1", 0, FALSE, FALSE, TRUE, NULL, buffer, sizeof(buffer), &size ); + ok( status == STATUS_INVALID_PARAMETER, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"abcxxxxxxx" ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = pRtlFormatMessage( L"abc%", 0, FALSE, FALSE, TRUE, NULL, buffer, sizeof(buffer), &size ); + ok( status == STATUS_INVALID_PARAMETER, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"abcxxxxxxx" ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"%1!u! %2!u", 0, FALSE, FALSE, buffer, sizeof(buffer), &size, 34 ); + ok( status == STATUS_INVALID_PARAMETER, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"34 xxxxxxx" ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"%1!**u!", 0, FALSE, FALSE, buffer, sizeof(buffer), &size, 34 ); + ok( status == STATUS_SUCCESS, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"*u" ), "got %s\n", wine_dbgstr_w(buffer) ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"%1!0.3+*u!", 0, FALSE, FALSE, buffer, sizeof(buffer), &size, 34 ); + ok( status == STATUS_SUCCESS, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"+*u" ), "got %s\n", wine_dbgstr_w(buffer) ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"aa%1!***u!", 0, FALSE, FALSE, buffer, sizeof(buffer), &size, 34 ); + ok( status == STATUS_INVALID_PARAMETER, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"aaxxxxxxxx" ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"abc%1!#.000000000000000000000000000x!", 0, FALSE, FALSE, buffer, sizeof(buffer), &size, 34 ); + ok( status == STATUS_SUCCESS, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"abc0x22" ), "got %s\n", wine_dbgstr_w(buffer) ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"abc%1!#.0000000000000000000000000000x!", 0, FALSE, FALSE, buffer, sizeof(buffer), &size, 34 ); + ok( status == STATUS_INVALID_PARAMETER, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"abcxxxxxxx" ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + + lstrcpyW( buffer, L"xxxxxxxxxx" ); + status = fmt( L"abc%1!hsaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!", 0, FALSE, FALSE, buffer, sizeof(buffer), &size, "hello" ); + ok( status == STATUS_INVALID_PARAMETER, "failed %x\n", status ); + ok( !lstrcmpW( buffer, L"abcxxxxxxx" ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( size == 0xdeadbeef, "wrong size %u\n", size ); + +} + START_TEST(rtlstr) { InitFunctionPtrs(); @@ -2621,11 +2919,9 @@ test_RtlCompareUnicodeString(); test_RtlUpcaseUnicodeChar(); test_RtlUpcaseUnicodeString(); - if(0) - { - test_RtlDowncaseUnicodeString(); - } + test_RtlDowncaseUnicodeString(); test_RtlHashUnicodeString(); test_RtlUnicodeToUTF8N(); test_RtlUTF8ToUnicodeN(); + test_RtlFormatMessage(); } diff -Nru wine-development-5.8/dlls/ntdll/tests/string.c wine-development-5.9/dlls/ntdll/tests/string.c --- wine-development-5.8/dlls/ntdll/tests/string.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/tests/string.c 2020-05-22 18:49:34.000000000 +0000 @@ -70,6 +70,8 @@ static void* (__cdecl *pbsearch)(void *,void*,size_t,size_t, int(__cdecl *compar)(const void *, const void *) ); static int (WINAPIV *p_snprintf)(char *, size_t, const char *, ...); static int (WINAPIV *p_snprintf_s)(char *, size_t, size_t, const char *, ...); +static int (WINAPIV *p_snwprintf)(WCHAR *, size_t, const WCHAR *, ...); +static int (WINAPIV *p_snwprintf_s)(WCHAR *, size_t, size_t, const WCHAR *, ...); static int (__cdecl *ptolower)(int); static int (__cdecl *ptoupper)(int); @@ -124,6 +126,8 @@ X(bsearch); X(_snprintf); X(_snprintf_s); + X(_snwprintf); + X(_snwprintf_s); X(tolower); X(toupper); X(_strnicmp); @@ -1457,8 +1461,7 @@ int res; res = p_snprintf(NULL, 0, teststring); - ok(res == lstrlenA(teststring) || broken(res == -1) /* <= w2k */, - "_snprintf returned %d, expected %d.\n", res, lstrlenA(teststring)); + ok(res == lstrlenA(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenA(teststring)); if (res != -1) { @@ -1488,6 +1491,20 @@ memset(buffer, 0x7c, sizeof(buffer)); res = p_snprintf(buffer, 3, "test"); ok(res == -1, "res = %d\n", res); + ok(!memcmp(buffer, "tes", 3), "buf = %s\n", buffer); + ok(buffer[3] == 0x7c, "buffer[3] = %x\n", buffer[3]); + + memset(buffer, 0x7c, sizeof(buffer)); + res = p_snprintf(buffer, 4, "%s", "test"); + ok(res == 4, "res = %d\n", res); + ok(!memcmp(buffer, "test", 4), "buf = %s\n", buffer); + ok(buffer[4] == 0x7c, "buffer[4] = %x\n", buffer[4]); + + memset(buffer, 0x7c, sizeof(buffer)); + res = p_snprintf(buffer, 3, "%s", "test"); + ok(res == -1, "res = %d\n", res); + ok(!memcmp(buffer, "tes", 3), "buf = %s\n", buffer); + ok(buffer[3] == 0x7c, "buffer[3] = %x\n", buffer[3]); res = p_snprintf(buffer, sizeof(buffer), "%I64x %d", (ULONGLONG)0x1234567890, 1); ok(res == strlen(buffer), "wrong size %d\n", res); @@ -1497,17 +1514,64 @@ ok(res == strlen(buffer), "wrong size %d\n", res); ok(!strcmp(buffer, "123456 1"), "got %s\n", debugstr_a(buffer)); + res = p_snprintf(buffer, sizeof(buffer), "%#x %#x", 0, 1); + ok(res == lstrlenA(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "0 0x1"), "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%hx %hd", 0x123456, 987654); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "3456 4614"), "got %s\n", debugstr_a(buffer)); + if (sizeof(void *) == 8) { res = p_snprintf(buffer, sizeof(buffer), "%Ix %d", (ULONG_PTR)0x1234567890, 1); ok(res == strlen(buffer), "wrong size %d\n", res); ok(!strcmp(buffer, "1234567890 1"), "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%zx %d", (ULONG_PTR)0x1234567890, 1); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "1234567890 1") || broken(!strcmp(buffer, "zx 878082192")), + "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%tx %d", (ULONG_PTR)0x1234567890, 1); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "1234567890 1") || broken(!strcmp(buffer, "tx 878082192")), + "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%jx %d", (ULONG_PTR)0x1234567890, 1); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "1234567890 1") || broken(!strcmp(buffer, "jx 878082192")), + "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%llx %d", (ULONG_PTR)0x1234567890, 1); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "1234567890 1"), "got %s\n", debugstr_a(buffer)); } else { res = p_snprintf(buffer, sizeof(buffer), "%Ix %d", (ULONG_PTR)0x123456, 1); ok(res == strlen(buffer), "wrong size %d\n", res); ok(!strcmp(buffer, "123456 1"), "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%zx %d", (ULONG_PTR)0x123456, 1); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "123456 1") || broken(!strcmp(buffer, "zx 1193046")), + "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%tx %d", (ULONG_PTR)0x123456, 1); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "123456 1") || broken(!strcmp(buffer, "tx 1193046")), + "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%jx %d", 0x1234567890ull, 1); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "1234567890 1") || broken(!strcmp(buffer, "jx 878082192")), + "got %s\n", debugstr_a(buffer)); + + res = p_snprintf(buffer, sizeof(buffer), "%llx %d", 0x1234567890ull, 1); + ok(res == strlen(buffer), "wrong size %d\n", res); + ok(!strcmp(buffer, "1234567890 1") || broken(!strcmp(buffer, "34567890 18")), /* winxp */ + "got %s\n", debugstr_a(buffer)); } } @@ -1554,6 +1618,167 @@ } +static void test__snwprintf(void) +{ + const WCHAR *origstring = L"XXXXXXXXXXXX"; + const WCHAR *teststring = L"hello world"; + WCHAR buffer[32]; + int res; + + res = p_snwprintf(NULL, 0, teststring); + ok(res == lstrlenW(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenW(teststring)); + + res = p_snwprintf(buffer, lstrlenW(teststring) - 1, teststring); + ok(res < 0, "_snprintf returned %d, expected < 0.\n", res); + + wcscpy(buffer, origstring); + res = p_snwprintf(buffer, lstrlenW(teststring), teststring); + ok(res == lstrlenW(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenW(teststring)); + ok(!wcscmp(buffer, L"hello worldX"), "_snprintf returned buffer %s, expected 'hello worldX'.\n", + debugstr_w(buffer)); + + wcscpy(buffer, origstring); + res = p_snwprintf(buffer, lstrlenW(teststring) + 1, teststring); + ok(res == lstrlenW(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenW(teststring)); + ok(!wcscmp(buffer, teststring), "_snprintf returned buffer %s, expected %s.\n", + debugstr_w(buffer), debugstr_w(teststring)); + + memset(buffer, 0xcc, sizeof(buffer)); + res = p_snwprintf(buffer, 4, L"test"); + ok(res == 4, "res = %d\n", res); + ok(!memcmp(buffer, L"test", 4 * sizeof(WCHAR)), "buf = %s\n", debugstr_w(buffer)); + ok(buffer[4] == 0xcccc, "buffer[4] = %x\n", buffer[4]); + + memset(buffer, 0xcc, sizeof(buffer)); + res = p_snwprintf(buffer, 3, L"test"); + ok(res == -1, "res = %d\n", res); + ok(!memcmp(buffer, L"tes", 3 * sizeof(WCHAR)), "buf = %s\n", debugstr_w(buffer)); + ok(buffer[3] == 0xcccc, "buffer[3] = %x\n", buffer[3]); + + memset(buffer, 0xcc, sizeof(buffer)); + res = p_snwprintf(buffer, 4, L"%s", L"test"); + ok(res == 4, "res = %d\n", res); + ok(!memcmp(buffer, L"test", 4 * sizeof(WCHAR)), "buf = %s\n", debugstr_w(buffer)); + ok(buffer[4] == 0xcccc, "buffer[4] = %x\n", buffer[4]); + + memset(buffer, 0xcc, sizeof(buffer)); + res = p_snwprintf(buffer, 3, L"%s", L"test"); + ok(res == -1, "res = %d\n", res); + ok(!memcmp(buffer, L"tes", 3), "buf = %s\n", debugstr_w(buffer)); + ok(buffer[3] == 0xcccc, "buffer[3] = %x\n", buffer[3]); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%I64x %d", (ULONGLONG)0x1234567890, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%I32x %d", 0x123456, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"123456 1"), "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%#x %#x", 0, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"0 0x1"), "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%hx %hd", 0x123456, 987654); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"3456 4614"), "got %s\n", debugstr_w(buffer)); + + if (sizeof(void *) == 8) + { + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%Ix %d", (ULONG_PTR)0x1234567890, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%zx %d", (ULONG_PTR)0x1234567890, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"zx 878082192")), + "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%tx %d", (ULONG_PTR)0x1234567890, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"tx 878082192")), + "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%jx %d", (ULONG_PTR)0x1234567890, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"jx 878082192")), + "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%llx %d", (ULONG_PTR)0x1234567890, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_w(buffer)); + } + else + { + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%Ix %d", (ULONG_PTR)0x123456, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"123456 1"), "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%zx %d", (ULONG_PTR)0x123456, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"123456 1") || broken(!wcscmp(buffer, L"zx 1193046")), + "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%tx %d", (ULONG_PTR)0x123456, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"123456 1") || broken(!wcscmp(buffer, L"tx 1193046")), + "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%jx %d", 0x1234567890ull, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"jx 878082192")), + "got %s\n", debugstr_w(buffer)); + + res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%llx %d", 0x1234567890ull, 1); + ok(res == lstrlenW(buffer), "wrong size %d\n", res); + ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"34567890 18")), /* winxp */ + "got %s\n", debugstr_w(buffer)); + } +} + +static void test__snwprintf_s(void) +{ + WCHAR buf[32]; + int res; + + if (!p_snwprintf_s) + { + win_skip("_snwprintf_s not available\n"); + return; + } + + memset(buf, 0xcc, sizeof(buf)); + res = p_snwprintf_s(buf, sizeof(buf), sizeof(buf), L"test"); + ok(res == 4, "res = %d\n", res); + ok(!wcscmp(buf, L"test"), "buf = %s\n", debugstr_w(buf)); + + memset(buf, 0xcc, sizeof(buf)); + res = p_snwprintf_s(buf, 4, 4, L"test"); + ok(res == -1, "res = %d\n", res); + ok(!buf[0], "buf = %s\n", debugstr_w(buf)); + + memset(buf, 0xcc, sizeof(buf)); + res = p_snwprintf_s(buf, 5, 4, L"test"); + ok(res == 4, "res = %d\n", res); + ok(!wcscmp(buf, L"test"), "buf = %s\n", debugstr_w(buf)); + + memset(buf, 0xcc, sizeof(buf)); + res = p_snwprintf_s(buf, 5, 3, L"test"); + ok(res == -1, "res = %d\n", res); + ok(!wcscmp(buf, L"tes"), "buf = %s\n", debugstr_w(buf)); + + memset(buf, 0xcc, sizeof(buf)); + res = p_snwprintf_s(buf, 4, 10, L"test"); + ok(res == -1, "res = %d\n", res); + ok(!buf[0], "buf = %s\n", debugstr_w(buf)); + + memset(buf, 0xcc, sizeof(buf)); + res = p_snwprintf_s(buf, 6, 5, L"test%c", 0); + ok(res == 5, "res = %d\n", res); + ok(!memcmp(buf, L"test\0", 6 * sizeof(WCHAR)), "buf = %s\n", debugstr_w(buf)); + +} + static void test_tolower(void) { int i, ret, exp_ret; @@ -1751,6 +1976,8 @@ test_bsearch(); test__snprintf(); test__snprintf_s(); + test__snwprintf(); + test__snwprintf_s(); test_tolower(); test_toupper(); test__strnicmp(); diff -Nru wine-development-5.8/dlls/ntdll/tests/time.c wine-development-5.9/dlls/ntdll/tests/time.c --- wine-development-5.8/dlls/ntdll/tests/time.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/tests/time.c 2020-05-22 18:49:34.000000000 +0000 @@ -18,7 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define NONAMELESSUNION #include "ntdll_test.h" +#include "ddk/wdm.h" #define TICKSPERSEC 10000000 #define TICKSPERMSEC 10000 @@ -29,6 +31,7 @@ static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency ); static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *); static NTSTATUS (WINAPI *pRtlQueryDynamicTimeZoneInformation)( RTL_DYNAMIC_TIME_ZONE_INFORMATION *); +static BOOL (WINAPI *pRtlQueryUnbiasedInterruptTime)( ULONGLONG *time ); static const int MonthLengths[2][12] = { @@ -153,6 +156,78 @@ wine_dbgstr_w(tzinfo.DaylightName)); } +static ULONGLONG read_ksystem_time(volatile KSYSTEM_TIME *time) +{ + ULONGLONG high, low; + do + { + high = time->High1Time; + low = time->LowPart; + } + while (high != time->High2Time); + return high << 32 | low; +} + +static void test_user_shared_data_time(void) +{ + KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000; + ULONGLONG t1, t2, t3; + int i = 0; + + i = 0; + do + { + t1 = GetTickCount(); + if (user_shared_data->NtMajorVersion <= 5 && user_shared_data->NtMinorVersion <= 1) + t2 = (*(volatile ULONG*)&user_shared_data->TickCountLowDeprecated * (ULONG64)user_shared_data->TickCountMultiplier) >> 24; + else + t2 = (read_ksystem_time(&user_shared_data->u.TickCount) * user_shared_data->TickCountMultiplier) >> 24; + t3 = GetTickCount(); + } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */ + + ok(t1 <= t2, "USD TickCount / GetTickCount are out of order: %s %s\n", + wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + ok(t2 <= t3, "USD TickCount / GetTickCount are out of order: %s %s\n", + wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3)); + + i = 0; + do + { + LARGE_INTEGER system_time; + NtQuerySystemTime(&system_time); + t1 = system_time.QuadPart; + t2 = read_ksystem_time(&user_shared_data->SystemTime); + NtQuerySystemTime(&system_time); + t3 = system_time.QuadPart; + } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */ + + /* FIXME: not always in order, but should be close */ + todo_wine_if(t1 > t2 && t1 - t2 < 50 * TICKSPERMSEC) + ok(t1 <= t2, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n", + wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + ok(t2 <= t3, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n", + wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3)); + + if (!pRtlQueryUnbiasedInterruptTime) + win_skip("skipping RtlQueryUnbiasedInterruptTime tests\n"); + else + { + i = 0; + do + { + pRtlQueryUnbiasedInterruptTime(&t1); + t2 = read_ksystem_time(&user_shared_data->InterruptTime); + pRtlQueryUnbiasedInterruptTime(&t3); + } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */ + + ok(t1 <= t2, "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n", + wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + ok(t2 <= t3 || broken(t2 == t3 + 82410089070) /* w864 has some weird offset on testbot */, + "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n", + wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3)); + } +} + START_TEST(time) { HMODULE mod = GetModuleHandleA("ntdll.dll"); @@ -163,6 +238,7 @@ (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation"); pRtlQueryDynamicTimeZoneInformation = (void *)GetProcAddress(mod, "RtlQueryDynamicTimeZoneInformation"); + pRtlQueryUnbiasedInterruptTime = (void *)GetProcAddress(mod, "RtlQueryUnbiasedInterruptTime"); if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime) test_pRtlTimeToTimeFields(); @@ -170,4 +246,5 @@ win_skip("Required time conversion functions are not available\n"); test_NtQueryPerformanceCounter(); test_RtlQueryTimeZoneInformation(); + test_user_shared_data_time(); } diff -Nru wine-development-5.8/dlls/ntdll/thread.c wine-development-5.9/dlls/ntdll/thread.c --- wine-development-5.8/dlls/ntdll/thread.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/thread.c 2020-05-22 18:49:34.000000000 +0000 @@ -28,9 +28,6 @@ #ifdef HAVE_SYS_MMAN_H #include #endif -#ifdef HAVE_SYS_PRCTL_H -# include -#endif #ifdef HAVE_SYS_TIMES_H #include #endif @@ -56,7 +53,6 @@ #endif struct _KUSER_SHARED_DATA *user_shared_data = NULL; -static const WCHAR default_windirW[] = {'C',':','\\','w','i','n','d','o','w','s',0}; void (WINAPI *kernel32_start_process)(LPTHREAD_START_ROUTINE,void*) = NULL; @@ -152,67 +148,150 @@ /*********************************************************************** - * set_process_name + * __wine_dbg_get_channel_flags (NTDLL.@) * - * Change the process name in the ps output. + * Get the flags to use for a given channel, possibly setting them too in case of lazy init */ -static void set_process_name( int argc, char *argv[] ) +unsigned char __cdecl __wine_dbg_get_channel_flags( struct __wine_debug_channel *channel ) { - BOOL shift_strings; - char *p, *name; - int i; - -#ifdef HAVE_SETPROCTITLE - setproctitle("-%s", argv[1]); - shift_strings = FALSE; -#else - p = argv[0]; + return unix_funcs->dbg_get_channel_flags( channel ); +} + +/*********************************************************************** + * __wine_dbg_strdup (NTDLL.@) + */ +const char * __cdecl __wine_dbg_strdup( const char *str ) +{ + return unix_funcs->dbg_strdup( str ); +} + +/*********************************************************************** + * __wine_dbg_header (NTDLL.@) + */ +int __cdecl __wine_dbg_header( enum __wine_debug_class cls, struct __wine_debug_channel *channel, + const char *function ) +{ + return unix_funcs->dbg_header( cls, channel, function ); +} - shift_strings = (argc >= 2); - for (i = 1; i < argc; i++) +/*********************************************************************** + * __wine_dbg_output (NTDLL.@) + */ +int __cdecl __wine_dbg_output( const char *str ) +{ + return unix_funcs->dbg_output( str ); +} + +static void fill_user_shared_data( struct _KUSER_SHARED_DATA *data ) +{ + RTL_OSVERSIONINFOEXW version; + SYSTEM_CPU_INFORMATION sci; + SYSTEM_BASIC_INFORMATION sbi; + BOOLEAN *features = data->ProcessorFeatures; + + version.dwOSVersionInfoSize = sizeof(version); + RtlGetVersion( &version ); + virtual_get_system_info( &sbi ); + NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL ); + + data->TickCountMultiplier = 1 << 24; + data->LargePageMinimum = 2 * 1024 * 1024; + data->NtBuildNumber = version.dwBuildNumber; + data->NtProductType = version.wProductType; + data->ProductTypeIsValid = TRUE; + data->NativeProcessorArchitecture = sci.Architecture; + data->NtMajorVersion = version.dwMajorVersion; + data->NtMinorVersion = version.dwMinorVersion; + data->SuiteMask = version.wSuiteMask; + data->NumberOfPhysicalPages = sbi.MmNumberOfPhysicalPages; + wcscpy( data->NtSystemRoot, windows_dir ); + + switch (sci.Architecture) { - p += strlen(p) + 1; - if (p != argv[i]) - { - shift_strings = FALSE; - break; - } + case PROCESSOR_ARCHITECTURE_INTEL: + case PROCESSOR_ARCHITECTURE_AMD64: + features[PF_COMPARE_EXCHANGE_DOUBLE] = !!(sci.FeatureSet & CPU_FEATURE_CX8); + features[PF_MMX_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_MMX); + features[PF_XMMI_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE); + features[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_3DNOW); + features[PF_RDTSC_INSTRUCTION_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_TSC); + features[PF_PAE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_PAE); + features[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE2); + features[PF_SSE3_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_SSE3); + features[PF_XSAVE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_XSAVE); + features[PF_COMPARE_EXCHANGE128] = !!(sci.FeatureSet & CPU_FEATURE_CX128); + features[PF_SSE_DAZ_MODE_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_DAZ); + features[PF_NX_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_NX); + features[PF_SECOND_LEVEL_ADDRESS_TRANSLATION] = !!(sci.FeatureSet & CPU_FEATURE_2NDLEV); + features[PF_VIRT_FIRMWARE_ENABLED] = !!(sci.FeatureSet & CPU_FEATURE_VIRT); + features[PF_RDWRFSGSBASE_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_RDFS); + features[PF_FASTFAIL_AVAILABLE] = TRUE; + break; + case PROCESSOR_ARCHITECTURE_ARM: + features[PF_ARM_VFP_32_REGISTERS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_VFP_32); + features[PF_ARM_NEON_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_NEON); + features[PF_ARM_V8_INSTRUCTIONS_AVAILABLE] = (sci.Level >= 8); + break; + case PROCESSOR_ARCHITECTURE_ARM64: + features[PF_ARM_V8_INSTRUCTIONS_AVAILABLE] = TRUE; + features[PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_V8_CRC32); + features[PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE] = !!(sci.FeatureSet & CPU_FEATURE_ARM_V8_CRYPTO); + break; } -#endif +} - if (shift_strings) +HANDLE user_shared_data_init_done(void) +{ + static const WCHAR wine_usdW[] = {'\\','K','e','r','n','e','l','O','b','j','e','c','t','s', + '\\','_','_','w','i','n','e','_','u','s','e','r','_','s','h','a','r','e','d','_','d','a','t','a',0}; + OBJECT_ATTRIBUTES attr = {sizeof(attr)}; + UNICODE_STRING wine_usd_str; + LARGE_INTEGER section_size; + NTSTATUS status; + HANDLE section; + SIZE_T size; + void *addr; + int res, fd, needs_close; + + section_size.QuadPart = sizeof(*user_shared_data); + + RtlInitUnicodeString( &wine_usd_str, wine_usdW ); + InitializeObjectAttributes( &attr, &wine_usd_str, OBJ_OPENIF, NULL, NULL ); + if ((status = NtCreateSection( §ion, SECTION_ALL_ACCESS, &attr, + §ion_size, PAGE_READWRITE, SEC_COMMIT, NULL )) && + status != STATUS_OBJECT_NAME_EXISTS) { - int offset = argv[1] - argv[0]; - char *end = argv[argc-1] + strlen(argv[argc-1]) + 1; - memmove( argv[0], argv[1], end - argv[1] ); - memset( end - offset, 0, offset ); - for (i = 1; i < argc; i++) - argv[i-1] = argv[i] - offset; - argv[i-1] = NULL; + MESSAGE( "wine: failed to create or open the USD section: %08x\n", status ); + exit(1); } - else + + if (status != STATUS_OBJECT_NAME_EXISTS) { - /* remove argv[0] */ - memmove( argv, argv + 1, argc * sizeof(argv[0]) ); - } + addr = NULL; + size = sizeof(*user_shared_data); + if ((status = NtMapViewOfSection( section, NtCurrentProcess(), &addr, 0, 0, 0, + &size, 0, 0, PAGE_READWRITE ))) + { + MESSAGE( "wine: failed to initialize the USD section: %08x\n", status ); + exit(1); + } - name = argv[0]; - if ((p = strrchr( name, '\\' ))) name = p + 1; - if ((p = strrchr( name, '/' ))) name = p + 1; + fill_user_shared_data( addr ); + NtUnmapViewOfSection( NtCurrentProcess(), addr ); + } -#if defined(HAVE_SETPROGNAME) - setprogname( name ); -#endif + if ((res = server_get_unix_fd( section, 0, &fd, &needs_close, NULL, NULL )) || + (user_shared_data != mmap( user_shared_data, sizeof(*user_shared_data), + PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0 ))) + { + MESSAGE( "wine: failed to remap the process USD: %d\n", res ); + exit(1); + } + if (needs_close) close( fd ); -#ifdef HAVE_PRCTL -#ifndef PR_SET_NAME -# define PR_SET_NAME 15 -#endif - prctl( PR_SET_NAME, name ); -#endif /* HAVE_PRCTL */ + return section; } - /*********************************************************************** * thread_init * @@ -222,11 +301,9 @@ */ TEB *thread_init(void) { - SYSTEM_BASIC_INFORMATION sbi; TEB *teb; void *addr; SIZE_T size; - LARGE_INTEGER now; NTSTATUS status; struct ntdll_thread_data *thread_data; @@ -235,16 +312,15 @@ /* reserve space for shared user data */ addr = (void *)0x7ffe0000; - size = 0x10000; + size = 0x1000; status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, - MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); + MEM_RESERVE|MEM_COMMIT, PAGE_READONLY ); if (status) { MESSAGE( "wine: failed to map the shared user data: %08x\n", status ); exit(1); } user_shared_data = addr; - memcpy( user_shared_data->NtSystemRoot, default_windirW, sizeof(default_windirW) ); /* allocate and initialize the PEB and initial TEB */ @@ -285,23 +361,9 @@ thread_data->wait_fd[0] = -1; thread_data->wait_fd[1] = -1; - debug_init(); - init_paths(); - set_process_name( __wine_main_argc, __wine_main_argv ); - - /* initialize time values in user_shared_data */ - NtQuerySystemTime( &now ); - user_shared_data->SystemTime.LowPart = now.u.LowPart; - user_shared_data->SystemTime.High1Time = user_shared_data->SystemTime.High2Time = now.u.HighPart; - user_shared_data->u.TickCountQuad = (now.QuadPart - server_start_time) / 10000; - user_shared_data->u.TickCount.High2Time = user_shared_data->u.TickCount.High1Time; - user_shared_data->TickCountLowDeprecated = user_shared_data->u.TickCount.LowPart; - user_shared_data->TickCountMultiplier = 1 << 24; + unix_funcs->dbg_init(); + unix_funcs->get_paths( &build_dir, &data_dir, &config_dir ); fill_cpu_info(); - - virtual_get_system_info( &sbi ); - user_shared_data->NumberOfPhysicalPages = sbi.MmNumberOfPhysicalPages; - return teb; } diff -Nru wine-development-5.8/dlls/ntdll/time.c wine-development-5.9/dlls/ntdll/time.c --- wine-development-5.8/dlls/ntdll/time.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/time.c 2020-05-22 18:49:34.000000000 +0000 @@ -44,8 +44,10 @@ #include "ntstatus.h" #define WIN32_NO_STATUS +#define NONAMELESSUNION #include "windef.h" #include "winternl.h" +#include "ddk/wdm.h" #include "wine/exception.h" #include "wine/debug.h" #include "ntdll_misc.h" @@ -577,9 +579,10 @@ * NtGetTickCount (NTDLL.@) * ZwGetTickCount (NTDLL.@) */ -ULONG WINAPI NtGetTickCount(void) +ULONG WINAPI DECLSPEC_HOTPATCH NtGetTickCount(void) { - return monotonic_counter() / TICKSPERMSEC; + /* note: we ignore TickCountMultiplier */ + return user_shared_data->u.TickCount.LowPart; } /* calculate the mday of dst change date, so that for instance Sun 5 Oct 2007 @@ -1126,11 +1129,21 @@ */ BOOL WINAPI RtlQueryUnbiasedInterruptTime(ULONGLONG *time) { + ULONG high, low; + if (!time) { RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); return FALSE; } - *time = monotonic_counter(); + + do + { + high = user_shared_data->InterruptTime.High1Time; + low = user_shared_data->InterruptTime.LowPart; + } + while (high != user_shared_data->InterruptTime.High2Time); + /* FIXME: should probably subtract InterruptTimeBias */ + *time = (ULONGLONG)high << 32 | low; return TRUE; } diff -Nru wine-development-5.8/dlls/ntdll/unix/debug.c wine-development-5.9/dlls/ntdll/unix/debug.c --- wine-development-5.8/dlls/ntdll/unix/debug.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/unix/debug.c 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,295 @@ +/* + * Debugging functions + * + * Copyright 2000 Alexandre Julliard + * + * 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 + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "wine/debug.h" +#include "ntdll_misc.h" + +WINE_DECLARE_DEBUG_CHANNEL(pid); +WINE_DECLARE_DEBUG_CHANNEL(timestamp); + +static BOOL init_done; +static struct debug_info initial_info; /* debug info for initial thread */ +static unsigned char default_flags = (1 << __WINE_DBCL_ERR) | (1 << __WINE_DBCL_FIXME); +static int nb_debug_options = -1; +static int options_size; +static struct __wine_debug_channel *debug_options; + +static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" }; + +/* get the debug info pointer for the current thread */ +static inline struct debug_info *get_info(void) +{ + if (!init_done) return &initial_info; + return ntdll_get_thread_data()->debug_info; +} + +/* add a string to the output buffer */ +static int append_output( struct debug_info *info, const char *str, size_t len ) +{ + if (len >= sizeof(info->output) - info->out_pos) + { + fprintf( stderr, "wine_dbg_output: debugstr buffer overflow (contents: '%s')\n", info->output ); + info->out_pos = 0; + abort(); + } + memcpy( info->output + info->out_pos, str, len ); + info->out_pos += len; + return len; +} + +/* add a new debug option at the end of the option list */ +static void add_option( const char *name, unsigned char set, unsigned char clear ) +{ + int min = 0, max = nb_debug_options - 1, pos, res; + + if (!name[0]) /* "all" option */ + { + default_flags = (default_flags & ~clear) | set; + return; + } + if (strlen(name) >= sizeof(debug_options[0].name)) return; + + while (min <= max) + { + pos = (min + max) / 2; + res = strcmp( name, debug_options[pos].name ); + if (!res) + { + debug_options[pos].flags = (debug_options[pos].flags & ~clear) | set; + return; + } + if (res < 0) max = pos - 1; + else min = pos + 1; + } + if (nb_debug_options >= options_size) + { + options_size = max( options_size * 2, 16 ); + debug_options = realloc( debug_options, options_size * sizeof(debug_options[0]) ); + } + + pos = min; + if (pos < nb_debug_options) memmove( &debug_options[pos + 1], &debug_options[pos], + (nb_debug_options - pos) * sizeof(debug_options[0]) ); + strcpy( debug_options[pos].name, name ); + debug_options[pos].flags = (default_flags & ~clear) | set; + nb_debug_options++; +} + +/* parse a set of debugging option specifications and add them to the option list */ +static void parse_options( const char *str ) +{ + char *opt, *next, *options; + unsigned int i; + + if (!(options = strdup(str))) return; + for (opt = options; opt; opt = next) + { + const char *p; + unsigned char set = 0, clear = 0; + + if ((next = strchr( opt, ',' ))) *next++ = 0; + + p = opt + strcspn( opt, "+-" ); + if (!p[0]) p = opt; /* assume it's a debug channel name */ + + if (p > opt) + { + for (i = 0; i < ARRAY_SIZE(debug_classes); i++) + { + int len = strlen(debug_classes[i]); + if (len != (p - opt)) continue; + if (!memcmp( opt, debug_classes[i], len )) /* found it */ + { + if (*p == '+') set |= 1 << i; + else clear |= 1 << i; + break; + } + } + if (i == ARRAY_SIZE(debug_classes)) /* bad class name, skip it */ + continue; + } + else + { + if (*p == '-') clear = ~0; + else set = ~0; + } + if (*p == '+' || *p == '-') p++; + if (!p[0]) continue; + + if (!strcmp( p, "all" )) + default_flags = (default_flags & ~clear) | set; + else + add_option( p, set, clear ); + } + free( options ); +} + +/* print the usage message */ +static void debug_usage(void) +{ + static const char usage[] = + "Syntax of the WINEDEBUG variable:\n" + " WINEDEBUG=[class]+xxx,[class]-yyy,...\n\n" + "Example: WINEDEBUG=+relay,warn-heap\n" + " turns on relay traces, disable heap warnings\n" + "Available message classes: err, warn, fixme, trace\n"; + write( 2, usage, sizeof(usage) - 1 ); + exit(1); +} + +/* initialize all options at startup */ +static void init_options(void) +{ + char *wine_debug = getenv("WINEDEBUG"); + struct stat st1, st2; + + nb_debug_options = 0; + + /* check for stderr pointing to /dev/null */ + if (!fstat( 2, &st1 ) && S_ISCHR(st1.st_mode) && + !stat( "/dev/null", &st2 ) && S_ISCHR(st2.st_mode) && + st1.st_rdev == st2.st_rdev) + { + default_flags = 0; + return; + } + if (!wine_debug) return; + if (!strcmp( wine_debug, "help" )) debug_usage(); + parse_options( wine_debug ); +} + +/*********************************************************************** + * __wine_dbg_get_channel_flags (NTDLL.@) + * + * Get the flags to use for a given channel, possibly setting them too in case of lazy init + */ +unsigned char __cdecl __wine_dbg_get_channel_flags( struct __wine_debug_channel *channel ) +{ + int min, max, pos, res; + + if (nb_debug_options == -1) init_options(); + + min = 0; + max = nb_debug_options - 1; + while (min <= max) + { + pos = (min + max) / 2; + res = strcmp( channel->name, debug_options[pos].name ); + if (!res) return debug_options[pos].flags; + if (res < 0) max = pos - 1; + else min = pos + 1; + } + /* no option for this channel */ + if (channel->flags & (1 << __WINE_DBCL_INIT)) channel->flags = default_flags; + return default_flags; +} + +/*********************************************************************** + * __wine_dbg_strdup (NTDLL.@) + */ +const char * __cdecl __wine_dbg_strdup( const char *str ) +{ + struct debug_info *info = get_info(); + unsigned int pos = info->str_pos; + size_t n = strlen( str ) + 1; + + assert( n <= sizeof(info->strings) ); + if (pos + n > sizeof(info->strings)) pos = 0; + info->str_pos = pos + n; + return memcpy( info->strings + pos, str, n ); +} + +/*********************************************************************** + * __wine_dbg_output (NTDLL.@) + */ +int __cdecl __wine_dbg_output( const char *str ) +{ + struct debug_info *info = get_info(); + const char *end = strrchr( str, '\n' ); + int ret = 0; + + if (end) + { + ret += append_output( info, str, end + 1 - str ); + write( 2, info->output, info->out_pos ); + info->out_pos = 0; + str = end + 1; + } + if (*str) ret += append_output( info, str, strlen( str )); + return ret; +} + +/*********************************************************************** + * __wine_dbg_header (NTDLL.@) + */ +int __cdecl __wine_dbg_header( enum __wine_debug_class cls, struct __wine_debug_channel *channel, + const char *function ) +{ + static const char * const classes[] = { "fixme", "err", "warn", "trace" }; + struct debug_info *info = get_info(); + char buffer[200], *pos = buffer; + + if (!(__wine_dbg_get_channel_flags( channel ) & (1 << cls))) return -1; + + /* only print header if we are at the beginning of the line */ + if (info->out_pos) return 0; + + if (init_done) + { + if (TRACE_ON(timestamp)) + { + ULONG ticks = NtGetTickCount(); + pos += sprintf( pos, "%3u.%03u:", ticks / 1000, ticks % 1000 ); + } + if (TRACE_ON(pid)) pos += sprintf( pos, "%04x:", GetCurrentProcessId() ); + pos += sprintf( pos, "%04x:", GetCurrentThreadId() ); + } + if (function && cls < ARRAY_SIZE( classes )) + snprintf( pos, sizeof(buffer) - (pos - buffer), "%s:%s:%s ", + classes[cls], channel->name, function ); + + return append_output( info, buffer, strlen( buffer )); +} + +/*********************************************************************** + * dbg_init + */ +void CDECL dbg_init(void) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + ntdll_get_thread_data()->debug_info = &initial_info; + init_done = TRUE; +} diff -Nru wine-development-5.8/dlls/ntdll/unix/loader.c wine-development-5.9/dlls/ntdll/unix/loader.c --- wine-development-5.8/dlls/ntdll/unix/loader.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/unix/loader.c 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,1374 @@ +/* + * Unix interface for loader functions + * + * Copyright (C) 2020 Alexandre Julliard + * + * 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 + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_PWD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#ifdef HAVE_SYS_PRCTL_H +# include +#endif +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef __APPLE__ +# include +# define LoadResource MacLoadResource +# define GetCurrentThread MacGetCurrentThread +# include +# undef LoadResource +# undef GetCurrentThread +# include +# include +# include +# include +# ifndef _POSIX_SPAWN_DISABLE_ASLR +# define _POSIX_SPAWN_DISABLE_ASLR 0x0100 +# endif +#endif + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winnt.h" +#include "winbase.h" +#include "winnls.h" +#include "winternl.h" +#include "unix_private.h" +#include "wine/library.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ntdll); + +extern IMAGE_NT_HEADERS __wine_spec_nt_header; +extern void CDECL __wine_set_unix_funcs( int version, const struct unix_funcs *funcs ); + +#ifdef __GNUC__ +static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2))); +#endif + +extern int __wine_main_argc; +extern char **__wine_main_argv; +extern char **__wine_main_environ; + +#if defined(linux) || defined(__APPLE__) +static const BOOL use_preloader = TRUE; +#else +static const BOOL use_preloader = FALSE; +#endif + +static const BOOL is_win64 = (sizeof(void *) > sizeof(int)); + +static int main_argc; +static char **main_argv; +static char **main_envp; +static char *argv0; +static const char *bin_dir; +static const char *dll_dir; +static const char *data_dir; +static const char *build_dir; +static const char *config_dir; +static const char **dll_paths; +static SIZE_T dll_path_maxlen; + +static CPTABLEINFO unix_table; + +static inline void *get_rva( const IMAGE_NT_HEADERS *nt, ULONG_PTR addr ) +{ + return (BYTE *)nt + addr; +} + +/* adjust an array of pointers to make them into RVAs */ +static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count ) +{ + BYTE **src = array; + DWORD *dst = array; + + for ( ; count; count--, src++, dst++) *dst = *src ? *src - base : 0; +} + +/* fixup an array of RVAs by adding the specified delta */ +static inline void fixup_rva_dwords( DWORD *ptr, int delta, unsigned int count ) +{ + for ( ; count; count--, ptr++) if (*ptr) *ptr += delta; +} + + +/* fixup an array of name/ordinal RVAs by adding the specified delta */ +static inline void fixup_rva_names( UINT_PTR *ptr, int delta ) +{ + for ( ; *ptr; ptr++) if (!(*ptr & IMAGE_ORDINAL_FLAG)) *ptr += delta; +} + + +/* fixup RVAs in the resource directory */ +static void fixup_so_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta ) +{ + IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); + unsigned int i; + + for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++) + { + void *ptr = root + entry->u2.s2.OffsetToDirectory; + if (entry->u2.s2.DataIsDirectory) fixup_so_resources( ptr, root, delta ); + else fixup_rva_dwords( &((IMAGE_RESOURCE_DATA_ENTRY *)ptr)->OffsetToData, delta, 1 ); + } +} + +/* die on a fatal error; use only during initialization */ +static void fatal_error( const char *err, ... ) +{ + va_list args; + + va_start( args, err ); + fprintf( stderr, "wine: " ); + vfprintf( stderr, err, args ); + va_end( args ); + exit(1); +} + +static void set_max_limit( int limit ) +{ + struct rlimit rlimit; + + if (!getrlimit( limit, &rlimit )) + { + rlimit.rlim_cur = rlimit.rlim_max; + setrlimit( limit, &rlimit ); + } +} + +/* canonicalize path and return its directory name */ +static char *realpath_dirname( const char *name ) +{ + char *p, *fullpath = realpath( name, NULL ); + + if (fullpath) + { + p = strrchr( fullpath, '/' ); + if (p == fullpath) p++; + if (p) *p = 0; + } + return fullpath; +} + +/* if string ends with tail, remove it */ +static char *remove_tail( const char *str, const char *tail ) +{ + size_t len = strlen( str ); + size_t tail_len = strlen( tail ); + char *ret; + + if (len < tail_len) return NULL; + if (strcmp( str + len - tail_len, tail )) return NULL; + ret = malloc( len - tail_len + 1 ); + memcpy( ret, str, len - tail_len ); + ret[len - tail_len] = 0; + return ret; +} + +/* build a path from the specified dir and name */ +static char *build_path( const char *dir, const char *name ) +{ + size_t len = strlen( dir ); + char *ret = malloc( len + strlen( name ) + 2 ); + + memcpy( ret, dir, len ); + if (len && ret[len - 1] != '/') ret[len++] = '/'; + strcpy( ret + len, name ); + return ret; +} + +static void set_dll_path(void) +{ + char *p, *path = getenv( "WINEDLLPATH" ); + int i, count = 0; + + if (path) for (p = path, count = 1; *p; p++) if (*p == ':') count++; + + dll_paths = malloc( (count + 2) * sizeof(*dll_paths) ); + count = 0; + + if (!build_dir) dll_paths[count++] = dll_dir; + + if (path) + { + path = strdup(path); + for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" )) dll_paths[count++] = strdup( p ); + free( path ); + } + + for (i = 0; i < count; i++) dll_path_maxlen = max( dll_path_maxlen, strlen(dll_paths[i]) ); + dll_paths[count] = NULL; +} + + +static void set_config_dir(void) +{ + char *p, *dir; + const char *prefix = getenv( "WINEPREFIX" ); + + if (prefix) + { + if (prefix[0] != '/') + fatal_error( "invalid directory %s in WINEPREFIX: not an absolute path\n", prefix ); + config_dir = dir = strdup( prefix ); + for (p = dir + strlen(dir) - 1; p > dir && *p == '/'; p--) *p = 0; + } + else + { + const char *home = getenv( "HOME" ); + if (!home) + { + struct passwd *pwd = getpwuid( getuid() ); + if (pwd) home = pwd->pw_dir; + } + if (!home) fatal_error( "could not determine your home directory\n" ); + if (home[0] != '/') fatal_error( "your home directory %s is not an absolute path\n", home ); + config_dir = build_path( home, ".wine" ); + } +} + +static void init_paths( int argc, char *argv[], char *envp[] ) +{ + Dl_info info; + + __wine_main_argc = main_argc = argc; + __wine_main_argv = main_argv = argv; + __wine_main_environ = main_envp = envp; + argv0 = strdup( argv[0] ); + + if (!dladdr( init_paths, &info ) || !(dll_dir = realpath_dirname( info.dli_fname ))) + fatal_error( "cannot get path to ntdll.so\n" ); + + if (!(build_dir = remove_tail( dll_dir, "/dlls/ntdll" ))) + { +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) + bin_dir = realpath_dirname( "/proc/self/exe" ); +#elif defined (__FreeBSD__) || defined(__DragonFly__) + bin_dir = realpath_dirname( "/proc/curproc/file" ); +#else + bin_dir = realpath_dirname( argv0 ); +#endif + if (!bin_dir) bin_dir = build_path( dll_dir, DLL_TO_BINDIR ); + data_dir = build_path( bin_dir, BIN_TO_DATADIR ); + } + + set_dll_path(); + set_config_dir(); +} + +#if !defined(__APPLE__) && !defined(__ANDROID__) /* these platforms always use UTF-8 */ + +/* charset to codepage map, sorted by name */ +static const struct { const char *name; UINT cp; } charset_names[] = +{ + { "ANSIX341968", 20127 }, + { "BIG5", 950 }, + { "BIG5HKSCS", 950 }, + { "CP1250", 1250 }, + { "CP1251", 1251 }, + { "CP1252", 1252 }, + { "CP1253", 1253 }, + { "CP1254", 1254 }, + { "CP1255", 1255 }, + { "CP1256", 1256 }, + { "CP1257", 1257 }, + { "CP1258", 1258 }, + { "CP932", 932 }, + { "CP936", 936 }, + { "CP949", 949 }, + { "CP950", 950 }, + { "EUCJP", 20932 }, + { "EUCKR", 949 }, + { "GB18030", 936 /* 54936 */ }, + { "GB2312", 936 }, + { "GBK", 936 }, + { "IBM037", 37 }, + { "IBM1026", 1026 }, + { "IBM424", 20424 }, + { "IBM437", 437 }, + { "IBM500", 500 }, + { "IBM850", 850 }, + { "IBM852", 852 }, + { "IBM855", 855 }, + { "IBM857", 857 }, + { "IBM860", 860 }, + { "IBM861", 861 }, + { "IBM862", 862 }, + { "IBM863", 863 }, + { "IBM864", 864 }, + { "IBM865", 865 }, + { "IBM866", 866 }, + { "IBM869", 869 }, + { "IBM874", 874 }, + { "IBM875", 875 }, + { "ISO88591", 28591 }, + { "ISO885913", 28603 }, + { "ISO885915", 28605 }, + { "ISO88592", 28592 }, + { "ISO88593", 28593 }, + { "ISO88594", 28594 }, + { "ISO88595", 28595 }, + { "ISO88596", 28596 }, + { "ISO88597", 28597 }, + { "ISO88598", 28598 }, + { "ISO88599", 28599 }, + { "KOI8R", 20866 }, + { "KOI8U", 21866 }, + { "TIS620", 28601 }, + { "UTF8", CP_UTF8 } +}; + +static void load_unix_cptable( unsigned int cp ) +{ + const char *dir = build_dir ? build_dir : data_dir; + struct stat st; + char *name; + void *data; + int fd; + + if (!(name = malloc( strlen(dir) + 22 ))) return; + sprintf( name, "%s/nls/c_%03u.nls", dir, cp ); + if ((fd = open( name, O_RDONLY )) != -1) + { + fstat( fd, &st ); + if ((data = malloc( st.st_size )) && st.st_size > 0x10000 && + read( fd, data, st.st_size ) == st.st_size) + { + RtlInitCodePageTable( data, &unix_table ); + } + else + { + free( data ); + } + close( fd ); + } + else ERR( "failed to load %s\n", name ); + free( name ); +} + +static void init_unix_codepage(void) +{ + char charset_name[16]; + const char *name; + size_t i, j; + int min = 0, max = ARRAY_SIZE(charset_names) - 1; + + setlocale( LC_CTYPE, "" ); + if (!(name = nl_langinfo( CODESET ))) return; + + /* remove punctuation characters from charset name */ + for (i = j = 0; name[i] && j < sizeof(charset_name)-1; i++) + { + if (name[i] >= '0' && name[i] <= '9') charset_name[j++] = name[i]; + else if (name[i] >= 'A' && name[i] <= 'Z') charset_name[j++] = name[i]; + else if (name[i] >= 'a' && name[i] <= 'z') charset_name[j++] = name[i] + ('A' - 'a'); + } + charset_name[j] = 0; + + while (min <= max) + { + int pos = (min + max) / 2; + int res = strcmp( charset_names[pos].name, charset_name ); + if (!res) + { + if (charset_names[pos].cp != CP_UTF8) load_unix_cptable( charset_names[pos].cp ); + return; + } + if (res > 0) max = pos - 1; + else min = pos + 1; + } + ERR( "unrecognized charset '%s'\n", name ); +} + +#else /* __APPLE__ || __ANDROID__ */ + +static void init_unix_codepage(void) { } + +#endif /* __APPLE__ || __ANDROID__ */ + + +/********************************************************************* + * get_version + */ +const char * CDECL get_version(void) +{ + return PACKAGE_VERSION; +} + + +/********************************************************************* + * get_build_id + */ +const char * CDECL get_build_id(void) +{ + extern const char wine_build[]; + return wine_build; +} + + +/********************************************************************* + * get_host_version + */ +void CDECL get_host_version( const char **sysname, const char **release ) +{ +#ifdef HAVE_SYS_UTSNAME_H + static struct utsname buf; + static BOOL init_done; + + if (!init_done) + { + uname( &buf ); + init_done = TRUE; + } + if (sysname) *sysname = buf.sysname; + if (release) *release = buf.release; +#else + if (sysname) *sysname = ""; + if (release) *release = ""; +#endif +} + + +/************************************************************************* + * get_main_args + * + * Return the initial arguments. + */ +static void CDECL get_main_args( int *argc, char **argv[], char **envp[] ) +{ + *argc = main_argc; + *argv = main_argv; + *envp = main_envp; +} + + +/************************************************************************* + * get_paths + * + * Return the various configuration paths. + */ +static void CDECL get_paths( const char **builddir, const char **datadir, const char **configdir ) +{ + *builddir = build_dir; + *datadir = data_dir; + *configdir = config_dir; +} + + +/************************************************************************* + * get_dll_path + * + * Return the various configuration paths. + */ +static void CDECL get_dll_path( const char ***paths, SIZE_T *maxlen ) +{ + *paths = dll_paths; + *maxlen = dll_path_maxlen; +} + + +/************************************************************************* + * get_unix_codepage + * + * Return the Unix codepage data. + */ +static void CDECL get_unix_codepage( CPTABLEINFO *table ) +{ + *table = unix_table; +} + + +static void preloader_exec( char **argv ) +{ + if (use_preloader) + { + static const char *preloader = "wine-preloader"; + char *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 ); + +#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] ); + } + execv( argv[1], argv + 1 ); +} + +static NTSTATUS loader_exec( const char *loader, char **argv, int is_child_64bit ) +{ + char *p, *path; + + if (build_dir) + { + argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" ); + preloader_exec( argv ); + return STATUS_INVALID_IMAGE_FORMAT; + } + + if ((p = strrchr( loader, '/' ))) loader = p + 1; + + argv[1] = build_path( bin_dir, loader ); + preloader_exec( argv ); + + argv[1] = getenv( "WINELOADER" ); + if (argv[1]) preloader_exec( argv ); + + if ((path = getenv( "PATH" ))) + { + for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" )) + { + argv[1] = build_path( p, loader ); + preloader_exec( argv ); + } + } + + argv[1] = build_path( BINDIR, loader ); + preloader_exec( argv ); + return STATUS_INVALID_IMAGE_FORMAT; +} + + +/*********************************************************************** + * exec_wineloader + * + * argv[0] and argv[1] must be reserved for the preloader and loader respectively. + */ +static NTSTATUS CDECL exec_wineloader( char **argv, int socketfd, int is_child_64bit, + ULONGLONG res_start, ULONGLONG res_end ) +{ + const char *loader = argv0; + const char *loader_env = getenv( "WINELOADER" ); + char preloader_reserve[64], socket_env[64]; + + if (!is_win64 ^ !is_child_64bit) + { + /* remap WINELOADER to the alternate 32/64-bit version if necessary */ + if (loader_env) + { + int len = strlen( loader_env ); + char *env = malloc( sizeof("WINELOADER=") + len + 2 ); + + if (!env) return STATUS_NO_MEMORY; + strcpy( env, "WINELOADER=" ); + strcat( env, loader_env ); + if (is_child_64bit) + { + strcat( env, "64" ); + } + else + { + len += sizeof("WINELOADER=") - 1; + if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0; + } + loader = env; + putenv( env ); + } + else loader = is_child_64bit ? "wine64" : "wine"; + } + + signal( SIGPIPE, SIG_DFL ); + + sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd ); + sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x", + (ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end ); + + putenv( preloader_reserve ); + putenv( socket_env ); + + return loader_exec( loader, argv, is_child_64bit ); +} + + +/*********************************************************************** + * exec_wineserver + * + * Exec a new wine server. + */ +static void exec_wineserver( char **argv ) +{ + char *path; + + if (build_dir) + { + if (!is_win64) /* look for 64-bit server */ + { + char *loader = realpath_dirname( build_path( build_dir, "loader/wine64" )); + if (loader) + { + argv[0] = build_path( loader, "../server/wineserver" ); + execv( argv[0], argv ); + } + } + argv[0] = build_path( build_dir, "server/wineserver" ); + execv( argv[0], argv ); + return; + } + + argv[0] = build_path( bin_dir, "wineserver" ); + execv( argv[0], argv ); + + argv[0] = getenv( "WINESERVER" ); + if (argv[0]) execv( argv[0], argv ); + + if ((path = getenv( "PATH" ))) + { + for (path = strtok( strdup( path ), ":" ); path; path = strtok( NULL, ":" )) + { + argv[0] = build_path( path, "wineserver" ); + execvp( argv[0], argv ); + } + } + + argv[0] = build_path( BINDIR, "wineserver" ); + execv( argv[0], argv ); +} + + +/*********************************************************************** + * start_server + * + * Start a new wine server. + */ +static void CDECL start_server( BOOL debug ) +{ + static BOOL started; /* we only try once */ + char *argv[3]; + static char debug_flag[] = "-d"; + + if (!started) + { + int status; + int pid = fork(); + if (pid == -1) fatal_error( "fork: %s", strerror(errno) ); + if (!pid) + { + argv[1] = debug ? debug_flag : NULL; + argv[2] = NULL; + exec_wineserver( argv ); + fatal_error( "could not exec wineserver\n" ); + } + waitpid( pid, &status, 0 ); + status = WIFEXITED(status) ? WEXITSTATUS(status) : 1; + if (status == 2) return; /* server lock held by someone else, will retry later */ + if (status) exit(status); /* server failed */ + started = TRUE; + } +} + + +/************************************************************************* + * map_so_dll + * + * Map a builtin dll in memory and fixup RVAs. + */ +static NTSTATUS CDECL map_so_dll( const IMAGE_NT_HEADERS *nt_descr, HMODULE module ) +{ + static const char builtin_signature[32] = "Wine builtin DLL"; + IMAGE_DATA_DIRECTORY *dir; + IMAGE_DOS_HEADER *dos; + IMAGE_NT_HEADERS *nt; + IMAGE_SECTION_HEADER *sec; + BYTE *addr = (BYTE *)module; + DWORD code_start, code_end, data_start, data_end, align_mask; + int delta, nb_sections = 2; /* code + data */ + unsigned int i; + DWORD size = (sizeof(IMAGE_DOS_HEADER) + + sizeof(builtin_signature) + + sizeof(IMAGE_NT_HEADERS) + + nb_sections * sizeof(IMAGE_SECTION_HEADER)); + + if (wine_anon_mmap( addr, size, PROT_READ | PROT_WRITE, MAP_FIXED ) != addr) return STATUS_NO_MEMORY; + + dos = (IMAGE_DOS_HEADER *)addr; + nt = (IMAGE_NT_HEADERS *)((BYTE *)(dos + 1) + sizeof(builtin_signature)); + sec = (IMAGE_SECTION_HEADER *)(nt + 1); + + /* build the DOS and NT headers */ + + dos->e_magic = IMAGE_DOS_SIGNATURE; + dos->e_cblp = 0x90; + dos->e_cp = 3; + dos->e_cparhdr = (sizeof(*dos) + 0xf) / 0x10; + dos->e_minalloc = 0; + dos->e_maxalloc = 0xffff; + dos->e_ss = 0x0000; + dos->e_sp = 0x00b8; + dos->e_lfanew = sizeof(*dos) + sizeof(builtin_signature); + + *nt = *nt_descr; + + delta = (const BYTE *)nt_descr - addr; + align_mask = nt->OptionalHeader.SectionAlignment - 1; + code_start = (size + align_mask) & ~align_mask; + data_start = delta & ~align_mask; +#ifdef __APPLE__ + { + Dl_info dli; + unsigned long data_size; + /* need the mach_header, not the PE header, to give to getsegmentdata(3) */ + dladdr(addr, &dli); + code_end = getsegmentdata(dli.dli_fbase, "__DATA", &data_size) - addr; + data_end = (code_end + data_size + align_mask) & ~align_mask; + } +#else + code_end = data_start; + data_end = (nt->OptionalHeader.SizeOfImage + delta + align_mask) & ~align_mask; +#endif + + fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 ); + + nt->FileHeader.NumberOfSections = nb_sections; + nt->OptionalHeader.BaseOfCode = code_start; +#ifndef _WIN64 + nt->OptionalHeader.BaseOfData = data_start; +#endif + nt->OptionalHeader.SizeOfCode = code_end - code_start; + nt->OptionalHeader.SizeOfInitializedData = data_end - data_start; + nt->OptionalHeader.SizeOfUninitializedData = 0; + nt->OptionalHeader.SizeOfImage = data_end; + nt->OptionalHeader.ImageBase = (ULONG_PTR)addr; + + /* build the code section */ + + memcpy( sec->Name, ".text", sizeof(".text") ); + sec->SizeOfRawData = code_end - code_start; + sec->Misc.VirtualSize = sec->SizeOfRawData; + sec->VirtualAddress = code_start; + sec->PointerToRawData = code_start; + sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ); + sec++; + + /* build the data section */ + + memcpy( sec->Name, ".data", sizeof(".data") ); + sec->SizeOfRawData = data_end - data_start; + sec->Misc.VirtualSize = sec->SizeOfRawData; + sec->VirtualAddress = data_start; + sec->PointerToRawData = data_start; + sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ); + sec++; + + for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++) + fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 ); + + /* build the import directory */ + + dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY]; + if (dir->Size) + { + IMAGE_IMPORT_DESCRIPTOR *imports = (IMAGE_IMPORT_DESCRIPTOR *)(addr + dir->VirtualAddress); + + while (imports->Name) + { + fixup_rva_dwords( &imports->u.OriginalFirstThunk, delta, 1 ); + fixup_rva_dwords( &imports->Name, delta, 1 ); + fixup_rva_dwords( &imports->FirstThunk, delta, 1 ); + if (imports->u.OriginalFirstThunk) + fixup_rva_names( (UINT_PTR *)(addr + imports->u.OriginalFirstThunk), delta ); + if (imports->FirstThunk) + fixup_rva_names( (UINT_PTR *)(addr + imports->FirstThunk), delta ); + imports++; + } + } + + /* build the resource directory */ + + dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY]; + if (dir->Size) + { + void *ptr = addr + dir->VirtualAddress; + fixup_so_resources( ptr, ptr, delta ); + } + + /* build the export directory */ + + dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY]; + if (dir->Size) + { + IMAGE_EXPORT_DIRECTORY *exports = (IMAGE_EXPORT_DIRECTORY *)(addr + dir->VirtualAddress); + + fixup_rva_dwords( &exports->Name, delta, 1 ); + fixup_rva_dwords( &exports->AddressOfFunctions, delta, 1 ); + fixup_rva_dwords( &exports->AddressOfNames, delta, 1 ); + fixup_rva_dwords( &exports->AddressOfNameOrdinals, delta, 1 ); + fixup_rva_dwords( (DWORD *)(addr + exports->AddressOfNames), delta, exports->NumberOfNames ); + fixup_rva_ptrs( addr + exports->AddressOfFunctions, addr, exports->NumberOfFunctions ); + } + return STATUS_SUCCESS; +} + +static const IMAGE_EXPORT_DIRECTORY *get_export_dir( HMODULE module ) +{ + const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)module; + const IMAGE_NT_HEADERS *nt; + DWORD addr; + + if (dos->e_magic != IMAGE_DOS_SIGNATURE) return NULL; + nt = (IMAGE_NT_HEADERS *)((const BYTE *)dos + dos->e_lfanew); + if (nt->Signature != IMAGE_NT_SIGNATURE) return NULL; + addr = nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY].VirtualAddress; + if (!addr) return NULL; + return (IMAGE_EXPORT_DIRECTORY *)((BYTE *)module + addr); +} + +static ULONG_PTR find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, DWORD ordinal ) +{ + const DWORD *functions = (const DWORD *)((BYTE *)module + exports->AddressOfFunctions); + + if (ordinal >= exports->NumberOfFunctions) return 0; + if (!functions[ordinal]) return 0; + return (ULONG_PTR)module + functions[ordinal]; +} + +static ULONG_PTR find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, + const IMAGE_IMPORT_BY_NAME *name ) +{ + const WORD *ordinals = (const WORD *)((BYTE *)module + exports->AddressOfNameOrdinals); + const DWORD *names = (const DWORD *)((BYTE *)module + exports->AddressOfNames); + int min = 0, max = exports->NumberOfNames - 1; + + /* first check the hint */ + if (name->Hint <= max) + { + char *ename = (char *)module + names[name->Hint]; + if (!strcmp( ename, (char *)name->Name )) + return find_ordinal_export( module, exports, ordinals[name->Hint] ); + } + + /* then do a binary search */ + while (min <= max) + { + int res, pos = (min + max) / 2; + char *ename = (char *)module + names[pos]; + if (!(res = strcmp( ename, (char *)name->Name ))) + return find_ordinal_export( module, exports, ordinals[pos] ); + if (res > 0) max = pos - 1; + else min = pos + 1; + } + return 0; +} + +static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt, HMODULE ntdll_module ) +{ + const IMAGE_EXPORT_DIRECTORY *ntdll_exports = get_export_dir( ntdll_module ); + const IMAGE_IMPORT_DESCRIPTOR *descr; + const IMAGE_THUNK_DATA *import_list; + IMAGE_THUNK_DATA *thunk_list; + + assert( ntdll_exports ); + + descr = get_rva( nt, nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].VirtualAddress ); + while (descr->Name) + { + /* ntdll must be the only import */ + assert( !strcmp( get_rva( nt, descr->Name ), "ntdll.dll" )); + + thunk_list = get_rva( nt, (DWORD)descr->FirstThunk ); + if (descr->u.OriginalFirstThunk) + import_list = get_rva( nt, (DWORD)descr->u.OriginalFirstThunk ); + else + import_list = thunk_list; + + + while (import_list->u1.Ordinal) + { + if (IMAGE_SNAP_BY_ORDINAL( import_list->u1.Ordinal )) + { + int ordinal = IMAGE_ORDINAL( import_list->u1.Ordinal ) - ntdll_exports->Base; + thunk_list->u1.Function = find_ordinal_export( ntdll_module, ntdll_exports, ordinal ); + if (!thunk_list->u1.Function) ERR( "ordinal %u not found\n", ordinal ); + } + else /* import by name */ + { + IMAGE_IMPORT_BY_NAME *pe_name = get_rva( nt, import_list->u1.AddressOfData ); + thunk_list->u1.Function = find_named_export( ntdll_module, ntdll_exports, pe_name ); + if (!thunk_list->u1.Function) ERR( "%s not found\n", pe_name->Name ); + } + import_list++; + thunk_list++; + } + + descr++; + } +} + +/*********************************************************************** + * load_ntdll + */ +static HMODULE load_ntdll(void) +{ + const IMAGE_NT_HEADERS *nt; + HMODULE module; + Dl_info info; + char *name; + void *handle; + + name = build_path( dll_dir, "ntdll.dll.so" ); + if (!dladdr( load_ntdll, &info )) fatal_error( "cannot get path to ntdll.so\n" ); + name = malloc( strlen(info.dli_fname) + 5 ); + strcpy( name, info.dli_fname ); + strcpy( name + strlen(info.dli_fname) - 3, ".dll.so" ); + if (!(handle = dlopen( name, RTLD_NOW ))) fatal_error( "failed to load %s: %s\n", name, dlerror() ); + if (!(nt = dlsym( handle, "__wine_spec_nt_header" ))) + fatal_error( "NT header not found in %s (too old?)\n", name ); + dll_dir = realpath_dirname( name ); + free( name ); + module = (HMODULE)((nt->OptionalHeader.ImageBase + 0xffff) & ~0xffff); + map_so_dll( nt, module ); + return module; +} + + +/*********************************************************************** + * unix_funcs + */ +static struct unix_funcs unix_funcs = +{ + get_main_args, + get_paths, + get_dll_path, + get_unix_codepage, + get_version, + get_build_id, + get_host_version, + exec_wineloader, + start_server, + map_so_dll, + mmap_add_reserved_area, + mmap_remove_reserved_area, + mmap_is_in_reserved_area, + mmap_enum_reserved_areas, + dbg_init, + __wine_dbg_get_channel_flags, + __wine_dbg_strdup, + __wine_dbg_output, + __wine_dbg_header, +}; + + +#ifdef __APPLE__ +struct apple_stack_info +{ + void *stack; + size_t desired_size; +}; + +static void *apple_wine_thread( void *arg ) +{ + __wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs ); + return NULL; +} + +/*********************************************************************** + * apple_alloc_thread_stack + * + * Callback for mmap_enum_reserved_areas to allocate space for + * the secondary thread's stack. + */ +#ifndef _WIN64 +static int CDECL apple_alloc_thread_stack( void *base, size_t size, void *arg ) +{ + struct apple_stack_info *info = arg; + + /* For mysterious reasons, putting the thread stack at the very top + * of the address space causes subsequent execs to fail, even on the + * child side of a fork. Avoid the top 16MB. */ + char * const limit = (char*)0xff000000; + if ((char *)base >= limit) return 0; + if (size > limit - (char*)base) + size = limit - (char*)base; + if (size < info->desired_size) return 0; + info->stack = wine_anon_mmap( (char *)base + size - info->desired_size, + info->desired_size, PROT_READ|PROT_WRITE, MAP_FIXED ); + return (info->stack != (void *)-1); +} +#endif + +/*********************************************************************** + * apple_create_wine_thread + * + * Spin off a secondary thread to complete Wine initialization, leaving + * the original thread for the Mac frameworks. + * + * Invoked as a CFRunLoopSource perform callback. + */ +static void apple_create_wine_thread( void *arg ) +{ + int success = 0; + pthread_t thread; + pthread_attr_t attr; + + if (!pthread_attr_init( &attr )) + { +#ifndef _WIN64 + struct apple_stack_info info; + + /* Try to put the new thread's stack in the reserved area. If this + * fails, just let it go wherever. It'll be a waste of space, but we + * can go on. */ + if (!pthread_attr_getstacksize( &attr, &info.desired_size ) && + mmap_enum_reserved_areas( apple_alloc_thread_stack, &info, 1 )) + { + mmap_remove_reserved_area( info.stack, info.desired_size ); + pthread_attr_setstackaddr( &attr, (char*)info.stack + info.desired_size ); + } +#endif + + if (!pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ) && + !pthread_create( &thread, &attr, apple_wine_thread, NULL )) + success = 1; + + pthread_attr_destroy( &attr ); + } + if (!success) exit(1); +} + + +/*********************************************************************** + * apple_main_thread + * + * Park the process's original thread in a Core Foundation run loop for + * use by the Mac frameworks, especially receiving and handling + * distributed notifications. Spin off a new thread for the rest of the + * Wine initialization. + */ +static void apple_main_thread(void) +{ + CFRunLoopSourceContext source_context = { 0 }; + CFRunLoopSourceRef source; + + if (!pthread_main_np()) return; + + /* Multi-processing Services can get confused about the main thread if the + * first time it's used is on a secondary thread. Use it here to make sure + * that doesn't happen. */ + MPTaskIsPreemptive(MPCurrentTaskID()); + + /* Give ourselves the best chance of having the distributed notification + * center scheduled on this thread's run loop. In theory, it's scheduled + * in the first thread to ask for it. */ + CFNotificationCenterGetDistributedCenter(); + + /* We use this run loop source for two purposes. First, a run loop exits + * if it has no more sources scheduled. So, we need at least one source + * to keep the run loop running. Second, although it's not critical, it's + * preferable for the Wine initialization to not proceed until we know + * the run loop is running. So, we signal our source immediately after + * adding it and have its callback spin off the Wine thread. */ + source_context.perform = apple_create_wine_thread; + source = CFRunLoopSourceCreate( NULL, 0, &source_context ); + CFRunLoopAddSource( CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes ); + CFRunLoopSourceSignal( source ); + CFRelease( source ); + CFRunLoopRun(); /* Should never return, except on error. */ +} +#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__)) + +static void check_vmsplit( void *stack ) +{ + if (stack < (void *)0x80000000) + { + /* if the stack is below 0x80000000, assume we can safely try a munmap there */ + if (munmap( (void *)0x80000000, 1 ) == -1 && errno == EINVAL) + ERR( "Warning: memory above 0x80000000 doesn't seem to be accessible.\n" + "Wine requires a 3G/1G user/kernel memory split to work properly.\n" ); + } +} + +static int pre_exec(void) +{ + int temp; + + check_vmsplit( &temp ); +#ifdef __i386__ + return 1; /* we have a preloader on x86 */ +#else + return 0; +#endif +} + +#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) +{ + struct rlimit rl; + + rl.rlim_cur = 0x02000000; + rl.rlim_max = 0x02000000; + setrlimit( RLIMIT_DATA, &rl ); + return 1; +} + +#else + +static int pre_exec(void) +{ + return 0; /* no exec needed */ +} + +#endif + + +/*********************************************************************** + * set_process_name + * + * Change the process name in the ps output. + */ +static void set_process_name( int argc, char *argv[] ) +{ + BOOL shift_strings; + char *p, *name; + int i; + +#ifdef HAVE_SETPROCTITLE + setproctitle("-%s", argv[1]); + shift_strings = FALSE; +#else + p = argv[0]; + + shift_strings = (argc >= 2); + for (i = 1; i < argc; i++) + { + p += strlen(p) + 1; + if (p != argv[i]) + { + shift_strings = FALSE; + break; + } + } +#endif + + if (shift_strings) + { + int offset = argv[1] - argv[0]; + char *end = argv[argc-1] + strlen(argv[argc-1]) + 1; + memmove( argv[0], argv[1], end - argv[1] ); + memset( end - offset, 0, offset ); + for (i = 1; i < argc; i++) + argv[i-1] = argv[i] - offset; + argv[i-1] = NULL; + } + else + { + /* remove argv[0] */ + memmove( argv, argv + 1, argc * sizeof(argv[0]) ); + } + + name = argv[0]; + if ((p = strrchr( name, '\\' ))) name = p + 1; + if ((p = strrchr( name, '/' ))) name = p + 1; + +#if defined(HAVE_SETPROGNAME) + setprogname( name ); +#endif + +#ifdef HAVE_PRCTL +#ifndef PR_SET_NAME +# define PR_SET_NAME 15 +#endif + prctl( PR_SET_NAME, name ); +#endif /* HAVE_PRCTL */ +} + + +/*********************************************************************** + * check_command_line + * + * Check if command line is one that needs to be handled specially. + */ +static void check_command_line( int argc, char *argv[] ) +{ + static const char usage[] = + "Usage: wine PROGRAM [ARGUMENTS...] Run the specified program\n" + " wine --help Display this help and exit\n" + " wine --version Output version information and exit"; + + if (argc <= 1) + { + fprintf( stderr, "%s\n", usage ); + exit(1); + } + if (!strcmp( argv[1], "--help" )) + { + printf( "%s\n", usage ); + exit(0); + } + if (!strcmp( argv[1], "--version" )) + { + printf( "%s\n", get_build_id() ); + exit(0); + } +} + + +/*********************************************************************** + * __wine_main + * + * Main entry point called by the wine loader. + */ +void __wine_main( int argc, char *argv[], char *envp[] ) +{ + HMODULE module; + + init_paths( argc, argv, envp ); + + if (!getenv( "WINELOADERNOEXEC" )) /* first time around */ + { + static char noexec[] = "WINELOADERNOEXEC=1"; + + putenv( noexec ); + check_command_line( argc, argv ); + if (pre_exec()) + { + char **new_argv = malloc( (argc + 2) * sizeof(*argv) ); + memcpy( new_argv + 1, argv, (argc + 1) * sizeof(*argv) ); + loader_exec( argv0, new_argv, is_win64 ); + fatal_error( "could not exec the wine loader\n" ); + } + } + +#ifdef RLIMIT_NOFILE + set_max_limit( RLIMIT_NOFILE ); +#endif +#ifdef RLIMIT_AS + set_max_limit( RLIMIT_AS ); +#endif + + virtual_init(); + + module = load_ntdll(); + fixup_ntdll_imports( &__wine_spec_nt_header, module ); + + set_process_name( argc, argv ); + init_unix_codepage(); + +#ifdef __APPLE__ + apple_main_thread(); +#endif + __wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs ); +} + + +static int add_area( void *base, size_t size, void *arg ) +{ + mmap_add_reserved_area( base, size ); + return 0; +} + +/*********************************************************************** + * __wine_init_unix_lib + * + * Lib entry point called by ntdll.dll.so if not yet initialized. + */ +NTSTATUS __cdecl __wine_init_unix_lib( HMODULE module, const void *ptr_in, void *ptr_out ) +{ + const IMAGE_NT_HEADERS *nt = ptr_in; + +#ifdef __APPLE__ + extern char **__wine_get_main_environment(void); + char **envp = __wine_get_main_environment(); +#else + char **envp = __wine_main_environ; +#endif + init_paths( __wine_main_argc, __wine_main_argv, envp ); + + map_so_dll( nt, module ); + fixup_ntdll_imports( &__wine_spec_nt_header, module ); + set_process_name( __wine_main_argc, __wine_main_argv ); + init_unix_codepage(); + *(struct unix_funcs **)ptr_out = &unix_funcs; + wine_mmap_enum_reserved_areas( add_area, NULL, 0 ); + return STATUS_SUCCESS; +} + +BOOL WINAPI DECLSPEC_HIDDEN DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) +{ + if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst ); + return TRUE; +} diff -Nru wine-development-5.8/dlls/ntdll/unix/unix_private.h wine-development-5.9/dlls/ntdll/unix/unix_private.h --- wine-development-5.8/dlls/ntdll/unix/unix_private.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/unix/unix_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Ntdll Unix private interface + * + * Copyright (C) 2020 Alexandre Julliard + * + * 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 + */ + +#ifndef __NTDLL_UNIX_PRIVATE_H +#define __NTDLL_UNIX_PRIVATE_H + +#include "unixlib.h" + +void CDECL mmap_add_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN; +void CDECL mmap_remove_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN; +int CDECL mmap_is_in_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN; +int CDECL mmap_enum_reserved_areas( int (CDECL *enum_func)(void *base, SIZE_T size, void *arg), void *arg, + int top_down ) DECLSPEC_HIDDEN; + +extern void virtual_init(void) DECLSPEC_HIDDEN; + +extern void CDECL dbg_init(void) DECLSPEC_HIDDEN; + +#endif /* __NTDLL_UNIX_PRIVATE_H */ diff -Nru wine-development-5.8/dlls/ntdll/unix/virtual.c wine-development-5.9/dlls/ntdll/unix/virtual.c --- wine-development-5.8/dlls/ntdll/unix/virtual.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/unix/virtual.c 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,373 @@ +/* + * Unix interface for virtual memory functions + * + * Copyright (C) 2020 Alexandre Julliard + * + * 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 + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" +#include "wine/port.h" + +#include +#include +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#if defined(__APPLE__) +# include +# include +#endif + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winnt.h" +#include "winternl.h" +#include "unix_private.h" +#include "wine/list.h" + +struct preload_info +{ + void *addr; + size_t size; +}; + +struct reserved_area +{ + struct list entry; + void *base; + size_t size; +}; + +static struct list reserved_areas = LIST_INIT(reserved_areas); + +static const unsigned int granularity_mask = 0xffff; /* reserved areas have 64k granularity */ + +extern IMAGE_NT_HEADERS __wine_spec_nt_header; + +#ifndef MAP_NORESERVE +#define MAP_NORESERVE 0 +#endif +#ifndef MAP_TRYFIXED +#define MAP_TRYFIXED 0 +#endif + + +static void reserve_area( void *addr, void *end ) +{ +#ifdef __APPLE__ + +#ifdef __i386__ + static const mach_vm_address_t max_address = VM_MAX_ADDRESS; +#else + static const mach_vm_address_t max_address = MACH_VM_MAX_ADDRESS; +#endif + mach_vm_address_t address = (mach_vm_address_t)addr; + mach_vm_address_t end_address = (mach_vm_address_t)end; + + if (!end_address || max_address < end_address) + end_address = max_address; + + while (address < end_address) + { + mach_vm_address_t hole_address = address; + kern_return_t ret; + mach_vm_size_t size; + vm_region_basic_info_data_64_t info; + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; + mach_port_t dummy_object_name = MACH_PORT_NULL; + + /* find the mapped region at or above the current address. */ + ret = mach_vm_region(mach_task_self(), &address, &size, VM_REGION_BASIC_INFO_64, + (vm_region_info_t)&info, &count, &dummy_object_name); + if (ret != KERN_SUCCESS) + { + address = max_address; + size = 0; + } + + if (end_address < address) + address = end_address; + if (hole_address < address) + { + /* found a hole, attempt to reserve it. */ + size_t hole_size = address - hole_address; + mach_vm_address_t alloc_address = hole_address; + + ret = mach_vm_map( mach_task_self(), &alloc_address, hole_size, 0, VM_FLAGS_FIXED, + MEMORY_OBJECT_NULL, 0, 0, PROT_NONE, VM_PROT_ALL, VM_INHERIT_COPY ); + if (!ret) mmap_add_reserved_area( (void*)hole_address, hole_size ); + else if (ret == KERN_NO_SPACE) + { + /* something filled (part of) the hole before we could. + go back and look again. */ + address = hole_address; + continue; + } + } + address += size; + } +#else + void *ptr; + int flags = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_TRYFIXED; + size_t size = (char *)end - (char *)addr; + + if (!size) return; + + ptr = mmap( addr, size, PROT_NONE, flags, -1, 0 ); + if (ptr == addr) + { + mmap_add_reserved_area( addr, size ); + return; + } + if (ptr != (void *)-1) munmap( ptr, size ); + + size = (size / 2) & ~granularity_mask; + if (size) + { + reserve_area( addr, (char *)addr + size ); + reserve_area( (char *)addr + size, end ); + } +#endif /* __APPLE__ */ +} + + +static void mmap_init( const struct preload_info *preload_info ) +{ +#ifdef __i386__ +#ifndef __APPLE__ + char stack; + char * const stack_ptr = &stack; +#endif + char *user_space_limit = (char *)0x7ffe0000; + int i; + + if (preload_info) + { + /* check for a reserved area starting at the user space limit */ + /* to avoid wasting time trying to allocate it again */ + for (i = 0; preload_info[i].size; i++) + { + if ((char *)preload_info[i].addr > user_space_limit) break; + if ((char *)preload_info[i].addr + preload_info[i].size > user_space_limit) + { + user_space_limit = (char *)preload_info[i].addr + preload_info[i].size; + break; + } + } + } + else reserve_area( (void *)0x00010000, (void *)0x40000000 ); + + +#ifndef __APPLE__ + if (stack_ptr >= user_space_limit) + { + char *end = 0; + char *base = stack_ptr - ((unsigned int)stack_ptr & granularity_mask) - (granularity_mask + 1); + if (base > user_space_limit) reserve_area( user_space_limit, base ); + base = stack_ptr - ((unsigned int)stack_ptr & granularity_mask) + (granularity_mask + 1); +#if defined(linux) || defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__) + /* Heuristic: assume the stack is near the end of the address */ + /* space, this avoids a lot of futile allocation attempts */ + end = (char *)(((unsigned long)base + 0x0fffffff) & 0xf0000000); +#endif + reserve_area( base, end ); + } + else +#endif + reserve_area( user_space_limit, 0 ); + +#elif defined(__x86_64__) || defined(__aarch64__) + + if (preload_info) return; + /* if we don't have a preloader, try to reserve the space now */ + reserve_area( (void *)0x000000010000, (void *)0x000068000000 ); + reserve_area( (void *)0x00007ff00000, (void *)0x00007fff0000 ); + reserve_area( (void *)0x7ffffe000000, (void *)0x7fffffff0000 ); + +#endif +} + +void CDECL mmap_add_reserved_area( void *addr, SIZE_T size ) +{ + struct reserved_area *area; + struct list *ptr; + + if (!((char *)addr + size)) size--; /* avoid wrap-around */ + + LIST_FOR_EACH( ptr, &reserved_areas ) + { + area = LIST_ENTRY( ptr, struct reserved_area, entry ); + if (area->base > addr) + { + /* try to merge with the next one */ + if ((char *)addr + size == (char *)area->base) + { + area->base = addr; + area->size += size; + return; + } + break; + } + else if ((char *)area->base + area->size == (char *)addr) + { + /* merge with the previous one */ + area->size += size; + + /* try to merge with the next one too */ + if ((ptr = list_next( &reserved_areas, ptr ))) + { + struct reserved_area *next = LIST_ENTRY( ptr, struct reserved_area, entry ); + if ((char *)addr + size == (char *)next->base) + { + area->size += next->size; + list_remove( &next->entry ); + free( next ); + } + } + return; + } + } + + if ((area = malloc( sizeof(*area) ))) + { + area->base = addr; + area->size = size; + list_add_before( ptr, &area->entry ); + } +} + +void CDECL mmap_remove_reserved_area( void *addr, SIZE_T size ) +{ + struct reserved_area *area; + struct list *ptr; + + if (!((char *)addr + size)) size--; /* avoid wrap-around */ + + ptr = list_head( &reserved_areas ); + /* find the first area covering address */ + while (ptr) + { + area = LIST_ENTRY( ptr, struct reserved_area, entry ); + if ((char *)area->base >= (char *)addr + size) break; /* outside the range */ + if ((char *)area->base + area->size > (char *)addr) /* overlaps range */ + { + if (area->base >= addr) + { + if ((char *)area->base + area->size > (char *)addr + size) + { + /* range overlaps beginning of area only -> shrink area */ + area->size -= (char *)addr + size - (char *)area->base; + area->base = (char *)addr + size; + break; + } + else + { + /* range contains the whole area -> remove area completely */ + ptr = list_next( &reserved_areas, ptr ); + list_remove( &area->entry ); + free( area ); + continue; + } + } + else + { + if ((char *)area->base + area->size > (char *)addr + size) + { + /* range is in the middle of area -> split area in two */ + struct reserved_area *new_area = malloc( sizeof(*new_area) ); + if (new_area) + { + new_area->base = (char *)addr + size; + new_area->size = (char *)area->base + area->size - (char *)new_area->base; + list_add_after( ptr, &new_area->entry ); + } + else size = (char *)area->base + area->size - (char *)addr; + area->size = (char *)addr - (char *)area->base; + break; + } + else + { + /* range overlaps end of area only -> shrink area */ + area->size = (char *)addr - (char *)area->base; + } + } + } + ptr = list_next( &reserved_areas, ptr ); + } +} + +int CDECL mmap_is_in_reserved_area( void *addr, SIZE_T size ) +{ + struct reserved_area *area; + struct list *ptr; + + LIST_FOR_EACH( ptr, &reserved_areas ) + { + area = LIST_ENTRY( ptr, struct reserved_area, entry ); + if (area->base > addr) break; + if ((char *)area->base + area->size <= (char *)addr) continue; + /* area must contain block completely */ + if ((char *)area->base + area->size < (char *)addr + size) return -1; + return 1; + } + return 0; +} + +int CDECL mmap_enum_reserved_areas( int (CDECL *enum_func)(void *base, SIZE_T size, void *arg), + void *arg, int top_down ) +{ + int ret = 0; + struct list *ptr; + + if (top_down) + { + for (ptr = reserved_areas.prev; ptr != &reserved_areas; ptr = ptr->prev) + { + struct reserved_area *area = LIST_ENTRY( ptr, struct reserved_area, entry ); + if ((ret = enum_func( area->base, area->size, arg ))) break; + } + } + else + { + for (ptr = reserved_areas.next; ptr != &reserved_areas; ptr = ptr->next) + { + struct reserved_area *area = LIST_ENTRY( ptr, struct reserved_area, entry ); + if ((ret = enum_func( area->base, area->size, arg ))) break; + } + } + return ret; +} + +void virtual_init(void) +{ + const struct preload_info **preload_info = dlsym( RTLD_DEFAULT, "wine_main_preload_info" ); + int i; + + if (preload_info && *preload_info) + for (i = 0; (*preload_info)[i].size; i++) + mmap_add_reserved_area( (*preload_info)[i].addr, (*preload_info)[i].size ); + + mmap_init( preload_info ? *preload_info : NULL ); +} diff -Nru wine-development-5.8/dlls/ntdll/unixlib.h wine-development-5.9/dlls/ntdll/unixlib.h --- wine-development-5.8/dlls/ntdll/unixlib.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/unixlib.h 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Ntdll Unix interface + * + * Copyright (C) 2020 Alexandre Julliard + * + * 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 + */ + +#ifndef __NTDLL_UNIXLIB_H +#define __NTDLL_UNIXLIB_H + +#include "wine/debug.h" + +/* increment this when you change the function table */ +#define NTDLL_UNIXLIB_VERSION 7 + +struct unix_funcs +{ + /* environment functions */ + void (CDECL *get_main_args)( int *argc, char **argv[], char **envp[] ); + void (CDECL *get_paths)( const char **builddir, const char **datadir, const char **configdir ); + void (CDECL *get_dll_path)( const char ***paths, SIZE_T *maxlen ); + void (CDECL *get_unix_codepage)( CPTABLEINFO *table ); + const char * (CDECL *get_version)(void); + const char * (CDECL *get_build_id)(void); + void (CDECL *get_host_version)( const char **sysname, const char **release ); + + /* loader functions */ + NTSTATUS (CDECL *exec_wineloader)( char **argv, int socketfd, int is_child_64bit, + ULONGLONG res_start, ULONGLONG res_end ); + void (CDECL *start_server)( BOOL debug ); + + /* virtual memory functions */ + NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module ); + void (CDECL *mmap_add_reserved_area)( void *addr, SIZE_T size ); + void (CDECL *mmap_remove_reserved_area)( void *addr, SIZE_T size ); + int (CDECL *mmap_is_in_reserved_area)( void *addr, SIZE_T size ); + int (CDECL *mmap_enum_reserved_areas)( int (CDECL *enum_func)(void *base, SIZE_T size, void *arg), + void *arg, int top_down ); + + /* debugging functions */ + void (CDECL *dbg_init)(void); + unsigned char (CDECL *dbg_get_channel_flags)( struct __wine_debug_channel *channel ); + const char * (CDECL *dbg_strdup)( const char *str ); + int (CDECL *dbg_output)( const char *str ); + int (CDECL *dbg_header)( enum __wine_debug_class cls, struct __wine_debug_channel *channel, + const char *function ); +}; + +#endif /* __NTDLL_UNIXLIB_H */ diff -Nru wine-development-5.8/dlls/ntdll/version.c wine-development-5.9/dlls/ntdll/version.c --- wine-development-5.8/dlls/ntdll/version.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/version.c 2020-05-22 18:49:34.000000000 +0000 @@ -540,12 +540,6 @@ NtCurrentTeb()->Peb->OSBuildNumber = current_version->dwBuildNumber; NtCurrentTeb()->Peb->OSPlatformId = current_version->dwPlatformId; - user_shared_data->NtProductType = current_version->wProductType; - user_shared_data->ProductTypeIsValid = TRUE; - user_shared_data->NtMajorVersion = current_version->dwMajorVersion; - user_shared_data->NtMinorVersion = current_version->dwMinorVersion; - user_shared_data->SuiteMask = current_version->wSuiteMask; - TRACE( "got %d.%d platform %d build %x name %s service pack %d.%d product %d\n", current_version->dwMajorVersion, current_version->dwMinorVersion, current_version->dwPlatformId, current_version->dwBuildNumber, diff -Nru wine-development-5.8/dlls/ntdll/virtual.c wine-development-5.9/dlls/ntdll/virtual.c --- wine-development-5.8/dlls/ntdll/virtual.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntdll/virtual.c 2020-05-22 18:49:34.000000000 +0000 @@ -685,7 +685,7 @@ } /* blow away existing mappings */ wine_anon_mmap( addr, size, PROT_NONE, MAP_NORESERVE | MAP_FIXED ); - wine_mmap_add_reserved_area( addr, size ); + unix_funcs->mmap_add_reserved_area( addr, size ); } @@ -700,7 +700,7 @@ struct file_view *view; TRACE( "removing %p-%p\n", addr, (char *)addr + size ); - wine_mmap_remove_reserved_area( addr, size, 0 ); + unix_funcs->mmap_remove_reserved_area( addr, size ); /* unmap areas not covered by an existing view */ WINE_RB_FOR_EACH_ENTRY( view, &views_tree, struct file_view, entry ) @@ -730,7 +730,7 @@ * in the specified region. If no boundaries are found, result is NULL. * The csVirtual section must be held by caller. */ -static int get_area_boundary_callback( void *start, size_t size, void *arg ) +static int CDECL get_area_boundary_callback( void *start, SIZE_T size, void *arg ) { struct area_boundary *area = arg; void *end = (char *)start + size; @@ -771,7 +771,7 @@ */ static inline void unmap_area( void *addr, size_t size ) { - switch (wine_mmap_is_in_reserved_area( addr, size )) + switch (unix_funcs->mmap_is_in_reserved_area( addr, size )) { case -1: /* partially in a reserved area */ { @@ -779,7 +779,7 @@ size_t lower_size; area.base = addr; area.size = size; - wine_mmap_enum_reserved_areas( get_area_boundary_callback, &area, 0 ); + unix_funcs->mmap_enum_reserved_areas( get_area_boundary_callback, &area, 0 ); assert( area.boundary ); lower_size = (char *)area.boundary - (char *)addr; unmap_area( addr, lower_size ); @@ -1129,9 +1129,9 @@ /*********************************************************************** * alloc_reserved_area_callback * - * Try to map some space inside a reserved area. Callback for wine_mmap_enum_reserved_areas. + * Try to map some space inside a reserved area. Callback for mmap_enum_reserved_areas. */ -static int alloc_reserved_area_callback( void *start, size_t size, void *arg ) +static int CDECL alloc_reserved_area_callback( void *start, SIZE_T size, void *arg ) { struct alloc_area *alloc = arg; void *end = (char *)start + size; @@ -1175,7 +1175,7 @@ { void *ptr; - switch (wine_mmap_is_in_reserved_area( base, size )) + switch (unix_funcs->mmap_is_in_reserved_area( base, size )) { case -1: /* partially in a reserved area */ { @@ -1184,7 +1184,7 @@ size_t lower_size; area.base = base; area.size = size; - wine_mmap_enum_reserved_areas( get_area_boundary_callback, &area, 0 ); + unix_funcs->mmap_enum_reserved_areas( get_area_boundary_callback, &area, 0 ); assert( area.boundary ); lower_size = (char *)area.boundary - (char *)base; status = map_fixed_area( base, lower_size, vprot ); @@ -1251,7 +1251,7 @@ alloc.top_down = top_down; alloc.limit = (void*)(get_zero_bits_64_mask( zero_bits_64 ) & (UINT_PTR)user_space_limit); - if (wine_mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down )) + if (unix_funcs->mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down )) { ptr = alloc.result; TRACE( "got mem in reserved area %p-%p\n", ptr, (char *)ptr + size ); @@ -1433,7 +1433,7 @@ /* check without the first 64K */ - if (wine_mmap_is_in_reserved_area( low_64k, dosmem_size - 0x10000 ) != 1) + if (unix_funcs->mmap_is_in_reserved_area( low_64k, dosmem_size - 0x10000 ) != 1) { addr = wine_anon_mmap( low_64k, dosmem_size - 0x10000, unix_prot, 0 ); if (addr != low_64k) @@ -1445,7 +1445,7 @@ /* now try to allocate the low 64K too */ - if (wine_mmap_is_in_reserved_area( NULL, 0x10000 ) != 1) + if (unix_funcs->mmap_is_in_reserved_area( NULL, 0x10000 ) != 1) { addr = wine_anon_mmap( (void *)page_size, 0x10000 - page_size, unix_prot, 0 ); if (addr == (void *)page_size) @@ -1588,6 +1588,7 @@ /* unaligned sections, this happens for native subsystem binaries */ /* in that case Windows simply maps in the whole file */ + total_size = min( total_size, ROUND_SIZE( 0, st.st_size )); if (map_file_into_view( view, fd, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY, removable ) != STATUS_SUCCESS) goto error; @@ -1921,8 +1922,8 @@ size_t size; }; -/* callback for wine_mmap_enum_reserved_areas to allocate space for the virtual heap */ -static int alloc_virtual_heap( void *base, size_t size, void *arg ) +/* callback for mmap_enum_reserved_areas to allocate space for the virtual heap */ +static int CDECL alloc_virtual_heap( void *base, SIZE_T size, void *arg ) { struct alloc_virtual_heap *alloc = arg; @@ -1984,8 +1985,8 @@ #else alloc_views.size = view_block_size + (1U << (32 - page_shift)); #endif - if (wine_mmap_enum_reserved_areas( alloc_virtual_heap, &alloc_views, 1 )) - wine_mmap_remove_reserved_area( alloc_views.base, alloc_views.size, 0 ); + if (unix_funcs->mmap_enum_reserved_areas( alloc_virtual_heap, &alloc_views, 1 )) + unix_funcs->mmap_remove_reserved_area( alloc_views.base, alloc_views.size ); else alloc_views.base = wine_anon_mmap( NULL, alloc_views.size, PROT_READ | PROT_WRITE, 0 ); @@ -1997,7 +1998,7 @@ /* make the DOS area accessible (except the low 64K) to hide bugs in broken apps like Excel 2003 */ size = (char *)address_space_start - (char *)0x10000; - if (size && wine_mmap_is_in_reserved_area( (void*)0x10000, size ) == 1) + if (size && unix_funcs->mmap_is_in_reserved_area( (void*)0x10000, size ) == 1) wine_anon_mmap( (void *)0x10000, size, PROT_READ | PROT_WRITE, MAP_FIXED ); } @@ -2700,8 +2701,8 @@ char *limit; }; -/* free reserved areas above the limit; callback for wine_mmap_enum_reserved_areas */ -static int free_reserved_memory( void *base, size_t size, void *arg ) +/* free reserved areas above the limit; callback for mmap_enum_reserved_areas */ +static int CDECL free_reserved_memory( void *base, SIZE_T size, void *arg ) { struct free_range *range = arg; @@ -2736,7 +2737,7 @@ if (range.limit > range.base) { - while (wine_mmap_enum_reserved_areas( free_reserved_memory, &range, 1 )) /* nothing */; + while (unix_funcs->mmap_enum_reserved_areas( free_reserved_memory, &range, 1 )) /* nothing */; #ifdef __APPLE__ /* On macOS, we still want to free some of low memory, for OpenGL resources */ range.base = (char *)0x40000000; @@ -2750,7 +2751,7 @@ if (range.base) { range.limit = (char *)0x7f000000; - while (wine_mmap_enum_reserved_areas( free_reserved_memory, &range, 0 )) /* nothing */; + while (unix_funcs->mmap_enum_reserved_areas( free_reserved_memory, &range, 0 )) /* nothing */; } server_leave_uninterrupted_section( &csVirtual, &sigset ); @@ -3086,8 +3087,8 @@ } -/* retrieve state for a free memory area; callback for wine_mmap_enum_reserved_areas */ -static int get_free_mem_state_callback( void *start, size_t size, void *arg ) +/* retrieve state for a free memory area; callback for mmap_enum_reserved_areas */ +static int CDECL get_free_mem_state_callback( void *start, SIZE_T size, void *arg ) { MEMORY_BASIC_INFORMATION *info = arg; void *end = (char *)start + size; @@ -3201,7 +3202,7 @@ if (!ptr) { - if (!wine_mmap_enum_reserved_areas( get_free_mem_state_callback, info, 0 )) + if (!unix_funcs->mmap_enum_reserved_areas( get_free_mem_state_callback, info, 0 )) { /* not in a reserved area at all, pretend it's allocated */ #ifdef __i386__ diff -Nru wine-development-5.8/dlls/ntoskrnl.exe/instr.c wine-development-5.9/dlls/ntoskrnl.exe/instr.c --- wine-development-5.8/dlls/ntoskrnl.exe/instr.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntoskrnl.exe/instr.c 2020-05-22 18:49:34.000000000 +0000 @@ -33,6 +33,15 @@ #include "wine/debug.h" #include "wine/exception.h" +#define KSHARED_USER_DATA_PAGE_SIZE 0x1000 + +enum instr_op +{ + INSTR_OP_MOV, + INSTR_OP_OR, + INSTR_OP_XOR, +}; + #ifdef __i386__ WINE_DEFAULT_DEBUG_CHANNEL(int); @@ -501,20 +510,49 @@ } /* store an operand into a register */ -static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op, int rex ) +static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op, int rex, + enum instr_op op ) { int index = REGMODRM_REG( regmodrm, rex ); BYTE *reg = (BYTE *)get_int_reg( context, index ); - memcpy( reg, addr, get_op_size( long_op, rex ) ); + int op_size = get_op_size( long_op, rex ); + int i; + + switch (op) + { + case INSTR_OP_MOV: + memcpy( reg, addr, op_size ); + break; + case INSTR_OP_OR: + for (i = 0; i < op_size; ++i) + reg[i] |= addr[i]; + break; + case INSTR_OP_XOR: + for (i = 0; i < op_size; ++i) + reg[i] ^= addr[i]; + break; + } } /* store an operand into a byte register */ -static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int rex ) +static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int rex, enum instr_op op ) { int index = REGMODRM_REG( regmodrm, rex ); BYTE *reg = (BYTE *)get_int_reg( context, index ); if (!rex && index >= 4 && index < 8) reg -= (4 * sizeof(DWORD64) - 1); /* special case: ah, ch, dh, bh */ - *reg = *addr; + + switch (op) + { + case INSTR_OP_MOV: + *reg = *addr; + break; + case INSTR_OP_OR: + *reg |= *addr; + break; + case INSTR_OP_XOR: + *reg ^= *addr; + break; + } } /*********************************************************************** @@ -593,15 +631,6 @@ } -static void update_shared_data(void) -{ - struct _KUSER_SHARED_DATA *shared_data = (struct _KUSER_SHARED_DATA *)wine_user_shared_data; - - shared_data->u.TickCountQuad = GetTickCount64(); - shared_data->u.TickCount.High2Time = shared_data->u.TickCount.High1Time; -} - - /*********************************************************************** * emulate_instruction * @@ -799,12 +828,13 @@ unsigned int data_size = (instr[1] == 0xb7) ? 2 : 1; SIZE_T offset = data - user_shared_data; - if (offset <= sizeof(KSHARED_USER_DATA) - data_size) + if (offset <= KSHARED_USER_DATA_PAGE_SIZE - data_size) { ULONGLONG temp = 0; - update_shared_data(); + + TRACE("USD offset %#x at %p.\n", (unsigned int)offset, (void *)context->Rip); memcpy( &temp, wine_user_shared_data + offset, data_size ); - store_reg_word( context, instr[2], (BYTE *)&temp, long_op, rex ); + store_reg_word( context, instr[2], (BYTE *)&temp, long_op, rex, INSTR_OP_MOV ); context->Rip += prefixlen + len + 2; return ExceptionContinueExecution; } @@ -815,19 +845,35 @@ case 0x8a: /* mov Eb, Gb */ case 0x8b: /* mov Ev, Gv */ + case 0x0b: /* or Ev, Gv */ + case 0x33: /* xor Ev, Gv */ { BYTE *data = INSTR_GetOperandAddr( context, instr + 1, prefixlen + 1, long_addr, rex, segprefix, &len ); unsigned int data_size = (*instr == 0x8b) ? get_op_size( long_op, rex ) : 1; SIZE_T offset = data - user_shared_data; - if (offset <= sizeof(KSHARED_USER_DATA) - data_size) + if (offset <= KSHARED_USER_DATA_PAGE_SIZE - data_size) { - update_shared_data(); + TRACE("USD offset %#x at %p.\n", (unsigned int)offset, (void *)context->Rip); switch (*instr) { - case 0x8a: store_reg_byte( context, instr[1], wine_user_shared_data + offset, rex ); break; - case 0x8b: store_reg_word( context, instr[1], wine_user_shared_data + offset, long_op, rex ); break; + case 0x8a: + store_reg_byte( context, instr[1], wine_user_shared_data + offset, + rex, INSTR_OP_MOV ); + break; + case 0x8b: + store_reg_word( context, instr[1], wine_user_shared_data + offset, + long_op, rex, INSTR_OP_MOV ); + break; + case 0x0b: + store_reg_word( context, instr[1], wine_user_shared_data + offset, + long_op, rex, INSTR_OP_OR ); + break; + case 0x33: + store_reg_word( context, instr[1], wine_user_shared_data + offset, + long_op, rex, INSTR_OP_XOR ); + break; } context->Rip += prefixlen + len + 1; return ExceptionContinueExecution; @@ -843,9 +889,9 @@ SIZE_T offset = data - user_shared_data; len = long_addr ? sizeof(DWORD64) : sizeof(DWORD); - if (offset <= sizeof(KSHARED_USER_DATA) - data_size) + if (offset <= KSHARED_USER_DATA_PAGE_SIZE - data_size) { - update_shared_data(); + TRACE("USD offset %#x at %p.\n", (unsigned int)offset, (void *)context->Rip); memcpy( &context->Rax, wine_user_shared_data + offset, data_size ); context->Rip += prefixlen + len + 1; return ExceptionContinueExecution; diff -Nru wine-development-5.8/dlls/ntoskrnl.exe/ntoskrnl.c wine-development-5.9/dlls/ntoskrnl.exe/ntoskrnl.c --- wine-development-5.8/dlls/ntoskrnl.exe/ntoskrnl.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntoskrnl.exe/ntoskrnl.c 2020-05-22 18:49:34.000000000 +0000 @@ -3413,8 +3413,8 @@ while (rel < end - 1 && rel->SizeOfBlock) { - void *page = get_rva( module, rel->VirtualAddress ); - DWORD old_prot; + char *page = get_rva( module, rel->VirtualAddress ); + DWORD old_prot1, old_prot2; if (rel->VirtualAddress >= len) { @@ -3424,10 +3424,12 @@ /* Relocation entries may hang over the end of the page, so we need to * protect two pages. */ - VirtualProtect( page, page_size * 2, PAGE_READWRITE, &old_prot ); + VirtualProtect( page, page_size, PAGE_READWRITE, &old_prot1 ); + VirtualProtect( page + page_size, page_size, PAGE_READWRITE, &old_prot2 ); rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT), (USHORT *)(rel + 1), delta ); - VirtualProtect( page, page_size * 2, old_prot, &old_prot ); + VirtualProtect( page, page_size, old_prot1, &old_prot1 ); + VirtualProtect( page + page_size, page_size, old_prot2, &old_prot2 ); if (!rel) return STATUS_INVALID_IMAGE_FORMAT; } diff -Nru wine-development-5.8/dlls/ntoskrnl.exe/ntoskrnl.exe.spec wine-development-5.9/dlls/ntoskrnl.exe/ntoskrnl.exe.spec --- wine-development-5.8/dlls/ntoskrnl.exe/ntoskrnl.exe.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ntoskrnl.exe/ntoskrnl.exe.spec 2020-05-22 18:49:34.000000000 +0000 @@ -1016,7 +1016,7 @@ @ stub RtlCreateSystemVolumeInformationFolder @ stdcall RtlCreateUnicodeString(ptr wstr) @ stdcall RtlCreateUserThread(long ptr long ptr long long ptr ptr ptr ptr) -@ stdcall RtlCustomCPToUnicodeN(ptr ptr long ptr str long) ntdll.RtlCustomCPToUnicodeN +@ stdcall RtlCustomCPToUnicodeN(ptr ptr long ptr str long) @ stdcall RtlDecompressBuffer(long ptr long ptr long ptr) @ stub RtlDecompressChunks @ stdcall RtlDecompressFragment(long ptr long ptr long long ptr ptr) @@ -1069,7 +1069,8 @@ @ stub RtlFindUnicodePrefix @ stdcall RtlFirstFreeAce(ptr ptr) @ stdcall RtlFormatCurrentUserKeyPath(ptr) -@ stdcall RtlFormatMessage(ptr long long long long ptr ptr long) +@ stdcall RtlFormatMessage(ptr long long long long ptr ptr long ptr) +@ stdcall RtlFormatMessageEx(ptr long long long long ptr ptr long ptr long) @ stdcall RtlFreeAnsiString(ptr) @ stdcall RtlFreeHeap(long long ptr) @ stdcall RtlFreeOemString(ptr) @@ -1103,7 +1104,7 @@ @ stdcall RtlImageNtHeader(long) @ stdcall RtlInitAnsiString(ptr str) @ stdcall RtlInitAnsiStringEx(ptr str) -@ stdcall RtlInitCodePageTable(ptr ptr) ntdll.RtlInitCodePageTable +@ stdcall RtlInitCodePageTable(ptr ptr) @ stdcall RtlInitString(ptr str) @ stdcall RtlInitUnicodeString(ptr wstr) @ stdcall RtlInitUnicodeStringEx(ptr wstr) @@ -1127,18 +1128,18 @@ @ stdcall RtlIpv4AddressToStringExA(ptr long ptr ptr) @ stdcall RtlIpv4AddressToStringExW(ptr long ptr ptr) @ stdcall RtlIpv4AddressToStringW(ptr ptr) -@ stdcall RtlIpv4StringToAddressA(str long ptr ptr) ntdll.RtlIpv4StringToAddressA -@ stdcall RtlIpv4StringToAddressExA(str long ptr ptr) ntdll.RtlIpv4StringToAddressExA +@ stdcall RtlIpv4StringToAddressA(str long ptr ptr) +@ stdcall RtlIpv4StringToAddressExA(str long ptr ptr) @ stdcall RtlIpv4StringToAddressExW(wstr long ptr ptr) @ stdcall RtlIpv4StringToAddressW(wstr long ptr ptr) @ stub RtlIpv6AddressToStringA @ stub RtlIpv6AddressToStringExA @ stub RtlIpv6AddressToStringExW @ stub RtlIpv6AddressToStringW -@ stub RtlIpv6StringToAddressA -@ stub RtlIpv6StringToAddressExA +@ stdcall RtlIpv6StringToAddressA(str ptr ptr) +@ stdcall RtlIpv6StringToAddressExA(str ptr ptr ptr) @ stdcall RtlIpv6StringToAddressExW(wstr ptr ptr ptr) -@ stub RtlIpv6StringToAddressW +@ stdcall RtlIpv6StringToAddressW(wstr ptr ptr) @ stub RtlIsGenericTableEmpty @ stub RtlIsGenericTableEmptyAvl @ stdcall RtlIsNameLegalDOS8Dot3(ptr ptr ptr) @@ -1249,7 +1250,7 @@ @ stdcall RtlUnicodeStringToInteger(ptr long ptr) @ stdcall RtlUnicodeStringToOemSize(ptr) @ stdcall RtlUnicodeStringToOemString(ptr ptr long) -@ stdcall RtlUnicodeToCustomCPN(ptr ptr long ptr wstr long) ntdll.RtlUnicodeToCustomCPN +@ stdcall RtlUnicodeToCustomCPN(ptr ptr long ptr wstr long) @ stdcall RtlUnicodeToMultiByteN(ptr long ptr ptr long) @ stdcall RtlUnicodeToMultiByteSize(ptr ptr long) @ stdcall RtlUnicodeToOemN(ptr long ptr ptr long) @@ -1262,7 +1263,7 @@ @ stdcall RtlUpcaseUnicodeStringToAnsiString(ptr ptr long) @ stdcall RtlUpcaseUnicodeStringToCountedOemString(ptr ptr long) @ stdcall RtlUpcaseUnicodeStringToOemString(ptr ptr long) -@ stdcall RtlUpcaseUnicodeToCustomCPN(ptr ptr long ptr wstr long) ntdll.RtlUpcaseUnicodeToCustomCPN +@ stdcall RtlUpcaseUnicodeToCustomCPN(ptr ptr long ptr wstr long) @ stdcall RtlUpcaseUnicodeToMultiByteN(ptr long ptr ptr long) @ stdcall RtlUpcaseUnicodeToOemN(ptr long ptr ptr long) @ stdcall RtlUpperChar(long) diff -Nru wine-development-5.8/dlls/qcap/tests/qcap.c wine-development-5.9/dlls/qcap/tests/qcap.c --- wine-development-5.8/dlls/qcap/tests/qcap.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/qcap/tests/qcap.c 2020-05-22 18:49:34.000000000 +0000 @@ -1643,150 +1643,6 @@ ok(ref == 0, "IStream was not destroyed (%d)\n", ref); } -/* Outer IUnknown for COM aggregation tests */ -struct unk_impl { - IUnknown IUnknown_iface; - LONG ref; - IUnknown *inner_unk; -}; - -static inline struct unk_impl *impl_from_IUnknown(IUnknown *iface) -{ - return CONTAINING_RECORD(iface, struct unk_impl, IUnknown_iface); -} - -static HRESULT WINAPI unk_QueryInterface(IUnknown *iface, REFIID riid, void **ret_iface) -{ - struct unk_impl *This = impl_from_IUnknown(iface); - - return IUnknown_QueryInterface(This->inner_unk, riid, ret_iface); -} - -static ULONG WINAPI unk_AddRef(IUnknown *iface) -{ - struct unk_impl *This = impl_from_IUnknown(iface); - - return InterlockedIncrement(&This->ref); -} - -static ULONG WINAPI unk_Release(IUnknown *iface) -{ - struct unk_impl *This = impl_from_IUnknown(iface); - - return InterlockedDecrement(&This->ref); -} - -static const IUnknownVtbl unk_vtbl = -{ - unk_QueryInterface, - unk_AddRef, - unk_Release -}; - -static void test_COM_vfwcapture(void) -{ - struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL}; - IBaseFilter *bf; - IMediaFilter *mf; - IPersist *p; - IPersistPropertyBag *ppb; - IAMVfwCaptureDialogs *amvcd; - IAMFilterMiscFlags *amfmf; - ISpecifyPropertyPages *spp; - IUnknown *unk; - ULONG refcount; - HRESULT hr; - - /* COM aggregation */ - hr = CoCreateInstance(&CLSID_VfwCapture, &unk_obj.IUnknown_iface, CLSCTX_INPROC_SERVER, - &IID_IUnknown, (void**)&unk_obj.inner_unk); - if ((hr == REGDB_E_CLASSNOTREG) || (hr == CLASS_E_CLASSNOTAVAILABLE)) - { - win_skip("CLSID_VfwCapture not supported (0x%x)\n", hr); - return; - } - ok(hr == S_OK, "VfwCapture create failed: %08x\n", hr); - hr = IUnknown_QueryInterface(unk_obj.inner_unk, &IID_IBaseFilter, (void**)&bf); - ok(hr == S_OK, "QueryInterface for IID_IBaseFilter failed: %08x\n", hr); - refcount = IBaseFilter_AddRef(bf); - ok(refcount == unk_obj.ref, "VfwCapture just pretends to support COM aggregation\n"); - refcount = IBaseFilter_Release(bf); - ok(refcount == unk_obj.ref, "VfwCapture just pretends to support COM aggregation\n"); - refcount = IBaseFilter_Release(bf); - ok(refcount == 19, "Refcount should be back at 19 but is %u\n", refcount); - IUnknown_Release(unk_obj.inner_unk); - - /* Invalid RIID */ - hr = CoCreateInstance(&CLSID_VfwCapture, NULL, CLSCTX_INPROC_SERVER, &IID_IClassFactory, - (void**)&bf); - ok(hr == E_NOINTERFACE, "VfwCapture create failed: %08x, expected E_NOINTERFACE\n", hr); - - /* Same refcount for all VfwCapture interfaces */ - hr = CoCreateInstance(&CLSID_VfwCapture, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, - (void**)&bf); - ok(hr == S_OK, "VfwCapture create failed: %08x, expected S_OK\n", hr); - refcount = IBaseFilter_AddRef(bf); - ok(refcount == 2, "refcount == %u, expected 2\n", refcount); - - hr = IBaseFilter_QueryInterface(bf, &IID_IMediaFilter, (void**)&mf); - ok(hr == S_OK, "QueryInterface for IID_IMediaFilter failed: %08x\n", hr); - refcount = IMediaFilter_AddRef(mf); - ok(refcount == 4, "refcount == %u, expected 4\n", refcount); - refcount = IMediaFilter_Release(mf); - - hr = IBaseFilter_QueryInterface(bf, &IID_IPersist, (void**)&p); - ok(hr == S_OK, "QueryInterface for IID_IPersist failed: %08x\n", hr); - refcount = IPersist_AddRef(p); - ok(refcount == 5, "refcount == %u, expected 5\n", refcount); - refcount = IPersist_Release(p); - - hr = IBaseFilter_QueryInterface(bf, &IID_IPersistPropertyBag, (void**)&ppb); - ok(hr == S_OK, "QueryInterface for IID_IPersistPropertyBag failed: %08x\n", hr); - refcount = IPersistPropertyBag_AddRef(ppb); - ok(refcount == 6, "refcount == %u, expected 6\n", refcount); - refcount = IPersistPropertyBag_Release(ppb); - - hr = IBaseFilter_QueryInterface(bf, &IID_IAMVfwCaptureDialogs, (void**)&amvcd); - todo_wine ok(hr == S_OK, "QueryInterface for IID_IAMVfwCaptureDialogs failed: %08x\n", hr); - if (hr == S_OK) { - refcount = IAMVfwCaptureDialogs_AddRef(amvcd); - ok(refcount == 7, "refcount == %u, expected 7\n", refcount); - refcount = IAMVfwCaptureDialogs_Release(amvcd); - } - - hr = IBaseFilter_QueryInterface(bf, &IID_IAMFilterMiscFlags, (void**)&amfmf); - todo_wine ok(hr == S_OK, "QueryInterface for IID_IAMFilterMiscFlags failed: %08x\n", hr); - if (hr == S_OK) { - refcount = IAMFilterMiscFlags_AddRef(amfmf); - ok(refcount == 8, "refcount == %u, expected 8\n", refcount); - refcount = IAMFilterMiscFlags_Release(amfmf); - } - - hr = IBaseFilter_QueryInterface(bf, &IID_ISpecifyPropertyPages, (void**)&spp); - todo_wine ok(hr == S_OK, "QueryInterface for IID_ISpecifyPropertyPages failed: %08x\n", hr); - if (hr == S_OK) { - refcount = ISpecifyPropertyPages_AddRef(spp); - ok(refcount == 9, "refcount == %u, expected 9\n", refcount); - refcount = ISpecifyPropertyPages_Release(spp); - } - - hr = IBaseFilter_QueryInterface(bf, &IID_IUnknown, (void**)&unk); - ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); - refcount = IUnknown_AddRef(unk); - todo_wine ok(refcount == 10, "refcount == %u, expected 10\n", refcount); - refcount = IUnknown_Release(unk); - - /* Unsupported interfaces */ - hr = IBaseFilter_QueryInterface(bf, &IID_IAMStreamConfig, (void**)&unk); - ok(hr == E_NOINTERFACE, "QueryInterface for IID_IAMStreamConfig failed: %08x\n", hr); - hr = IBaseFilter_QueryInterface(bf, &IID_IAMVideoProcAmp, (void**)&unk); - todo_wine ok(hr == E_NOINTERFACE, "QueryInterface for IID_IAMVideoProcAmp failed: %08x\n", hr); - hr = IBaseFilter_QueryInterface(bf, &IID_IOverlayNotify, (void**)&unk); - ok(hr == E_NOINTERFACE, "QueryInterface for IID_IOverlayNotify failed: %08x\n", hr); - - while (IBaseFilter_Release(bf)); -} - START_TEST(qcap) { if (SUCCEEDED(CoInitialize(NULL))) @@ -1797,7 +1653,6 @@ arg_c = winetest_get_mainargs(&arg_v); test_AviMux(arg_c>2 ? arg_v[2] : NULL); - test_COM_vfwcapture(); CoUninitialize(); } diff -Nru wine-development-5.8/dlls/qcap/tests/smartteefilter.c wine-development-5.9/dlls/qcap/tests/smartteefilter.c --- wine-development-5.8/dlls/qcap/tests/smartteefilter.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/qcap/tests/smartteefilter.c 2020-05-22 18:49:34.000000000 +0000 @@ -185,12 +185,12 @@ ULONG ref; filter = (IBaseFilter *)0xdeadbeef; - hr = CoCreateInstance(&CLSID_AviDest, &test_outer, CLSCTX_INPROC_SERVER, + hr = CoCreateInstance(&CLSID_SmartTee, &test_outer, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (void **)&filter); ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); ok(!filter, "Got interface %p.\n", filter); - hr = CoCreateInstance(&CLSID_AviDest, &test_outer, CLSCTX_INPROC_SERVER, + hr = CoCreateInstance(&CLSID_SmartTee, &test_outer, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); ok(hr == S_OK, "Got hr %#x.\n", hr); ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); diff -Nru wine-development-5.8/dlls/qcap/tests/videocapture.c wine-development-5.9/dlls/qcap/tests/videocapture.c --- wine-development-5.8/dlls/qcap/tests/videocapture.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/qcap/tests/videocapture.c 2020-05-22 18:49:34.000000000 +0000 @@ -23,6 +23,21 @@ #include "wine/test.h" #include "wine/strmbase.h" +#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) +static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) +{ + IUnknown *iface = iface_ptr; + HRESULT hr, expected_hr; + IUnknown *unk; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&unk); + ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unk); +} + static void test_media_types(IPin *pin) { IEnumMediaTypes *enum_media_types; @@ -176,11 +191,64 @@ { test_media_types(pin); test_stream_config(pin); + + todo_wine check_interface(pin, &IID_IAMBufferNegotiation, TRUE); + check_interface(pin, &IID_IAMStreamConfig, TRUE); + todo_wine check_interface(pin, &IID_IAMStreamControl, TRUE); + check_interface(pin, &IID_IKsPropertySet, TRUE); + todo_wine check_interface(pin, &IID_IMediaSeeking, TRUE); + check_interface(pin, &IID_IPin, TRUE); + todo_wine check_interface(pin, &IID_IQualityControl, TRUE); + todo_wine check_interface(pin, &IID_ISpecifyPropertyPages, TRUE); + + check_interface(pin, &IID_IAMCrossbar, FALSE); + check_interface(pin, &IID_IAMDroppedFrames, FALSE); + check_interface(pin, &IID_IAMFilterMiscFlags, FALSE); + check_interface(pin, &IID_IAMPushSource, FALSE); + check_interface(pin, &IID_IAMTVTuner, FALSE); + check_interface(pin, &IID_IAMVideoCompression, FALSE); + check_interface(pin, &IID_IAMVideoProcAmp, FALSE); + check_interface(pin, &IID_IPersistPropertyBag, FALSE); } IPin_Release(pin); } IEnumPins_Release(enum_pins); + + check_interface(filter, &IID_IAMFilterMiscFlags, TRUE); + check_interface(filter, &IID_IAMVideoControl, TRUE); + check_interface(filter, &IID_IAMVideoProcAmp, TRUE); + check_interface(filter, &IID_IBaseFilter, TRUE); + todo_wine check_interface(filter, &IID_IKsPropertySet, TRUE); + todo_wine check_interface(filter, &IID_IMediaSeeking, TRUE); + check_interface(filter, &IID_IPersistPropertyBag, TRUE); + todo_wine check_interface(filter, &IID_ISpecifyPropertyPages, TRUE); + + check_interface(filter, &IID_IAMCrossbar, FALSE); + check_interface(filter, &IID_IAMPushSource, FALSE); + check_interface(filter, &IID_IAMStreamConfig, FALSE); + check_interface(filter, &IID_IAMTVTuner, FALSE); + check_interface(filter, &IID_IAMVideoCompression, FALSE); + check_interface(filter, &IID_IAMVfwCaptureDialogs, FALSE); + check_interface(filter, &IID_IPin, FALSE); + check_interface(filter, &IID_IReferenceClock, FALSE); + check_interface(filter, &IID_IOverlayNotify, FALSE); +} + +static void test_misc_flags(IBaseFilter *filter) +{ + IAMFilterMiscFlags *misc_flags; + ULONG flags; + HRESULT hr; + + hr = IBaseFilter_QueryInterface(filter, &IID_IAMFilterMiscFlags, (void **)&misc_flags); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + flags = IAMFilterMiscFlags_GetMiscFlags(misc_flags); + ok(flags == AM_FILTER_MISC_FLAGS_IS_SOURCE + || broken(!flags) /* win7 */, "Got wrong flags: %#x.\n", flags); + + IAMFilterMiscFlags_Release(misc_flags); } START_TEST(videocapture) @@ -220,6 +288,7 @@ if (hr == S_OK) { test_capture(filter); + test_misc_flags(filter); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); } diff -Nru wine-development-5.8/dlls/qcap/v4l.c wine-development-5.9/dlls/qcap/v4l.c --- wine-development-5.8/dlls/qcap/v4l.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/qcap/v4l.c 2020-05-22 18:49:34.000000000 +0000 @@ -442,6 +442,7 @@ { LONG depth = 24; + memset(caps, 0, sizeof(*caps)); caps->video_info.dwBitRate = width * height * depth * max_fps; caps->video_info.bmiHeader.biSize = sizeof(caps->video_info.bmiHeader); caps->video_info.bmiHeader.biWidth = width; diff -Nru wine-development-5.8/dlls/qcap/vfwcapture.c wine-development-5.9/dlls/qcap/vfwcapture.c --- wine-development-5.8/dlls/qcap/vfwcapture.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/qcap/vfwcapture.c 2020-05-22 18:49:34.000000000 +0000 @@ -48,7 +48,9 @@ { struct strmbase_filter filter; IAMStreamConfig IAMStreamConfig_iface; + IAMVideoControl IAMVideoControl_iface; IAMVideoProcAmp IAMVideoProcAmp_iface; + IAMFilterMiscFlags IAMFilterMiscFlags_iface; IPersistPropertyBag IPersistPropertyBag_iface; BOOL init; Capture *driver_info; @@ -67,11 +69,21 @@ return CONTAINING_RECORD(iface, VfwCapture, IAMStreamConfig_iface); } +static inline VfwCapture *impl_from_IAMVideoControl(IAMVideoControl *iface) +{ + return CONTAINING_RECORD(iface, VfwCapture, IAMVideoControl_iface); +} + static inline VfwCapture *impl_from_IAMVideoProcAmp(IAMVideoProcAmp *iface) { return CONTAINING_RECORD(iface, VfwCapture, IAMVideoProcAmp_iface); } +static inline VfwCapture *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface) +{ + return CONTAINING_RECORD(iface, VfwCapture, IAMFilterMiscFlags_iface); +} + static inline VfwCapture *impl_from_IPersistPropertyBag(IPersistPropertyBag *iface) { return CONTAINING_RECORD(iface, VfwCapture, IPersistPropertyBag_iface); @@ -115,8 +127,12 @@ if (IsEqualGUID(iid, &IID_IPersistPropertyBag)) *out = &filter->IPersistPropertyBag_iface; + else if (IsEqualGUID(iid, &IID_IAMVideoControl)) + *out = &filter->IAMVideoControl_iface; else if (IsEqualGUID(iid, &IID_IAMVideoProcAmp)) *out = &filter->IAMVideoProcAmp_iface; + else if (IsEqualGUID(iid, &IID_IAMFilterMiscFlags)) + *out = &filter->IAMFilterMiscFlags_iface; else return E_NOINTERFACE; @@ -574,6 +590,127 @@ .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, }; +static HRESULT WINAPI misc_flags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) +{ + VfwCapture *filter = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_QueryInterface(filter->filter.outer_unk, riid, ppv); +} + +static ULONG WINAPI misc_flags_AddRef(IAMFilterMiscFlags *iface) +{ + VfwCapture *filter = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_AddRef(filter->filter.outer_unk); +} + +static ULONG WINAPI misc_flags_Release(IAMFilterMiscFlags *iface) +{ + VfwCapture *filter = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_Release(filter->filter.outer_unk); +} + +static ULONG WINAPI misc_flags_GetMiscFlags(IAMFilterMiscFlags *iface) +{ + return AM_FILTER_MISC_FLAGS_IS_SOURCE; +} + +static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_VTable = +{ + misc_flags_QueryInterface, + misc_flags_AddRef, + misc_flags_Release, + misc_flags_GetMiscFlags +}; + +static HRESULT WINAPI video_control_QueryInterface(IAMVideoControl *iface, REFIID riid, void **ppv) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + return IUnknown_QueryInterface(filter->filter.outer_unk, riid, ppv); +} + +static ULONG WINAPI video_control_AddRef(IAMVideoControl *iface) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + return IUnknown_AddRef(filter->filter.outer_unk); +} + +static ULONG WINAPI video_control_Release(IAMVideoControl *iface) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + return IUnknown_Release(filter->filter.outer_unk); +} + +static HRESULT WINAPI video_control_GetCaps(IAMVideoControl *iface, IPin *pin, LONG *flags) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + + FIXME("filter %p, pin %p, flags %p: stub.\n", filter, pin, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_control_SetMode(IAMVideoControl *iface, IPin *pin, LONG mode) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + + FIXME("filter %p, pin %p, mode %d: stub.\n", filter, pin, mode); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_control_GetMode(IAMVideoControl *iface, IPin *pin, LONG *mode) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + + FIXME("filter %p, pin %p, mode %p: stub.\n", filter, pin, mode); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_control_GetCurrentActualFrameRate(IAMVideoControl *iface, IPin *pin, + LONGLONG *frame_rate) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + + FIXME("filter %p, pin %p, frame rate %p: stub.\n", filter, pin, frame_rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_control_GetMaxAvailableFrameRate(IAMVideoControl *iface, IPin *pin, + LONG index, SIZE dimensions, LONGLONG *frame_rate) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + + FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), frame rate %p: stub.\n", + filter, pin, index, dimensions.cx, dimensions.cy, frame_rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_control_GetFrameRateList(IAMVideoControl *iface, IPin *pin, LONG index, + SIZE dimensions, LONG *list_size, LONGLONG **frame_rate) +{ + VfwCapture *filter = impl_from_IAMVideoControl(iface); + + FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), list size %p, frame rate: %p: stub.\n", + filter, pin, index, dimensions.cx, dimensions.cy, list_size, frame_rate); + + return E_NOTIMPL; +} + +static const IAMVideoControlVtbl IAMVideoControl_VTable = +{ + video_control_QueryInterface, + video_control_AddRef, + video_control_Release, + video_control_GetCaps, + video_control_SetMode, + video_control_GetMode, + video_control_GetCurrentActualFrameRate, + video_control_GetMaxAvailableFrameRate, + video_control_GetFrameRateList +}; + HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out) { static const WCHAR source_name[] = {'O','u','t','p','u','t',0}; @@ -585,7 +722,9 @@ strmbase_filter_init(&object->filter, outer, &CLSID_VfwCapture, &filter_ops); object->IAMStreamConfig_iface.lpVtbl = &IAMStreamConfig_VTable; + object->IAMVideoControl_iface.lpVtbl = &IAMVideoControl_VTable; object->IAMVideoProcAmp_iface.lpVtbl = &IAMVideoProcAmp_VTable; + object->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_VTable; object->IPersistPropertyBag_iface.lpVtbl = &IPersistPropertyBag_VTable; object->init = FALSE; diff -Nru wine-development-5.8/dlls/quartz/dsoundrender.c wine-development-5.9/dlls/quartz/dsoundrender.c --- wine-development-5.8/dlls/quartz/dsoundrender.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/dsoundrender.c 2020-05-22 18:49:34.000000000 +0000 @@ -351,8 +351,6 @@ tStart = tStop = -1; } - IMediaSample_IsDiscontinuity(pSample); - if (IMediaSample_IsPreroll(pSample) == S_OK) { TRACE("Preroll!\n"); diff -Nru wine-development-5.8/dlls/quartz/enummoniker.c wine-development-5.9/dlls/quartz/enummoniker.c --- wine-development-5.8/dlls/quartz/enummoniker.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/enummoniker.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,208 +0,0 @@ -/* - * IEnumMoniker implementation - * - * Copyright 2003 Robert Shearman - * - * 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 "quartz_private.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(quartz); - -typedef struct EnumMonikerImpl -{ - IEnumMoniker IEnumMoniker_iface; - LONG ref; - IMoniker ** ppMoniker; - ULONG nMonikerCount; - ULONG index; -} EnumMonikerImpl; - -static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl; - -static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface) -{ - return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface); -} - -static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface); - -HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) -{ - /* NOTE: assumes that array of IMonikers has already been AddRef'd - * I.e. this function does not AddRef the array of incoming - * IMonikers */ - EnumMonikerImpl * pemi = CoTaskMemAlloc(sizeof(EnumMonikerImpl)); - - TRACE("(%p, %d, %p)\n", ppMoniker, nMonikerCount, ppEnum); - - *ppEnum = NULL; - - if (!pemi) - return E_OUTOFMEMORY; - - pemi->IEnumMoniker_iface.lpVtbl = &EnumMonikerImpl_Vtbl; - pemi->ref = 1; - pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*)); - memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*)); - pemi->nMonikerCount = nMonikerCount; - pemi->index = 0; - - *ppEnum = &pemi->IEnumMoniker_iface; - - return S_OK; -} - -/********************************************************************** - * IEnumMoniker_QueryInterface (also IUnknown) - */ -static HRESULT WINAPI EnumMonikerImpl_QueryInterface( - LPENUMMONIKER iface, - REFIID riid, - LPVOID *ppvObj) -{ - EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); - TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); - - if (This == NULL || ppvObj == NULL) return E_POINTER; - - if (IsEqualGUID(riid, &IID_IUnknown) || - IsEqualGUID(riid, &IID_IEnumMoniker)) - { - *ppvObj = iface; - EnumMonikerImpl_AddRef(iface); - return S_OK; - } - - *ppvObj = NULL; - FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -/********************************************************************** - * IEnumMoniker_AddRef (also IUnknown) - */ -static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface) -{ - EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); - ULONG ref; - - if (This == NULL) return E_POINTER; - - ref = InterlockedIncrement(&This->ref); - - TRACE("(%p)->() AddRef from %d\n", iface, ref - 1); - - return ref; -} - -/********************************************************************** - * IEnumMoniker_Release (also IUnknown) - */ -static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface) -{ - EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p)->() Release from %d\n", iface, ref + 1); - - if (!ref) - { - ULONG i; - - for (i = 0; i < This->nMonikerCount; i++) - IMoniker_Release(This->ppMoniker[i]); - - CoTaskMemFree(This->ppMoniker); - This->ppMoniker = NULL; - CoTaskMemFree(This); - return 0; - } - return ref; -} - -static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched) -{ - ULONG fetched; - EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); - - TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched); - - for (fetched = 0; (This->index + fetched < This->nMonikerCount) && (fetched < celt); fetched++) - { - rgelt[fetched] = This->ppMoniker[This->index + fetched]; - IMoniker_AddRef(rgelt[fetched]); - } - - This->index += fetched; - - TRACE("-- fetched %d\n", fetched); - - if (pceltFetched) - *pceltFetched = fetched; - - if (fetched != celt) - return S_FALSE; - else - return S_OK; -} - -static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt) -{ - EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); - - TRACE("(%p)->(%d)\n", iface, celt); - - This->index += celt; - - return S_OK; -} - -static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface) -{ - EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); - - TRACE("(%p)->()\n", iface); - - This->index = 0; - - return S_OK; -} - -static HRESULT WINAPI EnumMonikerImpl_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum) -{ - FIXME("(%p)->(%p): stub\n", iface, ppenum); - - return E_NOTIMPL; -} - -/********************************************************************** - * IEnumMoniker_Vtbl - */ -static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl = -{ - EnumMonikerImpl_QueryInterface, - EnumMonikerImpl_AddRef, - EnumMonikerImpl_Release, - EnumMonikerImpl_Next, - EnumMonikerImpl_Skip, - EnumMonikerImpl_Reset, - EnumMonikerImpl_Clone -}; diff -Nru wine-development-5.8/dlls/quartz/enumregfilters.c wine-development-5.9/dlls/quartz/enumregfilters.c --- wine-development-5.8/dlls/quartz/enumregfilters.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/enumregfilters.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,224 +0,0 @@ -/* - * Implementation of IEnumRegFilters Interface - * - * Copyright 2004 Christian Costa - * - * 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 "quartz_private.h" - - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(quartz); - -typedef struct IEnumRegFiltersImpl -{ - IEnumRegFilters IEnumRegFilters_iface; - LONG refCount; - ULONG size; - REGFILTER* RegFilters; - ULONG uIndex; -} IEnumRegFiltersImpl; - -static inline IEnumRegFiltersImpl *impl_from_IEnumRegFilters(IEnumRegFilters *iface) -{ - return CONTAINING_RECORD(iface, IEnumRegFiltersImpl, IEnumRegFilters_iface); -} - -static const struct IEnumRegFiltersVtbl IEnumRegFiltersImpl_Vtbl; - -HRESULT IEnumRegFiltersImpl_Construct(REGFILTER* pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum) -{ - IEnumRegFiltersImpl* pEnumRegFilters; - REGFILTER* pRegFilters = NULL; - unsigned int i; - - TRACE("(%p, %d, %p)\n", pInRegFilters, size, ppEnum); - - pEnumRegFilters = CoTaskMemAlloc(sizeof(IEnumRegFiltersImpl)); - if (!pEnumRegFilters) - { - *ppEnum = NULL; - return E_OUTOFMEMORY; - } - - /* Accept size of 0 */ - if (size) - { - pRegFilters = CoTaskMemAlloc(sizeof(REGFILTER)*size); - if (!pRegFilters) - { - CoTaskMemFree(pEnumRegFilters); - *ppEnum = NULL; - return E_OUTOFMEMORY; - } - } - - for(i = 0; i < size; i++) - { - pRegFilters[i].Clsid = pInRegFilters[i].Clsid; - pRegFilters[i].Name = CoTaskMemAlloc((lstrlenW(pInRegFilters[i].Name)+1)*sizeof(WCHAR)); - if (!pRegFilters[i].Name) - { - while(i) - CoTaskMemFree(pRegFilters[--i].Name); - CoTaskMemFree(pRegFilters); - CoTaskMemFree(pEnumRegFilters); - return E_OUTOFMEMORY; - } - CopyMemory(pRegFilters[i].Name, pInRegFilters[i].Name, (lstrlenW(pInRegFilters[i].Name)+1)*sizeof(WCHAR)); - } - - pEnumRegFilters->IEnumRegFilters_iface.lpVtbl = &IEnumRegFiltersImpl_Vtbl; - pEnumRegFilters->refCount = 1; - pEnumRegFilters->uIndex = 0; - pEnumRegFilters->RegFilters = pRegFilters; - pEnumRegFilters->size = size; - - *ppEnum = &pEnumRegFilters->IEnumRegFilters_iface; - - return S_OK; -} - -static HRESULT WINAPI IEnumRegFiltersImpl_QueryInterface(IEnumRegFilters * iface, REFIID riid, LPVOID * ppv) -{ - TRACE("(%p)->(%s, %p)\n", iface, qzdebugstr_guid(riid), ppv); - - *ppv = NULL; - - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = iface; - else if (IsEqualIID(riid, &IID_IEnumRegFilters)) - *ppv = iface; - - if (*ppv) - { - IUnknown_AddRef((IUnknown *)(*ppv)); - return S_OK; - } - - FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); - - return E_NOINTERFACE; -} - -static ULONG WINAPI IEnumRegFiltersImpl_AddRef(IEnumRegFilters * iface) -{ - IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface); - ULONG refCount = InterlockedIncrement(&This->refCount); - - TRACE("(%p)\n", iface); - - return refCount; -} - -static ULONG WINAPI IEnumRegFiltersImpl_Release(IEnumRegFilters * iface) -{ - IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface); - ULONG refCount = InterlockedDecrement(&This->refCount); - - TRACE("(%p)\n", iface); - - if (!refCount) - { - ULONG i; - - for(i = 0; i < This->size; i++) - { - CoTaskMemFree(This->RegFilters[i].Name); - } - CoTaskMemFree(This->RegFilters); - CoTaskMemFree(This); - return 0; - } else - return refCount; -} - -static HRESULT WINAPI IEnumRegFiltersImpl_Next(IEnumRegFilters * iface, ULONG cFilters, REGFILTER ** ppRegFilter, ULONG * pcFetched) -{ - ULONG cFetched; - IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface); - unsigned int i; - - cFetched = min(This->size, This->uIndex + cFilters) - This->uIndex; - - TRACE("(%p)->(%u, %p, %p)\n", iface, cFilters, ppRegFilter, pcFetched); - - if (cFetched > 0) - { - for(i = 0; i < cFetched; i++) - { - /* The string in the REGFILTER structure must be allocated in the same block as the REGFILTER structure itself */ - ppRegFilter[i] = CoTaskMemAlloc(sizeof(REGFILTER)+(lstrlenW(This->RegFilters[This->uIndex + i].Name)+1)*sizeof(WCHAR)); - if (!ppRegFilter[i]) - { - while(i) - { - CoTaskMemFree(ppRegFilter[--i]); - ppRegFilter[i] = NULL; - } - return E_OUTOFMEMORY; - } - ppRegFilter[i]->Clsid = This->RegFilters[This->uIndex + i].Clsid; - ppRegFilter[i]->Name = (WCHAR*)((char*)ppRegFilter[i]+sizeof(REGFILTER)); - CopyMemory(ppRegFilter[i]->Name, This->RegFilters[This->uIndex + i].Name, - (lstrlenW(This->RegFilters[This->uIndex + i].Name)+1)*sizeof(WCHAR)); - } - - This->uIndex += cFetched; - if (pcFetched) - *pcFetched = cFetched; - return S_OK; - } - - return S_FALSE; -} - -static HRESULT WINAPI IEnumRegFiltersImpl_Skip(IEnumRegFilters * iface, ULONG n) -{ - TRACE("(%p)->(%u)\n", iface, n); - - return E_NOTIMPL; -} - -static HRESULT WINAPI IEnumRegFiltersImpl_Reset(IEnumRegFilters * iface) -{ - IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface); - - TRACE("(%p)\n", iface); - - This->uIndex = 0; - return S_OK; -} - -static HRESULT WINAPI IEnumRegFiltersImpl_Clone(IEnumRegFilters * iface, IEnumRegFilters ** ppEnum) -{ - TRACE("(%p)->(%p)\n", iface, ppEnum); - - return E_NOTIMPL; -} - -static const IEnumRegFiltersVtbl IEnumRegFiltersImpl_Vtbl = -{ - IEnumRegFiltersImpl_QueryInterface, - IEnumRegFiltersImpl_AddRef, - IEnumRegFiltersImpl_Release, - IEnumRegFiltersImpl_Next, - IEnumRegFiltersImpl_Skip, - IEnumRegFiltersImpl_Reset, - IEnumRegFiltersImpl_Clone -}; diff -Nru wine-development-5.8/dlls/quartz/filtergraph.c wine-development-5.9/dlls/quartz/filtergraph.c --- wine-development-5.8/dlls/quartz/filtergraph.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/filtergraph.c 2020-05-22 18:49:34.000000000 +0000 @@ -530,31 +530,22 @@ return CONTAINING_RECORD(iface, IFilterGraphImpl, IFilterGraph2_iface); } -static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, REFIID riid, void **ppvObj) +static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface) { - IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface) { - IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface); + return IUnknown_Release(graph->outer_unk); } static IBaseFilter *find_filter_by_name(IFilterGraphImpl *graph, const WCHAR *name) @@ -2012,31 +2003,22 @@ return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaControl_iface); } -static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID riid, void **ppvObj) +static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IMediaControl(iface); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IMediaControl(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) { - IFilterGraphImpl *This = impl_from_IMediaControl(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IMediaControl(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI MediaControl_Release(IMediaControl *iface) { - IFilterGraphImpl *This = impl_from_IMediaControl(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IMediaControl(iface); + return IUnknown_Release(graph->outer_unk); } @@ -2150,11 +2132,63 @@ return S_OK; } +static void CALLBACK wait_pause_cb(TP_CALLBACK_INSTANCE *instance, void *context) +{ + IMediaControl *control = context; + OAFilterState state; + HRESULT hr; + + if ((hr = IMediaControl_GetState(control, INFINITE, &state)) != S_OK) + ERR("Failed to get paused state, hr %#x.\n", hr); + + if (FAILED(hr = IMediaControl_Stop(control))) + ERR("Failed to stop, hr %#x.\n", hr); + + if ((hr = IMediaControl_GetState(control, INFINITE, &state)) != S_OK) + ERR("Failed to get paused state, hr %#x.\n", hr); + + IMediaControl_Release(control); +} + +static void CALLBACK wait_stop_cb(TP_CALLBACK_INSTANCE *instance, void *context) +{ + IMediaControl *control = context; + OAFilterState state; + HRESULT hr; + + if ((hr = IMediaControl_GetState(control, INFINITE, &state)) != S_OK) + ERR("Failed to get state, hr %#x.\n", hr); + + IMediaControl_Release(control); +} + static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) { - IFilterGraphImpl *This = impl_from_IMediaControl(iface); + IFilterGraphImpl *graph = impl_from_IMediaControl(iface); + HRESULT hr; - FIXME("(%p/%p)->(): stub !!!\n", This, iface); + TRACE("graph %p.\n", graph); + + /* Even if we are already stopped, we still pause. */ + hr = IMediaControl_Pause(iface); + if (FAILED(hr)) + return hr; + else if (hr == S_FALSE) + { + IMediaControl_AddRef(iface); + TrySubmitThreadpoolCallback(wait_pause_cb, iface, NULL); + return S_FALSE; + } + + hr = IMediaControl_Stop(iface); + if (FAILED(hr)) + return hr; + else if (hr == S_FALSE) + { + IMediaControl_AddRef(iface); + TrySubmitThreadpoolCallback(wait_stop_cb, iface, NULL); + return S_FALSE; + } return S_OK; } @@ -2185,31 +2219,22 @@ return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaSeeking_iface); } -static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppvObj) +static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IMediaSeeking(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) { - IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IMediaSeeking(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) { - IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IMediaSeeking(iface); + return IUnknown_Release(graph->outer_unk); } typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg); @@ -2659,31 +2684,22 @@ } /*** IUnknown methods ***/ -static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj) +static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IMediaPosition(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface) { - IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IMediaPosition(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface) { - IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IMediaPosition(iface); + return IUnknown_Release(graph->outer_unk); } /*** IDispatch methods ***/ @@ -2871,31 +2887,22 @@ } /*** IUnknown methods ***/ -static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj) +static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IObjectWithSite( iface ); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IObjectWithSite(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface) { - IFilterGraphImpl *This = impl_from_IObjectWithSite( iface ); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IObjectWithSite(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface) { - IFilterGraphImpl *This = impl_from_IObjectWithSite( iface ); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IObjectWithSite(iface); + return IUnknown_Release(graph->outer_unk); } /*** IObjectWithSite methods ***/ @@ -2983,31 +2990,22 @@ return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface); } -static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj) +static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IBasicAudio(iface); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IBasicAudio(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) { - IFilterGraphImpl *This = impl_from_IBasicAudio(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IBasicAudio(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) { - IFilterGraphImpl *This = impl_from_IBasicAudio(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IBasicAudio(iface); + return IUnknown_Release(graph->outer_unk); } static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *count) @@ -3159,31 +3157,22 @@ return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface); } -static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj) +static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IBasicVideo2(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface) { - IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IBasicVideo2(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface) { - IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IBasicVideo2(iface); + return IUnknown_Release(graph->outer_unk); } static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *count) @@ -3952,31 +3941,22 @@ return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface); } -static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj) +static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IVideoWindow(iface); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IVideoWindow(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) { - IFilterGraphImpl *This = impl_from_IVideoWindow(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IVideoWindow(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) { - IFilterGraphImpl *This = impl_from_IVideoWindow(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IVideoWindow(iface); + return IUnknown_Release(graph->outer_unk); } HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *count) @@ -4871,31 +4851,22 @@ return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface); } -static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj) +static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID iid, void **out) { - IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); - - return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); + IFilterGraphImpl *graph = impl_from_IMediaEventEx(iface); + return IUnknown_QueryInterface(graph->outer_unk, iid, out); } static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) { - IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_AddRef(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IMediaEventEx(iface); + return IUnknown_AddRef(graph->outer_unk); } static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) { - IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return IUnknown_Release(This->outer_unk); + IFilterGraphImpl *graph = impl_from_IMediaEventEx(iface); + return IUnknown_Release(graph->outer_unk); } /*** IDispatch methods ***/ @@ -5296,7 +5267,7 @@ else if (filter_hr != S_OK && filter_hr != VFW_S_STATE_INTERMEDIATE) hr = filter_hr; if (filter_state != graph->state) - WARN("Filter %p reported incorrect state %u.\n", filter->filter, filter_state); + ERR("Filter %p reported incorrect state %u.\n", filter->filter, filter_state); } LeaveCriticalSection(&graph->cs); diff -Nru wine-development-5.8/dlls/quartz/filtermapper.c wine-development-5.9/dlls/quartz/filtermapper.c --- wine-development-5.8/dlls/quartz/filtermapper.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/filtermapper.c 2020-05-22 18:49:34.000000000 +0000 @@ -42,6 +42,298 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); +struct enum_reg_filters +{ + IEnumRegFilters IEnumRegFilters_iface; + LONG refcount; + + unsigned int index, count; + REGFILTER *filters; +}; + +static struct enum_reg_filters *impl_from_IEnumRegFilters(IEnumRegFilters *iface) +{ + return CONTAINING_RECORD(iface, struct enum_reg_filters, IEnumRegFilters_iface); +} + +static HRESULT WINAPI enum_reg_filters_QueryInterface(IEnumRegFilters *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumRegFilters)) + { + IEnumRegFilters_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI enum_reg_filters_AddRef(IEnumRegFilters *iface) +{ + struct enum_reg_filters *enumerator = impl_from_IEnumRegFilters(iface); + ULONG refcount = InterlockedIncrement(&enumerator->refcount); + TRACE("%p increasing refcount to %u.\n", enumerator, refcount); + return refcount; +} + +static ULONG WINAPI enum_reg_filters_Release(IEnumRegFilters *iface) +{ + struct enum_reg_filters *enumerator = impl_from_IEnumRegFilters(iface); + ULONG refcount = InterlockedDecrement(&enumerator->refcount); + unsigned int i; + + TRACE("%p decreasing refcount to %u.\n", enumerator, refcount); + if (!refcount) + { + for (i = 0; i < enumerator->count; ++i) + free(enumerator->filters[i].Name); + free(enumerator->filters); + free(enumerator); + } + return refcount; +} + +static HRESULT WINAPI enum_reg_filters_Next(IEnumRegFilters *iface, ULONG count, + REGFILTER **filters, ULONG *ret_count) +{ + struct enum_reg_filters *enumerator = impl_from_IEnumRegFilters(iface); + unsigned int i; + + TRACE("iface %p, count %u, filters %p, ret_count %p.\n", iface, count, filters, ret_count); + + for (i = 0; i < count && enumerator->index + i < enumerator->count; ++i) + { + REGFILTER *filter = &enumerator->filters[enumerator->index + i]; + + if (!(filters[i] = CoTaskMemAlloc(sizeof(REGFILTER) + (wcslen(filter->Name) + 1) * sizeof(WCHAR)))) + { + while (i--) + CoTaskMemFree(filters[i]); + memset(filters, 0, count * sizeof(*filters)); + *ret_count = 0; + return E_OUTOFMEMORY; + } + + filters[i]->Clsid = filter->Clsid; + filters[i]->Name = (WCHAR *)(filters[i] + 1); + wcscpy(filters[i]->Name, filter->Name); + } + + enumerator->index += i; + if (ret_count) + *ret_count = i; + return i ? S_OK : S_FALSE; +} + +static HRESULT WINAPI enum_reg_filters_Skip(IEnumRegFilters *iface, ULONG count) +{ + TRACE("iface %p, count %u, unimplemented.\n", iface, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI enum_reg_filters_Reset(IEnumRegFilters *iface) +{ + struct enum_reg_filters *enumerator = impl_from_IEnumRegFilters(iface); + + TRACE("iface %p.\n", iface); + + enumerator->index = 0; + return S_OK; +} + +static HRESULT WINAPI enum_reg_filters_Clone(IEnumRegFilters *iface, IEnumRegFilters **out) +{ + TRACE("iface %p, out %p, unimplemented.\n", iface, out); + return E_NOTIMPL; +} + +static const IEnumRegFiltersVtbl enum_reg_filters_vtbl = +{ + enum_reg_filters_QueryInterface, + enum_reg_filters_AddRef, + enum_reg_filters_Release, + enum_reg_filters_Next, + enum_reg_filters_Skip, + enum_reg_filters_Reset, + enum_reg_filters_Clone, +}; + +static HRESULT enum_reg_filters_create(REGFILTER *filters, unsigned int count, IEnumRegFilters **out) +{ + struct enum_reg_filters *object; + unsigned int i; + + *out = NULL; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + if (!(object->filters = malloc(count * sizeof(*object->filters)))) + { + free(object); + return E_OUTOFMEMORY; + } + + for (i = 0; i < count; ++i) + { + object->filters[i].Clsid = filters[i].Clsid; + if (!(object->filters[i].Name = wcsdup(filters[i].Name))) + { + while (i--) + free(object->filters[i].Name); + free(object->filters); + free(object); + return E_OUTOFMEMORY; + } + } + + object->IEnumRegFilters_iface.lpVtbl = &enum_reg_filters_vtbl; + object->refcount = 1; + object->count = count; + + TRACE("Created enumerator %p.\n", object); + *out = &object->IEnumRegFilters_iface; + return S_OK; +} + +struct enum_moniker +{ + IEnumMoniker IEnumMoniker_iface; + LONG refcount; + + unsigned int index, count; + IMoniker **filters; +}; + +static struct enum_moniker *impl_from_IEnumMoniker(IEnumMoniker *iface) +{ + return CONTAINING_RECORD(iface, struct enum_moniker, IEnumMoniker_iface); +} + +static HRESULT WINAPI enum_moniker_QueryInterface(IEnumMoniker *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumMoniker)) + { + IEnumMoniker_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI enum_moniker_AddRef(IEnumMoniker *iface) +{ + struct enum_moniker *enumerator = impl_from_IEnumMoniker(iface); + ULONG refcount = InterlockedIncrement(&enumerator->refcount); + TRACE("%p increasing refcount to %u.\n", enumerator, refcount); + return refcount; +} + +static ULONG WINAPI enum_moniker_Release(IEnumMoniker *iface) +{ + struct enum_moniker *enumerator = impl_from_IEnumMoniker(iface); + ULONG refcount = InterlockedDecrement(&enumerator->refcount); + unsigned int i; + + TRACE("%p decreasing refcount to %u.\n", enumerator, refcount); + if (!refcount) + { + for (i = 0; i < enumerator->count; ++i) + IMoniker_Release(enumerator->filters[i]); + free(enumerator->filters); + free(enumerator); + } + return refcount; +} + +static HRESULT WINAPI enum_moniker_Next(IEnumMoniker *iface, ULONG count, + IMoniker **filters, ULONG *ret_count) +{ + struct enum_moniker *enumerator = impl_from_IEnumMoniker(iface); + unsigned int i; + + TRACE("iface %p, count %u, filters %p, ret_count %p.\n", iface, count, filters, ret_count); + + for (i = 0; i < count && enumerator->index + i < enumerator->count; ++i) + IMoniker_AddRef(filters[i] = enumerator->filters[enumerator->index + i]); + + enumerator->index += i; + if (ret_count) + *ret_count = i; + return i ? S_OK : S_FALSE; +} + +static HRESULT WINAPI enum_moniker_Skip(IEnumMoniker *iface, ULONG count) +{ + struct enum_moniker *enumerator = impl_from_IEnumMoniker(iface); + + TRACE("iface %p, count %u.\n", iface, count); + + enumerator->index += count; + return S_OK; +} + +static HRESULT WINAPI enum_moniker_Reset(IEnumMoniker *iface) +{ + struct enum_moniker *enumerator = impl_from_IEnumMoniker(iface); + + TRACE("iface %p.\n", iface); + + enumerator->index = 0; + return S_OK; +} + +static HRESULT WINAPI enum_moniker_Clone(IEnumMoniker *iface, IEnumMoniker **out) +{ + TRACE("iface %p, out %p, unimplemented.\n", iface, out); + return E_NOTIMPL; +} + +static const IEnumMonikerVtbl enum_moniker_vtbl = +{ + enum_moniker_QueryInterface, + enum_moniker_AddRef, + enum_moniker_Release, + enum_moniker_Next, + enum_moniker_Skip, + enum_moniker_Reset, + enum_moniker_Clone, +}; + +static HRESULT enum_moniker_create(IMoniker **filters, unsigned int count, IEnumMoniker **out) +{ + struct enum_moniker *object; + + *out = NULL; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + if (!(object->filters = malloc(count * sizeof(*object->filters)))) + { + free(object); + return E_OUTOFMEMORY; + } + memcpy(object->filters, filters, count * sizeof(*filters)); + + object->IEnumMoniker_iface.lpVtbl = &enum_moniker_vtbl; + object->refcount = 1; + object->count = count; + + TRACE("Created enumerator %p.\n", object); + *out = &object->IEnumMoniker_iface; + return S_OK; +} + typedef struct FilterMapper3Impl { IUnknown IUnknown_inner; @@ -912,7 +1204,7 @@ /* no need to AddRef here as already AddRef'd above */ ppMoniker[i] = ((struct MONIKER_MERIT *)monikers.pData)[i].pMoniker; } - hr = EnumMonikerImpl_Create(ppMoniker, nMonikerCount, ppEnum); + hr = enum_moniker_create(ppMoniker, nMonikerCount, ppEnum); CoTaskMemFree(ppMoniker); } @@ -1030,7 +1322,7 @@ if (!nb_mon) { IEnumMoniker_Release(ppEnumMoniker); - return IEnumRegFiltersImpl_Construct(NULL, 0, ppEnum); + return enum_reg_filters_create(NULL, 0, ppEnum); } regfilters = CoTaskMemAlloc(nb_mon * sizeof(REGFILTER)); @@ -1087,7 +1379,7 @@ if (SUCCEEDED(hr)) { - hr = IEnumRegFiltersImpl_Construct(regfilters, nb_mon, ppEnum); + hr = enum_reg_filters_create(regfilters, idx, ppEnum); } for (idx = 0; idx < nb_mon; idx++) diff -Nru wine-development-5.8/dlls/quartz/Makefile.in wine-development-5.9/dlls/quartz/Makefile.in --- wine-development-5.8/dlls/quartz/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -8,8 +8,6 @@ acmwrapper.c \ avidec.c \ dsoundrender.c \ - enummoniker.c \ - enumregfilters.c \ filesource.c \ filtergraph.c \ filtermapper.c \ diff -Nru wine-development-5.8/dlls/quartz/quartz_private.h wine-development-5.9/dlls/quartz/quartz_private.h --- wine-development-5.8/dlls/quartz/quartz_private.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/quartz_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -79,10 +79,6 @@ HRESULT vmr7_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; HRESULT vmr9_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; -HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) DECLSPEC_HIDDEN; - -HRESULT IEnumRegFiltersImpl_Construct(REGFILTER * pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum) DECLSPEC_HIDDEN; - extern const char * qzdebugstr_guid(const GUID * id) DECLSPEC_HIDDEN; extern void video_unregister_windowclass(void) DECLSPEC_HIDDEN; diff -Nru wine-development-5.8/dlls/quartz/tests/filtergraph.c wine-development-5.9/dlls/quartz/tests/filtergraph.c --- wine-development-5.8/dlls/quartz/tests/filtergraph.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/tests/filtergraph.c 2020-05-22 18:49:34.000000000 +0000 @@ -2496,6 +2496,7 @@ static void test_aggregation(void) { IFilterGraph2 *graph, *graph2; + IFilterMapper2 *mapper; IUnknown *unk, *unk2; HRESULT hr; ULONG ref; @@ -2550,6 +2551,30 @@ ref = IUnknown_Release(unk); ok(!ref, "Got unexpected refcount %d.\n", ref); ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); + + /* Test the aggregated filter mapper. */ + + graph = create_graph(); + + ref = get_refcount(graph); + ok(ref == 1, "Got unexpected refcount %d.\n", ref); + + hr = IFilterGraph2_QueryInterface(graph, &IID_IFilterMapper2, (void **)&mapper); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ref = get_refcount(graph); + ok(ref == 2, "Got unexpected refcount %d.\n", ref); + ref = get_refcount(mapper); + ok(ref == 2, "Got unexpected refcount %d.\n", ref); + + hr = IFilterMapper2_QueryInterface(mapper, &IID_IFilterGraph2, (void **)&graph2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(graph2 == graph, "Got unexpected IFilterGraph2 %p.\n", graph2); + IFilterGraph2_Release(graph2); + + IFilterMapper2_Release(mapper); + ref = IFilterGraph2_Release(graph); + ok(!ref, "Got unexpected refcount %d.\n", ref); } /* Test how methods from "control" interfaces (IBasicAudio, IBasicVideo, @@ -3178,6 +3203,26 @@ ok(hr == S_OK, "Got hr %#x.\n", hr); check_filter_state(graph, State_Stopped); + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_filter_state(graph, State_Paused); + + hr = IMediaControl_StopWhenReady(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_filter_state(graph, State_Stopped); + + hr = IMediaControl_Run(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_filter_state(graph, State_Running); + + hr = IMediaControl_StopWhenReady(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_filter_state(graph, State_Stopped); + + hr = IMediaControl_StopWhenReady(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_filter_state(graph, State_Stopped); + IReferenceClock_Release(clock); IMediaFilter_Release(filter); IMediaControl_Release(control); diff -Nru wine-development-5.8/dlls/quartz/tests/filtermapper.c wine-development-5.9/dlls/quartz/tests/filtermapper.c --- wine-development-5.8/dlls/quartz/tests/filtermapper.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/tests/filtermapper.c 2020-05-22 18:49:34.000000000 +0000 @@ -23,10 +23,22 @@ #include "wine/test.h" #include "winbase.h" #include "dshow.h" -#include "winternl.h" +#include "mediaobj.h" #include "initguid.h" +#include "dmo.h" #include "wine/fil_data.h" +static const GUID testclsid = {0x77777777}; + +static IFilterMapper3 *create_mapper(void) +{ + IFilterMapper3 *ret; + HRESULT hr; + hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper3, (void **)&ret); + ok(hr == S_OK, "Failed to create filter mapper, hr %#x.\n", hr); + return ret; +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -34,6 +46,36 @@ return IUnknown_Release(unknown); } +#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) +static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) +{ + IUnknown *iface = iface_ptr; + HRESULT hr, expected_hr; + IUnknown *unk; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&unk); + ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unk); +} + +static void test_interfaces(void) +{ + IFilterMapper3 *mapper = create_mapper(); + + check_interface(mapper, &IID_IAMFilterData, TRUE); + check_interface(mapper, &IID_IFilterMapper, TRUE); + check_interface(mapper, &IID_IFilterMapper2, TRUE); + check_interface(mapper, &IID_IFilterMapper3, TRUE); + check_interface(mapper, &IID_IUnknown, TRUE); + + check_interface(mapper, &IID_IFilterGraph, FALSE); + + IFilterMapper3_Release(mapper); +} + /* Helper function, checks if filter with given name was enumerated. */ static BOOL enum_find_filter(const WCHAR *wszFilterName, IEnumMoniker *pEnum) { @@ -80,7 +122,7 @@ IEnumMoniker *pEnum = NULL; BOOL found, registered = TRUE; REGFILTER *regfilter; - ULONG count; + ULONG count, ref; ZeroMemory(&rgf2, sizeof(rgf2)); @@ -188,6 +230,8 @@ } IEnumRegFilters_Release(enum_reg); ok(found, "IFilterMapper didn't find filter\n"); + + IFilterMapper_Release(mapper); } if (pEnum) IEnumMoniker_Release(pEnum); @@ -217,7 +261,8 @@ out: if (pEnum) IEnumMoniker_Release(pEnum); - if (pMapper) IFilterMapper2_Release(pMapper); + ref = IFilterMapper2_Release(pMapper); + ok(!ref, "Got outstanding refcount %d.\n", ref); } static void test_legacy_filter_registration(void) @@ -323,63 +368,6 @@ IFilterMapper2_Release(mapper2); } -static ULONG getRefcount(IUnknown *iface) -{ - IUnknown_AddRef(iface); - return IUnknown_Release(iface); -} - -static void test_ifiltermapper_from_filtergraph(void) -{ - IFilterGraph2* pgraph2 = NULL; - IFilterMapper2 *pMapper2 = NULL; - IFilterGraph *filtergraph = NULL; - HRESULT hr; - ULONG refcount; - - hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (LPVOID*)&pgraph2); - ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr); - if (!pgraph2) goto out; - - hr = IFilterGraph2_QueryInterface(pgraph2, &IID_IFilterMapper2, (LPVOID*)&pMapper2); - ok(hr == S_OK, "IFilterGraph2_QueryInterface failed with %08x\n", hr); - if (!pMapper2) goto out; - - refcount = getRefcount((IUnknown*)pgraph2); - ok(refcount == 2, "unexpected reference count: %u\n", refcount); - refcount = getRefcount((IUnknown*)pMapper2); - ok(refcount == 2, "unexpected reference count: %u\n", refcount); - - IFilterMapper2_AddRef(pMapper2); - refcount = getRefcount((IUnknown*)pgraph2); - ok(refcount == 3, "unexpected reference count: %u\n", refcount); - refcount = getRefcount((IUnknown*)pMapper2); - ok(refcount == 3, "unexpected reference count: %u\n", refcount); - IFilterMapper2_Release(pMapper2); - - hr = IFilterMapper2_QueryInterface(pMapper2, &IID_IFilterGraph, (LPVOID*)&filtergraph); - ok(hr == S_OK, "IFilterMapper2_QueryInterface failed with %08x\n", hr); - if (!filtergraph) goto out; - - IFilterMapper2_Release(pMapper2); - pMapper2 = NULL; - IFilterGraph_Release(filtergraph); - filtergraph = NULL; - - hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pMapper2); - ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr); - if (!pMapper2) goto out; - - hr = IFilterMapper2_QueryInterface(pMapper2, &IID_IFilterGraph, (LPVOID*)&filtergraph); - ok(hr == E_NOINTERFACE, "IFilterMapper2_QueryInterface unexpected result: %08x\n", hr); - - out: - - if (pMapper2) IFilterMapper2_Release(pMapper2); - if (filtergraph) IFilterGraph_Release(filtergraph); - if (pgraph2) IFilterGraph2_Release(pgraph2); -} - static void test_register_filter_with_null_clsMinorType(void) { static WCHAR wszPinName[] = L"Pin"; @@ -620,16 +608,66 @@ ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); } +static void test_dmo(void) +{ + DMO_PARTIAL_MEDIATYPE mt = {MEDIATYPE_Audio, MEDIASUBTYPE_PCM}; + IEnumMoniker *enumerator; + IFilterMapper3 *mapper; + IMoniker *moniker; + WCHAR *name; + HRESULT hr; + BOOL found; + ULONG ref; + + hr = DMORegister(L"dmo test", &testclsid, &DMOCATEGORY_AUDIO_DECODER, 0, 1, &mt, 1, &mt); + if (hr == E_FAIL) + { + skip("Not enough permissions to register DMOs.\n"); + return; + } + ok(hr == S_OK, "Got hr %#x.\n", hr); + + mapper = create_mapper(); + + hr = IFilterMapper3_EnumMatchingFilters(mapper, &enumerator, 0, FALSE, 0, + FALSE, 0, NULL, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + found = FALSE; + while (IEnumMoniker_Next(enumerator, 1, &moniker, NULL) == S_OK) + { + hr = IMoniker_GetDisplayName(moniker, NULL, NULL, &name); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + if (!wcscmp(name, L"@device:dmo:{77777777-0000-0000-0000-000000000000}{57F2DB8B-E6BB-4513-9D43-DCD2A6593125}")) + found = TRUE; + + CoTaskMemFree(name); + IMoniker_Release(moniker); + } + IEnumMoniker_Release(enumerator); + ok(found, "DMO should be enumerated.\n"); + + /* DMOs are enumerated by IFilterMapper in Windows 7 and higher. */ + + ref = IFilterMapper3_Release(mapper); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + hr = DMOUnregister(&testclsid, &DMOCATEGORY_AUDIO_DECODER); + ok(hr == S_OK, "Got hr %#x.\n", hr); +} + START_TEST(filtermapper) { CoInitialize(NULL); + test_interfaces(); test_fm2_enummatchingfilters(); test_legacy_filter_registration(); - test_ifiltermapper_from_filtergraph(); test_register_filter_with_null_clsMinorType(); test_parse_filter_data(); test_aggregation(); + test_dmo(); CoUninitialize(); } diff -Nru wine-development-5.8/dlls/quartz/tests/Makefile.in wine-development-5.9/dlls/quartz/tests/Makefile.in --- wine-development-5.8/dlls/quartz/tests/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/tests/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -1,5 +1,5 @@ TESTDLL = quartz.dll -IMPORTS = strmbase advapi32 d3d9 msvfw32 ole32 oleaut32 user32 uuid +IMPORTS = strmbase advapi32 d3d9 msdmo msvfw32 ole32 oleaut32 user32 uuid C_SRCS = \ acmwrapper.c \ diff -Nru wine-development-5.8/dlls/quartz/tests/systemclock.c wine-development-5.9/dlls/quartz/tests/systemclock.c --- wine-development-5.8/dlls/quartz/tests/systemclock.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/tests/systemclock.c 2020-05-22 18:49:34.000000000 +0000 @@ -259,18 +259,15 @@ hr = IReferenceClock_AdvisePeriodic(clock, -500 * 10000, 1000 * 10000, (HSEMAPHORE)semaphore, &cookie); ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); - hr = IReferenceClock_AdvisePeriodic(clock, current, 500 * 10000, (HSEMAPHORE)semaphore, &cookie); + hr = IReferenceClock_AdvisePeriodic(clock, current, 100 * 10000, (HSEMAPHORE)semaphore, &cookie); ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(!WaitForSingleObject(semaphore, 20), "Semaphore should be signaled.\n"); + ok(!WaitForSingleObject(semaphore, 50), "Semaphore should be signaled.\n"); for (i = 0; i < 5; ++i) - { - ok(WaitForSingleObject(semaphore, 460) == WAIT_TIMEOUT, "Semaphore should not be signaled.\n"); - ok(!WaitForSingleObject(semaphore, 60), "Semaphore should be signaled.\n"); - } + ok(!WaitForSingleObject(semaphore, 500), "Semaphore should be signaled.\n"); hr = IReferenceClock_Unadvise(clock, cookie); ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(WaitForSingleObject(semaphore, 520) == WAIT_TIMEOUT, "Semaphore should not be signaled.\n"); + ok(WaitForSingleObject(semaphore, 200) == WAIT_TIMEOUT, "Semaphore should not be signaled.\n"); CloseHandle(event); CloseHandle(semaphore); diff -Nru wine-development-5.8/dlls/quartz/tests/vmr9.c wine-development-5.9/dlls/quartz/tests/vmr9.c --- wine-development-5.8/dlls/quartz/tests/vmr9.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/tests/vmr9.c 2020-05-22 18:49:34.000000000 +0000 @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include #define COBJMACROS #include "ocidl.h" #include "olectl.h" @@ -58,7 +59,7 @@ ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_SetNumberOfStreams(config, count); - todo_wine_if (count != 1) ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); IVMRFilterConfig9_Release(config); return hr; @@ -70,6 +71,22 @@ && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat); } +static BOOL compare_double(double f, double g, unsigned int ulps) +{ + int64_t x = *(int64_t *)&f; + int64_t y = *(int64_t *)&g; + + if (x < 0) + x = INT64_MIN - x; + if (y < 0) + y = INT64_MIN - y; + + if (abs(x - y) > ulps) + return FALSE; + + return TRUE; +} + static IFilterGraph2 *create_graph(void) { IFilterGraph2 *ret; @@ -153,16 +170,14 @@ ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_GetNumberOfStreams(config, &count); - todo_wine ok(hr == VFW_E_VMR_NOT_IN_MIXER_MODE, "Got hr %#x.\n", hr); + ok(hr == VFW_E_VMR_NOT_IN_MIXER_MODE, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_SetNumberOfStreams(config, 3); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_GetNumberOfStreams(config, &count); - todo_wine { - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(count == 3, "Got count %u.\n", count); - } + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(count == 3, "Got count %u.\n", count); hr = IVMRFilterConfig9_GetRenderingMode(config, &mode); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -178,10 +193,8 @@ ok(mode == VMR9Mode_Windowless, "Got mode %#x.\n", mode); hr = IVMRFilterConfig9_GetNumberOfStreams(config, &count); - todo_wine { - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(count == 3, "Got count %u.\n", count); - } + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(count == 3, "Got count %u.\n", count); ref = IVMRFilterConfig9_Release(config); ok(!ref, "Got outstanding refcount %d.\n", ref); @@ -315,24 +328,22 @@ ok(!ref, "Got outstanding refcount %d.\n", ref); filter = create_vmr9(VMR9Mode_Windowed); - if (SUCCEEDED(set_mixing_mode(filter, 1))) - { - test_common_interfaces(filter); + set_mixing_mode(filter, 1); + test_common_interfaces(filter); - check_interface(filter, &IID_IBasicVideo, TRUE); - todo_wine check_interface(filter, &IID_IBasicVideo2, TRUE); - check_interface(filter, &IID_IVideoWindow, TRUE); - todo_wine check_interface(filter, &IID_IVMRMixerControl9, TRUE); - /* IVMRMonitorConfig9 may not be available if the d3d9 device has - * insufficient support. */ - check_interface_broken(filter, &IID_IVMRMonitorConfig9, TRUE); + check_interface(filter, &IID_IBasicVideo, TRUE); + todo_wine check_interface(filter, &IID_IBasicVideo2, TRUE); + check_interface(filter, &IID_IVideoWindow, TRUE); + check_interface(filter, &IID_IVMRMixerControl9, TRUE); + /* IVMRMonitorConfig9 may not be available if the d3d9 device has + * insufficient support. */ + check_interface_broken(filter, &IID_IVMRMonitorConfig9, TRUE); - check_interface(filter, &IID_IVMRSurfaceAllocatorNotify9, FALSE); - check_interface(filter, &IID_IVMRWindowlessControl9, FALSE); + check_interface(filter, &IID_IVMRSurfaceAllocatorNotify9, FALSE); + check_interface(filter, &IID_IVMRWindowlessControl9, FALSE); - ref = IBaseFilter_Release(filter); - ok(!ref, "Got outstanding refcount %d.\n", ref); - } + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); } static const GUID test_iid = {0x33333333}; @@ -515,43 +526,42 @@ IEnumPins_Release(enum2); - if (SUCCEEDED(set_mixing_mode(filter, 2))) - { - hr = IEnumPins_Next(enum1, 1, pins, NULL); - ok(hr == S_FALSE, "Got hr %#x.\n", hr); + set_mixing_mode(filter, 2); - hr = IEnumPins_Reset(enum1); - ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumPins_Next(enum1, 1, pins, NULL); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); - hr = IEnumPins_Next(enum1, 1, pins, NULL); - ok(hr == S_OK, "Got hr %#x.\n", hr); - IPin_Release(pins[0]); + hr = IEnumPins_Reset(enum1); + ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IEnumPins_Next(enum1, 1, pins, NULL); - ok(hr == S_OK, "Got hr %#x.\n", hr); - IPin_Release(pins[0]); + hr = IEnumPins_Next(enum1, 1, pins, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IPin_Release(pins[0]); - hr = IEnumPins_Next(enum1, 1, pins, NULL); - ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = IEnumPins_Next(enum1, 1, pins, NULL); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + if (hr == S_OK) IPin_Release(pins[0]); - hr = IEnumPins_Reset(enum1); - ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumPins_Next(enum1, 1, pins, NULL); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); - hr = IEnumPins_Next(enum1, 2, pins, &count); - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(count == 2, "Got count %u.\n", count); - IPin_Release(pins[0]); - IPin_Release(pins[1]); + hr = IEnumPins_Reset(enum1); + ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IEnumPins_Reset(enum1); - ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumPins_Next(enum1, 2, pins, &count); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(count == 2, "Got count %u.\n", count); + IPin_Release(pins[0]); + if (count > 1) IPin_Release(pins[1]); - hr = IEnumPins_Next(enum1, 3, pins, &count); - ok(hr == S_FALSE, "Got hr %#x.\n", hr); - ok(count == 2, "Got count %u.\n", count); - IPin_Release(pins[0]); - IPin_Release(pins[1]); - } + hr = IEnumPins_Reset(enum1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IEnumPins_Next(enum1, 3, pins, &count); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + todo_wine ok(count == 2, "Got count %u.\n", count); + IPin_Release(pins[0]); + if (count > 1) IPin_Release(pins[1]); IEnumPins_Release(enum1); ref = IBaseFilter_Release(filter); @@ -585,30 +595,32 @@ hr = IBaseFilter_FindPin(filter, L"VMR Input1", &pin); ok(hr == VFW_E_NOT_FOUND, "Got hr %#x.\n", hr); - if (SUCCEEDED(set_mixing_mode(filter, 2))) - { - IEnumPins_Reset(enum_pins); + set_mixing_mode(filter, 2); - hr = IBaseFilter_FindPin(filter, L"VMR Input0", &pin); - ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IEnumPins_Next(enum_pins, 1, &pin2, NULL); - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(pin == pin2, "Pins did not match.\n"); - IPin_Release(pin); - IPin_Release(pin2); + IEnumPins_Reset(enum_pins); - hr = IBaseFilter_FindPin(filter, L"VMR Input1", &pin); - ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IBaseFilter_FindPin(filter, L"VMR Input0", &pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumPins_Next(enum_pins, 1, &pin2, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(pin == pin2, "Pins did not match.\n"); + IPin_Release(pin); + IPin_Release(pin2); + + hr = IBaseFilter_FindPin(filter, L"VMR Input1", &pin); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + if (hr == S_OK) + { hr = IEnumPins_Next(enum_pins, 1, &pin2, NULL); ok(hr == S_OK, "Got hr %#x.\n", hr); ok(pin == pin2, "Pins did not match.\n"); IPin_Release(pin); IPin_Release(pin2); - - hr = IBaseFilter_FindPin(filter, L"VMR Input2", &pin); - ok(hr == VFW_E_NOT_FOUND, "Got hr %#x.\n", hr); } + hr = IBaseFilter_FindPin(filter, L"VMR Input2", &pin); + ok(hr == VFW_E_NOT_FOUND, "Got hr %#x.\n", hr); + IEnumPins_Release(enum_pins); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); @@ -645,9 +657,12 @@ IPin_Release(pin); - if (SUCCEEDED(set_mixing_mode(filter, 2))) + set_mixing_mode(filter, 2); + + hr = IBaseFilter_FindPin(filter, L"VMR Input1", &pin); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + if (hr == S_OK) { - IBaseFilter_FindPin(filter, L"VMR Input1", &pin); hr = IPin_QueryPinInfo(pin, &info); ok(info.pFilter == filter, "Expected filter %p, got %p.\n", filter, info.pFilter); ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir); @@ -1500,11 +1515,8 @@ ok(hr == S_OK, "Got hr %#x.\n", hr); ok(size == sizeof(buffer), "Got size %d.\n", size); ok(!memcmp(bih, &expect_bih, sizeof(BITMAPINFOHEADER)), "Bitmap headers didn't match.\n"); - if (0) /* FIXME: Rendering is currently broken on Wine. */ - { - for (i = 0; i < 32 * 16; ++i) - ok((data[i] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data[i], i); - } + for (i = 0; i < 32 * 16; ++i) + ok((data[i] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data[i], i); hr = IMediaControl_Run(control); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -1516,11 +1528,8 @@ ok(hr == S_OK, "Got hr %#x.\n", hr); ok(size == sizeof(buffer), "Got size %d.\n", size); ok(!memcmp(bih, &expect_bih, sizeof(BITMAPINFOHEADER)), "Bitmap headers didn't match.\n"); - if (0) /* FIXME: Rendering is currently broken on Wine. */ - { - for (i = 0; i < 32 * 16; ++i) - ok((data[i] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data[i], i); - } + for (i = 0; i < 32 * 16; ++i) + ok((data[i] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data[i], i); hr = IMediaControl_Stop(control); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -1723,8 +1732,8 @@ hwnd = (HWND)0xdeadbeef; hr = IOverlay_GetWindowHandle(overlay, &hwnd); - todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); - todo_wine ok(hwnd == (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd); + ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); + ok(hwnd == (HWND)0xdeadbeef, "Got window %p.\n", hwnd); IOverlay_Release(overlay); IPin_Release(pin); @@ -1739,8 +1748,8 @@ hwnd = (HWND)0xdeadbeef; hr = IOverlay_GetWindowHandle(overlay, &hwnd); - todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); - todo_wine ok(hwnd == (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd); + ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); + ok(hwnd == (HWND)0xdeadbeef, "Got window %p.\n", hwnd); IOverlay_Release(overlay); IPin_Release(pin); @@ -2613,18 +2622,22 @@ HRESULT hr; ULONG ref; + AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); + window = CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW, 0, 0, + rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); + if (!(device = create_device(window))) + { + IBaseFilter_Release(filter); + DestroyWindow(window); + return; + } + IBaseFilter_QueryInterface(filter, &IID_IVMRSurfaceAllocatorNotify9, (void **)¬ify); count = 2; hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify, &info, &count, surfaces); todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); - AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); - window = CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW, 0, 0, - rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); - if (!(device = create_device(window))) - goto out; - hr = IVMRSurfaceAllocatorNotify9_SetD3DDevice(notify, device, MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY)); if (hr == E_NOINTERFACE) { @@ -2966,14 +2979,14 @@ .pbFormat = (BYTE *)&vih, }; ALLOCATOR_PROPERTIES req_props = {5, 32 * 16 * 4, 1, 0}, ret_props; - IBaseFilter *filter = create_vmr9(VMR9Mode_Renderless); - IFilterGraph2 *graph = create_graph(); IVMRSurfaceAllocatorNotify9 *notify; RECT rect = {0, 0, 640, 480}; struct testfilter source; IDirect3DDevice9 *device; IMemAllocator *allocator; + IFilterGraph2 *graph; IMemInputPin *input; + IBaseFilter *filter; unsigned int i; HWND window; HRESULT hr; @@ -3007,13 +3020,17 @@ {&MEDIASUBTYPE_YV12, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface}, }; - IBaseFilter_QueryInterface(filter, &IID_IVMRSurfaceAllocatorNotify9, (void **)¬ify); - AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); window = CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW, 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); if (!(device = create_device(window))) - goto out; + { + DestroyWindow(window); + return; + } + + filter = create_vmr9(VMR9Mode_Renderless); + IBaseFilter_QueryInterface(filter, &IID_IVMRSurfaceAllocatorNotify9, (void **)¬ify); hr = IVMRSurfaceAllocatorNotify9_SetD3DDevice(notify, device, MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY)); if (hr == E_NOINTERFACE) @@ -3029,6 +3046,7 @@ allocator_notify = notify; testfilter_init(&source); + graph = create_graph(); IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL); IFilterGraph2_AddFilter(graph, filter, NULL); IBaseFilter_FindPin(filter, L"VMR Input0", &pin); @@ -3134,26 +3152,25 @@ ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); - todo_wine ok(hr == VFW_E_VMR_NOT_IN_MIXER_MODE, "Got hr %#x.\n", hr); + ok(hr == VFW_E_VMR_NOT_IN_MIXER_MODE, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_SetNumberOfStreams(config, 1); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(stream_count == 1, "Got %u streams.\n", stream_count); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(stream_count == 1, "Got %u streams.\n", stream_count); hr = IBaseFilter_QueryInterface(filter, &IID_IVMRMixerControl9, (void **)&mixer_control); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); - if (hr == S_OK) - IVMRMixerControl9_Release(mixer_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IVMRMixerControl9_Release(mixer_control); hr = IVMRFilterConfig9_SetNumberOfStreams(config, 2); - todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); + ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(stream_count == 1, "Got %u streams.\n", stream_count); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(stream_count == 1, "Got %u streams.\n", stream_count); IVMRFilterConfig9_Release(config); ref = IBaseFilter_Release(filter); @@ -3170,20 +3187,19 @@ ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(stream_count == 4, "Got %u streams.\n", stream_count); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(stream_count == 4, "Got %u streams.\n", stream_count); hr = IBaseFilter_QueryInterface(filter, &IID_IVMRMixerControl9, (void **)&mixer_control); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); - if (hr == S_OK) - IVMRMixerControl9_Release(mixer_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IVMRMixerControl9_Release(mixer_control); hr = IVMRFilterConfig9_SetNumberOfStreams(config, 2); - todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); + ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(stream_count == 4, "Got %u streams.\n", stream_count); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(stream_count == 4, "Got %u streams.\n", stream_count); IVMRWindowlessControl9_Release(windowless_control); IVMRFilterConfig9_Release(config); @@ -3693,7 +3709,7 @@ reftime = 0.0; hr = IBasicVideo_get_AvgTimePerFrame(video, &reftime); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(reftime == 0.02, "Got frame rate %.16e.\n", reftime); + todo_wine ok(compare_double(reftime, 0.02, 1 << 28), "Got frame rate %.16e.\n", reftime); l = 0xdeadbeef; hr = IBasicVideo_get_BitRate(video, &l); @@ -3729,6 +3745,137 @@ ok(!ref, "Got outstanding refcount %d.\n", ref); } +static void test_windowless_size(void) +{ + ALLOCATOR_PROPERTIES req_props = {1, 32 * 16 * 4, 1, 0}, ret_props; + VIDEOINFOHEADER vih = + { + .bmiHeader.biSize = sizeof(BITMAPINFOHEADER), + .bmiHeader.biWidth = 32, + .bmiHeader.biHeight = 16, + .bmiHeader.biBitCount = 32, + .bmiHeader.biPlanes = 1, + }; + AM_MEDIA_TYPE mt = + { + .majortype = MEDIATYPE_Video, + .subtype = MEDIASUBTYPE_RGB32, + .formattype = FORMAT_VideoInfo, + .cbFormat = sizeof(vih), + .pbFormat = (BYTE *)&vih, + }; + IBaseFilter *filter = create_vmr9(VMR9Mode_Windowless); + LONG width, height, aspect_width, aspect_height; + IVMRWindowlessControl9 *windowless_control; + IFilterGraph2 *graph = create_graph(); + struct testfilter source; + IMemAllocator *allocator; + RECT src, dst, expect; + IMemInputPin *input; + HWND window; + HRESULT hr; + ULONG ref; + IPin *pin; + + IBaseFilter_QueryInterface(filter, &IID_IVMRWindowlessControl9, (void **)&windowless_control); + IBaseFilter_FindPin(filter, L"VMR Input0", &pin); + IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input); + testfilter_init(&source); + IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source"); + IFilterGraph2_AddFilter(graph, filter, L"vmr9"); + window = CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0); + ok(!!window, "Failed to create a window.\n"); + + hr = IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control, window); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemInputPin_GetAllocator(input, &allocator); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + if (hr == S_OK) + { + hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props); + IMemAllocator_Release(allocator); + if (hr == E_FAIL) + { + skip("Got E_FAIL when setting allocator properties.\n"); + goto out; + } + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n"); + } + + hr = IVMRWindowlessControl9_GetNativeVideoSize(windowless_control, NULL, &height, &aspect_width, &aspect_height); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); + hr = IVMRWindowlessControl9_GetNativeVideoSize(windowless_control, &width, NULL, &aspect_width, &aspect_height); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); + + width = height = 0xdeadbeef; + hr = IVMRWindowlessControl9_GetNativeVideoSize(windowless_control, &width, &height, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(width == 32, "Got width %d.\n", width); + ok(height == 16, "Got height %d.\n", height); + + aspect_width = aspect_height = 0xdeadbeef; + hr = IVMRWindowlessControl9_GetNativeVideoSize(windowless_control, &width, &height, &aspect_width, &aspect_height); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(aspect_width == 32, "Got width %d.\n", aspect_width); + ok(aspect_height == 16, "Got height %d.\n", aspect_height); + + memset(&src, 0xcc, sizeof(src)); + hr = IVMRWindowlessControl9_GetVideoPosition(windowless_control, &src, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + SetRect(&expect, 0, 0, 32, 16); + ok(EqualRect(&src, &expect), "Got source rect %s.\n", wine_dbgstr_rect(&src)); + + memset(&dst, 0xcc, sizeof(dst)); + hr = IVMRWindowlessControl9_GetVideoPosition(windowless_control, NULL, &dst); + ok(hr == S_OK, "Got hr %#x.\n", hr); + SetRect(&expect, 0, 0, 0, 0); + todo_wine ok(EqualRect(&dst, &expect), "Got dest rect %s.\n", wine_dbgstr_rect(&dst)); + + SetRect(&src, 4, 6, 16, 12); + hr = IVMRWindowlessControl9_SetVideoPosition(windowless_control, &src, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + memset(&src, 0xcc, sizeof(src)); + memset(&dst, 0xcc, sizeof(dst)); + hr = IVMRWindowlessControl9_GetVideoPosition(windowless_control, &src, &dst); + ok(hr == S_OK, "Got hr %#x.\n", hr); + SetRect(&expect, 4, 6, 16, 12); + ok(EqualRect(&src, &expect), "Got source rect %s.\n", wine_dbgstr_rect(&src)); + SetRect(&expect, 0, 0, 0, 0); + todo_wine ok(EqualRect(&dst, &expect), "Got dest rect %s.\n", wine_dbgstr_rect(&dst)); + + SetRect(&dst, 40, 60, 120, 160); + hr = IVMRWindowlessControl9_SetVideoPosition(windowless_control, NULL, &dst); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + memset(&src, 0xcc, sizeof(src)); + memset(&dst, 0xcc, sizeof(dst)); + hr = IVMRWindowlessControl9_GetVideoPosition(windowless_control, &src, &dst); + ok(hr == S_OK, "Got hr %#x.\n", hr); + SetRect(&expect, 4, 6, 16, 12); + ok(EqualRect(&src, &expect), "Got source rect %s.\n", wine_dbgstr_rect(&src)); + SetRect(&expect, 40, 60, 120, 160); + ok(EqualRect(&dst, &expect), "Got dest rect %s.\n", wine_dbgstr_rect(&dst)); + + GetWindowRect(window, &src); + SetRect(&expect, 0, 0, 640, 480); + ok(EqualRect(&src, &expect), "Got window rect %s.\n", wine_dbgstr_rect(&src)); + +out: + ref = IFilterGraph2_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + IMemInputPin_Release(input); + IPin_Release(pin); + IVMRWindowlessControl9_Release(windowless_control); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + DestroyWindow(window); +} + START_TEST(vmr9) { IBaseFilter *filter; @@ -3762,6 +3909,7 @@ test_clipping_window(); test_surface_allocator_notify_refcount(); test_basic_video(); + test_windowless_size(); CoUninitialize(); } diff -Nru wine-development-5.8/dlls/quartz/vmr9.c wine-development-5.9/dlls/quartz/vmr9.c --- wine-development-5.8/dlls/quartz/vmr9.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/quartz/vmr9.c 2020-05-22 18:49:34.000000000 +0000 @@ -63,6 +63,7 @@ IVMRFilterConfig IVMRFilterConfig_iface; IVMRFilterConfig9 IVMRFilterConfig9_iface; IVMRMixerBitmap9 IVMRMixerBitmap9_iface; + IVMRMixerControl9 IVMRMixerControl9_iface; IVMRMonitorConfig IVMRMonitorConfig_iface; IVMRMonitorConfig9 IVMRMonitorConfig9_iface; IVMRSurfaceAllocatorNotify IVMRSurfaceAllocatorNotify_iface; @@ -82,6 +83,8 @@ IVMRImagePresenter9 *presenter; BOOL allocator_is_ex; + DWORD stream_count; + /* * The Video Mixing Renderer supports 3 modes, renderless, windowless and windowed * What I do is implement windowless as a special case of renderless, and then @@ -100,8 +103,7 @@ DWORD cur_surface; DWORD_PTR cookie; - /* for Windowless Mode */ - HWND hWndClippingWindow; + HWND clipping_window; LONG VideoWidth; LONG VideoHeight; @@ -179,11 +181,9 @@ IDirect3DDevice9 *d3d9_dev; IDirect3D9 *d3d9_ptr; IDirect3DSurface9 **d3d9_surfaces; - IDirect3DVertexBuffer9 *d3d9_vertex; HMONITOR hMon; DWORD num_surfaces; - BOOL reset; VMR9AllocationInfo info; struct quartz_vmr* pVMR9; @@ -339,25 +339,19 @@ return S_OK; } -static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info) +static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info, DWORD count) { - DWORD buffer_count = 1, i; HRESULT hr; + DWORD i; if (FAILED(hr = IVMRSurfaceAllocatorEx9_InitializeDevice(filter->allocator, - filter->cookie, info, &buffer_count))) + filter->cookie, info, &count))) { WARN("Failed to initialize device (flags %#x), hr %#x.\n", info->dwFlags, hr); return hr; } - if (!(filter->surfaces = calloc(buffer_count, sizeof(IDirect3DSurface9 *)))) - { - IVMRSurfaceAllocatorEx9_TerminateDevice(filter->allocator, filter->cookie); - return E_OUTOFMEMORY; - } - - for (i = 0; i < buffer_count; ++i) + for (i = 0; i < count; ++i) { if (FAILED(hr = IVMRSurfaceAllocatorEx9_GetSurface(filter->allocator, filter->cookie, i, 0, &filter->surfaces[i]))) @@ -370,7 +364,6 @@ } } - filter->num_surfaces = buffer_count; return hr; } @@ -378,6 +371,7 @@ { VMR9AllocationInfo info = {}; HRESULT hr = E_FAIL; + DWORD count = 1; unsigned int i; static const struct @@ -404,20 +398,19 @@ }; TRACE("Initializing in mode %u, our window %p, clipping window %p.\n", - filter->mode, filter->window.hwnd, filter->hWndClippingWindow); + filter->mode, filter->window.hwnd, filter->clipping_window); - if (filter->mode == VMR9Mode_Windowless && !filter->hWndClippingWindow) + if (filter->mode == VMR9Mode_Windowless && !filter->clipping_window) return S_OK; - info.dwWidth = filter->window.src.right; - info.dwHeight = filter->window.src.bottom; info.Pool = D3DPOOL_DEFAULT; - info.MinBuffers = 1; - info.szAspectRatio.cx = info.dwWidth; - info.szAspectRatio.cy = info.dwHeight; - info.szNativeSize.cx = filter->bmiheader.biWidth; - info.szNativeSize.cy = filter->bmiheader.biHeight; + info.MinBuffers = count; + info.dwWidth = info.szAspectRatio.cx = info.szNativeSize.cx = filter->bmiheader.biWidth; + info.dwHeight = info.szAspectRatio.cy = info.szNativeSize.cy = filter->bmiheader.biHeight; + if (!(filter->surfaces = calloc(count, sizeof(IDirect3DSurface9 *)))) + return E_OUTOFMEMORY; + filter->num_surfaces = count; filter->cur_surface = 0; if (!is_vmr9(filter)) @@ -435,7 +428,7 @@ } info.dwFlags = VMR9AllocFlag_TextureSurface; - return initialize_device(filter, &info); + return initialize_device(filter, &info, count); } for (i = 0; i < ARRAY_SIZE(formats); ++i) @@ -447,14 +440,14 @@ if (formats[i].flags & VMR9AllocFlag_TextureSurface) { info.dwFlags = VMR9AllocFlag_TextureSurface; - if (SUCCEEDED(hr = initialize_device(filter, &info))) + if (SUCCEEDED(hr = initialize_device(filter, &info, count))) return hr; } if (formats[i].flags & VMR9AllocFlag_OffscreenSurface) { info.dwFlags = VMR9AllocFlag_OffscreenSurface; - if (SUCCEEDED(hr = initialize_device(filter, &info))) + if (SUCCEEDED(hr = initialize_device(filter, &info, count))) return hr; } } @@ -465,13 +458,12 @@ static void vmr_start_stream(struct strmbase_renderer *iface) { - struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface); - - TRACE("(%p)\n", This); + struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface); - IVMRImagePresenter9_StartPresenting(This->presenter, This->cookie); - ShowWindow(This->window.hwnd, SW_SHOW); - SetEvent(This->run_event); + IVMRImagePresenter9_StartPresenting(filter->presenter, filter->cookie); + if (filter->window.hwnd) + ShowWindow(filter->window.hwnd, SW_SHOW); + SetEvent(filter->run_event); } static void vmr_stop_stream(struct strmbase_renderer *iface) @@ -603,6 +595,8 @@ *out = &filter->IVMRFilterConfig9_iface; else if (IsEqualGUID(iid, &IID_IVMRMixerBitmap9) && is_vmr9(filter)) *out = &filter->IVMRMixerBitmap9_iface; + else if (IsEqualGUID(iid, &IID_IVMRMixerControl9) && is_vmr9(filter) && filter->stream_count) + *out = &filter->IVMRMixerControl9_iface; else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig)) *out = &filter->IVMRMonitorConfig_iface; else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig9)) @@ -1282,18 +1276,49 @@ static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD count) { + struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface); + FIXME("iface %p, count %u, stub!\n", iface, count); - if (count == 1) - return S_OK; - return E_NOTIMPL; + + if (!count) + { + WARN("Application requested zero streams; returning E_INVALIDARG.\n"); + return E_INVALIDARG; + } + + EnterCriticalSection(&filter->renderer.filter.csFilter); + + if (filter->stream_count) + { + LeaveCriticalSection(&filter->renderer.filter.csFilter); + WARN("Stream count is already set; returning VFW_E_WRONG_STATE.\n"); + return VFW_E_WRONG_STATE; + } + + filter->stream_count = count; + + LeaveCriticalSection(&filter->renderer.filter.csFilter); + return S_OK; } -static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max) +static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *count) { - struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface); + struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface); - FIXME("(%p/%p)->(%p) stub\n", iface, This, max); - return E_NOTIMPL; + TRACE("filter %p, count %p.\n", filter, count); + + EnterCriticalSection(&filter->renderer.filter.csFilter); + + if (!filter->stream_count) + { + LeaveCriticalSection(&filter->renderer.filter.csFilter); + return VFW_E_VMR_NOT_IN_MIXER_MODE; + } + + *count = filter->stream_count; + + LeaveCriticalSection(&filter->renderer.filter.csFilter); + return S_OK; } static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags) @@ -1361,6 +1386,9 @@ return E_INVALIDARG; } + if (mode != VMR9Mode_Windowed) + video_window_cleanup(&This->window); + This->mode = mode; LeaveCriticalSection(&This->renderer.filter.csFilter); return hr; @@ -1466,13 +1494,7 @@ if (source) This->window.src = *source; if (dest) - { This->window.dst = *dest; - FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest)); - SetWindowPos(This->window.hwnd, NULL, - dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top, - SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW); - } LeaveCriticalSection(&This->renderer.filter.csFilter); @@ -1621,21 +1643,23 @@ return IUnknown_Release(This->renderer.filter.outer_unk); } -static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight) +static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, + LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height) { - struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface); - TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight); + struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface); - if (!width || !height || !arwidth || !arheight) - { - ERR("Got no pointer\n"); + TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n", + filter, width, height, aspect_width, aspect_height); + + if (!width || !height) return E_POINTER; - } - *width = This->bmiheader.biWidth; - *height = This->bmiheader.biHeight; - *arwidth = This->bmiheader.biWidth; - *arheight = This->bmiheader.biHeight; + *width = filter->bmiheader.biWidth; + *height = filter->bmiheader.biHeight; + if (aspect_width) + *aspect_width = filter->bmiheader.biWidth; + if (aspect_height) + *aspect_height = filter->bmiheader.biHeight; return S_OK; } @@ -1667,13 +1691,7 @@ if (source) This->window.src = *source; if (dest) - { This->window.dst = *dest; - FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest)); - SetWindowPos(This->window.hwnd, NULL, - dest->left, dest->top, dest->right - dest->left, dest->bottom - dest->top, - SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW); - } LeaveCriticalSection(&This->renderer.filter.csFilter); @@ -1713,6 +1731,7 @@ static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND window) { struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface); + HRESULT hr; TRACE("filter %p, window %p.\n", filter, window); @@ -1731,10 +1750,12 @@ return VFW_E_WRONG_STATE; } - filter->hWndClippingWindow = window; + filter->clipping_window = window; + + hr = IVMRFilterConfig9_SetNumberOfStreams(&filter->IVMRFilterConfig9_iface, 4); LeaveCriticalSection(&filter->renderer.filter.csFilter); - return S_OK; + return hr; } static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc) @@ -1745,7 +1766,7 @@ FIXME("(%p/%p)->(...) semi-stub\n", iface, This); EnterCriticalSection(&This->renderer.filter.csFilter); - if (hwnd != This->hWndClippingWindow && hwnd != This->window.hwnd) + if (hwnd != This->clipping_window) { ERR("Not handling changing windows yet!!!\n"); LeaveCriticalSection(&This->renderer.filter.csFilter); @@ -1760,7 +1781,7 @@ } /* Windowless extension */ - hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, This->window.hwnd, NULL); + hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, NULL, NULL); LeaveCriticalSection(&This->renderer.filter.csFilter); return hr; @@ -2103,6 +2124,173 @@ VMR9SurfaceAllocatorNotify_NotifyEvent }; +static inline struct quartz_vmr *impl_from_IVMRMixerControl9(IVMRMixerControl9 *iface) +{ + return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerControl9_iface); +} + +static HRESULT WINAPI mixer_control9_QueryInterface(IVMRMixerControl9 *iface, REFIID iid, void **out) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out); +} + +static ULONG WINAPI mixer_control9_AddRef(IVMRMixerControl9 *iface) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + return IUnknown_AddRef(filter->renderer.filter.outer_unk); +} + +static ULONG WINAPI mixer_control9_Release(IVMRMixerControl9 *iface) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + return IUnknown_Release(filter->renderer.filter.outer_unk); +} + +static HRESULT WINAPI mixer_control9_SetAlpha(IVMRMixerControl9 *iface, DWORD stream, float alpha) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, stream %u, alpha %.8e, stub!\n", filter, stream, alpha); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_GetAlpha(IVMRMixerControl9 *iface, DWORD stream, float *alpha) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, stream %u, alpha %p, stub!\n", filter, stream, alpha); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_SetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD z) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, stream %u, z %u, stub!\n", filter, stream, z); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_GetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD *z) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, stream %u, z %p, stub!\n", filter, stream, z); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_SetOutputRect(IVMRMixerControl9 *iface, + DWORD stream, const VMR9NormalizedRect *rect) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, stream %u, rect %s, stub!\n", filter, stream, debugstr_normalized_rect(rect)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_GetOutputRect(IVMRMixerControl9 *iface, + DWORD stream, VMR9NormalizedRect *rect) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, stream %u, rect %p, stub!\n", filter, stream, rect); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_SetBackgroundClr(IVMRMixerControl9 *iface, COLORREF color) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, color #%06x, stub!\n", filter, color); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_GetBackgroundClr(IVMRMixerControl9 *iface, COLORREF *color) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, color %p, stub!\n", filter, color); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_SetMixingPrefs(IVMRMixerControl9 *iface, DWORD flags) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, flags %#x, stub!\n", filter, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_GetMixingPrefs(IVMRMixerControl9 *iface, DWORD *flags) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, flags %p, stub!\n", filter, flags); + + *flags = MixerPref9_NoDecimation | MixerPref9_ARAdjustXorY | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetRGB; + + return S_OK; +} + +static HRESULT WINAPI mixer_control9_SetProcAmpControl(IVMRMixerControl9 *iface, + DWORD stream, VMR9ProcAmpControl *settings) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, settings %p, stub!\n", filter, settings); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_GetProcAmpControl(IVMRMixerControl9 *iface, + DWORD stream, VMR9ProcAmpControl *settings) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, settings %p, stub!\n", filter, settings); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mixer_control9_GetProcAmpControlRange(IVMRMixerControl9 *iface, + DWORD stream, VMR9ProcAmpControlRange *settings) +{ + struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface); + + FIXME("filter %p, settings %p, stub!\n", filter, settings); + + return E_NOTIMPL; +} + +static const IVMRMixerControl9Vtbl mixer_control9_vtbl = +{ + mixer_control9_QueryInterface, + mixer_control9_AddRef, + mixer_control9_Release, + mixer_control9_SetAlpha, + mixer_control9_GetAlpha, + mixer_control9_SetZOrder, + mixer_control9_GetZOrder, + mixer_control9_SetOutputRect, + mixer_control9_GetOutputRect, + mixer_control9_SetBackgroundClr, + mixer_control9_GetBackgroundClr, + mixer_control9_SetMixingPrefs, + mixer_control9_GetMixingPrefs, + mixer_control9_SetProcAmpControl, + mixer_control9_GetProcAmpControl, + mixer_control9_GetProcAmpControlRange, +}; + static inline struct quartz_vmr *impl_from_IVMRMixerBitmap9(IVMRMixerBitmap9 *iface) { return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerBitmap9_iface); @@ -2219,6 +2407,9 @@ TRACE("filter %p, window %p.\n", filter, window); + if (!filter->window.hwnd) + return VFW_E_WRONG_STATE; + *window = filter->window.hwnd; return S_OK; } @@ -2286,6 +2477,7 @@ object->IVMRFilterConfig_iface.lpVtbl = &VMR7_FilterConfig_Vtbl; object->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl; object->IVMRMixerBitmap9_iface.lpVtbl = &mixer_bitmap9_vtbl; + object->IVMRMixerControl9_iface.lpVtbl = &mixer_control9_vtbl; object->IVMRMonitorConfig_iface.lpVtbl = &VMR7_MonitorConfig_Vtbl; object->IVMRMonitorConfig9_iface.lpVtbl = &VMR9_MonitorConfig_Vtbl; object->IVMRSurfaceAllocatorNotify_iface.lpVtbl = &VMR7_SurfaceAllocatorNotify_Vtbl; @@ -2383,11 +2575,6 @@ free(This->d3d9_surfaces); This->d3d9_surfaces = NULL; This->num_surfaces = 0; - if (This->d3d9_vertex) - { - IDirect3DVertexBuffer9_Release(This->d3d9_vertex); - This->d3d9_vertex = NULL; - } free(This); return 0; } @@ -2410,57 +2597,10 @@ return S_OK; } -#define USED_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1) -struct VERTEX { float x, y, z, rhw, u, v; }; - -static HRESULT VMR9_ImagePresenter_PresentTexture(struct default_presenter *This, IDirect3DSurface9 *surface) -{ - IDirect3DTexture9 *texture = NULL; - HRESULT hr; - - hr = IDirect3DDevice9_SetFVF(This->d3d9_dev, USED_FVF); - if (FAILED(hr)) - { - FIXME("SetFVF: %08x\n", hr); - return hr; - } - - hr = IDirect3DDevice9_SetStreamSource(This->d3d9_dev, 0, This->d3d9_vertex, 0, sizeof(struct VERTEX)); - if (FAILED(hr)) - { - FIXME("SetStreamSource: %08x\n", hr); - return hr; - } - - hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **) &texture); - if (FAILED(hr)) - { - FIXME("IDirect3DSurface9_GetContainer failed\n"); - return hr; - } - hr = IDirect3DDevice9_SetTexture(This->d3d9_dev, 0, (IDirect3DBaseTexture9 *)texture); - IDirect3DTexture9_Release(texture); - if (FAILED(hr)) - { - FIXME("SetTexture: %08x\n", hr); - return hr; - } - - hr = IDirect3DDevice9_DrawPrimitive(This->d3d9_dev, D3DPT_TRIANGLESTRIP, 0, 2); - if (FAILED(hr)) - { - FIXME("DrawPrimitive: %08x\n", hr); - return hr; - } - - return S_OK; -} - static HRESULT VMR9_ImagePresenter_PresentOffscreenSurface(struct default_presenter *This, IDirect3DSurface9 *surface) { HRESULT hr; IDirect3DSurface9 *target = NULL; - RECT target_rect; hr = IDirect3DDevice9_GetBackBuffer(This->d3d9_dev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &target); if (FAILED(hr)) @@ -2469,12 +2609,7 @@ return hr; } - /* Move rect to origin and flip it */ - SetRect(&target_rect, 0, This->pVMR9->window.dst.bottom - This->pVMR9->window.dst.top, - This->pVMR9->window.dst.right - This->pVMR9->window.dst.left, 0); - - hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, - &This->pVMR9->window.src, target, &target_rect, D3DTEXF_LINEAR); + hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, NULL, target, NULL, D3DTEXF_POINT); if (FAILED(hr)) ERR("IDirect3DDevice9_StretchRect -- %08x\n", hr); IDirect3DSurface9_Release(target); @@ -2486,12 +2621,9 @@ { struct default_presenter *This = impl_from_IVMRImagePresenter9(iface); HRESULT hr; - RECT output; BOOL render = FALSE; TRACE("(%p/%p/%p)->(...) stub\n", iface, This, This->pVMR9); - GetWindowRect(This->pVMR9->window.hwnd, &output); - TRACE("Output rectangle: %s\n", wine_dbgstr_rect(&output)); /* This might happen if we don't have active focus (eg on a different virtual desktop) */ if (!This->d3d9_dev) @@ -2504,10 +2636,7 @@ hr = IDirect3DDevice9_BeginScene(This->d3d9_dev); if (SUCCEEDED(hr)) { - if (This->d3d9_vertex) - hr = VMR9_ImagePresenter_PresentTexture(This, info->lpSurf); - else - hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf); + hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf); render = SUCCEEDED(hr); } else @@ -2515,7 +2644,8 @@ hr = IDirect3DDevice9_EndScene(This->d3d9_dev); if (render && SUCCEEDED(hr)) { - hr = IDirect3DDevice9_Present(This->d3d9_dev, NULL, NULL, This->pVMR9->window.hwnd, NULL); + hr = IDirect3DDevice9_Present(This->d3d9_dev, &This->pVMR9->window.src, + &This->pVMR9->window.dst, NULL, NULL); if (FAILED(hr)) FIXME("Presenting image: %08x\n", hr); } @@ -2593,14 +2723,6 @@ FIXME("Square texture support required..\n"); } - hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF, allocinfo->Pool, &This->d3d9_vertex, NULL); - if (FAILED(hr)) - { - ERR("Couldn't create vertex buffer: %08x\n", hr); - return hr; - } - - This->reset = TRUE; allocinfo->dwHeight = height; allocinfo->dwWidth = width; @@ -2633,28 +2755,47 @@ static BOOL CreateRenderingWindow(struct default_presenter *This, VMR9AllocationInfo *info, DWORD *numbuffers) { D3DPRESENT_PARAMETERS d3dpp; + IDirect3DDevice9 *device; DWORD d3d9_adapter; + D3DCAPS9 caps; + HWND window; HRESULT hr; TRACE("(%p)->()\n", This); + if (This->pVMR9->mode == VMR9Mode_Windowed) + window = This->pVMR9->window.hwnd; + else + window = This->pVMR9->clipping_window; + /* Obtain a monitor and d3d9 device */ - d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->window.hwnd, &This->hMon); + d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, window, &This->hMon); /* Now try to create the d3d9 device */ ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; - d3dpp.hDeviceWindow = This->pVMR9->window.hwnd; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.BackBufferHeight = This->pVMR9->window.dst.bottom - This->pVMR9->window.dst.top; - d3dpp.BackBufferWidth = This->pVMR9->window.dst.right - This->pVMR9->window.dst.left; + d3dpp.hDeviceWindow = window; + d3dpp.SwapEffect = D3DSWAPEFFECT_COPY; + d3dpp.BackBufferWidth = info->dwWidth; + d3dpp.BackBufferHeight = info->dwHeight; - hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev); + hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL, + NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device); if (FAILED(hr)) { ERR("Could not create device: %08x\n", hr); return FALSE; } + + IDirect3DDevice9_GetDeviceCaps(device, &caps); + if (!(caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)) + { + WARN("Device does not support blitting from textures.\n"); + IDirect3DDevice9_Release(device); + return FALSE; + } + + This->d3d9_dev = device; IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon); if (!(This->d3d9_surfaces = calloc(*numbuffers, sizeof(IDirect3DSurface9 *)))) @@ -2686,12 +2827,6 @@ { struct default_presenter *This = impl_from_IVMRSurfaceAllocatorEx9(iface); - if (This->pVMR9->mode != VMR9Mode_Windowed && !This->pVMR9->hWndClippingWindow) - { - ERR("No window set\n"); - return VFW_E_WRONG_STATE; - } - This->info = *allocinfo; if (!CreateRenderingWindow(This, allocinfo, numbuffers)) @@ -2710,114 +2845,6 @@ return S_OK; } -/* Recreate all surfaces (If allocated as D3DPOOL_DEFAULT) and survive! */ -static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(struct default_presenter *This) -{ - struct VERTEX t_vert[4]; - UINT width, height; - unsigned int i; - void *bits = NULL; - D3DPRESENT_PARAMETERS d3dpp; - HRESULT hr; - - if (!This->d3d9_surfaces || !This->reset) - return S_OK; - - This->reset = FALSE; - TRACE("RESETTING\n"); - if (This->d3d9_vertex) - { - IDirect3DVertexBuffer9_Release(This->d3d9_vertex); - This->d3d9_vertex = NULL; - } - - for (i = 0; i < This->num_surfaces; ++i) - { - IDirect3DSurface9 *surface = This->d3d9_surfaces[i]; - TRACE("Releasing surface %p\n", surface); - if (surface) - IDirect3DSurface9_Release(surface); - } - ZeroMemory(This->d3d9_surfaces, sizeof(IDirect3DSurface9 *) * This->num_surfaces); - - /* Now try to create the d3d9 device */ - ZeroMemory(&d3dpp, sizeof(d3dpp)); - d3dpp.Windowed = TRUE; - d3dpp.hDeviceWindow = This->pVMR9->window.hwnd; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - - if (This->d3d9_dev) - IDirect3DDevice9_Release(This->d3d9_dev); - This->d3d9_dev = NULL; - hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, - This->pVMR9->window.hwnd, &This->hMon), D3DDEVTYPE_HAL, NULL, - D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev); - if (FAILED(hr)) - { - hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, - This->pVMR9->window.hwnd, &This->hMon), D3DDEVTYPE_HAL, NULL, - D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev); - if (FAILED(hr)) - { - ERR("--> Creating device: %08x\n", hr); - return S_OK; - } - } - IVMRSurfaceAllocatorNotify9_ChangeD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon); - - IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, &This->info, &This->num_surfaces, This->d3d9_surfaces); - - This->reset = FALSE; - - if (!(This->info.dwFlags & VMR9AllocFlag_TextureSurface)) - return S_OK; - - hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF, - This->info.Pool, &This->d3d9_vertex, NULL); - - width = This->info.dwWidth; - height = This->info.dwHeight; - - for (i = 0; i < ARRAY_SIZE(t_vert); ++i) - { - if (i % 2) - { - t_vert[i].x = (float)This->pVMR9->window.dst.right - (float)This->pVMR9->window.dst.left - 0.5f; - t_vert[i].u = (float)This->pVMR9->window.src.right / (float)width; - } - else - { - t_vert[i].x = -0.5f; - t_vert[i].u = (float)This->pVMR9->window.src.left / (float)width; - } - - if (i % 4 < 2) - { - t_vert[i].y = -0.5f; - t_vert[i].v = (float)This->pVMR9->window.src.bottom / (float)height; - } - else - { - t_vert[i].y = (float)This->pVMR9->window.dst.bottom - (float)This->pVMR9->window.dst.top - 0.5f; - t_vert[i].v = (float)This->pVMR9->window.src.top / (float)height; - } - t_vert[i].z = 0.0f; - t_vert[i].rhw = 1.0f; - } - - FIXME("Vertex rectangle:\n"); - FIXME("X, Y: %f, %f\n", t_vert[0].x, t_vert[0].y); - FIXME("X, Y: %f, %f\n", t_vert[3].x, t_vert[3].y); - FIXME("TOP, LEFT: %f, %f\n", t_vert[0].u, t_vert[0].v); - FIXME("DOWN, BOTTOM: %f, %f\n", t_vert[3].u, t_vert[3].v); - - IDirect3DVertexBuffer9_Lock(This->d3d9_vertex, 0, sizeof(t_vert), &bits, 0); - memcpy(bits, t_vert, sizeof(t_vert)); - IDirect3DVertexBuffer9_Unlock(This->d3d9_vertex); - - return S_OK; -} - static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface) { struct default_presenter *This = impl_from_IVMRSurfaceAllocatorEx9(iface); @@ -2829,8 +2856,6 @@ return E_FAIL; } - VMR9_SurfaceAllocator_UpdateDeviceReset(This); - if (surfaceindex >= This->num_surfaces) { ERR("surfaceindex is greater than num_surfaces\n"); diff -Nru wine-development-5.8/dlls/rsaenh/rsaenh.c wine-development-5.9/dlls/rsaenh/rsaenh.c --- wine-development-5.8/dlls/rsaenh/rsaenh.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/rsaenh/rsaenh.c 2020-05-22 18:49:34.000000000 +0000 @@ -4005,7 +4005,7 @@ * IE6 SP1 asks for it in the 'About' dialog. * Returning this BLOB seems to satisfy IE. The marked 0x00 seem * to be 'don't care's. If you know anything more specific about - * this provider parameter, please report to wine-devel@winehq.org */ + * this provider parameter, please contact the Wine developers */ static const BYTE abWTF[96] = { 0xb0, 0x25, 0x63, 0x86, 0x9c, 0xab, 0xb6, 0x37, 0xe8, 0x82, /**/0x00,/**/ 0x72, 0x06, 0xb2, /**/0x00,/**/ 0x3b, diff -Nru wine-development-5.8/dlls/setupapi/devinst.c wine-development-5.9/dlls/setupapi/devinst.c --- wine-development-5.8/dlls/setupapi/devinst.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/setupapi/devinst.c 2020-05-22 18:49:34.000000000 +0000 @@ -1845,18 +1845,18 @@ } /*********************************************************************** - * SetupDiGetActualSectionToInstallA (SETUPAPI.@) + * SetupDiGetActualSectionToInstallExA (SETUPAPI.@) */ -BOOL WINAPI SetupDiGetActualSectionToInstallA(HINF hinf, const char *section, - char *section_ext, DWORD size, DWORD *needed, char **extptr) +BOOL WINAPI SetupDiGetActualSectionToInstallExA(HINF hinf, const char *section, SP_ALTPLATFORM_INFO *altplatform, + char *section_ext, DWORD size, DWORD *needed, char **extptr, void *reserved) { WCHAR sectionW[LINE_LEN], section_extW[LINE_LEN], *extptrW; BOOL ret; MultiByteToWideChar(CP_ACP, 0, section, -1, sectionW, ARRAY_SIZE(sectionW)); - ret = SetupDiGetActualSectionToInstallW(hinf, sectionW, section_extW, - ARRAY_SIZE(section_extW), NULL, &extptrW); + ret = SetupDiGetActualSectionToInstallExW(hinf, sectionW, altplatform, section_extW, + ARRAY_SIZE(section_extW), NULL, &extptrW, reserved); if (ret) { if (needed) @@ -1879,73 +1879,94 @@ } /*********************************************************************** - * SetupDiGetActualSectionToInstallW (SETUPAPI.@) + * SetupDiGetActualSectionToInstallA (SETUPAPI.@) */ -BOOL WINAPI SetupDiGetActualSectionToInstallW( - HINF InfHandle, - PCWSTR InfSectionName, - PWSTR InfSectionWithExt, - DWORD InfSectionWithExtSize, - PDWORD RequiredSize, - PWSTR *Extension) +BOOL WINAPI SetupDiGetActualSectionToInstallA(HINF hinf, const char *section, char *section_ext, + DWORD size, DWORD *needed, char **extptr) { - WCHAR szBuffer[MAX_PATH]; - DWORD dwLength; - DWORD dwFullLength; - LONG lLineCount = -1; + return SetupDiGetActualSectionToInstallExA(hinf, section, NULL, section_ext, size, + needed, extptr, NULL); +} - lstrcpyW(szBuffer, InfSectionName); - dwLength = lstrlenW(szBuffer); +/*********************************************************************** + * SetupDiGetActualSectionToInstallExW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetActualSectionToInstallExW(HINF hinf, const WCHAR *section, SP_ALTPLATFORM_INFO *altplatform, + WCHAR *section_ext, DWORD size, DWORD *needed, WCHAR **extptr, void *reserved) +{ + WCHAR buffer[MAX_PATH]; + DWORD len; + DWORD full_len; + LONG line_count = -1; + + TRACE("hinf %p, section %s, altplatform %p, ext %p, size %d, needed %p, extptr %p, reserved %p.\n", + hinf, debugstr_w(section), altplatform, section_ext, size, needed, extptr, reserved); + + if (altplatform) + FIXME("SP_ALTPLATFORM_INFO unsupported\n"); + + lstrcpyW(buffer, section); + len = lstrlenW(buffer); if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { - /* Test section name with '.NTx86' extension */ - lstrcpyW(&szBuffer[dwLength], NtPlatformExtension); - lLineCount = SetupGetLineCountW(InfHandle, szBuffer); - - if (lLineCount == -1) - { - /* Test section name with '.NT' extension */ - lstrcpyW(&szBuffer[dwLength], NtExtension); - lLineCount = SetupGetLineCountW(InfHandle, szBuffer); - } + /* Test section name with '.NTx86' extension */ + lstrcpyW(&buffer[len], NtPlatformExtension); + line_count = SetupGetLineCountW(hinf, buffer); + + if (line_count == -1) + { + /* Test section name with '.NT' extension */ + lstrcpyW(&buffer[len], NtExtension); + line_count = SetupGetLineCountW(hinf, buffer); + } } else { - /* Test section name with '.Win' extension */ - lstrcpyW(&szBuffer[dwLength], WinExtension); - lLineCount = SetupGetLineCountW(InfHandle, szBuffer); + /* Test section name with '.Win' extension */ + lstrcpyW(&buffer[len], WinExtension); + line_count = SetupGetLineCountW(hinf, buffer); } - if (lLineCount == -1) - szBuffer[dwLength] = 0; + if (line_count == -1) + buffer[len] = 0; - dwFullLength = lstrlenW(szBuffer); + full_len = lstrlenW(buffer); - if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0) + if (section_ext != NULL && size != 0) { - if (InfSectionWithExtSize < (dwFullLength + 1)) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - lstrcpyW(InfSectionWithExt, szBuffer); - if (Extension != NULL) - { - *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength]; - } + if (size < (full_len + 1)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + lstrcpyW(section_ext, buffer); + if (extptr != NULL) + { + *extptr = (len == full_len) ? NULL : §ion_ext[len]; + } } - if (RequiredSize != NULL) + if (needed != NULL) { - *RequiredSize = dwFullLength + 1; + *needed = full_len + 1; } return TRUE; } /*********************************************************************** + * SetupDiGetActualSectionToInstallW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetActualSectionToInstallW(HINF hinf, const WCHAR *section, WCHAR *section_ext, + DWORD size, DWORD *needed, WCHAR **extptr) +{ + return SetupDiGetActualSectionToInstallExW(hinf, section, NULL, section_ext, size, + needed, extptr, NULL); +} + +/*********************************************************************** * SetupDiGetClassDescriptionA (SETUPAPI.@) */ BOOL WINAPI SetupDiGetClassDescriptionA( diff -Nru wine-development-5.8/dlls/setupapi/setupapi.spec wine-development-5.9/dlls/setupapi/setupapi.spec --- wine-development-5.8/dlls/setupapi/setupapi.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/setupapi/setupapi.spec 2020-05-22 18:49:34.000000000 +0000 @@ -89,8 +89,8 @@ @ stub CM_Get_Device_ID_List_Size_ExW @ stdcall CM_Get_Device_ID_Size(ptr ptr long) @ stub CM_Get_Device_ID_Size_Ex -@ stub CM_Get_Device_Interface_AliasA -@ stub CM_Get_Device_Interface_AliasW +@ stdcall CM_Get_Device_Interface_AliasA(str ptr ptr ptr long) +@ stdcall CM_Get_Device_Interface_AliasW(wstr ptr ptr ptr long) @ stub CM_Get_Device_Interface_Alias_ExA @ stub CM_Get_Device_Interface_Alias_ExW @ stub CM_Get_Device_Interface_ListA @@ -315,8 +315,10 @@ @ stdcall SetupDiEnumDeviceInterfaces(long ptr ptr long ptr) @ stdcall SetupDiEnumDriverInfoA(ptr ptr long long ptr) @ stdcall SetupDiEnumDriverInfoW(ptr ptr long long ptr) -@ stdcall SetupDiGetActualSectionToInstallA(long str str long ptr ptr) -@ stdcall SetupDiGetActualSectionToInstallW(long wstr wstr long ptr ptr) +@ stdcall SetupDiGetActualSectionToInstallA(long str ptr long ptr ptr) +@ stdcall SetupDiGetActualSectionToInstallExA(long str ptr ptr long ptr ptr ptr) +@ stdcall SetupDiGetActualSectionToInstallExW(long wstr ptr ptr long ptr ptr ptr) +@ stdcall SetupDiGetActualSectionToInstallW(long wstr ptr long ptr ptr) @ stdcall SetupDiGetClassBitmapIndex(ptr ptr) @ stdcall SetupDiGetClassDescriptionA(ptr str long ptr) @ stdcall SetupDiGetClassDescriptionExA(ptr str long ptr str ptr) diff -Nru wine-development-5.8/dlls/setupapi/stubs.c wine-development-5.9/dlls/setupapi/stubs.c --- wine-development-5.8/dlls/setupapi/stubs.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/setupapi/stubs.c 2020-05-22 18:49:34.000000000 +0000 @@ -392,6 +392,26 @@ } /*********************************************************************** + * CM_Get_Device_Interface_AliasA (SETUPAPI.@) + */ +CONFIGRET WINAPI CM_Get_Device_Interface_AliasA(const char *interface, GUID *class, + char *name, ULONG *len, ULONG flags) +{ + FIXME("%s %p %p %p 0x%08x: stub\n", debugstr_a(interface), class, name, len, flags); + return CR_FAILURE; +} + +/*********************************************************************** + * CM_Get_Device_Interface_AliasW (SETUPAPI.@) + */ +CONFIGRET WINAPI CM_Get_Device_Interface_AliasW(const WCHAR *interface, GUID *class, + WCHAR *name, ULONG *len, ULONG flags) +{ + FIXME("%s %p %p %p 0x%08x: stub\n", debugstr_w(interface), class, name, len, flags); + return CR_FAILURE; +} + +/*********************************************************************** * CM_Get_DevNode_Registry_Property_ExA (SETUPAPI.@) */ CONFIGRET WINAPI CM_Get_DevNode_Registry_Property_ExA(DEVINST dev, ULONG prop, PULONG regdatatype, diff -Nru wine-development-5.8/dlls/shcore/main.c wine-development-5.9/dlls/shcore/main.c --- wine-development-5.8/dlls/shcore/main.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/shcore/main.c 2020-05-22 18:49:34.000000000 +0000 @@ -245,7 +245,7 @@ HRESULT WINAPI SetCurrentProcessExplicitAppUserModelID(const WCHAR *appid) { FIXME("%s: stub\n", debugstr_w(appid)); - return E_NOTIMPL; + return S_OK; } HRESULT WINAPI GetCurrentProcessExplicitAppUserModelID(const WCHAR **appid) diff -Nru wine-development-5.8/dlls/shcore/Makefile.in wine-development-5.9/dlls/shcore/Makefile.in --- wine-development-5.8/dlls/shcore/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/shcore/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -1,4 +1,5 @@ MODULE = shcore.dll +IMPORTLIB = shcore IMPORTS = user32 gdi32 ole32 advapi32 EXTRADLLFLAGS = -mno-cygwin diff -Nru wine-development-5.8/dlls/shell32/shlview.c wine-development-5.9/dlls/shell32/shlview.c --- wine-development-5.8/dlls/shell32/shlview.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/shell32/shlview.c 2020-05-22 18:49:34.000000000 +0000 @@ -1838,7 +1838,7 @@ FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam); #endif - if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST)) + if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message<=WM_KEYLAST)) { TRACE("-- key=0x04%lx\n",lpmsg->wParam) ; } diff -Nru wine-development-5.8/dlls/shell32/tests/shelldispatch.c wine-development-5.9/dlls/shell32/tests/shelldispatch.c --- wine-development-5.8/dlls/shell32/tests/shelldispatch.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/shell32/tests/shelldispatch.c 2020-05-22 18:49:34.000000000 +0000 @@ -1018,6 +1018,7 @@ { IShellWindows *shellwindows; LONG cookie, cookie2, ret; + ITEMIDLIST *pidl; IDispatch *disp; VARIANT v, v2; HRESULT hr; @@ -1034,15 +1035,12 @@ ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "got 0x%08x\n", hr); hr = IShellWindows_Register(shellwindows, NULL, 0, SWC_EXPLORER, &cookie); -todo_wine ok(hr == E_POINTER, "got 0x%08x\n", hr); hr = IShellWindows_Register(shellwindows, (IDispatch*)shellwindows, 0, SWC_EXPLORER, &cookie); -todo_wine ok(hr == E_POINTER, "got 0x%08x\n", hr); hr = IShellWindows_Register(shellwindows, (IDispatch*)shellwindows, 0, SWC_EXPLORER, &cookie); -todo_wine ok(hr == E_POINTER, "got 0x%08x\n", hr); hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP, @@ -1051,34 +1049,56 @@ cookie = 0; hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_EXPLORER, &cookie); -todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(cookie != 0, "got %d\n", cookie); -} + cookie2 = 0; hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_EXPLORER, &cookie2); -todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(cookie2 != 0 && cookie2 != cookie, "got %d\n", cookie2); -} + + pidl = ILCreateFromPathA("C:\\"); + V_VT(&v) = VT_ARRAY | VT_UI1; + V_ARRAY(&v) = SafeArrayCreateVector(VT_UI1, 0, ILGetSize(pidl)); + memcpy(V_ARRAY(&v)->pvData, pidl, ILGetSize(pidl)); + + VariantInit(&v2); + hr = IShellWindows_FindWindowSW(shellwindows, &v, &v2, SWC_EXPLORER, &ret, 0, &disp); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(!ret, "Got window %#x.\n", ret); + ok(!disp, "Got IDispatch %p.\n", &disp); + + hr = IShellWindows_OnNavigate(shellwindows, 0, &v); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + + hr = IShellWindows_OnNavigate(shellwindows, cookie, &v); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IShellWindows_FindWindowSW(shellwindows, &v, &v2, SWC_EXPLORER, &ret, 0, &disp); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(ret == (LONG)(LONG_PTR)hwnd, "Expected %p, got %#x.\n", hwnd, ret); + ok(!disp, "Got IDispatch %p.\n", &disp); + hr = IShellWindows_Revoke(shellwindows, cookie); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IShellWindows_FindWindowSW(shellwindows, &v, &v2, SWC_EXPLORER, &ret, 0, &disp); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(!ret, "Got window %#x.\n", ret); + ok(!disp, "Got IDispatch %p.\n", &disp); + hr = IShellWindows_Revoke(shellwindows, cookie2); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); hr = IShellWindows_Revoke(shellwindows, 0); -todo_wine ok(hr == S_FALSE, "got 0x%08x\n", hr); /* we can register ourselves as desktop, but FindWindowSW still returns real desktop window */ cookie = 0; hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_DESKTOP, &cookie); -todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(cookie != 0, "got %d\n", cookie); -} + disp = (void*)0xdeadbeef; ret = 0xdead; VariantInit(&v); @@ -1208,7 +1228,6 @@ ok(ret == 0, "got %d\n", ret); hr = IShellWindows_Revoke(shellwindows, cookie); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); DestroyWindow(hwnd); IShellWindows_Release(shellwindows); diff -Nru wine-development-5.8/dlls/shlwapi/Makefile.in wine-development-5.9/dlls/shlwapi/Makefile.in --- wine-development-5.8/dlls/shlwapi/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/shlwapi/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -1,7 +1,7 @@ EXTRADEFS = -D_SHLWAPI_ MODULE = shlwapi.dll IMPORTLIB = shlwapi -IMPORTS = uuid user32 gdi32 advapi32 kernelbase +IMPORTS = uuid shcore user32 gdi32 advapi32 kernelbase DELAYIMPORTS = userenv oleaut32 ole32 comctl32 comdlg32 mpr mlang urlmon shell32 winmm version EXTRADLLFLAGS = -mno-cygwin diff -Nru wine-development-5.8/dlls/shlwapi/reg.c wine-development-5.9/dlls/shlwapi/reg.c --- wine-development-5.8/dlls/shlwapi/reg.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/shlwapi/reg.c 2020-05-22 18:49:34.000000000 +0000 @@ -47,430 +47,6 @@ INT WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT); HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY); - -/************************************************************************* - * SHRegGetPathA [SHLWAPI.@] - * - * Get a path from the registry. - * - * PARAMS - * hKey [I] Handle to registry key - * lpszSubKey [I] Name of sub key containing path to get - * lpszValue [I] Name of value containing path to get - * lpszPath [O] Buffer for returned path - * dwFlags [I] Reserved - * - * RETURNS - * Success: ERROR_SUCCESS. lpszPath contains the path. - * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(). - */ -DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue, - LPSTR lpszPath, DWORD dwFlags) -{ - DWORD dwSize = MAX_PATH; - - TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_a(lpszSubKey), - debugstr_a(lpszValue), lpszPath, dwFlags); - - return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize); -} - -/************************************************************************* - * SHRegGetPathW [SHLWAPI.@] - * - * See SHRegGetPathA. - */ -DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue, - LPWSTR lpszPath, DWORD dwFlags) -{ - DWORD dwSize = MAX_PATH; - - TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_w(lpszSubKey), - debugstr_w(lpszValue), lpszPath, dwFlags); - - return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize); -} - - -/************************************************************************* - * SHRegSetPathA [SHLWAPI.@] - * - * Write a path to the registry. - * - * PARAMS - * hKey [I] Handle to registry key - * lpszSubKey [I] Name of sub key containing path to set - * lpszValue [I] Name of value containing path to set - * lpszPath [O] Path to write - * dwFlags [I] Reserved, must be 0. - * - * RETURNS - * Success: ERROR_SUCCESS. - * Failure: An error code from SHSetValueA(). - */ -DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue, - LPCSTR lpszPath, DWORD dwFlags) -{ - char szBuff[MAX_PATH]; - - FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_a(lpszSubKey), - debugstr_a(lpszValue), lpszPath, dwFlags); - - lstrcpyA(szBuff, lpszPath); - - /* FIXME: PathUnExpandEnvStringsA(szBuff); */ - - return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff, - lstrlenA(szBuff)); -} - -/************************************************************************* - * SHRegSetPathW [SHLWAPI.@] - * - * See SHRegSetPathA. - */ -DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue, - LPCWSTR lpszPath, DWORD dwFlags) -{ - WCHAR szBuff[MAX_PATH]; - - FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_w(lpszSubKey), - debugstr_w(lpszValue), lpszPath, dwFlags); - - lstrcpyW(szBuff, lpszPath); - - /* FIXME: PathUnExpandEnvStringsW(szBuff); */ - - return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff, - lstrlenW(szBuff)); -} - -/************************************************************************* - * SHGetValueA [SHLWAPI.@] - * - * Get a value from the registry. - * - * PARAMS - * hKey [I] Handle to registry key - * lpszSubKey [I] Name of sub key containing value to get - * lpszValue [I] Name of value to get - * pwType [O] Pointer to the values type - * pvData [O] Pointer to the values data - * pcbData [O] Pointer to the values size - * - * RETURNS - * Success: ERROR_SUCCESS. Output parameters contain the details read. - * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(). - */ -DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue, - LPDWORD pwType, LPVOID pvData, LPDWORD pcbData) -{ - DWORD dwRet = 0; - HKEY hSubKey = 0; - - TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey), - debugstr_a(lpszValue), pwType, pvData, pcbData); - - /* lpszSubKey can be 0. In this case the value is taken from the - * current key. - */ - if(lpszSubKey) - dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey); - - if (! dwRet) - { - /* SHQueryValueEx expands Environment strings */ - dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData); - if (hSubKey) RegCloseKey(hSubKey); - } - return dwRet; -} - -/************************************************************************* - * SHGetValueW [SHLWAPI.@] - * - * See SHGetValueA. - */ -DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue, - LPDWORD pwType, LPVOID pvData, LPDWORD pcbData) -{ - DWORD dwRet = 0; - HKEY hSubKey = 0; - - TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey), - debugstr_w(lpszValue), pwType, pvData, pcbData); - - if(lpszSubKey) - dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey); - - if (! dwRet) - { - dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData); - if (hSubKey) RegCloseKey(hSubKey); - } - return dwRet; -} - -/************************************************************************* - * SHSetValueA [SHLWAPI.@] - * - * Set a value in the registry. - * - * PARAMS - * hKey [I] Handle to registry key - * lpszSubKey [I] Name of sub key under hKey - * lpszValue [I] Name of value to set - * dwType [I] Type of the value - * pvData [I] Data of the value - * cbData [I] Size of the value - * - * RETURNS - * Success: ERROR_SUCCESS. The value is set with the data given. - * Failure: An error code from RegCreateKeyExA() or RegSetValueExA() - * - * NOTES - * If lpszSubKey does not exist, it is created before the value is set. If - * lpszSubKey is NULL or an empty string, then the value is added directly - * to hKey instead. - */ -DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue, - DWORD dwType, LPCVOID pvData, DWORD cbData) -{ - DWORD dwRet = ERROR_SUCCESS, dwDummy; - HKEY hSubKey; - - TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_a(lpszSubKey), - debugstr_a(lpszValue), dwType, pvData, cbData); - - if (lpszSubKey && *lpszSubKey) - dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL, - 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy); - else - hSubKey = hKey; - if (!dwRet) - { - dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData); - if (hSubKey != hKey) - RegCloseKey(hSubKey); - } - return dwRet; -} - -/************************************************************************* - * SHSetValueW [SHLWAPI.@] - * - * See SHSetValueA. - */ -DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue, - DWORD dwType, LPCVOID pvData, DWORD cbData) -{ - DWORD dwRet = ERROR_SUCCESS, dwDummy; - HKEY hSubKey; - - TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_w(lpszSubKey), - debugstr_w(lpszValue), dwType, pvData, cbData); - - if (lpszSubKey && *lpszSubKey) - dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL, - 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy); - else - hSubKey = hKey; - if (!dwRet) - { - dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData); - if (hSubKey != hKey) - RegCloseKey(hSubKey); - } - return dwRet; -} - -/************************************************************************* - * SHQueryInfoKeyA [SHLWAPI.@] - * - * Get information about a registry key. See RegQueryInfoKeyA(). - * - * RETURNS - * The result of calling RegQueryInfoKeyA(). - */ -LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax, - LPDWORD pwValues, LPDWORD pwValueMax) -{ - TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax, - pwValues, pwValueMax); - return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax, - NULL, pwValues, pwValueMax, NULL, NULL, NULL); -} - -/************************************************************************* - * SHQueryInfoKeyW [SHLWAPI.@] - * - * See SHQueryInfoKeyA. - */ -LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax, - LPDWORD pwValues, LPDWORD pwValueMax) -{ - TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax, - pwValues, pwValueMax); - return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax, - NULL, pwValues, pwValueMax, NULL, NULL, NULL); -} - -/************************************************************************* - * SHQueryValueExA [SHLWAPI.@] - * - * Get a value from the registry, expanding environment variable strings. - * - * PARAMS - * hKey [I] Handle to registry key - * lpszValue [I] Name of value to query - * lpReserved [O] Reserved for future use; must be NULL - * pwType [O] Optional pointer updated with the values type - * pvData [O] Optional pointer updated with the values data - * pcbData [O] Optional pointer updated with the values size - * - * RETURNS - * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with - * information about the value. - * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the - * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error - * code from RegQueryValueExA() or ExpandEnvironmentStringsA(). - * - * NOTES - * Either pwType, pvData or pcbData may be NULL if the caller doesn't want - * the type, data or size information for the value. - * - * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The - * value returned will be truncated if it is of type REG_SZ and bigger than - * the buffer given to store it. - * - * REG_EXPAND_SZ: - * case-1: the unexpanded string is smaller than the expanded one - * subcase-1: the buffer is too small to hold the unexpanded string: - * function fails and returns the size of the unexpanded string. - * - * subcase-2: buffer is too small to hold the expanded string: - * the function return success (!!) and the result is truncated - * *** This is clearly an error in the native implementation. *** - * - * case-2: the unexpanded string is bigger than the expanded one - * The buffer must have enough space to hold the unexpanded - * string even if the result is smaller. - * - */ -DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue, - LPDWORD lpReserved, LPDWORD pwType, - LPVOID pvData, LPDWORD pcbData) -{ - DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen; - - TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_a(lpszValue), - lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0); - - if (pcbData) dwUnExpDataLen = *pcbData; - - dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen); - - if (pcbData && (dwType == REG_EXPAND_SZ)) - { - DWORD nBytesToAlloc; - - /* Expand type REG_EXPAND_SZ into REG_SZ */ - LPSTR szData; - - /* If the caller didn't supply a buffer or the buffer is too small we have - * to allocate our own - */ - if ((!pvData) || (dwRet == ERROR_MORE_DATA) ) - { - char cNull = '\0'; - nBytesToAlloc = dwUnExpDataLen; - - szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc); - RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc); - dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1); - dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen); - LocalFree(szData); - } - else - { - nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR); - szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc); - lstrcpyA(szData, pvData); - dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR)); - if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA; - dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen); - LocalFree(szData); - } - } - - /* Update the type and data size if the caller wanted them */ - if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ; - if ( pwType ) *pwType = dwType; - if ( pcbData ) *pcbData = dwUnExpDataLen; - return dwRet; -} - - -/************************************************************************* - * SHQueryValueExW [SHLWAPI.@] - * - * See SHQueryValueExA. - */ -DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue, - LPDWORD lpReserved, LPDWORD pwType, - LPVOID pvData, LPDWORD pcbData) -{ - DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen; - - TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_w(lpszValue), - lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0); - - if (pcbData) dwUnExpDataLen = *pcbData; - - dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen); - if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA) - return dwRet; - - if (pcbData && (dwType == REG_EXPAND_SZ)) - { - DWORD nBytesToAlloc; - - /* Expand type REG_EXPAND_SZ into REG_SZ */ - LPWSTR szData; - - /* If the caller didn't supply a buffer or the buffer is too small we have - * to allocate our own - */ - if ((!pvData) || (dwRet == ERROR_MORE_DATA) ) - { - WCHAR cNull = '\0'; - nBytesToAlloc = dwUnExpDataLen; - - szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc); - RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc); - dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1); - dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen); - LocalFree(szData); - } - else - { - nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR); - szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc); - lstrcpyW(szData, pvData); - dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) ); - if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA; - dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen); - LocalFree(szData); - } - } - - /* Update the type and data size if the caller wanted them */ - if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ; - if ( pwType ) *pwType = dwType; - if ( pcbData ) *pcbData = dwUnExpDataLen; - return dwRet; -} - /************************************************************************* * SHDeleteOrphanKeyA [SHLWAPI.@] * @@ -538,73 +114,8 @@ } /************************************************************************* - * SHDeleteValueA [SHLWAPI.@] - * - * Delete a value from the registry. - * - * PARAMS - * hKey [I] Handle to registry key - * lpszSubKey [I] Name of sub key containing value to delete - * lpszValue [I] Name of value to delete - * - * RETURNS - * Success: ERROR_SUCCESS. The value is deleted. - * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA(). - */ -DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue) -{ - DWORD dwRet; - HKEY hSubKey; - - TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue)); - - dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey); - if (!dwRet) - { - dwRet = RegDeleteValueA(hSubKey, lpszValue); - RegCloseKey(hSubKey); - } - return dwRet; -} - -/************************************************************************* - * SHDeleteValueW [SHLWAPI.@] - * - * See SHDeleteValueA. - */ -DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue) -{ - DWORD dwRet; - HKEY hSubKey; - - TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue)); - - dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey); - if (!dwRet) - { - dwRet = RegDeleteValueW(hSubKey, lpszValue); - RegCloseKey(hSubKey); - } - return dwRet; -} - -/************************************************************************* * @ [SHLWAPI.205] * - * Get a value from the registry. - * - * PARAMS - * hKey [I] Handle to registry key - * pSubKey [I] Name of sub key containing value to get - * pValue [I] Name of value to get - * pwType [O] Destination for the values type - * pvData [O] Destination for the values data - * pbData [O] Destination for the values size - * - * RETURNS - * Success: ERROR_SUCCESS. Output parameters contain the details read. - * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(), - * or ERROR_INVALID_FUNCTION in the machine is in safe mode. */ DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue, LPDWORD pwType, LPVOID pvData, LPDWORD pbData) @@ -617,7 +128,6 @@ /************************************************************************* * @ [SHLWAPI.206] * - * Unicode version of SHGetValueGoodBootW. */ DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue, LPDWORD pwType, LPVOID pvData, LPDWORD pbData) @@ -932,26 +442,6 @@ return TRUE; } -/************************************************************************* - * SHRegDuplicateHKey [SHLWAPI.@] - * - * Create a duplicate of a registry handle. - * - * PARAMS - * hKey [I] key to duplicate. - * - * RETURNS - * A new handle pointing to the same key as hKey. - */ -HKEY WINAPI SHRegDuplicateHKey(HKEY hKey) -{ - HKEY newKey = 0; - - RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey); - TRACE("new key is %p\n", newKey); - return newKey; -} - /* * The following functions are ORDINAL ONLY: */ diff -Nru wine-development-5.8/dlls/shlwapi/shlwapi.spec wine-development-5.9/dlls/shlwapi/shlwapi.spec --- wine-development-5.8/dlls/shlwapi/shlwapi.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/shlwapi/shlwapi.spec 2020-05-22 18:49:34.000000000 +0000 @@ -694,25 +694,25 @@ @ stdcall SHDeleteKeyW(long wstr) shcore.SHDeleteKeyW @ stdcall SHDeleteOrphanKeyA(long str) @ stdcall SHDeleteOrphanKeyW(long wstr) -@ stdcall SHDeleteValueA(long str str) -@ stdcall SHDeleteValueW(long wstr wstr) +@ stdcall -import SHDeleteValueA(long str str) +@ stdcall -import SHDeleteValueW(long wstr wstr) @ stdcall SHEnumKeyExA(long long str ptr) shcore.SHEnumKeyExA @ stdcall SHEnumKeyExW(long long wstr ptr) shcore.SHEnumKeyExW @ stdcall SHEnumValueA(long long str ptr ptr ptr ptr) shcore.SHEnumValueA @ stdcall SHEnumValueW(long long wstr ptr ptr ptr ptr) shcore.SHEnumValueW @ stdcall SHGetInverseCMAP ( ptr long ) @ stdcall SHGetThreadRef(ptr) shcore.SHGetThreadRef -@ stdcall SHGetValueA ( long str str ptr ptr ptr ) -@ stdcall SHGetValueW ( long wstr wstr ptr ptr ptr ) +@ stdcall -import SHGetValueA(long str str ptr ptr ptr) +@ stdcall -import SHGetValueW(long wstr wstr ptr ptr ptr) @ stdcall SHIsLowMemoryMachine(long) @ stdcall SHOpenRegStream2A(long str str long) shcore.SHOpenRegStream2A @ stdcall SHOpenRegStream2W(long wstr wstr long) shcore.SHOpenRegStream2W @ stdcall SHOpenRegStreamA(long str str long) shcore.SHOpenRegStreamA @ stdcall SHOpenRegStreamW(long wstr wstr long) shcore.SHOpenRegStreamW -@ stdcall SHQueryInfoKeyA(long ptr ptr ptr ptr) -@ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr) -@ stdcall SHQueryValueExA(long str ptr ptr ptr ptr) -@ stdcall SHQueryValueExW(long wstr ptr ptr ptr ptr) +@ stdcall -import SHQueryInfoKeyA(long ptr ptr ptr ptr) +@ stdcall -import SHQueryInfoKeyW(long ptr ptr ptr ptr) +@ stdcall -import SHQueryValueExA(long str ptr ptr ptr ptr) +@ stdcall -import SHQueryValueExW(long wstr ptr ptr ptr ptr) @ stdcall SHRegCloseUSKey(ptr) @ stdcall SHRegCreateUSKeyA(str long long ptr long) @ stdcall SHRegCreateUSKeyW(wstr long long ptr long) @@ -720,15 +720,15 @@ @ stdcall SHRegDeleteEmptyUSKeyW(long wstr long) @ stdcall SHRegDeleteUSValueA(long str long) @ stdcall SHRegDeleteUSValueW(long wstr long) -@ stdcall SHRegDuplicateHKey (long) +@ stdcall -import SHRegDuplicateHKey(long) @ stdcall SHRegEnumUSKeyA(long long str ptr long) @ stdcall SHRegEnumUSKeyW(long long wstr ptr long) @ stdcall SHRegEnumUSValueA(long long ptr ptr ptr ptr ptr long) @ stdcall SHRegEnumUSValueW(long long ptr ptr ptr ptr ptr long) @ stdcall SHRegGetBoolUSValueA(str str long long) @ stdcall SHRegGetBoolUSValueW(wstr wstr long long) -@ stdcall SHRegGetPathA(long str str ptr long) -@ stdcall SHRegGetPathW(long wstr wstr ptr long) +@ stdcall -import SHRegGetPathA(long str str ptr long) +@ stdcall -import SHRegGetPathW(long wstr wstr ptr long) @ stdcall SHRegGetUSValueA ( str str ptr ptr ptr long ptr long ) @ stdcall SHRegGetUSValueW ( wstr wstr ptr ptr ptr long ptr long ) @ stdcall SHRegGetValueA ( long str str long ptr ptr ptr ) advapi32.RegGetValueA @@ -739,8 +739,8 @@ @ stdcall SHRegQueryInfoUSKeyW ( long ptr ptr ptr ptr long ) @ stdcall SHRegQueryUSValueA ( long str ptr ptr ptr long ptr long ) @ stdcall SHRegQueryUSValueW ( long wstr ptr ptr ptr long ptr long ) -@ stdcall SHRegSetPathA(long str str str long) -@ stdcall SHRegSetPathW(long wstr wstr wstr long) +@ stdcall -import SHRegSetPathA(long str str str long) +@ stdcall -import SHRegSetPathW(long wstr wstr wstr long) @ stdcall SHRegSetUSValueA ( str str long ptr long long) @ stdcall SHRegSetUSValueW ( wstr wstr long ptr long long) @ stdcall SHRegWriteUSValueA (long str long ptr long long) @@ -748,8 +748,8 @@ @ stdcall SHRegisterValidateTemplate(wstr long) @ stdcall SHReleaseThreadRef() shcore.SHReleaseThreadRef @ stdcall SHSetThreadRef(ptr) shcore.SHSetThreadRef -@ stdcall SHSetValueA (long str str long ptr long) -@ stdcall SHSetValueW (long wstr wstr long ptr long) +@ stdcall -import SHSetValueA(long str str long ptr long) +@ stdcall -import SHSetValueW(long wstr wstr long ptr long) @ stdcall SHSkipJunction(ptr ptr) @ stdcall SHStrDupA (str ptr) @ stdcall SHStrDupW (wstr ptr) diff -Nru wine-development-5.8/dlls/shlwapi/tests/url.c wine-development-5.9/dlls/shlwapi/tests/url.c --- wine-development-5.8/dlls/shlwapi/tests/url.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/shlwapi/tests/url.c 2020-05-22 18:49:34.000000000 +0000 @@ -1052,6 +1052,22 @@ urllen = lstrlenA(winehqA); + /* Parameter checks */ + dwSize = ARRAY_SIZE(szReturnUrl); + hr = pUrlCanonicalizeA(NULL, szReturnUrl, &dwSize, URL_UNESCAPE); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + dwSize = ARRAY_SIZE(szReturnUrl); + hr = pUrlCanonicalizeA(winehqA, NULL, &dwSize, URL_UNESCAPE); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + hr = pUrlCanonicalizeA(winehqA, szReturnUrl, NULL, URL_UNESCAPE); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + dwSize = 0; + hr = pUrlCanonicalizeA(winehqA, szReturnUrl, &dwSize, URL_UNESCAPE); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + /* buffer has no space for the result */ dwSize=urllen-1; memset(szReturnUrl, '#', urllen+4); @@ -1137,6 +1153,22 @@ } urllen = lstrlenW(winehqW); + /* Parameter checks */ + dwSize = ARRAY_SIZE(szReturnUrl); + hr = pUrlCanonicalizeW(NULL, szReturnUrl, &dwSize, URL_UNESCAPE); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + dwSize = ARRAY_SIZE(szReturnUrl); + hr = pUrlCanonicalizeW(winehqW, NULL, &dwSize, URL_UNESCAPE); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + hr = pUrlCanonicalizeW(winehqW, szReturnUrl, NULL, URL_UNESCAPE); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + dwSize = 0; + hr = pUrlCanonicalizeW(winehqW, szReturnUrl, &dwSize, URL_UNESCAPE); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + /* buffer has no space for the result */ dwSize = (urllen-1); memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR)); diff -Nru wine-development-5.8/dlls/strmbase/pin.c wine-development-5.9/dlls/strmbase/pin.c --- wine-development-5.8/dlls/strmbase/pin.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/strmbase/pin.c 2020-05-22 18:49:34.000000000 +0000 @@ -516,17 +516,20 @@ return hr; } - for (i = 0; pin->pFuncsTable->base.pin_get_media_type(&pin->pin, i, &candidate) == S_OK; ++i) + if (pin->pFuncsTable->base.pin_get_media_type) { - strmbase_dump_media_type(&candidate); - if (compare_media_types(mt, &candidate) - && pin->pFuncsTable->pfnAttemptConnection(pin, peer, &candidate) == S_OK) + for (i = 0; pin->pFuncsTable->base.pin_get_media_type(&pin->pin, i, &candidate) == S_OK; ++i) { - LeaveCriticalSection(&pin->pin.filter->csFilter); + strmbase_dump_media_type(&candidate); + if (compare_media_types(mt, &candidate) + && pin->pFuncsTable->pfnAttemptConnection(pin, peer, &candidate) == S_OK) + { + LeaveCriticalSection(&pin->pin.filter->csFilter); + FreeMediaType(&candidate); + return S_OK; + } FreeMediaType(&candidate); - return S_OK; } - FreeMediaType(&candidate); } if (SUCCEEDED(IPin_EnumMediaTypes(peer, &enummt))) diff -Nru wine-development-5.8/dlls/ucrtbase/tests/printf.c wine-development-5.9/dlls/ucrtbase/tests/printf.c --- wine-development-5.8/dlls/ucrtbase/tests/printf.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ucrtbase/tests/printf.c 2020-05-22 18:49:34.000000000 +0000 @@ -90,52 +90,55 @@ static void test_snprintf (void) { - const char *tests[] = {"short", "justfit", "justfits", "muchlonger"}; + const char *tests[] = {"short", "justfit", "justfits", "muchlonger", "", "1"}; char buffer[8]; - const int bufsiz = sizeof buffer; - unsigned int i; - - /* Legacy _snprintf style termination */ - for (i = 0; i < ARRAY_SIZE(tests); i++) { - const char *fmt = tests[i]; - const int expect = strlen(fmt) > bufsiz ? -1 : strlen(fmt); - const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, bufsiz, fmt); - const int valid = n < 0 ? bufsiz : (n == bufsiz ? n : n+1); - - ok (n == expect, "\"%s\": expected %d, returned %d\n", - fmt, expect, n); - ok (!memcmp (fmt, buffer, valid), - "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer); - } - - /* C99 snprintf style termination */ - for (i = 0; i < ARRAY_SIZE(tests); i++) { - const char *fmt = tests[i]; - const int expect = strlen(fmt); - const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, bufsiz, fmt); - const int valid = n >= bufsiz ? bufsiz - 1 : n < 0 ? 0 : n; + int bufsizes[] = { 0, 1, sizeof(buffer) }; + unsigned int i, j; - ok (n == expect, "\"%s\": expected %d, returned %d\n", - fmt, expect, n); - ok (!memcmp (fmt, buffer, valid), - "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer); - ok (buffer[valid] == '\0', - "\"%s\": Missing null termination (ret %d) - is %d\n", fmt, n, buffer[valid]); - } - - /* swprintf style termination */ - for (i = 0; i < ARRAY_SIZE(tests); i++) { - const char *fmt = tests[i]; - const int expect = strlen(fmt) >= bufsiz ? -2 : strlen(fmt); - const int n = vsprintf_wrapper (0, buffer, bufsiz, fmt); - const int valid = n < 0 ? bufsiz - 1 : n; - - ok (n == expect, "\"%s\": expected %d, returned %d\n", - fmt, expect, n); - ok (!memcmp (fmt, buffer, valid), - "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer); - ok (buffer[valid] == '\0', - "\"%s\": Missing null termination (ret %d) - is %d\n", fmt, n, buffer[valid]); + for (j = 0; j < ARRAY_SIZE(bufsizes); j++) { + const int bufsiz = bufsizes[j]; + /* Legacy _snprintf style termination */ + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const char *fmt = tests[i]; + const int expect = strlen(fmt) > bufsiz ? -1 : strlen(fmt); + const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, bufsiz, fmt); + const int valid = n < 0 ? bufsiz : (n == bufsiz ? n : n+1); + + ok (n == expect, "\"%s\": expected %d, returned %d\n", + fmt, expect, n); + ok (!memcmp (fmt, buffer, valid), + "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer); + } + + /* C99 snprintf style termination */ + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const char *fmt = tests[i]; + const int expect = strlen(fmt); + const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, bufsiz, fmt); + const int valid = n >= bufsiz ? (bufsiz > 0 ? bufsiz - 1 : 0) : n < 0 ? 0 : n; + + ok (n == expect, "\"%s\": expected %d, returned %d\n", + fmt, expect, n); + ok (!memcmp (fmt, buffer, valid), + "\"%s\": rendered \"%.*s\" bufsiz %d\n", fmt, valid, buffer, bufsiz); + ok (bufsiz == 0 || buffer[valid] == '\0', + "\"%s\": Missing null termination (ret %d) - is %d (bufsiz %d)\n", fmt, n, buffer[valid], bufsiz); + } + + /* swprintf style termination */ + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const char *fmt = tests[i]; + const int expect = strlen(fmt) >= bufsiz ? bufsiz > 0 ? -2 : -1 : strlen(fmt); + const int n = vsprintf_wrapper (0, buffer, bufsiz, fmt); + const int valid = n < 0 ? bufsiz > 0 ? bufsiz - 1 : 0 : n; + + ok (n == expect, "\"%s\": expected %d, returned %d\n", + fmt, expect, n); + ok (!memcmp (fmt, buffer, valid), + "\"%s\": rendered \"%.*s\" bufsiz %d\n", fmt, valid, buffer, bufsiz); + ok (bufsiz == 0 || buffer[valid] == '\0', + "\"%s\": Missing null termination (ret %d) - is %d\n", fmt, n, buffer[valid]); + } } ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, NULL, 0, "abcd") == 4, @@ -144,6 +147,18 @@ "Failure to snprintf to NULL\n"); ok (vsprintf_wrapper (0, NULL, 0, "abcd") == 4, "Failure to snprintf to NULL\n"); + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, "abcd") == 4, + "Failure to snprintf to zero length buffer\n"); + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, "abcd") == -1, + "Failure to snprintf to zero length buffer\n"); + ok (vsprintf_wrapper (0, buffer, 0, "abcd") == -1, + "Failure to snprintf to zero length buffer\n"); + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, "") == 0, + "Failure to snprintf a zero length string to a zero length buffer\n"); + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, "") == 0, + "Failure to snprintf a zero length string to a zero length buffer\n"); + ok (vsprintf_wrapper (0, buffer, 0, "") == -1, + "Failure to snprintf a zero length string to a zero length buffer\n"); } static int WINAPIV vswprintf_wrapper(unsigned __int64 options, wchar_t *str, @@ -163,6 +178,7 @@ const wchar_t str_justfit[] = {'j','u','s','t','f','i','t',0}; const wchar_t str_justfits[] = {'j','u','s','t','f','i','t','s',0}; const wchar_t str_muchlonger[] = {'m','u','c','h','l','o','n','g','e','r',0}; + const wchar_t str_empty[] = {0}; const wchar_t *tests[] = {str_short, str_justfit, str_justfits, str_muchlonger}; wchar_t buffer[8]; @@ -225,6 +241,18 @@ "Failure to swprintf to NULL\n"); ok (vswprintf_wrapper (0, NULL, 0, str_short) == 5, "Failure to swprintf to NULL\n"); + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, str_short) == 5, + "Failure to swprintf to a zero length buffer\n"); + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, str_short) == -1, + "Failure to swprintf to a zero length buffer\n"); + ok (vswprintf_wrapper (0, buffer, 0, str_short) == -1, + "Failure to swprintf to a zero length buffer\n"); + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, str_empty) == 0, + "Failure to swprintf a zero length string to a zero length buffer\n"); + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, str_empty) == 0, + "Failure to swprintf a zero length string to a zero length buffer\n"); + ok (vswprintf_wrapper (0, buffer, 0, str_empty) == -1, + "Failure to swprintf a zero length string to a zero length buffer\n"); } static int WINAPIV vfprintf_wrapper(FILE *file, diff -Nru wine-development-5.8/dlls/ucrtbase/ucrtbase.spec wine-development-5.9/dlls/ucrtbase/ucrtbase.spec --- wine-development-5.8/dlls/ucrtbase/ucrtbase.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ucrtbase/ucrtbase.spec 2020-05-22 18:49:34.000000000 +0000 @@ -156,7 +156,7 @@ @ cdecl __stdio_common_vfwscanf(int64 ptr wstr ptr ptr) MSVCRT__stdio_common_vfwscanf @ cdecl __stdio_common_vsnprintf_s(int64 ptr long long str ptr ptr) MSVCRT__stdio_common_vsnprintf_s @ cdecl __stdio_common_vsnwprintf_s(int64 ptr long long wstr ptr ptr) MSVCRT__stdio_common_vsnwprintf_s -@ cdecl -norelay __stdio_common_vsprintf(int64 ptr long str ptr ptr) +@ cdecl -norelay __stdio_common_vsprintf(int64 ptr long str ptr ptr) MSVCRT__stdio_common_vsprintf @ cdecl __stdio_common_vsprintf_p(int64 ptr long str ptr ptr) MSVCRT__stdio_common_vsprintf_p @ cdecl __stdio_common_vsprintf_s(int64 ptr long str ptr ptr) MSVCRT__stdio_common_vsprintf_s @ cdecl __stdio_common_vsscanf(int64 ptr long str ptr ptr) MSVCRT__stdio_common_vsscanf @@ -356,7 +356,7 @@ @ cdecl _futime64(long ptr) @ cdecl _fwrite_nolock(ptr long long ptr) MSVCRT__fwrite_nolock @ cdecl _gcvt(double long str) MSVCRT__gcvt -@ cdecl _gcvt_s(ptr long double long) MSVCRT__gcvt_s +@ cdecl _gcvt_s(ptr long double long) MSVCRT__gcvt_s @ cdecl -arch=win64 _get_FMA3_enable() MSVCRT__get_FMA3_enable @ cdecl _get_current_locale() MSVCRT__get_current_locale @ cdecl _get_daylight(ptr) @@ -730,313 +730,313 @@ @ cdecl _msize(ptr) @ cdecl _nextafter(double double) MSVCRT__nextafter @ cdecl -arch=x86_64 _nextafterf(float float) MSVCRT__nextafterf -@ stub _o__CIacos -@ stub _o__CIasin -@ stub _o__CIatan -@ stub _o__CIatan2 -@ stub _o__CIcos -@ stub _o__CIcosh -@ stub _o__CIexp -@ stub _o__CIfmod -@ stub _o__CIlog -@ stub _o__CIlog10 -@ stub _o__CIpow -@ stub _o__CIsin -@ stub _o__CIsinh -@ stub _o__CIsqrt -@ stub _o__CItan -@ stub _o__CItanh -@ stub _o__Getdays -@ stub _o__Getmonths -@ stub _o__Gettnames -@ stub _o__Strftime -@ stub _o__W_Getdays -@ stub _o__W_Getmonths -@ stub _o__W_Gettnames -@ stub _o__Wcsftime -@ stub _o____lc_codepage_func -@ stub _o____lc_collate_cp_func -@ stub _o____lc_locale_name_func -@ stub _o____mb_cur_max_func +@ cdecl -arch=i386 _o__CIacos() _CIacos +@ cdecl -arch=i386 _o__CIasin() _CIasin +@ cdecl -arch=i386 _o__CIatan() _CIatan +@ cdecl -arch=i386 _o__CIatan2() _CIatan2 +@ cdecl -arch=i386 _o__CIcos() _CIcos +@ cdecl -arch=i386 _o__CIcosh() _CIcosh +@ cdecl -arch=i386 _o__CIexp() _CIexp +@ cdecl -arch=i386 _o__CIfmod() _CIfmod +@ cdecl -arch=i386 _o__CIlog() _CIlog +@ cdecl -arch=i386 _o__CIlog10() _CIlog10 +@ cdecl -arch=i386 _o__CIpow() _CIpow +@ cdecl -arch=i386 _o__CIsin() _CIsin +@ cdecl -arch=i386 _o__CIsinh() _CIsinh +@ cdecl -arch=i386 _o__CIsqrt() _CIsqrt +@ cdecl -arch=i386 _o__CItan() _CItan +@ cdecl -arch=i386 _o__CItanh() _CItanh +@ cdecl _o__Getdays() _Getdays +@ cdecl _o__Getmonths() _Getmonths +@ cdecl _o__Gettnames() _Gettnames +@ cdecl _o__Strftime(ptr long str ptr ptr) _Strftime +@ cdecl _o__W_Getdays() _W_Getdays +@ cdecl _o__W_Getmonths() _W_Getmonths +@ cdecl _o__W_Gettnames() _W_Gettnames +@ cdecl _o__Wcsftime(ptr long wstr ptr ptr) _Wcsftime +@ cdecl _o____lc_codepage_func() ___lc_codepage_func +@ cdecl _o____lc_collate_cp_func() ___lc_collate_cp_func +@ cdecl _o____lc_locale_name_func() ___lc_locale_name_func +@ cdecl _o____mb_cur_max_func() MSVCRT____mb_cur_max_func @ cdecl _o___acrt_iob_func(long) MSVCRT___acrt_iob_func -@ stub _o___conio_common_vcprintf +@ cdecl _o___conio_common_vcprintf(int64 str ptr ptr) MSVCRT__conio_common_vcprintf @ stub _o___conio_common_vcprintf_p @ stub _o___conio_common_vcprintf_s @ stub _o___conio_common_vcscanf -@ stub _o___conio_common_vcwprintf +@ cdecl _o___conio_common_vcwprintf(int64 wstr ptr ptr) MSVCRT__conio_common_vcwprintf @ stub _o___conio_common_vcwprintf_p @ stub _o___conio_common_vcwprintf_s @ stub _o___conio_common_vcwscanf -@ stub _o___daylight -@ stub _o___dstbias -@ stub _o___fpe_flt_rounds -@ stub _o___libm_sse2_acos -@ stub _o___libm_sse2_acosf -@ stub _o___libm_sse2_asin -@ stub _o___libm_sse2_asinf -@ stub _o___libm_sse2_atan -@ stub _o___libm_sse2_atan2 -@ stub _o___libm_sse2_atanf -@ stub _o___libm_sse2_cos -@ stub _o___libm_sse2_cosf -@ stub _o___libm_sse2_exp -@ stub _o___libm_sse2_expf -@ stub _o___libm_sse2_log -@ stub _o___libm_sse2_log10 -@ stub _o___libm_sse2_log10f -@ stub _o___libm_sse2_logf -@ stub _o___libm_sse2_pow -@ stub _o___libm_sse2_powf -@ stub _o___libm_sse2_sin -@ stub _o___libm_sse2_sinf -@ stub _o___libm_sse2_tan -@ stub _o___libm_sse2_tanf +@ cdecl _o___daylight() MSVCRT___p__daylight +@ cdecl _o___dstbias() MSVCRT___p__dstbias +@ cdecl _o___fpe_flt_rounds() __fpe_flt_rounds +@ cdecl -arch=i386 -norelay _o___libm_sse2_acos() MSVCRT___libm_sse2_acos +@ cdecl -arch=i386 -norelay _o___libm_sse2_acosf() MSVCRT___libm_sse2_acosf +@ cdecl -arch=i386 -norelay _o___libm_sse2_asin() MSVCRT___libm_sse2_asin +@ cdecl -arch=i386 -norelay _o___libm_sse2_asinf() MSVCRT___libm_sse2_asinf +@ cdecl -arch=i386 -norelay _o___libm_sse2_atan() MSVCRT___libm_sse2_atan +@ cdecl -arch=i386 -norelay _o___libm_sse2_atan2() MSVCRT___libm_sse2_atan2 +@ cdecl -arch=i386 -norelay _o___libm_sse2_atanf() MSVCRT___libm_sse2_atanf +@ cdecl -arch=i386 -norelay _o___libm_sse2_cos() MSVCRT___libm_sse2_cos +@ cdecl -arch=i386 -norelay _o___libm_sse2_cosf() MSVCRT___libm_sse2_cosf +@ cdecl -arch=i386 -norelay _o___libm_sse2_exp() MSVCRT___libm_sse2_exp +@ cdecl -arch=i386 -norelay _o___libm_sse2_expf() MSVCRT___libm_sse2_expf +@ cdecl -arch=i386 -norelay _o___libm_sse2_log() MSVCRT___libm_sse2_log +@ cdecl -arch=i386 -norelay _o___libm_sse2_log10() MSVCRT___libm_sse2_log10 +@ cdecl -arch=i386 -norelay _o___libm_sse2_log10f() MSVCRT___libm_sse2_log10f +@ cdecl -arch=i386 -norelay _o___libm_sse2_logf() MSVCRT___libm_sse2_logf +@ cdecl -arch=i386 -norelay _o___libm_sse2_pow() MSVCRT___libm_sse2_pow +@ cdecl -arch=i386 -norelay _o___libm_sse2_powf() MSVCRT___libm_sse2_powf +@ cdecl -arch=i386 -norelay _o___libm_sse2_sin() MSVCRT___libm_sse2_sin +@ cdecl -arch=i386 -norelay _o___libm_sse2_sinf() MSVCRT___libm_sse2_sinf +@ cdecl -arch=i386 -norelay _o___libm_sse2_tan() MSVCRT___libm_sse2_tan +@ cdecl -arch=i386 -norelay _o___libm_sse2_tanf() MSVCRT___libm_sse2_tanf @ cdecl _o___p___argc() MSVCRT___p___argc -@ stub _o___p___argv +@ cdecl _o___p___argv() MSVCRT___p___argv @ cdecl _o___p___wargv() MSVCRT___p___wargv -@ stub _o___p__acmdln +@ cdecl _o___p__acmdln() MSVCRT___p__acmdln @ cdecl _o___p__commode() __p__commode -@ stub _o___p__environ -@ stub _o___p__fmode +@ cdecl _o___p__environ() MSVCRT___p__environ +@ cdecl _o___p__fmode() MSVCRT___p__fmode @ stub _o___p__mbcasemap -@ stub _o___p__mbctype -@ stub _o___p__pgmptr -@ stub _o___p__wcmdln -@ stub _o___p__wenviron -@ stub _o___p__wpgmptr -@ stub _o___pctype_func +@ cdecl _o___p__mbctype() __p__mbctype +@ cdecl _o___p__pgmptr() MSVCRT___p__pgmptr +@ cdecl _o___p__wcmdln() MSVCRT___p__wcmdln +@ cdecl _o___p__wenviron() MSVCRT___p__wenviron +@ cdecl _o___p__wpgmptr() MSVCRT___p__wpgmptr +@ cdecl _o___pctype_func() MSVCRT___pctype_func @ stub _o___pwctype_func -@ stub _o___std_exception_copy +@ cdecl _o___std_exception_copy(ptr ptr) MSVCRT___std_exception_copy @ cdecl _o___std_exception_destroy(ptr) MSVCRT___std_exception_destroy @ cdecl _o___std_type_info_destroy_list(ptr) MSVCRT_type_info_destroy_list -@ stub _o___std_type_info_name +@ cdecl _o___std_type_info_name(ptr ptr) MSVCRT_type_info_name_list @ cdecl _o___stdio_common_vfprintf(int64 ptr str ptr ptr) MSVCRT__stdio_common_vfprintf @ stub _o___stdio_common_vfprintf_p -@ stub _o___stdio_common_vfprintf_s -@ stub _o___stdio_common_vfscanf +@ cdecl _o___stdio_common_vfprintf_s(int64 ptr str ptr ptr) MSVCRT__stdio_common_vfprintf_s +@ cdecl _o___stdio_common_vfscanf(int64 ptr str ptr ptr) MSVCRT__stdio_common_vfscanf @ cdecl _o___stdio_common_vfwprintf(int64 ptr wstr ptr ptr) MSVCRT__stdio_common_vfwprintf @ stub _o___stdio_common_vfwprintf_p -@ stub _o___stdio_common_vfwprintf_s -@ stub _o___stdio_common_vfwscanf +@ cdecl _o___stdio_common_vfwprintf_s(int64 ptr wstr ptr ptr) MSVCRT__stdio_common_vfwprintf_s +@ cdecl _o___stdio_common_vfwscanf(int64 ptr wstr ptr ptr) MSVCRT__stdio_common_vfwscanf @ cdecl _o___stdio_common_vsnprintf_s(int64 ptr long long str ptr ptr) MSVCRT__stdio_common_vsnprintf_s -@ stub _o___stdio_common_vsnwprintf_s -@ cdecl _o___stdio_common_vsprintf(int64 ptr long str ptr ptr) __stdio_common_vsprintf -@ stub _o___stdio_common_vsprintf_p +@ cdecl _o___stdio_common_vsnwprintf_s(int64 ptr long long wstr ptr ptr) MSVCRT__stdio_common_vsnwprintf_s +@ cdecl _o___stdio_common_vsprintf(int64 ptr long str ptr ptr) MSVCRT__stdio_common_vsprintf +@ cdecl _o___stdio_common_vsprintf_p(int64 ptr long str ptr ptr) MSVCRT__stdio_common_vsprintf_p @ cdecl _o___stdio_common_vsprintf_s(int64 ptr long str ptr ptr) MSVCRT__stdio_common_vsprintf_s -@ stub _o___stdio_common_vsscanf +@ cdecl _o___stdio_common_vsscanf(int64 ptr long str ptr ptr) MSVCRT__stdio_common_vsscanf @ cdecl _o___stdio_common_vswprintf(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswprintf -@ stub _o___stdio_common_vswprintf_p -@ stub _o___stdio_common_vswprintf_s -@ stub _o___stdio_common_vswscanf -@ stub _o___timezone -@ stub _o___tzname -@ stub _o___wcserror -@ stub _o__access -@ stub _o__access_s -@ stub _o__aligned_free -@ stub _o__aligned_malloc -@ stub _o__aligned_msize -@ stub _o__aligned_offset_malloc -@ stub _o__aligned_offset_realloc +@ cdecl _o___stdio_common_vswprintf_p(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswprintf_p +@ cdecl _o___stdio_common_vswprintf_s(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswprintf_s +@ cdecl _o___stdio_common_vswscanf(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswscanf +@ cdecl _o___timezone() MSVCRT___p__timezone +@ cdecl _o___tzname() __p__tzname +@ cdecl _o___wcserror(wstr) MSVCRT___wcserror +@ cdecl _o__access(str long) MSVCRT__access +@ cdecl _o__access_s(str long) MSVCRT__access_s +@ cdecl _o__aligned_free(ptr) _aligned_free +@ cdecl _o__aligned_malloc(long long) _aligned_malloc +@ cdecl _o__aligned_msize(ptr long long) _aligned_msize +@ cdecl _o__aligned_offset_malloc(long long long) _aligned_offset_malloc +@ cdecl _o__aligned_offset_realloc(ptr long long long) _aligned_offset_realloc @ stub _o__aligned_offset_recalloc -@ stub _o__aligned_realloc +@ cdecl _o__aligned_realloc(ptr long long) _aligned_realloc @ stub _o__aligned_recalloc -@ stub _o__atodbl -@ stub _o__atodbl_l -@ stub _o__atof_l -@ stub _o__atoflt -@ stub _o__atoflt_l -@ stub _o__atoi64 -@ stub _o__atoi64_l -@ stub _o__atoi_l -@ stub _o__atol_l -@ stub _o__atoldbl +@ cdecl _o__atodbl(ptr str) MSVCRT__atodbl +@ cdecl _o__atodbl_l(ptr str ptr) MSVCRT__atodbl_l +@ cdecl _o__atof_l(str ptr) MSVCRT__atof_l +@ cdecl _o__atoflt(ptr str) MSVCRT__atoflt +@ cdecl _o__atoflt_l(ptr str ptr) MSVCRT__atoflt_l +@ cdecl -ret64 _o__atoi64(str) MSVCRT__atoi64 +@ cdecl -ret64 _o__atoi64_l(str ptr) MSVCRT__atoi64_l +@ cdecl _o__atoi_l(str ptr) MSVCRT__atoi_l +@ cdecl _o__atol_l(str ptr) MSVCRT__atol_l +@ cdecl _o__atoldbl(ptr str) MSVCRT__atoldbl @ stub _o__atoldbl_l -@ stub _o__atoll_l -@ stub _o__beep -@ stub _o__beginthread -@ stub _o__beginthreadex -@ stub _o__cabs -@ stub _o__callnewh -@ stub _o__calloc_base -@ stub _o__cexit -@ stub _o__cgets +@ cdecl -ret64 _o__atoll_l(str ptr) MSVCRT__atoll_l +@ cdecl _o__beep(long long) MSVCRT__beep +@ cdecl _o__beginthread(ptr long ptr) _beginthread +@ cdecl _o__beginthreadex(ptr long ptr ptr long ptr) _beginthreadex +@ cdecl _o__cabs(long) MSVCRT__cabs +@ cdecl _o__callnewh(long) _callnewh +@ cdecl _o__calloc_base(long long) _calloc_base +@ cdecl _o__cexit() MSVCRT__cexit +@ cdecl _o__cgets(ptr) _cgets @ stub _o__cgets_s @ stub _o__cgetws @ stub _o__cgetws_s -@ stub _o__chdir -@ stub _o__chdrive -@ stub _o__chmod -@ stub _o__chsize -@ stub _o__chsize_s -@ stub _o__close -@ stub _o__commit +@ cdecl _o__chdir(str) MSVCRT__chdir +@ cdecl _o__chdrive(long) MSVCRT__chdrive +@ cdecl _o__chmod(str long) MSVCRT__chmod +@ cdecl _o__chsize(long long) MSVCRT__chsize +@ cdecl _o__chsize_s(long int64) MSVCRT__chsize_s +@ cdecl _o__close(long) MSVCRT__close +@ cdecl _o__commit(long) MSVCRT__commit @ cdecl _o__configthreadlocale(long) _configthreadlocale -@ stub _o__configure_narrow_argv +@ cdecl _o__configure_narrow_argv(long) _configure_narrow_argv @ cdecl _o__configure_wide_argv(long) _configure_wide_argv @ cdecl _o__controlfp_s(ptr long long) _controlfp_s -@ stub _o__cputs -@ stub _o__cputws -@ stub _o__creat -@ stub _o__create_locale +@ cdecl _o__cputs(str) _cputs +@ cdecl _o__cputws(wstr) _cputws +@ cdecl _o__creat(str long) MSVCRT__creat +@ cdecl _o__create_locale(long str) MSVCRT__create_locale @ cdecl _o__crt_atexit(ptr) MSVCRT__crt_atexit -@ stub _o__ctime32_s -@ stub _o__ctime64_s -@ stub _o__cwait +@ cdecl _o__ctime32_s(str long ptr) MSVCRT__ctime32_s +@ cdecl _o__ctime64_s(str long ptr) MSVCRT__ctime64_s +@ cdecl _o__cwait(ptr long long) _cwait @ stub _o__d_int -@ stub _o__dclass -@ stub _o__difftime32 -@ stub _o__difftime64 +@ cdecl _o__dclass(double) MSVCR120__dclass +@ cdecl _o__difftime32(long long) MSVCRT__difftime32 +@ cdecl _o__difftime64(int64 int64) MSVCRT__difftime64 @ stub _o__dlog @ stub _o__dnorm -@ stub _o__dpcomp +@ cdecl _o__dpcomp(double double) MSVCR120__dpcomp @ stub _o__dpoly @ stub _o__dscale -@ stub _o__dsign +@ cdecl _o__dsign(double) MSVCR120__dsign @ stub _o__dsin -@ stub _o__dtest +@ cdecl _o__dtest(ptr) MSVCR120__dtest @ stub _o__dunscale -@ stub _o__dup -@ stub _o__dup2 -@ stub _o__dupenv_s -@ stub _o__ecvt -@ stub _o__ecvt_s -@ stub _o__endthread -@ stub _o__endthreadex -@ stub _o__eof +@ cdecl _o__dup(long) MSVCRT__dup +@ cdecl _o__dup2(long long) MSVCRT__dup2 +@ cdecl _o__dupenv_s(ptr ptr str) _dupenv_s +@ cdecl _o__ecvt(double long ptr ptr) MSVCRT__ecvt +@ cdecl _o__ecvt_s(str long double long ptr ptr) MSVCRT__ecvt_s +@ cdecl _o__endthread() _endthread +@ cdecl _o__endthreadex(long) _endthreadex +@ cdecl _o__eof(long) MSVCRT__eof @ cdecl _o__errno() MSVCRT__errno -@ stub _o__except1 +@ cdecl _o__except1(long long double double long ptr) _except1 @ cdecl _o__execute_onexit_table(ptr) MSVCRT__execute_onexit_table -@ stub _o__execv -@ stub _o__execve -@ stub _o__execvp -@ stub _o__execvpe -@ stub _o__exit -@ stub _o__expand -@ stub _o__fclose_nolock -@ stub _o__fcloseall -@ stub _o__fcvt -@ stub _o__fcvt_s +@ cdecl _o__execv(str ptr) _execv +@ cdecl _o__execve(str ptr ptr) MSVCRT__execve +@ cdecl _o__execvp(str ptr) _execvp +@ cdecl _o__execvpe(str ptr ptr) _execvpe +@ cdecl _o__exit(long) MSVCRT__exit +@ cdecl _o__expand(ptr long) _expand +@ cdecl _o__fclose_nolock(ptr) MSVCRT__fclose_nolock +@ cdecl _o__fcloseall() MSVCRT__fcloseall +@ cdecl _o__fcvt(double long ptr ptr) MSVCRT__fcvt +@ cdecl _o__fcvt_s(ptr long double long ptr ptr) MSVCRT__fcvt_s @ stub _o__fd_int -@ stub _o__fdclass +@ cdecl _o__fdclass(float) MSVCR120__fdclass @ stub _o__fdexp @ stub _o__fdlog -@ stub _o__fdopen -@ stub _o__fdpcomp +@ cdecl _o__fdopen(long str) MSVCRT__fdopen +@ cdecl _o__fdpcomp(float float) MSVCR120__fdpcomp @ stub _o__fdpoly @ stub _o__fdscale -@ stub _o__fdsign +@ cdecl _o__fdsign(float) MSVCR120__fdsign @ stub _o__fdsin -@ stub _o__fflush_nolock -@ stub _o__fgetc_nolock -@ stub _o__fgetchar -@ stub _o__fgetwc_nolock -@ stub _o__fgetwchar -@ stub _o__filelength -@ stub _o__filelengthi64 -@ stub _o__fileno -@ stub _o__findclose -@ stub _o__findfirst32 +@ cdecl _o__fflush_nolock(ptr) MSVCRT__fflush_nolock +@ cdecl _o__fgetc_nolock(ptr) MSVCRT__fgetc_nolock +@ cdecl _o__fgetchar() MSVCRT__fgetchar +@ cdecl _o__fgetwc_nolock(ptr) MSVCRT__fgetwc_nolock +@ cdecl _o__fgetwchar() MSVCRT__fgetwchar +@ cdecl _o__filelength(long) MSVCRT__filelength +@ cdecl -ret64 _o__filelengthi64(long) MSVCRT__filelengthi64 +@ cdecl _o__fileno(ptr) MSVCRT__fileno +@ cdecl _o__findclose(long) MSVCRT__findclose +@ cdecl _o__findfirst32(str ptr) MSVCRT__findfirst32 @ stub _o__findfirst32i64 -@ stub _o__findfirst64 -@ stub _o__findfirst64i32 -@ stub _o__findnext32 +@ cdecl _o__findfirst64(str ptr) MSVCRT__findfirst64 +@ cdecl _o__findfirst64i32(str ptr) MSVCRT__findfirst64i32 +@ cdecl _o__findnext32(long ptr) MSVCRT__findnext32 @ stub _o__findnext32i64 -@ stub _o__findnext64 -@ stub _o__findnext64i32 -@ stub _o__flushall +@ cdecl _o__findnext64(long ptr) MSVCRT__findnext64 +@ cdecl _o__findnext64i32(long ptr) MSVCRT__findnext64i32 +@ cdecl _o__flushall() MSVCRT__flushall @ cdecl _o__fpclass(double) MSVCRT__fpclass @ stub _o__fpclassf -@ stub _o__fputc_nolock -@ stub _o__fputchar -@ stub _o__fputwc_nolock -@ stub _o__fputwchar -@ stub _o__fread_nolock -@ stub _o__fread_nolock_s -@ stub _o__free_base -@ stub _o__free_locale -@ stub _o__fseek_nolock -@ stub _o__fseeki64 -@ stub _o__fseeki64_nolock -@ stub _o__fsopen -@ stub _o__fstat32 -@ stub _o__fstat32i64 -@ stub _o__fstat64 -@ stub _o__fstat64i32 -@ stub _o__ftell_nolock -@ stub _o__ftelli64 -@ stub _o__ftelli64_nolock -@ stub _o__ftime32 -@ stub _o__ftime32_s -@ stub _o__ftime64 -@ stub _o__ftime64_s -@ stub _o__fullpath -@ stub _o__futime32 -@ stub _o__futime64 -@ stub _o__fwrite_nolock -@ stub _o__gcvt -@ stub _o__gcvt_s -@ stub _o__get_daylight -@ stub _o__get_doserrno -@ stub _o__get_dstbias -@ stub _o__get_errno -@ stub _o__get_fmode -@ stub _o__get_heap_handle -@ stub _o__get_initial_narrow_environment +@ cdecl _o__fputc_nolock(long ptr) MSVCRT__fputc_nolock +@ cdecl _o__fputchar(long) MSVCRT__fputchar +@ cdecl _o__fputwc_nolock(long ptr) MSVCRT__fputwc_nolock +@ cdecl _o__fputwchar(long) MSVCRT__fputwchar +@ cdecl _o__fread_nolock(ptr long long ptr) MSVCRT__fread_nolock +@ cdecl _o__fread_nolock_s(ptr long long long ptr) MSVCRT__fread_nolock_s +@ cdecl _o__free_base(ptr) _free_base +@ cdecl _o__free_locale(ptr) MSVCRT__free_locale +@ cdecl _o__fseek_nolock(ptr long long) MSVCRT__fseek_nolock +@ cdecl _o__fseeki64(ptr int64 long) MSVCRT__fseeki64 +@ cdecl _o__fseeki64_nolock(ptr int64 long) MSVCRT__fseeki64_nolock +@ cdecl _o__fsopen(str str long) MSVCRT__fsopen +@ cdecl _o__fstat32(long ptr) MSVCRT__fstat32 +@ cdecl _o__fstat32i64(long ptr) MSVCRT__fstat32i64 +@ cdecl _o__fstat64(long ptr) MSVCRT__fstat64 +@ cdecl _o__fstat64i32(long ptr) MSVCRT__fstat64i32 +@ cdecl _o__ftell_nolock(ptr) MSVCRT__ftell_nolock +@ cdecl -ret64 _o__ftelli64(ptr) MSVCRT__ftelli64 +@ cdecl -ret64 _o__ftelli64_nolock(ptr) MSVCRT__ftelli64_nolock +@ cdecl _o__ftime32(ptr) MSVCRT__ftime32 +@ cdecl _o__ftime32_s(ptr) MSVCRT__ftime32_s +@ cdecl _o__ftime64(ptr) MSVCRT__ftime64 +@ cdecl _o__ftime64_s(ptr) MSVCRT__ftime64_s +@ cdecl _o__fullpath(ptr str long) MSVCRT__fullpath +@ cdecl _o__futime32(long ptr) _futime32 +@ cdecl _o__futime64(long ptr) _futime64 +@ cdecl _o__fwrite_nolock(ptr long long ptr) MSVCRT__fwrite_nolock +@ cdecl _o__gcvt(double long str) MSVCRT__gcvt +@ cdecl _o__gcvt_s(ptr long double long) MSVCRT__gcvt_s +@ cdecl _o__get_daylight(ptr) _get_daylight +@ cdecl _o__get_doserrno(ptr) _get_doserrno +@ cdecl _o__get_dstbias(ptr) MSVCRT__get_dstbias +@ cdecl _o__get_errno(ptr) _get_errno +@ cdecl _o__get_fmode(ptr) MSVCRT__get_fmode +@ cdecl _o__get_heap_handle() _get_heap_handle +@ cdecl _o__get_initial_narrow_environment() _get_initial_narrow_environment @ cdecl _o__get_initial_wide_environment() _get_initial_wide_environment -@ stub _o__get_invalid_parameter_handler -@ stub _o__get_narrow_winmain_command_line -@ stub _o__get_osfhandle -@ stub _o__get_pgmptr -@ stub _o__get_stream_buffer_pointers -@ stub _o__get_terminate -@ stub _o__get_thread_local_invalid_parameter_handler -@ stub _o__get_timezone -@ stub _o__get_tzname -@ stub _o__get_wide_winmain_command_line -@ stub _o__get_wpgmptr -@ stub _o__getc_nolock -@ stub _o__getch -@ stub _o__getch_nolock -@ stub _o__getche -@ stub _o__getche_nolock -@ stub _o__getcwd -@ stub _o__getdcwd -@ stub _o__getdiskfree -@ stub _o__getdllprocaddr -@ stub _o__getdrive -@ stub _o__getdrives -@ stub _o__getmbcp +@ cdecl _o__get_invalid_parameter_handler() _get_invalid_parameter_handler +@ cdecl _o__get_narrow_winmain_command_line() _get_narrow_winmain_command_line +@ cdecl _o__get_osfhandle(long) MSVCRT__get_osfhandle +@ cdecl _o__get_pgmptr(ptr) _get_pgmptr +@ cdecl _o__get_stream_buffer_pointers(ptr ptr ptr ptr) MSVCRT__get_stream_buffer_pointers +@ cdecl _o__get_terminate() MSVCRT__get_terminate +@ cdecl _o__get_thread_local_invalid_parameter_handler() _get_thread_local_invalid_parameter_handler +@ cdecl _o__get_timezone(ptr) _get_timezone +@ cdecl _o__get_tzname(ptr str long long) MSVCRT__get_tzname +@ cdecl _o__get_wide_winmain_command_line() _get_wide_winmain_command_line +@ cdecl _o__get_wpgmptr(ptr) _get_wpgmptr +@ cdecl _o__getc_nolock(ptr) MSVCRT__fgetc_nolock +@ cdecl _o__getch() _getch +@ cdecl _o__getch_nolock() _getch_nolock +@ cdecl _o__getche() _getche +@ cdecl _o__getche_nolock() _getche_nolock +@ cdecl _o__getcwd(str long) MSVCRT__getcwd +@ cdecl _o__getdcwd(long str long) MSVCRT__getdcwd +@ cdecl _o__getdiskfree(long ptr) MSVCRT__getdiskfree +@ cdecl _o__getdllprocaddr(long str long) _getdllprocaddr +@ cdecl _o__getdrive() MSVCRT__getdrive +@ cdecl _o__getdrives() kernel32.GetLogicalDrives +@ cdecl _o__getmbcp() _getmbcp @ stub _o__getsystime -@ stub _o__getw -@ stub _o__getwc_nolock -@ stub _o__getwch -@ stub _o__getwch_nolock -@ stub _o__getwche -@ stub _o__getwche_nolock -@ stub _o__getws +@ cdecl _o__getw(ptr) MSVCRT__getw +@ cdecl _o__getwc_nolock(ptr) MSVCRT__fgetwc_nolock +@ cdecl _o__getwch() _getwch +@ cdecl _o__getwch_nolock() _getwch_nolock +@ cdecl _o__getwche() _getwche +@ cdecl _o__getwche_nolock() _getwche_nolock +@ cdecl _o__getws(ptr) MSVCRT__getws @ stub _o__getws_s -@ stub _o__gmtime32 -@ stub _o__gmtime32_s -@ stub _o__gmtime64 -@ stub _o__gmtime64_s -@ stub _o__heapchk -@ stub _o__heapmin -@ stub _o__hypot -@ stub _o__hypotf -@ stub _o__i64toa -@ stub _o__i64toa_s -@ stub _o__i64tow -@ stub _o__i64tow_s -@ stub _o__initialize_narrow_environment +@ cdecl _o__gmtime32(ptr) MSVCRT__gmtime32 +@ cdecl _o__gmtime32_s(ptr ptr) MSVCRT__gmtime32_s +@ cdecl _o__gmtime64(ptr) MSVCRT__gmtime64 +@ cdecl _o__gmtime64_s(ptr ptr) MSVCRT__gmtime64_s +@ cdecl _o__heapchk() _heapchk +@ cdecl _o__heapmin() _heapmin +@ cdecl _o__hypot(double double) _hypot +@ cdecl _o__hypotf(float float) MSVCRT__hypotf +@ cdecl _o__i64toa(int64 ptr long) ntdll._i64toa +@ cdecl _o__i64toa_s(int64 ptr long long) MSVCRT__i64toa_s +@ cdecl _o__i64tow(int64 ptr long) ntdll._i64tow +@ cdecl _o__i64tow_s(int64 ptr long long) MSVCRT__i64tow_s +@ cdecl _o__initialize_narrow_environment() _initialize_narrow_environment @ cdecl _o__initialize_onexit_table(ptr) MSVCRT__initialize_onexit_table @ cdecl _o__initialize_wide_environment() _initialize_wide_environment -@ stub _o__invalid_parameter_noinfo -@ stub _o__invalid_parameter_noinfo_noreturn -@ stub _o__isatty -@ stub _o__isctype -@ stub _o__isctype_l -@ stub _o__isleadbyte_l +@ cdecl _o__invalid_parameter_noinfo() _invalid_parameter_noinfo +@ cdecl _o__invalid_parameter_noinfo_noreturn() _invalid_parameter_noinfo_noreturn +@ cdecl _o__isatty(long) MSVCRT__isatty +@ cdecl _o__isctype(long long) MSVCRT__isctype +@ cdecl _o__isctype_l(long long ptr) MSVCRT__isctype_l +@ cdecl _o__isleadbyte_l(long ptr) MSVCRT__isleadbyte_l @ stub _o__ismbbalnum @ stub _o__ismbbalnum_l @ stub _o__ismbbalpha @@ -1047,798 +1047,798 @@ @ stub _o__ismbbgraph_l @ stub _o__ismbbkalnum @ stub _o__ismbbkalnum_l -@ stub _o__ismbbkana +@ cdecl _o__ismbbkana(long) _ismbbkana @ stub _o__ismbbkana_l @ stub _o__ismbbkprint @ stub _o__ismbbkprint_l @ stub _o__ismbbkpunct @ stub _o__ismbbkpunct_l -@ stub _o__ismbblead -@ stub _o__ismbblead_l +@ cdecl _o__ismbblead(long) _ismbblead +@ cdecl _o__ismbblead_l(long ptr) _ismbblead_l @ stub _o__ismbbprint @ stub _o__ismbbprint_l @ stub _o__ismbbpunct @ stub _o__ismbbpunct_l -@ stub _o__ismbbtrail -@ stub _o__ismbbtrail_l -@ stub _o__ismbcalnum +@ cdecl _o__ismbbtrail(long) _ismbbtrail +@ cdecl _o__ismbbtrail_l(long ptr) _ismbbtrail_l +@ cdecl _o__ismbcalnum(long) _ismbcalnum @ stub _o__ismbcalnum_l -@ stub _o__ismbcalpha +@ cdecl _o__ismbcalpha(long) _ismbcalpha @ stub _o__ismbcalpha_l @ stub _o__ismbcblank @ stub _o__ismbcblank_l -@ stub _o__ismbcdigit +@ cdecl _o__ismbcdigit(long) _ismbcdigit @ stub _o__ismbcdigit_l -@ stub _o__ismbcgraph +@ cdecl _o__ismbcgraph(long) _ismbcgraph @ stub _o__ismbcgraph_l -@ stub _o__ismbchira +@ cdecl _o__ismbchira(long) _ismbchira @ stub _o__ismbchira_l -@ stub _o__ismbckata +@ cdecl _o__ismbckata(long) _ismbckata @ stub _o__ismbckata_l -@ stub _o__ismbcl0 -@ stub _o__ismbcl0_l -@ stub _o__ismbcl1 -@ stub _o__ismbcl1_l -@ stub _o__ismbcl2 -@ stub _o__ismbcl2_l -@ stub _o__ismbclegal -@ stub _o__ismbclegal_l +@ cdecl _o__ismbcl0(long) _ismbcl0 +@ cdecl _o__ismbcl0_l(long ptr) _ismbcl0_l +@ cdecl _o__ismbcl1(long) _ismbcl1 +@ cdecl _o__ismbcl1_l(long ptr) _ismbcl1_l +@ cdecl _o__ismbcl2(long) _ismbcl2 +@ cdecl _o__ismbcl2_l(long ptr) _ismbcl2_l +@ cdecl _o__ismbclegal(long) _ismbclegal +@ cdecl _o__ismbclegal_l(long ptr) _ismbclegal_l @ stub _o__ismbclower @ stub _o__ismbclower_l -@ stub _o__ismbcprint +@ cdecl _o__ismbcprint(long) _ismbcprint @ stub _o__ismbcprint_l -@ stub _o__ismbcpunct +@ cdecl _o__ismbcpunct(long) _ismbcpunct @ stub _o__ismbcpunct_l -@ stub _o__ismbcspace +@ cdecl _o__ismbcspace(long) _ismbcspace @ stub _o__ismbcspace_l -@ stub _o__ismbcsymbol +@ cdecl _o__ismbcsymbol(long) _ismbcsymbol @ stub _o__ismbcsymbol_l -@ stub _o__ismbcupper +@ cdecl _o__ismbcupper(long) _ismbcupper @ stub _o__ismbcupper_l -@ stub _o__ismbslead +@ cdecl _o__ismbslead(ptr ptr) _ismbslead @ stub _o__ismbslead_l -@ stub _o__ismbstrail +@ cdecl _o__ismbstrail(ptr ptr) _ismbstrail @ stub _o__ismbstrail_l -@ stub _o__iswctype_l -@ stub _o__itoa -@ stub _o__itoa_s -@ stub _o__itow -@ stub _o__itow_s -@ stub _o__j0 -@ stub _o__j1 -@ stub _o__jn -@ stub _o__kbhit +@ cdecl _o__iswctype_l(long long ptr) MSVCRT__iswctype_l +@ cdecl _o__itoa(long ptr long) MSVCRT__itoa +@ cdecl _o__itoa_s(long ptr long long) MSVCRT__itoa_s +@ cdecl _o__itow(long ptr long) ntdll._itow +@ cdecl _o__itow_s(long ptr long long) MSVCRT__itow_s +@ cdecl _o__j0(double) MSVCRT__j0 +@ cdecl _o__j1(double) MSVCRT__j1 +@ cdecl _o__jn(long double) MSVCRT__jn +@ cdecl _o__kbhit() _kbhit @ stub _o__ld_int -@ stub _o__ldclass +@ cdecl _o__ldclass(double) MSVCR120__ldclass @ stub _o__ldexp @ stub _o__ldlog -@ stub _o__ldpcomp +@ cdecl _o__ldpcomp(double double) MSVCR120__dpcomp @ stub _o__ldpoly @ stub _o__ldscale -@ stub _o__ldsign +@ cdecl _o__ldsign(double) MSVCR120__dsign @ stub _o__ldsin -@ stub _o__ldtest +@ cdecl _o__ldtest(ptr) MSVCR120__ldtest @ stub _o__ldunscale -@ stub _o__lfind -@ stub _o__lfind_s -@ stub _o__libm_sse2_acos_precise -@ stub _o__libm_sse2_asin_precise -@ stub _o__libm_sse2_atan_precise -@ stub _o__libm_sse2_cos_precise -@ stub _o__libm_sse2_exp_precise -@ stub _o__libm_sse2_log10_precise -@ stub _o__libm_sse2_log_precise -@ stub _o__libm_sse2_pow_precise -@ stub _o__libm_sse2_sin_precise -@ stub _o__libm_sse2_sqrt_precise -@ stub _o__libm_sse2_tan_precise -@ stub _o__loaddll -@ stub _o__localtime32 -@ stub _o__localtime32_s -@ stub _o__localtime64 -@ stub _o__localtime64_s -@ stub _o__lock_file -@ stub _o__locking -@ stub _o__logb -@ stub _o__logbf -@ stub _o__lsearch +@ cdecl _o__lfind(ptr ptr ptr long ptr) _lfind +@ cdecl _o__lfind_s(ptr ptr ptr long ptr ptr) _lfind_s +@ cdecl -arch=i386 -norelay _o__libm_sse2_acos_precise() MSVCRT___libm_sse2_acos +@ cdecl -arch=i386 -norelay _o__libm_sse2_asin_precise() MSVCRT___libm_sse2_asin +@ cdecl -arch=i386 -norelay _o__libm_sse2_atan_precise() MSVCRT___libm_sse2_atan +@ cdecl -arch=i386 -norelay _o__libm_sse2_cos_precise() MSVCRT___libm_sse2_cos +@ cdecl -arch=i386 -norelay _o__libm_sse2_exp_precise() MSVCRT___libm_sse2_exp +@ cdecl -arch=i386 -norelay _o__libm_sse2_log10_precise() MSVCRT___libm_sse2_log10 +@ cdecl -arch=i386 -norelay _o__libm_sse2_log_precise() MSVCRT___libm_sse2_log +@ cdecl -arch=i386 -norelay _o__libm_sse2_pow_precise() MSVCRT___libm_sse2_pow +@ cdecl -arch=i386 -norelay _o__libm_sse2_sin_precise() MSVCRT___libm_sse2_sin +@ cdecl -arch=i386 -norelay _o__libm_sse2_sqrt_precise() MSVCRT___libm_sse2_sqrt_precise +@ cdecl -arch=i386 -norelay _o__libm_sse2_tan_precise() MSVCRT___libm_sse2_tan +@ cdecl _o__loaddll(str) _loaddll +@ cdecl _o__localtime32(ptr) MSVCRT__localtime32 +@ cdecl _o__localtime32_s(ptr ptr) _localtime32_s +@ cdecl _o__localtime64(ptr) MSVCRT__localtime64 +@ cdecl _o__localtime64_s(ptr ptr) _localtime64_s +@ cdecl _o__lock_file(ptr) MSVCRT__lock_file +@ cdecl _o__locking(long long long) MSVCRT__locking +@ cdecl _o__logb(double) MSVCRT__logb +@ cdecl -arch=!i386 _o__logbf(float) MSVCRT__logbf +@ cdecl _o__lsearch(ptr ptr ptr long ptr) _lsearch @ stub _o__lsearch_s -@ stub _o__lseek -@ stub _o__lseeki64 -@ stub _o__ltoa -@ stub _o__ltoa_s -@ stub _o__ltow -@ stub _o__ltow_s -@ stub _o__makepath -@ stub _o__makepath_s -@ stub _o__malloc_base -@ stub _o__mbbtombc +@ cdecl _o__lseek(long long long) MSVCRT__lseek +@ cdecl -ret64 _o__lseeki64(long int64 long) MSVCRT__lseeki64 +@ cdecl _o__ltoa(long ptr long) ntdll._ltoa +@ cdecl _o__ltoa_s(long ptr long long) MSVCRT__ltoa_s +@ cdecl _o__ltow(long ptr long) ntdll._ltow +@ cdecl _o__ltow_s(long ptr long long) MSVCRT__ltow_s +@ cdecl _o__makepath(ptr str str str str) MSVCRT__makepath +@ cdecl _o__makepath_s(ptr long str str str str) MSVCRT__makepath_s +@ cdecl _o__malloc_base(long) _malloc_base +@ cdecl _o__mbbtombc(long) _mbbtombc @ stub _o__mbbtombc_l -@ stub _o__mbbtype +@ cdecl _o__mbbtype(long long) _mbbtype @ stub _o__mbbtype_l -@ stub _o__mbccpy -@ stub _o__mbccpy_l -@ stub _o__mbccpy_s -@ stub _o__mbccpy_s_l -@ stub _o__mbcjistojms +@ cdecl _o__mbccpy(ptr ptr) _mbccpy +@ cdecl _o__mbccpy_l(ptr ptr ptr) _mbccpy_l +@ cdecl _o__mbccpy_s(ptr long ptr ptr) _mbccpy_s +@ cdecl _o__mbccpy_s_l(ptr long ptr ptr ptr) _mbccpy_s_l +@ cdecl _o__mbcjistojms(long) _mbcjistojms @ stub _o__mbcjistojms_l -@ stub _o__mbcjmstojis +@ cdecl _o__mbcjmstojis(long) _mbcjmstojis @ stub _o__mbcjmstojis_l -@ stub _o__mbclen +@ cdecl _o__mbclen(ptr) _mbclen @ stub _o__mbclen_l -@ stub _o__mbctohira +@ cdecl _o__mbctohira(long) _mbctohira @ stub _o__mbctohira_l -@ stub _o__mbctokata +@ cdecl _o__mbctokata(long) _mbctokata @ stub _o__mbctokata_l -@ stub _o__mbctolower +@ cdecl _o__mbctolower(long) _mbctolower @ stub _o__mbctolower_l -@ stub _o__mbctombb +@ cdecl _o__mbctombb(long) _mbctombb @ stub _o__mbctombb_l -@ stub _o__mbctoupper +@ cdecl _o__mbctoupper(long) _mbctoupper @ stub _o__mbctoupper_l @ stub _o__mblen_l -@ stub _o__mbsbtype +@ cdecl _o__mbsbtype(str long) _mbsbtype @ stub _o__mbsbtype_l -@ stub _o__mbscat_s -@ stub _o__mbscat_s_l -@ stub _o__mbschr +@ cdecl _o__mbscat_s(ptr long str) _mbscat_s +@ cdecl _o__mbscat_s_l(ptr long str ptr) _mbscat_s_l +@ cdecl _o__mbschr(str long) _mbschr @ stub _o__mbschr_l -@ stub _o__mbscmp +@ cdecl _o__mbscmp(str str) _mbscmp @ stub _o__mbscmp_l -@ stub _o__mbscoll -@ stub _o__mbscoll_l -@ stub _o__mbscpy_s -@ stub _o__mbscpy_s_l -@ stub _o__mbscspn -@ stub _o__mbscspn_l -@ stub _o__mbsdec +@ cdecl _o__mbscoll(str str) _mbscoll +@ cdecl _o__mbscoll_l(str str ptr) _mbscoll_l +@ cdecl _o__mbscpy_s(ptr long str) _mbscpy_s +@ cdecl _o__mbscpy_s_l(ptr long str ptr) _mbscpy_s_l +@ cdecl _o__mbscspn(str str) _mbscspn +@ cdecl _o__mbscspn_l(str str ptr) _mbscspn_l +@ cdecl _o__mbsdec(ptr ptr) _mbsdec @ stub _o__mbsdec_l -@ stub _o__mbsicmp +@ cdecl _o__mbsicmp(str str) _mbsicmp @ stub _o__mbsicmp_l -@ stub _o__mbsicoll -@ stub _o__mbsicoll_l -@ stub _o__mbsinc +@ cdecl _o__mbsicoll(str str) _mbsicoll +@ cdecl _o__mbsicoll_l(str str ptr) _mbsicoll_l +@ cdecl _o__mbsinc(str) _mbsinc @ stub _o__mbsinc_l -@ stub _o__mbslen -@ stub _o__mbslen_l -@ stub _o__mbslwr +@ cdecl _o__mbslen(str) _mbslen +@ cdecl _o__mbslen_l(str ptr) _mbslen_l +@ cdecl _o__mbslwr(str) _mbslwr @ stub _o__mbslwr_l -@ stub _o__mbslwr_s +@ cdecl _o__mbslwr_s(str long) _mbslwr_s @ stub _o__mbslwr_s_l -@ stub _o__mbsnbcat +@ cdecl _o__mbsnbcat(str str long) _mbsnbcat @ stub _o__mbsnbcat_l -@ stub _o__mbsnbcat_s +@ cdecl _o__mbsnbcat_s(str long ptr long) _mbsnbcat_s @ stub _o__mbsnbcat_s_l -@ stub _o__mbsnbcmp +@ cdecl _o__mbsnbcmp(str str long) _mbsnbcmp @ stub _o__mbsnbcmp_l -@ stub _o__mbsnbcnt +@ cdecl _o__mbsnbcnt(ptr long) _mbsnbcnt @ stub _o__mbsnbcnt_l -@ stub _o__mbsnbcoll -@ stub _o__mbsnbcoll_l -@ stub _o__mbsnbcpy +@ cdecl _o__mbsnbcoll(str str long) _mbsnbcoll +@ cdecl _o__mbsnbcoll_l(str str long ptr) _mbsnbcoll_l +@ cdecl _o__mbsnbcpy(ptr str long) _mbsnbcpy @ stub _o__mbsnbcpy_l -@ stub _o__mbsnbcpy_s -@ stub _o__mbsnbcpy_s_l -@ stub _o__mbsnbicmp +@ cdecl _o__mbsnbcpy_s(ptr long str long) _mbsnbcpy_s +@ cdecl _o__mbsnbcpy_s_l(ptr long str long ptr) _mbsnbcpy_s_l +@ cdecl _o__mbsnbicmp(str str long) _mbsnbicmp @ stub _o__mbsnbicmp_l -@ stub _o__mbsnbicoll -@ stub _o__mbsnbicoll_l -@ stub _o__mbsnbset +@ cdecl _o__mbsnbicoll(str str long) _mbsnbicoll +@ cdecl _o__mbsnbicoll_l(str str long ptr) _mbsnbicoll_l +@ cdecl _o__mbsnbset(ptr long long) _mbsnbset @ stub _o__mbsnbset_l @ stub _o__mbsnbset_s @ stub _o__mbsnbset_s_l -@ stub _o__mbsncat +@ cdecl _o__mbsncat(str str long) _mbsncat @ stub _o__mbsncat_l @ stub _o__mbsncat_s @ stub _o__mbsncat_s_l -@ stub _o__mbsnccnt +@ cdecl _o__mbsnccnt(str long) _mbsnccnt @ stub _o__mbsnccnt_l -@ stub _o__mbsncmp +@ cdecl _o__mbsncmp(str str long) _mbsncmp @ stub _o__mbsncmp_l @ stub _o__mbsncoll @ stub _o__mbsncoll_l -@ stub _o__mbsncpy +@ cdecl _o__mbsncpy(ptr str long) _mbsncpy @ stub _o__mbsncpy_l @ stub _o__mbsncpy_s @ stub _o__mbsncpy_s_l -@ stub _o__mbsnextc +@ cdecl _o__mbsnextc(str) _mbsnextc @ stub _o__mbsnextc_l -@ stub _o__mbsnicmp +@ cdecl _o__mbsnicmp(str str long) _mbsnicmp @ stub _o__mbsnicmp_l @ stub _o__mbsnicoll @ stub _o__mbsnicoll_l -@ stub _o__mbsninc +@ cdecl _o__mbsninc(str long) _mbsninc @ stub _o__mbsninc_l -@ stub _o__mbsnlen -@ stub _o__mbsnlen_l -@ stub _o__mbsnset +@ cdecl _o__mbsnlen(str long) _mbsnlen +@ cdecl _o__mbsnlen_l(str long ptr) _mbsnlen_l +@ cdecl _o__mbsnset(ptr long long) _mbsnset @ stub _o__mbsnset_l @ stub _o__mbsnset_s @ stub _o__mbsnset_s_l -@ stub _o__mbspbrk +@ cdecl _o__mbspbrk(str str) _mbspbrk @ stub _o__mbspbrk_l -@ stub _o__mbsrchr +@ cdecl _o__mbsrchr(str long) _mbsrchr @ stub _o__mbsrchr_l -@ stub _o__mbsrev +@ cdecl _o__mbsrev(str) _mbsrev @ stub _o__mbsrev_l -@ stub _o__mbsset +@ cdecl _o__mbsset(ptr long) _mbsset @ stub _o__mbsset_l @ stub _o__mbsset_s @ stub _o__mbsset_s_l -@ stub _o__mbsspn -@ stub _o__mbsspn_l -@ stub _o__mbsspnp +@ cdecl _o__mbsspn(str str) _mbsspn +@ cdecl _o__mbsspn_l(str str ptr) _mbsspn_l +@ cdecl _o__mbsspnp(str str) _mbsspnp @ stub _o__mbsspnp_l -@ stub _o__mbsstr +@ cdecl _o__mbsstr(str str) _mbsstr @ stub _o__mbsstr_l -@ stub _o__mbstok -@ stub _o__mbstok_l -@ stub _o__mbstok_s -@ stub _o__mbstok_s_l -@ stub _o__mbstowcs_l -@ stub _o__mbstowcs_s_l +@ cdecl _o__mbstok(str str) _mbstok +@ cdecl _o__mbstok_l(str str ptr) _mbstok_l +@ cdecl _o__mbstok_s(str str ptr) _mbstok_s +@ cdecl _o__mbstok_s_l(str str ptr ptr) _mbstok_s_l +@ cdecl _o__mbstowcs_l(ptr str long ptr) MSVCRT__mbstowcs_l +@ cdecl _o__mbstowcs_s_l(ptr ptr long str long ptr) MSVCRT__mbstowcs_s_l @ cdecl _o__mbstrlen(str) _mbstrlen -@ stub _o__mbstrlen_l +@ cdecl _o__mbstrlen_l(str ptr) _mbstrlen_l @ stub _o__mbstrnlen @ stub _o__mbstrnlen_l -@ stub _o__mbsupr +@ cdecl _o__mbsupr(str) _mbsupr @ stub _o__mbsupr_l -@ stub _o__mbsupr_s +@ cdecl _o__mbsupr_s(str long) _mbsupr_s @ stub _o__mbsupr_s_l -@ stub _o__mbtowc_l -@ stub _o__memicmp -@ stub _o__memicmp_l -@ stub _o__mkdir -@ stub _o__mkgmtime32 -@ stub _o__mkgmtime64 -@ stub _o__mktemp -@ stub _o__mktemp_s -@ stub _o__mktime32 -@ stub _o__mktime64 -@ stub _o__msize -@ stub _o__nextafter -@ stub _o__nextafterf -@ stub _o__open_osfhandle -@ stub _o__pclose -@ stub _o__pipe -@ stub _o__popen -@ stub _o__purecall -@ stub _o__putc_nolock -@ stub _o__putch -@ stub _o__putch_nolock -@ stub _o__putenv -@ stub _o__putenv_s -@ stub _o__putw -@ stub _o__putwc_nolock -@ stub _o__putwch -@ stub _o__putwch_nolock -@ stub _o__putws -@ stub _o__read -@ stub _o__realloc_base -@ stub _o__recalloc +@ cdecl _o__mbtowc_l(ptr str long ptr) MSVCRT_mbtowc_l +@ cdecl _o__memicmp(str str long) MSVCRT__memicmp +@ cdecl _o__memicmp_l(str str long ptr) MSVCRT__memicmp_l +@ cdecl _o__mkdir(str) MSVCRT__mkdir +@ cdecl _o__mkgmtime32(ptr) MSVCRT__mkgmtime32 +@ cdecl _o__mkgmtime64(ptr) MSVCRT__mkgmtime64 +@ cdecl _o__mktemp(str) MSVCRT__mktemp +@ cdecl _o__mktemp_s(str long) MSVCRT__mktemp_s +@ cdecl _o__mktime32(ptr) MSVCRT__mktime32 +@ cdecl _o__mktime64(ptr) MSVCRT__mktime64 +@ cdecl _o__msize(ptr) _msize +@ cdecl _o__nextafter(double double) MSVCRT__nextafter +@ cdecl -arch=x86_64 _o__nextafterf(float float) MSVCRT__nextafterf +@ cdecl _o__open_osfhandle(long long) MSVCRT__open_osfhandle +@ cdecl _o__pclose(ptr) MSVCRT__pclose +@ cdecl _o__pipe(ptr long long) MSVCRT__pipe +@ cdecl _o__popen(str str) MSVCRT__popen +@ cdecl _o__purecall() _purecall +@ cdecl _o__putc_nolock(long ptr) MSVCRT__fputc_nolock +@ cdecl _o__putch(long) _putch +@ cdecl _o__putch_nolock(long) _putch_nolock +@ cdecl _o__putenv(str) _putenv +@ cdecl _o__putenv_s(str str) _putenv_s +@ cdecl _o__putw(long ptr) MSVCRT__putw +@ cdecl _o__putwc_nolock(long ptr) MSVCRT__fputwc_nolock +@ cdecl _o__putwch(long) _putwch +@ cdecl _o__putwch_nolock(long) _putwch_nolock +@ cdecl _o__putws(wstr) MSVCRT__putws +@ cdecl _o__read(long ptr long) MSVCRT__read +@ cdecl _o__realloc_base(ptr long) _realloc_base +@ cdecl _o__recalloc(ptr long long) _recalloc @ cdecl _o__register_onexit_function(ptr ptr) MSVCRT__register_onexit_function -@ stub _o__resetstkoflw -@ stub _o__rmdir -@ stub _o__rmtmp -@ stub _o__scalb -@ stub _o__scalbf -@ stub _o__searchenv -@ stub _o__searchenv_s +@ cdecl _o__resetstkoflw() MSVCRT__resetstkoflw +@ cdecl _o__rmdir(str) MSVCRT__rmdir +@ cdecl _o__rmtmp() MSVCRT__rmtmp +@ cdecl _o__scalb(double long) MSVCRT__scalb +@ cdecl -arch=x86_64 _o__scalbf(float long) MSVCRT__scalbf +@ cdecl _o__searchenv(str str ptr) MSVCRT__searchenv +@ cdecl _o__searchenv_s(str str ptr long) MSVCRT__searchenv_s @ cdecl _o__seh_filter_dll(long ptr) __CppXcptFilter @ cdecl _o__seh_filter_exe(long ptr) _XcptFilter -@ stub _o__set_abort_behavior +@ cdecl _o__set_abort_behavior(long long) MSVCRT__set_abort_behavior @ cdecl _o__set_app_type(long) MSVCRT___set_app_type -@ stub _o__set_doserrno -@ stub _o__set_errno +@ cdecl _o__set_doserrno(long) _set_doserrno +@ cdecl _o__set_errno(long) _set_errno @ cdecl _o__set_fmode(long) MSVCRT__set_fmode -@ stub _o__set_invalid_parameter_handler -@ stub _o__set_new_handler +@ cdecl _o__set_invalid_parameter_handler(ptr) _set_invalid_parameter_handler +@ cdecl _o__set_new_handler(ptr) MSVCRT_set_new_handler @ cdecl _o__set_new_mode(long) MSVCRT__set_new_mode -@ stub _o__set_thread_local_invalid_parameter_handler -@ stub _o__seterrormode -@ stub _o__setmbcp -@ stub _o__setmode +@ cdecl _o__set_thread_local_invalid_parameter_handler(ptr) _set_thread_local_invalid_parameter_handler +@ cdecl _o__seterrormode(long) _seterrormode +@ cdecl _o__setmbcp(long) _setmbcp +@ cdecl _o__setmode(long long) MSVCRT__setmode @ stub _o__setsystime -@ stub _o__sleep -@ stub _o__sopen -@ stub _o__sopen_dispatch -@ stub _o__sopen_s -@ stub _o__spawnv -@ stub _o__spawnve -@ stub _o__spawnvp -@ stub _o__spawnvpe -@ stub _o__splitpath -@ stub _o__splitpath_s -@ stub _o__stat32 -@ stub _o__stat32i64 -@ stub _o__stat64 -@ stub _o__stat64i32 -@ stub _o__strcoll_l -@ stub _o__strdate -@ stub _o__strdate_s +@ cdecl _o__sleep(long) MSVCRT__sleep +@ varargs _o__sopen(str long long) MSVCRT__sopen +@ cdecl _o__sopen_dispatch(str long long long ptr long) MSVCRT__sopen_dispatch +@ cdecl _o__sopen_s(ptr str long long long) MSVCRT__sopen_s +@ cdecl _o__spawnv(long str ptr) MSVCRT__spawnv +@ cdecl _o__spawnve(long str ptr ptr) MSVCRT__spawnve +@ cdecl _o__spawnvp(long str ptr) MSVCRT__spawnvp +@ cdecl _o__spawnvpe(long str ptr ptr) MSVCRT__spawnvpe +@ cdecl _o__splitpath(str ptr ptr ptr ptr) MSVCRT__splitpath +@ cdecl _o__splitpath_s(str ptr long ptr long ptr long ptr long) MSVCRT__splitpath_s +@ cdecl _o__stat32(str ptr) MSVCRT__stat32 +@ cdecl _o__stat32i64(str ptr) MSVCRT__stat32i64 +@ cdecl _o__stat64(str ptr) MSVCRT_stat64 +@ cdecl _o__stat64i32(str ptr) MSVCRT__stat64i32 +@ cdecl _o__strcoll_l(str str ptr) MSVCRT_strcoll_l +@ cdecl _o__strdate(ptr) MSVCRT__strdate +@ cdecl _o__strdate_s(ptr long) _strdate_s @ cdecl _o__strdup(str) MSVCRT__strdup -@ stub _o__strerror +@ cdecl _o__strerror(long) MSVCRT__strerror @ stub _o__strerror_s -@ stub _o__strftime_l +@ cdecl _o__strftime_l(ptr long str ptr ptr) MSVCRT__strftime_l @ cdecl _o__stricmp(str str) MSVCRT__stricmp -@ stub _o__stricmp_l -@ stub _o__stricoll -@ stub _o__stricoll_l -@ stub _o__strlwr -@ stub _o__strlwr_l -@ stub _o__strlwr_s -@ stub _o__strlwr_s_l -@ stub _o__strncoll -@ stub _o__strncoll_l +@ cdecl _o__stricmp_l(str str ptr) MSVCRT__stricmp_l +@ cdecl _o__stricoll(str str) MSVCRT__stricoll +@ cdecl _o__stricoll_l(str str ptr) MSVCRT__stricoll_l +@ cdecl _o__strlwr(str) MSVCRT__strlwr +@ cdecl _o__strlwr_l(str ptr) _strlwr_l +@ cdecl _o__strlwr_s(ptr long) MSVCRT__strlwr_s +@ cdecl _o__strlwr_s_l(ptr long ptr) MSVCRT__strlwr_s_l +@ cdecl _o__strncoll(str str long) MSVCRT__strncoll +@ cdecl _o__strncoll_l(str str long ptr) MSVCRT__strncoll_l @ cdecl _o__strnicmp(str str long) MSVCRT__strnicmp -@ stub _o__strnicmp_l -@ stub _o__strnicoll -@ stub _o__strnicoll_l -@ stub _o__strnset_s +@ cdecl _o__strnicmp_l(str str long ptr) MSVCRT__strnicmp_l +@ cdecl _o__strnicoll(str str long) MSVCRT__strnicoll +@ cdecl _o__strnicoll_l(str str long ptr) MSVCRT__strnicoll_l +@ cdecl _o__strnset_s(str long long long) MSVCRT__strnset_s @ stub _o__strset_s -@ stub _o__strtime -@ stub _o__strtime_s -@ stub _o__strtod_l -@ stub _o__strtof_l -@ stub _o__strtoi64 -@ stub _o__strtoi64_l -@ stub _o__strtol_l +@ cdecl _o__strtime(ptr) MSVCRT__strtime +@ cdecl _o__strtime_s(ptr long) _strtime_s +@ cdecl _o__strtod_l(str ptr ptr) MSVCRT_strtod_l +@ cdecl _o__strtof_l(str ptr ptr) MSVCRT__strtof_l +@ cdecl -ret64 _o__strtoi64(str ptr long) MSVCRT_strtoi64 +@ cdecl -ret64 _o__strtoi64_l(str ptr long ptr) MSVCRT_strtoi64_l +@ cdecl _o__strtol_l(str ptr long ptr) MSVCRT__strtol_l @ stub _o__strtold_l -@ stub _o__strtoll_l -@ stub _o__strtoui64 -@ stub _o__strtoui64_l -@ stub _o__strtoul_l -@ stub _o__strtoull_l -@ stub _o__strupr -@ stub _o__strupr_l -@ stub _o__strupr_s -@ stub _o__strupr_s_l -@ stub _o__strxfrm_l -@ stub _o__swab -@ stub _o__tell -@ stub _o__telli64 -@ stub _o__timespec32_get -@ stub _o__timespec64_get -@ stub _o__tolower -@ stub _o__tolower_l -@ stub _o__toupper -@ stub _o__toupper_l -@ stub _o__towlower_l -@ stub _o__towupper_l -@ stub _o__tzset -@ stub _o__ui64toa -@ stub _o__ui64toa_s -@ stub _o__ui64tow -@ stub _o__ui64tow_s -@ stub _o__ultoa -@ stub _o__ultoa_s -@ stub _o__ultow -@ stub _o__ultow_s -@ stub _o__umask +@ cdecl -ret64 _o__strtoll_l(str ptr long ptr) MSVCRT_strtoi64_l +@ cdecl -ret64 _o__strtoui64(str ptr long) MSVCRT_strtoui64 +@ cdecl -ret64 _o__strtoui64_l(str ptr long ptr) MSVCRT_strtoui64_l +@ cdecl _o__strtoul_l(str ptr long ptr) MSVCRT_strtoul_l +@ cdecl -ret64 _o__strtoull_l(str ptr long ptr) MSVCRT_strtoui64_l +@ cdecl _o__strupr(str) MSVCRT__strupr +@ cdecl _o__strupr_l(str ptr) MSVCRT__strupr_l +@ cdecl _o__strupr_s(str long) MSVCRT__strupr_s +@ cdecl _o__strupr_s_l(str long ptr) MSVCRT__strupr_s_l +@ cdecl _o__strxfrm_l(ptr str long ptr) MSVCRT__strxfrm_l +@ cdecl _o__swab(str str long) MSVCRT__swab +@ cdecl _o__tell(long) MSVCRT__tell +@ cdecl -ret64 _o__telli64(long) _telli64 +@ cdecl _o__timespec32_get(ptr long) _timespec32_get +@ cdecl _o__timespec64_get(ptr long) _timespec64_get +@ cdecl _o__tolower(long) MSVCRT__tolower +@ cdecl _o__tolower_l(long ptr) MSVCRT__tolower_l +@ cdecl _o__toupper(long) MSVCRT__toupper +@ cdecl _o__toupper_l(long ptr) MSVCRT__toupper_l +@ cdecl _o__towlower_l(long ptr) MSVCRT__towlower_l +@ cdecl _o__towupper_l(long ptr) MSVCRT__towupper_l +@ cdecl _o__tzset() MSVCRT__tzset +@ cdecl _o__ui64toa(int64 ptr long) ntdll._ui64toa +@ cdecl _o__ui64toa_s(int64 ptr long long) MSVCRT__ui64toa_s +@ cdecl _o__ui64tow(int64 ptr long) ntdll._ui64tow +@ cdecl _o__ui64tow_s(int64 ptr long long) MSVCRT__ui64tow_s +@ cdecl _o__ultoa(long ptr long) ntdll._ultoa +@ cdecl _o__ultoa_s(long ptr long long) MSVCRT__ultoa_s +@ cdecl _o__ultow(long ptr long) ntdll._ultow +@ cdecl _o__ultow_s(long ptr long long) MSVCRT__ultow_s +@ cdecl _o__umask(long) MSVCRT__umask @ stub _o__umask_s -@ stub _o__ungetc_nolock -@ stub _o__ungetch -@ stub _o__ungetch_nolock -@ stub _o__ungetwc_nolock -@ stub _o__ungetwch -@ stub _o__ungetwch_nolock -@ stub _o__unlink -@ stub _o__unloaddll -@ stub _o__unlock_file -@ stub _o__utime32 -@ stub _o__utime64 -@ stub _o__waccess -@ stub _o__waccess_s -@ stub _o__wasctime -@ stub _o__wasctime_s -@ stub _o__wchdir -@ stub _o__wchmod -@ stub _o__wcreat -@ stub _o__wcreate_locale -@ stub _o__wcscoll_l -@ stub _o__wcsdup -@ stub _o__wcserror -@ stub _o__wcserror_s -@ stub _o__wcsftime_l -@ stub _o__wcsicmp -@ stub _o__wcsicmp_l -@ stub _o__wcsicoll -@ stub _o__wcsicoll_l -@ stub _o__wcslwr -@ stub _o__wcslwr_l -@ stub _o__wcslwr_s -@ stub _o__wcslwr_s_l -@ stub _o__wcsncoll -@ stub _o__wcsncoll_l -@ stub _o__wcsnicmp -@ stub _o__wcsnicmp_l -@ stub _o__wcsnicoll -@ stub _o__wcsnicoll_l -@ stub _o__wcsnset -@ stub _o__wcsnset_s -@ stub _o__wcsset -@ stub _o__wcsset_s -@ stub _o__wcstod_l -@ stub _o__wcstof_l -@ stub _o__wcstoi64 -@ stub _o__wcstoi64_l -@ stub _o__wcstol_l +@ cdecl _o__ungetc_nolock(long ptr) MSVCRT__ungetc_nolock +@ cdecl _o__ungetch(long) _ungetch +@ cdecl _o__ungetch_nolock(long) _ungetch_nolock +@ cdecl _o__ungetwc_nolock(long ptr) MSVCRT__ungetwc_nolock +@ cdecl _o__ungetwch(long) _ungetwch +@ cdecl _o__ungetwch_nolock(long) _ungetwch_nolock +@ cdecl _o__unlink(str) MSVCRT__unlink +@ cdecl _o__unloaddll(long) _unloaddll +@ cdecl _o__unlock_file(ptr) MSVCRT__unlock_file +@ cdecl _o__utime32(str ptr) _utime32 +@ cdecl _o__utime64(str ptr) _utime64 +@ cdecl _o__waccess(wstr long) MSVCRT__waccess +@ cdecl _o__waccess_s(wstr long) MSVCRT__waccess_s +@ cdecl _o__wasctime(ptr) MSVCRT__wasctime +@ cdecl _o__wasctime_s(ptr long ptr) MSVCRT__wasctime_s +@ cdecl _o__wchdir(wstr) MSVCRT__wchdir +@ cdecl _o__wchmod(wstr long) MSVCRT__wchmod +@ cdecl _o__wcreat(wstr long) MSVCRT__wcreat +@ cdecl _o__wcreate_locale(long wstr) MSVCRT__wcreate_locale +@ cdecl _o__wcscoll_l(wstr wstr ptr) MSVCRT__wcscoll_l +@ cdecl _o__wcsdup(wstr) MSVCRT__wcsdup +@ cdecl _o__wcserror(long) MSVCRT__wcserror +@ cdecl _o__wcserror_s(ptr long long) MSVCRT__wcserror_s +@ cdecl _o__wcsftime_l(ptr long wstr ptr ptr) MSVCRT__wcsftime_l +@ cdecl _o__wcsicmp(wstr wstr) MSVCRT__wcsicmp +@ cdecl _o__wcsicmp_l(wstr wstr ptr) MSVCRT__wcsicmp_l +@ cdecl _o__wcsicoll(wstr wstr) MSVCRT__wcsicoll +@ cdecl _o__wcsicoll_l(wstr wstr ptr) MSVCRT__wcsicoll_l +@ cdecl _o__wcslwr(wstr) MSVCRT__wcslwr +@ cdecl _o__wcslwr_l(wstr ptr) MSVCRT__wcslwr_l +@ cdecl _o__wcslwr_s(wstr long) MSVCRT__wcslwr_s +@ cdecl _o__wcslwr_s_l(wstr long ptr) MSVCRT__wcslwr_s_l +@ cdecl _o__wcsncoll(wstr wstr long) MSVCRT__wcsncoll +@ cdecl _o__wcsncoll_l(wstr wstr long ptr) MSVCRT__wcsncoll_l +@ cdecl _o__wcsnicmp(wstr wstr long) MSVCRT__wcsnicmp +@ cdecl _o__wcsnicmp_l(wstr wstr long ptr) MSVCRT__wcsnicmp_l +@ cdecl _o__wcsnicoll(wstr wstr long) MSVCRT__wcsnicoll +@ cdecl _o__wcsnicoll_l(wstr wstr long ptr) MSVCRT__wcsnicoll_l +@ cdecl _o__wcsnset(wstr long long) MSVCRT__wcsnset +@ cdecl _o__wcsnset_s(wstr long long long) MSVCRT__wcsnset_s +@ cdecl _o__wcsset(wstr long) MSVCRT__wcsset +@ cdecl _o__wcsset_s(wstr long long) MSVCRT__wcsset_s +@ cdecl _o__wcstod_l(wstr ptr long) MSVCRT__wcstod_l +@ cdecl _o__wcstof_l(wstr ptr ptr) MSVCRT__wcstof_l +@ cdecl -ret64 _o__wcstoi64(wstr ptr long) MSVCRT__wcstoi64 +@ cdecl -ret64 _o__wcstoi64_l(wstr ptr long ptr) MSVCRT__wcstoi64_l +@ cdecl _o__wcstol_l(wstr ptr long ptr) MSVCRT__wcstol_l @ stub _o__wcstold_l -@ stub _o__wcstoll_l -@ stub _o__wcstombs_l -@ stub _o__wcstombs_s_l -@ stub _o__wcstoui64 -@ stub _o__wcstoui64_l -@ stub _o__wcstoul_l -@ stub _o__wcstoull_l -@ stub _o__wcsupr -@ stub _o__wcsupr_l -@ stub _o__wcsupr_s -@ stub _o__wcsupr_s_l -@ stub _o__wcsxfrm_l -@ stub _o__wctime32 -@ stub _o__wctime32_s -@ stub _o__wctime64 -@ stub _o__wctime64_s -@ stub _o__wctomb_l -@ stub _o__wctomb_s_l -@ stub _o__wdupenv_s -@ stub _o__wexecv -@ stub _o__wexecve -@ stub _o__wexecvp -@ stub _o__wexecvpe -@ stub _o__wfdopen -@ stub _o__wfindfirst32 +@ cdecl -ret64 _o__wcstoll_l(wstr ptr long ptr) MSVCRT__wcstoi64_l +@ cdecl _o__wcstombs_l(ptr ptr long ptr) MSVCRT__wcstombs_l +@ cdecl _o__wcstombs_s_l(ptr ptr long wstr long ptr) MSVCRT__wcstombs_s_l +@ cdecl -ret64 _o__wcstoui64(wstr ptr long) MSVCRT__wcstoui64 +@ cdecl -ret64 _o__wcstoui64_l(wstr ptr long ptr) MSVCRT__wcstoui64_l +@ cdecl _o__wcstoul_l(wstr ptr long ptr) MSVCRT__wcstoul_l +@ cdecl -ret64 _o__wcstoull_l(wstr ptr long ptr) MSVCRT__wcstoui64_l +@ cdecl _o__wcsupr(wstr) MSVCRT__wcsupr +@ cdecl _o__wcsupr_l(wstr ptr) MSVCRT__wcsupr_l +@ cdecl _o__wcsupr_s(wstr long) MSVCRT__wcsupr_s +@ cdecl _o__wcsupr_s_l(wstr long ptr) MSVCRT__wcsupr_s_l +@ cdecl _o__wcsxfrm_l(ptr wstr long ptr) MSVCRT__wcsxfrm_l +@ cdecl _o__wctime32(ptr) MSVCRT__wctime32 +@ cdecl _o__wctime32_s(ptr long ptr) MSVCRT__wctime32_s +@ cdecl _o__wctime64(ptr) MSVCRT__wctime64 +@ cdecl _o__wctime64_s(ptr long ptr) MSVCRT__wctime64_s +@ cdecl _o__wctomb_l(ptr long ptr) MSVCRT__wctomb_l +@ cdecl _o__wctomb_s_l(ptr ptr long long ptr) MSVCRT__wctomb_s_l +@ cdecl _o__wdupenv_s(ptr ptr wstr) _wdupenv_s +@ cdecl _o__wexecv(wstr ptr) _wexecv +@ cdecl _o__wexecve(wstr ptr ptr) _wexecve +@ cdecl _o__wexecvp(wstr ptr) _wexecvp +@ cdecl _o__wexecvpe(wstr ptr ptr) _wexecvpe +@ cdecl _o__wfdopen(long wstr) MSVCRT__wfdopen +@ cdecl _o__wfindfirst32(wstr ptr) MSVCRT__wfindfirst32 @ stub _o__wfindfirst32i64 -@ stub _o__wfindfirst64 -@ stub _o__wfindfirst64i32 -@ stub _o__wfindnext32 +@ cdecl _o__wfindfirst64(wstr ptr) MSVCRT__wfindfirst64 +@ cdecl _o__wfindfirst64i32(wstr ptr) MSVCRT__wfindfirst64i32 +@ cdecl _o__wfindnext32(long ptr) MSVCRT__wfindnext32 @ stub _o__wfindnext32i64 -@ stub _o__wfindnext64 -@ stub _o__wfindnext64i32 -@ stub _o__wfopen -@ stub _o__wfopen_s -@ stub _o__wfreopen -@ stub _o__wfreopen_s -@ stub _o__wfsopen -@ stub _o__wfullpath -@ stub _o__wgetcwd -@ stub _o__wgetdcwd +@ cdecl _o__wfindnext64(long ptr) MSVCRT__wfindnext64 +@ cdecl _o__wfindnext64i32(long ptr) MSVCRT__wfindnext64i32 +@ cdecl _o__wfopen(wstr wstr) MSVCRT__wfopen +@ cdecl _o__wfopen_s(ptr wstr wstr) MSVCRT__wfopen_s +@ cdecl _o__wfreopen(wstr wstr ptr) MSVCRT__wfreopen +@ cdecl _o__wfreopen_s(ptr wstr wstr ptr) MSVCRT__wfreopen_s +@ cdecl _o__wfsopen(wstr wstr long) MSVCRT__wfsopen +@ cdecl _o__wfullpath(ptr wstr long) MSVCRT__wfullpath +@ cdecl _o__wgetcwd(wstr long) MSVCRT__wgetcwd +@ cdecl _o__wgetdcwd(long wstr long) MSVCRT__wgetdcwd @ cdecl _o__wgetenv(wstr) MSVCRT__wgetenv -@ stub _o__wgetenv_s -@ stub _o__wmakepath -@ stub _o__wmakepath_s -@ stub _o__wmkdir -@ stub _o__wmktemp -@ stub _o__wmktemp_s -@ stub _o__wperror -@ stub _o__wpopen -@ stub _o__wputenv -@ stub _o__wputenv_s -@ stub _o__wremove -@ stub _o__wrename -@ stub _o__write -@ stub _o__wrmdir -@ stub _o__wsearchenv -@ stub _o__wsearchenv_s +@ cdecl _o__wgetenv_s(ptr ptr long wstr) _wgetenv_s +@ cdecl _o__wmakepath(ptr wstr wstr wstr wstr) MSVCRT__wmakepath +@ cdecl _o__wmakepath_s(ptr long wstr wstr wstr wstr) MSVCRT__wmakepath_s +@ cdecl _o__wmkdir(wstr) MSVCRT__wmkdir +@ cdecl _o__wmktemp(wstr) MSVCRT__wmktemp +@ cdecl _o__wmktemp_s(wstr long) MSVCRT__wmktemp_s +@ cdecl _o__wperror(wstr) MSVCRT__wperror +@ cdecl _o__wpopen(wstr wstr) MSVCRT__wpopen +@ cdecl _o__wputenv(wstr) _wputenv +@ cdecl _o__wputenv_s(wstr wstr) _wputenv_s +@ cdecl _o__wremove(wstr) MSVCRT__wremove +@ cdecl _o__wrename(wstr wstr) MSVCRT__wrename +@ cdecl _o__write(long ptr long) MSVCRT__write +@ cdecl _o__wrmdir(wstr) MSVCRT__wrmdir +@ cdecl _o__wsearchenv(wstr wstr ptr) MSVCRT__wsearchenv +@ cdecl _o__wsearchenv_s(wstr wstr ptr long) MSVCRT__wsearchenv_s @ cdecl _o__wsetlocale(long wstr) MSVCRT__wsetlocale -@ stub _o__wsopen_dispatch -@ stub _o__wsopen_s -@ stub _o__wspawnv -@ stub _o__wspawnve -@ stub _o__wspawnvp -@ stub _o__wspawnvpe -@ stub _o__wsplitpath -@ stub _o__wsplitpath_s -@ stub _o__wstat32 -@ stub _o__wstat32i64 -@ stub _o__wstat64 -@ stub _o__wstat64i32 -@ stub _o__wstrdate -@ stub _o__wstrdate_s -@ stub _o__wstrtime -@ stub _o__wstrtime_s -@ stub _o__wsystem -@ stub _o__wtmpnam_s -@ stub _o__wtof -@ stub _o__wtof_l -@ stub _o__wtoi -@ stub _o__wtoi64 -@ stub _o__wtoi64_l -@ stub _o__wtoi_l -@ stub _o__wtol -@ stub _o__wtol_l -@ stub _o__wtoll -@ stub _o__wtoll_l -@ stub _o__wunlink -@ stub _o__wutime32 -@ stub _o__wutime64 -@ stub _o__y0 -@ stub _o__y1 -@ stub _o__yn -@ stub _o_abort -@ stub _o_acos -@ stub _o_acosf -@ stub _o_acosh -@ stub _o_acoshf -@ stub _o_acoshl -@ stub _o_asctime -@ stub _o_asctime_s -@ stub _o_asin -@ stub _o_asinf -@ stub _o_asinh -@ stub _o_asinhf -@ stub _o_asinhl -@ stub _o_atan -@ stub _o_atan2 -@ stub _o_atan2f -@ stub _o_atanf -@ stub _o_atanh -@ stub _o_atanhf -@ stub _o_atanhl +@ cdecl _o__wsopen_dispatch(wstr long long long ptr long) MSVCRT__wsopen_dispatch +@ cdecl _o__wsopen_s(ptr wstr long long long) MSVCRT__wsopen_s +@ cdecl _o__wspawnv(long wstr ptr) MSVCRT__wspawnv +@ cdecl _o__wspawnve(long wstr ptr ptr) MSVCRT__wspawnve +@ cdecl _o__wspawnvp(long wstr ptr) MSVCRT__wspawnvp +@ cdecl _o__wspawnvpe(long wstr ptr ptr) MSVCRT__wspawnvpe +@ cdecl _o__wsplitpath(wstr ptr ptr ptr ptr) MSVCRT__wsplitpath +@ cdecl _o__wsplitpath_s(wstr ptr long ptr long ptr long ptr long) MSVCRT__wsplitpath_s +@ cdecl _o__wstat32(wstr ptr) MSVCRT__wstat32 +@ cdecl _o__wstat32i64(wstr ptr) MSVCRT__wstat32i64 +@ cdecl _o__wstat64(wstr ptr) MSVCRT__wstat64 +@ cdecl _o__wstat64i32(wstr ptr) MSVCRT__wstat64i32 +@ cdecl _o__wstrdate(ptr) MSVCRT__wstrdate +@ cdecl _o__wstrdate_s(ptr long) _wstrdate_s +@ cdecl _o__wstrtime(ptr) MSVCRT__wstrtime +@ cdecl _o__wstrtime_s(ptr long) _wstrtime_s +@ cdecl _o__wsystem(wstr) _wsystem +@ cdecl _o__wtmpnam_s(ptr long) MSVCRT__wtmpnam_s +@ cdecl _o__wtof(wstr) MSVCRT__wtof +@ cdecl _o__wtof_l(wstr ptr) MSVCRT__wtof_l +@ cdecl _o__wtoi(wstr) MSVCRT__wtoi +@ cdecl -ret64 _o__wtoi64(wstr) MSVCRT__wtoi64 +@ cdecl -ret64 _o__wtoi64_l(wstr ptr) MSVCRT__wtoi64_l +@ cdecl _o__wtoi_l(wstr ptr) MSVCRT__wtoi_l +@ cdecl _o__wtol(wstr) MSVCRT__wtol +@ cdecl _o__wtol_l(wstr ptr) MSVCRT__wtol_l +@ cdecl -ret64 _o__wtoll(wstr) MSVCRT__wtoll +@ cdecl -ret64 _o__wtoll_l(wstr ptr) MSVCRT__wtoll_l +@ cdecl _o__wunlink(wstr) MSVCRT__wunlink +@ cdecl _o__wutime32(wstr ptr) _wutime32 +@ cdecl _o__wutime64(wstr ptr) _wutime64 +@ cdecl _o__y0(double) MSVCRT__y0 +@ cdecl _o__y1(double) MSVCRT__y1 +@ cdecl _o__yn(long double) MSVCRT__yn +@ cdecl _o_abort() MSVCRT_abort +@ cdecl _o_acos(double) MSVCRT_acos +@ cdecl -arch=!i386 _o_acosf(float) MSVCRT_acosf +@ cdecl _o_acosh(double) MSVCR120_acosh +@ cdecl _o_acoshf(float) MSVCR120_acoshf +@ cdecl _o_acoshl(double) MSVCR120_acoshl +@ cdecl _o_asctime(ptr) MSVCRT_asctime +@ cdecl _o_asctime_s(ptr long ptr) MSVCRT_asctime_s +@ cdecl _o_asin(double) MSVCRT_asin +@ cdecl -arch=!i386 _o_asinf(float) MSVCRT_asinf +@ cdecl _o_asinh(double) MSVCR120_asinh +@ cdecl _o_asinhf(float) MSVCR120_asinhf +@ cdecl _o_asinhl(double) MSVCR120_asinhl +@ cdecl _o_atan(double) MSVCRT_atan +@ cdecl _o_atan2(double double) MSVCRT_atan2 +@ cdecl -arch=!i386 _o_atan2f(float float) MSVCRT_atan2f +@ cdecl -arch=!i386 _o_atanf(float) MSVCRT_atanf +@ cdecl _o_atanh(double) MSVCR120_atanh +@ cdecl _o_atanhf(float) MSVCR120_atanhf +@ cdecl _o_atanhl(double) MSVCR120_atanhl @ cdecl _o_atof(str) MSVCRT_atof @ cdecl _o_atoi(str) MSVCRT_atoi -@ stub _o_atol -@ stub _o_atoll -@ stub _o_bsearch -@ stub _o_bsearch_s -@ stub _o_btowc +@ cdecl _o_atol(str) MSVCRT_atol +@ cdecl -ret64 _o_atoll(str) MSVCRT_atoll +@ cdecl _o_bsearch(ptr ptr long long ptr) MSVCRT_bsearch +@ cdecl _o_bsearch_s(ptr ptr long long ptr ptr) MSVCRT_bsearch_s +@ cdecl _o_btowc(long) MSVCRT_btowc @ cdecl _o_calloc(long long) MSVCRT_calloc -@ stub _o_cbrt -@ stub _o_cbrtf +@ cdecl _o_cbrt(double) MSVCR120_cbrt +@ cdecl _o_cbrtf(float) MSVCR120_cbrtf @ cdecl _o_ceil(double) MSVCRT_ceil -@ stub _o_ceilf -@ stub _o_clearerr -@ stub _o_clearerr_s -@ stub _o_cos -@ stub _o_cosf -@ stub _o_cosh -@ stub _o_coshf -@ stub _o_erf -@ stub _o_erfc -@ stub _o_erfcf -@ stub _o_erfcl -@ stub _o_erff -@ stub _o_erfl +@ cdecl -arch=!i386 _o_ceilf(float) MSVCRT_ceilf +@ cdecl _o_clearerr(ptr) MSVCRT_clearerr +@ cdecl _o_clearerr_s(ptr) MSVCRT_clearerr_s +@ cdecl _o_cos(double) MSVCRT_cos +@ cdecl -arch=!i386 _o_cosf(float) MSVCRT_cosf +@ cdecl _o_cosh(double) MSVCRT_cosh +@ cdecl -arch=!i386 _o_coshf(float) MSVCRT_coshf +@ cdecl _o_erf(double) MSVCR120_erf +@ cdecl _o_erfc(double) MSVCR120_erfc +@ cdecl _o_erfcf(float) MSVCR120_erfcf +@ cdecl _o_erfcl(double) MSVCR120_erfcl +@ cdecl _o_erff(float) MSVCR120_erff +@ cdecl _o_erfl(double) MSVCR120_erfl @ cdecl _o_exit(long) MSVCRT_exit -@ stub _o_exp -@ stub _o_exp2 -@ stub _o_exp2f -@ stub _o_exp2l -@ stub _o_expf -@ stub _o_fabs -@ stub _o_fclose -@ stub _o_feof -@ stub _o_ferror -@ stub _o_fflush -@ stub _o_fgetc -@ stub _o_fgetpos -@ stub _o_fgets -@ stub _o_fgetwc -@ stub _o_fgetws +@ cdecl _o_exp(double) MSVCRT_exp +@ cdecl _o_exp2(double) MSVCR120_exp2 +@ cdecl _o_exp2f(float) MSVCR120_exp2f +@ cdecl _o_exp2l(double) MSVCR120_exp2l +@ cdecl -arch=!i386 _o_expf(float) MSVCRT_expf +@ cdecl _o_fabs(double) MSVCRT_fabs +@ cdecl _o_fclose(ptr) MSVCRT_fclose +@ cdecl _o_feof(ptr) MSVCRT_feof +@ cdecl _o_ferror(ptr) MSVCRT_ferror +@ cdecl _o_fflush(ptr) MSVCRT_fflush +@ cdecl _o_fgetc(ptr) MSVCRT_fgetc +@ cdecl _o_fgetpos(ptr ptr) MSVCRT_fgetpos +@ cdecl _o_fgets(ptr long ptr) MSVCRT_fgets +@ cdecl _o_fgetwc(ptr) MSVCRT_fgetwc +@ cdecl _o_fgetws(ptr long ptr) MSVCRT_fgetws @ cdecl _o_floor(double) MSVCRT_floor -@ stub _o_floorf -@ stub _o_fma -@ stub _o_fmaf -@ stub _o_fmal +@ cdecl -arch=!i386 _o_floorf(float) MSVCRT_floorf +@ cdecl _o_fma(double double double) MSVCRT_fma +@ cdecl _o_fmaf(float float float) MSVCRT_fmaf +@ cdecl _o_fmal(double double double) MSVCRT_fma @ cdecl _o_fmod(double double) MSVCRT_fmod @ cdecl -arch=!i386 _o_fmodf(float float) MSVCRT_fmodf -@ stub _o_fopen -@ stub _o_fopen_s -@ stub _o_fputc -@ stub _o_fputs -@ stub _o_fputwc -@ stub _o_fputws -@ stub _o_fread -@ stub _o_fread_s +@ cdecl _o_fopen(str str) MSVCRT_fopen +@ cdecl _o_fopen_s(ptr str str) MSVCRT_fopen_s +@ cdecl _o_fputc(long ptr) MSVCRT_fputc +@ cdecl _o_fputs(str ptr) MSVCRT_fputs +@ cdecl _o_fputwc(long ptr) MSVCRT_fputwc +@ cdecl _o_fputws(wstr ptr) MSVCRT_fputws +@ cdecl _o_fread(ptr long long ptr) MSVCRT_fread +@ cdecl _o_fread_s(ptr long long long ptr) MSVCRT_fread_s @ cdecl _o_free(ptr) MSVCRT_free -@ stub _o_freopen -@ stub _o_freopen_s -@ stub _o_frexp -@ stub _o_fseek -@ stub _o_fsetpos -@ stub _o_ftell -@ stub _o_fwrite -@ stub _o_getc -@ stub _o_getchar +@ cdecl _o_freopen(str str ptr) MSVCRT_freopen +@ cdecl _o_freopen_s(ptr str str ptr) MSVCRT_freopen_s +@ cdecl _o_frexp(double ptr) MSVCRT_frexp +@ cdecl _o_fseek(ptr long long) MSVCRT_fseek +@ cdecl _o_fsetpos(ptr ptr) MSVCRT_fsetpos +@ cdecl _o_ftell(ptr) MSVCRT_ftell +@ cdecl _o_fwrite(ptr long long ptr) MSVCRT_fwrite +@ cdecl _o_getc(ptr) MSVCRT_getc +@ cdecl _o_getchar() MSVCRT_getchar @ cdecl _o_getenv(str) MSVCRT_getenv -@ stub _o_getenv_s -@ stub _o_gets -@ stub _o_gets_s -@ stub _o_getwc -@ stub _o_getwchar -@ stub _o_hypot -@ stub _o_is_wctype +@ cdecl _o_getenv_s(ptr ptr long str) getenv_s +@ cdecl _o_gets(str) MSVCRT_gets +@ cdecl _o_gets_s(ptr long) MSVCRT_gets_s +@ cdecl _o_getwc(ptr) MSVCRT_getwc +@ cdecl _o_getwchar() MSVCRT_getwchar +@ cdecl _o_hypot(double double) _hypot +@ cdecl _o_is_wctype(long long) MSVCRT_iswctype @ cdecl _o_isalnum(long) MSVCRT_isalnum @ cdecl _o_isalpha(long) MSVCRT_isalpha -@ stub _o_isblank -@ stub _o_iscntrl +@ cdecl _o_isblank(long) MSVCRT_isblank +@ cdecl _o_iscntrl(long) MSVCRT_iscntrl @ cdecl _o_isdigit(long) MSVCRT_isdigit -@ stub _o_isgraph -@ stub _o_isleadbyte -@ stub _o_islower +@ cdecl _o_isgraph(long) MSVCRT_isgraph +@ cdecl _o_isleadbyte(long) MSVCRT_isleadbyte +@ cdecl _o_islower(long) MSVCRT_islower @ cdecl _o_isprint(long) MSVCRT_isprint -@ stub _o_ispunct -@ stub _o_isspace -@ stub _o_isupper -@ stub _o_iswalnum -@ stub _o_iswalpha -@ stub _o_iswascii -@ stub _o_iswblank -@ stub _o_iswcntrl -@ stub _o_iswctype -@ stub _o_iswdigit -@ stub _o_iswgraph -@ stub _o_iswlower -@ stub _o_iswprint -@ stub _o_iswpunct -@ stub _o_iswspace -@ stub _o_iswupper -@ stub _o_iswxdigit +@ cdecl _o_ispunct(long) MSVCRT_ispunct +@ cdecl _o_isspace(long) MSVCRT_isspace +@ cdecl _o_isupper(long) MSVCRT_isupper +@ cdecl _o_iswalnum(long) MSVCRT_iswalnum +@ cdecl _o_iswalpha(long) MSVCRT_iswalpha +@ cdecl _o_iswascii(long) MSVCRT_iswascii +@ cdecl _o_iswblank(long) MSVCRT_iswblank +@ cdecl _o_iswcntrl(long) MSVCRT_iswcntrl +@ cdecl _o_iswctype(long long) MSVCRT_iswctype +@ cdecl _o_iswdigit(long) MSVCRT_iswdigit +@ cdecl _o_iswgraph(long) MSVCRT_iswgraph +@ cdecl _o_iswlower(long) MSVCRT_iswlower +@ cdecl _o_iswprint(long) MSVCRT_iswprint +@ cdecl _o_iswpunct(long) MSVCRT_iswpunct +@ cdecl _o_iswspace(long) MSVCRT_iswspace +@ cdecl _o_iswupper(long) MSVCRT_iswupper +@ cdecl _o_iswxdigit(long) MSVCRT_iswxdigit @ cdecl _o_isxdigit(long) MSVCRT_isxdigit -@ stub _o_ldexp -@ stub _o_lgamma -@ stub _o_lgammaf -@ stub _o_lgammal -@ stub _o_llrint -@ stub _o_llrintf -@ stub _o_llrintl -@ stub _o_llround -@ stub _o_llroundf -@ stub _o_llroundl -@ stub _o_localeconv +@ cdecl _o_ldexp(double long) MSVCRT_ldexp +@ cdecl _o_lgamma(double) MSVCR120_lgamma +@ cdecl _o_lgammaf(float) MSVCR120_lgammaf +@ cdecl _o_lgammal(double) MSVCR120_lgammal +@ cdecl -ret64 _o_llrint(double) MSVCR120_llrint +@ cdecl -ret64 _o_llrintf(float) MSVCR120_llrintf +@ cdecl -ret64 _o_llrintl(double) MSVCR120_llrintl +@ cdecl -ret64 _o_llround(double) MSVCR120_llround +@ cdecl -ret64 _o_llroundf(float) MSVCR120_llroundf +@ cdecl -ret64 _o_llroundl(double) MSVCR120_llroundl +@ cdecl _o_localeconv() MSVCRT_localeconv @ cdecl _o_log(double) MSVCRT_log -@ stub _o_log10 -@ stub _o_log10f -@ stub _o_log1p -@ stub _o_log1pf -@ stub _o_log1pl -@ stub _o_log2 -@ stub _o_log2f -@ stub _o_log2l -@ stub _o_logb -@ stub _o_logbf -@ stub _o_logbl -@ stub _o_logf -@ stub _o_lrint -@ stub _o_lrintf -@ stub _o_lrintl -@ stub _o_lround -@ stub _o_lroundf -@ stub _o_lroundl +@ cdecl _o_log10(double) MSVCRT_log10 +@ cdecl -arch=!i386 _o_log10f(float) MSVCRT_log10f +@ cdecl _o_log1p(double) MSVCR120_log1p +@ cdecl _o_log1pf(float) MSVCR120_log1pf +@ cdecl _o_log1pl(double) MSVCR120_log1pl +@ cdecl _o_log2(double) MSVCR120_log2 +@ cdecl _o_log2f(float) MSVCR120_log2f +@ cdecl _o_log2l(double) MSVCR120_log2l +@ cdecl _o_logb(double) MSVCRT__logb +@ cdecl _o_logbf(float) MSVCRT__logbf +@ cdecl _o_logbl(double) MSVCRT__logb +@ cdecl -arch=!i386 _o_logf(float) MSVCRT_logf +@ cdecl _o_lrint(double) MSVCR120_lrint +@ cdecl _o_lrintf(float) MSVCR120_lrintf +@ cdecl _o_lrintl(double) MSVCR120_lrintl +@ cdecl _o_lround(double) MSVCR120_lround +@ cdecl _o_lroundf(float) MSVCR120_lroundf +@ cdecl _o_lroundl(double) MSVCR120_lroundl @ cdecl _o_malloc(long) MSVCRT_malloc -@ stub _o_mblen -@ stub _o_mbrlen +@ cdecl _o_mblen(ptr long) MSVCRT_mblen +@ cdecl _o_mbrlen(ptr long ptr) MSVCRT_mbrlen @ stub _o_mbrtoc16 @ stub _o_mbrtoc32 -@ stub _o_mbrtowc -@ stub _o_mbsrtowcs -@ stub _o_mbsrtowcs_s -@ stub _o_mbstowcs -@ stub _o_mbstowcs_s -@ stub _o_mbtowc -@ stub _o_memcpy_s -@ stub _o_memset +@ cdecl _o_mbrtowc(ptr str long ptr) MSVCRT_mbrtowc +@ cdecl _o_mbsrtowcs(ptr ptr long ptr) MSVCRT_mbsrtowcs +@ cdecl _o_mbsrtowcs_s(ptr ptr long ptr long ptr) MSVCRT_mbsrtowcs_s +@ cdecl _o_mbstowcs(ptr str long) MSVCRT_mbstowcs +@ cdecl _o_mbstowcs_s(ptr ptr long str long) MSVCRT__mbstowcs_s +@ cdecl _o_mbtowc(ptr str long) MSVCRT_mbtowc +@ cdecl _o_memcpy_s(ptr long ptr long) MSVCRT_memcpy_s +@ cdecl _o_memset(ptr long long) MSVCRT_memset @ cdecl _o_modf(double ptr) MSVCRT_modf -@ stub _o_modff -@ stub _o_nan -@ stub _o_nanf -@ stub _o_nanl -@ stub _o_nearbyint -@ stub _o_nearbyintf -@ stub _o_nearbyintl -@ stub _o_nextafter -@ stub _o_nextafterf -@ stub _o_nextafterl -@ stub _o_nexttoward -@ stub _o_nexttowardf -@ stub _o_nexttowardl +@ cdecl -arch=!i386 _o_modff(float ptr) MSVCRT_modff +@ cdecl _o_nan(str) MSVCR120_nan +@ cdecl _o_nanf(str) MSVCR120_nanf +@ cdecl _o_nanl(str) MSVCR120_nan +@ cdecl _o_nearbyint(double) MSVCRT_nearbyint +@ cdecl _o_nearbyintf(float) MSVCRT_nearbyintf +@ cdecl _o_nearbyintl(double) MSVCRT_nearbyint +@ cdecl _o_nextafter(double double) MSVCRT__nextafter +@ cdecl _o_nextafterf(float float) MSVCRT__nextafterf +@ cdecl _o_nextafterl(double double) MSVCRT__nextafter +@ cdecl _o_nexttoward(double double) MSVCRT_nexttoward +@ cdecl _o_nexttowardf(float double) MSVCRT_nexttowardf +@ cdecl _o_nexttowardl(double double) MSVCRT_nexttoward @ cdecl _o_pow(double double) MSVCRT_pow -@ stub _o_powf -@ stub _o_putc -@ stub _o_putchar -@ stub _o_puts -@ stub _o_putwc -@ stub _o_putwchar +@ cdecl -arch=!i386 _o_powf(float float) MSVCRT_powf +@ cdecl _o_putc(long ptr) MSVCRT_putc +@ cdecl _o_putchar(long) MSVCRT_putchar +@ cdecl _o_puts(str) MSVCRT_puts +@ cdecl _o_putwc(long ptr) MSVCRT_fputwc +@ cdecl _o_putwchar(long) MSVCRT__fputwchar @ cdecl _o_qsort(ptr long long ptr) MSVCRT_qsort -@ stub _o_qsort_s -@ stub _o_raise -@ stub _o_rand -@ stub _o_rand_s +@ cdecl _o_qsort_s(ptr long long ptr ptr) MSVCRT_qsort_s +@ cdecl _o_raise(long) MSVCRT_raise +@ cdecl _o_rand() MSVCRT_rand +@ cdecl _o_rand_s(ptr) MSVCRT_rand_s @ cdecl _o_realloc(ptr long) MSVCRT_realloc -@ stub _o_remainder -@ stub _o_remainderf -@ stub _o_remainderl -@ stub _o_remove -@ stub _o_remquo -@ stub _o_remquof -@ stub _o_remquol -@ stub _o_rename -@ stub _o_rewind -@ stub _o_rint -@ stub _o_rintf -@ stub _o_rintl -@ stub _o_round -@ stub _o_roundf -@ stub _o_roundl -@ stub _o_scalbln -@ stub _o_scalblnf -@ stub _o_scalblnl -@ stub _o_scalbn -@ stub _o_scalbnf -@ stub _o_scalbnl -@ stub _o_set_terminate -@ stub _o_setbuf +@ cdecl _o_remainder(double double) MSVCR120_remainder +@ cdecl _o_remainderf(float float) MSVCR120_remainderf +@ cdecl _o_remainderl(double double) MSVCR120_remainderl +@ cdecl _o_remove(str) MSVCRT_remove +@ cdecl _o_remquo(double double ptr) MSVCR120_remquo +@ cdecl _o_remquof(float float ptr) MSVCR120_remquof +@ cdecl _o_remquol(double double ptr) MSVCR120_remquol +@ cdecl _o_rename(str str) MSVCRT_rename +@ cdecl _o_rewind(ptr) MSVCRT_rewind +@ cdecl _o_rint(double) MSVCR120_rint +@ cdecl _o_rintf(float) MSVCR120_rintf +@ cdecl _o_rintl(double) MSVCR120_rintl +@ cdecl _o_round(double) MSVCR120_round +@ cdecl _o_roundf(float) MSVCR120_roundf +@ cdecl _o_roundl(double) MSVCR120_roundl +@ cdecl _o_scalbln(double long) MSVCRT__scalb +@ cdecl _o_scalblnf(float long) MSVCRT__scalbf +@ cdecl _o_scalblnl(double long) MSVCR120_scalbnl +@ cdecl _o_scalbn(double long) MSVCRT__scalb +@ cdecl _o_scalbnf(float long) MSVCRT__scalbf +@ cdecl _o_scalbnl(double long) MSVCR120_scalbnl +@ cdecl _o_set_terminate(ptr) MSVCRT_set_terminate +@ cdecl _o_setbuf(ptr ptr) MSVCRT_setbuf @ cdecl _o_setlocale(long str) MSVCRT_setlocale -@ stub _o_setvbuf -@ stub _o_sin -@ stub _o_sinf -@ stub _o_sinh -@ stub _o_sinhf +@ cdecl _o_setvbuf(ptr str long long) MSVCRT_setvbuf +@ cdecl _o_sin(double) MSVCRT_sin +@ cdecl -arch=!i386 _o_sinf(float) MSVCRT_sinf +@ cdecl _o_sinh(double) MSVCRT_sinh +@ cdecl -arch=!i386 _o_sinhf(float) MSVCRT_sinhf @ cdecl _o_sqrt(double) MSVCRT_sqrt -@ stub _o_sqrtf -@ stub _o_srand +@ cdecl -arch=!i386 _o_sqrtf(float) MSVCRT_sqrtf +@ cdecl _o_srand(long) MSVCRT_srand @ cdecl _o_strcat_s(str long str) MSVCRT_strcat_s -@ stub _o_strcoll -@ stub _o_strcpy_s -@ stub _o_strerror -@ stub _o_strerror_s -@ stub _o_strftime -@ stub _o_strncat_s -@ stub _o_strncpy_s -@ stub _o_strtod -@ stub _o_strtof -@ stub _o_strtok -@ stub _o_strtok_s -@ stub _o_strtol +@ cdecl _o_strcoll(str str) MSVCRT_strcoll +@ cdecl _o_strcpy_s(ptr long str) MSVCRT_strcpy_s +@ cdecl _o_strerror(long) MSVCRT_strerror +@ cdecl _o_strerror_s(ptr long long) MSVCRT_strerror_s +@ cdecl _o_strftime(ptr long str ptr) MSVCRT_strftime +@ cdecl _o_strncat_s(str long str long) MSVCRT_strncat_s +@ cdecl _o_strncpy_s(ptr long str long) MSVCRT_strncpy_s +@ cdecl _o_strtod(str ptr) MSVCRT_strtod +@ cdecl _o_strtof(str ptr) MSVCRT_strtof +@ cdecl _o_strtok(str str) MSVCRT_strtok +@ cdecl _o_strtok_s(ptr str ptr) MSVCRT_strtok_s +@ cdecl _o_strtol(str ptr long) MSVCRT_strtol @ stub _o_strtold -@ stub _o_strtoll +@ cdecl -ret64 _o_strtoll(str ptr long) MSVCRT_strtoi64 @ cdecl _o_strtoul(str ptr long) MSVCRT_strtoul -@ stub _o_strtoull -@ stub _o_system -@ stub _o_tan -@ stub _o_tanf -@ stub _o_tanh -@ stub _o_tanhf -@ stub _o_terminate -@ stub _o_tgamma -@ stub _o_tgammaf -@ stub _o_tgammal -@ stub _o_tmpfile_s -@ stub _o_tmpnam_s +@ cdecl -ret64 _o_strtoull(str ptr long) MSVCRT_strtoui64 +@ cdecl _o_system(str) MSVCRT_system +@ cdecl _o_tan(double) MSVCRT_tan +@ cdecl -arch=!i386 _o_tanf(float) MSVCRT_tanf +@ cdecl _o_tanh(double) MSVCRT_tanh +@ cdecl -arch=!i386 _o_tanhf(float) MSVCRT_tanhf +@ cdecl _o_terminate() MSVCRT_terminate +@ cdecl _o_tgamma(double) MSVCR120_tgamma +@ cdecl _o_tgammaf(float) MSVCR120_tgammaf +@ cdecl _o_tgammal(double) MSVCR120_tgamma +@ cdecl _o_tmpfile_s(ptr) MSVCRT_tmpfile_s +@ cdecl _o_tmpnam_s(ptr long) MSVCRT_tmpnam_s @ cdecl _o_tolower(long) MSVCRT_tolower @ cdecl _o_toupper(long) MSVCRT_toupper -@ stub _o_towlower -@ stub _o_towupper -@ stub _o_ungetc -@ stub _o_ungetwc -@ stub _o_wcrtomb -@ stub _o_wcrtomb_s -@ stub _o_wcscat_s -@ stub _o_wcscoll -@ stub _o_wcscpy -@ stub _o_wcscpy_s -@ stub _o_wcsftime -@ stub _o_wcsncat_s -@ stub _o_wcsncpy_s -@ stub _o_wcsrtombs -@ stub _o_wcsrtombs_s -@ stub _o_wcstod -@ stub _o_wcstof -@ stub _o_wcstok -@ stub _o_wcstok_s -@ stub _o_wcstol +@ cdecl _o_towlower(long) MSVCRT_towlower +@ cdecl _o_towupper(long) MSVCRT_towupper +@ cdecl _o_ungetc(long ptr) MSVCRT_ungetc +@ cdecl _o_ungetwc(long ptr) MSVCRT_ungetwc +@ cdecl _o_wcrtomb(ptr long ptr) MSVCRT_wcrtomb +@ cdecl _o_wcrtomb_s(ptr ptr long long ptr) MSVCRT_wcrtomb_s +@ cdecl _o_wcscat_s(wstr long wstr) MSVCRT_wcscat_s +@ cdecl _o_wcscoll(wstr wstr) MSVCRT_wcscoll +@ cdecl _o_wcscpy(ptr wstr) ntdll.wcscpy +@ cdecl _o_wcscpy_s(ptr long wstr) MSVCRT_wcscpy_s +@ cdecl _o_wcsftime(ptr long wstr ptr) MSVCRT_wcsftime +@ cdecl _o_wcsncat_s(wstr long wstr long) MSVCRT_wcsncat_s +@ cdecl _o_wcsncpy_s(ptr long wstr long) MSVCRT_wcsncpy_s +@ cdecl _o_wcsrtombs(ptr ptr long ptr) MSVCRT_wcsrtombs +@ cdecl _o_wcsrtombs_s(ptr ptr long ptr long ptr) MSVCRT_wcsrtombs_s +@ cdecl _o_wcstod(wstr ptr) MSVCRT_wcstod +@ cdecl _o_wcstof(ptr ptr) MSVCRT_wcstof +@ cdecl _o_wcstok(wstr wstr ptr) MSVCRT_wcstok +@ cdecl _o_wcstok_s(ptr wstr ptr) MSVCRT_wcstok_s +@ cdecl _o_wcstol(wstr ptr long) MSVCRT_wcstol @ stub _o_wcstold -@ stub _o_wcstoll -@ stub _o_wcstombs -@ stub _o_wcstombs_s -@ stub _o_wcstoul -@ stub _o_wcstoull -@ stub _o_wctob -@ stub _o_wctomb -@ stub _o_wctomb_s -@ stub _o_wmemcpy_s -@ stub _o_wmemmove_s +@ cdecl -ret64 _o_wcstoll(wstr ptr long) MSVCRT__wcstoi64 +@ cdecl _o_wcstombs(ptr ptr long) MSVCRT_wcstombs +@ cdecl _o_wcstombs_s(ptr ptr long wstr long) MSVCRT_wcstombs_s +@ cdecl _o_wcstoul(wstr ptr long) MSVCRT_wcstoul +@ cdecl -ret64 _o_wcstoull(wstr ptr long) MSVCRT__wcstoui64 +@ cdecl _o_wctob(long) MSVCRT_wctob +@ cdecl _o_wctomb(ptr long) MSVCRT_wctomb +@ cdecl _o_wctomb_s(ptr ptr long long) MSVCRT_wctomb_s +@ cdecl _o_wmemcpy_s(ptr long ptr long) wmemcpy_s +@ cdecl _o_wmemmove_s(ptr long ptr long) wmemmove_s @ varargs _open(str long) MSVCRT__open @ cdecl _open_osfhandle(long long) MSVCRT__open_osfhandle @ cdecl _pclose(ptr) MSVCRT__pclose diff -Nru wine-development-5.8/dlls/user32/input.c wine-development-5.9/dlls/user32/input.c --- wine-development-5.8/dlls/user32/input.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/user32/input.c 2020-05-22 18:49:34.000000000 +0000 @@ -555,7 +555,7 @@ { req->tid = GetCurrentThreadId(); req->key = vkey; - if (!wine_server_call( req )) retval = (signed char)reply->state; + if (!wine_server_call( req )) retval = (signed char)(reply->state & 0x81); } SERVER_END_REQ; TRACE("key (0x%x) -> %x\n", vkey, retval); @@ -569,6 +569,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetKeyboardState( LPBYTE state ) { BOOL ret; + UINT i; TRACE("(%p)\n", state); @@ -579,6 +580,7 @@ req->key = -1; wine_server_set_reply( req, state, 256 ); ret = !wine_server_call_err( req ); + for (i = 0; i < 256; i++) state[i] &= 0x81; } SERVER_END_REQ; return ret; diff -Nru wine-development-5.8/dlls/user32/tests/input.c wine-development-5.9/dlls/user32/tests/input.c --- wine-development-5.8/dlls/user32/tests/input.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/user32/tests/input.c 2020-05-22 18:49:34.000000000 +0000 @@ -2759,6 +2759,9 @@ ok((result & 0x8000) || broken(!(result & 0x8000)), /* > Win 2003 */ "expected that highest bit is set, got %x\n", result); + ok((SHORT)(result & 0x007e) == 0, + "expected that undefined bits are unset, got %x\n", result); + ReleaseSemaphore(semaphores[0], 1, NULL); result = WaitForSingleObject(semaphores[1], 1000); ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); @@ -2766,6 +2769,9 @@ result = GetKeyState('X'); ok(!(result & 0x8000), "expected that highest bit is unset, got %x\n", result); + ok((SHORT)(result & 0x007e) == 0, + "expected that undefined bits are unset, got %x\n", result); + return 0; } diff -Nru wine-development-5.8/dlls/vcruntime140_1/except_x86_64.c wine-development-5.9/dlls/vcruntime140_1/except_x86_64.c --- wine-development-5.8/dlls/vcruntime140_1/except_x86_64.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/vcruntime140_1/except_x86_64.c 2020-05-22 18:49:34.000000000 +0000 @@ -603,7 +603,8 @@ (ULONG_PTR)rva_to_ptr(ci.handler, dispatch->ImageBase); catch_record.ExceptionInformation[6] = (ULONG_PTR)untrans_rec; catch_record.ExceptionInformation[7] = (ULONG_PTR)context; - catch_record.ExceptionInformation[8] = (ULONG_PTR)rva_to_ptr( + if (ci.ret_addr) + catch_record.ExceptionInformation[8] = (ULONG_PTR)rva_to_ptr( ci.ret_addr + dispatch->FunctionEntry->BeginAddress, dispatch->ImageBase); RtlUnwindEx((void*)frame, (void*)dispatch->ControlPc, &catch_record, NULL, &ctx, NULL); } diff -Nru wine-development-5.8/dlls/wbemprox/builtin.c wine-development-5.9/dlls/wbemprox/builtin.c --- wine-development-5.8/dlls/wbemprox/builtin.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wbemprox/builtin.c 2020-05-22 18:49:34.000000000 +0000 @@ -243,7 +243,7 @@ { L"OSProductSuite", CIM_UINT32 }, { L"OSType", CIM_UINT16 }, { L"Primary", CIM_BOOLEAN }, - { L"SerialNumber", CIM_STRING }, + { L"SerialNumber", CIM_STRING|COL_FLAG_DYNAMIC }, { L"ServicePackMajorVersion", CIM_UINT16 }, { L"ServicePackMinorVersion", CIM_UINT16 }, { L"SuiteMask", CIM_UINT32 }, @@ -3360,6 +3360,27 @@ memcpy( ret + len, partitionW, sizeof(partitionW) ); return ret; } +static WCHAR *get_osserialnumber(void) +{ + HKEY hkey = 0; + DWORD size, type; + WCHAR *ret = NULL; + + if (!RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hkey ) && + !RegQueryValueExW( hkey, L"ProductId", NULL, &type, NULL, &size ) && type == REG_SZ && + (ret = heap_alloc( size + sizeof(WCHAR) ))) + { + size += sizeof(WCHAR); + if (RegQueryValueExW( hkey, L"ProductId", NULL, NULL, (BYTE *)ret, &size )) + { + heap_free( ret ); + ret = NULL; + } + } + if (hkey) RegCloseKey( hkey ); + if (!ret) return heap_strdupW( L"12345-OEM-1234567-12345" ); + return ret; +} static WCHAR *get_osversion( OSVERSIONINFOEXW *ver ) { WCHAR *ret = heap_alloc( 33 * sizeof(WCHAR) ); @@ -3414,7 +3435,7 @@ rec->osproductsuite = 2461140; /* Windows XP Professional */ rec->ostype = 18; /* WINNT */ rec->primary = -1; - rec->serialnumber = L"12345-OEM-1234567-12345"; + rec->serialnumber = get_osserialnumber(); rec->servicepackmajor = ver.wServicePackMajor; rec->servicepackminor = ver.wServicePackMinor; rec->suitemask = 272; /* Single User + Terminal */ @@ -3761,7 +3782,7 @@ static WCHAR *get_pnpdeviceid( DXGI_ADAPTER_DESC *desc ) { - static const WCHAR *fmtW = L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X\\0&DEADBEEF&0&DEAD"; + static const WCHAR fmtW[] = L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X\\0&DEADBEEF&0&DEAD"; UINT len = sizeof(fmtW) + 2; WCHAR *ret; diff -Nru wine-development-5.8/dlls/windowscodecs/ddsformat.c wine-development-5.9/dlls/windowscodecs/ddsformat.c --- wine-development-5.8/dlls/windowscodecs/ddsformat.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/windowscodecs/ddsformat.c 2020-05-22 18:49:34.000000000 +0000 @@ -48,6 +48,15 @@ #define DDPF_LUMINANCE 0x00020000 #define DDPF_BUMPDUDV 0x00080000 +#define DDSCAPS2_CUBEMAP 0x00000200 +#define DDSCAPS2_VOLUME 0x00200000 + +#define DDS_DIMENSION_TEXTURE1D 2 +#define DDS_DIMENSION_TEXTURE2D 3 +#define DDS_DIMENSION_TEXTURE3D 4 + +#define DDS_RESOURCE_MISC_TEXTURECUBE 0x00000004 + typedef struct { DWORD size; DWORD flags; @@ -107,6 +116,65 @@ (header->ddspf.fourCC == MAKEFOURCC('D', 'X', '1', '0')); } +static WICDdsDimension get_dimension(DDS_HEADER *header, DDS_HEADER_DXT10 *header_dxt10) +{ + if (header_dxt10) { + if (header_dxt10->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE) return WICDdsTextureCube; + switch (header_dxt10->resourceDimension) + { + case DDS_DIMENSION_TEXTURE1D: return WICDdsTexture1D; + case DDS_DIMENSION_TEXTURE2D: return WICDdsTexture2D; + case DDS_DIMENSION_TEXTURE3D: return WICDdsTexture3D; + default: return WICDdsTexture2D; + } + } else { + if (header->caps2 & DDSCAPS2_CUBEMAP) { + return WICDdsTextureCube; + } else if (header->caps2 & DDSCAPS2_VOLUME) { + return WICDdsTexture3D; + } else { + return WICDdsTexture2D; + } + } +} + +static DXGI_FORMAT get_format_from_fourcc(DWORD fourcc) +{ + switch (fourcc) + { + case MAKEFOURCC('D', 'X', 'T', '1'): + return DXGI_FORMAT_BC1_UNORM; + case MAKEFOURCC('D', 'X', 'T', '2'): + case MAKEFOURCC('D', 'X', 'T', '3'): + return DXGI_FORMAT_BC2_UNORM; + case MAKEFOURCC('D', 'X', 'T', '4'): + case MAKEFOURCC('D', 'X', 'T', '5'): + return DXGI_FORMAT_BC3_UNORM; + case MAKEFOURCC('D', 'X', '1', '0'): + /* format is indicated in extended header */ + return DXGI_FORMAT_UNKNOWN; + default: + /* there are DDS files where fourCC is set directly to DXGI_FORMAT enumeration value */ + return fourcc; + } +} + +static WICDdsAlphaMode get_alpha_mode_from_fourcc(DWORD fourcc) +{ + switch (fourcc) + { + case MAKEFOURCC('D', 'X', 'T', '1'): + case MAKEFOURCC('D', 'X', 'T', '2'): + case MAKEFOURCC('D', 'X', 'T', '4'): + return WICDdsAlphaModePremultiplied; + case MAKEFOURCC('D', 'X', 'T', '3'): + case MAKEFOURCC('D', 'X', 'T', '5'): + return WICDdsAlphaModeStraight; + default: + return WICDdsAlphaModeUnknown; + } +} + static inline DdsDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) { return CONTAINING_RECORD(iface, DdsDecoder, IWICBitmapDecoder_iface); @@ -587,9 +655,47 @@ static HRESULT WINAPI DdsDecoder_Dds_GetParameters(IWICDdsDecoder *iface, WICDdsParameters *parameters) { - TRACE("(%p,%p): Stub.\n", iface, parameters); + DdsDecoder *This = impl_from_IWICDdsDecoder(iface); + HRESULT hr; - return E_NOTIMPL; + if (!parameters) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (!This->initialized) { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + parameters->Width = This->header.width; + parameters->Height = This->header.height; + parameters->Depth = 1; + parameters->MipLevels = 1; + parameters->ArraySize = 1; + if (This->header.depth) parameters->Depth = This->header.depth; + if (This->header.mipMapCount) parameters->MipLevels = This->header.mipMapCount; + + if (has_extended_header(&This->header)) { + if (This->header_dxt10.arraySize) parameters->ArraySize = This->header_dxt10.arraySize; + parameters->DxgiFormat = This->header_dxt10.dxgiFormat; + parameters->Dimension = get_dimension(NULL, &This->header_dxt10); + parameters->AlphaMode = This->header_dxt10.miscFlags2 & 0x00000008; + } else { + parameters->DxgiFormat = get_format_from_fourcc(This->header.ddspf.fourCC); + parameters->Dimension = get_dimension(&This->header, NULL); + parameters->AlphaMode = get_alpha_mode_from_fourcc(This->header.ddspf.fourCC); + } + + TRACE("(%p) -> (%dx%d depth=%d mipLevels=%d arraySize=%d dxgiFormat=0x%x dimension=0x%x alphaMode=0x%x)\n", + iface, parameters->Width, parameters->Height, parameters->Depth, parameters->MipLevels, + parameters->ArraySize, parameters->DxgiFormat, parameters->Dimension, parameters->AlphaMode); + + hr = S_OK; + +end: + LeaveCriticalSection(&This->lock); + + return hr; } static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface, diff -Nru wine-development-5.8/dlls/windowscodecs/tests/ddsformat.c wine-development-5.9/dlls/windowscodecs/tests/ddsformat.c --- wine-development-5.8/dlls/windowscodecs/tests/ddsformat.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/windowscodecs/tests/ddsformat.c 2020-05-22 18:49:34.000000000 +0000 @@ -120,6 +120,21 @@ 0xCC, 0x55, 0xCC, 0x55, 0x0E, 0x84, 0x0E, 0x84, 0x00, 0x00, 0x00, 0x00 }; +static struct test_data { + void *data; + UINT size; + UINT expected_frame_count; + WICDdsParameters expected_parameters; +} test_data[] = { + { test_dds_image, sizeof(test_dds_image), 1, + { 4, 4, 1, 1, 1, DXGI_FORMAT_BC1_UNORM, WICDdsTexture2D, WICDdsAlphaModePremultiplied } }, + { test_dds_mipmaps, sizeof(test_dds_mipmaps), 3, + { 4, 4, 1, 3, 1, DXGI_FORMAT_BC1_UNORM, WICDdsTexture2D, WICDdsAlphaModePremultiplied } }, + { test_dds_volume, sizeof(test_dds_volume), 7, + { 4, 4, 4, 3, 1, DXGI_FORMAT_BC1_UNORM, WICDdsTexture3D, WICDdsAlphaModePremultiplied } }, + { test_dds_array, sizeof(test_dds_array), 9, + { 4, 4, 1, 3, 3, DXGI_FORMAT_BC1_UNORM, WICDdsTexture2D, WICDdsAlphaModeUnknown } }, +}; static IWICImagingFactory *factory = NULL; @@ -234,16 +249,16 @@ static void test_dds_decoder_global_properties(IWICBitmapDecoder *decoder) { HRESULT hr; - IWICPalette *pallette = NULL; + IWICPalette *palette = NULL; IWICMetadataQueryReader *metadata_reader = NULL; IWICBitmapSource *preview = NULL, *thumnail = NULL; IWICColorContext *color_context = NULL; UINT count; - hr = IWICImagingFactory_CreatePalette(factory, &pallette); + hr = IWICImagingFactory_CreatePalette(factory, &palette); ok (hr == S_OK, "CreatePalette failed, hr=%x\n", hr); if (hr == S_OK) { - hr = IWICBitmapDecoder_CopyPalette(decoder, pallette); + hr = IWICBitmapDecoder_CopyPalette(decoder, palette); ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "Expected hr=WINCODEC_ERR_PALETTEUNAVAILABLE, got %x\n", hr); hr = IWICBitmapDecoder_CopyPalette(decoder, NULL); ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "Expected hr=WINCODEC_ERR_PALETTEUNAVAILABLE, got %x\n", hr); @@ -269,34 +284,25 @@ hr = IWICBitmapDecoder_GetThumbnail(decoder, NULL); ok (hr == WINCODEC_ERR_CODECNOTHUMBNAIL, "Expected hr=WINCODEC_ERR_CODECNOTHUMBNAIL, got %x\n", hr); - if (pallette) IWICPalette_Release(pallette); + if (palette) IWICPalette_Release(palette); if (metadata_reader) IWICMetadataQueryReader_Release(metadata_reader); if (preview) IWICBitmapSource_Release(preview); if (color_context) IWICColorContext_Release(color_context); if (thumnail) IWICBitmapSource_Release(thumnail); } -static void test_dds_decoder_frame_count(void) +static void test_dds_decoder_image_parameters(void) { - static struct test_data { - void *data; - UINT size; - UINT expected; - } test_data[] = { - { test_dds_image, sizeof(test_dds_image), 1 }, - { test_dds_mipmaps, sizeof(test_dds_mipmaps), 3 }, - { test_dds_volume, sizeof(test_dds_volume), 7 }, - { test_dds_array, sizeof(test_dds_array), 9 }, - }; - int i; HRESULT hr; + WICDdsParameters parameters; for (i = 0; i < ARRAY_SIZE(test_data); i++) { UINT frame_count; IWICStream *stream = NULL; IWICBitmapDecoder *decoder = NULL; + IWICDdsDecoder *dds_decoder = NULL; stream = create_stream(test_data[i].data, test_data[i].size); if (!stream) goto next; @@ -304,52 +310,151 @@ decoder = create_decoder(); if (!decoder) goto next; + hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICDdsDecoder, (void **)&dds_decoder); + ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr); + if (hr != S_OK) goto next; + hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); ok (hr == WINCODEC_ERR_WRONGSTATE, "%d: Expected hr=WINCODEC_ERR_WRONGSTATE, got %x\n", i, hr); hr = IWICBitmapDecoder_GetFrameCount(decoder, NULL); ok (hr == E_INVALIDARG, "%d: Expected hr=E_INVALIDARG, got %x\n", i, hr); + hr = IWICDdsDecoder_GetParameters(dds_decoder, ¶meters); + ok(hr == WINCODEC_ERR_WRONGSTATE, "%d: Expected hr=WINCODEC_ERR_WRONGSTATE, got %x\n", i, hr); + hr = IWICDdsDecoder_GetParameters(dds_decoder, NULL); + ok(hr == E_INVALIDARG, "%d: Expected hr=E_INVALIDARG, got %x\n", i, hr); + hr = init_decoder(decoder, stream, S_OK, -1); if (hr != S_OK) goto next; hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); ok (hr == S_OK, "%d: GetFrameCount failed, hr=%x\n", i, hr); if (hr == S_OK) { - ok (frame_count == test_data[i].expected, "%d: expected frame count %d, got %d\n", - i, test_data[i].expected, frame_count); + ok (frame_count == test_data[i].expected_frame_count, "%d: expected frame count %d, got %d\n", + i, test_data[i].expected_frame_count, frame_count); } hr = IWICBitmapDecoder_GetFrameCount(decoder, NULL); ok (hr == E_INVALIDARG, "%d: Expected hr=S_OK, got %x\n", i, hr); + hr = IWICDdsDecoder_GetParameters(dds_decoder, ¶meters); + ok (hr == S_OK, "%d: GetParameters failed, hr=%x\n", i, hr); + if (hr == S_OK) { + ok (parameters.Width == test_data[i].expected_parameters.Width, + "%d, Expected Width=%d, got %d\n", i, test_data[i].expected_parameters.Width, parameters.Width); + ok (parameters.Height == test_data[i].expected_parameters.Height, + "%d, Expected Height=%d, got %d\n", i, test_data[i].expected_parameters.Height, parameters.Height); + ok (parameters.Depth == test_data[i].expected_parameters.Depth, + "%d, Expected Depth=%d, got %d\n", i, test_data[i].expected_parameters.Depth, parameters.Depth); + ok (parameters.MipLevels == test_data[i].expected_parameters.MipLevels, + "%d, Expected MipLevels=%d, got %d\n", i, test_data[i].expected_parameters.MipLevels, parameters.MipLevels); + ok (parameters.ArraySize == test_data[i].expected_parameters.ArraySize, + "%d, Expected ArraySize=%d, got %d\n", i, test_data[i].expected_parameters.ArraySize, parameters.ArraySize); + ok (parameters.DxgiFormat == test_data[i].expected_parameters.DxgiFormat, + "%d, Expected DxgiFormat=0x%x, got 0x%x\n", i, test_data[i].expected_parameters.DxgiFormat, parameters.DxgiFormat); + ok (parameters.Dimension == test_data[i].expected_parameters.Dimension, + "%d, Expected Dimension=0x%x, got 0x%x\n", i, test_data[i].expected_parameters.Dimension, parameters.Dimension); + ok (parameters.AlphaMode == test_data[i].expected_parameters.AlphaMode, + "%d, Expected AlphaMode=0x%x, got 0x%x\n", i, test_data[i].expected_parameters.AlphaMode, parameters.AlphaMode); + } + hr = IWICDdsDecoder_GetParameters(dds_decoder, NULL); + ok (hr == E_INVALIDARG, "%d: Expected hr=E_INVALIDARG, got %x\n", i, hr); + next: if (decoder) IWICBitmapDecoder_Release(decoder); if (stream) IWICStream_Release(stream); + if (dds_decoder) IWICDdsDecoder_Release(dds_decoder); } } -static void test_dds_decoder(void) +static void test_dds_decoder_frame_size(IWICBitmapDecoder *decoder, IWICBitmapFrameDecode *frame_decode, + UINT frame_count, int i, int frame_index) { HRESULT hr; - IWICStream *stream = NULL; - IWICBitmapDecoder *decoder = NULL; - - stream = create_stream(test_dds_image, sizeof(test_dds_image)); - if (!stream) goto end; + WICDdsParameters params; + IWICDdsDecoder *dds_decoder; + UINT width, height ,expected_width, expected_height, slice_index, depth; - decoder = create_decoder(); - if (!decoder) goto end; + hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICDdsDecoder, (void **)&dds_decoder); + ok(hr == S_OK, "%d: QueryInterface failed, hr=%x\n", i, hr); + if (hr != S_OK) goto end; + hr = IWICDdsDecoder_GetParameters(dds_decoder, ¶ms); + ok (hr == S_OK, "%d: GetParameters failed, hr=%x\n", i, hr); + if (hr != S_OK) goto end; - hr = init_decoder(decoder, stream, S_OK, -1); + hr = IWICBitmapFrameDecode_GetSize(frame_decode, &width, &height); + todo_wine ok (hr == S_OK, "%d: GetSize failed for frame %d, hr=%x\n", i, frame_index, hr); if (hr != S_OK) goto end; - test_dds_decoder_initialize(); - test_dds_decoder_global_properties(decoder); - test_dds_decoder_frame_count(); + depth = params.Depth; + expected_width = params.Width; + expected_height = params.Height; + slice_index = frame_index % (frame_count / params.ArraySize); + while (slice_index >= depth) + { + if (expected_width > 1) expected_width /= 2; + if (expected_height > 1) expected_height /= 2; + slice_index -= depth; + if (depth > 1) depth /= 2; + } + ok (width == expected_width, "%d: Expected width %d for frame %d, got %d\n", i, expected_width, frame_index, width); + ok (height == expected_height, "%d: Expected height %d for frame %d, got %d\n", i, expected_height, frame_index, height); end: - if (decoder) IWICBitmapDecoder_Release(decoder); - if (stream) IWICStream_Release(stream); + if (dds_decoder) IWICDdsDecoder_Release(dds_decoder); +} + +static void test_dds_decoder_frame(IWICBitmapDecoder *decoder, int i) +{ + HRESULT hr; + UINT frame_count, j; + + hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); + ok (hr == S_OK, "%d: GetFrameCount failed, hr=%x\n", i, hr); + if (hr != S_OK) return; + + for (j = 0; j < frame_count; j++) + { + IWICBitmapFrameDecode *frame_decode = NULL; + + hr = IWICBitmapDecoder_GetFrame(decoder, j, &frame_decode); + ok (hr == S_OK, "%d: GetFrame failed for frame %d, hr=%x\n", i, j, hr); + if (hr != S_OK) { + IWICBitmapFrameDecode_Release(frame_decode); + continue; + } + + test_dds_decoder_frame_size(decoder, frame_decode, frame_count, i, j); + } +} + +static void test_dds_decoder(void) +{ + int i; + HRESULT hr; + + test_dds_decoder_initialize(); + test_dds_decoder_image_parameters(); + + for (i = 0; i < ARRAY_SIZE(test_data); i++) + { + IWICStream *stream = NULL; + IWICBitmapDecoder *decoder = NULL; + + stream = create_stream(test_data[i].data, test_data[i].size); + if (!stream) goto next; + decoder = create_decoder(); + if (!decoder) goto next; + hr = init_decoder(decoder, stream, S_OK, -1); + if (hr != S_OK) goto next; + + test_dds_decoder_global_properties(decoder); + test_dds_decoder_frame(decoder, i); + + next: + if (decoder) IWICBitmapDecoder_Release(decoder); + if (stream) IWICStream_Release(stream); + } } START_TEST(ddsformat) diff -Nru wine-development-5.8/dlls/windowscodecs/tests/tiffformat.c wine-development-5.9/dlls/windowscodecs/tests/tiffformat.c --- wine-development-5.8/dlls/windowscodecs/tests/tiffformat.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/windowscodecs/tests/tiffformat.c 2020-05-22 18:49:34.000000000 +0000 @@ -402,7 +402,7 @@ return hr; } -static HRESULT get_pixelformat_info(const GUID *format, UINT *bpp, UINT *channels, BOOL *trasparency) +static HRESULT get_pixelformat_info(const GUID *format, UINT *bpp, UINT *channels, BOOL *transparency) { HRESULT hr; IWICComponentInfo *info; @@ -415,7 +415,7 @@ hr = IWICComponentInfo_QueryInterface(info, &IID_IWICPixelFormatInfo2, (void **)&formatinfo); if (hr == S_OK) { - hr = IWICPixelFormatInfo2_SupportsTransparency(formatinfo, trasparency); + hr = IWICPixelFormatInfo2_SupportsTransparency(formatinfo, transparency); ok(hr == S_OK, "SupportsTransparency error %#x\n", hr); IWICPixelFormatInfo2_Release(formatinfo); } @@ -1093,7 +1093,7 @@ IWICBitmapFrameDecode *frame; GUID format; UINT count, i, bpp, channels, ret; - BOOL trasparency; + BOOL transparency; struct IFD_entry *tag, *tag_photo = NULL, *tag_bps = NULL, *tag_samples = NULL, *tag_colormap = NULL; struct IFD_entry *tag_width = NULL, *tag_height = NULL, *tag_extra_samples = NULL; short *bps; @@ -1236,12 +1236,12 @@ i, td[i].photometric, td[i].samples, td[i].extra_samples, td[i].bps, wine_dbgstr_guid(td[i].data->format), wine_dbgstr_guid(&format)); - trasparency = (td[i].photometric == 2 && td[i].samples == 4); /* for XP */ - hr = get_pixelformat_info(&format, &bpp, &channels, &trasparency); + transparency = (td[i].photometric == 2 && td[i].samples == 4); /* for XP */ + hr = get_pixelformat_info(&format, &bpp, &channels, &transparency); ok(hr == S_OK, "%u: get_pixelformat_bpp error %#x\n", i, hr); ok(bpp == td[i].data->bpp, "%u: expected %u, got %u\n", i, td[i].data->bpp, bpp); ok(channels == td[i].samples, "%u: expected %u, got %u\n", i, td[i].samples, channels); - ok(trasparency == (td[i].photometric == 2 && td[i].samples == 4), "%u: got %u\n", i, trasparency); + ok(transparency == (td[i].photometric == 2 && td[i].samples == 4), "%u: got %u\n", i, transparency); memset(pixels, 0, sizeof(pixels)); hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, width_bytes(td[i].data->width, bpp), sizeof(pixels), pixels); diff -Nru wine-development-5.8/dlls/winebus.sys/bus_udev.c wine-development-5.9/dlls/winebus.sys/bus_udev.c --- wine-development-5.8/dlls/winebus.sys/bus_udev.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winebus.sys/bus_udev.c 2020-05-22 18:49:34.000000000 +0000 @@ -139,7 +139,7 @@ {HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_THROTTLE}, /*ABS_THROTTLE*/ {HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_RUDDER}, /*ABS_RUDDER*/ {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_WHEEL}, /*ABS_WHEEL*/ - {HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_ACCELLERATOR}, /*ABS_GAS*/ + {HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_ACCELERATOR}, /*ABS_GAS*/ {HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_BRAKE}, /*ABS_BRAKE*/ {0,0}, /*ABS_HAT0X*/ {0,0}, /*ABS_HAT0Y*/ diff -Nru wine-development-5.8/dlls/wined3d/adapter_gl.c wine-development-5.9/dlls/wined3d/adapter_gl.c --- wine-development-5.8/dlls/wined3d/adapter_gl.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/adapter_gl.c 2020-05-22 18:49:34.000000000 +0000 @@ -3752,6 +3752,11 @@ WARN("Disabling ARB_texture_multisample because immutable storage is not supported.\n"); gl_info->supported[ARB_TEXTURE_MULTISAMPLE] = FALSE; } + if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT] && !gl_info->supported[EXT_PACKED_DEPTH_STENCIL]) + { + TRACE(" IMPLIED: GL_EXT_packed_depth_stencil (by GL_ARB_framebuffer_object).\n"); + gl_info->supported[EXT_PACKED_DEPTH_STENCIL] = TRUE; + } wined3d_adapter_init_limits(gl_info); @@ -4308,8 +4313,8 @@ if (!(device_gl = heap_alloc_zero(sizeof(*device_gl)))) return E_OUTOFMEMORY; - if (FAILED(hr = wined3d_device_init(&device_gl->d, wined3d, adapter->ordinal, device_type, - focus_window, flags, surface_alignment, levels, level_count, device_parent))) + if (FAILED(hr = wined3d_device_init(&device_gl->d, wined3d, adapter->ordinal, device_type, focus_window, + flags, surface_alignment, levels, level_count, adapter->gl_info.supported, device_parent))) { WARN("Failed to initialize device, hr %#x.\n", hr); heap_free(device_gl); diff -Nru wine-development-5.8/dlls/wined3d/adapter_vk.c wine-development-5.9/dlls/wined3d/adapter_vk.c --- wine-development-5.8/dlls/wined3d/adapter_vk.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/adapter_vk.c 2020-05-22 18:49:34.000000000 +0000 @@ -321,8 +321,20 @@ return E_FAIL; } -static void wined3d_disable_vulkan_features(VkPhysicalDeviceFeatures *features) +struct wined3d_physical_device_info { + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features; + + VkPhysicalDeviceFeatures2 features2; +}; + +static void wined3d_disable_vulkan_features(struct wined3d_physical_device_info *info) +{ + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features = &info->vertex_divisor_features; + VkPhysicalDeviceFeatures *features = &info->features2.features; + + vertex_divisor_features->vertexAttributeInstanceRateZeroDivisor = VK_FALSE; + features->depthBounds = VK_FALSE; features->alphaToOne = VK_FALSE; features->textureCompressionETC2 = VK_FALSE; @@ -398,18 +410,89 @@ .allocator_destroy_chunk = wined3d_allocator_vk_destroy_chunk, }; +static const struct +{ + const char *name; + unsigned int core_since_version; +} +vulkan_device_extensions[] = +{ + {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u}, + {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1}, + {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1}, +}; + +static bool enable_vulkan_device_extensions(VkPhysicalDevice physical_device, uint32_t *extension_count, + const char *enabled_extensions[], const struct wined3d_vk_info *vk_info) +{ + VkExtensionProperties *extensions = NULL; + bool success = false, found; + unsigned int i, j, count; + VkResult vr; + + *extension_count = 0; + + if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0) + { + ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr)); + goto done; + } + if (!(extensions = heap_calloc(count, sizeof(*extensions)))) + { + WARN("Out of memory.\n"); + goto done; + } + if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, extensions))) < 0) + { + ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr)); + goto done; + } + + for (i = 0; i < ARRAY_SIZE(vulkan_device_extensions); ++i) + { + if (vulkan_device_extensions[i].core_since_version <= vk_info->api_version) + continue; + + for (j = 0, found = false; j < count; ++j) + { + if (!strcmp(extensions[j].extensionName, vulkan_device_extensions[i].name)) + { + found = true; + break; + } + } + + if (!found) + { + WARN("Required extension '%s' is not available.\n", vulkan_device_extensions[i].name); + goto done; + } + + TRACE("Enabling instance extension '%s'.\n", vulkan_device_extensions[i].name); + enabled_extensions[(*extension_count)++] = vulkan_device_extensions[i].name; + } + success = true; + +done: + heap_free(extensions); + return success; +} + static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter, enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment, const enum wined3d_feature_level *levels, unsigned int level_count, struct wined3d_device_parent *device_parent, struct wined3d_device **device) { const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter); + const char *enabled_device_extensions[ARRAY_SIZE(vulkan_device_extensions)]; + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features; const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; + struct wined3d_physical_device_info physical_device_info; static const float priorities[] = {1.0f}; + VkPhysicalDeviceFeatures2 *features2; struct wined3d_device_vk *device_vk; VkDevice vk_device = VK_NULL_HANDLE; VkDeviceQueueCreateInfo queue_info; - VkPhysicalDeviceFeatures features; VkPhysicalDevice physical_device; VkDeviceCreateInfo device_info; uint32_t queue_family_index; @@ -424,8 +507,28 @@ physical_device = adapter_vk->physical_device; - VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features)); - wined3d_disable_vulkan_features(&features); + memset(&physical_device_info, 0, sizeof(physical_device_info)); + + vertex_divisor_features = &physical_device_info.vertex_divisor_features; + vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; + + features2 = &physical_device_info.features2; + features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + features2->pNext = vertex_divisor_features; + + if (vk_info->vk_ops.vkGetPhysicalDeviceFeatures2) + VK_CALL(vkGetPhysicalDeviceFeatures2(physical_device, features2)); + else + VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features2->features)); + + if (!vertex_divisor_features->vertexAttributeInstanceRateDivisor) + { + WARN("Vertex attribute divisors not supported.\n"); + hr = E_FAIL; + goto fail; + } + + wined3d_disable_vulkan_features(&physical_device_info); queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_info.pNext = NULL; @@ -435,15 +538,20 @@ queue_info.pQueuePriorities = priorities; device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_info.pNext = NULL; + device_info.pNext = features2->pNext; device_info.flags = 0; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &queue_info; device_info.enabledLayerCount = 0; device_info.ppEnabledLayerNames = NULL; - device_info.enabledExtensionCount = 0; - device_info.ppEnabledExtensionNames = NULL; - device_info.pEnabledFeatures = &features; + device_info.ppEnabledExtensionNames = enabled_device_extensions; + if (!enable_vulkan_device_extensions(physical_device, + &device_info.enabledExtensionCount, enabled_device_extensions, vk_info)) + { + hr = E_FAIL; + goto fail; + } + device_info.pEnabledFeatures = &features2->features; if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0) { @@ -477,8 +585,8 @@ goto fail; } - if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type, - focus_window, flags, surface_alignment, levels, level_count, device_parent))) + if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type, focus_window, + flags, surface_alignment, levels, level_count, vk_info->supported, device_parent))) { WARN("Failed to initialize device, hr %#x.\n", hr); wined3d_allocator_cleanup(&device_vk->allocator); @@ -678,6 +786,8 @@ wined3d_vk_blitter_create(&device_vk->d.blitter); wined3d_device_create_default_samplers(device, &context_vk->c); + wined3d_device_vk_create_null_resources(device_vk, context_vk); + wined3d_device_vk_create_null_views(device_vk, context_vk); return WINED3D_OK; } @@ -701,6 +811,8 @@ device->blitter->ops->blitter_destroy(device->blitter, NULL); device->shader_backend->shader_free_private(device, &context_vk->c); + wined3d_device_vk_destroy_null_views(device_vk, context_vk); + wined3d_device_vk_destroy_null_resources(device_vk, context_vk); wined3d_device_destroy_default_samplers(device, &context_vk->c); } @@ -810,6 +922,7 @@ { struct wined3d_context_vk *context_vk = wined3d_context_vk(context); const struct wined3d_vk_info *vk_info; + struct wined3d_bo_user_vk *bo_user_vk; struct wined3d_device_vk *device_vk; VkCommandBuffer vk_command_buffer; VkBufferMemoryBarrier vk_barrier; @@ -830,8 +943,15 @@ { if (wined3d_context_vk_create_bo(context_vk, bo->size, bo->usage, bo->memory_type, &tmp)) { + list_move_head(&tmp.users, &bo->users); wined3d_context_vk_destroy_bo(context_vk, bo); *bo = tmp; + list_init(&bo->users); + list_move_head(&bo->users, &tmp.users); + LIST_FOR_EACH_ENTRY(bo_user_vk, &bo->users, struct wined3d_bo_user_vk, entry) + { + bo_user_vk->valid = false; + } goto map; } @@ -847,6 +967,8 @@ return NULL; } + wined3d_context_vk_end_current_render_pass(context_vk); + vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; vk_barrier.pNext = NULL; vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(bo->usage); @@ -944,6 +1066,8 @@ return; } + wined3d_context_vk_end_current_render_pass(context_vk); + src_access_mask = vk_access_mask_from_buffer_usage(src_bo->usage); dst_access_mask = vk_access_mask_from_buffer_usage(dst_bo->usage); @@ -1375,6 +1499,7 @@ vk_buffer_view = &view_vk->u.vk_buffer_view; else vk_image_view = &view_vk->u.vk_image_info.imageView; + list_remove(&view_vk->bo_user.entry); wined3d_shader_resource_view_cleanup(&srv_vk->v); wined3d_view_vk_destroy(device, vk_buffer_view, vk_image_view, NULL, NULL, &view_vk->command_buffer_id, srv_vk); @@ -1429,6 +1554,7 @@ vk_buffer_view = &view_vk->u.vk_buffer_view; else vk_image_view = &view_vk->u.vk_image_info.imageView; + list_remove(&view_vk->bo_user.entry); wined3d_unordered_access_view_cleanup(&uav_vk->v); wined3d_view_vk_destroy(device, vk_buffer_view, vk_image_view, &uav_vk->counter_bo, &uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk); @@ -1503,13 +1629,111 @@ static void adapter_vk_draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, const struct wined3d_draw_parameters *parameters) { - FIXME("device %p, state %p, parameters %p.\n", device, state, parameters); + struct wined3d_buffer_vk *indirect_vk = NULL; + const struct wined3d_vk_info *vk_info; + struct wined3d_context_vk *context_vk; + VkCommandBuffer vk_command_buffer; + uint32_t instance_count; + + TRACE("device %p, state %p, parameters %p.\n", device, state, parameters); + + context_vk = wined3d_context_vk(context_acquire(device, NULL, 0)); + vk_info = context_vk->vk_info; + + if (parameters->indirect) + indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer); + + if (!(vk_command_buffer = wined3d_context_vk_apply_draw_state(context_vk, + state, indirect_vk, parameters->indexed))) + { + ERR("Failed to apply draw state.\n"); + context_release(&context_vk->c); + return; + } + + if (parameters->indirect) + { + struct wined3d_bo_vk *bo = &indirect_vk->bo; + uint32_t stride, size; + + wined3d_context_vk_reference_bo(context_vk, bo); + size = indirect_vk->b.resource.size - parameters->u.indirect.offset; + + if (parameters->indexed) + { + stride = sizeof(VkDrawIndexedIndirectCommand); + VK_CALL(vkCmdDrawIndexedIndirect(vk_command_buffer, bo->vk_buffer, + bo->buffer_offset + parameters->u.indirect.offset, size / stride, stride)); + } + else + { + stride = sizeof(VkDrawIndirectCommand); + VK_CALL(vkCmdDrawIndirect(vk_command_buffer, bo->vk_buffer, + bo->buffer_offset + parameters->u.indirect.offset, size / stride, stride)); + } + } + else + { + instance_count = parameters->u.direct.instance_count; + if (context_vk->c.instance_count) + instance_count = context_vk->c.instance_count; + if (!instance_count) + instance_count = 1; + + if (parameters->indexed) + VK_CALL(vkCmdDrawIndexed(vk_command_buffer, parameters->u.direct.index_count, + instance_count, parameters->u.direct.start_idx, parameters->u.direct.base_vertex_idx, + parameters->u.direct.start_instance)); + else + VK_CALL(vkCmdDraw(vk_command_buffer, parameters->u.direct.index_count, instance_count, + parameters->u.direct.start_idx, parameters->u.direct.start_instance)); + } + + context_release(&context_vk->c); } static void adapter_vk_dispatch_compute(struct wined3d_device *device, const struct wined3d_state *state, const struct wined3d_dispatch_parameters *parameters) { - FIXME("device %p, state %p, parameters %p.\n", device, state, parameters); + struct wined3d_buffer_vk *indirect_vk = NULL; + const struct wined3d_vk_info *vk_info; + struct wined3d_context_vk *context_vk; + VkCommandBuffer vk_command_buffer; + + TRACE("device %p, state %p, parameters %p.\n", device, state, parameters); + + context_vk = wined3d_context_vk(context_acquire(device, NULL, 0)); + vk_info = context_vk->vk_info; + + if (parameters->indirect) + indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer); + + if (!(vk_command_buffer = wined3d_context_vk_apply_compute_state(context_vk, state, indirect_vk))) + { + ERR("Failed to apply compute state.\n"); + context_release(&context_vk->c); + return; + } + + if (parameters->indirect) + { + struct wined3d_bo_vk *bo = &indirect_vk->bo; + + wined3d_context_vk_reference_bo(context_vk, bo); + VK_CALL(vkCmdDispatchIndirect(vk_command_buffer, bo->vk_buffer, + bo->buffer_offset + parameters->u.indirect.offset)); + } + else + { + const struct wined3d_direct_dispatch_parameters *direct = ¶meters->u.direct; + + VK_CALL(vkCmdDispatch(vk_command_buffer, direct->group_count_x, direct->group_count_y, direct->group_count_z)); + } + + VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 0, NULL)); + + context_release(&context_vk->c); } void adapter_vk_clear_uav(struct wined3d_context *context, @@ -1693,6 +1917,9 @@ if (!enable_vulkan_instance_extensions(&instance_info.enabledExtensionCount, enabled_instance_extensions, vk_info)) goto fail; + memset(vk_info->supported, 0, sizeof(vk_info->supported)); + vk_info->supported[WINED3D_VK_EXT_NONE] = TRUE; + if ((vr = VK_CALL(vkCreateInstance(&instance_info, NULL, &instance))) < 0) { WARN("Failed to create Vulkan instance, vr %s.\n", wined3d_debug_vkresult(vr)); @@ -1722,6 +1949,7 @@ if (!vk_ops->core_pfn) \ vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn)); MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR) + MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2, vkGetPhysicalDeviceFeaturess2KHR) #undef MAP_INSTANCE_FUNCTION vk_info->instance = instance; @@ -1883,10 +2111,10 @@ if (!wined3d_adapter_vk_init_format_info(adapter_vk, vk_info)) goto fail_vulkan; - adapter->vertex_pipe = &none_vertex_pipe; - adapter->fragment_pipe = &none_fragment_pipe; + adapter->vertex_pipe = wined3d_spirv_vertex_pipe_init_vk(); + adapter->fragment_pipe = wined3d_spirv_fragment_pipe_init_vk(); adapter->misc_state_template = misc_state_template_vk; - adapter->shader_backend = &none_shader_backend; + adapter->shader_backend = wined3d_spirv_shader_backend_init_vk(); wined3d_adapter_vk_init_d3d_info(adapter, wined3d_creation_flags); diff -Nru wine-development-5.8/dlls/wined3d/buffer.c wine-development-5.9/dlls/wined3d/buffer.c --- wine-development-5.8/dlls/wined3d/buffer.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/buffer.c 2020-05-22 18:49:34.000000000 +0000 @@ -1593,12 +1593,27 @@ return FALSE; } + list_init(&buffer_vk->bo_user.entry); + list_add_head(&buffer_vk->bo.users, &buffer_vk->bo_user.entry); buffer_vk->b.buffer_object = (uintptr_t)&buffer_vk->bo; buffer_invalidate_bo_range(&buffer_vk->b, 0, 0); return TRUE; } +const VkDescriptorBufferInfo *wined3d_buffer_vk_get_buffer_info(struct wined3d_buffer_vk *buffer_vk) +{ + if (buffer_vk->bo_user.valid) + return &buffer_vk->buffer_info; + + buffer_vk->buffer_info.buffer = buffer_vk->bo.vk_buffer; + buffer_vk->buffer_info.offset = buffer_vk->bo.buffer_offset; + buffer_vk->buffer_info.range = buffer_vk->b.resource.size; + buffer_vk->bo_user.valid = true; + + return &buffer_vk->buffer_info; +} + static BOOL wined3d_buffer_vk_prepare_location(struct wined3d_buffer *buffer, struct wined3d_context *context, unsigned int location) { @@ -1630,6 +1645,8 @@ switch (location) { case WINED3D_LOCATION_BUFFER: + buffer_vk->bo_user.valid = false; + list_remove(&buffer_vk->bo_user.entry); wined3d_context_vk_destroy_bo(context_vk, &buffer_vk->bo); buffer_vk->bo.vk_buffer = VK_NULL_HANDLE; buffer_vk->bo.memory = NULL; diff -Nru wine-development-5.8/dlls/wined3d/context_gl.c wine-development-5.9/dlls/wined3d/context_gl.c --- wine-development-5.8/dlls/wined3d/context_gl.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/context_gl.c 2020-05-22 18:49:34.000000000 +0000 @@ -38,6 +38,52 @@ static DWORD wined3d_context_tls_idx; +/* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these + * actually have the same values in GL and D3D. */ +static GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) +{ + switch (primitive_type) + { + case WINED3D_PT_POINTLIST: + return GL_POINTS; + + case WINED3D_PT_LINELIST: + return GL_LINES; + + case WINED3D_PT_LINESTRIP: + return GL_LINE_STRIP; + + case WINED3D_PT_TRIANGLELIST: + return GL_TRIANGLES; + + case WINED3D_PT_TRIANGLESTRIP: + return GL_TRIANGLE_STRIP; + + case WINED3D_PT_TRIANGLEFAN: + return GL_TRIANGLE_FAN; + + case WINED3D_PT_LINELIST_ADJ: + return GL_LINES_ADJACENCY_ARB; + + case WINED3D_PT_LINESTRIP_ADJ: + return GL_LINE_STRIP_ADJACENCY_ARB; + + case WINED3D_PT_TRIANGLELIST_ADJ: + return GL_TRIANGLES_ADJACENCY_ARB; + + case WINED3D_PT_TRIANGLESTRIP_ADJ: + return GL_TRIANGLE_STRIP_ADJACENCY_ARB; + + case WINED3D_PT_PATCH: + return GL_PATCHES; + + default: + FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); + case WINED3D_PT_UNDEFINED: + return ~0u; + } +} + /* FBO helper functions */ /* Context activation is done by the caller. */ @@ -3901,13 +3947,6 @@ wined3d_context_gl_apply_compute_state(context_gl, device, state); - if (!state->shader[WINED3D_SHADER_TYPE_COMPUTE]) - { - context_release(&context_gl->c); - WARN("No compute shader bound, skipping dispatch.\n"); - return; - } - if (parameters->indirect) { const struct wined3d_indirect_dispatch_parameters *indirect = ¶meters->u.indirect; @@ -3938,10 +3977,10 @@ const struct wined3d_ffp_attrib_ops *ops = &context_gl->c.d3d_info->ffp_attrib_ops; GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; const struct wined3d_stream_info *si = &context_gl->c.stream_info; + GLenum mode = gl_primitive_type_from_d3d(state->primitive_type); const struct wined3d_gl_info *gl_info = context_gl->gl_info; unsigned int instanced_elements[ARRAY_SIZE(si->elements)]; unsigned int instanced_element_count = 0; - GLenum mode = state->gl_primitive_type; const void *indices; unsigned int i, j; @@ -4111,7 +4150,7 @@ ops = &d3d_info->ffp_attrib_ops; - gl_info->gl_ops.gl.p_glBegin(state->gl_primitive_type); + gl_info->gl_ops.gl.p_glBegin(gl_primitive_type_from_d3d(state->primitive_type)); if (use_vs(state) || d3d_info->ffp_generic_attributes) { @@ -4296,6 +4335,7 @@ static void wined3d_context_gl_draw_indirect(struct wined3d_context_gl *context_gl, const struct wined3d_state *state, const struct wined3d_indirect_draw_parameters *parameters, unsigned int idx_size) { + GLenum gl_primitive_type = gl_primitive_type_from_d3d(state->primitive_type); const struct wined3d_gl_info *gl_info = context_gl->gl_info; struct wined3d_buffer *buffer = parameters->buffer; const void *offset; @@ -4314,11 +4354,11 @@ GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; if (state->index_offset) FIXME("Ignoring index offset %u.\n", state->index_offset); - GL_EXTCALL(glDrawElementsIndirect(state->gl_primitive_type, idx_type, offset)); + GL_EXTCALL(glDrawElementsIndirect(gl_primitive_type, idx_type, offset)); } else { - GL_EXTCALL(glDrawArraysIndirect(state->gl_primitive_type, offset)); + GL_EXTCALL(glDrawArraysIndirect(gl_primitive_type, offset)); } GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0)); @@ -4374,15 +4414,6 @@ } } -static unsigned int get_render_target_writemask(const struct wined3d_blend_state *state, unsigned int index) -{ - if (!state) - return 0xf; - if (!state->desc.independent) - index = 0; - return state->desc.rt[index].writemask; -} - /* Routine common to the draw primitive and draw indexed primitive routines */ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, const struct wined3d_draw_parameters *parameters) @@ -4440,7 +4471,7 @@ if (!(rtv = fb->render_targets[i]) || rtv->format->id == WINED3DFMT_NULL) continue; - if (get_render_target_writemask(state->blend_state, i)) + if (wined3d_blend_state_get_writemask(state->blend_state, i)) { wined3d_rendertarget_view_load_location(rtv, context, rtv->resource->draw_binding); wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding); @@ -4561,7 +4592,7 @@ else if (!context->transform_feedback_active) { enum wined3d_primitive_type primitive_type = shader->u.gs.output_type - ? shader->u.gs.output_type : d3d_primitive_type_from_gl(state->gl_primitive_type); + ? shader->u.gs.output_type : state->primitive_type; GLenum mode = gl_tfb_primitive_type_from_d3d(primitive_type); GL_EXTCALL(glBeginTransformFeedback(mode)); checkGLcall("glBeginTransformFeedback"); @@ -4569,9 +4600,9 @@ } } - if (state->gl_primitive_type == GL_PATCHES) + if (state->primitive_type == WINED3D_PT_PATCH) { - GL_EXTCALL(glPatchParameteri(GL_PATCH_VERTICES, state->gl_patch_vertices)); + GL_EXTCALL(glPatchParameteri(GL_PATCH_VERTICES, state->patch_vertex_count)); checkGLcall("glPatchParameteri"); } diff -Nru wine-development-5.8/dlls/wined3d/context_vk.c wine-development-5.9/dlls/wined3d/context_vk.c --- wine-development-5.8/dlls/wined3d/context_vk.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/context_vk.c 2020-05-22 18:49:34.000000000 +0000 @@ -58,6 +58,195 @@ } } +VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type) +{ + switch (shader_type) + { + case WINED3D_SHADER_TYPE_VERTEX: + return VK_SHADER_STAGE_VERTEX_BIT; + case WINED3D_SHADER_TYPE_HULL: + return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + case WINED3D_SHADER_TYPE_DOMAIN: + return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + case WINED3D_SHADER_TYPE_GEOMETRY: + return VK_SHADER_STAGE_GEOMETRY_BIT; + case WINED3D_SHADER_TYPE_PIXEL: + return VK_SHADER_STAGE_FRAGMENT_BIT; + case WINED3D_SHADER_TYPE_COMPUTE: + return VK_SHADER_STAGE_COMPUTE_BIT; + default: + ERR("Unhandled shader type %s.\n", debug_shader_type(shader_type)); + return 0; + } +} + +static VkBlendFactor vk_blend_factor_from_wined3d(enum wined3d_blend blend, + const struct wined3d_format *dst_format, bool alpha) +{ + switch (blend) + { + case WINED3D_BLEND_ZERO: + return VK_BLEND_FACTOR_ZERO; + case WINED3D_BLEND_ONE: + return VK_BLEND_FACTOR_ONE; + case WINED3D_BLEND_SRCCOLOR: + return VK_BLEND_FACTOR_SRC_COLOR; + case WINED3D_BLEND_INVSRCCOLOR: + return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + case WINED3D_BLEND_SRCALPHA: + return VK_BLEND_FACTOR_SRC_ALPHA; + case WINED3D_BLEND_INVSRCALPHA: + return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + case WINED3D_BLEND_DESTALPHA: + if (dst_format->alpha_size) + return VK_BLEND_FACTOR_DST_ALPHA; + return VK_BLEND_FACTOR_ONE; + case WINED3D_BLEND_INVDESTALPHA: + if (dst_format->alpha_size) + return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; + return VK_BLEND_FACTOR_ZERO; + case WINED3D_BLEND_DESTCOLOR: + return VK_BLEND_FACTOR_DST_COLOR; + case WINED3D_BLEND_INVDESTCOLOR: + return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; + case WINED3D_BLEND_SRCALPHASAT: + return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; + case WINED3D_BLEND_BLENDFACTOR: + if (alpha) + return VK_BLEND_FACTOR_CONSTANT_ALPHA; + return VK_BLEND_FACTOR_CONSTANT_COLOR; + case WINED3D_BLEND_INVBLENDFACTOR: + if (alpha) + return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; + return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR; + case WINED3D_BLEND_SRC1COLOR: + return VK_BLEND_FACTOR_SRC1_COLOR; + case WINED3D_BLEND_INVSRC1COLOR: + return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; + case WINED3D_BLEND_SRC1ALPHA: + return VK_BLEND_FACTOR_SRC1_ALPHA; + case WINED3D_BLEND_INVSRC1ALPHA: + return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; + default: + FIXME("Unhandled blend %#x.\n", blend); + return VK_BLEND_FACTOR_ZERO; + } +} + +static VkBlendOp vk_blend_op_from_wined3d(enum wined3d_blend_op op) +{ + switch (op) + { + case WINED3D_BLEND_OP_ADD: + return VK_BLEND_OP_ADD; + case WINED3D_BLEND_OP_SUBTRACT: + return VK_BLEND_OP_SUBTRACT; + case WINED3D_BLEND_OP_REVSUBTRACT: + return VK_BLEND_OP_REVERSE_SUBTRACT; + case WINED3D_BLEND_OP_MIN: + return VK_BLEND_OP_MIN; + case WINED3D_BLEND_OP_MAX: + return VK_BLEND_OP_MAX; + default: + FIXME("Unhandled blend op %#x.\n", op); + return VK_BLEND_OP_ADD; + } +} + +static VkColorComponentFlags vk_colour_write_mask_from_wined3d(uint32_t wined3d_mask) +{ + VkColorComponentFlags vk_mask = 0; + + if (wined3d_mask & WINED3DCOLORWRITEENABLE_RED) + vk_mask |= VK_COLOR_COMPONENT_R_BIT; + if (wined3d_mask & WINED3DCOLORWRITEENABLE_GREEN) + vk_mask |= VK_COLOR_COMPONENT_G_BIT; + if (wined3d_mask & WINED3DCOLORWRITEENABLE_BLUE) + vk_mask |= VK_COLOR_COMPONENT_B_BIT; + if (wined3d_mask & WINED3DCOLORWRITEENABLE_ALPHA) + vk_mask |= VK_COLOR_COMPONENT_A_BIT; + + return vk_mask; +} + +static VkCullModeFlags vk_cull_mode_from_wined3d(enum wined3d_cull mode) +{ + switch (mode) + { + case WINED3D_CULL_NONE: + return VK_CULL_MODE_NONE; + case WINED3D_CULL_FRONT: + return VK_CULL_MODE_FRONT_BIT; + case WINED3D_CULL_BACK: + return VK_CULL_MODE_BACK_BIT; + default: + FIXME("Unhandled cull mode %#x.\n", mode); + return VK_CULL_MODE_NONE; + } +} + +static VkPrimitiveTopology vk_topology_from_wined3d(enum wined3d_primitive_type t) +{ + switch (t) + { + case WINED3D_PT_POINTLIST: + return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; + case WINED3D_PT_LINELIST: + return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; + case WINED3D_PT_LINESTRIP: + return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; + case WINED3D_PT_TRIANGLELIST: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + case WINED3D_PT_TRIANGLESTRIP: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + case WINED3D_PT_TRIANGLEFAN: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; + case WINED3D_PT_LINELIST_ADJ: + return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; + case WINED3D_PT_LINESTRIP_ADJ: + return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY; + case WINED3D_PT_TRIANGLELIST_ADJ: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY; + case WINED3D_PT_TRIANGLESTRIP_ADJ: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; + case WINED3D_PT_PATCH: + return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; + default: + FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(t)); + case WINED3D_PT_UNDEFINED: + return ~0u; + } +} + +static VkStencilOp vk_stencil_op_from_wined3d(enum wined3d_stencil_op op) +{ + switch (op) + { + case WINED3D_STENCIL_OP_KEEP: + return VK_STENCIL_OP_KEEP; + case WINED3D_STENCIL_OP_ZERO: + return VK_STENCIL_OP_ZERO; + case WINED3D_STENCIL_OP_REPLACE: + return VK_STENCIL_OP_REPLACE; + case WINED3D_STENCIL_OP_INCR_SAT: + return VK_STENCIL_OP_INCREMENT_AND_CLAMP; + case WINED3D_STENCIL_OP_DECR_SAT: + return VK_STENCIL_OP_DECREMENT_AND_CLAMP; + case WINED3D_STENCIL_OP_INVERT: + return VK_STENCIL_OP_INVERT; + case WINED3D_STENCIL_OP_INCR: + return VK_STENCIL_OP_INCREMENT_AND_WRAP; + case WINED3D_STENCIL_OP_DECR: + return VK_STENCIL_OP_DECREMENT_AND_WRAP; + default: + if (!op) + WARN("Unhandled stencil operation %#x.\n", op); + else + FIXME("Unhandled stencil operation %#x.\n", op); + return VK_STENCIL_OP_KEEP; + } +} + void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk, struct wined3d_context_vk *context_vk) { @@ -221,6 +410,7 @@ bo->buffer_offset = idx * object_size; bo->memory_offset = slab->bo.memory_offset + bo->buffer_offset; bo->size = size; + list_init(&bo->users); bo->command_buffer_id = 0; TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n", @@ -297,6 +487,7 @@ bo->size = size; bo->usage = usage; bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags; + list_init(&bo->users); bo->command_buffer_id = 0; bo->slab = NULL; @@ -350,6 +541,31 @@ o->command_buffer_id = command_buffer_id; } +static void wined3d_context_vk_destroy_descriptor_pool(struct wined3d_context_vk *context_vk, + VkDescriptorPool vk_descriptor_pool, uint64_t command_buffer_id) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + struct wined3d_retired_object_vk *o; + + if (context_vk->completed_command_buffer_id > command_buffer_id) + { + VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, vk_descriptor_pool, NULL)); + TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool)); + return; + } + + if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk))) + { + ERR("Leaking descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool)); + return; + } + + o->type = WINED3D_RETIRED_DESCRIPTOR_POOL_VK; + o->u.vk_descriptor_pool = vk_descriptor_pool; + o->command_buffer_id = command_buffer_id; +} + void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk, VkDeviceMemory vk_memory, uint64_t command_buffer_id) { @@ -647,6 +863,11 @@ TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_framebuffer)); break; + case WINED3D_RETIRED_DESCRIPTOR_POOL_VK: + VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, o->u.vk_descriptor_pool, NULL)); + TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(o->u.vk_descriptor_pool)); + break; + case WINED3D_RETIRED_MEMORY_VK: VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL)); TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory)); @@ -718,6 +939,38 @@ } } +static void wined3d_context_vk_destroy_graphics_pipeline(struct wine_rb_entry *entry, void *ctx) +{ + struct wined3d_graphics_pipeline_vk *pipeline_vk = WINE_RB_ENTRY_VALUE(entry, + struct wined3d_graphics_pipeline_vk, entry); + struct wined3d_context_vk *context_vk = ctx; + const struct wined3d_vk_info *vk_info; + struct wined3d_device_vk *device_vk; + + vk_info = context_vk->vk_info; + device_vk = wined3d_device_vk(context_vk->c.device); + + VK_CALL(vkDestroyPipeline(device_vk->vk_device, pipeline_vk->vk_pipeline, NULL)); + heap_free(pipeline_vk); +} + +static void wined3d_context_vk_destroy_pipeline_layout(struct wine_rb_entry *entry, void *ctx) +{ + struct wined3d_pipeline_layout_vk *layout = WINE_RB_ENTRY_VALUE(entry, + struct wined3d_pipeline_layout_vk, entry); + struct wined3d_context_vk *context_vk = ctx; + const struct wined3d_vk_info *vk_info; + struct wined3d_device_vk *device_vk; + + vk_info = context_vk->vk_info; + device_vk = wined3d_device_vk(context_vk->c.device); + + VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL)); + VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL)); + heap_free(layout->key.bindings); + heap_free(layout); +} + static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key, const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags) { @@ -905,6 +1158,28 @@ return pass->vk_render_pass; } +void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk) +{ + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + VkCommandBuffer vk_command_buffer; + + if (context_vk->vk_render_pass) + { + vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer; + VK_CALL(vkCmdEndRenderPass(vk_command_buffer)); + context_vk->vk_render_pass = VK_NULL_HANDLE; + VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL)); + } + + if (context_vk->vk_framebuffer) + { + wined3d_context_vk_destroy_framebuffer(context_vk, + context_vk->vk_framebuffer, context_vk->current_command_buffer.id); + context_vk->vk_framebuffer = VK_NULL_HANDLE; + } +} + static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx) { struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry, @@ -914,6 +1189,11 @@ heap_free(pass); } +static void wined3d_shader_descriptor_writes_vk_cleanup(struct wined3d_shader_descriptor_writes_vk *writes) +{ + heap_free(writes->writes); +} + void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) { struct wined3d_command_buffer_vk *buffer = &context_vk->current_command_buffer; @@ -926,15 +1206,25 @@ context_vk->vk_command_pool, 1, &buffer->vk_command_buffer)); buffer->vk_command_buffer = VK_NULL_HANDLE; } - VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL)); wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1); context_vk->completed_command_buffer_id = buffer->id; + + heap_free(context_vk->compute.bindings.bindings); + heap_free(context_vk->graphics.bindings.bindings); + if (context_vk->vk_descriptor_pool) + VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, context_vk->vk_descriptor_pool, NULL)); + if (context_vk->vk_framebuffer) + VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, context_vk->vk_framebuffer, NULL)); + VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL)); wined3d_context_vk_cleanup_resources(context_vk); wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk); heap_free(context_vk->submitted.buffers); heap_free(context_vk->retired.objects); + wined3d_shader_descriptor_writes_vk_cleanup(&context_vk->descriptor_writes); + wine_rb_destroy(&context_vk->graphics_pipelines, wined3d_context_vk_destroy_graphics_pipeline, context_vk); + wine_rb_destroy(&context_vk->pipeline_layouts, wined3d_context_vk_destroy_pipeline_layout, context_vk); wine_rb_destroy(&context_vk->render_passes, wined3d_context_vk_destroy_render_pass, context_vk); wined3d_context_cleanup(&context_vk->c); @@ -1012,6 +1302,17 @@ TRACE("Submitting command buffer %p with id 0x%s.\n", buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id)); + wined3d_context_vk_end_current_render_pass(context_vk); + context_vk->graphics.vk_pipeline = VK_NULL_HANDLE; + context_vk->update_compute_pipeline = 1; + context_vk->c.update_shader_resource_bindings = 1; + context_vk->c.update_compute_shader_resource_bindings = 1; + context_vk->c.update_unordered_access_view_bindings = 1; + context_vk->c.update_compute_unordered_access_view_bindings = 1; + context_invalidate_state(&context_vk->c, STATE_STREAMSRC); + context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER); + context_invalidate_state(&context_vk->c, STATE_BLEND_FACTOR); + VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer)); fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; @@ -1083,6 +1384,8 @@ const struct wined3d_vk_info *vk_info = context_vk->vk_info; VkImageMemoryBarrier barrier; + wined3d_context_vk_end_current_render_pass(context_vk); + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.pNext = NULL; barrier.srcAccessMask = src_access_mask; @@ -1110,6 +1413,88 @@ return memcmp(k, &pass->key, sizeof(*k)); } +static int wined3d_pipeline_layout_vk_compare(const void *key, const struct wine_rb_entry *entry) +{ + const struct wined3d_pipeline_layout_key_vk *a = key; + const struct wined3d_pipeline_layout_key_vk *b = &WINE_RB_ENTRY_VALUE(entry, + const struct wined3d_pipeline_layout_vk, entry)->key; + + if (a->binding_count != b->binding_count) + return a->binding_count - b->binding_count; + return memcmp(a->bindings, b->bindings, a->binding_count * sizeof(*a->bindings)); +} + +static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wine_rb_entry *entry) +{ + const struct wined3d_graphics_pipeline_key_vk *a = key; + const struct wined3d_graphics_pipeline_key_vk *b = &WINE_RB_ENTRY_VALUE(entry, + const struct wined3d_graphics_pipeline_vk, entry)->key; + unsigned int i; + int ret; + + if (a->pipeline_desc.stageCount != b->pipeline_desc.stageCount) + return a->pipeline_desc.stageCount - b->pipeline_desc.stageCount; + for (i = 0; i < a->pipeline_desc.stageCount; ++i) + { + if (a->stages[i].module != b->stages[i].module) + return a->stages[i].module - b->stages[i].module; + } + + if (a->divisor_desc.vertexBindingDivisorCount != b->divisor_desc.vertexBindingDivisorCount) + return a->divisor_desc.vertexBindingDivisorCount - b->divisor_desc.vertexBindingDivisorCount; + if ((ret = memcmp(a->divisors, b->divisors, + a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors)))) + return ret; + + if (a->input_desc.vertexAttributeDescriptionCount != b->input_desc.vertexAttributeDescriptionCount) + return a->input_desc.vertexAttributeDescriptionCount - b->input_desc.vertexAttributeDescriptionCount; + if ((ret = memcmp(a->attributes, b->attributes, + a->input_desc.vertexAttributeDescriptionCount * sizeof(*a->attributes)))) + return ret; + if (a->input_desc.vertexBindingDescriptionCount != b->input_desc.vertexBindingDescriptionCount) + return a->input_desc.vertexBindingDescriptionCount - b->input_desc.vertexBindingDescriptionCount; + if ((ret = memcmp(a->bindings, b->bindings, + a->input_desc.vertexBindingDescriptionCount * sizeof(*a->bindings)))) + return ret; + + if (a->ia_desc.topology != b->ia_desc.topology) + return a->ia_desc.topology - b->ia_desc.topology; + if (a->ia_desc.primitiveRestartEnable != b->ia_desc.primitiveRestartEnable) + return a->ia_desc.primitiveRestartEnable - b->ia_desc.primitiveRestartEnable; + + if (a->ts_desc.patchControlPoints != b->ts_desc.patchControlPoints) + return a->ts_desc.patchControlPoints - b->ts_desc.patchControlPoints; + + if ((ret = memcmp(&a->viewport, &b->viewport, sizeof(a->viewport)))) + return ret; + + if ((ret = memcmp(&a->scissor, &b->scissor, sizeof(a->scissor)))) + return ret; + + if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc)))) + return ret; + + if ((ret = memcmp(&a->ms_desc, &b->ms_desc, sizeof(a->ms_desc)))) + return ret; + + if ((ret = memcmp(&a->ds_desc, &b->ds_desc, sizeof(a->ds_desc)))) + return ret; + + if (a->blend_desc.attachmentCount != b->blend_desc.attachmentCount) + return a->blend_desc.attachmentCount - b->blend_desc.attachmentCount; + if ((ret = memcmp(a->blend_attachments, b->blend_attachments, + a->blend_desc.attachmentCount * sizeof(*a->blend_attachments)))) + return ret; + + if (a->pipeline_desc.layout != b->pipeline_desc.layout) + return a->pipeline_desc.layout - b->pipeline_desc.layout; + + if (a->pipeline_desc.renderPass != b->pipeline_desc.renderPass) + return a->pipeline_desc.renderPass - b->pipeline_desc.renderPass; + + return 0; +} + static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry) { const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry); @@ -1122,6 +1507,1378 @@ return k->size - slab->bo.size; } +static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk *context_vk) +{ + struct wined3d_graphics_pipeline_key_vk *key; + VkPipelineShaderStageCreateInfo *stage; + unsigned int i; + + static const VkDynamicState dynamic_states[] = + { + VK_DYNAMIC_STATE_BLEND_CONSTANTS, + }; + + key = &context_vk->graphics.pipeline_key_vk; + memset(key, 0, sizeof(*key)); + + for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i) + { + stage = &key->stages[i]; + stage->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage->pName = "main"; + } + + key->input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + key->input_desc.pVertexBindingDescriptions = key->bindings; + key->input_desc.pVertexAttributeDescriptions = key->attributes; + + key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; + key->divisor_desc.pVertexBindingDivisors = key->divisors; + + key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + + key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; + + key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + key->vp_desc.viewportCount = 1; + key->vp_desc.pViewports = &key->viewport; + key->vp_desc.scissorCount = 1; + key->vp_desc.pScissors = &key->scissor; + + key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + key->rs_desc.lineWidth = 1.0f; + + key->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + + key->ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + key->ds_desc.maxDepthBounds = 1.0f; + + key->blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + key->blend_desc.logicOp = VK_LOGIC_OP_COPY; + key->blend_desc.pAttachments = key->blend_attachments; + key->blend_desc.blendConstants[0] = 1.0f; + key->blend_desc.blendConstants[1] = 1.0f; + key->blend_desc.blendConstants[2] = 1.0f; + key->blend_desc.blendConstants[3] = 1.0f; + + key->dynamic_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + key->dynamic_desc.dynamicStateCount = ARRAY_SIZE(dynamic_states); + key->dynamic_desc.pDynamicStates = dynamic_states; + + key->pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + key->pipeline_desc.pStages = key->stages; + key->pipeline_desc.pVertexInputState = &key->input_desc; + key->pipeline_desc.pInputAssemblyState = &key->ia_desc; + key->pipeline_desc.pTessellationState = &key->ts_desc; + key->pipeline_desc.pViewportState = &key->vp_desc; + key->pipeline_desc.pRasterizationState = &key->rs_desc; + key->pipeline_desc.pMultisampleState = &key->ms_desc; + key->pipeline_desc.pDepthStencilState = &key->ds_desc; + key->pipeline_desc.pColorBlendState = &key->blend_desc; + key->pipeline_desc.pDynamicState = &key->dynamic_desc; + key->pipeline_desc.basePipelineIndex = -1; +} + +static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk *context_vk, + const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key) +{ + const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info; + VkPipelineRasterizationStateCreateInfo *desc = &key->rs_desc; + const struct wined3d_rasterizer_state_desc *r; + float scale_bias; + union + { + uint32_t u32; + float f32; + } const_bias; + + if (!state->rasterizer_state) + { + desc->depthClampEnable = VK_FALSE; + desc->cullMode = VK_CULL_MODE_BACK_BIT; + desc->frontFace = VK_FRONT_FACE_CLOCKWISE; + desc->depthBiasEnable = VK_FALSE; + desc->depthBiasConstantFactor = 0.0f; + desc->depthBiasClamp = 0.0f; + desc->depthBiasSlopeFactor = 0.0f; + + return; + } + + r = &state->rasterizer_state->desc; + desc->depthClampEnable = !r->depth_clip; + desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode); + desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE; + + scale_bias = r->scale_bias; + const_bias.f32 = r->depth_bias; + if (!scale_bias && !const_bias.f32) + { + desc->depthBiasEnable = VK_FALSE; + desc->depthBiasConstantFactor = 0.0f; + desc->depthBiasClamp = 0.0f; + desc->depthBiasSlopeFactor = 0.0f; + + return; + } + + desc->depthBiasEnable = VK_TRUE; + if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS) + { + const struct wined3d_rendertarget_view *dsv; + + if ((dsv = state->fb.depth_stencil)) + { + desc->depthBiasConstantFactor = -(float)const_bias.u32 / dsv->format->depth_bias_scale; + desc->depthBiasSlopeFactor = -(float)const_bias.u32; + } + else + { + desc->depthBiasConstantFactor = 0.0f; + desc->depthBiasSlopeFactor = 0.0f; + } + } + else + { + desc->depthBiasConstantFactor = const_bias.f32; + desc->depthBiasSlopeFactor = scale_bias; + } + desc->depthBiasClamp = r->depth_bias_clamp; +} + +static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk *context_vk, + const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key) +{ + VkPipelineColorBlendStateCreateInfo *desc = &key->blend_desc; + const struct wined3d_blend_state_desc *b; + unsigned int i; + + desc->attachmentCount = context_vk->rt_count; + + memset(key->blend_attachments, 0, sizeof(key->blend_attachments)); + if (!state->blend_state) + { + for (i = 0; i < context_vk->rt_count; ++i) + { + key->blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT + | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT + | VK_COLOR_COMPONENT_A_BIT; + } + + return; + } + + b = &state->blend_state->desc; + for (i = 0; i < context_vk->rt_count; ++i) + { + const struct wined3d_rendertarget_blend_state_desc *rt = &b->rt[b->independent ? i : 0]; + const struct wined3d_rendertarget_view *rtv = state->fb.render_targets[i]; + VkPipelineColorBlendAttachmentState *a = &key->blend_attachments[i]; + enum wined3d_blend src_blend, dst_blend; + const struct wined3d_format *rt_format; + + a->colorWriteMask = vk_colour_write_mask_from_wined3d(rt->writemask); + if (!rt->enable) + continue; + + if (rtv) + rt_format = rtv->format; + else + rt_format = wined3d_get_format(context_vk->c.device->adapter, WINED3DFMT_NULL, 0); + a->blendEnable = VK_TRUE; + + src_blend = rt->src; + dst_blend = rt->dst; + if (src_blend == WINED3D_BLEND_BOTHSRCALPHA) + { + src_blend = WINED3D_BLEND_SRCALPHA; + dst_blend = WINED3D_BLEND_INVSRCALPHA; + } + else if (src_blend == WINED3D_BLEND_BOTHINVSRCALPHA) + { + src_blend = WINED3D_BLEND_INVSRCALPHA; + dst_blend = WINED3D_BLEND_SRCALPHA; + } + a->srcColorBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, FALSE); + a->dstColorBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, FALSE); + a->colorBlendOp = vk_blend_op_from_wined3d(rt->op); + + src_blend = rt->src_alpha; + dst_blend = rt->dst_alpha; + a->srcAlphaBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, TRUE); + a->dstAlphaBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, TRUE); + a->alphaBlendOp = vk_blend_op_from_wined3d(rt->op_alpha); + } +} + +static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk, + const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout) +{ + unsigned int i, attribute_count, binding_count, divisor_count, stage_count; + const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info; + struct wined3d_graphics_pipeline_key_vk *key; + VkPipelineShaderStageCreateInfo *stage; + struct wined3d_stream_info stream_info; + VkPrimitiveTopology vk_topology; + VkShaderModule module; + bool update = false; + uint32_t mask; + + key = &context_vk->graphics.pipeline_key_vk; + + if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE)) + { + stage_count = 0; + for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i) + { + if (!(module = context_vk->graphics.vk_modules[i])) + continue; + + stage = &key->stages[stage_count++]; + stage->stage = vk_shader_stage_from_wined3d(i); + stage->module = module; + } + + key->pipeline_desc.stageCount = stage_count; + + update = true; + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VDECL) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX))) + { + wined3d_stream_info_from_declaration(&stream_info, state, d3d_info); + divisor_count = 0; + for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i) + { + VkVertexInputBindingDivisorDescriptionEXT *d; + struct wined3d_stream_info_element *e; + VkVertexInputAttributeDescription *a; + VkVertexInputBindingDescription *b; + uint32_t binding; + + if (!(stream_info.use_map & (1u << i))) + continue; + + a = &key->attributes[attribute_count++]; + e = &stream_info.elements[i]; + binding = e->stream_idx; + + a->location = i; + a->binding = binding; + a->format = wined3d_format_vk(e->format)->vk_format; + a->offset = (UINT_PTR)e->data.addr - state->streams[binding].offset; + + if (mask & (1u << binding)) + continue; + mask |= 1u << binding; + + b = &key->bindings[binding_count++]; + b->binding = binding; + b->stride = e->stride; + b->inputRate = e->divisor ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; + + if (e->divisor > 1) + { + d = &key->divisors[divisor_count++]; + d->binding = binding; + d->divisor = e->divisor; + } + } + + key->input_desc.pNext = NULL; + key->input_desc.vertexBindingDescriptionCount = binding_count; + key->input_desc.vertexAttributeDescriptionCount = attribute_count; + + if (divisor_count) + { + key->input_desc.pNext = &key->divisor_desc; + key->divisor_desc.vertexBindingDivisorCount = divisor_count; + } + + update = true; + } + + vk_topology = vk_topology_from_wined3d(state->primitive_type); + if (key->ia_desc.topology != vk_topology) + { + key->ia_desc.topology = vk_topology; + key->ia_desc.primitiveRestartEnable = !(d3d_info->wined3d_creation_flags & WINED3D_NO_PRIMITIVE_RESTART) + && !wined3d_primitive_type_is_list(state->primitive_type); + + update = true; + } + + if (key->ts_desc.patchControlPoints != state->patch_vertex_count) + { + key->ts_desc.patchControlPoints = state->patch_vertex_count; + + update = true; + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VIEWPORT) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)) + { + key->viewport.x = state->viewports[0].x; + key->viewport.y = state->viewports[0].y; + key->viewport.width = state->viewports[0].width; + key->viewport.height = state->viewports[0].height; + key->viewport.minDepth = state->viewports[0].min_z; + key->viewport.maxDepth = state->viewports[0].max_z; + + if (state->rasterizer_state && state->rasterizer_state->desc.scissor) + { + const RECT *r = &state->scissor_rects[0]; + + key->scissor.offset.x = r->left; + key->scissor.offset.y = r->top; + key->scissor.extent.width = r->right - r->left; + key->scissor.extent.height = r->bottom - r->top; + } + else + { + key->scissor.offset.x = key->viewport.x; + key->scissor.offset.y = key->viewport.y; + key->scissor.extent.width = key->viewport.width; + key->scissor.extent.height = key->viewport.height; + } + key->viewport.y += key->viewport.height; + key->viewport.height = -key->viewport.height; + + update = true; + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)) + { + wined3d_context_vk_update_rasterisation_state(context_vk, state, key); + + update = true; + } + + if (key->ms_desc.rasterizationSamples != context_vk->sample_count + || isStateDirty(&context_vk->c, STATE_BLEND)) + { + key->ms_desc.rasterizationSamples = context_vk->sample_count; + key->ms_desc.alphaToCoverageEnable = state->blend_state && state->blend_state->desc.alpha_to_coverage; + + update = true; + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RENDER(WINED3D_RS_ZENABLE)) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER)) + { + key->ds_desc.depthTestEnable = !!state->render_states[WINED3D_RS_ZENABLE]; + key->ds_desc.depthWriteEnable = !!state->render_states[WINED3D_RS_ZWRITEENABLE]; + key->ds_desc.depthCompareOp = vk_compare_op_from_wined3d(state->render_states[WINED3D_RS_ZFUNC]); + key->ds_desc.stencilTestEnable = state->fb.depth_stencil && state->render_states[WINED3D_RS_STENCILENABLE]; + if (key->ds_desc.stencilTestEnable) + { + key->ds_desc.front.failOp = vk_stencil_op_from_wined3d(state->render_states[WINED3D_RS_STENCILFAIL]); + key->ds_desc.front.passOp = vk_stencil_op_from_wined3d(state->render_states[WINED3D_RS_STENCILPASS]); + key->ds_desc.front.depthFailOp = vk_stencil_op_from_wined3d(state->render_states[WINED3D_RS_STENCILZFAIL]); + key->ds_desc.front.compareOp = vk_compare_op_from_wined3d(state->render_states[WINED3D_RS_STENCILFUNC]); + key->ds_desc.front.compareMask = state->render_states[WINED3D_RS_STENCILMASK]; + key->ds_desc.front.writeMask = state->render_states[WINED3D_RS_STENCILWRITEMASK]; + key->ds_desc.front.reference = state->render_states[WINED3D_RS_STENCILREF] + & ((1 << state->fb.depth_stencil->format->stencil_size) - 1); + + if (state->render_states[WINED3D_RS_TWOSIDEDSTENCILMODE]) + { + key->ds_desc.back.failOp = vk_stencil_op_from_wined3d( + state->render_states[WINED3D_RS_BACK_STENCILFAIL]); + key->ds_desc.back.passOp = vk_stencil_op_from_wined3d( + state->render_states[WINED3D_RS_BACK_STENCILPASS]); + key->ds_desc.back.depthFailOp = vk_stencil_op_from_wined3d( + state->render_states[WINED3D_RS_BACK_STENCILZFAIL]); + key->ds_desc.back.compareOp = vk_compare_op_from_wined3d( + state->render_states[WINED3D_RS_BACK_STENCILFUNC]); + key->ds_desc.back.compareMask = state->render_states[WINED3D_RS_STENCILMASK]; + key->ds_desc.back.writeMask = state->render_states[WINED3D_RS_STENCILWRITEMASK]; + key->ds_desc.back.reference = state->render_states[WINED3D_RS_STENCILREF] + & ((1 << state->fb.depth_stencil->format->stencil_size) - 1); + } + else + { + key->ds_desc.back = key->ds_desc.front; + } + } + + update = true; + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER)) + { + wined3d_context_vk_update_blend_state(context_vk, state, key); + + update = true; + } + + if (key->pipeline_desc.layout != vk_pipeline_layout) + { + key->pipeline_desc.layout = vk_pipeline_layout; + + update = true; + } + + if (key->pipeline_desc.renderPass != context_vk->vk_render_pass) + { + key->pipeline_desc.renderPass = context_vk->vk_render_pass; + + update = true; + } + + return update; +} + +static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *context_vk, + VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1]; + unsigned int fb_width, fb_height, fb_layer_count; + struct wined3d_rendertarget_view_vk *rtv_vk; + struct wined3d_rendertarget_view *view; + const VkPhysicalDeviceLimits *limits; + VkRenderPassBeginInfo begin_info; + unsigned int attachment_count, i; + VkFramebufferCreateInfo fb_desc; + VkResult vr; + + if (context_vk->vk_render_pass) + return true; + + limits = &wined3d_adapter_vk(device_vk->d.adapter)->device_limits; + fb_width = limits->maxFramebufferWidth; + fb_height = limits->maxFramebufferHeight; + fb_layer_count = limits->maxFramebufferLayers; + attachment_count = 0; + + context_vk->rt_count = 0; + for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i) + { + if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL) + continue; + + rtv_vk = wined3d_rendertarget_view_vk(view); + vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk); + wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk); + + if (view->width < fb_width) + fb_width = view->width; + if (view->height < fb_height) + fb_height = view->height; + if (view->layer_count < fb_layer_count) + fb_layer_count = view->layer_count; + context_vk->rt_count = i + 1; + ++attachment_count; + } + + if ((state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE]) + && (view = state->fb.depth_stencil)) + { + rtv_vk = wined3d_rendertarget_view_vk(view); + vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk); + wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk); + + if (view->width < fb_width) + fb_width = view->width; + if (view->height < fb_height) + fb_height = view->height; + if (view->layer_count < fb_layer_count) + fb_layer_count = view->layer_count; + ++attachment_count; + } + + if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb, + ARRAY_SIZE(state->fb.render_targets), state->render_states[WINED3D_RS_ZWRITEENABLE] + || state->render_states[WINED3D_RS_ZENABLE], 0))) + { + ERR("Failed to get render pass.\n"); + return false; + } + + fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fb_desc.pNext = NULL; + fb_desc.flags = 0; + fb_desc.renderPass = context_vk->vk_render_pass; + fb_desc.attachmentCount = attachment_count; + fb_desc.pAttachments = vk_views; + fb_desc.width = fb_width; + fb_desc.height = fb_height; + fb_desc.layers = fb_layer_count; + + if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &context_vk->vk_framebuffer))) < 0) + { + WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr)); + return false; + } + + begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + begin_info.pNext = NULL; + begin_info.renderPass = context_vk->vk_render_pass; + begin_info.framebuffer = context_vk->vk_framebuffer; + begin_info.renderArea.offset.x = 0; + begin_info.renderArea.offset.y = 0; + begin_info.renderArea.extent.width = fb_width; + begin_info.renderArea.extent.height = fb_height; + begin_info.clearValueCount = 0; + begin_info.pClearValues = NULL; + VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE)); + + return true; +} + +static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *context_vk, + VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info) +{ + VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0}; + VkBuffer buffers[ARRAY_SIZE(state->streams)]; + const struct wined3d_stream_state *stream; + struct wined3d_buffer *buffer; + unsigned int i, first, count; + struct wined3d_bo_vk *bo; + + first = 0; + count = 0; + for (i = 0; i < ARRAY_SIZE(state->streams); ++i) + { + stream = &state->streams[i]; + + if ((buffer = stream->buffer)) + { + bo = &wined3d_buffer_vk(buffer)->bo; + wined3d_context_vk_reference_bo(context_vk, bo); + buffers[count] = bo->vk_buffer; + offsets[count] = bo->buffer_offset + stream->offset; + ++count; + continue; + } + + if (count) + VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets)); + first = i + 1; + count = 0; + } + + if (count) + VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets)); +} + +static VkResult wined3d_context_vk_create_descriptor_pool(struct wined3d_device_vk *device_vk, + const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool) +{ + struct VkDescriptorPoolCreateInfo pool_desc; + VkResult vr; + + static const VkDescriptorPoolSize pool_sizes[] = + { + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024}, + {VK_DESCRIPTOR_TYPE_SAMPLER, 1024}, + }; + + pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_desc.pNext = NULL; + pool_desc.flags = 0; + pool_desc.maxSets = 512; + pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes); + pool_desc.pPoolSizes = pool_sizes; + + if ((vr = VK_CALL(vkCreateDescriptorPool(device_vk->vk_device, &pool_desc, NULL, vk_pool))) < 0) + ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr)); + + return vr; +} + +static VkResult wined3d_context_vk_create_descriptor_set(struct wined3d_context_vk *context_vk, + VkDescriptorSetLayout vk_set_layout, VkDescriptorSet *vk_descriptor_set) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + struct VkDescriptorSetAllocateInfo set_desc; + VkResult vr; + + if (!context_vk->vk_descriptor_pool && (vr = wined3d_context_vk_create_descriptor_pool(device_vk, + vk_info, &context_vk->vk_descriptor_pool))) + { + WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr)); + return vr; + } + + set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + set_desc.pNext = NULL; + set_desc.descriptorPool = context_vk->vk_descriptor_pool; + set_desc.descriptorSetCount = 1; + set_desc.pSetLayouts = &vk_set_layout; + if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0) + return vr; + + if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY) + { + wined3d_context_vk_destroy_descriptor_pool(context_vk, + context_vk->vk_descriptor_pool, context_vk->current_command_buffer.id); + context_vk->vk_descriptor_pool = VK_NULL_HANDLE; + if ((vr = wined3d_context_vk_create_descriptor_pool(device_vk, vk_info, &context_vk->vk_descriptor_pool))) + { + WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr)); + return vr; + } + + set_desc.descriptorPool = context_vk->vk_descriptor_pool; + if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0) + return vr; + } + + WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr)); + + return vr; +} + +static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk *writes, + VkDescriptorSet vk_descriptor_set, size_t binding_idx, VkDescriptorType type, + const VkDescriptorBufferInfo *buffer_info, const VkDescriptorImageInfo *image_info, + const VkBufferView *buffer_view) +{ + SIZE_T write_count = writes->count; + VkWriteDescriptorSet *write; + + if (!wined3d_array_reserve((void **)&writes->writes, &writes->size, + write_count + 1, sizeof(*writes->writes))) + return false; + + write = &writes->writes[write_count]; + write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write->pNext = NULL; + write->dstSet = vk_descriptor_set; + write->dstBinding = binding_idx; + write->dstArrayElement = 0; + write->descriptorCount = 1; + write->descriptorType = type; + write->pImageInfo = image_info; + write->pBufferInfo = buffer_info; + write->pTexelBufferView = buffer_view; + + ++writes->count; + + return true; +} + +static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk *writes, + VkDescriptorSet vk_descriptor_set, size_t binding_idx, enum wined3d_shader_resource_type type, + enum wined3d_data_type data_type, struct wined3d_context_vk *context_vk) +{ + const struct wined3d_null_views_vk *v = &wined3d_device_vk(context_vk->c.device)->null_views_vk; + + switch (type) + { + case WINED3D_SHADER_RESOURCE_BUFFER: + if (data_type == WINED3D_DATA_FLOAT) + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_float); + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_uint); + + case WINED3D_SHADER_RESOURCE_TEXTURE_1D: + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d, NULL); + + case WINED3D_SHADER_RESOURCE_TEXTURE_2D: + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d, NULL); + + case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS: + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms, NULL); + + case WINED3D_SHADER_RESOURCE_TEXTURE_3D: + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_3d, NULL); + + case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE: + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube, NULL); + + case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d_array, NULL); + + case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY: + return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms_array, NULL); + + default: + FIXME("Unhandled resource type %#x.\n", type); + return false; + } +} + +static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *context_vk, + VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, enum wined3d_pipeline pipeline) +{ + struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes; + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + const struct wined3d_shader_resource_binding *binding; + struct wined3d_shader_resource_bindings *bindings; + struct wined3d_unordered_access_view_vk *uav_vk; + struct wined3d_shader_resource_view_vk *srv_vk; + struct wined3d_unordered_access_view *uav; + const VkDescriptorBufferInfo *buffer_info; + struct wined3d_shader_resource_view *srv; + const VkDescriptorImageInfo *image_info; + struct wined3d_buffer_vk *buffer_vk; + VkDescriptorSetLayout vk_set_layout; + VkPipelineLayout vk_pipeline_layout; + struct wined3d_resource *resource; + VkPipelineBindPoint vk_bind_point; + VkDescriptorSet vk_descriptor_set; + struct wined3d_view_vk *view_vk; + struct wined3d_sampler *sampler; + struct wined3d_buffer *buffer; + VkBufferView *buffer_view; + VkDescriptorType type; + VkResult vr; + size_t i; + + switch (pipeline) + { + case WINED3D_PIPELINE_GRAPHICS: + bindings = &context_vk->graphics.bindings; + vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; + vk_set_layout = context_vk->graphics.vk_set_layout; + vk_pipeline_layout = context_vk->graphics.vk_pipeline_layout; + break; + + case WINED3D_PIPELINE_COMPUTE: + bindings = &context_vk->compute.bindings; + vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; + vk_set_layout = context_vk->compute.vk_set_layout; + vk_pipeline_layout = context_vk->compute.vk_pipeline_layout; + break; + + default: + ERR("Invalid pipeline %#x.\n", pipeline); + return false; + } + + if ((vr = wined3d_context_vk_create_descriptor_set(context_vk, vk_set_layout, &vk_descriptor_set))) + { + WARN("Failed to create descriptor set, vr %s.\n", wined3d_debug_vkresult(vr)); + return false; + } + + writes->count = 0; + for (i = 0; i < bindings->count; ++i) + { + binding = &bindings->bindings[i]; + + switch (binding->shader_descriptor_type) + { + case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV: + if (!(buffer = state->cb[binding->shader_type][binding->resource_idx])) + { + FIXME("NULL constant buffer views not implemented.\n"); + return false; + } + buffer_vk = wined3d_buffer_vk(buffer); + buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk); + if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL)) + return false; + wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo); + break; + + case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV: + if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx])) + { + if (!wined3d_shader_resource_bindings_add_null_srv_binding(writes, vk_descriptor_set, + binding->binding_idx, binding->resource_type, binding->resource_data_type, context_vk)) + return false; + break; + } + resource = srv->resource; + + srv_vk = wined3d_shader_resource_view_vk(srv); + view_vk = &srv_vk->view_vk; + if (resource->type == WINED3D_RTYPE_BUFFER) + { + image_info = NULL; + buffer_view = &view_vk->u.vk_buffer_view; + type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + } + else + { + struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource)); + + if (view_vk->u.vk_image_info.imageView) + image_info = &view_vk->u.vk_image_info; + else + image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk); + buffer_view = NULL; + type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + } + + if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding->binding_idx, type, NULL, image_info, buffer_view)) + return false; + wined3d_context_vk_reference_shader_resource_view(context_vk, srv_vk); + break; + + case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV: + if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx])) + { + FIXME("NULL unordered access views not implemented.\n"); + return false; + } + resource = uav->resource; + + uav_vk = wined3d_unordered_access_view_vk(uav); + view_vk = &uav_vk->view_vk; + if (resource->type == WINED3D_RTYPE_BUFFER) + { + image_info = NULL; + buffer_view = &view_vk->u.vk_buffer_view; + type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + } + else + { + struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource)); + + if (view_vk->u.vk_image_info.imageView) + image_info = &view_vk->u.vk_image_info; + else + image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk); + buffer_view = NULL; + type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + } + + if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, + binding->binding_idx, type, NULL, image_info, buffer_view)) + return false; + wined3d_context_vk_reference_unordered_access_view(context_vk, uav_vk); + break; + + case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER: + if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx])) + { + FIXME("NULL unordered access view counters not implemented.\n"); + return false; + } + + uav_vk = wined3d_unordered_access_view_vk(uav); + if (!uav_vk->vk_counter_view || !wined3d_shader_descriptor_writes_vk_add_write(writes, + vk_descriptor_set, binding->binding_idx, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + NULL, NULL, &uav_vk->vk_counter_view)) + return false; + break; + + case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: + if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx])) + sampler = context_vk->c.device->null_sampler; + if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx, + VK_DESCRIPTOR_TYPE_SAMPLER, NULL, &wined3d_sampler_vk(sampler)->vk_image_info, NULL)) + return false; + wined3d_context_vk_reference_sampler(context_vk, wined3d_sampler_vk(sampler)); + break; + + default: + ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type); + return false; + } + } + + VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, writes->count, writes->writes, 0, NULL)); + VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, vk_bind_point, + vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, NULL)); + + return true; +} + +static VkResult wined3d_context_vk_create_descriptor_set_layout(struct wined3d_device_vk *device_vk, + const struct wined3d_vk_info *vk_info, const struct wined3d_pipeline_layout_key_vk *key, + VkDescriptorSetLayout *vk_set_layout) +{ + VkDescriptorSetLayoutCreateInfo layout_desc; + VkResult vr; + + layout_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_desc.pNext = NULL; + layout_desc.flags = 0; + layout_desc.bindingCount = key->binding_count; + layout_desc.pBindings = key->bindings; + + if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device_vk->vk_device, &layout_desc, NULL, vk_set_layout))) < 0) + WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr)); + + return vr; +} + +struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout( + struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + struct wined3d_pipeline_layout_key_vk key; + struct wined3d_pipeline_layout_vk *layout; + VkPipelineLayoutCreateInfo layout_desc; + struct wine_rb_entry *entry; + VkResult vr; + + key.bindings = bindings; + key.binding_count = binding_count; + if ((entry = wine_rb_get(&context_vk->pipeline_layouts, &key))) + return WINE_RB_ENTRY_VALUE(entry, struct wined3d_pipeline_layout_vk, entry); + + if (!(layout = heap_alloc(sizeof(*layout)))) + return NULL; + + if (!(layout->key.bindings = heap_alloc(sizeof(*layout->key.bindings) * key.binding_count))) + { + heap_free(layout); + return NULL; + } + memcpy(layout->key.bindings, key.bindings, sizeof(*layout->key.bindings) * key.binding_count); + layout->key.binding_count = key.binding_count; + + if ((vr = wined3d_context_vk_create_descriptor_set_layout(device_vk, vk_info, &key, &layout->vk_set_layout))) + { + WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + + layout_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_desc.pNext = NULL; + layout_desc.flags = 0; + layout_desc.setLayoutCount = 1; + layout_desc.pSetLayouts = &layout->vk_set_layout; + layout_desc.pushConstantRangeCount = 0; + layout_desc.pPushConstantRanges = NULL; + + if ((vr = VK_CALL(vkCreatePipelineLayout(device_vk->vk_device, + &layout_desc, NULL, &layout->vk_pipeline_layout))) < 0) + { + WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr)); + VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL)); + goto fail; + } + + if (wine_rb_put(&context_vk->pipeline_layouts, &layout->key, &layout->entry) == -1) + { + ERR("Failed to insert pipeline layout.\n"); + VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL)); + VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL)); + goto fail; + } + + return layout; + +fail: + heap_free(layout->key.bindings); + heap_free(layout); + return NULL; +} + +static VkPipeline wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk *context_vk) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + struct wined3d_graphics_pipeline_vk *pipeline_vk; + struct wined3d_graphics_pipeline_key_vk *key; + struct wine_rb_entry *entry; + VkResult vr; + + key = &context_vk->graphics.pipeline_key_vk; + if ((entry = wine_rb_get(&context_vk->graphics_pipelines, key))) + return WINE_RB_ENTRY_VALUE(entry, struct wined3d_graphics_pipeline_vk, entry)->vk_pipeline; + + if (!(pipeline_vk = heap_alloc(sizeof(*pipeline_vk)))) + return VK_NULL_HANDLE; + pipeline_vk->key = *key; + + if ((vr = VK_CALL(vkCreateGraphicsPipelines(device_vk->vk_device, + VK_NULL_HANDLE, 1, &key->pipeline_desc, NULL, &pipeline_vk->vk_pipeline))) < 0) + { + WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr)); + heap_free(pipeline_vk); + return VK_NULL_HANDLE; + } + + if (wine_rb_put(&context_vk->graphics_pipelines, &pipeline_vk->key, &pipeline_vk->entry) == -1) + ERR("Failed to insert pipeline.\n"); + + return pipeline_vk->vk_pipeline; +} + +static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *context_vk, + const struct wined3d_state *state, enum wined3d_pipeline pipeline) +{ + struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes; + const struct wined3d_shader_resource_bindings *bindings; + const struct wined3d_shader_resource_binding *binding; + struct wined3d_unordered_access_view_vk *uav_vk; + struct wined3d_shader_resource_view_vk *srv_vk; + struct wined3d_unordered_access_view *uav; + struct wined3d_shader_resource_view *srv; + struct wined3d_buffer_vk *buffer_vk; + struct wined3d_sampler *sampler; + struct wined3d_buffer *buffer; + size_t i; + + switch (pipeline) + { + case WINED3D_PIPELINE_GRAPHICS: + bindings = &context_vk->graphics.bindings; + break; + + case WINED3D_PIPELINE_COMPUTE: + bindings = &context_vk->compute.bindings; + break; + + default: + ERR("Invalid pipeline %#x.\n", pipeline); + return; + } + + writes->count = 0; + for (i = 0; i < bindings->count; ++i) + { + binding = &bindings->bindings[i]; + + switch (binding->shader_descriptor_type) + { + case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV: + if (!(buffer = state->cb[binding->shader_type][binding->resource_idx])) + break; + + buffer_vk = wined3d_buffer_vk(buffer); + wined3d_buffer_load(buffer, &context_vk->c, state); + if (!buffer_vk->bo_user.valid) + { + if (pipeline == WINED3D_PIPELINE_GRAPHICS) + context_invalidate_state(&context_vk->c, STATE_GRAPHICS_CONSTANT_BUFFER(binding->shader_type)); + else + context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER); + } + break; + + case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV: + if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx])) + break; + + srv_vk = wined3d_shader_resource_view_vk(srv); + if (srv->resource->type == WINED3D_RTYPE_BUFFER) + { + if (!srv_vk->view_vk.bo_user.valid) + { + wined3d_shader_resource_view_vk_update(srv_vk, context_vk); + if (pipeline == WINED3D_PIPELINE_GRAPHICS) + context_invalidate_state(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); + else + context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING); + } + wined3d_buffer_load(buffer_from_resource(srv->resource), &context_vk->c, state); + } + else + { + wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE); + } + break; + + case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV: + if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx])) + break; + + uav_vk = wined3d_unordered_access_view_vk(uav); + if (uav->resource->type == WINED3D_RTYPE_BUFFER) + { + if (!uav_vk->view_vk.bo_user.valid) + { + wined3d_unordered_access_view_vk_update(uav_vk, context_vk); + if (pipeline == WINED3D_PIPELINE_GRAPHICS) + context_invalidate_state(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING); + else + context_invalidate_compute_state(&context_vk->c, + STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING); + } + wined3d_buffer_load(buffer_from_resource(uav->resource), &context_vk->c, state); + wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_BUFFER); + } + else + { + wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE); + wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB); + } + break; + + case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER: + break; + + case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: + if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx])) + sampler = context_vk->c.device->null_sampler; + break; + + default: + ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type); + break; + } + } +} + +VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk, + const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + struct wined3d_rendertarget_view *dsv; + VkSampleCountFlagBits sample_count; + VkCommandBuffer vk_command_buffer; + struct wined3d_buffer *buffer; + unsigned int i; + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER)) + context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL); + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX))) + context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_VERTEX); + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY))) + context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_GEOMETRY); + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_HULL))) + context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_HULL) | (1u << WINED3D_SHADER_TYPE_DOMAIN); + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN))) + context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_DOMAIN); + + context_vk->sample_count = 0; + for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i) + { + struct wined3d_rendertarget_view *rtv; + + if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL) + continue; + + if (wined3d_blend_state_get_writemask(state->blend_state, i)) + { + wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding); + wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding); + } + else + { + wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding); + } + + sample_count = max(1, wined3d_resource_get_sample_count(rtv->resource)); + if (!context_vk->sample_count) + context_vk->sample_count = sample_count; + else if (context_vk->sample_count != sample_count) + FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count); + } + + if ((dsv = state->fb.depth_stencil)) + { + if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE]) + wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding); + else + wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding); + if (state->render_states[WINED3D_RS_ZWRITEENABLE]) + wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding); + + sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource)); + if (!context_vk->sample_count) + context_vk->sample_count = sample_count; + else if (context_vk->sample_count != sample_count) + FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count); + } + + if (!context_vk->sample_count) + context_vk->sample_count = VK_SAMPLE_COUNT_1_BIT; + if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE)) + { + device_vk->d.shader_backend->shader_select(device_vk->d.shader_priv, &context_vk->c, state); + if (!context_vk->graphics.vk_pipeline_layout) + { + ERR("No pipeline layout set.\n"); + return VK_NULL_HANDLE; + } + context_vk->c.update_shader_resource_bindings = 1; + context_vk->c.update_unordered_access_view_bindings = 1; + } + + wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_GRAPHICS); + + for (i = 0; i < ARRAY_SIZE(state->streams); ++i) + { + if (!(buffer = state->streams[i].buffer)) + continue; + + wined3d_buffer_load(buffer, &context_vk->c, state); + if (!wined3d_buffer_vk(buffer)->bo_user.valid) + context_invalidate_state(&context_vk->c, STATE_STREAMSRC); + } + + if (indexed) + { + wined3d_buffer_load(state->index_buffer, &context_vk->c, state); + if (!wined3d_buffer_vk(state->index_buffer)->bo_user.valid) + context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER); + } + + if (indirect_vk) + wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state); + + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + { + ERR("Failed to get command buffer.\n"); + return VK_NULL_HANDLE; + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER)) + wined3d_context_vk_end_current_render_pass(context_vk); + if (!wined3d_context_vk_begin_render_pass(context_vk, vk_command_buffer, state, vk_info)) + { + ERR("Failed to begin render pass.\n"); + return VK_NULL_HANDLE; + } + + if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout) + || !context_vk->graphics.vk_pipeline) + { + if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk))) + { + ERR("Failed to get graphics pipeline.\n"); + return VK_NULL_HANDLE; + } + + VK_CALL(vkCmdBindPipeline(vk_command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline)); + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC)) + wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info); + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer) + { + struct wined3d_bo_vk *bo = &wined3d_buffer_vk(state->index_buffer)->bo; + VkIndexType idx_type; + + if (state->index_format == WINED3DFMT_R16_UINT) + idx_type = VK_INDEX_TYPE_UINT16; + else + idx_type = VK_INDEX_TYPE_UINT32; + wined3d_context_vk_reference_bo(context_vk, bo); + VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, bo->vk_buffer, + bo->buffer_offset + state->index_offset, idx_type)); + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL)) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, + STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX)) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, + STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY)) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, + STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL)) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, + STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN)) + || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING)) + context_vk->c.update_shader_resource_bindings = 1; + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING)) + context_vk->c.update_unordered_access_view_bindings = 1; + + if (context_vk->c.update_shader_resource_bindings || context_vk->c.update_unordered_access_view_bindings) + { + if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_GRAPHICS)) + { + ERR("Failed to update shader descriptors.\n"); + return VK_NULL_HANDLE; + } + + context_vk->c.update_shader_resource_bindings = 0; + context_vk->c.update_unordered_access_view_bindings = 0; + } + + if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND_FACTOR)) + VK_CALL(vkCmdSetBlendConstants(vk_command_buffer, &state->blend_factor.r)); + + memset(context_vk->c.dirty_graphics_states, 0, sizeof(context_vk->c.dirty_graphics_states)); + context_vk->c.shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE; + + return vk_command_buffer; +} + +VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk, + const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + VkCommandBuffer vk_command_buffer; + + wined3d_context_vk_end_current_render_pass(context_vk); + + if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER)) + context_vk->c.shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE; + + if (context_vk->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE)) + { + device_vk->d.shader_backend->shader_select_compute(device_vk->d.shader_priv, &context_vk->c, state); + if (!context_vk->compute.vk_pipeline) + { + ERR("No compute pipeline set.\n"); + return VK_NULL_HANDLE; + } + context_vk->c.update_compute_shader_resource_bindings = 1; + context_vk->c.update_compute_unordered_access_view_bindings = 1; + context_vk->update_compute_pipeline = 1; + } + + wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE); + + if (indirect_vk) + wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER); + + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + { + ERR("Failed to get command buffer.\n"); + return VK_NULL_HANDLE; + } + + if (context_vk->update_compute_pipeline) + { + VK_CALL(vkCmdBindPipeline(vk_command_buffer, + VK_PIPELINE_BIND_POINT_COMPUTE, context_vk->compute.vk_pipeline)); + context_vk->update_compute_pipeline = 0; + } + + if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER) + || wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING)) + context_vk->c.update_compute_shader_resource_bindings = 1; + if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING)) + context_vk->c.update_compute_unordered_access_view_bindings = 1; + + if (context_vk->c.update_compute_shader_resource_bindings + || context_vk->c.update_compute_unordered_access_view_bindings) + { + if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_COMPUTE)) + { + ERR("Failed to update shader descriptors.\n"); + return VK_NULL_HANDLE; + } + + context_vk->c.update_compute_shader_resource_bindings = 0; + context_vk->c.update_compute_unordered_access_view_bindings = 0; + } + + memset(context_vk->c.dirty_compute_states, 0, sizeof(context_vk->c.dirty_compute_states)); + context_vk->c.shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE); + + return vk_command_buffer; +} + HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain) { VkCommandPoolCreateInfo command_pool_info; @@ -1150,7 +2907,11 @@ } context_vk->current_command_buffer.id = 1; + wined3d_context_vk_init_graphics_pipeline_key(context_vk); + wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare); + wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare); + wine_rb_init(&context_vk->graphics_pipelines, wined3d_graphics_pipeline_vk_compare); wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare); return WINED3D_OK; diff -Nru wine-development-5.8/dlls/wined3d/cs.c wine-development-5.9/dlls/wined3d/cs.c --- wine-development-5.8/dlls/wined3d/cs.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/cs.c 2020-05-22 18:49:34.000000000 +0000 @@ -21,6 +21,7 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(fps); #define WINED3D_INITIAL_CS_SIZE 4096 @@ -121,7 +122,7 @@ struct wined3d_cs_draw { enum wined3d_cs_op opcode; - GLenum primitive_type; + enum wined3d_primitive_type primitive_type; GLint patch_vertex_count; struct wined3d_draw_parameters parameters; }; @@ -529,6 +530,21 @@ swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->swap_interval, op->flags); + if (TRACE_ON(fps)) + { + DWORD time = GetTickCount(); + ++swapchain->frames; + + /* every 1.5 seconds */ + if (time - swapchain->prev_time > 1500) + { + TRACE_(fps)("%p @ approx %.2ffps\n", + swapchain, 1000.0 * swapchain->frames / (time - swapchain->prev_time)); + swapchain->prev_time = time; + swapchain->frames = 0; + } + } + wined3d_resource_release(&swapchain->front_buffer->resource); for (i = 0; i < swapchain->state.desc.backbuffer_count; ++i) { @@ -785,7 +801,10 @@ const struct wined3d_cs_dispatch *op = data; struct wined3d_state *state = &cs->state; - cs->device->adapter->adapter_ops->adapter_dispatch_compute(cs->device, state, &op->parameters); + if (!state->shader[WINED3D_SHADER_TYPE_COMPUTE]) + WARN("No compute shader bound, skipping dispatch.\n"); + else + cs->device->adapter->adapter_ops->adapter_dispatch_compute(cs->device, state, &op->parameters); if (op->parameters.indirect) wined3d_resource_release(&op->parameters.u.indirect.buffer->resource); @@ -878,15 +897,15 @@ device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX); } - if (state->gl_primitive_type != op->primitive_type) + if (state->primitive_type != op->primitive_type) { if ((geometry_shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) && !geometry_shader->function) device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)); - if (state->gl_primitive_type == GL_POINTS || op->primitive_type == GL_POINTS) + if (state->primitive_type == WINED3D_PT_POINTLIST || op->primitive_type == WINED3D_PT_POINTLIST) device_invalidate_state(cs->device, STATE_POINT_ENABLE); - state->gl_primitive_type = op->primitive_type; + state->primitive_type = op->primitive_type; } - state->gl_patch_vertices = op->patch_vertex_count; + state->patch_vertex_count = op->patch_vertex_count; cs->device->adapter->adapter_ops->adapter_draw_primitive(cs->device, state, &op->parameters); @@ -959,9 +978,9 @@ state->unordered_access_view[WINED3D_PIPELINE_GRAPHICS]); } -void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, unsigned int patch_vertex_count, - int base_vertex_idx, unsigned int start_idx, unsigned int index_count, - unsigned int start_instance, unsigned int instance_count, BOOL indexed) +void wined3d_cs_emit_draw(struct wined3d_cs *cs, enum wined3d_primitive_type primitive_type, + unsigned int patch_vertex_count, int base_vertex_idx, unsigned int start_idx, + unsigned int index_count, unsigned int start_instance, unsigned int instance_count, bool indexed) { const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info; const struct wined3d_state *state = &cs->device->state; @@ -984,8 +1003,8 @@ wined3d_cs_submit(cs, WINED3D_CS_QUEUE_DEFAULT); } -void wined3d_cs_emit_draw_indirect(struct wined3d_cs *cs, GLenum primitive_type, unsigned int patch_vertex_count, - struct wined3d_buffer *buffer, unsigned int offset, BOOL indexed) +void wined3d_cs_emit_draw_indirect(struct wined3d_cs *cs, enum wined3d_primitive_type primitive_type, + unsigned int patch_vertex_count, struct wined3d_buffer *buffer, unsigned int offset, bool indexed) { const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info; const struct wined3d_state *state = &cs->device->state; diff -Nru wine-development-5.8/dlls/wined3d/device.c wine-development-5.9/dlls/wined3d/device.c --- wine-development-5.8/dlls/wined3d/device.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/device.c 2020-05-22 18:49:34.000000000 +0000 @@ -90,96 +90,6 @@ 0.0f /* Phi */ }; -/* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these - * actually have the same values in GL and D3D. */ -GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) -{ - switch (primitive_type) - { - case WINED3D_PT_POINTLIST: - return GL_POINTS; - - case WINED3D_PT_LINELIST: - return GL_LINES; - - case WINED3D_PT_LINESTRIP: - return GL_LINE_STRIP; - - case WINED3D_PT_TRIANGLELIST: - return GL_TRIANGLES; - - case WINED3D_PT_TRIANGLESTRIP: - return GL_TRIANGLE_STRIP; - - case WINED3D_PT_TRIANGLEFAN: - return GL_TRIANGLE_FAN; - - case WINED3D_PT_LINELIST_ADJ: - return GL_LINES_ADJACENCY_ARB; - - case WINED3D_PT_LINESTRIP_ADJ: - return GL_LINE_STRIP_ADJACENCY_ARB; - - case WINED3D_PT_TRIANGLELIST_ADJ: - return GL_TRIANGLES_ADJACENCY_ARB; - - case WINED3D_PT_TRIANGLESTRIP_ADJ: - return GL_TRIANGLE_STRIP_ADJACENCY_ARB; - - case WINED3D_PT_PATCH: - return GL_PATCHES; - - default: - FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); - case WINED3D_PT_UNDEFINED: - return ~0u; - } -} - -enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) -{ - switch (primitive_type) - { - case GL_POINTS: - return WINED3D_PT_POINTLIST; - - case GL_LINES: - return WINED3D_PT_LINELIST; - - case GL_LINE_STRIP: - return WINED3D_PT_LINESTRIP; - - case GL_TRIANGLES: - return WINED3D_PT_TRIANGLELIST; - - case GL_TRIANGLE_STRIP: - return WINED3D_PT_TRIANGLESTRIP; - - case GL_TRIANGLE_FAN: - return WINED3D_PT_TRIANGLEFAN; - - case GL_LINES_ADJACENCY_ARB: - return WINED3D_PT_LINELIST_ADJ; - - case GL_LINE_STRIP_ADJACENCY_ARB: - return WINED3D_PT_LINESTRIP_ADJ; - - case GL_TRIANGLES_ADJACENCY_ARB: - return WINED3D_PT_TRIANGLELIST_ADJ; - - case GL_TRIANGLE_STRIP_ADJACENCY_ARB: - return WINED3D_PT_TRIANGLESTRIP_ADJ; - - case GL_PATCHES: - return WINED3D_PT_PATCH; - - default: - FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); - case ~0u: - return WINED3D_PT_UNDEFINED; - } -} - BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *context) { struct wined3d_context **new_array; @@ -655,6 +565,368 @@ device->null_sampler = NULL; } +static void wined3d_null_image_vk_cleanup(struct wined3d_null_image_vk *image, + struct wined3d_context_vk *context_vk, uint64_t command_buffer_id) +{ + wined3d_context_vk_destroy_image(context_vk, image->vk_image, command_buffer_id); + if (image->memory) + wined3d_context_vk_destroy_allocator_block(context_vk, image->memory, command_buffer_id); + else + wined3d_context_vk_destroy_memory(context_vk, image->vk_memory, command_buffer_id); +} + +static bool wined3d_null_image_vk_init(struct wined3d_null_image_vk *image, struct wined3d_context_vk *context_vk, + VkCommandBuffer vk_command_buffer, VkImageType type, unsigned int layer_count, unsigned int sample_count) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + VkMemoryRequirements memory_requirements; + VkImageSubresourceRange range; + VkImageCreateInfo image_desc; + unsigned int memory_type_idx; + uint32_t flags = 0; + VkResult vr; + + static const VkClearColorValue colour = {{0}}; + + TRACE("image %p, context_vk %p, vk_command_buffer %p, type %#x, layer_count %u, sample_count %u.\n", + image, context_vk, vk_command_buffer, type, layer_count, sample_count); + + if (type == VK_IMAGE_TYPE_2D && layer_count >= 6) + flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + image_desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_desc.pNext = NULL; + image_desc.flags = flags; + image_desc.imageType = type; + image_desc.format = VK_FORMAT_R8G8B8A8_UNORM; + image_desc.extent.width = 1; + image_desc.extent.height = 1; + image_desc.extent.depth = 1; + image_desc.mipLevels = 1; + image_desc.arrayLayers = layer_count; + image_desc.samples = sample_count; + image_desc.tiling = VK_IMAGE_TILING_OPTIMAL; + image_desc.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + image_desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_desc.queueFamilyIndexCount = 0; + image_desc.pQueueFamilyIndices = NULL; + image_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if ((vr = VK_CALL(vkCreateImage(device_vk->vk_device, &image_desc, NULL, &image->vk_image))) < 0) + { + ERR("Failed to create Vulkan image, vr %s.\n", wined3d_debug_vkresult(vr)); + return false; + } + + VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, image->vk_image, &memory_requirements)); + + memory_type_idx = wined3d_adapter_vk_get_memory_type_index(wined3d_adapter_vk(device_vk->d.adapter), + memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (memory_type_idx == ~0u) + { + ERR("Failed to find suitable image memory type.\n"); + VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL)); + image->vk_image = VK_NULL_HANDLE; + return false; + } + + image->memory = wined3d_context_vk_allocate_memory(context_vk, + memory_type_idx, memory_requirements.size, &image->vk_memory); + if (!image->vk_memory) + { + ERR("Failed to allocate image memory.\n"); + VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL)); + image->vk_image = VK_NULL_HANDLE; + return false; + } + + if ((vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, image->vk_image, + image->vk_memory, image->memory ? image->memory->offset : 0))) < 0) + { + ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr)); + if (image->memory) + wined3d_allocator_block_free(image->memory); + else + VK_CALL(vkFreeMemory(device_vk->vk_device, image->vk_memory, NULL)); + VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL)); + image->vk_image = VK_NULL_HANDLE; + return false; + } + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + image->vk_image, VK_IMAGE_ASPECT_COLOR_BIT); + + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.baseMipLevel = 0; + range.levelCount = 1; + range.baseArrayLayer = 0; + range.layerCount = layer_count; + VK_CALL(vkCmdClearColorImage(vk_command_buffer, image->vk_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colour, 1, &range)); + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 0, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + image->vk_image, VK_IMAGE_ASPECT_COLOR_BIT); + + TRACE("Created NULL image 0x%s, memory 0x%s.\n", + wine_dbgstr_longlong(image->vk_image), wine_dbgstr_longlong(image->vk_memory)); + + return true; +} + +bool wined3d_device_vk_create_null_resources(struct wined3d_device_vk *device_vk, + struct wined3d_context_vk *context_vk) +{ + struct wined3d_null_resources_vk *r = &device_vk->null_resources_vk; + const struct wined3d_vk_info *vk_info; + const struct wined3d_format *format; + VkMemoryPropertyFlags memory_type; + VkCommandBuffer vk_command_buffer; + unsigned int sample_count = 2; + VkBufferUsageFlags usage; + uint64_t id; + + format = wined3d_get_format(device_vk->d.adapter, WINED3DFMT_R8G8B8A8_UNORM, WINED3D_BIND_SHADER_RESOURCE); + while (sample_count && !(sample_count & format->multisample_types)) + sample_count <<= 1; + + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + { + ERR("Failed to get command buffer.\n"); + return false; + } + + vk_info = context_vk->vk_info; + + usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + memory_type = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + if (!wined3d_context_vk_create_bo(context_vk, 16, usage, memory_type, &r->bo)) + return false; + VK_CALL(vkCmdFillBuffer(vk_command_buffer, r->bo.vk_buffer, r->bo.buffer_offset, r->bo.size, 0x00000000u)); + + if (!wined3d_null_image_vk_init(&r->image_1d, context_vk, vk_command_buffer, VK_IMAGE_TYPE_1D, 1, 1)) + { + ERR("Failed to create 1D image.\n"); + goto fail; + } + + if (!wined3d_null_image_vk_init(&r->image_2d, context_vk, vk_command_buffer, VK_IMAGE_TYPE_2D, 6, 1)) + { + ERR("Failed to create 2D image.\n"); + goto fail; + } + + if (!wined3d_null_image_vk_init(&r->image_2dms, context_vk, vk_command_buffer, VK_IMAGE_TYPE_2D, 1, sample_count)) + { + ERR("Failed to create 2D MSAA image.\n"); + goto fail; + } + + if (!wined3d_null_image_vk_init(&r->image_3d, context_vk, vk_command_buffer, VK_IMAGE_TYPE_3D, 1, 1)) + { + ERR("Failed to create 3D image.\n"); + goto fail; + } + + return true; + +fail: + id = context_vk->current_command_buffer.id; + if (r->image_2dms.vk_image) + wined3d_null_image_vk_cleanup(&r->image_2dms, context_vk, id); + if (r->image_2d.vk_image) + wined3d_null_image_vk_cleanup(&r->image_2d, context_vk, id); + if (r->image_1d.vk_image) + wined3d_null_image_vk_cleanup(&r->image_1d, context_vk, id); + wined3d_context_vk_reference_bo(context_vk, &r->bo); + wined3d_context_vk_destroy_bo(context_vk, &r->bo); + return false; +} + +void wined3d_device_vk_destroy_null_resources(struct wined3d_device_vk *device_vk, + struct wined3d_context_vk *context_vk) +{ + struct wined3d_null_resources_vk *r = &device_vk->null_resources_vk; + uint64_t id = context_vk->current_command_buffer.id; + + /* We don't track command buffer references to NULL resources. We easily + * could, but it doesn't seem worth it. */ + wined3d_null_image_vk_cleanup(&r->image_3d, context_vk, id); + wined3d_null_image_vk_cleanup(&r->image_2dms, context_vk, id); + wined3d_null_image_vk_cleanup(&r->image_2d, context_vk, id); + wined3d_null_image_vk_cleanup(&r->image_1d, context_vk, id); + wined3d_context_vk_reference_bo(context_vk, &r->bo); + wined3d_context_vk_destroy_bo(context_vk, &r->bo); +} + +bool wined3d_device_vk_create_null_views(struct wined3d_device_vk *device_vk, struct wined3d_context_vk *context_vk) +{ + struct wined3d_null_resources_vk *r = &device_vk->null_resources_vk; + struct wined3d_null_views_vk *v = &device_vk->null_views_vk; + VkBufferViewCreateInfo buffer_create_info; + const struct wined3d_vk_info *vk_info; + VkImageViewCreateInfo view_desc; + VkResult vr; + + vk_info = context_vk->vk_info; + + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; + buffer_create_info.pNext = NULL; + buffer_create_info.flags = 0; + buffer_create_info.buffer = r->bo.vk_buffer; + buffer_create_info.format = VK_FORMAT_R32_UINT; + buffer_create_info.offset = r->bo.buffer_offset; + buffer_create_info.range = r->bo.size; + + if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device, + &buffer_create_info, NULL, &v->vk_view_buffer_uint))) < 0) + { + ERR("Failed to create buffer view, vr %s.\n", wined3d_debug_vkresult(vr)); + return false; + } + TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(v->vk_view_buffer_uint)); + + buffer_create_info.format = VK_FORMAT_R32G32B32A32_SFLOAT; + if ((vr = VK_CALL(vkCreateBufferView(device_vk->vk_device, + &buffer_create_info, NULL, &v->vk_view_buffer_float))) < 0) + { + ERR("Failed to create buffer view, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(v->vk_view_buffer_float)); + + view_desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_desc.pNext = NULL; + view_desc.flags = 0; + view_desc.image = r->image_1d.vk_image; + view_desc.viewType = VK_IMAGE_VIEW_TYPE_1D; + view_desc.format = VK_FORMAT_R8G8B8A8_UNORM; + view_desc.components.r = VK_COMPONENT_SWIZZLE_ZERO; + view_desc.components.g = VK_COMPONENT_SWIZZLE_ZERO; + view_desc.components.b = VK_COMPONENT_SWIZZLE_ZERO; + view_desc.components.a = VK_COMPONENT_SWIZZLE_ZERO; + view_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_desc.subresourceRange.baseMipLevel = 0; + view_desc.subresourceRange.levelCount = 1; + view_desc.subresourceRange.baseArrayLayer = 0; + view_desc.subresourceRange.layerCount = 1; + if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &view_desc, NULL, &v->vk_info_1d.imageView))) < 0) + { + ERR("Failed to create 1D image view, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + v->vk_info_1d.sampler = VK_NULL_HANDLE; + v->vk_info_1d.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + TRACE("Created 1D image view 0x%s.\n", wine_dbgstr_longlong(v->vk_info_1d.imageView)); + + view_desc.image = r->image_2d.vk_image; + view_desc.viewType = VK_IMAGE_VIEW_TYPE_2D; + if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &view_desc, NULL, &v->vk_info_2d.imageView))) < 0) + { + ERR("Failed to create 2D image view, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + v->vk_info_2d.sampler = VK_NULL_HANDLE; + v->vk_info_2d.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + TRACE("Created 2D image view 0x%s.\n", wine_dbgstr_longlong(v->vk_info_2d.imageView)); + + view_desc.image = r->image_2dms.vk_image; + view_desc.viewType = VK_IMAGE_VIEW_TYPE_2D; + if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &view_desc, NULL, &v->vk_info_2dms.imageView))) < 0) + { + ERR("Failed to create 2D MSAA image view, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + v->vk_info_2dms.sampler = VK_NULL_HANDLE; + v->vk_info_2dms.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + TRACE("Created 2D MSAA image view 0x%s.\n", wine_dbgstr_longlong(v->vk_info_2dms.imageView)); + + view_desc.image = r->image_3d.vk_image; + view_desc.viewType = VK_IMAGE_VIEW_TYPE_3D; + if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &view_desc, NULL, &v->vk_info_3d.imageView))) < 0) + { + ERR("Failed to create 3D image view, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + v->vk_info_3d.sampler = VK_NULL_HANDLE; + v->vk_info_3d.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + TRACE("Created 3D image view 0x%s.\n", wine_dbgstr_longlong(v->vk_info_3d.imageView)); + + view_desc.image = r->image_2d.vk_image; + view_desc.subresourceRange.layerCount = 6; + view_desc.viewType = VK_IMAGE_VIEW_TYPE_CUBE; + if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &view_desc, NULL, &v->vk_info_cube.imageView))) < 0) + { + ERR("Failed to create cube image view, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + v->vk_info_cube.sampler = VK_NULL_HANDLE; + v->vk_info_cube.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + TRACE("Created cube image view 0x%s.\n", wine_dbgstr_longlong(v->vk_info_cube.imageView)); + + view_desc.subresourceRange.layerCount = 1; + view_desc.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &view_desc, NULL, &v->vk_info_2d_array.imageView))) < 0) + { + ERR("Failed to create 2D array image view, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + v->vk_info_2d_array.sampler = VK_NULL_HANDLE; + v->vk_info_2d_array.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + TRACE("Created 2D array image view 0x%s.\n", wine_dbgstr_longlong(v->vk_info_2d_array.imageView)); + + view_desc.image = r->image_2dms.vk_image; + view_desc.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &view_desc, NULL, &v->vk_info_2dms_array.imageView))) < 0) + { + ERR("Failed to create 2D MSAA array image view, vr %s.\n", wined3d_debug_vkresult(vr)); + goto fail; + } + v->vk_info_2dms_array.sampler = VK_NULL_HANDLE; + v->vk_info_2dms_array.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + TRACE("Created 2D MSAA array image view 0x%s.\n", wine_dbgstr_longlong(v->vk_info_2dms_array.imageView)); + + return true; + +fail: + if (v->vk_info_2d_array.imageView) + VK_CALL(vkDestroyImageView(device_vk->vk_device, v->vk_info_2d_array.imageView, NULL)); + if (v->vk_info_cube.imageView) + VK_CALL(vkDestroyImageView(device_vk->vk_device, v->vk_info_cube.imageView, NULL)); + if (v->vk_info_3d.imageView) + VK_CALL(vkDestroyImageView(device_vk->vk_device, v->vk_info_3d.imageView, NULL)); + if (v->vk_info_2dms.imageView) + VK_CALL(vkDestroyImageView(device_vk->vk_device, v->vk_info_2dms.imageView, NULL)); + if (v->vk_info_2d.imageView) + VK_CALL(vkDestroyImageView(device_vk->vk_device, v->vk_info_2d.imageView, NULL)); + if (v->vk_info_1d.imageView) + VK_CALL(vkDestroyImageView(device_vk->vk_device, v->vk_info_1d.imageView, NULL)); + if (v->vk_view_buffer_float) + VK_CALL(vkDestroyBufferView(device_vk->vk_device, v->vk_view_buffer_float, NULL)); + VK_CALL(vkDestroyBufferView(device_vk->vk_device, v->vk_view_buffer_uint, NULL)); + return false; +} + +void wined3d_device_vk_destroy_null_views(struct wined3d_device_vk *device_vk, struct wined3d_context_vk *context_vk) +{ + struct wined3d_null_views_vk *v = &device_vk->null_views_vk; + uint64_t id = context_vk->current_command_buffer.id; + + wined3d_context_vk_destroy_image_view(context_vk, v->vk_info_2dms_array.imageView, id); + wined3d_context_vk_destroy_image_view(context_vk, v->vk_info_2d_array.imageView, id); + wined3d_context_vk_destroy_image_view(context_vk, v->vk_info_cube.imageView, id); + wined3d_context_vk_destroy_image_view(context_vk, v->vk_info_3d.imageView, id); + wined3d_context_vk_destroy_image_view(context_vk, v->vk_info_2dms.imageView, id); + wined3d_context_vk_destroy_image_view(context_vk, v->vk_info_2d.imageView, id); + wined3d_context_vk_destroy_image_view(context_vk, v->vk_info_1d.imageView, id); + + wined3d_context_vk_destroy_buffer_view(context_vk, v->vk_view_buffer_float, id); + wined3d_context_vk_destroy_buffer_view(context_vk, v->vk_view_buffer_uint, id); +} + HRESULT CDECL wined3d_device_acquire_focus_window(struct wined3d_device *device, HWND window) { unsigned int screensaver_active; @@ -3704,8 +3976,8 @@ TRACE("device %p, primitive_type %s, patch_vertex_count %u.\n", device, debug_d3dprimitivetype(primitive_type), patch_vertex_count); - device->state.gl_primitive_type = gl_primitive_type_from_d3d(primitive_type); - device->state.gl_patch_vertices = patch_vertex_count; + device->state.primitive_type = primitive_type; + device->state.patch_vertex_count = patch_vertex_count; } void CDECL wined3d_device_get_primitive_type(const struct wined3d_device *device, @@ -3714,9 +3986,9 @@ TRACE("device %p, primitive_type %p, patch_vertex_count %p.\n", device, primitive_type, patch_vertex_count); - *primitive_type = d3d_primitive_type_from_gl(device->state.gl_primitive_type); + *primitive_type = device->state.primitive_type; if (patch_vertex_count) - *patch_vertex_count = device->state.gl_patch_vertices; + *patch_vertex_count = device->state.patch_vertex_count; TRACE("Returning %s.\n", debug_d3dprimitivetype(*primitive_type)); } @@ -3725,8 +3997,8 @@ { TRACE("device %p, start_vertex %u, vertex_count %u.\n", device, start_vertex, vertex_count); - wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, - 0, start_vertex, vertex_count, 0, 0, FALSE); + wined3d_cs_emit_draw(device->cs, device->state.primitive_type, + device->state.patch_vertex_count, 0, start_vertex, vertex_count, 0, 0, false); return WINED3D_OK; } @@ -3737,8 +4009,8 @@ TRACE("device %p, start_vertex %u, vertex_count %u, start_instance %u, instance_count %u.\n", device, start_vertex, vertex_count, start_instance, instance_count); - wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, - 0, start_vertex, vertex_count, start_instance, instance_count, FALSE); + wined3d_cs_emit_draw(device->cs, device->state.primitive_type, device->state.patch_vertex_count, + 0, start_vertex, vertex_count, start_instance, instance_count, false); } void CDECL wined3d_device_draw_primitive_instanced_indirect(struct wined3d_device *device, @@ -3746,8 +4018,8 @@ { TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset); - wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, - buffer, offset, FALSE); + wined3d_cs_emit_draw_indirect(device->cs, device->state.primitive_type, + device->state.patch_vertex_count, buffer, offset, false); } HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count) @@ -3764,8 +4036,8 @@ return WINED3DERR_INVALIDCALL; } - wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, - device->state.base_vertex_index, start_idx, index_count, 0, 0, TRUE); + wined3d_cs_emit_draw(device->cs, device->state.primitive_type, device->state.patch_vertex_count, + device->state.base_vertex_index, start_idx, index_count, 0, 0, true); return WINED3D_OK; } @@ -3776,8 +4048,8 @@ TRACE("device %p, start_idx %u, index_count %u, start_instance %u, instance_count %u.\n", device, start_idx, index_count, start_instance, instance_count); - wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, - device->state.base_vertex_index, start_idx, index_count, start_instance, instance_count, TRUE); + wined3d_cs_emit_draw(device->cs, device->state.primitive_type, device->state.patch_vertex_count, + device->state.base_vertex_index, start_idx, index_count, start_instance, instance_count, true); } void CDECL wined3d_device_draw_indexed_primitive_instanced_indirect(struct wined3d_device *device, @@ -3785,8 +4057,8 @@ { TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset); - wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices, - buffer, offset, TRUE); + wined3d_cs_emit_draw_indirect(device->cs, device->state.primitive_type, + device->state.patch_vertex_count, buffer, offset, true); } HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, @@ -4834,6 +5106,13 @@ } } +void CDECL wined3d_device_flush(struct wined3d_device *device) +{ + TRACE("device %p.\n", device); + + wined3d_cs_emit_flush(device->cs); +} + static void update_swapchain_flags(struct wined3d_texture *texture) { unsigned int flags = texture->swapchain->state.desc.flags; @@ -4861,7 +5140,6 @@ struct wined3d_swapchain *swapchain; struct wined3d_view_desc view_desc; BOOL backbuffer_resized, windowed; - struct wined3d_output *output; HRESULT hr = WINED3D_OK; unsigned int i; @@ -4910,6 +5188,7 @@ } TRACE("New params:\n"); + TRACE("output %p\n", swapchain_desc->output); TRACE("backbuffer_width %u\n", swapchain_desc->backbuffer_width); TRACE("backbuffer_height %u\n", swapchain_desc->backbuffer_height); TRACE("backbuffer_format %s\n", debug_d3dformat(swapchain_desc->backbuffer_format)); @@ -4954,12 +5233,6 @@ || swapchain_desc->backbuffer_height != current_desc->backbuffer_height; windowed = current_desc->windowed; - if (!(output = wined3d_swapchain_get_output(swapchain))) - { - ERR("Failed to get output from swapchain %p.\n", swapchain); - return E_FAIL; - } - if (!swapchain_desc->windowed != !windowed || swapchain->reapply_mode || mode || (!swapchain_desc->windowed && backbuffer_resized)) { @@ -4978,7 +5251,7 @@ } if (FAILED(hr = wined3d_swapchain_state_set_fullscreen(&swapchain->state, - swapchain_desc, output, mode))) + swapchain_desc, mode))) return hr; /* Switch from fullscreen to windowed. */ @@ -4995,7 +5268,7 @@ * the window back into the right position. Some applications * (Battlefield 2, Guild Wars) move it and then call Reset() to clean * up their mess. Guild Wars also loses the device during that. */ - if (FAILED(hr = wined3d_output_get_desc(output, &output_desc))) + if (FAILED(hr = wined3d_output_get_desc(swapchain_desc->output, &output_desc))) { ERR("Failed to get output description, hr %#x.\n", hr); return hr; @@ -5320,7 +5593,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined3d, unsigned int adapter_idx, enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment, const enum wined3d_feature_level *levels, unsigned int level_count, - struct wined3d_device_parent *device_parent) + const BOOL *supported_extensions, struct wined3d_device_parent *device_parent) { struct wined3d_adapter *adapter = wined3d->adapters[adapter_idx]; const struct wined3d_fragment_pipe_ops *fragment_pipeline; @@ -5360,7 +5633,7 @@ if (vertex_pipeline->vp_states && fragment_pipeline->states && FAILED(hr = compile_state_table(device->state_table, device->multistate_funcs, - &adapter->d3d_info, adapter->gl_info.supported, vertex_pipeline, + &adapter->d3d_info, supported_extensions, vertex_pipeline, fragment_pipeline, adapter->misc_state_template))) { ERR("Failed to compile state table, hr %#x.\n", hr); diff -Nru wine-development-5.8/dlls/wined3d/directx.c wine-development-5.9/dlls/wined3d/directx.c --- wine-development-5.8/dlls/wined3d/directx.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/directx.c 2020-05-22 18:49:34.000000000 +0000 @@ -2483,8 +2483,8 @@ if (!(device_no3d = heap_alloc_zero(sizeof(*device_no3d)))) return E_OUTOFMEMORY; - if (FAILED(hr = wined3d_device_init(&device_no3d->d, wined3d, adapter->ordinal, device_type, - focus_window, flags, surface_alignment, levels, level_count, device_parent))) + if (FAILED(hr = wined3d_device_init(&device_no3d->d, wined3d, adapter->ordinal, device_type, focus_window, + flags, surface_alignment, levels, level_count, adapter->gl_info.supported, device_parent))) { WARN("Failed to initialize device, hr %#x.\n", hr); heap_free(device_no3d); diff -Nru wine-development-5.8/dlls/wined3d/glsl_shader.c wine-development-5.9/dlls/wined3d/glsl_shader.c --- wine-development-5.8/dlls/wined3d/glsl_shader.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/glsl_shader.c 2020-05-22 18:49:34.000000000 +0000 @@ -10348,7 +10348,7 @@ if (vshader->reg_maps.shader_version.major < 4) { reorder_shader_id = shader_glsl_generate_vs3_rasterizer_input_setup(priv, vshader, pshader, - state->gl_primitive_type == GL_POINTS && vshader->reg_maps.point_size, + state->primitive_type == WINED3D_PT_POINTLIST && vshader->reg_maps.point_size, d3d_info->emulated_flatshading && state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT, gl_info); TRACE("Attaching GLSL shader object %u to program %u.\n", reorder_shader_id, program_id); @@ -11809,7 +11809,8 @@ { static unsigned int once; - if (state->gl_primitive_type == GL_POINTS && !state->render_states[WINED3D_RS_POINTSPRITEENABLE] && !once++) + if (state->primitive_type == WINED3D_PT_POINTLIST + && !state->render_states[WINED3D_RS_POINTSPRITEENABLE] && !once++) FIXME("Non-point sprite points not supported in core profile.\n"); } diff -Nru wine-development-5.8/dlls/wined3d/Makefile.in wine-development-5.9/dlls/wined3d/Makefile.in --- wine-development-5.8/dlls/wined3d/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -24,6 +24,7 @@ shader.c \ shader_sm1.c \ shader_sm4.c \ + shader_spirv.c \ state.c \ stateblock.c \ surface.c \ diff -Nru wine-development-5.8/dlls/wined3d/shader.c wine-development-5.9/dlls/wined3d/shader.c --- wine-development-5.8/dlls/wined3d/shader.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/shader.c 2020-05-22 18:49:34.000000000 +0000 @@ -1123,6 +1123,7 @@ } reg_maps->resource_info[reg_idx].type = semantic->resource_type; reg_maps->resource_info[reg_idx].data_type = semantic->resource_data_type; + wined3d_bitmap_set(reg_maps->resource_map, reg_idx); break; case WINED3DSPR_UAV: @@ -1146,9 +1147,14 @@ { struct wined3d_shader_register *reg = &ins.declaration.src.reg; if (reg->idx[0].offset >= WINED3D_MAX_CBS) + { ERR("Invalid CB index %u.\n", reg->idx[0].offset); + } else + { reg_maps->cb_sizes[reg->idx[0].offset] = reg->idx[1].offset; + wined3d_bitmap_set(®_maps->cb_map, reg->idx[0].offset); + } } else if (ins.handler_idx == WINED3DSIH_DCL_GLOBAL_FLAGS) { @@ -1266,6 +1272,7 @@ reg_maps->resource_info[reg_idx].type = WINED3D_SHADER_RESOURCE_BUFFER; reg_maps->resource_info[reg_idx].data_type = WINED3D_DATA_UINT; reg_maps->resource_info[reg_idx].flags = WINED3D_VIEW_BUFFER_RAW; + wined3d_bitmap_set(reg_maps->resource_map, reg_idx); } else if (ins.handler_idx == WINED3DSIH_DCL_RESOURCE_STRUCTURED) { @@ -1279,6 +1286,7 @@ reg_maps->resource_info[reg_idx].data_type = WINED3D_DATA_UINT; reg_maps->resource_info[reg_idx].flags = 0; reg_maps->resource_info[reg_idx].stride = ins.declaration.structured_resource.byte_stride / 4; + wined3d_bitmap_set(reg_maps->resource_map, reg_idx); } else if (ins.handler_idx == WINED3DSIH_DCL_SAMPLER) { @@ -1605,6 +1613,7 @@ reg_maps->resource_info[reg_idx].type = WINED3D_SHADER_RESOURCE_TEXTURE_2D; reg_maps->resource_info[reg_idx].data_type = WINED3D_DATA_FLOAT; shader_record_sample(reg_maps, reg_idx, reg_idx, reg_idx); + wined3d_bitmap_set(reg_maps->resource_map, reg_idx); /* texbem is only valid with < 1.4 pixel shaders */ if (ins.handler_idx == WINED3DSIH_TEXBEM @@ -3532,7 +3541,7 @@ == WINED3D_FOG_NONE ? VS_FOG_COORD : VS_FOG_Z; args->clip_enabled = state->render_states[WINED3D_RS_CLIPPING] && state->render_states[WINED3D_RS_CLIPPLANEENABLE]; - args->point_size = state->gl_primitive_type == GL_POINTS; + args->point_size = state->primitive_type == WINED3D_PT_POINTLIST; args->per_vertex_point_size = shader->reg_maps.point_size; args->next_shader_type = hull_shader ? WINED3D_SHADER_TYPE_HULL : geometry_shader ? WINED3D_SHADER_TYPE_GEOMETRY : WINED3D_SHADER_TYPE_PIXEL; @@ -3890,7 +3899,7 @@ args->output_count = pixel_shader ? pixel_shader->limits->packed_input : shader->limits->packed_output; if (!(args->primitive_type = shader->u.gs.input_type)) - args->primitive_type = d3d_primitive_type_from_gl(state->gl_primitive_type); + args->primitive_type = state->primitive_type; init_interpolation_compile_args(args->interpolation_mode, pixel_shader, context->d3d_info); } @@ -4146,7 +4155,7 @@ } args->pointsprite = state->render_states[WINED3D_RS_POINTSPRITEENABLE] - && state->gl_primitive_type == GL_POINTS; + && state->primitive_type == WINED3D_PT_POINTLIST; if (d3d_info->ffp_alpha_test) args->alpha_test_func = WINED3D_CMP_ALWAYS - 1; diff -Nru wine-development-5.8/dlls/wined3d/shader_spirv.c wine-development-5.9/dlls/wined3d/shader_spirv.c --- wine-development-5.8/dlls/wined3d/shader_spirv.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/shader_spirv.c 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,877 @@ +/* + * Copyright 2018 Henri Verbeet for CodeWeavers + * Copyright 2019 Józef Kucia 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 "config.h" +#include "wine/port.h" + +#include "wined3d_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); + +static const struct wined3d_shader_backend_ops spirv_shader_backend_vk; + +struct shader_spirv_resource_bindings +{ + VkDescriptorSetLayoutBinding *vk_bindings; + SIZE_T vk_bindings_size, vk_binding_count; + + size_t binding_base[WINED3D_SHADER_TYPE_COUNT]; +}; + +struct shader_spirv_priv +{ + const struct wined3d_vertex_pipe_ops *vertex_pipe; + const struct wined3d_fragment_pipe_ops *fragment_pipe; + bool ffp_proj_control; + + struct shader_spirv_resource_bindings bindings; +}; + +struct shader_spirv_compile_arguments +{ + union + { + struct + { + uint32_t alpha_swizzle; + unsigned int sample_count; + } fs; + + struct + { + enum wined3d_tessellator_output_primitive output_primitive; + enum wined3d_tessellator_partitioning partitioning; + } tes; + } u; +}; + +struct shader_spirv_graphics_program_variant_vk +{ + struct shader_spirv_compile_arguments compile_args; + size_t binding_base; + + VkShaderModule vk_module; +}; + +struct shader_spirv_graphics_program_vk +{ + struct shader_spirv_graphics_program_variant_vk *variants; + SIZE_T variants_size, variant_count; +}; + +struct shader_spirv_compute_program_vk +{ + VkShaderModule vk_module; + VkPipeline vk_pipeline; + VkPipelineLayout vk_pipeline_layout; + VkDescriptorSetLayout vk_set_layout; +}; + +static void shader_spirv_handle_instruction(const struct wined3d_shader_instruction *ins) +{ +} + +static void shader_spirv_compile_arguments_init(struct shader_spirv_compile_arguments *args, + const struct wined3d_context *context, const struct wined3d_shader *shader, + const struct wined3d_state *state, unsigned int sample_count) +{ + const struct wined3d_shader *hull_shader; + struct wined3d_rendertarget_view *rtv; + unsigned int i; + + memset(args, 0, sizeof(*args)); + + switch (shader->reg_maps.shader_version.type) + { + case WINED3D_SHADER_TYPE_DOMAIN: + hull_shader = state->shader[WINED3D_SHADER_TYPE_HULL]; + args->u.tes.output_primitive = hull_shader->u.hs.tessellator_output_primitive; + if (args->u.tes.output_primitive == WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CW) + args->u.tes.output_primitive = WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW; + else if (args->u.tes.output_primitive == WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW) + args->u.tes.output_primitive = WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CW; + args->u.tes.partitioning = hull_shader->u.hs.tessellator_partitioning; + break; + + case WINED3D_SHADER_TYPE_PIXEL: + for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i) + { + if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL) + continue; + if (rtv->format->id == WINED3DFMT_A8_UNORM && !is_identity_fixup(rtv->format->color_fixup)) + args->u.fs.alpha_swizzle |= 1u << i; + } + args->u.fs.sample_count = sample_count; + break; + + default: + break; + } +} + +static VkShaderModule shader_spirv_compile(struct wined3d_context_vk *context_vk, + struct wined3d_shader *shader, const struct shader_spirv_compile_arguments *args, + const struct shader_spirv_resource_bindings *bindings) +{ + FIXME("Not implemented.\n"); + + return VK_NULL_HANDLE; +} + +static struct shader_spirv_graphics_program_variant_vk *shader_spirv_find_graphics_program_variant_vk( + struct shader_spirv_priv *priv, struct wined3d_context_vk *context_vk, struct wined3d_shader *shader, + const struct wined3d_state *state, const struct shader_spirv_resource_bindings *bindings) +{ + size_t binding_base = bindings->binding_base[shader->reg_maps.shader_version.type]; + struct shader_spirv_graphics_program_variant_vk *variant_vk; + struct shader_spirv_graphics_program_vk *program_vk; + struct shader_spirv_compile_arguments args; + size_t variant_count, i; + + shader_spirv_compile_arguments_init(&args, &context_vk->c, shader, state, context_vk->sample_count); + + if (!(program_vk = shader->backend_data)) + { + if (!(program_vk = heap_alloc_zero(sizeof(*program_vk)))) + return NULL; + shader->backend_data = program_vk; + } + + variant_count = program_vk->variant_count; + for (i = 0; i < variant_count; ++i) + { + variant_vk = &program_vk->variants[i]; + if (variant_vk->binding_base == binding_base + && !memcmp(&variant_vk->compile_args, &args, sizeof(args))) + return variant_vk; + } + + if (!wined3d_array_reserve((void **)&program_vk->variants, &program_vk->variants_size, + variant_count + 1, sizeof(*program_vk->variants))) + return NULL; + + variant_vk = &program_vk->variants[variant_count]; + variant_vk->compile_args = args; + variant_vk->binding_base = binding_base; + if (!(variant_vk->vk_module = shader_spirv_compile(context_vk, shader, &args, bindings))) + return NULL; + ++program_vk->variant_count; + + return variant_vk; +} + +static struct shader_spirv_compute_program_vk *shader_spirv_find_compute_program_vk(struct shader_spirv_priv *priv, + struct wined3d_context_vk *context_vk, struct wined3d_shader *shader, + const struct shader_spirv_resource_bindings *bindings) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + struct shader_spirv_compute_program_vk *program; + struct wined3d_pipeline_layout_vk *layout; + VkComputePipelineCreateInfo pipeline_info; + VkResult vr; + + if ((program = shader->backend_data)) + return program; + + if (!(program = heap_alloc(sizeof(*program)))) + return NULL; + + if (!(program->vk_module = shader_spirv_compile(context_vk, shader, NULL, bindings))) + { + heap_free(program); + return NULL; + } + + if (!(layout = wined3d_context_vk_get_pipeline_layout(context_vk, + bindings->vk_bindings, bindings->vk_binding_count))) + { + VK_CALL(vkDestroyShaderModule(device_vk->vk_device, program->vk_module, NULL)); + heap_free(program); + return NULL; + } + program->vk_set_layout = layout->vk_set_layout; + program->vk_pipeline_layout = layout->vk_pipeline_layout; + + pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipeline_info.pNext = NULL; + pipeline_info.flags = 0; + pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + pipeline_info.stage.pNext = NULL; + pipeline_info.stage.flags = 0; + pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; + pipeline_info.stage.pName = "main"; + pipeline_info.stage.pSpecializationInfo = NULL; + pipeline_info.stage.module = program->vk_module; + pipeline_info.layout = program->vk_pipeline_layout; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_info.basePipelineIndex = -1; + if ((vr = VK_CALL(vkCreateComputePipelines(device_vk->vk_device, + VK_NULL_HANDLE, 1, &pipeline_info, NULL, &program->vk_pipeline))) < 0) + { + ERR("Failed to create Vulkan compute pipeline, vr %s.\n", wined3d_debug_vkresult(vr)); + VK_CALL(vkDestroyShaderModule(device_vk->vk_device, program->vk_module, NULL)); + heap_free(program); + return NULL; + } + + shader->backend_data = program; + + return program; +} + +static void shader_spirv_resource_bindings_cleanup(struct shader_spirv_resource_bindings *bindings) +{ + heap_free(bindings->vk_bindings); +} + +static bool shader_spirv_resource_bindings_add_binding(struct shader_spirv_resource_bindings *bindings, + VkDescriptorType vk_type, VkShaderStageFlagBits vk_stage, size_t *binding_idx) +{ + SIZE_T binding_count = bindings->vk_binding_count; + VkDescriptorSetLayoutBinding *binding; + + if (!wined3d_array_reserve((void **)&bindings->vk_bindings, &bindings->vk_bindings_size, + binding_count + 1, sizeof(*bindings->vk_bindings))) + return false; + + *binding_idx = binding_count; + binding = &bindings->vk_bindings[binding_count]; + binding->binding = binding_count; + binding->descriptorType = vk_type; + binding->descriptorCount = 1; + binding->stageFlags = vk_stage; + binding->pImmutableSamplers = NULL; + ++bindings->vk_binding_count; + + return true; +} + +static bool wined3d_shader_resource_bindings_add_binding(struct wined3d_shader_resource_bindings *bindings, + enum wined3d_shader_type shader_type, enum wined3d_shader_descriptor_type shader_descriptor_type, + size_t resource_idx, enum wined3d_shader_resource_type resource_type, + enum wined3d_data_type resource_data_type, size_t binding_idx) +{ + struct wined3d_shader_resource_binding *binding; + SIZE_T binding_count = bindings->count; + + if (!wined3d_array_reserve((void **)&bindings->bindings, &bindings->size, + binding_count + 1, sizeof(*bindings->bindings))) + return false; + + binding = &bindings->bindings[binding_count]; + binding->shader_type = shader_type; + binding->shader_descriptor_type = shader_descriptor_type; + binding->resource_idx = resource_idx; + binding->resource_type = resource_type; + binding->resource_data_type = resource_data_type; + binding->binding_idx = binding_idx; + ++bindings->count; + + return true; +} + +static bool shader_spirv_resource_bindings_init(struct shader_spirv_resource_bindings *bindings, + struct wined3d_shader_resource_bindings *wined3d_bindings, + const struct wined3d_state *state, uint32_t shader_mask) +{ + const struct wined3d_shader_resource_info *resource_info; + const struct wined3d_shader_reg_maps *reg_maps; + enum wined3d_shader_type shader_type; + VkDescriptorType vk_descriptor_type; + size_t binding_idx, register_idx; + VkShaderStageFlagBits vk_stage; + struct wined3d_shader *shader; + unsigned int i; + uint32_t map; + + bindings->vk_binding_count = 0; + wined3d_bindings->count = 0; + + for (shader_type = 0; shader_type < WINED3D_SHADER_TYPE_COUNT; ++shader_type) + { + bindings->binding_base[shader_type] = bindings->vk_binding_count; + + if (!(shader_mask & (1u << shader_type)) || !(shader = state->shader[shader_type])) + continue; + + reg_maps = &shader->reg_maps; + vk_stage = vk_shader_stage_from_wined3d(shader_type); + + map = reg_maps->cb_map; + while (map) + { + register_idx = wined3d_bit_scan(&map); + + if (!shader_spirv_resource_bindings_add_binding(bindings, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk_stage, &binding_idx)) + return false; + if (!wined3d_shader_resource_bindings_add_binding(wined3d_bindings, + shader_type, WINED3D_SHADER_DESCRIPTOR_TYPE_CBV, register_idx, + WINED3D_SHADER_RESOURCE_BUFFER, WINED3D_DATA_UINT, binding_idx)) + return false; + } + + for (i = 0; i < ARRAY_SIZE(reg_maps->resource_map); ++i) + { + map = reg_maps->resource_map[i]; + while (map) + { + register_idx = (i << 5) + wined3d_bit_scan(&map); + resource_info = ®_maps->resource_info[register_idx]; + if (resource_info->type == WINED3D_SHADER_RESOURCE_BUFFER) + vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + else + vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + + if (!shader_spirv_resource_bindings_add_binding(bindings, + vk_descriptor_type, vk_stage, &binding_idx)) + return false; + if (!wined3d_shader_resource_bindings_add_binding(wined3d_bindings, + shader_type, WINED3D_SHADER_DESCRIPTOR_TYPE_SRV, register_idx, + resource_info->type, resource_info->data_type, binding_idx)) + return false; + } + } + + for (register_idx = 0; register_idx < ARRAY_SIZE(reg_maps->uav_resource_info); ++register_idx) + { + resource_info = ®_maps->uav_resource_info[register_idx]; + if (resource_info->type == WINED3D_SHADER_RESOURCE_NONE) + continue; + if (resource_info->type == WINED3D_SHADER_RESOURCE_BUFFER) + vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + else + vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + + if (!shader_spirv_resource_bindings_add_binding(bindings, + vk_descriptor_type, vk_stage, &binding_idx)) + return false; + if (!wined3d_shader_resource_bindings_add_binding(wined3d_bindings, + shader_type, WINED3D_SHADER_DESCRIPTOR_TYPE_UAV, register_idx, + resource_info->type, resource_info->data_type, binding_idx)) + return false; + + if (reg_maps->uav_counter_mask & (1u << register_idx)) + { + if (!shader_spirv_resource_bindings_add_binding(bindings, + VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, vk_stage, &binding_idx)) + return false; + if (!wined3d_shader_resource_bindings_add_binding(wined3d_bindings, + shader_type, WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER, register_idx, + WINED3D_SHADER_RESOURCE_BUFFER, WINED3D_DATA_UINT, binding_idx)) + return false; + } + } + + map = 0; + for (i = 0; i < reg_maps->sampler_map.count; ++i) + { + if (reg_maps->sampler_map.entries[i].sampler_idx != WINED3D_SAMPLER_DEFAULT) + map |= 1u << reg_maps->sampler_map.entries[i].sampler_idx; + } + + while (map) + { + register_idx = wined3d_bit_scan(&map); + + if (!shader_spirv_resource_bindings_add_binding(bindings, + VK_DESCRIPTOR_TYPE_SAMPLER, vk_stage, &binding_idx)) + return false; + if (!wined3d_shader_resource_bindings_add_binding(wined3d_bindings, + shader_type, WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, register_idx, + WINED3D_SHADER_RESOURCE_NONE, WINED3D_DATA_SAMPLER, binding_idx)) + return false; + } + } + + return true; +} + +static void shader_spirv_precompile(void *shader_priv, struct wined3d_shader *shader) +{ + WARN("Not implemented.\n"); +} + +static void shader_spirv_select(void *shader_priv, struct wined3d_context *context, + const struct wined3d_state *state) +{ + struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + struct shader_spirv_graphics_program_variant_vk *variant_vk; + struct shader_spirv_resource_bindings *bindings; + size_t binding_base[WINED3D_SHADER_TYPE_COUNT]; + struct wined3d_pipeline_layout_vk *layout_vk; + struct shader_spirv_priv *priv = shader_priv; + enum wined3d_shader_type shader_type; + struct wined3d_shader *shader; + + priv->vertex_pipe->vp_enable(context, !use_vs(state)); + priv->fragment_pipe->fp_enable(context, !use_ps(state)); + + bindings = &priv->bindings; + memcpy(binding_base, bindings->binding_base, sizeof(bindings)); + if (!shader_spirv_resource_bindings_init(bindings, &context_vk->graphics.bindings, + state, ~(1u << WINED3D_SHADER_TYPE_COMPUTE))) + { + ERR("Failed to initialise shader resource bindings.\n"); + goto fail; + } + + layout_vk = wined3d_context_vk_get_pipeline_layout(context_vk, bindings->vk_bindings, bindings->vk_binding_count); + context_vk->graphics.vk_set_layout = layout_vk->vk_set_layout; + context_vk->graphics.vk_pipeline_layout = layout_vk->vk_pipeline_layout; + + for (shader_type = 0; shader_type < ARRAY_SIZE(context_vk->graphics.vk_modules); ++shader_type) + { + if (!(context->shader_update_mask & (1u << shader_type)) && (!context_vk->graphics.vk_modules[shader_type] + || binding_base[shader_type] == bindings->binding_base[shader_type])) + continue; + + if (!(shader = state->shader[shader_type])) + { + context_vk->graphics.vk_modules[shader_type] = VK_NULL_HANDLE; + continue; + } + + if (!(variant_vk = shader_spirv_find_graphics_program_variant_vk(priv, context_vk, shader, state, bindings))) + goto fail; + context_vk->graphics.vk_modules[shader_type] = variant_vk->vk_module; + } + + return; + +fail: + context_vk->graphics.vk_set_layout = VK_NULL_HANDLE; + context_vk->graphics.vk_pipeline_layout = VK_NULL_HANDLE; +} + +static void shader_spirv_select_compute(void *shader_priv, + struct wined3d_context *context, const struct wined3d_state *state) +{ + struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + struct shader_spirv_compute_program_vk *program; + struct shader_spirv_priv *priv = shader_priv; + struct wined3d_shader *shader; + + if (!shader_spirv_resource_bindings_init(&priv->bindings, + &context_vk->compute.bindings, state, 1u << WINED3D_SHADER_TYPE_COMPUTE)) + ERR("Failed to initialise shader resource bindings.\n"); + + if ((shader = state->shader[WINED3D_SHADER_TYPE_COMPUTE])) + program = shader_spirv_find_compute_program_vk(priv, context_vk, shader, &priv->bindings); + else + program = NULL; + + if (program) + { + context_vk->compute.vk_pipeline = program->vk_pipeline; + context_vk->compute.vk_set_layout = program->vk_set_layout; + context_vk->compute.vk_pipeline_layout = program->vk_pipeline_layout; + } + else + { + context_vk->compute.vk_pipeline = VK_NULL_HANDLE; + context_vk->compute.vk_set_layout = VK_NULL_HANDLE; + context_vk->compute.vk_pipeline_layout = VK_NULL_HANDLE; + } +} + +static void shader_spirv_disable(void *shader_priv, struct wined3d_context *context) +{ + struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + struct shader_spirv_priv *priv = shader_priv; + + priv->vertex_pipe->vp_enable(context, false); + priv->fragment_pipe->fp_enable(context, false); + + context_vk->compute.vk_pipeline = VK_NULL_HANDLE; + context->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL) + | (1u << WINED3D_SHADER_TYPE_VERTEX) + | (1u << WINED3D_SHADER_TYPE_GEOMETRY) + | (1u << WINED3D_SHADER_TYPE_HULL) + | (1u << WINED3D_SHADER_TYPE_DOMAIN) + | (1u << WINED3D_SHADER_TYPE_COMPUTE); +} + +static void shader_spirv_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count) +{ + WARN("Not implemented.\n"); +} + +static void shader_spirv_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count) +{ + WARN("Not implemented.\n"); +} + +static void shader_spirv_load_constants(void *shader_priv, struct wined3d_context *context, + const struct wined3d_state *state) +{ + WARN("Not implemented.\n"); +} + +static void shader_spirv_invalidate_compute_program(struct wined3d_context_vk *context_vk, + const struct shader_spirv_compute_program_vk *program) +{ + if (context_vk->compute.vk_pipeline == program->vk_pipeline) + { + context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_COMPUTE); + context_vk->compute.vk_pipeline = VK_NULL_HANDLE; + } +} + +static void shader_spirv_invalidate_contexts_compute_program(struct wined3d_device *device, + const struct shader_spirv_compute_program_vk *program) +{ + unsigned int i; + + for (i = 0; i < device->context_count; ++i) + { + shader_spirv_invalidate_compute_program(wined3d_context_vk(device->contexts[i]), program); + } +} + +static void shader_spirv_invalidate_graphics_program_variant(struct wined3d_context_vk *context_vk, + const struct shader_spirv_graphics_program_variant_vk *variant) +{ + enum wined3d_shader_type shader_type; + + for (shader_type = 0; shader_type < WINED3D_SHADER_TYPE_GRAPHICS_COUNT; ++shader_type) + { + if (context_vk->graphics.vk_modules[shader_type] != variant->vk_module) + continue; + + context_vk->graphics.vk_modules[shader_type] = VK_NULL_HANDLE; + context_vk->c.shader_update_mask |= (1u << shader_type); + } +} + +static void shader_spirv_invalidate_contexts_graphics_program_variant(struct wined3d_device *device, + const struct shader_spirv_graphics_program_variant_vk *variant) +{ + unsigned int i; + + for (i = 0; i < device->context_count; ++i) + { + shader_spirv_invalidate_graphics_program_variant(wined3d_context_vk(device->contexts[i]), variant); + } +} + +static void shader_spirv_destroy_compute_vk(struct wined3d_shader *shader) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(shader->device); + struct shader_spirv_compute_program_vk *program = shader->backend_data; + struct wined3d_vk_info *vk_info = &device_vk->vk_info; + + shader_spirv_invalidate_contexts_compute_program(&device_vk->d, program); + VK_CALL(vkDestroyPipeline(device_vk->vk_device, program->vk_pipeline, NULL)); + VK_CALL(vkDestroyShaderModule(device_vk->vk_device, program->vk_module, NULL)); + shader->backend_data = NULL; + heap_free(program); +} + +static void shader_spirv_destroy(struct wined3d_shader *shader) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(shader->device); + struct shader_spirv_graphics_program_variant_vk *variant_vk; + struct wined3d_vk_info *vk_info = &device_vk->vk_info; + struct shader_spirv_graphics_program_vk *program_vk; + size_t i; + + if (!shader->backend_data) + return; + + if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_COMPUTE) + { + shader_spirv_destroy_compute_vk(shader); + return; + } + + program_vk = shader->backend_data; + for (i = 0; i < program_vk->variant_count; ++i) + { + variant_vk = &program_vk->variants[i]; + shader_spirv_invalidate_contexts_graphics_program_variant(&device_vk->d, variant_vk); + VK_CALL(vkDestroyShaderModule(device_vk->vk_device, variant_vk->vk_module, NULL)); + } + + shader->backend_data = NULL; + heap_free(program_vk); +} + +static HRESULT shader_spirv_alloc(struct wined3d_device *device, + const struct wined3d_vertex_pipe_ops *vertex_pipe, const struct wined3d_fragment_pipe_ops *fragment_pipe) +{ + struct fragment_caps fragment_caps; + void *vertex_priv, *fragment_priv; + struct shader_spirv_priv *priv; + + if (!(priv = heap_alloc(sizeof(*priv)))) + return E_OUTOFMEMORY; + + if (!(vertex_priv = vertex_pipe->vp_alloc(&spirv_shader_backend_vk, priv))) + { + ERR("Failed to initialise vertex pipe.\n"); + heap_free(priv); + return E_FAIL; + } + + if (!(fragment_priv = fragment_pipe->alloc_private(&spirv_shader_backend_vk, priv))) + { + ERR("Failed to initialise fragment pipe.\n"); + vertex_pipe->vp_free(device, NULL); + heap_free(priv); + return E_FAIL; + } + + priv->vertex_pipe = vertex_pipe; + priv->fragment_pipe = fragment_pipe; + fragment_pipe->get_caps(device->adapter, &fragment_caps); + priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL; + memset(&priv->bindings, 0, sizeof(priv->bindings)); + + device->vertex_priv = vertex_priv; + device->fragment_priv = fragment_priv; + device->shader_priv = priv; + + return WINED3D_OK; +} + +static void shader_spirv_free(struct wined3d_device *device, struct wined3d_context *context) +{ + struct shader_spirv_priv *priv = device->shader_priv; + + shader_spirv_resource_bindings_cleanup(&priv->bindings); + priv->fragment_pipe->free_private(device, context); + priv->vertex_pipe->vp_free(device, context); + heap_free(priv); +} + +static BOOL shader_spirv_allocate_context_data(struct wined3d_context *context) +{ + return TRUE; +} + +static void shader_spirv_free_context_data(struct wined3d_context *context) +{ +} + +static void shader_spirv_init_context_state(struct wined3d_context *context) +{ +} + +static void shader_spirv_get_caps(const struct wined3d_adapter *adapter, struct shader_caps *caps) +{ + memset(caps, 0, sizeof(*caps)); +} + +static BOOL shader_spirv_color_fixup_supported(struct color_fixup_desc fixup) +{ + return is_identity_fixup(fixup); +} + +static BOOL shader_spirv_has_ffp_proj_control(void *shader_priv) +{ + struct shader_spirv_priv *priv = shader_priv; + + return priv->ffp_proj_control; +} + +static const struct wined3d_shader_backend_ops spirv_shader_backend_vk = +{ + .shader_handle_instruction = shader_spirv_handle_instruction, + .shader_precompile = shader_spirv_precompile, + .shader_select = shader_spirv_select, + .shader_select_compute = shader_spirv_select_compute, + .shader_disable = shader_spirv_disable, + .shader_update_float_vertex_constants = shader_spirv_update_float_vertex_constants, + .shader_update_float_pixel_constants = shader_spirv_update_float_pixel_constants, + .shader_load_constants = shader_spirv_load_constants, + .shader_destroy = shader_spirv_destroy, + .shader_alloc_private = shader_spirv_alloc, + .shader_free_private = shader_spirv_free, + .shader_allocate_context_data = shader_spirv_allocate_context_data, + .shader_free_context_data = shader_spirv_free_context_data, + .shader_init_context_state = shader_spirv_init_context_state, + .shader_get_caps = shader_spirv_get_caps, + .shader_color_fixup_supported = shader_spirv_color_fixup_supported, + .shader_has_ffp_proj_control = shader_spirv_has_ffp_proj_control, +}; + +const struct wined3d_shader_backend_ops *wined3d_spirv_shader_backend_init_vk(void) +{ + return &spirv_shader_backend_vk; +} + +static void spirv_vertex_pipe_vk_vp_enable(const struct wined3d_context *context, BOOL enable) +{ + /* Nothing to do. */ +} + +static void spirv_vertex_pipe_vk_vp_get_caps(const struct wined3d_adapter *adapter, struct wined3d_vertex_caps *caps) +{ + memset(caps, 0, sizeof(*caps)); +} + +static uint32_t spirv_vertex_pipe_vk_vp_get_emul_mask(const struct wined3d_gl_info *gl_info) +{ + return 0; +} + +static void *spirv_vertex_pipe_vk_vp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv) +{ + if (shader_backend != &spirv_shader_backend_vk) + { + FIXME("SPIR-V vertex pipe without SPIR-V shader backend not implemented.\n"); + return NULL; + } + + return shader_priv; +} + +static void spirv_vertex_pipe_vk_vp_free(struct wined3d_device *device, struct wined3d_context *context) +{ + /* Nothing to do. */ +} + +static const struct wined3d_state_entry_template spirv_vertex_pipe_vk_vp_states[] = +{ + {STATE_RENDER(WINED3D_RS_RANGEFOGENABLE), {STATE_RENDER(WINED3D_RS_RANGEFOGENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_CLIPPING), {STATE_RENDER(WINED3D_RS_CLIPPING), state_nop}}, + {STATE_RENDER(WINED3D_RS_LIGHTING), {STATE_RENDER(WINED3D_RS_LIGHTING), state_nop}}, + {STATE_RENDER(WINED3D_RS_AMBIENT), {STATE_RENDER(WINED3D_RS_AMBIENT), state_nop}}, + {STATE_RENDER(WINED3D_RS_COLORVERTEX), {STATE_RENDER(WINED3D_RS_COLORVERTEX), state_nop}}, + {STATE_RENDER(WINED3D_RS_LOCALVIEWER), {STATE_RENDER(WINED3D_RS_LOCALVIEWER), state_nop}}, + {STATE_RENDER(WINED3D_RS_NORMALIZENORMALS), {STATE_RENDER(WINED3D_RS_NORMALIZENORMALS), state_nop}}, + {STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE), {STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE), state_nop}}, + {STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE), {STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE), state_nop}}, + {STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE), {STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE), state_nop}}, + {STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE), {STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE), state_nop}}, + {STATE_RENDER(WINED3D_RS_VERTEXBLEND), {STATE_RENDER(WINED3D_RS_VERTEXBLEND), state_nop}}, + {STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE), {STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_POINTSIZE), {STATE_RENDER(WINED3D_RS_POINTSIZE), state_nop}}, + {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), state_nop}}, + {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_POINTSCALE_A), {STATE_RENDER(WINED3D_RS_POINTSCALE_A), state_nop}}, + {STATE_RENDER(WINED3D_RS_POINTSCALE_B), {STATE_RENDER(WINED3D_RS_POINTSCALE_B), state_nop}}, + {STATE_RENDER(WINED3D_RS_POINTSCALE_C), {STATE_RENDER(WINED3D_RS_POINTSCALE_C), state_nop}}, + {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX), {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX), state_nop}}, + {STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE), {STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_TWEENFACTOR), {STATE_RENDER(WINED3D_RS_TWEENFACTOR), state_nop}}, + {STATE_MATERIAL, {STATE_MATERIAL, state_nop}}, + {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), state_nop}}, + {STATE_LIGHT_TYPE, {STATE_LIGHT_TYPE, state_nop}}, + {0}, /* Terminate */ +}; + +static const struct wined3d_vertex_pipe_ops spirv_vertex_pipe_vk = +{ + .vp_enable = spirv_vertex_pipe_vk_vp_enable, + .vp_get_caps = spirv_vertex_pipe_vk_vp_get_caps, + .vp_get_emul_mask = spirv_vertex_pipe_vk_vp_get_emul_mask, + .vp_alloc = spirv_vertex_pipe_vk_vp_alloc, + .vp_free = spirv_vertex_pipe_vk_vp_free, + .vp_states = spirv_vertex_pipe_vk_vp_states, +}; + +const struct wined3d_vertex_pipe_ops *wined3d_spirv_vertex_pipe_init_vk(void) +{ + return &spirv_vertex_pipe_vk; +} + +static void spirv_fragment_pipe_vk_fp_enable(const struct wined3d_context *context, BOOL enable) +{ + /* Nothing to do. */ +} + +static void spirv_fragment_pipe_vk_fp_get_caps(const struct wined3d_adapter *adapter, struct fragment_caps *caps) +{ + memset(caps, 0, sizeof(*caps)); +} + +static uint32_t spirv_fragment_pipe_vk_fp_get_emul_mask(const struct wined3d_gl_info *gl_info) +{ + return 0; +} + +static void *spirv_fragment_pipe_vk_fp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv) +{ + if (shader_backend != &spirv_shader_backend_vk) + { + FIXME("SPIR-V fragment pipe without SPIR-V shader backend not implemented.\n"); + return NULL; + } + + return shader_priv; +} + +static void spirv_fragment_pipe_vk_fp_free(struct wined3d_device *device, struct wined3d_context *context) +{ + /* Nothing to do. */ +} + +static BOOL spirv_fragment_pipe_vk_fp_alloc_context_data(struct wined3d_context *context) +{ + return TRUE; +} + +static void spirv_fragment_pipe_vk_fp_free_context_data(struct wined3d_context *context) +{ + /* Nothing to do. */ +} + +static const struct wined3d_state_entry_template spirv_fragment_pipe_vk_fp_states[] = +{ + {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), state_nop}}, + {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAREF), state_nop}}, + {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), state_nop}}, + {STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_FOGCOLOR), {STATE_RENDER(WINED3D_RS_FOGCOLOR), state_nop}}, + {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), state_nop}}, + {STATE_RENDER(WINED3D_RS_FOGSTART), {STATE_RENDER(WINED3D_RS_FOGSTART), state_nop}}, + {STATE_RENDER(WINED3D_RS_FOGEND), {STATE_RENDER(WINED3D_RS_FOGEND), state_nop}}, + {STATE_RENDER(WINED3D_RS_FOGDENSITY), {STATE_RENDER(WINED3D_RS_FOGDENSITY), state_nop}}, + {STATE_RENDER(WINED3D_RS_COLORKEYENABLE), {STATE_RENDER(WINED3D_RS_COLORKEYENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), state_nop}}, + {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), state_nop}}, + {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_nop}}, + {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), state_nop}}, + {STATE_POINT_ENABLE, {STATE_POINT_ENABLE, state_nop}}, + {STATE_COLOR_KEY, {STATE_COLOR_KEY, state_nop}}, + {0}, /* Terminate */ +}; + +static const struct wined3d_fragment_pipe_ops spirv_fragment_pipe_vk = +{ + .fp_enable = spirv_fragment_pipe_vk_fp_enable, + .get_caps = spirv_fragment_pipe_vk_fp_get_caps, + .get_emul_mask = spirv_fragment_pipe_vk_fp_get_emul_mask, + .alloc_private = spirv_fragment_pipe_vk_fp_alloc, + .free_private = spirv_fragment_pipe_vk_fp_free, + .allocate_context_data = spirv_fragment_pipe_vk_fp_alloc_context_data, + .free_context_data = spirv_fragment_pipe_vk_fp_free_context_data, + .color_fixup_supported = shader_spirv_color_fixup_supported, + .states = spirv_fragment_pipe_vk_fp_states, +}; + +const struct wined3d_fragment_pipe_ops *wined3d_spirv_fragment_pipe_init_vk(void) +{ + return &spirv_fragment_pipe_vk; +} diff -Nru wine-development-5.8/dlls/wined3d/stateblock.c wine-development-5.9/dlls/wined3d/stateblock.c --- wine-development-5.8/dlls/wined3d/stateblock.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/stateblock.c 2020-05-22 18:49:34.000000000 +0000 @@ -1818,8 +1818,8 @@ TRACE("state %p, d3d_info %p.\n", state, d3d_info); get_identity_matrix(&identity); - state->gl_primitive_type = ~0u; - state->gl_patch_vertices = 0; + state->primitive_type = WINED3D_PT_UNDEFINED; + state->patch_vertex_count = 0; /* Set some of the defaults for lights, transforms etc */ state->transforms[WINED3D_TS_PROJECTION] = identity; diff -Nru wine-development-5.8/dlls/wined3d/swapchain.c wine-development-5.9/dlls/wined3d/swapchain.c --- wine-development-5.8/dlls/wined3d/swapchain.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/swapchain.c 2020-05-22 18:49:34.000000000 +0000 @@ -25,7 +25,6 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); -WINE_DECLARE_DEBUG_CHANNEL(fps); void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain) { @@ -259,49 +258,11 @@ return swapchain->back_buffers[back_buffer_idx]; } -static struct wined3d_output * get_output_from_window(const struct wined3d *wined3d, HWND hwnd) -{ - unsigned int adapter_idx, output_idx; - struct wined3d_adapter *adapter; - MONITORINFOEXW monitor_info; - HMONITOR monitor; - - TRACE("wined3d %p, hwnd %p.\n", wined3d, hwnd); - - monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); - monitor_info.cbSize = sizeof(monitor_info); - if (!GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info)) - { - ERR("Failed to get monitor information.\n"); - return NULL; - } - - for (adapter_idx = 0; adapter_idx < wined3d->adapter_count; ++adapter_idx) - { - adapter = wined3d->adapters[adapter_idx]; - for (output_idx = 0; output_idx < adapter->output_count; ++output_idx) - { - if (!lstrcmpiW(adapter->outputs[output_idx].device_name, monitor_info.szDevice)) - return &adapter->outputs[output_idx]; - } - } - - /* Because wined3d only supports one output right now. A window can be on non-primary outputs - * and thus fails to get its correct output. In this case, return the primary output for now */ - return &wined3d->adapters[0]->outputs[0]; -} - struct wined3d_output * wined3d_swapchain_get_output(const struct wined3d_swapchain *swapchain) { - HWND hwnd; - TRACE("swapchain %p.\n", swapchain); - hwnd = swapchain->state.device_window; - if (!hwnd) - hwnd = swapchain->win_handle; - - return get_output_from_window(swapchain->device->wined3d, hwnd); + return swapchain->state.desc.output; } HRESULT CDECL wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain, @@ -603,21 +564,6 @@ wined3d_swapchain_gl_rotate(swapchain, context); TRACE("SwapBuffers called, Starting new frame\n"); - /* FPS support */ - if (TRACE_ON(fps)) - { - DWORD time = GetTickCount(); - ++swapchain->frames; - - /* every 1.5 seconds */ - if (time - swapchain->prev_time > 1500) - { - TRACE_(fps)("%p @ approx %.2ffps\n", - swapchain, 1000.0 * swapchain->frames / (time - swapchain->prev_time)); - swapchain->prev_time = time; - swapchain->frames = 0; - } - } wined3d_texture_validate_location(swapchain->front_buffer, 0, WINED3D_LOCATION_DRAWABLE); wined3d_texture_invalidate_location(swapchain->front_buffer, 0, ~WINED3D_LOCATION_DRAWABLE); @@ -740,23 +686,6 @@ back->bitmap = bitmap; swapchain->back_buffers[0]->resource.heap_memory = data; - /* FPS support */ - if (TRACE_ON(fps)) - { - static LONG prev_time, frames; - DWORD time = GetTickCount(); - - ++frames; - - /* every 1.5 seconds */ - if (time - prev_time > 1500) - { - TRACE_(fps)("@ approx %.2ffps\n", 1000.0 * frames / (time - prev_time)); - prev_time = time; - frames = 0; - } - } - SetRect(&swapchain->front_buffer_update, 0, 0, swapchain->front_buffer->resource.width, swapchain->front_buffer->resource.height); @@ -825,20 +754,13 @@ } static HRESULT wined3d_swapchain_state_init(struct wined3d_swapchain_state *state, - const struct wined3d_swapchain_desc *desc, HWND window, struct wined3d *wined3d) + const struct wined3d_swapchain_desc *desc, HWND window) { - struct wined3d_output *output; HRESULT hr; state->desc = *desc; - if (!(output = get_output_from_window(wined3d, window))) - { - WARN("Failed to get output from window %p.\n", window); - return E_FAIL; - } - - if (FAILED(hr = wined3d_output_get_display_mode(output, &state->original_mode, NULL))) + if (FAILED(hr = wined3d_output_get_display_mode(desc->output, &state->original_mode, NULL))) { ERR("Failed to get current display mode, hr %#x.\n", hr); return hr; @@ -850,7 +772,7 @@ { state->d3d_mode.width = desc->backbuffer_width; state->d3d_mode.height = desc->backbuffer_height; - state->d3d_mode.format_id = adapter_format_from_backbuffer_format(output->adapter, + state->d3d_mode.format_id = adapter_format_from_backbuffer_format(desc->output->adapter, desc->backbuffer_format); state->d3d_mode.refresh_rate = desc->refresh_rate; state->d3d_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN; @@ -873,7 +795,6 @@ { struct wined3d_resource_desc texture_desc; struct wined3d_output_desc output_desc; - struct wined3d_output *output; BOOL displaymode_set = FALSE; DWORD texture_flags = 0; HRESULT hr = E_FAIL; @@ -895,7 +816,7 @@ FIXME("Unimplemented swap effect %#x.\n", desc->swap_effect); window = desc->device_window ? desc->device_window : device->create_parms.focus_window; - if (FAILED(hr = wined3d_swapchain_state_init(&swapchain->state, desc, window, device->wined3d))) + if (FAILED(hr = wined3d_swapchain_state_init(&swapchain->state, desc, window))) { ERR("Failed to initialise swapchain state, hr %#x.\n", hr); goto err; @@ -934,13 +855,7 @@ } else { - if (!(output = wined3d_swapchain_get_output(swapchain))) - { - ERR("Failed to get output from swapchain %p.\n", swapchain); - goto err; - } - - if (FAILED(hr = wined3d_output_get_desc(output, &output_desc))) + if (FAILED(hr = wined3d_output_get_desc(desc->output, &output_desc))) { ERR("Failed to get output description, hr %#x.\n", hr); goto err; @@ -996,8 +911,7 @@ if (!desc->windowed && desc->flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH) { /* Change the display settings */ - output = wined3d_swapchain_get_output(swapchain); - if (!output || FAILED(hr = wined3d_output_set_display_mode(output, + if (FAILED(hr = wined3d_output_set_display_mode(desc->output, &swapchain->state.d3d_mode))) { WARN("Failed to set display mode, hr %#x.\n", hr); @@ -1081,7 +995,7 @@ err: if (displaymode_set) { - if (!output || FAILED(wined3d_output_set_display_mode(output, + if (FAILED(wined3d_output_set_display_mode(desc->output, &swapchain->state.original_mode))) ERR("Failed to restore display mode.\n"); } @@ -1292,9 +1206,11 @@ { struct wined3d_device *device = swapchain->device; HWND window = swapchain->state.device_window; + struct wined3d_output_desc output_desc; unsigned int screensaver_active; struct wined3d_output *output; BOOL focus_messages, filter; + HRESULT hr; /* This code is not protected by the wined3d mutex, so it may run while * wined3d_device_reset is active. Testing on Windows shows that changing @@ -1304,6 +1220,13 @@ if (!(focus_messages = device->wined3d->flags & WINED3D_FOCUS_MESSAGES)) filter = wined3d_filter_messages(window, TRUE); + output = wined3d_swapchain_get_output(swapchain); + if (!output) + { + ERR("Failed to get output from swapchain %p.\n", swapchain); + return; + } + if (activate) { SystemParametersInfoW(SPI_GETSCREENSAVEACTIVE, 0, &screensaver_active, 0); @@ -1319,16 +1242,19 @@ * * Guild Wars 1 wants a WINDOWPOSCHANGED message on the device window to * resume drawing after a focus loss. */ - SetWindowPos(window, NULL, 0, 0, swapchain->state.desc.backbuffer_width, - swapchain->state.desc.backbuffer_height, SWP_NOACTIVATE | SWP_NOZORDER); + if (SUCCEEDED(hr = wined3d_output_get_desc(output, &output_desc))) + SetWindowPos(window, NULL, output_desc.desktop_rect.left, + output_desc.desktop_rect.top, swapchain->state.desc.backbuffer_width, + swapchain->state.desc.backbuffer_height, SWP_NOACTIVATE | SWP_NOZORDER); + else + ERR("Failed to get output description, hr %#x.\n", hr); } if (device->wined3d->flags & WINED3D_RESTORE_MODE_ON_ACTIVATE) { - output = wined3d_swapchain_get_output(swapchain); - if (!output || FAILED(wined3d_output_set_display_mode(output, + if (FAILED(hr = wined3d_output_set_display_mode(output, &swapchain->state.d3d_mode))) - ERR("Failed to set display mode.\n"); + ERR("Failed to set display mode, hr %#x.\n", hr); } if (swapchain == device->swapchains[0]) @@ -1342,9 +1268,8 @@ device->restore_screensaver = FALSE; } - output = wined3d_swapchain_get_output(swapchain); - if (!output || FAILED(wined3d_output_set_display_mode(output, NULL))) - ERR("Failed to set display mode.\n"); + if (FAILED(hr = wined3d_output_set_display_mode(output, NULL))) + ERR("Failed to set display mode, hr %#x.\n", hr); swapchain->reapply_mode = TRUE; @@ -1476,6 +1401,21 @@ } } + if (output != state->desc.output) + { + if (FAILED(hr = wined3d_output_set_display_mode(state->desc.output, &state->original_mode))) + { + WARN("Failed to set display mode, hr %#x.\n", hr); + return hr; + } + + if (FAILED(hr = wined3d_output_get_display_mode(output, &state->original_mode, NULL))) + { + WARN("Failed to get current display mode, hr %#x.\n", hr); + return hr; + } + } + if (FAILED(hr = wined3d_output_set_display_mode(output, mode))) { WARN("Failed to set display mode, hr %#x.\n", hr); @@ -1486,7 +1426,7 @@ } HRESULT CDECL wined3d_swapchain_state_resize_target(struct wined3d_swapchain_state *state, - struct wined3d_output *output, const struct wined3d_display_mode *mode) + const struct wined3d_display_mode *mode) { struct wined3d_display_mode actual_mode; struct wined3d_output_desc output_desc; @@ -1495,7 +1435,7 @@ HWND window; HRESULT hr; - TRACE("state %p, output %p, mode %p.\n", state, output, mode); + TRACE("state %p, mode %p.\n", state, mode); wined3d_mutex_lock(); @@ -1519,7 +1459,8 @@ if (state->desc.flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH) { actual_mode = *mode; - if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, output, &actual_mode))) + if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, state->desc.output, + &actual_mode))) { ERR("Failed to set display mode, hr %#x.\n", hr); wined3d_mutex_unlock(); @@ -1527,7 +1468,7 @@ } } - if (FAILED(hr = wined3d_output_get_desc(output, &output_desc))) + if (FAILED(hr = wined3d_output_get_desc(state->desc.output, &output_desc))) { ERR("Failed to get output description, hr %#x.\n", hr); wined3d_mutex_unlock(); @@ -1658,15 +1599,14 @@ } HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_state *state, - const struct wined3d_swapchain_desc *swapchain_desc, struct wined3d_output *output, + const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode) { struct wined3d_display_mode actual_mode; struct wined3d_output_desc output_desc; HRESULT hr; - TRACE("state %p, swapchain_desc %p, output %p, mode %p.\n", - state, swapchain_desc, output, mode); + TRACE("state %p, swapchain_desc %p, mode %p.\n", state, swapchain_desc, mode); if (state->desc.flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH) { @@ -1681,7 +1621,7 @@ actual_mode.width = swapchain_desc->backbuffer_width; actual_mode.height = swapchain_desc->backbuffer_height; actual_mode.refresh_rate = swapchain_desc->refresh_rate; - actual_mode.format_id = adapter_format_from_backbuffer_format(output->adapter, + actual_mode.format_id = adapter_format_from_backbuffer_format(swapchain_desc->output->adapter, swapchain_desc->backbuffer_format); actual_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN; } @@ -1691,7 +1631,8 @@ } } - if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, output, &actual_mode))) + if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, swapchain_desc->output, + &actual_mode))) return hr; } else @@ -1699,7 +1640,8 @@ if (mode) WARN("WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH is not set, ignoring mode.\n"); - if (FAILED(hr = wined3d_output_get_display_mode(output, &actual_mode, NULL))) + if (FAILED(hr = wined3d_output_get_display_mode(swapchain_desc->output, &actual_mode, + NULL))) { ERR("Failed to get display mode, hr %#x.\n", hr); return WINED3DERR_INVALIDCALL; @@ -1711,7 +1653,7 @@ unsigned int width = actual_mode.width; unsigned int height = actual_mode.height; - if (FAILED(hr = wined3d_output_get_desc(output, &output_desc))) + if (FAILED(hr = wined3d_output_get_desc(swapchain_desc->output, &output_desc))) { ERR("Failed to get output description, hr %#x.\n", hr); return hr; @@ -1747,6 +1689,7 @@ wined3d_swapchain_state_restore_from_fullscreen(state, state->device_window, window_rect); } + state->desc.output = swapchain_desc->output; state->desc.windowed = swapchain_desc->windowed; return WINED3D_OK; @@ -1758,17 +1701,17 @@ } HRESULT CDECL wined3d_swapchain_state_create(const struct wined3d_swapchain_desc *desc, - HWND window, struct wined3d *wined3d, struct wined3d_swapchain_state **state) + HWND window, struct wined3d_swapchain_state **state) { struct wined3d_swapchain_state *s; HRESULT hr; - TRACE("desc %p, window %p, wined3d %p, state %p.\n", desc, window, wined3d, state); + TRACE("desc %p, window %p, state %p.\n", desc, window, state); if (!(s = heap_alloc_zero(sizeof(*s)))) return E_OUTOFMEMORY; - if (FAILED(hr = wined3d_swapchain_state_init(s, desc, window, wined3d))) + if (FAILED(hr = wined3d_swapchain_state_init(s, desc, window))) { heap_free(s); return hr; diff -Nru wine-development-5.8/dlls/wined3d/texture.c wine-development-5.9/dlls/wined3d/texture.c --- wine-development-5.8/dlls/wined3d/texture.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/texture.c 2020-05-22 18:49:34.000000000 +0000 @@ -1748,11 +1748,13 @@ const struct wined3d_d3d_info *d3d_info; const struct wined3d_gl_info *gl_info; const struct wined3d_format *format; - const struct wined3d *d3d; struct wined3d_device *device; unsigned int resource_size; + const struct wined3d *d3d; + unsigned int slice_pitch; DWORD valid_location = 0; - BOOL create_dib = FALSE; + bool update_memory_only; + bool create_dib = false; TRACE("texture %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u, " "mem %p, pitch %u.\n", @@ -1765,10 +1767,27 @@ format = wined3d_get_format(device->adapter, format_id, texture->resource.bind_flags); resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1); + update_memory_only = width == texture->resource.width && height == texture->resource.height + && format_id == texture->resource.format->id && multisample_type == texture->resource.multisample_type + && multisample_quality == texture->resource.multisample_quality; + + if (pitch) + slice_pitch = height * pitch; + else + wined3d_format_calculate_pitch(format, 1, width, height, &pitch, &slice_pitch); + + if (update_memory_only) + { + unsigned int current_row_pitch, current_slice_pitch; + + wined3d_texture_get_pitch(texture, 0, ¤t_row_pitch, ¤t_slice_pitch); + update_memory_only = pitch == current_row_pitch && slice_pitch == current_slice_pitch; + } + if (!resource_size) return WINED3DERR_INVALIDCALL; - if (texture->level_count * texture->layer_count > 1) + if (texture->level_count * texture->layer_count > 1 && !update_memory_only) { WARN("Texture has multiple sub-resources, not supported.\n"); return WINED3DERR_INVALIDCALL; @@ -1803,67 +1822,67 @@ wined3d_cs_emit_unload_resource(device->cs, &texture->resource); wined3d_resource_wait_idle(&texture->resource); - sub_resource = &texture->sub_resources[0]; if (texture->dc_info && texture->dc_info[0].dc) { struct wined3d_texture_idx texture_idx = {texture, 0}; wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx); wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); - create_dib = TRUE; + create_dib = true; } wined3d_resource_free_sysmem(&texture->resource); - if ((texture->row_pitch = pitch)) - texture->slice_pitch = height * pitch; - else - /* User memory surfaces don't have the regular surface alignment. */ - wined3d_format_calculate_pitch(format, 1, width, height, - &texture->row_pitch, &texture->slice_pitch); - - texture->resource.format = format; - texture->resource.multisample_type = multisample_type; - texture->resource.multisample_quality = multisample_quality; - texture->resource.width = width; - texture->resource.height = height; - if (!(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING) - adapter_adjust_memory(device->adapter, (INT64)texture->slice_pitch - texture->resource.size); - texture->resource.size = texture->slice_pitch; - sub_resource->size = texture->slice_pitch; - sub_resource->locations = WINED3D_LOCATION_DISCARDED; - - if (texture->texture_ops == &texture_gl_ops) + if (!update_memory_only) { - if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) + sub_resource = &texture->sub_resources[0]; + + texture->row_pitch = pitch; + texture->slice_pitch = slice_pitch; + + texture->resource.format = format; + texture->resource.multisample_type = multisample_type; + texture->resource.multisample_quality = multisample_quality; + texture->resource.width = width; + texture->resource.height = height; + if (!(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING) + adapter_adjust_memory(device->adapter, (INT64)texture->slice_pitch - texture->resource.size); + texture->resource.size = texture->slice_pitch; + sub_resource->size = texture->slice_pitch; + sub_resource->locations = WINED3D_LOCATION_DISCARDED; + + if (texture->texture_ops == &texture_gl_ops) + { + if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) + { + wined3d_texture_gl(texture)->target = GL_TEXTURE_2D_MULTISAMPLE; + texture->flags &= ~WINED3D_TEXTURE_DOWNLOADABLE; + } + else + { + wined3d_texture_gl(texture)->target = GL_TEXTURE_2D; + texture->flags |= WINED3D_TEXTURE_DOWNLOADABLE; + } + } + + if (((width & (width - 1)) || (height & (height - 1))) && !d3d_info->texture_npot + && !d3d_info->texture_npot_conditional) { - wined3d_texture_gl(texture)->target = GL_TEXTURE_2D_MULTISAMPLE; - texture->flags &= ~WINED3D_TEXTURE_DOWNLOADABLE; + texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED; + texture->pow2_width = texture->pow2_height = 1; + while (texture->pow2_width < width) + texture->pow2_width <<= 1; + while (texture->pow2_height < height) + texture->pow2_height <<= 1; } else { - wined3d_texture_gl(texture)->target = GL_TEXTURE_2D; - texture->flags |= WINED3D_TEXTURE_DOWNLOADABLE; + texture->flags &= ~WINED3D_TEXTURE_COND_NP2_EMULATED; + texture->pow2_width = width; + texture->pow2_height = height; } } - if (((width & (width - 1)) || (height & (height - 1))) && !d3d_info->texture_npot - && !d3d_info->texture_npot_conditional) - { - texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED; - texture->pow2_width = texture->pow2_height = 1; - while (texture->pow2_width < width) - texture->pow2_width <<= 1; - while (texture->pow2_height < height) - texture->pow2_height <<= 1; - } - else - { - texture->flags &= ~WINED3D_TEXTURE_COND_NP2_EMULATED; - texture->pow2_width = width; - texture->pow2_height = height; - } - if ((texture->user_memory = mem)) { texture->resource.map_binding = WINED3D_LOCATION_USER_MEMORY; @@ -6063,18 +6082,6 @@ heap_free(blitter); } -static inline VkImageView wined3d_rendertarget_view_vk_get_image_view(struct wined3d_rendertarget_view_vk *rtv_vk, - struct wined3d_context_vk *context_vk) -{ - struct wined3d_texture_vk *texture_vk; - - if (rtv_vk->vk_image_view) - return rtv_vk->vk_image_view; - - texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(rtv_vk->v.resource)); - return wined3d_texture_vk_get_default_image_info(texture_vk, context_vk)->imageView; -} - static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk, unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects, const RECT *draw_rect, uint32_t flags, const struct wined3d_color *colour, float depth, unsigned int stencil) @@ -6206,6 +6213,8 @@ begin_desc.clearValueCount = attachment_count; begin_desc.pClearValues = clear_values; + wined3d_context_vk_end_current_render_pass(context_vk); + for (i = 0; i < rect_count; ++i) { r.left = max(clear_rects[i].left, draw_rect->left); diff -Nru wine-development-5.8/dlls/wined3d/utils.c wine-development-5.9/dlls/wined3d/utils.c --- wine-development-5.8/dlls/wined3d/utils.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/utils.c 2020-05-22 18:49:34.000000000 +0000 @@ -1795,29 +1795,20 @@ GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, ARB_DEPTH_TEXTURE, NULL}, - {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, - GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, - EXT_PACKED_DEPTH_STENCIL, convert_s1_uint_d15_unorm}, {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, - ARB_FRAMEBUFFER_OBJECT, convert_s1_uint_d15_unorm}, + EXT_PACKED_DEPTH_STENCIL, convert_s1_uint_d15_unorm}, {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, ARB_DEPTH_TEXTURE, NULL}, - {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, - GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0, - WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING - | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, - EXT_PACKED_DEPTH_STENCIL, NULL}, {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, - ARB_FRAMEBUFFER_OBJECT, NULL}, + EXT_PACKED_DEPTH_STENCIL, NULL}, {WINED3DFMT_X8D24_UNORM, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 4, WINED3DFMT_FLAG_DEPTH, @@ -1831,14 +1822,10 @@ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, ARB_DEPTH_TEXTURE, NULL}, - {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, - GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4, - WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, - EXT_PACKED_DEPTH_STENCIL, convert_s4x4_uint_d24_unorm}, {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW, - ARB_FRAMEBUFFER_OBJECT, convert_s4x4_uint_d24_unorm}, + EXT_PACKED_DEPTH_STENCIL, convert_s4x4_uint_d24_unorm}, {WINED3DFMT_D16_UNORM, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, WINED3DFMT_FLAG_DEPTH, @@ -1885,16 +1872,11 @@ GL_RG, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING, ARB_TEXTURE_COMPRESSION_RGTC, NULL}, - {WINED3DFMT_INTZ, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0, - GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0, - WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING - | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - EXT_PACKED_DEPTH_STENCIL, NULL}, {WINED3DFMT_INTZ, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL, - ARB_FRAMEBUFFER_OBJECT, NULL}, + EXT_PACKED_DEPTH_STENCIL, NULL}, {WINED3DFMT_NULL, 0, 0, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_FBO_ATTACHABLE, @@ -2591,8 +2573,7 @@ BOOL match = TRUE; GLuint rb; - if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT] - || gl_info->supported[EXT_PACKED_DEPTH_STENCIL]) + if (gl_info->supported[EXT_PACKED_DEPTH_STENCIL]) { gl_info->fbo_ops.glGenRenderbuffers(1, &rb); gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb); @@ -2698,8 +2679,7 @@ } } - if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT] - || gl_info->supported[EXT_PACKED_DEPTH_STENCIL]) + if (gl_info->supported[EXT_PACKED_DEPTH_STENCIL]) { gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); @@ -6354,7 +6334,7 @@ } settings->pointsprite = state->render_states[WINED3D_RS_POINTSPRITEENABLE] - && state->gl_primitive_type == GL_POINTS; + && state->primitive_type == WINED3D_PT_POINTLIST; if (d3d_info->ffp_alpha_test) settings->alpha_test_func = WINED3D_CMP_ALWAYS - 1; @@ -6518,7 +6498,7 @@ if (si->position_transformed) { settings->transformed = 1; - settings->point_size = state->gl_primitive_type == GL_POINTS; + settings->point_size = state->primitive_type == WINED3D_PT_POINTLIST; settings->per_vertex_point_size = !!(si->use_map & 1u << WINED3D_FFP_PSIZE); if (!state->render_states[WINED3D_RS_FOGENABLE]) settings->fog_mode = WINED3D_FFP_VS_FOG_OFF; @@ -6566,7 +6546,7 @@ settings->normalize = settings->normal && state->render_states[WINED3D_RS_NORMALIZENORMALS]; settings->lighting = !!state->render_states[WINED3D_RS_LIGHTING]; settings->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER]; - settings->point_size = state->gl_primitive_type == GL_POINTS; + settings->point_size = state->primitive_type == WINED3D_PT_POINTLIST; settings->per_vertex_point_size = !!(si->use_map & 1u << WINED3D_FFP_PSIZE); wined3d_get_material_colour_source(&diffuse_source, &emissive_source, diff -Nru wine-development-5.8/dlls/wined3d/view.c wine-development-5.9/dlls/wined3d/view.c --- wine-development-5.8/dlls/wined3d/view.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/view.c 2020-05-22 18:49:34.000000000 +0000 @@ -1011,12 +1011,32 @@ return hr; } +void wined3d_shader_resource_view_vk_update(struct wined3d_shader_resource_view_vk *srv_vk, + struct wined3d_context_vk *context_vk) +{ + const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(srv_vk->v.format); + const struct wined3d_view_desc *desc = &srv_vk->v.desc; + struct wined3d_resource *resource = srv_vk->v.resource; + struct wined3d_view_vk *view_vk = &srv_vk->view_vk; + struct wined3d_buffer_vk *buffer_vk; + VkBufferView vk_buffer_view; + + buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource)); + wined3d_context_vk_destroy_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id); + if ((vk_buffer_view = wined3d_view_vk_create_buffer_view(context_vk, desc, buffer_vk, view_format_vk))) + { + view_vk->u.vk_buffer_view = vk_buffer_view; + view_vk->bo_user.valid = true; + } +} + static void wined3d_shader_resource_view_vk_cs_init(void *object) { struct wined3d_shader_resource_view_vk *srv_vk = object; struct wined3d_view_desc *desc = &srv_vk->v.desc; struct wined3d_texture_vk *texture_vk; const struct wined3d_format *format; + struct wined3d_buffer_vk *buffer_vk; struct wined3d_resource *resource; struct wined3d_context *context; VkBufferView vk_buffer_view; @@ -1028,9 +1048,11 @@ if (resource->type == WINED3D_RTYPE_BUFFER) { + buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource)); + context = context_acquire(resource->device, NULL, 0); vk_buffer_view = wined3d_view_vk_create_buffer_view(wined3d_context_vk(context), - desc, wined3d_buffer_vk(buffer_from_resource(resource)), wined3d_format_vk(format)); + desc, buffer_vk, wined3d_format_vk(format)); context_release(context); if (!vk_buffer_view) @@ -1039,6 +1061,8 @@ TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view)); srv_vk->view_vk.u.vk_buffer_view = vk_buffer_view; + srv_vk->view_vk.bo_user.valid = true; + list_add_head(&buffer_vk->bo.users, &srv_vk->view_vk.bo_user.entry); return; } @@ -1087,6 +1111,7 @@ if (FAILED(hr = wined3d_shader_resource_view_init(&view_vk->v, desc, resource, parent, parent_ops))) return hr; + list_init(&view_vk->view_vk.bo_user.entry); wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_vk_cs_init, view_vk); return hr; @@ -1453,6 +1478,25 @@ return hr; } +void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_view_vk *uav_vk, + struct wined3d_context_vk *context_vk) +{ + const struct wined3d_format_vk *view_format_vk = wined3d_format_vk(uav_vk->v.format); + const struct wined3d_view_desc *desc = &uav_vk->v.desc; + struct wined3d_resource *resource = uav_vk->v.resource; + struct wined3d_view_vk *view_vk = &uav_vk->view_vk; + struct wined3d_buffer_vk *buffer_vk; + VkBufferView vk_buffer_view; + + buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource)); + wined3d_context_vk_destroy_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id); + if ((vk_buffer_view = wined3d_view_vk_create_buffer_view(context_vk, desc, buffer_vk, view_format_vk))) + { + view_vk->u.vk_buffer_view = vk_buffer_view; + view_vk->bo_user.valid = true; + } +} + static void wined3d_unordered_access_view_vk_cs_init(void *object) { struct wined3d_unordered_access_view_vk *uav_vk = object; @@ -1463,6 +1507,7 @@ struct wined3d_texture_vk *texture_vk; struct wined3d_context_vk *context_vk; struct wined3d_device_vk *device_vk; + struct wined3d_buffer_vk *buffer_vk; VkBufferViewCreateInfo create_info; struct wined3d_resource *resource; VkBufferView vk_buffer_view; @@ -1476,15 +1521,18 @@ if (resource->type == WINED3D_RTYPE_BUFFER) { + buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource)); + context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0)); vk_info = context_vk->vk_info; - if ((vk_buffer_view = wined3d_view_vk_create_buffer_view(context_vk, - desc, wined3d_buffer_vk(buffer_from_resource(resource)), format_vk))) + if ((vk_buffer_view = wined3d_view_vk_create_buffer_view(context_vk, desc, buffer_vk, format_vk))) { TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view)); uav_vk->view_vk.u.vk_buffer_view = vk_buffer_view; + uav_vk->view_vk.bo_user.valid = true; + list_add_head(&buffer_vk->bo.users, &view_vk->bo_user.entry); } if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND)) @@ -1499,6 +1547,7 @@ return; } + wined3d_context_vk_end_current_render_pass(context_vk); VK_CALL(vkCmdFillBuffer(wined3d_context_vk_get_command_buffer(context_vk), uav_vk->counter_bo.vk_buffer, uav_vk->counter_bo.buffer_offset, sizeof(uint32_t), 0)); wined3d_context_vk_reference_bo(context_vk, &uav_vk->counter_bo); @@ -1572,6 +1621,7 @@ if (FAILED(hr = wined3d_unordered_access_view_init(&view_vk->v, desc, resource, parent, parent_ops))) return hr; + list_init(&view_vk->view_vk.bo_user.entry); wined3d_cs_init_object(resource->device->cs, wined3d_unordered_access_view_vk_cs_init, view_vk); return hr; diff -Nru wine-development-5.8/dlls/wined3d/wined3d_main.c wine-development-5.9/dlls/wined3d/wined3d_main.c --- wine-development-5.8/dlls/wined3d/wined3d_main.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/wined3d_main.c 2020-05-22 18:49:34.000000000 +0000 @@ -459,6 +459,39 @@ LeaveCriticalSection(&wined3d_wndproc_cs); } +static struct wined3d_output * wined3d_get_output_from_window(const struct wined3d *wined3d, + HWND hwnd) +{ + unsigned int adapter_idx, output_idx; + struct wined3d_adapter *adapter; + MONITORINFOEXW monitor_info; + HMONITOR monitor; + + TRACE("wined3d %p, hwnd %p.\n", wined3d, hwnd); + + monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + monitor_info.cbSize = sizeof(monitor_info); + if (!GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info)) + { + ERR("GetMonitorInfoW failed, error %#x.\n", GetLastError()); + return NULL; + } + + for (adapter_idx = 0; adapter_idx < wined3d->adapter_count; ++adapter_idx) + { + adapter = wined3d->adapters[adapter_idx]; + for (output_idx = 0; output_idx < adapter->output_count; ++output_idx) + { + if (!lstrcmpiW(adapter->outputs[output_idx].device_name, monitor_info.szDevice)) + return &adapter->outputs[output_idx]; + } + } + + /* Because wined3d only supports one output right now. A window can be on non-primary outputs + * and thus fails to get its correct output. In this case, return the primary output for now */ + return &wined3d->adapters[0]->outputs[0]; +} + static struct wined3d_wndproc *wined3d_find_wndproc(HWND window, struct wined3d *wined3d) { unsigned int i; @@ -565,13 +598,14 @@ wined3d_swapchain_get_desc(swapchain, &swapchain_desc); swapchain_desc.windowed = !swapchain_desc.windowed; - if (!(output = wined3d_swapchain_get_output(swapchain))) + if (!(output = wined3d_get_output_from_window(swapchain->device->wined3d, + swapchain->state.device_window))) { - ERR("Failed to get output from swapchain %p.\n", swapchain); + ERR("Failed to get output from window %p.\n", swapchain->state.device_window); break; } - wined3d_swapchain_state_set_fullscreen(&swapchain->state, &swapchain_desc, output, - NULL); + swapchain_desc.output = output; + wined3d_swapchain_state_set_fullscreen(&swapchain->state, &swapchain_desc, NULL); wined3d_wndproc_mutex_unlock(); diff -Nru wine-development-5.8/dlls/wined3d/wined3d_private.h wine-development-5.9/dlls/wined3d/wined3d_private.h --- wine-development-5.8/dlls/wined3d/wined3d_private.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/wined3d_private.h 2020-05-22 18:49:34.000000000 +0000 @@ -80,8 +80,11 @@ #define WINED3D_ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A','2','M','1') #define WINED3D_ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A','2','M','0') +#define WINED3D_BITMAP_SIZE(x) (((x) + 31) >> 5) + struct wined3d_fragment_pipe_ops; struct wined3d_adapter; +struct wined3d_buffer_vk; struct wined3d_context; struct wined3d_gl_info; struct wined3d_state; @@ -302,6 +305,7 @@ VkAccessFlags vk_access_mask_from_bind_flags(uint32_t bind_flags) DECLSPEC_HIDDEN; VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op) DECLSPEC_HIDDEN; VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags) DECLSPEC_HIDDEN; +VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type) DECLSPEC_HIDDEN; static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func) { @@ -1032,8 +1036,10 @@ WORD local_int_consts; /* WINED3D_MAX_CONSTS_I, 16 */ WORD local_bool_consts; /* WINED3D_MAX_CONSTS_B, 16 */ UINT cb_sizes[WINED3D_MAX_CBS]; + uint32_t cb_map; /* WINED3D_MAX_CBS, 15 */ struct wined3d_shader_resource_info resource_info[MAX_SHADER_RESOURCE_VIEWS]; + uint32_t resource_map[WINED3D_BITMAP_SIZE(MAX_SHADER_RESOURCE_VIEWS)]; struct wined3d_shader_sampler_map sampler_map; DWORD sampler_comparison_mode; BYTE bumpmat; /* WINED3D_MAX_TEXTURES, 8 */ @@ -1468,6 +1474,8 @@ extern const struct wined3d_shader_backend_ops arb_program_shader_backend DECLSPEC_HIDDEN; extern const struct wined3d_shader_backend_ops none_shader_backend DECLSPEC_HIDDEN; +const struct wined3d_shader_backend_ops *wined3d_spirv_shader_backend_init_vk(void) DECLSPEC_HIDDEN; + #define GL_EXTCALL(f) (gl_info->gl_ops.ext.p_##f) #define D3DCOLOR_B_R(dw) (((dw) >> 16) & 0xff) @@ -1532,6 +1540,12 @@ return bo ? ((struct wined3d_bo_gl *)bo)->id : 0; } +struct wined3d_bo_user_vk +{ + struct list entry; + bool valid; +}; + struct wined3d_bo_vk { VkBuffer vk_buffer; @@ -1546,6 +1560,7 @@ VkBufferUsageFlags usage; VkMemoryPropertyFlags memory_type; + struct list users; uint64_t command_buffer_id; }; @@ -1969,8 +1984,8 @@ { const struct wined3d_d3d_info *d3d_info; const struct wined3d_state_entry *state_table; - uint32_t dirty_graphics_states[STATE_HIGHEST / (sizeof(uint32_t) * CHAR_BIT) + 1]; - uint32_t dirty_compute_states[STATE_COMPUTE_COUNT / (sizeof(uint32_t) * CHAR_BIT) + 1]; + uint32_t dirty_graphics_states[WINED3D_BITMAP_SIZE(STATE_HIGHEST)]; + uint32_t dirty_compute_states[WINED3D_BITMAP_SIZE(STATE_COMPUTE_COUNT)]; struct wined3d_device *device; struct wined3d_swapchain *swapchain; @@ -2226,6 +2241,7 @@ { WINED3D_RETIRED_FREE_VK, WINED3D_RETIRED_FRAMEBUFFER_VK, + WINED3D_RETIRED_DESCRIPTOR_POOL_VK, WINED3D_RETIRED_MEMORY_VK, WINED3D_RETIRED_ALLOCATOR_BLOCK_VK, WINED3D_RETIRED_BO_SLAB_SLICE_VK, @@ -2243,6 +2259,7 @@ { struct wined3d_retired_object_vk *next; VkFramebuffer vk_framebuffer; + VkDescriptorPool vk_descriptor_pool; VkDeviceMemory vk_memory; struct wined3d_allocator_block *block; struct @@ -2289,12 +2306,109 @@ VkRenderPass vk_render_pass; }; +struct wined3d_pipeline_layout_key_vk +{ + VkDescriptorSetLayoutBinding *bindings; + SIZE_T binding_count; +}; + +struct wined3d_pipeline_layout_vk +{ + struct wine_rb_entry entry; + struct wined3d_pipeline_layout_key_vk key; + VkPipelineLayout vk_pipeline_layout; + VkDescriptorSetLayout vk_set_layout; +}; + +struct wined3d_graphics_pipeline_key_vk +{ + VkPipelineShaderStageCreateInfo stages[WINED3D_SHADER_TYPE_GRAPHICS_COUNT]; + VkVertexInputBindingDivisorDescriptionEXT divisors[MAX_ATTRIBS]; + VkVertexInputAttributeDescription attributes[MAX_ATTRIBS]; + VkVertexInputBindingDescription bindings[MAX_ATTRIBS]; + VkViewport viewport; + VkRect2D scissor; + VkPipelineColorBlendAttachmentState blend_attachments[WINED3D_MAX_RENDER_TARGETS]; + + VkPipelineVertexInputDivisorStateCreateInfoEXT divisor_desc; + VkPipelineVertexInputStateCreateInfo input_desc; + VkPipelineInputAssemblyStateCreateInfo ia_desc; + VkPipelineTessellationStateCreateInfo ts_desc; + VkPipelineViewportStateCreateInfo vp_desc; + VkPipelineRasterizationStateCreateInfo rs_desc; + VkPipelineMultisampleStateCreateInfo ms_desc; + VkPipelineDepthStencilStateCreateInfo ds_desc; + VkPipelineColorBlendStateCreateInfo blend_desc; + VkPipelineDynamicStateCreateInfo dynamic_desc; + + VkGraphicsPipelineCreateInfo pipeline_desc; +}; + +struct wined3d_graphics_pipeline_vk +{ + struct wine_rb_entry entry; + struct wined3d_graphics_pipeline_key_vk key; + VkPipeline vk_pipeline; +}; + +enum wined3d_shader_descriptor_type +{ + WINED3D_SHADER_DESCRIPTOR_TYPE_CBV, + WINED3D_SHADER_DESCRIPTOR_TYPE_SRV, + WINED3D_SHADER_DESCRIPTOR_TYPE_UAV, + WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER, + WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, +}; + +struct wined3d_shader_resource_binding +{ + enum wined3d_shader_type shader_type; + enum wined3d_shader_descriptor_type shader_descriptor_type; + size_t resource_idx; + enum wined3d_shader_resource_type resource_type; + enum wined3d_data_type resource_data_type; + size_t binding_idx; +}; + +struct wined3d_shader_resource_bindings +{ + struct wined3d_shader_resource_binding *bindings; + SIZE_T size, count; +}; + +struct wined3d_shader_descriptor_writes_vk +{ + VkWriteDescriptorSet *writes; + SIZE_T size, count; +}; + struct wined3d_context_vk { struct wined3d_context c; const struct wined3d_vk_info *vk_info; + uint32_t update_compute_pipeline : 1; + uint32_t padding : 31; + + struct + { + VkShaderModule vk_modules[WINED3D_SHADER_TYPE_GRAPHICS_COUNT]; + struct wined3d_graphics_pipeline_key_vk pipeline_key_vk; + VkPipeline vk_pipeline; + VkPipelineLayout vk_pipeline_layout; + VkDescriptorSetLayout vk_set_layout; + struct wined3d_shader_resource_bindings bindings; + } graphics; + + struct + { + VkPipeline vk_pipeline; + VkPipelineLayout vk_pipeline_layout; + VkDescriptorSetLayout vk_set_layout; + struct wined3d_shader_resource_bindings bindings; + } compute; + VkCommandPool vk_command_pool; struct wined3d_command_buffer_vk current_command_buffer; uint64_t completed_command_buffer_id; @@ -2306,8 +2420,19 @@ SIZE_T buffer_count; } submitted; + struct wined3d_shader_descriptor_writes_vk descriptor_writes; + + VkFramebuffer vk_framebuffer; + VkRenderPass vk_render_pass; + VkDescriptorPool vk_descriptor_pool; + + VkSampleCountFlagBits sample_count; + unsigned int rt_count; + struct wined3d_retired_objects_vk retired; struct wine_rb_tree render_passes; + struct wine_rb_tree pipeline_layouts; + struct wine_rb_tree graphics_pipelines; struct wine_rb_tree bo_slab_available; }; @@ -2320,6 +2445,10 @@ unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory) DECLSPEC_HIDDEN; VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk, unsigned int pool, size_t size) DECLSPEC_HIDDEN; +VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk, + const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk) DECLSPEC_HIDDEN; +VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk, + const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed) DECLSPEC_HIDDEN; void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo) DECLSPEC_HIDDEN; @@ -2339,7 +2468,10 @@ VkDeviceMemory vk_memory, uint64_t command_buffer_id) DECLSPEC_HIDDEN; void wined3d_context_vk_destroy_sampler(struct wined3d_context_vk *context_vk, VkSampler vk_sampler, uint64_t command_buffer_id) DECLSPEC_HIDDEN; +void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; +struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(struct wined3d_context_vk *context_vk, + VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count) DECLSPEC_HIDDEN; VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk, const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags) DECLSPEC_HIDDEN; @@ -2431,10 +2563,14 @@ extern const struct wined3d_fragment_pipe_ops nvrc_fragment_pipeline DECLSPEC_HIDDEN; extern const struct wined3d_fragment_pipe_ops glsl_fragment_pipe DECLSPEC_HIDDEN; +const struct wined3d_fragment_pipe_ops *wined3d_spirv_fragment_pipe_init_vk(void) DECLSPEC_HIDDEN; + extern const struct wined3d_vertex_pipe_ops none_vertex_pipe DECLSPEC_HIDDEN; extern const struct wined3d_vertex_pipe_ops ffp_vertex_pipe DECLSPEC_HIDDEN; extern const struct wined3d_vertex_pipe_ops glsl_vertex_pipe DECLSPEC_HIDDEN; +const struct wined3d_vertex_pipe_ops *wined3d_spirv_vertex_pipe_init_vk(void) DECLSPEC_HIDDEN; + /* "Base" state table */ HRESULT compile_state_table(struct wined3d_state_entry *state_table, APPLYSTATEFUNC **dev_multistate_funcs, const struct wined3d_d3d_info *d3d_info, const BOOL *supported_extensions, @@ -3301,6 +3437,16 @@ struct wine_rb_entry entry; }; +static inline unsigned int wined3d_blend_state_get_writemask(const struct wined3d_blend_state *state, + unsigned int index) +{ + if (!state) + return 0xf; + if (!state->desc.independent) + index = 0; + return state->desc.rt[index].writemask; +} + struct wined3d_rasterizer_state { LONG refcount; @@ -3345,8 +3491,8 @@ unsigned int index_offset; int base_vertex_index; int load_base_vertex_index; /* Non-indexed drawing needs 0 here, indexed needs base_vertex_index. */ - GLenum gl_primitive_type; - GLint gl_patch_vertices; + enum wined3d_primitive_type primitive_type; + unsigned int patch_vertex_count; struct wined3d_query *predicate; BOOL predicate_value; @@ -3490,7 +3636,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined3d, unsigned int adapter_idx, enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment, const enum wined3d_feature_level *levels, unsigned int level_count, - struct wined3d_device_parent *device_parent) DECLSPEC_HIDDEN; + const BOOL *supported_extensions, struct wined3d_device_parent *device_parent) DECLSPEC_HIDDEN; LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode, UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN; void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; @@ -3525,6 +3671,36 @@ return CONTAINING_RECORD(device, struct wined3d_device_gl, d); } +struct wined3d_null_image_vk +{ + VkImage vk_image; + struct wined3d_allocator_block *memory; + VkDeviceMemory vk_memory; +}; + +struct wined3d_null_resources_vk +{ + struct wined3d_bo_vk bo; + struct wined3d_null_image_vk image_1d; + struct wined3d_null_image_vk image_2d; + struct wined3d_null_image_vk image_2dms; + struct wined3d_null_image_vk image_3d; +}; + +struct wined3d_null_views_vk +{ + VkBufferView vk_view_buffer_uint; + VkBufferView vk_view_buffer_float; + + VkDescriptorImageInfo vk_info_1d; + VkDescriptorImageInfo vk_info_2d; + VkDescriptorImageInfo vk_info_2dms; + VkDescriptorImageInfo vk_info_3d; + VkDescriptorImageInfo vk_info_cube; + VkDescriptorImageInfo vk_info_2d_array; + VkDescriptorImageInfo vk_info_2dms_array; +}; + #define WINED3D_ALLOCATOR_CHUNK_SIZE (64 * 1024 * 1024) #define WINED3D_ALLOCATOR_CHUNK_ORDER_COUNT 15 #define WINED3D_ALLOCATOR_MIN_BLOCK_SIZE (WINED3D_ALLOCATOR_CHUNK_SIZE >> (WINED3D_ALLOCATOR_CHUNK_ORDER_COUNT - 1)) @@ -3609,6 +3785,9 @@ struct wined3d_vk_info vk_info; + struct wined3d_null_resources_vk null_resources_vk; + struct wined3d_null_views_vk null_views_vk; + struct wined3d_allocator allocator; }; @@ -3617,12 +3796,14 @@ return CONTAINING_RECORD(device, struct wined3d_device_vk, d); } -static inline BOOL isStateDirty(const struct wined3d_context *context, unsigned int state_id) -{ - unsigned int idx = state_id / (sizeof(*context->dirty_graphics_states) * CHAR_BIT); - unsigned int shift = state_id & ((sizeof(*context->dirty_graphics_states) * CHAR_BIT) - 1); - return context->dirty_graphics_states[idx] & (1u << shift); -} +bool wined3d_device_vk_create_null_resources(struct wined3d_device_vk *device_vk, + struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; +bool wined3d_device_vk_create_null_views(struct wined3d_device_vk *device_vk, + struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; +void wined3d_device_vk_destroy_null_resources(struct wined3d_device_vk *device_vk, + struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; +void wined3d_device_vk_destroy_null_views(struct wined3d_device_vk *device_vk, + struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; static inline float wined3d_alpha_ref(const struct wined3d_state *state) { @@ -4164,16 +4345,16 @@ struct wined3d_saved_states { - DWORD vs_consts_f[WINED3D_MAX_VS_CONSTS_F >> 5]; + uint32_t vs_consts_f[WINED3D_BITMAP_SIZE(WINED3D_MAX_VS_CONSTS_F)]; WORD vertexShaderConstantsI; /* WINED3D_MAX_CONSTS_I, 16 */ WORD vertexShaderConstantsB; /* WINED3D_MAX_CONSTS_B, 16 */ - DWORD ps_consts_f[WINED3D_MAX_PS_CONSTS_F >> 5]; + uint32_t ps_consts_f[WINED3D_BITMAP_SIZE(WINED3D_MAX_PS_CONSTS_F)]; WORD pixelShaderConstantsI; /* WINED3D_MAX_CONSTS_I, 16 */ WORD pixelShaderConstantsB; /* WINED3D_MAX_CONSTS_B, 16 */ - DWORD transform[(WINED3D_HIGHEST_TRANSFORM_STATE >> 5) + 1]; + uint32_t transform[WINED3D_BITMAP_SIZE(WINED3D_HIGHEST_TRANSFORM_STATE + 1)]; WORD streamSource; /* WINED3D_MAX_STREAMS, 16 */ WORD streamFreq; /* WINED3D_MAX_STREAMS, 16 */ - DWORD renderState[(WINEHIGHEST_RENDER_STATE >> 5) + 1]; + uint32_t renderState[WINED3D_BITMAP_SIZE(WINEHIGHEST_RENDER_STATE + 1)]; DWORD textureState[WINED3D_MAX_TEXTURES]; /* WINED3D_HIGHEST_TEXTURE_STATE + 1, 18 */ WORD samplerState[WINED3D_MAX_COMBINED_SAMPLERS]; /* WINED3D_HIGHEST_SAMPLER_STATE + 1, 14 */ DWORD clipplane; /* WINED3D_MAX_CLIP_DISTANCES, 8 */ @@ -4312,11 +4493,12 @@ unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) DECLSPEC_HIDDEN; void wined3d_cs_emit_dispatch_indirect(struct wined3d_cs *cs, struct wined3d_buffer *buffer, unsigned int offset) DECLSPEC_HIDDEN; -void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, unsigned int patch_vertex_count, - int base_vertex_idx, unsigned int start_idx, unsigned int index_count, - unsigned int start_instance, unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN; -void wined3d_cs_emit_draw_indirect(struct wined3d_cs *cs, GLenum primitive_type, unsigned int patch_vertex_count, - struct wined3d_buffer *buffer, unsigned int offset, BOOL indexed) DECLSPEC_HIDDEN; +void wined3d_cs_emit_draw(struct wined3d_cs *cs, enum wined3d_primitive_type primitive_type, + unsigned int patch_vertex_count, int base_vertex_idx, unsigned int start_idx, unsigned int index_count, + unsigned int start_instance, unsigned int instance_count, bool indexed) DECLSPEC_HIDDEN; +void wined3d_cs_emit_draw_indirect(struct wined3d_cs *cs, enum wined3d_primitive_type primitive_type, + unsigned int patch_vertex_count, struct wined3d_buffer *buffer, + unsigned int offset, bool indexed) DECLSPEC_HIDDEN; void wined3d_cs_emit_flush(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs *cs, struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; @@ -4504,6 +4686,8 @@ struct wined3d_buffer b; struct wined3d_bo_vk bo; + struct wined3d_bo_user_vk bo_user; + VkDescriptorBufferInfo buffer_info; }; static inline struct wined3d_buffer_vk *wined3d_buffer_vk(struct wined3d_buffer *buffer) @@ -4511,6 +4695,7 @@ return CONTAINING_RECORD(buffer, struct wined3d_buffer_vk, b); } +const VkDescriptorBufferInfo *wined3d_buffer_vk_get_buffer_info(struct wined3d_buffer_vk *buffer_vk) DECLSPEC_HIDDEN; HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined3d_device *device, const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; @@ -4580,6 +4765,18 @@ return CONTAINING_RECORD(view, struct wined3d_rendertarget_view_vk, v); } +static inline VkImageView wined3d_rendertarget_view_vk_get_image_view(struct wined3d_rendertarget_view_vk *rtv_vk, + struct wined3d_context_vk *context_vk) +{ + struct wined3d_texture_vk *texture_vk; + + if (rtv_vk->vk_image_view) + return rtv_vk->vk_image_view; + + texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(rtv_vk->v.resource)); + return wined3d_texture_vk_get_default_image_info(texture_vk, context_vk)->imageView; +} + HRESULT wined3d_rendertarget_view_vk_init(struct wined3d_rendertarget_view_vk *view_vk, const struct wined3d_view_desc *desc, struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; @@ -4620,6 +4817,7 @@ struct wined3d_view_vk { + struct wined3d_bo_user_vk bo_user; union { VkBufferView vk_buffer_view; @@ -4643,6 +4841,8 @@ HRESULT wined3d_shader_resource_view_vk_init(struct wined3d_shader_resource_view_vk *view_vk, const struct wined3d_view_desc *desc, struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; +void wined3d_shader_resource_view_vk_update(struct wined3d_shader_resource_view_vk *view_vk, + struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; struct wined3d_unordered_access_view { @@ -4703,6 +4903,8 @@ HRESULT wined3d_unordered_access_view_vk_init(struct wined3d_unordered_access_view_vk *view_vk, const struct wined3d_view_desc *desc, struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; +void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_view_vk *view_vk, + struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; struct wined3d_swapchain_state { @@ -4868,9 +5070,6 @@ void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; -GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) DECLSPEC_HIDDEN; -enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) DECLSPEC_HIDDEN; - /* Math utils */ void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1, const struct wined3d_matrix *src2) DECLSPEC_HIDDEN; @@ -5581,6 +5780,12 @@ texture_vk->command_buffer_id = context_vk->current_command_buffer.id; } +static inline void wined3d_context_vk_reference_sampler(const struct wined3d_context_vk *context_vk, + struct wined3d_sampler_vk *sampler_vk) +{ + sampler_vk->command_buffer_id = context_vk->current_command_buffer.id; +} + static inline void wined3d_context_vk_reference_rendertarget_view(const struct wined3d_context_vk *context_vk, struct wined3d_rendertarget_view_vk *rtv_vk) { @@ -5593,6 +5798,30 @@ rtv_vk->command_buffer_id = context_vk->current_command_buffer.id; } +static inline void wined3d_context_vk_reference_shader_resource_view(const struct wined3d_context_vk *context_vk, + struct wined3d_shader_resource_view_vk *srv_vk) +{ + struct wined3d_resource *resource = srv_vk->v.resource; + + if (resource->type == WINED3D_RTYPE_BUFFER) + wined3d_context_vk_reference_bo(context_vk, &wined3d_buffer_vk(buffer_from_resource(resource))->bo); + else + wined3d_context_vk_reference_texture(context_vk, wined3d_texture_vk(texture_from_resource(resource))); + srv_vk->view_vk.command_buffer_id = context_vk->current_command_buffer.id; +} + +static inline void wined3d_context_vk_reference_unordered_access_view(const struct wined3d_context_vk *context_vk, + struct wined3d_unordered_access_view_vk *uav_vk) +{ + struct wined3d_resource *resource = uav_vk->v.resource; + + if (resource->type == WINED3D_RTYPE_BUFFER) + wined3d_context_vk_reference_bo(context_vk, &wined3d_buffer_vk(buffer_from_resource(resource))->bo); + else + wined3d_context_vk_reference_texture(context_vk, wined3d_texture_vk(texture_from_resource(resource))); + uav_vk->view_vk.command_buffer_id = context_vk->current_command_buffer.id; +} + static inline BOOL wined3d_dsv_srv_conflict(const struct wined3d_rendertarget_view *dsv, const struct wined3d_format *srv_format) { @@ -5630,6 +5859,11 @@ *max_z = max(vp->max_z, vp->min_z + 0.001f); } +static inline BOOL wined3d_bitmap_set(uint32_t *map, unsigned int idx) +{ + return map[idx >> 5] |= (1u << (idx & 0x1f)); +} + static inline BOOL wined3d_bitmap_is_set(const uint32_t *map, unsigned int idx) { return map[idx >> 5] & (1u << (idx & 0x1f)); @@ -5689,6 +5923,21 @@ return TRUE; } +static inline bool wined3d_context_is_graphics_state_dirty(const struct wined3d_context *context, unsigned int state_id) +{ + return wined3d_bitmap_is_set(context->dirty_graphics_states, state_id); +} + +static inline bool wined3d_context_is_compute_state_dirty(const struct wined3d_context *context, unsigned int state_id) +{ + return wined3d_bitmap_is_set(context->dirty_compute_states, state_id - STATE_COMPUTE_OFFSET); +} + +static inline bool isStateDirty(const struct wined3d_context *context, unsigned int state_id) +{ + return wined3d_context_is_graphics_state_dirty(context, state_id); +} + static inline VkImageAspectFlags vk_aspect_mask_from_format(const struct wined3d_format *format) { VkImageAspectFlags mask = 0; @@ -5703,6 +5952,16 @@ return mask; } +static inline bool wined3d_primitive_type_is_list(enum wined3d_primitive_type t) +{ + return t == WINED3D_PT_POINTLIST + || t == WINED3D_PT_LINELIST + || t == WINED3D_PT_TRIANGLELIST + || t == WINED3D_PT_LINELIST_ADJ + || t == WINED3D_PT_TRIANGLELIST_ADJ + || t == WINED3D_PT_PATCH; +} + /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */ #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL" diff -Nru wine-development-5.8/dlls/wined3d/wined3d.spec wine-development-5.9/dlls/wined3d/wined3d.spec --- wine-development-5.8/dlls/wined3d/wined3d.spec 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/wined3d.spec 2020-05-22 18:49:34.000000000 +0000 @@ -53,6 +53,7 @@ @ cdecl wined3d_device_draw_primitive_instanced_indirect(ptr ptr long) @ cdecl wined3d_device_end_scene(ptr) @ cdecl wined3d_device_evict_managed_resources(ptr) +@ cdecl wined3d_device_flush(ptr) @ cdecl wined3d_device_get_available_texture_mem(ptr) @ cdecl wined3d_device_get_blend_state(ptr ptr) @ cdecl wined3d_device_get_clip_status(ptr ptr) @@ -281,10 +282,10 @@ @ cdecl wined3d_swapchain_set_palette(ptr ptr) @ cdecl wined3d_swapchain_set_window(ptr ptr) -@ cdecl wined3d_swapchain_state_create(ptr ptr ptr ptr) +@ cdecl wined3d_swapchain_state_create(ptr ptr ptr) @ cdecl wined3d_swapchain_state_destroy(ptr) -@ cdecl wined3d_swapchain_state_resize_target(ptr ptr ptr) -@ cdecl wined3d_swapchain_state_set_fullscreen(ptr ptr ptr ptr) +@ cdecl wined3d_swapchain_state_resize_target(ptr ptr) +@ cdecl wined3d_swapchain_state_set_fullscreen(ptr ptr ptr) @ cdecl wined3d_texture_add_dirty_region(ptr long ptr) @ cdecl wined3d_texture_blt(ptr long ptr ptr long ptr long ptr long) diff -Nru wine-development-5.8/dlls/wined3d/wined3d_vk.h wine-development-5.9/dlls/wined3d/wined3d_vk.h --- wine-development-5.8/dlls/wined3d/wined3d_vk.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wined3d/wined3d_vk.h 2020-05-22 18:49:34.000000000 +0000 @@ -40,6 +40,7 @@ VK_INSTANCE_PFN(vkGetPhysicalDeviceQueueFamilyProperties) \ VK_INSTANCE_PFN(vkGetPhysicalDeviceSparseImageFormatProperties) \ /* Vulkan 1.1 */ \ + VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceFeatures2) \ VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2) #define VK_DEVICE_FUNCS() \ @@ -181,6 +182,12 @@ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; }; +enum wined3d_vk_extension +{ + WINED3D_VK_EXT_NONE, + WINED3D_VK_EXT_COUNT, +}; + struct wined3d_vk_info { struct vulkan_ops vk_ops; @@ -188,6 +195,7 @@ VkInstance instance; unsigned int api_version; + BOOL supported[WINED3D_VK_EXT_COUNT]; #ifdef USE_WIN32_VULKAN HMODULE vulkan_lib; #endif diff -Nru wine-development-5.8/dlls/winegstreamer/gstdemux.c wine-development-5.9/dlls/winegstreamer/gstdemux.c --- wine-development-5.8/dlls/winegstreamer/gstdemux.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winegstreamer/gstdemux.c 2020-05-22 18:49:34.000000000 +0000 @@ -1003,7 +1003,7 @@ if (!(pin = create_pin(This, nameW))) { ERR("Failed to allocate memory.\n"); - return; + goto out; } if (!strcmp(typename, "video/x-raw")) @@ -1017,7 +1017,7 @@ { ERR("Failed to create videoconvert, are %u-bit GStreamer \"base\" plugins installed?\n", 8 * (int)sizeof(void *)); - return; + goto out; } /* GStreamer outputs RGB video top-down, but DirectShow expects bottom-up. */ @@ -1025,7 +1025,7 @@ { ERR("Failed to create videoflip, are %u-bit GStreamer \"good\" plugins installed?\n", 8 * (int)sizeof(void *)); - return; + goto out; } gst_bin_add(GST_BIN(This->container), vconv); /* bin takes ownership */ @@ -1051,7 +1051,7 @@ { ERR("Failed to create audioconvert, are %u-bit GStreamer \"base\" plugins installed?\n", 8 * (int)sizeof(void *)); - return; + goto out; } gst_bin_add(GST_BIN(This->container), convert); @@ -1069,7 +1069,7 @@ gst_pad_link_get_name(ret)); gst_object_unref(pin->post_sink); pin->post_sink = NULL; - return; + goto out; } if ((ret = gst_pad_link(pin->post_src, pin->my_sink)) < 0) @@ -1080,18 +1080,20 @@ pin->post_src = NULL; gst_object_unref(pin->post_sink); pin->post_sink = NULL; - return; + goto out; } } else if ((ret = gst_pad_link(pad, pin->my_sink)) < 0) { ERR("Failed to link decodebin source pad to our sink pad, error %s.\n", gst_pad_link_get_name(ret)); - return; + goto out; } gst_pad_set_active(pin->my_sink, 1); gst_object_ref(pin->their_src = pad); +out: + gst_caps_unref(caps); } static void existing_new_pad(GstElement *bin, GstPad *pad, gpointer user) diff -Nru wine-development-5.8/dlls/winemac.drv/cocoa_app.m wine-development-5.9/dlls/winemac.drv/cocoa_app.m --- wine-development-5.8/dlls/winemac.drv/cocoa_app.m 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winemac.drv/cocoa_app.m 2020-05-22 18:49:34.000000000 +0000 @@ -1229,9 +1229,9 @@ case kCGEventRightMouseDragged: case kCGEventOtherMouseDragged: return TRUE; + default: + return FALSE; } - - return FALSE; } - (int) warpsFinishedByEventTime:(CGEventTimestamp)eventTime location:(CGPoint)eventLocation diff -Nru wine-development-5.8/dlls/winemac.drv/opengl.c wine-development-5.9/dlls/winemac.drv/opengl.c --- wine-development-5.8/dlls/winemac.drv/opengl.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winemac.drv/opengl.c 2020-05-22 18:49:34.000000000 +0000 @@ -4242,7 +4242,7 @@ } -static BOOL init_opengl(void) +static BOOL CALLBACK init_opengl(INIT_ONCE *init_once, void *context, void **param) { static BOOL init_done = FALSE; unsigned int i; @@ -4654,13 +4654,15 @@ */ struct opengl_funcs * CDECL macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version) { + static INIT_ONCE opengl_init = INIT_ONCE_STATIC_INIT; + if (version != WINE_WGL_DRIVER_VERSION) { ERR("version mismatch, opengl32 wants %u but macdrv has %u\n", version, WINE_WGL_DRIVER_VERSION); return NULL; } - if (!init_opengl()) return (void *)-1; + if (!InitOnceExecuteOnce(&opengl_init, init_opengl, NULL, NULL)) return (void *)-1; return &opengl_funcs; } diff -Nru wine-development-5.8/dlls/wineusb.sys/wineusb.c wine-development-5.9/dlls/wineusb.sys/wineusb.c --- wine-development-5.8/dlls/wineusb.sys/wineusb.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/wineusb.sys/wineusb.c 2020-05-22 18:49:34.000000000 +0000 @@ -641,7 +641,7 @@ transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER; ret = libusb_submit_transfer(transfer); if (ret < 0) - ERR("Failed to submit GET_DESRIPTOR transfer: %s\n", libusb_strerror(ret)); + ERR("Failed to submit GET_DESCRIPTOR transfer: %s\n", libusb_strerror(ret)); return STATUS_PENDING; } diff -Nru wine-development-5.8/dlls/winex11.drv/desktop.c wine-development-5.9/dlls/winex11.drv/desktop.c --- wine-development-5.8/dlls/winex11.drv/desktop.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winex11.drv/desktop.c 2020-05-22 18:49:34.000000000 +0000 @@ -145,7 +145,10 @@ */ } TRACE("Resizing Wine desktop window to %dx%d\n", dd_modes[mode].width, dd_modes[mode].height); - X11DRV_resize_desktop(dd_modes[mode].width, dd_modes[mode].height); + + desktop_width = dd_modes[mode].width; + desktop_height = dd_modes[mode].height; + X11DRV_DisplayDevices_Update( TRUE ); return DISP_CHANGE_SUCCESSFUL; } @@ -321,29 +324,6 @@ return TRUE; } -static BOOL CALLBACK update_windows_on_desktop_resize( HWND hwnd, LPARAM lparam ) -{ - struct x11drv_win_data *data; - UINT mask = (UINT)lparam; - - if (!(data = get_win_data( hwnd ))) return TRUE; - - /* update the full screen state */ - update_net_wm_states( data ); - - if (mask && data->whole_window) - { - POINT pos = virtual_screen_to_root( data->whole_rect.left, data->whole_rect.top ); - XWindowChanges changes; - changes.x = pos.x; - changes.y = pos.y; - XReconfigureWMWindow( data->display, data->whole_window, data->vis.screen, mask, &changes ); - } - release_win_data( data ); - if (hwnd == GetForegroundWindow()) clip_fullscreen_window( hwnd, TRUE ); - return TRUE; -} - BOOL is_desktop_fullscreen(void) { RECT primary_rect = get_primary_monitor_rect(); @@ -387,36 +367,34 @@ /*********************************************************************** * X11DRV_resize_desktop */ -void X11DRV_resize_desktop( unsigned int width, unsigned int height ) +void X11DRV_resize_desktop( BOOL send_display_change ) { - RECT old_virtual_rect, new_virtual_rect; + RECT primary_rect, virtual_rect; HWND hwnd = GetDesktopWindow(); - UINT mask = 0; - - old_virtual_rect = get_virtual_screen_rect(); - desktop_width = width; - desktop_height = height; - X11DRV_DisplayDevices_Init( TRUE ); - new_virtual_rect = get_virtual_screen_rect(); + INT width, height; - if (old_virtual_rect.left != new_virtual_rect.left) mask |= CWX; - if (old_virtual_rect.top != new_virtual_rect.top) mask |= CWY; + virtual_rect = get_virtual_screen_rect(); + primary_rect = get_primary_monitor_rect(); + width = primary_rect.right; + height = primary_rect.bottom; if (GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId()) { - SendMessageW( hwnd, WM_X11DRV_RESIZE_DESKTOP, 0, MAKELPARAM( width, height ) ); + SendMessageW( hwnd, WM_X11DRV_RESIZE_DESKTOP, 0, (LPARAM)send_display_change ); } else { TRACE( "desktop %p change to (%dx%d)\n", hwnd, width, height ); update_desktop_fullscreen( width, height ); - SetWindowPos( hwnd, 0, new_virtual_rect.left, new_virtual_rect.top, - new_virtual_rect.right - new_virtual_rect.left, new_virtual_rect.bottom - new_virtual_rect.top, + SetWindowPos( hwnd, 0, virtual_rect.left, virtual_rect.top, + virtual_rect.right - virtual_rect.left, virtual_rect.bottom - virtual_rect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE ); ungrab_clipping_window(); - SendMessageTimeoutW( HWND_BROADCAST, WM_DISPLAYCHANGE, screen_bpp, - MAKELPARAM( width, height ), SMTO_ABORTIFHUNG, 2000, NULL ); - } - EnumWindows( update_windows_on_desktop_resize, (LPARAM)mask ); + if (send_display_change) + { + SendMessageTimeoutW( HWND_BROADCAST, WM_DISPLAYCHANGE, screen_bpp, MAKELPARAM( width, height ), + SMTO_ABORTIFHUNG, 2000, NULL ); + } + } } diff -Nru wine-development-5.8/dlls/winex11.drv/display.c wine-development-5.9/dlls/winex11.drv/display.c --- wine-development-5.8/dlls/winex11.drv/display.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winex11.drv/display.c 2020-05-22 18:49:34.000000000 +0000 @@ -273,6 +273,50 @@ handler->register_event_handlers(); } +static BOOL CALLBACK update_windows_on_display_change(HWND hwnd, LPARAM lparam) +{ + struct x11drv_win_data *data; + UINT mask = (UINT)lparam; + + if (!(data = get_win_data(hwnd))) + return TRUE; + + /* update the full screen state */ + update_net_wm_states(data); + + if (mask && data->whole_window) + { + POINT pos = virtual_screen_to_root(data->whole_rect.left, data->whole_rect.top); + XWindowChanges changes; + changes.x = pos.x; + changes.y = pos.y; + XReconfigureWMWindow(data->display, data->whole_window, data->vis.screen, mask, &changes); + } + release_win_data(data); + if (hwnd == GetForegroundWindow()) + clip_fullscreen_window(hwnd, TRUE); + return TRUE; +} + +void X11DRV_DisplayDevices_Update(BOOL send_display_change) +{ + RECT old_virtual_rect, new_virtual_rect; + UINT mask = 0; + + old_virtual_rect = get_virtual_screen_rect(); + X11DRV_DisplayDevices_Init(TRUE); + new_virtual_rect = get_virtual_screen_rect(); + + /* Calculate XReconfigureWMWindow() mask */ + if (old_virtual_rect.left != new_virtual_rect.left) + mask |= CWX; + if (old_virtual_rect.top != new_virtual_rect.top) + mask |= CWY; + + X11DRV_resize_desktop(send_display_change); + EnumWindows(update_windows_on_display_change, (LPARAM)mask); +} + /* Initialize a GPU instance and return its GUID string in guid_string and driver value in driver parameter */ static BOOL X11DRV_InitGpu(HDEVINFO devinfo, const struct x11drv_gpu *gpu, INT gpu_index, WCHAR *guid_string, WCHAR *driver) diff -Nru wine-development-5.8/dlls/winex11.drv/mouse.c wine-development-5.9/dlls/winex11.drv/mouse.c --- wine-development-5.8/dlls/winex11.drv/mouse.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winex11.drv/mouse.c 2020-05-22 18:49:34.000000000 +0000 @@ -74,8 +74,8 @@ MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_WHEEL, MOUSEEVENTF_WHEEL, - MOUSEEVENTF_XDOWN, /* FIXME: horizontal wheel */ - MOUSEEVENTF_XDOWN, + MOUSEEVENTF_HWHEEL, + MOUSEEVENTF_HWHEEL, MOUSEEVENTF_XDOWN, MOUSEEVENTF_XDOWN }; @@ -87,8 +87,8 @@ MOUSEEVENTF_RIGHTUP, 0, 0, - MOUSEEVENTF_XUP, - MOUSEEVENTF_XUP, + 0, + 0, MOUSEEVENTF_XUP, MOUSEEVENTF_XUP }; @@ -100,8 +100,8 @@ 0, WHEEL_DELTA, -WHEEL_DELTA, - XBUTTON1, - XBUTTON2, + -WHEEL_DELTA, + WHEEL_DELTA, XBUTTON1, XBUTTON2 }; @@ -113,8 +113,8 @@ 0, 0, 0, - XBUTTON1, - XBUTTON2, + 0, + 0, XBUTTON1, XBUTTON2 }; diff -Nru wine-development-5.8/dlls/winex11.drv/window.c wine-development-5.9/dlls/winex11.drv/window.c --- wine-development-5.8/dlls/winex11.drv/window.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winex11.drv/window.c 2020-05-22 18:49:34.000000000 +0000 @@ -1154,19 +1154,16 @@ /*********************************************************************** - * X11DRV_window_to_X_rect - * - * Convert a rect from client to X window coordinates + * get_decoration_rect */ -static void X11DRV_window_to_X_rect( struct x11drv_win_data *data, RECT *rect, - const RECT *window_rect, const RECT *client_rect ) +static void get_decoration_rect( struct x11drv_win_data *data, RECT *rect, + const RECT *window_rect, const RECT *client_rect ) { DWORD style, ex_style, style_mask = 0, ex_style_mask = 0; unsigned long decor; - RECT rc; + SetRectEmpty( rect ); if (!data->managed) return; - if (IsRectEmpty( rect )) return; style = GetWindowLongW( data->hwnd, GWL_STYLE ); ex_style = GetWindowLongW( data->hwnd, GWL_EXSTYLE ); @@ -1179,9 +1176,23 @@ ex_style_mask |= WS_EX_DLGMODALFRAME; } - SetRectEmpty( &rc ); - AdjustWindowRectEx( &rc, style & style_mask, FALSE, ex_style & ex_style_mask ); + AdjustWindowRectEx( rect, style & style_mask, FALSE, ex_style & ex_style_mask ); +} + + +/*********************************************************************** + * X11DRV_window_to_X_rect + * + * Convert a rect from client to X window coordinates + */ +static void X11DRV_window_to_X_rect( struct x11drv_win_data *data, RECT *rect, + const RECT *window_rect, const RECT *client_rect ) +{ + RECT rc; + + if (IsRectEmpty( rect )) return; + get_decoration_rect( data, &rc, window_rect, client_rect ); rect->left -= rc.left; rect->right -= rc.right; rect->top -= rc.top; @@ -1198,12 +1209,16 @@ */ void X11DRV_X_to_window_rect( struct x11drv_win_data *data, RECT *rect, int x, int y, int cx, int cy ) { - x += data->window_rect.left - data->whole_rect.left; - y += data->window_rect.top - data->whole_rect.top; - cx += (data->window_rect.right - data->window_rect.left) - - (data->whole_rect.right - data->whole_rect.left); - cy += (data->window_rect.bottom - data->window_rect.top) - - (data->whole_rect.bottom - data->whole_rect.top); + RECT rc; + + get_decoration_rect( data, &rc, &data->window_rect, &data->client_rect ); + + x += min( data->window_rect.left - data->whole_rect.left, rc.left ); + y += min( data->window_rect.top - data->whole_rect.top, rc.top ); + cx += max( (data->window_rect.right - data->window_rect.left) - + (data->whole_rect.right - data->whole_rect.left), rc.right - rc.left ); + cy += max( (data->window_rect.bottom - data->window_rect.top) - + (data->whole_rect.bottom - data->whole_rect.top), rc.bottom - rc.top ); SetRect( rect, x, y, x + cx, y + cy ); } @@ -2729,7 +2744,7 @@ } return 0; case WM_X11DRV_RESIZE_DESKTOP: - X11DRV_resize_desktop( LOWORD(lp), HIWORD(lp) ); + X11DRV_resize_desktop( (BOOL)lp ); return 0; case WM_X11DRV_SET_CURSOR: if ((data = get_win_data( hwnd ))) diff -Nru wine-development-5.8/dlls/winex11.drv/x11drv.h wine-development-5.9/dlls/winex11.drv/x11drv.h --- wine-development-5.8/dlls/winex11.drv/x11drv.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winex11.drv/x11drv.h 2020-05-22 18:49:34.000000000 +0000 @@ -657,7 +657,7 @@ }; extern void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) DECLSPEC_HIDDEN; -extern void X11DRV_resize_desktop(unsigned int width, unsigned int height) DECLSPEC_HIDDEN; +extern void X11DRV_resize_desktop(BOOL) DECLSPEC_HIDDEN; extern BOOL is_virtual_desktop(void) DECLSPEC_HIDDEN; extern BOOL is_desktop_fullscreen(void) DECLSPEC_HIDDEN; extern BOOL create_desktop_win_data( Window win ) DECLSPEC_HIDDEN; @@ -755,6 +755,7 @@ extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN; extern void X11DRV_DisplayDevices_Init(BOOL force) DECLSPEC_HIDDEN; extern void X11DRV_DisplayDevices_RegisterEventHandlers(void) DECLSPEC_HIDDEN; +extern void X11DRV_DisplayDevices_Update(BOOL) DECLSPEC_HIDDEN; /* Display device handler used in virtual desktop mode */ extern struct x11drv_display_device_handler desktop_handler DECLSPEC_HIDDEN; diff -Nru wine-development-5.8/dlls/winex11.drv/xrandr.c wine-development-5.9/dlls/winex11.drv/xrandr.c --- wine-development-5.8/dlls/winex11.drv/xrandr.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winex11.drv/xrandr.c 2020-05-22 18:49:34.000000000 +0000 @@ -209,7 +209,7 @@ if (stat == RRSetConfigSuccess) { xrandr_current_mode = mode; - X11DRV_resize_desktop( dd_modes[mode].width, dd_modes[mode].height ); + X11DRV_DisplayDevices_Update( TRUE ); return DISP_CHANGE_SUCCESSFUL; } @@ -457,7 +457,7 @@ } xrandr_current_mode = mode; - X11DRV_resize_desktop( dd_modes[mode].width, dd_modes[mode].height ); + X11DRV_DisplayDevices_Update( TRUE ); return DISP_CHANGE_SUCCESSFUL; } @@ -1094,7 +1094,12 @@ static BOOL xrandr14_device_change_handler( HWND hwnd, XEvent *event ) { if (hwnd == GetDesktopWindow() && GetWindowThreadProcessId( hwnd, NULL ) == GetCurrentThreadId()) - X11DRV_DisplayDevices_Init( TRUE ); + { + /* Don't send a WM_DISPLAYCHANGE message here because this event may be a result from + * ChangeDisplaySettings(). Otherwise, ChangeDisplaySettings() would send multiple + * WM_DISPLAYCHANGE messages instead of just one */ + X11DRV_DisplayDevices_Update( FALSE ); + } return FALSE; } diff -Nru wine-development-5.8/dlls/winex11.drv/xvidmode.c wine-development-5.9/dlls/winex11.drv/xvidmode.c --- wine-development-5.8/dlls/winex11.drv/xvidmode.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/winex11.drv/xvidmode.c 2020-05-22 18:49:34.000000000 +0000 @@ -145,7 +145,7 @@ XWarpPointer(gdi_display, None, DefaultRootWindow(gdi_display), 0, 0, 0, 0, 0, 0); #endif XSync(gdi_display, False); - X11DRV_resize_desktop( real_xf86vm_modes[mode]->hdisplay, real_xf86vm_modes[mode]->vdisplay ); + X11DRV_DisplayDevices_Update( TRUE ); return DISP_CHANGE_SUCCESSFUL; } diff -Nru wine-development-5.8/dlls/ws2_32/socket.c wine-development-5.9/dlls/ws2_32/socket.c --- wine-development-5.8/dlls/ws2_32/socket.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ws2_32/socket.c 2020-05-22 18:49:34.000000000 +0000 @@ -154,6 +154,7 @@ #include "winnt.h" #define USE_WC_PREFIX /* For CMSG_DATA */ #include "iphlpapi.h" +#include "ip2string.h" #include "wine/server.h" #include "wine/debug.h" #include "wine/exception.h" @@ -8393,10 +8394,10 @@ /*********************************************************************** * inet_pton (WS2_32.@) */ -INT WINAPI WS_inet_pton( INT family, PCSTR addr, PVOID buffer) +INT WINAPI WS_inet_pton(INT family, const char *addr, void *buffer) { -#ifdef HAVE_INET_PTON - int unixaf, ret; + NTSTATUS status; + const char *terminator; TRACE("family %d, addr %s, buffer (%p)\n", family, debugstr_a(addr), buffer); @@ -8406,21 +8407,20 @@ return SOCKET_ERROR; } - unixaf = convert_af_w2u(family); - if (unixaf != AF_INET && unixaf != AF_INET6) + switch (family) { + case WS_AF_INET: + status = RtlIpv4StringToAddressA(addr, TRUE, &terminator, buffer); + break; + case WS_AF_INET6: + status = RtlIpv6StringToAddressA(addr, &terminator, buffer); + break; + default: SetLastError(WSAEAFNOSUPPORT); return SOCKET_ERROR; } - ret = inet_pton(unixaf, addr, buffer); - if (ret == -1) SetLastError(wsaErrno()); - return ret; -#else - FIXME( "not supported on this platform\n" ); - SetLastError( WSAEAFNOSUPPORT ); - return SOCKET_ERROR; -#endif + return (status == STATUS_SUCCESS && *terminator == 0); } /*********************************************************************** @@ -8449,6 +8449,7 @@ WideCharToMultiByte(CP_ACP, 0, addr, -1, addrA, len, NULL, NULL); ret = WS_inet_pton(family, addrA, buffer); + if (!ret) SetLastError(WSAEINVAL); HeapFree(GetProcessHeap(), 0, addrA); return ret; @@ -8484,7 +8485,7 @@ LPINT lpAddressLength) { INT res=0; - LPSTR workBuffer=NULL,ptrPort; + NTSTATUS status; TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_a(AddressString), AddressFamily, lpProtocolInfo, lpAddress, lpAddressLength ); @@ -8500,21 +8501,11 @@ if (lpProtocolInfo) FIXME("ProtocolInfo not implemented.\n"); - workBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - strlen(AddressString) + 1); - if (!workBuffer) - { - SetLastError(WSA_NOT_ENOUGH_MEMORY); - return SOCKET_ERROR; - } - - strcpy(workBuffer, AddressString); - switch(AddressFamily) { case WS_AF_INET: { - struct in_addr inetaddr; + SOCKADDR_IN *addr4 = (SOCKADDR_IN *)lpAddress; /* If lpAddressLength is too small, tell caller the size we need */ if (*lpAddressLength < sizeof(SOCKADDR_IN)) @@ -8523,38 +8514,21 @@ res = WSAEFAULT; break; } - *lpAddressLength = sizeof(SOCKADDR_IN); memset(lpAddress, 0, sizeof(SOCKADDR_IN)); - ((LPSOCKADDR_IN)lpAddress)->sin_family = WS_AF_INET; - - ptrPort = strchr(workBuffer, ':'); - if(ptrPort) + status = RtlIpv4StringToAddressExA(AddressString, FALSE, &addr4->sin_addr, &addr4->sin_port); + if (status != STATUS_SUCCESS) { - /* User may have entered an IPv6 and asked to parse as IPv4 */ - if(strchr(ptrPort + 1, ':')) - { - res = WSAEINVAL; - break; - } - ((LPSOCKADDR_IN)lpAddress)->sin_port = htons(atoi(ptrPort+1)); - *ptrPort = '\0'; - } - - if(inet_aton(workBuffer, &inetaddr) > 0) - { - ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr; - res = 0; - } - else res = WSAEINVAL; - + break; + } + addr4->sin_family = WS_AF_INET; + *lpAddressLength = sizeof(SOCKADDR_IN); break; } case WS_AF_INET6: { - struct in6_addr inetaddr; - char *ptrAddr = workBuffer; + SOCKADDR_IN6 *addr6 = (SOCKADDR_IN6 *)lpAddress; /* If lpAddressLength is too small, tell caller the size we need */ if (*lpAddressLength < sizeof(SOCKADDR_IN6)) @@ -8563,42 +8537,16 @@ res = WSAEFAULT; break; } -#ifdef HAVE_INET_PTON - *lpAddressLength = sizeof(SOCKADDR_IN6); memset(lpAddress, 0, sizeof(SOCKADDR_IN6)); - ((LPSOCKADDR_IN6)lpAddress)->sin6_family = WS_AF_INET6; - - /* Valid IPv6 addresses can also be surrounded by [ ], and in this case - * a port number may follow after like in [fd12:3456:7890::1]:12345 - * We need to cut the brackets and find the port if any. */ - - if(*workBuffer == '[') - { - ptrPort = strchr(workBuffer, ']'); - if (!ptrPort) - { - SetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - if (ptrPort[1] == ':') - ((LPSOCKADDR_IN6)lpAddress)->sin6_port = htons(atoi(ptrPort + 2)); - - *ptrPort = '\0'; - ptrAddr = workBuffer + 1; - } - - if(inet_pton(AF_INET6, ptrAddr, &inetaddr) > 0) + status = RtlIpv6StringToAddressExA(AddressString, &addr6->sin6_addr, &addr6->sin6_scope_id, &addr6->sin6_port); + if (status != STATUS_SUCCESS) { - memcpy(&((LPSOCKADDR_IN6)lpAddress)->sin6_addr, &inetaddr, - sizeof(struct in6_addr)); - res = 0; - } - else -#endif /* HAVE_INET_PTON */ res = WSAEINVAL; - + break; + } + addr6->sin6_family = WS_AF_INET6; + *lpAddressLength = sizeof(SOCKADDR_IN6); break; } default: @@ -8607,8 +8555,6 @@ res = WSAEINVAL; } - HeapFree(GetProcessHeap(), 0, workBuffer); - if (!res) return 0; SetLastError(res); return SOCKET_ERROR; diff -Nru wine-development-5.8/dlls/ws2_32/tests/sock.c wine-development-5.9/dlls/ws2_32/tests/sock.c --- wine-development-5.8/dlls/ws2_32/tests/sock.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/dlls/ws2_32/tests/sock.c 2020-05-22 18:49:34.000000000 +0000 @@ -3412,266 +3412,159 @@ closesocket(v6); } -static void test_WSAStringToAddressA(void) +static void test_WSAStringToAddress(void) { - INT ret, len; - SOCKADDR_IN sockaddr; - SOCKADDR_IN6 sockaddr6; - int GLE; - - CHAR address1[] = "0.0.0.0"; - CHAR address2[] = "127.127.127.127"; - CHAR address3[] = "255.255.255.255"; - CHAR address4[] = "127.127.127.127:65535"; - CHAR address5[] = "255.255.255.255:65535"; - CHAR address6[] = "::1"; - CHAR address7[] = "[::1]"; - CHAR address8[] = "[::1]:65535"; - CHAR address9[] = "2001::1"; - - len = 0; - sockaddr.sin_family = AF_INET; - - ret = WSAStringToAddressA( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( ret == SOCKET_ERROR, "WSAStringToAddressA() succeeded unexpectedly: %d\n", - WSAGetLastError() ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressA( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( !ret && sockaddr.sin_addr.s_addr == 0, - "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressA( address2, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f, - "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressA( address3, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == 0 && sockaddr.sin_addr.s_addr == 0xffffffff) || - (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), - "WSAStringToAddressA() failed unexpectedly: %d\n", GLE ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressA( address4, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f && sockaddr.sin_port == 0xffff, - "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressA( address5, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == 0 && sockaddr.sin_addr.s_addr == 0xffffffff && sockaddr.sin_port == 0xffff) || - (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), - "WSAStringToAddressA() failed unexpectedly: %d\n", GLE ); - - len = sizeof(sockaddr); - - ret = WSAStringToAddressA( address9, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressA() should have failed with %d\n", GLE ); - - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; - - ret = WSAStringToAddressA( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - if (ret == SOCKET_ERROR) + static struct { - win_skip("IPv6 not supported\n"); - return; - } - - GLE = WSAGetLastError(); - ok( ret == 0, "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); - - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; - - ret = WSAStringToAddressA( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - GLE = WSAGetLastError(); - ok( ret == 0, "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); - - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; - - ret = WSAStringToAddressA( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - GLE = WSAGetLastError(); - ok( ret == 0 && sockaddr6.sin6_port == 0xffff, - "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); - - len = sizeof(sockaddr6); - - ret = WSAStringToAddressA( address7 + 1, AF_INET6, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressW() should have failed with %d\n", GLE ); - - len = sizeof(sockaddr6); - - ret = WSAStringToAddressA( address8 + 1, AF_INET6, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressW() should have failed with %d\n", GLE ); -} + char input[32]; + ULONG address; + USHORT port; + int error; + } + ipv4_tests[] = + { + { "0.0.0.0", 0 }, + { "127.127.127.127", 0x7f7f7f7f }, + { "255.255.255.255", 0xffffffff }, + { "127.127.127.127:65535", 0x7f7f7f7f, 65535 }, + { "255.255.255.255:65535", 0xffffffff, 65535 }, + { "2001::1", 0xd1070000, 0, WSAEINVAL }, + { "1.2.3.", 0, 0, WSAEINVAL }, + { "", 0, 0, WSAEINVAL }, + }; + static struct + { + char input[64]; + USHORT address[8]; + USHORT port; + int error; + } + ipv6_tests[] = + { + { "::1", { 0, 0, 0, 0, 0, 0, 0, 0x100 } }, + { "[::1]", { 0, 0, 0, 0, 0, 0, 0, 0x100 } }, + { "[::1]:65535", { 0, 0, 0, 0, 0, 0, 0, 0x100 }, 0xffff }, + { "2001::1", { 0x120, 0, 0, 0, 0, 0, 0, 0x100 } }, + { "::1]:65535", { 0, 0, 0, 0, 0, 0, 0, 0x100 }, 0, WSAEINVAL }, + { "001::1", { 0x100, 0, 0, 0, 0, 0, 0, 0x100 } }, + { "::1:2:3:4:5:6:7", { 0, 0, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600 }, 0, WSAEINVAL }, /* Windows bug */ + { "1.2.3.4", { 0x201, 0x3, 0, 0, 0, 0, 0, 0 }, 0, WSAEINVAL }, + { "1:2:3:", { 0x100, 0x200, 0x300, 0, 0, 0, 0 }, 0, WSAEINVAL }, + { "", { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, WSAEINVAL }, + }; -static void test_WSAStringToAddressW(void) -{ - INT ret, len; - SOCKADDR_IN sockaddr, *sin; + WCHAR inputW[64]; + INT len, ret, expected_len, expected_ret; + short expected_family; + SOCKADDR_IN sockaddr; SOCKADDR_IN6 sockaddr6; - SOCKADDR_STORAGE sockaddr_storage; - int GLE; - - WCHAR address1[] = { '0','.','0','.','0','.','0', 0 }; - WCHAR address2[] = { '1','2','7','.','1','2','7','.','1','2','7','.','1','2','7', 0 }; - WCHAR address3[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', 0 }; - WCHAR address4[] = { '1','2','7','.','1','2','7','.','1','2','7','.','1','2','7', - ':', '6', '5', '5', '3', '5', 0 }; - WCHAR address5[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', ':', - '6', '5', '5', '3', '5', 0 }; - WCHAR address6[] = {':',':','1','\0'}; - WCHAR address7[] = {'[',':',':','1',']','\0'}; - WCHAR address8[] = {'[',':',':','1',']',':','6','5','5','3','5','\0'}; - WCHAR address9[] = {'2','0','0','1',':',':','1','\0'}; + int i, j; len = 0; - sockaddr.sin_family = AF_INET; - - ret = WSAStringToAddressW( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( ret == SOCKET_ERROR, "WSAStringToAddressW() failed unexpectedly: %d\n", - WSAGetLastError() ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressW( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( !ret && sockaddr.sin_addr.s_addr == 0, - "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() ); + WSASetLastError( 0 ); + ret = WSAStringToAddressA( ipv4_tests[0].input, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( ret == SOCKET_ERROR, "WSAStringToAddressA() returned %d, expected SOCKET_ERROR\n", ret ); + ok( WSAGetLastError() == WSAEFAULT, "WSAStringToAddress() gave error %d, expected WSAEFAULT\n", WSAGetLastError() ); + ok( len >= sizeof(sockaddr) || broken(len == 0) /* xp */, + "WSAStringToAddress() gave length %d, expected at least %d\n", len, sizeof(sockaddr) ); + + for (i = 0; i < 2; i++) + { + for (j = 0; j < ARRAY_SIZE(ipv4_tests); j++) + { + len = sizeof(sockaddr) + 10; + expected_len = ipv4_tests[j].error ? len : sizeof(sockaddr); + memset( &sockaddr, 0xab, sizeof(sockaddr) ); - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressW( address2, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f, - "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressW( address3, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == 0 && sockaddr.sin_addr.s_addr == 0xffffffff) || - (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), - "WSAStringToAddressW() failed unexpectedly: %d\n", GLE ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressW( address4, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f && sockaddr.sin_port == 0xffff, - "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() ); - - len = sizeof(sockaddr); - sockaddr.sin_port = 0; - sockaddr.sin_addr.s_addr = 0; - - ret = WSAStringToAddressW( address5, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - ok( (ret == 0 && sockaddr.sin_addr.s_addr == 0xffffffff && sockaddr.sin_port == 0xffff) || - (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), - "WSAStringToAddressW() failed unexpectedly: %d\n", GLE ); - - /* Test with a larger buffer than necessary */ - len = sizeof(sockaddr_storage); - sin = (SOCKADDR_IN *)&sockaddr_storage; - sin->sin_port = 0; - sin->sin_addr.s_addr = 0; - - ret = WSAStringToAddressW( address5, AF_INET, NULL, (SOCKADDR*)sin, &len ); - ok( (ret == 0 && sin->sin_addr.s_addr == 0xffffffff && sin->sin_port == 0xffff) || - (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), - "WSAStringToAddressW() failed unexpectedly: %d\n", GLE ); - ok( len == sizeof(SOCKADDR_IN), "unexpected length %d\n", len ); - - len = sizeof(sockaddr); - - ret = WSAStringToAddressW( address9, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressW() should have failed with %d\n", GLE ); - - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; + WSASetLastError( 0 ); + if (i == 0) + { + ret = WSAStringToAddressA( ipv4_tests[j].input, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + } + else + { + MultiByteToWideChar( CP_ACP, 0, ipv4_tests[j].input, -1, inputW, ARRAY_SIZE(inputW) ); + ret = WSAStringToAddressW( inputW, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + } + expected_ret = ipv4_tests[j].error ? SOCKET_ERROR : 0; + expected_family = ipv4_tests[j].error ? 0 : AF_INET; + ok( ret == expected_ret, + "WSAStringToAddress(%s) returned %d, expected %d\n", + wine_dbgstr_a( ipv4_tests[j].input ), ret, expected_ret ); + ok( WSAGetLastError() == ipv4_tests[j].error, + "WSAStringToAddress(%s) gave error %d, expected %d\n", + wine_dbgstr_a( ipv4_tests[j].input ), WSAGetLastError(), ipv4_tests[j].error ); + ok( sockaddr.sin_family == expected_family, + "WSAStringToAddress(%s) gave family %d, expected %d\n", + wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_family, expected_family ); + ok( sockaddr.sin_addr.s_addr == ipv4_tests[j].address, + "WSAStringToAddress(%s) gave address %08x, expected %08x\n", + wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_addr.s_addr, ipv4_tests[j].address ); + ok( sockaddr.sin_port == ipv4_tests[j].port, + "WSAStringToAddress(%s) gave port %04x, expected %04x\n", + wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_port, ipv4_tests[j].port ); + ok( len == expected_len, + "WSAStringToAddress(%s) gave length %d, expected %d\n", + wine_dbgstr_a( ipv4_tests[j].input ), len, expected_len ); + } + + for (j = 0; j < ARRAY_SIZE(ipv6_tests); j++) + { + len = sizeof(sockaddr6) + 10; + expected_len = ipv6_tests[j].error ? len : sizeof(sockaddr6); + memset( &sockaddr6, 0xab, sizeof(sockaddr6) ); - ret = WSAStringToAddressW( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - if (ret == SOCKET_ERROR) - { - win_skip("IPv6 not supported\n"); - return; + WSASetLastError( 0 ); + if (i == 0) + { + ret = WSAStringToAddressA( ipv6_tests[j].input, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, &len ); + } + else + { + MultiByteToWideChar( CP_ACP, 0, ipv6_tests[j].input, -1, inputW, ARRAY_SIZE(inputW) ); + ret = WSAStringToAddressW( inputW, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, &len ); + } + if (j == 0 && ret == SOCKET_ERROR) + { + win_skip("IPv6 not supported\n"); + break; + } + expected_ret = ipv6_tests[j].error ? SOCKET_ERROR : 0; + expected_family = ipv6_tests[j].error ? 0 : AF_INET6; + ok( ret == expected_ret, + "WSAStringToAddress(%s) returned %d, expected %d\n", + wine_dbgstr_a( ipv6_tests[j].input ), ret, expected_ret ); + ok( WSAGetLastError() == ipv6_tests[j].error, + "WSAStringToAddress(%s) gave error %d, expected %d\n", + wine_dbgstr_a( ipv6_tests[j].input ), WSAGetLastError(), ipv6_tests[j].error ); + ok( sockaddr6.sin6_family == expected_family, + "WSAStringToAddress(%s) gave family %d, expected %d\n", + wine_dbgstr_a( ipv4_tests[j].input ), sockaddr6.sin6_family, expected_family ); + ok( memcmp(&sockaddr6.sin6_addr, ipv6_tests[j].address, sizeof(sockaddr6.sin6_addr)) == 0, + "WSAStringToAddress(%s) gave address %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n", + wine_dbgstr_a( ipv6_tests[j].input ), + sockaddr6.sin6_addr.s6_words[0], sockaddr6.sin6_addr.s6_words[1], + sockaddr6.sin6_addr.s6_words[2], sockaddr6.sin6_addr.s6_words[3], + sockaddr6.sin6_addr.s6_words[4], sockaddr6.sin6_addr.s6_words[5], + sockaddr6.sin6_addr.s6_words[6], sockaddr6.sin6_addr.s6_words[7], + ipv6_tests[j].address[0], ipv6_tests[j].address[1], + ipv6_tests[j].address[2], ipv6_tests[j].address[3], + ipv6_tests[j].address[4], ipv6_tests[j].address[5], + ipv6_tests[j].address[6], ipv6_tests[j].address[7] ); + ok( sockaddr6.sin6_scope_id == 0, + "WSAStringToAddress(%s) gave scope %d, expected 0\n", + wine_dbgstr_a( ipv6_tests[j].input ), sockaddr6.sin6_scope_id ); + ok( sockaddr6.sin6_port == ipv6_tests[j].port, + "WSAStringToAddress(%s) gave port %04x, expected %04x\n", + wine_dbgstr_a( ipv6_tests[j].input ), sockaddr6.sin6_port, ipv6_tests[j].port ); + ok( sockaddr6.sin6_flowinfo == 0, + "WSAStringToAddress(%s) gave flowinfo %d, expected 0\n", + wine_dbgstr_a( ipv6_tests[j].input ), sockaddr6.sin6_flowinfo ); + ok( len == expected_len, + "WSAStringToAddress(%s) gave length %d, expected %d\n", + wine_dbgstr_a( ipv6_tests[j].input ), len, expected_len ); + } } - - GLE = WSAGetLastError(); - ok( ret == 0, "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); - - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; - - ret = WSAStringToAddressW( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - GLE = WSAGetLastError(); - ok( ret == 0, "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); - - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; - - ret = WSAStringToAddressW( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - GLE = WSAGetLastError(); - ok( ret == 0 && sockaddr6.sin6_port == 0xffff, - "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); - - len = sizeof(sockaddr6); - - ret = WSAStringToAddressW( address7 + 1, AF_INET6, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressW() should have failed with %d\n", GLE ); - - len = sizeof(sockaddr6); - - ret = WSAStringToAddressW( address8 + 1, AF_INET6, NULL, (SOCKADDR*)&sockaddr, &len ); - GLE = WSAGetLastError(); - ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressW() should have failed with %d\n", GLE ); } static DWORD WINAPI SelectReadThread(void *param) @@ -5110,7 +5003,11 @@ "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"}, {AF_INET6, 1, 0, "2001:cdba:0:0:0:0:3257:9652", "2001:cdba::3257:9652", - "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"} + "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"}, + {AF_INET, 0, 0, + "0x12345678", NULL, NULL}, + {AF_INET6, 0, 0, /* windows bug */ + "::1:2:3:4:5:6:7", NULL, NULL}, }; int i, ret; DWORD err; @@ -5131,11 +5028,11 @@ WSASetLastError(0xdeadbeef); ret = pInetPtonA(tests[i].family, tests[i].printable, buffer); ok (ret == tests[i].ret, "Test [%d]: Expected %d, got %d\n", i, tests[i].ret, ret); + err = WSAGetLastError(); if (tests[i].ret == -1) - { - err = WSAGetLastError(); ok (tests[i].err == err, "Test [%d]: Expected 0x%x, got 0x%x\n", i, tests[i].err, err); - } + else + ok (err == 0xdeadbeef, "Test [%d]: Expected 0xdeadbeef, got 0x%x\n", i, err); if (tests[i].ret != 1) continue; ok (memcmp(buffer, tests[i].raw_data, tests[i].family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)) == 0, @@ -5158,11 +5055,14 @@ WSASetLastError(0xdeadbeef); ret = pInetPtonW(tests[i].family, tests[i].printable ? printableW : NULL, buffer); ok(ret == tests[i].ret, "Test [%d]: Expected %d, got %d\n", i, tests[i].ret, ret); + err = WSAGetLastError(); if (tests[i].ret == -1) - { - err = WSAGetLastError(); ok(tests[i].err == err, "Test [%d]: Expected 0x%x, got 0x%x\n", i, tests[i].err, err); - } + else if (tests[i].ret == 0) + ok(err == WSAEINVAL || broken(err == 0xdeadbeef) /* win2008 */, + "Test [%d]: Expected WSAEINVAL, got 0x%x\n", i, err); + else + ok(err == 0xdeadbeef, "Test [%d]: Expected 0xdeadbeef, got 0x%x\n", i, err); if (tests[i].ret != 1) continue; ok(memcmp(buffer, tests[i].raw_data, tests[i].family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)) == 0, @@ -11677,8 +11577,7 @@ test_WSAAddressToStringA(); test_WSAAddressToStringW(); - test_WSAStringToAddressA(); - test_WSAStringToAddressW(); + test_WSAStringToAddress(); test_errors(); test_listen(); diff -Nru wine-development-5.8/include/asferr.h wine-development-5.9/include/asferr.h --- wine-development-5.8/include/asferr.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/include/asferr.h 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2020 Zebediah Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _ASFERR_H +#define _ASFERR_H + +#ifdef RC_INVOKED +#define _ASF_HRESULT_TYPEDEF_(x) x +#else +#define _ASF_HRESULT_TYPEDEF_(x) ((HRESULT)x) +#endif + +#define ASF_S_OPAQUEPACKET _ASF_HRESULT_TYPEDEF_(0x000d07f0) + +#define ASF_E_BUFFEROVERRUN _ASF_HRESULT_TYPEDEF_(0xc00d07d0) +#define ASF_E_BUFFERTOOSMALL _ASF_HRESULT_TYPEDEF_(0xc00d07d1) +#define ASF_E_BADLANGUAGEID _ASF_HRESULT_TYPEDEF_(0xc00d07d2) +#define ASF_E_NOPAYLOADLENGTH _ASF_HRESULT_TYPEDEF_(0xc00d07db) +#define ASF_E_TOOMANYPAYLOADS _ASF_HRESULT_TYPEDEF_(0xc00d07dc) +#define ASF_E_PACKETCONTENTTOOLARGE _ASF_HRESULT_TYPEDEF_(0xc00d07de) +#define ASF_E_UNKNOWNPACKETSIZE _ASF_HRESULT_TYPEDEF_(0xc00d07e0) +#define ASF_E_INVALIDHEADER _ASF_HRESULT_TYPEDEF_(0xc00d07e2) +#define ASF_E_NOCLOCKOBJECT _ASF_HRESULT_TYPEDEF_(0xc00d07e6) +#define ASF_E_UNKNOWNCLOCKTYPE _ASF_HRESULT_TYPEDEF_(0xc00d07eb) +#define ASF_E_OPAQUEPACKET _ASF_HRESULT_TYPEDEF_(0xc00d07ed) +#define ASF_E_WRONGVERSION _ASF_HRESULT_TYPEDEF_(0xc00d07ee) +#define ASF_E_OVERFLOW _ASF_HRESULT_TYPEDEF_(0xc00d07ef) +#define ASF_E_NOTFOUND _ASF_HRESULT_TYPEDEF_(0xc00d07f0) +#define ASF_E_OBJECTTOOBIG _ASF_HRESULT_TYPEDEF_(0xc00d07f3) +#define ASF_E_UNEXPECTEDVALUE _ASF_HRESULT_TYPEDEF_(0xc00d07f4) +#define ASF_E_INVALIDSTATE _ASF_HRESULT_TYPEDEF_(0xc00d07f5) +#define ASF_E_NOLIBRARY _ASF_HRESULT_TYPEDEF_(0xc00d07f6) +#define ASF_E_ALREADYINITIALIZED _ASF_HRESULT_TYPEDEF_(0xc00d07f7) +#define ASF_E_INVALIDINIT _ASF_HRESULT_TYPEDEF_(0xc00d07f8) +#define ASF_E_NOHEADEROBJECT _ASF_HRESULT_TYPEDEF_(0xc00d07f9) +#define ASF_E_NODATAOBJECT _ASF_HRESULT_TYPEDEF_(0xc00d07fa) +#define ASF_E_NOINDEXOBJECT _ASF_HRESULT_TYPEDEF_(0xc00d07fb) +#define ASF_E_NOSTREAMPROPS _ASF_HRESULT_TYPEDEF_(0xc00d07fc) +#define ASF_E_NOFILEPROPS _ASF_HRESULT_TYPEDEF_(0xc00d07fd) +#define ASF_E_NOLANGUAGELIST _ASF_HRESULT_TYPEDEF_(0xc00d07fe) +#define ASF_E_NOINDEXPARAMETERS _ASF_HRESULT_TYPEDEF_(0xc00d07ff) +#define ASF_E_UNSUPPORTEDERRORCONCEALMENT _ASF_HRESULT_TYPEDEF_(0xc00d0800) +#define ASF_E_INVALIDFLAGS _ASF_HRESULT_TYPEDEF_(0xc00d0801) +#define ASF_E_BADDATADESCRIPTOR _ASF_HRESULT_TYPEDEF_(0xc00d0802) +#define ASF_E_BADINDEXINTERVAL _ASF_HRESULT_TYPEDEF_(0xc00d0803) +#define ASF_E_INVALIDTIME _ASF_HRESULT_TYPEDEF_(0xc00d0804) +#define ASF_E_INVALIDINDEX _ASF_HRESULT_TYPEDEF_(0xc00d0805) +#define ASF_E_STREAMNUMBERINUSE _ASF_HRESULT_TYPEDEF_(0xc00d0806) +#define ASF_E_BADMEDIATYPE _ASF_HRESULT_TYPEDEF_(0xc00d0807) +#define ASF_E_WRITEFAILED _ASF_HRESULT_TYPEDEF_(0xc00d0808) +#define ASF_E_NOTENOUGHDESCRIPTORS _ASF_HRESULT_TYPEDEF_(0xc00d0809) +#define ASF_E_INDEXBLOCKUNLOADED _ASF_HRESULT_TYPEDEF_(0xc00d080a) +#define ASF_E_NOTENOUGHBANDWIDTH _ASF_HRESULT_TYPEDEF_(0xc00d080b) +#define ASF_E_EXCEEDEDMAXIMUMOBJECTSIZE _ASF_HRESULT_TYPEDEF_(0xc00d080c) +#define ASF_E_BADDATAUNIT _ASF_HRESULT_TYPEDEF_(0xc00d080d) +#define ASF_E_HEADERSIZE _ASF_HRESULT_TYPEDEF_(0xc00d080e) + +#endif diff -Nru wine-development-5.8/include/axextendenums.h wine-development-5.9/include/axextendenums.h --- wine-development-5.8/include/axextendenums.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/include/axextendenums.h 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Jactry Zeng 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 + */ + +#ifndef AXEXTEND_ENUM_H +#define AXEXTEND_ENUM_H + +#include + +ENUM16 TAG(TunerInputType) +{ + TunerInputCable, + TunerInputAntenna +} TunerInputType; + +#include + +#endif /* AXEXTEND_ENUM_H */ diff -Nru wine-development-5.8/include/axextend.idl wine-development-5.9/include/axextend.idl --- wine-development-5.8/include/axextend.idl 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/axextend.idl 2020-05-22 18:49:34.000000000 +0000 @@ -20,6 +20,8 @@ #pragma makedep install #endif +#include + interface IAMAnalogVideoDecoder; interface IAMAnalogVideoEncoder; interface IAMAudioInputMixer; @@ -1288,3 +1290,184 @@ [in] long data1, [in] long data2); } + +[ + local, + object, + uuid(6a2e0670-28e4-11d0-a18c-00a0c9118956), + pointer_default(unique) +] +interface IAMVideoControl : IUnknown +{ + HRESULT GetCaps([in] IPin *pin, [out] long *flags); + HRESULT SetMode([in] IPin *pin, long mode); + HRESULT GetMode([in] IPin *pin, [out] long *mode); + HRESULT GetCurrentActualFrameRate([in] IPin *pin, [out] LONGLONG *frame_rate); + HRESULT GetMaxAvailableFrameRate([in] IPin *pin, [in] long index, + [in] SIZE dimensions, [out] LONGLONG *frame_rate); + HRESULT GetFrameRateList([in] IPin *pin, [in] long index, [in] SIZE dimensions, + [out] long *list_size, [out] LONGLONG **frame_rate); +} + +[ + local, + object, + uuid(56ed71a0-af5f-11d0-b3f0-00aa003761c5), + pointer_default(unique) +] +interface IAMBufferNegotiation : IUnknown +{ + HRESULT SuggestAllocatorProperties([in] const ALLOCATOR_PROPERTIES *prop); + HRESULT GetAllocatorProperties([out] ALLOCATOR_PROPERTIES *prop); +} + +[ + local, + object, + uuid(c6e13344-30ac-11d0-a18c-00a0c9118956), + pointer_default(unique) +] +interface IAMDroppedFrames : IUnknown +{ + HRESULT GetNumDropped([out] long *number); + HRESULT GetNumNotDropped([out] long *number); + HRESULT GetDroppedInfo([in] long size, [out] long *array, [out] long *copied); + HRESULT GetAverageFrameSize([out] long *size); +} + +[ + local, + object, + uuid(62ea93ba-ec62-11d2-b770-00c04fb6bd3d), + pointer_default(unique) +] +interface IAMLatency : IUnknown +{ + HRESULT GetLatency([in, out] REFERENCE_TIME *latency); +} + +[ + local, + object, + uuid(f185fe76-e64e-11d2-b76e-00c04fb6bd3d), + pointer_default(unique) +] +interface IAMPushSource : IAMLatency +{ + HRESULT GetPushSourceFlags([out] ULONG *flags); + HRESULT SetPushSourceFlags([in] ULONG flags); + HRESULT SetStreamOffset([in] REFERENCE_TIME offset); + HRESULT GetStreamOffset([out] REFERENCE_TIME *offset); + HRESULT GetMaxStreamOffset([out] REFERENCE_TIME *offset); + HRESULT SetMaxStreamOffset([in] REFERENCE_TIME offset); +}; + +[ + local, + object, + uuid(c6e13343-30ac-11d0-a18c-00a0c9118956), + pointer_default(unique) +] +interface IAMVideoCompression : IUnknown +{ + HRESULT put_KeyFrameRate([in] long frame_rate); + HRESULT get_KeyFrameRate([out] long *frame_rate); + HRESULT put_PFramesPerKeyFrame([in] long frame); + HRESULT get_PFramesPerKeyFrame([out] long *frame); + HRESULT put_Quality([in] double quality); + HRESULT get_Quality([out] double *quality); + HRESULT put_WindowSize([in] DWORDLONG size); + HRESULT get_WindowSize([out] DWORDLONG *size); + HRESULT GetInfo([out, size_is(*version_size)] LPWSTR version, [in, out] int *version_size, + [out, size_is(*description_size)] LPWSTR description, [in, out] int *description_size, + [out] long *frame_rate, [out] long *key, [out] double *quality, [out] long *capabilities); + HRESULT OverrideKeyFrame([in] long number); + HRESULT OverrideFrameSize([in] long number, [in] long size); +} + +[ + local, + object, + uuid(c6e13380-30ac-11d0-a18c-00a0c9118956), + pointer_default(unique) +] +interface IAMCrossbar : IUnknown +{ + HRESULT get_PinCounts([out] long *output, [out] long *intput); + HRESULT CanRoute([in] long output, [in] long input); + HRESULT Route([in] long output, [in] long input); + HRESULT get_IsRoutedTo([in] long output, [out] long *input); + HRESULT get_CrossbarPinInfo([in] BOOL is_input, [in] long index, + [out] long *related, [out] long *type); +} + +typedef enum tagAMTunerEventType +{ + AMTUNER_EVENT_CHANGED = 0x0001, +} AMTunerEventType; + +[ + local, + object, + uuid(211a8760-03ac-11d1-8d13-00aa00bd8339), + pointer_default(unique) +] +interface IAMTunerNotification : IUnknown +{ + HRESULT OnEvent([in] AMTunerEventType event); +} + +typedef enum tagAMTunerModeType +{ + AMTUNER_MODE_DEFAULT = 0x0000, + AMTUNER_MODE_TV = 0x0001, + AMTUNER_MODE_FM_RADIO = 0x0002, + AMTUNER_MODE_AM_RADIO = 0x0004, + AMTUNER_MODE_DSS = 0x0008, +} AMTunerModeType; + +[ + local, + object, + uuid(211a8761-03ac-11d1-8d13-00aa00bd8339), + pointer_default(unique) +] +interface IAMTuner : IUnknown +{ + HRESULT put_Channel([in] long channel, [in] long video, [in] long audio); + HRESULT get_Channel([out] long *channel, [out] long *video, [out] long *audio); + HRESULT ChannelMinMax([out] long *min, [out] long *max); + HRESULT put_CountryCode([in] long country); + HRESULT get_CountryCode([out] long *country); + HRESULT put_TuningSpace([in] long tuning_space); + HRESULT get_TuningSpace([out] long *tuning_space); + [local] HRESULT Logon([in] HANDLE user); + HRESULT Logout(); + HRESULT SignalPresent([out] long *signal_strength); + HRESULT put_Mode([in] AMTunerModeType mode); + HRESULT get_Mode([out] AMTunerModeType *mode); + HRESULT GetAvailableModes([out] long *modes); + HRESULT RegisterNotificationCallBack([in] IAMTunerNotification *notify, [in] long events); + HRESULT UnRegisterNotificationCallBack([in] IAMTunerNotification *notify); +} + +[ + local, + object, + uuid(211a8766-03ac-11d1-8d13-00aa00bd8339), + pointer_default(unique) +] +interface IAMTVTuner : IAMTuner +{ + HRESULT get_AvailableTVFormats([out] long *standard); + HRESULT get_TVFormat([out] long *standard); + HRESULT AutoTune([in] long channel, [out] long *signal); + HRESULT StoreAutoTune(); + HRESULT get_NumInputConnections([out] long *number); + HRESULT put_InputType([in] long index, [in] TunerInputType type); + HRESULT get_InputType([in] long index, [out] TunerInputType *type); + HRESULT put_ConnectInput([in] long index); + HRESULT get_ConnectInput([out] long *index); + HRESULT get_VideoFrequency([out] long *freq); + HRESULT get_AudioFrequency([out] long *freq); +} diff -Nru wine-development-5.8/include/basetyps.h wine-development-5.9/include/basetyps.h --- wine-development-5.8/include/basetyps.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/basetyps.h 2020-05-22 18:49:34.000000000 +0000 @@ -26,18 +26,26 @@ # define EXTERN_C extern #endif -#define STDMETHODCALLTYPE WINAPI -#define STDMETHODVCALLTYPE WINAPIV -#define STDAPICALLTYPE WINAPI -#define STDAPIVCALLTYPE WINAPIV -#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE -#define STDAPI_(t) EXTERN_C t STDAPICALLTYPE -#define STDMETHODIMP HRESULT STDMETHODCALLTYPE -#define STDMETHODIMP_(t) t STDMETHODCALLTYPE -#define STDAPIV EXTERN_C HRESULT STDAPIVCALLTYPE -#define STDAPIV_(t) EXTERN_C t STDAPIVCALLTYPE -#define STDMETHODIMPV HRESULT STDMETHODVCALLTYPE -#define STDMETHODIMPV_(t) t STDMETHODVCALLTYPE +#define STDMETHODCALLTYPE WINAPI +#define STDMETHODVCALLTYPE WINAPIV +#define STDAPICALLTYPE WINAPI +#define STDAPIVCALLTYPE WINAPIV +#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE +#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE +#define STDMETHODIMP HRESULT STDMETHODCALLTYPE +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE +#define STDAPIV EXTERN_C HRESULT STDAPIVCALLTYPE +#define STDAPIV_(type) EXTERN_C type STDAPIVCALLTYPE +#define STDMETHODIMPV HRESULT STDMETHODVCALLTYPE +#define STDMETHODIMPV_(type) type STDMETHODVCALLTYPE + +#undef STDMETHOD +#undef STDMETHOD_ +#undef PURE +#undef THIS_ +#undef THIS +#undef DECLARE_INTERFACE +#undef DECLARE_INTERFACE_ #if defined(__cplusplus) && !defined(CINTERFACE) diff -Nru wine-development-5.8/include/ddk/wdm.h wine-development-5.9/include/ddk/wdm.h --- wine-development-5.8/include/ddk/wdm.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/ddk/wdm.h 2020-05-22 18:49:34.000000000 +0000 @@ -1170,52 +1170,107 @@ #define NX_SUPPORT_POLICY_OPTIN 2 #define NX_SUPPORT_POLICY_OPTOUT 3 -#define MAX_WOW64_SHARED_ENTRIES 16 +#define XSTATE_LEGACY_FLOATING_POINT 0 +#define XSTATE_LEGACY_SSE 1 +#define XSTATE_GSSE 2 + +#define XSTATE_MASK_LEGACY_FLOATING_POINT (1 << XSTATE_LEGACY_FLOATING_POINT) +#define XSTATE_MASK_LEGACY_SSE (1 << XSTATE_LEGACY_SSE) +#define XSTATE_MASK_LEGACY (XSTATE_MASK_LEGACY_FLOATING_POINT | XSTATE_MASK_LEGACY_SSE) +#define XSTATE_MASK_GSSE (1 << XSTATE_GSSE) + +#define MAXIMUM_XSTATE_FEATURES 64 + +typedef struct _XSTATE_FEATURE +{ + ULONG Offset; + ULONG Size; +} XSTATE_FEATURE, *PXSTATE_FEATURE; + +typedef struct _XSTATE_CONFIGURATION +{ + ULONG64 EnabledFeatures; + ULONG Size; + ULONG OptimizedSave:1; + XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES]; +} XSTATE_CONFIGURATION, *PXSTATE_CONFIGURATION; typedef struct _KUSER_SHARED_DATA { - ULONG TickCountLowDeprecated; - ULONG TickCountMultiplier; - volatile KSYSTEM_TIME InterruptTime; - volatile KSYSTEM_TIME SystemTime; - volatile KSYSTEM_TIME TimeZoneBias; - USHORT ImageNumberLow; - USHORT ImageNumberHigh; - WCHAR NtSystemRoot[260]; - ULONG MaxStackTraceDepth; - ULONG CryptoExponent; - ULONG TimeZoneId; - ULONG LargePageMinimum; - ULONG Reserved2[7]; - NT_PRODUCT_TYPE NtProductType; - BOOLEAN ProductTypeIsValid; - ULONG NtMajorVersion; - ULONG NtMinorVersion; - BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; - ULONG Reserved1; - ULONG Reserved3; - volatile ULONG TimeSlip; - ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; - LARGE_INTEGER SystemExpirationDate; - ULONG SuiteMask; - BOOLEAN KdDebuggerEnabled; - UCHAR NXSupportPolicy; - volatile ULONG ActiveConsoleId; - volatile ULONG DismountCount; - ULONG ComPlusPackage; - ULONG LastSystemRITEventTickCount; - ULONG NumberOfPhysicalPages; - BOOLEAN SafeBootMode; - ULONG TraceLogging; - ULONGLONG TestRetInstruction; - ULONG SystemCall; - ULONG SystemCallReturn; - ULONGLONG SystemCallPad[3]; + ULONG TickCountLowDeprecated; /* 0x000 */ + ULONG TickCountMultiplier; /* 0x004 */ + volatile KSYSTEM_TIME InterruptTime; /* 0x008 */ + volatile KSYSTEM_TIME SystemTime; /* 0x014 */ + volatile KSYSTEM_TIME TimeZoneBias; /* 0x020 */ + USHORT ImageNumberLow; /* 0x02c */ + USHORT ImageNumberHigh; /* 0x02e */ + WCHAR NtSystemRoot[260]; /* 0x030 */ + ULONG MaxStackTraceDepth; /* 0x238 */ + ULONG CryptoExponent; /* 0x23c */ + ULONG TimeZoneId; /* 0x240 */ + ULONG LargePageMinimum; /* 0x244 */ + ULONG AitSamplingValue; /* 0x248 */ + ULONG AppCompatFlag; /* 0x24c */ + ULONGLONG RNGSeedVersion; /* 0x250 */ + ULONG GlobalValidationRunLevel; /* 0x258 */ + volatile ULONG TimeZoneBiasStamp; /* 0x25c */ + ULONG NtBuildNumber; /* 0x260 */ + NT_PRODUCT_TYPE NtProductType; /* 0x264 */ + BOOLEAN ProductTypeIsValid; /* 0x268 */ + USHORT NativeProcessorArchitecture; /* 0x26a */ + ULONG NtMajorVersion; /* 0x26c */ + ULONG NtMinorVersion; /* 0x270 */ + BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; /* 0x274 */ + ULONG Reserved1; /* 0x2b4 */ + ULONG Reserved3; /* 0x2b8 */ + volatile ULONG TimeSlip; /* 0x2bc */ + ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; /* 0x2c0 */ + ULONG BootId; /* 0x2c4 */ + LARGE_INTEGER SystemExpirationDate; /* 0x2c8 */ + ULONG SuiteMask; /* 0x2d0 */ + BOOLEAN KdDebuggerEnabled; /* 0x2d4 */ + UCHAR NXSupportPolicy; /* 0x2d5 */ + volatile ULONG ActiveConsoleId; /* 0x2d8 */ + volatile ULONG DismountCount; /* 0x2dc */ + ULONG ComPlusPackage; /* 0x2e0 */ + ULONG LastSystemRITEventTickCount; /* 0x2e4 */ + ULONG NumberOfPhysicalPages; /* 0x2e8 */ + BOOLEAN SafeBootMode; /* 0x2ec */ + UCHAR VirtualizationFlags; /* 0x2ed */ + ULONG TraceLogging; /* 0x2f0 */ + ULONGLONG TestRetInstruction; /* 0x2f8 */ + ULONG SystemCall; /* 0x300 */ + ULONG SystemCallReturn; /* 0x304 */ + ULONGLONG SystemCallPad[3]; /* 0x308 */ union { - volatile KSYSTEM_TIME TickCount; + volatile KSYSTEM_TIME TickCount; /* 0x320 */ volatile ULONG64 TickCountQuad; } DUMMYUNIONNAME; - ULONG Cookie; - ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES]; + ULONG Cookie; /* 0x330 */ + LONGLONG ConsoleSessionForegroundProcessId; /* 0x338 */ + ULONGLONG TimeUpdateLock; /* 0x340 */ + ULONGLONG BaselineSystemTimeQpc; /* 0x348 */ + ULONGLONG BaselineInterruptTimeQpc; /* 0x350 */ + ULONGLONG QpcSystemTimeIncrement; /* 0x358 */ + ULONGLONG QpcInterruptTimeIncrement; /* 0x360 */ + UCHAR QpcSystemTimeIncrementShift; /* 0x368 */ + UCHAR QpcInterruptTimeIncrementShift; /* 0x369 */ + USHORT UnparkedProcessorCount; /* 0x36a */ + ULONG EnclaveFeatureMask[4]; /* 0x36c */ + ULONG TelemetryCoverageRound; /* 0x37c */ + USHORT UserModeGlobalLogger[16]; /* 0x380 */ + ULONG HeapTracingPid[2]; /* 0x390 */ + ULONG CritSecTracingPid[2]; /* 0x398 */ + ULONG ImageFileExecutionOptions; /* 0x3a0 */ + ULONG LangGenerationCount; /* 0x3a4 */ + ULONG ActiveProcessorAffinity; /* 0x3a8 */ + volatile ULONGLONG InterruptTimeBias; /* 0x3b0 */ + volatile ULONGLONG QpcBias; /* 0x3b8 */ + ULONG ActiveProcessorCount; /* 0x3c0 */ + volatile UCHAR ActiveGroupCount; /* 0x3c4 */ + USHORT QpcData; /* 0x3c6 */ + LARGE_INTEGER TimeZoneBiasEffectiveStart; /* 0x3c8 */ + LARGE_INTEGER TimeZoneBiasEffectiveEnd; /* 0x3d0 */ + XSTATE_CONFIGURATION XState; /* 0x3d8 */ } KSHARED_USER_DATA, *PKSHARED_USER_DATA; typedef enum _MEMORY_CACHING_TYPE { diff -Nru wine-development-5.8/include/dmusicf.h wine-development-5.9/include/dmusicf.h --- wine-development-5.8/include/dmusicf.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/dmusicf.h 2020-05-22 18:49:34.000000000 +0000 @@ -320,11 +320,6 @@ /***************************************************************************** * Enumerations */ -/* typedef definitions */ -typedef enum enumDMUS_VARIATIONT_TYPES DMUS_VARIATIONT_TYPES; -typedef enum enumDMUS_EMBELLISHT_TYPES DMUS_EMBELLISHT_TYPES; -typedef enum enumDMUS_PATTERNT_TYPES DMUS_PATTERNT_TYPES; - /* actual enumerations */ enum enumDMUS_VARIATIONT_TYPES { DMUS_VARIATIONT_SEQUENTIAL = 0x0, @@ -353,6 +348,10 @@ DMUS_PATTERNT_RANDOM_ROW = 0x5 }; +typedef enum enumDMUS_VARIATIONT_TYPES DMUS_VARIATIONT_TYPES; +typedef enum enumDMUS_EMBELLISHT_TYPES DMUS_EMBELLISHT_TYPES; +typedef enum enumDMUS_PATTERNT_TYPES DMUS_PATTERNT_TYPES; + /***************************************************************************** * Structures diff -Nru wine-development-5.8/include/dpfilter.h wine-development-5.9/include/dpfilter.h --- wine-development-5.8/include/dpfilter.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/include/dpfilter.h 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2020 Zebediah Figura + * + * 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 + */ + +#ifndef __WINE_DPFILTER_H +#define __WINE_DPFILTER_H + +#define DPFLTR_ERROR_LEVEL 0 +#define DPFLTR_WARNING_LEVEL 1 +#define DPFLTR_TRACE_LEVEL 2 +#define DPFLTR_INFO_LEVEL 3 +#define DPFLTR_MASK 0x8000000 + +typedef enum _DPFLTR_TYPE +{ + DPFLTR_SYSTEM_ID = 0, + DPFLTR_SMSS_ID = 1, + DPFLTR_SETUP_ID = 2, + DPFLTR_NTFS_ID = 3, + DPFLTR_FSTUB_ID = 4, + DPFLTR_CRASHDUMP_ID = 5, + DPFLTR_CDAUDIO_ID = 6, + DPFLTR_CDROM_ID = 7, + DPFLTR_CLASSPNP_ID = 8, + DPFLTR_DISK_ID = 9, + DPFLTR_REDBOOK_ID = 10, + DPFLTR_STORPROP_ID = 11, + DPFLTR_SCSIPORT_ID = 12, + DPFLTR_SCSIMINIPORT_ID = 13, + DPFLTR_CONFIG_ID = 14, + DPFLTR_I8042PRT_ID = 15, + DPFLTR_SERMOUSE_ID = 16, + DPFLTR_LSERMOUS_ID = 17, + DPFLTR_KBDHID_ID = 18, + DPFLTR_MOUHID_ID = 19, + DPFLTR_KBDCLASS_ID = 20, + DPFLTR_MOUCLASS_ID = 21, + DPFLTR_TWOTRACK_ID = 22, + DPFLTR_WMILIB_ID = 23, + DPFLTR_ACPI_ID = 24, + DPFLTR_AMLI_ID = 25, + DPFLTR_HALIA64_ID = 26, + DPFLTR_VIDEO_ID = 27, + DPFLTR_SVCHOST_ID = 28, + DPFLTR_VIDEOPRT_ID = 29, + DPFLTR_TCPIP_ID = 30, + DPFLTR_DMSYNTH_ID = 31, + DPFLTR_NTOSPNP_ID = 32, + DPFLTR_FASTFAT_ID = 33, + DPFLTR_SAMSS_ID = 34, + DPFLTR_PNPMGR_ID = 35, + DPFLTR_NETAPI_ID = 36, + DPFLTR_SCSERVER_ID = 37, + DPFLTR_SCCLIENT_ID = 38, + DPFLTR_SERIAL_ID = 39, + DPFLTR_SERENUM_ID = 40, + DPFLTR_UHCD_ID = 41, + DPFLTR_RPCPROXY_ID = 42, + DPFLTR_AUTOCHK_ID = 43, + DPFLTR_DCOMSS_ID = 44, + DPFLTR_UNIMODEM_ID = 45, + DPFLTR_SIS_ID = 46, + DPFLTR_FLTMGR_ID = 47, + DPFLTR_WMICORE_ID = 48, + DPFLTR_BURNENG_ID = 49, + DPFLTR_IMAPI_ID = 50, + DPFLTR_SXS_ID = 51, + DPFLTR_FUSION_ID = 52, + DPFLTR_IDLETASK_ID = 53, + DPFLTR_SOFTPCI_ID = 54, + DPFLTR_TAPE_ID = 55, + DPFLTR_MCHGR_ID = 56, + DPFLTR_IDEP_ID = 57, + DPFLTR_PCIIDE_ID = 58, + DPFLTR_FLOPPY_ID = 59, + DPFLTR_FDC_ID = 60, + DPFLTR_TERMSRV_ID = 61, + DPFLTR_W32TIME_ID = 62, + DPFLTR_PREFETCHER_ID = 63, + DPFLTR_RSFILTER_ID = 64, + DPFLTR_FCPORT_ID = 65, + DPFLTR_PCI_ID = 66, + DPFLTR_DMIO_ID = 67, + DPFLTR_DMCONFIG_ID = 68, + DPFLTR_DMADMIN_ID = 69, + DPFLTR_WSOCKTRANSPORT_ID = 70, + DPFLTR_VSS_ID = 71, + DPFLTR_PNPMEM_ID = 72, + DPFLTR_PROCESSOR_ID = 73, + DPFLTR_DMSERVER_ID = 74, + DPFLTR_SR_ID = 75, + DPFLTR_INFINIBAND_ID = 76, + DPFLTR_IHVDRIVER_ID = 77, + DPFLTR_IHVVIDEO_ID = 78, + DPFLTR_IHVAUDIO_ID = 79, + DPFLTR_IHVNETWORK_ID = 80, + DPFLTR_IHVSTREAMING_ID = 81, + DPFLTR_IHVBUS_ID = 82, + DPFLTR_HPS_ID = 83, + DPFLTR_RTLTHREADPOOL_ID = 84, + DPFLTR_LDR_ID = 85, + DPFLTR_TCPIP6_ID = 86, + DPFLTR_ISAPNP_ID = 87, + DPFLTR_SHPC_ID = 88, + DPFLTR_STORPORT_ID = 89, + DPFLTR_STORMINIPORT_ID = 90, + DPFLTR_PRINTSPOOLER_ID = 91, + DPFLTR_VSSDYNDISK_ID = 92, + DPFLTR_VERIFIER_ID = 93, + DPFLTR_VDS_ID = 94, + DPFLTR_VDSBAS_ID = 95, + DPFLTR_VDSDYN_ID = 96, + DPFLTR_VDSDYNDR_ID = 97, + DPFLTR_VDSLDR_ID = 98, + DPFLTR_VDSUTIL_ID = 99, + DPFLTR_DFRGIFC_ID = 100, + DPFLTR_DEFAULT_ID = 101, + DPFLTR_MM_ID = 102, + DPFLTR_DFSC_ID = 103, + DPFLTR_WOW64_ID = 104, + DPFLTR_ALPC_ID = 105, + DPFLTR_WDI_ID = 106, + DPFLTR_PERFLIB_ID = 107, + DPFLTR_KTM_ID = 108, + DPFLTR_IOSTRESS_ID = 109, + DPFLTR_HEAP_ID = 110, + DPFLTR_WHEA_ID = 111, + DPFLTR_USERGDI_ID = 112, + DPFLTR_MMCSS_ID = 113, + DPFLTR_TPM_ID = 114, + DPFLTR_THREADORDER_ID = 115, + DPFLTR_ENVIRON_ID = 116, + DPFLTR_EMS_ID = 117, + DPFLTR_WDT_ID = 118, + DPFLTR_FVEVOL_ID = 119, + DPFLTR_NDIS_ID = 120, + DPFLTR_NVCTRACE_ID = 121, + DPFLTR_LUAFV_ID = 122, + DPFLTR_APPCOMPAT_ID = 123, + DPFLTR_USBSTOR_ID = 124, + DPFLTR_SBP2PORT_ID = 125, + DPFLTR_COVERAGE_ID = 126, + DPFLTR_CACHEMGR_ID = 127, + DPFLTR_MOUNTMGR_ID = 128, + DPFLTR_CFR_ID = 129, + DPFLTR_TXF_ID = 130, + DPFLTR_KSECDD_ID = 131, + DPFLTR_FLTREGRESS_ID = 132, + DPFLTR_MPIO_ID = 133, + DPFLTR_MSDSM_ID = 134, + DPFLTR_UDFS_ID = 135, + DPFLTR_PSHED_ID = 136, + DPFLTR_STORVSP_ID = 137, + DPFLTR_LSASS_ID = 138, + DPFLTR_SSPICLI_ID = 139, + DPFLTR_CNG_ID = 140, + DPFLTR_EXFAT_ID = 141, + DPFLTR_FILETRACE_ID = 142, + DPFLTR_XSAVE_ID = 143, + DPFLTR_SE_ID = 144, + DPFLTR_DRIVEEXTENDER_ID = 145, + DPFLTR_POWER_ID = 146, + DPFLTR_CRASHDUMPXHCI_ID = 147, + DPFLTR_GPIO_ID = 148, + DPFLTR_REFS_ID = 149, + DPFLTR_WER_ID = 150, + DPFLTR_CAPIMG_ID = 151, + DPFLTR_VPCI_ID = 152, + DPFLTR_STORAGECLASSMEMORY_ID = 153, + DPFLTR_FSLIB_ID = 154, + DPFLTR_ENDOFTABLE_ID +} DPFLTR_TYPE; + +#endif diff -Nru wine-development-5.8/include/dwrite_1.idl wine-development-5.9/include/dwrite_1.idl --- wine-development-5.8/include/dwrite_1.idl 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/dwrite_1.idl 2020-05-22 18:49:34.000000000 +0000 @@ -114,7 +114,7 @@ DWRITE_PANOSE_STROKE_VARIATION_RAPID_HORIZONTAL, DWRITE_PANOSE_STROKE_VARIATION_INSTANT_VERTICAL, DWRITE_PANOSE_STROKE_VARIATION_INSTANT_HORIZONTAL -} DWRITE_PANOSE_STROKE_VARIANTION; +} DWRITE_PANOSE_STROKE_VARIATION; typedef enum DWRITE_PANOSE_ARM_STYLE { diff -Nru wine-development-5.8/include/dwrite.idl wine-development-5.9/include/dwrite.idl --- wine-development-5.8/include/dwrite.idl 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/dwrite.idl 2020-05-22 18:49:34.000000000 +0000 @@ -138,7 +138,7 @@ DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG, DWRITE_INFORMATIONAL_STRING_PREFERRED_FAMILY_NAMES = DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_FAMILY_NAMES, DWRITE_INFORMATIONAL_STRING_PREFERRED_SUBFAMILY_NAMES = DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_SUBFAMILY_NAMES, - DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAMES = DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME, + DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME = DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME, } DWRITE_INFORMATIONAL_STRING_ID; typedef enum DWRITE_FONT_SIMULATIONS diff -Nru wine-development-5.8/include/dxgi1_6.idl wine-development-5.9/include/dxgi1_6.idl --- wine-development-5.8/include/dxgi1_6.idl 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/dxgi1_6.idl 2020-05-22 18:49:34.000000000 +0000 @@ -34,6 +34,13 @@ DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_CURSOR_STRETCHED = 0x4, } DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAGS; +typedef enum DXGI_GPU_PREFERENCE +{ + DXGI_GPU_PREFERENCE_UNSPECIFIED = 0x0, + DXGI_GPU_PREFERENCE_MINIMUM_POWER = 0x1, + DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE = 0x2, +} DXGI_GPU_PREFERENCE; + typedef struct DXGI_ADAPTER_DESC3 { WCHAR Description[128]; @@ -96,3 +103,36 @@ [out] UINT *flags ); } + +[ + object, + uuid(c1b6694f-ff09-44a9-b03c-77900a0a1d17), + local, + pointer_default(unique) +] +interface IDXGIFactory6 : IDXGIFactory5 +{ + HRESULT EnumAdapterByGpuPreference( + [in] UINT adapter_idx, + [in] DXGI_GPU_PREFERENCE gpu_preference, + [in] REFIID iid, + [out] void **adapter + ); +} + +[ + object, + uuid(a4966eed-76db-44da-84c1-ee9a7afb20a8), + local, + pointer_default(unique) +] +interface IDXGIFactory7 : IDXGIFactory6 +{ + HRESULT RegisterAdaptersChangedEvent( + [in] HANDLE event, + [out] DWORD *cookie + ); + HRESULT UnregisterAdaptersChangedEvent( + [in] DWORD cookie + ); +} diff -Nru wine-development-5.8/include/exposeenums2managed.h wine-development-5.9/include/exposeenums2managed.h --- wine-development-5.8/include/exposeenums2managed.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/include/exposeenums2managed.h 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Copyright 2020 Jactry Zeng 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 + */ + +#ifdef MANAGED_ENUMS + +#define TAG(x) x +#define ENUM16 ENUM + +#else /* MANAGED_ENUMS */ + +#define TAG(x) tag##x +#define ENUM16 typedef enum + +#endif /* MANAGED_ENUMS */ diff -Nru wine-development-5.8/include/gdiplusenums.h wine-development-5.9/include/gdiplusenums.h --- wine-development-5.8/include/gdiplusenums.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/gdiplusenums.h 2020-05-22 18:49:34.000000000 +0000 @@ -784,7 +784,6 @@ typedef enum StringFormatFlags StringFormatFlags; typedef enum HotkeyPrefix HotkeyPrefix; typedef enum PenAlignment PenAlignment; -typedef enum PaletteFlags PaletteFlags; typedef enum ImageCodecFlags ImageCodecFlags; typedef enum EncoderParameterValueType EncoderParameterValueType; typedef enum EncoderValue EncoderValue; diff -Nru wine-development-5.8/include/gdiplusflat.h wine-development-5.9/include/gdiplusflat.h --- wine-development-5.8/include/gdiplusflat.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/gdiplusflat.h 2020-05-22 18:49:34.000000000 +0000 @@ -545,6 +545,7 @@ GpMetafile**); GpStatus WINGDIPAPI GdipCreateMetafileFromFile(GDIPCONST WCHAR*,GpMetafile**); GpStatus WINGDIPAPI GdipCreateMetafileFromStream(IStream*,GpMetafile**); +GpStatus WINGDIPAPI GdipGetMetafileDownLevelRasterizationLimit(GDIPCONST GpMetafile*,UINT*); GpStatus WINGDIPAPI GdipGetHemfFromMetafile(GpMetafile*,HENHMETAFILE*); GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile*,EmfPlusRecordType,UINT,UINT,GDIPCONST BYTE*); GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpMetafile*,UINT); diff -Nru wine-development-5.8/include/hidusage.h wine-development-5.9/include/hidusage.h --- wine-development-5.8/include/hidusage.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/hidusage.h 2020-05-22 18:49:34.000000000 +0000 @@ -200,7 +200,7 @@ #define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA) #define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB) -#define HID_USAGE_SIMULATION_ACCELLERATOR ((USAGE) 0xC4) +#define HID_USAGE_SIMULATION_ACCELERATOR ((USAGE) 0xC4) #define HID_USAGE_SIMULATION_BRAKE ((USAGE) 0xC5) #define HID_USAGE_SIMULATION_STEERING ((USAGE) 0xC8) diff -Nru wine-development-5.8/include/ip2string.h wine-development-5.9/include/ip2string.h --- wine-development-5.8/include/ip2string.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/ip2string.h 2020-05-22 18:49:34.000000000 +0000 @@ -30,6 +30,13 @@ NTSTATUS WINAPI RtlIpv4StringToAddressExW(const WCHAR *str, BOOLEAN strict, IN_ADDR *address, USHORT *port); #define RtlIpv4StringToAddressEx WINELIB_NAME_AW(RtlIpv4StringToAddressEx) +NTSTATUS WINAPI RtlIpv6StringToAddressA(const char *str, const char **terminator, IN6_ADDR *address); +NTSTATUS WINAPI RtlIpv6StringToAddressW(const WCHAR *str, const WCHAR **terminator, IN6_ADDR *address); +#define RtlIpv6StringToAddress WINELIB_NAME_AW(RtlIpv6StringToAddress) +NTSTATUS WINAPI RtlIpv6StringToAddressExA(const char *str, IN6_ADDR *address, ULONG *scope, USHORT *port); +NTSTATUS WINAPI RtlIpv6StringToAddressExW(const WCHAR *str, IN6_ADDR *address, ULONG *scope, USHORT *port); +#define RtlIpv6StringToAddressEx WINELIB_NAME_AW(RtlIpv6StringToAddressEx) + #ifdef __cplusplus } #endif diff -Nru wine-development-5.8/include/Makefile.in wine-development-5.9/include/Makefile.in --- wine-development-5.8/include/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -18,6 +18,7 @@ appcompatapi.h \ appmgmt.h \ appmodel.h \ + asferr.h \ asptlb.idl \ asynot.idl \ asysta.idl \ @@ -36,6 +37,7 @@ avrt.h \ axcore.idl \ axextend.idl \ + axextendenums.h \ basetsd.h \ basetyps.h \ bcrypt.h \ @@ -226,6 +228,7 @@ docobjectservice.idl \ downloadmgr.idl \ dpaddr.h \ + dpfilter.h \ dplay.h \ dplay8.h \ dplobby.h \ @@ -274,6 +277,7 @@ excpt.h \ exdisp.idl \ exdispid.h \ + exposeenums2managed.h \ fci.h \ fdi.h \ fileapi.h \ @@ -678,6 +682,7 @@ uiautomationcore.idl \ uiautomationcoreapi.h \ uiribbon.idl \ + unexposeenums2managed.h \ unknwn.idl \ urlhist.idl \ urlmon.idl \ @@ -710,6 +715,7 @@ wia_xp.idl \ wiadef.h \ wimgapi.h \ + winapifamily.h \ winbase.h \ wincodec.idl \ wincodecsdk.idl \ diff -Nru wine-development-5.8/include/mfapi.h wine-development-5.9/include/mfapi.h --- wine-development-5.8/include/mfapi.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/mfapi.h 2020-05-22 18:49:34.000000000 +0000 @@ -535,6 +535,7 @@ HRESULT WINAPI MFInitMediaTypeFromWaveFormatEx(IMFMediaType *mediatype, const WAVEFORMATEX *format, UINT32 size); HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result); HRESULT WINAPI MFLockPlatform(void); +HRESULT WINAPI MFPutWaitingWorkItem(HANDLE event, LONG priority, IMFAsyncResult *result, MFWORKITEM_KEY *key); HRESULT WINAPI MFPutWorkItem(DWORD queue, IMFAsyncCallback *callback, IUnknown *state); HRESULT WINAPI MFPutWorkItem2(DWORD queue, LONG priority, IMFAsyncCallback *callback, IUnknown *state); HRESULT WINAPI MFPutWorkItemEx(DWORD queue, IMFAsyncResult *result); diff -Nru wine-development-5.8/include/mfidl.idl wine-development-5.9/include/mfidl.idl --- wine-development-5.8/include/mfidl.idl 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/mfidl.idl 2020-05-22 18:49:34.000000000 +0000 @@ -230,6 +230,29 @@ HRESULT GetOutputNodeCollection([out] IMFCollection **collection); } +typedef struct _MFTOPONODE_ATTRIBUTE_UPDATE +{ + TOPOID NodeId; + GUID guidAttributeKey; + MF_ATTRIBUTE_TYPE attrType; + [switch_type(DWORD), switch_is(attrType)] union + { + [case(MF_ATTRIBUTE_UINT32)] UINT32 u32; + [case(MF_ATTRIBUTE_UINT64)] UINT64 u64; + [case(MF_ATTRIBUTE_DOUBLE)] double d; + }; +} MFTOPONODE_ATTRIBUTE_UPDATE; + +[ + object, + uuid(676aa6dd-238a-410d-bb99-65668d01605a), +] +interface IMFTopologyNodeAttributeEditor : IUnknown +{ + HRESULT UpdateNodeAttributes([in] TOPOID id, [in] DWORD count, + [in, size_is(count)] MFTOPONODE_ATTRIBUTE_UPDATE *attr_updates); +} + [ object, uuid(de9a6157-f660-4643-b56a-df9f7998c7cd), @@ -1104,6 +1127,7 @@ cpp_quote("EXTERN_GUID(MF_RATE_CONTROL_SERVICE, 0x866fa297, 0xb802, 0x4bf8, 0x9d, 0xc9, 0x5e, 0x3b, 0x6a, 0x9f, 0x53, 0xc9);") cpp_quote("EXTERN_GUID(MF_LOCAL_MFT_REGISTRATION_SERVICE, 0xddf5cf9c, 0x4506, 0x45aa, 0xab, 0xf0, 0x6d, 0x5d, 0x94, 0xdd, 0x1b, 0x4a);") cpp_quote("EXTERN_C const GUID MF_SCRUBBING_SERVICE;") +cpp_quote("EXTERN_GUID(MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, 0x65656e1a, 0x077f, 0x4472, 0x83, 0xef, 0x31, 0x6f, 0x11, 0xd5, 0x08, 0x7a);") cpp_quote("EXTERN_GUID(MR_POLICY_VOLUME_SERVICE, 0x1abaa2ac, 0x9d3b, 0x47c6, 0xab, 0x48, 0xc5, 0x95, 0x06, 0xde, 0x78, 0x4d);") cpp_quote("EXTERN_GUID(MR_CAPTURE_POLICY_VOLUME_SERVICE, 0x24030acd, 0x107a, 0x4265, 0x97, 0x5c, 0x41, 0x4e, 0x33, 0xe6, 0x5f, 0x2a);") cpp_quote("EXTERN_GUID(MR_STREAM_VOLUME_SERVICE, 0xf8b5fa2f, 0x32ef, 0x46f5, 0xb1, 0x72, 0x13, 0x21, 0x21, 0x2f, 0xb2, 0xc4);") diff -Nru wine-development-5.8/include/msvcrt/corecrt.h wine-development-5.9/include/msvcrt/corecrt.h --- wine-development-5.8/include/msvcrt/corecrt.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/msvcrt/corecrt.h 2020-05-22 18:49:34.000000000 +0000 @@ -33,6 +33,14 @@ #define _WIN64 #endif +#ifndef _MSVCR_VER +# define _MSVCR_VER 140 +#endif + +#if !defined(_UCRT) && _MSVCR_VER >= 140 +# define _UCRT +#endif + #if !defined(_MSC_VER) && !defined(__int64) # if defined(_WIN64) && !defined(__MINGW64__) # define __int64 long diff -Nru wine-development-5.8/include/msvcrt/math.h wine-development-5.9/include/msvcrt/math.h --- wine-development-5.8/include/msvcrt/math.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/msvcrt/math.h 2020-05-22 18:49:34.000000000 +0000 @@ -101,6 +101,9 @@ long __cdecl lround(double); long __cdecl lroundf(float); +_ACRTIMP double __cdecl scalbn(double,int); +_ACRTIMP float __cdecl scalbnf(float,int); + double __cdecl _copysign (double, double); double __cdecl _chgsign (double); double __cdecl _scalb(double, __msvcrt_long); @@ -182,8 +185,13 @@ static inline float ldexpf(float x, int y) { return ldexp(x, y); } +#ifdef _UCRT +_ACRTIMP double __cdecl copysign(double, double); +_ACRTIMP float __cdecl copysignf(float, float); +#else #define copysign(x,y) _copysign(x,y) #define copysignf(x,y) _copysignf(x,y) +#endif double __cdecl nearbyint(double); float __cdecl nearbyintf(float); diff -Nru wine-development-5.8/include/msvcrt/stdlib.h wine-development-5.9/include/msvcrt/stdlib.h --- wine-development-5.8/include/msvcrt/stdlib.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/msvcrt/stdlib.h 2020-05-22 18:49:34.000000000 +0000 @@ -175,7 +175,6 @@ void __cdecl _seterrormode(int); void __cdecl _sleep(__msvcrt_ulong); void __cdecl _splitpath(const char*,char*,char*,char*,char*); -long double __cdecl _strtold(const char*,char**); void __cdecl _swab(char*,char*,int); char* __cdecl _ui64toa(unsigned __int64,char*,int); errno_t __cdecl _ui64toa_s(unsigned __int64,char*,size_t,int); @@ -212,7 +211,6 @@ void __cdecl srand(unsigned int); float __cdecl strtof(const char*,char**); double __cdecl strtod(const char*,char**); -double __cdecl strtold(const char*,char**); __msvcrt_long __cdecl strtol(const char*,char**,int); __msvcrt_ulong __cdecl strtoul(const char*,char**,int); __int64 __cdecl strtoll_l(const char*,char**,int,_locale_t); @@ -233,6 +231,11 @@ void __cdecl _invalid_parameter(const wchar_t *expr, const wchar_t *func, const wchar_t *file, unsigned int line, uintptr_t arg); +#ifdef _UCRT +_ACRTIMP double __cdecl _strtold_l(const char*,char**,_locale_t); +static inline long double strtold(const char *string, char **endptr) { return _strtold_l(string, endptr, NULL); } +#endif /* _UCRT */ + #ifdef __cplusplus } #endif diff -Nru wine-development-5.8/include/netioapi.h wine-development-5.9/include/netioapi.h --- wine-development-5.8/include/netioapi.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/netioapi.h 2020-05-22 18:49:34.000000000 +0000 @@ -236,6 +236,8 @@ typedef VOID (WINAPI *PUNICAST_IPADDRESS_CHANGE_CALLBACK)(PVOID, PMIB_UNICASTIPADDRESS_ROW, MIB_NOTIFICATION_TYPE); +typedef VOID (WINAPI *PIPFORWARD_CHANGE_CALLBACK)(VOID*,MIB_IPFORWARD_ROW2*,MIB_NOTIFICATION_TYPE); + DWORD WINAPI ConvertInterfaceGuidToLuid(const GUID*,NET_LUID*); DWORD WINAPI ConvertInterfaceIndexToLuid(NET_IFINDEX,NET_LUID*); DWORD WINAPI ConvertInterfaceLuidToGuid(const NET_LUID*,GUID*); diff -Nru wine-development-5.8/include/objbase.h wine-development-5.9/include/objbase.h --- wine-development-5.8/include/objbase.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/objbase.h 2020-05-22 18:49:34.000000000 +0000 @@ -170,6 +170,14 @@ * macro is defined in which case we would not be here. */ +#undef STDMETHOD +#undef STDMETHOD_ +#undef PURE +#undef THIS_ +#undef THIS +#undef DECLARE_INTERFACE +#undef DECLARE_INTERFACE_ + #if defined(__cplusplus) && !defined(CINTERFACE) #ifdef COM_STDMETHOD_CAN_THROW diff -Nru wine-development-5.8/include/oleacc.idl wine-development-5.9/include/oleacc.idl --- wine-development-5.8/include/oleacc.idl 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/oleacc.idl 2020-05-22 18:49:34.000000000 +0000 @@ -16,6 +16,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#if 0 +#pragma makedep install +#pragma makedep typelib +#pragma makedep header +#endif + import "oaidl.idl"; #ifndef __WIDL__ diff -Nru wine-development-5.8/include/setupapi.h wine-development-5.9/include/setupapi.h --- wine-development-5.8/include/setupapi.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/setupapi.h 2020-05-22 18:49:34.000000000 +0000 @@ -1516,8 +1516,8 @@ BOOL WINAPI SetupDiGetActualSectionToInstallA(HINF, PCSTR, PSTR, DWORD, PDWORD, PSTR *); BOOL WINAPI SetupDiGetActualSectionToInstallW(HINF, PCWSTR, PWSTR, DWORD, PDWORD, PWSTR *); #define SetupDiGetActualSectionToInstall WINELIB_NAME_AW(SetupDiGetActualSectionToInstall) -BOOL WINAPI SetupDiGetActualSectionToInstallExA(HINF, PCSTR, PSTR, DWORD, PDWORD, PSTR *, PVOID); -BOOL WINAPI SetupDiGetActualSectionToInstallExW(HINF, PCWSTR, PWSTR, DWORD, PDWORD, PWSTR *, PVOID); +BOOL WINAPI SetupDiGetActualSectionToInstallExA(HINF, PCSTR, PSP_ALTPLATFORM_INFO, PSTR, DWORD, PDWORD, PSTR *, PVOID); +BOOL WINAPI SetupDiGetActualSectionToInstallExW(HINF, PCWSTR, PSP_ALTPLATFORM_INFO, PWSTR, DWORD, PDWORD, PWSTR *, PVOID); #define SetupDiGetActualSectionToInstallEx WINELIB_NAME_AW(SetupDiGetActualSectionToInstallEx) BOOL WINAPI SetupDiGetClassBitmapIndex(const GUID *, PINT); BOOL WINAPI SetupDiGetClassDescriptionA(const GUID*, PSTR, DWORD, PDWORD); diff -Nru wine-development-5.8/include/unexposeenums2managed.h wine-development-5.9/include/unexposeenums2managed.h --- wine-development-5.8/include/unexposeenums2managed.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/include/unexposeenums2managed.h 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,20 @@ +/* + * Copyright 2020 Jactry Zeng 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 + */ + +#undef ENUM16 +#undef TAG diff -Nru wine-development-5.8/include/winapifamily.h wine-development-5.9/include/winapifamily.h --- wine-development-5.8/include/winapifamily.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-development-5.9/include/winapifamily.h 2020-05-22 18:49:34.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright 2020 Jacek Caban 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 + */ + +#ifndef _INC_WINAPIFAMILY +#define _INC_WINAPIFAMILY + +#define WINAPI_FAMILY_PC_APP 2 +#define WINAPI_FAMILY_PHONE_APP 3 +#define WINAPI_FAMILY_SYSTEM 4 +#define WINAPI_FAMILY_SERVER 5 +#define WINAPI_FAMILY_DESKTOP_APP 100 + +#define WINAPI_FAMILY_APP WINAPI_FAMILY_PC_APP + +#ifndef WINAPI_FAMILY +#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP +#endif + +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) +#endif + +#ifndef WINAPI_PARTITION_APP +#define WINAPI_PARTITION_APP (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP || \ + WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || \ + WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) +#endif + +#ifndef WINAPI_PARTITION_PC_APP +#define WINAPI_PARTITION_PC_APP (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP || \ + WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) +#endif + +#ifndef WINAPI_PARTITION_PHONE_APP +#define WINAPI_PARTITION_PHONE_APP (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) +#endif + +#ifndef WINAPI_PARTITION_SYSTEM +#define WINAPI_PARTITION_SYSTEM (WINAPI_FAMILY == WINAPI_FAMILY_SYSTEM || \ + WINAPI_FAMILY == WINAPI_FAMILY_SERVER) +#endif + +#define WINAPI_PARTITION_PHONE WINAPI_PARTITION_PHONE_APP + +#define WINAPI_FAMILY_PARTITION(x) x + +#endif /* _INC_WINAPIFAMILY */ diff -Nru wine-development-5.8/include/wine/test.h wine-development-5.9/include/wine/test.h --- wine-development-5.8/include/wine/test.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/wine/test.h 2020-05-22 18:49:34.000000000 +0000 @@ -44,15 +44,6 @@ #define INVALID_SET_FILE_POINTER (~0u) #endif -#ifdef _MSC_VER -# ifndef INFINITY -# define INFINITY ((float)HUGE_VAL) -# endif -# ifndef NAN -# define NAN (INFINITY * 0.0f) -# endif -#endif - /* debug level */ extern int winetest_debug; diff -Nru wine-development-5.8/include/wine/wined3d.h wine-development-5.9/include/wine/wined3d.h --- wine-development-5.8/include/wine/wined3d.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/wine/wined3d.h 2020-05-22 18:49:34.000000000 +0000 @@ -1756,6 +1756,7 @@ struct wined3d_swapchain_desc { + struct wined3d_output *output; unsigned int backbuffer_width; unsigned int backbuffer_height; enum wined3d_format_id backbuffer_format; @@ -2020,7 +2021,7 @@ { BOOL alpha_to_coverage; BOOL independent; - struct + struct wined3d_rendertarget_blend_state_desc { BOOL enable; enum wined3d_blend src; @@ -2333,6 +2334,7 @@ struct wined3d_buffer *buffer, unsigned int offset); HRESULT __cdecl wined3d_device_end_scene(struct wined3d_device *device); void __cdecl wined3d_device_evict_managed_resources(struct wined3d_device *device); +void __cdecl wined3d_device_flush(struct wined3d_device *device); UINT __cdecl wined3d_device_get_available_texture_mem(const struct wined3d_device *device); struct wined3d_blend_state * __cdecl wined3d_device_get_blend_state(const struct wined3d_device *device, struct wined3d_color *blend_factor); @@ -2768,13 +2770,12 @@ void __cdecl wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWND window); HRESULT __cdecl wined3d_swapchain_state_create(const struct wined3d_swapchain_desc *desc, - HWND window, struct wined3d *wined3d, struct wined3d_swapchain_state **state); + HWND window, struct wined3d_swapchain_state **state); void __cdecl wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *state); HRESULT __cdecl wined3d_swapchain_state_resize_target(struct wined3d_swapchain_state *state, - struct wined3d_output *output, const struct wined3d_display_mode *mode); -HRESULT __cdecl wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_state *state, - const struct wined3d_swapchain_desc *desc, struct wined3d_output *output, const struct wined3d_display_mode *mode); +HRESULT __cdecl wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_state *state, + const struct wined3d_swapchain_desc *desc, const struct wined3d_display_mode *mode); HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture, UINT layer, const struct wined3d_box *dirty_region); diff -Nru wine-development-5.8/include/wine/winedxgi.idl wine-development-5.9/include/wine/winedxgi.idl --- wine-development-5.8/include/wine/winedxgi.idl 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/wine/winedxgi.idl 2020-05-22 18:49:34.000000000 +0000 @@ -89,6 +89,6 @@ local, uuid(ea02a0d1-4c95-488a-a82c-6034621e8c4f) ] -interface IWineDXGIFactory : IDXGIFactory5 +interface IWineDXGIFactory : IDXGIFactory7 { } diff -Nru wine-development-5.8/include/winnls.h wine-development-5.9/include/winnls.h --- wine-development-5.8/include/winnls.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/winnls.h 2020-05-22 18:49:34.000000000 +0000 @@ -938,6 +938,7 @@ WINBASEAPI LCID WINAPI GetThreadLocale(void); WINBASEAPI BOOL WINAPI GetThreadPreferredUILanguages(DWORD,ULONG*,WCHAR*,ULONG*); WINBASEAPI LANGID WINAPI GetThreadUILanguage(void); +WINBASEAPI BOOL WINAPI GetUserPreferredUILanguages(DWORD,ULONG*,WCHAR*,ULONG*); WINBASEAPI INT WINAPI GetTimeFormatA(LCID,DWORD,const SYSTEMTIME*,LPCSTR,LPSTR,INT); WINBASEAPI INT WINAPI GetTimeFormatEx(LPCWSTR,DWORD,const SYSTEMTIME*,LPCWSTR,LPWSTR,INT); WINBASEAPI INT WINAPI GetTimeFormatW(LCID,DWORD,const SYSTEMTIME*,LPCWSTR,LPWSTR,INT); @@ -973,7 +974,9 @@ WINBASEAPI BOOL WINAPI SetLocaleInfoA(LCID,LCTYPE,LPCSTR); WINBASEAPI BOOL WINAPI SetLocaleInfoW(LCID,LCTYPE,LPCWSTR); #define SetLocaleInfo WINELIB_NAME_AW(SetLocaleInfo) +WINBASEAPI BOOL WINAPI SetProcessPreferredUILanguages(DWORD,PCZZWSTR,PULONG); WINBASEAPI BOOL WINAPI SetThreadLocale(LCID); +WINBASEAPI BOOL WINAPI SetThreadPreferredUILanguages(DWORD,PCZZWSTR,PULONG); WINBASEAPI LANGID WINAPI SetThreadUILanguage(LANGID); WINBASEAPI BOOL WINAPI SetUserGeoID(GEOID); WINBASEAPI INT WINAPI WideCharToMultiByte(UINT,DWORD,LPCWSTR,INT,LPSTR,INT,LPCSTR,LPBOOL); diff -Nru wine-development-5.8/include/winnt.h wine-development-5.9/include/winnt.h --- wine-development-5.8/include/winnt.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/winnt.h 2020-05-22 18:49:34.000000000 +0000 @@ -23,6 +23,7 @@ #include #include +#include #ifndef RC_INVOKED #include @@ -796,6 +797,7 @@ #define CONTAINING_RECORD(address, type, field) \ ((type *)((PCHAR)(address) - offsetof(type, field))) +#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) #ifdef __WINESRC__ # define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif @@ -922,6 +924,10 @@ #define PF_ARM_V8_INSTRUCTIONS_AVAILABLE 29 #define PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE 30 #define PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE 31 +#define PF_RDTSCP_INSTRUCTION_AVAILABLE 32 +#define PF_RDPID_INSTRUCTION_AVAILABLE 33 +#define PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE 34 +#define PF_MONITORX_INSTRUCTION_AVAILABLE 35 /* Execution state flags */ diff -Nru wine-development-5.8/include/winternl.h wine-development-5.9/include/winternl.h --- wine-development-5.8/include/winternl.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/winternl.h 2020-05-22 18:49:34.000000000 +0000 @@ -1368,6 +1368,21 @@ #define CPU_FEATURE_SSE2 0x00010000 /* SSE2 extensions (XMMI64) */ #define CPU_FEATURE_DS 0x00020000 /* Debug Store */ #define CPU_FEATURE_HTT 0x00040000 /* Hyper Threading Technology */ +#define CPU_FEATURE_SSE3 0x00080000 /* SSE3 extensions */ +#define CPU_FEATURE_CX128 0x00100000 /* cmpxchg16b instruction */ +#define CPU_FEATURE_XSAVE 0x00800000 /* XSAVE instructions */ +#define CPU_FEATURE_2NDLEV 0x04000000 /* Second-level address translation */ +#define CPU_FEATURE_VIRT 0x08000000 /* Virtualization support */ +#define CPU_FEATURE_RDFS 0x10000000 /* RDFSBASE etc. instructions */ +#define CPU_FEATURE_NX 0x20000000 /* Data execution prevention */ + +/* FIXME: following values are made up, actual flags are unknown */ +#define CPU_FEATURE_PAE 0x00200000 +#define CPU_FEATURE_DAZ 0x00400000 +#define CPU_FEATURE_ARM_VFP_32 0x00000001 +#define CPU_FEATURE_ARM_NEON 0x00000002 +#define CPU_FEATURE_ARM_V8_CRC32 0x00000004 +#define CPU_FEATURE_ARM_V8_CRYPTO 0x00000008 /* System Information Class 0x02 */ @@ -1609,6 +1624,12 @@ PVOID Reserved1; } SYSTEM_REGISTRY_QUOTA_INFORMATION, *PSYSTEM_REGISTRY_QUOTA_INFORMATION; +typedef struct _SYSTEM_TIME_ADJUSTMENT_QUERY { + ULONG TimeAdjustment; + ULONG TimeIncrement; + BOOLEAN TimeAdjustmentDisabled; +} SYSTEM_TIME_ADJUSTMENT_QUERY, *PSYSTEM_TIME_ADJUSTMENT_QUERY; + typedef struct _SYSTEM_TIME_ADJUSTMENT { ULONG TimeAdjustment; BOOLEAN TimeAdjustmentDisabled; @@ -2841,7 +2862,8 @@ NTSYSAPI ULONG WINAPI RtlFindSetRuns(PCRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN); NTSYSAPI BOOLEAN WINAPI RtlFirstFreeAce(PACL,PACE_HEADER *); NTSYSAPI NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(PUNICODE_STRING); -NTSYSAPI NTSTATUS WINAPI RtlFormatMessage(LPWSTR,UCHAR,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG); +NTSYSAPI NTSTATUS WINAPI RtlFormatMessage(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*); +NTSYSAPI NTSTATUS WINAPI RtlFormatMessageEx(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*,ULONG); NTSYSAPI void WINAPI RtlFreeAnsiString(PANSI_STRING); NTSYSAPI BOOLEAN WINAPI RtlFreeHandle(RTL_HANDLE_TABLE *,RTL_HANDLE *); NTSYSAPI BOOLEAN WINAPI RtlFreeHeap(HANDLE,ULONG,PVOID); @@ -2868,10 +2890,14 @@ NTSYSAPI BOOLEAN WINAPI RtlGetNtProductType(LPDWORD); NTSYSAPI NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID *,PBOOLEAN); NTSYSAPI ULONG WINAPI RtlGetProcessHeaps(ULONG,HANDLE*); +NTSYSAPI NTSTATUS WINAPI RtlGetProcessPreferredUILanguages(DWORD,ULONG*,WCHAR*,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR,PBOOLEAN,PACL *,PBOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlGetSearchPath(PWSTR*); +NTSYSAPI NTSTATUS WINAPI RtlGetSystemPreferredUILanguages(DWORD,ULONG,ULONG*,WCHAR*,ULONG*); NTSYSAPI LONGLONG WINAPI RtlGetSystemTimePrecise(void); NTSYSAPI DWORD WINAPI RtlGetThreadErrorMode(void); +NTSYSAPI NTSTATUS WINAPI RtlGetThreadPreferredUILanguages(DWORD,ULONG*,WCHAR*,ULONG*); +NTSYSAPI NTSTATUS WINAPI RtlGetUserPreferredUILanguages(DWORD,ULONG,ULONG*,WCHAR*,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlGetVersion(RTL_OSVERSIONINFOEXW*); NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING,GUID*); NTSYSAPI PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid(PSID); @@ -2944,6 +2970,7 @@ NTSYSAPI NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings(DWORD,HANDLE,const WCHAR*,const WCHAR*,WCHAR*,SIZE_T,SIZE_T*); NTSYSAPI NTSTATUS WINAPI RtlQueryAtomInAtomTable(RTL_ATOM_TABLE,RTL_ATOM,ULONG*,ULONG*,WCHAR*,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlQueryDynamicTimeZoneInformation(RTL_DYNAMIC_TIME_ZONE_INFORMATION*); +NTSYSAPI NTSTATUS WINAPI RtlQueryEnvironmentVariable(WCHAR*,const WCHAR*,SIZE_T,WCHAR*,SIZE_T,SIZE_T*); NTSYSAPI NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR,PUNICODE_STRING,PUNICODE_STRING); NTSYSAPI NTSTATUS WINAPI RtlQueryHeapInformation(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T,PSIZE_T); NTSYSAPI NTSTATUS WINAPI RtlQueryInformationAcl(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS); @@ -2986,9 +3013,11 @@ NTSYSAPI NTSTATUS WINAPI RtlSetIoCompletionCallback(HANDLE,PRTL_OVERLAPPED_COMPLETION_ROUTINE,ULONG); NTSYSAPI void WINAPI RtlSetLastWin32Error(DWORD); NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS); +NTSYSAPI NTSTATUS WINAPI RtlSetProcessPreferredUILanguages(DWORD,PCZZWSTR,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR,BOOLEAN,PACL,BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlSetSearchPathMode(ULONG); NTSYSAPI NTSTATUS WINAPI RtlSetThreadErrorMode(DWORD,LPDWORD); +NTSYSAPI NTSTATUS WINAPI RtlSetThreadPreferredUILanguages(DWORD,PCZZWSTR,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlSetTimeZoneInformation(const RTL_TIME_ZONE_INFORMATION*); NTSYSAPI void WINAPI RtlSetUnhandledExceptionFilter(PRTL_EXCEPTION_FILTER); NTSYSAPI SIZE_T WINAPI RtlSizeHeap(HANDLE,ULONG,const void*); diff -Nru wine-development-5.8/include/wmistr.h wine-development-5.9/include/wmistr.h --- wine-development-5.8/include/wmistr.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/wmistr.h 2020-05-22 18:49:34.000000000 +0000 @@ -27,14 +27,19 @@ #define WNODE_FLAG_TOO_SMALL 0x00000020 #define WNODE_FLAG_INSTANCES_SAME 0x00000040 #define WNODE_FLAG_STATIC_INSTANCE_NAMES 0x00000080 +#define WNODE_FLAG_INTERNAL 0x00000100 #define WNODE_FLAG_USE_TIMESTAMP 0x00000200 +#define WNODE_FLAG_PERSIST_EVENT 0x00000400 #define WNODE_FLAG_EVENT_REFERENCE 0x00002000 +#define WNODE_FLAG_ANSI_INSTANCENAMES 0x00004000 #define WNODE_FLAG_METHOD_ITEM 0x00008000 #define WNODE_FLAG_PDO_INSTANCE_NAMES 0x00010000 #define WNODE_FLAG_TRACED_GUID 0x00020000 #define WNODE_FLAG_LOG_WNODE 0x00040000 #define WNODE_FLAG_USE_GUID_PTR 0x00080000 #define WNODE_FLAG_USE_MOF_PTR 0x00100000 +#define WNODE_FLAG_NO_HEADER 0x00200000 +#define WNODE_FLAG_SEND_DATA_BLOCK 0x00400000 #define WNODE_FLAG_SEVERITY_MASK 0xFF000000 typedef enum @@ -49,12 +54,13 @@ WMI_DISABLE_CONNECTION = 7, WMI_REGINFO = 8, WMI_EXECUTE_METHOD = 9, + WMI_CAPTURE_STATE = 10 } WMIDPREQUESTCODE; typedef struct _WNODE_HEADER { ULONG BufferSize; - ULONG ProvicerId; + ULONG ProviderId; union { ULONG64 HistoricalContext; @@ -63,10 +69,10 @@ ULONG Version; ULONG Linkage; } DUMMYSTRUCTNAME; - } DUMMYUNIONNAME; union { + ULONG CountLost; HANDLE KernelHandle; LARGE_INTEGER TimeStamp; } DUMMYUNIONNAME2; diff -Nru wine-development-5.8/include/wmsdk.h wine-development-5.9/include/wmsdk.h --- wine-development-5.8/include/wmsdk.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/include/wmsdk.h 2020-05-22 18:49:34.000000000 +0000 @@ -20,7 +20,5 @@ /* #include */ #include "wmsdkidl.h" - -/* Currently unimplemented */ -/* #include "asferr.h" */ +#include "asferr.h" #include "nserror.h" diff -Nru wine-development-5.8/libs/wine/mmap.c wine-development-5.9/libs/wine/mmap.c --- wine-development-5.8/libs/wine/mmap.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/libs/wine/mmap.c 2020-05-22 18:49:34.000000000 +0000 @@ -211,18 +211,21 @@ if (!(flags & MAP_FIXED)) { -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) - /* Even FreeBSD 5.3 does not properly support NULL here. */ - if( start == NULL ) start = (void *)0x110000; -#endif - #ifdef MAP_TRYFIXED /* If available, this will attempt a fixed mapping in-kernel */ flags |= MAP_TRYFIXED; +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + if ( start && mmap( start, size, prot, flags | MAP_FIXED | MAP_EXCL, get_fdzero(), 0 ) ) + return start; #elif defined(__svr4__) || defined(__NetBSD__) || defined(__APPLE__) if ( try_mmap_fixed( start, size, prot, flags, get_fdzero(), 0 ) ) return start; #endif + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) + /* Even FreeBSD 5.3 does not properly support NULL here. */ + if( start == NULL ) start = (void *)0x110000; +#endif } return mmap( start, size, prot, flags, get_fdzero(), 0 ); } diff -Nru wine-development-5.8/loader/main.c wine-development-5.9/loader/main.c --- wine-development-5.8/loader/main.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/loader/main.c 2020-05-22 18:49:34.000000000 +0000 @@ -40,6 +40,8 @@ #include "wine/library.h" #include "main.h" +extern char **environ; + /* the preloader will set this variable */ const struct wine_preload_info *wine_main_preload_info = NULL; @@ -158,6 +160,116 @@ #endif +/* canonicalize path and return its directory name */ +static char *realpath_dirname( const char *name ) +{ + char *p, *fullpath = realpath( name, NULL ); + + if (fullpath) + { + p = strrchr( fullpath, '/' ); + if (p == fullpath) p++; + if (p) *p = 0; + } + return fullpath; +} + +/* if string ends with tail, remove it */ +static char *remove_tail( const char *str, const char *tail ) +{ + size_t len = strlen( str ); + size_t tail_len = strlen( tail ); + char *ret; + + if (len < tail_len) return NULL; + if (strcmp( str + len - tail_len, tail )) return NULL; + ret = malloc( len - tail_len + 1 ); + memcpy( ret, str, len - tail_len ); + ret[len - tail_len] = 0; + return ret; +} + +/* build a path from the specified dir and name */ +static char *build_path( const char *dir, const char *name ) +{ + size_t len = strlen( dir ); + char *ret = malloc( len + strlen( name ) + 2 ); + + memcpy( ret, dir, len ); + if (len && ret[len - 1] != '/') ret[len++] = '/'; + strcpy( ret + len, name ); + return ret; +} + +static const char *get_self_exe( char *argv0 ) +{ +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) + return "/proc/self/exe"; +#elif defined (__FreeBSD__) || defined(__DragonFly__) + return "/proc/curproc/file"; +#else + if (!strchr( argv0, '/' )) /* search in PATH */ + { + char *p, *path = getenv( "PATH" ); + + if (!path || !(path = strdup(path))) return NULL; + for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" )) + { + char *name = build_path( p, argv0 ); + int found = !access( name, X_OK ); + free( name ); + if (found) break; + } + if (p) p = strdup( p ); + free( path ); + return p; + } + return argv0; +#endif +} + +static void *try_dlopen( const char *dir, const char *name ) +{ + char *path = build_path( dir, name ); + void *handle = dlopen( path, RTLD_NOW ); + free( path ); + return handle; +} + +static void *load_ntdll( char *argv0 ) +{ + const char *self = get_self_exe( argv0 ); + char *path, *p; + void *handle = NULL; + + if (self && ((path = realpath_dirname( self )))) + { + if ((p = remove_tail( path, "/loader" ))) + { + handle = try_dlopen( p, "dlls/ntdll/ntdll.so" ); + free( p ); + } + else handle = try_dlopen( path, BIN_TO_DLLDIR "/ntdll.so" ); + free( path ); + } + + if (!handle && (path = getenv( "WINEDLLPATH" ))) + { + path = strdup( path ); + for (p = strtok( path, ":" ); p; p = strtok( NULL, ":" )) + { + handle = try_dlopen( p, "ntdll.so" ); + if (handle) break; + } + free( path ); + } + + if (!handle && !self) handle = try_dlopen( DLLDIR, "ntdll.so" ); + + return handle; +} + + /********************************************************************** * main */ @@ -165,6 +277,15 @@ { char error[1024]; int i; + void *handle; + + if ((handle = load_ntdll( argv[0] ))) + { + void (*init_func)(int, char **, char **) = dlsym( handle, "__wine_main" ); + if (init_func) init_func( argc, argv, environ ); + fprintf( stderr, "wine: __wine_main function not found in ntdll.so\n" ); + exit(1); + } if (!getenv( "WINELOADERNOEXEC" )) /* first time around */ { diff -Nru wine-development-5.8/loader/Makefile.in wine-development-5.9/loader/Makefile.in --- wine-development-5.8/loader/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/loader/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -18,6 +18,8 @@ preloader_EXTRADEFS = -fno-builtin +main_EXTRADEFS = -DDLLDIR=\"${dlldir}\" -DBIN_TO_DLLDIR=\"`$(MAKEDEP) -R ${bindir} ${dlldir}`\" + wine_OBJS = main.o wine_DEPS = $(WINELOADER_DEPENDS) wine_LDFLAGS = $(WINELOADER_LDFLAGS) $(LDEXECFLAGS) -lwine $(PTHREAD_LIBS) @@ -27,7 +29,9 @@ wine64_LDFLAGS = $(WINELOADER_LDFLAGS) $(LDEXECFLAGS) -lwine $(PTHREAD_LIBS) wine_preloader_OBJS = preloader.o preloader_mac.o +wine_preloader_DEPS = $(WINELOADER_DEPENDS) wine_preloader_LDFLAGS = $(WINEPRELOADER_LDFLAGS) wine64_preloader_OBJS = preloader.o preloader_mac.o +wine64_preloader_DEPS = $(WINELOADER_DEPENDS) wine64_preloader_LDFLAGS = $(WINEPRELOADER_LDFLAGS) diff -Nru wine-development-5.8/loader/wine.inf.in wine-development-5.9/loader/wine.inf.in --- wine-development-5.8/loader/wine.inf.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/loader/wine.inf.in 2020-05-22 18:49:34.000000000 +0000 @@ -2612,10 +2612,14 @@ 11,,iexplore.exe 11,,winetest.exe,- 12,,fltmgr.sys,- +12,,hidclass.sys,- +12,,http.sys,- 12,,ksecdd.sys,- 12,,mountmgr.sys,- 12,,ndis.sys,- +12,,scsiport.sys,- 12,,tdi.sys,- +12,,usbd.sys,- 12,,winebus.sys,- 12,,winehid.sys,- 12,,wineusb.sys,- @@ -2664,10 +2668,14 @@ 11,,notepad.exe 11,,winetest.exe,- 12,,fltmgr.sys +12,,hidclass.sys +12,,http.sys 12,,ksecdd.sys 12,,mountmgr.sys 12,,ndis.sys +12,,scsiport.sys 12,,tdi.sys +12,,usbd.sys 12,,winebus.sys 12,,winehid.sys 12,,wineusb.sys diff -Nru wine-development-5.8/.mailmap wine-development-5.9/.mailmap --- wine-development-5.8/.mailmap 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/.mailmap 2020-05-22 18:49:34.000000000 +0000 @@ -26,6 +26,7 @@ Erich Hoover Erich Hoover Erwin Wolff +Esme Povirk Evgeny Putin Fatih Aşıcı Fernando Martins diff -Nru wine-development-5.8/MAINTAINERS wine-development-5.9/MAINTAINERS --- wine-development-5.8/MAINTAINERS 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/MAINTAINERS 2020-05-22 18:49:34.000000000 +0000 @@ -53,7 +53,7 @@ F: dlls/comctl32/ Common Item Dialog -P: Vincent Povirk +P: Esme Povirk F: dlls/comdlg32/itemdlg.c F: dlls/comdlg32/tests/itemdlg.c @@ -122,7 +122,7 @@ F: dlls/dwrite/ DotNet Runtime -M: Vincent Povirk +M: Esme Povirk F: dlls/mscoree/ GDI @@ -130,7 +130,7 @@ F: dlls/gdi32/ GDIPlus -M: Vincent Povirk +M: Esme Povirk F: dlls/gdiplus/ GPhoto Driver @@ -202,7 +202,7 @@ F: dlls/ole32/usrmarshal.c OLE Storage -M: Vincent Povirk +M: Esme Povirk F: dlls/ole32/filelockbytes.c F: dlls/ole32/memlockbytes.c F: dlls/ole32/stg_stream.c @@ -243,7 +243,7 @@ F: tools/widl TWAIN -P: Vincent Povirk +P: Esme Povirk F: dlls/twain_32/ F: dlls/sane.ds/ F: dlls/gphoto2.ds/ @@ -271,7 +271,7 @@ F: dlls/shdocvw/ Windows Imaging Component -M: Vincent Povirk +M: Esme Povirk F: dlls/windowscodecs/ F: dlls/windowscodecsext/ @@ -315,7 +315,6 @@ X11 Driver M: Alexandre Julliard -P: Vincent Povirk F: dlls/winex11.drv/ XML parsing @@ -329,7 +328,7 @@ P: Andrew Eikum P: Huw Davies P: Jacek Caban -P: Vincent Povirk +P: Esme Povirk P: Erich E. Hoover F: * F: */ diff -Nru wine-development-5.8/Makefile.in wine-development-5.9/Makefile.in --- wine-development-5.8/Makefile.in 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/Makefile.in 2020-05-22 18:49:34.000000000 +0000 @@ -69,6 +69,7 @@ ICOTOOL = @ICOTOOL@ MSGFMT = @MSGFMT@ CROSSTARGET = @CROSSTARGET@ +CROSSDEBUG = @CROSSDEBUG@ SUBDIRS = @SUBDIRS@ RUNTESTFLAGS = -q -P wine MAKEDEP = $(TOOLSDIR)/tools/makedep$(TOOLSEXT) diff -Nru wine-development-5.8/po/ar.po wine-development-5.9/po/ar.po --- wine-development-5.8/po/ar.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ar.po 2020-05-22 18:49:34.000000000 +0000 @@ -685,7 +685,7 @@ msgid "Match &Case" msgstr "مطابقة ال&حالة" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "الاتجاه" @@ -3573,27 +3573,27 @@ msgid "High" msgstr "عالي" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "مقابض اللعب" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "مع&طل" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "م&فعل" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "م&تصل" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "معطل" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3601,23 +3601,23 @@ "بعد تعطيل أو تفعيل جهاز ، مقبض اللعب المتصل لنيتم تحديثه هنا حتى إعادة تشغيل " "التطبيق." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "اختبار مقبض اللعب" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "الأزرار" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "اختبار الهزّاز" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "المؤثرات المتاحة" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3629,6 +3629,10 @@ msgid "Game Controllers" msgstr "متحكمات الألعاب" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "خطأ في تحويل العنصر إلى النمط الأولي" diff -Nru wine-development-5.8/po/ast.po wine-development-5.9/po/ast.po --- wine-development-5.8/po/ast.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ast.po 2020-05-22 18:49:34.000000000 +0000 @@ -681,7 +681,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direición" @@ -3468,27 +3468,27 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joysticks" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Inhabilitar" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Habilitar" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3496,23 +3496,23 @@ "Tres in/habilitar un preséu, los joysticks coneutaos nun van anovase equí " "hasta que reanicies esti applet." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Botones" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Efeutos disponibles" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3522,6 +3522,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/bg.po wine-development-5.9/po/bg.po --- wine-development-5.8/po/bg.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/bg.po 2020-05-22 18:49:34.000000000 +0000 @@ -697,7 +697,7 @@ msgid "Match &Case" msgstr "&Чувствителен регистър" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Посока" @@ -3587,54 +3587,54 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Забрани" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy msgid "&Enable" msgstr "&Таблица" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy msgid "Connected" msgstr "Файлът не е намерен" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "&Забрани" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy msgid "Available Effects" msgstr "На&пред" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3645,6 +3645,10 @@ msgid "Game Controllers" msgstr "Контрол на потока" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/ca.po wine-development-5.9/po/ca.po --- wine-development-5.8/po/ca.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ca.po 2020-05-22 18:49:34.000000000 +0000 @@ -687,7 +687,7 @@ msgid "Match &Case" msgstr "&Distingeix entre majúscules i minúscules" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direcció" @@ -3573,27 +3573,27 @@ msgid "High" msgstr "Alt" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Palanques de control" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Inhabilita" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Habilita" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Connectat" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Inhabilitat" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3601,23 +3601,23 @@ "Després d'inhabilitar o habilitar un dispositiu, no s'actualitzaran aquí les " "palanques de control connectades fins que reinicieu aquesta miniaplicació." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Prova de palanca de control" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Botons" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Prova de retroacció de força" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Efectes disponibles" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3629,6 +3629,10 @@ msgid "Game Controllers" msgstr "Controladors de joc" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Error en convertir l'objecte a tipus primitiu" diff -Nru wine-development-5.8/po/cs.po wine-development-5.9/po/cs.po --- wine-development-5.8/po/cs.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/cs.po 2020-05-22 18:49:34.000000000 +0000 @@ -692,7 +692,7 @@ msgid "Match &Case" msgstr "&Rozlišovat velikost" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Směr" @@ -3522,27 +3522,27 @@ msgid "High" msgstr "Vysoká" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Pákové ovladače" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Zakázat" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "P&ovolit" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Připojeno" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Zakázáno" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3550,23 +3550,23 @@ "Po povolení či zakázání zařízení bude stav připojeného pákového ovladače " "aktualizován až po restartu tohoto appletu." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Otestovat pákový ovladač" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Tlačítka" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Otestovat silovou zpětnou vazbu" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Dostupné efekty" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3578,6 +3578,10 @@ msgid "Game Controllers" msgstr "Herní ovladače" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Chyba při převodu objektu na jednoduchý typ" diff -Nru wine-development-5.8/po/da.po wine-development-5.9/po/da.po --- wine-development-5.8/po/da.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/da.po 2020-05-22 18:49:34.000000000 +0000 @@ -700,7 +700,7 @@ msgid "Match &Case" msgstr "Forskel på store/små &bogstaver" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Retning" @@ -3604,57 +3604,57 @@ msgid "High" msgstr "&Høj" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Deaktiver" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy #| msgid "&enable" msgid "&Enable" msgstr "&Aktiver" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy #| msgid "Disconnected" msgid "Connected" msgstr "Forbindelse mistet" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "&Deaktiver" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "Available formats" msgid "Available Effects" msgstr "Tilgængelige formater" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3666,6 +3666,10 @@ msgid "Game Controllers" msgstr "Opret control" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Fejl ved konvertering af objekt til primitiv type" diff -Nru wine-development-5.8/po/de.po wine-development-5.9/po/de.po --- wine-development-5.8/po/de.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/de.po 2020-05-22 18:49:34.000000000 +0000 @@ -685,7 +685,7 @@ msgid "Match &Case" msgstr "Groß-/Klein&schreibung" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Suchrichtung" @@ -3563,27 +3563,27 @@ msgid "High" msgstr "Hoch" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joysticks" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Deaktivieren" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Aktivieren" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Verbunden" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Deaktiviert" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3591,23 +3591,23 @@ "Nach dem De-/Aktivieren eines Gerätes wird die Liste der verbundenen " "Controller bis zum Neustart dieses Applets nicht mehr aktualisiert." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Joystick testen" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Tasten" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Force Feedback testen" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Verfügbare Effekte" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3620,6 +3620,10 @@ msgid "Game Controllers" msgstr "Gamecontroller" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Fehler beim Umwandeln des Objektes in einen Grundtyp" diff -Nru wine-development-5.8/po/el.po wine-development-5.9/po/el.po --- wine-development-5.8/po/el.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/el.po 2020-05-22 18:49:34.000000000 +0000 @@ -675,7 +675,7 @@ msgid "Match &Case" msgstr "Ταίριασμα &Κεφαλαίων" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Κατεύθυνση" @@ -3504,52 +3504,52 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy msgid "Connected" msgstr "Το αρχείο δε βρέθηκε" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "A&vailable buttons:" msgid "Available Effects" msgstr "Δ&ιαθέσιμα κουμπιά:" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3560,6 +3560,10 @@ msgid "Game Controllers" msgstr "&Περιεχόμενα" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/en.po wine-development-5.9/po/en.po --- wine-development-5.8/po/en.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/en.po 2020-05-22 18:49:34.000000000 +0000 @@ -684,7 +684,7 @@ msgid "Match &Case" msgstr "Match &Case" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direction" @@ -3556,27 +3556,27 @@ msgid "High" msgstr "High" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joysticks" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Disable" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Enable" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Connected" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Disabled" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3584,23 +3584,23 @@ "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Test Joystick" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Buttons" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Test Force Feedback" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Available Effects" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3612,6 +3612,10 @@ msgid "Game Controllers" msgstr "Game Controllers" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "Test and configure game controllers." + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Error converting object to primitive type" diff -Nru wine-development-5.8/po/en_US.po wine-development-5.9/po/en_US.po --- wine-development-5.8/po/en_US.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/en_US.po 2020-05-22 18:49:34.000000000 +0000 @@ -684,7 +684,7 @@ msgid "Match &Case" msgstr "Match &Case" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direction" @@ -3556,27 +3556,27 @@ msgid "High" msgstr "High" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joysticks" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Disable" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Enable" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Connected" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Disabled" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3584,23 +3584,23 @@ "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Test Joystick" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Buttons" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Test Force Feedback" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Available Effects" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3612,6 +3612,10 @@ msgid "Game Controllers" msgstr "Game Controllers" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "Test and configure game controllers." + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Error converting object to primitive type" diff -Nru wine-development-5.8/po/eo.po wine-development-5.9/po/eo.po --- wine-development-5.8/po/eo.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/eo.po 2020-05-22 18:49:34.000000000 +0000 @@ -682,7 +682,7 @@ msgid "Match &Case" msgstr "Atenti &Usklecon" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direkto" @@ -3490,57 +3490,57 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Malaktivigi" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy #| msgid "&enable" msgid "&Enable" msgstr "&aktivigi" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy #| msgid "Disconnected" msgid "Connected" msgstr "Malkonektita" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "&Malaktivigi" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "Available formats" msgid "Available Effects" msgstr "Disponeblaj formatoj" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3552,6 +3552,10 @@ msgid "Game Controllers" msgstr "Regado" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/es.po wine-development-5.9/po/es.po --- wine-development-5.8/po/es.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/es.po 2020-05-22 18:49:34.000000000 +0000 @@ -703,7 +703,7 @@ msgid "Match &Case" msgstr "&Mayúsculas/minúsculas" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Dirección" @@ -3613,57 +3613,57 @@ msgid "High" msgstr "Alta" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Deshabilitar" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy #| msgid "&enable" msgid "&Enable" msgstr "&habilitar" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy #| msgid "Disconnected" msgid "Connected" msgstr "Desconectado" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "&Deshabilitar" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "Available formats" msgid "Available Effects" msgstr "Formatos disponibles" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3673,6 +3673,10 @@ msgid "Game Controllers" msgstr "Mandos de juego" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Error al convertir objeto a tipo primitivo" diff -Nru wine-development-5.8/po/fa.po wine-development-5.9/po/fa.po --- wine-development-5.8/po/fa.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/fa.po 2020-05-22 18:49:34.000000000 +0000 @@ -684,7 +684,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 #, fuzzy msgid "Direction" msgstr "اطلاعات" @@ -3537,49 +3537,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3590,6 +3590,10 @@ msgid "Game Controllers" msgstr "&محتویات" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/fi.po wine-development-5.9/po/fi.po --- wine-development-5.8/po/fi.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/fi.po 2020-05-22 18:49:34.000000000 +0000 @@ -679,7 +679,7 @@ msgid "Match &Case" msgstr "Kirjaink&oko" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Suunta" @@ -3550,27 +3550,27 @@ msgid "High" msgstr "Korkea" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joystickit" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Poista käytöstä" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Ota käyttöön" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Yhdistetty" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Ei käytössä" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3578,23 +3578,23 @@ "Kun laite poistetaan käytöstä tai otetaan käyttöön, liitetyt ohjaimet eivät " "päivity tähän, ellei tätä sovelmaa käynnistetä uudelleen." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Testaa joystickia" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Painikkeet" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Testaa voimapalautetta" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Mahdolliset efektit" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3606,6 +3606,10 @@ msgid "Game Controllers" msgstr "Peliohjaimet" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Virhe muunnettaessa objektia alkeistyypiksi" diff -Nru wine-development-5.8/po/fr.po wine-development-5.9/po/fr.po --- wine-development-5.8/po/fr.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/fr.po 2020-05-22 18:49:34.000000000 +0000 @@ -695,7 +695,7 @@ msgid "Match &Case" msgstr "Respecter la &casse" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direction" @@ -3605,27 +3605,27 @@ msgid "High" msgstr "Haute" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joysticks" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Désactiver" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Activer" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Connecté" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Désactivé" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3634,23 +3634,23 @@ "joysticks connectés ne sera pas mise à jour à moins de redémarrer cette " "applet." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Tester le joystick" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Boutons" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Tester le retour de force" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Effets disponibles" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3662,6 +3662,10 @@ msgid "Game Controllers" msgstr "Contrôleurs de jeu" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Erreur lors de la conversion de l'objet vers un type primitif" diff -Nru wine-development-5.8/po/he.po wine-development-5.9/po/he.po --- wine-development-5.8/po/he.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/he.po 2020-05-22 18:49:34.000000000 +0000 @@ -698,7 +698,7 @@ msgid "Match &Case" msgstr "התאמת &רשיות" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "כיוון" @@ -3571,57 +3571,57 @@ msgid "High" msgstr "גבוהה" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 #, fuzzy msgid "&Disable" msgstr "Table" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy #| msgid "&enable" msgid "&Enable" msgstr "ה&פעלה" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy #| msgid "Disconnected" msgid "Connected" msgstr "Disconnected" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy msgid "Disabled" msgstr "Table" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "Available formats" msgid "Available Effects" msgstr "התבניות הזמינות" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3633,6 +3633,10 @@ msgid "Game Controllers" msgstr "יצירת פקד" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "שגיאה בהמרת הפריט לטיפוס פרימיטיבי" diff -Nru wine-development-5.8/po/hi.po wine-development-5.9/po/hi.po --- wine-development-5.8/po/hi.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/hi.po 2020-05-22 18:49:34.000000000 +0000 @@ -670,7 +670,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "" @@ -3472,49 +3472,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3524,6 +3524,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/hr.po wine-development-5.9/po/hr.po --- wine-development-5.8/po/hr.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/hr.po 2020-05-22 18:49:34.000000000 +0000 @@ -690,7 +690,7 @@ msgid "Match &Case" msgstr "Odgovara &veličina slova" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Smjer" @@ -3578,27 +3578,27 @@ msgid "High" msgstr "Visoke" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joystici" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Isključi" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Uključi" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Povezan" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Isključen" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3606,23 +3606,23 @@ "Nakon isključivanja ili uključivanja uređaja, povezani joystici neće biti " "osvježeni ovdje dok ponovno ne pokrenete ovaj applet." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Isprobaj joystick" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Gumbi" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Isprobaj povratnu vezu sile" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Dostupni efekti" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3634,6 +3634,10 @@ msgid "Game Controllers" msgstr "Igraći upravljači" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Greška u pretvaranju objekta u osnovnu vrstu" diff -Nru wine-development-5.8/po/hu.po wine-development-5.9/po/hu.po --- wine-development-5.8/po/hu.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/hu.po 2020-05-22 18:49:34.000000000 +0000 @@ -704,7 +704,7 @@ msgid "Match &Case" msgstr "Kis/&nagybetű különbség" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Irány" @@ -3620,57 +3620,57 @@ msgid "High" msgstr "Magas" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "Tiltá&s" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy #| msgid "&enable" msgid "&Enable" msgstr "&engedélyez" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy #| msgid "Disconnected" msgid "Connected" msgstr "Lecsatlakozott" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "Tiltá&s" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "Available formats" msgid "Available Effects" msgstr "Elérhető formátumok" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3682,6 +3682,10 @@ msgid "Game Controllers" msgstr "Vezérlő létrehozása" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Hiba az objektum primitív típusra való konvertálásánál" diff -Nru wine-development-5.8/po/it.po wine-development-5.9/po/it.po --- wine-development-5.8/po/it.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/it.po 2020-05-22 18:49:34.000000000 +0000 @@ -710,7 +710,7 @@ msgid "Match &Case" msgstr "&Maiuscole/Minuscole" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direzione" @@ -3628,57 +3628,57 @@ msgid "High" msgstr "Alta" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Disabilita" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy #| msgid "&enable" msgid "&Enable" msgstr "&abilita" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy #| msgid "Disconnected" msgid "Connected" msgstr "Disconnesso" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "&Disabilita" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "Available formats" msgid "Available Effects" msgstr "Formati disponibili" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3690,6 +3690,10 @@ msgid "Game Controllers" msgstr "Crea controllo" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Errore nel convertire un oggetto ad un tipo primitivo" diff -Nru wine-development-5.8/po/ja.po wine-development-5.9/po/ja.po --- wine-development-5.8/po/ja.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ja.po 2020-05-22 18:49:34.000000000 +0000 @@ -5,7 +5,7 @@ "Project-Id-Version: Wine\n" "Report-Msgid-Bugs-To: https://bugs.winehq.org\n" "POT-Creation-Date: N/A\n" -"PO-Revision-Date: 2019-11-29 22:03+0900\n" +"PO-Revision-Date: 2020-05-10 19:59+0900\n" "Last-Translator: Akihiro Sagawa \n" "Language-Team: Japanese\n" "Language: ja\n" @@ -685,7 +685,7 @@ msgid "Match &Case" msgstr "大文字と小文字を区別する(&C)" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "方向" @@ -3548,27 +3548,27 @@ msgid "High" msgstr "高" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "ジョイスティック" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "無効化(&D)" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "有効化(&E)" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "接続済み" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "無効" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3576,23 +3576,23 @@ "このアプレットを再起動するまでは、デバイスを無効化または有効化したあとでも、" "ここにある接続済みジョイスティックの一覧は更新されません。" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "ジョイスティックのテスト" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "ボタン" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "フォース フィードバックのテスト" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "利用可能な効果" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3604,6 +3604,10 @@ msgid "Game Controllers" msgstr "ゲーム コントローラ" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "オブジェクトを基本型に変換できません" @@ -3702,17 +3706,15 @@ #: jscript.rc:75 msgid "Microsoft JScript compilation error" -msgstr "" +msgstr "Microsoft JScript コンパイル エラー" #: jscript.rc:76 msgid "Microsoft JScript runtime error" -msgstr "" +msgstr "Microsoft JScript 実行時エラー" #: jscript.rc:77 -#, fuzzy -#| msgid "Unknown error" msgid "Unknown runtime error" -msgstr "不明なエラー" +msgstr "未知の実行時エラー" #: jscript.rc:54 msgid "Number expected" @@ -3760,7 +3762,7 @@ #: jscript.rc:63 msgid "Exception thrown and not caught" -msgstr "" +msgstr "例外が送出されましたが捕捉されませんでした" #: jscript.rc:65 msgid "URI to be encoded contains invalid characters" @@ -6839,10 +6841,8 @@ msgstr "シンクは確定されていません。\n" #: mferror.mc:732 -#, fuzzy -#| msgid "Sink was already stopped.\n" msgid "Clock was stopped\n" -msgstr "シンクはすでに停止していました。\n" +msgstr "クロックは停止されていました\n" #: mferror.mc:32 msgid "Media Foundation platform is not initialized.\n" @@ -7221,10 +7221,8 @@ msgstr "クロックの状態は設定済みでした。\n" #: mferror.mc:725 -#, fuzzy -#| msgid "Clock is not available.\n" msgid "Clock is not simple\n" -msgstr "クロックは利用可能ではありません。\n" +msgstr "クロックが単純ではありません\n" #: mpr.rc:35 wininet.rc:37 msgid "Enter Network Password" @@ -8319,206 +8317,160 @@ msgstr "Off" #: version.rc:56 -#, fuzzy -#| msgid "video" msgid "Provider" -msgstr "ビデオ" +msgstr "プロバイダ" #: version.rc:59 -#, fuzzy -#| msgid "Select the format you want to use:" msgid "Select the data you want to connect to:" -msgstr "形式を選択してください:" +msgstr "接続したいデータを選択してください:" #: version.rc:66 -#, fuzzy -#| msgid "Connections" msgid "Connection" msgstr "接続" #: version.rc:69 -#, fuzzy -#| msgid "Select the format you want to use:" msgid "Specify the following to connect to ODBC data:" -msgstr "形式を選択してください:" +msgstr "ODBC データに接続するため以下を指定してください:" #: version.rc:70 msgid "1. Specify the source of data:" -msgstr "" +msgstr "1. データ ソース:" #: version.rc:71 -#, fuzzy -#| msgid "Please enter your name" msgid "Use &data source name" -msgstr "名前を入力しましょう" +msgstr "利用するデータ ソース名(&D)" #: version.rc:74 -#, fuzzy -#| msgid "Reset Connections" msgid "Use c&onnection string" -msgstr "リセットされた接続" +msgstr "利用する接続文字列(&C)" #: version.rc:75 -#, fuzzy -#| msgid "Connections" msgid "&Connection string:" -msgstr "接続" +msgstr "接続文字列:" #: version.rc:77 -#, fuzzy -#| msgid "A&dd..." msgid "B&uild..." -msgstr "追加(&D)..." +msgstr "構築(&U)..." #: version.rc:78 msgid "2. Enter information to log on to the server" -msgstr "" +msgstr "2. サーバにログオンするための情報" #: version.rc:79 -#, fuzzy -#| msgid "&User name:" msgid "User &name:" -msgstr "ユーザ名(&U):" +msgstr "ユーザ名(&N):" #: version.rc:83 -#, fuzzy -#| msgid "&Blank page" msgid "&Blank password" -msgstr "空白(&B)" +msgstr "空のパスワード(&B)" #: version.rc:84 -#, fuzzy -#| msgid "Wrong password.\n" msgid "Allow &saving password" -msgstr "パスワードが違います。\n" +msgstr "パスワードを保存する(&S)" #: version.rc:85 msgid "3. Enter the &initial catalog to use:" -msgstr "" +msgstr "3. 最初に利用するカタログ(&I):" #: version.rc:87 -#, fuzzy -#| msgid "Reset Connections" msgid "&Test Connection" -msgstr "リセットされた接続" +msgstr "接続をテスト(&T)" #: version.rc:92 winemine.rc:65 msgid "Advanced" msgstr "中級" #: version.rc:95 -#, fuzzy -#| msgid "Network share" msgid "Network settings" -msgstr "ネットワーク共有" +msgstr "ネットワーク設定" #: version.rc:96 -#, fuzzy -#| msgid "Bad impersonation level.\n" msgid "&Impersonation level:" -msgstr "不正な偽装レベルです。\n" +msgstr "偽装レベル(&I):" #: version.rc:98 msgid "P&rotection level:" -msgstr "" +msgstr "保護レベル(&R):" #: version.rc:101 -#, fuzzy -#| msgid "Connected" msgid "Connect:" -msgstr "接続済み" +msgstr "接続:" #: version.rc:103 -#, fuzzy -#| msgid "seconds" msgid "seconds." msgstr "秒" #: version.rc:104 -#, fuzzy -#| msgid "Success" msgid "A&ccess:" -msgstr "成功" +msgstr "アクセス(&C):" #: version.rc:110 -#, fuzzy -#| msgid "&All" msgid "All" -msgstr "すべて(&A)" +msgstr "すべて" #: version.rc:114 msgid "" "These are the initialization properties for this type of data. To edit a " "value, select a property, then choose Edit Value below." msgstr "" +"このデータ型には初期プロパティがあります。値を編集するには、プロパティを選ん" +"でから、下にある[値の編集]を選択してください。" #: version.rc:115 -#, fuzzy -#| msgid "&Edit..." msgid "&Edit Value..." -msgstr "編集(&E)..." +msgstr "値の編集(&E)..." #: version.rc:49 -#, fuzzy -#| msgid "Properties" msgid "Data Link Error" -msgstr "プロパティ" +msgstr "データ リンク エラー" #: version.rc:50 -#, fuzzy -#| msgid "Please select a file." msgid "Please select a provider." -msgstr "ファイルを選択してください。" +msgstr "プロバイダを選択してください。" #: version.rc:51 msgid "" "Provider is no longer available. Ensure that the provider is installed " "properly." msgstr "" +"プロバイダが有効ではありません。当該プロバイダが正しくインストールされている" +"か確かめてください。" #: version.rc:36 -#, fuzzy -#| msgid "Properties" msgid "Data Link Properties" -msgstr "プロパティ" +msgstr "データ リンク プロパティ" #: version.rc:37 msgid "OLE DB Provider(s)" -msgstr "" +msgstr "OLE DB プロバイダ" #: version.rc:41 -#, fuzzy -#| msgid "Ready" msgid "Read" -msgstr "待機中" +msgstr "読み取り" #: version.rc:42 -#, fuzzy -#| msgid "Readme:" msgid "ReadWrite" -msgstr "付属文書:" +msgstr "読み書き" #: version.rc:43 msgid "Share Deny None" -msgstr "" +msgstr "共有(拒否なし)" #: version.rc:44 msgid "Share Deny Read" -msgstr "" +msgstr "共有(読取拒否)" #: version.rc:45 msgid "Share Deny Write" -msgstr "" +msgstr "共有(書込拒否)" #: version.rc:46 msgid "Share Exclusive" -msgstr "" +msgstr "共有の排他制御" #: version.rc:47 -#, fuzzy -#| msgid "I/O Writes" msgid "Write" -msgstr "I/O 書き込み" +msgstr "書き込み" #: oledlg.rc:55 msgid "Insert Object" @@ -9710,16 +9662,12 @@ msgstr "カーボベルデ夏時間" #: tzres.rc:120 -#, fuzzy -#| msgid "Hawaiian Standard Time" msgid "Haiti Standard Time" -msgstr "ハワイ標準時" +msgstr "ハイチ標準時" #: tzres.rc:121 -#, fuzzy -#| msgid "Hawaiian Daylight Time" msgid "Haiti Daylight Time" -msgstr "ハワイ夏時間" +msgstr "ハイチ夏時間" #: tzres.rc:78 msgid "Central European Standard Time" @@ -9930,16 +9878,12 @@ msgstr "アルゼンチン夏時間" #: tzres.rc:142 -#, fuzzy -#| msgid "Mauritius Standard Time" msgid "Marquesas Standard Time" -msgstr "モーリシャス標準時" +msgstr "マルキーズ標準時" #: tzres.rc:143 -#, fuzzy -#| msgid "Mauritius Daylight Time" msgid "Marquesas Daylight Time" -msgstr "モーリシャス夏時間" +msgstr "マルキーズ夏時間" #: tzres.rc:156 msgid "Myanmar Standard Time" @@ -10314,16 +10258,12 @@ msgstr "ベネズエラ夏時間" #: tzres.rc:60 -#, fuzzy -#| msgid "Mountain Standard Time" msgid "Bougainville Standard Time" -msgstr "山地標準時" +msgstr "ブーゲンビル標準時" #: tzres.rc:61 -#, fuzzy -#| msgid "Mountain Daylight Time" msgid "Bougainville Daylight Time" -msgstr "山地夏時間" +msgstr "ブーゲンビル夏時間" #: tzres.rc:122 msgid "Hawaiian Standard Time" @@ -10350,16 +10290,12 @@ msgstr "ニュージーランド夏時間" #: tzres.rc:34 -#, fuzzy -#| msgid "Argentina Standard Time" msgid "Aleutian Standard Time" -msgstr "アルゼンチン標準時" +msgstr "アリューシャン標準時" #: tzres.rc:35 -#, fuzzy -#| msgid "Argentina Daylight Time" msgid "Aleutian Daylight Time" -msgstr "アルゼンチン夏時間" +msgstr "アリューシャン夏時間" #: tzres.rc:74 msgid "Central Brazilian Standard Time" @@ -10442,16 +10378,12 @@ msgstr "韓国 (夏時間)" #: tzres.rc:86 -#, fuzzy -#| msgid "Easter Island Standard Time" msgid "Chatham Islands Standard Time" -msgstr "イースター島標準時" +msgstr "チャタム諸島標準時" #: tzres.rc:87 -#, fuzzy -#| msgid "Easter Island Daylight Time" msgid "Chatham Islands Daylight Time" -msgstr "イースター島夏時間" +msgstr "チャタム諸島夏時間" #: tzres.rc:92 msgid "E. Africa Standard Time" diff -Nru wine-development-5.8/po/ko.po wine-development-5.9/po/ko.po --- wine-development-5.8/po/ko.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ko.po 2020-05-22 18:49:34.000000000 +0000 @@ -684,7 +684,7 @@ msgid "Match &Case" msgstr "대/소문자 구분(&C)" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "방향" @@ -3540,27 +3540,27 @@ msgid "High" msgstr "높음" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "조이스틱" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "사용하지 않음(&D)" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "가능(&E)" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "연결됨" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "불가능" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3568,23 +3568,23 @@ "장치를 비활성화하거나 활성화한 후, 이 애플릿을 다시 시작할 때까지 연결된 조이" "스틱을 업데이트하지 않습니다." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "조이스틱 테스트" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "버튼" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "강제 피드백 테스트" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "가능한 효과들" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3596,6 +3596,10 @@ msgid "Game Controllers" msgstr "게임 컨트롤러" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "객체를 기본 형식으로 변환하는 중에 오류 발생" diff -Nru wine-development-5.8/po/lt.po wine-development-5.9/po/lt.po --- wine-development-5.8/po/lt.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/lt.po 2020-05-22 18:49:34.000000000 +0000 @@ -5,7 +5,7 @@ "Project-Id-Version: Wine\n" "Report-Msgid-Bugs-To: https://bugs.winehq.org\n" "POT-Creation-Date: N/A\n" -"PO-Revision-Date: 2020-03-31 23:40+0300\n" +"PO-Revision-Date: 2020-05-12 00:24+0300\n" "Last-Translator: Aurimas Fišeras \n" "Language-Team: Lithuanian \n" "Language: lt\n" @@ -684,7 +684,7 @@ msgid "Match &Case" msgstr "Skirti raidžių &dydį" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Kryptis" @@ -3559,27 +3559,27 @@ msgid "High" msgstr "Aukštos" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Vairasvirtės" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Išjungti" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "Įj&ungti" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Prijungta" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Išjungta" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3587,23 +3587,23 @@ "Po įtaiso išjungimo ar įjungimo, prijungtos vairasvirtės nebus automatiškai " "čia atnaujintos, kol nepaleisite šios programėlės iš naujo." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Testuoti vairasvirtę" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Mygtukai" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Testuoti „Force Feedback“" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Prieinami efektai" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3615,6 +3615,10 @@ msgid "Game Controllers" msgstr "Žaidimų valdikliai" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "Tikrinti ir konfigūruoti žaidimų valdiklius." + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Klaida keičiant objektą į primityvų tipą" diff -Nru wine-development-5.8/po/ml.po wine-development-5.9/po/ml.po --- wine-development-5.8/po/ml.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ml.po 2020-05-22 18:49:34.000000000 +0000 @@ -672,7 +672,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "" @@ -3474,49 +3474,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3526,6 +3526,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/nb_NO.po wine-development-5.9/po/nb_NO.po --- wine-development-5.8/po/nb_NO.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/nb_NO.po 2020-05-22 18:49:34.000000000 +0000 @@ -683,7 +683,7 @@ msgid "Match &Case" msgstr "Skill &mellom store og små bokstaver" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Retning" @@ -3562,27 +3562,27 @@ msgid "High" msgstr "Høy" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Styrespaker" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Deaktiver" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "Sl&å på" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Tilkoblet" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Slått av" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3590,23 +3590,23 @@ "Etter at en enhet er slått på eller av vil ikke styrespaken bli oppdatert " "her før programmet startes på nytt." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Test styrespake" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Knapper" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Test Force Feedback" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Tilgjengelige effekter" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3618,6 +3618,10 @@ msgid "Game Controllers" msgstr "Spillkontrollere" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Klarte ikke konvertere objekt til primitiv type" diff -Nru wine-development-5.8/po/nl.po wine-development-5.9/po/nl.po --- wine-development-5.8/po/nl.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/nl.po 2020-05-22 18:49:34.000000000 +0000 @@ -696,7 +696,7 @@ msgid "Match &Case" msgstr "Gelijke &hoofd-/kleine letters" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Zoekrichting" @@ -3613,27 +3613,27 @@ msgid "High" msgstr "Hoog" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joysticks" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Uitzetten" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "Activ&eren" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Verbonden" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Deactiveren" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3641,23 +3641,23 @@ "Na het uit- of inschakelen van een apparaat zullen de aangesloten joysticks " "niet vernieuwd worden totdat U deze applet herstart." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Joystick testen" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Knoppen" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Force Feedback Testen" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Beschikbare effecten" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3669,6 +3669,10 @@ msgid "Game Controllers" msgstr "Spelbesturing" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Fout bij het omzetten van het object naar een primitief type" diff -Nru wine-development-5.8/po/or.po wine-development-5.9/po/or.po --- wine-development-5.8/po/or.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/or.po 2020-05-22 18:49:34.000000000 +0000 @@ -670,7 +670,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "" @@ -3472,49 +3472,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3524,6 +3524,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/pa.po wine-development-5.9/po/pa.po --- wine-development-5.8/po/pa.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/pa.po 2020-05-22 18:49:34.000000000 +0000 @@ -670,7 +670,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "" @@ -3472,49 +3472,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3524,6 +3524,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/pl.po wine-development-5.9/po/pl.po --- wine-development-5.8/po/pl.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/pl.po 2020-05-22 18:49:34.000000000 +0000 @@ -698,7 +698,7 @@ msgid "Match &Case" msgstr "&Uwzględniaj wielkość liter" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Kierunek" @@ -3600,27 +3600,27 @@ msgid "High" msgstr "Najwyższy" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joysticki" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "Wyłą&cz" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Włącz" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Włączone" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Wyłączone" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3628,23 +3628,23 @@ "Po wyłączeniu lub włączeniu urządzenia, podłączone joysticki nie będą tutaj " "uaktualnione do momentu ponownego uruchomienia tego apletu." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Próba Joysticka" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Przyciski" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Próba odczucia siły zwrotnej" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Dostępne efekty" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3656,6 +3656,10 @@ msgid "Game Controllers" msgstr "Kontrolery gier" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Błąd przy przekształcaniu obiektu do typu podstawowego" diff -Nru wine-development-5.8/po/pt_BR.po wine-development-5.9/po/pt_BR.po --- wine-development-5.8/po/pt_BR.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/pt_BR.po 2020-05-22 18:49:34.000000000 +0000 @@ -688,7 +688,7 @@ msgid "Match &Case" msgstr "&Maiúsculas/minúsculas" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direção" @@ -3571,27 +3571,27 @@ msgid "High" msgstr "Alta" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Controles" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Desativar" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Habilitar" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Conectado" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Desativado" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3599,23 +3599,23 @@ "Depois de habilitar/desabilitar um dispositivo, os controles conectados não " "serão atualizados até que o applet seja reaberto." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Testar Controle" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Botões" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Testar Force Feedback" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Efeitos Disponíveis" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3627,6 +3627,10 @@ msgid "Game Controllers" msgstr "Controles de Jogos" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Erro ao converter objeto em tipo primitivo" diff -Nru wine-development-5.8/po/pt_PT.po wine-development-5.9/po/pt_PT.po --- wine-development-5.8/po/pt_PT.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/pt_PT.po 2020-05-22 18:49:34.000000000 +0000 @@ -704,7 +704,7 @@ msgid "Match &Case" msgstr "&Maiúsculas/minúsculas" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direção" @@ -3604,27 +3604,27 @@ msgid "High" msgstr "Alta" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Desactivar" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Activar" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Conectado" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Desactivado" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3632,23 +3632,23 @@ "Depois de activar ou desactivar um dispositivo, os joysticks ligados não " "serão actualisados aqui até reiniciar esta mini-aplicação." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Testar Joystick" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Botões" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Testar Force Feedback" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Efeitos Disponíveis" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3660,6 +3660,10 @@ msgid "Game Controllers" msgstr "Controladores de Jogo" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Erro ao converter objecto em tipo primitivo" diff -Nru wine-development-5.8/po/rm.po wine-development-5.9/po/rm.po --- wine-development-5.8/po/rm.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/rm.po 2020-05-22 18:49:34.000000000 +0000 @@ -681,7 +681,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "" @@ -3501,49 +3501,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3553,6 +3553,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/ro.po wine-development-5.9/po/ro.po --- wine-development-5.8/po/ro.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ro.po 2020-05-22 18:49:34.000000000 +0000 @@ -679,7 +679,7 @@ msgid "Match &Case" msgstr "Sensibil la registru" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direcție" @@ -3561,49 +3561,49 @@ msgid "High" msgstr "Înalt" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joystick-uri" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Dezactivează" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "Activ&ează" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Conectat" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "&Dezactivat" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Testează joystick-ul" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Butoane" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Efecte disponibile" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3615,6 +3615,10 @@ msgid "Game Controllers" msgstr "Creează un control" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Eroare la convertirea obiectului la un tip primitiv" diff -Nru wine-development-5.8/po/ru.po wine-development-5.9/po/ru.po --- wine-development-5.8/po/ru.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ru.po 2020-05-22 18:49:34.000000000 +0000 @@ -688,7 +688,7 @@ msgid "Match &Case" msgstr "C &учетом регистра" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Направление" @@ -3566,27 +3566,27 @@ msgid "High" msgstr "Высокий" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Джойстики" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Отключить" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Включить" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Подключено" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Выключено" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3594,23 +3594,23 @@ "Список подключенных джойстиков не обновляется автоматически при подключении/" "отключении устройств, требуется перезапуск этой программы." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Проверить джойстик" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Кнопки" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Проверить отдачу" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Доступные эффекты" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3622,6 +3622,10 @@ msgid "Game Controllers" msgstr "Игровые контроллеры" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Ошибка конвертирования объекта в примитивный тип" diff -Nru wine-development-5.8/po/si.po wine-development-5.9/po/si.po --- wine-development-5.8/po/si.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/si.po 2020-05-22 18:49:34.000000000 +0000 @@ -686,7 +686,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "දිශාව" @@ -3493,49 +3493,49 @@ msgid "High" msgstr "වැඩි" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "නියාමක යටි" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "ඕෆ් කරන්න (&D)" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "සබල කරන්න (&E)" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "සබඳිලා" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "ඕෆ් කරලා" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "බොත්තම්" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3545,6 +3545,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/sk.po wine-development-5.9/po/sk.po --- wine-development-5.8/po/sk.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/sk.po 2020-05-22 18:49:34.000000000 +0000 @@ -710,7 +710,7 @@ msgid "Match &Case" msgstr "&Rozlišovať malé a veľké písmená" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Smer" @@ -3530,56 +3530,56 @@ msgid "High" msgstr "Vysoké" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Zakázať" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy #| msgid "&Disable" msgid "&Enable" msgstr "&Zakázať" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy msgid "Connected" msgstr "Súbor nenájdený" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "&Zakázať" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "Available formats" msgid "Available Effects" msgstr "Dostupné formáty" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3589,6 +3589,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/sl.po wine-development-5.9/po/sl.po --- wine-development-5.8/po/sl.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/sl.po 2020-05-22 18:49:34.000000000 +0000 @@ -709,7 +709,7 @@ msgid "Match &Case" msgstr "&Razlikuj velikost črk" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Smer iskanja" @@ -3622,57 +3622,57 @@ msgid "High" msgstr "Visoka" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Onemogoči" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy #| msgid "&enable" msgid "&Enable" msgstr "&omogoči" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy #| msgid "Disconnected" msgid "Connected" msgstr "Povezava je bila prekinjena" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "&Onemogoči" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "Available formats" msgid "Available Effects" msgstr "Razpoložljive oblike" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3684,6 +3684,10 @@ msgid "Game Controllers" msgstr "Ustvari nadzornik" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Napaka med pretvarjanjem predmeta v primitivno vrsto" diff -Nru wine-development-5.8/po/sr_RS@cyrillic.po wine-development-5.9/po/sr_RS@cyrillic.po --- wine-development-5.8/po/sr_RS@cyrillic.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/sr_RS@cyrillic.po 2020-05-22 18:49:34.000000000 +0000 @@ -699,7 +699,7 @@ msgid "Match &Case" msgstr "Подударање &малих и великих слова" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Правац" @@ -3604,54 +3604,54 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 #, fuzzy msgid "&Disable" msgstr "табела" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy msgid "&Enable" msgstr "&Табела" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy msgid "Connected" msgstr "Датотека није пронађена" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy msgid "Disabled" msgstr "табела" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy msgid "Available Effects" msgstr "Н&апред" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3663,6 +3663,10 @@ msgid "Game Controllers" msgstr "Направи контролу" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Грешка у претварању објекта у основну врсту" diff -Nru wine-development-5.8/po/sr_RS@latin.po wine-development-5.9/po/sr_RS@latin.po --- wine-development-5.8/po/sr_RS@latin.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/sr_RS@latin.po 2020-05-22 18:49:34.000000000 +0000 @@ -745,7 +745,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 #, fuzzy msgid "Direction" msgstr "Opis" @@ -3684,54 +3684,54 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Isključi" -#: joy.rc:40 +#: joy.rc:41 #, fuzzy msgid "&Enable" msgstr "&Tabela" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy msgid "Connected" msgstr "Datoteka nije pronađena" -#: joy.rc:43 +#: joy.rc:44 #, fuzzy #| msgid "&Disable" msgid "Disabled" msgstr "&Isključi" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy msgid "Available Effects" msgstr "N&apred" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3743,6 +3743,10 @@ msgid "Game Controllers" msgstr "Napravi kontrolu" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Greška u pretvaranju objekta u osnovnu vrstu" diff -Nru wine-development-5.8/po/sv.po wine-development-5.9/po/sv.po --- wine-development-5.8/po/sv.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/sv.po 2020-05-22 18:49:34.000000000 +0000 @@ -691,7 +691,7 @@ msgid "Match &Case" msgstr "&Skillnad på stora/små bokstäver" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Riktning" @@ -3583,27 +3583,27 @@ msgid "High" msgstr "Hög" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Joysticks" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Inaktivera" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Aktivera" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Ansluten" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Inaktiverad" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3611,23 +3611,23 @@ "Efter att ha inaktiverat eller aktiverat en enhet kommer de anslutna " "styrspakarna inte att uppdateras här innan du startar om detta miniprogram." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Testa joysticken" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Knappar" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Testa kraftåterkoppling" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Tillgängliga effekter" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3639,6 +3639,10 @@ msgid "Game Controllers" msgstr "Spelkontroller" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Kunde inte konvertera objekt till primitiv typ" diff -Nru wine-development-5.8/po/ta.po wine-development-5.9/po/ta.po --- wine-development-5.8/po/ta.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/ta.po 2020-05-22 18:49:34.000000000 +0000 @@ -663,7 +663,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "" @@ -3436,49 +3436,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3488,6 +3488,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/te.po wine-development-5.9/po/te.po --- wine-development-5.8/po/te.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/te.po 2020-05-22 18:49:34.000000000 +0000 @@ -670,7 +670,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "" @@ -3472,49 +3472,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3524,6 +3524,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/th.po wine-development-5.9/po/th.po --- wine-development-5.8/po/th.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/th.po 2020-05-22 18:49:34.000000000 +0000 @@ -677,7 +677,7 @@ msgid "Match &Case" msgstr "พิจารณาตัวเล็ก-ใหญ่" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "ทาง" @@ -3522,52 +3522,52 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 #, fuzzy msgid "Connected" msgstr "ไม่พบแฟ้ม" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 #, fuzzy #| msgid "A&vailable buttons:" msgid "Available Effects" msgstr "ทีเลือกได้:" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3578,6 +3578,10 @@ msgid "Game Controllers" msgstr "เนื้อหา" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/tr.po wine-development-5.9/po/tr.po --- wine-development-5.8/po/tr.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/tr.po 2020-05-22 18:49:34.000000000 +0000 @@ -685,7 +685,7 @@ msgid "Match &Case" msgstr "BÜYÜK/küçük Harf &Duyarlı" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Yön" @@ -3557,27 +3557,27 @@ msgid "High" msgstr "Yüksek" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Oyun Kolları" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "&Devre Dışı Bırak" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Etkinleştir" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Bağlı" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Devre dışı" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3585,23 +3585,23 @@ "Bir aygıtı etkinleştirdiğinizde veya kapattığınızda, siz bu ayarlara yeniden " "girene kadar bağlı oyun kolları burada güncellenmeyecektir." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Oyun Kolunu Test Et" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Düğmeler" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "Zorunlu Geri Beslemeyi Kontrol Et" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Kullanılabilir Efektler" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3613,6 +3613,10 @@ msgid "Game Controllers" msgstr "Oyun Denetleyicileri" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Nesneyi ilkel birime dönüştürürken hata" diff -Nru wine-development-5.8/po/uk.po wine-development-5.9/po/uk.po --- wine-development-5.8/po/uk.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/uk.po 2020-05-22 18:49:34.000000000 +0000 @@ -682,7 +682,7 @@ msgid "Match &Case" msgstr "Враховувати &регістр" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Напрям" @@ -3560,27 +3560,27 @@ msgid "High" msgstr "Високі" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "Джойстик" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "Вим&кнути" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "&Увімкнути" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "Під'єднано" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "Вимкнений" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3588,23 +3588,23 @@ "Після увімкнення чи вимкнення пристрою, під’єднаний джойстик не буде " "оновлений, поки Ви не перезавантажите цей аплет." -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "Випробувати Джойстик" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "Кнопки" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "Доступні Ефекти" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3616,6 +3616,10 @@ msgid "Game Controllers" msgstr "Ігрові Контролери" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "Помилка конвертування об'єкту в примітивний тип" diff -Nru wine-development-5.8/po/wa.po wine-development-5.9/po/wa.po --- wine-development-5.8/po/wa.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/wa.po 2020-05-22 18:49:34.000000000 +0000 @@ -681,7 +681,7 @@ msgid "Match &Case" msgstr "Rispecter les &madjuscules/minuscules" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "Direccion" @@ -3533,49 +3533,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3585,6 +3585,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/wine.pot wine-development-5.9/po/wine.pot --- wine-development-5.8/po/wine.pot 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/wine.pot 2020-05-22 18:49:34.000000000 +0000 @@ -656,7 +656,7 @@ msgid "Match &Case" msgstr "" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "" @@ -3429,49 +3429,49 @@ msgid "High" msgstr "" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3481,6 +3481,10 @@ msgid "Game Controllers" msgstr "" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "" diff -Nru wine-development-5.8/po/zh_CN.po wine-development-5.9/po/zh_CN.po --- wine-development-5.8/po/zh_CN.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/zh_CN.po 2020-05-22 18:49:34.000000000 +0000 @@ -671,7 +671,7 @@ msgid "Match &Case" msgstr "区分大小写(&C)" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "方向" @@ -3505,27 +3505,27 @@ msgid "High" msgstr "高" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "操纵杆" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "停用(&D)" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "启用(&E)" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "已连接" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "停用" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." @@ -3533,23 +3533,23 @@ "在禁用或启用设备之后,已连接的操纵杆的信息将不会在这里更新,直到您重启该小工" "具为止。" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "测试操纵杆" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "按钮" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "测试力反馈" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "可选效果" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3559,6 +3559,10 @@ msgid "Game Controllers" msgstr "游戏控制器" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "将对象转换为基本类型时出错" diff -Nru wine-development-5.8/po/zh_TW.po wine-development-5.9/po/zh_TW.po --- wine-development-5.8/po/zh_TW.po 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/po/zh_TW.po 2020-05-22 18:49:34.000000000 +0000 @@ -680,7 +680,7 @@ msgid "Match &Case" msgstr "大小寫視為相異(&C)" -#: comdlg32.rc:325 joy.rc:71 +#: comdlg32.rc:325 joy.rc:72 msgid "Direction" msgstr "方向" @@ -3545,49 +3545,49 @@ msgid "High" msgstr "高" -#: joy.rc:36 +#: joy.rc:37 msgid "Joysticks" msgstr "搖桿" -#: joy.rc:39 winecfg.rc:212 +#: joy.rc:40 winecfg.rc:212 msgid "&Disable" msgstr "停用(&D)" -#: joy.rc:40 +#: joy.rc:41 msgid "&Enable" msgstr "啟用(&E)" -#: joy.rc:41 +#: joy.rc:42 msgid "Connected" msgstr "已連線" -#: joy.rc:43 +#: joy.rc:44 msgid "Disabled" msgstr "已停用" -#: joy.rc:45 +#: joy.rc:46 msgid "" "After disabling or enabling a device, the connected joysticks won't be " "updated here until you restart this applet." msgstr "停用或啟用裝置之後,已連線的搖桿將無法更新,直到您重新啟動這個小程式。" -#: joy.rc:50 +#: joy.rc:51 msgid "Test Joystick" msgstr "測試搖桿" -#: joy.rc:54 +#: joy.rc:55 msgid "Buttons" msgstr "按鈕" -#: joy.rc:63 +#: joy.rc:64 msgid "Test Force Feedback" msgstr "測試應力回饋" -#: joy.rc:67 +#: joy.rc:68 msgid "Available Effects" msgstr "可用效果" -#: joy.rc:69 +#: joy.rc:70 msgid "" "Press any button in the controller to activate the chosen effect. The effect " "direction can be changed with the controller axis." @@ -3599,6 +3599,10 @@ msgid "Game Controllers" msgstr "遊戲控制器" +#: joy.rc:32 +msgid "Test and configure game controllers." +msgstr "" + #: jscript.rc:28 msgid "Error converting object to primitive type" msgstr "轉換物件到基本類型時發生錯誤" diff -Nru wine-development-5.8/programs/attrib/attrib.c wine-development-5.9/programs/attrib/attrib.c --- wine-development-5.8/programs/attrib/attrib.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/attrib/attrib.c 2020-05-22 18:49:34.000000000 +0000 @@ -74,11 +74,10 @@ } __ms_va_start(parms, format); - SetLastError(NO_ERROR); len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, format, 0, 0, output_bufW, MAX_WRITECONSOLE_SIZE/sizeof(*output_bufW), &parms); __ms_va_end(parms); - if (len == 0 && GetLastError() != NO_ERROR) { + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(format)); return 0; } diff -Nru wine-development-5.8/programs/cmd/wcmdmain.c wine-development-5.9/programs/cmd/wcmdmain.c --- wine-development-5.8/programs/cmd/wcmdmain.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/cmd/wcmdmain.c 2020-05-22 18:49:34.000000000 +0000 @@ -134,12 +134,11 @@ DWORD len; __ms_va_start(ap,format); - SetLastError(NO_ERROR); string = NULL; len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, format, 0, 0, (LPWSTR)&string, 0, &ap); __ms_va_end(ap); - if (len == 0 && GetLastError() != NO_ERROR) + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(format)); else { @@ -160,12 +159,11 @@ DWORD len; __ms_va_start(ap,format); - SetLastError(NO_ERROR); string = NULL; len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, format, 0, 0, (LPWSTR)&string, 0, &ap); __ms_va_end(ap); - if (len == 0 && GetLastError() != NO_ERROR) + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(format)); else { @@ -186,11 +184,10 @@ DWORD len; __ms_va_start(ap,format); - SetLastError(NO_ERROR); len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, format, 0, 0, (LPWSTR)&string, 0, &ap); __ms_va_end(ap); - if (len == 0 && GetLastError() != NO_ERROR) { + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(format)); string = (WCHAR*)LocalAlloc(LMEM_FIXED, 2); *string = 0; diff -Nru wine-development-5.8/programs/explorer/desktop.c wine-development-5.9/programs/explorer/desktop.c --- wine-development-5.8/programs/explorer/desktop.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/explorer/desktop.c 2020-05-22 18:49:34.000000000 +0000 @@ -118,9 +118,49 @@ return S_OK; } +static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size) +{ + unsigned int new_capacity, max_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~(SIZE_T)0 / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(4, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity; + + if (!(new_elements = realloc(*elements, new_capacity * size))) + return FALSE; + + *elements = new_elements; + *capacity = new_capacity; + + return TRUE; +} + +static LONG cookie_counter; + +struct window +{ + LONG cookie, hwnd; + int class; + ITEMIDLIST *pidl; +}; + struct shellwindows { IShellWindows IShellWindows_iface; + CRITICAL_SECTION cs; + + unsigned int count, max; + struct window *windows; }; /* This is not limited to desktop itself, every file browser window that @@ -1140,10 +1180,34 @@ } static HRESULT WINAPI shellwindows_Register(IShellWindows *iface, - IDispatch *disp, LONG hWnd, int class, LONG *cookie) + IDispatch *disp, LONG hwnd, int class, LONG *cookie) { - FIXME("%p 0x%x 0x%x %p\n", disp, hWnd, class, cookie); - return E_NOTIMPL; + struct shellwindows *sw = impl_from_IShellWindows(iface); + struct window *window; + + TRACE("iface %p, disp %p, hwnd %#x, class %u, cookie %p.\n", iface, disp, hwnd, class, cookie); + + if (!hwnd) + return E_POINTER; + + if (disp) + FIXME("Ignoring IDispatch %p.\n", disp); + + EnterCriticalSection(&sw->cs); + + if (!array_reserve((void **)&sw->windows, &sw->max, sw->count + 1, sizeof(*sw->windows))) + { + LeaveCriticalSection(&sw->cs); + return E_OUTOFMEMORY; + } + + window = &sw->windows[sw->count++]; + window->hwnd = hwnd; + window->class = class; + *cookie = window->cookie = ++cookie_counter; + + LeaveCriticalSection(&sw->cs); + return S_OK; } static HRESULT WINAPI shellwindows_RegisterPending(IShellWindows *iface, @@ -1156,14 +1220,62 @@ static HRESULT WINAPI shellwindows_Revoke(IShellWindows *iface, LONG cookie) { - FIXME("0x%x\n", cookie); - return E_NOTIMPL; + struct shellwindows *sw = impl_from_IShellWindows(iface); + unsigned int i; + + TRACE("iface %p, cookie %u.\n", iface, cookie); + + EnterCriticalSection(&sw->cs); + + for (i = 0; i < sw->count; ++i) + { + if (sw->windows[i].cookie == cookie) + { + --sw->count; + memmove(&sw->windows[i], &sw->windows[i + 1], (sw->count - i) * sizeof(*sw->windows)); + LeaveCriticalSection(&sw->cs); + return S_OK; + } + } + + LeaveCriticalSection(&sw->cs); + return S_FALSE; } -static HRESULT WINAPI shellwindows_OnNavigate(IShellWindows *iface, LONG cookie, VARIANT *loc) +static HRESULT WINAPI shellwindows_OnNavigate(IShellWindows *iface, LONG cookie, VARIANT *location) { - FIXME("0x%x %s\n", cookie, debugstr_variant(loc)); - return E_NOTIMPL; + struct shellwindows *sw = impl_from_IShellWindows(iface); + unsigned int i; + + TRACE("iface %p, cookie %u, location %s.\n", iface, cookie, debugstr_variant(location)); + + if (V_VT(location) != (VT_ARRAY | VT_UI1)) + { + FIXME("Unexpected variant type %s.\n", debugstr_vt(V_VT(location))); + return E_NOTIMPL; + } + + EnterCriticalSection(&sw->cs); + + for (i = 0; i < sw->count; ++i) + { + if (sw->windows[i].cookie == cookie) + { + size_t len = V_ARRAY(location)->rgsabound[0].cElements; + if (!(sw->windows[i].pidl = realloc(sw->windows[i].pidl, len))) + { + LeaveCriticalSection(&sw->cs); + return E_OUTOFMEMORY; + } + memcpy(sw->windows[i].pidl, V_ARRAY(location)->pvData, len); + + LeaveCriticalSection(&sw->cs); + return S_OK; + } + } + + LeaveCriticalSection(&sw->cs); + return E_INVALIDARG; } static HRESULT WINAPI shellwindows_OnActivated(IShellWindows *iface, LONG cookie, VARIANT_BOOL active) @@ -1172,26 +1284,49 @@ return E_NOTIMPL; } -static HRESULT WINAPI shellwindows_FindWindowSW(IShellWindows *iface, VARIANT *loc, - VARIANT *root, int class, LONG *hwnd, int options, IDispatch **disp) +static HRESULT WINAPI shellwindows_FindWindowSW(IShellWindows *iface, VARIANT *location, + VARIANT *root, int class, LONG *hwnd, int options, IDispatch **disp) { - TRACE("%s %s 0x%x %p 0x%x %p\n", debugstr_variant(loc), debugstr_variant(root), - class, hwnd, options, disp); + struct shellwindows *sw = impl_from_IShellWindows(iface); + unsigned int i; + + TRACE("iface %p, location %p, root %p, class %#x, hwnd %p, options %#x, disp %p.\n", + iface, location, root, class, hwnd, options, disp); + + if (class == SWC_DESKTOP) + { + *hwnd = (LONG)(LONG_PTR)GetDesktopWindow(); + if (options & SWFO_NEEDDISPATCH) + { + *disp = (IDispatch *)&desktopshellbrowserwindow.IWebBrowser2_iface; + IDispatch_AddRef(*disp); + } + return S_OK; + } + + if (options) + FIXME("Ignoring options %#x.\n", options); - if (class != SWC_DESKTOP) + if (V_VT(location) != (VT_ARRAY | VT_UI1)) { - WARN("only SWC_DESKTOP class supported.\n"); + FIXME("Unexpected variant type %s.\n", debugstr_vt(V_VT(location))); return E_NOTIMPL; } - *hwnd = HandleToLong(GetDesktopWindow()); - if (options & SWFO_NEEDDISPATCH) + EnterCriticalSection(&sw->cs); + + for (i = 0; i < sw->count; ++i) { - *disp = (IDispatch*)&desktopshellbrowserwindow.IWebBrowser2_iface; - IDispatch_AddRef(*disp); + if (sw->windows[i].class == class && ILIsEqual(V_ARRAY(location)->pvData, sw->windows[i].pidl)) + { + *hwnd = sw->windows[i].hwnd; + LeaveCriticalSection(&sw->cs); + return S_OK; + } } - return S_OK; + LeaveCriticalSection(&sw->cs); + return S_FALSE; } static HRESULT WINAPI shellwindows_OnCreated(IShellWindows *iface, LONG cookie, IUnknown *punk) @@ -2157,6 +2292,8 @@ CoInitialize(NULL); shellwindows.IShellWindows_iface.lpVtbl = &shellwindowsvtbl; + InitializeCriticalSection(&shellwindows.cs); + shellwindows.cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": shellwindows.cs"); hr = CoRegisterClassObject(&CLSID_ShellWindows, (IUnknown*)&shellwindows_classfactory.IClassFactory_iface, diff -Nru wine-development-5.8/programs/explorer/explorer.c wine-development-5.9/programs/explorer/explorer.c --- wine-development-5.8/programs/explorer/explorer.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/explorer/explorer.c 2020-05-22 18:49:34.000000000 +0000 @@ -70,6 +70,9 @@ LPITEMIDLIST pidl; IImageList *icon_list; DWORD advise_cookie; + + IShellWindows *sw; + LONG sw_cookie; } explorer_info; enum @@ -77,6 +80,13 @@ BACK_BUTTON,FORWARD_BUTTON,UP_BUTTON }; +static void variant_from_pidl(VARIANT *var, const ITEMIDLIST *pidl) +{ + V_VT(var) = VT_ARRAY | VT_UI1; + V_ARRAY(var) = SafeArrayCreateVector(VT_UI1, 0, ILGetSize(pidl)); + memcpy(V_ARRAY(var)->pvData, pidl, ILGetSize(pidl)); +} + typedef struct { IExplorerBrowserEvents IExplorerBrowserEvents_iface; @@ -265,6 +275,15 @@ STRRET strret; WCHAR *name; + if (This->info->sw) + { + VARIANT var; + + variant_from_pidl(&var, pidl); + IShellWindows_OnNavigate(This->info->sw, This->info->sw_cookie, &var); + VariantClear(&var); + } + ILFree(This->info->pidl); This->info->pidl = ILClone(pidl); update_path_box(This->info); @@ -325,7 +344,35 @@ return &ret->IExplorerBrowserEvents_iface; } -static void make_explorer_window(IShellFolder* startFolder) +static IShellFolder *get_starting_shell_folder(WCHAR *path) +{ + IShellFolder* desktop,*folder; + LPITEMIDLIST root_pidl; + HRESULT hres; + + SHGetDesktopFolder(&desktop); + + if (!path) + return desktop; + + hres = IShellFolder_ParseDisplayName(desktop, NULL, NULL, path, NULL, &root_pidl, NULL); + if(FAILED(hres)) + { + return desktop; + } + hres = IShellFolder_BindToObject(desktop,root_pidl,NULL, + &IID_IShellFolder, + (void**)&folder); + ILFree(root_pidl); + if(FAILED(hres)) + { + return desktop; + } + IShellFolder_Release(desktop); + return folder; +} + +static void make_explorer_window(parameters_struct *params) { RECT rect; HWND rebar,nav_toolbar; @@ -339,8 +386,49 @@ TBBUTTON nav_buttons[3]; int hist_offset,view_offset; REBARBANDINFOW band_info; + VARIANT var, empty_var; + IShellFolder *folder; + IDispatch *dispatch; + WCHAR *path = NULL; + IShellWindows *sw; + ITEMIDLIST *pidl; UINT dpix, dpiy; + DWORD size; + LONG hwnd; HDC hdc; + MSG msg; + + CoCreateInstance(&CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, + &IID_IShellWindows, (void **)&sw); + + if (params->root[0]) + { + size = GetFullPathNameW(params->root, 0, NULL, NULL); + path = malloc(size); + GetFullPathNameW(params->root, size, path, NULL); + } + + if (sw && path) + { + if (!(pidl = ILCreateFromPathW(path))) + { + ERR("Failed to create PIDL for %s.\n", debugstr_w(path)); + IShellWindows_Release(sw); + return; + } + + variant_from_pidl(&var, pidl); + V_VT(&empty_var) = VT_EMPTY; + if (IShellWindows_FindWindowSW(sw, &var, &empty_var, SWC_EXPLORER, &hwnd, 0, &dispatch) == S_OK) + { + TRACE("Found window %#x already browsing path %s.\n", hwnd, debugstr_w(path)); + SetForegroundWindow((HWND)(LONG_PTR)hwnd); + IShellWindows_Release(sw); + return; + } + ILFree(pidl); + VariantClear(&var); + } memset(nav_buttons,0,sizeof(nav_buttons)); @@ -376,6 +464,12 @@ CW_USEDEFAULT,CW_USEDEFAULT,default_width, default_height,NULL,NULL,explorer_hInstance,NULL); + if (sw) + { + IShellWindows_Register(sw, NULL, (LONG_PTR)info->main_window, SWC_EXPLORER, &info->sw_cookie); + info->sw = sw; + } + fs.ViewMode = FVM_DETAILS; fs.fFlags = FWF_AUTOARRANGE; @@ -439,11 +533,20 @@ SendMessageW(rebar,RB_INSERTBANDW,-1,(LPARAM)&band_info); events = make_explorer_events(info); IExplorerBrowser_Advise(info->browser,events,&info->advise_cookie); - IExplorerBrowser_BrowseToObject(info->browser,(IUnknown*)startFolder, - SBSP_ABSOLUTE); + + folder = get_starting_shell_folder(path); + IExplorerBrowser_BrowseToObject(info->browser, (IUnknown *)folder, SBSP_ABSOLUTE); + IShellFolder_Release(folder); + ShowWindow(info->main_window,SW_SHOWDEFAULT); UpdateWindow(info->main_window); IExplorerBrowserEvents_Release(events); + + while (GetMessageW(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } } static void update_window_size(explorer_info *info, int height, int width) @@ -568,6 +671,9 @@ switch(uMsg) { case WM_DESTROY: + IShellWindows_Revoke(info->sw, info->sw_cookie); + IShellWindows_Release(info->sw); + IExplorerBrowser_Unadvise(browser,info->advise_cookie); IExplorerBrowser_Destroy(browser); IExplorerBrowser_Release(browser); @@ -625,47 +731,6 @@ RegisterClassExW(&window_class); } -static IShellFolder* get_starting_shell_folder(parameters_struct* params) -{ - IShellFolder* desktop,*folder; - LPITEMIDLIST root_pidl; - WCHAR *fullpath = NULL; - HRESULT hres; - DWORD size; - - SHGetDesktopFolder(&desktop); - if (!params->root[0]) - { - return desktop; - } - - size = GetFullPathNameW(params->root, 0, fullpath, NULL); - if (!size) - return desktop; - fullpath = heap_alloc(size * sizeof(WCHAR)); - GetFullPathNameW(params->root, size, fullpath, NULL); - - hres = IShellFolder_ParseDisplayName(desktop,NULL,NULL, - fullpath,NULL, - &root_pidl,NULL); - heap_free(fullpath); - - if(FAILED(hres)) - { - return desktop; - } - hres = IShellFolder_BindToObject(desktop,root_pidl,NULL, - &IID_IShellFolder, - (void**)&folder); - ILFree(root_pidl); - if(FAILED(hres)) - { - return desktop; - } - IShellFolder_Release(desktop); - return folder; -} - static WCHAR *copy_path_string(WCHAR *target, WCHAR *source) { INT i = 0; @@ -793,8 +858,6 @@ parameters_struct parameters; HRESULT hres; - MSG msg; - IShellFolder *folder; INITCOMMONCONTROLSEX init_info; memset(¶meters,0,sizeof(parameters)); @@ -817,13 +880,6 @@ ExitProcess(EXIT_FAILURE); } register_explorer_window_class(); - folder = get_starting_shell_folder(¶meters); - make_explorer_window(folder); - IShellFolder_Release(folder); - while(GetMessageW( &msg, NULL, 0, 0 ) != 0) - { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } + make_explorer_window(¶meters); return 0; } diff -Nru wine-development-5.8/programs/net/net.c wine-development-5.9/programs/net/net.c --- wine-development-5.8/programs/net/net.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/net/net.c 2020-05-22 18:49:34.000000000 +0000 @@ -59,9 +59,8 @@ WCHAR str[8192]; int len; - SetLastError(NO_ERROR); len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt, 0, 0, str, ARRAY_SIZE(str), &va_args); - if (len == 0 && GetLastError() != NO_ERROR) + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); else output_write(str, len); diff -Nru wine-development-5.8/programs/notepad/main.c wine-development-5.9/programs/notepad/main.c --- wine-development-5.8/programs/notepad/main.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/notepad/main.c 2020-05-22 18:49:34.000000000 +0000 @@ -215,7 +215,8 @@ if(RegOpenKeyW(HKEY_CURRENT_USER, notepad_reg_key, &hkey) == ERROR_SUCCESS) { WORD data_helper[MAX_PATH]; - DWORD type, data, size; + DWORD type, size; + int point_size; #define QUERY_NOTEPAD_REG(hkey, value_name, ret) do { DWORD type, data; DWORD size = sizeof(DWORD); if(RegQueryValueExW(hkey, value_name, 0, &type, (LPBYTE)&data, &size) == ERROR_SUCCESS) if(type == REG_DWORD) ret = data; } while(0) QUERY_NOTEPAD_REG(hkey, value_fWrap, Globals.bWrapLongLines); @@ -244,10 +245,10 @@ main_rect.bottom = main_rect.top + dy; size = sizeof(DWORD); - if(RegQueryValueExW(hkey, value_iPointSize, 0, &type, (LPBYTE)&data, &size) == ERROR_SUCCESS) + if(RegQueryValueExW(hkey, value_iPointSize, 0, &type, (LPBYTE)&point_size, &size) == ERROR_SUCCESS) if(type == REG_DWORD) /* The value is stored as 10 * twips */ - Globals.lfFont.lfHeight = -MulDiv(abs(data), get_dpi(), 720); + Globals.lfFont.lfHeight = -MulDiv(abs(point_size), get_dpi(), 720); size = sizeof(Globals.lfFont.lfFaceName); if(RegQueryValueExW(hkey, value_lfFaceName, 0, &type, (LPBYTE)&data_helper, &size) == ERROR_SUCCESS) diff -Nru wine-development-5.8/programs/reg/reg.c wine-development-5.9/programs/reg/reg.c --- wine-development-5.8/programs/reg/reg.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/reg/reg.c 2020-05-22 18:49:34.000000000 +0000 @@ -132,10 +132,9 @@ WCHAR *str; DWORD len; - SetLastError(NO_ERROR); len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, fmt, 0, 0, (WCHAR *)&str, 0, &va_args); - if (len == 0 && GetLastError() != NO_ERROR) + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); return; diff -Nru wine-development-5.8/programs/regedit/regedit.c wine-development-5.9/programs/regedit/regedit.c --- wine-development-5.8/programs/regedit/regedit.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/regedit/regedit.c 2020-05-22 18:49:34.000000000 +0000 @@ -55,10 +55,9 @@ WCHAR *str; DWORD len; - SetLastError(NO_ERROR); len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, fmt, 0, 0, (WCHAR *)&str, 0, &va_args); - if (len == 0 && GetLastError() != NO_ERROR) + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); return; diff -Nru wine-development-5.8/programs/regsvr32/regsvr32.c wine-development-5.9/programs/regsvr32/regsvr32.c --- wine-development-5.8/programs/regsvr32/regsvr32.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/regsvr32/regsvr32.c 2020-05-22 18:49:34.000000000 +0000 @@ -51,11 +51,10 @@ } __ms_va_start(va_args, id); - SetLastError(NO_ERROR); len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, fmt, 0, 0, (LPWSTR)&str, 0, &va_args); __ms_va_end(va_args); - if (len == 0 && GetLastError() != NO_ERROR) + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); return; diff -Nru wine-development-5.8/programs/uninstaller/main.c wine-development-5.9/programs/uninstaller/main.c --- wine-development-5.8/programs/uninstaller/main.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/uninstaller/main.c 2020-05-22 18:49:34.000000000 +0000 @@ -84,10 +84,9 @@ WCHAR *str; DWORD len; - SetLastError(NO_ERROR); len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, fmt, 0, 0, (LPWSTR)&str, 0, &va_args); - if (len == 0 && GetLastError() != NO_ERROR) + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); return; diff -Nru wine-development-5.8/programs/wineboot/wineboot.c wine-development-5.9/programs/wineboot/wineboot.c --- wine-development-5.8/programs/wineboot/wineboot.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/wineboot/wineboot.c 2020-05-22 18:49:34.000000000 +0000 @@ -84,34 +84,28 @@ static WCHAR windowsdir[MAX_PATH]; static const BOOL is_64bit = sizeof(void *) > sizeof(int); -static const WCHAR winebuilddirW[] = {'W','I','N','E','B','U','I','L','D','D','I','R',0}; -static const WCHAR winedatadirW[] = {'W','I','N','E','D','A','T','A','D','I','R',0}; -static const WCHAR wineconfigdirW[] = {'W','I','N','E','C','O','N','F','I','G','D','I','R',0}; - /* retrieve the path to the wine.inf file */ static WCHAR *get_wine_inf_path(void) { - static const WCHAR loaderW[] = {'\\','l','o','a','d','e','r',0}; - static const WCHAR wine_infW[] = {'\\','w','i','n','e','.','i','n','f',0}; WCHAR *dir, *name = NULL; - if ((dir = _wgetenv( winebuilddirW ))) + if ((dir = _wgetenv( L"WINEBUILDDIR" ))) { if (!(name = HeapAlloc( GetProcessHeap(), 0, - sizeof(loaderW) + sizeof(wine_infW) + lstrlenW(dir) * sizeof(WCHAR) ))) + sizeof(L"\\loader\\wine.inf") + lstrlenW(dir) * sizeof(WCHAR) ))) return NULL; lstrcpyW( name, dir ); - lstrcatW( name, loaderW ); + lstrcatW( name, L"\\loader" ); } - else if ((dir = _wgetenv( winedatadirW ))) + else if ((dir = _wgetenv( L"WINEDATADIR" ))) { - if (!(name = HeapAlloc( GetProcessHeap(), 0, sizeof(wine_infW) + lstrlenW(dir) * sizeof(WCHAR) ))) + if (!(name = HeapAlloc( GetProcessHeap(), 0, sizeof(L"\\wine.inf") + lstrlenW(dir) * sizeof(WCHAR) ))) return NULL; lstrcpyW( name, dir ); } else return NULL; - lstrcatW( name, wine_infW ); + lstrcatW( name, L"\\wine.inf" ); name[1] = '\\'; /* change \??\ to \\?\ */ return name; } @@ -119,15 +113,14 @@ /* update the timestamp if different from the reference time */ static BOOL update_timestamp( const WCHAR *config_dir, unsigned long timestamp ) { - static const WCHAR timestampW[] = {'\\','.','u','p','d','a','t','e','-','t','i','m','e','s','t','a','m','p',0}; BOOL ret = FALSE; int fd, count; char buffer[100]; - WCHAR *file = HeapAlloc( GetProcessHeap(), 0, lstrlenW(config_dir) * sizeof(WCHAR) + sizeof(timestampW) ); + WCHAR *file = HeapAlloc( GetProcessHeap(), 0, lstrlenW(config_dir) * sizeof(WCHAR) + sizeof(L"\\.update-timestamp") ); if (!file) return FALSE; lstrcpyW( file, config_dir ); - lstrcatW( file, timestampW ); + lstrcatW( file, L"\\.update-timestamp" ); if ((fd = _wopen( file, O_RDWR )) != -1) { @@ -164,10 +157,10 @@ static const WCHAR *prettyprint_configdir(void) { static WCHAR buffer[MAX_PATH]; - WCHAR *p, *path = _wgetenv( wineconfigdirW ); + WCHAR *p, *path = _wgetenv( L"WINECONFIGDIR" ); lstrcpynW( buffer, path, ARRAY_SIZE(buffer) ); - if (lstrlenW( wineconfigdirW ) >= ARRAY_SIZE(buffer) ) + if (lstrlenW( path ) >= ARRAY_SIZE(buffer) ) lstrcpyW( buffer + ARRAY_SIZE(buffer) - 4, L"..." ); if (!wcsncmp( buffer, L"\\??\\unix\\", 9 )) @@ -221,14 +214,12 @@ static void get_identifier( WCHAR *buf, size_t size, const WCHAR *arch ) { - static const WCHAR fmtW[] = {'%','s',' ','F','a','m','i','l','y',' ','%','u',' ','M','o','d','e','l', - ' ','%','u',' ','S','t','e','p','p','i','n','g',' ','%','u',0}; unsigned int family, model, stepping; int regs[4] = {0, 0, 0, 0}; __cpuid( regs, 1 ); model = get_model( regs[0], &stepping, &family ); - swprintf( buf, size, fmtW, arch, family, model, stepping ); + swprintf( buf, size, L"%s Family %u Model %u Stepping %u", arch, family, model, stepping ); } static void get_vendorid( WCHAR *buf ) @@ -505,24 +496,6 @@ /* create the volatile hardware registry keys */ static void create_hardware_registry_keys(void) { - static const WCHAR SystemW[] = {'H','a','r','d','w','a','r','e','\\','D','e','s','c','r','i','p','t','i','o','n','\\', - 'S','y','s','t','e','m',0}; - static const WCHAR fpuW[] = {'F','l','o','a','t','i','n','g','P','o','i','n','t','P','r','o','c','e','s','s','o','r',0}; - static const WCHAR cpuW[] = {'C','e','n','t','r','a','l','P','r','o','c','e','s','s','o','r',0}; - static const WCHAR FeatureSetW[] = {'F','e','a','t','u','r','e','S','e','t',0}; - static const WCHAR IdentifierW[] = {'I','d','e','n','t','i','f','i','e','r',0}; - static const WCHAR ProcessorNameStringW[] = {'P','r','o','c','e','s','s','o','r','N','a','m','e','S','t','r','i','n','g',0}; - static const WCHAR SysidW[] = {'A','T',' ','c','o','m','p','a','t','i','b','l','e',0}; - static const WCHAR ARMSysidW[] = {'A','R','M',' ','p','r','o','c','e','s','s','o','r',' ','f','a','m','i','l','y',0}; - static const WCHAR mhzKeyW[] = {'~','M','H','z',0}; - static const WCHAR VendorIdentifierW[] = {'V','e','n','d','o','r','I','d','e','n','t','i','f','i','e','r',0}; - static const WCHAR PercentDW[] = {'%','d',0}; - static const WCHAR ARMCpuDescrW[] = {'A','R','M',' ','F','a','m','i','l','y',' ','%','d',' ','M','o','d','e','l',' ','%','d', - ' ','R','e','v','i','s','i','o','n',' ','%','d',0}; - static const WCHAR x86W[] = {'x','8','6',0}; - static const WCHAR intel64W[] = {'I','n','t','e','l','6','4',0}; - static const WCHAR amd64W[] = {'A','M','D','6','4',0}; - static const WCHAR authenticamdW[] = {'A','u','t','h','e','n','t','i','c','A','M','D',0}; unsigned int i; HKEY hkey, system_key, cpu_key, fpu_key; SYSTEM_CPU_INFORMATION sci; @@ -544,21 +517,22 @@ { case PROCESSOR_ARCHITECTURE_ARM: case PROCESSOR_ARCHITECTURE_ARM64: - swprintf( id, ARRAY_SIZE(id), ARMCpuDescrW, sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) ); + swprintf( id, ARRAY_SIZE(id), L"ARM Family %u Model %u Revision %u", + sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) ); break; case PROCESSOR_ARCHITECTURE_AMD64: - get_identifier( id, ARRAY_SIZE(id), !wcscmp(vendorid, authenticamdW) ? amd64W : intel64W ); + get_identifier( id, ARRAY_SIZE(id), !wcscmp(vendorid, L"AuthenticAMD") ? L"AMD64" : L"Intel64" ); break; case PROCESSOR_ARCHITECTURE_INTEL: default: - get_identifier( id, ARRAY_SIZE(id), x86W ); + get_identifier( id, ARRAY_SIZE(id), L"x86" ); break; } - if (RegCreateKeyExW( HKEY_LOCAL_MACHINE, SystemW, 0, NULL, REG_OPTION_VOLATILE, - KEY_ALL_ACCESS, NULL, &system_key, NULL )) + if (RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"Hardware\\Description\\System", 0, NULL, + REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &system_key, NULL )) { HeapFree( GetProcessHeap(), 0, power_info ); return; @@ -568,22 +542,22 @@ { case PROCESSOR_ARCHITECTURE_ARM: case PROCESSOR_ARCHITECTURE_ARM64: - set_reg_value( system_key, IdentifierW, ARMSysidW ); + set_reg_value( system_key, L"Identifier", L"ARM processor family" ); break; case PROCESSOR_ARCHITECTURE_INTEL: case PROCESSOR_ARCHITECTURE_AMD64: default: - set_reg_value( system_key, IdentifierW, SysidW ); + set_reg_value( system_key, L"Identifier", L"AT compatible" ); break; } if (sci.Architecture == PROCESSOR_ARCHITECTURE_ARM || sci.Architecture == PROCESSOR_ARCHITECTURE_ARM64 || - RegCreateKeyExW( system_key, fpuW, 0, NULL, REG_OPTION_VOLATILE, + RegCreateKeyExW( system_key, L"FloatingPointProcessor", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &fpu_key, NULL )) fpu_key = 0; - if (RegCreateKeyExW( system_key, cpuW, 0, NULL, REG_OPTION_VOLATILE, + if (RegCreateKeyExW( system_key, L"CentralProcessor", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &cpu_key, NULL )) cpu_key = 0; @@ -591,16 +565,16 @@ { WCHAR numW[10]; - swprintf( numW, ARRAY_SIZE(numW), PercentDW, i ); + swprintf( numW, ARRAY_SIZE(numW), L"%u", i ); if (!RegCreateKeyExW( cpu_key, numW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL )) { - RegSetValueExW( hkey, FeatureSetW, 0, REG_DWORD, (BYTE *)&sci.FeatureSet, sizeof(DWORD) ); - set_reg_value( hkey, IdentifierW, id ); + RegSetValueExW( hkey, L"FeatureSet", 0, REG_DWORD, (BYTE *)&sci.FeatureSet, sizeof(DWORD) ); + set_reg_value( hkey, L"Identifier", id ); /* TODO: report ARM properly */ - set_reg_value( hkey, ProcessorNameStringW, namestr ); - set_reg_value( hkey, VendorIdentifierW, vendorid ); - RegSetValueExW( hkey, mhzKeyW, 0, REG_DWORD, (BYTE *)&power_info[i].MaxMhz, sizeof(DWORD) ); + set_reg_value( hkey, L"ProcessorNameString", namestr ); + set_reg_value( hkey, L"VendorIdentifier", vendorid ); + RegSetValueExW( hkey, L"~MHz", 0, REG_DWORD, (BYTE *)&power_info[i].MaxMhz, sizeof(DWORD) ); RegCloseKey( hkey ); } if (sci.Architecture != PROCESSOR_ARCHITECTURE_ARM && @@ -608,7 +582,7 @@ !RegCreateKeyExW( fpu_key, numW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL )) { - set_reg_value( hkey, IdentifierW, id ); + set_reg_value( hkey, L"Identifier", id ); RegCloseKey( hkey ); } } @@ -625,72 +599,49 @@ /* create the DynData registry keys */ static void create_dynamic_registry_keys(void) { - static const WCHAR StatDataW[] = {'P','e','r','f','S','t','a','t','s','\\', - 'S','t','a','t','D','a','t','a',0}; - static const WCHAR ConfigManagerW[] = {'C','o','n','f','i','g',' ','M','a','n','a','g','e','r','\\', - 'E','n','u','m',0}; HKEY key; - if (!RegCreateKeyExW( HKEY_DYN_DATA, StatDataW, 0, NULL, 0, KEY_WRITE, NULL, &key, NULL )) + if (!RegCreateKeyExW( HKEY_DYN_DATA, L"PerfStats\\StatData", 0, NULL, 0, KEY_WRITE, NULL, &key, NULL )) RegCloseKey( key ); - if (!RegCreateKeyExW( HKEY_DYN_DATA, ConfigManagerW, 0, NULL, 0, KEY_WRITE, NULL, &key, NULL )) + if (!RegCreateKeyExW( HKEY_DYN_DATA, L"Config Manager\\Enum", 0, NULL, 0, KEY_WRITE, NULL, &key, NULL )) RegCloseKey( key ); } /* create the platform-specific environment registry keys */ static void create_environment_registry_keys( void ) { - static const WCHAR EnvironW[] = {'S','y','s','t','e','m','\\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\', - 'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\', - 'E','n','v','i','r','o','n','m','e','n','t',0}; - static const WCHAR NumProcW[] = {'N','U','M','B','E','R','_','O','F','_','P','R','O','C','E','S','S','O','R','S',0}; - static const WCHAR ProcArchW[] = {'P','R','O','C','E','S','S','O','R','_','A','R','C','H','I','T','E','C','T','U','R','E',0}; - static const WCHAR x86W[] = {'x','8','6',0}; - static const WCHAR intel64W[] = {'I','n','t','e','l','6','4',0}; - static const WCHAR amd64W[] = {'A','M','D','6','4',0}; - static const WCHAR authenticamdW[] = {'A','u','t','h','e','n','t','i','c','A','M','D',0}; - static const WCHAR commaW[] = {',',' ',0}; - static const WCHAR ProcIdW[] = {'P','R','O','C','E','S','S','O','R','_','I','D','E','N','T','I','F','I','E','R',0}; - static const WCHAR ProcLvlW[] = {'P','R','O','C','E','S','S','O','R','_','L','E','V','E','L',0}; - static const WCHAR ProcRevW[] = {'P','R','O','C','E','S','S','O','R','_','R','E','V','I','S','I','O','N',0}; - static const WCHAR PercentDW[] = {'%','d',0}; - static const WCHAR Percent04XW[] = {'%','0','4','x',0}; - static const WCHAR ARMCpuDescrW[] = {'A','R','M',' ','F','a','m','i','l','y',' ','%','d',' ','M','o','d','e','l',' ','%','d', - ' ','R','e','v','i','s','i','o','n',' ','%','d',0}; HKEY env_key; SYSTEM_CPU_INFORMATION sci; WCHAR buffer[60], vendorid[13]; const WCHAR *arch, *parch; - if (RegCreateKeyW( HKEY_LOCAL_MACHINE, EnvironW, &env_key )) return; + if (RegCreateKeyW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Session Manager\\Environment", &env_key )) return; get_vendorid( vendorid ); NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL ); - swprintf( buffer, ARRAY_SIZE(buffer), PercentDW, NtCurrentTeb()->Peb->NumberOfProcessors ); - set_reg_value( env_key, NumProcW, buffer ); + swprintf( buffer, ARRAY_SIZE(buffer), L"%u", NtCurrentTeb()->Peb->NumberOfProcessors ); + set_reg_value( env_key, L"NUMBER_OF_PROCESSORS", buffer ); switch (sci.Architecture) { case PROCESSOR_ARCHITECTURE_AMD64: - arch = amd64W; - parch = !wcscmp(vendorid, authenticamdW) ? amd64W : intel64W; + arch = L"AMD64"; + parch = !wcscmp(vendorid, L"AuthenticAMD") ? L"AMD64" : L"Intel64"; break; case PROCESSOR_ARCHITECTURE_INTEL: default: - arch = parch = x86W; + arch = parch = L"x86"; break; } - set_reg_value( env_key, ProcArchW, arch ); + set_reg_value( env_key, L"PROCESSOR_ARCHITECTURE", arch ); switch (sci.Architecture) { case PROCESSOR_ARCHITECTURE_ARM: case PROCESSOR_ARCHITECTURE_ARM64: - swprintf( buffer, ARRAY_SIZE(buffer), ARMCpuDescrW, + swprintf( buffer, ARRAY_SIZE(buffer), L"ARM Family %u Model %u Revision %u", sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) ); break; @@ -698,81 +649,67 @@ case PROCESSOR_ARCHITECTURE_INTEL: default: get_identifier( buffer, ARRAY_SIZE(buffer), parch ); - lstrcatW( buffer, commaW ); + lstrcatW( buffer, L", " ); lstrcatW( buffer, vendorid ); break; } - set_reg_value( env_key, ProcIdW, buffer ); + set_reg_value( env_key, L"PROCESSOR_IDENTIFIER", buffer ); - swprintf( buffer, ARRAY_SIZE(buffer), PercentDW, sci.Level ); - set_reg_value( env_key, ProcLvlW, buffer ); + swprintf( buffer, ARRAY_SIZE(buffer), L"%u", sci.Level ); + set_reg_value( env_key, L"PROCESSOR_LEVEL", buffer ); - swprintf( buffer, ARRAY_SIZE(buffer), Percent04XW, sci.Revision ); - set_reg_value( env_key, ProcRevW, buffer ); + swprintf( buffer, ARRAY_SIZE(buffer), L"%04x", sci.Revision ); + set_reg_value( env_key, L"PROCESSOR_REVISION", buffer ); RegCloseKey( env_key ); } static void create_volatile_environment_registry_key(void) { - static const WCHAR VolatileEnvW[] = {'V','o','l','a','t','i','l','e',' ','E','n','v','i','r','o','n','m','e','n','t',0}; - static const WCHAR AppDataW[] = {'A','P','P','D','A','T','A',0}; - static const WCHAR ClientNameW[] = {'C','L','I','E','N','T','N','A','M','E',0}; - static const WCHAR HomeDriveW[] = {'H','O','M','E','D','R','I','V','E',0}; - static const WCHAR HomePathW[] = {'H','O','M','E','P','A','T','H',0}; - static const WCHAR HomeShareW[] = {'H','O','M','E','S','H','A','R','E',0}; - static const WCHAR LocalAppDataW[] = {'L','O','C','A','L','A','P','P','D','A','T','A',0}; - static const WCHAR LogonServerW[] = {'L','O','G','O','N','S','E','R','V','E','R',0}; - static const WCHAR SessionNameW[] = {'S','E','S','S','I','O','N','N','A','M','E',0}; - static const WCHAR UserNameW[] = {'U','S','E','R','N','A','M','E',0}; - static const WCHAR UserDomainW[] = {'U','S','E','R','D','O','M','A','I','N',0}; - static const WCHAR UserProfileW[] = {'U','S','E','R','P','R','O','F','I','L','E',0}; - static const WCHAR ConsoleW[] = {'C','o','n','s','o','l','e',0}; - static const WCHAR EmptyW[] = {0}; WCHAR path[MAX_PATH]; WCHAR computername[MAX_COMPUTERNAME_LENGTH + 1 + 2]; DWORD size; HKEY hkey; HRESULT hr; - if (RegCreateKeyExW( HKEY_CURRENT_USER, VolatileEnvW, 0, NULL, REG_OPTION_VOLATILE, + if (RegCreateKeyExW( HKEY_CURRENT_USER, L"Volatile Environment", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL )) return; hr = SHGetFolderPathW( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, path ); - if (SUCCEEDED(hr)) set_reg_value( hkey, AppDataW, path ); + if (SUCCEEDED(hr)) set_reg_value( hkey, L"APPDATA", path ); - set_reg_value( hkey, ClientNameW, ConsoleW ); + set_reg_value( hkey, L"CLIENTNAME", L"Console" ); /* Write the profile path's drive letter and directory components into * HOMEDRIVE and HOMEPATH respectively. */ hr = SHGetFolderPathW( NULL, CSIDL_PROFILE | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, path ); if (SUCCEEDED(hr)) { - set_reg_value( hkey, UserProfileW, path ); - set_reg_value( hkey, HomePathW, path + 2 ); + set_reg_value( hkey, L"USERPROFILE", path ); + set_reg_value( hkey, L"HOMEPATH", path + 2 ); path[2] = '\0'; - set_reg_value( hkey, HomeDriveW, path ); + set_reg_value( hkey, L"HOMEDRIVE", path ); } size = ARRAY_SIZE(path); - if (GetUserNameW( path, &size )) set_reg_value( hkey, UserNameW, path ); + if (GetUserNameW( path, &size )) set_reg_value( hkey, L"USERNAME", path ); - set_reg_value( hkey, HomeShareW, EmptyW ); + set_reg_value( hkey, L"HOMESHARE", L"" ); hr = SHGetFolderPathW( NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, path ); if (SUCCEEDED(hr)) - set_reg_value( hkey, LocalAppDataW, path ); + set_reg_value( hkey, L"LOCALAPPDATA", path ); size = ARRAY_SIZE(computername) - 2; if (GetComputerNameW(&computername[2], &size)) { - set_reg_value( hkey, UserDomainW, &computername[2] ); + set_reg_value( hkey, L"USERDOMAIN", &computername[2] ); computername[0] = computername[1] = '\\'; - set_reg_value( hkey, LogonServerW, computername ); + set_reg_value( hkey, L"LOGONSERVER", computername ); } - set_reg_value( hkey, SessionNameW, ConsoleW ); + set_reg_value( hkey, L"SESSIONNAME", L"Console" ); RegCloseKey( hkey ); } @@ -781,10 +718,6 @@ */ static BOOL wininit(void) { - static const WCHAR nulW[] = {'N','U','L',0}; - static const WCHAR renameW[] = {'r','e','n','a','m','e',0}; - static const WCHAR wininitW[] = {'w','i','n','i','n','i','t','.','i','n','i',0}; - static const WCHAR wininitbakW[] = {'w','i','n','i','n','i','t','.','b','a','k',0}; WCHAR initial_buffer[1024]; WCHAR *str, *buffer = initial_buffer; DWORD size = ARRAY_SIZE(initial_buffer); @@ -792,7 +725,7 @@ for (;;) { - if (!(res = GetPrivateProfileSectionW( renameW, buffer, size, wininitW ))) return TRUE; + if (!(res = GetPrivateProfileSectionW( L"rename", buffer, size, L"wininit.ini" ))) return TRUE; if (res < size - 2) break; if (buffer != initial_buffer) HeapFree( GetProcessHeap(), 0, buffer ); size *= 2; @@ -809,7 +742,7 @@ /* split the line into key and value */ *value++ = 0; - if (!lstrcmpiW( nulW, str )) + if (!lstrcmpiW( L"NUL", str )) { WINE_TRACE("Deleting file %s\n", wine_dbgstr_w(value) ); if( !DeleteFileW( value ) ) @@ -827,7 +760,7 @@ if (buffer != initial_buffer) HeapFree( GetProcessHeap(), 0, buffer ); - if( !MoveFileExW( wininitW, wininitbakW, MOVEFILE_REPLACE_EXISTING) ) + if( !MoveFileExW( L"wininit.ini", L"wininit.bak", MOVEFILE_REPLACE_EXISTING) ) { WINE_ERR("Couldn't rename wininit.ini, error %d\n", GetLastError() ); @@ -837,64 +770,24 @@ return TRUE; } -static BOOL pendingRename(void) +static void pendingRename(void) { - static const WCHAR ValueName[] = {'P','e','n','d','i','n','g', - 'F','i','l','e','R','e','n','a','m','e', - 'O','p','e','r','a','t','i','o','n','s',0}; - static const WCHAR SessionW[] = { 'S','y','s','t','e','m','\\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\', - 'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r',0}; WCHAR *buffer=NULL; const WCHAR *src=NULL, *dst=NULL; DWORD dataLength=0; - HKEY hSession=NULL; - DWORD res; - - WINE_TRACE("Entered\n"); - - if( (res=RegOpenKeyExW( HKEY_LOCAL_MACHINE, SessionW, 0, KEY_ALL_ACCESS, &hSession )) - !=ERROR_SUCCESS ) - { - WINE_TRACE("The key was not found - skipping\n"); - return TRUE; - } - - res=RegQueryValueExW( hSession, ValueName, NULL, NULL /* The value type does not really interest us, as it is not - truly a REG_MULTI_SZ anyways */, - NULL, &dataLength ); - if( res==ERROR_FILE_NOT_FOUND ) - { - /* No value - nothing to do. Great! */ - WINE_TRACE("Value not present - nothing to rename\n"); - res=TRUE; - goto end; - } + HKEY hSession; - if( res!=ERROR_SUCCESS ) - { - WINE_ERR("Couldn't query value's length (%d)\n", res ); - res=FALSE; - goto end; - } + if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Session Manager", + 0, KEY_ALL_ACCESS, &hSession )) + return; - buffer=HeapAlloc( GetProcessHeap(),0,dataLength ); - if( buffer==NULL ) - { - WINE_ERR("Couldn't allocate %u bytes for the value\n", dataLength ); - res=FALSE; + if (RegQueryValueExW( hSession, L"PendingFileRenameOperations", NULL, NULL, NULL, &dataLength )) goto end; - } + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, dataLength ))) goto end; - res=RegQueryValueExW( hSession, ValueName, NULL, NULL, (LPBYTE)buffer, &dataLength ); - if( res!=ERROR_SUCCESS ) - { - WINE_ERR("Couldn't query value after successfully querying before (%u),\n" - "please report to wine-devel@winehq.org\n", res); - res=FALSE; + if (RegQueryValueExW( hSession, L"PendingFileRenameOperations", NULL, NULL, + (LPBYTE)buffer, &dataLength )) goto end; - } /* Make sure that the data is long enough and ends with two NULLs. This * simplifies the code later on. @@ -902,19 +795,13 @@ if( dataLength<2*sizeof(buffer[0]) || buffer[dataLength/sizeof(buffer[0])-1]!='\0' || buffer[dataLength/sizeof(buffer[0])-2]!='\0' ) - { - WINE_ERR("Improper value format - doesn't end with NULL\n"); - res=FALSE; goto end; - } for( src=buffer; (src-buffer)*sizeof(src[0])User.Sid, &sid); - if (!RegCreateKeyExW(HKEY_LOCAL_MACHINE, profile_list, 0, NULL, 0, - KEY_ALL_ACCESS, NULL, &hkey, NULL)) + if (!RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", + 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL)) { if (!RegCreateKeyExW(hkey, sid, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &profile_hkey, NULL)) { DWORD flags = 0; if (SHGetSpecialFolderPathW(NULL, profile, CSIDL_PROFILE, TRUE)) - set_reg_value(profile_hkey, profile_image_path, profile); + set_reg_value(profile_hkey, L"ProfileImagePath", profile); RegSetValueExW( profile_hkey, L"Flags", 0, REG_DWORD, (const BYTE *)&flags, sizeof(flags) ); RegCloseKey(profile_hkey); } @@ -1418,7 +1267,7 @@ /* execute rundll32 on the wine.inf file if necessary */ static void update_wineprefix( BOOL force ) { - const WCHAR *config_dir = _wgetenv( wineconfigdirW ); + const WCHAR *config_dir = _wgetenv( L"WINECONFIGDIR" ); WCHAR *inf_path = get_wine_inf_path(); int fd; struct stat st; @@ -1563,13 +1412,6 @@ int __cdecl main( int argc, char *argv[] ) { - static const WCHAR RunW[] = {'R','u','n',0}; - static const WCHAR RunOnceW[] = {'R','u','n','O','n','c','e',0}; - static const WCHAR RunServicesW[] = {'R','u','n','S','e','r','v','i','c','e','s',0}; - static const WCHAR RunServicesOnceW[] = {'R','u','n','S','e','r','v','i','c','e','s','O','n','c','e',0}; - static const WCHAR wineboot_eventW[] = {'\\','K','e','r','n','e','l','O','b','j','e','c','t','s', - '\\','_','_','w','i','n','e','b','o','o','t','_','e','v','e','n','t',0}; - /* First, set the current directory to SystemRoot */ int i, j; BOOL end_session, force, init, kill, restart, shutdown, update; @@ -1655,7 +1497,7 @@ /* create event to be inherited by services.exe */ InitializeObjectAttributes( &attr, &nameW, OBJ_OPENIF | OBJ_INHERIT, 0, NULL ); - RtlInitUnicodeString( &nameW, wineboot_eventW ); + RtlInitUnicodeString( &nameW, L"\\KernelObjects\\__wineboot_event" ); NtCreateEvent( &event, EVENT_ALL_ACCESS, &attr, NotificationEvent, 0 ); ResetEvent( event ); /* in case this is a restart */ @@ -1667,23 +1509,23 @@ pendingRename(); ProcessWindowsFileProtection(); - ProcessRunKeys( HKEY_LOCAL_MACHINE, RunServicesOnceW, TRUE, FALSE ); + ProcessRunKeys( HKEY_LOCAL_MACHINE, L"RunServicesOnce", TRUE, FALSE ); if (init || (kill && !restart)) { - ProcessRunKeys( HKEY_LOCAL_MACHINE, RunServicesW, FALSE, FALSE ); + ProcessRunKeys( HKEY_LOCAL_MACHINE, L"RunServices", FALSE, FALSE ); start_services_process(); } if (init || update) update_wineprefix( update ); create_volatile_environment_registry_key(); - ProcessRunKeys( HKEY_LOCAL_MACHINE, RunOnceW, TRUE, TRUE ); + ProcessRunKeys( HKEY_LOCAL_MACHINE, L"RunOnce", TRUE, TRUE ); if (!init && !restart) { - ProcessRunKeys( HKEY_LOCAL_MACHINE, RunW, FALSE, FALSE ); - ProcessRunKeys( HKEY_CURRENT_USER, RunW, FALSE, FALSE ); + ProcessRunKeys( HKEY_LOCAL_MACHINE, L"Run", FALSE, FALSE ); + ProcessRunKeys( HKEY_CURRENT_USER, L"Run", FALSE, FALSE ); ProcessStartupItems(); } diff -Nru wine-development-5.8/programs/xcopy/xcopy.c wine-development-5.9/programs/xcopy/xcopy.c --- wine-development-5.8/programs/xcopy/xcopy.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/programs/xcopy/xcopy.c 2020-05-22 18:49:34.000000000 +0000 @@ -122,11 +122,10 @@ } __ms_va_start(parms, format); - SetLastError(NO_ERROR); len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, format, 0, 0, output_bufW, MAX_WRITECONSOLE_SIZE/sizeof(*output_bufW), &parms); __ms_va_end(parms); - if (len == 0 && GetLastError() != NO_ERROR) { + if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(format)); return 0; } diff -Nru wine-development-5.8/server/file.h wine-development-5.9/server/file.h --- wine-development-5.8/server/file.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/server/file.h 2020-05-22 18:49:34.000000000 +0000 @@ -173,6 +173,8 @@ extern void free_mapped_views( struct process *process ); extern int get_page_size(void); +extern void init_kusd_mapping( struct mapping *mapping ); + /* device functions */ extern struct object *create_named_pipe_device( struct object *root, const struct unicode_str *name ); diff -Nru wine-development-5.8/server/mapping.c wine-development-5.9/server/mapping.c --- wine-development-5.8/server/mapping.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/server/mapping.c 2020-05-22 18:49:34.000000000 +0000 @@ -35,6 +35,7 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" +#include "ddk/wdm.h" #include "file.h" #include "handle.h" @@ -579,7 +580,7 @@ } opt; } nt; off_t pos; - int size; + int size, opt_size; size_t mz_size, clr_va, clr_size; unsigned int i, cpu_mask = get_supported_cpu_mask(); @@ -595,7 +596,8 @@ size = pread( unix_fd, &nt, sizeof(nt), pos ); if (size < sizeof(nt.Signature) + sizeof(nt.FileHeader)) return STATUS_INVALID_IMAGE_PROTECT; /* zero out Optional header in the case it's not present or partial */ - size = min( size, sizeof(nt.Signature) + sizeof(nt.FileHeader) + nt.FileHeader.SizeOfOptionalHeader ); + opt_size = max( nt.FileHeader.SizeOfOptionalHeader, offsetof( IMAGE_OPTIONAL_HEADER32, CheckSum )); + size = min( size, sizeof(nt.Signature) + sizeof(nt.FileHeader) + opt_size ); if (size < sizeof(nt)) memset( (char *)&nt + size, 0, sizeof(nt) - size ); if (nt.Signature != IMAGE_NT_SIGNATURE) { @@ -943,6 +945,68 @@ return page_mask + 1; } +static KSHARED_USER_DATA *kusd = MAP_FAILED; +static const timeout_t kusd_timeout = 16 * -TICKS_PER_SEC / 1000; + +static void kusd_set_current_time( void *private ) +{ + ULONG system_time_high = current_time >> 32; + ULONG system_time_low = current_time & 0xffffffff; + ULONG interrupt_time_high = monotonic_time >> 32; + ULONG interrupt_time_low = monotonic_time & 0xffffffff; + ULONG tick_count_high = (monotonic_time * 1000 / TICKS_PER_SEC) >> 32; + ULONG tick_count_low = (monotonic_time * 1000 / TICKS_PER_SEC) & 0xffffffff; + KSHARED_USER_DATA *ptr = kusd; + + add_timeout_user( kusd_timeout, kusd_set_current_time, NULL ); + + /* on X86 there should be total store order guarantees, so volatile is enough + * to ensure the stores aren't reordered by the compiler, and then they will + * always be seen in-order from other CPUs. On other archs, we need atomic + * intrinsics to guarantee that. */ +#if defined(__i386__) || defined(__x86_64__) + ptr->SystemTime.High2Time = system_time_high; + ptr->SystemTime.LowPart = system_time_low; + ptr->SystemTime.High1Time = system_time_high; + + ptr->InterruptTime.High2Time = interrupt_time_high; + ptr->InterruptTime.LowPart = interrupt_time_low; + ptr->InterruptTime.High1Time = interrupt_time_high; + + ptr->TickCount.High2Time = tick_count_high; + ptr->TickCount.LowPart = tick_count_low; + ptr->TickCount.High1Time = tick_count_high; + *(volatile ULONG *)&ptr->TickCountLowDeprecated = tick_count_low; +#else + __atomic_store_n(&ptr->SystemTime.High2Time, system_time_high, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->SystemTime.LowPart, system_time_low, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->SystemTime.High1Time, system_time_high, __ATOMIC_SEQ_CST); + + __atomic_store_n(&ptr->InterruptTime.High2Time, interrupt_time_high, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->InterruptTime.LowPart, interrupt_time_low, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->InterruptTime.High1Time, interrupt_time_high, __ATOMIC_SEQ_CST); + + __atomic_store_n(&ptr->TickCount.High2Time, tick_count_high, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->TickCount.LowPart, tick_count_low, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->TickCount.High1Time, tick_count_high, __ATOMIC_SEQ_CST); + __atomic_store_n(&ptr->TickCountLowDeprecated, tick_count_low, __ATOMIC_SEQ_CST); +#endif +} + +void init_kusd_mapping( struct mapping *mapping ) +{ + if (kusd != MAP_FAILED) return; + + grab_object( mapping ); + make_object_static( &mapping->obj ); + + if ((kusd = mmap( NULL, mapping->size, PROT_WRITE, MAP_SHARED, + get_unix_fd( mapping->fd ), 0 )) == MAP_FAILED) + set_error( STATUS_NO_MEMORY ); + else + kusd_set_current_time( NULL ); +} + /* create a file mapping */ DECL_HANDLER(create_mapping) { diff -Nru wine-development-5.8/server/process.c wine-development-5.9/server/process.c --- wine-development-5.8/server/process.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/server/process.c 2020-05-22 18:49:34.000000000 +0000 @@ -1361,6 +1361,7 @@ { struct process_dll *dll; struct process *process = current->process; + struct mapping *mapping; if (is_process_init_done(process)) { @@ -1372,6 +1373,13 @@ set_error( STATUS_DLL_NOT_FOUND ); return; } + if (!(mapping = get_mapping_obj( current->process, req->usd_handle, SECTION_MAP_WRITE ))) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + init_kusd_mapping( mapping ); + release_object( mapping ); /* main exe is the first in the dll list */ list_remove( &dll->entry ); diff -Nru wine-development-5.8/server/protocol.def wine-development-5.9/server/protocol.def --- wine-development-5.8/server/protocol.def 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/server/protocol.def 2020-05-22 18:49:34.000000000 +0000 @@ -854,6 +854,7 @@ mod_handle_t module; /* main module base address */ client_ptr_t ldt_copy; /* address of LDT copy (in thread address space) */ client_ptr_t entry; /* process entry point */ + obj_handle_t usd_handle; /* USD mapping handle */ @REPLY int suspend; /* is process suspended? */ @END diff -Nru wine-development-5.8/server/request.h wine-development-5.9/server/request.h --- wine-development-5.8/server/request.h 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/server/request.h 2020-05-22 18:49:34.000000000 +0000 @@ -784,7 +784,8 @@ C_ASSERT( FIELD_OFFSET(struct init_process_done_request, module) == 16 ); C_ASSERT( FIELD_OFFSET(struct init_process_done_request, ldt_copy) == 24 ); C_ASSERT( FIELD_OFFSET(struct init_process_done_request, entry) == 32 ); -C_ASSERT( sizeof(struct init_process_done_request) == 40 ); +C_ASSERT( FIELD_OFFSET(struct init_process_done_request, usd_handle) == 40 ); +C_ASSERT( sizeof(struct init_process_done_request) == 48 ); C_ASSERT( FIELD_OFFSET(struct init_process_done_reply, suspend) == 8 ); C_ASSERT( sizeof(struct init_process_done_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_pid) == 12 ); diff -Nru wine-development-5.8/server/trace.c wine-development-5.9/server/trace.c --- wine-development-5.8/server/trace.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/server/trace.c 2020-05-22 18:49:34.000000000 +0000 @@ -1317,6 +1317,7 @@ dump_uint64( ", module=", &req->module ); dump_uint64( ", ldt_copy=", &req->ldt_copy ); dump_uint64( ", entry=", &req->entry ); + fprintf( stderr, ", usd_handle=%04x", req->usd_handle ); } static void dump_init_process_done_reply( const struct init_process_done_reply *req ) diff -Nru wine-development-5.8/tools/makedep.c wine-development-5.9/tools/makedep.c --- wine-development-5.8/tools/makedep.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/tools/makedep.c 2020-05-22 18:49:34.000000000 +0000 @@ -152,6 +152,7 @@ static const char *dll_ext; static const char *man_ext; static const char *crosstarget; +static const char *crossdebug; static const char *fontforge; static const char *convert; static const char *flex; @@ -214,6 +215,7 @@ struct strarray unixobj_files; struct strarray res_files; struct strarray c2man_files; + struct strarray debug_files; struct strarray dlldata_files; struct strarray implib_objs; struct strarray all_targets; @@ -1967,7 +1969,10 @@ { /* default to .c for unknown extra object files */ if (strendswith( objs.str[i], ".o" )) - add_generated_source( make, objs.str[i], replace_extension( objs.str[i], ".o", ".c" )); + { + file = add_generated_source( make, objs.str[i], replace_extension( objs.str[i], ".o", ".c" )); + if (make->module || make->staticlib) file->file->flags |= FLAG_C_UNIX; + } else if (strendswith( objs.str[i], ".res" )) add_generated_source( make, replace_extension( objs.str[i], ".res", ".rc" ), NULL ); else @@ -2142,13 +2147,14 @@ /******************************************************************* * add_default_libraries */ -static struct strarray add_default_libraries( const struct makefile *make, struct strarray *deps ) +static struct strarray add_default_libraries( const struct makefile *make, struct strarray *deps, + int add_unix_libs ) { struct strarray ret = empty_strarray; struct strarray all_libs = empty_strarray; unsigned int i, j; - if (!make->use_msvcrt) + if (add_unix_libs) { strarray_add( &all_libs, "-lwine_port" ); strarray_addall( &all_libs, get_expanded_make_var_array( make, "EXTRALIBS" )); @@ -2187,10 +2193,11 @@ * add_import_libs */ static struct strarray add_import_libs( const struct makefile *make, struct strarray *deps, - struct strarray imports, int delay ) + struct strarray imports, int delay, int is_unix ) { struct strarray ret = empty_strarray; unsigned int i, j; + int is_cross = make->is_cross && !is_unix; for (i = 0; i < imports.count; i++) { @@ -2198,7 +2205,7 @@ const char *lib = NULL; /* skip module's own importlib, its object files will be linked directly */ - if (make->importlib && !strcmp( make->importlib, imports.str[i] )) continue; + if (make->importlib && !is_unix && !strcmp( make->importlib, imports.str[i] )) continue; for (j = 0; j < top_makefile->subdirs.count; j++) { @@ -2206,7 +2213,7 @@ if (submake->importlib && !strcmp( submake->importlib, name )) { - if (make->is_cross || !*dll_ext || submake->staticimplib) + if (is_cross || !*dll_ext || submake->staticimplib) lib = base_dir_path( submake, strmake( "lib%s.a", name )); else strarray_add( deps, top_obj_dir_path( make, @@ -2219,9 +2226,9 @@ if (lib) { - if (delay && !delay_load_flag && (make->is_cross || !*dll_ext)) + if (delay && !delay_load_flag && (is_cross || !*dll_ext)) lib = replace_extension( lib, ".a", ".delay.a" ); - else if (make->is_cross) + else if (is_cross) lib = replace_extension( lib, ".a", ".cross.a" ); lib = top_obj_dir_path( make, lib ); strarray_add( deps, lib ); @@ -2342,9 +2349,23 @@ /******************************************************************* + * get_debug_file + */ +static const char *get_debug_file( struct makefile *make, const char *name ) +{ + const char *debug_file = NULL; + if (!make->is_cross || !crossdebug) return NULL; + if (!strcmp( crossdebug, "pdb" )) debug_file = strmake( "%s.pdb", get_base_name( name )); + else if(!strncmp( crossdebug, "split", 5 )) debug_file = strmake( "%s.debug", name ); + if (debug_file) strarray_add( &make->debug_files, debug_file ); + return debug_file; +} + + +/******************************************************************* * output_winegcc_command */ -static void output_winegcc_command( struct makefile *make ) +static void output_winegcc_command( struct makefile *make, int is_cross ) { output( "\t%s -o $@", tools_path( make, "winegcc" )); output_filename( "--wine-objdir" ); @@ -2354,7 +2375,7 @@ output_filename( "--winebuild" ); output_filename( tools_path( make, "winebuild" )); } - if (make->is_cross) + if (is_cross) { output_filename( "-b" ); output_filename( crosstarget ); @@ -2808,6 +2829,9 @@ if (source->file->flags & FLAG_IDL_HEADER) add_install_rule( make, source->name, strmake( "%s.h", obj ), strmake( "d$(includedir)/wine/%s.h", get_include_install_path( obj ) )); + if (source->file->flags & FLAG_IDL_TYPELIB) + add_install_rule( make, source->name, strmake( "%s.tlb", obj ), + strmake( "d$(includedir)/wine/%s.tlb", get_include_install_path( obj ) )); } if (!targets.count) return; @@ -2998,34 +3022,38 @@ struct strarray imports = get_expanded_file_local_var( make, obj, "IMPORTS" ); struct strarray dll_flags = get_expanded_file_local_var( make, obj, "EXTRADLLFLAGS" ); struct strarray all_libs, dep_libs = empty_strarray; - char *dll_name, *obj_name; + char *dll_name, *obj_name, *output_file; + const char *debug_file; if (!imports.count) imports = make->imports; if (!dll_flags.count) dll_flags = make->extradllflags; - all_libs = add_import_libs( make, &dep_libs, imports, 0 ); - add_import_libs( make, &dep_libs, get_default_imports( make ), 0 ); /* dependencies only */ + all_libs = add_import_libs( make, &dep_libs, imports, 0, 0 ); + add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */ dll_name = strmake( "%s.dll%s", obj, make->is_cross ? "" : dll_ext ); obj_name = strmake( "%s%s", obj_dir_path( make, obj ), make->is_cross ? ".cross.o" : ".o" ); + output_file = obj_dir_path( make, dll_name ); strarray_add( &make->clean_files, dll_name ); strarray_add( &make->res_files, strmake( "%s.res", obj )); output( "%s.res: %s\n", obj_dir_path( make, obj ), obj_dir_path( make, dll_name )); - output( "\techo \"%s.dll TESTDLL \\\"%s\\\"\" | %s -u -o $@\n", obj, - obj_dir_path( make, dll_name ), tools_path( make, "wrc" )); + output( "\techo \"%s.dll TESTDLL \\\"%s\\\"\" | %s -u -o $@\n", obj, output_file, + tools_path( make, "wrc" )); - output( "%s:", obj_dir_path( make, dll_name )); + output( "%s:", output_file); output_filename( source->filename ); output_filename( obj_name ); output_filenames( dep_libs ); output_filename( tools_path( make, "winebuild" )); output_filename( tools_path( make, "winegcc" )); output( "\n" ); - output_winegcc_command( make ); + output_winegcc_command( make, make->is_cross ); output_filename( "-s" ); output_filenames( dll_flags ); output_filename( "-shared" ); output_filename( source->filename ); output_filename( obj_name ); + if ((debug_file = get_debug_file( make, output_file ))) + output_filename( strmake( "-Wl,--debug-file,%s", debug_file )); output_filenames( all_libs ); output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" ); output( "\n" ); @@ -3222,13 +3250,14 @@ struct strarray all_libs = empty_strarray; struct strarray dep_libs = empty_strarray; char *module_path = obj_dir_path( make, make->module ); + const char *debug_file = NULL; char *spec_file = NULL; unsigned int i; if (!make->is_exe) spec_file = src_dir_path( make, replace_extension( make->module, ".dll", ".spec" )); - strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->delayimports, 1 )); - strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->imports, 0 )); - add_import_libs( make, &dep_libs, get_default_imports( make ), 0 ); /* dependencies only */ + strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->delayimports, 1, 0 )); + strarray_addall( &all_libs, add_import_libs( make, &dep_libs, make->imports, 0, 0 )); + add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */ if (make->is_cross) { @@ -3241,32 +3270,31 @@ strarray_add( &make->all_targets, strmake( "%s", make->module )); add_install_rule( make, make->module, strmake( "%s", make->module ), strmake( "c$(dlldir)/%s", make->module )); + debug_file = get_debug_file( make, module_path ); output( "%s:", module_path ); } + else if (*dll_ext) + { + strarray_addall( &all_libs, add_default_libraries( make, &dep_libs, !make->use_msvcrt )); + for (i = 0; i < make->delayimports.count; i++) + strarray_add( &all_libs, strmake( "-Wl,-delayload,%s%s", make->delayimports.str[i], + strchr( make->delayimports.str[i], '.' ) ? "" : ".dll" )); + strarray_add( &make->all_targets, strmake( "%s%s", make->module, dll_ext )); + strarray_add( &make->all_targets, strmake( "%s.fake", make->module )); + add_install_rule( make, make->module, strmake( "%s%s", make->module, dll_ext ), + strmake( "p$(dlldir)/%s%s", make->module, dll_ext )); + add_install_rule( make, make->module, strmake( "%s.fake", make->module ), + strmake( "d$(dlldir)/fakedlls/%s", make->module )); + output( "%s%s %s.fake:", module_path, dll_ext, module_path ); + } else { - strarray_addall( &all_libs, add_default_libraries( make, &dep_libs )); - - if (*dll_ext) - { - for (i = 0; i < make->delayimports.count; i++) - strarray_add( &all_libs, strmake( "-Wl,-delayload,%s%s", make->delayimports.str[i], - strchr( make->delayimports.str[i], '.' ) ? "" : ".dll" )); - strarray_add( &make->all_targets, strmake( "%s%s", make->module, dll_ext )); - strarray_add( &make->all_targets, strmake( "%s.fake", make->module )); - add_install_rule( make, make->module, strmake( "%s%s", make->module, dll_ext ), - strmake( "p$(dlldir)/%s%s", make->module, dll_ext )); - add_install_rule( make, make->module, strmake( "%s.fake", make->module ), - strmake( "d$(dlldir)/fakedlls/%s", make->module )); - output( "%s%s %s.fake:", module_path, dll_ext, module_path ); - } - else - { - strarray_add( &make->all_targets, make->module ); - add_install_rule( make, make->module, make->module, - strmake( "p$(%s)/%s", spec_file ? "dlldir" : "bindir", make->module )); - output( "%s:", module_path ); - } + strarray_addall( &all_libs, add_default_libraries( make, &dep_libs, 1 )); + strarray_add( &make->all_targets, make->module ); + add_install_rule( make, make->module, make->module, + strmake( "p$(%s)/%s", spec_file ? "dlldir" : "bindir", make->module )); + debug_file = get_debug_file( make, module_path ); + output( "%s:", module_path ); } if (spec_file) output_filename( spec_file ); @@ -3276,7 +3304,7 @@ output_filename( tools_path( make, "winebuild" )); output_filename( tools_path( make, "winegcc" )); output( "\n" ); - output_winegcc_command( make ); + output_winegcc_command( make, make->is_cross ); if (make->is_cross) output_filename( "-Wl,--wine-builtin" ); if (spec_file) { @@ -3286,10 +3314,48 @@ output_filenames( make->extradllflags ); output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files ); output_filenames_obj_dir( make, make->res_files ); + if (debug_file) output_filename( strmake( "-Wl,--debug-file,%s", debug_file )); output_filenames( all_libs ); output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" ); output( "\n" ); + if (make->unixobj_files.count) + { + struct strarray unix_libs = empty_strarray; + struct strarray unix_deps = empty_strarray; + char *ext, *unix_lib = xmalloc( strlen( make->module ) + strlen( dll_ext ) + 1 ); + strcpy( unix_lib, make->module ); + if ((ext = get_extension( unix_lib ))) *ext = 0; + strcat( unix_lib, dll_ext ); + + if (make->importlib) + { + struct strarray imp = empty_strarray; + strarray_add( &imp, make->importlib ); + strarray_addall( &unix_libs, add_import_libs( make, &unix_deps, imp, 1, 1 )); + } + strarray_addall( &unix_libs, add_import_libs( make, &unix_deps, make->delayimports, 1, 1 )); + strarray_addall( &unix_libs, add_import_libs( make, &unix_deps, make->imports, 0, 1 )); + add_import_libs( make, &unix_deps, get_default_imports( make ), 0, 1 ); /* dependencies only */ + strarray_addall( &unix_libs, add_default_libraries( make, &unix_deps, 1 )); + + strarray_add( &make->all_targets, unix_lib ); + add_install_rule( make, make->module, unix_lib, strmake( "p$(dlldir)/%s", unix_lib )); + output( "%s:", unix_lib ); + output_filenames_obj_dir( make, make->unixobj_files ); + output_filenames( unix_deps ); + output_filename( tools_path( make, "winebuild" )); + output_filename( tools_path( make, "winegcc" )); + output( "\n" ); + output_winegcc_command( make, 0 ); + output_filename( "-shared" ); + if (strarray_exists( &make->extradllflags, "-nodefaultlibs" )) output_filename( "-nodefaultlibs" ); + output_filenames_obj_dir( make, make->unixobj_files ); + output_filenames( unix_libs ); + output_filename( "$(LDFLAGS)" ); + output( "\n" ); + } + if (spec_file && make->importlib) { char *importlib_path = obj_dir_path( make, strmake( "lib%s", make->importlib )); @@ -3411,7 +3477,7 @@ strarray_addall( &dep_libs, get_local_dependencies( make, basename, make->in_files )); strarray_addall( &all_libs, get_expanded_file_local_var( make, basename, "LDFLAGS" )); - strarray_addall( &all_libs, add_default_libraries( make, &dep_libs )); + strarray_addall( &all_libs, add_default_libraries( make, &dep_libs, 1 )); output( "%s:", obj_dir_path( make, make->sharedlib )); output_filenames_obj_dir( make, make->object_files ); @@ -3444,24 +3510,29 @@ char *stripped = replace_extension( make->testdll, ".dll", "_test-stripped.exe" ); char *testres = replace_extension( make->testdll, ".dll", "_test.res" ); struct strarray dep_libs = empty_strarray; - struct strarray all_libs = add_import_libs( make, &dep_libs, make->imports, 0 ); + struct strarray all_libs = add_import_libs( make, &dep_libs, make->imports, 0, 0 ); struct makefile *parent = get_parent_makefile( make ); const char *ext = make->is_cross ? "" : dll_ext; const char *parent_ext = parent && parent->is_cross ? "" : dll_ext; + const char *debug_file; + char *output_file; - add_import_libs( make, &dep_libs, get_default_imports( make ), 0 ); /* dependencies only */ + add_import_libs( make, &dep_libs, get_default_imports( make ), 0, 0 ); /* dependencies only */ strarray_add( &make->all_targets, strmake( "%s%s", testmodule, ext )); strarray_add( &make->clean_files, strmake( "%s%s", stripped, ext )); - output( "%s%s:\n", obj_dir_path( make, testmodule ), ext ); - output_winegcc_command( make ); + output_file = strmake( "%s%s", obj_dir_path( make, testmodule ), ext ); + output( "%s:\n", output_file ); + output_winegcc_command( make, make->is_cross ); output_filenames( make->extradllflags ); output_filenames_obj_dir( make, make->is_cross ? make->crossobj_files : make->object_files ); output_filenames_obj_dir( make, make->res_files ); + if ((debug_file = get_debug_file( make, output_file ))) + output_filename( strmake( "-Wl,--debug-file,%s", debug_file )); output_filenames( all_libs ); output_filename( make->is_cross ? "$(CROSSLDFLAGS)" : "$(LDFLAGS)" ); output( "\n" ); output( "%s%s:\n", obj_dir_path( make, stripped ), ext ); - output_winegcc_command( make ); + output_winegcc_command( make, make->is_cross ); output_filename( "-s" ); output_filename( strmake( "-Wb,-F,%s", testmodule )); output_filenames( make->extradllflags ); @@ -3521,7 +3592,7 @@ if (!objs.count) objs = make->object_files; if (!strarray_exists( &all_libs, "-nodefaultlibs" )) - strarray_addall( &all_libs, add_default_libraries( make, &deps )); + strarray_addall( &all_libs, add_default_libraries( make, &deps, 1 )); output( "%s:", obj_dir_path( make, program ) ); output_filenames_obj_dir( make, objs ); @@ -3899,6 +3970,7 @@ strarray_addall( &make->clean_files, make->crossobj_files ); strarray_addall( &make->clean_files, make->unixobj_files ); strarray_addall( &make->clean_files, make->res_files ); + strarray_addall( &make->clean_files, make->debug_files ); strarray_addall( &make->clean_files, make->all_targets ); strarray_addall( &make->clean_files, make->extra_targets ); @@ -4265,11 +4337,13 @@ if (make->use_msvcrt) { + unsigned int msvcrt_version = 0; for (i = 0; i < make->imports.count; i++) { if (strncmp( make->imports.str[i], "msvcr", 5 ) && strncmp( make->imports.str[i], "ucrt", 4 )) continue; if (crt_dll) fatal_error( "More than one crt DLL imported: %s %s\n", crt_dll, make->imports.str[i] ); crt_dll = make->imports.str[i]; + sscanf( crt_dll, "msvcr%u", &msvcrt_version ); } if (!crt_dll && !strarray_exists( &make->extradllflags, "-nodefaultlibs" )) { @@ -4277,6 +4351,7 @@ strarray_add( &make->imports, crt_dll ); } if (crt_dll && !strncmp( crt_dll, "ucrt", 4 )) strarray_add( &make->define_args, "-D_UCRT" ); + else strarray_add( &make->define_args, strmake( "-D_MSVCR_VER=%u", msvcrt_version )); } LIST_FOR_EACH_ENTRY( file, &make->includes, struct incl_file, entry ) parse_file( make, file, 0 ); @@ -4415,6 +4490,7 @@ man_ext = get_expanded_make_variable( top_makefile, "api_manext" ); dll_ext = (exe_ext && !strcmp( exe_ext, ".exe" )) ? "" : ".so"; crosstarget = get_expanded_make_variable( top_makefile, "CROSSTARGET" ); + crossdebug = get_expanded_make_variable( top_makefile, "CROSSDEBUG" ); fontforge = get_expanded_make_variable( top_makefile, "FONTFORGE" ); convert = get_expanded_make_variable( top_makefile, "CONVERT" ); flex = get_expanded_make_variable( top_makefile, "FLEX" ); diff -Nru wine-development-5.8/tools/widl/typegen.c wine-development-5.9/tools/widl/typegen.c --- wine-development-5.8/tools/widl/typegen.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/tools/widl/typegen.c 2020-05-22 18:49:34.000000000 +0000 @@ -4813,20 +4813,21 @@ if (is_array( arg->declspec.type ) || is_ptr( arg->declspec.type )) align = pointer_size; else type_memsize_and_alignment( arg->declspec.type, &align ); - if (align >= pointer_size) - fprintf( file, "%s;\n", arg->name ); - else - fprintf( file, "DECLSPEC_ALIGN(%u) %s;\n", pointer_size, arg->name ); + if (align < pointer_size) + fprintf( file, "DECLSPEC_ALIGN(%u) ", pointer_size ); + fprintf( file, "%s;\n", arg->name ); } if (add_retval && !is_void( retval->declspec.type )) { print_file(file, 2, "%s", ""); - write_type_decl( file, &retval->declspec, retval->name ); - if (is_array( retval->declspec.type ) || is_ptr( retval->declspec.type ) || - type_memsize( retval->declspec.type ) == pointer_size) - fprintf( file, ";\n" ); - else - fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size ); + write_type_left( file, &retval->declspec, NAME_DEFAULT, TRUE, TRUE ); + if (needs_space_after( retval->declspec.type )) fputc( ' ', file ); + if (!is_array( retval->declspec.type ) && !is_ptr( retval->declspec.type ) && + type_memsize( retval->declspec.type ) != pointer_size) + { + fprintf( file, "DECLSPEC_ALIGN(%u) ", pointer_size ); + } + fprintf( file, "%s;\n", retval->name ); } print_file(file, 1, "} %s;\n", var_decl ); if (needs_packing) print_file( file, 0, "#include \n" ); diff -Nru wine-development-5.8/tools/winegcc/winegcc.c wine-development-5.9/tools/winegcc/winegcc.c --- wine-development-5.8/tools/winegcc/winegcc.c 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/tools/winegcc/winegcc.c 2020-05-22 18:49:34.000000000 +0000 @@ -140,6 +140,7 @@ ; static const char *output_file_name; +static const char *output_debug_file; static int keep_generated = 0; static strarray* tmp_files; #ifdef HAVE_SIGSET_T @@ -227,6 +228,7 @@ const char* subsystem; const char* entry_point; const char* prelink; + const char* debug_file; strarray* prefix; strarray* lib_dirs; strarray* linker_args; @@ -267,6 +269,7 @@ static void cleanup_output_files(void) { if (output_file_name) unlink( output_file_name ); + if (output_debug_file) unlink( output_debug_file ); } static void clean_temp_files(void) @@ -321,6 +324,7 @@ TOOL_CXX, TOOL_CPP, TOOL_LD, + TOOL_OBJCOPY, }; static const struct @@ -330,10 +334,11 @@ const char *deflt; } tool_names[] = { - { "gcc", "clang --driver-mode=gcc", CC }, - { "g++", "clang --driver-mode=g++", CXX }, - { "cpp", "clang --driver-mode=cpp", CPP }, - { "ld", "ld.lld", LD }, + { "gcc", "clang --driver-mode=gcc", CC }, + { "g++", "clang --driver-mode=g++", CXX }, + { "cpp", "clang --driver-mode=cpp", CPP }, + { "ld", "ld.lld", LD }, + { "objcopy", "llvm-objcopy" }, }; static strarray* build_tool_name( struct options *opts, enum tool tool ) @@ -358,7 +363,7 @@ str = strmake("%s-%s", base, opts->version); } else - str = xstrdup(deflt); + str = xstrdup((deflt && *deflt) ? deflt : base); if ((path = find_binary( opts->prefix, str ))) return strarray_fromstring( path, " " ); @@ -511,6 +516,9 @@ /* make sure we don't need a libgcc_s dll on Windows */ strarray_add( flags, "-static-libgcc" ); + if (opts->debug_file && strendswith(opts->debug_file, ".pdb")) + strarray_add(link_args, strmake("-Wl,-pdb,%s", opts->debug_file)); + strarray_addall( link_args, flags ); return link_args; @@ -529,6 +537,14 @@ else strarray_add( flags, strmake("-Wl,-subsystem:%s", opts->gui_app ? "windows" : "console" )); + if (opts->debug_file && strendswith(opts->debug_file, ".pdb")) + { + strarray_add(link_args, "-Wl,-debug"); + strarray_add(link_args, strmake("-Wl,-pdb:%s", opts->debug_file)); + } + else if (!opts->strip) + strarray_add(link_args, "-Wl,-debug:dwarf"); + strarray_addall( link_args, flags ); return link_args; @@ -1091,12 +1107,12 @@ if (strendswith(output_file, ".fake")) fake_module = 1; /* normalize the filename a bit: strip .so, ensure it has proper ext */ - if (strendswith(output_file, ".so")) - output_file[strlen(output_file) - 3] = 0; if ((output_name = strrchr(output_file, '/'))) output_name++; else output_name = output_file; if (!strchr(output_name, '.')) output_file = strmake("%s.%s", output_file, opts->shared ? "dll" : "exe"); + else if (strendswith(output_file, ".so")) + output_file[strlen(output_file) - 3] = 0; output_path = is_pe ? output_file : strmake( "%s.so", output_file ); /* get the filename from the path */ @@ -1192,7 +1208,7 @@ add_library(opts, lib_dirs, files, "winecrt0"); if (opts->use_msvcrt) { - if (!crt_lib) add_library(opts, lib_dirs, files, "msvcrt"); + if (!crt_lib) add_library(opts, lib_dirs, files, "ucrtbase"); else strarray_add(files, strmake("-a%s", crt_lib)); } if (opts->win16_app) add_library(opts, lib_dirs, files, "kernel"); @@ -1388,11 +1404,37 @@ if (libgcc) strarray_add(link_args, libgcc); output_file_name = output_path; + output_debug_file = opts->debug_file; atexit( cleanup_output_files ); spawn(opts->prefix, link_args, 0); strarray_free (link_args); + if (opts->debug_file && !strendswith(opts->debug_file, ".pdb")) + { + strarray *tool, *objcopy = build_tool_name(opts, TOOL_OBJCOPY); + + tool = strarray_dup(objcopy); + strarray_add(tool, "--only-keep-debug"); + strarray_add(tool, output_path); + strarray_add(tool, opts->debug_file); + spawn(opts->prefix, tool, 1); + strarray_free(tool); + + tool = strarray_dup(objcopy); + strarray_add(tool, "--strip-debug"); + strarray_add(tool, output_path); + spawn(opts->prefix, tool, 1); + strarray_free(tool); + + tool = objcopy; + strarray_add(tool, "--add-gnu-debuglink"); + strarray_add(tool, opts->debug_file); + strarray_add(tool, output_path); + spawn(opts->prefix, tool, 0); + strarray_free(tool); + } + /* set the base address with prelink if linker support is not present */ if (opts->prelink && !opts->target) { @@ -1420,13 +1462,10 @@ static void forward(int argc, char **argv, struct options* opts) { strarray* args = strarray_alloc(); - int j; strarray_addall(args, get_translator(opts)); - - for( j = 1; j < argc; j++ ) - strarray_add(args, argv[j]); - + strarray_addall(args, opts->compiler_args); + strarray_addall(args, opts->linker_args); spawn(opts->prefix, args, 0); strarray_free (args); } @@ -1843,6 +1882,11 @@ strarray_add( opts.delayimports, Wl->base[++j] ); continue; } + if (!strcmp(Wl->base[j], "--debug-file") && j < Wl->size - 1) + { + opts.debug_file = strdup( Wl->base[++j] ); + continue; + } if (!strcmp(Wl->base[j], "-static")) linking = -1; strarray_add(opts.linker_args, strmake("-Wl,%s",Wl->base[j])); } @@ -1926,5 +1970,6 @@ else compile(&opts, lang); output_file_name = NULL; + output_debug_file = NULL; return 0; } diff -Nru wine-development-5.8/VERSION wine-development-5.9/VERSION --- wine-development-5.8/VERSION 2020-05-08 20:18:56.000000000 +0000 +++ wine-development-5.9/VERSION 2020-05-22 18:49:34.000000000 +0000 @@ -1 +1 @@ -Wine version 5.8 +Wine version 5.9