diff -Nru wine-staging-2.3.0~ubuntu16.04.1/ANNOUNCE wine-staging-2.4.0~ubuntu16.04.1/ANNOUNCE --- wine-staging-2.3.0~ubuntu16.04.1/ANNOUNCE 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/ANNOUNCE 2017-03-21 14:02:57.000000000 +0000 @@ -1,17 +1,17 @@ -The Wine development release 2.3 is now available. +The Wine development release 2.4 is now available. What's new in this release (see below for details): - - Obsolete wineinstall script removed. + - Built-in implementation of cryptographic hashes. + - Mono engine updated with upstream fixes. - More Direct3D command stream work. - - A few more Shader Model 5 instructions. - - Better underline rendering in DirectWrite. - - Improved ODBC support on 64-bit. + - Simulated bold and italic in DirectWrite. + - Improvements to the XML reader. - Various bug fixes. The source is available from the following locations: - http://dl.winehq.org/wine/source/2.x/wine-2.3.tar.xz - http://mirrors.ibiblio.org/wine/source/2.x/wine-2.3.tar.xz + http://dl.winehq.org/wine/source/2.x/wine-2.4.tar.xz + http://mirrors.ibiblio.org/wine/source/2.x/wine-2.4.tar.xz Binary packages for various distributions will be available from: @@ -27,448 +27,382 @@ ---------------------------------------------------------------- -Bugs fixed in 2.3 (total 41): +Bugs fixed in 2.4 (total 32): - 13249 Putty 0.60: Yes/No/Cancel dialog moving with keyboard arrows - 20215 Extra mouse buttons do not work in Firefox - 23187 DeferWindowPos behaves wrong when invalid HWND - 25700 MessageBox does not display last word if string contains '&' (ampersand) - 33423 Cultures 3 multiplayer hangs while creating a game - 33717 regedit: Sorting registry keys on refreshing - 37070 Missing polygons on 3D objects in Revenant (ddraw:d3d_device7_GetClipStatus iface, clip_status stub) - 37390 Word 2007: crashes when choosing a font - 37976 Poedit 1.7.4 crashes on unimplemented function msvcr120.dll.??0_ReentrantBlockingLock@details@Concurrency@@QAE@XZ - 38354 Multiple games and applications need msvcr120.dll._except1 (Audacity 2.1.0, Tera Online) - 39895 MalwareBytes Anti-malware software needs msvcr100.dll.lldiv implementation - 40488 Revenant crashes when starting a new game - 40948 Multiple apps need api-ms-win-crt-locale-l1-1-0.dll.__initialize_lconv_for_unsigned_char - 40956 unimplemented function msvcr110.dll._Lock_shared_ptr_spin_lock when starting Zoner Photo Studio 18 - 41394 3DMark2001se 'Car chase' speed regression on mesa/nouveau - 41408 Multiple applications crash on unimplemented function msvcp140.dll.??0task_continuation_context@Concurrency@@AAE@XZ - 41682 SPG-Verein 3.2 fails to install, needs advapi32.LookupSecurityDescriptorPartsA - 41725 Unimplemented function api-ms-win-crt-math-l1-1-0.dll._except1 (Starcraft 2 main menu, Firefox) - 41907 Necropolis: Unimplemented copy from WINED3D_LOCATION_TEXTURE_RGB to WINED3D_LOCATION_TEXTURE_RGB for depth/stencil buffers - 41928 Mortal Kombat X needs msvcr110.dll._get_dstbias - 42001 SC2 unimplemented function ucrtbase.dll._except1 - 42129 Steam client - unimplemented function mfreadwrite.dll.MFCreateSourceReaderFromMediaSource - 42138 bug when running reaktor 6: "Unhandled exception: unimplemented function concrt140.dll.??0_ReentrantBlockingLock@details@Concurrency@@QAE@XZ called in 32-bit code (0x7b43bf1c)." - 42240 Kontact 5.6 needs concrt140.dll.??0_ReentrantBlockingLock@details@Concurrency@@QEAA@XZ - 42381 Final Fantasy V crashes - 42405 Drawn lines are too long. - 42426 ReportTool, part of SteuerSparErklaerung 2017 (german tax app) crashes on unimplemented function wlanapi.dll.WlanRegisterNotification - 42463 ZmLearn crash at startup: "Assertion 'm->state == STATE_PASSIVE' failed at pulse/mainloop.c:787, function pa_mainloop_prepare(). Aborting." - 42465 winhttp set_cookies() violates RFC6265 string comparison rules - 42469 GetOpenFileName should expand environment variables in lpstrInitialDir - 42483 Build for Ubuntu Precise fails because MPG123_IGNORE_INFOFRAME is undeclared - 42487 Free Devanagari font Samanata crashes during GPOS processing - 42490 Assertion failure when clicking boxes in altWinDirStat - 42504 Computemark 2.1 runs with Wine 2.2 but black benchmark window.. - 42506 STALKER Shadow of Chernobyl crashes on startup - 42507 Final Fantasy XI Online: Intermittent crashes. - 42509 The Witcher 3 hangs the system on startup - 42511 winnt.h: invalid conversion from 'void*' to 'volatile char*' - 42516 Kholat hangs on splash screen - 42547 winex11.drv compilation fails on systems without XInput2 support - 42567 Acid Pro Trial 7.0e fails to install + 10858 BlueByte Game Channel fails to install + 14371 cleanup undefined members in vartest + 29133 Gómez PEER fails to update + 30378 Xuzhou network client crashes at start + 33987 Secret Files 3 demo shows only some parts of background in ConfigTool + 36599 winhttp/tests/winhttp.c: test_secure_connection() fails under valgrind + 36600 valgrind shows a possible leak in winhttp/tests/winhttp.c + 36608 valgrind shows a definite leak in xmllite/tests/writer.c + 37436 Aliens vs. Predator (2010, Steam) crashes when loading save game + 38793 Lotus Smartsuite 3.1 installer reports insufficient disk space + 39685 Multiple applications crash on startup, need unimplemented function msvcr120.dll.??0event@Concurrency@@QAE@XZ (Rollcage Redux v1.3.8, ARC client, Playstation Now) + 40798 ACDSee Pro 9 (64-bit) needs msvcr120.dll.??0event@Concurrency@@QEAA@XZ + 40910 The Next BIG Thing can't save the game (needs native xmllite) + 41340 Unhandled page fault for Polaris Office Installer + 41472 kolotibablo needs ntoskrnl.exe.KeAcquireInStackQueuedSpinLock + 41684 unimplemented function uiautomationcore.dll.UiaClientsAreListening called in 32-bit code + 41832 Galactic Civ 3 - ships are not visible + 41951 Unimplemented function bcrypt.dll.BCryptDuplicateHash prevents DOOM from running + 42209 Native Instruments Native Access 1.0.25 (R37) crashes on unimplemented function concrt140.dll.??1_ReentrantBlockingLock@details@Concurrency@@QAE@XZ + 42239 Kontact 5.6 needs api-ms-win-crt-time-l1-1-0.dll._Wcsftime + 42450 Unimplemented copy from WINED3D_LOCATION_TEXTURE_RGB to WINED3D_LOCATION_TEXTURE_SRGB for depth/stencil buffers. + 42510 InternetOpenUrl does not send query parameters for HTTPS urls + 42557 NVIDIA GeForce GT 525M detected as GeForce GTX 470 + 42559 Adobe Reader DC: No longer installs (Unimplemented function msi.dll.MsiGetComponentPathExW) + 42575 Multiple applications need msvcp140.dll.?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z + 42576 Poedit crashes on start on unimplemented function msvcp140.dll.?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ + 42578 WSAStringToAddress fails to parse IP v6 addresses with port number + 42586 Adobe Reader DC crashes on startup (needs GetCurrentPackageFullName stub) + 42603 Steep (Ubisoft) needs iphlpapi.dll.NotifyUnicastIpAddressChange + 42625 Flushing file (int 0x21, ah=0x68) fails with access denied error in 16-bit code (affects QuickBooks 5.0) + 42639 Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7eff5a34) + 42641 winetricks ie8_kb2936068 installer fails with error ---------------------------------------------------------------- -Changes since 2.2: +Changes since 2.3: -Alex Henrie (5): - comctl32: Return TRUE from LVM_REDRAWITEMS with bad indices. - user32: Translate WM_(NC)XBUTTONUP to WM_APPCOMMAND in DefWindowProc. - user32: Include space for ampersands when determining MessageBox size. - d3dx9/tests: Fix a copy-paste error in test_D3DXSHMultiply3. - oledb32/tests: Fix a use-after-free in test_converttobyrefwstr. - -Alexandre Julliard (1): - include: Add back a typecast that's needed for C++. - -Alistair Leslie-Hughes (7): - oledb32: Support converting to DBTYPE_BYREF | DBTYPE_STR in DataConvert. - dplayx/tests: Fix memory leaks (valgrind). - include: Add mfreadwrite.idl. - mfreadwrite: Add MFCreateSourceReaderFromMediaSource stub. - dpnet: Handle unknown service GUID in enum_services_providers. - dpwsockx: Implementation of GetCaps callback. - oledb32/tests: Add tests for conversion to DBTYPE_STR. - -Andreas Damm (1): - odbc32: Made ODBC function signatures 64-bit compliant. - -André Hentschel (30): - widl: Initialize decoded_size. - setupapi: Fix some more spec file entries. - ntoskrnl.exe: Fix some spec file entries. - wintrust: Fix CryptCATAdminAcquireContext spec file entry. - shell32: Fix some more spec file entries. - krnl386.exe16: Fix AllocSLCallback spec file entry. - wininet: Fix some more spec file entries. - dbgeng: Fix DebugConnect spec file entry. - d3dx9_36: Fix some spec file entries. - advpack: Fix some spec file entries. - advapi32: Fix even more spec file entries. - msi: Fix some more spec file entries. - urlmon: Fix some spec file entries. - ieframe: Fix IEWinMain spec file entry. - xmllite: Fix CreateXmlReaderInputWithEncodingName spec file entry. - serialui: Fix some spec file entries. - propsys: Fix PSGetPropertyDescriptionListFromString spec file entry. - odbccp32: Fix some spec file entries. - hhcrtl.ocx: Fix some spec file entries. - mscoree: Fix some spec file entries. - gdiplus: Fix GdipCreateStreamOnFile spec file entry. - user32: Fix some spec file entries. - oleaut32: Fix OleLoadPictureEx spec file entry. - kernel32: Fix some more spec file entries. - mscms: Fix some spec file entries. - msvcrt: Fix _CxxThrowException spec file entry. - usp10: Fix ScriptGetProperties spec file entry. - iphlpapi/tests: Test ScopeID only for IPv6. - tapi32: Fix phoneInitializeExW spec file entry. - d3dx9: Fix some spec file entries. - -Aurimas Fišeras (1): - po: Update Lithuanian translation. - -Austin English (2): - advapi32: Add LookupSecurityDescriptorPartsA/W stubs. - tools: Remove wineinstall. - -Bruno Jesus (15): - ws2_32: Trace accept() error. - ws2_32/tests: Add IP_HDRINCL tests. - winemp3.acm: Fixes compilation for older mpg123 library versions. - ws2_32: Cope with NULL address in connect() call. - include: Add missing GetIfTable2 to netioapi.h. - ws2_32/tests: Add a 2 buffer WSARecv test. - winegstreamer: Avoid a magic number for empty offset. - ws2_32: Discard MSG_PARTIAL as it is supported only in message protocols. - ws2_32: Make it clear that bit flags are in hex when tracing. - wined3d: Recognize Geforce GT 525M. - wine.inf: Add RtlTryEnterCriticalSection to default RelayExclude. - winmm: Cope with empty string in mciSendString. - ws2_32: Turn SIO_GET_EXTENSION_FUNCTION_POINTER into a table. - ws2_32/tests: Rework WSAStringToAddress tests. - ws2_32: Fix WSAStringToAddress parsing for IPv6. - -Carlo Bramini (1): - msvcrt: Use return value of *printf() instead of calling strlen() and simplify code. - -Chris Morgan (1): - winex11: Wrap XInput2 dependent functions with appropriate #ifdef. - -Eric Kohl (1): - comctl32: Update the tooltip rectangle when a tool button is hidden. - -Fabian Maurer (2): - user32: Send WM_NCPAINT and WM_ERASEBKGND when window is shown. - user32: Only send position-change messages when needed. - -François Gouget (24): - odbccp32: Add a __WINE_ALLOC_SIZE attribute to heap_alloc(). - netprofm: Add a __WINE_ALLOC_SIZE attribute to heap_alloc(). - msident: Add a __WINE_ALLOC_SIZE attribute to heap_alloc(). - hlink: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - dnsapi: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - user32/tests: Occasional spelling fixes in comments. - msxml3: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - dwrite: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - urlmon: Add a __WINE_ALLOC_SIZE attribute to heap_alloc(). - jscript: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - ieframe: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - webservices: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - wbemdisp: Simplify and standardize the heap_xxx() declarations. - pdh: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - oledb32: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - taskschd: Simplify and standardize the heap_xxx() declarations. - wine/test.h: Identify the process responsible for test summary lines. - vbscript: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - urlmon: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - xmllite: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - gdiplus: Simplify and standardize the heap_xxx() declarations. - usp10: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. - wbemprox: Simplify and standardize the heap_xxx() declarations. - wmiutils: Simplify and standardize the heap_xxx() declarations. - -Gerald Pfeifer (1): - propsys: Use snprintf in PROPVAR_ConvertFILETIME. - -Guillaume Charifi (2): - wined3d: Recognize SM5 dcl_hs_join_phase_instance_count instruction. - wined3d: Recognize SM5 vJoinInstanceId register. - -Hans Leidekker (6): - winhttp: Parse cookie attributes. - winhttp: Cookie attributes are case-insensitive. - winhttp/tests: Fix two memory leaks. - webservices: Enforce the heap limit. - riched20/tests: Add a test to show that empty paragraphs get a font size declaration. - msi: Implement MsiGetComponentPathExA/W. - -Henri Verbeet (45): - wined3d: Send light updates through the command stream. - wined3d: Send light enable updates through the command stream. - wined3d: Parse the shader version in shader_sm4_init(). - wined3d: Validate the SM4 token count (AFL). - wined3d: Explicitly pass the byte-code format to shader creation functions (AFL). - wined3d: Store used pixel shader input registers as a bitmap (AFL). - wined3d: Validate WINED3DSPR_TEXCRDOUT indices in shader_get_registers_used() (AFL). - wined3d: Validate ps 1.x sampler indices in shader_get_registers_used(). - usp10: Properly get glyph widths for OpenType fonts in ScriptPlaceOpenType(). - usp10: Introduce an enumeration for GPOS lookup types. - usp10: Return the logical offset in GPOS_apply_PairAdjustment(). - usp10: Return the logical offset in GPOS_apply_ContextPos(). - usp10: Return the logical offset in GPOS_apply_ChainContextPos(). - usp10: Return the logical offset in GPOS_apply_lookup(). - usp10: Iterate in visual order in GPOS_apply_feature(). - wined3d: Return a BOOL from surface_load_location(). - wined3d: Return a failure if the location couldn't be loaded in surface_load_sysmem(). - wined3d: Check for depth/stencil surfaces in individual surface location loaders. - wined3d: Merge surface_convert_depth_to_float() into wined3d_format_convert_color_to_float(). - wined3d: Support depth formats in wined3d_format_convert_from_float(). - wined3d: Copy the shader byte-code before initialising the front-end. - wined3d: Validate WINED3D_LOCATION_BUFFER on WINED3D_MAP_DISCARD buffer maps. - d2d1/tests: Add tests for drawing simple shapes. - d2d1: Create open, hollow geometry in d2d_d3d_render_target_DrawLine(). - wined3d: Support downloading depth textures in surface_load_sysmem(). - wined3d: Support uploading depth textures in surface_load_texture(). - wined3d: Get rid of the depth/stencil FIXME in texture_resource_sub_resource_unmap(). - wined3d: Implement depth fills in the CPU blitter. - ddraw/tests: Test depth fill results in test_color_fill(). - wined3d: Get rid of some redundant "texture" accesses in texture_resource_sub_resource_map(). - wined3d: Do not record the GL primitive type in stateblocks. - wined3d: Pass the primitive type to wined3d_cs_emit_draw(). - wined3d: Use the command stream state in device_clear_render_targets(). - wined3d: Use the command stream state in wined3d_cs_exec_clear(). - usp10: Introduce an enumeration for GSUB lookup types. - wined3d: Use the command stream state in wined3d_cs_exec_draw(). - wined3d: Use the command stream state in wined3d_cs_exec_dispatch(). - wined3d: Use the command stream state in swapchain_gl_present(). - wined3d: Get rid of an unneeded context_release() in swapchain_init(). - wined3d: Send swapchain context destruction through the command stream. - wined3d: Send swapchain context creation through the command stream. - ddraw: Avoid destroying ddraw objects from DllMain(). - usp10: Make feature tables const. - usp10: Use memmove() in GSUB_apply_LigatureSubst(). - usp10: Use USP10_FindGlyphInLogClust() in UpdateClusters(). - -Hugh McMaster (3): - regedit/tests: Test import with non-standard registry file headers. - reg/tests: Test import with non-standard registry file headers. - reg/tests: Add some line concatenation tests. - -Huw D. M. Davies (12): - widl: Add missing width and alignment for VARIANT. - dsound: Correctly update buflen. - dsound: Merge two identical allocation blocks. - dsound: Allow enough space for multi-channel frames. - oledb32: Fixed length calculation in conversion to DBTYPE_STR. - oledb32: Fix conversion of strings with embedded '\0' to DBTYPE_STR | DBTYPE_BYREF. - dsound: Don't propagate writepos in the non-WRITEPRIMARY case - it's unused. - dsound: Use frame rather than byte counts to clarify the mixing. - dsound: Pass sample count to the normfunction. - riched20: Write the char format for the end-of-paragraph marker. - riched20: Remove a hack that should be longer be needed. - riched20: Add linefeeds after the colortbl and generator groups. - -Jacek Caban (31): - msvcrt: Added lldiv implementation. - ole32: Added generic class factory implementation and use it for file moniker. - ole32: Use generic class factory for item moniker. - ole32: Use generic class factory for anti moniker. - ole32: Use generic class factory for composite moniker. - ole32: Use generic class factory for class moniker. - ole32: Use generic class factory for pointer moniker. - ole32: Use generic class factory for StdComponentCategoriesMgr object. - server: Removed no longer needed user_arg from irp_call struct. - server: Allow creating async object not associated with a queue. - server: Create async objects in read and write request handlers. - server: Create async object in register_async handler. - server: Create async object in ioctl request handler. - server: Create async object in flush request handler. - server: Pass existing async object to fd_queue_async. - server: Introduced new pipe_end struct containing common parts of pipe_client and pipe_server. - server: Moved server-independent parts of pipe_server_flush into separated function. - uiautomationcore: Added stub dll. - uiautomationcore: Added UiaClientsAreListening stub. - ole32: Added GlobalOptions object stub implementation. - shlobj.h: Added SHGetPathFromIDListEx declaration. - shlwapi: Fixed error handling in StrRetToBufW. - shell32: Added SHGetPathFromIDListEx implementation. - wininet: Improved netconn_drain_content. - secur32: Added support for SECPKG_ATTR_ENDPOINT_BINDINGS in schannel. - psapi.h: Added support for PSAPI_VERSION version 2. - dbghelp: Removed no longer needed psapi import. - dxdiagn: Removed no longer needed psapi import. - taskkill: Removed no longer needed psapi import. - taskmgr: Removed no longer needed psapi import. - winedbg: Removed no longer needed psapi import. - -Jetro Jormalainen (2): - dinput: Keep username same between device objects. - dinput: Handle username in EnumDevicesBySemantics. - -Józef Kucia (69): - d3d11/tests: Properly check if raw buffers are supported. - d3d8: Allocate WINED3DCAPS on stack. - d3d9: Allocate WINED3DCAPS on stack. - wined3d: Expose double precision shader capability in WINED3DCAPS. - d3d11: Implement CheckFeatureSupport() for D3D11_FEATURE_DOUBLES. - wined3d: Fix swizzle for ld_raw instruction. - wined3d: Get rid of shader_glsl_get_version_declaration(). - wined3d: Request compatibility profile in GLSL for legacy contexts. - d3d8: Get rid of WINECAPSTOD3D8CAPS() macro. - d3d8: Merge fixup_caps() into d3dcaps_from_wined3dcaps(). - d3d9: Get rid of WINECAPSTOD3D9CAPS() macro. - d3d9: Merge filter_caps() into d3dcaps_from_wined3dcaps(). - wined3d: Get rid of "tmp" variables in wined3d_adapter_init_limits(). - wined3d: Store actual GL_MAX_TEXTURE_IMAGE_UNITS in "fragment_samplers". - wined3d: Check if texture unit mapping is required in context_update_tex_unit_map(). - wined3d: Load unordered access resources before binding shader resources. - wined3d: Do not try to invalidate compute states for freshly created contexts. - wined3d: Do not read rev_tex_unit_mapping for texture units >= MAX_COMBINED_SAMPLERS. - wined3d: Allocate "context->texture_type" dynamically. - wined3d: Introduce wined3d_device_set_cs_resource_view(). - d3d11: Implement d3d11_immediate_context_CSSetShaderResources(). - wined3d: Introduce wined3d_device_set_cs_sampler(). - d3d11: Implement d3d11_immediate_context_CSSetSamplers(). - wined3d: Allocate texture binding set for compute pipeline. - wined3d: Load sampler bindings for compute shaders. - wined3d: Implement compute shader resource binding. - wined3d: Fix return type for surface_load_texture(). - wined3d: Fix handling of SM4+ integer registers. - wined3d: Handle structured UAV declarations. - wined3d: Implement SM5 store_structured instruction. - wined3d: Pass structure byte stride to wined3d_buffer_create(). - wined3d: Implement structured buffer views. - d3d11/tests: Add test for compute shader input registers. - wined3d: Extract common code to validate_shader_resource_view(). - wined3d: Use string_buffer_sprintf() in shader_glsl_sprintf_cast(). - wined3d: Record sampler usage for ld_structured. - wined3d: Handle structured resource declarations. - wined3d: Implement ld_structured instruction. - wined3d: Update UAV read bitmask for ld_raw and ld_structured instructions. - wined3d: Always use correct sampler bind index for ld_raw and ld_structured. - d3d11/tests: Add test for ld_structured instruction. - wined3d: Allow swizzle on vThreadIDInGroupFlattened register. - wined3d: Use GL_ARB_shading_language_420pack for swizzle operations on scalars. - wined3d: Implement [imm_]atomic_{umax, umin} instructions for unsigned integers. - wined3d: Implement [imm_]atomic_{imax, imin} instructions for signed integers. - wined3d: Do not crash when attempting to issue draw call with no attachments. - wined3d: Pass wined3d_caps_gl_ctx to driver quirk match() function. - wined3d: Add quirk for Nvidia viewport subpixel bits bug. - wined3d: Implement atomic instructions on structured buffer memory. - wined3d: Introduce helper function to reserve memory for arrays. - wined3d: Handle raw thread group shared memory declarations. - wined3d: Handle structured thread group shared memory declarations. - wined3d: Add shader_reg_maps_add_tgsm() helper function. - wined3d: Add support for ld_raw on thread group shared memory. - wined3d: Rename shader_glsl_ld_buffer() to shader_glsl_ld_raw_structured(). - wined3d: Add support for atomic operations on thread group shared memory. - wined3d: Add support for store_{raw, structured} on thread group shared memory. - wined3d: Implement SM5 sync instruction. - wined3d: Add ARB_shader_storage_buffer_object extension. - d3d11/tests: Add test for thread group shared memory. - wined3d: Don't leak texture in wined3d_unordered_access_view_destroy_object(). - wined3d: Add support for atomic min/max operations on thread group shared memory. - wined3d: Add FIXME() for unhandled UAV flags. - wined3d: Add ARB_shader_atomic_counters extension. - wined3d: Implement SM5 imm_atomic_alloc instruction. - wined3d: Implement SM5 imm_atomic_consume instruction. - wined3d: Implement UAV counters. - ntdll/tests: Add test for flushing file with FILE_APPEND_DATA access. - ntdll: Fix NtFlushBuffersFile() for files with FILE_APPEND_DATA access. - -Kim Malmo (1): - po: Update Norwegian translation. - -Lauri Kenttä (3): - po: Update Finnish translation. - readme: Update Finnish translation. - readme: Update Swedish translation. - -Louis Lenders (2): - httpapi: Add stub for HttpCreateServerSession. - wmvcore: Add version resource. - -Marcin Mikołajczak (1): - po: Updated Polish translation. - -Matteo Bruni (3): - wined3d: Don't require a separate sRGB GL texture if the format doesn't support sRGB reads. - wined3d: Fix querying texture-related limits on core profile. - ddraw: Get rid of multiple interfaces from vertex buffer objects. - -Michael Müller (1): - wininet: Handle query parameters for HTTPS urls in InternetOpenUrlW. - -Nikolay Sivov (25): - regedit: Sort each of top level branches separately. - oledlg: Use W-functions to access window property. - explorerframe: Use W-functions to access window property. - include: Fix PROPSHEETPAGE_V4_SIZE definition. - comctl32/tests: Some tests for property page initialization. - po: Update Russian translation. - comdlg32: Expand initial directory path for file open dialog. - comdlg32: Consolidate file dialog initialization to avoid duplication. - comdlg32: Use GetPropW() to get to file dialog data. - usp10: Ignore device tables with invalid delta format. - dwrite/tests: Test runHeight underline attribute with all available fonts. - dwrite: Set runHeight attribute for underlines. - d2d1: Use DrawLine() to draw underlines. - dxgi: Fix naming in error traces. - ddraw: Remove references to IWineD3DDevice that doesn't exist anymore. - d3d8: Fix debug messages. - d2d1: Support strikethrough in DrawText()/DrawTextLayout(). - usp10: Filter out DeltaFormat == 0 too, valid range is [1, 3]. - shell32: Implement SHGetPropertyStoreFromParsingName() as a wrapper over IShellItem2. - gdiplus/tests: Fix region leak (Valgrind). - comctl32/propsheet: Enforce minimal PROPSHEETPAGE structure size when creating a page. - comctl32/propsheet: Implement PSPCB_ADDREF/PSPCB_RELEASE notifications. - xmllite/reader: Fix writing back resolved character reference value. - xmllite/writer: Implement WriteString(). - xmllite/writer: Fix Release() trace. - -Paul Gofman (2): - ntdll/tests: Add test for NtFlushBuffersFile error conditions. - ntdll: NtFlushBuffersFile should fail if the file handle has no write access. +Akihiro Sagawa (2): + iexplore: Follow translation version info to detect native IE. + Use CP 1200 (Unicode) for Win32/Win64 version info. + +Alex Henrie (1): + crypt32/tests: Print an error if CertOpenStore fails. + +Alexandre Julliard (6): + gdi32: Add more helper functions for RGB to pixel conversions. + gdi32: Fix color conversion when blitting to 1-bpp by matching pixels instead of color values. + gdi32: Add support for DIBINDEX colors in 1-bpp blits. + gdi32: Map the black and white entries to the DIB color table after dithering. + gdi32/tests: Remove workarounds for old Windows versions in the DIB tests. + user32/tests: Re-enable a test about window positions. + +Alistair Leslie-Hughes (10): + dplayx: Skip over unknown DataTypes guids in EnumAddressTypes. + dplayx/tests: Free IDirectPlayLobby objects. + include: Add msstkppg.h. + ole32/tests: Stop crash on XP. + oledb32: Ignore IRunnableObject in IDataSourceLocator_QueryInterface. + dpnet/tests: Stop thread test from failing. + odbccp32: Implement SQLInstallDriverEx. + oledb32: Support DBTYPE_NUMERIC in IDataConvert GetConversionSize. + dpnet/tests: Show that async handlers are per object. + dpnet/tests: Add EnumHosts synchronous tests. + +Andrew Wesie (1): + ntdll: Save rdi and rsi in raise_func_trampoline. + +André Hentschel (3): + iphlpapi: Add stub for NotifyUnicastIpAddressChange. + iphlpapi: Flesh out NotifyIpInterfaceChange arguments. + opencl: Fix some spec file entries. + +Austin English (4): + ntoskrnl.exe: Add KeAcquireInStackQueuedSpinLock stub. + ntoskrnl.exe: Add KeWaitForMultipleObjects stub. + dhcpcsvc: Add DhcpCApiInitialize and DhcpCApiCleanup stubs. + setupapi: Add SetupDiEnumDriverInfoA/W stubs. + +Bruno Jesus (9): + mciavi32: Trace MCIAVI_CreateWindow. + mciavi32: Implement MCI_BREAK. + winmm: Dispatch MCI_BREAK to the driver. + wininet: Forward InternetGetConnectedState to Ex function. + include: Add missing connection check flags to wininet.h. + iphlpapi/tests: Test route type and protocol in GetIpForwardTable. + wininet/test: Improve tests for InternetGetConnectedStateEx. + kernel32/tests: Add 64bit number tests for FormatMessage[A|W]. + wined3d: Recognize GeForce 940M. + +Daniel Lehman (2): + msvcrt: Add Concurrency::event stubs. + msxml3: Don't QI for IPersistStream in internal_parse. + +Fabian Maurer (1): + comctl32/taskdialog: Move TaskDialogIndirect and its tests into own source files. + +François Gouget (6): + ddraw/tests: Spelling fixes in comments and an ok() message. + ntdll/tests: A spelling fix in an ok() message. + scrobj: Make scriptlet_typelib_CreateInstance() static. + schedsvc/tests: Add the current process id to the test summary line. + advapi32/tests: Trace the display name if CreateService() unexpectedly succeeds. + ddraw: Make ddraw_destroy_swapchain() static. + +Hans Leidekker (8): + webservices: Implement WS_HEAP_PROPERTY_REQUESTED_SIZE and WS_HEAP_PROPERTY_ACTUAL_SIZE. + webservices: Protect messages with a critical section. + webservices: Protect channels with a critical section. + webservices: Protect proxies with a critical section. + webservices: Protect writers with a critical section. + webservices: Protect errors with a critical section. + webservices: Protect heaps with a critical section. + webservices: Protect readers with a critical section. + +Henri Verbeet (30): + wined3d: Map buffers in wined3d_device_process_vertices(). + wined3d: Explicitly pass d3d_info and gl_info to context_stream_info_from_declaration(). + wined3d: Send sub-resource update calls through the command stream. + wined3d: Check rectangle alignment in wined3d_surface_blt(). + wined3d: Merge wined3d_texture_check_block_align() into wined3d_texture_check_box_dimensions(). + usp10/tests: Add a latn shaping test with ligatures. + usp10/tests: Add a ligature and diacritic to the syrc shaping test. + usp10: Take the script direction into account when applying OpenType features. + usp10: Properly determine the glyph run direction when shaping Script_Arabic. + usp10/tests: Add shaping tests for fLogicalOrder and fRTL. + wined3d: Use wined3d_texture_blt() in surface_upload_from_surface(). + wined3d: Validate blit parameters in wined3d_texture_blt(). + wined3d: Send blits through the command stream. + wined3d: Send sub-resource copy calls through the command stream. + wined3d: Send resource copy calls through the command stream. + wined3d: Abort on invalid instructions in shader_generate_main(). + wined3d: Abort on invalid instructions in shader_get_registers_used(). + usp10: Do not fall back to presentation form B if the contextual feature exists in ContextualShape_Arabic(). + usp10: Introduce an enumeration for script types. + usp10: Use bsearch() to lookup the script range in get_char_script(). + wined3d: Validate instruction lengths in shader_sm4_read_instruction() (AFL). + wined3d: Don't read modifiers for opcodes with "read_opcode_func" set (AFL). + usp10: Use heap_alloc_zero() instead of HeapAlloc() with HEAP_ZERO_MEMORY. + usp10: Use heap_alloc() instead of HeapAlloc(). + usp10: Use heap_free() instead of HeapFree(). + wined3d: Avoid device_invalidate_state() in wined3d_texture_set_lod(). + wined3d: Create and destroy surface DCs through the CS. + wined3d: Pass a context to blit_shader.blit_surface(). + wined3d: Only copy source/destination rectangles when needed in arbfp_blit_surface(). + wined3d: Modify resource locations in wined3d_surface_blt() instead of the blitters. + +Hugh McMaster (1): + regedit/tests: Add some line concatenation tests. + +Huw D. M. Davies (5): + wined3d: Zero-initialize count. + gdi32/tests: Combine the matching macros into a single function. + shell32/tests: Return early if the shell folder creation fails in order to avoid a compiler warning. + shell32/tests: Ignore the compressed attribute. + krnl386.exe16: Fix mask values. + +Jacek Caban (15): + ntdll: Don't modify LockCount in RtlLeaveCriticalSection if section is not acquired. + wininet: Propagate WSAEWOULDBLOCK result from content decoding reads. + wininet: Pass blocking mode to HTTPREQ_Read. + wininet: Propagate WSAEWOULDBLOCK from read_http_stream. + wininet: Rewrite asynchronous read to try to fill whole buffer and not buffer additional data unless requested. + wininet: Rewrite InternetReadFileEx for http protocol to make use of non-blocking reads. + wininet: Reimplemented InternetQueryDataAvailable on top of async_read. + wininet: Merge InternetReadFile and InternetReadFileEx implementations. + wininet: Get rid of no longer needed BLOCKING_WAITALL. + wininet: Get rid of no longer needed blocking_mode_t. + wininet/tests: Added more HTTP read tests. + wininet: Always use non-blocking reads in HTTP_ReceiveRequestData. + wininet: Get rid of no longer needed get_avail_data from data stream implementations. + rpcrt4: Get rid of manual_listen_count and use binary state instead. + rpcrt4/tests: Added more server listening tests. + +Jactry Zeng (1): + devenum: Implement IMoniker::GetClassID(). + +Julian Rüger (3): + po: Update German translation. + readme: Update German translation. + readme: Fix typo in German translation. + +Józef Kucia (52): + wined3d: Bind unordered access views even if they are not used by current shaders. + d3d11/tests: Add test for UAV counters. + d3d11/tests: Use 256-byte aligned offsets for bufinfo test. + wined3d: Implement SM5 bufinfo instruction. + d3d11: Print FIXME() about ignoring initial UAV count values only when necessary. + d3d11/tests: Accept additional value as expected result in test_tgsm(). + oledb32/tests: Do not use pointer to freed memory (Coverity). + wined3d: Introduce wined3d_device_get_compute_shader(). + d3d11: Implement d3d11_immediate_context_CSGetShader(). + wined3d: Introduce wined3d_device_get_cs_cb(). + d3d11: Implement d3d11_immediate_context_CSGetConstantBuffers(). + wined3d: Introduce wined3d_device_get_cs_resource_view(). + d3d11: Implement d3d11_immediate_context_CSGetShaderResources(). + wined3d: Introduce wined3d_device_get_cs_sampler(). + d3d11: Implement d3d11_immediate_context_CSGetSamplers(). + wined3d: Introduce wined3d_device_get_constant_buffer() helper function. + wined3d: Introduce wined3d_device_get_shader_resource_view() helper function. + wined3d: Introduce wined3d_device_get_sampler() helper function. + wined3d: Make sure that "tgsm_count" is not decreased while adding TGSM declarations. + wined3d: Fix parsing of SM5 "_opc" flag. + wined3d: Add FIXME() messages for unhandled shader bytecode UAV flags. + wined3d: Create dummy cube array textures. + wined3d: Avoid FIXME() message for unhandled cube map arrays. + d3d11/tests: Add test for cube maps. + wined3d: Add support for seamless cube map filtering. + d3d11: Fix typo in TRACE() message. + d3d11/tests: Add test for unbinding shader resource view. + wined3d: Recognize SM4 umul opcode. + wined3d: Implement SM4 umul instruction. + wined3d: Recognize SM4 dcl_index_range opcode. + d3d10core/tests: Add test for cube maps. + d3d10core/tests: Add test for unbinding shader resource view. + d3d11/tests: Fix render target format in test_resinfo_instruction(). + d3d10core/tests: Fix render target format in test_resinfo_instruction(). + wined3d: Simplify computation of "num_textures_used" in ATI fragment pipeline. + wined3d: Get rid of incorrect usage of "tex_unit_map". + wined3d: Move legacy texture image unit range allocation to wined3d_gl_limits_get_texture_unit_range(). + wined3d: Introduce shader_glsl_load_program_resources() helper function. + wined3d: Use layout qualifiers to bind GLSL images. + wined3d: Use layout qualifiers to bind GLSL uniform blocks. + wined3d: Do not use texture unit mapping for SM4+ shaders. + wined3d: Allow using more than MAX_COMBINED_SAMPLERS texture image units. + wined3d: Introduce context_get_tex_unit_mapping() helper function. + wined3d: Use layout qualifiers to bind GLSL samplers. + wined3d: Add support for samplers in geometry shaders. + d3d9/tests: Add test for vertex textures. + wined3d: Use context_get_tex_unit_mapping() in context_bind_shader_resources(). + wined3d: Get rid of redundant WARN() from context_load_shader_resources(). + d3d11/tests: Add basic test for texturing on feature level 9. + wined3d: Store GL sampler limits as array. + wined3d: Recompute sampler count before allocating sampler range for compute shaders. + wined3d: Fix off-by-one error in wined3d_gl_limits_get_texture_unit_range(). + +Ken Thomases (2): + winemac: Discard key repeat events after a modifier key has been pressed. + wineps.drv: Set the AP_D_InputSlot CUPS option if no input slot is specified. + +Louis Lenders (1): + kernel32: Add stub for GetCurrentPackageFullName. + +Mark Jansen (1): + msi: Use the correct type when calculating feature cost. + +Matteo Bruni (15): + ddraw: Keep a ddraw object reference in d3d7 vertex buffers. + d3d9/tests: Skip test_vshader_input() if PS 3.0 isn't supported. + d3d9/tests: Fix pixel shader version check in test_pointsize(). + ddraw/tests: Add a ddraw4 vertex buffer refcount test. + ddraw/tests: Add a ddraw7 vertex buffer refcount test. + wined3d: Don't advertise unsupported shader versions. + d3d9/tests: Skip UpdateTexture tests if texture filtering isn't supported. + wined3d: Use the MAX_TEXTURES define in a few more places. + d3d9/tests: Ignore test_vshader_input() "no color attribute" test result on WARP. + wined3d: Fix the TRACE in wined3d_texture_remove_buffer_object(). + d3d9/tests: Fix test_updatetexture() on GPUs not supporting WINED3DFMT_R32_FLOAT. + ddraw: Take user clip planes into account in d3d7 ComputeSphereVisibility(). + ddraw/tests: Cleanup and extend d3d7 ComputeSphereVisibility() tests. + ddraw: Fix d3d6 version of ComputeSphereVisibility(). + ddraw/tests: Port test_compute_sphere_visibility() to ddraw4. + +Michael Müller (8): + kernel32: Add stub for GetCurrentPackageFamilyName. + cabinet: Set index of folder in FDICopy callback. + bcrypt: Add builtin HMAC implementation. + bcrypt: Use builtin MD5/SHA1 implementation. + bcrypt: Add a builtin sha256 implementation. + bcrypt: Add a builtin sha384/sha512 implementation. + bcrypt: Always use builtin hash implementation. + bcrypt: Implement BCryptDuplicateHash. + +Nikolay Sivov (49): + xmllite/reader: Improve input stream encoding detection. + xmllite/reader: Always return node type from Read(). + xmllite/reader: Reset node type to XmlNodeType_None on EOF. + xmllite/reader: Implement IsEOF(). + xmllite/reader: Improve the way nesting level returned by GetDepth() is updated. + d3d9: Remove reference to IWineD3DDevice. + ddraw: Remove referenced to IWineD3D* interfaces. + xmllite/reader: Return proper name for xml declaration PI. + xmllite/reader: Return empty value for elements. + xmllite/reader: Fix prefix returned after moving back to element. + xmllite/reader: Return qualified names for attributes. + xmllite/reader: Enforce maximum element depth limit. + gdi32/tests: Test that otmfsType field is cleaned up from reserved bits. + gdi32: Cleanup otmfsType bit mask from reserved bits. + xmllite/tests: A couple of newline normalization tests for text nodes. + xmllite/reader: Fix GetValue() for comments. + xmllite/reader: Return empty string for namespace uri for some nodes. + xmllite/reader: Return local element names from the stack, instead of input buffer. + xmllite/reader: Return qualified element names from the stack, instead of input buffer. + xmllite/tests: Fix a memory leak (Valgrind). + xmllite/reader: Return prefixes from namespace stack. + xmllite/tests: Some tests for reader position. + xmllite/reader: Remove redundant parameter. + xmllite/reader: Improve returned reader position for elements and attributes. + xmllite/reader: Fix reader position returned for xml declaration node. + xmllite/reader: Return static empty string as xml declaration node value. + xmllite/reader: Explicitly return empty static string as local name for nodes without names. + xmllite/reader: Explicitly return empty string as qualified name for some node types. + xmllite/reader: Return correct error for multiple colons in qualified name. + xmllite/reader: Fix position methods return values in closed reader state. + xmllite/reader: Improve line number updating when switching to the next line. + xmllite/reader: Improve returned position for whitespace text nodes. + wlanapi/tests: Always free interface list (Valgrind). + comdlg32: Take nMaxFile into account when converting A->W. + xmllite/reader: Enter error state on parsing error. + xmllite/reader: Reset reader nesting depth on error. + dwrite: Added support for oblique simulation in bitmap rendering mode. + inetcomm/tests: Fix test stream leak (Valgrind). + msctf/tests: Fix test object leak (Valgrind). + schedsvc: Fix xml buffer leak (Valgrind). + usp10/tests: Fix a buffer leak (Valgrind). + dwrite: Added support for bold simulation. + dwrite: Use version neutral variable name. + dwrite: Fix a typo to actually return kerning pair adjustments. + msxml3/tests: A bit more tests for IPersist* interfaces. + msxml3/saxreader: Handle NULL interface input in parse(). + xmllite/reader: Always return local name from element structure. + xmllite/reader: For elements without a prefix return same string for both local and qualified names. + xmllite/reader: Return same string for local and qualified names for attributes when appropriate. + +Owen Rudge (2): + gdiplus: Check for null in GdipGetFontHeight. + gdiplus/tests: Add tests for invalid parameter handling for GdipGetFontHeight. + +Paul Gofman (4): + d3dx9/tests: Add test for out of bounds array selector in effect. + d3dx9: Set dirty flag on parameter change. + d3dx9/tests: Extend test effect and add checks to test_effect_preshader(). + d3dx9/tests: Factor out op results test helper function from test_effect_preshader(). + +Pierre Schweitzer (1): + iphlpapi: Flags in IP_ADAPTER_ADDRESSES_LH can be used as a bit field. Piotr Caban (11): - ucrtbase: Add __initialize_lconv_for_unsigned_char implementation. - msvcrt: Use charmax to initialize lconv fields. - msvcrt: Add __ExceptionPtrCopyException implementation. - msvcr100: Add _ReentrantBlockingLock class implementation. - msvcr100: Add _NonReentrantBlockingLock class implementation. - msvcr100: Add _ReentrantBlockingLock tests. - msvcp110: Add _Lock_shared_ptr_spin_lock implementation. - msvcr110: Add _Lock_shared_ptr_spin_lock implementation. - msvcr100: Use InterlockedDecrement in SpinWait::_SpinOnce. - msvcr: Add _get_dstbias implementation. - msvcp140: Add task_continuation_context constructor implementation. - -Sebastian Lackner (1): - wined3d: Clear device state in wined3d_device_reset. - -Stefan Dösinger (5): - d3d8/tests: Allow a higher slop for test_updatetexture. - d3d9/tests: Allow a higher slop for test_updatetexture. - d3d8/tests: Work around a r500 Windows point sprite bug. - d3d9/tests: Work around a r500 Windows point sprite bug. - d3d9/tests: AMD r500 needs dummy texture output from vertex shaders for point sprites to work. - -Thomas Faber (3): - winex11: Avoid unused variable warning when building without LIBGL. - ole32: Zero STGMEDIUM before calling IDataObject::GetData. - msacm32: Free session driver instance using the correct heap. - -Zebediah Figura (5): - compobj.dll16: Implement CoGetClassObject16(). - storage.dll16: Fix an error in a comment. - storage.dll16: Fix get_nth_next_small_blocknr. - mciavi32: Report version as 1.1. - winmm/tests: Test for avivideo driver version. + msvcp140: Add _ContextCallback implementation. + msvcp140: Add _ContextCallback tests. + msvcp140: Add __crtCreateThreadpoolTimer implementation. + msvcp140: Add __crtSetThreadpoolTimer implementation. + msvcp140: Add __crtCreateThreadpoolWait implementation. + msvcp140: Add __crtSetThreadpoolWait implementation. + msvcr: Add _Wcsftime implementation. + msvcr: Fix strftime spec file entry. + msvcp140: Add _TaskEventLogger class implementation. + msvcp140/tests: Add _TaskEventLogger tests. + msvcr: Add __crtUnhandledException implementation. + +Sebastian Lackner (18): + ntdll: Use FD_CLOEXEC instead of hardcoded values. + ntoskrnl.exe: Add KeReleaseInStackQueuedSpinLock stub. + ntdll: Implement FileAccessInformation class in NtQueryInformationFile. + rasapi32: Set *lpcDevices in RasEnumDevicesA. + include: Avoid typedef for tls_data. + webservices: Unlock critical section before returning. + webservices: Don't set is_addressed when an error occurred. + webservices: Return the correct HRESULT on error. + webservices: Fix uninitialized variable in WsWriteArray. + server: Explicitly mark memory as undefined in mem_alloc wrapper. + schedsvc: Simplify and standardize the heap_xxx() declarations. + bcrypt: Unify the object length handling. + bcrypt: Return error when requesting BCRYPT_HASH_LENGTH for unsupported object. + bcrypt/tests: Move common tests to a helper function. + bcrypt/tests: Add basic tests for BCryptDuplicateHash. + bcrypt: Remove a FIXME which no longer applies. + vcomp/tests: Use ULL macro to define 64-bit constants. + krnl386.exe16: Ignore access denied error when flushing file. + +Stefan Dösinger (1): + ddraw/tests: Rewrite SrcColorKey32BlitTest. + +Vincent Povirk (1): + mscoree: Update Wine Mono to 4.7.0. -- Alexandre Julliard diff -Nru wine-staging-2.3.0~ubuntu16.04.1/configure wine-staging-2.4.0~ubuntu16.04.1/configure --- wine-staging-2.3.0~ubuntu16.04.1/configure 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/configure 2017-03-21 14:02:57.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for Wine 2.3. +# Generated by GNU Autoconf 2.69 for Wine 2.4. # # Report bugs to . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='Wine' PACKAGE_TARNAME='wine' -PACKAGE_VERSION='2.3' -PACKAGE_STRING='Wine 2.3' +PACKAGE_VERSION='2.4' +PACKAGE_STRING='Wine 2.4' PACKAGE_BUGREPORT='wine-devel@winehq.org' PACKAGE_URL='http://www.winehq.org' @@ -2226,7 +2226,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Wine 2.3 to adapt to many kinds of systems. +\`configure' configures Wine 2.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -2296,7 +2296,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Wine 2.3:";; + short | recursive ) echo "Configuration of Wine 2.4:";; esac cat <<\_ACEOF @@ -2504,7 +2504,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Wine configure 2.3 +Wine configure 2.4 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -3022,7 +3022,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Wine $as_me 2.3, which was +It was created by Wine $as_me 2.4, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -19200,7 +19200,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Wine $as_me 2.3, which was +This file was extended by Wine $as_me 2.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -19271,7 +19271,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Wine config.status 2.3 +Wine config.status 2.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru wine-staging-2.3.0~ubuntu16.04.1/debian/bzr-builder.manifest wine-staging-2.4.0~ubuntu16.04.1/debian/bzr-builder.manifest --- wine-staging-2.3.0~ubuntu16.04.1/debian/bzr-builder.manifest 2017-03-06 23:09:53.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/debian/bzr-builder.manifest 2017-03-21 16:27:33.000000000 +0000 @@ -1,4 +1,4 @@ -# bzr-builder format 0.4 deb-version 2.3.0 -lp:wine revid:git-v1:a2460b2424163bbf5b885db6a5423c3d98f883e0 -merge wine-staging-files lp:wine-compholio revid:git-v1:73cb57f5b9a3c5b749e43d29f3f14a4a68359feb -merge wine-build-staging lp:~wine/wine/build-staging revid:sebastian@fds-team.de-20170306205004-ps1jkpyodtfdpcm3 +# bzr-builder format 0.4 deb-version 2.4.0 +lp:wine revid:git-v1:6a05069a43f1a8f0e69c4cedd134f8d7400b8a95 +merge wine-staging-files lp:wine-compholio revid:git-v1:4232441093d41c244328458d176fe561a742e3ae +merge wine-build-staging lp:~wine/wine/build-staging revid:sebastian@fds-team.de-20170321134750-bz4pm398ygs7n2ym diff -Nru wine-staging-2.3.0~ubuntu16.04.1/debian/changelog wine-staging-2.4.0~ubuntu16.04.1/debian/changelog --- wine-staging-2.3.0~ubuntu16.04.1/debian/changelog 2017-03-06 23:09:53.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/debian/changelog 2017-03-21 16:27:33.000000000 +0000 @@ -1,9 +1,9 @@ -wine-staging (2.3.0~ubuntu16.04.1) xenial; urgency=low +wine-staging (2.4.0~ubuntu16.04.1) xenial; urgency=low * Auto build. - -- Sebastian Lackner Mon, 06 Mar 2017 23:09:53 +0000 + -- Sebastian Lackner Tue, 21 Mar 2017 16:27:33 +0000 -wine-staging (2.3.0) unstable; urgency=low +wine-staging (2.4.0) unstable; urgency=low * Auto build. - -- Michael Müller Mon, 06 Mar 2017 20:40:03 -0000 + -- Michael Müller Tue, 21 Mar 2017 13:41:04 -0000 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/advapi32/tests/service.c wine-staging-2.4.0~ubuntu16.04.1/dlls/advapi32/tests/service.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/advapi32/tests/service.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/advapi32/tests/service.c 2017-03-21 14:02:57.000000000 +0000 @@ -379,7 +379,7 @@ { svc_handle1 = CreateServiceA(scm_handle, servicename, display, 0, SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); - ok(!svc_handle1, "Expected failure\n"); + ok(!svc_handle1, "Expected failure for display name '%s'\n", display); ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError()); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec 2017-03-21 14:02:57.000000000 +0000 @@ -3,8 +3,8 @@ @ stub FormatApplicationUserModelId @ stub GetApplicationUserModelId @ stub GetCurrentApplicationUserModelId -@ stub GetCurrentPackageFamilyName -@ stub GetCurrentPackageFullName +@ stdcall GetCurrentPackageFamilyName(ptr ptr) kernel32.GetCurrentPackageFamilyName +@ stdcall GetCurrentPackageFullName(ptr ptr) kernel32.GetCurrentPackageFullName @ stdcall GetCurrentPackageId(ptr ptr) kernel32.GetCurrentPackageId @ stub GetCurrentPackageInfo @ stub GetCurrentPackagePath diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/api-ms-win-crt-time-l1-1-0/api-ms-win-crt-time-l1-1-0.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/api-ms-win-crt-time-l1-1-0/api-ms-win-crt-time-l1-1-0.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/api-ms-win-crt-time-l1-1-0/api-ms-win-crt-time-l1-1-0.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/api-ms-win-crt-time-l1-1-0/api-ms-win-crt-time-l1-1-0.spec 2017-03-21 14:02:57.000000000 +0000 @@ -1,11 +1,11 @@ @ cdecl _Getdays() ucrtbase._Getdays @ cdecl _Getmonths() ucrtbase._Getmonths @ cdecl _Gettnames() ucrtbase._Gettnames -@ cdecl _Strftime(str long str ptr ptr) ucrtbase._Strftime +@ cdecl _Strftime(ptr long str ptr ptr) ucrtbase._Strftime @ cdecl _W_Getdays() ucrtbase._W_Getdays @ cdecl _W_Getmonths() ucrtbase._W_Getmonths @ cdecl _W_Gettnames() ucrtbase._W_Gettnames -@ stub _Wcsftime +@ cdecl _Wcsftime(ptr long wstr ptr ptr) ucrtbase._Wcsftime @ cdecl __daylight() ucrtbase.__daylight @ cdecl __dstbias() ucrtbase.__dstbias @ cdecl __timezone() ucrtbase.__timezone @@ -42,7 +42,7 @@ @ cdecl _setsystime(ptr long) ucrtbase._setsystime @ cdecl _strdate(ptr) ucrtbase._strdate @ cdecl _strdate_s(ptr long) ucrtbase._strdate_s -@ cdecl _strftime_l(str long str ptr ptr) ucrtbase._strftime_l +@ cdecl _strftime_l(ptr long str ptr ptr) ucrtbase._strftime_l @ cdecl _strtime(ptr) ucrtbase._strtime @ cdecl _strtime_s(ptr long) ucrtbase._strtime_s @ cdecl _time32(ptr) ucrtbase._time32 @@ -68,5 +68,5 @@ @ cdecl asctime(ptr) ucrtbase.asctime @ cdecl asctime_s(ptr long ptr) ucrtbase.asctime_s @ cdecl clock() ucrtbase.clock -@ cdecl strftime(str long str ptr) ucrtbase.strftime +@ cdecl strftime(ptr long str ptr) ucrtbase.strftime @ cdecl wcsftime(ptr long wstr ptr) ucrtbase.wcsftime diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/appwiz.cpl/addons.c wine-staging-2.4.0~ubuntu16.04.1/dlls/appwiz.cpl/addons.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/appwiz.cpl/addons.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/appwiz.cpl/addons.c 2017-03-21 14:02:57.000000000 +0000 @@ -64,8 +64,8 @@ #define GECKO_SHA "???" #endif -#define MONO_VERSION "4.6.4" -#define MONO_SHA "d58509c3a4e5fa88c56c14e0413a803aa82f6118" +#define MONO_VERSION "4.7.0" +#define MONO_SHA "ff05e1d2a93c3a07672cefc7a8f3a087d75828ac" typedef struct { const char *version; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/bcrypt_internal.h wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/bcrypt_internal.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/bcrypt_internal.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/bcrypt_internal.h 2017-03-21 14:02:57.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright 2016 Michael Müller + * + * 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 __BCRYPT_INTERNAL_H +#define __BCRYPT_INTERNAL_H + +#include + +#include "windef.h" +#include "winbase.h" + +typedef struct +{ + ULONG64 len; + DWORD h[8]; + UCHAR buf[64]; +} SHA256_CTX; + +void sha256_init(SHA256_CTX *ctx) DECLSPEC_HIDDEN; +void sha256_update(SHA256_CTX *ctx, const UCHAR *buffer, ULONG len) DECLSPEC_HIDDEN; +void sha256_finalize(SHA256_CTX *ctx, UCHAR *buffer) DECLSPEC_HIDDEN; + +typedef struct +{ + ULONG64 len; + ULONG64 h[8]; + UCHAR buf[128]; +} SHA512_CTX; + +void sha512_init(SHA512_CTX *ctx) DECLSPEC_HIDDEN; +void sha512_update(SHA512_CTX *ctx, const UCHAR *buffer, ULONG len) DECLSPEC_HIDDEN; +void sha512_finalize(SHA512_CTX *ctx, UCHAR *buffer) DECLSPEC_HIDDEN; + +void sha384_init(SHA512_CTX *ctx) DECLSPEC_HIDDEN; +#define sha384_update sha512_update +void sha384_finalize(SHA512_CTX *ctx, UCHAR *buffer) DECLSPEC_HIDDEN; + +/* Definitions from advapi32 */ +typedef struct +{ + unsigned int i[2]; + unsigned int buf[4]; + unsigned char in[64]; + unsigned char digest[16]; +} MD5_CTX; + +VOID WINAPI MD5Init(MD5_CTX *ctx); +VOID WINAPI MD5Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len); +VOID WINAPI MD5Final(MD5_CTX *ctx); + +typedef struct +{ + ULONG Unknown[6]; + ULONG State[5]; + ULONG Count[2]; + UCHAR Buffer[64]; +} SHA_CTX; + +VOID WINAPI A_SHAInit(SHA_CTX *ctx); +VOID WINAPI A_SHAUpdate(SHA_CTX *ctx, const UCHAR *buffer, UINT size); +VOID WINAPI A_SHAFinal(SHA_CTX *ctx, PULONG result); + +#endif /* __BCRYPT_INTERNAL_H */ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/bcrypt_main.c wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/bcrypt_main.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/bcrypt_main.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/bcrypt_main.c 2017-03-21 14:02:57.000000000 +0000 @@ -36,6 +36,8 @@ #include "ntsecapi.h" #include "bcrypt.h" +#include "bcrypt_internal.h" + #include "wine/debug.h" #include "wine/library.h" #include "wine/unicode.h" @@ -53,12 +55,6 @@ MAKE_FUNCPTR(gnutls_global_init); MAKE_FUNCPTR(gnutls_global_set_log_function); MAKE_FUNCPTR(gnutls_global_set_log_level); -MAKE_FUNCPTR(gnutls_hash); -MAKE_FUNCPTR(gnutls_hash_deinit); -MAKE_FUNCPTR(gnutls_hash_init); -MAKE_FUNCPTR(gnutls_hmac); -MAKE_FUNCPTR(gnutls_hmac_deinit); -MAKE_FUNCPTR(gnutls_hmac_init); MAKE_FUNCPTR(gnutls_perror); #undef MAKE_FUNCPTR @@ -88,12 +84,6 @@ LOAD_FUNCPTR(gnutls_global_init) LOAD_FUNCPTR(gnutls_global_set_log_function) LOAD_FUNCPTR(gnutls_global_set_log_level) - LOAD_FUNCPTR(gnutls_hash); - LOAD_FUNCPTR(gnutls_hash_deinit); - LOAD_FUNCPTR(gnutls_hash_init); - LOAD_FUNCPTR(gnutls_hmac); - LOAD_FUNCPTR(gnutls_hmac_deinit); - LOAD_FUNCPTR(gnutls_hmac_init); LOAD_FUNCPTR(gnutls_perror) #undef LOAD_FUNCPTR @@ -153,16 +143,21 @@ ALG_ID_SHA512 }; +#define MAX_HASH_OUTPUT_BYTES 64 +#define MAX_HASH_BLOCK_BITS 1024 + static const struct { + ULONG object_length; ULONG hash_length; + ULONG block_bits; const WCHAR *alg_name; } alg_props[] = { - /* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM }, - /* ALG_ID_RNG */ { 0, BCRYPT_RNG_ALGORITHM }, - /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM }, - /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM }, - /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM }, - /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM } + /* ALG_ID_MD5 */ { 274, 16, 512, BCRYPT_MD5_ALGORITHM }, + /* ALG_ID_RNG */ { 0, 0, 0, BCRYPT_RNG_ALGORITHM }, + /* ALG_ID_SHA1 */ { 278, 20, 512, BCRYPT_SHA1_ALGORITHM }, + /* ALG_ID_SHA256 */ { 286, 32, 512, BCRYPT_SHA256_ALGORITHM }, + /* ALG_ID_SHA384 */ { 382, 48, 1024, BCRYPT_SHA384_ALGORITHM }, + /* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM } }; struct algorithm @@ -277,325 +272,140 @@ return STATUS_SUCCESS; } -#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H -struct hash +struct hash_impl { - struct object hdr; - enum alg_id alg_id; - BOOL hmac; union { - CC_MD5_CTX md5_ctx; - CC_SHA1_CTX sha1_ctx; - CC_SHA256_CTX sha256_ctx; - CC_SHA512_CTX sha512_ctx; - CCHmacContext hmac_ctx; + MD5_CTX md5; + SHA_CTX sha1; + SHA256_CTX sha256; + SHA512_CTX sha512; } u; }; -static NTSTATUS hash_init( struct hash *hash ) +static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) { - switch (hash->alg_id) + switch (alg_id) { case ALG_ID_MD5: - CC_MD5_Init( &hash->u.md5_ctx ); + MD5Init( &hash->u.md5 ); break; case ALG_ID_SHA1: - CC_SHA1_Init( &hash->u.sha1_ctx ); + A_SHAInit( &hash->u.sha1 ); break; case ALG_ID_SHA256: - CC_SHA256_Init( &hash->u.sha256_ctx ); + sha256_init( &hash->u.sha256 ); break; case ALG_ID_SHA384: - CC_SHA384_Init( &hash->u.sha512_ctx ); + sha384_init( &hash->u.sha512 ); break; case ALG_ID_SHA512: - CC_SHA512_Init( &hash->u.sha512_ctx ); + sha512_init( &hash->u.sha512 ); break; default: - ERR( "unhandled id %u\n", hash->alg_id ); + ERR( "unhandled id %u\n", alg_id ); return STATUS_NOT_IMPLEMENTED; } return STATUS_SUCCESS; } -static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) +static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, + UCHAR *input, ULONG size ) { - CCHmacAlgorithm cc_algorithm; - switch (hash->alg_id) + switch (alg_id) { case ALG_ID_MD5: - cc_algorithm = kCCHmacAlgMD5; + MD5Update( &hash->u.md5, input, size ); break; case ALG_ID_SHA1: - cc_algorithm = kCCHmacAlgSHA1; + A_SHAUpdate( &hash->u.sha1, input, size ); break; case ALG_ID_SHA256: - cc_algorithm = kCCHmacAlgSHA256; + sha256_update( &hash->u.sha256, input, size ); break; case ALG_ID_SHA384: - cc_algorithm = kCCHmacAlgSHA384; + sha384_update( &hash->u.sha512, input, size ); break; case ALG_ID_SHA512: - cc_algorithm = kCCHmacAlgSHA512; + sha512_update( &hash->u.sha512, input, size ); break; default: - ERR( "unhandled id %u\n", hash->alg_id ); + ERR( "unhandled id %u\n", alg_id ); return STATUS_NOT_IMPLEMENTED; } - - CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size ); return STATUS_SUCCESS; } - -static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) +static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, + UCHAR *output, ULONG size ) { - switch (hash->alg_id) + switch (alg_id) { case ALG_ID_MD5: - CC_MD5_Update( &hash->u.md5_ctx, input, size ); + MD5Final( &hash->u.md5 ); + memcpy( output, hash->u.md5.digest, 16 ); break; case ALG_ID_SHA1: - CC_SHA1_Update( &hash->u.sha1_ctx, input, size ); + A_SHAFinal( &hash->u.sha1, (ULONG *)output ); break; case ALG_ID_SHA256: - CC_SHA256_Update( &hash->u.sha256_ctx, input, size ); + sha256_finalize( &hash->u.sha256, output ); break; case ALG_ID_SHA384: - CC_SHA384_Update( &hash->u.sha512_ctx, input, size ); + sha384_finalize( &hash->u.sha512, output ); break; case ALG_ID_SHA512: - CC_SHA512_Update( &hash->u.sha512_ctx, input, size ); + sha512_finalize( &hash->u.sha512, output ); break; default: - ERR( "unhandled id %u\n", hash->alg_id ); + ERR( "unhandled id %u\n", alg_id ); return STATUS_NOT_IMPLEMENTED; } return STATUS_SUCCESS; } -static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) -{ - CCHmacUpdate( &hash->u.hmac_ctx, input, size ); - return STATUS_SUCCESS; -} - -static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) -{ - switch (hash->alg_id) - { - case ALG_ID_MD5: - CC_MD5_Final( output, &hash->u.md5_ctx ); - break; - - case ALG_ID_SHA1: - CC_SHA1_Final( output, &hash->u.sha1_ctx ); - break; - - case ALG_ID_SHA256: - CC_SHA256_Final( output, &hash->u.sha256_ctx ); - break; - - case ALG_ID_SHA384: - CC_SHA384_Final( output, &hash->u.sha512_ctx ); - break; - - case ALG_ID_SHA512: - CC_SHA512_Final( output, &hash->u.sha512_ctx ); - break; - - default: - ERR( "unhandled id %u\n", hash->alg_id ); - break; - } - return STATUS_SUCCESS; -} - -static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) -{ - CCHmacFinal( &hash->u.hmac_ctx, output ); - - return STATUS_SUCCESS; -} -#elif defined(HAVE_GNUTLS_HASH) struct hash { struct object hdr; enum alg_id alg_id; - BOOL hmac; - union - { - gnutls_hash_hd_t hash_handle; - gnutls_hmac_hd_t hmac_handle; - } u; + BOOL hmac; + struct hash_impl outer; + struct hash_impl inner; }; -static NTSTATUS hash_init( struct hash *hash ) -{ - gnutls_digest_algorithm_t alg; - - if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; - - switch (hash->alg_id) - { - case ALG_ID_MD5: - alg = GNUTLS_DIG_MD5; - break; - case ALG_ID_SHA1: - alg = GNUTLS_DIG_SHA1; - break; - - case ALG_ID_SHA256: - alg = GNUTLS_DIG_SHA256; - break; - - case ALG_ID_SHA384: - alg = GNUTLS_DIG_SHA384; - break; - - case ALG_ID_SHA512: - alg = GNUTLS_DIG_SHA512; - break; - - default: - ERR( "unhandled id %u\n", hash->alg_id ); - return STATUS_NOT_IMPLEMENTED; - } - - if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR; - return STATUS_SUCCESS; -} - -static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) +static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) { - gnutls_mac_algorithm_t alg; - - if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; - - switch (hash->alg_id) + if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) { - case ALG_ID_MD5: - alg = GNUTLS_MAC_MD5; - break; - case ALG_ID_SHA1: - alg = GNUTLS_MAC_SHA1; - break; - - case ALG_ID_SHA256: - alg = GNUTLS_MAC_SHA256; - break; - - case ALG_ID_SHA384: - alg = GNUTLS_MAC_SHA384; - break; - - case ALG_ID_SHA512: - alg = GNUTLS_MAC_SHA512; - break; - - default: - ERR( "unhandled id %u\n", hash->alg_id ); - return STATUS_NOT_IMPLEMENTED; + if (!alg_props[id].object_length) + return STATUS_NOT_SUPPORTED; + *ret_size = sizeof(ULONG); + if (size < sizeof(ULONG)) + return STATUS_BUFFER_TOO_SMALL; + if (buf) + *(ULONG *)buf = alg_props[id].object_length; + return STATUS_SUCCESS; } - if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR; - return STATUS_SUCCESS; -} - -static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) -{ - if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR; - return STATUS_SUCCESS; -} - -static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) -{ - if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR; - return STATUS_SUCCESS; -} - -static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) -{ - pgnutls_hash_deinit( hash->u.hash_handle, output ); - return STATUS_SUCCESS; -} - -static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) -{ - pgnutls_hmac_deinit( hash->u.hmac_handle, output ); - return STATUS_SUCCESS; -} -#else -struct hash -{ - struct object hdr; - BOOL hmac; - enum alg_id alg_id; -}; - -static NTSTATUS hash_init( struct hash *hash ) -{ - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) -{ - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) -{ - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) -{ - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) -{ - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) -{ - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; -} -#endif - -#define OBJECT_LENGTH_MD5 274 -#define OBJECT_LENGTH_SHA1 278 -#define OBJECT_LENGTH_SHA256 286 -#define OBJECT_LENGTH_SHA384 382 -#define OBJECT_LENGTH_SHA512 382 - -static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) -{ if (!strcmpW( prop, BCRYPT_HASH_LENGTH )) { + if (!alg_props[id].hash_length) + return STATUS_NOT_SUPPORTED; *ret_size = sizeof(ULONG); if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL; @@ -620,78 +430,11 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) { NTSTATUS status; - ULONG value; status = generic_alg_property( id, prop, buf, size, ret_size ); - if (status != STATUS_NOT_IMPLEMENTED) - return status; - - switch (id) - { - case ALG_ID_MD5: - if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) - { - value = OBJECT_LENGTH_MD5; - break; - } - FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) ); - return STATUS_NOT_IMPLEMENTED; - - case ALG_ID_RNG: - if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) return STATUS_NOT_SUPPORTED; - FIXME( "unsupported rng algorithm property %s\n", debugstr_w(prop) ); - return STATUS_NOT_IMPLEMENTED; - - case ALG_ID_SHA1: - if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) - { - value = OBJECT_LENGTH_SHA1; - break; - } - FIXME( "unsupported sha1 algorithm property %s\n", debugstr_w(prop) ); - return STATUS_NOT_IMPLEMENTED; - - case ALG_ID_SHA256: - if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) - { - value = OBJECT_LENGTH_SHA256; - break; - } - FIXME( "unsupported sha256 algorithm property %s\n", debugstr_w(prop) ); - return STATUS_NOT_IMPLEMENTED; - - case ALG_ID_SHA384: - if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) - { - value = OBJECT_LENGTH_SHA384; - break; - } - FIXME( "unsupported sha384 algorithm property %s\n", debugstr_w(prop) ); - return STATUS_NOT_IMPLEMENTED; - - case ALG_ID_SHA512: - if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) - { - value = OBJECT_LENGTH_SHA512; - break; - } - FIXME( "unsupported sha512 algorithm property %s\n", debugstr_w(prop) ); - return STATUS_NOT_IMPLEMENTED; - - default: - FIXME( "unsupported algorithm %u\n", id ); - return STATUS_NOT_IMPLEMENTED; - } - - if (size < sizeof(ULONG)) - { - *ret_size = sizeof(ULONG); - return STATUS_BUFFER_TOO_SMALL; - } - if (buf) *(ULONG *)buf = value; - *ret_size = sizeof(ULONG); - - return STATUS_SUCCESS; + if (status == STATUS_NOT_IMPLEMENTED) + FIXME( "unsupported property %s\n", debugstr_w(prop) ); + return status; } static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) @@ -735,8 +478,11 @@ UCHAR *secret, ULONG secretlen, ULONG flags ) { struct algorithm *alg = algorithm; + UCHAR buffer[MAX_HASH_BLOCK_BITS / 8] = {0}; struct hash *hash; + int block_bytes; NTSTATUS status; + int i; TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen, secret, secretlen, flags ); @@ -754,15 +500,31 @@ hash->alg_id = alg->id; hash->hmac = alg->hmac; - if (hash->hmac) - { - status = hmac_init( hash, secret, secretlen ); + /* initialize hash */ + if ((status = hash_init( &hash->inner, hash->alg_id ))) goto end; + if (!hash->hmac) goto end; + + /* initialize hmac */ + if ((status = hash_init( &hash->outer, hash->alg_id ))) goto end; + block_bytes = alg_props[hash->alg_id].block_bits / 8; + if (secretlen > block_bytes) + { + struct hash_impl temp; + if ((status = hash_init( &temp, hash->alg_id ))) goto end; + if ((status = hash_update( &temp, hash->alg_id, secret, secretlen ))) goto end; + if ((status = hash_finish( &temp, hash->alg_id, buffer, + alg_props[hash->alg_id].hash_length ))) goto end; } else { - status = hash_init( hash ); + memcpy( buffer, secret, secretlen ); } + for (i = 0; i < block_bytes; i++) buffer[i] ^= 0x5c; + if ((status = hash_update( &hash->outer, hash->alg_id, buffer, block_bytes ))) goto end; + for (i = 0; i < block_bytes; i++) buffer[i] ^= (0x5c ^ 0x36); + status = hash_update( &hash->inner, hash->alg_id, buffer, block_bytes ); +end: if (status != STATUS_SUCCESS) { HeapFree( GetProcessHeap(), 0, hash ); @@ -773,6 +535,27 @@ return STATUS_SUCCESS; } +NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HANDLE *handle_copy, + UCHAR *object, ULONG objectlen, ULONG flags ) +{ + struct hash *hash_orig = handle; + struct hash *hash_copy; + + TRACE( "%p, %p, %p, %u, %u\n", handle, handle_copy, object, objectlen, flags ); + + if (!hash_orig || hash_orig->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; + if (!handle_copy) return STATUS_INVALID_PARAMETER; + if (object) FIXME( "ignoring object buffer\n" ); + + if (!(hash_copy = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash_copy) ))) + return STATUS_NO_MEMORY; + + memcpy( hash_copy, hash_orig, sizeof(*hash_orig) ); + + *handle_copy = hash_copy; + return STATUS_SUCCESS; +} + NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle ) { struct hash *hash = handle; @@ -793,33 +576,28 @@ if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; if (!input) return STATUS_SUCCESS; - if (hash->hmac) - { - return hmac_update( hash, input, size ); - } - else - { - return hash_update( hash, input, size ); - } + return hash_update( &hash->inner, hash->alg_id, input, size ); } NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags ) { + UCHAR buffer[MAX_HASH_OUTPUT_BYTES]; struct hash *hash = handle; + NTSTATUS status; + int hash_length; TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags ); if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; if (!output) return STATUS_INVALID_PARAMETER; - if (hash->hmac) - { - return hmac_finish( hash, output, size ); - } - else - { - return hash_finish( hash, output, size ); - } + if (!hash->hmac) + return hash_finish( &hash->inner, hash->alg_id, output, size ); + + hash_length = alg_props[hash->alg_id].hash_length; + if ((status = hash_finish( &hash->inner, hash->alg_id, buffer, hash_length ))) return status; + if ((status = hash_update( &hash->outer, hash->alg_id, buffer, hash_length ))) return status; + return hash_finish( &hash->outer, hash->alg_id, output, size ); } NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/bcrypt.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/bcrypt.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/bcrypt.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/bcrypt.spec 2017-03-21 14:02:57.000000000 +0000 @@ -11,7 +11,7 @@ @ stdcall BCryptDestroyHash(ptr) @ stub BCryptDestroyKey @ stub BCryptDestroySecret -@ stub BCryptDuplicateHash +@ stdcall BCryptDuplicateHash(ptr ptr ptr long long) @ stub BCryptDuplicateKey @ stub BCryptEncrypt @ stdcall BCryptEnumAlgorithms(long ptr ptr long) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/Makefile.in wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/Makefile.in --- wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/Makefile.in 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/Makefile.in 2017-03-21 14:02:57.000000000 +0000 @@ -4,6 +4,8 @@ EXTRAINCL = $(GNUTLS_CFLAGS) C_SRCS = \ - bcrypt_main.c + bcrypt_main.c \ + sha256.c \ + sha512.c RC_SRCS = version.rc diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/sha256.c wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/sha256.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/sha256.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/sha256.c 2017-03-21 14:02:57.000000000 +0000 @@ -0,0 +1,169 @@ +/* + * Copyright 2016 Michael Müller + * + * 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 + * + */ + +/* Based on public domain implementation from + https://git.musl-libc.org/cgit/musl/tree/src/crypt/crypt_sha256.c */ + +#include "bcrypt_internal.h" + +static DWORD ror(DWORD n, int k) { return (n >> k) | (n << (32-k)); } +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) ((x & y) | (z & (x | y))) +#define S0(x) (ror(x,2) ^ ror(x,13) ^ ror(x,22)) +#define S1(x) (ror(x,6) ^ ror(x,11) ^ ror(x,25)) +#define R0(x) (ror(x,7) ^ ror(x,18) ^ (x>>3)) +#define R1(x) (ror(x,17) ^ ror(x,19) ^ (x>>10)) + +static const DWORD K[64] = +{ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static void processblock(SHA256_CTX *ctx, const UCHAR *buffer) +{ + DWORD W[64], t1, t2, a, b, c, d, e, f, g, h; + int i; + + for (i = 0; i < 16; i++) + { + W[i] = (DWORD)buffer[4*i]<<24; + W[i] |= (DWORD)buffer[4*i+1]<<16; + W[i] |= (DWORD)buffer[4*i+2]<<8; + W[i] |= buffer[4*i+3]; + } + + for (; i < 64; i++) + W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; + + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + for (i = 0; i < 64; i++) + { + t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; + t2 = S0(a) + Maj(a,b,c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; +} + +static void pad(SHA256_CTX *ctx) +{ + ULONG64 r = ctx->len % 64; + + ctx->buf[r++] = 0x80; + + if (r > 56) + { + memset(ctx->buf + r, 0, 64 - r); + r = 0; + processblock(ctx, ctx->buf); + } + + memset(ctx->buf + r, 0, 56 - r); + ctx->len *= 8; + ctx->buf[56] = ctx->len >> 56; + ctx->buf[57] = ctx->len >> 48; + ctx->buf[58] = ctx->len >> 40; + ctx->buf[59] = ctx->len >> 32; + ctx->buf[60] = ctx->len >> 24; + ctx->buf[61] = ctx->len >> 16; + ctx->buf[62] = ctx->len >> 8; + ctx->buf[63] = ctx->len; + + processblock(ctx, ctx->buf); +} + +void sha256_init(SHA256_CTX *ctx) +{ + ctx->len = 0; + ctx->h[0] = 0x6a09e667; + ctx->h[1] = 0xbb67ae85; + ctx->h[2] = 0x3c6ef372; + ctx->h[3] = 0xa54ff53a; + ctx->h[4] = 0x510e527f; + ctx->h[5] = 0x9b05688c; + ctx->h[6] = 0x1f83d9ab; + ctx->h[7] = 0x5be0cd19; +} + +void sha256_update(SHA256_CTX *ctx, const UCHAR *buffer, ULONG len) +{ + const UCHAR *p = buffer; + ULONG64 r = ctx->len % 64; + + ctx->len += len; + if (r) + { + if (len < 64 - r) + { + memcpy(ctx->buf + r, p, len); + return; + } + memcpy(ctx->buf + r, p, 64 - r); + len -= 64 - r; + p += 64 - r; + processblock(ctx, ctx->buf); + } + for (; len >= 64; len -= 64, p += 64) + processblock(ctx, p); + memcpy(ctx->buf, p, len); +} + +void sha256_finalize(SHA256_CTX *ctx, UCHAR *buffer) +{ + int i; + + pad(ctx); + for (i = 0; i < 8; i++) + { + buffer[4*i] = ctx->h[i] >> 24; + buffer[4*i+1] = ctx->h[i] >> 16; + buffer[4*i+2] = ctx->h[i] >> 8; + buffer[4*i+3] = ctx->h[i]; + } +} diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/sha512.c wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/sha512.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/sha512.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/sha512.c 2017-03-21 14:02:57.000000000 +0000 @@ -0,0 +1,212 @@ +/* + * Copyright 2016 Michael Müller + * + * 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 + * + */ + +/* Based on public domain implementation from + https://git.musl-libc.org/cgit/musl/tree/src/crypt/crypt_sha512.c */ + +#include "bcrypt_internal.h" + +static ULONG64 ror(ULONG64 n, int k) { return (n >> k) | (n << (64-k)); } +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) ((x & y) | (z & (x | y))) +#define S0(x) (ror(x,28) ^ ror(x,34) ^ ror(x,39)) +#define S1(x) (ror(x,14) ^ ror(x,18) ^ ror(x,41)) +#define R0(x) (ror(x,1) ^ ror(x,8) ^ (x>>7)) +#define R1(x) (ror(x,19) ^ ror(x,61) ^ (x>>6)) +#define ULL(a,b) (((ULONG64)(a) << 32) | (b)) + +static const ULONG64 K[80] = +{ + ULL(0x428a2f98,0xd728ae22), ULL(0x71374491,0x23ef65cd), ULL(0xb5c0fbcf,0xec4d3b2f), ULL(0xe9b5dba5,0x8189dbbc), + ULL(0x3956c25b,0xf348b538), ULL(0x59f111f1,0xb605d019), ULL(0x923f82a4,0xaf194f9b), ULL(0xab1c5ed5,0xda6d8118), + ULL(0xd807aa98,0xa3030242), ULL(0x12835b01,0x45706fbe), ULL(0x243185be,0x4ee4b28c), ULL(0x550c7dc3,0xd5ffb4e2), + ULL(0x72be5d74,0xf27b896f), ULL(0x80deb1fe,0x3b1696b1), ULL(0x9bdc06a7,0x25c71235), ULL(0xc19bf174,0xcf692694), + ULL(0xe49b69c1,0x9ef14ad2), ULL(0xefbe4786,0x384f25e3), ULL(0x0fc19dc6,0x8b8cd5b5), ULL(0x240ca1cc,0x77ac9c65), + ULL(0x2de92c6f,0x592b0275), ULL(0x4a7484aa,0x6ea6e483), ULL(0x5cb0a9dc,0xbd41fbd4), ULL(0x76f988da,0x831153b5), + ULL(0x983e5152,0xee66dfab), ULL(0xa831c66d,0x2db43210), ULL(0xb00327c8,0x98fb213f), ULL(0xbf597fc7,0xbeef0ee4), + ULL(0xc6e00bf3,0x3da88fc2), ULL(0xd5a79147,0x930aa725), ULL(0x06ca6351,0xe003826f), ULL(0x14292967,0x0a0e6e70), + ULL(0x27b70a85,0x46d22ffc), ULL(0x2e1b2138,0x5c26c926), ULL(0x4d2c6dfc,0x5ac42aed), ULL(0x53380d13,0x9d95b3df), + ULL(0x650a7354,0x8baf63de), ULL(0x766a0abb,0x3c77b2a8), ULL(0x81c2c92e,0x47edaee6), ULL(0x92722c85,0x1482353b), + ULL(0xa2bfe8a1,0x4cf10364), ULL(0xa81a664b,0xbc423001), ULL(0xc24b8b70,0xd0f89791), ULL(0xc76c51a3,0x0654be30), + ULL(0xd192e819,0xd6ef5218), ULL(0xd6990624,0x5565a910), ULL(0xf40e3585,0x5771202a), ULL(0x106aa070,0x32bbd1b8), + ULL(0x19a4c116,0xb8d2d0c8), ULL(0x1e376c08,0x5141ab53), ULL(0x2748774c,0xdf8eeb99), ULL(0x34b0bcb5,0xe19b48a8), + ULL(0x391c0cb3,0xc5c95a63), ULL(0x4ed8aa4a,0xe3418acb), ULL(0x5b9cca4f,0x7763e373), ULL(0x682e6ff3,0xd6b2b8a3), + ULL(0x748f82ee,0x5defb2fc), ULL(0x78a5636f,0x43172f60), ULL(0x84c87814,0xa1f0ab72), ULL(0x8cc70208,0x1a6439ec), + ULL(0x90befffa,0x23631e28), ULL(0xa4506ceb,0xde82bde9), ULL(0xbef9a3f7,0xb2c67915), ULL(0xc67178f2,0xe372532b), + ULL(0xca273ece,0xea26619c), ULL(0xd186b8c7,0x21c0c207), ULL(0xeada7dd6,0xcde0eb1e), ULL(0xf57d4f7f,0xee6ed178), + ULL(0x06f067aa,0x72176fba), ULL(0x0a637dc5,0xa2c898a6), ULL(0x113f9804,0xbef90dae), ULL(0x1b710b35,0x131c471b), + ULL(0x28db77f5,0x23047d84), ULL(0x32caab7b,0x40c72493), ULL(0x3c9ebe0a,0x15c9bebc), ULL(0x431d67c4,0x9c100d4c), + ULL(0x4cc5d4be,0xcb3e42b6), ULL(0x597f299c,0xfc657e2a), ULL(0x5fcb6fab,0x3ad6faec), ULL(0x6c44198c,0x4a475817) +}; + +static void processblock(SHA512_CTX *ctx, const UCHAR *buffer) +{ + ULONG64 W[80], t1, t2, a, b, c, d, e, f, g, h; + int i; + + for (i = 0; i < 16; i++) + { + W[i] = (ULONG64)buffer[8*i]<<56; + W[i] |= (ULONG64)buffer[8*i+1]<<48; + W[i] |= (ULONG64)buffer[8*i+2]<<40; + W[i] |= (ULONG64)buffer[8*i+3]<<32; + W[i] |= (ULONG64)buffer[8*i+4]<<24; + W[i] |= (ULONG64)buffer[8*i+5]<<16; + W[i] |= (ULONG64)buffer[8*i+6]<<8; + W[i] |= buffer[8*i+7]; + } + + for (; i < 80; i++) + W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; + + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + for (i = 0; i < 80; i++) + { + t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; + t2 = S0(a) + Maj(a,b,c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; +} + +static void pad(SHA512_CTX *ctx) +{ + ULONG64 r = ctx->len % 128; + + ctx->buf[r++] = 0x80; + if (r > 112) + { + memset(ctx->buf + r, 0, 128 - r); + r = 0; + processblock(ctx, ctx->buf); + } + + memset(ctx->buf + r, 0, 120 - r); + ctx->len *= 8; + ctx->buf[120] = ctx->len >> 56; + ctx->buf[121] = ctx->len >> 48; + ctx->buf[122] = ctx->len >> 40; + ctx->buf[123] = ctx->len >> 32; + ctx->buf[124] = ctx->len >> 24; + ctx->buf[125] = ctx->len >> 16; + ctx->buf[126] = ctx->len >> 8; + ctx->buf[127] = ctx->len; + + processblock(ctx, ctx->buf); +} + +void sha512_init(SHA512_CTX *ctx) +{ + ctx->len = 0; + ctx->h[0] = ULL(0x6a09e667,0xf3bcc908); + ctx->h[1] = ULL(0xbb67ae85,0x84caa73b); + ctx->h[2] = ULL(0x3c6ef372,0xfe94f82b); + ctx->h[3] = ULL(0xa54ff53a,0x5f1d36f1); + ctx->h[4] = ULL(0x510e527f,0xade682d1); + ctx->h[5] = ULL(0x9b05688c,0x2b3e6c1f); + ctx->h[6] = ULL(0x1f83d9ab,0xfb41bd6b); + ctx->h[7] = ULL(0x5be0cd19,0x137e2179); +} + +void sha512_update(SHA512_CTX *ctx, const UCHAR *buffer, ULONG len) +{ + const UCHAR *p = buffer; + unsigned r = ctx->len % 128; + + ctx->len += len; + if (r) + { + if (len < 128 - r) + { + memcpy(ctx->buf + r, p, len); + return; + } + memcpy(ctx->buf + r, p, 128 - r); + len -= 128 - r; + p += 128 - r; + processblock(ctx, ctx->buf); + } + + for (; len >= 128; len -= 128, p += 128) + processblock(ctx, p); + + memcpy(ctx->buf, p, len); +} + +void sha512_finalize(SHA512_CTX *ctx, UCHAR *buffer) +{ + int i; + + pad(ctx); + for (i = 0; i < 8; i++) + { + buffer[8*i] = ctx->h[i] >> 56; + buffer[8*i+1] = ctx->h[i] >> 48; + buffer[8*i+2] = ctx->h[i] >> 40; + buffer[8*i+3] = ctx->h[i] >> 32; + buffer[8*i+4] = ctx->h[i] >> 24; + buffer[8*i+5] = ctx->h[i] >> 16; + buffer[8*i+6] = ctx->h[i] >> 8; + buffer[8*i+7] = ctx->h[i]; + } +} + +void sha384_init(SHA512_CTX *ctx) +{ + ctx->len = 0; + ctx->h[0] = ULL(0xcbbb9d5d,0xc1059ed8); + ctx->h[1] = ULL(0x629a292a,0x367cd507); + ctx->h[2] = ULL(0x9159015a,0x3070dd17); + ctx->h[3] = ULL(0x152fecd8,0xf70e5939); + ctx->h[4] = ULL(0x67332667,0xffc00b31); + ctx->h[5] = ULL(0x8eb44a87,0x68581511); + ctx->h[6] = ULL(0xdb0c2e0d,0x64f98fa7); + ctx->h[7] = ULL(0x47b5481d,0xbefa4fa4); +} + +void sha384_finalize(SHA512_CTX *ctx, UCHAR *buffer) +{ + UCHAR buffer512[64]; + + sha512_finalize(ctx, buffer512); + memcpy(buffer, buffer512, 48); +} diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/tests/bcrypt.c wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/tests/bcrypt.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/bcrypt/tests/bcrypt.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/bcrypt/tests/bcrypt.c 2017-03-21 14:02:57.000000000 +0000 @@ -33,6 +33,7 @@ ULONG, ULONG); static NTSTATUS (WINAPI *pBCryptHash)(BCRYPT_ALG_HANDLE, UCHAR *, ULONG, UCHAR *, ULONG, UCHAR *, ULONG); static NTSTATUS (WINAPI *pBCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptDuplicateHash)(BCRYPT_HASH_HANDLE, BCRYPT_HASH_HANDLE *, UCHAR *, ULONG, ULONG); static NTSTATUS (WINAPI *pBCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE); static NTSTATUS (WINAPI *pBCryptGenRandom)(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, ULONG); @@ -142,6 +143,42 @@ return lstrcmpW(strw, buf); } +#define test_object_length(a) _test_object_length(__LINE__,a) +static void _test_object_length(unsigned line, void *handle) +{ + NTSTATUS status; + ULONG len, size; + + len = size = 0xdeadbeef; + status = pBCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); + ok_(__FILE__,line)(status == STATUS_INVALID_HANDLE, "BCryptGetProperty failed: %08x\n", status); + + len = size = 0xdeadbeef; + status = pBCryptGetProperty(handle, NULL, (UCHAR *)&len, sizeof(len), &size, 0); + ok_(__FILE__,line)(status == STATUS_INVALID_PARAMETER, "BCryptGetProperty failed: %08x\n", status); + + len = size = 0xdeadbeef; + status = pBCryptGetProperty(handle, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); + ok_(__FILE__,line)(status == STATUS_INVALID_PARAMETER, "BCryptGetProperty failed: %08x\n", status); + + len = size = 0xdeadbeef; + status = pBCryptGetProperty(handle, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); + ok_(__FILE__,line)(status == STATUS_SUCCESS, "BCryptGetProperty failed: %08x\n", status); + ok_(__FILE__,line)(size == sizeof(len), "got %u\n", size); + + len = size = 0xdeadbeef; + status = pBCryptGetProperty(handle, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); + ok_(__FILE__,line)(status == STATUS_BUFFER_TOO_SMALL, "BCryptGetProperty failed: %08x\n", status); + ok_(__FILE__,line)(len == 0xdeadbeef, "got %u\n", len); + ok_(__FILE__,line)(size == sizeof(len), "got %u\n", size); + + len = size = 0xdeadbeef; + status = pBCryptGetProperty(handle, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); + ok_(__FILE__,line)(status == STATUS_SUCCESS, "BCryptGetProperty failed: %08x\n", status); + ok_(__FILE__,line)(len != 0xdeadbeef, "len not set\n"); + ok_(__FILE__,line)(size == sizeof(len), "got %u\n", size); +} + #define test_hash_length(a,b) _test_hash_length(__LINE__,a,b) static void _test_hash_length(unsigned line, void *handle, ULONG exlen) { @@ -172,47 +209,19 @@ { static const char expected[] = "961fa64958818f767707072755d7018dcd278e94"; static const char expected_hmac[] = "2472cf65d0e090618d769d3e46f0d9446cf212da"; + UCHAR buf[512], buf_hmac[1024], buf_hmac2[1024], sha1[20], sha1_hmac[20]; + BCRYPT_HASH_HANDLE hash, hash2; BCRYPT_ALG_HANDLE alg; - BCRYPT_HASH_HANDLE hash; - UCHAR buf[512], buf_hmac[1024], sha1[20], sha1_hmac[20]; - ULONG size, len; char str[41]; NTSTATUS ret; + ULONG len; alg = NULL; ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); - ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); - ok(len == 0xdeadbeef, "got %u\n", len); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(len != 0xdeadbeef, "len not set\n"); - ok(size == sizeof(len), "got %u\n", size); - + test_object_length(alg); test_hash_length(alg, 20); test_alg_name(alg, "SHA1"); @@ -260,6 +269,29 @@ test_hash_length(hash, 20); test_alg_name(hash, "SHA1"); + len = sizeof(buf_hmac2); + ret = pBCryptDuplicateHash(NULL, &hash2, buf_hmac2, len, 0); + ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); + + len = sizeof(buf_hmac2); + ret = pBCryptDuplicateHash(hash, NULL, buf_hmac2, len, 0); + ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); + + hash2 = NULL; + len = sizeof(buf_hmac2); + ret = pBCryptDuplicateHash(hash, &hash2, buf_hmac2, len, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ok(hash2 != NULL, "hash not set\n"); + + memset(sha1_hmac, 0, sizeof(sha1_hmac)); + ret = pBCryptFinishHash(hash2, sha1_hmac, sizeof(sha1_hmac), 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + format_hash( sha1_hmac, sizeof(sha1_hmac), str ); + ok(!strcmp(str, expected_hmac), "got %s\n", str); + + ret = pBCryptDestroyHash(hash2); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + memset(sha1_hmac, 0, sizeof(sha1_hmac)); ret = pBCryptFinishHash(hash, sha1_hmac, sizeof(sha1_hmac), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); @@ -282,44 +314,16 @@ BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], buf_hmac[1024], sha256[32], sha256_hmac[32]; - ULONG size, len; char str[65]; NTSTATUS ret; + ULONG len; alg = NULL; ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA256_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); - ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); - ok(len == 0xdeadbeef, "got %u\n", len); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(len != 0xdeadbeef, "len not set\n"); - ok(size == sizeof(len), "got %u\n", size); - + test_object_length(alg); test_hash_length(alg, 32); test_alg_name(alg, "SHA256"); @@ -389,44 +393,16 @@ BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], buf_hmac[1024], sha384[48], sha384_hmac[48]; - ULONG size, len; char str[97]; NTSTATUS ret; + ULONG len; alg = NULL; ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA384_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); - ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); - ok(len == 0xdeadbeef, "got %u\n", len); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(len != 0xdeadbeef, "len not set\n"); - ok(size == sizeof(len), "got %u\n", size); - + test_object_length(alg); test_hash_length(alg, 48); test_alg_name(alg, "SHA384"); @@ -498,44 +474,16 @@ BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], buf_hmac[1024], sha512[64], sha512_hmac[64]; - ULONG size, len; char str[129]; NTSTATUS ret; + ULONG len; alg = NULL; ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA512_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); - ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); - ok(len == 0xdeadbeef, "got %u\n", len); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(len != 0xdeadbeef, "len not set\n"); - ok(size == sizeof(len), "got %u\n", size); - + test_object_length(alg); test_hash_length(alg, 64); test_alg_name(alg, "SHA512"); @@ -606,44 +554,16 @@ BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], buf_hmac[1024], md5[16], md5_hmac[16]; - ULONG size, len; char str[65]; NTSTATUS ret; + ULONG len; alg = NULL; ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); - ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); - ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); - ok(len == 0xdeadbeef, "got %u\n", len); - ok(size == sizeof(len), "got %u\n", size); - - len = size = 0xdeadbeef; - ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - ok(len != 0xdeadbeef, "len not set\n"); - ok(size == sizeof(len), "got %u\n", size); - + test_object_length(alg); test_hash_length(alg, 16); test_alg_name(alg, "MD5"); @@ -763,6 +683,10 @@ ret = pBCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret); + len = size = 0xdeadbeef; + ret = pBCryptGetProperty(alg, BCRYPT_HASH_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); + ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret); + test_alg_name(alg, "RNG"); memset(buf, 0, 16); @@ -1090,6 +1014,7 @@ pBCryptCreateHash = (void *)GetProcAddress(module, "BCryptCreateHash"); pBCryptHash = (void *)GetProcAddress(module, "BCryptHash"); pBCryptHashData = (void *)GetProcAddress(module, "BCryptHashData"); + pBCryptDuplicateHash = (void *)GetProcAddress(module, "BCryptDuplicateHash"); pBCryptFinishHash = (void *)GetProcAddress(module, "BCryptFinishHash"); pBCryptDestroyHash = (void *)GetProcAddress(module, "BCryptDestroyHash"); pBCryptGenRandom = (void *)GetProcAddress(module, "BCryptGenRandom"); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/cabinet/fdi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/cabinet/fdi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/cabinet/fdi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/cabinet/fdi.c 2017-03-21 14:02:57.000000000 +0000 @@ -2640,6 +2640,7 @@ fdin.date = file->date; fdin.time = file->time; fdin.attribs = file->attribs; + fdin.iFolder = file->index; if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) { set_error( fdi, FDIERROR_USER_ABORT, 0 ); filehf = 0; @@ -2765,6 +2766,7 @@ fdin.date = file->date; fdin.time = file->time; fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */ + fdin.iFolder = file->index; ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin)); filehf = 0; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/cabinet/tests/fdi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/cabinet/tests/fdi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/cabinet/tests/fdi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/cabinet/tests/fdi.c 2017-03-21 14:02:57.000000000 +0000 @@ -116,7 +116,7 @@ { { {'M','S','C','F'}, 0, 0x59, 0, sizeof(struct CFHEADER) + sizeof(struct CFFOLDER), 0, 3,1, 1, 1, 0, 0x1225, 0x2013 }, { sizeof(struct CFHEADER) + sizeof(struct CFFOLDER) + sizeof(struct CFFILE) + sizeof("file.dat"), 1, tcompTYPE_NONE }, - { sizeof("Hello World!")-1, 0, 0, 0x1225, 0x2013, 0xa114 }, + { sizeof("Hello World!")-1, 0, 0x1234, 0x1225, 0x2013, 0xa114 }, { 'f','i','l','e','.','d','a','t',0 }, { 0, sizeof("Hello World!")-1, sizeof("Hello World!")-1 }, { 'H','e','l','l','o',' ','W','o','r','l','d','!' } @@ -841,7 +841,7 @@ ok(info->date == 0x1225, "expected 0x1225, got %#x\n", info->date); ok(info->time == 0x2013, "expected 0x2013, got %#x\n", info->time); ok(info->attribs == 0xa114, "expected 0xa114, got %#x\n", info->attribs); - ok(info->iFolder == 0, "expected 0, got %#x\n", info->iFolder); + ok(info->iFolder == 0x1234, "expected 0x1234, got %#x\n", info->iFolder); return 1; case fdintCOPY_FILE: @@ -850,6 +850,7 @@ ok(info->cb == 12, "expected 12, got %u\n", info->cb); ok(!strcmp(info->psz1, expected), "expected %s, got %s\n", expected, info->psz1); + ok(info->iFolder == 0x1234, "expected 0x1234, got %#x\n", info->iFolder); return 0x12345678; /* call write() callback */ } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/commctrl.c wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/commctrl.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/commctrl.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/commctrl.c 2017-03-21 14:02:57.000000000 +0000 @@ -1622,45 +1622,6 @@ } /*********************************************************************** - * TaskDialogIndirect [COMCTL32.@] - */ -HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton, - int *pnRadioButton, BOOL *pfVerificationFlagChecked) -{ - UINT uType = 0; - INT ret; - FIXME("%p, %p, %p, %p\n", pTaskConfig, pnButton, pnRadioButton, pfVerificationFlagChecked); - - if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON && - pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON && - pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON) - uType |= MB_YESNOCANCEL; - else - if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON && - pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON) - uType |= MB_YESNO; - else - if (pTaskConfig->dwCommonButtons & TDCBF_RETRY_BUTTON && - pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON) - uType |= MB_RETRYCANCEL; - else - if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON && - pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON) - uType |= MB_OKCANCEL; - else - if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON) - uType |= MB_OK; - ret = MessageBoxW(pTaskConfig->hwndParent, pTaskConfig->pszMainInstruction, - pTaskConfig->pszWindowTitle, uType); - FIXME("dwCommonButtons=%x uType=%x ret=%x\n", pTaskConfig->dwCommonButtons, uType, ret); - - if (pnButton) *pnButton = ret; - if (pnRadioButton) *pnRadioButton = pTaskConfig->nDefaultButton; - if (pfVerificationFlagChecked) *pfVerificationFlagChecked = TRUE; - return S_OK; -} - -/*********************************************************************** * LoadIconWithScaleDown [COMCTL32.@] */ HRESULT WINAPI LoadIconWithScaleDown(HINSTANCE hinst, const WCHAR *name, int cx, int cy, HICON *icon) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/Makefile.in wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/Makefile.in --- wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/Makefile.in 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/Makefile.in 2017-03-21 14:02:57.000000000 +0000 @@ -30,6 +30,7 @@ string.c \ syslink.c \ tab.c \ + taskdialog.c \ theme_button.c \ theme_combo.c \ theme_dialog.c \ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/taskdialog.c wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/taskdialog.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/taskdialog.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/taskdialog.c 2017-03-21 14:02:57.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Task dialog control + * + * Copyright 2017 Fabian Maurer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "commctrl.h" +#include "winerror.h" +#include "comctl32.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(taskdialog); + +/*********************************************************************** + * TaskDialogIndirect [COMCTL32.@] + */ +HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *taskconfig, int *button, + int *radio_button, BOOL *verification_flag_checked) +{ + UINT type = 0; + INT ret; + + TRACE("%p, %p, %p, %p\n", taskconfig, button, radio_button, verification_flag_checked); + + if (taskconfig->dwCommonButtons & TDCBF_YES_BUTTON && + taskconfig->dwCommonButtons & TDCBF_NO_BUTTON && + taskconfig->dwCommonButtons & TDCBF_CANCEL_BUTTON) + type |= MB_YESNOCANCEL; + else + if (taskconfig->dwCommonButtons & TDCBF_YES_BUTTON && + taskconfig->dwCommonButtons & TDCBF_NO_BUTTON) + type |= MB_YESNO; + else + if (taskconfig->dwCommonButtons & TDCBF_RETRY_BUTTON && + taskconfig->dwCommonButtons & TDCBF_CANCEL_BUTTON) + type |= MB_RETRYCANCEL; + else + if (taskconfig->dwCommonButtons & TDCBF_OK_BUTTON && + taskconfig->dwCommonButtons & TDCBF_CANCEL_BUTTON) + type |= MB_OKCANCEL; + else + if (taskconfig->dwCommonButtons & TDCBF_OK_BUTTON) + type |= MB_OK; + + ret = MessageBoxW(taskconfig->hwndParent, taskconfig->pszMainInstruction, + taskconfig->pszWindowTitle, type); + + FIXME("dwCommonButtons=%x type=%x ret=%x\n", taskconfig->dwCommonButtons, type, ret); + + if (button) *button = ret; + if (radio_button) *radio_button = taskconfig->nDefaultButton; + if (verification_flag_checked) *verification_flag_checked = TRUE; + + return S_OK; +} diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/tests/Makefile.in wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/tests/Makefile.in --- wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/tests/Makefile.in 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/tests/Makefile.in 2017-03-21 14:02:57.000000000 +0000 @@ -22,6 +22,7 @@ subclass.c \ syslink.c \ tab.c \ + taskdialog.c \ toolbar.c \ tooltips.c \ trackbar.c \ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/tests/misc.c wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/tests/misc.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/tests/misc.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/tests/misc.c 2017-03-21 14:02:57.000000000 +0000 @@ -200,24 +200,6 @@ ok(res == TRUE, "Expected TRUE, got %d\n", res); } -static void test_TaskDialogIndirect(void) -{ - HINSTANCE hinst; - void *ptr, *ptr2; - - hinst = LoadLibraryA("comctl32.dll"); - - ptr = GetProcAddress(hinst, "TaskDialogIndirect"); - if (!ptr) - { - win_skip("TaskDialogIndirect not exported by name\n"); - return; - } - - ptr2 = GetProcAddress(hinst, (const CHAR*)345); - ok(ptr == ptr2, "got wrong pointer for ordinal 345, %p expected %p\n", ptr2, ptr); -} - static void test_LoadIconWithScaleDown(void) { static const WCHAR nonexisting_fileW[] = {'n','o','n','e','x','i','s','t','i','n','g','.','i','c','o',0}; @@ -402,7 +384,6 @@ return; test_builtin_classes(); - test_TaskDialogIndirect(); test_LoadIconWithScaleDown(); unload_v6_module(ctx_cookie, hCtx); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/tests/taskdialog.c wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/tests/taskdialog.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/comctl32/tests/taskdialog.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/comctl32/tests/taskdialog.c 2017-03-21 14:02:57.000000000 +0000 @@ -0,0 +1,58 @@ +/* Unit tests for the task dialog control. + * + * Copyright 2017 Fabian Maurer for the Wine project + * + * 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 + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "commctrl.h" + +#include "wine/test.h" +#include "v6util.h" + +static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *); + +START_TEST(taskdialog) +{ + ULONG_PTR ctx_cookie; + void *ptr_ordinal; + HINSTANCE hinst; + HANDLE hCtx; + + if (!load_v6_module(&ctx_cookie, &hCtx)) + return; + + /* Check if task dialogs are available */ + hinst = LoadLibraryA("comctl32.dll"); + + pTaskDialogIndirect = (void *)GetProcAddress(hinst, "TaskDialogIndirect"); + if (!pTaskDialogIndirect) + { + win_skip("TaskDialogIndirect not exported by name\n"); + unload_v6_module(ctx_cookie, hCtx); + return; + } + + ptr_ordinal = GetProcAddress(hinst, (const char *)345); + ok(pTaskDialogIndirect == ptr_ordinal, "got wrong pointer for ordinal 345, %p expected %p\n", + ptr_ordinal, pTaskDialogIndirect); + + unload_v6_module(ctx_cookie, hCtx); +} diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/comdlg32/filedlg.c wine-staging-2.4.0~ubuntu16.04.1/dlls/comdlg32/filedlg.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/comdlg32/filedlg.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/comdlg32/filedlg.c 2017-03-21 14:02:57.000000000 +0000 @@ -383,18 +383,26 @@ static void init_filedlg_infoA(OPENFILENAMEA *ofn, FileOpenDlgInfos *info) { OPENFILENAMEW ofnW; + int len; ofnW = *(OPENFILENAMEW *)ofn; ofnW.lpstrInitialDir = heap_strdupAtoW(ofn->lpstrInitialDir); - ofnW.lpstrFile = heap_strdupAtoW(ofn->lpstrFile); ofnW.lpstrDefExt = heap_strdupAtoW(ofn->lpstrDefExt); ofnW.lpstrTitle = heap_strdupAtoW(ofn->lpstrTitle); + if (ofn->lpstrFile) + { + len = MultiByteToWideChar(CP_ACP, 0, ofn->lpstrFile, ofn->nMaxFile, NULL, 0); + ofnW.lpstrFile = MemAlloc(len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, ofn->lpstrFile, ofn->nMaxFile, ofnW.lpstrFile, len); + ofnW.nMaxFile = len; + } + if (ofn->lpstrFilter) { - int n, len; LPCSTR s; + int n; /* filter is a list... title\0ext\0......\0\0 */ s = ofn->lpstrFilter; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/concrt140/concrt140.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/concrt140/concrt140.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/concrt140/concrt140.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/concrt140/concrt140.spec 2017-03-21 14:02:57.000000000 +0000 @@ -74,8 +74,8 @@ @ stub -arch=win64 ??0default_scheduler_exists@Concurrency@@QEAA@PEBD@Z @ stub -arch=i386 ??0default_scheduler_exists@Concurrency@@QAE@XZ @ stub -arch=win64 ??0default_scheduler_exists@Concurrency@@QEAA@XZ -@ stub -arch=i386 ??0event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0event@Concurrency@@QEAA@XZ +@ thiscall -arch=win32 ??0event@Concurrency@@QAE@XZ(ptr) msvcr120.??0event@Concurrency@@QAE@XZ +@ cdecl -arch=win64 ??0event@Concurrency@@QEAA@XZ(ptr) msvcr120.??0event@Concurrency@@QEAA@XZ @ stub -arch=i386 ??0improper_lock@Concurrency@@QAE@PBD@Z @ stub -arch=win64 ??0improper_lock@Concurrency@@QEAA@PEBD@Z @ stub -arch=i386 ??0improper_lock@Concurrency@@QAE@XZ @@ -188,8 +188,8 @@ @ stub -arch=win64 ??1agent@Concurrency@@UEAA@XZ @ thiscall -arch=i386 ??1critical_section@Concurrency@@QAE@XZ(ptr) msvcr120.??1critical_section@Concurrency@@QAE@XZ @ cdecl -arch=win64 ??1critical_section@Concurrency@@QEAA@XZ(ptr) msvcr120.??1critical_section@Concurrency@@QEAA@XZ -@ stub -arch=i386 ??1event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1event@Concurrency@@QEAA@XZ +@ thiscall -arch=win32 ??1event@Concurrency@@QAE@XZ(ptr) msvcr120.??1event@Concurrency@@QAE@XZ +@ cdecl -arch=win64 ??1event@Concurrency@@QEAA@XZ(ptr) msvcr120.??1event@Concurrency@@QEAA@XZ @ thiscall -arch=win32 ??1reader_writer_lock@Concurrency@@QAE@XZ(ptr) msvcr120.??1reader_writer_lock@Concurrency@@QAE@XZ @ cdecl -arch=win64 ??1reader_writer_lock@Concurrency@@QEAA@XZ(ptr) msvcr120.??1reader_writer_lock@Concurrency@@QEAA@XZ @ thiscall -arch=i386 ??1scoped_lock@critical_section@Concurrency@@QAE@XZ(ptr) msvcr120.??1scoped_lock@critical_section@Concurrency@@QAE@XZ @@ -490,10 +490,10 @@ @ cdecl -arch=win64 ?notify_all@_Condition_variable@details@Concurrency@@QEAAXXZ(ptr) msvcr120.?notify_all@_Condition_variable@details@Concurrency@@QEAAXXZ @ thiscall -arch=i386 ?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ(ptr) msvcr120.?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ @ cdecl -arch=win64 ?notify_one@_Condition_variable@details@Concurrency@@QEAAXXZ(ptr) msvcr120.?notify_one@_Condition_variable@details@Concurrency@@QEAAXXZ -@ stub -arch=i386 ?reset@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?reset@event@Concurrency@@QEAAXXZ -@ stub -arch=i386 ?set@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?set@event@Concurrency@@QEAAXXZ +@ thiscall -arch=win32 ?reset@event@Concurrency@@QAEXXZ(ptr) msvcr120.?reset@event@Concurrency@@QAEXXZ +@ cdecl -arch=win64 ?reset@event@Concurrency@@QEAAXXZ(ptr) msvcr120.?reset@event@Concurrency@@QEAAXXZ +@ thiscall -arch=win32 ?set@event@Concurrency@@QAEXXZ(ptr) msvcr120.?set@event@Concurrency@@QAEXXZ +@ cdecl -arch=win64 ?set@event@Concurrency@@QEAAXXZ(ptr) msvcr120.?set@event@Concurrency@@QEAAXXZ @ stub -arch=win32 ?set_task_execution_resources@Concurrency@@YAXGPAU_GROUP_AFFINITY@@@Z @ stub -arch=win64 ?set_task_execution_resources@Concurrency@@YAXGPEAU_GROUP_AFFINITY@@@Z @ stub -arch=win32 ?set_task_execution_resources@Concurrency@@YAXK@Z @@ -521,13 +521,13 @@ @ cdecl -arch=win64 ?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z(ptr ptr) msvcr120.?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z @ stub -arch=win32 ?wait@agent@Concurrency@@SA?AW4agent_status@2@PAV12@I@Z @ stub -arch=win64 ?wait@agent@Concurrency@@SA?AW4agent_status@2@PEAV12@I@Z -@ stub -arch=i386 ?wait@event@Concurrency@@QAEII@Z -@ stub -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z +@ thiscall -arch=win32 ?wait@event@Concurrency@@QAEII@Z(ptr) msvcr120.?wait@event@Concurrency@@QAEII@Z +@ cdecl -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z(ptr) msvcr120.?wait@event@Concurrency@@QEAA_KI@Z @ thiscall -arch=i386 ?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z(ptr ptr long) msvcr120.?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z @ cdecl -arch=win64 ?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z(ptr ptr long) msvcr120.?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z @ stub -arch=win32 ?wait_for_all@agent@Concurrency@@SAXIPAPAV12@PAW4agent_status@2@I@Z @ stub -arch=win64 ?wait_for_all@agent@Concurrency@@SAX_KPEAPEAV12@PEAW4agent_status@2@I@Z -@ stub -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z -@ stub -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z +@ cdecl -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z(ptr long long long) msvcr120.?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z +@ cdecl -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z(ptr long long long) msvcr120.?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z @ stub -arch=win32 ?wait_for_one@agent@Concurrency@@SAXIPAPAV12@AAW4agent_status@2@AAII@Z @ stub -arch=win64 ?wait_for_one@agent@Concurrency@@SAX_KPEAPEAV12@AEAW4agent_status@2@AEA_KI@Z diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/crtdll/crtdll.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/crtdll/crtdll.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/crtdll/crtdll.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/crtdll/crtdll.spec 2017-03-21 14:02:57.000000000 +0000 @@ -470,7 +470,7 @@ @ cdecl strcpy(ptr str) msvcrt.strcpy @ cdecl strcspn(str str) msvcrt.strcspn @ cdecl strerror(long) msvcrt.strerror -@ cdecl strftime(str long str ptr) msvcrt.strftime +@ cdecl strftime(ptr long str ptr) msvcrt.strftime @ cdecl strlen(str) msvcrt.strlen @ cdecl strncat(str str long) msvcrt.strncat @ cdecl strncmp(str str long) msvcrt.strncmp diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/crypt32/tests/crl.c wine-staging-2.4.0~ubuntu16.04.1/dlls/crypt32/tests/crl.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/crypt32/tests/crl.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/crypt32/tests/crl.c 2017-03-21 14:02:57.000000000 +0000 @@ -148,6 +148,7 @@ BOOL ret; DWORD GLE; + ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); if (!store) return; /* Bad CRL encoding type */ @@ -425,21 +426,24 @@ static void testFindCRL(void) { - HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, - CERT_STORE_CREATE_NEW_FLAG, NULL); + HCERTSTORE store; PCCRL_CONTEXT context; PCCERT_CONTEXT cert, endCert, rootCert; CRL_FIND_ISSUED_FOR_PARA issuedForPara = { NULL, NULL }; DWORD count, revoked_count; BOOL ret; - if (!store) return; if (!pCertFindCRLInStore || !pCertFindCertificateInCRL) { win_skip("CertFindCRLInStore or CertFindCertificateInCRL not available\n"); return; } + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); + if (!store) return; + ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL); ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError()); @@ -783,6 +787,7 @@ DWORD flags; BOOL ret; + ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); if (!store) return; /* Crash diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d10core/tests/device.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d10core/tests/device.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d10core/tests/device.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d10core/tests/device.c 2017-03-21 14:02:57.000000000 +0000 @@ -6110,6 +6110,206 @@ release_test_context(&test_context); } +static void test_cube_maps(void) +{ + unsigned int i, j, sub_resource_idx, sub_resource_count; + struct d3d10core_test_context test_context; + D3D10_TEXTURE2D_DESC texture_desc; + ID3D10ShaderResourceView *srv; + ID3D10Texture2D *rtv_texture; + ID3D10RenderTargetView *rtv; + struct vec4 expected_result; + ID3D10Resource *texture; + ID3D10PixelShader *ps; + ID3D10Device *device; + float data[64 * 64]; + ID3D10Buffer *cb; + HRESULT hr; + RECT rect; + struct + { + unsigned int face; + unsigned int level; + unsigned int padding[2]; + } constant; + + static const DWORD ps_cube_code[] = + { +#if 0 + TextureCube t; + SamplerState s; + + uint face; + uint level; + + float4 main(float4 position : SV_POSITION) : SV_Target + { + float2 p; + p.x = position.x / 640.0f; + p.y = position.y / 480.0f; + + float3 coord; + switch (face) + { + case 0: + coord = float3(1.0f, p.x, p.y); + break; + case 1: + coord = float3(-1.0f, p.x, p.y); + break; + case 2: + coord = float3(p.x, 1.0f, p.y); + break; + case 3: + coord = float3(p.x, -1.0f, p.y); + break; + case 4: + coord = float3(p.x, p.y, 1.0f); + break; + case 5: + default: + coord = float3(p.x, p.y, -1.0f); + break; + } + return t.SampleLevel(s, coord, level); + } +#endif + 0x43425844, 0x039aee18, 0xfd630453, 0xb884cf0f, 0x10100744, 0x00000001, 0x00000310, 0x00000003, + 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040, + 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, + 0x04003058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, + 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0400004c, 0x0020800a, 0x00000000, + 0x00000000, 0x03000006, 0x00004001, 0x00000000, 0x05000036, 0x00100012, 0x00000000, 0x00004001, + 0x3f800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x00000000, + 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000001, 0x05000036, + 0x00100012, 0x00000000, 0x00004001, 0xbf800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, + 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, + 0x00004001, 0x00000002, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, 0x00004002, + 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, + 0x3f800000, 0x01000002, 0x03000006, 0x00004001, 0x00000003, 0x0a000038, 0x00100052, 0x00000000, + 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, + 0x00100022, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x03000006, 0x00004001, 0x00000004, + 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, + 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x01000002, + 0x0100000a, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, + 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0xbf800000, + 0x01000002, 0x01000017, 0x06000056, 0x00100082, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, + 0x0b000048, 0x001020f2, 0x00000000, 0x00100246, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, + 0x00000000, 0x0010003a, 0x00000000, 0x0100003e, + }; + static const struct test + { + unsigned int miplevel_count; + unsigned int array_size; + } + tests[] = + { + {1, 6}, + {2, 6}, + {3, 6}, + {0, 0}, + }; + + if (!init_test_context(&test_context)) + return; + + device = test_context.device; + + ID3D10Texture2D_GetDesc(test_context.backbuffer, &texture_desc); + texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &rtv_texture); + ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); + hr = ID3D10Device_CreateRenderTargetView(device, (ID3D10Resource *)rtv_texture, NULL, &rtv); + ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); + + memset(&constant, 0, sizeof(constant)); + cb = create_buffer(device, D3D10_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); + + ID3D10Device_OMSetRenderTargets(device, 1, &rtv, NULL); + ID3D10Device_PSSetConstantBuffers(device, 0, 1, &cb); + + hr = ID3D10Device_CreatePixelShader(device, ps_cube_code, sizeof(ps_cube_code), &ps); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); + ID3D10Device_PSSetShader(device, ps); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i) + { + const struct test *test = &tests[i]; + + if (!test->miplevel_count) + { + srv = NULL; + ID3D10Device_PSSetShaderResources(device, 0, 1, &srv); + + memset(&expected_result, 0, sizeof(expected_result)); + + memset(&constant, 0, sizeof(constant)); + ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)cb, 0, NULL, &constant, 0, 0); + draw_quad(&test_context); + check_texture_vec4(rtv_texture, &expected_result, 0); + constant.level = 1; + ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)cb, 0, NULL, &constant, 0, 0); + draw_quad(&test_context); + check_texture_vec4(rtv_texture, &expected_result, 0); + continue; + } + + texture_desc.Width = 64; + texture_desc.Height = 64; + texture_desc.MipLevels = test->miplevel_count; + texture_desc.ArraySize = test->array_size; + texture_desc.Format = DXGI_FORMAT_R32_FLOAT; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D10_USAGE_DEFAULT; + texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = D3D10_RESOURCE_MISC_TEXTURECUBE; + hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D10Texture2D **)&texture); + ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); + + hr = ID3D10Device_CreateShaderResourceView(device, texture, NULL, &srv); + ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); + ID3D10Device_PSSetShaderResources(device, 0, 1, &srv); + + sub_resource_count = texture_desc.MipLevels * texture_desc.ArraySize; + for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) + { + for (j = 0; j < sizeof(data) / sizeof(*data); ++j) + data[j] = sub_resource_idx; + ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, sub_resource_idx, NULL, + data, texture_desc.Width * sizeof(*data), 0); + } + + expected_result.y = expected_result.z = 0.0f; + expected_result.w = 1.0f; + for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) + { + constant.face = (sub_resource_idx / texture_desc.MipLevels) % 6; + constant.level = sub_resource_idx % texture_desc.MipLevels; + ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)cb, 0, NULL, &constant, 0, 0); + + draw_quad(&test_context); + expected_result.x = sub_resource_idx; + /* Avoid testing values affected by seamless cube map filtering. */ + SetRect(&rect, 100, 100, 540, 380); + check_texture_sub_resource_vec4(rtv_texture, 0, &rect, &expected_result, 0); + } + + ID3D10Resource_Release(texture); + ID3D10ShaderResourceView_Release(srv); + } + + ID3D10Buffer_Release(cb); + ID3D10PixelShader_Release(ps); + ID3D10RenderTargetView_Release(rtv); + ID3D10Texture2D_Release(rtv_texture); + release_test_context(&test_context); +} + static void test_depth_stencil_sampling(void) { ID3D10PixelShader *ps_cmp, *ps_depth, *ps_stencil, *ps_depth_stencil; @@ -10358,6 +10558,93 @@ release_test_context(&test_context); } +static void test_unbind_shader_resource_view(void) +{ + struct d3d10core_test_context test_context; + D3D10_SUBRESOURCE_DATA resource_data; + ID3D10ShaderResourceView *srv, *srv2; + D3D10_TEXTURE2D_DESC texture_desc; + ID3D10Texture2D *texture; + ID3D10PixelShader *ps; + ID3D10Device *device; + HRESULT hr; + + static const DWORD ps_code[] = + { +#if 0 + Texture2D t0; + Texture2D t1; + SamplerState s; + + float4 main() : SV_Target + { + return min(t0.Sample(s, float2(0, 0)) + t1.Sample(s, float2(0, 0)), 1.0f); + } +#endif + 0x43425844, 0x698dc0cb, 0x0bf322b8, 0xee127418, 0xfe9214ce, 0x00000001, 0x00000168, 0x00000003, + 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, + 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, + 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000f0, 0x00000040, 0x0000003c, + 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, + 0x00107000, 0x00000001, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, + 0x0c000045, 0x001000f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0c000045, 0x001000f2, 0x00000001, 0x00004002, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, + 0x07000000, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100e46, 0x00000001, 0x0a000033, + 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, + 0x3f800000, 0x0100003e, + }; + static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; + static const DWORD texture_data[] = {0xff00ff00}; + + if (!init_test_context(&test_context)) + return; + + device = test_context.device; + + texture_desc.Width = 1; + texture_desc.Height = 1; + texture_desc.MipLevels = 0; + texture_desc.ArraySize = 1; + texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D10_USAGE_DEFAULT; + texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = 0; + + resource_data.pSysMem = texture_data; + resource_data.SysMemPitch = sizeof(texture_data); + resource_data.SysMemSlicePitch = 0; + + hr = ID3D10Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); + ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); + hr = ID3D10Device_CreateShaderResourceView(device, (ID3D10Resource *)texture, NULL, &srv); + ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); + hr = ID3D10Device_CreatePixelShader(device, ps_code, sizeof(ps_code), &ps); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); + ID3D10Device_PSSetShader(device, ps); + + ID3D10Device_PSSetShaderResources(device, 0, 1, &srv); + ID3D10Device_PSSetShaderResources(device, 1, 1, &srv); + ID3D10Device_ClearRenderTargetView(device, test_context.backbuffer_rtv, white); + draw_quad(&test_context); + check_texture_color(test_context.backbuffer, 0xff00ff00, 1); + + srv2 = NULL; + ID3D10Device_PSSetShaderResources(device, 0, 1, &srv2); + ID3D10Device_PSSetShaderResources(device, 1, 1, &srv2); + ID3D10Device_ClearRenderTargetView(device, test_context.backbuffer_rtv, white); + draw_quad(&test_context); + todo_wine check_texture_color(test_context.backbuffer, 0x00000000, 1); + + ID3D10PixelShader_Release(ps); + ID3D10ShaderResourceView_Release(srv); + ID3D10Texture2D_Release(texture); + release_test_context(&test_context); +} + static void test_stencil_separate(void) { struct d3d10core_test_context test_context; @@ -10915,7 +11202,7 @@ texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; - texture_desc.Format = DXGI_FORMAT_R32G32B32A32_UINT; + texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D10_USAGE_DEFAULT; @@ -11296,6 +11583,7 @@ test_clear_state(); test_blend(); test_texture(); + test_cube_maps(); test_depth_stencil_sampling(); test_multiple_render_targets(); test_private_data(); @@ -11326,6 +11614,7 @@ test_required_format_support(); test_ddy(); test_shader_input_registers_limits(); + test_unbind_shader_resource_view(); test_stencil_separate(); test_sm4_ret_instruction(); test_primitive_restart(); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d11/device.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d11/device.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d11/device.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d11/device.c 2017-03-21 14:02:57.000000000 +0000 @@ -654,9 +654,6 @@ if (unordered_access_view_count != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) { - if (initial_counts) - FIXME("Ignoring initial counts.\n"); - wined3d_mutex_lock(); for (i = 0; i < unordered_access_view_start_slot; ++i) { @@ -667,6 +664,12 @@ struct d3d11_unordered_access_view *view = unsafe_impl_from_ID3D11UnorderedAccessView(unordered_access_views[i]); + if (initial_counts && view && view->desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER + && (view->desc.u.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER)) + && initial_counts[i] != ~(UINT)0) + FIXME("Ignoring initial count %u for slot %u.\n", + initial_counts[i], unordered_access_view_start_slot + i); + wined3d_device_set_unordered_access_view(device->wined3d_device, unordered_access_view_start_slot + i, view ? view->wined3d_view : NULL); @@ -1226,14 +1229,16 @@ TRACE("iface %p, start_slot %u, view_count %u, views %p, initial_counts %p.\n", iface, start_slot, view_count, views, initial_counts); - if (initial_counts) - FIXME("Ignoring initial counts.\n"); - wined3d_mutex_lock(); for (i = 0; i < view_count; ++i) { struct d3d11_unordered_access_view *view = unsafe_impl_from_ID3D11UnorderedAccessView(views[i]); + if (initial_counts && view && view->desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER + && (view->desc.u.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER)) + && initial_counts[i] != ~(UINT)0) + FIXME("Ignoring initial count %u for slot %u.\n", initial_counts[i], start_slot + i); + wined3d_device_set_cs_uav(device->wined3d_device, start_slot + i, view ? view->wined3d_view : NULL); } @@ -1985,7 +1990,27 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_CSGetShaderResources(ID3D11DeviceContext *iface, UINT start_slot, UINT view_count, ID3D11ShaderResourceView **views) { - FIXME("iface %p, start_slot %u, view_count %u, views %p stub!\n", iface, start_slot, view_count, views); + struct d3d_device *device = device_from_immediate_ID3D11DeviceContext(iface); + unsigned int i; + + TRACE("iface %p, start_slot %u, view_count %u, views %p.\n", iface, start_slot, view_count, views); + + wined3d_mutex_lock(); + for (i = 0; i < view_count; ++i) + { + struct wined3d_shader_resource_view *wined3d_view; + struct d3d_shader_resource_view *view_impl; + + if (!(wined3d_view = wined3d_device_get_cs_resource_view(device->wined3d_device, start_slot + i))) + { + views[i] = NULL; + continue; + } + + view_impl = wined3d_shader_resource_view_get_parent(wined3d_view); + ID3D11ShaderResourceView_AddRef(views[i] = &view_impl->ID3D11ShaderResourceView_iface); + } + wined3d_mutex_unlock(); } static void STDMETHODCALLTYPE d3d11_immediate_context_CSGetUnorderedAccessViews(ID3D11DeviceContext *iface, @@ -1997,22 +2022,81 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_CSGetShader(ID3D11DeviceContext *iface, ID3D11ComputeShader **shader, ID3D11ClassInstance **class_instances, UINT *class_instance_count) { - FIXME("iface %p, shader %p, class_instances %p, class_instance_count %p stub!\n", + struct d3d_device *device = device_from_immediate_ID3D11DeviceContext(iface); + struct d3d11_compute_shader *shader_impl; + struct wined3d_shader *wined3d_shader; + + TRACE("iface %p, shader %p, class_instances %p, class_instance_count %p.\n", iface, shader, class_instances, class_instance_count); + + if (class_instances || class_instance_count) + FIXME("Dynamic linking not implemented yet.\n"); + + wined3d_mutex_lock(); + if (!(wined3d_shader = wined3d_device_get_compute_shader(device->wined3d_device))) + { + wined3d_mutex_unlock(); + *shader = NULL; + return; + } + + shader_impl = wined3d_shader_get_parent(wined3d_shader); + wined3d_mutex_unlock(); + ID3D11ComputeShader_AddRef(*shader = &shader_impl->ID3D11ComputeShader_iface); } static void STDMETHODCALLTYPE d3d11_immediate_context_CSGetSamplers(ID3D11DeviceContext *iface, UINT start_slot, UINT sampler_count, ID3D11SamplerState **samplers) { - FIXME("iface %p, start_slot %u, sampler_count %u, samplers %p stub!\n", + struct d3d_device *device = device_from_immediate_ID3D11DeviceContext(iface); + unsigned int i; + + TRACE("iface %p, start_slot %u, sampler_count %u, samplers %p.\n", iface, start_slot, sampler_count, samplers); + + wined3d_mutex_lock(); + for (i = 0; i < sampler_count; ++i) + { + struct wined3d_sampler *wined3d_sampler; + struct d3d_sampler_state *sampler_impl; + + if (!(wined3d_sampler = wined3d_device_get_cs_sampler(device->wined3d_device, start_slot + i))) + { + samplers[i] = NULL; + continue; + } + + sampler_impl = wined3d_sampler_get_parent(wined3d_sampler); + ID3D11SamplerState_AddRef(samplers[i] = &sampler_impl->ID3D11SamplerState_iface); + } + wined3d_mutex_unlock(); } static void STDMETHODCALLTYPE d3d11_immediate_context_CSGetConstantBuffers(ID3D11DeviceContext *iface, UINT start_slot, UINT buffer_count, ID3D11Buffer **buffers) { - FIXME("iface %p, start_slot %u, buffer_count %u, buffer %p stub!\n", + struct d3d_device *device = device_from_immediate_ID3D11DeviceContext(iface); + unsigned int i; + + TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p.\n", iface, start_slot, buffer_count, buffers); + + wined3d_mutex_lock(); + for (i = 0; i < buffer_count; ++i) + { + struct wined3d_buffer *wined3d_buffer; + struct d3d_buffer *buffer_impl; + + if (!(wined3d_buffer = wined3d_device_get_cs_cb(device->wined3d_device, start_slot + i))) + { + buffers[i] = NULL; + continue; + } + + buffer_impl = wined3d_buffer_get_parent(wined3d_buffer); + ID3D11Buffer_AddRef(buffers[i] = &buffer_impl->ID3D11Buffer_iface); + } + wined3d_mutex_unlock(); } static void STDMETHODCALLTYPE d3d11_immediate_context_ClearState(ID3D11DeviceContext *iface) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d11/tests/d3d11.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d11/tests/d3d11.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d11/tests/d3d11.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d11/tests/d3d11.c 2017-03-21 14:02:57.000000000 +0000 @@ -18,6 +18,7 @@ */ #include +#include #define COBJMACROS #include "initguid.h" #include "d3d11.h" @@ -6439,6 +6440,312 @@ release_test_context(&test_context); } +static void test_cube_maps(void) +{ + struct shader + { + const DWORD *code; + size_t size; + }; + + unsigned int i, j, sub_resource_idx, sub_resource_count; + struct d3d11_test_context test_context; + D3D11_TEXTURE2D_DESC texture_desc; + const struct shader *current_ps; + D3D_FEATURE_LEVEL feature_level; + ID3D11ShaderResourceView *srv; + ID3D11DeviceContext *context; + ID3D11Texture2D *rtv_texture; + ID3D11RenderTargetView *rtv; + struct vec4 expected_result; + ID3D11Resource *texture; + ID3D11PixelShader *ps; + ID3D11Device *device; + float data[64 * 64]; + ID3D11Buffer *cb; + HRESULT hr; + RECT rect; + struct + { + unsigned int face; + unsigned int level; + unsigned int cube; + unsigned int padding; + } constant; + + static const DWORD ps_cube_code[] = + { +#if 0 + TextureCube t; + SamplerState s; + + uint face; + uint level; + + float4 main(float4 position : SV_POSITION) : SV_Target + { + float2 p; + p.x = position.x / 640.0f; + p.y = position.y / 480.0f; + + float3 coord; + switch (face) + { + case 0: + coord = float3(1.0f, p.x, p.y); + break; + case 1: + coord = float3(-1.0f, p.x, p.y); + break; + case 2: + coord = float3(p.x, 1.0f, p.y); + break; + case 3: + coord = float3(p.x, -1.0f, p.y); + break; + case 4: + coord = float3(p.x, p.y, 1.0f); + break; + case 5: + default: + coord = float3(p.x, p.y, -1.0f); + break; + } + return t.SampleLevel(s, coord, level); + } +#endif + 0x43425844, 0x039aee18, 0xfd630453, 0xb884cf0f, 0x10100744, 0x00000001, 0x00000310, 0x00000003, + 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040, + 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, 0x00000000, + 0x04003058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, + 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0400004c, 0x0020800a, 0x00000000, + 0x00000000, 0x03000006, 0x00004001, 0x00000000, 0x05000036, 0x00100012, 0x00000000, 0x00004001, + 0x3f800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x00000000, + 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000001, 0x05000036, + 0x00100012, 0x00000000, 0x00004001, 0xbf800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, + 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, + 0x00004001, 0x00000002, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, 0x00004002, + 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x00004001, + 0x3f800000, 0x01000002, 0x03000006, 0x00004001, 0x00000003, 0x0a000038, 0x00100052, 0x00000000, + 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, + 0x00100022, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x03000006, 0x00004001, 0x00000004, + 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, + 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x01000002, + 0x0100000a, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, + 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0xbf800000, + 0x01000002, 0x01000017, 0x06000056, 0x00100082, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, + 0x0b000048, 0x001020f2, 0x00000000, 0x00100246, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, + 0x00000000, 0x0010003a, 0x00000000, 0x0100003e, + }; + static const struct shader ps_cube = {ps_cube_code, sizeof(ps_cube_code)}; + static const DWORD ps_cube_array_code[] = + { +#if 0 + TextureCubeArray t; + SamplerState s; + + uint face; + uint level; + uint cube; + + float4 main(float4 position : SV_POSITION) : SV_Target + { + float2 p; + p.x = position.x / 640.0f; + p.y = position.y / 480.0f; + + float3 coord; + switch (face) + { + case 0: + coord = float3(1.0f, p.x, p.y); + break; + case 1: + coord = float3(-1.0f, p.x, p.y); + break; + case 2: + coord = float3(p.x, 1.0f, p.y); + break; + case 3: + coord = float3(p.x, -1.0f, p.y); + break; + case 4: + coord = float3(p.x, p.y, 1.0f); + break; + case 5: + default: + coord = float3(p.x, p.y, -1.0f); + break; + } + return t.SampleLevel(s, float4(coord, cube), level); + } +#endif + 0x43425844, 0xb8d5b94a, 0xdb4be034, 0x183aed19, 0xad4af415, 0x00000001, 0x00000328, 0x00000003, + 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000028c, 0x00000041, + 0x000000a3, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300005a, 0x00106000, + 0x00000000, 0x04005058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, + 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0400004c, 0x0020800a, + 0x00000000, 0x00000000, 0x03000006, 0x00004001, 0x00000000, 0x05000036, 0x00100012, 0x00000000, + 0x00004001, 0x3f800000, 0x0a000038, 0x00100062, 0x00000000, 0x00101106, 0x00000000, 0x00004002, + 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, 0x03000006, 0x00004001, 0x00000001, + 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0xbf800000, 0x0a000038, 0x00100062, 0x00000000, + 0x00101106, 0x00000000, 0x00004002, 0x00000000, 0x3acccccd, 0x3b088889, 0x00000000, 0x01000002, + 0x03000006, 0x00004001, 0x00000002, 0x0a000038, 0x00100052, 0x00000000, 0x00101106, 0x00000000, + 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, 0x05000036, 0x00100022, 0x00000000, + 0x00004001, 0x3f800000, 0x01000002, 0x03000006, 0x00004001, 0x00000003, 0x0a000038, 0x00100052, + 0x00000000, 0x00101106, 0x00000000, 0x00004002, 0x3acccccd, 0x00000000, 0x3b088889, 0x00000000, + 0x05000036, 0x00100022, 0x00000000, 0x00004001, 0xbf800000, 0x01000002, 0x03000006, 0x00004001, + 0x00000004, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd, + 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, + 0x01000002, 0x0100000a, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, + 0x3acccccd, 0x3b088889, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, + 0xbf800000, 0x01000002, 0x01000017, 0x06000056, 0x00100032, 0x00000001, 0x00208a66, 0x00000000, + 0x00000000, 0x05000036, 0x00100082, 0x00000000, 0x0010000a, 0x00000001, 0x0b000048, 0x001020f2, + 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0010001a, + 0x00000001, 0x0100003e, + }; + static const struct shader ps_cube_array = {ps_cube_array_code, sizeof(ps_cube_array_code)}; + static const struct ps_test + { + const struct shader *ps; + unsigned int miplevel_count; + unsigned int array_size; + } + ps_tests[] = + { + {&ps_cube, 1, 6}, + {&ps_cube, 2, 6}, + {&ps_cube, 3, 6}, + {&ps_cube, 0, 6}, + + {&ps_cube_array, 1, 12}, + {&ps_cube_array, 2, 12}, + {&ps_cube_array, 3, 12}, + {&ps_cube_array, 0, 12}, + }; + + if (!init_test_context(&test_context, NULL)) + return; + + device = test_context.device; + context = test_context.immediate_context; + feature_level = ID3D11Device_GetFeatureLevel(device); + + ID3D11Texture2D_GetDesc(test_context.backbuffer, &texture_desc); + texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &rtv_texture); + ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); + hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)rtv_texture, NULL, &rtv); + ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr); + + memset(&constant, 0, sizeof(constant)); + cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), &constant); + + ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); + ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); + + ps = NULL; + current_ps = NULL; + for (i = 0; i < sizeof(ps_tests) / sizeof(*ps_tests); ++i) + { + const struct ps_test *test = &ps_tests[i]; + + if (test->array_size / 6 > 1 && feature_level < D3D_FEATURE_LEVEL_10_1) + { + skip("Test %u: Cube map array textures require feature level 10_1.\n", i); + continue; + } + + if (current_ps != test->ps) + { + if (ps) + ID3D11PixelShader_Release(ps); + + current_ps = test->ps; + + hr = ID3D11Device_CreatePixelShader(device, current_ps->code, current_ps->size, NULL, &ps); + ok(SUCCEEDED(hr), "Test %u: Failed to create pixel shader, hr %#x.\n", i, hr); + ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); + } + + if (!test->miplevel_count) + { + srv = NULL; + ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); + + memset(&expected_result, 0, sizeof(expected_result)); + + memset(&constant, 0, sizeof(constant)); + ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); + draw_quad(&test_context); + check_texture_vec4(rtv_texture, &expected_result, 0); + constant.level = 1; + ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); + draw_quad(&test_context); + check_texture_vec4(rtv_texture, &expected_result, 0); + continue; + } + + texture_desc.Width = 64; + texture_desc.Height = 64; + texture_desc.MipLevels = test->miplevel_count; + texture_desc.ArraySize = test->array_size; + texture_desc.Format = DXGI_FORMAT_R32_FLOAT; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&texture); + ok(SUCCEEDED(hr), "Test %u: Failed to create 2d texture, hr %#x.\n", i, hr); + + hr = ID3D11Device_CreateShaderResourceView(device, texture, NULL, &srv); + ok(SUCCEEDED(hr), "Test %u: Failed to create shader resource view, hr %#x.\n", i, hr); + ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); + + sub_resource_count = texture_desc.MipLevels * texture_desc.ArraySize; + for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) + { + for (j = 0; j < sizeof(data) / sizeof(*data); ++j) + data[j] = sub_resource_idx; + ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)texture, sub_resource_idx, NULL, + data, texture_desc.Width * sizeof(*data), 0); + } + + expected_result.y = expected_result.z = 0.0f; + expected_result.w = 1.0f; + for (sub_resource_idx = 0; sub_resource_idx < sub_resource_count; ++sub_resource_idx) + { + constant.face = (sub_resource_idx / texture_desc.MipLevels) % 6; + constant.level = sub_resource_idx % texture_desc.MipLevels; + constant.cube = (sub_resource_idx / texture_desc.MipLevels) / 6; + ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &constant, 0, 0); + + draw_quad(&test_context); + expected_result.x = sub_resource_idx; + /* Avoid testing values affected by seamless cube map filtering. */ + SetRect(&rect, 100, 100, 540, 380); + check_texture_sub_resource_vec4(rtv_texture, 0, &rect, &expected_result, 0); + } + + ID3D11Resource_Release(texture); + ID3D11ShaderResourceView_Release(srv); + } + ID3D11PixelShader_Release(ps); + + ID3D11Buffer_Release(cb); + ID3D11RenderTargetView_Release(rtv); + ID3D11Texture2D_Release(rtv_texture); + release_test_context(&test_context); +} + static void test_depth_stencil_sampling(void) { ID3D11PixelShader *ps_cmp, *ps_depth, *ps_stencil, *ps_depth_stencil; @@ -11519,7 +11826,11 @@ static void test_fl9_draw(const D3D_FEATURE_LEVEL feature_level) { struct d3d11_test_context test_context; + D3D11_SUBRESOURCE_DATA resource_data; + D3D11_TEXTURE2D_DESC texture_desc; + ID3D11ShaderResourceView *srv; ID3D11DeviceContext *context; + ID3D11Texture2D *texture; ID3D11PixelShader *ps; ID3D11Device *device; HRESULT hr; @@ -11546,6 +11857,34 @@ 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, }; + static const DWORD ps_texture_code[] = + { +#if 0 + Texture2D t; + SamplerState s; + + float4 main() : SV_TARGET + { + return t.Sample(s, (float2)0); + } +#endif + 0x43425844, 0xf876c2db, 0x13725f1f, 0xcb6d3d65, 0x9994473f, 0x00000001, 0x000001d4, 0x00000005, + 0x00000034, 0x000000a0, 0x00000124, 0x00000190, 0x000001a0, 0x53414e58, 0x00000064, 0x00000064, + 0xffff0200, 0x0000003c, 0x00000028, 0x00280000, 0x00280000, 0x00280000, 0x00240001, 0x00280000, + 0x00000000, 0xffff0200, 0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0200001f, 0x90000000, 0xa00f0800, 0x03000042, 0x800f0800, 0xa0000000, 0xa0e40800, 0x0000ffff, + 0x396e6f41, 0x0000007c, 0x0000007c, 0xffff0200, 0x00000054, 0x00000028, 0x00280000, 0x00280000, + 0x00280000, 0x00240001, 0x00280000, 0x00000000, 0xffff0200, 0x05000051, 0xa00f0000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x90000000, 0xa00f0800, 0x02000001, 0x80030000, + 0xa0000000, 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40800, 0x02000001, 0x800f0800, 0x80e40000, + 0x0000ffff, 0x52444853, 0x00000064, 0x00000040, 0x00000019, 0x0300005a, 0x00106000, 0x00000000, + 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x0c000045, + 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, + 0x00000000, 0x00106000, 0x00000000, 0x0100003e, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, + }; + static const DWORD texture_data[] = {0xffffff00}; if (!init_test_context(&test_context, &feature_level)) return; @@ -11553,9 +11892,27 @@ device = test_context.device; context = test_context.immediate_context; + texture_desc.Width = 1; + texture_desc.Height = 1; + texture_desc.MipLevels = 0; + texture_desc.ArraySize = 1; + texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = 0; + resource_data.pSysMem = texture_data; + resource_data.SysMemPitch = sizeof(texture_data); + resource_data.SysMemSlicePitch = 0; + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); + ok(SUCCEEDED(hr), "Failed to create 2d texture, hr %#x.\n", hr); + hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); + ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); + hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); - ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x, feature level %#x.\n", - hr, feature_level); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x, feature level %#x.\n", hr, feature_level); ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); draw_quad(&test_context); check_texture_color(test_context.backbuffer, 0x7f0000ff, 1); @@ -11564,6 +11921,16 @@ draw_color_quad(&test_context, &color); todo_wine check_texture_color(test_context.backbuffer, 0xff004c33, 1); + hr = ID3D11Device_CreatePixelShader(device, ps_texture_code, sizeof(ps_texture_code), NULL, &ps); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x, feature level %#x.\n", hr, feature_level); + ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); + ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); + draw_quad(&test_context); + check_texture_color(test_context.backbuffer, 0xffffff00, 1); + ID3D11PixelShader_Release(ps); + + ID3D11ShaderResourceView_Release(srv); + ID3D11Texture2D_Release(texture); release_test_context(&test_context); } @@ -11941,6 +12308,95 @@ release_test_context(&test_context); } +static void test_unbind_shader_resource_view(void) +{ + struct d3d11_test_context test_context; + D3D11_SUBRESOURCE_DATA resource_data; + ID3D11ShaderResourceView *srv, *srv2; + D3D11_TEXTURE2D_DESC texture_desc; + ID3D11DeviceContext *context; + ID3D11Texture2D *texture; + ID3D11PixelShader *ps; + ID3D11Device *device; + HRESULT hr; + + static const DWORD ps_code[] = + { +#if 0 + Texture2D t0; + Texture2D t1; + SamplerState s; + + float4 main() : SV_Target + { + return min(t0.Sample(s, float2(0, 0)) + t1.Sample(s, float2(0, 0)), 1.0f); + } +#endif + 0x43425844, 0x698dc0cb, 0x0bf322b8, 0xee127418, 0xfe9214ce, 0x00000001, 0x00000168, 0x00000003, + 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, + 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, + 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000f0, 0x00000040, 0x0000003c, + 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, + 0x00107000, 0x00000001, 0x00005555, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, + 0x0c000045, 0x001000f2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0c000045, 0x001000f2, 0x00000001, 0x00004002, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, + 0x07000000, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100e46, 0x00000001, 0x0a000033, + 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, + 0x3f800000, 0x0100003e, + }; + static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; + static const DWORD texture_data[] = {0xff00ff00}; + + if (!init_test_context(&test_context, NULL)) + return; + + device = test_context.device; + context = test_context.immediate_context; + + texture_desc.Width = 1; + texture_desc.Height = 1; + texture_desc.MipLevels = 0; + texture_desc.ArraySize = 1; + texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = 0; + + resource_data.pSysMem = texture_data; + resource_data.SysMemPitch = sizeof(texture_data); + resource_data.SysMemSlicePitch = 0; + + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); + ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x.\n", hr); + hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, NULL, &srv); + ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x.\n", hr); + hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); + ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); + + ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); + ID3D11DeviceContext_PSSetShaderResources(context, 1, 1, &srv); + ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); + draw_quad(&test_context); + check_texture_color(test_context.backbuffer, 0xff00ff00, 1); + + srv2 = NULL; + ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv2); + ID3D11DeviceContext_PSSetShaderResources(context, 1, 1, &srv2); + ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); + draw_quad(&test_context); + todo_wine check_texture_color(test_context.backbuffer, 0x00000000, 1); + + ID3D11PixelShader_Release(ps); + ID3D11ShaderResourceView_Release(srv); + ID3D11Texture2D_Release(texture); + release_test_context(&test_context); +} + static void test_stencil_separate(void) { struct d3d11_test_context test_context; @@ -13673,7 +14129,7 @@ texture_desc.Height = 64; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; - texture_desc.Format = DXGI_FORMAT_R32G32B32A32_UINT; + texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_DEFAULT; @@ -13823,6 +14279,34 @@ 0x00000000, 0x00004002, 0x00000000, 0x00000014, 0x00000000, 0x00000001, 0x0100003e, }; static const struct shader ps_uav_structured = {ps_uav_structured_code, sizeof(ps_uav_structured_code)}; + static const DWORD ps_uav_structured32_code[] = + { +#if 0 + struct s + { + uint4 u; + bool4 b; + }; + + RWStructuredBuffer b; + + uint4 main(void) : SV_Target + { + uint count, stride; + b.GetDimensions(count, stride); + return uint4(count, stride, 0, 1); + } +#endif + 0x43425844, 0xdd87a805, 0x28090470, 0xe4fa7c4d, 0x57963f52, 0x00000001, 0x000000fc, 0x00000003, + 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, + 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000084, 0x00000050, 0x00000021, + 0x0100086a, 0x0400009e, 0x0011e000, 0x00000001, 0x00000020, 0x03000065, 0x001020f2, 0x00000000, + 0x02000068, 0x00000001, 0x87000079, 0x80010302, 0x00199983, 0x00100012, 0x00000000, 0x0011ee46, + 0x00000001, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x08000036, 0x001020e2, + 0x00000000, 0x00004002, 0x00000000, 0x00000020, 0x00000000, 0x00000001, 0x0100003e, + }; + static const struct shader ps_uav_structured32 = {ps_uav_structured32_code, sizeof(ps_uav_structured32_code)}; static const DWORD ps_srv_structured_code[] = { #if 0 @@ -13945,24 +14429,24 @@ { #define RAW D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS #define STRUCTURED D3D11_RESOURCE_MISC_BUFFER_STRUCTURED - {&ps_uav_raw, TRUE, 100, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 0, 25, {100, 100, 100, 100}}, - {&ps_uav_raw, TRUE, 100, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 8, 17, { 68, 68, 68, 68}}, - {&ps_srv_raw, FALSE, 100, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 0, 25, {100, 100, 100, 100}}, - {&ps_srv_raw, FALSE, 100, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 8, 17, { 68, 68, 68, 68}}, - {&ps_uav_structured, TRUE, 100, STRUCTURED, 20, DXGI_FORMAT_UNKNOWN, 0, 5, { 5, 20, 0, 1}}, - {&ps_uav_structured, TRUE, 100, STRUCTURED, 20, DXGI_FORMAT_UNKNOWN, 0, 2, { 2, 20, 0, 1}}, - {&ps_uav_structured, TRUE, 100, STRUCTURED, 20, DXGI_FORMAT_UNKNOWN, 1, 2, { 2, 20, 0, 1}}, - {&ps_srv_structured, FALSE, 100, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 0, 5, { 5, 4, 0, 1}}, - {&ps_srv_structured, FALSE, 100, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 0, 2, { 2, 4, 0, 1}}, - {&ps_srv_structured, FALSE, 100, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 1, 2, { 2, 4, 0, 1}}, - {&ps_uav_typed, TRUE, 200, 0, 0, DXGI_FORMAT_R32_FLOAT, 0, 50, { 50, 50, 50, 50}}, - {&ps_uav_typed, TRUE, 200, 0, 0, DXGI_FORMAT_R32_FLOAT, 49, 1, { 1, 1, 1, 1}}, - {&ps_uav_typed, TRUE, 100, 0, 0, DXGI_FORMAT_R16_FLOAT, 0, 50, { 50, 50, 50, 50}}, - {&ps_uav_typed, TRUE, 100, 0, 0, DXGI_FORMAT_R16_FLOAT, 49, 1, { 1, 1, 1, 1}}, - {&ps_srv_typed, FALSE, 200, 0, 0, DXGI_FORMAT_R32_FLOAT, 0, 50, { 50, 50, 50, 50}}, - {&ps_srv_typed, FALSE, 200, 0, 0, DXGI_FORMAT_R32_FLOAT, 49, 1, { 1, 1, 1, 1}}, - {&ps_srv_typed, FALSE, 100, 0, 0, DXGI_FORMAT_R16_FLOAT, 0, 50, { 50, 50, 50, 50}}, - {&ps_srv_typed, FALSE, 100, 0, 0, DXGI_FORMAT_R16_FLOAT, 49, 1, { 1, 1, 1, 1}}, + {&ps_uav_raw, TRUE, 100, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 0, 25, {100, 100, 100, 100}}, + {&ps_uav_raw, TRUE, 512, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 64, 64, {256, 256, 256, 256}}, + {&ps_srv_raw, FALSE, 100, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 0, 25, {100, 100, 100, 100}}, + {&ps_srv_raw, FALSE, 500, RAW, 0, DXGI_FORMAT_R32_TYPELESS, 64, 4, { 16, 16, 16, 16}}, + {&ps_uav_structured, TRUE, 100, STRUCTURED, 20, DXGI_FORMAT_UNKNOWN, 0, 5, { 5, 20, 0, 1}}, + {&ps_uav_structured, TRUE, 100, STRUCTURED, 20, DXGI_FORMAT_UNKNOWN, 0, 2, { 2, 20, 0, 1}}, + {&ps_uav_structured32, TRUE, 320, STRUCTURED, 32, DXGI_FORMAT_UNKNOWN, 8, 2, { 2, 32, 0, 1}}, + {&ps_srv_structured, FALSE, 100, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 0, 5, { 5, 4, 0, 1}}, + {&ps_srv_structured, FALSE, 100, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 0, 2, { 2, 4, 0, 1}}, + {&ps_srv_structured, FALSE, 400, STRUCTURED, 4, DXGI_FORMAT_UNKNOWN, 64, 2, { 2, 4, 0, 1}}, + {&ps_uav_typed, TRUE, 200, 0, 0, DXGI_FORMAT_R32_FLOAT, 0, 50, { 50, 50, 50, 50}}, + {&ps_uav_typed, TRUE, 400, 0, 0, DXGI_FORMAT_R32_FLOAT, 64, 1, { 1, 1, 1, 1}}, + {&ps_uav_typed, TRUE, 100, 0, 0, DXGI_FORMAT_R16_FLOAT, 0, 50, { 50, 50, 50, 50}}, + {&ps_uav_typed, TRUE, 400, 0, 0, DXGI_FORMAT_R16_FLOAT, 128, 1, { 1, 1, 1, 1}}, + {&ps_srv_typed, FALSE, 200, 0, 0, DXGI_FORMAT_R32_FLOAT, 0, 50, { 50, 50, 50, 50}}, + {&ps_srv_typed, FALSE, 400, 0, 0, DXGI_FORMAT_R32_FLOAT, 64, 1, { 1, 1, 1, 1}}, + {&ps_srv_typed, FALSE, 100, 0, 0, DXGI_FORMAT_R16_FLOAT, 0, 50, { 50, 50, 50, 50}}, + {&ps_srv_typed, FALSE, 400, 0, 0, DXGI_FORMAT_R16_FLOAT, 128, 2, { 2, 2, 2, 2}}, #undef RAW #undef STRUCTURED }; @@ -14050,7 +14534,7 @@ } draw_quad(&test_context); - todo_wine check_texture_uvec4(texture, &test->expected_result); + check_texture_uvec4(texture, &test->expected_result); if (srv) ID3D11ShaderResourceView_Release(srv); @@ -14703,6 +15187,204 @@ release_test_context(&test_context); } +static unsigned int read_uav_counter(ID3D11DeviceContext *context, + ID3D11Buffer *staging_buffer, ID3D11UnorderedAccessView *uav) +{ + D3D11_MAPPED_SUBRESOURCE map_desc; + unsigned int counter; + + ID3D11DeviceContext_CopyStructureCount(context, staging_buffer, 0, uav); + + if (FAILED(ID3D11DeviceContext_Map(context, (ID3D11Resource *)staging_buffer, 0, + D3D11_MAP_READ, 0, &map_desc))) + return 0xdeadbeef; + counter = *(unsigned int *)map_desc.pData; + ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)staging_buffer, 0); + return counter; +} + +static int compare_id(const void *a, const void *b) +{ + return *(int *)a - *(int *)b; +} + +static void test_uav_counters(void) +{ + ID3D11Buffer *buffer, *buffer2, *staging_buffer; + ID3D11ComputeShader *cs_producer, *cs_consumer; + D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; + struct d3d11_test_context test_context; + ID3D11UnorderedAccessView *uav, *uav2; + unsigned int data, id[128], i; + D3D11_BUFFER_DESC buffer_desc; + ID3D11DeviceContext *context; + struct resource_readback rb; + ID3D11Device *device; + D3D11_BOX box; + HRESULT hr; + + static const DWORD cs_producer_code[] = + { +#if 0 + RWStructuredBuffer u; + + [numthreads(4, 1, 1)] + void main(uint3 dispatch_id : SV_DispatchThreadID) + { + uint counter = u.IncrementCounter(); + u[counter] = dispatch_id.x; + } +#endif + 0x43425844, 0x013163a8, 0xe7d371b8, 0x4f71e39a, 0xd479e584, 0x00000001, 0x000000c8, 0x00000003, + 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, + 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000074, 0x00050050, 0x0000001d, 0x0100086a, + 0x0480009e, 0x0011e000, 0x00000000, 0x00000004, 0x0200005f, 0x00020012, 0x02000068, 0x00000001, + 0x0400009b, 0x00000004, 0x00000001, 0x00000001, 0x050000b2, 0x00100012, 0x00000000, 0x0011e000, + 0x00000000, 0x080000a8, 0x0011e012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, + 0x0002000a, 0x0100003e, + }; + static const DWORD cs_consumer_code[] = + { +#if 0 + RWStructuredBuffer u; + RWStructuredBuffer u2; + + [numthreads(4, 1, 1)] + void main() + { + uint counter = u.DecrementCounter(); + u2[counter] = u[counter]; + } +#endif + 0x43425844, 0x957ef3dd, 0x9f317559, 0x09c8f12d, 0xdbfd98c8, 0x00000001, 0x00000100, 0x00000003, + 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, + 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000ac, 0x00050050, 0x0000002b, 0x0100086a, + 0x0480009e, 0x0011e000, 0x00000000, 0x00000004, 0x0400009e, 0x0011e000, 0x00000001, 0x00000004, + 0x02000068, 0x00000001, 0x0400009b, 0x00000004, 0x00000001, 0x00000001, 0x050000b3, 0x00100012, + 0x00000000, 0x0011e000, 0x00000000, 0x8b0000a7, 0x80002302, 0x00199983, 0x00100022, 0x00000000, + 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0011e006, 0x00000000, 0x090000a8, 0x0011e012, + 0x00000001, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0010001a, 0x00000000, 0x0100003e, + }; + static const D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; + + if (!init_test_context(&test_context, &feature_level)) + return; + + device = test_context.device; + context = test_context.immediate_context; + + hr = ID3D11Device_CreateComputeShader(device, cs_producer_code, sizeof(cs_producer_code), NULL, &cs_producer); + ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); + hr = ID3D11Device_CreateComputeShader(device, cs_consumer_code, sizeof(cs_consumer_code), NULL, &cs_consumer); + ok(SUCCEEDED(hr), "Failed to create compute shader, hr %#x.\n", hr); + + memset(&buffer_desc, 0, sizeof(buffer_desc)); + buffer_desc.ByteWidth = sizeof(unsigned int); + buffer_desc.Usage = D3D11_USAGE_STAGING; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &staging_buffer); + ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); + + buffer_desc.ByteWidth = 1024; + buffer_desc.Usage = D3D11_USAGE_DEFAULT; + buffer_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; + buffer_desc.CPUAccessFlags = 0; + buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + buffer_desc.StructureByteStride = sizeof(unsigned int); + hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer); + ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); + uav_desc.Format = DXGI_FORMAT_UNKNOWN; + uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + U(uav_desc).Buffer.FirstElement = 0; + U(uav_desc).Buffer.NumElements = buffer_desc.ByteWidth / sizeof(unsigned int); + U(uav_desc).Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER; + hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer, &uav_desc, &uav); + ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); + hr = ID3D11Device_CreateBuffer(device, &buffer_desc, NULL, &buffer2); + ok(SUCCEEDED(hr), "Failed to create a buffer, hr %#x.\n", hr); + hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)buffer2, NULL, &uav2); + ok(SUCCEEDED(hr), "Failed to create unordered access view, hr %#x.\n", hr); + + data = read_uav_counter(context, staging_buffer, uav); + ok(!data, "Got unexpected initial value %u.\n", data); + data = 8; + ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); + data = read_uav_counter(context, staging_buffer, uav); + todo_wine ok(data == 8, "Got unexpected value %u.\n", data); + + ID3D11DeviceContext_CSSetShader(context, cs_producer, NULL, 0); + data = 0; + ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); + ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 1, 1, &uav2, NULL); + data = read_uav_counter(context, staging_buffer, uav); + ok(!data, "Got unexpected value %u.\n", data); + + /* produce */ + ID3D11DeviceContext_Dispatch(context, 16, 1, 1); + data = read_uav_counter(context, staging_buffer, uav); + todo_wine ok(data == 64, "Got unexpected value %u.\n", data); + get_buffer_readback(buffer, &rb); + memcpy(id, rb.map_desc.pData, 64 * sizeof(*id)); + release_resource_readback(&rb); + qsort(id, 64, sizeof(*id), compare_id); + for (i = 0; i < 64; ++i) + { + if (id[i] != i) + break; + } + ok(i == 64, "Got unexpected id %u at %u.\n", id[i], i); + + /* consume */ + ID3D11DeviceContext_CSSetShader(context, cs_consumer, NULL, 0); + ID3D11DeviceContext_Dispatch(context, 16, 1, 1); + data = read_uav_counter(context, staging_buffer, uav); + ok(!data, "Got unexpected value %u.\n", data); + get_buffer_readback(buffer2, &rb); + memcpy(id, rb.map_desc.pData, 64 * sizeof(*id)); + release_resource_readback(&rb); + qsort(id, 64, sizeof(*id), compare_id); + for (i = 0; i < 64; ++i) + { + if (id[i] != i) + break; + } + ok(i == 64, "Got unexpected id %u at %u.\n", id[i], i); + + /* produce on CPU */ + for (i = 0; i < 8; ++i) + id[i] = 0xdeadbeef; + set_box(&box, 0, 0, 0, 8 * sizeof(*id), 1, 1); + ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)buffer, 0, &box, id, 0, 0); + data = 8; + ID3D11DeviceContext_CSSetUnorderedAccessViews(context, 0, 1, &uav, &data); + data = read_uav_counter(context, staging_buffer, uav); + todo_wine ok(data == 8, "Got unexpected value %u.\n", data); + + /* consume */ + ID3D11DeviceContext_Dispatch(context, 1, 1, 1); + data = read_uav_counter(context, staging_buffer, uav); + todo_wine ok(data == 4, "Got unexpected value %u.\n", data); + ID3D11DeviceContext_Dispatch(context, 1, 1, 1); + data = read_uav_counter(context, staging_buffer, uav); + ok(!data, "Got unexpected value %u.\n", data); + get_buffer_readback(buffer2, &rb); + for (i = 0; i < 8; ++i) + { + data = get_readback_color(&rb, i, 0); + todo_wine ok(data == 0xdeadbeef, "Got data %u at %u.\n", data, i); + } + release_resource_readback(&rb); + + ID3D11Buffer_Release(buffer); + ID3D11Buffer_Release(buffer2); + ID3D11Buffer_Release(staging_buffer); + ID3D11ComputeShader_Release(cs_producer); + ID3D11ComputeShader_Release(cs_consumer); + ID3D11UnorderedAccessView_Release(uav); + ID3D11UnorderedAccessView_Release(uav2); + release_test_context(&test_context); +} + static void test_compute_shader_registers(void) { struct data @@ -15082,7 +15764,7 @@ data = get_readback_color(&rb, i, 0); ok(data == expected, "Got %u, expected %u (index %u).\n", data, expected, i); data = get_readback_color(&rb2, i, 0); - ok(data == expected, "Got %u, expected %u (index %u).\n", data, expected, i); + ok(data == expected || !data, "Got %u, expected %u (index %u).\n", data, expected, i); } release_resource_readback(&rb); release_resource_readback(&rb2); @@ -15163,6 +15845,7 @@ test_private_data(); test_blend(); test_texture(); + test_cube_maps(); test_depth_stencil_sampling(); test_multiple_render_targets(); test_render_target_views(); @@ -15200,6 +15883,7 @@ run_for_each_9_x_feature_level(test_fl9_draw); test_ddy(); test_shader_input_registers_limits(); + test_unbind_shader_resource_view(); test_stencil_separate(); test_uav_load(); test_cs_uav_store(); @@ -15213,6 +15897,7 @@ test_buffer_srv(); run_for_each_feature_level_in_range(D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_11_0, test_unaligned_raw_buffer_access); + test_uav_counters(); test_compute_shader_registers(); test_tgsm(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d8/directx.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d8/directx.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d8/directx.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d8/directx.c 2017-03-21 14:02:57.000000000 +0000 @@ -411,7 +411,8 @@ { DWORD flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER - | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART; + | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART + | WINED3D_LEGACY_CUBEMAP_FILTERING; d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl; d3d8->refcount = 1; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/device.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/device.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/device.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/device.c 2017-03-21 14:02:57.000000000 +0000 @@ -2120,7 +2120,7 @@ wined3d_mutex_unlock(); if (FAILED(hr)) { - WARN("IWineD3DDevice_EndStateBlock() failed, hr %#x.\n", hr); + WARN("Failed to end the state block, hr %#x.\n", hr); return hr; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/directx.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/directx.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/directx.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/directx.c 2017-03-21 14:02:57.000000000 +0000 @@ -580,7 +580,7 @@ { DWORD flags = WINED3D_PRESENT_CONVERSION | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER | WINED3D_SRGB_READ_WRITE_CONTROL | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR - | WINED3D_NO_PRIMITIVE_RESTART; + | WINED3D_NO_PRIMITIVE_RESTART | WINED3D_LEGACY_CUBEMAP_FILTERING; if (!extended) flags |= WINED3D_VIDMEM_ACCOUNTING; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/tests/d3d9ex.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/tests/d3d9ex.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/tests/d3d9ex.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/tests/d3d9ex.c 2017-03-21 14:02:57.000000000 +0000 @@ -2429,7 +2429,7 @@ hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_3_224, &ps); ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_2_0_boolint, &ps); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); if (ps) IDirect3DPixelShader9_Release(ps); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/tests/device.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/tests/device.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/tests/device.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/tests/device.c 2017-03-21 14:02:57.000000000 +0000 @@ -6528,7 +6528,7 @@ hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps); ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); if (ps) IDirect3DPixelShader9_Release(ps); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/tests/visual.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/tests/visual.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3d9/tests/visual.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3d9/tests/visual.c 2017-03-21 14:02:57.000000000 +0000 @@ -7828,6 +7828,12 @@ IDirect3DDevice9_Release(device); goto done; } + if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + { + skip("No ps_3_0 support, skipping tests.\n"); + IDirect3DDevice9_Release(device); + goto done; + } hr = IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier); ok(SUCCEEDED(hr), "Failed to get adapter identifier, hr %#x.\n", hr); @@ -8087,11 +8093,8 @@ hr = IDirect3DDevice9_EndScene(device); ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); - /* WARP ends up using the color attribute from the previous draw. Let's mark - * that behavior as broken. */ color = getPixelColor(device, 160, 360); - ok(color_match(color, 0x00000000, 1) - || broken(color_match(color, 0x00ffff00, 1)), + ok(color_match(color, 0x00000000, 1) || broken(warp), "Got unexpected color 0x%08x for no color attribute test.\n", color); IDirect3DDevice9_SetVertexShader(device, NULL); @@ -10582,7 +10585,7 @@ ps2 = {D3DPS_VERSION(2, 0), pshader2_code}, ps2_zw = {D3DPS_VERSION(2, 0), pshader2_zw_code}, ps3 = {D3DPS_VERSION(3, 0), pshader3_code}, - ps3_zw = {D3DVS_VERSION(3, 0), pshader3_zw_code}; + ps3_zw = {D3DPS_VERSION(3, 0), pshader3_zw_code}; static const struct { const struct test_shader *vs; @@ -19628,18 +19631,18 @@ static void test_updatetexture(void) { - IDirect3DDevice9 *device; - IDirect3D9 *d3d9; - HWND window; - HRESULT hr; + BOOL r32f_supported, ati2n_supported, do_visual_test; IDirect3DBaseTexture9 *src, *dst; unsigned int t, i, f, l, x, y, z; D3DLOCKED_RECT locked_rect; D3DLOCKED_BOX locked_box; + IDirect3DDevice9 *device; + IDirect3D9 *d3d9; ULONG refcount; - D3DCAPS9 caps; D3DCOLOR color; - BOOL ati2n_supported, do_visual_test; + D3DCAPS9 caps; + HWND window; + HRESULT hr; static const struct { struct vec3 pos; @@ -19766,16 +19769,26 @@ skip("%s textures not supported, skipping some tests.\n", texture_types[t].name); continue; } - if (FAILED(IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, - D3DFMT_X8R8G8B8, 0, texture_types[t].type, MAKEFOURCC('A','T','I','2')))) + D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER, texture_types[t].type, D3DFMT_A8R8G8B8))) { - skip("%s ATI2N textures are not supported, skipping some tests.\n", texture_types[t].name); - ati2n_supported = FALSE; + skip("%s D3DFMT_A8R8G8B8 texture filtering is not supported, skipping some tests.\n", + texture_types[t].name); + continue; } - else + r32f_supported = TRUE; + if (FAILED(IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER, texture_types[t].type, D3DFMT_R32F))) + { + skip("%s R32F textures are not supported, skipping some tests.\n", texture_types[t].name); + r32f_supported = FALSE; + } + ati2n_supported = TRUE; + if (FAILED(IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER, texture_types[t].type, MAKEFOURCC('A','T','I','2')))) { - ati2n_supported = TRUE; + skip("%s ATI2N textures are not supported, skipping some tests.\n", texture_types[t].name); + ati2n_supported = FALSE; } hr = IDirect3DDevice9_SetFVF(device, texture_types[t].fvf); @@ -19783,7 +19796,9 @@ for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i) { - if (tests[i].src_format == MAKEFOURCC('A','T','I','2') && !ati2n_supported) + if (tests[i].dst_format == D3DFMT_R32F && !r32f_supported) + continue; + if (tests[i].dst_format == MAKEFOURCC('A','T','I','2') && !ati2n_supported) continue; switch (texture_types[t].type) @@ -22393,6 +22408,134 @@ DestroyWindow(window); } +static void test_vertex_texture(void) +{ + static const D3DVERTEXELEMENT9 decl_elements[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END() + }; + static const struct vec3 quad[] = + { + {-1.0f, -1.0f, 0.0f}, + {-1.0f, 1.0f, 0.0f}, + { 1.0f, -1.0f, 0.0f}, + { 1.0f, 1.0f, 0.0f}, + }; + static const DWORD vs_code[] = + { + 0xfffe0300, /* vs_3_0 */ + 0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0, 0, 0, 0 */ + 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */ + 0x0200001f, 0x90000000, 0xa00f0800, /* dcl_2d s0 */ + 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */ + 0x0200001f, 0x8000000a, 0xe00f0001, /* dcl_color o1 */ + 0x0300005f, 0xe00f0001, 0xa0000000, 0xa0e40800, /* texldl o1, c0.x, s0 */ + 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */ + 0x0000ffff, /* end */ + }; + static const DWORD ps_code[] = + { + 0xffff0300, /* ps_3_0 */ + 0x0200001f, 0x8000000a, 0x900f0000, /* dcl_color v0 */ + 0x02000001, 0x800f0800, 0x90e40000, /* mov oC0, v0 */ + 0x0000ffff, /* end */ + }; + static const DWORD texture_data[4] = {0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00ffff00}; + IDirect3DVertexDeclaration9 *declaration; + IDirect3DTexture9 *texture; + IDirect3DVertexShader9 *vs; + IDirect3DPixelShader9 *ps; + IDirect3DDevice9 *device; + D3DLOCKED_RECT lr; + IDirect3D9 *d3d; + D3DCOLOR color; + ULONG refcount; + D3DCAPS9 caps; + HWND window; + HRESULT hr; + + window = create_window(); + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create D3D object.\n"); + + if (!(device = create_device(d3d, window, window, TRUE))) + { + skip("Failed to create D3D device.\n"); + IDirect3D9_Release(d3d); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); + if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0) || caps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + { + skip("SM3 is not supported.\n"); + goto done; + } + if (!(caps.VertexTextureFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) + || !(caps.VertexTextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT)) + { + skip("Vertex texture point filtering is not supported, caps %#x.\n", caps.VertexTextureFilterCaps); + goto done; + } + hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); + if (hr != D3D_OK) + { + skip("No vertex texture fetch support for D3DFMT_A8R8G8B8, hr %#x.\n", hr); + goto done; + } + + hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL); + ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr); + memset(&lr, 0, sizeof(lr)); + hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0); + ok(hr == D3D_OK, "Failed to lock texture, hr %#x.\n", hr); + memcpy(lr.pBits, texture_data, sizeof(texture_data)); + hr = IDirect3DTexture9_UnlockRect(texture, 0); + ok(hr == D3D_OK, "Failed to unlock texture, hr %#x.\n", hr); + + hr = IDirect3DDevice9_SetTexture(device, D3DVERTEXTEXTURESAMPLER0, (IDirect3DBaseTexture9 *)texture); + ok(hr == D3D_OK, "Failed to set texture, hr %#x.\n", hr); + + hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &declaration); + ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr); + hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vs); + ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); + hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); + + hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration); + ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetVertexShader(device, vs); + ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetPixelShader(device, ps); + ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr); + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + hr = IDirect3DDevice9_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad)); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + hr = IDirect3DDevice9_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + color = getPixelColor(device, 160, 360); + ok(color == texture_data[0], "Got unexpected color 0x%08x.\n", color); + + IDirect3DPixelShader9_Release(ps); + IDirect3DVertexShader9_Release(vs); + IDirect3DTexture9_Release(texture); + IDirect3DVertexDeclaration9_Release(declaration); +done: + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + START_TEST(visual) { D3DADAPTER_IDENTIFIER9 identifier; @@ -22522,4 +22665,5 @@ test_max_index16(); test_backbuffer_resize(); test_drawindexedprimitiveup(); + test_vertex_texture(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3dx9_36/d3dx9_private.h wine-staging-2.4.0~ubuntu16.04.1/dlls/d3dx9_36/d3dx9_private.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3dx9_36/d3dx9_private.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3dx9_36/d3dx9_private.h 2017-03-21 14:02:57.000000000 +0000 @@ -192,6 +192,8 @@ struct d3dx_const_tab shader_inputs; }; +#define PARAMETER_FLAG_DIRTY 0x1u + struct d3dx_parameter { char *name; @@ -206,6 +208,7 @@ UINT member_count; DWORD flags; UINT bytes; + DWORD runtime_flags; DWORD object_id; D3DXHANDLE handle; @@ -215,6 +218,8 @@ struct d3dx_parameter *referenced_param; struct d3dx_param_eval *param_eval; + + DWORD *dirty_flag_ptr; }; struct d3dx9_base_effect; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3dx9_36/effect.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3dx9_36/effect.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3dx9_36/effect.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3dx9_36/effect.c 2017-03-21 14:02:57.000000000 +0000 @@ -1316,6 +1316,29 @@ return NULL; } +static BOOL walk_parameter_tree(struct d3dx_parameter *param, walk_parameter_dep_func param_func, + void *data) +{ + unsigned int i; + unsigned int member_count; + + if (param_func(data, param)) + return TRUE; + + member_count = param->element_count ? param->element_count : param->member_count; + for (i = 0; i < member_count; ++i) + { + if (walk_parameter_tree(¶m->members[i], param_func, data)) + return TRUE; + } + return FALSE; +} + +static void set_dirty(struct d3dx_parameter *param) +{ + *param->dirty_flag_ptr |= PARAMETER_FLAG_DIRTY; +} + static HRESULT d3dx9_base_effect_set_value(struct d3dx9_base_effect *base, D3DXHANDLE parameter, const void *data, UINT bytes) { @@ -1364,6 +1387,7 @@ case D3DXPT_FLOAT: TRACE("Copy %u bytes\n", param->bytes); memcpy(param->data, data, param->bytes); + set_dirty(param); break; default: @@ -1450,6 +1474,7 @@ if (param && !param->element_count && param->rows == 1 && param->columns == 1) { set_number(param->data, param->type, &b, D3DXPT_BOOL); + set_dirty(param); return D3D_OK; } @@ -1495,6 +1520,7 @@ /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */ set_number((DWORD *)param->data + i, param->type, &b[i], D3DXPT_INT); } + set_dirty(param); return D3D_OK; case D3DXPC_OBJECT: @@ -1544,7 +1570,12 @@ { if (param->rows == 1 && param->columns == 1) { - set_number(param->data, param->type, &n, D3DXPT_INT); + DWORD value; + + set_number(&value, param->type, &n, D3DXPT_INT); + if (value != *(DWORD *)param->data) + set_dirty(param); + *(DWORD *)param->data = value; return D3D_OK; } @@ -1564,6 +1595,7 @@ { ((FLOAT *)param->data)[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE; } + set_dirty(param); return D3D_OK; } } @@ -1631,6 +1663,7 @@ { set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT); } + set_dirty(param); return D3D_OK; case D3DXPC_OBJECT: @@ -1678,7 +1711,12 @@ if (param && !param->element_count && param->rows == 1 && param->columns == 1) { - set_number((DWORD *)param->data, param->type, &f, D3DXPT_FLOAT); + DWORD value; + + set_number(&value, param->type, &f, D3DXPT_FLOAT); + if (value != *(DWORD *)param->data) + set_dirty(param); + *(DWORD *)param->data = value; return D3D_OK; } @@ -1723,6 +1761,7 @@ { set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT); } + set_dirty(param); return D3D_OK; case D3DXPC_OBJECT: @@ -1777,6 +1816,7 @@ { case D3DXPC_SCALAR: case D3DXPC_VECTOR: + set_dirty(param); if (param->type == D3DXPT_INT && param->bytes == 4) { DWORD tmp; @@ -1870,6 +1910,7 @@ switch (param->class) { case D3DXPC_VECTOR: + set_dirty(param); if (param->type == D3DXPT_FLOAT) { if (param->columns == 4) @@ -1956,6 +1997,7 @@ { case D3DXPC_MATRIX_ROWS: set_matrix(param, matrix); + set_dirty(param); return D3D_OK; case D3DXPC_SCALAR: @@ -2021,6 +2063,7 @@ switch (param->class) { case D3DXPC_MATRIX_ROWS: + set_dirty(param); for (i = 0; i < count; ++i) { set_matrix(¶m->members[i], &matrix[i]); @@ -2095,6 +2138,7 @@ switch (param->class) { case D3DXPC_MATRIX_ROWS: + set_dirty(param); for (i = 0; i < count; ++i) { set_matrix(¶m->members[i], matrix[i]); @@ -2167,6 +2211,7 @@ switch (param->class) { case D3DXPC_MATRIX_ROWS: + set_dirty(param); set_matrix_transpose(param, matrix); return D3D_OK; @@ -2236,6 +2281,7 @@ switch (param->class) { case D3DXPC_MATRIX_ROWS: + set_dirty(param); for (i = 0; i < count; ++i) { set_matrix_transpose(¶m->members[i], &matrix[i]); @@ -2310,6 +2356,7 @@ switch (param->class) { case D3DXPC_MATRIX_ROWS: + set_dirty(param); for (i = 0; i < count; ++i) { set_matrix_transpose(¶m->members[i], matrix[i]); @@ -2414,6 +2461,7 @@ if (oltexture) IDirect3DBaseTexture9_Release(oltexture); *(struct IDirect3DBaseTexture9 **)param->data = texture; + set_dirty(param); return D3D_OK; } @@ -5798,6 +5846,12 @@ return hr; } +static BOOL param_set_dirty_flag_ptr(void *dirty_flag_ptr, struct d3dx_parameter *param) +{ + param->dirty_flag_ptr = (DWORD *)dirty_flag_ptr; + return FALSE; +} + static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *data, UINT data_size, DWORD start) { const char *ptr = data + start; @@ -5907,6 +5961,9 @@ } } + for (i = 0; i < base->parameter_count; ++i) + walk_parameter_tree(&base->parameters[i], param_set_dirty_flag_ptr, + &base->parameters[i].runtime_flags); return D3D_OK; err_out: diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/d3dx9_36/tests/effect.c wine-staging-2.4.0~ubuntu16.04.1/dlls/d3dx9_36/tests/effect.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/d3dx9_36/tests/effect.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/d3dx9_36/tests/effect.c 2017-03-21 14:02:57.000000000 +0000 @@ -3084,11 +3084,11 @@ }; test_struct ts1[1] = {{{9, 10, 11}, 12, {13, 14, 15, 16}}}; -test_struct ts2[2] = {{{0, 0, 0}, 0, {0, 0, 0, 0}}, {{1, 2, 3}, 4, {5, 6, 7, 8}}}; +shared test_struct ts2[2] = {{{0, 0, 0}, 0, {0, 0, 0, 0}}, {{1, 2, 3}, 4, {5, 6, 7, 8}}}; struct_array ts3 = {{{1, 2, 3}, 4, {5, 6, 7, 8}}, {{9, 10, 11}, 12, {13, 14, 15, 16}}}; float arr1[1] = {91}; -float arr2[2] = {92, 93}; +shared float arr2[2] = {92, 93}; Texture2D tex1; Texture2D tex2; @@ -3136,6 +3136,16 @@ return Output; } +VS_OUTPUT RenderSceneVS2(float4 vPos : POSITION) +{ + VS_OUTPUT Output; + + Output.Position = g_Pos1; + Output.TextureUV = float2(0, 0); + Output.Diffuse = 0; + return Output; +} + struct PS_OUTPUT { float4 RGBColor : COLOR0; /* Pixel color */ @@ -3167,7 +3177,7 @@ return Output; } -vertexshader vs_arr2[1] = {compile vs_3_0 RenderSceneVS(1, true)}; +shared vertexshader vs_arr2[2] = {compile vs_3_0 RenderSceneVS(1, true), compile vs_3_0 RenderSceneVS2()}; pixelshader ps_arr[1] = {compile ps_3_0 RenderScenePS(mb2x3row)}; technique tech0 @@ -3216,6 +3226,12 @@ LightSpecular[1] = float4(opvect1[g_iVect.z], g_iVect[opvect2.y], g_Selector[g_iVect.w].x + g_Selector[g_iVect.w].y, g_Selector[g_iVect.w].x + g_Selector[g_iVect.x].y); + + FogEnable = TRUE; + FogDensity = ts2[0].fv; + FogStart = ts2[1].fv; + PointScale_A = ts3.ts[0].fv; + PointScale_B = ts3.ts[1].fv; } pass p1 { @@ -3225,7 +3241,7 @@ #endif static const DWORD test_effect_preshader_effect_blob[] = { - 0xfeff0901, 0x00000ef4, 0x00000000, 0x00000003, 0x00000001, 0x00000030, 0x00000000, 0x00000000, + 0xfeff0901, 0x00000f98, 0x00000000, 0x00000003, 0x00000001, 0x00000030, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x6f505f67, 0x00003173, 0x00000003, 0x00000001, 0x00000068, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x6f505f67, 0x00003273, 0x00000003, @@ -3299,30 +3315,26 @@ 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000003, 0x000000a4, 0x00000100, 0x00000898, 0x00000894, 0x000000aa, 0x00000100, 0x000008b0, 0x000008ac, 0x000000a9, 0x00000100, 0x000008d0, 0x000008cc, 0x00000009, 0x706d6173, 0x3172656c, 0x00000000, 0x00000010, 0x00000004, - 0x00000948, 0x00000000, 0x00000001, 0x00000007, 0x00000008, 0x615f7376, 0x00327272, 0x0000000f, - 0x00000004, 0x0000096c, 0x00000000, 0x00000001, 0x00000008, 0x00000007, 0x615f7370, 0x00007272, - 0x00000009, 0x00000010, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x0000000a, 0x0000000f, - 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, - 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, - 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x0000094c, 0x00000000, 0x00000002, 0x00000007, 0x00000008, 0x00000008, 0x615f7376, 0x00327272, + 0x0000000f, 0x00000004, 0x00000970, 0x00000000, 0x00000001, 0x00000009, 0x00000007, 0x615f7370, + 0x00007272, 0x0000000a, 0x00000010, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x0000000b, + 0x0000000f, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, @@ -3343,208 +3355,287 @@ 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, - 0x00000004, 0x00000001, 0x00000003, 0x00003070, 0x0000000b, 0x00000010, 0x00000004, 0x00000000, - 0x00000000, 0x00000000, 0x00000003, 0x00003170, 0x00000006, 0x68636574, 0x00000030, 0x0000001f, - 0x00000001, 0x0000000b, 0x0000000c, 0x00000004, 0x00000020, 0x00000000, 0x00000000, 0x0000003c, - 0x00000058, 0x00000000, 0x00000000, 0x00000074, 0x00000090, 0x00000000, 0x00000000, 0x000000c0, - 0x000000dc, 0x00000000, 0x00000000, 0x000000f8, 0x00000114, 0x00000000, 0x00000000, 0x00000130, - 0x0000014c, 0x00000000, 0x00000000, 0x00000168, 0x00000184, 0x00000000, 0x00000000, 0x000001a8, - 0x000001c4, 0x00000000, 0x00000000, 0x000001e0, 0x000001f4, 0x00000000, 0x00000000, 0x0000020c, - 0x00000228, 0x00000000, 0x00000000, 0x00000264, 0x00000280, 0x00000000, 0x00000000, 0x000002bc, - 0x000002d8, 0x00000000, 0x00000000, 0x00000318, 0x00000334, 0x00000000, 0x00000000, 0x00000374, - 0x00000390, 0x00000000, 0x00000000, 0x000003ac, 0x000003c8, 0x00000000, 0x00000000, 0x000003e8, - 0x00000404, 0x00000000, 0x00000000, 0x00000428, 0x00000444, 0x00000000, 0x00000000, 0x0000046c, - 0x00000488, 0x00000000, 0x00000000, 0x000004ac, 0x000004c8, 0x00000000, 0x00000000, 0x000004f0, - 0x0000050c, 0x00000000, 0x00000000, 0x00000534, 0x00000550, 0x00000000, 0x00000000, 0x00000578, - 0x000005e4, 0x00000000, 0x00000000, 0x00000624, 0x00000690, 0x00000000, 0x00000000, 0x000006f0, - 0x00000774, 0x00000000, 0x00000000, 0x000007dc, 0x000007f8, 0x00000000, 0x00000000, 0x00000808, - 0x00000824, 0x00000000, 0x00000000, 0x00000838, 0x0000084c, 0x00000000, 0x00000000, 0x0000085c, - 0x00000870, 0x00000000, 0x00000000, 0x00000880, 0x000008ec, 0x00000000, 0x00000000, 0x00000930, - 0x00000944, 0x00000000, 0x00000000, 0x00000954, 0x00000968, 0x00000000, 0x00000000, 0x00000ee8, - 0x00000000, 0x00000002, 0x00000ec0, 0x00000000, 0x00000024, 0x00000092, 0x00000000, 0x0000097c, - 0x00000978, 0x00000093, 0x00000000, 0x00000994, 0x00000990, 0x00000091, 0x00000000, 0x000009ac, - 0x000009a8, 0x00000091, 0x00000001, 0x000009cc, 0x000009c8, 0x00000091, 0x00000002, 0x000009ec, - 0x000009e8, 0x00000091, 0x00000003, 0x00000a0c, 0x00000a08, 0x00000091, 0x00000004, 0x00000a2c, - 0x00000a28, 0x00000091, 0x00000005, 0x00000a4c, 0x00000a48, 0x00000091, 0x00000006, 0x00000a6c, - 0x00000a68, 0x00000091, 0x00000007, 0x00000a8c, 0x00000a88, 0x00000084, 0x00000000, 0x00000aac, - 0x00000aa8, 0x00000084, 0x00000001, 0x00000acc, 0x00000ac8, 0x00000084, 0x00000002, 0x00000aec, - 0x00000ae8, 0x00000084, 0x00000003, 0x00000b0c, 0x00000b08, 0x00000084, 0x00000004, 0x00000b2c, - 0x00000b28, 0x00000084, 0x00000005, 0x00000b4c, 0x00000b48, 0x00000084, 0x00000006, 0x00000b6c, - 0x00000b68, 0x00000084, 0x00000007, 0x00000b8c, 0x00000b88, 0x00000085, 0x00000000, 0x00000bb8, - 0x00000ba8, 0x00000085, 0x00000001, 0x00000be4, 0x00000bd4, 0x00000085, 0x00000002, 0x00000c10, - 0x00000c00, 0x00000085, 0x00000003, 0x00000c3c, 0x00000c2c, 0x00000085, 0x00000004, 0x00000c68, - 0x00000c58, 0x00000085, 0x00000005, 0x00000c94, 0x00000c84, 0x00000085, 0x00000006, 0x00000cc0, - 0x00000cb0, 0x00000085, 0x00000007, 0x00000cec, 0x00000cdc, 0x00000087, 0x00000000, 0x00000d18, - 0x00000d08, 0x00000087, 0x00000001, 0x00000d44, 0x00000d34, 0x00000087, 0x00000002, 0x00000d70, - 0x00000d60, 0x00000087, 0x00000003, 0x00000d9c, 0x00000d8c, 0x00000087, 0x00000004, 0x00000dc8, - 0x00000db8, 0x00000087, 0x00000005, 0x00000df4, 0x00000de4, 0x00000087, 0x00000006, 0x00000e20, - 0x00000e10, 0x00000087, 0x00000007, 0x00000e4c, 0x00000e3c, 0x00000086, 0x00000000, 0x00000e78, - 0x00000e68, 0x00000086, 0x00000001, 0x00000ea4, 0x00000e94, 0x00000ee0, 0x00000000, 0x00000001, - 0x00000092, 0x00000000, 0x00000ecc, 0x00000ec8, 0x00000007, 0x00000018, 0x00000008, 0x000007cc, - 0xffff0300, 0x00c0fffe, 0x42415443, 0x0000001c, 0x000002cb, 0xffff0300, 0x00000009, 0x0000001c, - 0x00000000, 0x000002c4, 0x000000d0, 0x00000001, 0x00000001, 0x000000d8, 0x000000e8, 0x000000f8, - 0x00080002, 0x00000002, 0x00000104, 0x00000114, 0x00000134, 0x00060002, 0x00000002, 0x0000013c, - 0x0000014c, 0x0000016c, 0x00000002, 0x00000003, 0x00000178, 0x00000188, 0x000001b8, 0x000a0002, - 0x00000002, 0x000001c0, 0x000001d0, 0x000001f0, 0x000c0002, 0x00000002, 0x000001fc, 0x0000020c, - 0x0000022c, 0x00030002, 0x00000003, 0x00000234, 0x00000244, 0x00000274, 0x00000000, 0x00000005, - 0x00000280, 0x00000290, 0x000002a8, 0x00000003, 0x00000001, 0x000002b4, 0x00000000, 0x56695f67, - 0x00746365, 0x00020001, 0x00040001, 0x00000001, 0x00000000, 0x00000004, 0x00000003, 0x00000002, - 0x00000001, 0x3278326d, 0x756c6f63, 0xab006e6d, 0x00030003, 0x00020002, 0x00000001, 0x00000000, - 0x41300000, 0x41a80000, 0x00000000, 0x00000000, 0x41400000, 0x41b00000, 0x00000000, 0x00000000, - 0x3278326d, 0x00776f72, 0x00030002, 0x00020002, 0x00000001, 0x00000000, 0x41300000, 0x41400000, - 0x00000000, 0x00000000, 0x41a80000, 0x41b00000, 0x00000000, 0x00000000, 0x3378326d, 0x756c6f63, - 0xab006e6d, 0x00030003, 0x00030002, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x00000000, - 0x00000000, 0x41400000, 0x41b00000, 0x00000000, 0x00000000, 0x41500000, 0x41b80000, 0x00000000, - 0x00000000, 0x3378326d, 0x00776f72, 0x00030002, 0x00030002, 0x00000001, 0x00000000, 0x41300000, - 0x41400000, 0x41500000, 0x00000000, 0x41a80000, 0x41b00000, 0x41b80000, 0x00000000, 0x3278336d, - 0x756c6f63, 0xab006e6d, 0x00030003, 0x00020003, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, - 0x41f80000, 0x00000000, 0x41400000, 0x41b00000, 0x42000000, 0x00000000, 0x3278336d, 0x00776f72, - 0x00030002, 0x00020003, 0x00000001, 0x00000000, 0x41300000, 0x41400000, 0x00000000, 0x00000000, - 0x41a80000, 0x41b00000, 0x00000000, 0x00000000, 0x41f80000, 0x42000000, 0x00000000, 0x00000000, - 0x7832626d, 0x776f7233, 0xababab00, 0x00010002, 0x00030002, 0x00000001, 0x00000000, 0xffffffff, - 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x706d6173, 0x3172656c, 0xababab00, - 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x335f7370, 0x4d00305f, 0x6f726369, 0x74666f73, - 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, - 0x332e3235, 0x00313131, 0x05000051, 0xa00f000e, 0x3d2aaaa4, 0xbf000000, 0x3f800000, 0xbe22f983, - 0x05000051, 0xa00f000f, 0x00000000, 0x3e22f983, 0x3e800000, 0xbab609ba, 0x05000051, 0xa00f0010, - 0x40c90fdb, 0xc0490fdb, 0xb4878163, 0x37cfb5a1, 0x0200001f, 0x80000005, 0x90030000, 0x0200001f, - 0x8000000a, 0x900f0001, 0x0200001f, 0x90000000, 0xa00f0800, 0x03000005, 0x80030000, 0xa0e40007, - 0x90550001, 0x04000004, 0x80030000, 0x90000001, 0xa0e40006, 0x80e40000, 0x03000002, 0x80030000, - 0x80e40000, 0x90e40001, 0x02000001, 0x80010001, 0xa000000f, 0x0400005a, 0x80010002, 0x90e40001, - 0xa0e40008, 0x80000001, 0x0400005a, 0x80020002, 0x90e40001, 0xa0e40009, 0x80000001, 0x03000002, - 0x80030000, 0x80e40000, 0x80e40002, 0x03000005, 0x800c0000, 0xa0440004, 0x90550001, 0x04000004, - 0x800c0000, 0x90000001, 0xa0440003, 0x80e40000, 0x04000004, 0x800c0000, 0x90aa0001, 0xa0440005, - 0x80e40000, 0x03000002, 0x80030000, 0x80ee0000, 0x80e40000, 0x03000008, 0x80010002, 0x90e40001, - 0xa0e4000c, 0x03000008, 0x80020002, 0x90e40001, 0xa0e4000d, 0x03000002, 0x80030000, 0x80e40000, - 0x80e40002, 0x03000005, 0x800e0001, 0xa090000b, 0x90550001, 0x04000004, 0x800e0001, 0x90000001, - 0xa090000a, 0x80e40001, 0x02000001, 0x80040000, 0x90aa0001, 0x03000002, 0x80070000, 0x80e40000, - 0x80f90001, 0x0400005a, 0x80010002, 0x90e40001, 0xa0e40000, 0x80000001, 0x0400005a, 0x80020002, - 0x90e40001, 0xa0e40001, 0x80000001, 0x0400005a, 0x80040002, 0x90e40001, 0xa0e40002, 0x80000001, - 0x03000002, 0x80070000, 0x80e40000, 0x80e40002, 0x02000001, 0x80070003, 0x80e40000, 0x01000026, - 0xf0e40000, 0x03000002, 0x80070003, 0x80e40002, 0x80e40003, 0x00000027, 0x01000028, 0xe0e40804, - 0x02000001, 0x80080003, 0x90ff0001, 0x04000004, 0x800f0000, 0x80e40003, 0xa055000f, 0xa0aa000f, - 0x02000013, 0x800f0000, 0x80e40000, 0x04000004, 0x800f0000, 0x80e40000, 0xa0000010, 0xa0550010, - 0x03000005, 0x800f0000, 0x80e40000, 0x80e40000, 0x04000004, 0x800f0002, 0x80e40000, 0xa0aa0010, - 0xa0ff0010, 0x04000004, 0x800f0002, 0x80e40000, 0x80e40002, 0xa0ff000f, 0x04000004, 0x800f0002, - 0x80e40000, 0x80e40002, 0xa000000e, 0x04000004, 0x800f0002, 0x80e40000, 0x80e40002, 0xa055000e, - 0x04000004, 0x800f0000, 0x80e40000, 0x80e40002, 0x80e40003, 0x03000002, 0x800f0000, 0x80e40000, - 0xa0aa000e, 0x04000004, 0x800f0002, 0x80e40000, 0xa1ff000e, 0xa155000e, 0x02000013, 0x800f0002, - 0x80e40002, 0x04000004, 0x800f0002, 0x80e40002, 0xa0000010, 0xa0550010, 0x03000005, 0x800f0002, - 0x80e40002, 0x80e40002, 0x04000004, 0x800f0004, 0x80e40002, 0xa0aa0010, 0xa0ff0010, 0x04000004, - 0x800f0004, 0x80e40002, 0x80e40004, 0xa0ff000f, 0x04000004, 0x800f0004, 0x80e40002, 0x80e40004, - 0xa000000e, 0x04000004, 0x800f0004, 0x80e40002, 0x80e40004, 0xa055000e, 0x04000004, 0x800f0000, - 0x80e40002, 0x80e40004, 0x80e40000, 0x03000002, 0x800f0003, 0x80e40000, 0xa0aa000e, 0x0400005a, - 0x80010000, 0x80e40003, 0xa0e40000, 0x80000001, 0x0400005a, 0x80020000, 0x80e40003, 0xa0e40001, - 0x80000001, 0x0400005a, 0x80040000, 0x80e40003, 0xa0e40002, 0x80000001, 0x03000002, 0x80070000, - 0x80e40000, 0x80e40003, 0x03000005, 0x80070001, 0x80550000, 0xa0e4000b, 0x04000004, 0x80070001, - 0x80000000, 0xa0e4000a, 0x80e40001, 0x03000002, 0x80070003, 0x80e40000, 0x80e40001, 0x03000008, - 0x80010000, 0x80e40003, 0xa0e4000c, 0x03000008, 0x80020000, 0x80e40003, 0xa0e4000d, 0x03000002, - 0x80030000, 0x80e40000, 0x80e40003, 0x03000005, 0x800c0000, 0x80550000, 0xa0440004, 0x04000004, - 0x800c0000, 0x80000000, 0xa0440003, 0x80e40000, 0x04000004, 0x800c0000, 0x80aa0003, 0xa0440005, - 0x80e40000, 0x03000002, 0x80030003, 0x80ee0000, 0x80e40000, 0x0000002a, 0x02000001, 0x80080003, - 0x90ff0001, 0x0000002b, 0x03000042, 0x800f0000, 0x90e40000, 0xa0e40800, 0x03000002, 0x800f0800, - 0x80e40000, 0x80e40003, 0x0000ffff, 0x00000007, 0x00000afc, 0xfffe0300, 0x012ffffe, 0x42415443, - 0x0000001c, 0x00000487, 0xfffe0300, 0x0000000b, 0x0000001c, 0x00000000, 0x00000480, 0x000000f8, - 0x00200002, 0x00000001, 0x00000100, 0x00000110, 0x00000120, 0x001d0002, 0x00000002, 0x00000128, - 0x00000138, 0x00000158, 0x001f0002, 0x00000001, 0x00000160, 0x00000170, 0x00000180, 0x00100002, - 0x00000004, 0x0000018c, 0x0000019c, 0x000001dc, 0x00140002, 0x00000003, 0x000001e4, 0x000001f4, - 0x00000224, 0x00170002, 0x00000003, 0x00000230, 0x00000240, 0x00000270, 0x000c0002, 0x00000004, - 0x00000278, 0x00000288, 0x000002c8, 0x00000003, 0x00000001, 0x000002d4, 0x00000000, 0x000002e4, - 0x001a0002, 0x00000003, 0x0000033c, 0x0000034c, 0x0000037c, 0x00000002, 0x00000006, 0x00000380, - 0x00000390, 0x000003f0, 0x00060002, 0x00000006, 0x00000410, 0x00000420, 0x31727261, 0xababab00, - 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0x42b60000, 0x00000000, 0x00000000, 0x00000000, - 0x32727261, 0xababab00, 0x00030000, 0x00010001, 0x00000002, 0x00000000, 0x42b80000, 0x00000000, - 0x00000000, 0x00000000, 0x42ba0000, 0x00000000, 0x00000000, 0x00000000, 0x6f505f67, 0xab003173, + 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000003, 0x00003070, 0x0000000c, 0x00000010, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00003170, 0x00000006, 0x68636574, 0x00000030, + 0x0000001f, 0x00000001, 0x0000000c, 0x0000000d, 0x00000004, 0x00000020, 0x00000000, 0x00000000, + 0x0000003c, 0x00000058, 0x00000000, 0x00000000, 0x00000074, 0x00000090, 0x00000000, 0x00000000, + 0x000000c0, 0x000000dc, 0x00000000, 0x00000000, 0x000000f8, 0x00000114, 0x00000000, 0x00000000, + 0x00000130, 0x0000014c, 0x00000000, 0x00000000, 0x00000168, 0x00000184, 0x00000000, 0x00000000, + 0x000001a8, 0x000001c4, 0x00000000, 0x00000000, 0x000001e0, 0x000001f4, 0x00000000, 0x00000000, + 0x0000020c, 0x00000228, 0x00000000, 0x00000000, 0x00000264, 0x00000280, 0x00000000, 0x00000000, + 0x000002bc, 0x000002d8, 0x00000000, 0x00000000, 0x00000318, 0x00000334, 0x00000000, 0x00000000, + 0x00000374, 0x00000390, 0x00000000, 0x00000000, 0x000003ac, 0x000003c8, 0x00000000, 0x00000000, + 0x000003e8, 0x00000404, 0x00000000, 0x00000000, 0x00000428, 0x00000444, 0x00000000, 0x00000000, + 0x0000046c, 0x00000488, 0x00000000, 0x00000000, 0x000004ac, 0x000004c8, 0x00000000, 0x00000000, + 0x000004f0, 0x0000050c, 0x00000000, 0x00000000, 0x00000534, 0x00000550, 0x00000000, 0x00000000, + 0x00000578, 0x000005e4, 0x00000000, 0x00000000, 0x00000624, 0x00000690, 0x00000001, 0x00000000, + 0x000006f0, 0x00000774, 0x00000000, 0x00000000, 0x000007dc, 0x000007f8, 0x00000000, 0x00000000, + 0x00000808, 0x00000824, 0x00000001, 0x00000000, 0x00000838, 0x0000084c, 0x00000000, 0x00000000, + 0x0000085c, 0x00000870, 0x00000000, 0x00000000, 0x00000880, 0x000008ec, 0x00000000, 0x00000000, + 0x00000930, 0x00000944, 0x00000001, 0x00000000, 0x00000958, 0x0000096c, 0x00000000, 0x00000000, + 0x00000f8c, 0x00000000, 0x00000002, 0x00000f64, 0x00000000, 0x00000029, 0x00000092, 0x00000000, + 0x00000980, 0x0000097c, 0x00000093, 0x00000000, 0x00000998, 0x00000994, 0x00000091, 0x00000000, + 0x000009b0, 0x000009ac, 0x00000091, 0x00000001, 0x000009d0, 0x000009cc, 0x00000091, 0x00000002, + 0x000009f0, 0x000009ec, 0x00000091, 0x00000003, 0x00000a10, 0x00000a0c, 0x00000091, 0x00000004, + 0x00000a30, 0x00000a2c, 0x00000091, 0x00000005, 0x00000a50, 0x00000a4c, 0x00000091, 0x00000006, + 0x00000a70, 0x00000a6c, 0x00000091, 0x00000007, 0x00000a90, 0x00000a8c, 0x00000084, 0x00000000, + 0x00000ab0, 0x00000aac, 0x00000084, 0x00000001, 0x00000ad0, 0x00000acc, 0x00000084, 0x00000002, + 0x00000af0, 0x00000aec, 0x00000084, 0x00000003, 0x00000b10, 0x00000b0c, 0x00000084, 0x00000004, + 0x00000b30, 0x00000b2c, 0x00000084, 0x00000005, 0x00000b50, 0x00000b4c, 0x00000084, 0x00000006, + 0x00000b70, 0x00000b6c, 0x00000084, 0x00000007, 0x00000b90, 0x00000b8c, 0x00000085, 0x00000000, + 0x00000bbc, 0x00000bac, 0x00000085, 0x00000001, 0x00000be8, 0x00000bd8, 0x00000085, 0x00000002, + 0x00000c14, 0x00000c04, 0x00000085, 0x00000003, 0x00000c40, 0x00000c30, 0x00000085, 0x00000004, + 0x00000c6c, 0x00000c5c, 0x00000085, 0x00000005, 0x00000c98, 0x00000c88, 0x00000085, 0x00000006, + 0x00000cc4, 0x00000cb4, 0x00000085, 0x00000007, 0x00000cf0, 0x00000ce0, 0x00000087, 0x00000000, + 0x00000d1c, 0x00000d0c, 0x00000087, 0x00000001, 0x00000d48, 0x00000d38, 0x00000087, 0x00000002, + 0x00000d74, 0x00000d64, 0x00000087, 0x00000003, 0x00000da0, 0x00000d90, 0x00000087, 0x00000004, + 0x00000dcc, 0x00000dbc, 0x00000087, 0x00000005, 0x00000df8, 0x00000de8, 0x00000087, 0x00000006, + 0x00000e24, 0x00000e14, 0x00000087, 0x00000007, 0x00000e50, 0x00000e40, 0x00000086, 0x00000000, + 0x00000e7c, 0x00000e6c, 0x00000086, 0x00000001, 0x00000ea8, 0x00000e98, 0x0000000e, 0x00000000, + 0x00000ec8, 0x00000ec4, 0x00000014, 0x00000000, 0x00000ee8, 0x00000ee4, 0x00000012, 0x00000000, + 0x00000f08, 0x00000f04, 0x00000041, 0x00000000, 0x00000f28, 0x00000f24, 0x00000042, 0x00000000, + 0x00000f48, 0x00000f44, 0x00000f84, 0x00000000, 0x00000001, 0x00000092, 0x00000000, 0x00000f70, + 0x00000f6c, 0x00000008, 0x0000001c, 0x00000009, 0x000007cc, 0xffff0300, 0x00c0fffe, 0x42415443, + 0x0000001c, 0x000002cb, 0xffff0300, 0x00000009, 0x0000001c, 0x00000000, 0x000002c4, 0x000000d0, + 0x00000001, 0x00000001, 0x000000d8, 0x000000e8, 0x000000f8, 0x00080002, 0x00000002, 0x00000104, + 0x00000114, 0x00000134, 0x00060002, 0x00000002, 0x0000013c, 0x0000014c, 0x0000016c, 0x00000002, + 0x00000003, 0x00000178, 0x00000188, 0x000001b8, 0x000a0002, 0x00000002, 0x000001c0, 0x000001d0, + 0x000001f0, 0x000c0002, 0x00000002, 0x000001fc, 0x0000020c, 0x0000022c, 0x00030002, 0x00000003, + 0x00000234, 0x00000244, 0x00000274, 0x00000000, 0x00000005, 0x00000280, 0x00000290, 0x000002a8, + 0x00000003, 0x00000001, 0x000002b4, 0x00000000, 0x56695f67, 0x00746365, 0x00020001, 0x00040001, + 0x00000001, 0x00000000, 0x00000004, 0x00000003, 0x00000002, 0x00000001, 0x3278326d, 0x756c6f63, + 0xab006e6d, 0x00030003, 0x00020002, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x00000000, + 0x00000000, 0x41400000, 0x41b00000, 0x00000000, 0x00000000, 0x3278326d, 0x00776f72, 0x00030002, + 0x00020002, 0x00000001, 0x00000000, 0x41300000, 0x41400000, 0x00000000, 0x00000000, 0x41a80000, + 0x41b00000, 0x00000000, 0x00000000, 0x3378326d, 0x756c6f63, 0xab006e6d, 0x00030003, 0x00030002, + 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x00000000, 0x00000000, 0x41400000, 0x41b00000, + 0x00000000, 0x00000000, 0x41500000, 0x41b80000, 0x00000000, 0x00000000, 0x3378326d, 0x00776f72, + 0x00030002, 0x00030002, 0x00000001, 0x00000000, 0x41300000, 0x41400000, 0x41500000, 0x00000000, + 0x41a80000, 0x41b00000, 0x41b80000, 0x00000000, 0x3278336d, 0x756c6f63, 0xab006e6d, 0x00030003, + 0x00020003, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x41f80000, 0x00000000, 0x41400000, + 0x41b00000, 0x42000000, 0x00000000, 0x3278336d, 0x00776f72, 0x00030002, 0x00020003, 0x00000001, + 0x00000000, 0x41300000, 0x41400000, 0x00000000, 0x00000000, 0x41a80000, 0x41b00000, 0x00000000, + 0x00000000, 0x41f80000, 0x42000000, 0x00000000, 0x00000000, 0x7832626d, 0x776f7233, 0xababab00, + 0x00010002, 0x00030002, 0x00000001, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, + 0xffffffff, 0xffffffff, 0x706d6173, 0x3172656c, 0xababab00, 0x000c0004, 0x00010001, 0x00000001, + 0x00000000, 0x335f7370, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, + 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x05000051, + 0xa00f000e, 0x3d2aaaa4, 0xbf000000, 0x3f800000, 0xbe22f983, 0x05000051, 0xa00f000f, 0x00000000, + 0x3e22f983, 0x3e800000, 0xbab609ba, 0x05000051, 0xa00f0010, 0x40c90fdb, 0xc0490fdb, 0xb4878163, + 0x37cfb5a1, 0x0200001f, 0x80000005, 0x90030000, 0x0200001f, 0x8000000a, 0x900f0001, 0x0200001f, + 0x90000000, 0xa00f0800, 0x03000005, 0x80030000, 0xa0e40007, 0x90550001, 0x04000004, 0x80030000, + 0x90000001, 0xa0e40006, 0x80e40000, 0x03000002, 0x80030000, 0x80e40000, 0x90e40001, 0x02000001, + 0x80010001, 0xa000000f, 0x0400005a, 0x80010002, 0x90e40001, 0xa0e40008, 0x80000001, 0x0400005a, + 0x80020002, 0x90e40001, 0xa0e40009, 0x80000001, 0x03000002, 0x80030000, 0x80e40000, 0x80e40002, + 0x03000005, 0x800c0000, 0xa0440004, 0x90550001, 0x04000004, 0x800c0000, 0x90000001, 0xa0440003, + 0x80e40000, 0x04000004, 0x800c0000, 0x90aa0001, 0xa0440005, 0x80e40000, 0x03000002, 0x80030000, + 0x80ee0000, 0x80e40000, 0x03000008, 0x80010002, 0x90e40001, 0xa0e4000c, 0x03000008, 0x80020002, + 0x90e40001, 0xa0e4000d, 0x03000002, 0x80030000, 0x80e40000, 0x80e40002, 0x03000005, 0x800e0001, + 0xa090000b, 0x90550001, 0x04000004, 0x800e0001, 0x90000001, 0xa090000a, 0x80e40001, 0x02000001, + 0x80040000, 0x90aa0001, 0x03000002, 0x80070000, 0x80e40000, 0x80f90001, 0x0400005a, 0x80010002, + 0x90e40001, 0xa0e40000, 0x80000001, 0x0400005a, 0x80020002, 0x90e40001, 0xa0e40001, 0x80000001, + 0x0400005a, 0x80040002, 0x90e40001, 0xa0e40002, 0x80000001, 0x03000002, 0x80070000, 0x80e40000, + 0x80e40002, 0x02000001, 0x80070003, 0x80e40000, 0x01000026, 0xf0e40000, 0x03000002, 0x80070003, + 0x80e40002, 0x80e40003, 0x00000027, 0x01000028, 0xe0e40804, 0x02000001, 0x80080003, 0x90ff0001, + 0x04000004, 0x800f0000, 0x80e40003, 0xa055000f, 0xa0aa000f, 0x02000013, 0x800f0000, 0x80e40000, + 0x04000004, 0x800f0000, 0x80e40000, 0xa0000010, 0xa0550010, 0x03000005, 0x800f0000, 0x80e40000, + 0x80e40000, 0x04000004, 0x800f0002, 0x80e40000, 0xa0aa0010, 0xa0ff0010, 0x04000004, 0x800f0002, + 0x80e40000, 0x80e40002, 0xa0ff000f, 0x04000004, 0x800f0002, 0x80e40000, 0x80e40002, 0xa000000e, + 0x04000004, 0x800f0002, 0x80e40000, 0x80e40002, 0xa055000e, 0x04000004, 0x800f0000, 0x80e40000, + 0x80e40002, 0x80e40003, 0x03000002, 0x800f0000, 0x80e40000, 0xa0aa000e, 0x04000004, 0x800f0002, + 0x80e40000, 0xa1ff000e, 0xa155000e, 0x02000013, 0x800f0002, 0x80e40002, 0x04000004, 0x800f0002, + 0x80e40002, 0xa0000010, 0xa0550010, 0x03000005, 0x800f0002, 0x80e40002, 0x80e40002, 0x04000004, + 0x800f0004, 0x80e40002, 0xa0aa0010, 0xa0ff0010, 0x04000004, 0x800f0004, 0x80e40002, 0x80e40004, + 0xa0ff000f, 0x04000004, 0x800f0004, 0x80e40002, 0x80e40004, 0xa000000e, 0x04000004, 0x800f0004, + 0x80e40002, 0x80e40004, 0xa055000e, 0x04000004, 0x800f0000, 0x80e40002, 0x80e40004, 0x80e40000, + 0x03000002, 0x800f0003, 0x80e40000, 0xa0aa000e, 0x0400005a, 0x80010000, 0x80e40003, 0xa0e40000, + 0x80000001, 0x0400005a, 0x80020000, 0x80e40003, 0xa0e40001, 0x80000001, 0x0400005a, 0x80040000, + 0x80e40003, 0xa0e40002, 0x80000001, 0x03000002, 0x80070000, 0x80e40000, 0x80e40003, 0x03000005, + 0x80070001, 0x80550000, 0xa0e4000b, 0x04000004, 0x80070001, 0x80000000, 0xa0e4000a, 0x80e40001, + 0x03000002, 0x80070003, 0x80e40000, 0x80e40001, 0x03000008, 0x80010000, 0x80e40003, 0xa0e4000c, + 0x03000008, 0x80020000, 0x80e40003, 0xa0e4000d, 0x03000002, 0x80030000, 0x80e40000, 0x80e40003, + 0x03000005, 0x800c0000, 0x80550000, 0xa0440004, 0x04000004, 0x800c0000, 0x80000000, 0xa0440003, + 0x80e40000, 0x04000004, 0x800c0000, 0x80aa0003, 0xa0440005, 0x80e40000, 0x03000002, 0x80030003, + 0x80ee0000, 0x80e40000, 0x0000002a, 0x02000001, 0x80080003, 0x90ff0001, 0x0000002b, 0x03000042, + 0x800f0000, 0x90e40000, 0xa0e40800, 0x03000002, 0x800f0800, 0x80e40000, 0x80e40003, 0x0000ffff, + 0x00000007, 0x00000afc, 0xfffe0300, 0x012ffffe, 0x42415443, 0x0000001c, 0x00000487, 0xfffe0300, + 0x0000000b, 0x0000001c, 0x00000000, 0x00000480, 0x000000f8, 0x00200002, 0x00000001, 0x00000100, + 0x00000110, 0x00000120, 0x001d0002, 0x00000002, 0x00000128, 0x00000138, 0x00000158, 0x001f0002, + 0x00000001, 0x00000160, 0x00000170, 0x00000180, 0x00100002, 0x00000004, 0x0000018c, 0x0000019c, + 0x000001dc, 0x00140002, 0x00000003, 0x000001e4, 0x000001f4, 0x00000224, 0x00170002, 0x00000003, + 0x00000230, 0x00000240, 0x00000270, 0x000c0002, 0x00000004, 0x00000278, 0x00000288, 0x000002c8, + 0x00000003, 0x00000001, 0x000002d4, 0x00000000, 0x000002e4, 0x001a0002, 0x00000003, 0x0000033c, + 0x0000034c, 0x0000037c, 0x00000002, 0x00000006, 0x00000380, 0x00000390, 0x000003f0, 0x00060002, + 0x00000006, 0x00000410, 0x00000420, 0x31727261, 0xababab00, 0x00030000, 0x00010001, 0x00000001, + 0x00000000, 0x42b60000, 0x00000000, 0x00000000, 0x00000000, 0x32727261, 0xababab00, 0x00030000, + 0x00010001, 0x00000002, 0x00000000, 0x42b80000, 0x00000000, 0x00000000, 0x00000000, 0x42ba0000, + 0x00000000, 0x00000000, 0x00000000, 0x6f505f67, 0xab003173, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3478336d, 0x756c6f63, 0xab006e6d, + 0x00030003, 0x00040003, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x41f80000, 0x00000000, + 0x41400000, 0x41b00000, 0x42000000, 0x00000000, 0x41500000, 0x41b80000, 0x42040000, 0x00000000, + 0x41600000, 0x41c00000, 0x42080000, 0x00000000, 0x3478336d, 0x00776f72, 0x00030002, 0x00040003, + 0x00000001, 0x00000000, 0x41300000, 0x41400000, 0x41500000, 0x41600000, 0x41a80000, 0x41b00000, + 0x41b80000, 0x41c00000, 0x41f80000, 0x42000000, 0x42040000, 0x42080000, 0x3378346d, 0x756c6f63, + 0xab006e6d, 0x00030003, 0x00030004, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x41f80000, + 0x42240000, 0x41400000, 0x41b00000, 0x42000000, 0x42280000, 0x41500000, 0x41b80000, 0x42040000, + 0x422c0000, 0x3378346d, 0x00776f72, 0x00030002, 0x00030004, 0x00000001, 0x00000000, 0x41300000, + 0x41400000, 0x41500000, 0x00000000, 0x41a80000, 0x41b00000, 0x41b80000, 0x00000000, 0x41f80000, + 0x42000000, 0x42040000, 0x00000000, 0x42240000, 0x42280000, 0x422c0000, 0x00000000, 0x706d6173, + 0x3172656c, 0xababab00, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x00317374, 0xab003176, + 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0xab007666, 0x00030000, 0x00010001, 0x00000001, + 0x00000000, 0xab003276, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x000002e8, 0x000002ec, + 0x000002fc, 0x00000300, 0x00000310, 0x00000314, 0x00000005, 0x00080001, 0x00030001, 0x00000324, + 0x41100000, 0x41200000, 0x41300000, 0x00000000, 0x41400000, 0x00000000, 0x00000000, 0x00000000, + 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x00327374, 0x00000005, 0x00080001, 0x00030002, + 0x00000324, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x40000000, 0x40400000, + 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, + 0x41000000, 0x00337374, 0xab007374, 0x00000005, 0x00080001, 0x00030002, 0x00000324, 0x000003f4, + 0x000003f8, 0x00000005, 0x00100001, 0x00010001, 0x00000408, 0x3f800000, 0x40000000, 0x40400000, + 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, + 0x41000000, 0x41100000, 0x41200000, 0x41300000, 0x00000000, 0x41400000, 0x00000000, 0x00000000, + 0x00000000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x335f7376, 0x4d00305f, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x00ecfffe, 0x53455250, 0x46580201, 0x0043fffe, 0x42415443, + 0x0000001c, 0x000000d7, 0x46580201, 0x00000003, 0x0000001c, 0x00000100, 0x000000d4, 0x00000058, + 0x00020002, 0x00000001, 0x00000060, 0x00000070, 0x00000080, 0x00030002, 0x00000001, 0x00000088, + 0x00000070, 0x00000098, 0x00000002, 0x00000002, 0x000000a4, 0x000000b4, 0x6f505f67, 0xab003173, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x3478336d, 0x756c6f63, 0xab006e6d, 0x00030003, 0x00040003, 0x00000001, 0x00000000, 0x41300000, - 0x41a80000, 0x41f80000, 0x00000000, 0x41400000, 0x41b00000, 0x42000000, 0x00000000, 0x41500000, - 0x41b80000, 0x42040000, 0x00000000, 0x41600000, 0x41c00000, 0x42080000, 0x00000000, 0x3478336d, - 0x00776f72, 0x00030002, 0x00040003, 0x00000001, 0x00000000, 0x41300000, 0x41400000, 0x41500000, - 0x41600000, 0x41a80000, 0x41b00000, 0x41b80000, 0x41c00000, 0x41f80000, 0x42000000, 0x42040000, - 0x42080000, 0x3378346d, 0x756c6f63, 0xab006e6d, 0x00030003, 0x00030004, 0x00000001, 0x00000000, - 0x41300000, 0x41a80000, 0x41f80000, 0x42240000, 0x41400000, 0x41b00000, 0x42000000, 0x42280000, - 0x41500000, 0x41b80000, 0x42040000, 0x422c0000, 0x3378346d, 0x00776f72, 0x00030002, 0x00030004, - 0x00000001, 0x00000000, 0x41300000, 0x41400000, 0x41500000, 0x00000000, 0x41a80000, 0x41b00000, - 0x41b80000, 0x00000000, 0x41f80000, 0x42000000, 0x42040000, 0x00000000, 0x42240000, 0x42280000, - 0x422c0000, 0x00000000, 0x706d6173, 0x3172656c, 0xababab00, 0x000c0004, 0x00010001, 0x00000001, - 0x00000000, 0x00317374, 0xab003176, 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0xab007666, - 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0xab003276, 0x00030001, 0x00040001, 0x00000001, - 0x00000000, 0x000002e8, 0x000002ec, 0x000002fc, 0x00000300, 0x00000310, 0x00000314, 0x00000005, - 0x00080001, 0x00030001, 0x00000324, 0x41100000, 0x41200000, 0x41300000, 0x00000000, 0x41400000, - 0x00000000, 0x00000000, 0x00000000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x00327374, - 0x00000005, 0x00080001, 0x00030002, 0x00000324, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x3f800000, 0x40000000, 0x40400000, 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, - 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x00337374, 0xab007374, 0x00000005, 0x00080001, - 0x00030002, 0x00000324, 0x000003f4, 0x000003f8, 0x00000005, 0x00100001, 0x00010001, 0x00000408, - 0x3f800000, 0x40000000, 0x40400000, 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, - 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000, 0x00000000, - 0x41400000, 0x00000000, 0x00000000, 0x00000000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, - 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, - 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x00ecfffe, 0x53455250, - 0x46580201, 0x0043fffe, 0x42415443, 0x0000001c, 0x000000d7, 0x46580201, 0x00000003, 0x0000001c, - 0x00000100, 0x000000d4, 0x00000058, 0x00020002, 0x00000001, 0x00000060, 0x00000070, 0x00000080, - 0x00030002, 0x00000001, 0x00000088, 0x00000070, 0x00000098, 0x00000002, 0x00000002, 0x000000a4, - 0x000000b4, 0x6f505f67, 0xab003173, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x6f505f67, 0xab003273, 0x00030001, 0x00040001, 0x00000001, - 0x00000000, 0x65535f67, 0x7463656c, 0xab00726f, 0x00030001, 0x00040001, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x41200000, 0x41200000, 0x41200000, 0x41200000, - 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, - 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x000cfffe, 0x49535250, 0x00000021, - 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000021, 0x00000001, - 0x00000000, 0x00000000, 0x0032fffe, 0x54494c43, 0x00000018, 0x00000000, 0x00000000, 0x00000000, + 0x6f505f67, 0xab003273, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x65535f67, 0x7463656c, + 0xab00726f, 0x00030001, 0x00040001, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x41200000, 0x41200000, 0x41200000, 0x41200000, 0x4d007874, 0x6f726369, 0x74666f73, + 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, + 0x332e3235, 0x00313131, 0x000cfffe, 0x49535250, 0x00000021, 0x00000000, 0x00000000, 0x00000001, + 0x00000000, 0x00000000, 0x00000001, 0x00000021, 0x00000001, 0x00000000, 0x00000000, 0x0032fffe, + 0x54494c43, 0x00000018, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3fe00000, 0x00000000, - 0xc0000000, 0x00000000, 0xc0080000, 0x00000000, 0x00000000, 0x00000000, 0x40100000, 0x00000000, - 0x40140000, 0x00000000, 0x40180000, 0x00000000, 0x401c0000, 0x0064fffe, 0x434c5846, 0x00000009, - 0xa0500004, 0x00000002, 0x00000000, 0x00000001, 0x00000011, 0x00000000, 0x00000002, 0x00000008, - 0x00000000, 0x00000007, 0x00000000, 0x20400004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, - 0x00000000, 0x00000001, 0x00000014, 0x00000000, 0x00000007, 0x00000004, 0xa0500004, 0x00000002, - 0x00000000, 0x00000001, 0x00000012, 0x00000000, 0x00000002, 0x0000000c, 0x00000000, 0x00000007, - 0x00000000, 0x20400004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000001, - 0x00000014, 0x00000000, 0x00000007, 0x00000008, 0x10100004, 0x00000001, 0x00000000, 0x00000007, - 0x00000008, 0x00000000, 0x00000007, 0x00000000, 0x20400004, 0x00000002, 0x00000000, 0x00000007, - 0x00000000, 0x00000000, 0x00000007, 0x00000004, 0x00000000, 0x00000007, 0x0000000c, 0xa0200001, - 0x00000002, 0x00000000, 0x00000001, 0x00000010, 0x00000000, 0x00000002, 0x00000005, 0x00000000, - 0x00000007, 0x00000000, 0xa0500004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000007, 0x0000000c, 0x00000000, 0x00000007, 0x00000004, 0x20400004, 0x00000002, 0x00000000, - 0x00000007, 0x00000004, 0x00000000, 0x00000007, 0x00000008, 0x00000000, 0x00000004, 0x00000084, - 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x05000051, 0xa00f0022, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, + 0x00000000, 0x00000000, 0x00000000, 0x3fe00000, 0x00000000, 0xc0000000, 0x00000000, 0xc0080000, + 0x00000000, 0x00000000, 0x00000000, 0x40100000, 0x00000000, 0x40140000, 0x00000000, 0x40180000, + 0x00000000, 0x401c0000, 0x0064fffe, 0x434c5846, 0x00000009, 0xa0500004, 0x00000002, 0x00000000, + 0x00000001, 0x00000011, 0x00000000, 0x00000002, 0x00000008, 0x00000000, 0x00000007, 0x00000000, + 0x20400004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000001, 0x00000014, + 0x00000000, 0x00000007, 0x00000004, 0xa0500004, 0x00000002, 0x00000000, 0x00000001, 0x00000012, + 0x00000000, 0x00000002, 0x0000000c, 0x00000000, 0x00000007, 0x00000000, 0x20400004, 0x00000002, + 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000001, 0x00000014, 0x00000000, 0x00000007, + 0x00000008, 0x10100004, 0x00000001, 0x00000000, 0x00000007, 0x00000008, 0x00000000, 0x00000007, + 0x00000000, 0x20400004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000007, + 0x00000004, 0x00000000, 0x00000007, 0x0000000c, 0xa0200001, 0x00000002, 0x00000000, 0x00000001, + 0x00000010, 0x00000000, 0x00000002, 0x00000005, 0x00000000, 0x00000007, 0x00000000, 0xa0500004, + 0x00000002, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000007, 0x0000000c, 0x00000000, + 0x00000007, 0x00000004, 0x20400004, 0x00000002, 0x00000000, 0x00000007, 0x00000004, 0x00000000, + 0x00000007, 0x00000008, 0x00000000, 0x00000004, 0x00000084, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + 0x05000051, 0xa00f0022, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, + 0x900f0000, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x80000000, 0xe00f0000, 0x0200001f, + 0x80000005, 0xe0030001, 0x0200001f, 0x8000000a, 0xe00f0002, 0x03000009, 0x80010000, 0x90e40000, + 0xa0e40017, 0x03000009, 0x80020000, 0x90e40000, 0xa0e40018, 0x03000009, 0x80040000, 0x90e40000, + 0xa0e40019, 0x03000008, 0x80010001, 0x90e40000, 0xa0e40010, 0x03000008, 0x80020001, 0x90e40000, + 0xa0e40011, 0x03000008, 0x80040001, 0x90e40000, 0xa0e40012, 0x03000008, 0x80080001, 0x90e40000, + 0xa0e40013, 0x02000001, 0x80080000, 0xa0000022, 0x03000002, 0x800f0000, 0x80e40000, 0x80e40001, + 0x03000005, 0x800f0001, 0xa0e40015, 0x90550000, 0x04000004, 0x800f0001, 0x90000000, 0xa0e40014, + 0x80e40001, 0x04000004, 0x800f0001, 0x90aa0000, 0xa0e40016, 0x80e40001, 0x03000002, 0x800f0000, + 0x80e40000, 0x80e40001, 0x03000005, 0x80070001, 0xa0e4000d, 0x90550000, 0x04000004, 0x80070001, + 0x90000000, 0xa0e4000c, 0x80e40001, 0x04000004, 0x80070001, 0x90aa0000, 0xa0e4000e, 0x80e40001, + 0x04000004, 0x80070001, 0x90ff0000, 0xa0e4000f, 0x80e40001, 0x03000002, 0x80070000, 0x80e40000, + 0x80e40001, 0x04000004, 0x800f0000, 0x90e40000, 0xa000001b, 0x80e40000, 0x03000009, 0x80010001, + 0x90e40000, 0xa0e4001c, 0x03000002, 0x800f0000, 0x80e40000, 0x80000001, 0x04000004, 0x800f0000, + 0x90e40000, 0xa0000004, 0x80e40000, 0x03000009, 0x80010001, 0x90e40000, 0xa0e40005, 0x03000002, + 0x800f0000, 0x80e40000, 0x80000001, 0x04000004, 0x800f0000, 0x90e40000, 0xa0000020, 0x80e40000, + 0x04000004, 0x800f0000, 0x90e40000, 0xa000001e, 0x80e40000, 0x04000004, 0x800f0000, 0x90e40000, + 0xa000000a, 0x80e40000, 0x03000009, 0x80010001, 0x90e40000, 0xa0e4000b, 0x03000002, 0x800f0000, + 0x80e40000, 0x80000001, 0x0300005f, 0x800f0001, 0xa0e4001f, 0xa0e40800, 0x03000002, 0xe00f0002, + 0x80e40000, 0x80e40001, 0x02000001, 0xe00f0000, 0xa0e40021, 0x02000001, 0xe0030001, 0xa0000022, + 0x0000ffff, 0x00000008, 0x000001dc, 0xfffe0300, 0x0016fffe, 0x42415443, 0x0000001c, 0x00000023, + 0xfffe0300, 0x00000000, 0x00000000, 0x00000000, 0x0000001c, 0x335f7376, 0x4d00305f, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0045fffe, 0x53455250, 0x46580201, 0x0024fffe, 0x42415443, + 0x0000001c, 0x0000005b, 0x46580201, 0x00000001, 0x0000001c, 0x00000100, 0x00000058, 0x00000030, + 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x6f505f67, 0xab003173, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x000cfffe, 0x49535250, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000, + 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000004, 0x00000001, + 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, + 0x0000ffff, 0x05000051, 0xa00f0001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, 0xe00f0000, 0x0200001f, 0x80000005, 0xe0030001, 0x0200001f, 0x8000000a, 0xe00f0002, - 0x03000009, 0x80010000, 0x90e40000, 0xa0e40017, 0x03000009, 0x80020000, 0x90e40000, 0xa0e40018, - 0x03000009, 0x80040000, 0x90e40000, 0xa0e40019, 0x03000008, 0x80010001, 0x90e40000, 0xa0e40010, - 0x03000008, 0x80020001, 0x90e40000, 0xa0e40011, 0x03000008, 0x80040001, 0x90e40000, 0xa0e40012, - 0x03000008, 0x80080001, 0x90e40000, 0xa0e40013, 0x02000001, 0x80080000, 0xa0000022, 0x03000002, - 0x800f0000, 0x80e40000, 0x80e40001, 0x03000005, 0x800f0001, 0xa0e40015, 0x90550000, 0x04000004, - 0x800f0001, 0x90000000, 0xa0e40014, 0x80e40001, 0x04000004, 0x800f0001, 0x90aa0000, 0xa0e40016, - 0x80e40001, 0x03000002, 0x800f0000, 0x80e40000, 0x80e40001, 0x03000005, 0x80070001, 0xa0e4000d, - 0x90550000, 0x04000004, 0x80070001, 0x90000000, 0xa0e4000c, 0x80e40001, 0x04000004, 0x80070001, - 0x90aa0000, 0xa0e4000e, 0x80e40001, 0x04000004, 0x80070001, 0x90ff0000, 0xa0e4000f, 0x80e40001, - 0x03000002, 0x80070000, 0x80e40000, 0x80e40001, 0x04000004, 0x800f0000, 0x90e40000, 0xa000001b, - 0x80e40000, 0x03000009, 0x80010001, 0x90e40000, 0xa0e4001c, 0x03000002, 0x800f0000, 0x80e40000, - 0x80000001, 0x04000004, 0x800f0000, 0x90e40000, 0xa0000004, 0x80e40000, 0x03000009, 0x80010001, - 0x90e40000, 0xa0e40005, 0x03000002, 0x800f0000, 0x80e40000, 0x80000001, 0x04000004, 0x800f0000, - 0x90e40000, 0xa0000020, 0x80e40000, 0x04000004, 0x800f0000, 0x90e40000, 0xa000001e, 0x80e40000, - 0x04000004, 0x800f0000, 0x90e40000, 0xa000000a, 0x80e40000, 0x03000009, 0x80010001, 0x90e40000, - 0xa0e4000b, 0x03000002, 0x800f0000, 0x80e40000, 0x80000001, 0x0300005f, 0x800f0001, 0xa0e4001f, - 0xa0e40800, 0x03000002, 0xe00f0002, 0x80e40000, 0x80e40001, 0x02000001, 0xe00f0000, 0xa0e40021, - 0x02000001, 0xe0030001, 0xa0000022, 0x0000ffff, 0x00000005, 0x00000000, 0x00000004, 0x00000000, - 0x00000001, 0x0000002c, 0xfffe0101, 0x00000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, - 0x3f800000, 0x00000001, 0xc00f0000, 0xa0e40000, 0x0000ffff, 0x00000002, 0x0000002c, 0xfffe0101, - 0x00000051, 0xa00f0000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000001, 0xc00f0000, - 0xa0e40000, 0x0000ffff, 0x00000003, 0x0000002c, 0xfffe0200, 0x05000051, 0xa00f0000, 0x40400000, - 0x40400000, 0x40400000, 0x40400000, 0x02000001, 0xc00f0000, 0xa0e40000, 0x0000ffff, 0x00000000, - 0x00000001, 0xffffffff, 0x00000000, 0x00000002, 0x000000e8, 0x00000008, 0x615f7376, 0x00007272, - 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, - 0x00000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x56695f67, - 0x00746365, 0x00020001, 0x00040001, 0x00000001, 0x00000000, 0x40800000, 0x40400000, 0x40000000, - 0x3f800000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, + 0x02000001, 0xe00f0000, 0xa0e40000, 0x02000001, 0xe0030001, 0xa0000001, 0x02000001, 0xe00f0002, + 0xa0000001, 0x0000ffff, 0x00000005, 0x00000000, 0x00000004, 0x00000000, 0x00000001, 0x0000002c, + 0xfffe0101, 0x00000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000001, + 0xc00f0000, 0xa0e40000, 0x0000ffff, 0x00000002, 0x0000002c, 0xfffe0101, 0x00000051, 0xa00f0000, + 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000001, 0xc00f0000, 0xa0e40000, 0x0000ffff, + 0x00000003, 0x0000002c, 0xfffe0200, 0x05000051, 0xa00f0000, 0x40400000, 0x40400000, 0x40400000, + 0x40400000, 0x02000001, 0xc00f0000, 0xa0e40000, 0x0000ffff, 0x00000000, 0x00000001, 0xffffffff, + 0x00000000, 0x00000002, 0x000000e8, 0x00000008, 0x615f7376, 0x00007272, 0x46580200, 0x0024fffe, + 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x00000100, 0x00000058, + 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x56695f67, 0x00746365, 0x00020001, + 0x00040001, 0x00000001, 0x00000000, 0x40800000, 0x40400000, 0x40000000, 0x3f800000, 0x4d007874, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, + 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000002, 0x00000000, + 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, + 0x00000028, 0x00000000, 0x00000198, 0x46580200, 0x0053fffe, 0x42415443, 0x0000001c, 0x00000117, + 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000114, 0x00000030, 0x00000002, 0x00000005, + 0x000000a4, 0x000000b4, 0x00337374, 0x76007374, 0xabab0031, 0x00030001, 0x00030001, 0x00000001, + 0x00000000, 0xab007666, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0xab003276, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x00000037, 0x0000003c, 0x0000004c, 0x00000050, 0x00000060, + 0x00000064, 0x00000005, 0x00080001, 0x00030002, 0x00000074, 0x00000034, 0x0000008c, 0x00000005, + 0x00100001, 0x00010001, 0x0000009c, 0x3f800000, 0x40000000, 0x40400000, 0x00000000, 0x40800000, + 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x41100000, + 0x41200000, 0x41300000, 0x00000000, 0x41400000, 0x00000000, 0x00000000, 0x00000000, 0x41500000, + 0x41600000, 0x41700000, 0x41800000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, + 0x00000000, 0x00000002, 0x00000010, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, + 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000027, 0x00000000, 0x00000198, 0x46580200, + 0x0053fffe, 0x42415443, 0x0000001c, 0x00000117, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, + 0x00000114, 0x00000030, 0x00000002, 0x00000002, 0x000000a4, 0x000000b4, 0x00337374, 0x76007374, + 0xabab0031, 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0xab007666, 0x00030000, 0x00010001, + 0x00000001, 0x00000000, 0xab003276, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000037, + 0x0000003c, 0x0000004c, 0x00000050, 0x00000060, 0x00000064, 0x00000005, 0x00080001, 0x00030002, + 0x00000074, 0x00000034, 0x0000008c, 0x00000005, 0x00100001, 0x00010001, 0x0000009c, 0x3f800000, + 0x40000000, 0x40400000, 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, + 0x40c00000, 0x40e00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000, 0x00000000, 0x41400000, + 0x00000000, 0x00000000, 0x00000000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x4d007874, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, + 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000004, 0x00000000, + 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, + 0x00000026, 0x00000000, 0x0000017c, 0x46580200, 0x004cfffe, 0x42415443, 0x0000001c, 0x000000fb, + 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x000000f8, 0x00000030, 0x00000002, 0x00000005, + 0x00000088, 0x00000098, 0x00327374, 0xab003176, 0x00030001, 0x00030001, 0x00000001, 0x00000000, + 0xab007666, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0xab003276, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x00000034, 0x00000038, 0x00000048, 0x0000004c, 0x0000005c, 0x00000060, + 0x00000005, 0x00080001, 0x00030002, 0x00000070, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x40000000, 0x40400000, 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, + 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, + 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, + 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, + 0x00000001, 0x00000000, 0x00000002, 0x00000010, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, + 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000025, 0x00000000, 0x0000017c, + 0x46580200, 0x004cfffe, 0x42415443, 0x0000001c, 0x000000fb, 0x46580200, 0x00000001, 0x0000001c, + 0x20000100, 0x000000f8, 0x00000030, 0x00000002, 0x00000002, 0x00000088, 0x00000098, 0x00327374, + 0xab003176, 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0xab007666, 0x00030000, 0x00010001, + 0x00000001, 0x00000000, 0xab003276, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000034, + 0x00000038, 0x00000048, 0x0000004c, 0x0000005c, 0x00000060, 0x00000005, 0x00080001, 0x00030002, + 0x00000070, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x40000000, 0x40400000, + 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, + 0x41000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, - 0x00000002, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, + 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000023, 0x00000000, 0x000003f0, 0x46580200, 0x0056fffe, 0x42415443, 0x0000001c, 0x00000123, 0x46580200, 0x00000004, 0x0000001c, 0x20000100, 0x00000120, 0x0000006c, 0x00000002, 0x00000002, 0x00000078, 0x00000088, 0x000000a8, 0x00040002, 0x00000001, 0x000000b0, @@ -3810,9 +3901,125 @@ 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0xffffffff, 0x0000001c, 0x00000000, 0x00000000, 0x00000001, 0x00000005, 0x31786574, 0x00000000, }; -#define TEST_EFFECT_PRESHADER_VSHADER_POS 2458 +#define TEST_EFFECT_PRESHADER_VSHADER_POS 2640 #define TEST_EFFECT_PRESHADER_VSHADER_LEN 13 +#define test_effect_preshader_compare_shader(a, b, c) \ + test_effect_preshader_compare_shader_(__LINE__, a, b, c) +static void test_effect_preshader_compare_shader_(unsigned int line, IDirect3DDevice9 *device, + int expected_shader_index, BOOL todo) +{ + IDirect3DVertexShader9 *vshader; + void *byte_code; + unsigned int byte_code_size; + HRESULT hr; + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok_(__FILE__, line)(hr == D3D_OK, "IDirect3DDevice9_GetVertexShader result %#x.\n", hr); + + todo_wine_if(todo) + ok_(__FILE__, line)(!!vshader, "Got NULL vshader.\n"); + if (!vshader) + return; + + hr = IDirect3DVertexShader9_GetFunction(vshader, NULL, &byte_code_size); + ok_(__FILE__, line)(hr == D3D_OK, "IDirect3DVertexShader9_GetFunction %#x.\n", hr); + ok_(__FILE__, line)(byte_code_size > 1, "Got unexpected byte code size %u.\n", byte_code_size); + + byte_code = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, byte_code_size); + hr = IDirect3DVertexShader9_GetFunction(vshader, byte_code, &byte_code_size); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + + todo_wine_if(todo) + ok_(__FILE__, line)(!memcmp(byte_code, &test_effect_preshader_effect_blob[TEST_EFFECT_PRESHADER_VSHADER_POS + + expected_shader_index * TEST_EFFECT_PRESHADER_VSHADER_LEN], byte_code_size), + "Incorrect shader selected.\n"); + HeapFree(GetProcessHeap(), 0, byte_code); + IDirect3DVertexShader9_Release(vshader); + } + +static const struct +{ + const char *comment; + BOOL todo[4]; + unsigned int result[4]; + unsigned int ulps; +} +test_effect_preshader_op_expected[] = +{ + {"1 / op", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbee8ba2e, 0x00200000}}, + {"rsq", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0x7f800000, 0x3f2c985c, 0x1f800001}, 1}, + {"mul", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0x40d33334, 0x7f800000}}, + {"add", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x40000000, 0xc0a66666, 0x7f7fffff}}, + {"lt", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x3f800000, 0x00000000, 0x00000000}}, + {"ge", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {"neg", {FALSE, FALSE, FALSE, FALSE}, {0x80000000, 0x00000000, 0x400ccccd, 0xff7fffff}}, + {"rcp", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbee8ba2e, 0x00200000}}, + + {"frac", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x00000000, 0x3f4ccccc, 0x00000000}}, + {"min", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0xc0400000, 0x40800000}}, + {"max", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x40000000, 0xc00ccccd, 0x7f7fffff}}, +#if __x86_64__ + {"sin", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0xbf4ef99e, 0xbf0599b3}}, + {"cos", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x3f800000, 0xbf16a803, 0x3f5a5f96}}, +#else + {"sin", {FALSE, FALSE, FALSE, TRUE}, {0x00000000, 0x80000000, 0xbf4ef99e, 0x3f792dc4}}, + {"cos", {FALSE, FALSE, FALSE, TRUE}, {0x3f800000, 0x3f800000, 0xbf16a803, 0xbe6acefc}}, +#endif + {"den mul",{FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbb94f209, 0x000051ec}}, + {"dot", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x7f800000, 0x41f00000, 0x00000000}}, + {"prec", {FALSE, FALSE, TRUE, FALSE}, {0x2b8cbccc, 0x2c0cbccc, 0xac531800, 0x00000000}}, + + {"dotswiz", {FALSE, FALSE, FALSE, FALSE}, {0xc00ccccd, 0xc0d33334, 0xc10ccccd, 0}}, + {"reladdr", { TRUE, TRUE, TRUE, TRUE}, {0xc00ccccd, 0x40000000, 0x41a00000, 0x41500000}}, +}; + +enum expected_state_update +{ + EXPECTED_STATE_ZERO, + EXPECTED_STATE_UPDATED, + EXPECTED_STATE_ANYTHING +}; + +#define test_effect_preshader_op_results(a, b, c) test_effect_preshader_op_results_(__LINE__, a, b, c) +static void test_effect_preshader_op_results_(unsigned int line, IDirect3DDevice9 *device, + const enum expected_state_update *expected_state, const char *updated_param) +{ + static const D3DCOLORVALUE black = {0.0f}; + unsigned int i, j; + D3DLIGHT9 light; + const float *v; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(test_effect_preshader_op_expected); ++i) + { + hr = IDirect3DDevice9_GetLight(device, i % 8, &light); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + + v = i < 8 ? &light.Diffuse.r : (i < 16 ? &light.Ambient.r : &light.Specular.r); + if (!expected_state || expected_state[i] == EXPECTED_STATE_UPDATED) + { + for (j = 0; j < 4; ++j) + { + todo_wine_if(test_effect_preshader_op_expected[i].todo[j]) + ok_(__FILE__, line)(compare_float(v[j], + ((const float *)test_effect_preshader_op_expected[i].result)[j], + test_effect_preshader_op_expected[i].ulps), + "Operation %s, component %u, expected %#x, got %#x (%g).\n", + test_effect_preshader_op_expected[i].comment, j, + test_effect_preshader_op_expected[i].result[j], + ((const unsigned int *)v)[j], v[j]); + } + } + else if (expected_state[i] == EXPECTED_STATE_ZERO) + { + ok_(__FILE__, line)(!memcmp(v, &black, sizeof(black)), + "Parameter %s, test %d, operation %s, state updated unexpectedly.\n", + updated_param, i, test_effect_preshader_op_expected[i].comment); + } + } +} + static void test_effect_preshader(IDirect3DDevice9 *device) { static const D3DXVECTOR4 test_effect_preshader_fconstsv[] = @@ -3877,46 +4084,12 @@ { {4, 3, 2, 1} }; - static const struct - { - const char *comment; - BOOL todo[4]; - unsigned int result[4]; - unsigned int ulps; - } - test_effect_preshader_op_results[] = - { - {"1 / op", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbee8ba2e, 0x00200000}}, - {"rsq", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0x7f800000, 0x3f2c985c, 0x1f800001}, 1}, - {"mul", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0x40d33334, 0x7f800000}}, - {"add", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x40000000, 0xc0a66666, 0x7f7fffff}}, - {"lt", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x3f800000, 0x00000000, 0x00000000}}, - {"ge", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, - {"neg", {FALSE, FALSE, FALSE, FALSE}, {0x80000000, 0x00000000, 0x400ccccd, 0xff7fffff}}, - {"rcp", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbee8ba2e, 0x00200000}}, - {"frac", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x00000000, 0x3f4ccccc, 0x00000000}}, - {"min", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0xc0400000, 0x40800000}}, - {"max", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x40000000, 0xc00ccccd, 0x7f7fffff}}, -#if __x86_64__ - {"sin", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0xbf4ef99e, 0xbf0599b3}}, - {"cos", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x3f800000, 0xbf16a803, 0x3f5a5f96}}, -#else - {"sin", {FALSE, FALSE, FALSE, TRUE}, {0x00000000, 0x80000000, 0xbf4ef99e, 0x3f792dc4}}, - {"cos", {FALSE, FALSE, FALSE, TRUE}, {0x3f800000, 0x3f800000, 0xbf16a803, 0xbe6acefc}}, -#endif - {"den mul",{FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbb94f209, 0x000051ec}}, - {"dot", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x7f800000, 0x41f00000, 0x00000000}}, - {"prec", {FALSE, FALSE, TRUE, FALSE}, {0x2b8cbccc, 0x2c0cbccc, 0xac531800, 0x00000000}}, - {"dotswiz", {FALSE, FALSE, FALSE, FALSE}, {0xc00ccccd, 0xc0d33334, 0xc10ccccd, 0}}, - {"reladdr", { TRUE, TRUE, TRUE, TRUE}, {0xc00ccccd, 0x40000000, 0x41a00000, 0x41500000}}, - }; #define TEST_EFFECT_PRES_NFLOATV ARRAY_SIZE(test_effect_preshader_fconstsv) #define TEST_EFFECT_PRES_NFLOATP ARRAY_SIZE(test_effect_preshader_fconstsp) #define TEST_EFFECT_PRES_NFLOATMAX (TEST_EFFECT_PRES_NFLOATV > TEST_EFFECT_PRES_NFLOATP ? \ TEST_EFFECT_PRES_NFLOATV : TEST_EFFECT_PRES_NFLOATP) #define TEST_EFFECT_PRES_NBOOL ARRAY_SIZE(test_effect_preshader_bconsts) #define TEST_EFFECT_PRES_NINT ARRAY_SIZE(test_effect_preshader_iconsts) -#define TEST_EFFECT_PRES_NOPTESTS ARRAY_SIZE(test_effect_preshader_op_results) static const D3DXVECTOR4 fvect1 = {28.0f, 29.0f, 30.0f, 31.0f}; static const D3DXVECTOR4 fvect2 = {0.0f, 0.0f, 1.0f, 0.0f}; @@ -3928,14 +4101,11 @@ unsigned int npasses; DWORD value; BOOL bval; - D3DLIGHT9 light; D3DXVECTOR4 fdata[TEST_EFFECT_PRES_NFLOATMAX]; int idata[TEST_EFFECT_PRES_NINT][4]; BOOL bdata[TEST_EFFECT_PRES_NBOOL]; IDirect3DVertexShader9 *vshader; - void *byte_code; - unsigned int byte_code_size; - unsigned int i, j; + unsigned int i; D3DCAPS9 caps; hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); @@ -3985,6 +4155,12 @@ hr = effect->lpVtbl->BeginPass(effect, 0); ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, &fdata[0].x, TEST_EFFECT_PRES_NFLOATV); ok(hr == D3D_OK, "Got result %#x.\n", hr); ok(!memcmp(fdata, test_effect_preshader_fconstsv, sizeof(test_effect_preshader_fconstsv)), @@ -4031,23 +4207,7 @@ ok(hr == D3D_OK && !bval, "Got result %#x, boolean register value %u.\n", hr, bval); } - for (i = 0; i < TEST_EFFECT_PRES_NOPTESTS; ++i) - { - float *v; - - hr = IDirect3DDevice9_GetLight(device, i % 8, &light); - v = i < 8 ? &light.Diffuse.r : (i < 16 ? &light.Ambient.r : &light.Specular.r); - ok(hr == D3D_OK, "Got result %#x.\n", hr); - for (j = 0; j < 4; ++j) - { - todo_wine_if(test_effect_preshader_op_results[i].todo[j]) - ok(compare_float(v[j], ((float *)test_effect_preshader_op_results[i].result)[j], - test_effect_preshader_op_results[i].ulps), - "Operation %s, component %u, expected %#x, got %#x (%g).\n", - test_effect_preshader_op_results[i].comment, j, - test_effect_preshader_op_results[i].result[j], ((unsigned int *)v)[j], v[j]); - } - } + test_effect_preshader_op_results(device, NULL, NULL); hr = IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_MINFILTER, &value); ok(hr == D3D_OK, "Got result %#x.\n", hr); @@ -4062,6 +4222,19 @@ ok(hr == D3D_OK, "Got result %#x.\n", hr); todo_wine ok(value == 3, "Unexpected sampler 0 magfilter %u.\n", value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGDENSITY, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 0, "Unexpected fog density %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGSTART, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 4.0f, "Unexpected fog start %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSCALE_A, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 4.0f, "Unexpected point scale A %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSCALE_B, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 12.0f, "Unexpected point scale B %g.\n", *(float *)&value); + hr = effect->lpVtbl->EndPass(effect); par = effect->lpVtbl->GetParameterByName(effect, NULL, "g_iVect"); @@ -4071,22 +4244,7 @@ hr = effect->lpVtbl->BeginPass(effect, 1); ok(hr == D3D_OK, "Got result %#x.\n", hr); - hr = IDirect3DDevice9_GetVertexShader(device, &vshader); - ok(hr == D3D_OK, "Got result %#x.\n", hr); - ok(!!vshader, "Got NULL vshader.\n"); - - hr = IDirect3DVertexShader9_GetFunction(vshader, NULL, &byte_code_size); - ok(hr == D3D_OK, "Got result %#x.\n", hr); - byte_code = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, byte_code_size); - hr = IDirect3DVertexShader9_GetFunction(vshader, byte_code, &byte_code_size); - ok(hr == D3D_OK, "Got result %#x.\n", hr); - ok(byte_code_size > 1, "Got unexpected byte code size %u.\n", byte_code_size); - ok(!memcmp(byte_code, - &test_effect_preshader_effect_blob[TEST_EFFECT_PRESHADER_VSHADER_POS + - TEST_EFFECT_PRESHADER_VSHADER_LEN], byte_code_size), - "Incorrect shader selected.\n"); - HeapFree(GetProcessHeap(), 0, byte_code); - IDirect3DVertexShader9_Release(vshader); + test_effect_preshader_compare_shader(device, 1, FALSE); hr = IDirect3DDevice9_SetVertexShader(device, NULL); ok(hr == D3D_OK, "Got result %#x.\n", hr); @@ -4129,8 +4287,8 @@ blob_position[] = { {0, 0}, - {4334, 0}, - {4185, 2} + {4934, 0}, + {4785, 2} }; DWORD *test_effect_blob; HRESULT hr; @@ -4284,6 +4442,118 @@ effect->lpVtbl->Release(effect); } +static void test_effect_out_of_bounds_selector(IDirect3DDevice9 *device) +{ + ID3DXEffect *effect; + HRESULT hr; + D3DXHANDLE param; + int ivect[4]; + unsigned int passes_count; + IDirect3DVertexShader9 *vshader; + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ivect[0] = ivect[1] = ivect[3] = 1; + + param = effect->lpVtbl->GetParameterByName(effect, NULL, "g_iVect"); + ok(!!param, "GetParameterByName failed.\n"); + ivect[2] = 3; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + todo_wine ok(hr == E_FAIL, "Got result %#x.\n", hr); + if (SUCCEEDED(hr)) + effect->lpVtbl->EndPass(effect); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader(device, 2, TRUE); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ivect[2] = -2; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + todo_wine ok(hr == E_FAIL, "Got result %#x.\n", hr); + if (SUCCEEDED(hr)) + hr = effect->lpVtbl->EndPass(effect); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader(device, 2, TRUE); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ivect[2] = -1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader(device, 0, TRUE); + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ivect[2] = 3; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + + ivect[2] = -1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + + ivect[2] = 1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader(device, 1, FALSE); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); +} + START_TEST(effect) { HWND wnd; @@ -4327,6 +4597,7 @@ test_effect_preshader(device); test_effect_preshader_ops(device); test_effect_isparameterused(device); + test_effect_out_of_bounds_selector(device); count = IDirect3DDevice9_Release(device); ok(count == 0, "The device was not properly freed: refcount %u\n", count); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/ddraw.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/ddraw.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/ddraw.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/ddraw.c 2017-03-21 14:02:57.000000000 +0000 @@ -361,7 +361,7 @@ return ddraw1_AddRef(&This->IDirectDraw_iface); } -void ddraw_destroy_swapchain(struct ddraw *ddraw) +static void ddraw_destroy_swapchain(struct ddraw *ddraw) { TRACE("Destroying the swapchain.\n"); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/ddraw_private.h wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/ddraw_private.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/ddraw_private.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/ddraw_private.h 2017-03-21 14:02:57.000000000 +0000 @@ -61,7 +61,8 @@ #define DDRAW_WINED3D_FLAGS (WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING \ | WINED3D_RESTORE_MODE_ON_ACTIVATE | WINED3D_FOCUS_MESSAGES | WINED3D_PIXEL_CENTER_INTEGER \ - | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART) + | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART \ + | WINED3D_LEGACY_CUBEMAP_FILTERING) enum ddraw_device_state { @@ -126,7 +127,6 @@ HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type device_type) DECLSPEC_HIDDEN; void ddraw_d3dcaps1_from_7(D3DDEVICEDESC *caps1, D3DDEVICEDESC7 *caps7) DECLSPEC_HIDDEN; -void ddraw_destroy_swapchain(struct ddraw *ddraw) DECLSPEC_HIDDEN; HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps) DECLSPEC_HIDDEN; void ddraw_update_lost_surfaces(struct ddraw *ddraw) DECLSPEC_HIDDEN; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/device.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/device.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/device.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/device.c 2017-03-21 14:02:57.000000000 +0000 @@ -4392,10 +4392,7 @@ if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos) ib_pos = 0; - /* Copy the index stream into the index buffer. A new IWineD3DDevice - * method could be created which takes an user pointer containing the - * indices or a SetData-Method for the index buffer, which overrides the - * index buffer data with our pointer. */ + /* Copy the index stream into the index buffer. */ wined3d_box.left = ib_pos; wined3d_box.right = ib_pos + index_count * sizeof(WORD); ib = wined3d_buffer_get_resource(device->index_buffer); @@ -4497,96 +4494,163 @@ * *****************************************************************************/ -static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius) +static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality) { float distance, norm; - norm = sqrtf(normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z); - distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm; + norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z); + distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm; - if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane; - if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane; + if (equality) + { + if (fabs(distance) <= radius) + return D3DSTATUS_CLIPUNIONLEFT << idx; + if (distance <= -radius) + return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx; + } + else + { + if (fabs(distance) < radius) + return D3DSTATUS_CLIPUNIONLEFT << idx; + if (distance < -radius) + return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx; + } return 0; } -static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface, - D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) +static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane) { D3DMATRIX m, temp; - D3DVALUE origin_plane[6]; - D3DVECTOR vec[6]; - HRESULT hr; - UINT i, j; - TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n", - iface, centers, radii, sphere_count, flags, return_values); + /* We want the wined3d matrices since those include the legacy viewport + * transformation. */ + wined3d_mutex_lock(); + wined3d_device_get_transform(device->wined3d_device, + WINED3D_TS_WORLD, (struct wined3d_matrix *)&m); - hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m); - if ( hr != DD_OK ) return DDERR_INVALIDPARAMS; - hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp); - if ( hr != DD_OK ) return DDERR_INVALIDPARAMS; + wined3d_device_get_transform(device->wined3d_device, + WINED3D_TS_VIEW, (struct wined3d_matrix *)&temp); multiply_matrix(&m, &temp, &m); - hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp); - if ( hr != DD_OK ) return DDERR_INVALIDPARAMS; + wined3d_device_get_transform(device->wined3d_device, + WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&temp); multiply_matrix(&m, &temp, &m); + wined3d_mutex_unlock(); + + /* Left plane. */ + plane[0].x = m._14 + m._11; + plane[0].y = m._24 + m._21; + plane[0].z = m._34 + m._31; + plane[0].w = m._44 + m._41; + + /* Right plane. */ + plane[1].x = m._14 - m._11; + plane[1].y = m._24 - m._21; + plane[1].z = m._34 - m._31; + plane[1].w = m._44 - m._41; + + /* Top plane. */ + plane[2].x = m._14 - m._12; + plane[2].y = m._24 - m._22; + plane[2].z = m._34 - m._32; + plane[2].w = m._44 - m._42; + + /* Bottom plane. */ + plane[3].x = m._14 + m._12; + plane[3].y = m._24 + m._22; + plane[3].z = m._34 + m._32; + plane[3].w = m._44 + m._42; + + /* Front plane. */ + plane[4].x = m._13; + plane[4].y = m._23; + plane[4].z = m._33; + plane[4].w = m._43; + + /* Back plane. */ + plane[5].x = m._14 - m._13; + plane[5].y = m._24 - m._23; + plane[5].z = m._34 - m._33; + plane[5].w = m._44 - m._43; +} -/* Left plane */ - vec[0].u1.x = m._14 + m._11; - vec[0].u2.y = m._24 + m._21; - vec[0].u3.z = m._34 + m._31; - origin_plane[0] = m._44 + m._41; - -/* Right plane */ - vec[1].u1.x = m._14 - m._11; - vec[1].u2.y = m._24 - m._21; - vec[1].u3.z = m._34 - m._31; - origin_plane[1] = m._44 - m._41; - -/* Top plane */ - vec[2].u1.x = m._14 - m._12; - vec[2].u2.y = m._24 - m._22; - vec[2].u3.z = m._34 - m._32; - origin_plane[2] = m._44 - m._42; - -/* Bottom plane */ - vec[3].u1.x = m._14 + m._12; - vec[3].u2.y = m._24 + m._22; - vec[3].u3.z = m._34 + m._32; - origin_plane[3] = m._44 + m._42; - -/* Front plane */ - vec[4].u1.x = m._13; - vec[4].u2.y = m._23; - vec[4].u3.z = m._33; - origin_plane[4] = m._43; - -/* Back plane*/ - vec[5].u1.x = m._14 - m._13; - vec[5].u2.y = m._24 - m._23; - vec[5].u3.z = m._34 - m._33; - origin_plane[5] = m._44 - m._43; +static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality, + D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values) +{ + UINT i, j; for (i = 0; i < sphere_count; ++i) { return_values[i] = 0; - for (j = 0; j < 6; ++j) - return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]); + for (j = 0; j < 12; ++j) + if (enabled_planes & 1u << j) + return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality); } +} +static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface, + D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) +{ + struct wined3d_vec4 plane[12]; + DWORD enabled_planes = 0x3f; + DWORD user_clip_planes; + UINT j; + + TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n", + iface, centers, radii, sphere_count, flags, return_values); + + prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane); + + IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes); + enabled_planes |= user_clip_planes << 6; + for (j = 6; j < 12; ++j) + IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]); + + compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values); return D3D_OK; } static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface, D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) { - struct d3d_device *device = impl_from_IDirect3DDevice3(iface); + static const DWORD enabled_planes = 0x3f; + struct wined3d_vec4 plane[6]; + unsigned int i, j; TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n", iface, centers, radii, sphere_count, flags, return_values); - return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface, - centers, radii, sphere_count, flags, return_values); + prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane); + + compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values); + for (i = 0; i < sphere_count; ++i) + { + BOOL intersect_frustum = FALSE, outside_frustum = FALSE; + DWORD d3d7_result = return_values[i]; + + return_values[i] = 0; + + for (j = 0; j < 6; ++j) + { + DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT); + + if (clip == D3DSTATUS_CLIPUNIONLEFT) + { + return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2; + intersect_frustum = TRUE; + } + else if (clip) + { + return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2; + outside_frustum = TRUE; + } + } + if (outside_frustum) + return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM; + else if (intersect_frustum) + return_values[i] |= D3DVIS_INTERSECT_FRUSTUM; + } + return D3D_OK; } /***************************************************************************** diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/surface.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/surface.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/surface.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/surface.c 2017-03-21 14:02:57.000000000 +0000 @@ -950,7 +950,6 @@ * Returns: * DD_OK on success * DDERR_INVALIDPARAMS if DDSD is NULL - * For more details, see IWineD3DSurface::LockRect * *****************************************************************************/ static HRESULT surface_lock(struct ddraw_surface *surface, @@ -1005,10 +1004,10 @@ switch(hr) { /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more - * specific error. But since IWineD3DSurface::LockRect returns that error in this - * only occasion, keep d3d8 and d3d9 free from the return value override. There are - * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it - * is much easier to do it in one place in ddraw + * specific error. But since wined3d returns that error in this only occasion, + * keep d3d8 and d3d9 free from the return value override. There are many different + * places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it is much easier + * to do it in one place in ddraw. */ case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY; default: return hr; @@ -1170,8 +1169,7 @@ * Rect: Not used by this implementation * * Returns: - * D3D_OK on success - * For more details, see IWineD3DSurface::UnlockRect + * D3D_OK on success, error code otherwise. * *****************************************************************************/ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect) @@ -1537,8 +1535,7 @@ * DDBltFx: Some extended blt parameters, connected to the flags * * Returns: - * D3D_OK on success - * See IWineD3DSurface::Blt for more details + * D3D_OK on success, error code otherwise. * *****************************************************************************/ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *dst_rect, @@ -1657,6 +1654,12 @@ if (flags & DDBLT_KEYSRC && (!src_impl || !(src_impl->surface_desc.dwFlags & DDSD_CKSRCBLT))) { + WARN("DDBLT_KEYSRC blit without color key in surface, returning DDERR_INVALIDPARAMS\n"); + wined3d_mutex_unlock(); + return DDERR_INVALIDPARAMS; + } + if (flags & DDBLT_KEYDEST && !(dst_impl->surface_desc.dwFlags & DDSD_CKDESTBLT)) + { WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n"); wined3d_mutex_unlock(); return DDERR_INVALIDPARAMS; @@ -2141,7 +2144,6 @@ * Returns: * DD_OK on success * DDERR_INVALIDPARAMS if hdc is NULL - * For details, see IWineD3DSurface::GetDC * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc) @@ -2241,8 +2243,7 @@ * hdc: HDC to release * * Returns: - * DD_OK on success - * For more details, see IWineD3DSurface::ReleaseDC + * DD_OK on success, error code otherwise. * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc) @@ -2458,8 +2459,7 @@ * Flags: Some flags * * Returns: - * D3D_OK on success - * For more details, see IWineD3DSurface::SetPrivateData + * D3D_OK on success, error code otherwise. * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface, @@ -2507,7 +2507,6 @@ * Returns: * DD_OK on success * DDERR_INVALIDPARAMS if Data is NULL - * For more details, see IWineD3DSurface::GetPrivateData * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size) @@ -2571,8 +2570,7 @@ * tag: Tag of the data to free * * Returns: - * D3D_OK on success - * For more details, see IWineD3DSurface::FreePrivateData + * D3D_OK on success, error code otherwise. * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag) @@ -3004,9 +3002,6 @@ * Params: * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE * - * Returns: - * See IWineD3DSurface::Blt - * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags) { @@ -3176,9 +3171,6 @@ * Params: * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE * - * Returns: - * See IWineD3DSurface::GetFlipStatus - * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags) { @@ -3554,7 +3546,6 @@ * Returns: * DD_OK, if the surface is usable * DDERR_ISLOST if the surface is lost - * See IWineD3DSurface::IsLost for more details * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface) @@ -3612,8 +3603,7 @@ * doesn't reload its old contents * * Returns: - * DD_OK on success - * See IWineD3DSurface::Restore for more details + * DD_OK on success, error code otherwise. * *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface) @@ -4187,8 +4177,7 @@ * trans: Type of transfer. Some DDBLTFAST_* flags * * Returns: - * DD_OK on success - * For more details, see IWineD3DSurface::BltFast + * DD_OK on success, error code otherwise. * *****************************************************************************/ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, @@ -5063,8 +5052,7 @@ /***************************************************************************** * IDirect3DTexture2::GetHandle * - * Returns handle for the texture. At the moment, the interface - * to the IWineD3DTexture is used. + * Returns handle for the texture. * * Params: * device: Device this handle is assigned to diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/d3d.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/d3d.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/d3d.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/d3d.c 2017-03-21 14:02:57.000000000 +0000 @@ -1126,7 +1126,7 @@ /* Interface consistency check. */ hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt); ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr); - ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1); + ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer mismatch: %p != %p\n", Direct3D_alt, Direct3D1); IDirect3D_Release(Direct3D_alt); memset(&desc, 0, sizeof(desc)); @@ -2526,194 +2526,6 @@ ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc); } -static void ComputeSphereVisibility(void) -{ - D3DMATRIX proj = - { - 1.810660f, 0.000000f, 0.000000f, 0.000000f, - 0.000000f, 2.414213f, 0.000000f, 0.000000f, - 0.000000f, 0.000000f, 1.020408f, 1.000000f, - 0.000000f, 0.000000f, -0.102041f, 0.000000f, - }; - D3DMATRIX view = - { - 1.000000f, 0.000000f, 0.000000f, 0.000000f, - 0.000000f, 0.768221f, -0.640185f, 0.000000f, - -0.000000f, 0.640185f, 0.768221f, 0.000000f, - -14.852037f, 9.857489f, 11.600972f, 1.000000f, - }; - D3DMATRIX world = - { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, - }; - D3DVALUE radius[3]; - D3DVECTOR center[3]; - DWORD result[3]; - HRESULT rc; - - IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world); - IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view); - IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj); - - U1(center[0]).x=11.461533; - U2(center[0]).y=-4.761727; - U3(center[0]).z=-1.171646; - - radius[0]=38.252632; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]); - - U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638; - radius[0]=4.354097; - U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312; - radius[1]=12.500704; - U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010; - radius[2]=17.251318; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]); - ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]); - ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]); - - view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0; - view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0; - view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0; - view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0; - - proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0; - proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0; - proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0; - proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0; - - U1(center[0]).x=0.0; - U2(center[0]).y=0.0; - U3(center[0]).z=0.05; - - radius[0]=0.04; - - IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view); - IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj); - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]); - - proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0; - proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0; - proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0; - proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0; - - IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj); - - U1(center[0]).x=0.0; - U2(center[0]).y=0.0; - U3(center[0]).z=0.5; - - radius[0]=0.5; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]); - - U1(center[0]).x=0.0; - U2(center[0]).y=0.0; - U3(center[0]).z=0.0; - - radius[0]=0.0; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]); - - U1(center[0]).x=-1.0; - U2(center[0]).y=-1.0; - U3(center[0]).z=0.50; - - radius[0]=0.25; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]); - - U1(center[0]).x=-20.0; - U2(center[0]).y=0.0; - U3(center[0]).z=0.50; - - radius[0]=3.0; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]); - - U1(center[0]).x=20.0; - U2(center[0]).y=0.0; - U3(center[0]).z=0.50; - - radius[0]=3.0f; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]); - - U1(center[0]).x=0.0; - U2(center[0]).y=-20.0; - U3(center[0]).z=0.50; - - radius[0]=3.0; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]); - - U1(center[0]).x=0.0; - U2(center[0]).y=20.0; - U3(center[0]).z=0.5; - - radius[0]=3.0; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]); - - U1(center[0]).x=0.0; - U2(center[0]).y=0.0; - U3(center[0]).z=-20; - - radius[0]=3.0; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]); - - U1(center[0]).x=0.0; - U2(center[0]).y=0.0; - U3(center[0]).z=20.0; - - radius[0]=3.0; - - rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result); - - ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc); - ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]); -} - static void SetRenderTargetTest(void) { HRESULT hr; @@ -3667,7 +3479,6 @@ D3D7EnumTest(); D3D7EnumLifetimeTest(); SetMaterialTest(); - ComputeSphereVisibility(); CapsTest(); VertexBufferDescTest(); D3D7_OldRenderStateTest(); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw1.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw1.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw1.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw1.c 2017-03-21 14:02:57.000000000 +0000 @@ -10202,6 +10202,487 @@ DestroyWindow(window); } +static void test_ck_operation(void) +{ + IDirectDrawSurface *src, *dst; + IDirectDrawSurface7 *src7, *dst7; + DDSURFACEDESC surface_desc; + IDirectDraw *ddraw; + ULONG refcount; + HWND window; + HRESULT hr; + D3DCOLOR *color; + unsigned int i; + DDCOLORKEY ckey; + DDBLTFX fx; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 4; + surface_desc.dwHeight = 1; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32; + U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000; + U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00; + U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff; + hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + surface_desc.dwFlags |= DDSD_CKSRCBLT; + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff; + hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n"); + color = surface_desc.lpSurface; + color[0] = 0x77010203; + color[1] = 0x00010203; + color[2] = 0x77ff00ff; + color[3] = 0x00ff00ff; + hr = IDirectDrawSurface_Unlock(src, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + for (i = 0; i < 2; ++i) + { + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = 0xcccccccc; + color[1] = 0xcccccccc; + color[2] = 0xcccccccc; + color[3] = 0xcccccccc; + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + if (i) + { + hr = IDirectDrawSurface_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + } + else + { + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + } + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n"); + color = surface_desc.lpSurface; + /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when + * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for + * color keying, but do not copy it into the destination surface. Nvidia neither uses it for + * color keying nor copies it. */ + ok((color[0] == 0x77010203 && color[1] == 0x00010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */ + || broken(color[0] == 0x00010203 && color[1] == 0x00010203 + && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */ + || broken(color[0] == 0x00010203 && color[1] == 0x00010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */ + || broken(color[0] == 0xff010203 && color[1] == 0xff010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */, + "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n", + color[0], color[1], color[2], color[3], i); + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00; + hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface_GetSurfaceDesc(src, &surface_desc); + ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00 + && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00, + "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue, + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue); + + /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */ + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x00000000; + hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x00000001; + hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = 0x000000fe; + ckey.dwColorSpaceHighValue = 0x000000fd; + hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + IDirectDrawSurface_Release(src); + IDirectDrawSurface_Release(dst); + + /* Test source and destination keys and where they are read from. Use a surface with alpha + * to avoid driver-dependent content in the X channel. */ + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 6; + surface_desc.dwHeight = 1; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; + U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32; + U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000; + U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00; + U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff; + U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = 0x0000ff00; + ckey.dwColorSpaceHighValue = 0x0000ff00; + hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + ckey.dwColorSpaceLowValue = 0x00ff0000; + ckey.dwColorSpaceHighValue = 0x00ff0000; + hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_DESTBLT, &ckey); + ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr); + if (FAILED(hr)) + { + /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */ + skip("Failed to set destination color key, skipping related tests.\n"); + goto done; + } + + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x000000ff; + hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + ckey.dwColorSpaceLowValue = 0x000000aa; + ckey.dwColorSpaceHighValue = 0x000000aa; + hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_DESTBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000; + fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000; + fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100; + fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100; + + hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = 0x000000ff; /* Applies to src blt key in src surface. */ + color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */ + color[2] = 0x00ff0000; /* Dst color key in dst surface. */ + color[3] = 0x0000ff00; /* Src color key in dst surface. */ + color[4] = 0x00001100; /* Src color key in ddbltfx. */ + color[5] = 0x00110000; /* Dst color key in ddbltfx. */ + hr = IDirectDrawSurface_Unlock(src, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Test a blit without keying. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, 0, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Should have copied src data unmodified to dst. */ + ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src key. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Src key applied to color[0]. It is unmodified, the others are copied. */ + ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src override. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Override key applied to color[5]. It is unmodified, the others are copied. */ + ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src override AND src key. That is not supposed to work. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Ensure the destination was not changed. */ + ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 && + color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + /* Use different dst colors for the dst key test. */ + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[4,5], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* What happens with a QI'd newer version of the interface? It takes the key + * from the destination surface. */ + hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirectDrawSurface7, (void **)&src7); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr); + hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirectDrawSurface7, (void **)&dst7); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Blt(dst7, NULL, src7, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + IDirectDrawSurface7_Release(dst7); + IDirectDrawSurface7_Release(src7); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[0,1], they are the only changed pixels. */ + todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest override key blit. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[2,3], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest override together with surface key. Supposed to fail. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Destination is unchanged. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Source and destination key. This is driver dependent. New HW treats it like + * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */ + if (0) + { + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if + * the driver applies it. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + /* Override keys without ddbltfx parameter fail */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + /* Try blitting without keys in the source surface. */ + hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_DESTBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + /* That fails now. Do not bother to check that the data is unmodified. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + /* Surprisingly this still works. It uses the old key from the src surface. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[4,5], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + hr = IDirectDrawSurface_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* This returns DDERR_NOCOLORKEY as expected. */ + hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_DESTBLT, &ckey); + ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr); + + /* GetSurfaceDesc returns a zeroed key as expected. */ + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x12345678; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x12345678; + hr = IDirectDrawSurface_GetSurfaceDesc(src, &surface_desc); + ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(!surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue + && !surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue, + "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue, + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue); + + /* Try blitting without keys in the destination surface. */ + hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_DESTBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + /* This is weird. It makes sense in v4 and v7, but because v1 + * uses the key from the src surface it makes no sense here. */ + hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + +done: + IDirectDrawSurface_Release(src); + IDirectDrawSurface_Release(dst); + refcount = IDirectDraw_Release(ddraw); + ok(!refcount, "DirectDraw has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw1) { IDirectDraw *ddraw; @@ -10288,4 +10769,5 @@ test_display_mode_surface_pixel_format(); test_surface_desc_size(); test_texture_load(); + test_ck_operation(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw2.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw2.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw2.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw2.c 2017-03-21 14:02:57.000000000 +0000 @@ -11526,6 +11526,501 @@ ok(!refcount, "DirectDraw has %u references left.\n", refcount); } +static void test_ck_operation(void) +{ + IDirectDrawSurface2 *src, *dst; + IDirectDrawSurface7 *src7, *dst7; + IDirectDrawSurface *surface1; + DDSURFACEDESC surface_desc; + IDirectDraw2 *ddraw; + ULONG refcount; + HWND window; + HRESULT hr; + D3DCOLOR *color; + unsigned int i; + DDCOLORKEY ckey; + DDBLTFX fx; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 4; + surface_desc.dwHeight = 1; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32; + U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000; + U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00; + U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff; + hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&dst); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr); + IDirectDrawSurface_Release(surface1); + + surface_desc.dwFlags |= DDSD_CKSRCBLT; + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff; + hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&src); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr); + IDirectDrawSurface_Release(surface1); + + hr = IDirectDrawSurface2_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n"); + color = surface_desc.lpSurface; + color[0] = 0x77010203; + color[1] = 0x00010203; + color[2] = 0x77ff00ff; + color[3] = 0x00ff00ff; + hr = IDirectDrawSurface2_Unlock(src, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + for (i = 0; i < 2; ++i) + { + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = 0xcccccccc; + color[1] = 0xcccccccc; + color[2] = 0xcccccccc; + color[3] = 0xcccccccc; + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + if (i) + { + hr = IDirectDrawSurface2_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + } + else + { + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + } + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n"); + color = surface_desc.lpSurface; + /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when + * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for + * color keying, but do not copy it into the destination surface. Nvidia neither uses it for + * color keying nor copies it. */ + ok((color[0] == 0x77010203 && color[1] == 0x00010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */ + || broken(color[0] == 0x00010203 && color[1] == 0x00010203 + && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */ + || broken(color[0] == 0x00010203 && color[1] == 0x00010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */ + || broken(color[0] == 0xff010203 && color[1] == 0xff010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */, + "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n", + color[0], color[1], color[2], color[3], i); + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00; + hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface2_GetSurfaceDesc(src, &surface_desc); + ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00 + && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00, + "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue, + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue); + + /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */ + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x00000000; + hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x00000001; + hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = 0x000000fe; + ckey.dwColorSpaceHighValue = 0x000000fd; + hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + IDirectDrawSurface2_Release(src); + IDirectDrawSurface2_Release(dst); + + /* Test source and destination keys and where they are read from. Use a surface with alpha + * to avoid driver-dependent content in the X channel. */ + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 6; + surface_desc.dwHeight = 1; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; + U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32; + U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000; + U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00; + U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff; + U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000; + hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&dst); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr); + IDirectDrawSurface_Release(surface1); + + hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&src); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr); + IDirectDrawSurface_Release(surface1); + + ckey.dwColorSpaceLowValue = 0x0000ff00; + ckey.dwColorSpaceHighValue = 0x0000ff00; + hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + ckey.dwColorSpaceLowValue = 0x00ff0000; + ckey.dwColorSpaceHighValue = 0x00ff0000; + hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_DESTBLT, &ckey); + ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr); + if (FAILED(hr)) + { + /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */ + skip("Failed to set destination color key, skipping related tests.\n"); + goto done; + } + + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x000000ff; + hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + ckey.dwColorSpaceLowValue = 0x000000aa; + ckey.dwColorSpaceHighValue = 0x000000aa; + hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_DESTBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000; + fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000; + fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100; + fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100; + + hr = IDirectDrawSurface2_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = 0x000000ff; /* Applies to src blt key in src surface. */ + color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */ + color[2] = 0x00ff0000; /* Dst color key in dst surface. */ + color[3] = 0x0000ff00; /* Src color key in dst surface. */ + color[4] = 0x00001100; /* Src color key in ddbltfx. */ + color[5] = 0x00110000; /* Dst color key in ddbltfx. */ + hr = IDirectDrawSurface2_Unlock(src, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Test a blit without keying. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, 0, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Should have copied src data unmodified to dst. */ + ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src key. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Src key applied to color[0]. It is unmodified, the others are copied. */ + ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src override. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Override key applied to color[5]. It is unmodified, the others are copied. */ + ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src override AND src key. That is not supposed to work. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Ensure the destination was not changed. */ + ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 && + color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + /* Use different dst colors for the dst key test. */ + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest key blit. The key is taken from the SOURCE surface in v2! */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[4,5], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* What happens with a QI'd newer version of the interface? It takes the key + * from the destination surface. */ + hr = IDirectDrawSurface2_QueryInterface(src, &IID_IDirectDrawSurface7, (void **)&src7); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr); + hr = IDirectDrawSurface2_QueryInterface(dst, &IID_IDirectDrawSurface7, (void **)&dst7); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Blt(dst7, NULL, src7, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + IDirectDrawSurface7_Release(dst7); + IDirectDrawSurface7_Release(src7); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[0,1], they are the only changed pixels. */ + todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest override key blit. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[2,3], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest override together with surface key. Supposed to fail. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Destination is unchanged. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Source and destination key. This is driver dependent. New HW treats it like + * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */ + if (0) + { + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if + * the driver applies it. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + /* Override keys without ddbltfx parameter fail */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + /* Try blitting without keys in the source surface. */ + hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_DESTBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + /* That fails now. Do not bother to check that the data is unmodified. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + /* Surprisingly this still works. It uses the old key from the src surface. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[4,5], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + hr = IDirectDrawSurface2_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* This returns DDERR_NOCOLORKEY as expected. */ + hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_DESTBLT, &ckey); + ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr); + + /* GetSurfaceDesc returns a zeroed key as expected. */ + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x12345678; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x12345678; + hr = IDirectDrawSurface2_GetSurfaceDesc(src, &surface_desc); + ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(!surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue + && !surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue, + "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue, + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue); + + /* Try blitting without keys in the destination surface. */ + hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_SRCBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_DESTBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + /* This fails, as sanity would dictate. */ + hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + +done: + IDirectDrawSurface2_Release(src); + IDirectDrawSurface2_Release(dst); + refcount = IDirectDraw2_Release(ddraw); + ok(!refcount, "DirectDraw has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw2) { IDirectDraw2 *ddraw; @@ -11620,4 +12115,5 @@ test_transform_vertices(); test_display_mode_surface_pixel_format(); test_surface_desc_size(); + test_ck_operation(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw4.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw4.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw4.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw4.c 2017-03-21 14:02:57.000000000 +0000 @@ -12919,6 +12919,638 @@ DestroyWindow(window); } +static void test_ck_operation(void) +{ + IDirectDrawSurface4 *src, *dst; + IDirectDrawSurface *src1, *dst1; + DDSURFACEDESC2 surface_desc; + IDirectDraw4 *ddraw; + ULONG refcount; + HWND window; + HRESULT hr; + D3DCOLOR *color; + unsigned int i; + DDCOLORKEY ckey; + DDBLTFX fx; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 4; + surface_desc.dwHeight = 1; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32; + U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000; + U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00; + U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff; + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + surface_desc.dwFlags |= DDSD_CKSRCBLT; + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff; + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n"); + color = surface_desc.lpSurface; + color[0] = 0x77010203; + color[1] = 0x00010203; + color[2] = 0x77ff00ff; + color[3] = 0x00ff00ff; + hr = IDirectDrawSurface4_Unlock(src, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + for (i = 0; i < 2; ++i) + { + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = 0xcccccccc; + color[1] = 0xcccccccc; + color[2] = 0xcccccccc; + color[3] = 0xcccccccc; + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + if (i) + { + hr = IDirectDrawSurface4_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + } + else + { + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + } + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n"); + color = surface_desc.lpSurface; + /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when + * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for + * color keying, but do not copy it into the destination surface. Nvidia neither uses it for + * color keying nor copies it. */ + ok((color[0] == 0x77010203 && color[1] == 0x00010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */ + || broken(color[0] == 0x00010203 && color[1] == 0x00010203 + && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */ + || broken(color[0] == 0x00010203 && color[1] == 0x00010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */ + || broken(color[0] == 0xff010203 && color[1] == 0xff010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */, + "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n", + color[0], color[1], color[2], color[3], i); + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00; + hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface4_GetSurfaceDesc(src, &surface_desc); + ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00 + && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00, + "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue, + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue); + + /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */ + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x00000000; + hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x00000001; + hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = 0x000000fe; + ckey.dwColorSpaceHighValue = 0x000000fd; + hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + IDirectDrawSurface4_Release(src); + IDirectDrawSurface4_Release(dst); + + /* Test source and destination keys and where they are read from. Use a surface with alpha + * to avoid driver-dependent content in the X channel. */ + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 6; + surface_desc.dwHeight = 1; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; + U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32; + U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000; + U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00; + U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff; + U5(U4(surface_desc.ddpfPixelFormat)).dwRGBAlphaBitMask = 0xff000000; + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = 0x0000ff00; + ckey.dwColorSpaceHighValue = 0x0000ff00; + hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + ckey.dwColorSpaceLowValue = 0x00ff0000; + ckey.dwColorSpaceHighValue = 0x00ff0000; + hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, &ckey); + ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr); + if (FAILED(hr)) + { + /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */ + skip("Failed to set destination color key, skipping related tests.\n"); + goto done; + } + + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x000000ff; + hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + ckey.dwColorSpaceLowValue = 0x000000aa; + ckey.dwColorSpaceHighValue = 0x000000aa; + hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000; + fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000; + fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100; + fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100; + + hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = 0x000000ff; /* Applies to src blt key in src surface. */ + color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */ + color[2] = 0x00ff0000; /* Dst color key in dst surface. */ + color[3] = 0x0000ff00; /* Src color key in dst surface. */ + color[4] = 0x00001100; /* Src color key in ddbltfx. */ + color[5] = 0x00110000; /* Dst color key in ddbltfx. */ + hr = IDirectDrawSurface4_Unlock(src, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Test a blit without keying. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, 0, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Should have copied src data unmodified to dst. */ + ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src key. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Src key applied to color[0]. It is unmodified, the others are copied. */ + ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src override. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Override key applied to color[5]. It is unmodified, the others are copied. */ + ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src override AND src key. That is not supposed to work. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Ensure the destination was not changed. */ + ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 && + color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + /* Use different dst colors for the dst key test. */ + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest key blit. The key is taken from the DESTINATION surface in v4! */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[0,1], they are the only changed pixels. */ + todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* What happens with a QI'd older version of the interface? It takes the key + * from the source surface. */ + hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr); + hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + IDirectDrawSurface_Release(dst1); + IDirectDrawSurface_Release(src1); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[4,5], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest override key blit. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[2,3], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest override together with surface key. Supposed to fail. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Destination is unchanged. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Source and destination key. This is driver dependent. New HW treats it like + * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */ + if (0) + { + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if + * the driver applies it. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + /* Override keys without ddbltfx parameter fail */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + /* Try blitting without keys in the source surface. */ + hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + /* That fails now. Do not bother to check that the data is unmodified. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + /* Dest key blit still works, the destination surface key is used in v4. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[0,1], they are the only changed pixels. */ + todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + hr = IDirectDrawSurface4_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Try blitting without keys in the destination surface. */ + hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + /* This fails, as sanity would dictate. */ + hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + +done: + IDirectDrawSurface4_Release(src); + IDirectDrawSurface4_Release(dst); + refcount = IDirectDraw4_Release(ddraw); + ok(!refcount, "DirectDraw has %u references left.\n", refcount); + DestroyWindow(window); +} + +static void test_vb_refcount(void) +{ + ULONG prev_d3d_refcount, prev_device_refcount; + ULONG cur_d3d_refcount, cur_device_refcount; + IDirect3DVertexBuffer *vb, *vb1; + IDirect3DVertexBuffer7 *vb7; + D3DVERTEXBUFFERDESC vb_desc; + IDirect3DDevice3 *device; + IDirect3D3 *d3d; + ULONG refcount; + IUnknown *unk; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "d3d3_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice3_GetDirect3D(device, &d3d); + ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr); + + prev_d3d_refcount = get_refcount((IUnknown *)d3d); + prev_device_refcount = get_refcount((IUnknown *)device); + + memset(&vb_desc, 0, sizeof(vb_desc)); + vb_desc.dwSize = sizeof(vb_desc); + vb_desc.dwFVF = D3DFVF_XYZ; + vb_desc.dwNumVertices = 4; + hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL); + ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr); + + cur_d3d_refcount = get_refcount((IUnknown *)d3d); + cur_device_refcount = get_refcount((IUnknown *)device); + ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n", + prev_d3d_refcount, cur_d3d_refcount); + ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n", + prev_device_refcount, cur_device_refcount); + + hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1); + ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer, hr %#x.\n", hr); + IDirect3DVertexBuffer_Release(vb1); + + hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7); + ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer7 returned unexpected hr %#x.\n", hr); + + hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk); + ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr); + ok((IUnknown *)vb == unk, + "IDirect3DVertexBuffer and IUnknown interface pointers don't match, %p != %p.\n", vb, unk); + IUnknown_Release(unk); + + refcount = IDirect3DVertexBuffer_Release(vb); + ok(!refcount, "Vertex buffer has %u references left.\n", refcount); + IDirect3D3_Release(d3d); + refcount = IDirect3DDevice3_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + +static void test_compute_sphere_visibility(void) +{ + static D3DMATRIX proj_1 = + { + 1.810660f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 2.414213f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.020408f, 1.000000f, + 0.000000f, 0.000000f, -0.102041f, 0.000000f, + }; + static D3DMATRIX proj_2 = + { + 10.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 10.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 10.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }; + static D3DMATRIX view_1 = + { + 1.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.768221f, -0.640185f, 0.000000f, + -0.000000f, 0.640185f, 0.768221f, 0.000000f, + -14.852037f, 9.857489f, 11.600972f, 1.000000f, + }; + static D3DMATRIX identity = + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }; + static struct + { + D3DMATRIX *view, *proj; + unsigned int sphere_count; + D3DVECTOR center[3]; + D3DVALUE radius[3]; + const DWORD expected[3]; + BOOL todo; + } + tests[] = + { + {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, {0x1555}}, + {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}}, + {{14.290396f}, {-2.981143f}, {-24.311312f}}, + {{1.461626f}, {-6.093709f}, {-13.901010f}}}, + {4.354097f, 12.500704f, 17.251318f}, {0x154a, 0x1555, 0x1555}}, + {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, {0x1555}, TRUE}, + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, {0x1401}}, + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, {0x401}}, + {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, {0x1505}, TRUE}, /* 5 */ + {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x154a}}, + {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x1562}}, + {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, {0x1616}}, + {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, {0x1496}}, + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, {0x956}}, /* 10 */ + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, {0x2156}}, + }; + IDirect3DViewport3 *viewport; + IDirect3DDevice3 *device; + unsigned int i, j; + DWORD result[3]; + ULONG refcount; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "d3d_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + viewport = create_viewport(device, 0, 0, 640, 480); + hr = IDirect3DDevice3_SetCurrentViewport(device, viewport); + ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr); + + IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) + { + IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view); + IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj); + + hr = IDirect3DDevice3_ComputeSphereVisibility(device, tests[i].center, tests[i].radius, + tests[i].sphere_count, 0, result); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + for (j = 0; j < tests[i].sphere_count; ++j) + todo_wine_if(tests[i].todo) + ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n", + i, j, tests[i].expected[j], result[j]); + } + + destroy_viewport(device, viewport); + refcount = IDirect3DDevice3_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw4) { IDirectDraw4 *ddraw; @@ -13022,4 +13654,7 @@ test_display_mode_surface_pixel_format(); test_surface_desc_size(); test_get_surface_from_dc(); + test_ck_operation(); + test_vb_refcount(); + test_compute_sphere_visibility(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw7.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw7.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw7.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/ddraw7.c 2017-03-21 14:02:57.000000000 +0000 @@ -12592,6 +12592,647 @@ DestroyWindow(window); } +static void test_ck_operation(void) +{ + IDirectDrawSurface7 *src, *dst; + IDirectDrawSurface *src1, *dst1; + DDSURFACEDESC2 surface_desc; + IDirectDraw7 *ddraw; + ULONG refcount; + HWND window; + HRESULT hr; + D3DCOLOR *color; + unsigned int i; + DDCOLORKEY ckey; + DDBLTFX fx; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 4; + surface_desc.dwHeight = 1; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32; + U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000; + U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00; + U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + surface_desc.dwFlags |= DDSD_CKSRCBLT; + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n"); + color = surface_desc.lpSurface; + color[0] = 0x77010203; + color[1] = 0x00010203; + color[2] = 0x77ff00ff; + color[3] = 0x00ff00ff; + hr = IDirectDrawSurface7_Unlock(src, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + for (i = 0; i < 2; ++i) + { + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = 0xcccccccc; + color[1] = 0xcccccccc; + color[2] = 0xcccccccc; + color[3] = 0xcccccccc; + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + if (i) + { + hr = IDirectDrawSurface7_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + } + else + { + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + } + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n"); + color = surface_desc.lpSurface; + /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when + * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for + * color keying, but do not copy it into the destination surface. Nvidia neither uses it for + * color keying nor copies it. */ + ok((color[0] == 0x77010203 && color[1] == 0x00010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */ + || broken(color[0] == 0x00010203 && color[1] == 0x00010203 + && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */ + || broken(color[0] == 0x00010203 && color[1] == 0x00010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */ + || broken(color[0] == 0xff010203 && color[1] == 0xff010203 + && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */, + "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n", + color[0], color[1], color[2], color[3], i); + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00; + hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0; + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface7_GetSurfaceDesc(src, &surface_desc); + ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr); + ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00 + && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00, + "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue, + surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue); + + /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */ + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x00000000; + hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x00000001; + hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + ckey.dwColorSpaceLowValue = 0x000000fe; + ckey.dwColorSpaceHighValue = 0x000000fd; + hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0; + hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr); + ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe, + "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue); + + IDirectDrawSurface7_Release(src); + IDirectDrawSurface7_Release(dst); + + /* Test source and destination keys and where they are read from. Use a surface with alpha + * to avoid driver-dependent content in the X channel. */ + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 6; + surface_desc.dwHeight = 1; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; + U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32; + U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000; + U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00; + U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff; + U5(U4(surface_desc.ddpfPixelFormat)).dwRGBAlphaBitMask = 0xff000000; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + ckey.dwColorSpaceLowValue = 0x0000ff00; + ckey.dwColorSpaceHighValue = 0x0000ff00; + hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + ckey.dwColorSpaceLowValue = 0x00ff0000; + ckey.dwColorSpaceHighValue = 0x00ff0000; + hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, &ckey); + ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr); + if (FAILED(hr)) + { + /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */ + skip("Failed to set destination color key, skipping related tests.\n"); + goto done; + } + + ckey.dwColorSpaceLowValue = 0x000000ff; + ckey.dwColorSpaceHighValue = 0x000000ff; + hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + ckey.dwColorSpaceLowValue = 0x000000aa; + ckey.dwColorSpaceHighValue = 0x000000aa; + hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, &ckey); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000; + fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000; + fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100; + fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100; + + hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = 0x000000ff; /* Applies to src blt key in src surface. */ + color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */ + color[2] = 0x00ff0000; /* Dst color key in dst surface. */ + color[3] = 0x0000ff00; /* Src color key in dst surface. */ + color[4] = 0x00001100; /* Src color key in ddbltfx. */ + color[5] = 0x00110000; /* Dst color key in ddbltfx. */ + hr = IDirectDrawSurface7_Unlock(src, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Test a blit without keying. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, 0, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Should have copied src data unmodified to dst. */ + ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src key. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Src key applied to color[0]. It is unmodified, the others are copied. */ + ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src override. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Override key applied to color[5]. It is unmodified, the others are copied. */ + ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555; + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Src override AND src key. That is not supposed to work. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Ensure the destination was not changed. */ + ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 && + color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + /* Use different dst colors for the dst key test. */ + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest key blit. The key is taken from the DESTINATION surface in v7! */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[0,1], they are the only changed pixels. */ + todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* What happens with a QI'd older version of the interface? It takes the key + * from the source surface. */ + hr = IDirectDrawSurface7_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr); + hr = IDirectDrawSurface7_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1); + ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + IDirectDrawSurface_Release(dst1); + IDirectDrawSurface_Release(src1); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[4,5], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest override key blit. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[2,3], they are the only changed pixels. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Dest override together with surface key. Supposed to fail. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Destination is unchanged. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Source and destination key. This is driver dependent. New HW treats it like + * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */ + if (0) + { + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if + * the driver applies it. */ + ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 && + color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + + color[0] = 0x00ff0000; /* Dest key in dst surface. */ + color[1] = 0x00ff0000; /* Dest key in dst surface. */ + color[2] = 0x00001100; /* Dest key in override. */ + color[3] = 0x00001100; /* Dest key in override. */ + color[4] = 0x000000aa; /* Dest key in src surface. */ + color[5] = 0x000000aa; /* Dest key in src surface. */ + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + /* Override keys without ddbltfx parameter fail */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + /* Try blitting without keys in the source surface. */ + hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + /* That fails now. Do not bother to check that the data is unmodified. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + + /* Dest key blit still works, the destination surface key is used in v7. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + color = surface_desc.lpSurface; + /* Dst key applied to color[0,1], they are the only changed pixels. */ + todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 && + color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa, + "Got unexpected content %08x %08x %08x %08x %08x %08x.\n", + color[0], color[1], color[2], color[3], color[4], color[5]); + hr = IDirectDrawSurface7_Unlock(dst, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Try blitting without keys in the destination surface. */ + hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, NULL); + ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr); + + /* This fails, as sanity would dictate. */ + hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx); + ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr); + +done: + IDirectDrawSurface7_Release(src); + IDirectDrawSurface7_Release(dst); + refcount = IDirectDraw7_Release(ddraw); + ok(!refcount, "DirectDraw has %u references left.\n", refcount); + DestroyWindow(window); +} + +static void test_vb_refcount(void) +{ + ULONG prev_d3d_refcount, prev_device_refcount; + ULONG cur_d3d_refcount, cur_device_refcount; + IDirect3DVertexBuffer7 *vb, *vb7; + D3DVERTEXBUFFERDESC vb_desc; + IDirect3DVertexBuffer *vb1; + IDirect3DDevice7 *device; + IDirect3D7 *d3d; + ULONG refcount; + IUnknown *unk; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice7_GetDirect3D(device, &d3d); + ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr); + + prev_d3d_refcount = get_refcount((IUnknown *)d3d); + prev_device_refcount = get_refcount((IUnknown *)device); + + memset(&vb_desc, 0, sizeof(vb_desc)); + vb_desc.dwSize = sizeof(vb_desc); + vb_desc.dwFVF = D3DFVF_XYZ; + vb_desc.dwNumVertices = 4; + hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0); + ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr); + + cur_d3d_refcount = get_refcount((IUnknown *)d3d); + cur_device_refcount = get_refcount((IUnknown *)device); + ok(cur_d3d_refcount > prev_d3d_refcount, "D3D object refcount didn't change from %u.\n", prev_d3d_refcount); + ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n", + prev_device_refcount, cur_device_refcount); + + prev_d3d_refcount = cur_d3d_refcount; + hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7); + ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer7, hr %#x.\n", hr); + cur_d3d_refcount = get_refcount((IUnknown *)d3d); + ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n", + prev_d3d_refcount, cur_d3d_refcount); + IDirect3DVertexBuffer7_Release(vb7); + + hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1); + ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer returned unexpected hr %#x.\n", hr); + + hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk); + ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr); + ok((IUnknown *)vb == unk, + "IDirect3DVertexBuffer7 and IUnknown interface pointers don't match, %p != %p.\n", vb, unk); + IUnknown_Release(unk); + + refcount = IDirect3DVertexBuffer7_Release(vb); + ok(!refcount, "Vertex buffer has %u references left.\n", refcount); + + IDirect3D7_Release(d3d); + refcount = IDirect3DDevice7_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + +static void test_compute_sphere_visibility(void) +{ + static D3DVALUE clip_plane[4] = {1.0f, 0.0f, 0.0f, 0.5f}; + static D3DMATRIX proj_1 = + { + 1.810660f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 2.414213f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.020408f, 1.000000f, + 0.000000f, 0.000000f, -0.102041f, 0.000000f, + }; + static D3DMATRIX proj_2 = + { + 10.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 10.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 10.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }; + static D3DMATRIX view_1 = + { + 1.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.768221f, -0.640185f, 0.000000f, + -0.000000f, 0.640185f, 0.768221f, 0.000000f, + -14.852037f, 9.857489f, 11.600972f, 1.000000f, + }; + static D3DMATRIX identity = + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }; + static struct + { + D3DMATRIX *view, *proj; + unsigned int sphere_count; + D3DVECTOR center[3]; + D3DVALUE radius[3]; + DWORD enable_planes; + const DWORD expected[3]; + } + tests[] = + { + {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, 0, {0x3f}}, + {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}}, + {{14.290396f}, {-2.981143f}, {-24.311312f}}, + {{1.461626f}, {-6.093709f}, {-13.901010f}}}, + {4.354097f, 12.500704f, 17.251318f}, 0, {0x103d, 0x3f, 0x3f}}, + {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, 0, {0}}, + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, 0, {0}}, + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, 0, {0}}, + {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, 0, {0x9}}, /* 5 */ + {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x103d}}, + {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x203e}}, + {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, 0, {0x803b}}, + {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, 0, {0x4037}}, + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, 0, {0x1001f}}, /* 10 */ + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, 0, {0x2002f}}, + {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}}, + {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}}, + {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x51}}, + {&identity, &identity, 1, {{{-2.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x41051}}, /* 15 */ + }; + IDirect3DDevice7 *device; + unsigned int i, j; + DWORD result[3]; + ULONG refcount; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "d3d_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice7_SetClipPlane(device, 0, clip_plane); + ok(SUCCEEDED(hr), "Failed to set user clip plane, hr %#x.\n", hr); + + IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) + { + IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view); + IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj); + + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, + tests[i].enable_planes); + ok(SUCCEEDED(hr), "Failed to enable / disable user clip planes, hr %#x.\n", hr); + + hr = IDirect3DDevice7_ComputeSphereVisibility(device, tests[i].center, tests[i].radius, + tests[i].sphere_count, 0, result); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + for (j = 0; j < tests[i].sphere_count; ++j) + ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n", + i, j, tests[i].expected[j], result[j]); + } + + refcount = IDirect3DDevice7_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw7) { HMODULE module = GetModuleHandleA("ddraw.dll"); @@ -12705,4 +13346,7 @@ test_display_mode_surface_pixel_format(); test_surface_desc_size(); test_get_surface_from_dc(); + test_ck_operation(); + test_vb_refcount(); + test_compute_sphere_visibility(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/dsurface.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/dsurface.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/tests/dsurface.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/tests/dsurface.c 2017-03-21 14:02:57.000000000 +0000 @@ -61,515 +61,6 @@ } } -static void SrcColorKey32BlitTest(void) -{ - IDirectDrawSurface *lpSrc; - IDirectDrawSurface *lpDst; - DDSURFACEDESC ddsd, ddsd2; - DDCOLORKEY DDColorKey; - LPDWORD lpData; - HRESULT rc; - DDBLTFX fx; - - ddsd2.dwSize = sizeof(ddsd2); - ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat); - - ddsd.dwSize = sizeof(ddsd); - ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - ddsd.dwWidth = 800; - ddsd.dwHeight = 600; - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32; - U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000; - U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00; - U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF; - rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL); - ok(rc==DD_OK,"CreateSurface returned: %x\n",rc); - if (FAILED(rc)) - { - skip("failed to create surface\n"); - return; - } - - ddsd.dwFlags |= DDSD_CKSRCBLT; - ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0xFF00FF; - ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0xFF00FF; - rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL); - ok(rc==DD_OK,"CreateSurface returned: %x\n",rc); - if (FAILED(rc)) - { - skip("failed to create surface\n"); - return; - } - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - lpData = ddsd2.lpSurface; - lpData[0] = 0xCCCCCCCC; - lpData[1] = 0xCCCCCCCC; - lpData[2] = 0xCCCCCCCC; - lpData[3] = 0xCCCCCCCC; - - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - lpData[0] = 0x77010203; - lpData[1] = 0x00010203; - lpData[2] = 0x77FF00FF; - lpData[3] = 0x00FF00FF; - rc = IDirectDrawSurface_Unlock(lpSrc, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, NULL); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when - * color keying, but copy it to the destination surface. Others apply it for color keying, but - * do not copy it into the destination surface. - */ - if(lpData[0]==0x00010203) { - trace("X channel was not copied into the destination surface\n"); - ok((lpData[0]==0x00010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0x00FF00FF)&&(lpData[3]==0xCCCCCCCC), - "Destination data after blitting is not correct\n"); - } else { - ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC), - "Destination data after blitting is not correct\n"); - } - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Below we repeat the same test as above but now using BltFast instead of Blt. Before - * we can carry out the test we need to restore the color of the destination surface. - */ - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - lpData = ddsd2.lpSurface; - lpData[0] = 0xCCCCCCCC; - lpData[1] = 0xCCCCCCCC; - lpData[2] = 0xCCCCCCCC; - lpData[3] = 0xCCCCCCCC; - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - IDirectDrawSurface_BltFast(lpDst, 0, 0, lpSrc, NULL, DDBLTFAST_SRCCOLORKEY); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when - * color keying, but copy it to the destination surface. Others apply it for color keying, but - * do not copy it into the destination surface. - */ - if(lpData[0]==0x00010203) { - trace("X channel was not copied into the destination surface\n"); - ok((lpData[0]==0x00010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0x00FF00FF)&&(lpData[3]==0xCCCCCCCC), - "Destination data after blitting is not correct\n"); - } else { - ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC), - "Destination data after blitting is not correct\n"); - } - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Also test SetColorKey */ - IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - ok(DDColorKey.dwColorSpaceLowValue == 0xFF00FF && DDColorKey.dwColorSpaceHighValue == 0xFF00FF, - "GetColorKey does not return the colorkey used at surface creation\n"); - - DDColorKey.dwColorSpaceLowValue = 0x00FF00; - DDColorKey.dwColorSpaceHighValue = 0x00FF00; - IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - - DDColorKey.dwColorSpaceLowValue = 0; - DDColorKey.dwColorSpaceHighValue = 0; - IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - ok(DDColorKey.dwColorSpaceLowValue == 0x00FF00 && DDColorKey.dwColorSpaceHighValue == 0x00FF00, - "GetColorKey does not return the colorkey set with SetColorKey\n"); - - ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0; - ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0; - IDirectDrawSurface_GetSurfaceDesc(lpSrc, &ddsd); - ok(ddsd.ddckCKSrcBlt.dwColorSpaceLowValue == 0x00FF00 && ddsd.ddckCKSrcBlt.dwColorSpaceHighValue == 0x00FF00, - "GetSurfaceDesc does not return the colorkey set with SetColorKey\n"); - - /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */ - DDColorKey.dwColorSpaceLowValue = 0x0000FF; - DDColorKey.dwColorSpaceHighValue = 0x000000; - IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - - DDColorKey.dwColorSpaceLowValue = 0; - DDColorKey.dwColorSpaceHighValue = 0; - IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF, - "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue); - - DDColorKey.dwColorSpaceLowValue = 0x0000FF; - DDColorKey.dwColorSpaceHighValue = 0x000001; - IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - - DDColorKey.dwColorSpaceLowValue = 0; - DDColorKey.dwColorSpaceHighValue = 0; - IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF, - "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue); - - DDColorKey.dwColorSpaceLowValue = 0x0000FF; - DDColorKey.dwColorSpaceHighValue = 0x0000FE; - IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - - DDColorKey.dwColorSpaceLowValue = 0; - DDColorKey.dwColorSpaceHighValue = 0; - IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey); - ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF, - "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue); - - IDirectDrawSurface_Release(lpSrc); - IDirectDrawSurface_Release(lpDst); - - /* start with a new set of surfaces to test the color keying parameters to blit */ - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - ddsd.dwWidth = 800; - ddsd.dwHeight = 600; - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32; - U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000; - U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00; - U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF; - ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0xFF0000; - ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0xFF0000; - ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00FF00; - ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00FF00; - rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL); - ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc); - if(FAILED(rc)) - { - skip("Failed to create surface\n"); - return; - } - - /* start with a new set of surfaces to test the color keying parameters to blit */ - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - ddsd.dwWidth = 800; - ddsd.dwHeight = 600; - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32; - U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000; - U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00; - U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF; - ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x0000FF; - ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x0000FF; - ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0x000000; - ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0x000000; - rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL); - ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc); - if(FAILED(rc)) - { - skip("Failed to create surface\n"); - IDirectDrawSurface_Release(lpDst); - return; - } - - memset(&fx, 0, sizeof(fx)); - fx.dwSize = sizeof(fx); - fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x110000; - fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x110000; - fx.ddckDestColorkey.dwColorSpaceHighValue = 0x001100; - fx.ddckDestColorkey.dwColorSpaceLowValue = 0x001100; - - rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - lpData[0] = 0x000000FF; /* Applies to src blt key in src surface */ - lpData[1] = 0x00000000; /* Applies to dst blt key in src surface */ - lpData[2] = 0x00FF0000; /* Dst color key in dst surface */ - lpData[3] = 0x0000FF00; /* Src color key in dst surface */ - lpData[4] = 0x00001100; /* Src color key in ddbltfx */ - lpData[5] = 0x00110000; /* Dst color key in ddbltfx */ - rc = IDirectDrawSurface_Unlock(lpSrc, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - lpData[0] = 0x55555555; - lpData[1] = 0x55555555; - lpData[2] = 0x55555555; - lpData[3] = 0x55555555; - lpData[4] = 0x55555555; - lpData[5] = 0x55555555; - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Test a blit without keying */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, 0, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - /* Should have copied src data unmodified to dst */ - ok(lpData[0] == 0x000000FF && - lpData[1] == 0x00000000 && - lpData[2] == 0x00FF0000 && - lpData[3] == 0x0000FF00 && - lpData[4] == 0x00001100 && - lpData[5] == 0x00110000, "Surface data after unkeyed blit does not match\n"); - - lpData[0] = 0x55555555; - lpData[1] = 0x55555555; - lpData[2] = 0x55555555; - lpData[3] = 0x55555555; - lpData[4] = 0x55555555; - lpData[5] = 0x55555555; - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Src key */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - - ok(lpData[0] == 0x55555555 && /* Here the src key applied */ - lpData[1] == 0x00000000 && - lpData[2] == 0x00FF0000 && - lpData[3] == 0x0000FF00 && - lpData[4] == 0x00001100 && - lpData[5] == 0x00110000, "Surface data after srckey blit does not match\n"); - - lpData[0] = 0x55555555; - lpData[1] = 0x55555555; - lpData[2] = 0x55555555; - lpData[3] = 0x55555555; - lpData[4] = 0x55555555; - lpData[5] = 0x55555555; - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Src override */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - - ok(lpData[0] == 0x000000FF && - lpData[1] == 0x00000000 && - lpData[2] == 0x00FF0000 && - lpData[3] == 0x0000FF00 && - lpData[4] == 0x00001100 && - lpData[5] == 0x55555555, /* Override key applies here */ - "Surface data after src override key blit does not match\n"); - - lpData[0] = 0x55555555; - lpData[1] = 0x55555555; - lpData[2] = 0x55555555; - lpData[3] = 0x55555555; - lpData[4] = 0x55555555; - lpData[5] = 0x55555555; - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Src override AND src key. That is not supposed to work */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx); - ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc); - - /* Verify that the destination is unchanged */ - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - - ok(lpData[0] == 0x55555555 && - lpData[1] == 0x55555555 && - lpData[2] == 0x55555555 && - lpData[3] == 0x55555555 && - lpData[4] == 0x55555555 && - lpData[5] == 0x55555555, /* Override key applies here */ - "Surface data after src key blit with override does not match\n"); - - lpData[0] = 0x00FF0000; /* Dest key in dst surface */ - lpData[1] = 0x00FF0000; /* Dest key in dst surface */ - lpData[2] = 0x00001100; /* Dest key in override */ - lpData[3] = 0x00001100; /* Dest key in override */ - lpData[4] = 0x00000000; /* Dest key in src surface */ - lpData[5] = 0x00000000; /* Dest key in src surface */ - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Dest key blit */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - - /* DirectDraw uses the dest blit key from the SOURCE surface ! */ - ok(lpData[0] == 0x00ff0000 && - lpData[1] == 0x00ff0000 && - lpData[2] == 0x00001100 && - lpData[3] == 0x00001100 && - lpData[4] == 0x00001100 && /* Key applies here */ - lpData[5] == 0x00110000, /* Key applies here */ - "Surface data after dest key blit does not match\n"); - - lpData[0] = 0x00FF0000; /* Dest key in dst surface */ - lpData[1] = 0x00FF0000; /* Dest key in dst surface */ - lpData[2] = 0x00001100; /* Dest key in override */ - lpData[3] = 0x00001100; /* Dest key in override */ - lpData[4] = 0x00000000; /* Dest key in src surface */ - lpData[5] = 0x00000000; /* Dest key in src surface */ - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Dest override key blit */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - - ok(lpData[0] == 0x00FF0000 && - lpData[1] == 0x00FF0000 && - lpData[2] == 0x00FF0000 && /* Key applies here */ - lpData[3] == 0x0000FF00 && /* Key applies here */ - lpData[4] == 0x00000000 && - lpData[5] == 0x00000000, - "Surface data after dest key override blit does not match\n"); - - lpData[0] = 0x00FF0000; /* Dest key in dst surface */ - lpData[1] = 0x00FF0000; /* Dest key in dst surface */ - lpData[2] = 0x00001100; /* Dest key in override */ - lpData[3] = 0x00001100; /* Dest key in override */ - lpData[4] = 0x00000000; /* Dest key in src surface */ - lpData[5] = 0x00000000; /* Dest key in src surface */ - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Dest override key blit. Supposed to fail too */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx); - ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc); - - /* Check for unchanged data */ - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - - ok(lpData[0] == 0x00FF0000 && - lpData[1] == 0x00FF0000 && - lpData[2] == 0x00001100 && /* Key applies here */ - lpData[3] == 0x00001100 && /* Key applies here */ - lpData[4] == 0x00000000 && - lpData[5] == 0x00000000, - "Surface data with dest key and dest override does not match\n"); - - lpData[0] = 0x00FF0000; /* Dest key in dst surface */ - lpData[1] = 0x00FF0000; /* Dest key in dst surface */ - lpData[2] = 0x00001100; /* Dest key in override */ - lpData[3] = 0x00001100; /* Dest key in override */ - lpData[4] = 0x00000000; /* Dest key in src surface */ - lpData[5] = 0x00000000; /* Dest key in src surface */ - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Modify the source data a bit to give some more conclusive results */ - rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - lpData[5] = 0x000000FF; /* Applies to src blt key in src surface */ - rc = IDirectDrawSurface_Unlock(lpSrc, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Source and destination key */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - - rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); - ok(rc==DD_OK,"Lock returned: %x\n",rc); - ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); - lpData = ddsd2.lpSurface; - - ok(lpData[0] == 0x00FF0000 && /* Masked by Destination key */ - lpData[1] == 0x00FF0000 && /* Masked by Destination key */ - lpData[2] == 0x00001100 && /* Masked by Destination key */ - lpData[3] == 0x00001100 && /* Masked by Destination key */ - lpData[4] == 0x00001100 && /* Allowed by destination key, not masked by source key */ - lpData[5] == 0x00000000, /* Allowed by dst key, but masked by source key */ - "Surface data with src key and dest key blit does not match\n"); - - lpData[0] = 0x00FF0000; /* Dest key in dst surface */ - lpData[1] = 0x00FF0000; /* Dest key in dst surface */ - lpData[2] = 0x00001100; /* Dest key in override */ - lpData[3] = 0x00001100; /* Dest key in override */ - lpData[4] = 0x00000000; /* Dest key in src surface */ - lpData[5] = 0x00000000; /* Dest key in src surface */ - rc = IDirectDrawSurface_Unlock(lpDst, NULL); - ok(rc==DD_OK,"Unlock returned: %x\n",rc); - - /* Override keys without ddbltfx parameter fail */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, NULL); - ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc); - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, NULL); - ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc); - - /* Try blitting without keys in the source surface*/ - rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, NULL); - ok(rc == DD_OK, "SetColorKey returned %x\n", rc); - rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_DESTBLT, NULL); - ok(rc == DD_OK, "SetColorKey returned %x\n", rc); - - /* That fails now. Do not bother to check that the data is unmodified */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx); - ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc); - - /* Dest key blit still works. Which key is used this time??? */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - - /* With correctly passed override keys no key in the surface is needed. - * Again, the result was checked before, no need to do that again - */ - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx); - ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc); - - IDirectDrawSurface_Release(lpSrc); - IDirectDrawSurface_Release(lpDst); -} - static void QueryInterface(void) { IDirectDrawSurface *dsurface; @@ -3141,7 +2632,6 @@ return; } - SrcColorKey32BlitTest(); QueryInterface(); GetDDInterface_1(); GetDDInterface_2(); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/vertexbuffer.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/vertexbuffer.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ddraw/vertexbuffer.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ddraw/vertexbuffer.c 2017-03-21 14:02:57.000000000 +0000 @@ -81,25 +81,27 @@ TRACE("%p decreasing refcount to %u.\n", buffer, ref); - if (ref == 0) + if (!ref) { - struct wined3d_buffer *curVB = NULL; + struct wined3d_buffer *vb = NULL; UINT offset, stride; - /* D3D7 Vertex buffers don't stay bound in the device, they are passed - * as a parameter to drawPrimitiveVB. DrawPrimitiveVB sets them as the - * stream source in wined3d, and they should get unset there before + /* D3D7 vertex buffers don't stay bound in the device, they are passed + * as a parameter to DrawPrimitiveVB. DrawPrimitiveVB sets them as the + * stream source in wined3d and they should get unset there before * they are destroyed. */ wined3d_mutex_lock(); - wined3d_device_get_stream_source(buffer->ddraw->wined3d_device, - 0, &curVB, &offset, &stride); - if (curVB == buffer->wined3d_buffer) + wined3d_device_get_stream_source(buffer->ddraw->wined3d_device, 0, &vb, &offset, &stride); + if (vb == buffer->wined3d_buffer) wined3d_device_set_stream_source(buffer->ddraw->wined3d_device, 0, NULL, 0, 0); wined3d_vertex_declaration_decref(buffer->wined3d_declaration); wined3d_buffer_decref(buffer->wined3d_buffer); wined3d_mutex_unlock(); + if (buffer->version == 7) + IDirectDraw7_Release(&buffer->ddraw->IDirectDraw7_iface); + HeapFree(GetProcessHeap(), 0, buffer); } @@ -451,7 +453,8 @@ buffer->IDirect3DVertexBuffer7_iface.lpVtbl = &d3d_vertex_buffer7_vtbl; buffer->ref = 1; buffer->version = ddraw->d3dversion; - + if (buffer->version == 7) + IDirectDraw7_AddRef(&ddraw->IDirectDraw7_iface); buffer->ddraw = ddraw; buffer->Caps = desc->dwCaps; buffer->fvf = desc->dwFVF; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/devenum/mediacatenum.c wine-staging-2.4.0~ubuntu16.04.1/dlls/devenum/mediacatenum.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/devenum/mediacatenum.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/devenum/mediacatenum.c 2017-03-21 14:02:57.000000000 +0000 @@ -355,12 +355,14 @@ { MediaCatMoniker *This = impl_from_IMoniker(iface); - FIXME("(%p)->(%p): stub\n", This, pClassID); + TRACE("(%p)->(%p)\n", This, pClassID); if (pClassID == NULL) - return E_POINTER; + return E_INVALIDARG; - return E_NOTIMPL; + *pClassID = CLSID_CDeviceMoniker; + + return S_OK; } static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsDirty(IMoniker *iface) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/devenum/tests/devenum.c wine-staging-2.4.0~ubuntu16.04.1/dlls/devenum/tests/devenum.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/devenum/tests/devenum.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/devenum/tests/devenum.c 2017-03-21 14:02:57.000000000 +0000 @@ -79,6 +79,15 @@ IPropertyBag* prop_bag = NULL; VARIANT var; HRESULT hr; + CLSID clsid = {0}; + + hr = IMoniker_GetClassID(moniker, NULL); + ok(hr == E_INVALIDARG, "IMoniker_GetClassID should failed %x\n", hr); + + hr = IMoniker_GetClassID(moniker, &clsid); + ok(hr == S_OK, "IMoniker_GetClassID failed with error %x\n", hr); + ok(IsEqualGUID(&clsid, &CLSID_CDeviceMoniker), + "Expected CLSID_CDeviceMoniker got %s\n", wine_dbgstr_guid(&clsid)); VariantInit(&var); hr = IMoniker_BindToStorage(moniker, bind_ctx, NULL, &IID_IPropertyBag, (LPVOID*)&prop_bag); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dhcpcsvc/dhcpcsvc.c wine-staging-2.4.0~ubuntu16.04.1/dlls/dhcpcsvc/dhcpcsvc.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dhcpcsvc/dhcpcsvc.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dhcpcsvc/dhcpcsvc.c 2017-03-21 14:02:57.000000000 +0000 @@ -39,6 +39,18 @@ return TRUE; } +void WINAPI DhcpCApiCleanup(void) +{ + FIXME(": stub\n"); +} + +DWORD WINAPI DhcpCApiInitialize(LPDWORD version) +{ + *version = 2; /* 98, XP, and 8 */ + FIXME(": stub\n"); + return ERROR_SUCCESS; +} + DWORD WINAPI DhcpRequestParams( DWORD flags, void *reserved, WCHAR *adaptername, DHCPCAPI_CLASSID *classid, DHCPCAPI_PARAMS_ARRAY sendparams, DHCPCAPI_PARAMS_ARRAY recdparams, BYTE *buffer, DWORD *size, WCHAR *requestidstr ) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dhcpcsvc/dhcpcsvc.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/dhcpcsvc/dhcpcsvc.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dhcpcsvc/dhcpcsvc.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dhcpcsvc/dhcpcsvc.spec 2017-03-21 14:02:57.000000000 +0000 @@ -1,7 +1,7 @@ @ stub DhcpAcquireParameters @ stub DhcpAcquireParametersByBroadcast -@ stub DhcpCApiCleanup -@ stub DhcpCApiInitialize +@ stdcall DhcpCApiCleanup() +@ stdcall DhcpCApiInitialize(ptr) @ stub DhcpDeRegisterConnectionStateNotification @ stub DhcpDeRegisterOptions @ stub DhcpDeRegisterParamChange diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dplayx/dplobby.c wine-staging-2.4.0~ubuntu16.04.1/dlls/dplayx/dplobby.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dplayx/dplobby.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dplayx/dplobby.c 2017-03-21 14:02:57.000000000 +0000 @@ -1726,8 +1726,7 @@ } else { - ERR( "Unknown GUID %s\n", debugstr_guid(&lpElements->guidDataType) ); - return DPERR_INVALIDFLAGS; + WARN( "Skipping Unknown GUID %s\n", debugstr_guid(&lpElements->guidDataType) ); } } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dplayx/tests/dplayx.c wine-staging-2.4.0~ubuntu16.04.1/dlls/dplayx/tests/dplayx.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dplayx/tests/dplayx.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dplayx/tests/dplayx.c 2017-03-21 14:02:57.000000000 +0000 @@ -64,6 +64,7 @@ DEFINE_GUID(appGuid, 0xbdcfe03e, 0xf0ec, 0x415b, 0x82, 0x11, 0x6f, 0x86, 0xd8, 0x19, 0x7f, 0xe1); DEFINE_GUID(appGuid2, 0x93417d3f, 0x7d26, 0x46ba, 0xb5, 0x76, 0xfe, 0x4b, 0x20, 0xbb, 0xad, 0x70); DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); +DEFINE_GUID(invalid_guid, 0x7b48b707, 0x0034, 0xc000, 0x02, 0x00, 0x00, 0x00, 0xec, 0xf6, 0x32, 0x00); typedef struct tagCallbackData @@ -699,7 +700,7 @@ checkHR( DP_OK, hr ); HeapFree( GetProcessHeap(), 0, pAddress ); - + IDirectPlayLobby_Release(pDPL); } static BOOL CALLBACK EnumSessions_cb_join( LPCDPSESSIONDESC2 lpThisSD, @@ -939,6 +940,8 @@ callbackData->dwCounter1++; + IDirectPlayLobby_Release(pDPL); + return TRUE; } @@ -1128,6 +1131,53 @@ IDirectPlayX_Release( pDP ); } +static void test_EnumAddressTypes(void) +{ + IDirectPlay4 *pDP; + HRESULT hr; + DPCOMPOUNDADDRESSELEMENT addressElements[2]; + LPVOID pAddress = NULL; + DWORD dwAddressSize = 0; + IDirectPlayLobby3 *pDPL; + WORD port = 6001; + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ok( SUCCEEDED(hr), "CCI of CLSID_DirectPlay / IID_IDirectPlay4A failed\n" ); + if (FAILED(hr)) + return; + + hr = CoCreateInstance( &CLSID_DirectPlayLobby, NULL, CLSCTX_ALL, + &IID_IDirectPlayLobby3A, (LPVOID*) &pDPL ); + ok (SUCCEEDED (hr), "CCI of CLSID_DirectPlayLobby / IID_IDirectPlayLobby3A failed\n"); + if (FAILED (hr)) return; + + addressElements[0].guidDataType = DPAID_ServiceProvider; + addressElements[0].dwDataSize = sizeof(GUID); + addressElements[0].lpData = (void*) &DPSPGUID_TCPIP; + + addressElements[1].guidDataType = invalid_guid; + addressElements[1].dwDataSize = sizeof(WORD); + addressElements[1].lpData = &port; + + hr = IDirectPlayLobby_CreateCompoundAddress( pDPL, addressElements, 2, NULL, &dwAddressSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + + if( hr == DPERR_BUFFERTOOSMALL ) + { + pAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressSize ); + hr = IDirectPlayLobby_CreateCompoundAddress( pDPL, addressElements, 2, + pAddress, &dwAddressSize ); + checkHR( DP_OK, hr ); + } + + IDirectPlayX_Close(pDP); + IDirectPlayX_Release(pDP); + IDirectPlayLobby_Release(pDPL); + + HeapFree( GetProcessHeap(), 0, pAddress ); +} + /* Open */ static BOOL CALLBACK EnumSessions_cb2( LPCDPSESSIONDESC2 lpThisSD, @@ -3027,7 +3077,7 @@ if ( hr == DP_OK ) { todo_wine win_skip( "GetPlayerAddress not implemented\n" ); - return; + goto cleanup; } init_TCPIP_provider( pDP[0], "127.0.0.1", 0 ); @@ -3123,9 +3173,11 @@ HeapFree( GetProcessHeap(), 0, lpData ); + +cleanup: IDirectPlayX_Release( pDP[0] ); IDirectPlayX_Release( pDP[1] ); - + IDirectPlayLobby_Release(pDPL); } /* GetPlayerFlags */ @@ -6894,6 +6946,7 @@ test_EnumConnections(); test_InitializeConnection(); test_GetCaps(); + test_EnumAddressTypes(); if (!winetest_interactive) { diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dpnet/tests/client.c wine-staging-2.4.0~ubuntu16.04.1/dlls/dpnet/tests/client.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dpnet/tests/client.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dpnet/tests/client.c 2017-03-21 14:02:57.000000000 +0000 @@ -306,6 +306,13 @@ todo_wine ok(lastAsyncCode == DPNERR_USERCANCEL, "got 0x%08x\n", lastAsyncCode); todo_wine ok(lastAsyncHandle == async, "got 0x%08x\n", async); + hr = IDirectPlay8Client_Initialize(client2, NULL, DirectPlayMessageHandler, 0); + ok(hr == S_OK, "got %x\n", hr); + + /* Show that handlers are per object. */ + hr = IDirectPlay8Client_CancelAsyncOperation(client2, async2, 0); + todo_wine ok(hr == DPNERR_INVALIDHANDLE, "IDirectPlay8Client_CancelAsyncOperation failed with 0x%08x\n", hr); + lastAsyncCode = E_FAIL; lastAsyncHandle = 0xdeadbeef; hr = IDirectPlay8Client_CancelAsyncOperation(client, async2, 0); @@ -318,6 +325,68 @@ IDirectPlay8Client_Release(client2); } +static void test_enum_hosts_sync(void) +{ + HRESULT hr; + IDirectPlay8Address *host = NULL; + IDirectPlay8Address *local = NULL; + DPN_APPLICATION_DESC appdesc; + DWORD port = 5445, type = 0, size; + + memset( &appdesc, 0, sizeof(DPN_APPLICATION_DESC) ); + appdesc.dwSize = sizeof( DPN_APPLICATION_DESC ); + appdesc.guidApplication = appguid; + + hr = CoCreateInstance( &CLSID_DirectPlay8Address, NULL, CLSCTX_ALL, &IID_IDirectPlay8Address, (void**)&local); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + hr = IDirectPlay8Address_SetSP(local, &CLSID_DP8SP_TCPIP); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + hr = CoCreateInstance( &CLSID_DirectPlay8Address, NULL, CLSCTX_ALL, &IID_IDirectPlay8Address, (void**)&host); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + hr = IDirectPlay8Address_SetSP(host, &CLSID_DP8SP_TCPIP); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + hr = IDirectPlay8Address_AddComponent(host, DPNA_KEY_HOSTNAME, localhost, sizeof(localhost), + DPNA_DATATYPE_STRING); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + handlecnt = 0; + lastAsyncCode = 0xdeadbeef; + hr = IDirectPlay8Client_EnumHosts(client, &appdesc, host, local, NULL, 0, 3, 1500, 1000, + NULL, NULL, DPNENUMHOSTS_SYNC); + ok(hr == DPN_OK, "got 0x%08x\n", hr); + ok(lastAsyncCode == 0xdeadbeef, "got 0x%08x\n", lastAsyncCode); + todo_wine ok(handlecnt == 2, "message handler not called\n"); + + size = sizeof(port); + hr = IDirectPlay8Address_GetComponentByName(host, DPNA_KEY_PORT, &port, &size, &type); + ok(hr == DPNERR_DOESNOTEXIST, "got 0x%08x\n", hr); + + size = sizeof(port); + hr = IDirectPlay8Address_GetComponentByName(local, DPNA_KEY_PORT, &port, &size, &type); + ok(hr == DPNERR_DOESNOTEXIST, "got 0x%08x\n", hr); + + /* Try with specific port */ + port = 5445; + hr = IDirectPlay8Address_AddComponent(host, DPNA_KEY_PORT, &port, sizeof(port), + DPNA_DATATYPE_DWORD); + + handlecnt = 0; + lastAsyncCode = 0xbeefdead; + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + hr = IDirectPlay8Client_EnumHosts(client, &appdesc, host, local, NULL, 0, 1, 1500, 1000, + NULL, NULL, DPNENUMHOSTS_SYNC); + ok(hr == DPN_OK, "got 0x%08x\n", hr); + ok(lastAsyncCode == 0xbeefdead, "got 0x%08x\n", lastAsyncCode); + ok(handlecnt == 0, "message handler called\n"); + + IDirectPlay8Address_Release(local); + IDirectPlay8Address_Release(host); +} + static void test_get_sp_caps(void) { DPN_SP_CAPS caps; @@ -662,6 +731,68 @@ IDirectPlay8Address_Release(host); } +static void test_enum_hosts_sync_peer(void) +{ + HRESULT hr; + IDirectPlay8Address *host = NULL; + IDirectPlay8Address *local = NULL; + DPN_APPLICATION_DESC appdesc; + DWORD port = 5445, type = 0, size; + + memset( &appdesc, 0, sizeof(DPN_APPLICATION_DESC) ); + appdesc.dwSize = sizeof( DPN_APPLICATION_DESC ); + appdesc.guidApplication = appguid; + + hr = CoCreateInstance( &CLSID_DirectPlay8Address, NULL, CLSCTX_ALL, &IID_IDirectPlay8Address, (void**)&local); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + hr = IDirectPlay8Address_SetSP(local, &CLSID_DP8SP_TCPIP); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + hr = CoCreateInstance( &CLSID_DirectPlay8Address, NULL, CLSCTX_ALL, &IID_IDirectPlay8Address, (void**)&host); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + hr = IDirectPlay8Address_SetSP(host, &CLSID_DP8SP_TCPIP); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + hr = IDirectPlay8Address_AddComponent(host, DPNA_KEY_HOSTNAME, localhost, sizeof(localhost), + DPNA_DATATYPE_STRING); + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + + handlecnt = 0; + lastAsyncCode = 0xdeadbeef; + hr = IDirectPlay8Peer_EnumHosts(peer, &appdesc, host, local, NULL, 0, 3, 1500, 1000, + NULL, NULL, DPNENUMHOSTS_SYNC); + ok(hr == DPN_OK, "got 0x%08x\n", hr); + ok(lastAsyncCode == 0xdeadbeef, "got 0x%08x\n", lastAsyncCode); + todo_wine ok(handlecnt == 2, "wrong handle cnt\n"); + + size = sizeof(port); + hr = IDirectPlay8Address_GetComponentByName(host, DPNA_KEY_PORT, &port, &size, &type); + ok(hr == DPNERR_DOESNOTEXIST, "got 0x%08x\n", hr); + + size = sizeof(port); + hr = IDirectPlay8Address_GetComponentByName(local, DPNA_KEY_PORT, &port, &size, &type); + ok(hr == DPNERR_DOESNOTEXIST, "got 0x%08x\n", hr); + + /* Try with specific port */ + port = 5445; + hr = IDirectPlay8Address_AddComponent(host, DPNA_KEY_PORT, &port, sizeof(port), + DPNA_DATATYPE_DWORD); + + handlecnt = 0; + lastAsyncCode = 0xbeefdead; + ok(hr == S_OK, "Failed with 0x%08x\n", hr); + hr = IDirectPlay8Peer_EnumHosts(peer, &appdesc, host, local, NULL, 0, 1, 1500, 1000, + NULL, NULL, DPNENUMHOSTS_SYNC); + ok(hr == DPN_OK, "got 0x%08x\n", hr); + ok(lastAsyncCode == 0xbeefdead, "got 0x%08x\n", lastAsyncCode); + ok(handlecnt == 0, "message handler called\n"); + + IDirectPlay8Address_Release(local); + IDirectPlay8Address_Release(host); +} + static void test_get_sp_caps_peer(void) { DPN_SP_CAPS caps; @@ -823,6 +954,7 @@ test_enum_service_providers(); test_enum_hosts(); + test_enum_hosts_sync(); test_get_sp_caps(); test_player_info(); test_lobbyclient(); @@ -832,6 +964,7 @@ test_init_dp_peer(); test_enum_service_providers_peer(); test_enum_hosts_peer(); + test_enum_hosts_sync_peer(); test_get_sp_caps_peer(); test_player_info_peer(); test_cleanup_dp_peer(); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dpnet/tests/thread.c wine-staging-2.4.0~ubuntu16.04.1/dlls/dpnet/tests/thread.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dpnet/tests/thread.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dpnet/tests/thread.c 2017-03-21 14:02:57.000000000 +0000 @@ -119,7 +119,7 @@ DPN_APPLICATION_DESC appdesc; DPNHANDLE async = 0, async2 = 0; static const WCHAR localhost[] = {'1','2','7','.','0','.','0','.','1',0}; - DWORD threadcnt; + DWORD threadcnt, threadorig; enumevent = CreateEventA( NULL, TRUE, FALSE, NULL); @@ -170,9 +170,10 @@ ok(hr == DPNSUCCESS_PENDING, "IDirectPlay8Client_EnumHosts failed with 0x%08x\n", hr); todo_wine ok(async, "No Handle returned\n"); - hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); + /* The first EnumHosts call will increase the thread count */ + hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadorig, 0); ok(hr == S_OK, "got 0x%08x\n", hr); - todo_wine ok(threadcnt == 6, "got %d\n", threadcnt); + todo_wine ok(threadorig > 1, "got %d\n", threadorig); hr = IDirectPlay8Client_EnumHosts(client, &appdesc, host, local, NULL, 0, INFINITE, 0, INFINITE, NULL, &async2, 0); ok(hr == DPNSUCCESS_PENDING, "IDirectPlay8Client_EnumHosts failed with 0x%08x\n", hr); @@ -181,21 +182,21 @@ hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); - todo_wine ok(threadcnt == 6, "got %d\n", threadcnt); + ok(threadcnt == threadorig, "got %d\n", threadcnt); hr = IDirectPlay8Client_CancelAsyncOperation(client, async, 0); ok(hr == S_OK, "IDirectPlay8Client_CancelAsyncOperation failed with 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); - todo_wine ok(threadcnt == 6, "got %d\n", threadcnt); + ok(threadcnt == threadorig, "got %d\n", threadcnt); hr = IDirectPlay8Client_CancelAsyncOperation(client, async2, 0); ok(hr == S_OK, "IDirectPlay8Client_CancelAsyncOperation failed with 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); - todo_wine ok(threadcnt == 6, "got %d\n", threadcnt); + ok(threadcnt == threadorig, "got %d\n", threadcnt); IDirectPlay8Address_Release(local); IDirectPlay8Address_Release(host); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dwrite/dwrite_private.h wine-staging-2.4.0~ubuntu16.04.1/dlls/dwrite/dwrite_private.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dwrite/dwrite_private.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dwrite/dwrite_private.h 2017-03-21 14:02:57.000000000 +0000 @@ -286,7 +286,7 @@ extern void freetype_get_glyph_bbox(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; extern BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; extern INT freetype_get_charmap_index(IDWriteFontFace4*,BOOL*) DECLSPEC_HIDDEN; -extern INT32 freetype_get_glyph_advance(IDWriteFontFace4*,FLOAT,UINT16,DWRITE_MEASURING_MODE) DECLSPEC_HIDDEN; +extern INT32 freetype_get_glyph_advance(IDWriteFontFace4*,FLOAT,UINT16,DWRITE_MEASURING_MODE,BOOL*) DECLSPEC_HIDDEN; extern void freetype_get_design_glyph_bbox(IDWriteFontFace4*,UINT16,UINT16,RECT*) DECLSPEC_HIDDEN; /* Glyph shaping */ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dwrite/font.c wine-staging-2.4.0~ubuntu16.04.1/dlls/dwrite/font.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dwrite/font.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dwrite/font.c 2017-03-21 14:02:57.000000000 +0000 @@ -212,7 +212,7 @@ enum fontface_flags { FONTFACE_IS_SYMBOL = 1 << 0, FONTFACE_IS_MONOSPACED = 1 << 1, - FONTFACE_HAS_KERN_PAIRS = 1 << 2, + FONTFACE_HAS_KERNING_PAIRS = 1 << 2, FONTFACE_HAS_VERTICAL_VARIANTS = 1 << 3 }; @@ -739,11 +739,20 @@ return (int)floorf(metric + 0.5f); } +static UINT32 fontface_get_horz_metric_adjustment(const struct dwrite_fontface *fontface) +{ + if (!(fontface->simulations & DWRITE_FONT_SIMULATIONS_BOLD)) + return 0; + + return (fontface->metrics.designUnitsPerEm + 49) / 50; +} + static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace4 *iface, FLOAT emSize, FLOAT ppdip, DWRITE_MATRIX const *m, BOOL use_gdi_natural, UINT16 const *glyphs, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways) { struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface); + UINT32 adjustment = fontface_get_horz_metric_adjustment(This); DWRITE_MEASURING_MODE mode; FLOAT scale, size; HRESULT hr; @@ -762,13 +771,17 @@ for (i = 0; i < glyph_count; i++) { DWRITE_GLYPH_METRICS *ret = metrics + i; DWRITE_GLYPH_METRICS design; + BOOL has_contours; hr = IDWriteFontFace4_GetDesignGlyphMetrics(iface, glyphs + i, 1, &design, is_sideways); if (FAILED(hr)) return hr; - ret->advanceWidth = freetype_get_glyph_advance(iface, size, glyphs[i], mode); - ret->advanceWidth = round_metric(ret->advanceWidth * This->metrics.designUnitsPerEm / size); + ret->advanceWidth = freetype_get_glyph_advance(iface, size, glyphs[i], mode, &has_contours); + if (has_contours) + ret->advanceWidth = round_metric(ret->advanceWidth * This->metrics.designUnitsPerEm / size + adjustment); + else + ret->advanceWidth = round_metric(ret->advanceWidth * This->metrics.designUnitsPerEm / size); #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale) SCALE_METRIC(leftSideBearing); @@ -878,6 +891,7 @@ UINT32 glyph_count, UINT16 const *glyphs, INT32 *advances, BOOL is_sideways) { struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface); + UINT32 adjustment = fontface_get_horz_metric_adjustment(This); UINT32 i; TRACE("(%p)->(%u %p %p %d)\n", This, glyph_count, glyphs, advances, is_sideways); @@ -885,8 +899,14 @@ if (is_sideways) FIXME("sideways mode not supported\n"); - for (i = 0; i < glyph_count; i++) - advances[i] = freetype_get_glyph_advance(iface, This->metrics.designUnitsPerEm, glyphs[i], DWRITE_MEASURING_MODE_NATURAL); + for (i = 0; i < glyph_count; i++) { + BOOL has_contours; + + advances[i] = freetype_get_glyph_advance(iface, This->metrics.designUnitsPerEm, glyphs[i], + DWRITE_MEASURING_MODE_NATURAL, &has_contours); + if (has_contours) + advances[i] += adjustment; + } return S_OK; } @@ -896,6 +916,7 @@ BOOL is_sideways, UINT32 glyph_count, UINT16 const *glyphs, INT32 *advances) { struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface); + UINT32 adjustment = fontface_get_horz_metric_adjustment(This); DWRITE_MEASURING_MODE mode; UINT32 i; @@ -918,8 +939,13 @@ mode = use_gdi_natural ? DWRITE_MEASURING_MODE_GDI_NATURAL : DWRITE_MEASURING_MODE_GDI_CLASSIC; for (i = 0; i < glyph_count; i++) { - advances[i] = freetype_get_glyph_advance(iface, em_size, glyphs[i], mode); - advances[i] = round_metric(advances[i] * This->metrics.designUnitsPerEm / em_size); + BOOL has_contours; + + advances[i] = freetype_get_glyph_advance(iface, em_size, glyphs[i], mode, &has_contours); + if (has_contours) + advances[i] = round_metric(advances[i] * This->metrics.designUnitsPerEm / em_size + adjustment); + else + advances[i] = round_metric(advances[i] * This->metrics.designUnitsPerEm / em_size); } return S_OK; @@ -941,7 +967,7 @@ return E_INVALIDARG; } - if (This->flags & FONTFACE_HAS_KERN_PAIRS) { + if (!(This->flags & FONTFACE_HAS_KERNING_PAIRS)) { memset(adjustments, 0, count*sizeof(INT32)); return S_OK; } @@ -957,7 +983,7 @@ { struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface); TRACE("(%p)\n", This); - return !!(This->flags & FONTFACE_HAS_KERN_PAIRS); + return !!(This->flags & FONTFACE_HAS_KERNING_PAIRS); } static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace4 *iface, @@ -4284,7 +4310,7 @@ if (is_symbol) fontface->flags |= FONTFACE_IS_SYMBOL; if (freetype_has_kerning_pairs(&fontface->IDWriteFontFace4_iface)) - fontface->flags |= FONTFACE_HAS_KERN_PAIRS; + fontface->flags |= FONTFACE_HAS_KERNING_PAIRS; if (freetype_is_monospaced(&fontface->IDWriteFontFace4_iface)) fontface->flags |= FONTFACE_IS_MONOSPACED; if (opentype_has_vertical_variants(&fontface->IDWriteFontFace4_iface)) @@ -4877,14 +4903,14 @@ { static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; struct dwrite_glyphbitmap glyph_bitmap; - IDWriteFontFace4 *fontface2; + IDWriteFontFace4 *fontface; D2D_POINT_2F origin; UINT32 i, size; BOOL is_rtl; HRESULT hr; RECT *bbox; - hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace4, (void**)&fontface2); + hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace4, (void **)&fontface); if (FAILED(hr)) { WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr); return; @@ -4899,7 +4925,7 @@ is_rtl = analysis->run.bidiLevel & 1; memset(&glyph_bitmap, 0, sizeof(glyph_bitmap)); - glyph_bitmap.fontface = fontface2; + glyph_bitmap.fontface = fontface; glyph_bitmap.emsize = analysis->run.fontEmSize * analysis->ppdip; glyph_bitmap.nohint = is_natural_rendering_mode(analysis->rendering_mode); glyph_bitmap.type = type; @@ -4987,7 +5013,7 @@ origin.y += advance->y; } - IDWriteFontFace4_Release(fontface2); + IDWriteFontFace4_Release(fontface); analysis->flags |= RUNANALYSIS_BITMAP_READY; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/dwrite/freetype.c wine-staging-2.4.0~ubuntu16.04.1/dlls/dwrite/freetype.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/dwrite/freetype.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/dwrite/freetype.c 2017-03-21 14:02:57.000000000 +0000 @@ -1,7 +1,7 @@ /* * FreeType integration * - * Copyright 2014-2015 Nikolay Sivov for CodeWeavers + * Copyright 2014-2017 Nikolay Sivov for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -74,10 +74,12 @@ MAKE_FUNCPTR(FT_Init_FreeType); MAKE_FUNCPTR(FT_Library_Version); MAKE_FUNCPTR(FT_Load_Glyph); +MAKE_FUNCPTR(FT_Matrix_Multiply); MAKE_FUNCPTR(FT_New_Memory_Face); MAKE_FUNCPTR(FT_Outline_Copy); MAKE_FUNCPTR(FT_Outline_Decompose); MAKE_FUNCPTR(FT_Outline_Done); +MAKE_FUNCPTR(FT_Outline_Embolden); MAKE_FUNCPTR(FT_Outline_Get_Bitmap); MAKE_FUNCPTR(FT_Outline_New); MAKE_FUNCPTR(FT_Outline_Transform); @@ -92,6 +94,7 @@ MAKE_FUNCPTR(FTC_Manager_LookupSize); MAKE_FUNCPTR(FTC_Manager_RemoveFaceID); #undef MAKE_FUNCPTR +static FT_Error (*pFT_Outline_EmboldenXY)(FT_Outline *, FT_Pos, FT_Pos); struct face_finalizer_data { @@ -194,10 +197,12 @@ LOAD_FUNCPTR(FT_Init_FreeType) LOAD_FUNCPTR(FT_Library_Version) LOAD_FUNCPTR(FT_Load_Glyph) + LOAD_FUNCPTR(FT_Matrix_Multiply) LOAD_FUNCPTR(FT_New_Memory_Face) LOAD_FUNCPTR(FT_Outline_Copy) LOAD_FUNCPTR(FT_Outline_Decompose) LOAD_FUNCPTR(FT_Outline_Done) + LOAD_FUNCPTR(FT_Outline_Embolden) LOAD_FUNCPTR(FT_Outline_Get_Bitmap) LOAD_FUNCPTR(FT_Outline_New) LOAD_FUNCPTR(FT_Outline_Transform) @@ -212,6 +217,7 @@ LOAD_FUNCPTR(FTC_Manager_LookupSize) LOAD_FUNCPTR(FTC_Manager_RemoveFaceID) #undef LOAD_FUNCPTR + pFT_Outline_EmboldenXY = wine_dlsym(ft_handle, "FT_Outline_EmboldenXY", NULL, 0); if (pFT_Init_FreeType(&library) != 0) { ERR("Can't init FreeType library\n"); @@ -272,6 +278,7 @@ EnterCriticalSection(&freetype_cs); if (pFTC_Manager_LookupSize(cache_manager, &scaler, &size) == 0) { if (pFT_Load_Glyph(size->face, glyph, FT_LOAD_NO_SCALE) == 0) { + USHORT simulations = IDWriteFontFace4_GetSimulations(fontface); FT_Glyph_Metrics *metrics = &size->face->glyph->metrics; ret->leftSideBearing = metrics->horiBearingX; @@ -281,6 +288,13 @@ ret->advanceHeight = metrics->vertAdvance; ret->bottomSideBearing = metrics->vertAdvance - metrics->vertBearingY - metrics->height; ret->verticalOriginY = metrics->height + metrics->vertBearingY; + + /* Adjust in case of bold simulation, glyphs without contours are ignored. */ + if (simulations & DWRITE_FONT_SIMULATIONS_BOLD && size->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && + size->face->glyph->outline.n_contours != 0) { + if (ret->advanceWidth) + ret->advanceWidth += (unitsperEm + 49) / 50; + } } } LeaveCriticalSection(&freetype_cs); @@ -445,8 +459,29 @@ ID2D1SimplifiedGeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED); } -HRESULT freetype_get_glyphrun_outline(IDWriteFontFace4 *fontface, FLOAT emSize, UINT16 const *glyphs, FLOAT const *advances, - DWRITE_GLYPH_OFFSET const *offsets, UINT32 count, BOOL is_rtl, IDWriteGeometrySink *sink) +static void embolden_glyph_outline(FT_Outline *outline, FLOAT emsize) +{ + FT_Pos strength; + + strength = MulDiv(emsize, 1 << 6, 24); + if (pFT_Outline_EmboldenXY) + pFT_Outline_EmboldenXY(outline, strength, 0); + else + pFT_Outline_Embolden(outline, strength); +} + +static void embolden_glyph(FT_Glyph glyph, FLOAT emsize) +{ + FT_OutlineGlyph outline_glyph = (FT_OutlineGlyph)glyph; + + if (glyph->format != FT_GLYPH_FORMAT_OUTLINE) + return; + + embolden_glyph_outline(&outline_glyph->outline, emsize); +} + +HRESULT freetype_get_glyphrun_outline(IDWriteFontFace4 *fontface, FLOAT emSize, UINT16 const *glyphs, + FLOAT const *advances, DWRITE_GLYPH_OFFSET const *offsets, UINT32 count, BOOL is_rtl, IDWriteGeometrySink *sink) { FTC_ScalerRec scaler; USHORT simulations; @@ -479,6 +514,9 @@ FLOAT xoffset = 0.0f, yoffset = 0.0f; FT_Matrix m; + if (simulations & DWRITE_FONT_SIMULATIONS_BOLD) + embolden_glyph_outline(outline, emSize); + m.xx = 1 << 16; m.xy = simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE ? (1 << 16) / 3 : 0; m.yx = 0; @@ -596,35 +634,66 @@ return FALSE; } +static BOOL get_glyph_transform(struct dwrite_glyphbitmap *bitmap, FT_Matrix *ret) +{ + USHORT simulations = IDWriteFontFace4_GetSimulations(bitmap->fontface); + FT_Matrix m; + + ret->xx = 1 << 16; + ret->xy = 0; + ret->yx = 0; + ret->yy = 1 << 16; + + /* Some fonts provide mostly bitmaps and very few outlines, for example for .notdef. + Disable transform if that's the case. */ + if (!is_face_scalable(bitmap->fontface) || (!bitmap->m && simulations == 0)) + return FALSE; + + if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) { + m.xx = 1 << 16; + m.xy = (1 << 16) / 3; + m.yx = 0; + m.yy = 1 << 16; + pFT_Matrix_Multiply(&m, ret); + } + + if (bitmap->m) { + ft_matrix_from_dwrite_matrix(bitmap->m, &m); + pFT_Matrix_Multiply(&m, ret); + } + + return TRUE; +} + void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap) { + USHORT simulations = IDWriteFontFace4_GetSimulations(bitmap->fontface); FTC_ImageTypeRec imagetype; FT_BBox bbox = { 0 }; + BOOL needs_transform; FT_Glyph glyph; + FT_Matrix m; EnterCriticalSection(&freetype_cs); - /* Some fonts provide mostly bitmaps and very few outlines, for example for .notdef, - disable transform if that's the case. */ - if (bitmap->m) { - if (!is_face_scalable(bitmap->fontface)) - bitmap->m = NULL; - } + needs_transform = get_glyph_transform(bitmap, &m); imagetype.face_id = bitmap->fontface; imagetype.width = 0; imagetype.height = bitmap->emsize; - imagetype.flags = bitmap->m ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT; + imagetype.flags = needs_transform ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT; if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) { - if (bitmap->m) { + if (needs_transform) { FT_Glyph glyph_copy; if (pFT_Glyph_Copy(glyph, &glyph_copy) == 0) { - FT_Matrix ft_matrix; + if (simulations & DWRITE_FONT_SIMULATIONS_BOLD) + embolden_glyph(glyph_copy, bitmap->emsize); + + if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) + pFT_Glyph_Transform(glyph_copy, &m, NULL); - ft_matrix_from_dwrite_matrix(bitmap->m, &ft_matrix); - pFT_Glyph_Transform(glyph_copy, &ft_matrix, NULL); pFT_Glyph_Get_CBox(glyph_copy, FT_GLYPH_BBOX_PIXELS, &bbox); pFT_Done_Glyph(glyph_copy); } @@ -758,31 +827,32 @@ BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) { + USHORT simulations = IDWriteFontFace4_GetSimulations(bitmap->fontface); FTC_ImageTypeRec imagetype; + BOOL needs_transform; BOOL ret = FALSE; FT_Glyph glyph; + FT_Matrix m; EnterCriticalSection(&freetype_cs); - if (bitmap->m) { - if (!is_face_scalable(bitmap->fontface)) - bitmap->m = NULL; - } + needs_transform = get_glyph_transform(bitmap, &m); imagetype.face_id = bitmap->fontface; imagetype.width = 0; imagetype.height = bitmap->emsize; - imagetype.flags = bitmap->m ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT; + imagetype.flags = needs_transform ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT; if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) { FT_Glyph glyph_copy; - if (bitmap->m) { + if (needs_transform) { if (pFT_Glyph_Copy(glyph, &glyph_copy) == 0) { - FT_Matrix ft_matrix; + if (simulations & DWRITE_FONT_SIMULATIONS_BOLD) + embolden_glyph(glyph_copy, bitmap->emsize); - ft_matrix_from_dwrite_matrix(bitmap->m, &ft_matrix); - pFT_Glyph_Transform(glyph_copy, &ft_matrix, NULL); + if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) + pFT_Glyph_Transform(glyph_copy, &m, NULL); glyph = glyph_copy; } } @@ -835,7 +905,8 @@ return charmap_index; } -INT32 freetype_get_glyph_advance(IDWriteFontFace4 *fontface, FLOAT emSize, UINT16 index, DWRITE_MEASURING_MODE mode) +INT32 freetype_get_glyph_advance(IDWriteFontFace4 *fontface, FLOAT emSize, UINT16 index, DWRITE_MEASURING_MODE mode, + BOOL *has_contours) { FTC_ImageTypeRec imagetype; FT_Glyph glyph; @@ -849,10 +920,14 @@ imagetype.flags |= FT_LOAD_NO_HINTING; EnterCriticalSection(&freetype_cs); - if (pFTC_ImageCache_Lookup(image_cache, &imagetype, index, &glyph, NULL) == 0) + if (pFTC_ImageCache_Lookup(image_cache, &imagetype, index, &glyph, NULL) == 0) { + *has_contours = glyph->format == FT_GLYPH_FORMAT_OUTLINE && ((FT_OutlineGlyph)glyph)->outline.n_contours; advance = glyph->advance.x >> 16; - else + } + else { + *has_contours = FALSE; advance = 0; + } LeaveCriticalSection(&freetype_cs); return advance; @@ -931,8 +1006,10 @@ return -1; } -INT32 freetype_get_glyph_advance(IDWriteFontFace4 *fontface, FLOAT emSize, UINT16 index, DWRITE_MEASURING_MODE mode) +INT32 freetype_get_glyph_advance(IDWriteFontFace4 *fontface, FLOAT emSize, UINT16 index, DWRITE_MEASURING_MODE mode, + BOOL *has_contours) { + *has_contours = FALSE; return 0; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/bitblt.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/bitblt.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/bitblt.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/bitblt.c 2017-03-21 14:02:57.000000000 +0000 @@ -221,7 +221,7 @@ return blend_bitmapinfo( src_info, src_bits->ptr, src, dst_info, dst_bits->ptr, dst, blend ); } -static RGBQUAD get_dc_rgb_color( DC *dc, COLORREF color ) +static RGBQUAD get_dc_rgb_color( DC *dc, int color_table_size, COLORREF color ) { RGBQUAD ret = { 0, 0, 0, 0 }; @@ -238,8 +238,11 @@ } if (color >> 16 == 0x10ff) /* DIBINDEX */ { - /* FIXME: need to propagate the index into the conversion functions */ - WARN( "monochrome blit uses DIBINDEX %x\n", color ); + if (color_table_size) + { + if (LOWORD(color) >= color_table_size) color = 0x10ff0000; /* fallback to index 0 */ + *(DWORD *)&ret = color; + } return ret; } ret.rgbRed = GetRValue( color ); @@ -249,10 +252,10 @@ } /* helper to retrieve either both colors or only the background color for monochrome blits */ -void get_mono_dc_colors( DC *dc, BITMAPINFO *info, int count ) +void get_mono_dc_colors( DC *dc, int color_table_size, BITMAPINFO *info, int count ) { - info->bmiColors[count - 1] = get_dc_rgb_color( dc, dc->backgroundColor ); - if (count > 1) info->bmiColors[0] = get_dc_rgb_color( dc, dc->textColor ); + info->bmiColors[count - 1] = get_dc_rgb_color( dc, color_table_size, dc->backgroundColor ); + if (count > 1) info->bmiColors[0] = get_dc_rgb_color( dc, color_table_size, dc->textColor ); info->bmiHeader.biClrUsed = count; } @@ -284,18 +287,12 @@ /* 1-bpp source without a color table uses the destination DC colors */ if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed) - get_mono_dc_colors( dc_dst, src_info, 2 ); + get_mono_dc_colors( dc_dst, dst_info->bmiHeader.biClrUsed, src_info, 2 ); + /* 1-bpp destination without a color table requires a fake 1-entry table + * that contains only the background color */ if (dst_info->bmiHeader.biBitCount == 1 && !dst_colors) - { - /* 1-bpp destination without a color table requires a fake 1-entry table - * that contains only the background color; except with a 1-bpp source, - * in which case it uses the source colors */ - if (src_info->bmiHeader.biBitCount > 1) - get_mono_dc_colors( dc_src, dst_info, 1 ); - else - get_mono_dc_colors( dc_src, dst_info, 2 ); - } + get_mono_dc_colors( dc_src, src_info->bmiHeader.biClrUsed, dst_info, 1 ); if (!(err = convert_bits( src_info, src, dst_info, &bits ))) { diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/dib.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/dib.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/dib.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/dib.c 2017-03-21 14:02:57.000000000 +0000 @@ -577,17 +577,13 @@ DWORD dst_colors = dst_info->bmiHeader.biClrUsed; /* 1-bpp destination without a color table requires a fake 1-entry table - * that contains only the background color; except with a 1-bpp source, - * in which case it uses the source colors */ + * that contains only the background color. There is no source DC to get + * it from, so the background is hardcoded to the default color. */ if (dst_info->bmiHeader.biBitCount == 1 && !dst_colors) { - if (src_info->bmiHeader.biBitCount > 1) - get_mono_dc_colors( dc, dst_info, 1 ); - else - { - memcpy( dst_info->bmiColors, src_info->bmiColors, 2 * sizeof(dst_info->bmiColors[0]) ); - dst_info->bmiHeader.biClrUsed = 2; - } + static const RGBQUAD default_bg = { 255, 255, 255 }; + dst_info->bmiColors[0] = default_bg; + dst_info->bmiHeader.biClrUsed = 1; } if (!(err = convert_bits( src_info, &src, dst_info, &src_bits ))) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/dibdrv/bitblt.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/dibdrv/bitblt.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/dibdrv/bitblt.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/dibdrv/bitblt.c 2017-03-21 14:02:57.000000000 +0000 @@ -1001,7 +1001,7 @@ /* For mask_rect, 1-bpp source without a color table uses the destination DC colors */ if (info->bmiHeader.biBitCount == 1 && pdev->dib.bit_count != 1 && !info->bmiHeader.biClrUsed) - get_mono_dc_colors( dc, info, 2 ); + get_mono_dc_colors( dc, pdev->dib.color_table_size, info, 2 ); init_dib_info_from_bitmapinfo( &src_dib, info, bits->ptr ); src_dib.bits.is_copy = bits->is_copy; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/dibdrv/primitives.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/dibdrv/primitives.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/dibdrv/primitives.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/dibdrv/primitives.c 2017-03-21 14:02:57.000000000 +0000 @@ -108,6 +108,9 @@ static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; static const BYTE edge_masks_1[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; +#define FILTER_DIBINDEX(rgbquad,other_val) \ + (HIWORD( *(DWORD *)(&rgbquad) ) == 0x10ff ? LOWORD( *(DWORD *)(&rgbquad) ) : (other_val)) + #define ROPS_WITHOUT_COPY( _d, _s ) \ case R2_BLACK: LOOP( (_d) = 0 ) break; \ case R2_NOTMERGEPEN: LOOP( (_d) = ~((_d) | (_s)) ) break; \ @@ -2082,19 +2085,23 @@ return field; } -static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour) +static DWORD rgb_to_pixel_masks(const dib_info *dib, DWORD r, DWORD g, DWORD b) { - DWORD r,g,b; - - r = GetRValue(colour); - g = GetGValue(colour); - b = GetBValue(colour); - return put_field(r, dib->red_shift, dib->red_len) | put_field(g, dib->green_shift, dib->green_len) | put_field(b, dib->blue_shift, dib->blue_len); } +static DWORD rgbquad_to_pixel_masks(const dib_info *dib, RGBQUAD rgb) +{ + return rgb_to_pixel_masks(dib, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); +} + +static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour) +{ + return rgb_to_pixel_masks(dib, GetRValue(colour), GetGValue(colour), GetBValue(colour)); +} + static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color) { return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) ); @@ -2107,14 +2114,6 @@ int i, best_index = 0; DWORD diff, best_diff = 0xffffffff; - /* special case for conversion to 1-bpp without a color table: - * we get a 1-entry table containing the background color - */ - if (dib->bit_count == 1 && size == 1) - return (r == color_table[0].rgbRed && - g == color_table[0].rgbGreen && - b == color_table[0].rgbBlue); - for(i = 0; i < size; i++) { const RGBQUAD *cur = color_table + i; @@ -2137,18 +2136,30 @@ return best_index; } -static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y, BYTE r, BYTE g, BYTE b) +static DWORD rgb_to_pixel_mono(const dib_info *dib, BOOL dither, int x, int y, + DWORD src_pixel, DWORD bg_pixel, BYTE r, BYTE g, BYTE b) { DWORD ret; - if (!dither) + if (dib->color_table_size != 1) + { + if (dither) + { + if (((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255) r = g = b = 255; + else r = g = b = 0; + } ret = rgb_to_pixel_colortable( dib, r, g, b ); - else - ret = ((30 * r + 59 * g + 11 * b) / 100 + bayer_16x16[y % 16][x % 16]) > 255; + } + else ret = (src_pixel == bg_pixel); /* only match raw pixel value */ return ret ? 0xff : 0; } +static DWORD rgbquad_to_pixel_colortable(const dib_info *dib, RGBQUAD rgb) +{ + return rgb_to_pixel_colortable( dib, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue ); +} + static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color) { return rgb_to_pixel_colortable( dib, GetRValue(color), GetGValue(color), GetBValue(color) ); @@ -2475,9 +2486,7 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) | - put_field(src_val >> 8, dst->green_shift, dst->green_len) | - put_field(src_val, dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, src_val >> 16, src_val >> 8, src_val); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 4; @@ -2527,9 +2536,10 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) | - put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) | - put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + get_field(src_val, src->red_shift, src->red_len), + get_field(src_val, src->green_shift, src->green_len), + get_field(src_val, src->blue_shift, src->blue_len)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 4; @@ -2547,17 +2557,8 @@ { dst_pixel = dst_start; src_pixel = src_start; - for(x = src_rect->left; x < src_rect->right; x++) - { - RGBQUAD rgb; - rgb.rgbBlue = *src_pixel++; - rgb.rgbGreen = *src_pixel++; - rgb.rgbRed = *src_pixel++; - - *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) | - put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) | - put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len); - } + for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3) + *dst_pixel++ = rgb_to_pixel_masks(dst, src_pixel[2], src_pixel[1], src_pixel[0]); if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 4; src_start += src->stride; @@ -2577,9 +2578,10 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) | - put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) | - put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), + ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), + ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 4; @@ -2595,12 +2597,13 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) | - (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) | - put_field( (((src_val >> src->green_shift) << 3) & 0xf8) | - (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) | - put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) | - (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + (((src_val >> src->red_shift) << 3) & 0xf8) | + (((src_val >> src->red_shift) >> 2) & 0x07), + (((src_val >> src->green_shift) << 3) & 0xf8) | + (((src_val >> src->green_shift) >> 2) & 0x07), + (((src_val >> src->blue_shift) << 3) & 0xf8) | + (((src_val >> src->blue_shift) >> 2) & 0x07)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 4; @@ -2616,12 +2619,13 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) | - (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) | - put_field( (((src_val >> src->green_shift) << 2) & 0xfc) | - (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) | - put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) | - (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + (((src_val >> src->red_shift) << 3) & 0xf8) | + (((src_val >> src->red_shift) >> 2) & 0x07), + (((src_val >> src->green_shift) << 2) & 0xfc) | + (((src_val >> src->green_shift) >> 4) & 0x03), + (((src_val >> src->blue_shift) << 3) & 0xf8) | + (((src_val >> src->blue_shift) >> 2) & 0x07)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 4; @@ -2637,9 +2641,10 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) | - put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) | - put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + get_field(src_val, src->red_shift, src->red_len), + get_field(src_val, src->green_shift, src->green_len), + get_field(src_val, src->blue_shift, src->blue_len)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 4; @@ -2656,12 +2661,7 @@ DWORD dst_colors[256], i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) | - put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) | - put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len); - } + dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -2684,12 +2684,7 @@ DWORD dst_colors[16], i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) | - put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) | - put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len); - } + dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -2716,12 +2711,7 @@ DWORD dst_colors[2], i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) | - put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) | - put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len); - } + dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -3260,9 +3250,7 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(src_val >> 16, dst->red_shift, dst->red_len) | - put_field(src_val >> 8, dst->green_shift, dst->green_len) | - put_field(src_val, dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, src_val >> 16, src_val >> 8, src_val); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 2; @@ -3278,9 +3266,10 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(src_val >> src->red_shift, dst->red_shift, dst->red_len) | - put_field(src_val >> src->green_shift, dst->green_shift, dst->green_len) | - put_field(src_val >> src->blue_shift, dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + src_val >> src->red_shift, + src_val >> src->green_shift, + src_val >> src->blue_shift); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 2; @@ -3296,9 +3285,10 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) | - put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) | - put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + get_field(src_val, src->red_shift, src->red_len), + get_field(src_val, src->green_shift, src->green_len), + get_field(src_val, src->blue_shift, src->blue_len )); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 2; @@ -3316,17 +3306,8 @@ { dst_pixel = dst_start; src_pixel = src_start; - for(x = src_rect->left; x < src_rect->right; x++) - { - RGBQUAD rgb; - rgb.rgbBlue = *src_pixel++; - rgb.rgbGreen = *src_pixel++; - rgb.rgbRed = *src_pixel++; - - *dst_pixel++ = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) | - put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) | - put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len); - } + for(x = src_rect->left; x < src_rect->right; x++, src_pixel += 3) + *dst_pixel++ = rgb_to_pixel_masks(dst, src_pixel[2], src_pixel[1], src_pixel[0]); if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 2; src_start += src->stride; @@ -3346,9 +3327,10 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) | - put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) | - put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), + ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), + ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 2; @@ -3379,12 +3361,13 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) | - (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) | - put_field( (((src_val >> src->green_shift) << 3) & 0xf8) | - (((src_val >> src->green_shift) >> 2) & 0x07), dst->green_shift, dst->green_len ) | - put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) | - (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + (((src_val >> src->red_shift) << 3) & 0xf8) | + (((src_val >> src->red_shift) >> 2) & 0x07), + (((src_val >> src->green_shift) << 3) & 0xf8) | + (((src_val >> src->green_shift) >> 2) & 0x07), + (((src_val >> src->blue_shift) << 3) & 0xf8) | + (((src_val >> src->blue_shift) >> 2) & 0x07)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 2; @@ -3400,12 +3383,13 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field( (((src_val >> src->red_shift) << 3) & 0xf8) | - (((src_val >> src->red_shift) >> 2) & 0x07), dst->red_shift, dst->red_len ) | - put_field( (((src_val >> src->green_shift) << 2) & 0xfc) | - (((src_val >> src->green_shift) >> 4) & 0x03), dst->green_shift, dst->green_len ) | - put_field( (((src_val >> src->blue_shift) << 3) & 0xf8) | - (((src_val >> src->blue_shift) >> 2) & 0x07), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + (((src_val >> src->red_shift) << 3) & 0xf8) | + (((src_val >> src->red_shift) >> 2) & 0x07), + (((src_val >> src->green_shift) << 2) & 0xfc) | + (((src_val >> src->green_shift) >> 4) & 0x03), + (((src_val >> src->blue_shift) << 3) & 0xf8) | + (((src_val >> src->blue_shift) >> 2) & 0x07)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 2; @@ -3421,9 +3405,10 @@ for(x = src_rect->left; x < src_rect->right; x++) { src_val = *src_pixel++; - *dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) | - put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) | - put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len); + *dst_pixel++ = rgb_to_pixel_masks(dst, + get_field(src_val, src->red_shift, src->red_len), + get_field(src_val, src->green_shift, src->green_len), + get_field(src_val, src->blue_shift, src->blue_len)); } if(pad_size) memset(dst_pixel, 0, pad_size); dst_start += dst->stride / 2; @@ -3441,12 +3426,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) | - put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) | - put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len); - } + dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -3470,12 +3450,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) | - put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) | - put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len); - } + dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -3503,12 +3478,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = put_field(rgb.rgbRed, dst->red_shift, dst->red_len) | - put_field(rgb.rgbGreen, dst->green_shift, dst->green_len) | - put_field(rgb.rgbBlue, dst->blue_shift, dst->blue_len); - } + dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -3741,10 +3711,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); - } + dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -3769,10 +3736,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); - } + dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -3800,10 +3764,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); - } + dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i])); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -4095,10 +4056,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); - } + dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -4152,10 +4110,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); - } + dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -4196,10 +4151,7 @@ int i; for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - { - RGBQUAD rgb = color_table[i]; - dst_colors[i] = rgb_to_pixel_colortable(dst, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); - } + dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i])); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -4234,6 +4186,7 @@ { BYTE *dst_start = get_pixel_ptr_1(dst, 0, 0), *dst_pixel, dst_val; INT x, y, pad_size = ((dst->width + 31) & ~31) / 8 - (src_rect->right - src_rect->left + 7) / 8; + RGBQUAD rgb, bg_entry = *get_dib_color_table( dst ); /* entry 0 is the background color */ DWORD src_val; int bit_pos; @@ -4242,6 +4195,7 @@ case 32: { DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel; + DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry)); if(src->funcs == &funcs_8888) { @@ -4252,8 +4206,8 @@ for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++) { src_val = *src_pixel++; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val >> 16, src_val >> 8, src_val); - + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, + src_val >> 16, src_val >> 8, src_val); if(bit_pos == 0) *dst_pixel = 0; *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]); @@ -4281,7 +4235,7 @@ for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++) { src_val = *src_pixel++; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, src_val >> src->red_shift, src_val >> src->green_shift, src_val >> src->blue_shift); @@ -4313,7 +4267,7 @@ for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++) { src_val = *src_pixel++; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, get_field(src_val, src->red_shift, src->red_len), get_field(src_val, src->green_shift, src->green_len), get_field(src_val, src->blue_shift, src->blue_len)); @@ -4342,6 +4296,7 @@ case 24: { BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel; + DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, RGB(bg_entry.rgbRed, bg_entry.rgbGreen, bg_entry.rgbBlue)); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -4349,7 +4304,8 @@ src_pixel = src_start; for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, src_pixel += 3) { - dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_pixel[2], src_pixel[1], src_pixel[0]); + dst_val = rgb_to_pixel_mono(dst, dither, x, y, RGB(src_pixel[2], src_pixel[1], src_pixel[0]), + bg_pixel, src_pixel[2], src_pixel[1], src_pixel[0]); if(bit_pos == 0) *dst_pixel = 0; *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]); @@ -4374,6 +4330,8 @@ case 16: { WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel; + DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry)); + if(src->funcs == &funcs_555) { for(y = src_rect->top; y < src_rect->bottom; y++) @@ -4383,7 +4341,7 @@ for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++) { src_val = *src_pixel++; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, ((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), ((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), ((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07)); @@ -4415,7 +4373,7 @@ for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++) { src_val = *src_pixel++; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, (((src_val >> src->red_shift) << 3) & 0xf8) | (((src_val >> src->red_shift) >> 2) & 0x07), (((src_val >> src->green_shift) << 3) & 0xf8) | @@ -4449,7 +4407,7 @@ for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++) { src_val = *src_pixel++; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, (((src_val >> src->red_shift) << 3) & 0xf8) | (((src_val >> src->red_shift) >> 2) & 0x07), (((src_val >> src->green_shift) << 2) & 0xfc) | @@ -4483,7 +4441,7 @@ for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++) { src_val = *src_pixel++; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, get_field(src_val, src->red_shift, src->red_len), get_field(src_val, src->green_shift, src->green_len), get_field(src_val, src->blue_shift, src->blue_len)); @@ -4512,6 +4470,7 @@ { const RGBQUAD *color_table = get_dib_color_table( src ); BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel; + DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry)); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -4519,8 +4478,10 @@ src_pixel = src_start; for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++) { - RGBQUAD rgb = color_table[*src_pixel++]; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); + BYTE src_val = *src_pixel++; + rgb = color_table[src_val]; + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, + rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); if(bit_pos == 0) *dst_pixel = 0; *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]); @@ -4546,6 +4507,7 @@ { const RGBQUAD *color_table = get_dib_color_table( src ); BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel; + DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry)); for(y = src_rect->top; y < src_rect->bottom; y++) { @@ -4554,12 +4516,10 @@ src_pixel = src_start; for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++) { - RGBQUAD rgb; - if (pos & 1) - rgb = color_table[*src_pixel++ & 0xf]; - else - rgb = color_table[*src_pixel >> 4]; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); + src_val = (pos & 1) ? *src_pixel++ & 0xf : *src_pixel >> 4; + rgb = color_table[src_val]; + dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, + rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); if(bit_pos == 0) *dst_pixel = 0; *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]); @@ -4590,17 +4550,18 @@ { const RGBQUAD *color_table = get_dib_color_table( src ); BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top); + DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry)); + for(y = src_rect->top; y < src_rect->bottom; y++) { int pos = (src->rect.left + src_rect->left) & 7; dst_pixel = dst_start; for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++, pos++) { - RGBQUAD rgb; src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0; rgb = color_table[src_val]; - dst_val = rgb_to_pixel_mono(dst, dither, x, y, rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); - + dst_val = FILTER_DIBINDEX(rgb, rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel, + rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue)); if(bit_pos == 0) *dst_pixel = 0; *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]); @@ -4751,9 +4712,7 @@ get_field( dst_ptr[x], dst->green_shift, dst->green_len ), get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ), src_ptr[x], blend ); - dst_ptr[x] = (put_field( val >> 16, dst->red_shift, dst->red_len ) | - put_field( val >> 8, dst->green_shift, dst->green_len ) | - put_field( val, dst->blue_shift, dst->blue_len )); + dst_ptr[x] = rgb_to_pixel_masks( dst, val >> 16, val >> 8, val ); } } } @@ -4814,9 +4773,7 @@ get_field( dst_ptr[x], dst->green_shift, dst->green_len ), get_field( dst_ptr[x], dst->blue_shift, dst->blue_len ), src_ptr[x], blend ); - dst_ptr[x] = (put_field((val >> 16), dst->red_shift, dst->red_len) | - put_field((val >> 8), dst->green_shift, dst->green_len) | - put_field( val, dst->blue_shift, dst->blue_len)); + dst_ptr[x] = rgb_to_pixel_masks( dst, val >> 16, val >> 8, val ); } } } @@ -5067,9 +5024,7 @@ for (x = 0; x < rc->right - rc->left; x++) { DWORD val = gradient_rgb_24( v, rc->left + x - v[0].x, v[1].x - v[0].x ); - ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) | - put_field( val >> 8, dib->green_shift, dib->green_len ) | - put_field( val, dib->blue_shift, dib->blue_len )); + ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); } } @@ -5086,9 +5041,7 @@ (((val >> 8) & 0xff) << dib->green_shift) | (((val >> 16) & 0xff) << dib->red_shift)); else - val = (put_field( val >> 16, dib->red_shift, dib->red_len ) | - put_field( val >> 8, dib->green_shift, dib->green_len ) | - put_field( val, dib->blue_shift, dib->blue_len )); + val = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); memset_32( ptr, val, rc->right - rc->left ); } @@ -5112,9 +5065,7 @@ for (x = left; x < right; x++) { DWORD val = gradient_triangle_24( v, x, y, det ); - ptr[x - rc->left] = (put_field( val >> 16, dib->red_shift, dib->red_len ) | - put_field( val >> 8, dib->green_shift, dib->green_len ) | - put_field( val, dib->blue_shift, dib->blue_len )); + ptr[x - rc->left] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); } } break; @@ -5221,9 +5172,10 @@ for (x = rc->left; x < rc->right; x++) { WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y ); - ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) | - put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) | - put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len)); + ptr[x - rc->left] = rgb_to_pixel_masks( dib, + ((val >> 7) & 0xf8) | ((val >> 12) & 0x07), + ((val >> 2) & 0xf8) | ((val >> 7) & 0x07), + ((val << 3) & 0xf8) | ((val >> 2) & 0x07) ); } for ( ; y < rc->bottom; y++, ptr += dib->stride / 2) memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 ); @@ -5236,9 +5188,10 @@ for (x = 0; x < 4; x++) { WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y ); - values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) | - put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) | - put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len)); + values[x] = rgb_to_pixel_masks( dib, + ((val >> 7) & 0xf8) | ((val >> 12) & 0x07), + ((val >> 2) & 0xf8) | ((val >> 7) & 0x07), + ((val << 3) & 0xf8) | ((val >> 2) & 0x07) ); } for (x = rc->left; x < rc->right; x++) ptr[x - rc->left] = values[x % 4]; } @@ -5252,9 +5205,10 @@ for (x = left; x < right; x++) { WORD val = gradient_triangle_555( v, x, y, det ); - ptr[x - rc->left] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift, dib->red_len) | - put_field(((val >> 2) & 0xf8) | ((val >> 7) & 0x07), dib->green_shift, dib->green_len) | - put_field(((val << 3) & 0xf8) | ((val >> 2) & 0x07), dib->blue_shift, dib->blue_len)); + ptr[x - rc->left] = rgb_to_pixel_masks( dib, + ((val >> 7) & 0xf8) | ((val >> 12) & 0x07), + ((val >> 2) & 0xf8) | ((val >> 7) & 0x07), + ((val << 3) & 0xf8) | ((val >> 2) & 0x07) ); } } break; @@ -5437,9 +5391,7 @@ color_table[i].rgbBlue; else for (i = 0; i < 2; i++) - dst_colors[i] = put_field(color_table[i].rgbRed, dst->red_shift, dst->red_len) | - put_field(color_table[i].rgbGreen, dst->green_shift, dst->green_len) | - put_field(color_table[i].rgbBlue, dst->blue_shift, dst->blue_len); + dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]); /* Creating a BYTE-sized table so we don't need to mask the lsb of bit_val */ for (i = 2; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) @@ -5785,9 +5737,7 @@ ((color_table[i].rgbBlue >> 3) & 0x001f); else for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - dst_colors[i] = put_field(color_table[i].rgbRed, dst->red_shift, dst->red_len) | - put_field(color_table[i].rgbGreen, dst->green_shift, dst->green_len) | - put_field(color_table[i].rgbBlue, dst->blue_shift, dst->blue_len); + dst_colors[i] = rgbquad_to_pixel_masks(dst, color_table[i]); /* Special case starting and finishing in same byte, neither on byte boundary */ if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7)) @@ -5923,8 +5873,7 @@ get_rop_codes( rop2, &codes ); for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) - dst_colors[i] = rgb_to_pixel_colortable( dst, color_table[i].rgbRed, color_table[i].rgbGreen, - color_table[i].rgbBlue ); + dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i])); /* Special case starting and finishing in same byte, neither on byte boundary */ if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7)) @@ -6063,8 +6012,7 @@ for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++) { - dst_colors[i] = rgb_to_pixel_colortable( dst, color_table[i].rgbRed, color_table[i].rgbGreen, - color_table[i].rgbBlue ); + dst_colors[i] = FILTER_DIBINDEX(color_table[i],rgbquad_to_pixel_colortable(dst, color_table[i])); /* Set high nibble to match so we don't need to shift it later. */ dst_colors[i] |= dst_colors[i] << 4; } @@ -6160,9 +6108,7 @@ get_field(dst_ptr[x], dib->green_shift, dib->green_len), get_field(dst_ptr[x], dib->blue_shift, dib->blue_len), text, ranges + glyph_ptr[x] ); - dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) | - put_field( val >> 8, dib->green_shift, dib->green_len ) | - put_field( val, dib->blue_shift, dib->blue_len )); + dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); } dst_ptr += dib->stride / 4; glyph_ptr += glyph->stride; @@ -6247,9 +6193,7 @@ get_field(dst_ptr[x], dib->green_shift, dib->green_len), get_field(dst_ptr[x], dib->blue_shift, dib->blue_len), text, ranges + glyph_ptr[x] ); - dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) | - put_field( val >> 8, dib->green_shift, dib->green_len ) | - put_field( val, dib->blue_shift, dib->blue_len )); + dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); } dst_ptr += dib->stride / 2; glyph_ptr += glyph->stride; @@ -6376,9 +6320,7 @@ get_field(dst_ptr[x], dib->green_shift, dib->green_len), get_field(dst_ptr[x], dib->blue_shift, dib->blue_len), text, glyph_ptr[x] ); - dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) | - put_field( val >> 8, dib->green_shift, dib->green_len ) | - put_field( val, dib->blue_shift, dib->blue_len )); + dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); } dst_ptr += dib->stride / 4; glyph_ptr += glyph->stride / 4; @@ -6458,9 +6400,7 @@ get_field(dst_ptr[x], dib->green_shift, dib->green_len), get_field(dst_ptr[x], dib->blue_shift, dib->blue_len), text, glyph_ptr[x] ); - dst_ptr[x] = (put_field( val >> 16, dib->red_shift, dib->red_len ) | - put_field( val >> 8, dib->green_shift, dib->green_len ) | - put_field( val, dib->blue_shift, dib->blue_len )); + dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); } dst_ptr += dib->stride / 2; glyph_ptr += glyph->stride / 4; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/freetype.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/freetype.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/freetype.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/freetype.c 2017-03-21 14:02:57.000000000 +0000 @@ -7914,7 +7914,8 @@ font->potm->otmfsSelection |= 1; if (font->fake_bold) font->potm->otmfsSelection |= 1 << 5; - font->potm->otmfsType = pOS2->fsType; + /* Only return valid bits that define embedding and subsetting restrictions */ + font->potm->otmfsType = pOS2->fsType & 0x30e; font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise; font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run; font->potm->otmItalicAngle = 0; /* POST table */ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/gdi_private.h wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/gdi_private.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/gdi_private.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/gdi_private.h 2017-03-21 14:02:57.000000000 +0000 @@ -200,7 +200,7 @@ extern DWORD stretch_bits( const BITMAPINFO *src_info, struct bitblt_coords *src, BITMAPINFO *dst_info, struct bitblt_coords *dst, struct gdi_image_bits *bits, int mode ) DECLSPEC_HIDDEN; -extern void get_mono_dc_colors( DC *dc, BITMAPINFO *info, int count ) DECLSPEC_HIDDEN; +extern void get_mono_dc_colors( DC *dc, int color_table_size, BITMAPINFO *info, int count ) DECLSPEC_HIDDEN; /* brush.c */ extern BOOL store_brush_pattern( LOGBRUSH *brush, struct brush_pattern *pattern ) DECLSPEC_HIDDEN; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/tests/dib.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/tests/dib.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/tests/dib.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/tests/dib.c 2017-03-21 14:02:57.000000000 +0000 @@ -32,9 +32,6 @@ #include "wine/test.h" static HCRYPTPROV crypt_prov; -static BOOL (WINAPI *pGdiAlphaBlend)(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION); -static BOOL (WINAPI *pGdiGradientFill)(HDC,TRIVERTEX*,ULONG,void*,ULONG,ULONG); -static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout); static const DWORD rop3[256] = { @@ -106,7 +103,6 @@ "8b66f14d51ecdeea12bc993302bb9b7d3ec085a1", "7da9dd3d40d44d92deb9883fb7110443c2d5769a", "e358efb1c11172e40855de620bdb8a8e545cd790", - "9e0c2596c6ecb4f1bc97b18ec3ca493d37626608", "58806549380c964e7a53ad54821d2eb86fa5b9ce", "7fc30d3058c235ce39088de0a598b8c7fe7ca61f", "52a6c769c227f2bb1949097c4c87fed5ee0cbcb1", @@ -131,6 +127,7 @@ "d7e34fa02db7ad52327f80389bd1ba1b72b6c692", "d7dd4700f49808541bba99244b7eb5840e0a2439", "00b4e9b243a36a7210a48bcb7c2d410d9cd8c8c7", + "8eb1f99d21a84153e88e7958707049d517ab7641", "af99228aa4cfbd1f61bd824db046144a3c6c2ed7", "568f87f0194ca19b69a5b2bcdef795d89c5721ce", "a37810f46dee8741fe5adbb3f1f2e87012ffc929", @@ -142,11 +139,8 @@ "eca1998a4d79fb81b2a4103f79e3b846a864eaaf", "e4acfcf2d001fbc431d9af59ab3d3ca7c2d965e5", "2b3198bd5c0a87db5dab13df8bbe14363d02acec", - "f115ef8392ba82d8cd6e7a039320edcd812c1d28", "aebb1b3baa4fd5213bf80a5ad7a50d54de8fdba4", - "f451a05f699ac3bbe155d059e7871a2636887b5f", "5dca709c60e0cd50fa85274a2836aec9eb6168e3", - "dccaef62738ff90da4554a85d8cb846d6436799e", "cc4e1372ddf6e303a7fd159090c9d3a1f8ec2a89", NULL }; @@ -180,7 +174,6 @@ "8b66f14d51ecdeea12bc993302bb9b7d3ec085a1", "7da9dd3d40d44d92deb9883fb7110443c2d5769a", "e358efb1c11172e40855de620bdb8a8e545cd790", - "9e0c2596c6ecb4f1bc97b18ec3ca493d37626608", "58806549380c964e7a53ad54821d2eb86fa5b9ce", "7fc30d3058c235ce39088de0a598b8c7fe7ca61f", "52a6c769c227f2bb1949097c4c87fed5ee0cbcb1", @@ -205,6 +198,7 @@ "d7e34fa02db7ad52327f80389bd1ba1b72b6c692", "d7dd4700f49808541bba99244b7eb5840e0a2439", "00b4e9b243a36a7210a48bcb7c2d410d9cd8c8c7", + "8eb1f99d21a84153e88e7958707049d517ab7641", "af99228aa4cfbd1f61bd824db046144a3c6c2ed7", "568f87f0194ca19b69a5b2bcdef795d89c5721ce", "a37810f46dee8741fe5adbb3f1f2e87012ffc929", @@ -216,11 +210,8 @@ "eca1998a4d79fb81b2a4103f79e3b846a864eaaf", "e4acfcf2d001fbc431d9af59ab3d3ca7c2d965e5", "e4f110504dd3e4e34f960a39ba91a91c67bf26af", - "f115ef8392ba82d8cd6e7a039320edcd812c1d28", "aebb1b3baa4fd5213bf80a5ad7a50d54de8fdba4", - "f451a05f699ac3bbe155d059e7871a2636887b5f", "5dca709c60e0cd50fa85274a2836aec9eb6168e3", - "dccaef62738ff90da4554a85d8cb846d6436799e", "cc4e1372ddf6e303a7fd159090c9d3a1f8ec2a89", NULL }; @@ -254,7 +245,6 @@ "9aa506e3df33e0d5298755aa4144e10eb4b5adcf", "abdf003699364fe45fab7dc61e67c606d0063b40", "89abaadff4e68c738cf9251c51e3609564843381", - "f6aa3f907f620b9f3493f03cb3b4b292df3a9545", "77d0ad32938147aa4038c1eced232b7b5a5f88f3", "43d36e57b702ce56eb250bf53f1ecc4680990cfe", "fd6e0ebb52710ebcdd8dd69931165c83c4930b41", @@ -279,6 +269,7 @@ "eac5d164b83edf2cf85bac242686f9f617ec1fa4", "86c84cc8306975edecc6d4a89a8aff29f59b55a7", "698d6393e97539806351368f95be478c6fbc62b0", + "c272d1e0342e6089a0182dc42b37e47889116a9b", "af99228aa4cfbd1f61bd824db046144a3c6c2ed7", "25675c30adfe24d6cae60793b156dfdaa36ac3ba", "849d4abf4b690128a5f70e9b8ac78f20c437de06", @@ -290,11 +281,8 @@ "b76e0724496e471b01ef8b34f8beba69f5bde261", "34201d3d3583f89ce3267d3d0c4e01c64463de4b", "693f5c5fbaeaadb5928d34b035499626fecb8394", - "8a9aa84c42dedc3e681191a1229846887ed262ec", "66041875232f64dbfd2d18353aa28e43e8ccb6b5", - "707bc44fc9fed68ff1f537f0473e0cd825dd660f", "f19f5d8e2c96328f06f3985d02ff474fa37b1ea8", - "175a7bcb73c74eceecc000657a0100bccf158ff4", "d26eeb6b2d345b587d4305a1234ec0842a96d4b6", NULL }; @@ -328,7 +316,6 @@ "d578210815e27fe210eb678a71e6d22ba4b4c196", "c7a027c7079dfcc831ca8bc134a509958273073c", "19cf978596195b848df8709aaf637f83f92b8336", - "798a835fe50156eeb478c0a6085b088f53409d52", "86ddf268d854f37e5b478c48792b551b57635db6", "8259d388e02542207b6a08d65d553871ce1c4a09", "faea73ff9436223f8c4ee76ac9861a6609ac4ae4", @@ -353,6 +340,7 @@ "5a713a91fd471fd331bd13b0868c994aa2ffe2b2", "fc0c32afb719295f28bcfef22803bef94f798e20", "bb2a421bab95f9b5420704ef44c0f3214a0b5a11", + "7735098af7535d8c57266190a13f92d8869e8529", "36f6db4fbe2a1630a7597d3a446f2902755c96ef", "d3f08946300e1700865042aed121870e292d1095", "4782df8e24127e66a434b4e839adebf2dbb223fb", @@ -364,11 +352,8 @@ "555b6f04ba8dec9e2a60693dcaac594227052727", "c199b96a71c3aab2d49ccb5b6294bf14eb0dd1eb", "4238fe9d296b5c72b0a8745cc761f308605b2094", - "943dc6033ab335a6a63e666f70a6bb3a0677e157", "88b6427cf71a6b9a26bfd6026103d50f721651a9", - "88cfa7b7c1487f8eda05fce92b622942c9fb7ca4", "64cf929548bc5324fb14b053077bf5bc4be3e15c", - "ad91dde8566dceaadc3523cdc8149cd7415a1b70", "1936661eee8073068506131c9e89265b2f8403e8", NULL }; @@ -402,7 +387,6 @@ "66b130f83381957cfc4763558c5f5cddf2e3b564", "d548135ce2320499277ce12b80bc35004f8a9787", "85a4f3f1b4b0a170198f1bb5d225fcf77887665e", - "1906ddfd829e735af49245171f8eb7673295d399", "971a0b786d5bccb1bfb9cbb054740e4eb36f9b7a", "e2896035f178b3d20e4f4d1accb1b3d1b4028865", "defd95a10d44cad6e736542920b74efd53e9e7eb", @@ -427,6 +411,7 @@ "8ad5cd520cd628b76d2e5a3f318ae1bbb6b4c994", "49341c297a887186bd47d7465d827ab3147f05e3", "514c07281ef6702c35e68b230e897303a8cdec81", + "4b41865829b50b2e29beda51b055bd1f908a649c", "325279e76367200d3fd7194d81c09fd139988ece", "c3def160a1e847605ff0fc7edd30397fa90635a0", "2b3e87e0b705b03c7c08f403409ab82cce095ba1", @@ -438,11 +423,8 @@ "3d0853f4f7580d7cd5148c21c34d878ecf39a5f3", "1e5a4ef7f8634847a251d1fcce298c409fd13d87", "481337fbedf181d4324bf7f8299b0327197ff468", - "9ab957870fa4e17aec6a79bc1a4fdb42a5ffcc30", "b4b9f0bf127ef11f510f25684ae21d692609c85e", - "8e32ea3614c3b20899d748db48258761c7158d2b", "5da35bad12e3e9b26a0444d30820099481281e45", - "94f004e98ae8035af948611770a4a2dd6643f510", "045ddaf752e7ffc7ded792f36af3c7c0cfeeae42", NULL }; @@ -476,7 +458,6 @@ "8bc3128ba47891366fd7b02fde7ca19100e64b9f", "e649e00efe7fea1eb8b17f7867fe089e5270c44b", "a0bffbbfb0adf6f188479c88da04e25d76ab4822", - "92a1ab214dd8027c407814420449119466c92840", "b58f19c1800344a2b8e017eb784705bdb2bd8450", "5747a6d5c6ce79731c55e8cf33f7da3025cd35fd", "955390669afed2369b15b32fa519f2f921cdf1a0", @@ -501,6 +482,7 @@ "5578c80048520732557abf3a3a3fa22c85015d7d", "b25ba91487ec945410deb2b51bc1156890c032a8", "4c8c936372755f95051f1159b7ff65a484e1a555", + "bf55d4bdb26ae0f358bd67ef01932563519aab98", "d347ca5c6c4b6a61389247c3b6f61564033e8c25", "ee315634ed92da3a32c2675ecd1b369471c60936", "099c688a920f606655b485e8f0a433dc811bc976", @@ -512,11 +494,8 @@ "0bbdf0a0489428f96e3c1d3e5305f9a893820852", "9d86b1b2bbce90efd3c0b9fe20d23ffa3eeecd20", "8f7a0af421101952e674f37154c1e8c4646ea2d2", - "e96b79bf88988b5694a04dfc3bd0029361b39801", "d12284f58daabbd173dfae6c7e55fd5d822d89b4", - "09cb4ab070083144bed4271c0a2a34ccb6ed13c0", "cc5ed4c9e925f0a457a7437fbb8054528cdd9469", - "c95afd0a020e68a76982fe8663b5d64113987233", "48658ff76c137185c56a53f3ccf0e958d0296742", NULL }; @@ -550,7 +529,6 @@ "d7d97e28ed316f6596c737eb83baa5948d86b673", "ecc2991277d7314f55b00e0f284ae3703aeef81e", "656bf3b7121bcd620a0a3ad488f0d66604824577", - "d7d8493b5fa7a3a8323d6ac84245093a79f052c1", "df5dafe96e528c2cc7fd11e4934e298f53cec34b", "a49530722328ae88fd765792ac0c657efbcce75d", "aa46aa2226e3121eaefa9d0836418e0b69262d69", @@ -561,24 +539,20 @@ "7df915bedcc5951a1b6f828490f7dbb93212e835", "8720478d904a84c24071e97c731c1ba7882b131e", "76215275593631f5900aad3616d725733dc39493", - "81655a550703849a616d4a16504bb9c6f999285f", "573d65665d20f00d36d9782ae2b89772140524ab", - "619414c1b33ac60cb0c0de61df86245d472259b0", "c3d4a1425e17de9e05e3f6dfc6a24c26bfd5ee12", "2a66dae03890ff791eabb982949435adb19af02b", "24ac219478ba406f30794550690486b14cbac5e8", "2b28d20690dc92374ebecb5508f8fdc6c7581790", - "db8c34882ddd46716d14bbf569d530f80db65ed4", "6c652ecce55e71fee16bc1c9b2c5ae4161bdd2ea", "9b02173f424c098ea0f4cc5db9eb65f69263d127", "a92942269911a88793b3460b6f2a2cd56e48eec1", "059db9f0426b371e464ef3d30f1a4f4aa599e101", - "a52d6ceee5c2a04b4e059c0d49337a997cc17e40", "aa4a0a4b7f2697aaf270c89874631974bd9d7183", "a7506e2c001d271593297c9eda9b984d4d894774", "8f447a3820c83662086dfa836da2205b0130fd5f", - "3772003c7fb420003512d0c437b3659d96d89ce4", "2ebf37d81da3f11434652d06bf65d55e96b090aa", + "ace2c60bd76b11a002bee852686e8783f102eba1", "dab47c9dc149e570045d699598b14a613bf319b3", "2daca4d26a086ed34894693be0b0374402232809", "904f1d82159bcf5485f323bd12b859dc5e83f8eb", @@ -590,11 +564,8 @@ "2230f36f12d4becb242e2962fa1b3694db2496ca", "d81e41a765d7a2d68073f5fde3f74f09df84001d", "0de013c2c6aba9f99cbcf5f8cfd3212ded7ae72a", - "5950f7d00cd8692872377df0e869a7d5ea5e4420", "fedc67d1b0797be5f40cd45280844f2b61d29b0a", - "7de23c68ca224818fdf127c5e96729dcd0de2b8b", "a848b1b0293b05b3f9358a3ffcb21a2e5fdecf05", - "1a0fd0df17fa4c455a4a91cad30b5242f77fd233", "af45bf81d119be5cf6845ad41191ba52637e65e9", NULL }; @@ -628,7 +599,6 @@ "0e183a4c30b3da345129cffe33fe0fc593d8666b", "f14d9a4bd8a365b7c8f068a0dad481b6eb2b178b", "8933450132bf949ba4bc28626968425b5ed2867d", - "9928a8f28a66c00069a124f7171b248817005763", "e4a9dcc3e565cd3a6b7087dd1433f3898bb9cdb2", "eca4f9b16b3bddfd0735fdd792e0ccaadfb9ba49", "233e588cf660e2c9b552cf02065cf63fa6655864", @@ -652,6 +622,7 @@ "104e85bad287a62dfe25f0e78280179f18bac765", "f0acb3cfcda62e95bee5f7bc8830ffeb3dd7e5a7", "fde993dfce1551ef220f5a07ce4acd66e8524ac5", + "a80f3df0aea1e1b30d9833039157bca658218f48", "07b10c3f191d0a93e5e5694aae37dcad407e10f5", "f7900e60347029876ba55e8f0c4c02e89deb36b6", "f373a5f37b82e7523c64c08eb509b6191e49b173", @@ -663,11 +634,8 @@ "13d1634e03bc49cfe14a32278d9b1f5ddbb9be10", "a79e4cc419b9e1735e275e2823da52875536943a", "b0182002cb1f4fba9df3c21a4d046ab41ce7e9be", - "3830cd728c1e72837310940bcdac4e294d6c9843", "f571c7c4aac92491017963032194690c0fa06b42", - "6fd751b7328c02954bce98bed94b3ce3c73db118", "91d50b5a604d6c38aa0d08b9af995490f8ec246b", - "8585783d0373e9696b508776b6e6b18a80b09888", "b53cde47b0e28063770d3b1328c3cc2f774a6300", NULL }; @@ -701,7 +669,6 @@ "1df851515ecf46df5c2d3279535c1763f72353dd", "b68922915ebc2797d58deecf983f7d0cf9a5efbd", "359bd76088a965bb0cee7c44800bc46b2638807e", - "e14e5734b33057b890368f3e9d482d9e5a0358c5", "64205ccaa277e64eeea0c20e99900ac79858ca2c", "2cdee35d43d62da09b4ddfddbd0948ddbb9fc48e", "91f988f575338505ba8a40727865a8d3f2298624", @@ -711,26 +678,21 @@ "4fd49cb49853ef950fd0b7e2e35718a71c8374c7", "e15a355fc09bfd22267917898e2266168ff410e3", "7a9c326a56a94621377a7258be70ba50042ca9a2", - "5e38e03310f1c66f2052af2a745d8c60515707c5", "f994fb5019bf4c1a96eccf89af599eae0aa6b412", "3a71ad6fef147067641e49a5f69b2454e3a5010d", "ea10eac72830dcae19bcb16a076c2b21d844b5b6", - "6376234f542467e5887adfece62f753e998dc19d", "add949d009217ef2b847e34772ba363e4be7b1b8", - "28fcf9f7d098c05de632ae38b2fe33b9635ad445", "0b58666deb3615e912896a764e5c6475989e95e4", - "bf460cc44c0edee851d72587c8425c3f06a62c55", "ea74c00c45569007383b632d7f1d2adc82645717", "5ac22e1a33b0204fdc7a68d54ee94648e96079a0", - "284abed096637c80bb50844e393da9dd4b3f19ac", "9dc776c5ab8256b1301c7d1da60544a9410e6715", - "a433c41c05b6db008a4cb2c52a321d027c6be1fe", "46f772c2832b3aad584674db666bd63e48b4f338", "a9f9ca0049235db51ab7359a5fc3d21be42d2aac", "f3dc739da41fb299637c8660e8c46917ddcf87a8", "abd2fff80f74b311072ecdb91ce9ceba268fa6e9", "9ae38bb94c7b4c0c6dfebbee23d1de4db9b77488", "8269b32b4a34440f1fa37927308debc7eb85f3fa", + "65b2c868790806be7ab4aaa6114d445c42a31f98", "678979a45126a76eb629992cd64734862f53a555", "2f7ba8803604c032cb1a1228bc021f0f1c03e245", "52e7c2f8b01592898c13f1e7633881e350244209", @@ -742,11 +704,8 @@ "5e9e3e71b06c5efe20f93b3838e745b40b878471", "153ae5c9fc2a31b38c4878b25d9026b9f51f132d", "488341e88810d737de0b26de4e4d4fa0e78eb482", - "bd1e7f40e3971e2ff6c5561286901193a1557527", "5a42b7eeff8198e7b005e4afa4282e6ffb939906", - "d7ffa3893c6fa937569791cf49986518a4a4d96e", "26bc25a011e2b60961ee9d6c6141d928ae24389b", - "8771d5ff7b93b9dd9d077e672b342235dfb28472", "6a1f6e1d494bf6b0ece7af5fa164ebaadb3a19bd", NULL }; @@ -769,13 +728,9 @@ "114bb377b4e78a1978e1ac09388c48861b5223a3", "8d0a92e6333e1b99591962e2def9bc9121111cf5", "9dc511d6947fe816185cdff93bf0cfe0349b72b4", - "eb4c14ee66b012187f5fe6a2ec28b6be956567c8", "216388ddf6b563dd2058a9df65b40b6f72df1715", - "ad11e4b6979cf055e3bf1868112a7bef207385a4", "47f72be971bd2d3399dabd018201f4f5075e96fe", - "de09d41c9ae4338fbfcfe9f8ed71d343537a6f3d", "f39ab890a2b99d0c31e6e047f2315244972f5ffd", - "6e7baf7d328bc2c55366e32967a0db4d2f43ab82", "15b991814d84d6aa252696dd0c6150ef88a8db3f", "1cb52f2a4d17b9b0d8375d016aa8cf0677fcd29a", "9a6cfd68523e40ea1d52847d7747da912cfe2ca9", @@ -784,7 +739,6 @@ "15db343049e3a9b31addc5d2ffebc3fe91b39c51", "a895daf1f20371d4d1c3f93c070124cc13e341c3", "3ddc872384ed8f9eaef472aa14a1d79a2c3f3b04", - "0000000000000000000000000000000000000000", "bd7d8c1cb4b2adc31cf8c7d39a4fa1e3ac7f2545", "33fc8618ce62f5cdd9e06ad61e296f718a99899e", "dcaa7fe030ae4d3029e38ca584047eeb2d17fe10", @@ -794,26 +748,21 @@ "650a51bedd1af92469d2950eb95220db35f95c6e", "3f43aa11e6fccb747cc13224583fb2f951fee08c", "b83f78ae85df87fc7af565db276c60c102274f20", - "6b6f4b97f05e015eb37a5f6aff637235feacd030", "1bd06e4e11929e5e91c3c9f20def639b20e731e8", "d63a6086547e90d2ba84aaebfeae24f3ba0c04f1", "85425940daf119125deb52421b2057acebe6d1cf", - "a3db92382cf0a4c7cafe52c27b1f41520aaa677d", "9869b6f088822fb423996f9968e5a931301fc2c3", - "cdf63ab4ab32c2e8e27527a9588d0fb525f1c945", "a7f81cf3326fa3608acc13cfce2f573912e9d745", - "f2ea92f523f8918b1d514a2d9555dcb4750273b4", "e9c16e43a8f589ae85289c5c3ffea6b22fba1806", "84a4bc0c2c5d36d016da4df95a5d8d6c8ce3ba6f", - "f543efc84e638afbaa456e629100f0274de1a35b", "1bd2587399006eed0d46beff397d32081f6bc58e", - "f8a571de89ed82ffb9cbc041ce1eacb064be2853", "640a49455acabca6954a7fbb6af4e872af342d11", "589e7911e09332ee090371deae17b0120ff990b5", "a1a941fa270cda48c648553ed4b427e16e96f8e0", "115c90df05b1ff754dbdfe2a712ef126034d952d", "fb63bbb2f944fb63ed2d7399f07b168740c1034b", "ae45f0d463ff916f3cb630103969fd49e8d09ef4", + "2becf041f83d22ac072fef5e0efd9bc1572796fd", "3685c9ae95118a83db3569832c29753276fa1264", "09640bad951c33e7d70a1fced83b1869f65b3fc5", "5eb00252664ec39e61359adb1dade4906a87a248", @@ -826,11 +775,8 @@ "55d302ece31a9b7fc4be4a07a53767ba210273e7", "a6a29836291f9dbca85e25cee60f62ef5faca6d7", "3494a23633405e46af96cb57715617fef1ac252e", - "5a3ae1da30d83cc157e6a4a5617c85598309f4ac", "edc1ad2704452354aa6f79fac244a55b6f509c2e", - "87eab8f81fb2a036080e099760f628037f9306e7", "a3eac75d30f681b3898ee469d368960529634d7d", - "cd5caeabdb71241766d24f038cfc5f1e91e11256", "e2b393dc3f5833f7868668ea31369e90348768cd", NULL }; @@ -864,7 +810,6 @@ "3caf512cfddfd463d0750cfe3cadb58548eb2ae8", "4e5e7d5fd64818b2b3d3e793c88f603b699d2f0f", "c4efce8f7ed2d380ea5dc6fe1ef8448a27827532", - "bdc0a354635b879871077c5b712570e469863c99", "d599bf210423fe3adbb4f1de87d9360de97827d0", "bae7c8b789e4e9b336c03c4daee3bce63fe039d9", "cc01f17928f7780cefd423ea653b072eea723a1b", @@ -874,15 +819,11 @@ "9a603513cd81acf70cf8b27b0d544e7f672e9d40", "f4a334e69535de74ee5ed54be93a75120a66e54a", "f751a55fb738b63b6fd7c229c33ef92605d0c9c1", - "995f77f2f53398399f09d1365cb4dfd105764e5c", "61907a6685bba93077da40cfb28cf2ab74552fd2", "122015e5e17c1c317c6e51c0e207826b606a4077", "c21851589a5f8a45ea5f9bb3e72f4f88d0a6697d", - "8c609921d4a3ed89a994a75482b27496bf103cf5", "eb2ce16a6ae251f4965135ee776776b5fc02c42c", - "66493ee117719e172f327a426af601996025f28c", "acead2745fec0b6c817fa601353bdf2d197b64f7", - "a6b858b2d125c159529d3f3ec45b31925a79acff", "1f1379089d7c6e8d733aaa4eaffbe02db6255b61", "d83adc669c0dea0dc4812b93f998514b6f02d805", "9e8ceb7c3cd68e043b6d875c8c84a1e394962412", @@ -892,6 +833,7 @@ "5a1d8f9ea978b820edbc5c9e1c6f1cac022620ad", "31e667c2dbb81dcf81d01cb88f794e88ddb90ff2", "c404446958788fac00ee1eff571d682bc21dd7ac", + "95060f3dc9e6d01ada42f09a871b69f0699cb77c", "465d9cd0a77ab4fcf035aa67544b2a26269e0b09", "600d6b2713d5e4c0d90c02660245ed26c7ae3033", "0025a440866a404523a8a20e79a8891e45a2ff56", @@ -903,11 +845,8 @@ "293c41a7ed923a4617560481ae8815cebf83701a", "ec06b56f3abe277be42650ebd49dabeaae9e756d", "750c923785ba2afb9ce597516c072f90f014bf95", - "80089132f8a11d86e8038f2f8e12dfba46624ee5", "bde5a62a065c027561226fbec5155e938ba7f6b3", - "a6311d74fc058079a327abb536e69353be719925", "fbaa8848a1d3896469c37fd43ab44233f5b875a3", - "0000000000000000000000000000000000000000", "c2ac98ef716fd8a5ac8f08ce66293d9a96344337", NULL }; @@ -941,7 +880,6 @@ "26ad5116562e7b58c76a26eaf521e2e40899e944", "1bcc54eaf8e3c2b7c59ecccb23c240181d7ba8b8", "4f827ca6927f15191588456f985bf29d2a3b3c24", - "e7de769c3d12ea9dd223bef4881c578823bec67e", "6fb102d020e5554116feefc8482104f3ae2036d2", "ae546ffd30b837afc7dfcb5c9ce4f01d15b35ddc", "20c9eb3276c08fdce35755e349bec94b04929812", @@ -965,6 +903,7 @@ "c644f460937107214a88d5eb9e846d27abd8c874", "df5feb905a31c288008cf5e82d73ac818a160d82", "4f9658dde0432a711a4d783c1b5aa3365fb7d54b", + "09438163dcbede3890a0e6d8e614c97a06759380", "d8af3868c66c7d6dac35ec8ee0317b38a6910bb1", "ec8e2aebfb4a1c28ebcd0e053b9e4d8638b50951", "ccf8d11b1e81895e9781f17c227c821228d8714b", @@ -976,11 +915,8 @@ "287ea7db721e641439888cb9f4bac3a5f16124eb", "dd9eaa5325cdf250e89162ac84207978ebb6458e", "42466aab11852741d937c1ff6f3bb711e58415a6", - "0663cf6330591fcf744aba96664e05d90243d07a", "3024fa38333f83a639b0f0e6ac6d4b9868231157", - "6fe7d0d17b892032cfd171c3d7c365f030b5be38", "7ae780dcc7cf04dda50648bfc07cc6a7a2f2189e", - "0000000000000000000000000000000000000000", "9ab46e0c42f82dc73df8a55cbf881abd72397cec", NULL }; @@ -1014,7 +950,6 @@ "afdf41fca7951c6dd6193320de1295f2c68fe52a", "f2f1f331fe6b1b31d7c9ddd37793b375fc01d3d4", "f0af0f1edcb837bdf1535c1f5e9988c21ae9bfd1", - "0000000000000000000000000000000000000000", "71c4577baaf35f12f6707b1e2f78a1e8c0d41d0b", "9b7d6b12385bb9e1cd881758aff342bd5427432b", "6fdd5aa022da2a8af6f1d02b6072ebc068b4b600", @@ -1038,6 +973,7 @@ "30c256a783c4874261667bb31307eb282ab9470e", "f8681c09f1abfc38d31e47622cb8798cd896a00e", "0ba7e5d68419702605739acb52fcc01c96cb63d4", + "f8d2f196ba8a16f54acb934e61a759ab7d3f2f05", "b5ee51cfc73acb59a2f6124509ea236f8fc7f9f7", "d374d4d92c940ae42a9b42c14d744341b68a8c14", "06a6a224be0f5cdc51ac4704f9f57fc1f3813d6f", @@ -1049,11 +985,8 @@ "aa89612798fbc4e11a73b6233c0ac4832e6af2f9", "c96a998be5c1d588ef1243cfd2610d056d16947e", "68bee638d59a373f33f308751471b3ef41849582", - "be0501175cc3cbb61217fca76356f761117fb40f", "8fa37e26cdae406c2d1c81b1175dcf0311cf60c9", - "3efe128a5bf250f2c460664e8f543f5ec54d5dc2", "2d5123e757cf00e423a89160d7dc4997c3688829", - "0000000000000000000000000000000000000000", "36dfdad9f3f5cfde6add3cef23368c343d30469a", NULL }; @@ -1076,34 +1009,17 @@ "b0cc1f5e244ae0c0835a9866a46abdfcd56d1cb1", "7ddf19df5bbdf4475b6ec1bc042425e382502864", "144c9a846e5e37ac6efd5ed3a97ec231479e8fca", - "c5ffc59048bf786b5646ad6226cd8633965de9ef", - "40fadc2d24c713b04ff96f7dc26e70e85f26c55e", "400a21caa01e015096ee1afcf1b54e7f8ec515bd", - "0ff4b49797e30e3555aab45219adf449a9a560ff", - "280327328ca940c212ce24fe72e0b00014072767", "144c9a846e5e37ac6efd5ed3a97ec231479e8fca", - "b85463875f755b85f1464b1b6275912bcbad6c9f", - "816f200969feecc788b61dfeecf05b1790984401", "a4964d8bbf80fe785f906bc0f7c5b113242a58fc", - "a5d204cc7342d40b765ca042f8668e22601c4ff9", "adb2818f6d3845dd140bc0f9abdbaa89d2a8c3de", - "0a76e0121facb103857130bc6e12185ad77fc3fa", - "02aede714773d654d0fc2f640afaa133ec718ad5", "13cc63972aee4f6ae27091a8af18de01f1d3a5da", - "3bb745ccb08402ce6fac6ee26fb8d7aad2dba27e", - "b26699f62661e16a1dc452d24c88ce363a1f2998", "4d95c3d1e170f004c80aa8c52feafb8e0e90760e", - "c14832e69ec3585c15987b3d69d5007236fa9814", - "e44ea620b0c47125a34193537ab9d219a52ad028", "ef2db9fb75a672f69bab88e5d08fe64f50ec2bc4", - "df81db2a9b3942a82e0dc5e57247b642f9b42702", - "8819bf7a43295161fe045a42936000b3a51fe200", - "e08dbc26469c229f75ccbf1a38a133401f270b84", "d1e6091caa4482d3142df3b958606c41ebf4698e", "07c1116d8286fb665a1005de220eadc3d5999aaf", "4afb0649488f6e6f7d3a2b8bf438d82f2c88f4d1", "f2fe295317e795a88edd0b2c52618b8cb0e7f2ce", - "ffc78c075d4be66806f6c59180772d5eed963dc0", "c86eeaeed09871dee4b43722ba512d2d3af7f4d0", "24b1a6241c81dbb950cfbe5da6798fd59eb36266", "1007d3b531b4bc3553d4547bc88443fc1f497cf6", @@ -1129,6 +1045,7 @@ "41a417c1f25f2619301afa44bfcde85198985792", "23366004515f3bc46796ea505d748f8d0f97fbe1", "ba682eb15c0ddffb942e6086e0ccad2353ed7241", + "58273e1fbf961ff2c772d57160d60170e258d3fe", "88763f8e8fcf4f78fa864325791a9dd35a0bd279", "013cee26bac8f815eadad4bfc012d9b5d01c3b7f", "44a28536466dc895feb824b23dfd4a47c6948af8", @@ -1140,14 +1057,8 @@ "53ab1fcccd09fa5cbff77497f36a70a3b3cb8b81", "4842a30dd7fdf38ddc3ddec85c08efe13a0e2e0b", "cc76db6da5ba1776f20240a5ad97a26a9cdf96b0", - "014f477664a7f4ce4a948d6359a2707119afc8e2", - "74d01690e344bc22e7a0478e7a09ccd92354c486", "9ab50a663b74577b656e9849484a909d7ac52eeb", - "128eefd2ee043d59dc37918065f687e378e5ca95", - "d7e2daab98ce1f698c4bfedfc01c0d79fcb76b8e", "8d34215487088b5d4ef63062270ce25c2862643d", - "826562eb11a0d0bba77fa21245f7406a194e9225", - "bbae6f0659e095a42b420082079663f937065813", "bbabe686a6955402c90530e7c67f1428868369b3", NULL }; @@ -1204,6 +1115,7 @@ { 10, 10, 356, 356 }, { 100, 100, 356, 356 }, { 0, 0, 260, 39 }, + { 0, 0, 16, 16 }, { 10, 10, 416, 26 }, { 10, 8, 60, 104 }, { 0, 10, 511, 306 }, @@ -1295,12 +1207,6 @@ current_bounds++; } -static void skip_compare( int count ) -{ - current_sha1 += count; - current_bounds++; -} - static void compare_hash_broken_todo(HDC hdc, const BITMAPINFO *bmi, BYTE *bits, const char *info, int num_broken, BOOL todo) { char *hash = hash_dib(bmi, bits); @@ -1832,10 +1738,7 @@ y += 25; } } - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed == 256) /* 8-bpp grayscale broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "top-down 8888 dib brush patblt", 1, FALSE); - else - compare_hash_broken_todo(hdc, bmi, bits, "top-down 8888 dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 8888 dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1862,10 +1765,7 @@ y += 25; } } - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed == 256) /* 8-bpp grayscale broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "bottom-up 8888 dib brush patblt", 1, FALSE); - else - compare_hash_broken_todo(hdc, bmi, bits, "bottom-up 8888 dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash(hdc, bmi, bits, "bottom-up 8888 dib brush patblt"); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1892,10 +1792,7 @@ y += 25; } } - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed == 256) /* 8-bpp grayscale broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "top-down 24 bpp brush patblt", 1, FALSE); - else - compare_hash_broken_todo(hdc, bmi, bits, "top-down 24 bpp brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash(hdc, bmi, bits, "top-down 24 bpp brush patblt"); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1922,10 +1819,7 @@ y += 25; } } - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed == 256) /* 8-bpp grayscale broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "top-down 555 dib brush patblt", 1, FALSE); - else - compare_hash_broken_todo(hdc, bmi, bits, "top-down 555 dib brush patblt", dib_is_1bpp ? 1 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 555 dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1962,7 +1856,7 @@ y += 25; } } - compare_hash_broken_todo(hdc, bmi, bits, "top-down 8 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 8 bpp dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1984,7 +1878,7 @@ y += 25; } } - compare_hash_broken_todo(hdc, bmi, bits, "top-down 4 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 4 bpp dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -2010,7 +1904,7 @@ } } - compare_hash_broken_todo(hdc, bmi, bits, "top-down 1 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 1 bpp dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -2034,7 +1928,7 @@ } } - compare_hash_broken_todo(hdc, bmi, bits, "1 bpp ddb brush patblt", dib_is_1bpp ? 3 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "1 bpp ddb brush patblt", 0, dib_is_1bpp); DeleteObject(bmp); SelectObject(hdc, orig_brush); @@ -2069,21 +1963,12 @@ /* RTL rectangles */ - if( !pSetLayout ) - { - win_skip("Don't have SetLayout\n"); - skip_compare(1); - } - else - { - pSetLayout(hdc, LAYOUT_RTL); - PaintRgn(hdc, hrgn); - PatBlt(hdc, 10, 250, 10, 10, PATCOPY); - Rectangle(hdc, 100, 250, 110, 260); - compare_hash(hdc, bmi, bits, "rtl"); - - pSetLayout(hdc, LAYOUT_LTR); - } + SetLayout(hdc, LAYOUT_RTL); + PaintRgn(hdc, hrgn); + PatBlt(hdc, 10, 250, 10, 10, PATCOPY); + Rectangle(hdc, 100, 250, 110, 260); + compare_hash(hdc, bmi, bits, "rtl"); + SetLayout(hdc, LAYOUT_LTR); DeleteObject( hrgn ); for(i = 0, y = 10; i < 256; i++) @@ -2103,7 +1988,7 @@ } } - compare_hash_broken_todo(hdc, bmi, bits, "hatch brushes", 1, FALSE); /* nt4 is different */ + compare_hash(hdc, bmi, bits, "hatch brushes"); /* overlapping blits */ @@ -2207,39 +2092,17 @@ BitBlt( hdc, 7, 28, 2, 2, src_dc, 0, 0, SRCCOPY ); BitBlt( hdc, 7, 32, 9, 2, src_dc, 0, 0, SRCCOPY ); BitBlt( hdc, 7, 36, 10, 2, src_dc, 0, 0, SRCCOPY ); - - if (bmi->bmiHeader.biBitCount == 8) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 32-bpp SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp SRCCOPY" ); blend.SourceConstantAlpha = 0xd0; blend.AlphaFormat = 0; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp no alpha", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp no alpha", 0, dib_is_1bpp ); - } + GdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp no alpha", 0, dib_is_1bpp ); blend.SourceConstantAlpha = 0xb0; blend.AlphaFormat = AC_SRC_ALPHA; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 50, 50, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp alpha", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp alpha", 0, dib_is_1bpp ); - } + GdiAlphaBlend( hdc, 50, 50, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp alpha", 0, dib_is_1bpp ); /* blitting with 32-bpp r10g10b10 source */ @@ -2260,10 +2123,7 @@ } BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 32-bpp r10g10b10 SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp r10g10b10 SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp r10g10b10 SRCCOPY" ); /* blitting with 32-bpp b6g6r6 source */ @@ -2284,10 +2144,7 @@ } BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 32-bpp b6g6r6 SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp b6g6r6 SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp b6g6r6 SRCCOPY" ); /* blitting with 24-bpp source */ @@ -2304,24 +2161,12 @@ } BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 24-bpp SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 24-bpp SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 24-bpp SRCCOPY" ); blend.SourceConstantAlpha = 0xe0; blend.AlphaFormat = 0; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 24-bpp", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 24-bpp", 0, dib_is_1bpp ); - } + GdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 24-bpp", 0, dib_is_1bpp ); /* blitting with 16-bpp BI_RGB source */ @@ -2334,10 +2179,7 @@ ((WORD *)src_bits)[y * 256 + x] = x | x << 4 | x << 8 | y << 3 | y << 7; BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed > 5) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 16-bpp SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 16-bpp SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 16-bpp SRCCOPY" ); /* blitting with 16-bpp b4g4r4 source */ @@ -2353,10 +2195,7 @@ ((WORD *)src_bits)[y * 256 + x] = x | x << 4 | x << 8 | y << 3 | y << 7; BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed > 5) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 16-bpp b4g4r4 SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 16-bpp b4g4r4 SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 16-bpp b4g4r4 SRCCOPY" ); /* blitting with 8-bpp source */ @@ -2375,17 +2214,8 @@ blend.SourceConstantAlpha = 0xd0; blend.AlphaFormat = 0; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 8-bpp", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 8-bpp", 0, dib_is_1bpp ); - } + GdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 8-bpp", 0, dib_is_1bpp ); /* blitting with 4-bpp source */ @@ -2423,17 +2253,8 @@ blend.SourceConstantAlpha = 0x90; blend.AlphaFormat = 0; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 1-bpp", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash(hdc, bmi, bits, "AlphaBlend src 1-bpp" ); - } + GdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash(hdc, bmi, bits, "AlphaBlend src 1-bpp" ); /* blitting with 1-bpp ddb source */ @@ -2462,8 +2283,65 @@ } SetTextColor( hdc, old_text ); SetBkColor( hdc, old_bkgnd ); - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 1-bpp ddb SRCCOPY", 0, - bmi->bmiHeader.biBitCount <= 8 /* todo: DIBINDEX for indexed formats */ ); + compare_hash(hdc, bmi, bits, "BitBlt src 1-bpp ddb SRCCOPY" ); + + DeleteObject( bmp ); + + /* blitting to 1-bpp ddb dest */ + + bmp = CreateBitmap( 16, 16, 1, 1, ddb_brush_bits ); + DeleteObject( SelectObject( src_dc, bmp ) ); + + for (y = 0; y < 16; y++) + for (x = 0; x < 16; x++) + SetPixel( hdc, x, y, RGB( 16 * x, 16 * y, 8 * (x + y)) ); + PatBlt( hdc, 15, 15, 1, 1, WHITENESS ); + /* source colors are ignored */ + SetTextColor( src_dc, 0xbeef ); + SetBkColor( src_dc, RGB( 16 * 2, 16 * 3, 8 * (2 + 3) )); + /* destination text color is also ignored */ + SetTextColor( hdc, 0xbedead ); + + i = 16; + SetBkColor( hdc, 0xffffff ); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, 0 ); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, RGB( 16 * 2, 16 * 3, 8 * (2 + 3) )); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, RGB( 16 * 13, 16 * 14, 8 * (13 + 14) )); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, PALETTEINDEX( 1 )); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, DIBINDEX( 2 )); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetTextColor( hdc, old_text ); + SetBkColor( hdc, old_bkgnd ); + compare_hash(hdc, bmi, bits, "BitBlt dst 1-bpp ddb"); DeleteDC( src_dc ); DeleteObject( bmp ); @@ -2594,7 +2472,6 @@ /* gradients */ - if (pGdiGradientFill) { TRIVERTEX vrect[] = { @@ -2641,28 +2518,17 @@ { 2, 1, 0 }, { 3, 5, 4 }, { 7, 6, 8 }, { 10, 11, 9 }, { 14, 13, 12 }, { 17, 15, 16 }, { 19, 20, 18 } }; - pGdiGradientFill( hdc, vrect, 4, rect, 2, GRADIENT_FILL_RECT_H ); + GdiGradientFill( hdc, vrect, 4, rect, 2, GRADIENT_FILL_RECT_H ); for (i = 0; i < 4; i++) vrect[i].y += 250; - pGdiGradientFill( hdc, vrect, 4, rect, 2, GRADIENT_FILL_RECT_V ); + GdiGradientFill( hdc, vrect, 4, rect, 2, GRADIENT_FILL_RECT_V ); + /* Wine's 8-bit dithering isn't identical to Windows */ + compare_hash_broken_todo(hdc, bmi, bits, "GdiGradientFill", 0, (bmi->bmiHeader.biBitCount <= 8) ); - if (bmi->bmiHeader.biBitCount <= 8) /* Wine's 8-bit dithering isn't identical to Windows */ - compare_hash_broken_todo(hdc, bmi, bits, "GdiGradientFill", 0, 1 ); - else - compare_hash(hdc, bmi, bits, "GdiGradientFill" ); - - pGdiGradientFill( hdc, vtri, 7*3, tri, 7, GRADIENT_FILL_TRIANGLE ); + GdiGradientFill( hdc, vtri, 7*3, tri, 7, GRADIENT_FILL_TRIANGLE ); for (i = 0; i < 7*3; i++) vtri[i].y += 100; - pGdiGradientFill( hdc, vtri, 7*3, tri + 7, 7, GRADIENT_FILL_TRIANGLE ); - if (bmi->bmiHeader.biBitCount <= 8) /* Wine's 8-bit dithering isn't identical to Windows */ - compare_hash_broken_todo(hdc, bmi, bits, "GdiGradientFill", 0, 1 ); - else - compare_hash(hdc, bmi, bits, "GdiGradientFill" ); - } - else - { - win_skip( "GdiGradientFill not supported\n" ); - skip_compare(1); - skip_compare(1); + GdiGradientFill( hdc, vtri, 7*3, tri + 7, 7, GRADIENT_FILL_TRIANGLE ); + /* Wine's 8-bit dithering isn't identical to Windows */ + compare_hash_broken_todo(hdc, bmi, bits, "GdiGradientFill", 0, (bmi->bmiHeader.biBitCount <= 8) ); } /* wide pen */ @@ -2741,8 +2607,7 @@ LineTo( hdc, 10 * i, 200 + i ); LineTo( hdc, 20 * i, 200 + i ); } - /* NT4 broken for all cases, W2K for 1 bpp only */ - compare_hash_broken_todo(hdc, bmi, bits, "wide brushed pen", 1 + dib_is_1bpp, dib_is_1bpp ); + compare_hash_broken_todo(hdc, bmi, bits, "wide brushed pen", 0, dib_is_1bpp ); for (i = 1; i < 20; i++) { @@ -2755,8 +2620,7 @@ LineTo( hdc, 10 * i, 200 + i ); LineTo( hdc, 20 * i, 200 + i ); } - /* NT4 broken for all cases, W2K for 1 bpp only */ - compare_hash_broken_todo(hdc, bmi, bits, "dashed wide brushed pen", 1 + dib_is_1bpp, dib_is_1bpp ); + compare_hash_broken_todo(hdc, bmi, bits, "dashed wide brushed pen", 0, dib_is_1bpp ); DeleteObject(bmp); SetTextColor(hdc, old_text); @@ -2812,8 +2676,7 @@ SelectPalette( hdc, old_hpal, FALSE ); DeleteObject( hpal ); - /* NT4 broken for all cases, W2K for 1 bpp only */ - compare_hash_broken_todo(hdc, bmi, bits, "PALETTEINDEX", 1 + dib_is_1bpp, dib_is_1bpp ); + compare_hash_broken_todo(hdc, bmi, bits, "PALETTEINDEX", 0, dib_is_1bpp ); /* ExtFloodFill */ @@ -3060,9 +2923,7 @@ ok(ds.dsBitfields[0] == 0, "got %08x\n", ds.dsBitfields[0]); ok(ds.dsBitfields[1] == 0, "got %08x\n", ds.dsBitfields[1]); ok(ds.dsBitfields[2] == 0, "got %08x\n", ds.dsBitfields[2]); - ok(ds.dsBmih.biCompression == BI_RGB || - broken(ds.dsBmih.biCompression == BI_BITFIELDS), /* nt4 sp1 and 2 */ - "got %x\n", ds.dsBmih.biCompression); + ok(ds.dsBmih.biCompression == BI_RGB, "got %x\n", ds.dsBmih.biCompression); orig_bm = SelectObject(mem_dc, dib); @@ -3393,11 +3254,6 @@ START_TEST(dib) { - HMODULE mod = GetModuleHandleA("gdi32.dll"); - pSetLayout = (void *)GetProcAddress( mod, "SetLayout" ); - pGdiAlphaBlend = (void *)GetProcAddress( mod, "GdiAlphaBlend" ); - pGdiGradientFill = (void *)GetProcAddress( mod, "GdiGradientFill" ); - CryptAcquireContextW(&crypt_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); test_simple_graphics(); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/tests/font.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/tests/font.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/tests/font.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/tests/font.c 2017-03-21 14:02:57.000000000 +0000 @@ -30,10 +30,12 @@ #include "wine/test.h" -/* Do not allow more than 1 deviation here */ -#define match_off_by_1(a, b, exact) (abs((a) - (b)) <= ((exact) ? 0 : 1)) - -#define near_match(a, b) (abs((a) - (b)) <= 6) +static inline BOOL match_off_by_n(int a, int b, unsigned int n) +{ + return abs(a - b) <= n; +} +#define match_off_by_1(a, b, exact) match_off_by_n((a), (b), (exact) ? 0 : 1) +#define near_match(a, b) match_off_by_n((a), (b), 6) #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) static LONG (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height); @@ -5646,6 +5648,45 @@ ReleaseDC(NULL, hdc); } +static void test_fstype_fixup(void) +{ + HDC hdc; + LOGFONTA lf; + HFONT hfont, hfont_prev; + DWORD ret; + OUTLINETEXTMETRICA *otm; + DWORD otm_size; + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = 72; + lstrcpyA(lf.lfFaceName, "wine_test"); + + SetLastError(0xdeadbeef); + hfont = CreateFontIndirectA(&lf); + ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError()); + + hdc = GetDC(NULL); + + hfont_prev = SelectObject(hdc, hfont); + ok(hfont_prev != NULL, "SelectObject failed\n"); + + otm_size = GetOutlineTextMetricsA(hdc, 0, NULL); + otm = HeapAlloc(GetProcessHeap(), 0, otm_size); + otm->otmSize = sizeof(*otm); + ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm); + ok(ret == otm->otmSize, "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError()); + + /* Test font has fsType set to 0x7fff, test that reserved bits are filtered out, + valid bits are 1, 2, 3, 8, 9. */ + ok((otm->otmfsType & ~0x30e) == 0, "fsType %#x\n", otm->otmfsType); + + HeapFree(GetProcessHeap(), 0, otm); + + SelectObject(hdc, hfont_prev); + DeleteObject(hfont); + ReleaseDC(NULL, hdc); +} + static void test_CreateScalableFontResource(void) { char ttf_name[MAX_PATH]; @@ -5729,6 +5770,7 @@ test_GetGlyphOutline_empty_contour(); test_GetGlyphOutline_metric_clipping(); + test_fstype_fixup(); ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0); ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n"); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/tests/wine_test.sfd wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/tests/wine_test.sfd --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/tests/wine_test.sfd 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/tests/wine_test.sfd 2017-03-21 14:02:57.000000000 +0000 @@ -15,7 +15,7 @@ Layer: 0 1 "Back" 1 Layer: 1 1 "Fore" 0 XUID: [1021 905 592216984 1247726] -FSType: 0 +FSType: 32767 OS2Version: 2 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 1 Binary files /tmp/tmp87oaUw/z1VHZjeWLn/wine-staging-2.3.0~ubuntu16.04.1/dlls/gdi32/tests/wine_test.ttf and /tmp/tmp87oaUw/7Hd6Q3cMPT/wine-staging-2.4.0~ubuntu16.04.1/dlls/gdi32/tests/wine_test.ttf differ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdiplus/font.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdiplus/font.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdiplus/font.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdiplus/font.c 2017-03-21 14:02:57.000000000 +0000 @@ -558,6 +558,8 @@ TRACE("%p %p %p\n", font, graphics, height); + if (!font || !height) return InvalidParameter; + stat = GdipGetFontHeightGivenDPI(font, font->family->dpi, &font_height); if (stat != Ok) return stat; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/gdiplus/tests/font.c wine-staging-2.4.0~ubuntu16.04.1/dlls/gdiplus/tests/font.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/gdiplus/tests/font.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/gdiplus/tests/font.c 2017-03-21 14:02:57.000000000 +0000 @@ -546,6 +546,12 @@ stat = GdipGetFontStyle(font, &style); expect(Ok, stat); + stat = GdipGetFontHeight(NULL, NULL, &fm->font_height); + expect(InvalidParameter, stat); + + stat = GdipGetFontHeight(font, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipGetFontHeight(font, NULL, &fm->font_height); expect(Ok, stat); stat = GdipGetFontSize(font, &fm->font_size); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/hal/hal.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/hal/hal.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/hal/hal.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/hal/hal.spec 2017-03-21 14:02:57.000000000 +0000 @@ -4,12 +4,12 @@ @ stub HalClearSoftwareInterrupt @ stub HalRequestSoftwareInterrupt @ stub HalSystemVectorDispatchEntry -@ stub KeAcquireInStackQueuedSpinLock +@ stdcall -norelay KeAcquireInStackQueuedSpinLock(ptr ptr) ntoskrnl.exe.KeAcquireInStackQueuedSpinLock @ stub KeAcquireInStackQueuedSpinLockRaiseToSynch @ stub KeAcquireQueuedSpinLock @ stub KeAcquireQueuedSpinLockRaiseToSynch @ stub KeAcquireSpinLockRaiseToSynch -@ stub KeReleaseInStackQueuedSpinLock +@ stdcall -norelay KeReleaseInStackQueuedSpinLock(ptr) ntoskrnl.exe.KeReleaseInStackQueuedSpinLock @ stub KeReleaseQueuedSpinLock @ stub KeTryToAcquireQueuedSpinLock @ stub KeTryToAcquireQueuedSpinLockRaiseToSynch diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/inetcomm/tests/mimeole.c wine-staging-2.4.0~ubuntu16.04.1/dlls/inetcomm/tests/mimeole.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/inetcomm/tests/mimeole.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/inetcomm/tests/mimeole.c 2017-03-21 14:02:57.000000000 +0000 @@ -323,7 +323,12 @@ static ULONG WINAPI Stream_Release(IStream *iface) { TestStream *This = impl_from_IStream(iface); - return InterlockedDecrement(&This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + if (!ref) + HeapFree(GetProcessHeap(), 0, This); + + return ref; } static HRESULT WINAPI Stream_Read(IStream *iface, void *pv, ULONG cb, ULONG *pcbRead) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/iphlpapi/iphlpapi_main.c wine-staging-2.4.0~ubuntu16.04.1/dlls/iphlpapi/iphlpapi_main.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/iphlpapi/iphlpapi_main.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/iphlpapi/iphlpapi_main.c 2017-03-21 14:02:57.000000000 +0000 @@ -1067,7 +1067,7 @@ { IP_ADAPTER_UNICAST_ADDRESS *ua; struct WS_sockaddr_in *sa; - aa->Flags |= IP_ADAPTER_IPV4_ENABLED; + aa->u1.s1.Ipv4Enabled = TRUE; ua = aa->FirstUnicastAddress = (IP_ADAPTER_UNICAST_ADDRESS *)ptr; for (i = 0; i < num_v4addrs; i++) { @@ -1101,7 +1101,7 @@ IP_ADAPTER_UNICAST_ADDRESS *ua; struct WS_sockaddr_in6 *sa; - aa->Flags |= IP_ADAPTER_IPV6_ENABLED; + aa->u1.s1.Ipv6Enabled = TRUE; if (aa->FirstUnicastAddress) { for (ua = aa->FirstUnicastAddress; ua->Next; ua = ua->Next) @@ -2640,8 +2640,8 @@ /****************************************************************** * NotifyIpInterfaceChange (IPHLPAPI.@) */ -DWORD WINAPI NotifyIpInterfaceChange(ULONG family, PVOID callback, PVOID context, - BOOLEAN init_notify, PHANDLE handle) +DWORD WINAPI NotifyIpInterfaceChange(ADDRESS_FAMILY family, PIPINTERFACE_CHANGE_CALLBACK callback, + PVOID context, BOOLEAN init_notify, PHANDLE handle) { FIXME("(family %d, callback %p, context %p, init_notify %d, handle %p): stub\n", family, callback, context, init_notify, handle); @@ -2674,6 +2674,18 @@ /****************************************************************** + * NotifyUnicastIpAddressChange (IPHLPAPI.@) + */ +DWORD WINAPI NotifyUnicastIpAddressChange(ADDRESS_FAMILY family, PUNICAST_IPADDRESS_CHANGE_CALLBACK callback, + PVOID context, BOOLEAN init_notify, PHANDLE 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 ERROR_NOT_SUPPORTED; +} + +/****************************************************************** * SendARP (IPHLPAPI.@) * * Send an ARP request. diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/iphlpapi/iphlpapi.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/iphlpapi/iphlpapi.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/iphlpapi/iphlpapi.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/iphlpapi/iphlpapi.spec 2017-03-21 14:02:57.000000000 +0000 @@ -239,7 +239,7 @@ @ stub NotifyRouteChangeEx #@ stub NotifyStableUnicastIpAddressTable #@ stub NotifyTeredoPortChange -#@ stub NotifyUnicastIpAddressChange +@ stdcall NotifyUnicastIpAddressChange(long ptr ptr long ptr) #@ stub NTPTimeToNTFileTime #@ stub NTTimeToNTPTime #@ stub ParseNetworkString diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/iphlpapi/tests/iphlpapi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/iphlpapi/tests/iphlpapi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/iphlpapi/tests/iphlpapi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/iphlpapi/tests/iphlpapi.c 2017-03-21 14:02:57.000000000 +0000 @@ -355,7 +355,7 @@ "GetIpForwardTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n", apiReturn); - if (apiReturn == NO_ERROR && winetest_debug > 1) + if (apiReturn == NO_ERROR) { DWORD i; @@ -363,11 +363,31 @@ for (i = 0; i < buf->dwNumEntries; i++) { char buffer[100]; + + if (!U1(buf->table[i]).dwForwardDest) /* Default route */ + { +todo_wine + ok (U1(buf->table[i]).dwForwardProto == MIB_IPPROTO_NETMGMT, + "Unexpected dwForwardProto %d\n", U1(buf->table[i]).dwForwardProto); + ok (U1(buf->table[i]).dwForwardType == MIB_IPROUTE_TYPE_INDIRECT, + "Unexpected dwForwardType %d\n", U1(buf->table[i]).dwForwardType); + } + else + { + /* In general we should get MIB_IPPROTO_LOCAL but does not work + * for Vista, 2008 and 7. */ + ok (U1(buf->table[i]).dwForwardProto == MIB_IPPROTO_LOCAL || + broken(U1(buf->table[i]).dwForwardProto == MIB_IPPROTO_NETMGMT), + "Unexpected dwForwardProto %d\n", U1(buf->table[i]).dwForwardProto); + /* The forward type varies depending on the address and gateway + * value so it is not worth testing in this case. */ + } + sprintf( buffer, "dest %s", ntoa( buf->table[i].dwForwardDest )); sprintf( buffer + strlen(buffer), " mask %s", ntoa( buf->table[i].dwForwardMask )); - trace( "%u: %s gw %s if %u type %u\n", i, buffer, - ntoa( buf->table[i].dwForwardNextHop ), - buf->table[i].dwForwardIfIndex, U1(buf->table[i]).dwForwardType ); + trace( "%u: %s gw %s if %u type %u proto %u\n", i, buffer, + ntoa( buf->table[i].dwForwardNextHop ), buf->table[i].dwForwardIfIndex, + U1(buf->table[i]).dwForwardType, U1(buf->table[i]).dwForwardProto ); } } HeapFree(GetProcessHeap(), 0, buf); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/kernel32/kernel32.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/kernel32/kernel32.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/kernel32/kernel32.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/kernel32/kernel32.spec 2017-03-21 14:02:57.000000000 +0000 @@ -628,6 +628,8 @@ # @ stub GetCurrentConsoleFontEx @ stdcall GetCurrentDirectoryA(long ptr) @ stdcall GetCurrentDirectoryW(long ptr) +@ stdcall GetCurrentPackageFamilyName(ptr ptr) +@ stdcall GetCurrentPackageFullName(ptr ptr) @ stdcall GetCurrentPackageId(ptr ptr) @ stdcall -norelay GetCurrentProcess() @ stdcall -norelay GetCurrentProcessId() diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/kernel32/tests/format_msg.c wine-staging-2.4.0~ubuntu16.04.1/dlls/kernel32/tests/format_msg.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/kernel32/tests/format_msg.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/kernel32/tests/format_msg.c 2017-03-21 14:02:57.000000000 +0000 @@ -24,6 +24,8 @@ #include "winbase.h" #include "winnls.h" +#define ULL(a,b) (((ULONG64)(a) << 32) | (b)) + static DWORD __cdecl doit(DWORD flags, LPCVOID src, DWORD msg_id, DWORD lang_id, LPSTR out, DWORD outsize, ... ) { @@ -1781,6 +1783,80 @@ "Expected the output buffer to be untouched\n"); } +static void test_message_from_64bit_number(void) +{ + static const WCHAR I64d[] = {'%', '1', '!', 'I', '6', '4', 'd', '!', 0}; + static const WCHAR I64u[] = {'%', '1', '!', 'I', '6', '4', 'u', '!', 0}; + WCHAR outW[0x100], expW[0x100]; + char outA[0x100]; + DWORD r; + static const struct + { + UINT64 number; + const char expected[32]; + int len; + } unsigned_tests[] = + { + { 0, "0", 1 }, + { 1234567890, "1234567890", 10}, + { ULL(0xFFFFFFFF,0xFFFFFFFF), "18446744073709551615", 20 }, + { ULL(0x7FFFFFFF,0xFFFFFFFF), "9223372036854775807", 19 }, + }; + static const struct + { + INT64 number; + const char expected[32]; + int len; + } signed_tests[] = + { + { 0, "0" , 1}, + { 1234567890, "1234567890", 10 }, + { -1, "-1", 2}, + { ULL(0xFFFFFFFF,0xFFFFFFFF), "-1", 2}, + { ULL(0x7FFFFFFF,0xFFFFFFFF), "9223372036854775807", 19 }, + { -ULL(0x7FFFFFFF,0xFFFFFFFF), "-9223372036854775807", 20}, + }; + int i; + + for (i = 0; i < sizeof(unsigned_tests) / sizeof(unsigned_tests[0]); i++) + { + r = doitW(FORMAT_MESSAGE_FROM_STRING, I64u, + 0, 0, outW, sizeof(outW) / sizeof(WCHAR), unsigned_tests[i].number); + MultiByteToWideChar(CP_ACP, 0, unsigned_tests[i].expected, -1, expW, sizeof(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 < sizeof(signed_tests) / sizeof(signed_tests[0]); i++) + { + r = doitW(FORMAT_MESSAGE_FROM_STRING, I64d, + 0, 0, outW, sizeof(outW) / sizeof(WCHAR), signed_tests[i].number); + MultiByteToWideChar(CP_ACP, 0, signed_tests[i].expected, -1, expW, sizeof(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); +} + } +} + START_TEST(format_msg) { DWORD ret; @@ -1808,4 +1884,5 @@ test_message_null_buffer_wide(); test_message_allocate_buffer_wide(); test_message_invalid_flags_wide(); + test_message_from_64bit_number(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/kernel32/version.c wine-staging-2.4.0~ubuntu16.04.1/dlls/kernel32/version.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/kernel32/version.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/kernel32/version.c 2017-03-21 14:02:57.000000000 +0000 @@ -202,8 +202,29 @@ dwSpMajorVersion, dwSpMinorVersion, pdwReturnedProductType); } +/*********************************************************************** + * GetCurrentPackageId (KERNEL32.@) + */ LONG WINAPI GetCurrentPackageId(UINT32 *len, BYTE *buffer) { FIXME("(%p %p): stub\n", len, buffer); return APPMODEL_ERROR_NO_PACKAGE; } + +/*********************************************************************** + * GetCurrentPackageFamilyName (KERNEL32.@) + */ +LONG WINAPI GetCurrentPackageFamilyName(UINT32 *length, PWSTR name) +{ + FIXME("(%p %p): stub\n", length, name); + return APPMODEL_ERROR_NO_PACKAGE; +} + +/*********************************************************************** + * GetCurrentPackageFullName (KERNEL32.@) + */ +LONG WINAPI GetCurrentPackageFullName(UINT32 *length, PWSTR name) +{ + FIXME("(%p %p): stub\n", length, name); + return APPMODEL_ERROR_NO_PACKAGE; +} diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/krnl386.exe16/dma.c wine-staging-2.4.0~ubuntu16.04.1/dlls/krnl386.exe16/dma.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/krnl386.exe16/dma.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/krnl386.exe16/dma.c 2017-03-21 14:02:57.000000000 +0000 @@ -201,22 +201,22 @@ break; /* Low Page Base Address */ - case 0x87: DMA_BaseAddress[0]=(DMA_BaseAddress[0] & (~0xFF << 16))|((val & 0xFF) << 16); break; - case 0x83: DMA_BaseAddress[1]=(DMA_BaseAddress[1] & (~0xFF << 16))|((val & 0xFF) << 16); break; - case 0x81: DMA_BaseAddress[2]=(DMA_BaseAddress[2] & (~0xFF << 16))|((val & 0xFF) << 16); break; - case 0x82: DMA_BaseAddress[3]=(DMA_BaseAddress[3] & (~0xFF << 16))|((val & 0xFF) << 16); break; - case 0x8B: DMA_BaseAddress[5]=(DMA_BaseAddress[5] & (~0xFF << 16))|((val & 0xFF) << 16); break; - case 0x89: DMA_BaseAddress[6]=(DMA_BaseAddress[6] & (~0xFF << 16))|((val & 0xFF) << 16); break; - case 0x8A: DMA_BaseAddress[7]=(DMA_BaseAddress[7] & (~0xFF << 16))|((val & 0xFF) << 16); break; + case 0x87: DMA_BaseAddress[0]=(DMA_BaseAddress[0] & 0xFF00FFFF)|((val & 0xFF) << 16); break; + case 0x83: DMA_BaseAddress[1]=(DMA_BaseAddress[1] & 0xFF00FFFF)|((val & 0xFF) << 16); break; + case 0x81: DMA_BaseAddress[2]=(DMA_BaseAddress[2] & 0xFF00FFFF)|((val & 0xFF) << 16); break; + case 0x82: DMA_BaseAddress[3]=(DMA_BaseAddress[3] & 0xFF00FFFF)|((val & 0xFF) << 16); break; + case 0x8B: DMA_BaseAddress[5]=(DMA_BaseAddress[5] & 0xFF00FFFF)|((val & 0xFF) << 16); break; + case 0x89: DMA_BaseAddress[6]=(DMA_BaseAddress[6] & 0xFF00FFFF)|((val & 0xFF) << 16); break; + case 0x8A: DMA_BaseAddress[7]=(DMA_BaseAddress[7] & 0xFF00FFFF)|((val & 0xFF) << 16); break; /* Low Page Base Address (only 4 lower bits are significant) */ - case 0x487: DMA_BaseAddress[0]=(DMA_BaseAddress[0] & (~0xFFu << 24))|((val & 0x0F) << 24); break; - case 0x483: DMA_BaseAddress[1]=(DMA_BaseAddress[1] & (~0xFFu << 24))|((val & 0x0F) << 24); break; - case 0x481: DMA_BaseAddress[2]=(DMA_BaseAddress[2] & (~0xFFu << 24))|((val & 0x0F) << 24); break; - case 0x482: DMA_BaseAddress[3]=(DMA_BaseAddress[3] & (~0xFFu << 24))|((val & 0x0F) << 24); break; - case 0x48B: DMA_BaseAddress[5]=(DMA_BaseAddress[5] & (~0xFFu << 24))|((val & 0x0F) << 24); break; - case 0x489: DMA_BaseAddress[6]=(DMA_BaseAddress[6] & (~0xFFu << 24))|((val & 0x0F) << 24); break; - case 0x48A: DMA_BaseAddress[7]=(DMA_BaseAddress[7] & (~0xFFu << 24))|((val & 0x0F) << 24); break; + case 0x487: DMA_BaseAddress[0]=(DMA_BaseAddress[0] & 0x00FFFFFF)|((val & 0x0F) << 24); break; + case 0x483: DMA_BaseAddress[1]=(DMA_BaseAddress[1] & 0x00FFFFFF)|((val & 0x0F) << 24); break; + case 0x481: DMA_BaseAddress[2]=(DMA_BaseAddress[2] & 0x00FFFFFF)|((val & 0x0F) << 24); break; + case 0x482: DMA_BaseAddress[3]=(DMA_BaseAddress[3] & 0x00FFFFFF)|((val & 0x0F) << 24); break; + case 0x48B: DMA_BaseAddress[5]=(DMA_BaseAddress[5] & 0x00FFFFFF)|((val & 0x0F) << 24); break; + case 0x489: DMA_BaseAddress[6]=(DMA_BaseAddress[6] & 0x00FFFFFF)|((val & 0x0F) << 24); break; + case 0x48A: DMA_BaseAddress[7]=(DMA_BaseAddress[7] & 0x00FFFFFF)|((val & 0x0F) << 24); break; case 0x08: case 0xD0: diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/krnl386.exe16/int21.c wine-staging-2.4.0~ubuntu16.04.1/dlls/krnl386.exe16/int21.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/krnl386.exe16/int21.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/krnl386.exe16/int21.c 2017-03-21 14:02:57.000000000 +0000 @@ -5282,7 +5282,8 @@ case 0x68: /* "FFLUSH" - COMMIT FILE */ TRACE( "FFLUSH - handle %d\n", BX_reg(context) ); - if (!FlushFileBuffers( DosFileHandleToWin32Handle(BX_reg(context)) )) + if (!FlushFileBuffers( DosFileHandleToWin32Handle(BX_reg(context)) ) && + GetLastError() != ERROR_ACCESS_DENIED) bSetDOSExtendedError = TRUE; break; @@ -5307,7 +5308,8 @@ case 0x6a: /* COMMIT FILE */ TRACE( "COMMIT FILE - handle %d\n", BX_reg(context) ); - if (!FlushFileBuffers( DosFileHandleToWin32Handle(BX_reg(context)) )) + if (!FlushFileBuffers( DosFileHandleToWin32Handle(BX_reg(context)) ) && + GetLastError() != ERROR_ACCESS_DENIED) bSetDOSExtendedError = TRUE; break; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/mciavi32/mciavi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/mciavi32/mciavi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/mciavi32/mciavi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/mciavi32/mciavi.c 2017-03-21 14:02:57.000000000 +0000 @@ -353,6 +353,7 @@ DWORD numEvents = 1; HANDLE events[2]; double next_frame_us; + BOOL wait_audio = TRUE; EnterCriticalSection(&wma->cs); @@ -419,19 +420,37 @@ else delta = 0; + /* check if the playback was cancelled */ + if ((wma->mci_break.flags & MCI_BREAK_KEY) && + (GetAsyncKeyState(wma->mci_break.parms.nVirtKey) & 0x8000)) + { + if (!(wma->mci_break.flags & MCI_BREAK_HWND) || + GetForegroundWindow() == wma->mci_break.parms.hwndBreak) + { + /* we queue audio blocks ahead so ignore them otherwise the audio + * will keep playing until the buffer is empty */ + wait_audio = FALSE; + + TRACE("playback cancelled using break key\n"); + break; + } + } + LeaveCriticalSection(&wma->cs); ret = WaitForMultipleObjects(numEvents, events, FALSE, delta / 1000); EnterCriticalSection(&wma->cs); if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break; } - if (wma->lpWaveFormat) { - while (wma->dwEventCount != nHdr - 1) - { - LeaveCriticalSection(&wma->cs); - Sleep(100); - EnterCriticalSection(&wma->cs); - } + if (wma->lpWaveFormat) + { + if (wait_audio) + while (wma->dwEventCount != nHdr - 1) + { + LeaveCriticalSection(&wma->cs); + Sleep(100); + EnterCriticalSection(&wma->cs); + } /* just to get rid of some race conditions between play, stop and pause */ LeaveCriticalSection(&wma->cs); @@ -871,6 +890,30 @@ } /****************************************************************************** + * MCIAVI_mciBreak [internal] + */ +static DWORD MCIAVI_mciBreak(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms) +{ + WINE_MCIAVI *wma; + + TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms); + + if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; + + wma = MCIAVI_mciGetOpenDev(wDevID); + if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; + + EnterCriticalSection(&wma->cs); + + wma->mci_break.flags = dwFlags; + wma->mci_break.parms = *lpParms; + + LeaveCriticalSection(&wma->cs); + + return 0; +} + +/****************************************************************************** * MCIAVI_mciSetAudio [internal] */ static DWORD MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSW lpParms) @@ -988,6 +1031,7 @@ case MCI_WHERE: return MCIAVI_mciWhere (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS) dwParam2); case MCI_STEP: return MCIAVI_mciStep (dwDevID, dwParam1, (LPMCI_DGV_STEP_PARMS) dwParam2); case MCI_CUE: return MCIAVI_mciCue (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS) dwParam2); + case MCI_BREAK: return MCIAVI_mciBreak (dwDevID, dwParam1, (LPMCI_BREAK_PARMS) dwParam2); /* Digital Video specific */ case MCI_SETAUDIO: return MCIAVI_mciSetAudio (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2); case MCI_SIGNAL: return MCIAVI_mciSignal (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS) dwParam2); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/mciavi32/private_mciavi.h wine-staging-2.4.0~ubuntu16.04.1/dlls/mciavi32/private_mciavi.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/mciavi32/private_mciavi.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/mciavi32/private_mciavi.h 2017-03-21 14:02:57.000000000 +0000 @@ -76,6 +76,11 @@ DWORD dwToVideoFrame; /* play to */ DWORD dwCurrAudioBlock; /* current audio block being played */ RECT source, dest; + struct + { + DWORD flags; + MCI_BREAK_PARMS parms; + } mci_break; /* data for the background mechanism */ CRITICAL_SECTION cs; HANDLE hStopEvent; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/mciavi32/wnd.c wine-staging-2.4.0~ubuntu16.04.1/dlls/mciavi32/wnd.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/mciavi32/wnd.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/mciavi32/wnd.c 2017-03-21 14:02:57.000000000 +0000 @@ -109,7 +109,7 @@ return FALSE; } -BOOL MCIAVI_CreateWindow(WINE_MCIAVI* wma, DWORD dwFlags, LPMCI_DGV_OPEN_PARMSW lpOpenParms) +BOOL MCIAVI_CreateWindow(WINE_MCIAVI* wma, DWORD dwFlags, LPMCI_DGV_OPEN_PARMSW lpParms) { static const WCHAR captionW[] = {'W','i','n','e',' ','M','C','I','-','A','V','I',' ','p','l','a','y','e','r',0}; HWND hParent = 0; @@ -119,8 +119,8 @@ /* what should be done ? */ if (wma->hWnd) return TRUE; - if (dwFlags & MCI_DGV_OPEN_PARENT) hParent = lpOpenParms->hWndParent; - if (dwFlags & MCI_DGV_OPEN_WS) dwStyle = lpOpenParms->dwStyle; + if (dwFlags & MCI_DGV_OPEN_PARENT) hParent = lpParms->hWndParent; + if (dwFlags & MCI_DGV_OPEN_WS) dwStyle = lpParms->dwStyle; if (wma->hic) SetRect(&rc, 0, 0, wma->outbih->biWidth, wma->outbih->biHeight); @@ -141,6 +141,9 @@ hParent, 0, MCIAVI_hInstance, ULongToPtr(wma->wDevID)); wma->hWndPaint = wma->hWnd; + + TRACE("(%04x, %08X, %p, style %x, parent %p, dimensions %dx%d, hwnd %p)\n", wma->wDevID, + dwFlags, lpParms, dwStyle, hParent, rc.right - rc.left, rc.bottom - rc.top, wma->hWnd); return wma->hWnd != 0; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/mscoree/mscoree_main.c wine-staging-2.4.0~ubuntu16.04.1/dlls/mscoree/mscoree_main.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/mscoree/mscoree_main.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/mscoree/mscoree_main.c 2017-03-21 14:02:57.000000000 +0000 @@ -675,7 +675,7 @@ LONG len; BOOL ret; - static const char* mono_version = "4.6.4"; + static const char* mono_version = "4.7.0"; static const char* mono_product_code = "{E45D8920-A758-4088-B6C6-31DBB276992E}"; static const WCHAR controlW[] = {'\\','c','o','n','t','r','o','l','.','e','x','e',0}; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msctf/tests/inputprocessor.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msctf/tests/inputprocessor.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msctf/tests/inputprocessor.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msctf/tests/inputprocessor.c 2017-03-21 14:02:57.000000000 +0000 @@ -1692,6 +1692,7 @@ ITfContext_Release(cxt); ITfContext_Release(cxt2); ITfContext_Release(cxt3); + ITextStoreACP_Release(ts); } static void test_endSession(void) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msi/install.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msi/install.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msi/install.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msi/install.c 2017-03-21 14:02:57.000000000 +0000 @@ -1189,11 +1189,11 @@ static INT feature_cost( MSIFEATURE *feature ) { INT cost = 0; - MSICOMPONENT *comp; + ComponentList *cl; - LIST_FOR_EACH_ENTRY( comp, &feature->Components, MSICOMPONENT, entry ) + LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry ) { - cost += comp->Cost; + cost += cl->component->Cost; } return cost; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcp140/msvcp140.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcp140/msvcp140.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcp140/msvcp140.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcp140/msvcp140.spec 2017-03-21 14:02:57.000000000 +0000 @@ -1096,9 +1096,9 @@ @ cdecl -arch=win64 ?_Addfac@_Locimp@locale@std@@AEAAXPEAVfacet@23@_K@Z(ptr ptr long) locale__Locimp__Addfac @ cdecl -arch=win32 ?_Addstd@ios_base@std@@SAXPAV12@@Z(ptr) ios_base_Addstd @ cdecl -arch=win64 ?_Addstd@ios_base@std@@SAXPEAV12@@Z(ptr) ios_base_Addstd -@ stub -arch=arm ?_Assign@_ContextCallback@details@Concurrency@@AAAXPAX@Z -@ stub -arch=i386 ?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z -@ stub -arch=win64 ?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z +@ cdecl -arch=arm ?_Assign@_ContextCallback@details@Concurrency@@AAAXPAX@Z(ptr ptr) _ContextCallback__Assign +@ thiscall -arch=i386 ?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z(ptr ptr) _ContextCallback__Assign +@ cdecl -arch=win64 ?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z(ptr ptr) _ContextCallback__Assign @ stub ?_Atexit@@YAXP6AXXZ@Z @ extern ?_BADOFF@std@@3_JB std_BADOFF @ cdecl -arch=arm ?_C_str@?$_Yarn@D@std@@QBAPBDXZ(ptr) _Yarn_char_c_str @@ -1110,15 +1110,15 @@ @ cdecl -arch=arm ?_C_str@?$_Yarn@_W@std@@QBAPB_WXZ(ptr) _Yarn_wchar__C_str @ thiscall -arch=i386 ?_C_str@?$_Yarn@_W@std@@QBEPB_WXZ(ptr) _Yarn_wchar__C_str @ cdecl -arch=win64 ?_C_str@?$_Yarn@_W@std@@QEBAPEB_WXZ(ptr) _Yarn_wchar__C_str -@ stub -arch=arm ?_CallInContext@_ContextCallback@details@Concurrency@@QBAXV?$function@$$A6AXXZ@std@@_N@Z -@ stub -arch=i386 ?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z -@ stub -arch=win64 ?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z +@ cdecl -arch=arm ?_CallInContext@_ContextCallback@details@Concurrency@@QBAXV?$function@$$A6AXXZ@std@@_N@Z(ptr ptr long) _ContextCallback__CallInContext +@ thiscall -arch=i386 ?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr long) _ContextCallback__CallInContext +@ cdecl -arch=win64 ?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z(ptr ptr long) _ContextCallback__CallInContext @ cdecl -arch=arm ?_Callfns@ios_base@std@@AAAXW4event@12@@Z(ptr long) ios_base_Callfns @ thiscall -arch=i386 ?_Callfns@ios_base@std@@AAEXW4event@12@@Z(ptr long) ios_base_Callfns @ cdecl -arch=win64 ?_Callfns@ios_base@std@@AEAAXW4event@12@@Z(ptr long) ios_base_Callfns -@ stub -arch=arm ?_Capture@_ContextCallback@details@Concurrency@@AAAXXZ -@ stub -arch=i386 ?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ -@ stub -arch=win64 ?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ +@ cdecl -arch=arm ?_Capture@_ContextCallback@details@Concurrency@@AAAXXZ(ptr) _ContextCallback__Capture +@ thiscall -arch=i386 ?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ(ptr) _ContextCallback__Capture +@ cdecl -arch=win64 ?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ(ptr) _ContextCallback__Capture @ extern -arch=win32 ?_Clocptr@_Locimp@locale@std@@0PAV123@A locale__Locimp__Clocptr @ extern -arch=win64 ?_Clocptr@_Locimp@locale@std@@0PEAV123@EA locale__Locimp__Clocptr @ cdecl -arch=arm ?_Decref@facet@locale@std@@UAAPAV_Facet_base@3@XZ(ptr) locale_facet__Decref @@ -1442,7 +1442,7 @@ @ cdecl -arch=win64 ?_Iput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEAD_K@Z(ptr ptr ptr ptr long ptr long) num_put_short__Iput @ cdecl -arch=win32 ?_Iput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPADI@Z(ptr ptr long ptr ptr long ptr long) num_put_wchar__Iput @ cdecl -arch=win64 ?_Iput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEAD_K@Z(ptr ptr ptr ptr long ptr long) num_put_wchar__Iput -@ stub ?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ +@ cdecl ?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ(ptr) _ContextCallback__IsCurrentOriginSTA @ stub ?_IsNonBlockingThread@_Task_impl_base@details@Concurrency@@SA_NXZ @ cdecl -arch=win32 ?_Locimp_Addfac@_Locimp@locale@std@@CAXPAV123@PAVfacet@23@I@Z(ptr ptr long) locale__Locimp__Locimp_Addfac @ cdecl -arch=win64 ?_Locimp_Addfac@_Locimp@locale@std@@CAXPEAV123@PEAVfacet@23@_K@Z(ptr ptr long) locale__Locimp__Locimp_Addfac @@ -1475,24 +1475,24 @@ @ cdecl -arch=win32 ?_Lockit_dtor@_Lockit@std@@CAXPAV12@@Z(ptr) _Lockit__Lockit_dtor @ cdecl -arch=win64 ?_Lockit_dtor@_Lockit@std@@CAXPEAV12@@Z(ptr) _Lockit__Lockit_dtor @ cdecl ?_Lockit_dtor@_Lockit@std@@SAXH@Z(long) _Lockit_free -@ stub -arch=arm ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAAXXZ -@ stub -arch=i386 ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ -@ stub -arch=win64 ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ -@ stub -arch=arm ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAAX_N@Z -@ stub -arch=i386 ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z -@ stub -arch=win64 ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z -@ stub -arch=arm ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ -@ stub -arch=i386 ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ -@ stub -arch=win64 ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ -@ stub -arch=arm ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ -@ stub -arch=i386 ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ -@ stub -arch=win64 ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ -@ stub -arch=arm ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ -@ stub -arch=i386 ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ -@ stub -arch=win64 ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ -@ stub -arch=arm ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAAXXZ -@ stub -arch=win32 ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ -@ stub -arch=win64 ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ +@ cdecl -arch=arm ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAAXXZ(ptr) _TaskEventLogger__LogCancelTask +@ thiscall -arch=i386 ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ(ptr) _TaskEventLogger__LogCancelTask +@ cdecl -arch=win64 ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ(ptr) _TaskEventLogger__LogCancelTask +@ cdecl -arch=arm ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAAX_N@Z(ptr long) _TaskEventLogger__LogScheduleTask +@ thiscall -arch=i386 ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z(ptr long) _TaskEventLogger__LogScheduleTask +@ cdecl -arch=win64 ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z(ptr long) _TaskEventLogger__LogScheduleTask +@ cdecl -arch=arm ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ(ptr) _TaskEventLogger__LogTaskCompleted +@ thiscall -arch=i386 ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ(ptr) _TaskEventLogger__LogTaskCompleted +@ cdecl -arch=win64 ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ(ptr) _TaskEventLogger__LogTaskCompleted +@ cdecl -arch=arm ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ(ptr) _TaskEventLogger__LogTaskExecutionCompleted +@ thiscall -arch=i386 ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ(ptr) _TaskEventLogger__LogTaskExecutionCompleted +@ cdecl -arch=win64 ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ(ptr) _TaskEventLogger__LogTaskExecutionCompleted +@ cdecl -arch=arm ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ(ptr) _TaskEventLogger__LogWorkItemCompleted +@ thiscall -arch=i386 ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ(ptr) _TaskEventLogger__LogWorkItemCompleted +@ cdecl -arch=win64 ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ(ptr) _TaskEventLogger__LogWorkItemCompleted +@ cdecl -arch=arm ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAAXXZ(ptr) _TaskEventLogger__LogWorkItemStarted +@ thiscall -arch=i386 ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ(ptr) _TaskEventLogger__LogWorkItemStarted +@ cdecl -arch=win64 ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ(ptr) _TaskEventLogger__LogWorkItemStarted @ stub -arch=win32 ?_MP_Add@std@@YAXQA_K_K@Z @ stub -arch=win64 ?_MP_Add@std@@YAXQEA_K_K@Z @ stub -arch=win32 ?_MP_Get@std@@YA_KQA_K@Z @@ -1592,9 +1592,9 @@ @ stub ?_ReportUnobservedException@details@Concurrency@@YAXXZ @ stub -arch=win32 ?_Reschedule_chore@details@Concurrency@@YAHPBU_Threadpool_chore@12@@Z @ stub -arch=win64 ?_Reschedule_chore@details@Concurrency@@YAHPEBU_Threadpool_chore@12@@Z -@ stub -arch=arm ?_Reset@_ContextCallback@details@Concurrency@@AAAXXZ -@ stub -arch=i386 ?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ -@ stub -arch=win64 ?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ +@ cdecl -arch=arm ?_Reset@_ContextCallback@details@Concurrency@@AAAXXZ(ptr) _ContextCallback__Reset +@ thiscall -arch=i386 ?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ(ptr) _ContextCallback__Reset +@ cdecl -arch=win64 ?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ(ptr) _ContextCallback__Reset @ stub ?_Rethrow_future_exception@std@@YAXVexception_ptr@1@@Z @ stub -arch=win32 ?_Rng_abort@std@@YAXPBD@Z @ stub -arch=win64 ?_Rng_abort@std@@YAXPEBD@Z @@ -3760,8 +3760,8 @@ @ cdecl __crtCreateEventExW(ptr wstr long long) MSVCP__crtCreateEventExW @ cdecl __crtCreateSemaphoreExW(ptr long long wstr long long) MSVCP__crtCreateSemaphoreExW @ stub __crtCreateSymbolicLinkW -@ stub __crtCreateThreadpoolTimer -@ stub __crtCreateThreadpoolWait +@ cdecl __crtCreateThreadpoolTimer(ptr ptr ptr) MSVCP__crtCreateThreadpoolTimer +@ cdecl __crtCreateThreadpoolWait(ptr ptr ptr) MSVCP__crtCreateThreadpoolWait @ stub __crtFlushProcessWriteBuffers @ stub __crtFreeLibraryWhenCallbackReturns @ stub __crtGetCurrentProcessorNumber @@ -3776,8 +3776,8 @@ @ stub __crtLCMapStringEx @ cdecl __crtLCMapStringW(long long wstr long ptr long long long) msvcrt.__crtLCMapStringW @ stub __crtSetFileInformationByHandle -@ stub __crtSetThreadpoolTimer -@ stub __crtSetThreadpoolWait +@ cdecl __crtSetThreadpoolTimer(ptr ptr long long) MSVCP__crtSetThreadpoolTimer +@ cdecl __crtSetThreadpoolWait(ptr long ptr) MSVCP__crtSetThreadpoolWait @ stub __crtWaitForThreadpoolTimerCallbacks @ stub __set_stl_sync_api_mode @ cdecl xtime_get(ptr long) xtime_get diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcp140/tests/msvcp140.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcp140/tests/msvcp140.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcp140/tests/msvcp140.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcp140/tests/msvcp140.c 2017-03-21 14:02:57.000000000 +0000 @@ -21,6 +21,38 @@ #include "wine/test.h" #include "winbase.h" +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + do { \ + expect_ ## func = TRUE; \ + errno = 0xdeadbeef; \ + }while(0) + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +#ifdef _WIN64 +DEFINE_EXPECT(function_do_call); +DEFINE_EXPECT(function_do_clean); +#endif + #undef __thiscall #ifdef __i386__ #define __thiscall __stdcall @@ -43,6 +75,7 @@ #include "poppack.h" static void * (WINAPI *call_thiscall_func1)( void *func, void *this ); +static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a ); static void init_thiscall_thunk(void) { @@ -54,24 +87,57 @@ thunk->push_eax = 0x50; /* pushl %eax */ thunk->jmp_edx = 0xe2ff; /* jmp *%edx */ call_thiscall_func1 = (void *)thunk; + call_thiscall_func2 = (void *)thunk; } #define call_func1(func,_this) call_thiscall_func1(func,_this) +#define call_func2(func,_this,a) call_thiscall_func2(func,_this,a) #else #define init_thiscall_thunk() #define call_func1(func,_this) func(_this) +#define call_func2(func,_this,a) func(_this,a) #endif /* __i386__ */ +typedef unsigned char MSVCP_bool; typedef struct { void *unk0; BYTE unk1; } task_continuation_context; +typedef struct { + void *unused; +} _ContextCallback; + +typedef struct { + const void *vtable; + void (__cdecl *func)(void); + int unk[4]; + void *unk2[3]; + void *this; +} function_void_cdecl_void; + +typedef struct { + void *task; + MSVCP_bool scheduled; + MSVCP_bool started; +} _TaskEventLogger; + static unsigned int (__cdecl *p__Thrd_id)(void); static task_continuation_context* (__thiscall *p_task_continuation_context_ctor)(task_continuation_context*); +static void (__thiscall *p__ContextCallback__Assign)(_ContextCallback*, void*); +static void (__thiscall *p__ContextCallback__CallInContext)(const _ContextCallback*, function_void_cdecl_void, MSVCP_bool); +static void (__thiscall *p__ContextCallback__Capture)(_ContextCallback*); +static void (__thiscall *p__ContextCallback__Reset)(_ContextCallback*); +static MSVCP_bool (__cdecl *p__ContextCallback__IsCurrentOriginSTA)(_ContextCallback*); +static void (__thiscall *p__TaskEventLogger__LogCancelTask)(_TaskEventLogger*); +static void (__thiscall *p__TaskEventLogger__LogScheduleTask)(_TaskEventLogger*, MSVCP_bool); +static void (__thiscall *p__TaskEventLogger__LogTaskCompleted)(_TaskEventLogger*); +static void (__thiscall *p__TaskEventLogger__LogTaskExecutionCompleted)(_TaskEventLogger*); +static void (__thiscall *p__TaskEventLogger__LogWorkItemCompleted)(_TaskEventLogger*); +static void (__thiscall *p__TaskEventLogger__LogWorkItemStarted)(_TaskEventLogger*); static HMODULE msvcp; #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y) @@ -86,14 +152,45 @@ } SET(p__Thrd_id, "_Thrd_id"); + SET(p__ContextCallback__IsCurrentOriginSTA, "?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ"); if(sizeof(void*) == 8) { /* 64-bit initialization */ SET(p_task_continuation_context_ctor, "??0task_continuation_context@Concurrency@@AEAA@XZ"); + SET(p__ContextCallback__Assign, "?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z"); + SET(p__ContextCallback__CallInContext, "?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z"); + SET(p__ContextCallback__Capture, "?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ"); + SET(p__ContextCallback__Reset, "?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ"); + SET(p__TaskEventLogger__LogCancelTask, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ"); + SET(p__TaskEventLogger__LogScheduleTask, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z"); + SET(p__TaskEventLogger__LogTaskCompleted, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ"); + SET(p__TaskEventLogger__LogTaskExecutionCompleted, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ"); + SET(p__TaskEventLogger__LogWorkItemCompleted, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ"); + SET(p__TaskEventLogger__LogWorkItemStarted, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ"); } else { #ifdef __arm__ SET(p_task_continuation_context_ctor, "??0task_continuation_context@Concurrency@@AAA@XZ"); + SET(p__ContextCallback__Assign, "?_Assign@_ContextCallback@details@Concurrency@@AAAXPAX@Z"); + SET(p__ContextCallback__CallInContext, "?_CallInContext@_ContextCallback@details@Concurrency@@QBAXV?$function@$$A6AXXZ@std@@_N@Z"); + SET(p__ContextCallback__Capture, "?_Capture@_ContextCallback@details@Concurrency@@AAAXXZ"); + SET(p__ContextCallback__Reset, "?_Reset@_ContextCallback@details@Concurrency@@AAAXXZ"); + SET(p__TaskEventLogger__LogCancelTask, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAAXXZ"); + SET(p__TaskEventLogger__LogScheduleTask, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z"); + SET(p__TaskEventLogger__LogTaskCompleted, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ"); + SET(p__TaskEventLogger__LogTaskExecutionCompleted, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ"); + SET(p__TaskEventLogger__LogWorkItemCompleted, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAAXXZ"); + SET(p__TaskEventLogger__LogWorkItemStarted, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAAXXZ"); #else SET(p_task_continuation_context_ctor, "??0task_continuation_context@Concurrency@@AAE@XZ"); + SET(p__ContextCallback__Assign, "?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z"); + SET(p__ContextCallback__CallInContext, "?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z"); + SET(p__ContextCallback__Capture, "?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ"); + SET(p__ContextCallback__Reset, "?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ"); + SET(p__TaskEventLogger__LogCancelTask, "?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ"); + SET(p__TaskEventLogger__LogScheduleTask, "?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z"); + SET(p__TaskEventLogger__LogTaskCompleted, "?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ"); + SET(p__TaskEventLogger__LogTaskExecutionCompleted, "?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ"); + SET(p__TaskEventLogger__LogWorkItemCompleted, "?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ"); + SET(p__TaskEventLogger__LogWorkItemStarted, "?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ"); #endif } @@ -153,11 +250,158 @@ ok(!tcc.unk1, "tcc.unk1 != 0 (%x)\n", tcc.unk1); } +#ifdef _WIN64 +static void __cdecl function_do_call(void *this) +{ + CHECK_EXPECT(function_do_call); +} + +static void __cdecl function_do_clean(void *this, MSVCP_bool b) +{ + CHECK_EXPECT(function_do_clean); + ok(b, "b == FALSE\n"); +} +#endif + +static void test__ContextCallback(void) +{ + _ContextCallback cc = {0}; + void *v = (void*)0xdeadbeef; +#ifdef _WIN64 + void* function_vtbl[] = { + NULL, + NULL, + (void*)function_do_call, + NULL, + (void*)function_do_clean, + NULL + }; + function_void_cdecl_void function = { function_vtbl, NULL, {0}, {NULL}, &function }; + function_void_cdecl_void function2 = { NULL, NULL, {0}, {NULL}, &function }; +#endif + + call_func2(p__ContextCallback__Assign, &cc, v); + ok(!cc.unused, "cc.unused = %p\n", cc.unused); + call_func1(p__ContextCallback__Reset, &cc); + ok(!cc.unused, "cc.unused = %p\n", cc.unused); + call_func1(p__ContextCallback__Capture, &cc); + ok(!cc.unused, "cc.unused = %p\n", cc.unused); + ok(!p__ContextCallback__IsCurrentOriginSTA(&cc), "IsCurrentOriginSTA returned TRUE\n"); + + cc.unused = v; + call_func2(p__ContextCallback__Assign, &cc, NULL); + ok(cc.unused == v, "cc.unused = %p\n", cc.unused); + call_func1(p__ContextCallback__Reset, &cc); + ok(cc.unused == v, "cc.unused = %p\n", cc.unused); + call_func1(p__ContextCallback__Capture, &cc); + ok(cc.unused == v, "cc.unused = %p\n", cc.unused); + ok(!p__ContextCallback__IsCurrentOriginSTA(&cc), "IsCurrentOriginSTA returned TRUE\n"); + ok(cc.unused == v, "cc.unused = %p\n", cc.unused); + +#ifdef _WIN64 + SET_EXPECT(function_do_call); + SET_EXPECT(function_do_clean); + p__ContextCallback__CallInContext(&cc, function, FALSE); + CHECK_CALLED(function_do_call); + CHECK_CALLED(function_do_clean); + + SET_EXPECT(function_do_call); + SET_EXPECT(function_do_clean); + p__ContextCallback__CallInContext(&cc, function, TRUE); + CHECK_CALLED(function_do_call); + CHECK_CALLED(function_do_clean); + + SET_EXPECT(function_do_call); + SET_EXPECT(function_do_clean); + p__ContextCallback__CallInContext(&cc, function2, FALSE); + CHECK_CALLED(function_do_call); + CHECK_CALLED(function_do_clean); + + SET_EXPECT(function_do_call); + SET_EXPECT(function_do_clean); + p__ContextCallback__CallInContext(&cc, function2, TRUE); + CHECK_CALLED(function_do_call); + CHECK_CALLED(function_do_clean); +#endif +} + +static void test__TaskEventLogger(void) +{ + _TaskEventLogger logger; + memset(&logger, 0, sizeof(logger)); + + call_func1(p__TaskEventLogger__LogCancelTask, &logger); + ok(!logger.task, "logger.task = %p\n", logger.task); + ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled); + ok(!logger.started, "logger.started = %x\n", logger.started); + + call_func2(p__TaskEventLogger__LogScheduleTask, &logger, FALSE); + ok(!logger.task, "logger.task = %p\n", logger.task); + ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled); + ok(!logger.started, "logger.started = %x\n", logger.started); + + call_func1(p__TaskEventLogger__LogTaskCompleted, &logger); + ok(!logger.task, "logger.task = %p\n", logger.task); + ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled); + ok(!logger.started, "logger.started = %x\n", logger.started); + + call_func1(p__TaskEventLogger__LogTaskExecutionCompleted, &logger); + ok(!logger.task, "logger.task = %p\n", logger.task); + ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled); + ok(!logger.started, "logger.started = %x\n", logger.started); + + call_func1(p__TaskEventLogger__LogWorkItemCompleted, &logger); + ok(!logger.task, "logger.task = %p\n", logger.task); + ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled); + ok(!logger.started, "logger.started = %x\n", logger.started); + + call_func1(p__TaskEventLogger__LogWorkItemStarted, &logger); + ok(!logger.task, "logger.task = %p\n", logger.task); + ok(!logger.scheduled, "logger.scheduled = %x\n", logger.scheduled); + ok(!logger.started, "logger.started = %x\n", logger.started); + + logger.task = (void*)0xdeadbeef; + logger.scheduled = TRUE; + logger.started = TRUE; + + call_func1(p__TaskEventLogger__LogCancelTask, &logger); + ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task); + ok(logger.scheduled, "logger.scheduled = FALSE\n"); + ok(logger.started, "logger.started = FALSE\n"); + + call_func2(p__TaskEventLogger__LogScheduleTask, &logger, FALSE); + ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task); + ok(logger.scheduled, "logger.scheduled = FALSE\n"); + ok(logger.started, "logger.started = FALSE\n"); + + call_func1(p__TaskEventLogger__LogTaskCompleted, &logger); + ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task); + ok(logger.scheduled, "logger.scheduled = FALSE\n"); + ok(logger.started, "logger.started = FALSE\n"); + + call_func1(p__TaskEventLogger__LogTaskExecutionCompleted, &logger); + ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task); + ok(logger.scheduled, "logger.scheduled = FALSE\n"); + ok(logger.started, "logger.started = FALSE\n"); + + call_func1(p__TaskEventLogger__LogWorkItemCompleted, &logger); + ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task); + ok(logger.scheduled, "logger.scheduled = FALSE\n"); + ok(logger.started, "logger.started = FALSE\n"); + + call_func1(p__TaskEventLogger__LogWorkItemStarted, &logger); + ok(logger.task == (void*)0xdeadbeef, "logger.task = %p\n", logger.task); + ok(logger.scheduled, "logger.scheduled = FALSE\n"); + ok(logger.started, "logger.started = FALSE\n"); +} + START_TEST(msvcp140) { if(!init()) return; test_thrd(); test_vbtable_size_exports(); test_task_continuation_context(); + test__ContextCallback(); + test__TaskEventLogger(); FreeLibrary(msvcp); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcp90/misc.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcp90/misc.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcp90/misc.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcp90/misc.c 2017-03-21 14:02:57.000000000 +0000 @@ -1266,6 +1266,45 @@ return CreateSemaphoreExW(attribs, initial_count, max_count, name, flags, access); } +/********************************************************************* + * __crtCreateThreadpoolTimer (MSVCP140.@) + */ +PTP_TIMER CDECL MSVCP__crtCreateThreadpoolTimer(PTP_TIMER_CALLBACK callback, + PVOID userdata, TP_CALLBACK_ENVIRON *environment) +{ + TRACE("(%p %p %p)\n", callback, userdata, environment); + return CreateThreadpoolTimer(callback, userdata, environment); +} + +/********************************************************************* + * __crtSetThreadpoolTimer (MSVCP140.@) + */ +VOID CDECL MSVCP__crtSetThreadpoolTimer(TP_TIMER *timer, + FILETIME *due_time, DWORD period, DWORD window_length) +{ + TRACE("(%p %p 0x%08x 0x%08x)\n", timer, due_time, period, window_length); + return SetThreadpoolTimer(timer, due_time, period, window_length); +} + +/********************************************************************* + * __crtCreateThreadpoolWait (MSVCP140.@) + */ +PTP_WAIT CDECL MSVCP__crtCreateThreadpoolWait(PTP_WAIT_CALLBACK callback, + PVOID userdata, TP_CALLBACK_ENVIRON *environment) +{ + TRACE("(%p %p %p)\n", callback, userdata, environment); + return CreateThreadpoolWait(callback, userdata, environment); +} + +/********************************************************************* + * __crtSetThreadpoolWait (MSVCP140.@) + */ +VOID CDECL MSVCP__crtSetThreadpoolWait(TP_WAIT *wait, HANDLE handle, FILETIME *due_time) +{ + TRACE("(%p %p %p)\n", wait, handle, due_time); + return SetThreadpoolWait(wait, handle, due_time); +} + /* ?_Execute_once@std@@YAHAAUonce_flag@1@P6GHPAX1PAPAX@Z1@Z */ /* ?_Execute_once@std@@YAHAEAUonce_flag@1@P6AHPEAX1PEAPEAX@Z1@Z */ BOOL __cdecl _Execute_once(INIT_ONCE *flag, PINIT_ONCE_FN func, void *param) @@ -1376,4 +1415,109 @@ memset(this, 0, sizeof(*this)); return this; } + +typedef struct { + const vtable_ptr *vtable; + void (__cdecl *func)(void); + int unk[4]; + void *unk2[3]; + void *this; +} function_void_cdecl_void; + +/* ?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z */ +/* ?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z */ +DEFINE_THISCALL_WRAPPER(_ContextCallback__Assign, 8) +void __thiscall _ContextCallback__Assign(void *this, void *v) +{ + TRACE("(%p %p)\n", this, v); +} + +#define call_function_do_call(this) CALL_VTBL_FUNC(this, 8, void, (function_void_cdecl_void*), (this)) +#define call_function_do_clean(this,b) CALL_VTBL_FUNC(this, 16, void, (function_void_cdecl_void*,MSVCP_bool), (this, b)) +/* ?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z */ +/* ?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z */ +DEFINE_THISCALL_WRAPPER(_ContextCallback__CallInContext, 48) +void __thiscall _ContextCallback__CallInContext(const void *this, function_void_cdecl_void func, MSVCP_bool b) +{ + TRACE("(%p %p %x)\n", this, func.func, b); + call_function_do_call(func.this); + call_function_do_clean(func.this, func.this!=&func); +} + +/* ?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ */ +/* ?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_ContextCallback__Capture, 4) +void __thiscall _ContextCallback__Capture(void *this) +{ + TRACE("(%p)\n", this); +} + +/* ?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ */ +/* ?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_ContextCallback__Reset, 4) +void __thiscall _ContextCallback__Reset(void *this) +{ + TRACE("(%p)\n", this); +} + +/* ?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ */ +MSVCP_bool __cdecl _ContextCallback__IsCurrentOriginSTA(void *this) +{ + TRACE("(%p)\n", this); + return FALSE; +} + +typedef struct { + /*_Task_impl_base*/void *task; + MSVCP_bool scheduled; + MSVCP_bool started; +} _TaskEventLogger; + +/* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ */ +/* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogCancelTask, 4) +void __thiscall _TaskEventLogger__LogCancelTask(_TaskEventLogger *this) +{ + TRACE("(%p)\n", this); +} + +/* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z */ +/* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z */ +DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogScheduleTask, 8) +void __thiscall _TaskEventLogger__LogScheduleTask(_TaskEventLogger *this, MSVCP_bool continuation) +{ + TRACE("(%p %x)\n", this, continuation); +} + +/* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */ +/* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskCompleted, 4) +void __thiscall _TaskEventLogger__LogTaskCompleted(_TaskEventLogger *this) +{ + TRACE("(%p)\n", this); +} + +/* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */ +/* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskExecutionCompleted, 4) +void __thiscall _TaskEventLogger__LogTaskExecutionCompleted(_TaskEventLogger *this) +{ + TRACE("(%p)\n", this); +} + +/* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */ +/* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemCompleted, 4) +void __thiscall _TaskEventLogger__LogWorkItemCompleted(_TaskEventLogger *this) +{ + TRACE("(%p)\n", this); +} + +/* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ */ +/* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemStarted, 4) +void __thiscall _TaskEventLogger__LogWorkItemStarted(_TaskEventLogger *this) +{ + TRACE("(%p)\n", this); +} #endif diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr100/msvcr100.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr100/msvcr100.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr100/msvcr100.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr100/msvcr100.spec 2017-03-21 14:02:57.000000000 +0000 @@ -64,8 +64,8 @@ @ stub -arch=win64 ??0default_scheduler_exists@Concurrency@@QEAA@PEBD@Z @ stub -arch=win32 ??0default_scheduler_exists@Concurrency@@QAE@XZ @ stub -arch=win64 ??0default_scheduler_exists@Concurrency@@QEAA@XZ -@ stub -arch=win32 ??0event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0event@Concurrency@@QEAA@XZ +@ thiscall -arch=win32 ??0event@Concurrency@@QAE@XZ(ptr) event_ctor +@ cdecl -arch=win64 ??0event@Concurrency@@QEAA@XZ(ptr) event_ctor @ thiscall -arch=i386 ??0exception@std@@QAE@ABQBD@Z(ptr ptr) MSVCRT_exception_ctor @ cdecl -arch=win64 ??0exception@std@@QEAA@AEBQEBD@Z(ptr ptr) MSVCRT_exception_ctor @ thiscall -arch=i386 ??0exception@std@@QAE@ABQBDH@Z(ptr ptr long) MSVCRT_exception_ctor_noalloc @@ -182,8 +182,8 @@ @ cdecl -arch=win64 ??1bad_typeid@std@@UEAA@XZ(ptr) MSVCRT_bad_typeid_dtor @ thiscall -arch=win32 ??1critical_section@Concurrency@@QAE@XZ(ptr) critical_section_dtor @ cdecl -arch=win64 ??1critical_section@Concurrency@@QEAA@XZ(ptr) critical_section_dtor -@ stub -arch=win32 ??1event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1event@Concurrency@@QEAA@XZ +@ thiscall -arch=win32 ??1event@Concurrency@@QAE@XZ(ptr) event_dtor +@ cdecl -arch=win64 ??1event@Concurrency@@QEAA@XZ(ptr) event_dtor @ thiscall -arch=i386 ??1exception@std@@UAE@XZ(ptr) MSVCRT_exception_dtor @ cdecl -arch=win64 ??1exception@std@@UEAA@XZ(ptr) MSVCRT_exception_dtor @ thiscall -arch=win32 ??1reader_writer_lock@Concurrency@@QAE@XZ(ptr) reader_writer_lock_dtor @@ -472,10 +472,10 @@ @ cdecl -arch=arm ?raw_name@type_info@@QBAPBDXZ(ptr) MSVCRT_type_info_raw_name @ thiscall -arch=i386 ?raw_name@type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_raw_name @ cdecl -arch=win64 ?raw_name@type_info@@QEBAPEBDXZ(ptr) MSVCRT_type_info_raw_name -@ stub -arch=win32 ?reset@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?reset@event@Concurrency@@QEAAXXZ -@ stub -arch=win32 ?set@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?set@event@Concurrency@@QEAAXXZ +@ thiscall -arch=win32 ?reset@event@Concurrency@@QAEXXZ(ptr) event_reset +@ cdecl -arch=win64 ?reset@event@Concurrency@@QEAAXXZ(ptr) event_reset +@ thiscall -arch=win32 ?set@event@Concurrency@@QAEXXZ(ptr) event_set +@ cdecl -arch=win64 ?set@event@Concurrency@@QEAAXXZ(ptr) event_set @ cdecl ?set_new_handler@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_new_handler @ stub ?set_terminate@@YAP6AXXZH@Z @ cdecl ?set_terminate@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_terminate @@ -497,10 +497,10 @@ @ cdecl -arch=win64 ?unlock@reader_writer_lock@Concurrency@@QEAAXXZ(ptr) reader_writer_lock_unlock @ cdecl ?vswprintf@@YAHPA_WIPB_WPAD@Z(ptr long wstr ptr) MSVCRT_vsnwprintf @ stub ?wait@Concurrency@@YAXI@Z -@ stub -arch=win32 ?wait@event@Concurrency@@QAEII@Z -@ stub -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z -@ stub -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z -@ stub -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z +@ thiscall -arch=win32 ?wait@event@Concurrency@@QAEII@Z(ptr) event_wait +@ cdecl -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z(ptr) event_wait +@ cdecl -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z(ptr long long long) event_wait_for_multiple +@ cdecl -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z(ptr long long long) event_wait_for_multiple @ thiscall -arch=i386 ?what@exception@std@@UBEPBDXZ(ptr) MSVCRT_what_exception @ cdecl -arch=win64 ?what@exception@std@@UEBAPEBDXZ(ptr) MSVCRT_what_exception @ cdecl -norelay $I10_OUTPUT(double long long long ptr) MSVCRT_I10_OUTPUT @@ -536,7 +536,7 @@ @ stub _NLG_Return2 @ stub -arch=win64 _SetImageBase @ stub -arch=win64 _SetThrowImageBase -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _XcptFilter(long ptr) @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @@ -1340,7 +1340,7 @@ @ cdecl _strdup(str) MSVCRT__strdup @ cdecl _strerror(long) MSVCRT__strerror @ stub _strerror_s -@ cdecl _strftime_l(str long str ptr ptr) MSVCRT__strftime_l +@ cdecl _strftime_l(ptr long str ptr ptr) MSVCRT__strftime_l @ cdecl _stricmp(str str) MSVCRT__stricmp @ cdecl _stricmp_l(str str ptr) MSVCRT__stricmp_l @ cdecl _stricoll(str str) MSVCRT__stricoll @@ -1805,7 +1805,7 @@ @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strerror_s(ptr long long) MSVCRT_strerror_s -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncat_s(str long str long) MSVCRT_strncat_s diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr110/msvcr110.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr110/msvcr110.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr110/msvcr110.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr110/msvcr110.spec 2017-03-21 14:02:57.000000000 +0000 @@ -122,9 +122,9 @@ @ stub -arch=arm ??0default_scheduler_exists@Concurrency@@QAA@XZ @ stub -arch=i386 ??0default_scheduler_exists@Concurrency@@QAE@XZ @ stub -arch=win64 ??0default_scheduler_exists@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0event@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0event@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0event@Concurrency@@QAA@XZ(ptr) event_ctor +@ thiscall -arch=win32 ??0event@Concurrency@@QAE@XZ(ptr) event_ctor +@ cdecl -arch=win64 ??0event@Concurrency@@QEAA@XZ(ptr) event_ctor @ cdecl -arch=arm ??0exception@std@@QAA@ABQBD@Z(ptr ptr) MSVCRT_exception_ctor @ thiscall -arch=i386 ??0exception@std@@QAE@ABQBD@Z(ptr ptr) MSVCRT_exception_ctor @ cdecl -arch=win64 ??0exception@std@@QEAA@AEBQEBD@Z(ptr ptr) MSVCRT_exception_ctor @@ -314,9 +314,9 @@ @ cdecl -arch=arm ??1critical_section@Concurrency@@QAA@XZ(ptr) critical_section_dtor @ thiscall -arch=i386 ??1critical_section@Concurrency@@QAE@XZ(ptr) critical_section_dtor @ cdecl -arch=win64 ??1critical_section@Concurrency@@QEAA@XZ(ptr) critical_section_dtor -@ stub -arch=arm ??1event@Concurrency@@QAA@XZ -@ stub -arch=i386 ??1event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1event@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??1event@Concurrency@@QAA@XZ(ptr) event_dtor +@ thiscall -arch=win32 ??1event@Concurrency@@QAE@XZ(ptr) event_dtor +@ cdecl -arch=win64 ??1event@Concurrency@@QEAA@XZ(ptr) event_dtor @ cdecl -arch=arm ??1exception@std@@UAA@XZ(ptr) MSVCRT_exception_dtor @ thiscall -arch=i386 ??1exception@std@@UAE@XZ(ptr) MSVCRT_exception_dtor @ cdecl -arch=win64 ??1exception@std@@UEAA@XZ(ptr) MSVCRT_exception_dtor @@ -770,12 +770,12 @@ @ cdecl -arch=arm ?raw_name@type_info@@QBAPBDXZ(ptr) MSVCRT_type_info_raw_name @ thiscall -arch=i386 ?raw_name@type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_raw_name @ cdecl -arch=win64 ?raw_name@type_info@@QEBAPEBDXZ(ptr) MSVCRT_type_info_raw_name -@ stub -arch=arm ?reset@event@Concurrency@@QAAXXZ -@ stub -arch=i386 ?reset@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?reset@event@Concurrency@@QEAAXXZ -@ stub -arch=arm ?set@event@Concurrency@@QAAXXZ -@ stub -arch=i386 ?set@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?set@event@Concurrency@@QEAAXXZ +@ cdecl -arch=arm ?reset@event@Concurrency@@QAAXXZ(ptr) event_reset +@ thiscall -arch=win32 ?reset@event@Concurrency@@QAEXXZ(ptr) event_reset +@ cdecl -arch=win64 ?reset@event@Concurrency@@QEAAXXZ(ptr) event_reset +@ cdecl -arch=arm ?set@event@Concurrency@@QAAXXZ(ptr) event_set +@ thiscall -arch=win32 ?set@event@Concurrency@@QAEXXZ(ptr) event_set +@ cdecl -arch=win64 ?set@event@Concurrency@@QEAAXXZ(ptr) event_set @ cdecl ?set_new_handler@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_new_handler @ stub -arch=win32 ?set_task_execution_resources@Concurrency@@YAXGPAU_GROUP_AFFINITY@@@Z @ stub -arch=win64 ?set_task_execution_resources@Concurrency@@YAXGPEAU_GROUP_AFFINITY@@@Z @@ -812,14 +812,14 @@ @ cdecl -arch=arm ?wait@_Condition_variable@details@Concurrency@@QAAXAAVcritical_section@3@@Z(ptr ptr) _Condition_variable_wait @ thiscall -arch=i386 ?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z(ptr ptr) _Condition_variable_wait @ cdecl -arch=win64 ?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z(ptr ptr) _Condition_variable_wait -@ stub -arch=arm ?wait@event@Concurrency@@QAAII@Z -@ stub -arch=i386 ?wait@event@Concurrency@@QAEII@Z -@ stub -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z +@ cdecl -arch=arm ?wait@event@Concurrency@@QAAII@Z(ptr) event_wait +@ thiscall -arch=win32 ?wait@event@Concurrency@@QAEII@Z(ptr) event_wait +@ cdecl -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z(ptr) event_wait @ cdecl -arch=arm ?wait_for@_Condition_variable@details@Concurrency@@QAA_NAAVcritical_section@3@I@Z(ptr ptr long) _Condition_variable_wait_for @ thiscall -arch=i386 ?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z(ptr ptr long) _Condition_variable_wait_for @ cdecl -arch=win64 ?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z(ptr ptr long) _Condition_variable_wait_for -@ stub -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z -@ stub -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z +@ cdecl -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z(ptr long long long) event_wait_for_multiple +@ cdecl -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z(ptr long long long) event_wait_for_multiple @ cdecl -arch=arm ?what@exception@std@@UBAPBDXZ(ptr) MSVCRT_what_exception @ thiscall -arch=i386 ?what@exception@std@@UBEPBDXZ(ptr) MSVCRT_what_exception @ cdecl -arch=win64 ?what@exception@std@@UEBAPEBDXZ(ptr) MSVCRT_what_exception @@ -862,12 +862,12 @@ @ stub -arch=arm,win64 __NLG_Return2 @ stub -arch=win64 _SetImageBase @ stub -arch=win64 _SetThrowImageBase -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _Unlock_shared_ptr_spin_lock() @ cdecl _W_Getdays() @ cdecl _W_Getmonths() @ cdecl _W_Gettnames() -@ stub _Wcsftime +@ cdecl _Wcsftime(ptr long wstr ptr ptr) @ cdecl _XcptFilter(long ptr) @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @@ -930,7 +930,7 @@ @ stub -arch=i386,win64 __crtSetThreadStackGuarantee @ cdecl __crtSetUnhandledExceptionFilter(ptr) MSVCR110__crtSetUnhandledExceptionFilter @ cdecl -arch=i386,win64 __crtTerminateProcess(long) MSVCR110__crtTerminateProcess -@ stub -arch=i386,win64 __crtUnhandledException +@ cdecl -arch=i386,win64 __crtUnhandledException(ptr) MSVCRT__crtUnhandledException @ cdecl __daylight() MSVCRT___p__daylight @ cdecl __dllonexit(ptr ptr ptr) @ cdecl __doserrno() MSVCRT___doserrno @@ -1697,7 +1697,7 @@ @ cdecl _strdup(str) MSVCRT__strdup @ cdecl _strerror(long) MSVCRT__strerror @ stub _strerror_s -@ cdecl _strftime_l(str long str ptr ptr) MSVCRT__strftime_l +@ cdecl _strftime_l(ptr long str ptr ptr) MSVCRT__strftime_l @ cdecl _stricmp(str str) MSVCRT__stricmp @ cdecl _stricmp_l(str str ptr) MSVCRT__stricmp_l @ cdecl _stricoll(str str) MSVCRT__stricoll @@ -2163,7 +2163,7 @@ @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strerror_s(ptr long long) MSVCRT_strerror_s -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncat_s(str long str long) MSVCRT_strncat_s diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr120/msvcr120.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr120/msvcr120.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr120/msvcr120.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr120/msvcr120.spec 2017-03-21 14:02:57.000000000 +0000 @@ -119,9 +119,9 @@ @ stub -arch=arm ??0default_scheduler_exists@Concurrency@@QAA@XZ @ stub -arch=i386 ??0default_scheduler_exists@Concurrency@@QAE@XZ @ stub -arch=win64 ??0default_scheduler_exists@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0event@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0event@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0event@Concurrency@@QAA@XZ(ptr) event_ctor +@ thiscall -arch=win32 ??0event@Concurrency@@QAE@XZ(ptr) event_ctor +@ cdecl -arch=win64 ??0event@Concurrency@@QEAA@XZ(ptr) event_ctor @ cdecl -arch=arm ??0exception@std@@QAA@ABQBD@Z(ptr ptr) MSVCRT_exception_ctor @ thiscall -arch=i386 ??0exception@std@@QAE@ABQBD@Z(ptr ptr) MSVCRT_exception_ctor @ cdecl -arch=win64 ??0exception@std@@QEAA@AEBQEBD@Z(ptr ptr) MSVCRT_exception_ctor @@ -310,9 +310,9 @@ @ cdecl -arch=arm ??1critical_section@Concurrency@@QAA@XZ(ptr) critical_section_dtor @ thiscall -arch=i386 ??1critical_section@Concurrency@@QAE@XZ(ptr) critical_section_dtor @ cdecl -arch=win64 ??1critical_section@Concurrency@@QEAA@XZ(ptr) critical_section_dtor -@ stub -arch=arm ??1event@Concurrency@@QAA@XZ -@ stub -arch=i386 ??1event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1event@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??1event@Concurrency@@QAA@XZ(ptr) event_dtor +@ thiscall -arch=win32 ??1event@Concurrency@@QAE@XZ(ptr) event_dtor +@ cdecl -arch=win64 ??1event@Concurrency@@QEAA@XZ(ptr) event_dtor @ cdecl -arch=arm ??1exception@std@@UAA@XZ(ptr) MSVCRT_exception_dtor @ thiscall -arch=i386 ??1exception@std@@UAE@XZ(ptr) MSVCRT_exception_dtor @ cdecl -arch=win64 ??1exception@std@@UEAA@XZ(ptr) MSVCRT_exception_dtor @@ -752,12 +752,12 @@ @ cdecl -arch=arm ?raw_name@type_info@@QBAPBDXZ(ptr) MSVCRT_type_info_raw_name @ thiscall -arch=i386 ?raw_name@type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_raw_name @ cdecl -arch=win64 ?raw_name@type_info@@QEBAPEBDXZ(ptr) MSVCRT_type_info_raw_name -@ stub -arch=arm ?reset@event@Concurrency@@QAAXXZ -@ stub -arch=i386 ?reset@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?reset@event@Concurrency@@QEAAXXZ -@ stub -arch=arm ?set@event@Concurrency@@QAAXXZ -@ stub -arch=i386 ?set@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?set@event@Concurrency@@QEAAXXZ +@ cdecl -arch=arm ?reset@event@Concurrency@@QAAXXZ(ptr) event_reset +@ thiscall -arch=win32 ?reset@event@Concurrency@@QAEXXZ(ptr) event_reset +@ cdecl -arch=win64 ?reset@event@Concurrency@@QEAAXXZ(ptr) event_reset +@ cdecl -arch=arm ?set@event@Concurrency@@QAAXXZ(ptr) event_set +@ thiscall -arch=win32 ?set@event@Concurrency@@QAEXXZ(ptr) event_set +@ cdecl -arch=win64 ?set@event@Concurrency@@QEAAXXZ(ptr) event_set @ cdecl ?set_new_handler@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_new_handler @ stub -arch=win32 ?set_task_execution_resources@Concurrency@@YAXGPAU_GROUP_AFFINITY@@@Z @ stub -arch=win64 ?set_task_execution_resources@Concurrency@@YAXGPEAU_GROUP_AFFINITY@@@Z @@ -794,14 +794,14 @@ @ cdecl -arch=arm ?wait@_Condition_variable@details@Concurrency@@QAAXAAVcritical_section@3@@Z(ptr ptr) _Condition_variable_wait @ thiscall -arch=i386 ?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z(ptr ptr) _Condition_variable_wait @ cdecl -arch=win64 ?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z(ptr ptr) _Condition_variable_wait -@ stub -arch=arm ?wait@event@Concurrency@@QAAII@Z -@ stub -arch=i386 ?wait@event@Concurrency@@QAEII@Z -@ stub -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z +@ cdecl -arch=arm ?wait@event@Concurrency@@QAAII@Z(ptr) event_wait +@ thiscall -arch=win32 ?wait@event@Concurrency@@QAEII@Z(ptr) event_wait +@ cdecl -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z(ptr) event_wait @ cdecl -arch=arm ?wait_for@_Condition_variable@details@Concurrency@@QAA_NAAVcritical_section@3@I@Z(ptr ptr long) _Condition_variable_wait_for @ thiscall -arch=i386 ?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z(ptr ptr long) _Condition_variable_wait_for @ cdecl -arch=win64 ?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z(ptr ptr long) _Condition_variable_wait_for -@ stub -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z -@ stub -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z +@ cdecl -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z(ptr long long long) event_wait_for_multiple +@ cdecl -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z(ptr long long long) event_wait_for_multiple @ cdecl -arch=arm ?what@exception@std@@UBAPBDXZ(ptr) MSVCRT_what_exception @ thiscall -arch=i386 ?what@exception@std@@UBEPBDXZ(ptr) MSVCRT_what_exception @ cdecl -arch=win64 ?what@exception@std@@UEBAPEBDXZ(ptr) MSVCRT_what_exception @@ -847,11 +847,11 @@ @ stub _SetWinRTOutOfMemoryExceptionCallback @ stub -arch=win64 _SetImageBase @ stub -arch=win64 _SetThrowImageBase -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _W_Getdays() @ cdecl _W_Getmonths() @ cdecl _W_Gettnames() -@ stub _Wcsftime +@ cdecl _Wcsftime(ptr long wstr ptr ptr) @ cdecl _XcptFilter(long ptr) @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @@ -920,7 +920,7 @@ @ cdecl __crtSetUnhandledExceptionFilter(ptr) MSVCR110__crtSetUnhandledExceptionFilter @ cdecl -arch=i386,win64 __crtTerminateProcess(long) MSVCR110__crtTerminateProcess @ stub __crtSleep -@ stub -arch=i386,win64 __crtUnhandledException +@ cdecl -arch=i386,win64 __crtUnhandledException(ptr) MSVCRT__crtUnhandledException @ cdecl __daylight() MSVCRT___p__daylight @ cdecl __dllonexit(ptr ptr ptr) @ cdecl __doserrno() MSVCRT___doserrno @@ -1708,7 +1708,7 @@ @ cdecl _strdup(str) MSVCRT__strdup @ cdecl _strerror(long) MSVCRT__strerror @ stub _strerror_s -@ cdecl _strftime_l(str long str ptr ptr) MSVCRT__strftime_l +@ cdecl _strftime_l(ptr long str ptr ptr) MSVCRT__strftime_l @ cdecl _stricmp(str str) MSVCRT__stricmp @ cdecl _stricmp_l(str str ptr) MSVCRT__stricmp_l @ cdecl _stricoll(str str) MSVCRT__stricoll @@ -2373,7 +2373,7 @@ @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strerror_s(ptr long long) MSVCRT_strerror_s -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncat_s(str long str long) MSVCRT_strncat_s diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr120_app/msvcr120_app.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr120_app/msvcr120_app.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr120_app/msvcr120_app.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr120_app/msvcr120_app.spec 2017-03-21 14:02:57.000000000 +0000 @@ -117,9 +117,9 @@ @ stub -arch=arm ??0default_scheduler_exists@Concurrency@@QAA@XZ @ stub -arch=i386 ??0default_scheduler_exists@Concurrency@@QAE@XZ @ stub -arch=win64 ??0default_scheduler_exists@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0event@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0event@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0event@Concurrency@@QAA@XZ(ptr) msvcr120.??0event@Concurrency@@QAA@XZ +@ thiscall -arch=win32 ??0event@Concurrency@@QAE@XZ(ptr) msvcr120.??0event@Concurrency@@QAE@XZ +@ cdecl -arch=win64 ??0event@Concurrency@@QEAA@XZ(ptr) msvcr120.??0event@Concurrency@@QEAA@XZ @ cdecl -arch=arm ??0exception@std@@QAA@ABQBD@Z(ptr ptr) msvcr120.??0exception@std@@QAA@ABQBD@Z @ thiscall -arch=i386 ??0exception@std@@QAE@ABQBD@Z(ptr ptr) msvcr120.??0exception@std@@QAE@ABQBD@Z @ cdecl -arch=win64 ??0exception@std@@QEAA@AEBQEBD@Z(ptr ptr) msvcr120.??0exception@std@@QEAA@AEBQEBD@Z @@ -307,9 +307,9 @@ @ cdecl -arch=arm ??1critical_section@Concurrency@@QAA@XZ(ptr) msvcr120.??1critical_section@Concurrency@@QAA@XZ @ thiscall -arch=i386 ??1critical_section@Concurrency@@QAE@XZ(ptr) msvcr120.??1critical_section@Concurrency@@QAE@XZ @ cdecl -arch=win64 ??1critical_section@Concurrency@@QEAA@XZ(ptr) msvcr120.??1critical_section@Concurrency@@QEAA@XZ -@ stub -arch=arm ??1event@Concurrency@@QAA@XZ -@ stub -arch=i386 ??1event@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1event@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??1event@Concurrency@@QAA@XZ(ptr) msvcr120.??1event@Concurrency@@QAA@XZ +@ thiscall -arch=win32 ??1event@Concurrency@@QAE@XZ(ptr) msvcr120.??1event@Concurrency@@QAE@XZ +@ cdecl -arch=win64 ??1event@Concurrency@@QEAA@XZ(ptr) msvcr120.??1event@Concurrency@@QEAA@XZ @ cdecl -arch=arm ??1exception@std@@UAA@XZ(ptr) msvcr120.??1exception@std@@UAA@XZ @ thiscall -arch=i386 ??1exception@std@@UAE@XZ(ptr) msvcr120.??1exception@std@@UAE@XZ @ cdecl -arch=win64 ??1exception@std@@UEAA@XZ(ptr) msvcr120.??1exception@std@@UEAA@XZ @@ -748,12 +748,12 @@ @ cdecl -arch=arm ?raw_name@type_info@@QBAPBDXZ(ptr) msvcr120.?raw_name@type_info@@QBAPBDXZ @ thiscall -arch=i386 ?raw_name@type_info@@QBEPBDXZ(ptr) msvcr120.?raw_name@type_info@@QBEPBDXZ @ cdecl -arch=win64 ?raw_name@type_info@@QEBAPEBDXZ(ptr) msvcr120.?raw_name@type_info@@QEBAPEBDXZ -@ stub -arch=arm ?reset@event@Concurrency@@QAAXXZ -@ stub -arch=i386 ?reset@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?reset@event@Concurrency@@QEAAXXZ -@ stub -arch=arm ?set@event@Concurrency@@QAAXXZ -@ stub -arch=i386 ?set@event@Concurrency@@QAEXXZ -@ stub -arch=win64 ?set@event@Concurrency@@QEAAXXZ +@ cdecl -arch=arm ?reset@event@Concurrency@@QAAXXZ(ptr) msvcr120.?reset@event@Concurrency@@QAAXXZ +@ thiscall -arch=win32 ?reset@event@Concurrency@@QAEXXZ(ptr) msvcr120.?reset@event@Concurrency@@QAEXXZ +@ cdecl -arch=win64 ?reset@event@Concurrency@@QEAAXXZ(ptr) msvcr120.?reset@event@Concurrency@@QEAAXXZ +@ cdecl -arch=arm ?set@event@Concurrency@@QAAXXZ(ptr) msvcr120.?set@event@Concurrency@@QAAXXZ +@ thiscall -arch=win32 ?set@event@Concurrency@@QAEXXZ(ptr) msvcr120.?set@event@Concurrency@@QAEXXZ +@ cdecl -arch=win64 ?set@event@Concurrency@@QEAAXXZ(ptr) msvcr120.?set@event@Concurrency@@QEAAXXZ @ cdecl ?set_new_handler@@YAP6AXXZP6AXXZ@Z(ptr) msvcr120.?set_new_handler@@YAP6AXXZP6AXXZ@Z @ stub -arch=win32 ?set_task_execution_resources@Concurrency@@YAXGPAU_GROUP_AFFINITY@@@Z @ stub -arch=win64 ?set_task_execution_resources@Concurrency@@YAXGPEAU_GROUP_AFFINITY@@@Z @@ -790,14 +790,14 @@ @ cdecl -arch=arm ?wait@_Condition_variable@details@Concurrency@@QAAXAAVcritical_section@3@@Z(ptr ptr) msvcr120.?wait@_Condition_variable@details@Concurrency@@QAAXAAVcritical_section@3@@Z @ thiscall -arch=i386 ?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z(ptr ptr) msvcr120.?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z @ cdecl -arch=win64 ?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z(ptr ptr) msvcr120.?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z -@ stub -arch=arm ?wait@event@Concurrency@@QAAII@Z -@ stub -arch=i386 ?wait@event@Concurrency@@QAEII@Z -@ stub -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z +@ cdecl -arch=arm ?wait@event@Concurrency@@QAAII@Z(ptr) msvcr120.?wait@event@Concurrency@@QAAII@Z +@ thiscall -arch=win32 ?wait@event@Concurrency@@QAEII@Z(ptr) msvcr120.?wait@event@Concurrency@@QAEII@Z +@ cdecl -arch=win64 ?wait@event@Concurrency@@QEAA_KI@Z(ptr) msvcr120.?wait@event@Concurrency@@QEAA_KI@Z @ cdecl -arch=arm ?wait_for@_Condition_variable@details@Concurrency@@QAA_NAAVcritical_section@3@I@Z(ptr ptr long) msvcr120.?wait_for@_Condition_variable@details@Concurrency@@QAA_NAAVcritical_section@3@I@Z @ thiscall -arch=i386 ?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z(ptr ptr long) msvcr120.?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z @ cdecl -arch=win64 ?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z(ptr ptr long) msvcr120.?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z -@ stub -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z -@ stub -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z +@ cdecl -arch=win32 ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z(ptr long long long) msvcr120.?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z +@ cdecl -arch=win64 ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z(ptr long long long) msvcr120.?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z @ cdecl -arch=arm ?what@exception@std@@UBAPBDXZ(ptr) msvcr120.?what@exception@std@@UBAPBDXZ @ thiscall -arch=i386 ?what@exception@std@@UBEPBDXZ(ptr) msvcr120.?what@exception@std@@UBEPBDXZ @ cdecl -arch=win64 ?what@exception@std@@UEBAPEBDXZ(ptr) msvcr120.?what@exception@std@@UEBAPEBDXZ @@ -841,11 +841,11 @@ @ stub _SetWinRTOutOfMemoryExceptionCallback @ stub -arch=win64 _SetImageBase @ stub -arch=win64 _SetThrowImageBase -@ cdecl _Strftime(str long str ptr ptr) msvcr120._Strftime +@ cdecl _Strftime(ptr long str ptr ptr) msvcr120._Strftime @ cdecl _W_Getdays() msvcr120._W_Getdays @ cdecl _W_Getmonths() msvcr120._W_Getmonths @ cdecl _W_Gettnames() msvcr120._W_Gettnames -@ stub _Wcsftime +@ cdecl _Wcsftime(ptr long wstr ptr ptr) msvcr120._Wcsftime @ cdecl _XcptFilter(long ptr) msvcr120._XcptFilter @ cdecl __AdjustPointer(ptr ptr) msvcr120.__AdjustPointer @ stub __BuildCatchObject @@ -1419,7 +1419,7 @@ @ cdecl _strdup(str) msvcr120._strdup @ cdecl _strerror(long) msvcr120._strerror @ stub _strerror_s -@ cdecl _strftime_l(str long str ptr ptr) msvcr120._strftime_l +@ cdecl _strftime_l(ptr long str ptr ptr) msvcr120._strftime_l @ cdecl _stricmp(str str) msvcr120._stricmp @ cdecl _stricmp_l(str str ptr) msvcr120._stricmp_l @ cdecl _stricoll(str str) msvcr120._stricoll @@ -2036,7 +2036,7 @@ @ cdecl strcspn(str str) msvcr120.strcspn @ cdecl strerror(long) msvcr120.strerror @ cdecl strerror_s(ptr long long) msvcr120.strerror_s -@ cdecl strftime(str long str ptr) msvcr120.strftime +@ cdecl strftime(ptr long str ptr) msvcr120.strftime @ cdecl strlen(str) msvcr120.strlen @ cdecl strncat(str str long) msvcr120.strncat @ cdecl strncat_s(str long str long) msvcr120.strncat_s diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr70/msvcr70.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr70/msvcr70.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr70/msvcr70.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr70/msvcr70.spec 2017-03-21 14:02:57.000000000 +0000 @@ -114,7 +114,7 @@ @ cdecl _Getmonths() @ cdecl _Gettnames() @ extern _HUGE MSVCRT__HUGE -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _XcptFilter(long ptr) @ stub __CxxCallUnwindDtor @ stub __CxxCallUnwindVecDtor @@ -816,7 +816,7 @@ @ cdecl strcpy(ptr str) ntdll.strcpy @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncmp(str str long) MSVCRT_strncmp diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr71/msvcr71.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr71/msvcr71.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr71/msvcr71.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr71/msvcr71.spec 2017-03-21 14:02:57.000000000 +0000 @@ -108,7 +108,7 @@ @ cdecl _Getmonths() @ cdecl _Gettnames() @ extern _HUGE MSVCRT__HUGE -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _XcptFilter(long ptr) @ cdecl -arch=i386,x86_64,arm __CppXcptFilter(long ptr) @ stub __CxxCallUnwindDtor @@ -812,7 +812,7 @@ @ cdecl strcpy(ptr str) ntdll.strcpy @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncmp(str str long) MSVCRT_strncmp diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr80/msvcr80.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr80/msvcr80.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr80/msvcr80.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr80/msvcr80.spec 2017-03-21 14:02:57.000000000 +0000 @@ -170,7 +170,7 @@ @ stub -arch=arm,win64 __NLG_Return2 @ stub -arch=win64 _SetImageBase @ stub -arch=win64 _SetThrowImageBase -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _XcptFilter(long ptr) @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @@ -1020,7 +1020,7 @@ @ cdecl _strdup(str) MSVCRT__strdup @ cdecl _strerror(long) MSVCRT__strerror @ stub _strerror_s -@ cdecl _strftime_l(str long str ptr ptr) MSVCRT__strftime_l +@ cdecl _strftime_l(ptr long str ptr ptr) MSVCRT__strftime_l @ cdecl _stricmp(str str) MSVCRT__stricmp @ cdecl _stricmp_l(str str ptr) MSVCRT__stricmp_l @ cdecl _stricoll(str str) MSVCRT__stricoll @@ -1485,7 +1485,7 @@ @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strerror_s(ptr long long) MSVCRT_strerror_s -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncat_s(str long str long) MSVCRT_strncat_s diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr90/msvcr90.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr90/msvcr90.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcr90/msvcr90.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcr90/msvcr90.spec 2017-03-21 14:02:57.000000000 +0000 @@ -161,7 +161,7 @@ @ stub _NLG_Dispatch2 @ stub _NLG_Return @ stub _NLG_Return2 -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _XcptFilter(long ptr) @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @@ -995,7 +995,7 @@ @ cdecl _strdup(str) MSVCRT__strdup @ cdecl _strerror(long) MSVCRT__strerror @ stub _strerror_s -@ cdecl _strftime_l(str long str ptr ptr) MSVCRT__strftime_l +@ cdecl _strftime_l(ptr long str ptr ptr) MSVCRT__strftime_l @ cdecl _stricmp(str str) MSVCRT__stricmp @ cdecl _stricmp_l(str str ptr) MSVCRT__stricmp_l @ cdecl _stricoll(str str) MSVCRT__stricoll @@ -1458,7 +1458,7 @@ @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strerror_s(ptr long long) MSVCRT_strerror_s -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncat_s(str long str long) MSVCRT_strncat_s diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/lock.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/lock.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/lock.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/lock.c 2017-03-21 14:02:57.000000000 +0000 @@ -550,6 +550,63 @@ return val; } +typedef struct +{ + volatile void *wait; + void *reset; + critical_section cs; +} event; + +/* ??0event@Concurrency@@QAE@XZ */ +/* ??0event@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(event_ctor, 4) +event* __thiscall event_ctor(event *this) +{ + FIXME("(%p) stub\n", this); + return this; +} + +/* ??1event@Concurrency@@QAE@XZ */ +/* ??1event@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(event_dtor, 4) +void __thiscall event_dtor(event *this) +{ + FIXME("(%p) stub\n", this); +} + +/* ?reset@event@Concurrency@@QAEXXZ */ +/* ?reset@event@Concurrency@@QEAAXXZ */ +DEFINE_THISCALL_WRAPPER(event_reset, 4) +void __thiscall event_reset(event *this) +{ + FIXME("(%p) stub\n", this); +} + +/* ?set@event@Concurrency@@QAEXXZ */ +/* ?set@event@Concurrency@@QEAAXXZ */ +DEFINE_THISCALL_WRAPPER(event_set, 4) +void __thiscall event_set(event *this) +{ + FIXME("(%p) stub\n", this); +} + +/* ?wait@event@Concurrency@@QAEII@Z */ +/* ?wait@event@Concurrency@@QEAA_KI@Z */ +DEFINE_THISCALL_WRAPPER(event_wait, 8) +size_t __thiscall event_wait(event *this, unsigned int timeout) +{ + FIXME("(%p %u) stub\n", this, timeout); + return COOPERATIVE_WAIT_TIMEOUT; +} + +/* ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z */ +/* ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z */ +int __cdecl event_wait_for_multiple(event **events, MSVCRT_size_t count, MSVCRT_bool wait_all, unsigned int timeout) +{ + FIXME("(%p %ld %d %u) stub\n", events, count, wait_all, timeout); + return COOPERATIVE_WAIT_TIMEOUT; +} + #endif #if _MSVCR_VER >= 110 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/misc.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/misc.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/misc.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/misc.c 2017-03-21 14:02:57.000000000 +0000 @@ -532,3 +532,13 @@ { WARN("(%x)\n", reserved); } + +/********************************************************************* + * __crtUnhandledException (MSVCR110.@) + */ +LONG CDECL MSVCRT__crtUnhandledException(EXCEPTION_POINTERS *ep) +{ + TRACE("(%p)\n", ep); + SetUnhandledExceptionFilter(NULL); + return UnhandledExceptionFilter(ep); +} diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/msvcrt.h wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/msvcrt.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/msvcrt.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/msvcrt.h 2017-03-21 14:02:57.000000000 +0000 @@ -1181,6 +1181,8 @@ #define UCRTBASE_SCANF_MASK (0x0007) +#define COOPERATIVE_WAIT_TIMEOUT ~0 + typedef enum { _FpCodeUnspecified, _FpCodeAdd, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/msvcrt.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/msvcrt.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/msvcrt.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/msvcrt.spec 2017-03-21 14:02:57.000000000 +0000 @@ -170,7 +170,7 @@ @ cdecl _Getmonths() @ cdecl _Gettnames() @ extern _HUGE MSVCRT__HUGE -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _XcptFilter(long ptr) @ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler @ cdecl -arch=i386,x86_64,arm __CppXcptFilter(long ptr) @@ -1426,7 +1426,7 @@ @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strerror_s(ptr long long) MSVCRT_strerror_s -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncat_s(str long str long) MSVCRT_strncat_s diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/time.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/time.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt/time.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt/time.c 2017-03-21 14:02:57.000000000 +0000 @@ -1273,16 +1273,14 @@ return strftime_helper(str, max, format, mstm, NULL, NULL); } -/********************************************************************* - * _wcsftime_l (MSVCRT.@) - */ -MSVCRT_size_t CDECL MSVCRT__wcsftime_l( MSVCRT_wchar_t *str, MSVCRT_size_t max, - const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm, MSVCRT__locale_t loc ) +static MSVCRT_size_t wcsftime_helper( MSVCRT_wchar_t *str, MSVCRT_size_t max, + const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm, + MSVCRT___lc_time_data *time_data, MSVCRT__locale_t loc ) { char *s, *fmt; MSVCRT_size_t len; - TRACE("%p %ld %s %p %p\n", str, max, debugstr_w(format), mstm, loc); + TRACE("%p %ld %s %p %p %p\n", str, max, debugstr_w(format), mstm, time_data, loc); len = MSVCRT__wcstombs_l( NULL, format, 0, loc ) + 1; if (!(fmt = MSVCRT_malloc( len ))) return 0; @@ -1290,7 +1288,7 @@ if ((s = MSVCRT_malloc( max*4 ))) { - if (!MSVCRT__strftime_l( s, max*4, fmt, mstm, loc )) s[0] = 0; + if (!strftime_helper( s, max*4, fmt, mstm, time_data, loc )) s[0] = 0; len = MSVCRT__mbstowcs_l( str, s, max, loc ); MSVCRT_free( s ); } @@ -1301,12 +1299,31 @@ } /********************************************************************* + * _wcsftime_l (MSVCRT.@) + */ +MSVCRT_size_t CDECL MSVCRT__wcsftime_l( MSVCRT_wchar_t *str, MSVCRT_size_t max, + const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm, MSVCRT__locale_t loc ) +{ + return wcsftime_helper(str, max, format, mstm, NULL, loc); +} + +/********************************************************************* * wcsftime (MSVCRT.@) */ MSVCRT_size_t CDECL MSVCRT_wcsftime( MSVCRT_wchar_t *str, MSVCRT_size_t max, const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm ) { - return MSVCRT__wcsftime_l(str, max, format, mstm, NULL); + return wcsftime_helper(str, max, format, mstm, NULL, NULL); +} + +/********************************************************************* + * _Wcsftime (MSVCRT.@) + */ +MSVCRT_size_t CDECL _Wcsftime(MSVCRT_wchar_t *str, MSVCRT_size_t max, + const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm, + MSVCRT___lc_time_data *time_data) +{ + return wcsftime_helper(str, max, format, mstm, time_data, NULL); } static char* asctime_buf(char *buf, const struct MSVCRT_tm *mstm) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt20/msvcrt20.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt20/msvcrt20.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt20/msvcrt20.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt20/msvcrt20.spec 2017-03-21 14:02:57.000000000 +0000 @@ -1404,7 +1404,7 @@ @ cdecl strcpy(ptr str) msvcrt.strcpy @ cdecl strcspn(str str) msvcrt.strcspn @ cdecl strerror(long) msvcrt.strerror -@ cdecl strftime(str long str ptr) msvcrt.strftime +@ cdecl strftime(ptr long str ptr) msvcrt.strftime @ cdecl strlen(str) msvcrt.strlen @ cdecl strncat(str str long) msvcrt.strncat @ cdecl strncmp(str str long) msvcrt.strncmp diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt40/msvcrt40.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt40/msvcrt40.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrt40/msvcrt40.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrt40/msvcrt40.spec 2017-03-21 14:02:57.000000000 +0000 @@ -1472,7 +1472,7 @@ @ cdecl strcpy(ptr str) msvcrt.strcpy @ cdecl strcspn(str str) msvcrt.strcspn @ cdecl strerror(long) msvcrt.strerror -@ cdecl strftime(str long str ptr) msvcrt.strftime +@ cdecl strftime(ptr long str ptr) msvcrt.strftime @ cdecl strlen(str) msvcrt.strlen @ cdecl strncat(str str long) msvcrt.strncat @ cdecl strncmp(str str long) msvcrt.strncmp diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrtd/msvcrtd.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrtd/msvcrtd.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msvcrtd/msvcrtd.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msvcrtd/msvcrtd.spec 2017-03-21 14:02:57.000000000 +0000 @@ -122,7 +122,7 @@ @ cdecl _Getmonths() msvcrt._Getmonths @ cdecl _Gettnames() msvcrt._Gettnames @ extern _HUGE msvcrt._HUGE -@ cdecl _Strftime(str long str ptr ptr) msvcrt._Strftime +@ cdecl _Strftime(ptr long str ptr ptr) msvcrt._Strftime @ cdecl _XcptFilter(long ptr) msvcrt._XcptFilter @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr) msvcrt.__CxxFrameHandler @ stdcall -arch=i386 __CxxLongjmpUnwind(ptr) msvcrt.__CxxLongjmpUnwind @@ -768,7 +768,7 @@ @ cdecl strcpy(ptr str) msvcrt.strcpy @ cdecl strcspn(str str) msvcrt.strcspn @ cdecl strerror(long) msvcrt.strerror -@ cdecl strftime(str long str ptr) msvcrt.strftime +@ cdecl strftime(ptr long str ptr) msvcrt.strftime @ cdecl strlen(str) msvcrt.strlen @ cdecl strncat(str str long) msvcrt.strncat @ cdecl strncmp(str str long) msvcrt.strncmp diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msxml3/saxreader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msxml3/saxreader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msxml3/saxreader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msxml3/saxreader.c 2017-03-21 14:02:57.000000000 +0000 @@ -2661,10 +2661,12 @@ } case VT_UNKNOWN: case VT_DISPATCH: { - IPersistStream *persistStream; ISequentialStream *stream = NULL; IXMLDOMDocument *xmlDoc; + if (!V_UNKNOWN(&varInput)) + return E_INVALIDARG; + if(IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK) { @@ -2678,34 +2680,11 @@ break; } - if(IUnknown_QueryInterface(V_UNKNOWN(&varInput), - &IID_IPersistStream, (void**)&persistStream) == S_OK) - { - IStream *stream_copy; - - hr = CreateStreamOnHGlobal(NULL, TRUE, &stream_copy); - if(hr != S_OK) - { - IPersistStream_Release(persistStream); - return hr; - } - - hr = IPersistStream_Save(persistStream, stream_copy, TRUE); - IPersistStream_Release(persistStream); - if(hr == S_OK) - IStream_QueryInterface(stream_copy, &IID_ISequentialStream, (void**)&stream); - - IStream_Release(stream_copy); - } - /* try base interface first */ - if(!stream) - { - IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream); - if (!stream) - /* this should never happen if IStream is implemented properly, but just in case */ - IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream); - } + IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream); + if (!stream) + /* this should never happen if IStream is implemented properly, but just in case */ + IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream); if(stream) { diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msxml3/tests/domdoc.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msxml3/tests/domdoc.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msxml3/tests/domdoc.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msxml3/tests/domdoc.c 2017-03-21 14:02:57.000000000 +0000 @@ -1839,12 +1839,15 @@ free_bstrs(); } -static void test_persiststreaminit(void) +static void test_persiststream(void) { - IXMLDOMDocument *doc; IPersistStreamInit *streaminit; + IPersistStream *stream; + IXMLDOMDocument *doc; ULARGE_INTEGER size; + IPersist *persist; HRESULT hr; + CLSID clsid; doc = create_document(&IID_IXMLDOMDocument); @@ -1857,6 +1860,26 @@ hr = IPersistStreamInit_GetSizeMax(streaminit, &size); ok(hr == E_NOTIMPL, "got 0x%08x\n", hr); + hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStream, (void **)&stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok((IUnknown *)stream == (IUnknown *)streaminit, "got %p, %p\n", stream, streaminit); + + hr = IPersistStream_QueryInterface(stream, &IID_IPersist, (void **)&persist); + ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); + + hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersist, (void **)&persist); + ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); + + hr = IPersistStreamInit_GetClassID(streaminit, NULL); + ok(hr == E_POINTER, "got 0x%08x\n", hr); + + memset(&clsid, 0, sizeof(clsid)); + hr = IPersistStreamInit_GetClassID(streaminit, &clsid); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(IsEqualGUID(&clsid, &CLSID_DOMDocument2), "wrong clsid %s\n", wine_dbgstr_guid(&clsid)); + + IPersistStream_Release(stream); + IPersistStreamInit_Release(streaminit); IXMLDOMDocument_Release(doc); } @@ -12189,7 +12212,7 @@ } test_domdoc(); - test_persiststreaminit(); + test_persiststream(); test_domnode(); test_refs(); test_create(); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/msxml3/tests/saxreader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/msxml3/tests/saxreader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/msxml3/tests/saxreader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/msxml3/tests/saxreader.c 2017-03-21 14:02:57.000000000 +0000 @@ -1908,6 +1908,8 @@ { *ppvObject = NULL; + ok(!IsEqualGUID(riid, &IID_IPersistStream), "Did not expect QI for IPersistStream\n"); + if(IsEqualGUID(riid, &IID_IStream) || IsEqualGUID(riid, &IID_IUnknown)) *ppvObject = iface; else @@ -2219,6 +2221,16 @@ SafeArrayDestroy(sa); + V_VT(&var) = VT_UNKNOWN; + V_UNKNOWN(&var) = NULL; + hr = ISAXXMLReader_parse(reader, var); + ok(hr == E_INVALIDARG, "got %#x\n", hr); + + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = NULL; + hr = ISAXXMLReader_parse(reader, var); + ok(hr == E_INVALIDARG, "got %#x\n", hr); + stream = create_test_stream(testXML, -1); V_VT(&var) = VT_UNKNOWN; V_UNKNOWN(&var) = (IUnknown*)stream; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ncrypt/ncrypt.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/ncrypt/ncrypt.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ncrypt/ncrypt.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ncrypt/ncrypt.spec 2017-03-21 14:02:57.000000000 +0000 @@ -13,7 +13,7 @@ @ stdcall BCryptDestroyHash(ptr) bcrypt.BCryptDestroyHash @ stub BCryptDestroyKey @ stub BCryptDestroySecret -@ stub BCryptDuplicateHash +@ stdcall BCryptDuplicateHash(ptr ptr ptr long long) bcrypt.BCryptDuplicateHash @ stub BCryptDuplicateKey @ stub BCryptEncrypt @ stdcall BCryptEnumAlgorithms(long ptr ptr long) bcrypt.BCryptEnumAlgorithms diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/npmshtml/rsrc.rc wine-staging-2.4.0~ubuntu16.04.1/dlls/npmshtml/rsrc.rc --- wine-staging-2.3.0~ubuntu16.04.1/dlls/npmshtml/rsrc.rc 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/npmshtml/rsrc.rc 2017-03-21 14:02:57.000000000 +0000 @@ -18,6 +18,7 @@ #define WINE_FILEDESCRIPTION_STR "Wine ActiveX plugin" #define WINE_FILENAME_STR "npmshtml.dll" +#define WINE_CODEPAGE 04E4 /* need to set "Windows Multilingual" */ #define WINE_EXTRAVALUES \ VALUE "OLESelfRegister", "" \ VALUE "MIMEType", "application/x-oleobject" diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/critsection.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/critsection.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/critsection.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/critsection.c 2017-03-21 14:02:57.000000000 +0000 @@ -665,7 +665,11 @@ */ NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit ) { - if (--crit->RecursionCount) interlocked_dec( &crit->LockCount ); + if (--crit->RecursionCount) + { + if (crit->RecursionCount > 0) interlocked_dec( &crit->LockCount ); + else ERR( "section %p is not acquired\n", crit ); + } else { crit->OwningThread = 0; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/file.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/file.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/file.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/file.c 2017-03-21 14:02:57.000000000 +0000 @@ -2446,6 +2446,19 @@ info->EaSize = 0; } break; + case FileAccessInformation: + { + FILE_ACCESS_INFORMATION *info = ptr; + SERVER_START_REQ( get_object_info ) + { + req->handle = wine_server_obj_handle( hFile ); + io->u.Status = wine_server_call( req ); + if (io->u.Status == STATUS_SUCCESS) + info->AccessFlags = reply->access; + } + SERVER_END_REQ; + } + break; case FileEndOfFileInformation: if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus(); else fill_file_info( &st, attr, ptr, class ); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/server.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/server.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/server.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/server.c 2017-03-21 14:02:57.000000000 +0000 @@ -1211,7 +1211,7 @@ /* retrieve the current directory */ fd_cwd = open( ".", O_RDONLY ); - if (fd_cwd != -1) fcntl( fd_cwd, F_SETFD, 1 ); /* set close on exec flag */ + if (fd_cwd != -1) fcntl( fd_cwd, F_SETFD, FD_CLOEXEC ); setup_config_dir(); serverdir = wine_get_server_dir(); @@ -1274,7 +1274,7 @@ fchdir( fd_cwd ); close( fd_cwd ); } - fcntl( s, F_SETFD, 1 ); /* set close on exec flag */ + fcntl( s, F_SETFD, FD_CLOEXEC ); return s; } close( s ); @@ -1371,7 +1371,7 @@ if (env_socket) { fd_socket = atoi( env_socket ); - if (fcntl( fd_socket, F_SETFD, 1 ) == -1) + if (fcntl( fd_socket, F_SETFD, FD_CLOEXEC ) == -1) fatal_perror( "Bad server socket %d", fd_socket ); unsetenv( "WINESERVERSOCKET" ); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/signal_x86_64.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/signal_x86_64.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/signal_x86_64.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/signal_x86_64.c 2017-03-21 14:02:57.000000000 +0000 @@ -2066,9 +2066,11 @@ extern void raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func ); __ASM_GLOBAL_FUNC( raise_func_trampoline, __ASM_CFI(".cfi_signal_frame\n\t") - __ASM_CFI(".cfi_def_cfa %rbp,144\n\t") /* red zone + rip + rbp */ - __ASM_CFI(".cfi_rel_offset %rip,8\n\t") - __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") + __ASM_CFI(".cfi_def_cfa %rbp,160\n\t") /* red zone + rip + rbp + rdi + rsi */ + __ASM_CFI(".cfi_rel_offset %rip,24\n\t") + __ASM_CFI(".cfi_rel_offset %rbp,16\n\t") + __ASM_CFI(".cfi_rel_offset %rdi,8\n\t") + __ASM_CFI(".cfi_rel_offset %rsi,0\n\t") "call *%rdx\n\t" "int $3") @@ -2085,6 +2087,8 @@ { CONTEXT context; EXCEPTION_RECORD rec; + ULONG64 rsi; + ULONG64 rdi; ULONG64 rbp; ULONG64 rip; ULONG64 red_zone[16]; @@ -2154,6 +2158,8 @@ rsp_ptr = (ULONG64 *)RSP_sig(sigcontext) - 16; *(--rsp_ptr) = RIP_sig(sigcontext); *(--rsp_ptr) = RBP_sig(sigcontext); + *(--rsp_ptr) = RDI_sig(sigcontext); + *(--rsp_ptr) = RSI_sig(sigcontext); /* now modify the sigcontext to return to the raise function */ RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/tests/file.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/tests/file.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/tests/file.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/tests/file.c 2017-03-21 14:02:57.000000000 +0000 @@ -3433,6 +3433,29 @@ CloseHandle( h ); } +static void test_file_access_information(void) +{ + FILE_ACCESS_INFORMATION info; + IO_STATUS_BLOCK io; + NTSTATUS status; + HANDLE h; + + if (!(h = create_temp_file(0))) return; + + status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAccessInformation ); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status ); + + status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAccessInformation ); + ok( status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status ); + + memset(&info, 0x11, sizeof(info)); + status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAccessInformation ); + ok( status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status ); + ok( info.AccessFlags == 0x13019f, "got %08x\n", info.AccessFlags ); + + CloseHandle( h ); +} + static void test_query_volume_information_file(void) { NTSTATUS status; @@ -4385,7 +4408,7 @@ NTSTATUS status; file = create_temp_file(FILE_FLAG_OVERLAPPED); - ok(file != INVALID_HANDLE_VALUE, "coult not create temp file\n"); + ok(file != INVALID_HANDLE_VALUE, "could not create temp file\n"); SetEvent(event); status = pNtFsControlFile(file, event, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0); @@ -4506,6 +4529,7 @@ test_file_disposition_information(); test_file_completion_information(); test_file_id_information(); + test_file_access_information(); test_query_volume_information_file(); test_query_attribute_information_file(); test_ioctl(); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/tests/rtl.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/tests/rtl.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ntdll/tests/rtl.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ntdll/tests/rtl.c 2017-03-21 14:02:57.000000000 +0000 @@ -2094,6 +2094,65 @@ RtlDeleteCriticalSection(&cs); } +static void test_RtlLeaveCriticalSection(void) +{ + RTL_CRITICAL_SECTION cs; + NTSTATUS status; + + if (!pRtlInitializeCriticalSectionEx) + return; /* Skip winxp */ + + status = RtlInitializeCriticalSection(&cs); + ok(!status, "RtlInitializeCriticalSection failed: %x\n", status); + + status = RtlEnterCriticalSection(&cs); + ok(!status, "RtlEnterCriticalSection failed: %x\n", status); + todo_wine + ok(cs.LockCount == -2, "expected LockCount == -2, got %d\n", cs.LockCount); + ok(cs.RecursionCount == 1, "expected RecursionCount == 1, got %d\n", cs.RecursionCount); + ok(cs.OwningThread == ULongToHandle(GetCurrentThreadId()), "unexpected OwningThread\n"); + + status = RtlLeaveCriticalSection(&cs); + ok(!status, "RtlLeaveCriticalSection failed: %x\n", status); + ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount); + ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount); + ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread); + + /* + * Trying to leave a section that wasn't acquired modifies RecusionCount to an invalid value, + * but doesn't modify LockCount so that an attempt to enter the section later will work. + */ + status = RtlLeaveCriticalSection(&cs); + ok(!status, "RtlLeaveCriticalSection failed: %x\n", status); + ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount); + ok(cs.RecursionCount == -1, "expected RecursionCount == -1, got %d\n", cs.RecursionCount); + ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread); + + /* and again */ + status = RtlLeaveCriticalSection(&cs); + ok(!status, "RtlLeaveCriticalSection failed: %x\n", status); + ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount); + ok(cs.RecursionCount == -2, "expected RecursionCount == -2, got %d\n", cs.RecursionCount); + ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread); + + /* entering section fixes RecursionCount */ + status = RtlEnterCriticalSection(&cs); + ok(!status, "RtlEnterCriticalSection failed: %x\n", status); + todo_wine + ok(cs.LockCount == -2, "expected LockCount == -2, got %d\n", cs.LockCount); + ok(cs.RecursionCount == 1, "expected RecursionCount == 1, got %d\n", cs.RecursionCount); + ok(cs.OwningThread == ULongToHandle(GetCurrentThreadId()), "unexpected OwningThread\n"); + + status = RtlLeaveCriticalSection(&cs); + ok(!status, "RtlLeaveCriticalSection failed: %x\n", status); + ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount); + ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount); + ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread); + + status = RtlDeleteCriticalSection(&cs); + ok(!status, "RtlDeleteCriticalSection failed: %x\n", status); +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -2125,4 +2184,5 @@ test_RtlDecompressBuffer(); test_RtlIsCriticalSectionLocked(); test_RtlInitializeCriticalSectionEx(); + test_RtlLeaveCriticalSection(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ntoskrnl.exe/ntoskrnl.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ntoskrnl.exe/ntoskrnl.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ntoskrnl.exe/ntoskrnl.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ntoskrnl.exe/ntoskrnl.c 2017-03-21 14:02:57.000000000 +0000 @@ -1999,6 +1999,19 @@ } /*********************************************************************** + * KeWaitForMultipleObjects (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG Count, PVOID Object[], WAIT_TYPE WaitType, + KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, PLARGE_INTEGER Timeout, + PKWAIT_BLOCK WaitBlockArray) +{ + FIXME( "stub: %u, %p, %d, %d, %d, %d, %p, %p\n", Count, Object, WaitType, WaitReason, WaitMode, + Alertable, Timeout, WaitBlockArray ); + return STATUS_NOT_IMPLEMENTED; +} + +/*********************************************************************** * IoRegisterFileSystem (NTOSKRNL.EXE.@) */ VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject) @@ -3188,3 +3201,29 @@ { FIXME("stub: %p\n", event); } + +/*********************************************************************** + * KeAcquireInStackQueuedSpinLock (NTOSKRNL.EXE.@) + */ +#ifdef DEFINE_FASTCALL2_ENTRYPOINT +DEFINE_FASTCALL2_ENTRYPOINT( KeAcquireInStackQueuedSpinLock ) +void WINAPI __regs_KeAcquireInStackQueuedSpinLock( KSPIN_LOCK *spinlock, KLOCK_QUEUE_HANDLE *handle ) +#else +void WINAPI KeAcquireInStackQueuedSpinLock( KSPIN_LOCK *spinlock, KLOCK_QUEUE_HANDLE *handle ) +#endif +{ + FIXME( "stub: %p %p\n", spinlock, handle ); +} + +/*********************************************************************** + * KeReleaseInStackQueuedSpinLock (NTOSKRNL.EXE.@) + */ +#ifdef DEFINE_FASTCALL1_ENTRYPOINT +DEFINE_FASTCALL1_ENTRYPOINT( KeReleaseInStackQueuedSpinLock ) +void WINAPI __regs_KeReleaseInStackQueuedSpinLock( KLOCK_QUEUE_HANDLE *handle ) +#else +void WINAPI KeReleaseInStackQueuedSpinLock( KLOCK_QUEUE_HANDLE *handle ) +#endif +{ + FIXME( "stub: %p\n", handle); +} diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ntoskrnl.exe/ntoskrnl.exe.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/ntoskrnl.exe/ntoskrnl.exe.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ntoskrnl.exe/ntoskrnl.exe.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ntoskrnl.exe/ntoskrnl.exe.spec 2017-03-21 14:02:57.000000000 +0000 @@ -41,7 +41,9 @@ @ stub IoWritePartitionTable @ stdcall -norelay IofCallDriver(ptr ptr) @ stdcall -norelay IofCompleteRequest(ptr long) +@ stdcall -norelay KeAcquireInStackQueuedSpinLock(ptr ptr) @ stub KeAcquireInStackQueuedSpinLockAtDpcLevel +@ stdcall -norelay KeReleaseInStackQueuedSpinLock(ptr) @ stub KeReleaseInStackQueuedSpinLockFromDpcLevel @ stub KeSetTimeUpdateNotifyRoutine @ stub KefAcquireSpinLockAtDpcLevel @@ -627,7 +629,7 @@ @ stub KeUpdateRunTime @ stub KeUpdateSystemTime @ stub KeUserModeCallback -@ stub KeWaitForMultipleObjects +@ stdcall KeWaitForMultipleObjects(long ptr long long long long ptr ptr) @ stdcall KeWaitForMutexObject(ptr long long long ptr) @ stdcall KeWaitForSingleObject(ptr long long long ptr) @ stub KiBugCheckData diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/odbccp32/odbccp32.c wine-staging-2.4.0~ubuntu16.04.1/dlls/odbccp32/odbccp32.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/odbccp32/odbccp32.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/odbccp32/odbccp32.c 2017-03-21 14:02:57.000000000 +0000 @@ -29,6 +29,7 @@ #include "winbase.h" #include "winreg.h" #include "winnls.h" +#include "wine/unicode.h" #include "wine/debug.h" #include "odbcinst.h" @@ -38,6 +39,8 @@ /* Registry key names */ static const WCHAR drivers_key[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C','\\','O','D','B','C','I','N','S','T','.','I','N','I','\\','O','D','B','C',' ','D','r','i','v','e','r','s',0}; static const WCHAR odbcW[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C',0}; +static const WCHAR odbcini[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C','\\','O','D','B','C','I','N','S','T','.','I','N','I','\\',0}; +static const WCHAR odbcdrivers[] = {'O','D','B','C',' ','D','r','i','v','e','r','s',0}; /* This config mode is known to be process-wide. * MSDN documentation suggests that the value is hidden somewhere in the registry but I haven't found it yet. @@ -626,12 +629,115 @@ pcbPathOut, ODBC_INSTALL_COMPLETE, &usage); } +static void write_registry_values(const WCHAR *regkey, const WCHAR *driver, const WCHAR *path_in, WCHAR *path, + DWORD *usage_count) +{ + static const WCHAR installed[] = {'I','n','s','t','a','l','l','e','d',0}; + static const WCHAR slash[] = {'\\', 0}; + static const WCHAR driverW[] = {'D','r','i','v','e','r',0}; + static const WCHAR setupW[] = {'S','e','t','u','p',0}; + HKEY hkey, hkeydriver; + + if (RegCreateKeyW(HKEY_LOCAL_MACHINE, odbcini, &hkey) == ERROR_SUCCESS) + { + if (RegCreateKeyW(hkey, regkey, &hkeydriver) == ERROR_SUCCESS) + { + if(RegSetValueExW(hkeydriver, driver, 0, REG_SZ, (BYTE*)installed, sizeof(installed)) != ERROR_SUCCESS) + ERR("Failed to write registry installed key\n"); + + RegCloseKey(hkeydriver); + } + + if (RegCreateKeyW(hkey, driver, &hkeydriver) == ERROR_SUCCESS) + { + WCHAR entry[1024]; + const WCHAR *p; + DWORD usagecount = 0; + DWORD type, size; + + /* Skip name entry */ + p = driver; + p += lstrlenW(p) + 1; + + if (!path_in) + GetSystemDirectoryW(path, MAX_PATH); + else + lstrcpyW(path, path_in); + + /* Store Usage */ + size = sizeof(usagecount); + RegGetValueA(hkeydriver, NULL, "UsageCount", RRF_RT_DWORD, &type, &usagecount, &size); + TRACE("Usage count %d\n", usagecount); + + for (; *p; p += lstrlenW(p) + 1) + { + WCHAR *divider = strchrW(p,'='); + + if (divider) + { + WCHAR *value; + int len; + + /* Write pair values to the registry. */ + lstrcpynW(entry, p, divider - p + 1); + + divider++; + TRACE("Writing pair %s,%s\n", debugstr_w(entry), debugstr_w(divider)); + + /* Driver and Setup entries use the system path unless a path is specified. */ + if(lstrcmpiW(driverW, entry) == 0 || lstrcmpiW(setupW, entry) == 0) + { + len = lstrlenW(path) + lstrlenW(slash) + lstrlenW(divider) + 1; + value = heap_alloc(len * sizeof(WCHAR)); + if(!value) + { + ERR("Out of memory\n"); + return; + } + + lstrcpyW(value, path); + lstrcatW(value, slash); + lstrcatW(value, divider); + } + else + { + len = lstrlenW(divider) + 1; + value = heap_alloc(len * sizeof(WCHAR)); + lstrcpyW(value, divider); + } + + if (RegSetValueExW(hkeydriver, entry, 0, REG_SZ, (BYTE*)value, + (lstrlenW(value)+1)*sizeof(WCHAR)) != ERROR_SUCCESS) + ERR("Failed to write registry data %s %s\n", debugstr_w(entry), debugstr_w(value)); + heap_free(value); + } + else + { + ERR("No pair found. %s\n", debugstr_w(p)); + break; + } + } + + /* Set Usage Count */ + usagecount++; + if (RegSetValueExA(hkeydriver, "UsageCount", 0, REG_DWORD, (BYTE*)&usagecount, sizeof(usagecount)) != ERROR_SUCCESS) + ERR("Failed to write registry UsageCount key\n"); + + if (usage_count) + *usage_count = usagecount; + + RegCloseKey(hkeydriver); + } + + RegCloseKey(hkey); + } +} + BOOL WINAPI SQLInstallDriverExW(LPCWSTR lpszDriver, LPCWSTR lpszPathIn, LPWSTR lpszPathOut, WORD cbPathOutMax, WORD *pcbPathOut, WORD fRequest, LPDWORD lpdwUsageCount) { UINT len; - LPCWSTR p; WCHAR path[MAX_PATH]; clear_errors(); @@ -639,16 +745,13 @@ debugstr_w(lpszPathIn), lpszPathOut, cbPathOutMax, pcbPathOut, fRequest, lpdwUsageCount); - for (p = lpszDriver; *p; p += lstrlenW(p) + 1) - TRACE("%s\n", debugstr_w(p)); + write_registry_values(odbcdrivers, lpszDriver, lpszPathIn, path, lpdwUsageCount); - len = GetSystemDirectoryW(path, MAX_PATH); + len = lstrlenW(path); if (pcbPathOut) *pcbPathOut = len; - len = GetSystemDirectoryW(path, MAX_PATH); - if (lpszPathOut && cbPathOutMax > len) { lstrcpyW(lpszPathOut, path); @@ -661,7 +764,6 @@ LPSTR lpszPathOut, WORD cbPathOutMax, WORD *pcbPathOut, WORD fRequest, LPDWORD lpdwUsageCount) { - LPCSTR p; LPWSTR driver, pathin; WCHAR pathout[MAX_PATH]; BOOL ret; @@ -672,9 +774,6 @@ debugstr_a(lpszPathIn), lpszPathOut, cbPathOutMax, pcbPathOut, fRequest, lpdwUsageCount); - for (p = lpszDriver; *p; p += lstrlenA(p) + 1) - TRACE("%s\n", debugstr_a(p)); - driver = SQLInstall_strdup_multi(lpszDriver); pathin = SQLInstall_strdup(lpszPathIn); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/odbccp32/tests/misc.c wine-staging-2.4.0~ubuntu16.04.1/dlls/odbccp32/tests/misc.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/odbccp32/tests/misc.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/odbccp32/tests/misc.c 2017-03-21 14:02:57.000000000 +0000 @@ -412,6 +412,64 @@ } } +void test_SQLInstallDriverEx(void) +{ + char path[MAX_PATH]; + char syspath[MAX_PATH]; + WORD size = 0; + BOOL ret, sql_ret; + DWORD cnt, error_code = 0; + HKEY hkey; + DWORD reg_ret; + + GetSystemDirectoryA(syspath, MAX_PATH); + + SQLInstallDriverEx("WINE ODBC Driver\0Driver=sample.dll\0Setup=sample.dll\0\0", NULL, path, MAX_PATH, &size, ODBC_INSTALL_COMPLETE, NULL); + sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL); + if (sql_ret && error_code == ODBC_ERROR_WRITING_SYSINFO_FAILED) + { + win_skip("not enough privileges\n"); + return; + } + ok(sql_ret && error_code == SQL_SUCCESS, "SQLInstallDriverEx failed %d, %u\n", sql_ret, error_code); + ok(!strcmp(path, syspath), "invalid path %s\n", path); + + ret = SQLInstallDriverEx("WINE ODBC Driver Path\0Driver=sample.dll\0Setup=sample.dll\0\0", "c:\\temp", path, MAX_PATH, &size, ODBC_INSTALL_COMPLETE, NULL); + sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL); + ok(sql_ret && error_code == SQL_SUCCESS, "SQLInstallDriverEx failed %d, %u\n", sql_ret, error_code); + ok(!strcmp(path, "c:\\temp"), "invalid path %s\n", path); + + if (ret) + { + reg_ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBCINST.INI\\WINE ODBC Driver", 0, KEY_READ, &hkey); + ok(reg_ret == ERROR_SUCCESS, "RegOpenKeyExW failed\n"); + if (reg_ret == ERROR_SUCCESS) + { + DWORD type, size = MAX_PATH; + char driverpath[MAX_PATH]; + + strcpy(driverpath, syspath); + strcat(driverpath, "\\sample.dll"); + + reg_ret = RegGetValueA(hkey, NULL, "Driver", RRF_RT_REG_SZ, &type, &path, &size); + ok(reg_ret == ERROR_SUCCESS, "RegGetValueA failed\n"); + ok(!strcmp(path, driverpath), "invalid path %s\n", path); + + RegCloseKey(hkey); + } + } + + cnt = 100; + ret = SQLRemoveDriver("WINE ODBC Driver", FALSE, &cnt); + ok(ret, "SQLRemoveDriver failed\n"); + todo_wine ok(cnt == 0, "SQLRemoveDriver failed %d\n", cnt); + + cnt = 100; + ret = SQLRemoveDriver("WINE ODBC Driver Path", FALSE, &cnt); + ok(ret, "SQLRemoveDriver failed\n"); + todo_wine ok(cnt == 0, "SQLRemoveDriver failed %d\n", cnt); +} + START_TEST(misc) { test_SQLConfigMode(); @@ -420,4 +478,5 @@ test_SQLWritePrivateProfileString(); test_SQLGetPrivateProfileString(); test_SQLGetPrivateProfileStringW(); + test_SQLInstallDriverEx(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ole32/tests/compobj.c wine-staging-2.4.0~ubuntu16.04.1/dlls/ole32/tests/compobj.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ole32/tests/compobj.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ole32/tests/compobj.c 2017-03-21 14:02:57.000000000 +0000 @@ -3569,7 +3569,13 @@ hres = CoCreateInstance(&CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalOptions, (void**)&global_options); - ok(hres == S_OK, "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres); + ok(hres == S_OK || broken(hres == E_NOINTERFACE), "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres); + if(FAILED(hres)) + { + win_skip("CLSID_GlobalOptions not available\n"); + CoUninitialize(); + return; + } IGlobalOptions_Release(global_options); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/oledb32/convert.c wine-staging-2.4.0~ubuntu16.04.1/dlls/oledb32/convert.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/oledb32/convert.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/oledb32/convert.c 2017-03-21 14:02:57.000000000 +0000 @@ -139,6 +139,8 @@ return sizeof(FILETIME); case DBTYPE_GUID: return sizeof(GUID); + case DBTYPE_NUMERIC: + return sizeof(DB_NUMERIC); case DBTYPE_BYTES: case DBTYPE_WSTR: case DBTYPE_STR: diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/oledb32/dslocator.c wine-staging-2.4.0~ubuntu16.04.1/dlls/oledb32/dslocator.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/oledb32/dslocator.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/oledb32/dslocator.c 2017-03-21 14:02:57.000000000 +0000 @@ -73,6 +73,11 @@ { *ppvoid = &This->IDataInitialize_iface; } + else if (IsEqualIID(riid, &IID_IRunnableObject)) + { + TRACE("IID_IRunnableObject returning NULL\n"); + return E_NOINTERFACE; + } if(*ppvoid) { diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/oledb32/tests/convert.c wine-staging-2.4.0~ubuntu16.04.1/dlls/oledb32/tests/convert.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/oledb32/tests/convert.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/oledb32/tests/convert.c 2017-03-21 14:02:57.000000000 +0000 @@ -2266,7 +2266,7 @@ dst_len = 44; V_VT(&v) = VT_NULL; - hr = IDataConvert_DataConvert(convert, DBTYPE_VARIANT, DBTYPE_STR | DBTYPE_BYREF, 0, &dst_len, &v, dst, sizeof(dst), 0, &dst_status, 0, 0, 0); + hr = IDataConvert_DataConvert(convert, DBTYPE_VARIANT, DBTYPE_STR | DBTYPE_BYREF, 0, &dst_len, &v, &dst, sizeof(dst), 0, &dst_status, 0, 0, 0); ok(hr == S_OK, "got %08x\n", hr); ok(dst_status == DBSTATUS_S_ISNULL, "got %08x\n", dst_status); ok(dst_len == 44, "got %ld\n", dst_len); @@ -2857,6 +2857,9 @@ ok(hr == S_OK, "got 0x%08x\n", hr); VariantClear(&var); + hr = IDataConvert_GetConversionSize(convert, DBTYPE_NUMERIC, DBTYPE_NUMERIC, NULL, &dst_len, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(dst_len == sizeof(DB_NUMERIC), "%ld\n", dst_len); } static void test_converttobytes(void) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/oledb32/tests/database.c wine-staging-2.4.0~ubuntu16.04.1/dlls/oledb32/tests/database.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/oledb32/tests/database.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/oledb32/tests/database.c 2017-03-21 14:02:57.000000000 +0000 @@ -859,6 +859,7 @@ if(SUCCEEDED(hr)) { IDataInitialize *datainit, *datainit2; + IRunnableObject *runable; COMPATIBLE_LONG hwnd = 0; if (0) /* Crashes under Window 7 */ @@ -898,6 +899,9 @@ ok(hr == S_OK, "got %08x\n", hr); ok(datainit == datainit2, "Got %p, previous %p\n", datainit, datainit2); + hr = IDataSourceLocator_QueryInterface(dslocator, &IID_IRunnableObject, (void **)&runable); + ok(hr == E_NOINTERFACE, "got %08x\n", hr); + IDataInitialize_Release(datainit2); IDataInitialize_Release(datainit); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/opencl/opencl.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/opencl/opencl.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/opencl/opencl.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/opencl/opencl.spec 2017-03-21 14:02:57.000000000 +0000 @@ -5,8 +5,8 @@ @ stdcall clGetDeviceIDs( long long long ptr ptr ) wine_clGetDeviceIDs @ stdcall clGetDeviceInfo( long long long ptr ptr ) wine_clGetDeviceInfo -@ stdcall clCreateContext( ptr long ptr long ptr ptr ) wine_clCreateContext -@ stdcall clCreateContextFromType( ptr long long ptr ptr ) wine_clCreateContextFromType +@ stdcall clCreateContext(ptr long ptr ptr ptr ptr) wine_clCreateContext +@ stdcall clCreateContextFromType(ptr long ptr ptr ptr) wine_clCreateContextFromType @ stdcall clRetainContext( long ) wine_clRetainContext @ stdcall clReleaseContext( long ) wine_clReleaseContext @ stdcall clGetContextInfo( long long long ptr ptr ) wine_clGetContextInfo @@ -71,7 +71,7 @@ @ stdcall clEnqueueUnmapMemObject( long long ptr long ptr ptr ) wine_clEnqueueUnmapMemObject @ stdcall clEnqueueNDRangeKernel( long long long ptr ptr ptr long ptr ptr ) wine_clEnqueueNDRangeKernel @ stdcall clEnqueueTask( long long long ptr ptr ) wine_clEnqueueTask -@ stdcall clEnqueueNativeKernel( long long ptr long long ptr ptr long ptr ptr ) wine_clEnqueueNativeKernel +@ stdcall clEnqueueNativeKernel(long ptr ptr long long ptr ptr long ptr ptr) wine_clEnqueueNativeKernel @ stdcall clEnqueueMarker( long ptr ) wine_clEnqueueMarker @ stdcall clEnqueueWaitForEvents( long long ptr ) wine_clEnqueueWaitForEvents @ stdcall clEnqueueBarrier( long ) wine_clEnqueueBarrier diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/rasapi32/rasapi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/rasapi32/rasapi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/rasapi32/rasapi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/rasapi32/rasapi.c 2017-03-21 14:02:57.000000000 +0000 @@ -254,6 +254,8 @@ if(lpRasDevinfo && lpRasDevinfo->dwSize != sizeof(RASDEVINFOA)) return ERROR_INVALID_SIZE; + *lpcDevices = 1; + if (!lpRasDevinfo || (*lpcb < sizeof(RASDEVINFOA))) { *lpcb = sizeof(RASDEVINFOA); return ERROR_BUFFER_TOO_SMALL; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/rasapi32/tests/rasapi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/rasapi32/tests/rasapi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/rasapi32/tests/rasapi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/rasapi32/tests/rasapi.c 2017-03-21 14:02:57.000000000 +0000 @@ -77,54 +77,71 @@ /* test first parameter */ cb = bufsize; + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(NULL, &cb, &cDevices); + ok(0 < cDevices && cDevices < 32, "expected 0 < cDevices < 32, got %u\n", cDevices); ok(result == ERROR_BUFFER_TOO_SMALL || result == ERROR_INVALID_USER_BUFFER, /* win98 */ "Expected ERROR_BUFFER_TOO_SMALL, got %08d\n", result); rasDevInfo[0].dwSize = 0; cb = bufsize; + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); + ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); ok(result == ERROR_INVALID_SIZE || result == ERROR_INVALID_USER_BUFFER, /* win98 */ "Expected ERROR_INVALID_SIZE, got %08d\n", result); rasDevInfo[0].dwSize = sizeof(RASDEVINFOA) -1; cb = bufsize; + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); + ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); ok(result == ERROR_INVALID_SIZE || result == ERROR_INVALID_USER_BUFFER, /* win98 */ "Expected ERROR_INVALID_SIZE, got %08d\n", result); rasDevInfo[0].dwSize = sizeof(RASDEVINFOA) +1; cb = bufsize; + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); + ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); ok(result == ERROR_INVALID_SIZE || result == ERROR_INVALID_USER_BUFFER, /* win98 */ "Expected ERROR_INVALID_SIZE, got %08d\n", result); /* test second parameter */ rasDevInfo[0].dwSize = sizeof(RASDEVINFOA); + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(rasDevInfo, NULL, &cDevices); + ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); ok(result == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08d\n", result); rasDevInfo[0].dwSize = sizeof(RASDEVINFOA); cb = 0; + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); + todo_wine + ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); ok(result == ERROR_BUFFER_TOO_SMALL || result == ERROR_INVALID_SIZE, /* vista, 2k8 */ "Expected ERROR_BUFFER_TOO_SMALL/ERROR_INVALID_SIZE, got %08d\n", result); rasDevInfo[0].dwSize = sizeof(RASDEVINFOA); cb = bufsize -1; + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); + ok(0 < cDevices && cDevices < 32, "expected 0 < cDevices < 32, got %u\n", cDevices); ok(result == ERROR_BUFFER_TOO_SMALL, "Expected ERROR_BUFFER_TOO_SMALL, got %08d\n", result); rasDevInfo[0].dwSize = sizeof(RASDEVINFOA); cb = bufsize +1; + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); + ok(0 < cDevices && cDevices < 32, "expected 0 < cDevices < 32, got %u\n", cDevices); ok(result == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08d\n", result); @@ -136,7 +153,9 @@ "Expected ERROR_INVALID_PARAMETER, got %08d\n", result); /* test combinations of invalid parameters */ + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(NULL, NULL, &cDevices); + ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); ok(result == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08d\n", result); @@ -147,7 +166,9 @@ cb = 0; rasDevInfo[0].dwSize = 0; + cDevices = 0xdeadbeef; result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); + ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); ok(result == ERROR_INVALID_SIZE || broken(result == ERROR_BUFFER_TOO_SMALL), /* win98 */ "Expected ERROR_INVALID_SIZE, got %08d\n", result); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/rpcrt4/rpc_server.c wine-staging-2.4.0~ubuntu16.04.1/dlls/rpcrt4/rpc_server.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/rpcrt4/rpc_server.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/rpcrt4/rpc_server.c 2017-03-21 14:02:57.000000000 +0000 @@ -101,11 +101,9 @@ /* whether the server is currently listening */ static BOOL std_listen; -/* number of manual listeners (calls to RpcServerListen) */ -static LONG manual_listen_count; /* total listeners including auto listeners */ static LONG listen_count; -/* event set once all listening is finished */ +/* event set once all manual listening is finished */ static HANDLE listen_done_event; static UUID uuid_nil; @@ -735,13 +733,16 @@ TRACE("\n"); EnterCriticalSection(&listen_cs); - if (auto_listen || (manual_listen_count++ == 0)) + if (auto_listen || !listen_done_event) { status = RPC_S_OK; + if(!auto_listen) + listen_done_event = CreateEventW(NULL, TRUE, FALSE, NULL); if (++listen_count == 1) std_listen = TRUE; } LeaveCriticalSection(&listen_cs); + if (status) return status; if (std_listen) { @@ -764,38 +765,38 @@ static RPC_STATUS RPCRT4_stop_listen(BOOL auto_listen) { + BOOL stop_listen = FALSE; RPC_STATUS status = RPC_S_OK; EnterCriticalSection(&listen_cs); - - if (!std_listen) + if (!std_listen && (auto_listen || !listen_done_event)) { status = RPC_S_NOT_LISTENING; - goto done; } - - if (auto_listen || (--manual_listen_count == 0)) + else { - if (listen_count != 0 && --listen_count == 0) { - RpcServerProtseq *cps; - + stop_listen = listen_count != 0 && --listen_count == 0; + assert(listen_count >= 0); + if (stop_listen) std_listen = FALSE; - LeaveCriticalSection(&listen_cs); + } + LeaveCriticalSection(&listen_cs); - LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) - RPCRT4_sync_with_server_thread(cps); + if (status) return status; - EnterCriticalSection(&listen_cs); - if (listen_done_event) SetEvent( listen_done_event ); - listen_done_event = 0; - goto done; - } - assert(listen_count >= 0); + if (stop_listen) { + RpcServerProtseq *cps; + LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) + RPCRT4_sync_with_server_thread(cps); } -done: - LeaveCriticalSection(&listen_cs); - return status; + if (!auto_listen) + { + EnterCriticalSection(&listen_cs); + SetEvent( listen_done_event ); + LeaveCriticalSection(&listen_cs); + } + return RPC_S_OK; } static BOOL RPCRT4_protseq_is_endpoint_registered(RpcServerProtseq *protseq, const char *endpoint) @@ -1527,25 +1528,23 @@ TRACE("()\n"); EnterCriticalSection(&listen_cs); - - if (!std_listen) { - LeaveCriticalSection(&listen_cs); - return RPC_S_NOT_LISTENING; - } - if (listen_done_event) { - LeaveCriticalSection(&listen_cs); - return RPC_S_ALREADY_LISTENING; - } - event = CreateEventW( NULL, TRUE, FALSE, NULL ); - listen_done_event = event; - + event = listen_done_event; LeaveCriticalSection(&listen_cs); + if (!event) + return RPC_S_NOT_LISTENING; + TRACE( "waiting for server calls to finish\n" ); WaitForSingleObject( event, INFINITE ); TRACE( "done waiting\n" ); - CloseHandle( event ); + EnterCriticalSection(&listen_cs); + if (listen_done_event == event) + { + listen_done_event = NULL; + CloseHandle( event ); + } + LeaveCriticalSection(&listen_cs); return RPC_S_OK; } @@ -1671,7 +1670,7 @@ status = RPCRT4_IsServerListening(rpc_binding->Protseq, rpc_binding->Endpoint); }else { EnterCriticalSection(&listen_cs); - if (manual_listen_count > 0) status = RPC_S_OK; + if (listen_done_event && std_listen) status = RPC_S_OK; LeaveCriticalSection(&listen_cs); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/rpcrt4/tests/rpc.c wine-staging-2.4.0~ubuntu16.04.1/dlls/rpcrt4/tests/rpc.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/rpcrt4/tests/rpc.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/rpcrt4/tests/rpc.c 2017-03-21 14:02:57.000000000 +0000 @@ -250,10 +250,8 @@ ok(status == RPC_S_OK, "RpcServerListen failed (%u)\n", status); status = RpcServerListen(1, 20, TRUE); -todo_wine { ok(status == RPC_S_ALREADY_LISTENING, "wrong RpcServerListen error (%u)\n", status); -} status = RpcStringBindingComposeA(NULL, ncacn_ip_tcp, address, endpoint, NULL, &binding); @@ -301,9 +299,7 @@ ok(status == RPC_S_OK, "RpcServerUnregisterIf failed (%u)\n", status); status = RpcMgmtWaitServerListen(); -todo_wine { ok(status == RPC_S_OK, "RpcMgmtWaitServerListen failed (%u)\n", status); -} status = RpcStringFreeA(&binding); ok(status == RPC_S_OK, "RpcStringFree failed (%u)\n", status); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/rpcrt4/tests/server.c wine-staging-2.4.0~ubuntu16.04.1/dlls/rpcrt4/tests/server.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/rpcrt4/tests/server.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/rpcrt4/tests/server.c 2017-03-21 14:02:57.000000000 +0000 @@ -1752,10 +1752,42 @@ if (ret == WAIT_OBJECT_0) { status = RpcMgmtWaitServerListen(); - todo_wine { - ok(status == RPC_S_OK, "RpcMgmtWaitServerListening failed with status %d\n", status); - } + ok(status == RPC_S_OK, "RpcMgmtWaitServerListening failed with status %d\n", status); } + + CloseHandle(stop_event); + stop_event = NULL; +} + +static void test_server_listening(void) +{ + static unsigned char np[] = "ncacn_np"; + static unsigned char pipe[] = PIPE "listen_test"; + RPC_STATUS status; + + status = RpcServerUseProtseqEpA(np, 0, pipe, NULL); + ok(status == RPC_S_OK, "RpcServerUseProtseqEp(ncacn_np) failed with status %d\n", status); + + status = RpcServerRegisterIf(s_IServer_v0_0_s_ifspec, NULL, NULL); + ok(status == RPC_S_OK, "RpcServerRegisterIf failed with status %d\n", status); + + test_is_server_listening(NULL, RPC_S_NOT_LISTENING); + status = RpcServerListen(1, 20, TRUE); + ok(status == RPC_S_OK, "RpcServerListen failed with status %d\n", status); + test_is_server_listening(NULL, RPC_S_OK); + + status = RpcServerListen(1, 20, TRUE); + ok(status == RPC_S_ALREADY_LISTENING, "RpcServerListen failed with status %d\n", status); + + status = RpcMgmtStopServerListening(NULL); + ok(status == RPC_S_OK, "RpcMgmtStopServerListening\n"); + test_is_server_listening(NULL, RPC_S_NOT_LISTENING); + + status = RpcMgmtWaitServerListen(); + ok(status == RPC_S_OK, "RpcMgmtWaitServerListening failed with status %d\n", status); + + status = RpcMgmtWaitServerListen(); + ok(status == RPC_S_NOT_LISTENING, "RpcMgmtWaitServerListening failed with status %d\n", status); } static BOOL is_process_elevated(void) @@ -1913,6 +1945,10 @@ } RpcEndExcept } + else if (argc == 4) + { + test_server_listening(); + } else { if (firewall_enabled) @@ -1926,6 +1962,7 @@ } } server(); + run_client("test listen"); if (firewall_enabled) set_firewall(APP_REMOVE); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/schedsvc/schedsvc.c wine-staging-2.4.0~ubuntu16.04.1/dlls/schedsvc/schedsvc.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/schedsvc/schedsvc.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/schedsvc/schedsvc.c 2017-03-21 14:02:57.000000000 +0000 @@ -259,9 +259,10 @@ static HRESULT read_xml(const WCHAR *name, WCHAR **xml) { + char *src, *buff; HANDLE hfile; DWORD size, attrs; - char *src; + HRESULT hr = S_OK; int cp; attrs = GetFileAttributesW(name); @@ -275,7 +276,7 @@ return HRESULT_FROM_WIN32(GetLastError()); size = GetFileSize(hfile, NULL); - src = heap_alloc(size + 2); + buff = src = heap_alloc(size + 2); if (!src) { CloseHandle(hfile); @@ -300,9 +301,13 @@ size = MultiByteToWideChar(cp, 0, src, -1, NULL, 0); *xml = heap_alloc(size * sizeof(WCHAR)); - if (!*xml) return E_OUTOFMEMORY; - MultiByteToWideChar(cp, 0, src, -1, *xml, size); - return S_OK; + if (*xml) + MultiByteToWideChar(cp, 0, src, -1, *xml, size); + else + hr = E_OUTOFMEMORY; + heap_free(buff); + + return hr; } HRESULT __cdecl SchRpcRetrieveTask(const WCHAR *path, const WCHAR *languages, ULONG *n_languages, WCHAR **xml) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/schedsvc/schedsvc_private.h wine-staging-2.4.0~ubuntu16.04.1/dlls/schedsvc/schedsvc_private.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/schedsvc/schedsvc_private.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/schedsvc/schedsvc_private.h 2017-03-21 14:02:57.000000000 +0000 @@ -23,26 +23,24 @@ void schedsvc_auto_start(void) DECLSPEC_HIDDEN; -static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(SIZE_T size) +static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) { - return MIDL_user_allocate(size); + return HeapAlloc(GetProcessHeap(), 0, size); } -static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(SIZE_T size) +static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t size) { - void *ptr = MIDL_user_allocate(size); - if (ptr) memset(ptr, 0, size); - return ptr; + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); } -static inline void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, SIZE_T size) +static inline void* __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t size) { - return HeapReAlloc(GetProcessHeap(), 0, ptr, size); + return HeapReAlloc(GetProcessHeap(), 0, mem, size); } -static inline void heap_free(void *ptr) +static inline BOOL heap_free(void *mem) { - MIDL_user_free(ptr); + return HeapFree(GetProcessHeap(), 0, mem); } static inline WCHAR *heap_strdupW(const WCHAR *src) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/schedsvc/svc_main.c wine-staging-2.4.0~ubuntu16.04.1/dlls/schedsvc/svc_main.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/schedsvc/svc_main.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/schedsvc/svc_main.c 2017-03-21 14:02:57.000000000 +0000 @@ -27,6 +27,8 @@ #include "schrpc.h" #include "wine/debug.h" +#include "schedsvc_private.h" + WINE_DEFAULT_DEBUG_CHANNEL(schedsvc); static const WCHAR scheduleW[] = {'S','c','h','e','d','u','l','e',0}; @@ -200,10 +202,10 @@ void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len) { - return HeapAlloc(GetProcessHeap(), 0, len); + return heap_alloc(len); } void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) { - HeapFree(GetProcessHeap(), 0, ptr); + heap_free(ptr); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/schedsvc/tests/rpcapi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/schedsvc/tests/rpcapi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/schedsvc/tests/rpcapi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/schedsvc/tests/rpcapi.c 2017-03-21 14:02:57.000000000 +0000 @@ -33,7 +33,7 @@ if (winetest_debug) { - fprintf(stdout, "rpcapi: 0 tests executed (0 marked as todo, 0 failures), 1 skipped.\n"); + fprintf(stdout, "%04x:rpcapi: 0 tests executed (0 marked as todo, 0 failures), 1 skipped.\n", GetCurrentProcessId()); fflush(stdout); } ExitProcess(0); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/scrobj/scrobj.c wine-staging-2.4.0~ubuntu16.04.1/dlls/scrobj/scrobj.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/scrobj/scrobj.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/scrobj/scrobj.c 2017-03-21 14:02:57.000000000 +0000 @@ -445,7 +445,7 @@ return __wine_unregister_resources(scrobj_instance); } -HRESULT WINAPI scriptlet_typelib_CreateInstance(IClassFactory *factory, IUnknown *outer, REFIID riid, void **obj) +static HRESULT WINAPI scriptlet_typelib_CreateInstance(IClassFactory *factory, IUnknown *outer, REFIID riid, void **obj) { struct scriptlet_typelib *This; HRESULT hr; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/setupapi/setupapi.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/setupapi/setupapi.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/setupapi/setupapi.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/setupapi/setupapi.spec 2017-03-21 14:02:57.000000000 +0000 @@ -311,8 +311,8 @@ @ stdcall SetupDiDrawMiniIcon(ptr int128 long long) @ stdcall SetupDiEnumDeviceInfo(long long ptr) @ stdcall SetupDiEnumDeviceInterfaces(long ptr ptr long ptr) -@ stub SetupDiEnumDriverInfoA -@ stub SetupDiEnumDriverInfoW +@ 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 SetupDiGetClassBitmapIndex(ptr ptr) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/setupapi/stubs.c wine-staging-2.4.0~ubuntu16.04.1/dlls/setupapi/stubs.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/setupapi/stubs.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/setupapi/stubs.c 2017-03-21 14:02:57.000000000 +0000 @@ -675,3 +675,25 @@ return TRUE; } + +/*********************************************************************** + * SetupDiEnumDriverInfoA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiEnumDriverInfoA(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD DriverType, DWORD MemberIndex, PSP_DRVINFO_DATA_A DriverInfoData) +{ + FIXME("(%p, %p, 0x%x, %u, %p stub\n", DeviceInfoSet, DeviceInfoData, DriverType, MemberIndex, DriverInfoData); + + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/*********************************************************************** + * SetupDiEnumDriverInfoW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiEnumDriverInfoW(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD DriverType, DWORD MemberIndex, PSP_DRVINFO_DATA_W DriverInfoData) +{ + FIXME("(%p, %p, 0x%x, %u, %p stub\n", DeviceInfoSet, DeviceInfoData, DriverType, MemberIndex, DriverInfoData); + + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/shell32/tests/shlfolder.c wine-staging-2.4.0~ubuntu16.04.1/dlls/shell32/tests/shlfolder.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/shell32/tests/shlfolder.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/shell32/tests/shlfolder.c 2017-03-21 14:02:57.000000000 +0000 @@ -454,7 +454,7 @@ flags = ~0u; hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags); ok(hr == S_OK, "GetAttributesOf returns %08x\n", hr); - ok((flags & ~SFGAO_HASSUBFOLDER) == full_attrs[i], "%d: got %08x expected %08x\n", i, flags, full_attrs[i]); + ok((flags & ~(SFGAO_HASSUBFOLDER|SFGAO_COMPRESSED)) == full_attrs[i], "%d: got %08x expected %08x\n", i, flags, full_attrs[i]); } for (i=0;i<5;i++) @@ -3800,10 +3800,10 @@ hr = IShellFolder_BindToObject(pdesktopsf, pidl_testdir, NULL, (REFIID)&IID_IShellFolder, (void**)&psf); ok(hr == S_OK, "Got 0x%08x\n", hr); - if(SUCCEEDED(hr)) - pILFree(pidl_testdir); + pILFree(pidl_testdir); } IShellFolder_Release(pdesktopsf); + if (FAILED(hr)) return; hr = IShellFolder_EnumObjects(psf, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &peidl); ok(hr == S_OK, "Got %08x\n", hr); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/ucrtbase/ucrtbase.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/ucrtbase/ucrtbase.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/ucrtbase/ucrtbase.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/ucrtbase/ucrtbase.spec 2017-03-21 14:02:57.000000000 +0000 @@ -40,11 +40,11 @@ @ stub _NLG_Return @ stub _NLG_Return2 @ stub _SetWinRTOutOfMemoryExceptionCallback -@ cdecl _Strftime(str long str ptr ptr) +@ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _W_Getdays() @ cdecl _W_Getmonths() @ cdecl _W_Gettnames() -@ stub _Wcsftime +@ cdecl _Wcsftime(ptr long wstr ptr ptr) @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @ stub __BuildCatchObjectHelper @@ -1926,7 +1926,7 @@ @ cdecl _strdup(str) MSVCRT__strdup @ cdecl _strerror(long) MSVCRT__strerror @ stub _strerror_s -@ cdecl _strftime_l(str long str ptr ptr) MSVCRT__strftime_l +@ cdecl _strftime_l(ptr long str ptr ptr) MSVCRT__strftime_l @ cdecl _stricmp(str str) MSVCRT__stricmp @ cdecl _stricmp_l(str str ptr) MSVCRT__stricmp_l @ cdecl _stricoll(str str) MSVCRT__stricoll @@ -2504,7 +2504,7 @@ @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strerror_s(ptr long long) MSVCRT_strerror_s -@ cdecl strftime(str long str ptr) MSVCRT_strftime +@ cdecl strftime(ptr long str ptr) MSVCRT_strftime @ cdecl strlen(str) MSVCRT_strlen @ cdecl strncat(str str long) MSVCRT_strncat @ cdecl strncat_s(str long str long) MSVCRT_strncat_s diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/user32/tests/win.c wine-staging-2.4.0~ubuntu16.04.1/dlls/user32/tests/win.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/user32/tests/win.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/user32/tests/win.c 2017-03-21 14:02:57.000000000 +0000 @@ -805,10 +805,7 @@ GetWindowRect(hwnd, &rc1); SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy); /* note: winpos coordinates are relative to parent */ - MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2); - if (0) - { - /* Uncomment this once the test succeeds in all cases */ + MapWindowPoints(GetAncestor(hwnd,GA_PARENT), 0, (LPPOINT)&rc2, 2); ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2)); @@ -817,7 +814,6 @@ MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2); ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2)); - } break; } case WM_NCCREATE: diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/bidi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/bidi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/bidi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/bidi.c 2017-03-21 14:02:57.000000000 +0000 @@ -695,8 +695,8 @@ int pair_count = 0; int i; - open_stack = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * iso_run->length); - stack_index = HeapAlloc(GetProcessHeap(), 0, sizeof(int) * iso_run->length); + open_stack = heap_alloc(iso_run->length * sizeof(*open_stack)); + stack_index = heap_alloc(iso_run->length * sizeof(*stack_index)); for (i = 0; i < iso_run->length; i++) { @@ -705,7 +705,7 @@ { if (!out) { - out = HeapAlloc(GetProcessHeap(),0,sizeof(BracketPair)); + out = heap_alloc(sizeof(*out)); out[0].start = -1; } @@ -742,14 +742,14 @@ } if (pair_count == 0) { - HeapFree(GetProcessHeap(),0,out); + heap_free(out); out = NULL; } else if (pair_count > 1) qsort(out, pair_count, sizeof(BracketPair), compr); - HeapFree(GetProcessHeap(), 0, open_stack); - HeapFree(GetProcessHeap(), 0, stack_index); + heap_free(open_stack); + heap_free(stack_index); return out; } @@ -848,7 +848,7 @@ i++; p = &pairs[i]; } - HeapFree(GetProcessHeap(),0,pairs); + heap_free(pairs); } /* N1 */ @@ -995,8 +995,8 @@ Run *runs; IsolatedRun *current_isolated; - runs = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(Run)); - if (!runs) return; + if (!(runs = heap_alloc(uCount * sizeof(*runs)))) + return; list_init(set); @@ -1023,8 +1023,9 @@ { int type_fence, real_end; int j; - current_isolated = HeapAlloc(GetProcessHeap(), 0, sizeof(IsolatedRun) + sizeof(RunChar)*uCount); - if (!current_isolated) break; + + if (!(current_isolated = heap_alloc(FIELD_OFFSET(IsolatedRun, item[uCount])))) + break; run_start = runs[k].start; current_isolated->e = runs[k].e; @@ -1119,7 +1120,7 @@ i++; } - HeapFree(GetProcessHeap(), 0, runs); + heap_free(runs); } /************************************************************* @@ -1141,8 +1142,7 @@ TRACE("%s, %d\n", debugstr_wn(lpString, uCount), uCount); - chartype = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD)); - if (!chartype) + if (!(chartype = heap_alloc(uCount * sizeof(*chartype)))) { WARN("Out of memory\n"); return FALSE; @@ -1175,7 +1175,7 @@ if (TRACE_ON(bidi)) iso_dump_types("After Neutrals", iso_run); list_remove(&iso_run->entry); - HeapFree(GetProcessHeap(),0,iso_run); + heap_free(iso_run); } if (TRACE_ON(bidi)) dump_types("Before Implicit", chartype, 0, uCount); @@ -1186,7 +1186,7 @@ classify(lpString, chartype, uCount, c); resolveResolved(baselevel, chartype, lpOutLevels, 0, uCount-1); - HeapFree(GetProcessHeap(), 0, chartype); + heap_free(chartype); return TRUE; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/breaking.c wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/breaking.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/breaking.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/breaking.c 2017-03-21 14:02:57.000000000 +0000 @@ -81,8 +81,8 @@ TRACE("In %s\n",debugstr_wn(chars,count)); - break_class = HeapAlloc(GetProcessHeap(),0, count * sizeof(short)); - break_before = HeapAlloc(GetProcessHeap(),0, count * sizeof(short)); + break_class = heap_alloc(count * sizeof(*break_class)); + break_before = heap_alloc(count * sizeof(*break_before)); for (i = 0; i < count; i++) { @@ -438,6 +438,6 @@ } } - HeapFree(GetProcessHeap(), 0, break_before); - HeapFree(GetProcessHeap(), 0, break_class); + heap_free(break_before); + heap_free(break_class); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/indic.c wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/indic.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/indic.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/indic.c 2017-03-21 14:02:57.000000000 +0000 @@ -342,7 +342,7 @@ if (*syllable_count) *syllables = HeapReAlloc(GetProcessHeap(),0,*syllables, sizeof(IndicSyllable)*(*syllable_count+1)); else - *syllables = HeapAlloc(GetProcessHeap(),0,sizeof(IndicSyllable)); + *syllables = heap_alloc(sizeof(**syllables)); (*syllables)[*syllable_count].start = index; (*syllables)[*syllable_count].base = center; (*syllables)[*syllable_count].ralf = -1; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/opentype.c wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/opentype.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/opentype.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/opentype.c 2017-03-21 14:02:57.000000000 +0000 @@ -634,7 +634,7 @@ length = GetFontData(hdc, CMAP_TAG , 0, NULL, 0); if (length != GDI_ERROR) { - psc->CMAP_Table = HeapAlloc(GetProcessHeap(),0,length); + psc->CMAP_Table = heap_alloc(length); GetFontData(hdc, CMAP_TAG , 0, psc->CMAP_Table, length); TRACE("Loaded cmap table of %i bytes\n",length); } @@ -2472,7 +2472,7 @@ TRACE("initializing %i scripts in this font\n",psc->script_count); if (psc->script_count) { - psc->scripts = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LoadedScript) * psc->script_count); + psc->scripts = heap_alloc_zero(psc->script_count * sizeof(*psc->scripts)); for (i = 0; i < psc->script_count; i++) { int offset = GET_BE_WORD(script->ScriptRecord[i].Script); @@ -2504,7 +2504,7 @@ TRACE("initializing %i scripts in this font\n",psc->script_count); if (psc->script_count) { - psc->scripts = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LoadedScript) * psc->script_count); + psc->scripts = heap_alloc_zero(psc->script_count * sizeof(*psc->scripts)); for (i = 0; i < psc->script_count; i++) { int offset = GET_BE_WORD(script->ScriptRecord[i].Script); @@ -2602,7 +2602,7 @@ { TRACE("Deflang %p, LangCount %i\n",script->default_language.gsub_table, script->language_count); - script->languages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LoadedLanguage) * script->language_count); + script->languages = heap_alloc_zero(script->language_count * sizeof(*script->languages)); for (i = 0; i < script->language_count; i++) { @@ -2639,7 +2639,7 @@ int i; script->language_count = count; - script->languages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LoadedLanguage) * script->language_count); + script->languages = heap_alloc_zero(script->language_count * sizeof(*script->languages)); for (i = 0; i < script->language_count; i++) { @@ -2763,24 +2763,29 @@ if (language->feature_count) { - language->features = HeapAlloc(GetProcessHeap(),0,sizeof(LoadedFeature)*language->feature_count); + language->features = heap_alloc(language->feature_count * sizeof(*language->features)); feature_list = (const OT_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList)); for (i = 0; i < language->feature_count; i++) { + LoadedFeature *loaded_feature = &language->features[i]; const OT_Feature *feature; int j; int index = GET_BE_WORD(lang->FeatureIndex[i]); - language->features[i].tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], feature_list->FeatureRecord[index].FeatureTag[1], feature_list->FeatureRecord[index].FeatureTag[2], feature_list->FeatureRecord[index].FeatureTag[3]); - language->features[i].feature = ((const BYTE*)feature_list + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); - feature = (const OT_Feature*)language->features[i].feature; - language->features[i].lookup_count = GET_BE_WORD(feature->LookupCount); - language->features[i].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[i].lookup_count); - for (j = 0; j < language->features[i].lookup_count; j++) - language->features[i].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); - language->features[i].tableType = FEATURE_GSUB_TABLE; + loaded_feature->tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], + feature_list->FeatureRecord[index].FeatureTag[1], + feature_list->FeatureRecord[index].FeatureTag[2], + feature_list->FeatureRecord[index].FeatureTag[3]); + loaded_feature->feature = ((const BYTE *)feature_list + + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); + feature = loaded_feature->feature; + loaded_feature->lookup_count = GET_BE_WORD(feature->LookupCount); + loaded_feature->lookups = heap_alloc(loaded_feature->lookup_count * sizeof(*loaded_feature->lookups)); + for (j = 0; j < loaded_feature->lookup_count; ++j) + loaded_feature->lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); + loaded_feature->tableType = FEATURE_GSUB_TABLE; } } } @@ -2810,22 +2815,27 @@ if (language->feature_count) { - language->features = HeapAlloc(GetProcessHeap(),0,sizeof(LoadedFeature)*language->feature_count); + language->features = heap_alloc(language->feature_count * sizeof(*language->features)); for (i = 0; i < language->feature_count; i++) { + LoadedFeature *loaded_feature = &language->features[i]; const OT_Feature *feature; int j; int index = GET_BE_WORD(lang->FeatureIndex[i]); - language->features[i].tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], feature_list->FeatureRecord[index].FeatureTag[1], feature_list->FeatureRecord[index].FeatureTag[2], feature_list->FeatureRecord[index].FeatureTag[3]); - language->features[i].feature = ((const BYTE*)feature_list + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); - feature = (const OT_Feature*)language->features[i].feature; - language->features[i].lookup_count = GET_BE_WORD(feature->LookupCount); - language->features[i].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[i].lookup_count); - for (j = 0; j < language->features[i].lookup_count; j++) - language->features[i].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); - language->features[i].tableType = FEATURE_GPOS_TABLE; + loaded_feature->tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], + feature_list->FeatureRecord[index].FeatureTag[1], + feature_list->FeatureRecord[index].FeatureTag[2], + feature_list->FeatureRecord[index].FeatureTag[3]); + loaded_feature->feature = ((const BYTE *)feature_list + + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); + feature = loaded_feature->feature; + loaded_feature->lookup_count = GET_BE_WORD(feature->LookupCount); + loaded_feature->lookups = heap_alloc(loaded_feature->lookup_count * sizeof(*loaded_feature->lookups)); + for (j = 0; j < loaded_feature->lookup_count; ++j) + loaded_feature->lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); + loaded_feature->tableType = FEATURE_GPOS_TABLE; } } } @@ -2835,19 +2845,25 @@ for (i = 0; i < count; i++) { + LoadedFeature *loaded_feature; const OT_Feature *feature; int j; int index = GET_BE_WORD(lang->FeatureIndex[i]); int idx = language->feature_count + i; - language->features[idx].tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], feature_list->FeatureRecord[index].FeatureTag[1], feature_list->FeatureRecord[index].FeatureTag[2], feature_list->FeatureRecord[index].FeatureTag[3]); - language->features[idx].feature = ((const BYTE*)feature_list + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); - feature = (const OT_Feature*)language->features[idx].feature; - language->features[idx].lookup_count = GET_BE_WORD(feature->LookupCount); - language->features[idx].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[idx].lookup_count); - for (j = 0; j < language->features[idx].lookup_count; j++) - language->features[idx].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); - language->features[idx].tableType = FEATURE_GPOS_TABLE; + loaded_feature = &language->features[idx]; + loaded_feature->tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], + feature_list->FeatureRecord[index].FeatureTag[1], + feature_list->FeatureRecord[index].FeatureTag[2], + feature_list->FeatureRecord[index].FeatureTag[3]); + loaded_feature->feature = ((const BYTE *)feature_list + + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); + feature = loaded_feature->feature; + loaded_feature->lookup_count = GET_BE_WORD(feature->LookupCount); + loaded_feature->lookups = heap_alloc(loaded_feature->lookup_count * sizeof(*loaded_feature->lookups)); + for (j = 0; j < loaded_feature->lookup_count; ++j) + loaded_feature->lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); + loaded_feature->tableType = FEATURE_GPOS_TABLE; } language->feature_count += count; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/shape.c wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/shape.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/shape.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/shape.c 2017-03-21 14:02:57.000000000 +0000 @@ -660,7 +660,7 @@ int length = GetFontData(hdc, MS_MAKE_TAG('G', 'S', 'U', 'B'), 0, NULL, 0); if (length != GDI_ERROR) { - GSUB_Table = HeapAlloc(GetProcessHeap(),0,length); + GSUB_Table = heap_alloc(length); GetFontData(hdc, MS_MAKE_TAG('G', 'S', 'U', 'B'), 0, GSUB_Table, length); TRACE("Loaded GSUB table of %i bytes\n",length); } @@ -673,7 +673,7 @@ int length = GetFontData(hdc, MS_MAKE_TAG('G', 'P', 'O', 'S'), 0, NULL, 0); if (length != GDI_ERROR) { - GPOS_Table = HeapAlloc(GetProcessHeap(),0,length); + GPOS_Table = heap_alloc(length); GetFontData(hdc, MS_MAKE_TAG('G', 'P', 'O', 'S'), 0, GPOS_Table, length); TRACE("Loaded GPOS table of %i bytes\n",length); } @@ -686,7 +686,7 @@ int length = GetFontData(hdc, MS_MAKE_TAG('G', 'D', 'E', 'F'), 0, NULL, 0); if (length != GDI_ERROR) { - GDEF_Table = HeapAlloc(GetProcessHeap(),0,length); + GDEF_Table = heap_alloc(length); GetFontData(hdc, MS_MAKE_TAG('G', 'D', 'E', 'F'), 0, GDEF_Table, length); TRACE("Loaded GDEF table of %i bytes\n",length); } @@ -709,7 +709,7 @@ INT glyph_count = count; INT rc; - glyphs = HeapAlloc(GetProcessHeap(),0,sizeof(WORD)*(count*2)); + glyphs = heap_alloc(2 * count * sizeof(*glyphs)); GetGlyphIndicesW(hdc, chars, count, glyphs, 0); rc = apply_GSUB_feature_to_glyph(hdc, psa, psc, glyphs, 0, write_dir, &glyph_count, feature); if (rc > GSUB_E_NOGLYPH) @@ -717,7 +717,7 @@ else rc = 0; - HeapFree(GetProcessHeap(),0,glyphs); + heap_free(glyphs); return rc; } @@ -751,6 +751,7 @@ return; else { + int cluster_dir = pwLogClust[0] < pwLogClust[chars-1] ? 1 : -1; int i; int target_glyph = nextIndex - write_dir; int target_index = -1; @@ -775,7 +776,7 @@ if (changeCount < 0) { /* merge glyphs */ - for(i = target_index; i < chars && i >= 0; i+=write_dir) + for (i = target_index; i < chars && i >= 0; i += cluster_dir) { if (pwLogClust[i] == target_glyph) continue; @@ -794,8 +795,8 @@ } } - /* renumber trailing indexes*/ - for(i = target_index; i < chars && i >= 0; i+=write_dir) + /* renumber trailing indexes */ + for (i = target_index; i < chars && i >= 0; i += cluster_dir) { if (pwLogClust[i] != target_glyph) pwLogClust[i] += changeCount; @@ -803,8 +804,8 @@ } else { - for(i = target_index; i < chars && i >= 0; i+=write_dir) - pwLogClust[i] += changeCount; + for (i = target_index; i < chars && i >= 0; i += cluster_dir) + pwLogClust[i] += changeCount; } } } @@ -897,7 +898,7 @@ WCHAR invalid = 0x25cc; WORD invalid_glyph; - context_type = HeapAlloc(GetProcessHeap(),0,cChars); + context_type = heap_alloc(cChars); /* Mark invalid combinations */ for (i = 0; i < cChars; i++) @@ -913,7 +914,7 @@ } } - HeapFree(GetProcessHeap(),0,context_type); + heap_free(context_type); } static void ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) @@ -1054,21 +1055,21 @@ return; } - if (!psa->fLogicalOrder && psa->fRTL) + if (psa->fLogicalOrder && psa->fRTL) { - dirR = 1; - dirL = -1; + dirR = -1; + dirL = 1; } else { - dirR = -1; - dirL = 1; + dirR = 1; + dirL = -1; } load_ot_tables(hdc, psc); - context_type = HeapAlloc(GetProcessHeap(),0,cChars); - context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + context_type = heap_alloc(cChars); + context_shape = heap_alloc(cChars * sizeof(*context_shape)); for (i = 0; i < cChars; i++) context_type[i] = get_table_entry( wine_shaping_table, pwcChars[i] ); @@ -1128,8 +1129,14 @@ offset = *pcGlyphs - prevCount; glyph_index += dirL * (offset + 1); } + shaped = TRUE; + } + else if (nextIndex == GSUB_E_NOGLYPH) + { + char_index += dirL; + glyph_index += dirL; + shaped = TRUE; } - shaped = (nextIndex > GSUB_E_NOGLYPH); } if (!shaped) @@ -1150,8 +1157,8 @@ } } - HeapFree(GetProcessHeap(),0,context_shape); - HeapFree(GetProcessHeap(),0,context_type); + heap_free(context_shape); + heap_free(context_type); mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Arabic); } @@ -1318,8 +1325,8 @@ if (!psc->GSUB_Table) return; - context_type = HeapAlloc(GetProcessHeap(),0,cChars); - context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + context_type = heap_alloc(cChars); + context_shape = heap_alloc(cChars * sizeof(*context_shape)); for (i = 0; i < cChars; i++) context_type[i] = get_table_entry( wine_shaping_table, pwcChars[i] ); @@ -1398,8 +1405,8 @@ } } - HeapFree(GetProcessHeap(),0,context_shape); - HeapFree(GetProcessHeap(),0,context_type); + heap_free(context_shape); + heap_free(context_type); mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Syriac); } @@ -1480,7 +1487,7 @@ if (!psc->GSUB_Table) return; - context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + context_shape = heap_alloc(cChars * sizeof(*context_shape)); for (i = 0; i < cChars; i++) { @@ -1537,7 +1544,7 @@ } } - HeapFree(GetProcessHeap(),0,context_shape); + heap_free(context_shape); } static int combining_lexical_Thai(WCHAR c) @@ -2268,7 +2275,7 @@ return; } - input = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR) * (cChars * 3)); + input = heap_alloc(3 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); @@ -2294,8 +2301,8 @@ *pcGlyphs = cCount; ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, sinhala_lex, NULL, TRUE); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int devanagari_lex(WCHAR c) @@ -2335,7 +2342,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + input = heap_alloc(cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Compose Consonant and Nukta */ @@ -2351,8 +2358,8 @@ /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, devanagari_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int bengali_lex(WCHAR c) @@ -2391,7 +2398,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars * 2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels and Compose Consonants */ @@ -2421,8 +2428,8 @@ /* Step 4: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, bengali_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int gurmukhi_lex(WCHAR c) @@ -2455,7 +2462,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + input = heap_alloc(cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Compose Consonants */ @@ -2471,8 +2478,8 @@ /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, gurmukhi_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int gujarati_lex(WCHAR c) @@ -2499,7 +2506,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + input = heap_alloc(cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Reorder within Syllables */ @@ -2511,8 +2518,8 @@ /* Step 2: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, gujarati_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int oriya_lex(WCHAR c) @@ -2550,7 +2557,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels and Compose Consonants */ @@ -2567,8 +2574,8 @@ /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, oriya_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int tamil_lex(WCHAR c) @@ -2600,7 +2607,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels and Compose Consonants */ @@ -2617,8 +2624,8 @@ /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, tamil_lex, SecondReorder_Like_Tamil, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int telugu_lex(WCHAR c) @@ -2650,7 +2657,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels */ @@ -2666,8 +2673,8 @@ /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, telugu_lex, SecondReorder_Like_Telugu, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int kannada_lex(WCHAR c) @@ -2702,7 +2709,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*3) * sizeof(WCHAR)); + input = heap_alloc(3 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels */ @@ -2718,8 +2725,8 @@ /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, kannada_lex, SecondReorder_Like_Telugu, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int malayalam_lex(WCHAR c) @@ -2747,7 +2754,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels */ @@ -2763,8 +2770,8 @@ /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, malayalam_lex, SecondReorder_Like_Tamil, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int khmer_lex(WCHAR c) @@ -2785,7 +2792,7 @@ return; } - input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + input = heap_alloc(cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Reorder within Syllables */ @@ -2797,8 +2804,8 @@ /* Step 2: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, khmer_lex, NULL, FALSE); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static inline BOOL mongolian_wordbreak(WCHAR chr) @@ -2828,7 +2835,7 @@ if (!psc->GSUB_Table) return; - context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + context_shape = heap_alloc(cChars * sizeof(*context_shape)); for (i = 0; i < cChars; i++) { @@ -2873,7 +2880,7 @@ } } - HeapFree(GetProcessHeap(),0,context_shape); + heap_free(context_shape); } static void ShapeCharGlyphProp_Default( ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) @@ -2942,23 +2949,23 @@ INT dirR, dirL; BYTE *spaces; - spaces = HeapAlloc(GetProcessHeap(),0,cGlyphs); + spaces = heap_alloc(cGlyphs); memset(spaces,0,cGlyphs); - if (!psa->fLogicalOrder && psa->fRTL) - { - initGlyph = cGlyphs-1; - finaGlyph = 0; - dirR = 1; - dirL = -1; - } - else + if (psa->fLogicalOrder && psa->fRTL) { initGlyph = 0; finaGlyph = cGlyphs-1; dirR = -1; dirL = 1; } + else + { + initGlyph = cGlyphs-1; + finaGlyph = 0; + dirR = 1; + dirL = -1; + } for (i = 0; i < cGlyphs; i++) { @@ -3042,7 +3049,7 @@ OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); - HeapFree(GetProcessHeap(),0,spaces); + heap_free(spaces); } static void ShapeCharGlyphProp_Hebrew( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) @@ -3290,7 +3297,7 @@ } } - HeapFree(GetProcessHeap(), 0, syllables); + heap_free(syllables); } UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); @@ -3382,7 +3389,7 @@ if (!psc->GSUB_Table) return; - if (!psa->fLogicalOrder && psa->fRTL) + if (scriptInformation[psa->eScript].a.fRTL && (!psa->fLogicalOrder || !psa->fRTL)) dirL = -1; else dirL = 1; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/tests/usp10.c wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/tests/usp10.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/tests/usp10.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/tests/usp10.c 2017-03-21 14:02:57.000000000 +0000 @@ -141,6 +141,7 @@ #define thai_tag MS_MAKE_TAG('t','h','a','i') #define hebr_tag MS_MAKE_TAG('h','e','b','r') #define syrc_tag MS_MAKE_TAG('s','y','r','c') +#define thaa_tag MS_MAKE_TAG('t','h','a','a') #define deva_tag MS_MAKE_TAG('d','e','v','a') #define beng_tag MS_MAKE_TAG('b','e','n','g') #define guru_tag MS_MAKE_TAG('g','u','r','u') @@ -934,16 +935,22 @@ const SCRIPT_GLYPHPROP *props2) { HRESULT hr; - int x, outnItems=0, outnGlyphs=0; + int x, outnItems = 0, outnGlyphs = 0, outnGlyphs2 = 0; + const SCRIPT_PROPERTIES **script_properties; SCRIPT_ITEM outpItems[15]; SCRIPT_CACHE sc = NULL; - WORD *glyphs; - WORD *logclust; + WORD *glyphs, *glyphs2; + WORD *logclust, *logclust2; int maxGlyphs = cchString * 1.5; - SCRIPT_GLYPHPROP *glyphProp; - SCRIPT_CHARPROP *charProp; + SCRIPT_GLYPHPROP *glyphProp, *glyphProp2; + SCRIPT_CHARPROP *charProp, *charProp2; + int script_count; + WCHAR *string2; ULONG tags[15]; + hr = ScriptGetProperties(&script_properties, &script_count); + winetest_ok(SUCCEEDED(hr), "Failed to get script properties, hr %#x.\n", hr); + hr = pScriptItemizeOpenType(string, cchString, 15, Control, State, outpItems, tags, &outnItems); if (hr == USP_E_SCRIPT_NOT_IN_FONT) { @@ -976,6 +983,18 @@ glyphProp = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPT_GLYPHPROP) * maxGlyphs); memset(glyphProp,'a',sizeof(SCRIPT_GLYPHPROP) * cchString); + string2 = HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(*string2)); + logclust2 = HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(*logclust2)); + memset(logclust2, 'a', cchString * sizeof(*logclust2)); + charProp2 = HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(*charProp2)); + memset(charProp2, 'a', cchString * sizeof(*charProp2)); + glyphs2 = HeapAlloc(GetProcessHeap(), 0, maxGlyphs * sizeof(*glyphs2)); + memset(glyphs2, 'a', maxGlyphs * sizeof(*glyphs2)); + glyphProp2 = HeapAlloc(GetProcessHeap(), 0, maxGlyphs * sizeof(*glyphProp2)); + memset(glyphProp2, 'a', maxGlyphs * sizeof(*glyphProp2)); + + winetest_ok(!outpItems[item].a.fLogicalOrder, "Got unexpected fLogicalOrder %#x.\n", + outpItems[item].a.fLogicalOrder); hr = pScriptShapeOpenType(hdc, &sc, &outpItems[item].a, tags[item], 0x00000000, NULL, NULL, 0, string, cchString, maxGlyphs, logclust, charProp, glyphs, glyphProp, &outnGlyphs); if (valid > 0) winetest_ok(hr == S_OK, "ScriptShapeOpenType failed (%x)\n",hr); @@ -1017,11 +1036,16 @@ winetest_trace("%i: Glyph present when it should not be\n",x); } if (valid > 0) - winetest_ok(glyphProp[x].sva.uJustification == glyphItems[x].GlyphProp.sva.uJustification || - (props2 && glyphProp[x].sva.uJustification == props2[x].sva.uJustification), - "%i: uJustification incorrect (%i)\n",x,glyphProp[x].sva.uJustification); + { + todo_wine_if(tags[item] == syrc_tag && !x) + winetest_ok(glyphProp[x].sva.uJustification == glyphItems[x].GlyphProp.sva.uJustification || + (props2 && glyphProp[x].sva.uJustification == props2[x].sva.uJustification), + "%i: uJustification incorrect (%i)\n",x,glyphProp[x].sva.uJustification); + } else if (glyphProp[x].sva.uJustification != glyphItems[x].GlyphProp.sva.uJustification) + { winetest_trace("%i: uJustification incorrect (%i)\n",x,glyphProp[x].sva.uJustification); + } if (valid > 0) winetest_ok(glyphProp[x].sva.fClusterStart == glyphItems[x].GlyphProp.sva.fClusterStart || (props2 && glyphProp[x].sva.fClusterStart == props2[x].sva.fClusterStart), @@ -1042,7 +1066,132 @@ winetest_trace("%i: fZeroWidth incorrect (%i)\n",x,glyphProp[x].sva.fZeroWidth); } + outpItems[item].a.fLogicalOrder = 1; + hr = pScriptShapeOpenType(hdc, &sc, &outpItems[item].a, tags[item], 0x00000000, NULL, NULL, 0, + string, cchString, maxGlyphs, logclust2, charProp2, glyphs2, glyphProp2, &outnGlyphs2); + winetest_ok(hr == S_OK, "ScriptShapeOpenType failed (%x)\n",hr); + /* Cluster maps are hard. */ + if (tags[item] != thaa_tag && tags[item] != syrc_tag) + { + for (x = 0; x < cchString; ++x) + { + unsigned int compare_idx = outpItems[item].a.fRTL ? cchString - x - 1 : x; + winetest_ok(logclust2[x] == logclust[compare_idx], + "Got unexpected logclust2[%u] %#x, expected %#x.\n", + x, logclust2[x], logclust[compare_idx]); + winetest_ok(charProp2[x].fCanGlyphAlone == charProp[compare_idx].fCanGlyphAlone, + "Got unexpected charProp2[%u].fCanGlyphAlone %#x, expected %#x.\n", + x, charProp2[x].fCanGlyphAlone, charProp[compare_idx].fCanGlyphAlone); + } + } + winetest_ok(outnGlyphs2 == outnGlyphs, "Got unexpected glyph count %u.\n", outnGlyphs2); + for (x = 0; x < outnGlyphs2; ++x) + { + unsigned int compare_idx = outpItems[item].a.fRTL ? outnGlyphs2 - x - 1 : x; + winetest_ok(glyphs2[x] == glyphs[compare_idx], "Got unexpected glyphs2[%u] %#x, expected %#x.\n", + x, glyphs2[x], glyphs[compare_idx]); + winetest_ok(glyphProp2[x].sva.uJustification == glyphProp[compare_idx].sva.uJustification, + "Got unexpected glyphProp2[%u].sva.uJustification %#x, expected %#x.\n", + x, glyphProp2[x].sva.uJustification, glyphProp[compare_idx].sva.uJustification); + winetest_ok(glyphProp2[x].sva.fClusterStart == glyphProp[compare_idx].sva.fClusterStart, + "Got unexpected glyphProp2[%u].sva.fClusterStart %#x, expected %#x.\n", + x, glyphProp2[x].sva.fClusterStart, glyphProp[compare_idx].sva.fClusterStart); + winetest_ok(glyphProp2[x].sva.fDiacritic == glyphProp[compare_idx].sva.fDiacritic, + "Got unexpected glyphProp2[%u].sva.fDiacritic %#x, expected %#x.\n", + x, glyphProp2[x].sva.fDiacritic, glyphProp[compare_idx].sva.fDiacritic); + winetest_ok(glyphProp2[x].sva.fZeroWidth == glyphProp[compare_idx].sva.fZeroWidth, + "Got unexpected glyphProp2[%u].sva.fZeroWidth %#x, expected %#x.\n", + x, glyphProp2[x].sva.fZeroWidth, glyphProp[compare_idx].sva.fZeroWidth); + } + + /* Most scripts get this wrong. For example, when the font has the + * appropriate ligatures, "ttfffi" get rendered as "", but + * "iffftt" gets rendered as "ti". Arabic gets it right, + * and there exist applications that depend on that. */ + if (tags[item] == arab_tag && broken(script_count <= 75)) + { + winetest_win_skip("Test broken on this platform, skipping.\n"); + } + else if (tags[item] == arab_tag) + { + for (x = 0; x < cchString; ++x) + { + string2[x] = string[cchString - x - 1]; + } + outpItems[item].a.fLogicalOrder = 0; + outpItems[item].a.fRTL = !outpItems[item].a.fRTL; + hr = pScriptShapeOpenType(hdc, &sc, &outpItems[item].a, tags[item], 0x00000000, NULL, NULL, 0, + string2, cchString, maxGlyphs, logclust2, charProp2, glyphs2, glyphProp2, &outnGlyphs2); + winetest_ok(hr == S_OK, "ScriptShapeOpenType failed (%x)\n",hr); + for (x = 0; x < cchString; ++x) + { + unsigned int compare_idx = cchString - x - 1; + winetest_ok(logclust2[x] == logclust[compare_idx], + "Got unexpected logclust2[%u] %#x, expected %#x.\n", + x, logclust2[x], logclust[compare_idx]); + winetest_ok(charProp2[x].fCanGlyphAlone == charProp[compare_idx].fCanGlyphAlone, + "Got unexpected charProp2[%u].fCanGlyphAlone %#x, expected %#x.\n", + x, charProp2[x].fCanGlyphAlone, charProp[compare_idx].fCanGlyphAlone); + } + winetest_ok(outnGlyphs2 == outnGlyphs, "Got unexpected glyph count %u.\n", outnGlyphs2); + for (x = 0; x < outnGlyphs2; ++x) + { + winetest_ok(glyphs2[x] == glyphs[x], "Got unexpected glyphs2[%u] %#x, expected %#x.\n", + x, glyphs2[x], glyphs[x]); + winetest_ok(glyphProp2[x].sva.uJustification == glyphProp[x].sva.uJustification, + "Got unexpected glyphProp2[%u].sva.uJustification %#x, expected %#x.\n", + x, glyphProp2[x].sva.uJustification, glyphProp[x].sva.uJustification); + winetest_ok(glyphProp2[x].sva.fClusterStart == glyphProp[x].sva.fClusterStart, + "Got unexpected glyphProp2[%u].sva.fClusterStart %#x, expected %#x.\n", + x, glyphProp2[x].sva.fClusterStart, glyphProp[x].sva.fClusterStart); + winetest_ok(glyphProp2[x].sva.fDiacritic == glyphProp[x].sva.fDiacritic, + "Got unexpected glyphProp2[%u].sva.fDiacritic %#x, expected %#x.\n", + x, glyphProp2[x].sva.fDiacritic, glyphProp[x].sva.fDiacritic); + winetest_ok(glyphProp2[x].sva.fZeroWidth == glyphProp[x].sva.fZeroWidth, + "Got unexpected glyphProp2[%u].sva.fZeroWidth %#x, expected %#x.\n", + x, glyphProp2[x].sva.fZeroWidth, glyphProp[x].sva.fZeroWidth); + } + outpItems[item].a.fLogicalOrder = 1; + hr = pScriptShapeOpenType(hdc, &sc, &outpItems[item].a, tags[item], 0x00000000, NULL, NULL, 0, + string2, cchString, maxGlyphs, logclust2, charProp2, glyphs2, glyphProp2, &outnGlyphs2); + winetest_ok(hr == S_OK, "ScriptShapeOpenType failed (%x)\n",hr); + for (x = 0; x < cchString; ++x) + { + unsigned int compare_idx = outpItems[item].a.fRTL ? x : cchString - x - 1; + winetest_ok(logclust2[x] == logclust[compare_idx], "Got unexpected logclust2[%u] %#x, expected %#x.\n", + x, logclust2[x], logclust[compare_idx]); + winetest_ok(charProp2[x].fCanGlyphAlone == charProp[compare_idx].fCanGlyphAlone, + "Got unexpected charProp2[%u].fCanGlyphAlone %#x, expected %#x.\n", + x, charProp2[x].fCanGlyphAlone, charProp[compare_idx].fCanGlyphAlone); + } + winetest_ok(outnGlyphs2 == outnGlyphs, "Got unexpected glyph count %u.\n", outnGlyphs2); + for (x = 0; x < outnGlyphs2; ++x) + { + unsigned int compare_idx = outpItems[item].a.fRTL ? outnGlyphs2 - x - 1 : x; + winetest_ok(glyphs2[x] == glyphs[compare_idx], "Got unexpected glyphs2[%u] %#x, expected %#x.\n", + x, glyphs2[x], glyphs[compare_idx]); + winetest_ok(glyphProp2[x].sva.uJustification == glyphProp[compare_idx].sva.uJustification, + "Got unexpected glyphProp2[%u].sva.uJustification %#x, expected %#x.\n", + x, glyphProp2[x].sva.uJustification, glyphProp[compare_idx].sva.uJustification); + winetest_ok(glyphProp2[x].sva.fClusterStart == glyphProp[compare_idx].sva.fClusterStart, + "Got unexpected glyphProp2[%u].sva.fClusterStart %#x, expected %#x.\n", + x, glyphProp2[x].sva.fClusterStart, glyphProp[compare_idx].sva.fClusterStart); + winetest_ok(glyphProp2[x].sva.fDiacritic == glyphProp[compare_idx].sva.fDiacritic, + "Got unexpected glyphProp2[%u].sva.fDiacritic %#x, expected %#x.\n", + x, glyphProp2[x].sva.fDiacritic, glyphProp[compare_idx].sva.fDiacritic); + winetest_ok(glyphProp2[x].sva.fZeroWidth == glyphProp[compare_idx].sva.fZeroWidth, + "Got unexpected glyphProp2[%u].sva.fZeroWidth %#x, expected %#x.\n", + x, glyphProp2[x].sva.fZeroWidth, glyphProp[compare_idx].sva.fZeroWidth); + } + } + cleanup: + HeapFree(GetProcessHeap(),0,string2); + HeapFree(GetProcessHeap(),0,logclust2); + HeapFree(GetProcessHeap(),0,charProp2); + HeapFree(GetProcessHeap(),0,glyphs2); + HeapFree(GetProcessHeap(),0,glyphProp2); + HeapFree(GetProcessHeap(),0,logclust); HeapFree(GetProcessHeap(),0,charProp); HeapFree(GetProcessHeap(),0,glyphs); @@ -1185,6 +1334,13 @@ {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, {0,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}} }; + static const WCHAR test3[] = {'t', 't', 'f', 'f', 'f', 'i', 0}; + static const shapeTest_char t3_c[] = {{0, {0, 0}}, {0, {0, 0}}, {0, {0, 0}}, + {1, {0, 0}}, {1, {0, 0}}, {1, {0, 0}}}; + static const shapeTest_glyph t3_g[] = { + {1, {{SCRIPT_JUSTIFY_CHARACTER, 1, 0, 0, 0, 0}, 0}}, + {1, {{SCRIPT_JUSTIFY_CHARACTER, 1, 0, 0, 0, 0}, 0}}}; + /* Hebrew */ static const WCHAR test_hebrew[] = {0x05e9, 0x05dc, 0x05d5, 0x05dd,0}; static const shapeTest_char hebrew_c[] = {{3,{0,0}},{2,{0,0}},{1,{0,0}},{0,{0,0}}}; @@ -1218,12 +1374,14 @@ {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}}; /* Syriac */ - static const WCHAR test_syriac[] = {0x0710, 0x0710, 0x0710, 0x0728, 0x0718, 0x0723,0}; - static const shapeTest_char syriac_c[] = {{5,{0,0}},{4,{0,0}},{3,{0,0}},{2,{0,0}},{1,{0,0}},{0,{0,0}}}; + static const WCHAR test_syriac[] = {0x0710, 0x072c, 0x0728, 0x0742, 0x0718, 0x0723, 0x0720, 0x0710, 0}; + static const shapeTest_char syriac_c[] = {{6, {0, 0}}, {5, {0, 0}}, {4, {0, 0}}, + {4, {0, 0}}, {2, {0, 0}}, {1, {0, 0}}, {0, {0, 0}}, {0, {0, 0}}}; static const shapeTest_glyph syriac_g[] = { + {1,{{SCRIPT_JUSTIFY_ARABIC_NORMAL,1,0,0,0,0},0}}, {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, - {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, + {1,{{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}}, {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}} }; @@ -1467,6 +1625,14 @@ test_shape_ok(hdc, test2, 4, &Control, &State, 1, 4, t2_c, glyph_test); + test_valid = find_font_for_range(hdc, "Calibri", 0, test3[0], &hfont, &hfont_orig); + if (hfont != NULL) + { + test_shape_ok_valid(test_valid, hdc, test3, 6, &Control, &State, 0, 2, t3_c, t3_g); + SelectObject(hdc, hfont_orig); + DeleteObject(hfont); + } + test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 11, test_hebrew[0], &hfont, &hfont_orig); if (hfont != NULL) { @@ -1494,7 +1660,7 @@ test_valid = find_font_for_range(hdc, "Estrangelo Edessa", 71, test_syriac[0], &hfont, &hfont_orig); if (hfont != NULL) { - test_shape_ok_valid(test_valid, hdc, test_syriac, 6, &Control, &State, 0, 6, syriac_c, syriac_g); + test_shape_ok_valid(test_valid, hdc, test_syriac, 8, &Control, &State, 0, 7, syriac_c, syriac_g); SelectObject(hdc, hfont_orig); DeleteObject(hfont); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/usp10.c wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/usp10.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/usp10.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/usp10.c 2017-03-21 14:02:57.000000000 +0000 @@ -43,16 +43,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); -typedef struct _scriptRange +static const struct usp10_script_range { - WORD script; + enum usp10_script script; DWORD rangeFirst; DWORD rangeLast; - WORD numericScript; - WORD punctScript; -} scriptRange; - -static const scriptRange scriptRanges[] = { + enum usp10_script numericScript; + enum usp10_script punctScript; +} +script_ranges[] = +{ /* Basic Latin: U+0000–U+007A */ { Script_Latin, 0x00, 0x07a , Script_Numeric, Script_Punctuation}, /* Latin-1 Supplement: U+0080–U+00FF */ @@ -296,8 +296,6 @@ { Script_Osmanya, 0x10480, 0x104AF, Script_Osmanya_Numeric, 0}, /* Mathematical Alphanumeric Symbols: U+1D400–U+1D7FF */ { Script_MathAlpha, 0x1D400, 0x1D7FF, 0, 0}, - /* END */ - { SCRIPT_UNDEFINED, 0, 0, 0} }; /* this must be in order so that the index matches the Script value */ @@ -710,21 +708,6 @@ WORD target; } FindGlyph_struct; -static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) -{ - return HeapAlloc(GetProcessHeap(), 0, size); -} - -static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t size) -{ - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); -} - -static inline BOOL heap_free(void *mem) -{ - return HeapFree(GetProcessHeap(), 0, mem); -} - /* TODO Fix font properties on Arabic locale */ static inline BOOL set_cache_font_properties(const HDC hdc, ScriptCache *sc) { @@ -888,12 +871,25 @@ return 0; } -static WORD get_char_script( LPCWSTR str, INT index, INT end, INT *consumed) +static int usp10_compare_script_range(const void *key, const void *value) +{ + const struct usp10_script_range *range = value; + const DWORD *ch = key; + + if (*ch < range->rangeFirst) + return -1; + if (*ch > range->rangeLast) + return 1; + return 0; +} + +static enum usp10_script get_char_script(const WCHAR *str, unsigned int index, + unsigned int end, unsigned int *consumed) { static const WCHAR latin_punc[] = {'#','$','&','\'',',',';','<','>','?','@','\\','^','_','`','{','|','}','~', 0x00a0, 0}; + struct usp10_script_range *range; WORD type = 0, type2 = 0; DWORD ch; - int i; *consumed = 1; @@ -935,24 +931,15 @@ else ch = str[index]; - i = 0; - do - { - if (ch < scriptRanges[i].rangeFirst || scriptRanges[i].script == SCRIPT_UNDEFINED) - break; - - if (ch >= scriptRanges[i].rangeFirst && ch <= scriptRanges[i].rangeLast) - { - if (scriptRanges[i].numericScript && (type & C1_DIGIT || type2 == C2_ARABICNUMBER)) - return scriptRanges[i].numericScript; - if (scriptRanges[i].punctScript && type & C1_PUNCT) - return scriptRanges[i].punctScript; - return scriptRanges[i].script; - } - i++; - } while (1); - - return SCRIPT_UNDEFINED; + if (!(range = bsearch(&ch, script_ranges, ARRAY_SIZE(script_ranges), + sizeof(*script_ranges), usp10_compare_script_range))) + return Script_Undefined; + + if (range->numericScript && (type & C1_DIGIT || type2 == C2_ARABICNUMBER)) + return range->numericScript; + if (range->punctScript && type & C1_PUNCT) + return range->punctScript; + return range->script; } static int compare_FindGlyph(const void *a, const void* b) @@ -1220,12 +1207,12 @@ } } -static inline BOOL is_indic(WORD script) +static inline BOOL is_indic(enum usp10_script script) { return (script >= Script_Devanagari && script <= Script_Malayalam_Numeric); } -static inline WORD base_indic(WORD script) +static inline enum usp10_script base_indic(enum usp10_script script) { switch (script) { @@ -1250,11 +1237,11 @@ case Script_Malayalam: case Script_Malayalam_Numeric: return Script_Malayalam; default: - return -1; + return Script_Undefined; }; } -static BOOL script_is_numeric(WORD script) +static BOOL script_is_numeric(enum usp10_script script) { return scriptInformation[script].props.fNumeric; } @@ -1270,21 +1257,21 @@ #define ZWNJ 0x200C #define ZWJ 0x200D + enum usp10_script last_indic = Script_Undefined; int cnt = 0, index = 0, str = 0; - int New_Script = -1; + enum usp10_script New_Script = -1; int i; WORD *levels = NULL; WORD *layout_levels = NULL; WORD *overrides = NULL; WORD *strength = NULL; - WORD *scripts = NULL; + enum usp10_script *scripts; WORD baselevel = 0; WORD baselayout = 0; BOOL new_run; - WORD last_indic = -1; WORD layoutRTL = 0; BOOL forceLevels = FALSE; - INT consumed = 0; + unsigned int consumed = 0; HRESULT res = E_OUTOFMEMORY; TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, @@ -1293,13 +1280,12 @@ if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2) return E_INVALIDARG; - scripts = heap_alloc(cInChars * sizeof(WORD)); - if (!scripts) + if (!(scripts = heap_alloc(cInChars * sizeof(*scripts)))) return E_OUTOFMEMORY; for (i = 0; i < cInChars; i++) { - if (consumed <= 0) + if (!consumed) { scripts[i] = get_char_script(pwcInChars,i,cInChars,&consumed); consumed --; @@ -1311,7 +1297,7 @@ } /* Devanagari danda (U+0964) and double danda (U+0965) are used for all Indic scripts */ - if ((pwcInChars[i] == 0x964 || pwcInChars[i] ==0x965) && last_indic > 0) + if ((pwcInChars[i] == 0x964 || pwcInChars[i] ==0x965) && last_indic != Script_Undefined) scripts[i] = last_indic; else if (is_indic(scripts[i])) last_indic = base_indic(scripts[i]); @@ -1338,10 +1324,10 @@ { int j; BOOL asian = FALSE; - WORD first_script = scripts[i-1]; + enum usp10_script first_script = scripts[i-1]; for (j = i-1; j >= 0 && scripts[j] == first_script && pwcInChars[j] != Numeric_space; j--) { - WORD original = scripts[j]; + enum usp10_script original = scripts[j]; if (original == Script_Ideograph || original == Script_Kana || original == Script_Yi || original == Script_CJK_Han || original == Script_Bopomofo) { asian = TRUE; @@ -1877,7 +1863,7 @@ return FALSE; } -static void find_fallback_font(DWORD scriptid, LPWSTR FaceName) +static void find_fallback_font(enum usp10_script scriptid, WCHAR *FaceName) { HKEY hkey; @@ -2995,14 +2981,13 @@ */ HRESULT WINAPI ScriptIsComplex(const WCHAR *chars, int len, DWORD flag) { - int i; - INT consumed = 0; + enum usp10_script script; + unsigned int i, consumed; TRACE("(%s,%d,0x%x)\n", debugstr_wn(chars, len), len, flag); for (i = 0; i < len; i+=consumed) { - int script; if (i >= len) break; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/usp10_internal.h wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/usp10_internal.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/usp10/usp10_internal.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/usp10/usp10_internal.h 2017-03-21 14:02:57.000000000 +0000 @@ -24,101 +24,108 @@ ( (ULONG)_x2 << 8 ) | \ (ULONG)_x1 ) +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#endif -#define Script_Latin 1 -#define Script_CR 2 -#define Script_Numeric 3 -#define Script_Control 4 -#define Script_Punctuation 5 -#define Script_Arabic 6 -#define Script_Arabic_Numeric 7 -#define Script_Hebrew 8 -#define Script_Syriac 9 -#define Script_Persian 10 -#define Script_Thaana 11 -#define Script_Greek 12 -#define Script_Cyrillic 13 -#define Script_Armenian 14 -#define Script_Georgian 15 -/* Unicode Chapter 10 */ -#define Script_Sinhala 16 -#define Script_Tibetan 17 -#define Script_Tibetan_Numeric 18 -#define Script_Phags_pa 19 -/* Unicode Chapter 11 */ -#define Script_Thai 20 -#define Script_Thai_Numeric 21 -#define Script_Lao 22 -#define Script_Lao_Numeric 23 -/* Unicode Chapter 9 */ -#define Script_Devanagari 24 -#define Script_Devanagari_Numeric 25 -#define Script_Bengali 26 -#define Script_Bengali_Numeric 27 -#define Script_Bengali_Currency 28 -#define Script_Gurmukhi 29 -#define Script_Gurmukhi_Numeric 30 -#define Script_Gujarati 31 -#define Script_Gujarati_Numeric 32 -#define Script_Gujarati_Currency 33 -#define Script_Oriya 34 -#define Script_Oriya_Numeric 35 -#define Script_Tamil 36 -#define Script_Tamil_Numeric 37 -#define Script_Telugu 38 -#define Script_Telugu_Numeric 39 -#define Script_Kannada 40 -#define Script_Kannada_Numeric 41 -#define Script_Malayalam 42 -#define Script_Malayalam_Numeric 43 -/* More supplemental */ -#define Script_Diacritical 44 -#define Script_Punctuation2 45 -#define Script_Numeric2 46 -/* Unicode Chapter 11 continued */ -#define Script_Myanmar 47 -#define Script_Myanmar_Numeric 48 -#define Script_Tai_Le 49 -#define Script_New_Tai_Lue 50 -#define Script_New_Tai_Lue_Numeric 51 -#define Script_Khmer 52 -#define Script_Khmer_Numeric 53 -/* Unicode Chapter 12 */ -#define Script_CJK_Han 54 -#define Script_Ideograph 55 -#define Script_Bopomofo 56 -#define Script_Kana 57 -#define Script_Hangul 58 -#define Script_Yi 59 -/* Unicode Chapter 13 */ -#define Script_Ethiopic 60 -#define Script_Ethiopic_Numeric 61 -#define Script_Mongolian 62 -#define Script_Mongolian_Numeric 63 -#define Script_Tifinagh 64 -#define Script_NKo 65 -#define Script_Vai 66 -#define Script_Vai_Numeric 67 -#define Script_Cherokee 68 -#define Script_Canadian 69 -/* Unicode Chapter 14 */ -#define Script_Ogham 70 -#define Script_Runic 71 -/* Unicode Chapter 15 */ -#define Script_Braille 72 -/* Unicode Chapter 16 */ -#define Script_Surrogates 73 -#define Script_Private 74 -/* Unicode Chapter 13 : Plane 1 */ -#define Script_Deseret 75 -#define Script_Osmanya 76 -#define Script_Osmanya_Numeric 77 -/* Unicode Chapter 15 : Plane 1 */ -#define Script_MathAlpha 78 -/* Additional Currency Scripts */ -#define Script_Hebrew_Currency 79 -#define Script_Vietnamese_Currency 80 -#define Script_Thai_Currency 81 +enum usp10_script +{ + Script_Undefined = 0x00, + Script_Latin = 0x01, + Script_CR = 0x02, + Script_Numeric = 0x03, + Script_Control = 0x04, + Script_Punctuation = 0x05, + Script_Arabic = 0x06, + Script_Arabic_Numeric = 0x07, + Script_Hebrew = 0x08, + Script_Syriac = 0x09, + Script_Persian = 0x0a, + Script_Thaana = 0x0b, + Script_Greek = 0x0c, + Script_Cyrillic = 0x0d, + Script_Armenian = 0x0e, + Script_Georgian = 0x0f, + /* Unicode Chapter 10 */ + Script_Sinhala = 0x10, + Script_Tibetan = 0x11, + Script_Tibetan_Numeric = 0x12, + Script_Phags_pa = 0x13, + /* Unicode Chapter 11 */ + Script_Thai = 0x14, + Script_Thai_Numeric = 0x15, + Script_Lao = 0x16, + Script_Lao_Numeric = 0x17, + /* Unicode Chapter 9 */ + Script_Devanagari = 0x18, + Script_Devanagari_Numeric = 0x19, + Script_Bengali = 0x1a, + Script_Bengali_Numeric = 0x1b, + Script_Bengali_Currency = 0x1c, + Script_Gurmukhi = 0x1d, + Script_Gurmukhi_Numeric = 0x1e, + Script_Gujarati = 0x1f, + Script_Gujarati_Numeric = 0x20, + Script_Gujarati_Currency = 0x21, + Script_Oriya = 0x22, + Script_Oriya_Numeric = 0x23, + Script_Tamil = 0x24, + Script_Tamil_Numeric = 0x25, + Script_Telugu = 0x26, + Script_Telugu_Numeric = 0x27, + Script_Kannada = 0x28, + Script_Kannada_Numeric = 0x29, + Script_Malayalam = 0x2a, + Script_Malayalam_Numeric = 0x2b, + /* More supplemental */ + Script_Diacritical = 0x2c, + Script_Punctuation2 = 0x2d, + Script_Numeric2 = 0x2e, + /* Unicode Chapter 11 continued */ + Script_Myanmar = 0x2f, + Script_Myanmar_Numeric = 0x30, + Script_Tai_Le = 0x31, + Script_New_Tai_Lue = 0x32, + Script_New_Tai_Lue_Numeric = 0x33, + Script_Khmer = 0x34, + Script_Khmer_Numeric = 0x35, + /* Unicode Chapter 12 */ + Script_CJK_Han = 0x36, + Script_Ideograph = 0x37, + Script_Bopomofo = 0x38, + Script_Kana = 0x39, + Script_Hangul = 0x3a, + Script_Yi = 0x3b, + /* Unicode Chapter 13 */ + Script_Ethiopic = 0x3c, + Script_Ethiopic_Numeric = 0x3d, + Script_Mongolian = 0x3e, + Script_Mongolian_Numeric = 0x3f, + Script_Tifinagh = 0x40, + Script_NKo = 0x41, + Script_Vai = 0x42, + Script_Vai_Numeric = 0x43, + Script_Cherokee = 0x44, + Script_Canadian = 0x45, + /* Unicode Chapter 14 */ + Script_Ogham = 0x46, + Script_Runic = 0x47, + /* Unicode Chapter 15 */ + Script_Braille = 0x48, + /* Unicode Chapter 16 */ + Script_Surrogates = 0x49, + Script_Private = 0x4a, + /* Unicode Chapter 13 : Plane 1 */ + Script_Deseret = 0x4b, + Script_Osmanya = 0x4c, + Script_Osmanya_Numeric = 0x4d, + /* Unicode Chapter 15 : Plane 1 */ + Script_MathAlpha = 0x4e, + /* Additional Currency Scripts */ + Script_Hebrew_Currency = 0x4f, + Script_Vietnamese_Currency = 0x50, + Script_Thai_Currency = 0x51, +}; #define GLYPH_BLOCK_SHIFT 8 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT) @@ -205,6 +212,21 @@ enum {lex_Halant, lex_Composed_Vowel, lex_Matra_post, lex_Matra_pre, lex_Matra_above, lex_Matra_below, lex_ZWJ, lex_ZWNJ, lex_NBSP, lex_Modifier, lex_Vowel, lex_Consonant, lex_Generic, lex_Ra, lex_Vedic, lex_Anudatta, lex_Nukta}; +static inline void * __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) +{ + return HeapAlloc(GetProcessHeap(), 0, size); +} + +static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t size) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); +} + +static inline BOOL heap_free(void *mem) +{ + return HeapFree(GetProcessHeap(), 0, mem); +} + static inline BOOL is_consonant( int type ) { return (type == lex_Ra || type == lex_Consonant); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/vcomp/tests/vcomp.c wine-staging-2.4.0~ubuntu16.04.1/dlls/vcomp/tests/vcomp.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/vcomp/tests/vcomp.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/vcomp/tests/vcomp.c 2017-03-21 14:02:57.000000000 +0000 @@ -149,6 +149,8 @@ #define VCOMP_REDUCTION_FLAGS_BOOL_AND 0x600 #define VCOMP_REDUCTION_FLAGS_BOOL_OR 0x700 +#define ULL(a,b) (((ULONG64)(a) << 32) | (b)) + #ifdef __i386__ #define ARCH "x86" #elif defined(__x86_64__) @@ -1750,15 +1752,15 @@ } tests1[] = { - { p_vcomp_atomic_add_i8, 0x1122334455667788, 0x7766554433221100, -0x7777777777777778 }, - { p_vcomp_atomic_and_i8, 0x1122334455667788, 0x7766554433221100, 0x1122114411221100 }, - { p_vcomp_atomic_div_i8, 0x7766554433221100, 0x1122334455667788, 6 }, - { p_vcomp_atomic_div_i8, 0x7766554433221100, -0x1122334455667788, -6 }, - { p_vcomp_atomic_mul_i8, 0x1122334455667788, 0x7766554433221100, 0x3e963337c6000800 }, - { p_vcomp_atomic_mul_i8, 0x1122334455667788, -0x7766554433221100, 0xc169ccc839fff800 }, - { p_vcomp_atomic_or_i8, 0x1122334455667788, 0x7766554433221100, 0x7766774477667788 }, - { p_vcomp_atomic_sub_i8, 0x1122334455667788, 0x7766554433221100, -0x664421ffddbb9978 }, - { p_vcomp_atomic_xor_i8, 0x1122334455667788, 0x7766554433221100, 0x6644660066446688 }, + { p_vcomp_atomic_add_i8, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), -ULL(0x77777777,0x77777778) }, + { p_vcomp_atomic_and_i8, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), ULL(0x11221144,0x11221100) }, + { p_vcomp_atomic_div_i8, ULL(0x77665544,0x33221100), ULL(0x11223344,0x55667788), 6 }, + { p_vcomp_atomic_div_i8, ULL(0x77665544,0x33221100), -ULL(0x11223344,0x55667788), -6 }, + { p_vcomp_atomic_mul_i8, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), ULL(0x3e963337,0xc6000800) }, + { p_vcomp_atomic_mul_i8, ULL(0x11223344,0x55667788), -ULL(0x77665544,0x33221100), ULL(0xc169ccc8,0x39fff800) }, + { p_vcomp_atomic_or_i8, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), ULL(0x77667744,0x77667788) }, + { p_vcomp_atomic_sub_i8, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), -ULL(0x664421ff,0xddbb9978) }, + { p_vcomp_atomic_xor_i8, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), ULL(0x66446600,0x66446688) }, }; struct { @@ -1770,22 +1772,22 @@ } tests2[] = { - { p_vcomp_atomic_shl_i8, 0x1122334455667788, 3, -0x76ee65dd54cc43c0 }, - { p_vcomp_atomic_shl_i8, 0x1122334455667788, 60, 0x8000000000000000 }, - { p_vcomp_atomic_shl_i8, -0x1122334455667788, 3, 0x76ee65dd54cc43c0 }, - { p_vcomp_atomic_shr_i8, 0x1122334455667788, 3, 0x22446688aaccef1 }, - { p_vcomp_atomic_shr_i8, 0x1122334455667788, 60, 1 }, - { p_vcomp_atomic_shr_i8, -0x1122334455667788, 3, -0x22446688aaccef1 }, + { p_vcomp_atomic_shl_i8, ULL(0x11223344,0x55667788), 3, -ULL(0x76ee65dd,0x54cc43c0) }, + { p_vcomp_atomic_shl_i8, ULL(0x11223344,0x55667788), 60, ULL(0x80000000,0x00000000) }, + { p_vcomp_atomic_shl_i8, -ULL(0x11223344,0x55667788), 3, ULL(0x76ee65dd,0x54cc43c0) }, + { p_vcomp_atomic_shr_i8, ULL(0x11223344,0x55667788), 3, ULL(0x02244668,0x8aaccef1) }, + { p_vcomp_atomic_shr_i8, ULL(0x11223344,0x55667788), 60, 1 }, + { p_vcomp_atomic_shr_i8, -ULL(0x11223344,0x55667788), 3, -ULL(0x02244668,0x8aaccef1) }, #if defined(__i386__) - { p_vcomp_atomic_shl_i8, 0x1122334455667788, 64, 0, TRUE }, - { p_vcomp_atomic_shl_i8, 0x1122334455667788, 67, 0, TRUE }, - { p_vcomp_atomic_shr_i8, 0x1122334455667788, 64, 0, TRUE }, - { p_vcomp_atomic_shr_i8, 0x1122334455667788, 67, 0, TRUE }, + { p_vcomp_atomic_shl_i8, ULL(0x11223344,0x55667788), 64, 0, TRUE }, + { p_vcomp_atomic_shl_i8, ULL(0x11223344,0x55667788), 67, 0, TRUE }, + { p_vcomp_atomic_shr_i8, ULL(0x11223344,0x55667788), 64, 0, TRUE }, + { p_vcomp_atomic_shr_i8, ULL(0x11223344,0x55667788), 67, 0, TRUE }, #elif defined(__x86_64__) - { p_vcomp_atomic_shl_i8, 0x1122334455667788, 64, 0x1122334455667788 }, - { p_vcomp_atomic_shl_i8, 0x1122334455667788, 67, -0x76ee65dd54cc43c0 }, - { p_vcomp_atomic_shr_i8, 0x1122334455667788, 64, 0x1122334455667788 }, - { p_vcomp_atomic_shr_i8, 0x1122334455667788, 67, 0x22446688aaccef1 }, + { p_vcomp_atomic_shl_i8, ULL(0x11223344,0x55667788), 64, ULL(0x11223344,0x55667788) }, + { p_vcomp_atomic_shl_i8, ULL(0x11223344,0x55667788), 67, -ULL(0x76ee65dd,0x54cc43c0) }, + { p_vcomp_atomic_shr_i8, ULL(0x11223344,0x55667788), 64, ULL(0x11223344,0x55667788) }, + { p_vcomp_atomic_shr_i8, ULL(0x11223344,0x55667788), 67, ULL(0x02244668,0x8aaccef1) }, #endif }; struct @@ -1795,8 +1797,8 @@ } tests3[] = { - { p_vcomp_atomic_div_ui8, 0x7766554455667788, 0x1122334433221100, 6 }, - { p_vcomp_atomic_div_ui8, 0x7766554455667788, 0xeeddccbbaa998878, 0 }, + { p_vcomp_atomic_div_ui8, ULL(0x77665544,0x55667788), ULL(0x11223344,0x33221100), 6 }, + { p_vcomp_atomic_div_ui8, ULL(0x77665544,0x55667788), ULL(0xeeddccbb,0xaa998878), 0 }, }; struct { @@ -1808,15 +1810,15 @@ } tests4[] = { - { p_vcomp_atomic_shr_ui8, 0x1122334455667788, 3, 0x22446688aaccef1 }, - { p_vcomp_atomic_shr_ui8, 0x1122334455667788, 60, 1 }, - { p_vcomp_atomic_shr_ui8, 0xeeddccbbaa998878, 3, 0x1ddbb9977553310f }, + { p_vcomp_atomic_shr_ui8, ULL(0x11223344,0x55667788), 3, ULL(0x02244668,0x8aaccef1) }, + { p_vcomp_atomic_shr_ui8, ULL(0x11223344,0x55667788), 60, 1 }, + { p_vcomp_atomic_shr_ui8, ULL(0xeeddccbb,0xaa998878), 3, ULL(0x1ddbb997,0x7553310f) }, #if defined(__i386__) - { p_vcomp_atomic_shr_ui8, 0x1122334455667788, 64, 0, TRUE }, - { p_vcomp_atomic_shr_ui8, 0x1122334455667788, 67, 0, TRUE }, + { p_vcomp_atomic_shr_ui8, ULL(0x11223344,0x55667788), 64, 0, TRUE }, + { p_vcomp_atomic_shr_ui8, ULL(0x11223344,0x55667788), 67, 0, TRUE }, #elif defined(__x86_64__) - { p_vcomp_atomic_shr_ui8, 0x1122334455667788, 64, 0x1122334455667788 }, - { p_vcomp_atomic_shr_ui8, 0x1122334455667788, 67, 0x22446688aaccef1 }, + { p_vcomp_atomic_shr_ui8, ULL(0x11223344,0x55667788), 64, ULL(0x11223344,0x55667788) }, + { p_vcomp_atomic_shr_ui8, ULL(0x11223344,0x55667788), 67, ULL(0x02244668,0x8aaccef1) }, #endif }; int i; @@ -2078,23 +2080,23 @@ } tests[] = { - { 0x000, 0x1122334455667788, 0x7766554433221100, -0x7777777777777778 }, - { VCOMP_REDUCTION_FLAGS_ADD, 0x1122334455667788, 0x7766554433221100, -0x7777777777777778 }, - { VCOMP_REDUCTION_FLAGS_MUL, 0x1122334455667788, 0x7766554433221100, 0x3e963337c6000800 }, - { VCOMP_REDUCTION_FLAGS_MUL, 0x1122334455667788, -0x7766554433221100, 0xc169ccc839fff800 }, - { VCOMP_REDUCTION_FLAGS_AND, 0x1122334455667788, 0x7766554433221100, 0x1122114411221100 }, - { VCOMP_REDUCTION_FLAGS_OR, 0x1122334455667788, 0x7766554433221100, 0x7766774477667788 }, - { VCOMP_REDUCTION_FLAGS_XOR, 0x1122334455667788, 0x7766554433221100, 0x6644660066446688 }, - { VCOMP_REDUCTION_FLAGS_BOOL_AND, 1, 2, 1 }, - { VCOMP_REDUCTION_FLAGS_BOOL_OR, 0, 2, 1 }, - { 0x800, 0, 2, 1 }, - { 0x900, 0, 2, 1 }, - { 0xa00, 0, 2, 1 }, - { 0xb00, 0, 2, 1 }, - { 0xc00, 0, 2, 1 }, - { 0xd00, 0, 2, 1 }, - { 0xe00, 0, 2, 1 }, - { 0xf00, 0, 2, 1 }, + { 0x000, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), -ULL(0x77777777,0x77777778) }, + { VCOMP_REDUCTION_FLAGS_ADD, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), -ULL(0x77777777,0x77777778) }, + { VCOMP_REDUCTION_FLAGS_MUL, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), ULL(0x3e963337,0xc6000800) }, + { VCOMP_REDUCTION_FLAGS_MUL, ULL(0x11223344,0x55667788), -ULL(0x77665544,0x33221100), ULL(0xc169ccc8,0x39fff800) }, + { VCOMP_REDUCTION_FLAGS_AND, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), ULL(0x11221144,0x11221100) }, + { VCOMP_REDUCTION_FLAGS_OR, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), ULL(0x77667744,0x77667788) }, + { VCOMP_REDUCTION_FLAGS_XOR, ULL(0x11223344,0x55667788), ULL(0x77665544,0x33221100), ULL(0x66446600,0x66446688) }, + { VCOMP_REDUCTION_FLAGS_BOOL_AND, 1, 2, 1 }, + { VCOMP_REDUCTION_FLAGS_BOOL_OR, 0, 2, 1 }, + { 0x800, 0, 2, 1 }, + { 0x900, 0, 2, 1 }, + { 0xa00, 0, 2, 1 }, + { 0xb00, 0, 2, 1 }, + { 0xc00, 0, 2, 1 }, + { 0xd00, 0, 2, 1 }, + { 0xe00, 0, 2, 1 }, + { 0xf00, 0, 2, 1 }, }; int i; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/version/tests/info.c wine-staging-2.4.0~ubuntu16.04.1/dlls/version/tests/info.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/version/tests/info.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/version/tests/info.c 2017-03-21 14:02:57.000000000 +0000 @@ -664,7 +664,6 @@ todo_wine_if(lang != english) ok(LOWORD(translation) == lang, "got %u, expected lang is %u\n", LOWORD(translation), lang); - todo_wine ok(HIWORD(translation) == unicode, "got %u, expected codepage is %u\n", HIWORD(translation), unicode); @@ -706,7 +705,6 @@ else ok(LOWORD(translation) == english, "[%u] got %u, expected lang is %u\n", i, LOWORD(translation), english); - todo_wine ok(HIWORD(translation) == unicode, "[%u] got %u, expected codepage is %u\n", i, HIWORD(translation), unicode); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/channel.c wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/channel.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/channel.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/channel.c 2017-03-21 14:02:57.000000000 +0000 @@ -87,6 +87,8 @@ struct channel { + ULONG magic; + CRITICAL_SECTION cs; WS_CHANNEL_TYPE type; WS_CHANNEL_BINDING binding; WS_CHANNEL_STATE state; @@ -100,6 +102,8 @@ struct prop prop[sizeof(channel_props)/sizeof(channel_props[0])]; }; +#define CHANNEL_MAGIC (('C' << 24) | ('H' << 16) | ('A' << 8) | 'N') + static struct channel *alloc_channel(void) { static const ULONG count = sizeof(channel_props)/sizeof(channel_props[0]); @@ -107,6 +111,11 @@ ULONG size = sizeof(*ret) + prop_size( channel_props, count ); if (!(ret = heap_alloc_zero( size ))) return NULL; + + ret->magic = CHANNEL_MAGIC; + InitializeCriticalSection( &ret->cs ); + ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": channel.cs"); + prop_init( channel_props, count, ret->prop, &ret[1] ); ret->prop_count = count; return ret; @@ -114,13 +123,15 @@ static void free_channel( struct channel *channel ) { - if (!channel) return; WsFreeWriter( channel->writer ); WsFreeReader( channel->reader ); WinHttpCloseHandle( channel->http_request ); WinHttpCloseHandle( channel->http_connect ); WinHttpCloseHandle( channel->http_session ); heap_free( channel->addr.url.chars ); + + channel->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &channel->cs ); heap_free( channel ); } @@ -197,6 +208,20 @@ struct channel *channel = (struct channel *)handle; TRACE( "%p\n", handle ); + + if (!channel) return; + + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + LeaveCriticalSection( &channel->cs ); + return; + } + + channel->magic = 0; + + LeaveCriticalSection( &channel->cs ); free_channel( channel ); } @@ -207,12 +232,25 @@ ULONG size, WS_ERROR *error ) { struct channel *channel = (struct channel *)handle; + HRESULT hr; TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle) return E_INVALIDARG; - return prop_get( channel->prop, channel->prop_count, id, buf, size ); + if (!channel) return E_INVALIDARG; + + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + LeaveCriticalSection( &channel->cs ); + return E_INVALIDARG; + } + + hr = prop_get( channel->prop, channel->prop_count, id, buf, size ); + + LeaveCriticalSection( &channel->cs ); + return hr; } /************************************************************************** @@ -222,12 +260,25 @@ ULONG size, WS_ERROR *error ) { struct channel *channel = (struct channel *)handle; + HRESULT hr; TRACE( "%p %u %p %u\n", handle, id, value, size ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle) return E_INVALIDARG; - return prop_set( channel->prop, channel->prop_count, id, value, size ); + if (!channel) return E_INVALIDARG; + + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + LeaveCriticalSection( &channel->cs ); + return E_INVALIDARG; + } + + hr = prop_set( channel->prop, channel->prop_count, id, value, size ); + + LeaveCriticalSection( &channel->cs ); + return hr; } static HRESULT open_channel( struct channel *channel, const WS_ENDPOINT_ADDRESS *endpoint ) @@ -253,15 +304,32 @@ const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct channel *channel = (struct channel *)handle; + HRESULT hr; TRACE( "%p %p %p %p\n", handle, endpoint, ctx, error ); if (error) FIXME( "ignoring error parameter\n" ); if (ctx) FIXME( "ignoring ctx parameter\n" ); - if (!handle || !endpoint) return E_INVALIDARG; - if (channel->state != WS_CHANNEL_STATE_CREATED) return WS_E_INVALID_OPERATION; + if (!channel || !endpoint) return E_INVALIDARG; + + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + LeaveCriticalSection( &channel->cs ); + return E_INVALIDARG; + } + + if (channel->state != WS_CHANNEL_STATE_CREATED) + { + LeaveCriticalSection( &channel->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = open_channel( channel, endpoint ); - return open_channel( channel, endpoint ); + LeaveCriticalSection( &channel->cs ); + return hr; } static HRESULT close_channel( struct channel *channel ) @@ -287,13 +355,26 @@ HRESULT WINAPI WsCloseChannel( WS_CHANNEL *handle, const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct channel *channel = (struct channel *)handle; + HRESULT hr; TRACE( "%p %p %p\n", handle, ctx, error ); if (error) FIXME( "ignoring error parameter\n" ); if (ctx) FIXME( "ignoring ctx parameter\n" ); - if (!handle) return E_INVALIDARG; - return close_channel( channel ); + if (!channel) return E_INVALIDARG; + + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + LeaveCriticalSection( &channel->cs ); + return E_INVALIDARG; + } + + hr = close_channel( channel ); + + LeaveCriticalSection( &channel->cs ); + return hr; } static HRESULT parse_url( const WCHAR *url, ULONG len, URL_COMPONENTS *uc ) @@ -444,10 +525,26 @@ WS_BYTES buf; HRESULT hr; - if ((hr = connect_channel( channel, msg )) != S_OK) return hr; + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + LeaveCriticalSection( &channel->cs ); + return E_INVALIDARG; + } + + if ((hr = connect_channel( channel, msg )) != S_OK) + { + LeaveCriticalSection( &channel->cs ); + return hr; + } + WsGetMessageProperty( msg, WS_MESSAGE_PROPERTY_BODY_WRITER, &writer, sizeof(writer), NULL ); WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &buf, sizeof(buf), NULL ); - return send_message( channel, buf.bytes, buf.length ); + hr = send_message( channel, buf.bytes, buf.length ); + + LeaveCriticalSection( &channel->cs ); + return hr; } /************************************************************************** @@ -464,18 +561,28 @@ if (error) FIXME( "ignoring error parameter\n" ); if (ctx) FIXME( "ignoring ctx parameter\n" ); - if (!handle || !msg || !desc) return E_INVALIDARG; + if (!channel || !msg || !desc) return E_INVALIDARG; - if ((hr = WsInitializeMessage( msg, WS_REQUEST_MESSAGE, NULL, NULL )) != S_OK) return hr; - if ((hr = WsAddressMessage( msg, &channel->addr, NULL )) != S_OK) return hr; - if ((hr = message_set_action( msg, desc->action )) != S_OK) return hr; - - if (!channel->writer && (hr = WsCreateWriter( NULL, 0, &channel->writer, NULL )) != S_OK) return hr; - if ((hr = set_output( channel->writer )) != S_OK) return hr; - if ((hr = write_message( msg, channel->writer, desc->bodyElementDescription, option, body, size )) != S_OK) - return hr; + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + LeaveCriticalSection( &channel->cs ); + return E_INVALIDARG; + } + + if ((hr = WsInitializeMessage( msg, WS_REQUEST_MESSAGE, NULL, NULL )) != S_OK) goto done; + if ((hr = WsAddressMessage( msg, &channel->addr, NULL )) != S_OK) goto done; + if ((hr = message_set_action( msg, desc->action )) != S_OK) goto done; - return channel_send_message( handle, msg ); + if (!channel->writer && (hr = WsCreateWriter( NULL, 0, &channel->writer, NULL )) != S_OK) goto done; + if ((hr = set_output( channel->writer )) != S_OK) goto done; + hr = write_message( msg, channel->writer, desc->bodyElementDescription, option, body, size ); + +done: + LeaveCriticalSection( &channel->cs ); + if (hr == S_OK) hr = channel_send_message( handle, msg ); + return hr; } #define INITIAL_READ_BUFFER_SIZE 4096 @@ -529,9 +636,21 @@ { struct channel *channel = (struct channel *)handle; ULONG max_len; + HRESULT hr; + + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + LeaveCriticalSection( &channel->cs ); + return E_INVALIDARG; + } WsGetChannelProperty( handle, WS_CHANNEL_PROPERTY_MAX_BUFFERED_MESSAGE_SIZE, &max_len, sizeof(max_len), NULL ); - return receive_message( channel, max_len, buf, len ); + hr = receive_message( channel, max_len, buf, len ); + + LeaveCriticalSection( &channel->cs ); + return hr; } HRESULT set_input( WS_XML_READER *reader, char *data, ULONG size ) @@ -586,14 +705,25 @@ return E_NOTIMPL; } - if (!handle || !msg || !desc || !count) return E_INVALIDARG; + if (!channel || !msg || !desc || !count) return E_INVALIDARG; if ((hr = channel_receive_message( handle, &buf, &len )) != S_OK) return hr; + + EnterCriticalSection( &channel->cs ); + + if (channel->magic != CHANNEL_MAGIC) + { + heap_free( buf ); + LeaveCriticalSection( &channel->cs ); + return E_INVALIDARG; + } + if (!channel->reader && (hr = WsCreateReader( NULL, 0, &channel->reader, NULL )) != S_OK) goto done; if ((hr = set_input( channel->reader, buf, len )) != S_OK) goto done; hr = read_message( msg, channel->reader, desc[0]->bodyElementDescription, read_option, heap, value, size ); done: heap_free( buf ); + LeaveCriticalSection( &channel->cs ); return hr; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/msg.c wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/msg.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/msg.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/msg.c 2017-03-21 14:02:57.000000000 +0000 @@ -64,6 +64,8 @@ struct msg { + ULONG magic; + CRITICAL_SECTION cs; WS_MESSAGE_INITIALIZATION init; WS_MESSAGE_STATE state; GUID id; @@ -86,7 +88,9 @@ struct prop prop[sizeof(msg_props)/sizeof(msg_props[0])]; }; +#define MSG_MAGIC (('M' << 24) | ('E' << 16) | ('S' << 8) | 'S') #define HEADER_ARRAY_SIZE 2 + static struct msg *alloc_msg(void) { static const ULONG count = sizeof(msg_props)/sizeof(msg_props[0]); @@ -99,8 +103,13 @@ heap_free( ret ); return NULL; } + ret->magic = MSG_MAGIC; ret->state = WS_MESSAGE_STATE_EMPTY; ret->header_size = HEADER_ARRAY_SIZE; + + InitializeCriticalSection( &ret->cs ); + ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": msg.cs"); + prop_init( msg_props, count, ret->prop, &ret[1] ); ret->prop_count = count; return ret; @@ -117,13 +126,16 @@ static void free_msg( struct msg *msg ) { ULONG i; - if (!msg) return; + WsFreeWriter( msg->writer ); WsFreeHeap( msg->heap ); heap_free( msg->addr.chars ); heap_free( msg->action.chars ); for (i = 0; i < msg->header_count; i++) free_header( msg->header[i] ); heap_free( msg->header ); + + msg->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &msg->cs ); heap_free( msg ); } @@ -221,6 +233,20 @@ struct msg *msg = (struct msg *)handle; TRACE( "%p\n", handle ); + + if (!msg) return; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return; + } + + msg->magic = 0; + + LeaveCriticalSection( &msg->cs ); free_msg( msg ); } @@ -231,57 +257,69 @@ ULONG size, WS_ERROR *error ) { struct msg *msg = (struct msg *)handle; + HRESULT hr = S_OK; TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle) return E_INVALIDARG; + if (!msg) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } switch (id) { case WS_MESSAGE_PROPERTY_STATE: - if (!buf || size != sizeof(msg->state)) return E_INVALIDARG; - *(WS_MESSAGE_STATE *)buf = msg->state; - return S_OK; + if (!buf || size != sizeof(msg->state)) hr = E_INVALIDARG; + else *(WS_MESSAGE_STATE *)buf = msg->state; + break; case WS_MESSAGE_PROPERTY_HEAP: - if (!buf || size != sizeof(msg->heap)) return E_INVALIDARG; - *(WS_HEAP **)buf = msg->heap; - return S_OK; + if (!buf || size != sizeof(msg->heap)) hr = E_INVALIDARG; + else *(WS_HEAP **)buf = msg->heap; + break; case WS_MESSAGE_PROPERTY_ENVELOPE_VERSION: - if (!buf || size != sizeof(msg->version_env)) return E_INVALIDARG; - *(WS_ENVELOPE_VERSION *)buf = msg->version_env; - return S_OK; + if (!buf || size != sizeof(msg->version_env)) hr = E_INVALIDARG; + else *(WS_ENVELOPE_VERSION *)buf = msg->version_env; + break; case WS_MESSAGE_PROPERTY_ADDRESSING_VERSION: - if (!buf || size != sizeof(msg->version_addr)) return E_INVALIDARG; - *(WS_ADDRESSING_VERSION *)buf = msg->version_addr; - return S_OK; + if (!buf || size != sizeof(msg->version_addr)) hr = E_INVALIDARG; + else *(WS_ADDRESSING_VERSION *)buf = msg->version_addr; + break; case WS_MESSAGE_PROPERTY_HEADER_BUFFER: - if (!buf || size != sizeof(msg->buf)) return E_INVALIDARG; - *(WS_XML_BUFFER **)buf = msg->buf; - return S_OK; + if (!buf || size != sizeof(msg->buf)) hr = E_INVALIDARG; + else *(WS_XML_BUFFER **)buf = msg->buf; + break; case WS_MESSAGE_PROPERTY_BODY_READER: - if (!buf || size != sizeof(msg->reader_body)) return E_INVALIDARG; - *(WS_XML_READER **)buf = msg->reader_body; - return S_OK; + if (!buf || size != sizeof(msg->reader_body)) hr = E_INVALIDARG; + else *(WS_XML_READER **)buf = msg->reader_body; + break; case WS_MESSAGE_PROPERTY_BODY_WRITER: - if (!buf || size != sizeof(msg->writer_body)) return E_INVALIDARG; - *(WS_XML_WRITER **)buf = msg->writer_body; - return S_OK; + if (!buf || size != sizeof(msg->writer_body)) hr = E_INVALIDARG; + else *(WS_XML_WRITER **)buf = msg->writer_body; + break; case WS_MESSAGE_PROPERTY_IS_ADDRESSED: - if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; - *(BOOL *)buf = msg->is_addressed; - return S_OK; + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) hr = WS_E_INVALID_OPERATION; + else *(BOOL *)buf = msg->is_addressed; + break; default: - return prop_get( msg->prop, msg->prop_count, id, buf, size ); + hr = prop_get( msg->prop, msg->prop_count, id, buf, size ); } + + LeaveCriticalSection( &msg->cs ); + return hr; } /************************************************************************** @@ -291,11 +329,20 @@ ULONG size, WS_ERROR *error ) { struct msg *msg = (struct msg *)handle; + HRESULT hr; TRACE( "%p %u %p %u\n", handle, id, value, size ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle) return E_INVALIDARG; + if (!msg) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } switch (id) { @@ -303,13 +350,16 @@ case WS_MESSAGE_PROPERTY_ENVELOPE_VERSION: case WS_MESSAGE_PROPERTY_ADDRESSING_VERSION: case WS_MESSAGE_PROPERTY_IS_ADDRESSED: - if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; - return E_INVALIDARG; + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) hr = WS_E_INVALID_OPERATION; + else hr = E_INVALIDARG; + break; default: - break; + hr = prop_set( msg->prop, msg->prop_count, id, value, size ); } - return prop_set( msg->prop, msg->prop_count, id, value, size ); + + LeaveCriticalSection( &msg->cs ); + return hr; } /************************************************************************** @@ -318,6 +368,7 @@ HRESULT WINAPI WsAddressMessage( WS_MESSAGE *handle, const WS_ENDPOINT_ADDRESS *addr, WS_ERROR *error ) { struct msg *msg = (struct msg *)handle; + HRESULT hr = S_OK; TRACE( "%p %p %p\n", handle, addr, error ); if (error) FIXME( "ignoring error parameter\n" ); @@ -327,18 +378,36 @@ return E_NOTIMPL; } - if (!handle) return E_INVALIDARG; - if (msg->state < WS_MESSAGE_STATE_INITIALIZED || msg->is_addressed) return WS_E_INVALID_OPERATION; + if (!msg) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state < WS_MESSAGE_STATE_INITIALIZED || msg->is_addressed) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } if (addr && addr->url.length) { - if (!(msg->addr.chars = heap_alloc( addr->url.length * sizeof(WCHAR) ))) return E_OUTOFMEMORY; - memcpy( msg->addr.chars, addr->url.chars, addr->url.length * sizeof(WCHAR) ); - msg->addr.length = addr->url.length; + if (!(msg->addr.chars = heap_alloc( addr->url.length * sizeof(WCHAR) ))) hr = E_OUTOFMEMORY; + else + { + memcpy( msg->addr.chars, addr->url.chars, addr->url.length * sizeof(WCHAR) ); + msg->addr.length = addr->url.length; + } } - msg->is_addressed = TRUE; - return S_OK; + if (hr == S_OK) msg->is_addressed = TRUE; + + LeaveCriticalSection( &msg->cs ); + return hr; } static HRESULT get_env_namespace( WS_ENVELOPE_VERSION ver, WS_XML_STRING *str ) @@ -523,15 +592,31 @@ return E_NOTIMPL; } - if (!handle || !writer) return E_INVALIDARG; - if (msg->state != WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; + if (!msg || !writer) return E_INVALIDARG; - if ((hr = write_envelope( msg )) != S_OK) return hr; - if ((hr = write_envelope_start( msg, writer )) != S_OK) return hr; + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state != WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } + + if ((hr = write_envelope( msg )) != S_OK) goto done; + if ((hr = write_envelope_start( msg, writer )) != S_OK) goto done; msg->writer_body = writer; msg->state = WS_MESSAGE_STATE_WRITING; - return S_OK; + +done: + LeaveCriticalSection( &msg->cs ); + return hr; } /************************************************************************** @@ -545,13 +630,26 @@ TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle) return E_INVALIDARG; - if (msg->state != WS_MESSAGE_STATE_WRITING) return WS_E_INVALID_OPERATION; + if (!msg) return E_INVALIDARG; - if ((hr = write_envelope_end( msg->writer_body )) != S_OK) return hr; + EnterCriticalSection( &msg->cs ); - msg->state = WS_MESSAGE_STATE_DONE; - return S_OK; + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state != WS_MESSAGE_STATE_WRITING) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } + + if ((hr = write_envelope_end( msg->writer_body )) == S_OK) msg->state = WS_MESSAGE_STATE_DONE; + + LeaveCriticalSection( &msg->cs ); + return hr; } /************************************************************************** @@ -566,17 +664,33 @@ TRACE( "%p %p %08x %p %u %p\n", handle, desc, option, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle || !desc) return E_INVALIDARG; - if (msg->state != WS_MESSAGE_STATE_WRITING) return WS_E_INVALID_OPERATION; + if (!msg || !desc) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state != WS_MESSAGE_STATE_WRITING) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } if (desc->elementLocalName && (hr = WsWriteStartElement( msg->writer_body, NULL, desc->elementLocalName, desc->elementNs, - NULL )) != S_OK) return hr; + NULL )) != S_OK) goto done; if ((hr = WsWriteType( msg->writer_body, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription, - option, value, size, NULL )) != S_OK) return hr; + option, value, size, NULL )) != S_OK) goto done; if (desc->elementLocalName) hr = WsWriteEndElement( msg->writer_body, NULL ); + +done: + LeaveCriticalSection( &msg->cs ); return hr; } @@ -621,14 +735,30 @@ return E_NOTIMPL; } - if (!handle || !reader) return E_INVALIDARG; - if (msg->state != WS_MESSAGE_STATE_EMPTY) return WS_E_INVALID_OPERATION; + if (!msg || !reader) return E_INVALIDARG; - if ((hr = read_envelope_start( reader )) != S_OK) return hr; + EnterCriticalSection( &msg->cs ); - msg->reader_body = reader; - msg->state = WS_MESSAGE_STATE_READING; - return S_OK; + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state != WS_MESSAGE_STATE_EMPTY) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } + + if ((hr = read_envelope_start( reader )) == S_OK) + { + msg->reader_body = reader; + msg->state = WS_MESSAGE_STATE_READING; + } + + LeaveCriticalSection( &msg->cs ); + return hr; } static HRESULT read_envelope_end( WS_XML_READER *reader ) @@ -649,13 +779,26 @@ TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle) return E_INVALIDARG; - if (msg->state != WS_MESSAGE_STATE_READING) return WS_E_INVALID_OPERATION; + if (!msg) return E_INVALIDARG; - if ((hr = read_envelope_end( msg->reader_body )) != S_OK) return hr; + EnterCriticalSection( &msg->cs ); - msg->state = WS_MESSAGE_STATE_DONE; - return S_OK; + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state != WS_MESSAGE_STATE_READING) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } + + if ((hr = read_envelope_end( msg->reader_body )) == S_OK) msg->state = WS_MESSAGE_STATE_DONE; + + LeaveCriticalSection( &msg->cs ); + return hr; } /************************************************************************** @@ -665,14 +808,31 @@ WS_HEAP *heap, void *value, ULONG size, WS_ERROR *error ) { struct msg *msg = (struct msg *)handle; + HRESULT hr; TRACE( "%p %p %08x %p %p %u %p\n", handle, desc, option, heap, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle || !desc) return E_INVALIDARG; - if (msg->state != WS_MESSAGE_STATE_READING) return WS_E_INVALID_OPERATION; + if (!msg || !desc) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } - return WsReadElement( msg->reader_body, desc, option, heap, value, size, NULL ); + if (msg->state != WS_MESSAGE_STATE_READING) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = WsReadElement( msg->reader_body, desc, option, heap, value, size, NULL ); + + LeaveCriticalSection( &msg->cs ); + return hr; } /************************************************************************** @@ -682,6 +842,7 @@ WS_MESSAGE *src_handle, WS_ERROR *error ) { struct msg *msg = (struct msg *)handle; + HRESULT hr; TRACE( "%p %u %p %p\n", handle, init, src_handle, error ); if (error) FIXME( "ignoring error parameter\n" ); @@ -691,12 +852,30 @@ return E_NOTIMPL; } - if (!handle || init > WS_FAULT_MESSAGE) return E_INVALIDARG; - if (msg->state >= WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; + if (!msg || init > WS_FAULT_MESSAGE) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state >= WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } - msg->init = init; - msg->state = WS_MESSAGE_STATE_INITIALIZED; - return write_envelope( msg ); + if ((hr = write_envelope( msg )) == S_OK) + { + msg->init = init; + msg->state = WS_MESSAGE_STATE_INITIALIZED; + } + + LeaveCriticalSection( &msg->cs ); + return hr; } static HRESULT grow_header_array( struct msg *msg, ULONG size ) @@ -799,8 +978,21 @@ TRACE( "%p %u %u %08x %p %u %p\n", handle, type, value_type, option, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle || type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG; - if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; + if (!msg || type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } for (i = 0; i < msg->header_count; i++) { @@ -813,18 +1005,22 @@ if (!found) { - if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) return hr; + if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) goto done; i = msg->header_count; } if ((hr = build_standard_header( msg->heap, type, value_type, option, value, size, &header )) != S_OK) - return hr; + goto done; if (!found) msg->header_count++; else free_header( msg->header[i] ); msg->header[i] = header; - return write_envelope( msg ); + hr = write_envelope( msg ); + +done: + LeaveCriticalSection( &msg->cs ); + return hr; } static void remove_header( struct msg *msg, ULONG i ) @@ -841,14 +1037,33 @@ { struct msg *msg = (struct msg *)handle; BOOL removed = FALSE; + HRESULT hr = S_OK; ULONG i; TRACE( "%p %u %p\n", handle, type, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle) return E_INVALIDARG; - if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; - if (type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG; + if (!msg) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } + + if (type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } for (i = 0; i < msg->header_count; i++) { @@ -860,8 +1075,10 @@ } } - if (removed) return write_envelope( msg ); - return S_OK; + if (removed) hr = write_envelope( msg ); + + LeaveCriticalSection( &msg->cs ); + return hr; } static HRESULT build_mapped_header( const WS_XML_STRING *name, WS_TYPE type, WS_WRITE_OPTION option, @@ -966,8 +1183,21 @@ TRACE( "%p %s %u %08x %p %u %p\n", handle, debugstr_xmlstr(name), type, option, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle || !name) return E_INVALIDARG; - if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; + if (!msg || !name) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } for (i = 0; i < msg->header_count; i++) { @@ -981,17 +1211,20 @@ if (!found) { - if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) return hr; + if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) goto done; i = msg->header_count; } - if ((hr = build_mapped_header( name, type, option, value, size, &header )) != S_OK) return hr; + if ((hr = build_mapped_header( name, type, option, value, size, &header )) != S_OK) goto done; if (!found) msg->header_count++; else free_header( msg->header[i] ); msg->header[i] = header; - return S_OK; + +done: + LeaveCriticalSection( &msg->cs ); + return hr; } /************************************************************************** @@ -1005,8 +1238,21 @@ TRACE( "%p %s %p\n", handle, debugstr_xmlstr(name), error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle || !name) return E_INVALIDARG; - if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; + if (!msg || !name) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } for (i = 0; i < msg->header_count; i++) { @@ -1018,6 +1264,7 @@ } } + LeaveCriticalSection( &msg->cs ); return S_OK; } @@ -1070,15 +1317,31 @@ TRACE( "%p %p %08x %p %u %08x %p\n", handle, desc, option, value, size, attrs, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle || !desc) return E_INVALIDARG; - if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; + if (!msg || !desc) return E_INVALIDARG; - if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) return hr; - if ((hr = build_custom_header( msg->heap, desc->elementLocalName, desc->elementNs, desc->type, - desc->typeDescription, option, value, size, &header )) != S_OK) return hr; + EnterCriticalSection( &msg->cs ); + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } + + if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) goto done; + if ((hr = build_custom_header( msg->heap, desc->elementLocalName, desc->elementNs, desc->type, + desc->typeDescription, option, value, size, &header )) != S_OK) goto done; msg->header[msg->header_count++] = header; - return write_envelope( msg ); + hr = write_envelope( msg ); + +done: + LeaveCriticalSection( &msg->cs ); + return hr; } /************************************************************************** @@ -1089,13 +1352,27 @@ { struct msg *msg = (struct msg *)handle; BOOL removed = FALSE; + HRESULT hr = S_OK; ULONG i; TRACE( "%p %s %s %p\n", handle, debugstr_xmlstr(name), debugstr_xmlstr(ns), error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!handle || !name || !ns) return E_INVALIDARG; - if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; + if (!msg || !name || !ns) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } for (i = 0; i < msg->header_count; i++) { @@ -1109,8 +1386,10 @@ } } - if (removed) return write_envelope( msg ); - return S_OK; + if (removed) hr = write_envelope( msg ); + + LeaveCriticalSection( &msg->cs ); + return hr; } static WCHAR *build_http_header( const WCHAR *name, const WCHAR *value, ULONG *ret_len ) @@ -1121,6 +1400,12 @@ return ret; } +static inline HRESULT insert_http_header( HINTERNET req, const WCHAR *header, ULONG len, ULONG flags ) +{ + if (WinHttpAddRequestHeaders( req, header, len, flags )) return S_OK; + return HRESULT_FROM_WIN32( GetLastError() ); +} + HRESULT message_insert_http_headers( WS_MESSAGE *handle, HINTERNET req ) { static const WCHAR contenttypeW[] = @@ -1132,9 +1417,17 @@ static const WCHAR charsetW[] = {'c','h','a','r','s','e','t','=','u','t','f','-','8',0}; struct msg *msg = (struct msg *)handle; - WCHAR *header, *buf; + HRESULT hr = E_OUTOFMEMORY; + WCHAR *header = NULL, *buf; ULONG len; - BOOL ret; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } switch (msg->version_env) { @@ -1148,18 +1441,19 @@ default: FIXME( "unhandled envelope version %u\n", msg->version_env ); - return E_NOTIMPL; + hr = E_NOTIMPL; } - if (!header) return E_OUTOFMEMORY; + if (!header) goto done; - ret = WinHttpAddRequestHeaders( req, header, len, WINHTTP_ADDREQ_FLAG_ADD ); + if ((hr = insert_http_header( req, header, len, WINHTTP_ADDREQ_FLAG_ADD )) != S_OK) goto done; heap_free( header ); - if (!ret) return HRESULT_FROM_WIN32( GetLastError() ); - if (!(header = build_http_header( contenttypeW, charsetW, &len ))) return E_OUTOFMEMORY; - ret = WinHttpAddRequestHeaders( req, header, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON ); + hr = E_OUTOFMEMORY; + if (!(header = build_http_header( contenttypeW, charsetW, &len ))) goto done; + if ((hr = insert_http_header( req, header, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON )) != S_OK) + goto done; heap_free( header ); - if (!ret) return HRESULT_FROM_WIN32( GetLastError() ); + header = NULL; switch (msg->version_env) { @@ -1168,18 +1462,19 @@ static const WCHAR soapactionW[] = {'S','O','A','P','A','c','t','i','o','n',0}; if (!(len = msg->action.length)) break; - if (!(buf = heap_alloc( (len + 3) * sizeof(WCHAR) ))) return E_OUTOFMEMORY; + + hr = E_OUTOFMEMORY; + if (!(buf = heap_alloc( (len + 3) * sizeof(WCHAR) ))) goto done; buf[0] = '"'; memcpy( buf + 1, msg->action.chars, len * sizeof(WCHAR) ); buf[len + 1] = '"'; buf[len + 2] = 0; + header = build_http_header( soapactionW, buf, &len ); heap_free( buf ); - if (!header) return E_OUTOFMEMORY; + if (!header) goto done; - ret = WinHttpAddRequestHeaders( req, header, len, WINHTTP_ADDREQ_FLAG_ADD ); - heap_free( header ); - if (!ret) return HRESULT_FROM_WIN32( GetLastError() ); + hr = insert_http_header( req, header, len, WINHTTP_ADDREQ_FLAG_ADD ); break; } case WS_ENVELOPE_VERSION_SOAP_1_2: @@ -1188,46 +1483,81 @@ ULONG len_action = sizeof(actionW)/sizeof(actionW[0]); if (!(len = msg->action.length)) break; - if (!(buf = heap_alloc( (len + len_action + 2) * sizeof(WCHAR) ))) return E_OUTOFMEMORY; + + hr = E_OUTOFMEMORY; + if (!(buf = heap_alloc( (len + len_action + 2) * sizeof(WCHAR) ))) goto done; memcpy( buf, actionW, len_action * sizeof(WCHAR) ); memcpy( buf + len_action, msg->action.chars, len * sizeof(WCHAR) ); len += len_action; buf[len++] = '"'; buf[len] = 0; + header = build_http_header( contenttypeW, buf, &len ); heap_free( buf ); - if (!header) return E_OUTOFMEMORY; + if (!header) goto done; - ret = WinHttpAddRequestHeaders( req, header, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON ); - heap_free( header ); - if (!ret) return HRESULT_FROM_WIN32( GetLastError() ); + hr = insert_http_header( req, header, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON ); break; } default: FIXME( "unhandled envelope version %u\n", msg->version_env ); - return E_NOTIMPL; + hr = E_NOTIMPL; } - return S_OK; +done: + heap_free( header ); + LeaveCriticalSection( &msg->cs ); + return hr; } void message_set_send_context( WS_MESSAGE *handle, const WS_PROXY_MESSAGE_CALLBACK_CONTEXT *ctx ) { struct msg *msg = (struct msg *)handle; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return; + } + msg->ctx_send.callback = ctx->callback; msg->ctx_send.state = ctx->state; + + LeaveCriticalSection( &msg->cs ); } void message_set_receive_context( WS_MESSAGE *handle, const WS_PROXY_MESSAGE_CALLBACK_CONTEXT *ctx ) { struct msg *msg = (struct msg *)handle; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return; + } + msg->ctx_receive.callback = ctx->callback; msg->ctx_receive.state = ctx->state; + + LeaveCriticalSection( &msg->cs ); } void message_do_send_callback( WS_MESSAGE *handle ) { struct msg *msg = (struct msg *)handle; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return; + } + if (msg->ctx_send.callback) { HRESULT hr; @@ -1235,11 +1565,22 @@ hr = msg->ctx_send.callback( handle, msg->heap, msg->ctx_send.state, NULL ); TRACE( "callback %p returned %08x\n", msg->ctx_send.callback, hr ); } + + LeaveCriticalSection( &msg->cs ); } void message_do_receive_callback( WS_MESSAGE *handle ) { struct msg *msg = (struct msg *)handle; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return; + } + if (msg->ctx_receive.callback) { HRESULT hr; @@ -1247,28 +1588,43 @@ hr = msg->ctx_receive.callback( handle, msg->heap, msg->ctx_receive.state, NULL ); TRACE( "callback %p returned %08x\n", msg->ctx_receive.callback, hr ); } + + LeaveCriticalSection( &msg->cs ); } HRESULT message_set_action( WS_MESSAGE *handle, const WS_XML_STRING *action ) { struct msg *msg = (struct msg *)handle; - WCHAR *chars; - int len; + HRESULT hr = S_OK; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } if (!action || !action->length) { heap_free( msg->action.chars ); msg->action.chars = NULL; msg->action.length = 0; - return S_OK; } - len = MultiByteToWideChar( CP_UTF8, 0, (char *)action->bytes, action->length, NULL, 0 ); - if (!(chars = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY; - MultiByteToWideChar( CP_UTF8, 0, (char *)action->bytes, action->length, chars, len ); - - heap_free( msg->action.chars ); - msg->action.chars = chars; - msg->action.length = len; + else + { + WCHAR *chars; + int len = MultiByteToWideChar( CP_UTF8, 0, (char *)action->bytes, action->length, NULL, 0 ); + if (!(chars = heap_alloc( len * sizeof(WCHAR) ))) hr = E_OUTOFMEMORY; + else + { + MultiByteToWideChar( CP_UTF8, 0, (char *)action->bytes, action->length, chars, len ); + heap_free( msg->action.chars ); + msg->action.chars = chars; + msg->action.length = len; + } + } - return S_OK; + LeaveCriticalSection( &msg->cs ); + return hr; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/proxy.c wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/proxy.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/proxy.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/proxy.c 2017-03-21 14:02:57.000000000 +0000 @@ -43,11 +43,15 @@ struct proxy { - WS_CHANNEL *channel; - ULONG prop_count; - struct prop prop[sizeof(proxy_props)/sizeof(proxy_props[0])]; + ULONG magic; + CRITICAL_SECTION cs; + WS_CHANNEL *channel; + ULONG prop_count; + struct prop prop[sizeof(proxy_props)/sizeof(proxy_props[0])]; }; +#define PROXY_MAGIC (('P' << 24) | ('R' << 16) | ('O' << 8) | 'X') + static struct proxy *alloc_proxy(void) { static const ULONG count = sizeof(proxy_props)/sizeof(proxy_props[0]); @@ -55,6 +59,11 @@ ULONG size = sizeof(*ret) + prop_size( proxy_props, count ); if (!(ret = heap_alloc_zero( size ))) return NULL; + + ret->magic = PROXY_MAGIC; + InitializeCriticalSection( &ret->cs ); + ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": proxy.cs"); + prop_init( proxy_props, count, ret->prop, &ret[1] ); ret->prop_count = count; return ret; @@ -62,8 +71,9 @@ static void free_proxy( struct proxy *proxy ) { - if (!proxy) return; WsFreeChannel( proxy->channel ); + proxy->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &proxy->cs ); heap_free( proxy ); } @@ -188,6 +198,20 @@ struct proxy *proxy = (struct proxy *)handle; TRACE( "%p\n", handle ); + + if (!proxy) return; + + EnterCriticalSection( &proxy->cs ); + + if (proxy->magic != PROXY_MAGIC) + { + LeaveCriticalSection( &proxy->cs ); + return; + } + + proxy->magic = 0; + + LeaveCriticalSection( &proxy->cs ); free_proxy( proxy ); } @@ -198,11 +222,25 @@ void *buf, ULONG size, WS_ERROR *error ) { struct proxy *proxy = (struct proxy *)handle; + HRESULT hr; TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - return prop_get( proxy->prop, proxy->prop_count, id, buf, size ); + if (!proxy) return E_INVALIDARG; + + EnterCriticalSection( &proxy->cs ); + + if (proxy->magic != PROXY_MAGIC) + { + LeaveCriticalSection( &proxy->cs ); + return E_INVALIDARG; + } + + hr = prop_get( proxy->prop, proxy->prop_count, id, buf, size ); + + LeaveCriticalSection( &proxy->cs ); + return hr; } /************************************************************************** @@ -212,13 +250,26 @@ const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct proxy *proxy = (struct proxy *)handle; + HRESULT hr; TRACE( "%p %p %p %p\n", handle, endpoint, ctx, error ); if (error) FIXME( "ignoring error parameter\n" ); if (ctx) FIXME( "ignoring ctx parameter\n" ); - if (!handle || !endpoint) return E_INVALIDARG; - return WsOpenChannel( proxy->channel, endpoint, NULL, NULL ); + if (!proxy || !endpoint) return E_INVALIDARG; + + EnterCriticalSection( &proxy->cs ); + + if (proxy->magic != PROXY_MAGIC) + { + LeaveCriticalSection( &proxy->cs ); + return E_INVALIDARG; + } + + hr = WsOpenChannel( proxy->channel, endpoint, NULL, NULL ); + + LeaveCriticalSection( &proxy->cs ); + return hr; } /************************************************************************** @@ -227,13 +278,26 @@ HRESULT WINAPI WsCloseServiceProxy( WS_SERVICE_PROXY *handle, const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct proxy *proxy = (struct proxy *)handle; + HRESULT hr; TRACE( "%p %p %p\n", handle, ctx, error ); if (error) FIXME( "ignoring error parameter\n" ); if (ctx) FIXME( "ignoring ctx parameter\n" ); - if (!handle) return E_INVALIDARG; - return WsCloseChannel( proxy->channel, NULL, NULL ); + if (!proxy) return E_INVALIDARG; + + EnterCriticalSection( &proxy->cs ); + + if (proxy->magic != PROXY_MAGIC) + { + LeaveCriticalSection( &proxy->cs ); + return E_INVALIDARG; + } + + hr = WsCloseChannel( proxy->channel, NULL, NULL ); + + LeaveCriticalSection( &proxy->cs ); + return hr; } /************************************************************************** @@ -374,7 +438,7 @@ const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct proxy *proxy = (struct proxy *)handle; - WS_MESSAGE *msg; + WS_MESSAGE *msg = NULL; HRESULT hr; ULONG i; @@ -391,17 +455,29 @@ } } - if (!handle || !desc || (desc->parameterCount && !args)) return E_INVALIDARG; + if (!proxy || !desc || (desc->parameterCount && !args)) return E_INVALIDARG; + + EnterCriticalSection( &proxy->cs ); + + if (proxy->magic != PROXY_MAGIC) + { + LeaveCriticalSection( &proxy->cs ); + return E_INVALIDARG; + } + + if ((hr = create_input_message( proxy->channel, properties, count, &msg )) != S_OK) goto done; + if ((hr = send_message( proxy->channel, msg, desc->inputMessageDescription, desc->parameterDescription, + desc->parameterCount, args )) != S_OK) goto done; - if ((hr = create_input_message( proxy->channel, properties, count, &msg )) != S_OK) return hr; - hr = send_message( proxy->channel, msg, desc->inputMessageDescription, desc->parameterDescription, - desc->parameterCount, args ); WsFreeMessage( msg ); - if (hr != S_OK) return hr; + msg = NULL; - if ((hr = create_output_message( proxy->channel, properties, count, &msg )) != S_OK) return hr; + if ((hr = create_output_message( proxy->channel, properties, count, &msg )) != S_OK) goto done; hr = receive_message( proxy->channel, msg, desc->outputMessageDescription, desc->parameterDescription, desc->parameterCount, heap, args ); + +done: WsFreeMessage( msg ); + LeaveCriticalSection( &proxy->cs ); return hr; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/reader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/reader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/reader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/reader.c 2017-03-21 14:02:57.000000000 +0000 @@ -79,10 +79,14 @@ struct error { - ULONG prop_count; - struct prop prop[sizeof(error_props)/sizeof(error_props[0])]; + ULONG magic; + CRITICAL_SECTION cs; + ULONG prop_count; + struct prop prop[sizeof(error_props)/sizeof(error_props[0])]; }; +#define ERROR_MAGIC (('E' << 24) | ('R' << 16) | ('R' << 8) | 'O') + static struct error *alloc_error(void) { static const ULONG count = sizeof(error_props)/sizeof(error_props[0]); @@ -90,11 +94,23 @@ ULONG size = sizeof(*ret) + prop_size( error_props, count ); if (!(ret = heap_alloc_zero( size ))) return NULL; + + ret->magic = ERROR_MAGIC; + InitializeCriticalSection( &ret->cs ); + ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": error.cs"); + prop_init( error_props, count, ret->prop, &ret[1] ); ret->prop_count = count; return ret; } +static void free_error( struct error *error ) +{ + error->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &error->cs ); + heap_free( error ); +} + /************************************************************************** * WsCreateError [webservices.@] */ @@ -115,14 +131,14 @@ { if (properties[i].id == WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE) { - heap_free( error ); + free_error( error ); return E_INVALIDARG; } hr = prop_set( error->prop, error->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); if (hr != S_OK) { - heap_free( error ); + free_error( error ); return hr; } } @@ -131,6 +147,13 @@ return S_OK; } +static void reset_error( struct error *error ) +{ + ULONG code = 0; + /* FIXME: release strings added with WsAddErrorString when it's implemented, reset string count */ + prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE, &code, sizeof(code) ); +} + /************************************************************************** * WsFreeError [webservices.@] */ @@ -139,7 +162,22 @@ struct error *error = (struct error *)handle; TRACE( "%p\n", handle ); - heap_free( error ); + + if (!error) return; + + EnterCriticalSection( &error->cs ); + + if (error->magic != ERROR_MAGIC) + { + LeaveCriticalSection( &error->cs ); + return; + } + + reset_error( error ); + error->magic = 0; + + LeaveCriticalSection( &error->cs ); + free_error( error ); } /************************************************************************** @@ -148,15 +186,92 @@ HRESULT WINAPI WsResetError( WS_ERROR *handle ) { struct error *error = (struct error *)handle; - ULONG code; TRACE( "%p\n", handle ); - if (!handle) return E_INVALIDARG; + if (!error) return E_INVALIDARG; - /* FIXME: release strings added with WsAddErrorString when it's implemented, reset string count */ - code = 0; - return prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE, &code, sizeof(code) ); + EnterCriticalSection( &error->cs ); + + if (error->magic != ERROR_MAGIC) + { + LeaveCriticalSection( &error->cs ); + return E_INVALIDARG; + } + + reset_error( error ); + + LeaveCriticalSection( &error->cs ); + return S_OK; +} + +/************************************************************************** + * WsGetErrorProperty [webservices.@] + */ +HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf, + ULONG size ) +{ + struct error *error = (struct error *)handle; + HRESULT hr; + + TRACE( "%p %u %p %u\n", handle, id, buf, size ); + + if (!error) return E_INVALIDARG; + + EnterCriticalSection( &error->cs ); + + if (error->magic != ERROR_MAGIC) + { + LeaveCriticalSection( &error->cs ); + return E_INVALIDARG; + } + + hr = prop_get( error->prop, error->prop_count, id, buf, size ); + + LeaveCriticalSection( &error->cs ); + return hr; +} + +/************************************************************************** + * WsGetErrorString [webservices.@] + */ +HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str ) +{ + FIXME( "%p %u %p: stub\n", handle, index, str ); + return E_NOTIMPL; +} + +/************************************************************************** + * WsSetErrorProperty [webservices.@] + */ +HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value, + ULONG size ) +{ + struct error *error = (struct error *)handle; + HRESULT hr; + + TRACE( "%p %u %p %u\n", handle, id, value, size ); + + if (!error) return E_INVALIDARG; + + EnterCriticalSection( &error->cs ); + + if (error->magic != ERROR_MAGIC) + { + LeaveCriticalSection( &error->cs ); + return E_INVALIDARG; + } + + if (id == WS_ERROR_PROPERTY_LANGID) + { + LeaveCriticalSection( &error->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = prop_set( error->prop, error->prop_count, id, value, size ); + + LeaveCriticalSection( &error->cs ); + return hr; } static const struct prop_desc heap_props[] = @@ -169,13 +284,17 @@ struct heap { - HANDLE handle; - SIZE_T max_size; - SIZE_T allocated; - ULONG prop_count; - struct prop prop[sizeof(heap_props)/sizeof(heap_props[0])]; + ULONG magic; + CRITICAL_SECTION cs; + HANDLE handle; + SIZE_T max_size; + SIZE_T allocated; + ULONG prop_count; + struct prop prop[sizeof(heap_props)/sizeof(heap_props[0])]; }; +#define HEAP_MAGIC (('H' << 24) | ('E' << 16) | ('A' << 8) | 'P') + static BOOL ensure_heap( struct heap *heap ) { SIZE_T size; @@ -189,31 +308,48 @@ void *ws_alloc( WS_HEAP *handle, SIZE_T size ) { - void *ret; struct heap *heap = (struct heap *)handle; - if (!ensure_heap( heap ) || size > heap->max_size - heap->allocated) return NULL; + void *ret = NULL; + + EnterCriticalSection( &heap->cs ); + + if (heap->magic != HEAP_MAGIC) goto done; + if (!ensure_heap( heap ) || size > heap->max_size - heap->allocated) goto done; if ((ret = HeapAlloc( heap->handle, 0, size ))) heap->allocated += size; + +done: + LeaveCriticalSection( &heap->cs ); return ret; } static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size ) { - void *ret; struct heap *heap = (struct heap *)handle; - if (!ensure_heap( heap ) || size > heap->max_size - heap->allocated) return NULL; + void *ret = NULL; + + EnterCriticalSection( &heap->cs ); + + if (heap->magic != HEAP_MAGIC) goto done; + if (!ensure_heap( heap ) || size > heap->max_size - heap->allocated) goto done; if ((ret = HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size ))) heap->allocated += size; + +done: + LeaveCriticalSection( &heap->cs ); return ret; } void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T old_size, SIZE_T new_size ) { - void *ret; struct heap *heap = (struct heap *)handle; - if (!ensure_heap( heap )) return NULL; + void *ret = NULL; + + EnterCriticalSection( &heap->cs ); + + if (heap->magic != HEAP_MAGIC || !ensure_heap( heap )) goto done; if (new_size >= old_size) { SIZE_T size = new_size - old_size; - if (size > heap->max_size - heap->allocated) return NULL; + if (size > heap->max_size - heap->allocated) goto done; if ((ret = HeapReAlloc( heap->handle, 0, ptr, new_size ))) heap->allocated += size; } else @@ -221,18 +357,24 @@ SIZE_T size = old_size - new_size; if ((ret = HeapReAlloc( heap->handle, 0, ptr, new_size ))) heap->allocated -= size; } + +done: + LeaveCriticalSection( &heap->cs ); return ret; } static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T old_size, SIZE_T new_size ) { - void *ret; struct heap *heap = (struct heap *)handle; - if (!ensure_heap( heap )) return NULL; + void *ret = NULL; + + EnterCriticalSection( &heap->cs ); + + if (heap->magic != HEAP_MAGIC || !ensure_heap( heap )) goto done; if (new_size >= old_size) { SIZE_T size = new_size - old_size; - if (size > heap->max_size - heap->allocated) return NULL; + if (size > heap->max_size - heap->allocated) goto done; if ((ret = HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, new_size ))) heap->allocated += size; } else @@ -240,15 +382,25 @@ SIZE_T size = old_size - new_size; if ((ret = HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, new_size ))) heap->allocated -= size; } + +done: + LeaveCriticalSection( &heap->cs ); return ret; } void ws_free( WS_HEAP *handle, void *ptr, SIZE_T size ) { struct heap *heap = (struct heap *)handle; - if (!heap->handle) return; - HeapFree( heap->handle, 0, ptr ); - heap->allocated -= size; + + EnterCriticalSection( &heap->cs ); + + if (heap->magic == HEAP_MAGIC) + { + HeapFree( heap->handle, 0, ptr ); + heap->allocated -= size; + } + + LeaveCriticalSection( &heap->cs ); } /************************************************************************** @@ -274,6 +426,11 @@ ULONG size = sizeof(*ret) + prop_size( heap_props, count ); if (!(ret = heap_alloc_zero( size ))) return NULL; + + ret->magic = HEAP_MAGIC; + InitializeCriticalSection( &ret->cs ); + ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": heap.cs"); + prop_init( heap_props, count, ret->prop, &ret[1] ); ret->prop_count = count; return ret; @@ -300,6 +457,13 @@ return S_OK; } +static void reset_heap( struct heap *heap ) +{ + HeapDestroy( heap->handle ); + heap->handle = NULL; + heap->max_size = heap->allocated = 0; +} + /************************************************************************** * WsFreeHeap [webservices.@] */ @@ -310,7 +474,22 @@ TRACE( "%p\n", handle ); if (!heap) return; - HeapDestroy( heap->handle ); + + EnterCriticalSection( &heap->cs ); + + if (heap->magic != HEAP_MAGIC) + { + LeaveCriticalSection( &heap->cs ); + return; + } + + reset_heap( heap ); + heap->magic = 0; + + LeaveCriticalSection( &heap->cs ); + + heap->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &heap->cs ); heap_free( heap ); } @@ -326,12 +505,60 @@ if (!heap) return E_INVALIDARG; - HeapDestroy( heap->handle ); - heap->handle = NULL; - heap->max_size = heap->allocated = 0; + EnterCriticalSection( &heap->cs ); + + if (heap->magic != HEAP_MAGIC) + { + LeaveCriticalSection( &heap->cs ); + return E_INVALIDARG; + } + + reset_heap( heap ); + + LeaveCriticalSection( &heap->cs ); return S_OK; } +/************************************************************************** + * WsGetHeapProperty [webservices.@] + */ +HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf, + ULONG size, WS_ERROR *error ) +{ + struct heap *heap = (struct heap *)handle; + HRESULT hr = S_OK; + + TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error ); + if (error) FIXME( "ignoring error parameter\n" ); + + if (!heap) return E_INVALIDARG; + + EnterCriticalSection( &heap->cs ); + + if (heap->magic != HEAP_MAGIC) + { + LeaveCriticalSection( &heap->cs ); + return E_INVALIDARG; + } + + switch (id) + { + case WS_HEAP_PROPERTY_REQUESTED_SIZE: + case WS_HEAP_PROPERTY_ACTUAL_SIZE: + { + SIZE_T *heap_size = buf; + if (!buf || size != sizeof(heap_size)) hr = E_INVALIDARG; + else *heap_size = heap->allocated; + break; + } + default: + hr = prop_get( heap->prop, heap->prop_count, id, buf, size ); + } + + LeaveCriticalSection( &heap->cs ); + return hr; +} + struct node *alloc_node( WS_XML_NODE_TYPE type ) { struct node *ret; @@ -607,26 +834,30 @@ struct reader { - ULONG read_size; - ULONG read_pos; - const unsigned char *read_bufptr; - enum reader_state state; - struct node *root; - struct node *current; - ULONG current_attr; - struct node *last; - struct prefix *prefixes; - ULONG nb_prefixes; - ULONG nb_prefixes_allocated; - WS_XML_READER_INPUT_TYPE input_type; - struct xmlbuf *input_buf; - const unsigned char *input_data; - ULONG input_size; - ULONG text_conv_offset; - ULONG prop_count; - struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])]; + ULONG magic; + CRITICAL_SECTION cs; + ULONG read_size; + ULONG read_pos; + const unsigned char *read_bufptr; + enum reader_state state; + struct node *root; + struct node *current; + ULONG current_attr; + struct node *last; + struct prefix *prefixes; + ULONG nb_prefixes; + ULONG nb_prefixes_allocated; + WS_XML_READER_INPUT_TYPE input_type; + struct xmlbuf *input_buf; + const unsigned char *input_data; + ULONG input_size; + ULONG text_conv_offset; + ULONG prop_count; + struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])]; }; +#define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D') + static struct reader *alloc_reader(void) { static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]); @@ -641,8 +872,12 @@ } ret->nb_prefixes = ret->nb_prefixes_allocated = 1; + ret->magic = READER_MAGIC; + InitializeCriticalSection( &ret->cs ); + ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": reader.cs"); + prop_init( reader_props, count, ret->prop, &ret[1] ); - ret->prop_count = count; + ret->prop_count = count; return ret; } @@ -661,19 +896,23 @@ } } -static void free_reader( struct reader *reader ) -{ - if (!reader) return; - destroy_nodes( reader->root ); - clear_prefixes( reader->prefixes, reader->nb_prefixes ); - heap_free( reader->prefixes ); - heap_free( reader ); -} - HRESULT copy_node( WS_XML_READER *handle, struct node **node ) { struct reader *reader = (struct reader *)handle; - return dup_tree( node, reader->current ); + HRESULT hr; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = dup_tree( node, reader->current ); + + LeaveCriticalSection( &reader->cs ); + return hr; } static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns ) @@ -754,18 +993,28 @@ reader->current = reader->last = node; } -static HRESULT read_init_state( struct reader *reader ) +static void free_reader( struct reader *reader ) +{ + destroy_nodes( reader->root ); + clear_prefixes( reader->prefixes, reader->nb_prefixes ); + heap_free( reader->prefixes ); + reader->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &reader->cs ); + heap_free( reader ); +} + +static HRESULT init_reader( struct reader *reader ) { struct node *node; + reader->state = READER_STATE_INITIAL; destroy_nodes( reader->root ); - reader->root = NULL; - reader->input_buf = NULL; + reader->root = reader->current = NULL; + reader->current_attr = 0; clear_prefixes( reader->prefixes, reader->nb_prefixes ); - reader->nb_prefixes = 1; + reader->nb_prefixes = 1; if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY; read_insert_eof( reader, node ); - reader->state = READER_STATE_INITIAL; return S_OK; } @@ -804,7 +1053,7 @@ } } - if ((hr = read_init_state( reader )) != S_OK) + if ((hr = init_reader( reader )) != S_OK) { free_reader( reader ); return hr; @@ -822,6 +1071,20 @@ struct reader *reader = (struct reader *)handle; TRACE( "%p\n", handle ); + + if (!reader) return; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return; + } + + reader->magic = 0; + + LeaveCriticalSection( &reader->cs ); free_reader( reader ); } @@ -838,49 +1101,23 @@ if (!reader) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + /* FIXME: add support for stream input */ reader->read_size = min( min_size, reader->input_size ); reader->read_pos = 0; + LeaveCriticalSection( &reader->cs ); return S_OK; } /************************************************************************** - * WsGetErrorProperty [webservices.@] - */ -HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf, - ULONG size ) -{ - struct error *error = (struct error *)handle; - - TRACE( "%p %u %p %u\n", handle, id, buf, size ); - return prop_get( error->prop, error->prop_count, id, buf, size ); -} - -/************************************************************************** - * WsGetErrorString [webservices.@] - */ -HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str ) -{ - FIXME( "%p %u %p: stub\n", handle, index, str ); - return E_NOTIMPL; -} - -/************************************************************************** - * WsGetHeapProperty [webservices.@] - */ -HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf, - ULONG size, WS_ERROR *error ) -{ - struct heap *heap = (struct heap *)handle; - - TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error ); - if (error) FIXME( "ignoring error parameter\n" ); - - return prop_get( heap->prop, heap->prop_count, id, buf, size ); -} - -/************************************************************************** * WsGetNamespaceFromPrefix [webservices.@] */ HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix, @@ -898,7 +1135,20 @@ if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !prefix || !ns) return E_INVALIDARG; - if (reader->state != READER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (reader->state != READER_STATE_STARTELEMENT) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } if (!prefix->length) { @@ -932,12 +1182,15 @@ } } + LeaveCriticalSection( &reader->cs ); + if (!found) { if (required) return WS_E_INVALID_FORMAT; *ns = NULL; return S_FALSE; } + return S_OK; } @@ -954,7 +1207,17 @@ if (!reader || !node) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + *node = &reader->current->hdr.node; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -965,23 +1228,44 @@ void *buf, ULONG size, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!reader->input_type) return WS_E_INVALID_OPERATION; + if (!reader) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } if (id == WS_XML_READER_PROPERTY_CHARSET) { WS_CHARSET charset; - HRESULT hr; - - if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) return hr; - if (!charset) return WS_E_INVALID_FORMAT; + if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) goto done; + if (!charset) + { + hr = WS_E_INVALID_FORMAT; + goto done; + } *(WS_CHARSET *)buf = charset; - return S_OK; + hr = S_OK; } - return prop_get( reader->prop, reader->prop_count, id, buf, size ); + else hr = prop_get( reader->prop, reader->prop_count, id, buf, size ); + +done: + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -1199,8 +1483,7 @@ static int codepoint_to_utf8( int cp, unsigned char *dst ) { - if (!cp) - return -1; + if (!cp) return -1; if (cp < 0x80) { *dst = cp; @@ -1284,7 +1567,7 @@ p++; len--; if (!len) return WS_E_INVALID_FORMAT; - else if (*p == 'x') + if (*p == 'x') { p++; len--; @@ -1848,12 +2131,25 @@ HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - return read_endelement( reader ); + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_endelement( reader ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -1862,12 +2158,25 @@ HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - return read_node( reader ); + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_node( reader ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -1876,12 +2185,25 @@ HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - return read_startelement( reader ); + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_startelement( reader ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -1891,6 +2213,7 @@ const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error ); if (error) FIXME( "ignoring error parameter\n" ); @@ -1898,7 +2221,18 @@ if (!reader) return E_INVALIDARG; if (localname || ns) FIXME( "name and/or namespace not verified\n" ); - return read_to_startelement( reader, found ); + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_to_startelement( reader, found ); + + LeaveCriticalSection( &reader->cs ); + return hr; } BOOL move_to_root_element( struct node *root, struct node **current ) @@ -2177,14 +2511,31 @@ HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %u %p %p\n", handle, move, found, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - if (!reader->input_type) return WS_E_INVALID_OPERATION; - return read_move_to( reader, move, found ); + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = read_move_to( reader, move, found ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -2193,19 +2544,32 @@ HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; - WS_XML_ELEMENT_NODE *elem; + const WS_XML_ELEMENT_NODE *elem; TRACE( "%p %u %p\n", handle, index, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + elem = &reader->current->hdr; if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount) + { + LeaveCriticalSection( &reader->cs ); return WS_E_INVALID_FORMAT; + } reader->current_attr = index; - reader->state = READER_STATE_STARTATTRIBUTE; + reader->state = READER_STATE_STARTATTRIBUTE; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -2221,10 +2585,23 @@ if (!reader) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + if (reader->state != READER_STATE_STARTATTRIBUTE) + { + LeaveCriticalSection( &reader->cs ); return WS_E_INVALID_FORMAT; + } reader->state = READER_STATE_STARTELEMENT; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -2818,6 +3195,7 @@ WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr = S_OK; TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), required, index, error ); @@ -2825,16 +3203,32 @@ if (!reader || !localname || !ns || !index) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) + { + LeaveCriticalSection( &reader->cs ); return WS_E_INVALID_OPERATION; + } if (!find_attribute( reader, localname, ns, index )) { - if (required) return WS_E_INVALID_FORMAT; - *index = ~0u; - return S_FALSE; + if (required) hr = WS_E_INVALID_FORMAT; + else + { + *index = ~0u; + hr = S_FALSE; + } } - return S_OK; + + LeaveCriticalSection( &reader->cs ); + return hr; } static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping, @@ -4293,21 +4687,34 @@ if (!reader || !value) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK) + { + LeaveCriticalSection( &reader->cs ); return hr; + } switch (mapping) { case WS_ELEMENT_TYPE_MAPPING: - if ((hr = read_node( reader )) != S_OK) return hr; + hr = read_node( reader ); break; default: break; } - if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT; - return S_OK; + if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT; + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -4318,14 +4725,26 @@ WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !desc || !value) return E_INVALIDARG; - return read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName, - desc->elementNs, desc->typeDescription, option, heap, value, size ); + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName, + desc->elementNs, desc->typeDescription, option, heap, value, size ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -4336,28 +4755,26 @@ { struct reader *reader = (struct reader *)handle; WS_TYPE type = map_value_type( value_type ); + HRESULT hr; TRACE( "%p %u %p %u %p\n", handle, type, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !value || type == ~0u) return E_INVALIDARG; - return read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE, - NULL, value, size ); -} + EnterCriticalSection( &reader->cs ); -/************************************************************************** - * WsSetErrorProperty [webservices.@] - */ -HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value, - ULONG size ) -{ - struct error *error = (struct error *)handle; + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } - TRACE( "%p %u %p %u\n", handle, id, value, size ); + hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE, + NULL, value, size ); - if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION; - return prop_set( error->prop, error->prop_count, id, value, size ); + LeaveCriticalSection( &reader->cs ); + return hr; } static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset ) @@ -4406,6 +4823,8 @@ reader->read_size = reader->input_size; reader->read_pos = 0; reader->read_bufptr = reader->input_data; + + reader->text_conv_offset = 0; } /************************************************************************** @@ -4417,22 +4836,30 @@ { struct reader *reader = (struct reader *)handle; struct node *node; - HRESULT hr; ULONG i, offset = 0; + HRESULT hr; TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + for (i = 0; i < count; i++) { hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; } - if ((hr = read_init_state( reader )) != S_OK) return hr; + if ((hr = init_reader( reader )) != S_OK) goto done; switch (encoding->encodingType) { @@ -4445,7 +4872,8 @@ if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER) { FIXME( "charset detection on input type %u not supported\n", input->inputType ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } if (charset == WS_CHARSET_AUTO) @@ -4453,13 +4881,15 @@ hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; break; } default: FIXME( "encoding type %u not supported\n", encoding->encodingType ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } + switch (input->inputType) { case WS_XML_READER_INPUT_TYPE_BUFFER: @@ -4471,12 +4901,16 @@ } default: FIXME( "input type %u not supported\n", input->inputType ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } - if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY; - read_insert_bof( reader, node ); - return S_OK; + if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY; + else read_insert_bof( reader, node ); + +done: + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -4490,32 +4924,43 @@ struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer; WS_CHARSET charset; struct node *node; - HRESULT hr; ULONG i, offset = 0; + HRESULT hr; TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !xmlbuf) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + for (i = 0; i < count; i++) { hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; } - if ((hr = read_init_state( reader )) != S_OK) return hr; + if ((hr = init_reader( reader )) != S_OK) goto done; charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset ); - hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, - &charset, sizeof(charset) ); - if (hr != S_OK) return hr; + hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, + sizeof(charset) ); + if (hr != S_OK) goto done; set_input_buffer( reader, xmlbuf, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset ); - if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY; - read_insert_bof( reader, node ); - return S_OK; + if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY; + else read_insert_bof( reader, node ); + +done: + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -4544,10 +4989,25 @@ if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !pos) return E_INVALIDARG; - if (!reader->input_buf) return WS_E_INVALID_OPERATION; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_buf) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } pos->buffer = (WS_XML_BUFFER *)reader->input_buf; pos->node = reader->current; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4561,10 +5021,25 @@ TRACE( "%p %p %p\n", handle, pos, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!reader || !pos || (struct xmlbuf *)pos->buffer != reader->input_buf) return E_INVALIDARG; - if (!reader->input_buf) return WS_E_INVALID_OPERATION; + if (!reader || !pos) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_buf) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } reader->current = pos->node; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4588,8 +5063,26 @@ if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - if (!reader->input_type) return WS_E_INVALID_OPERATION; - if (!count) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + if (!count) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } *count = 0; if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes) @@ -4597,11 +5090,17 @@ const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current; WS_XML_BASE64_TEXT base64; - if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK) return hr; + if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK) + { + LeaveCriticalSection( &reader->cs ); + return hr; + } if (reader->text_conv_offset == base64.length) { heap_free( base64.bytes ); - return read_node( reader ); + hr = read_node( reader ); + LeaveCriticalSection( &reader->cs ); + return hr; } *count = min( base64.length - reader->text_conv_offset, max_count ); memcpy( bytes, base64.bytes + reader->text_conv_offset, *count ); @@ -4609,6 +5108,7 @@ heap_free( base64.bytes ); } + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4632,8 +5132,26 @@ if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - if (!reader->input_type) return WS_E_INVALID_OPERATION; - if (!count) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + if (!count) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } *count = 0; if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars) @@ -4642,11 +5160,17 @@ WS_XML_UTF16_TEXT utf16; HRESULT hr; - if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK) return hr; + if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK) + { + LeaveCriticalSection( &reader->cs ); + return hr; + } if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR)) { heap_free( utf16.bytes ); - return read_node( reader ); + hr = read_node( reader ); + LeaveCriticalSection( &reader->cs ); + return hr; } *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count ); memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) ); @@ -4654,6 +5178,7 @@ heap_free( utf16.bytes ); } + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4663,13 +5188,32 @@ HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - if (!reader->input_type) return WS_E_INVALID_OPERATION; - if (!count) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + if (!count) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } *count = 0; if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes) @@ -4677,12 +5221,18 @@ const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current; const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text; - if (reader->text_conv_offset == utf8->value.length) return read_node( reader ); + if (reader->text_conv_offset == utf8->value.length) + { + hr = read_node( reader ); + LeaveCriticalSection( &reader->cs ); + return hr; + } *count = min( utf8->value.length - reader->text_conv_offset, max_count ); memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count ); reader->text_conv_offset += *count; } + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4756,8 +5306,16 @@ if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK) - return hr; + goto done; for (i = 0; i < count; i++) { @@ -4765,18 +5323,19 @@ if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES) { FIXME( "messages type not supported\n" ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } - if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) return hr; + if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done; if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL) { void *ptr = *(void **)args[i]; - if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) return hr; + if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done; } else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY) { void **ptr = *(void ***)args[i]; - if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) return hr; + if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done; set_array_len( params, count, params[i].outputMessageIndex, len, args ); } } @@ -4787,5 +5346,9 @@ parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT; } - return end_mapping( reader, WS_ELEMENT_TYPE_MAPPING ); + hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING ); + +done: + LeaveCriticalSection( &reader->cs ); + return hr; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/tests/reader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/tests/reader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/tests/reader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/tests/reader.c 2017-03-21 14:02:57.000000000 +0000 @@ -1758,6 +1758,8 @@ HRESULT hr; WS_HEAP *heap; void *ptr; + SIZE_T requested, actual; + ULONG size; hr = WsCreateHeap( 256, 0, NULL, 0, &heap, NULL ); ok( hr == S_OK, "got %08x\n", hr ); @@ -1776,6 +1778,19 @@ hr = WsAlloc( heap, 16, &ptr, NULL ); ok( hr == S_OK, "got %08x\n", hr ); ok( ptr != NULL, "ptr not set\n" ); + + requested = 0xdeadbeef; + size = sizeof(requested); + hr = WsGetHeapProperty( heap, WS_HEAP_PROPERTY_REQUESTED_SIZE, &requested, size, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( requested == 16, "got %u\n", (ULONG)requested ); + + actual = 0xdeadbeef; + size = sizeof(actual); + hr = WsGetHeapProperty( heap, WS_HEAP_PROPERTY_ACTUAL_SIZE, &actual, size, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + todo_wine ok( actual == 128, "got %u\n", (ULONG)actual ); + WsFreeHeap( heap ); } @@ -3078,13 +3093,13 @@ size = sizeof(requested); hr = WsGetHeapProperty( heap, WS_HEAP_PROPERTY_REQUESTED_SIZE, &requested, size, NULL ); ok( hr == S_OK, "got %08x\n", hr ); - todo_wine ok( requested == 128, "got %u\n", (ULONG)requested ); + ok( requested == 128, "got %u\n", (ULONG)requested ); actual = 0xdeadbeef; size = sizeof(actual); hr = WsGetHeapProperty( heap, WS_HEAP_PROPERTY_ACTUAL_SIZE, &actual, size, NULL ); ok( hr == S_OK, "got %08x\n", hr ); - todo_wine ok( actual == 128, "got %u\n", (ULONG)actual ); + ok( actual == 128, "got %u\n", (ULONG)actual ); hr = WsAlloc( heap, 1, &ptr, NULL ); ok( hr == S_OK, "got %08x\n", hr ); @@ -3093,7 +3108,7 @@ size = sizeof(requested); hr = WsGetHeapProperty( heap, WS_HEAP_PROPERTY_REQUESTED_SIZE, &requested, size, NULL ); ok( hr == S_OK, "got %08x\n", hr ); - todo_wine ok( requested == 129, "got %u\n", (ULONG)requested ); + ok( requested == 129, "got %u\n", (ULONG)requested ); actual = 0xdeadbeef; size = sizeof(actual); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/writer.c wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/writer.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/webservices/writer.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/webservices/writer.c 2017-03-21 14:02:57.000000000 +0000 @@ -71,19 +71,23 @@ struct writer { - ULONG write_pos; - unsigned char *write_bufptr; - enum writer_state state; - struct node *root; - struct node *current; - WS_XML_STRING *current_ns; - WS_XML_WRITER_OUTPUT_TYPE output_type; - struct xmlbuf *output_buf; - WS_HEAP *output_heap; - ULONG prop_count; - struct prop prop[sizeof(writer_props)/sizeof(writer_props[0])]; + ULONG magic; + CRITICAL_SECTION cs; + ULONG write_pos; + unsigned char *write_bufptr; + enum writer_state state; + struct node *root; + struct node *current; + WS_XML_STRING *current_ns; + WS_XML_WRITER_OUTPUT_TYPE output_type; + struct xmlbuf *output_buf; + WS_HEAP *output_heap; + ULONG prop_count; + struct prop prop[sizeof(writer_props)/sizeof(writer_props[0])]; }; +#define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T') + static struct writer *alloc_writer(void) { static const ULONG count = sizeof(writer_props)/sizeof(writer_props[0]); @@ -91,6 +95,11 @@ ULONG size = sizeof(*ret) + prop_size( writer_props, count ); if (!(ret = heap_alloc_zero( size ))) return NULL; + + ret->magic = WRITER_MAGIC; + InitializeCriticalSection( &ret->cs ); + ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": writer.cs"); + prop_init( writer_props, count, ret->prop, &ret[1] ); ret->prop_count = count; return ret; @@ -98,10 +107,12 @@ static void free_writer( struct writer *writer ) { - if (!writer) return; destroy_nodes( writer->root ); heap_free( writer->current_ns ); WsFreeHeap( writer->output_heap ); + + writer->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &writer->cs ); heap_free( writer ); } @@ -137,18 +148,20 @@ return NULL; } -static HRESULT write_init_state( struct writer *writer ) +static HRESULT init_writer( struct writer *writer ) { struct node *node; - heap_free( writer->current_ns ); - writer->current_ns = NULL; + writer->write_pos = 0; + writer->write_bufptr = NULL; destroy_nodes( writer->root ); - writer->root = NULL; + writer->root = writer->current = NULL; + heap_free( writer->current_ns ); + writer->current_ns = NULL; if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY; write_insert_eof( writer, node ); - writer->state = WRITER_STATE_INITIAL; + writer->state = WRITER_STATE_INITIAL; return S_OK; } @@ -203,7 +216,7 @@ return hr; } - hr = write_init_state( writer ); + hr = init_writer( writer ); if (hr != S_OK) { free_writer( writer ); @@ -222,6 +235,20 @@ struct writer *writer = (struct writer *)handle; TRACE( "%p\n", handle ); + + if (!writer) return; + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return; + } + + writer->magic = 0; + + LeaveCriticalSection( &writer->cs ); free_writer( writer ); } @@ -273,25 +300,46 @@ void *buf, ULONG size, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr = S_OK; TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!writer->output_type) return WS_E_INVALID_OPERATION; + if (!writer) return E_INVALIDARG; + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (!writer->output_type) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } switch (id) { case WS_XML_WRITER_PROPERTY_BYTES: { WS_BYTES *bytes = buf; - if (size != sizeof(*bytes)) return E_INVALIDARG; - bytes->bytes = writer->output_buf->ptr; - bytes->length = writer->output_buf->size; - return S_OK; + if (size != sizeof(*bytes)) hr = E_INVALIDARG; + else + { + bytes->bytes = writer->output_buf->ptr; + bytes->length = writer->output_buf->size; + } + break; } default: - return prop_get( writer->prop, writer->prop_count, id, buf, size ); + hr = prop_get( writer->prop, writer->prop_count, id, buf, size ); } + + LeaveCriticalSection( &writer->cs ); + return hr; } static void set_output_buffer( struct writer *writer, struct xmlbuf *xmlbuf ) @@ -324,14 +372,22 @@ if (!writer) return E_INVALIDARG; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + for (i = 0; i < count; i++) { hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; } - if ((hr = write_init_state( writer )) != S_OK) return hr; + if ((hr = init_writer( writer )) != S_OK) goto done; switch (encoding->encodingType) { @@ -341,32 +397,39 @@ if (text->charSet != WS_CHARSET_UTF8) { FIXME( "charset %u not supported\n", text->charSet ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } break; } default: FIXME( "encoding type %u not supported\n", encoding->encodingType ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } + switch (output->outputType) { case WS_XML_WRITER_OUTPUT_TYPE_BUFFER: { struct xmlbuf *xmlbuf; - if (!(xmlbuf = alloc_xmlbuf( writer->output_heap ))) return WS_E_QUOTA_EXCEEDED; - set_output_buffer( writer, xmlbuf ); + if (!(xmlbuf = alloc_xmlbuf( writer->output_heap ))) hr = WS_E_QUOTA_EXCEEDED; + else set_output_buffer( writer, xmlbuf ); break; } default: FIXME( "output type %u not supported\n", output->outputType ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } - if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY; - write_insert_bof( writer, node ); - return S_OK; + if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY; + else write_insert_bof( writer, node ); + +done: + LeaveCriticalSection( &writer->cs ); + return hr; } /************************************************************************** @@ -387,19 +450,30 @@ if (!writer || !xmlbuf) return E_INVALIDARG; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + for (i = 0; i < count; i++) { hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; } - if ((hr = write_init_state( writer )) != S_OK) return hr; + if ((hr = init_writer( writer )) != S_OK) goto done; set_output_buffer( writer, xmlbuf ); - if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY; - write_insert_bof( writer, node ); - return S_OK; + if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY; + else write_insert_bof( writer, node ); + +done: + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_grow_buffer( struct writer *writer, ULONG size ) @@ -526,25 +600,40 @@ struct writer *writer = (struct writer *)handle; WS_XML_ELEMENT_NODE *elem; BOOL found = FALSE; + HRESULT hr = S_OK; TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(ns), required, prefix, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer || !ns || !prefix) return E_INVALIDARG; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + elem = &writer->current->hdr; if (elem->prefix && is_current_namespace( writer, ns )) { *prefix = elem->prefix; found = TRUE; } + if (!found) { - if (required) return WS_E_INVALID_FORMAT; - *prefix = NULL; - return S_FALSE; + if (required) hr = WS_E_INVALID_FORMAT; + else + { + *prefix = NULL; + hr = S_FALSE; + } } - return S_OK; + + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT set_current_namespace( struct writer *writer, const WS_XML_STRING *ns ) @@ -663,7 +752,17 @@ if (!writer) return E_INVALIDARG; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + writer->state = WRITER_STATE_STARTELEMENT; + + LeaveCriticalSection( &writer->cs ); return S_OK; } @@ -783,12 +882,25 @@ HRESULT WINAPI WsWriteEndElement( WS_XML_WRITER *handle, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer) return E_INVALIDARG; - return write_endelement_node( writer ); + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + hr = write_endelement_node( writer ); + + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_endstartelement( struct writer *writer ) @@ -811,14 +923,29 @@ if (error) FIXME( "ignoring error parameter\n" ); if (!writer) return E_INVALIDARG; - if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION; - if ((hr = write_set_element_namespace( writer )) != S_OK) return hr; - if ((hr = write_startelement( writer )) != S_OK) return hr; - if ((hr = write_endstartelement( writer )) != S_OK) return hr; + EnterCriticalSection( &writer->cs ); + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (writer->state != WRITER_STATE_STARTELEMENT) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } + + if ((hr = write_set_element_namespace( writer )) != S_OK) goto done; + if ((hr = write_startelement( writer )) != S_OK) goto done; + if ((hr = write_endstartelement( writer )) != S_OK) goto done; writer->state = WRITER_STATE_ENDSTARTELEMENT; - return S_OK; + +done: + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_add_attribute( struct writer *writer, const WS_XML_STRING *prefix, @@ -873,11 +1000,25 @@ if (!writer || !localname || !ns) return E_INVALIDARG; - if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION; + EnterCriticalSection( &writer->cs ); - if ((hr = write_add_attribute( writer, prefix, localname, ns, single )) != S_OK) return hr; - writer->state = WRITER_STATE_STARTATTRIBUTE; - return S_OK; + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (writer->state != WRITER_STATE_STARTELEMENT) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } + + if ((hr = write_add_attribute( writer, prefix, localname, ns, single )) == S_OK) + writer->state = WRITER_STATE_STARTATTRIBUTE; + + LeaveCriticalSection( &writer->cs ); + return hr; } /* flush current start element if necessary */ @@ -937,12 +1078,25 @@ HRESULT WINAPI WsWriteStartCData( WS_XML_WRITER *handle, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer) return E_INVALIDARG; - return write_cdata_node( writer ); + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + hr = write_cdata_node( writer ); + + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_endcdata( struct writer *writer ) @@ -968,14 +1122,31 @@ HRESULT WINAPI WsWriteEndCData( WS_XML_WRITER *handle, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer) return E_INVALIDARG; - if (writer->state != WRITER_STATE_TEXT) return WS_E_INVALID_OPERATION; - return write_endcdata_node( writer ); + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (writer->state != WRITER_STATE_TEXT) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = write_endcdata_node( writer ); + + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_add_element_node( struct writer *writer, const WS_XML_STRING *prefix, @@ -1042,13 +1213,26 @@ WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr; TRACE( "%p %s %s %s %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname), debugstr_xmlstr(ns), error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer || !localname || !ns) return E_INVALIDARG; - return write_element_node( writer, prefix, localname, ns ); + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + hr = write_element_node( writer, prefix, localname, ns ); + + LeaveCriticalSection( &writer->cs ); + return hr; } static ULONG format_bool( const BOOL *ptr, unsigned char *buf ) @@ -1479,13 +1663,25 @@ HRESULT WINAPI WsWriteText( WS_XML_WRITER *handle, const WS_XML_TEXT *text, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr; TRACE( "%p %p %p\n", handle, text, error ); if (!writer || !text) return E_INVALIDARG; - if (writer->state == WRITER_STATE_STARTATTRIBUTE) return write_set_attribute_value( writer, text ); - return write_text_node( writer, text ); + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (writer->state == WRITER_STATE_STARTATTRIBUTE) hr = write_set_attribute_value( writer, text ); + else hr = write_text_node( writer, text ); + + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping, const WS_XML_TEXT *text ) @@ -2211,14 +2407,31 @@ if (!writer || !desc || !desc->attributeLocalName || !desc->attributeNs || !value) return E_INVALIDARG; - if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (writer->state != WRITER_STATE_STARTELEMENT) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } - if ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs, - FALSE )) != S_OK) return hr; + if ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs, FALSE )) != S_OK) + { + LeaveCriticalSection( &writer->cs ); + return hr; + } writer->state = WRITER_STATE_STARTATTRIBUTE; - return write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription, - option, value, size ); + hr = write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription, option, value, size ); + + LeaveCriticalSection( &writer->cs ); + return hr; } /************************************************************************** @@ -2237,12 +2450,24 @@ if (!writer || !desc || !desc->elementLocalName || !desc->elementNs || !value) return E_INVALIDARG; - if ((hr = write_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK) return hr; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if ((hr = write_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK) goto done; if ((hr = write_type( writer, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription, - option, value, size )) != S_OK) return hr; + option, value, size )) != S_OK) goto done; + + hr = write_endelement_node( writer ); - return write_endelement_node( writer ); +done: + LeaveCriticalSection( &writer->cs ); + return hr; } /************************************************************************** @@ -2261,17 +2486,25 @@ if (!writer || !value) return E_INVALIDARG; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + switch (mapping) { case WS_ATTRIBUTE_TYPE_MAPPING: - if (writer->state != WRITER_STATE_STARTATTRIBUTE) return WS_E_INVALID_FORMAT; - hr = write_type( writer, mapping, type, desc, option, value, size ); + if (writer->state != WRITER_STATE_STARTATTRIBUTE) hr = WS_E_INVALID_FORMAT; + else hr = write_type( writer, mapping, type, desc, option, value, size ); break; case WS_ELEMENT_TYPE_MAPPING: case WS_ELEMENT_CONTENT_TYPE_MAPPING: - if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_FORMAT; - hr = write_type( writer, mapping, type, desc, option, value, size ); + if (writer->state != WRITER_STATE_STARTELEMENT) hr = WS_E_INVALID_FORMAT; + else hr = write_type( writer, mapping, type, desc, option, value, size ); break; case WS_ANY_ELEMENT_TYPE_MAPPING: @@ -2280,9 +2513,10 @@ default: FIXME( "mapping %u not implemented\n", mapping ); - return E_NOTIMPL; + hr = E_NOTIMPL; } + LeaveCriticalSection( &writer->cs ); return hr; } @@ -2319,6 +2553,7 @@ { struct writer *writer = (struct writer *)handle; WS_TYPE_MAPPING mapping; + HRESULT hr = S_OK; WS_TYPE type; TRACE( "%p %u %p %u %p\n", handle, value_type, value, size, error ); @@ -2326,6 +2561,14 @@ if (!writer || !value || (type = map_value_type( value_type )) == ~0u) return E_INVALIDARG; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + switch (writer->state) { case WRITER_STATE_STARTATTRIBUTE: @@ -2337,10 +2580,13 @@ break; default: - return WS_E_INVALID_FORMAT; + hr = WS_E_INVALID_FORMAT; } - return write_type( writer, mapping, type, NULL, WS_WRITE_REQUIRED_VALUE, value, size ); + if (hr == S_OK) hr = write_type( writer, mapping, type, NULL, WS_WRITE_REQUIRED_VALUE, value, size ); + + LeaveCriticalSection( &writer->cs ); + return hr; } /************************************************************************** @@ -2353,29 +2599,53 @@ struct writer *writer = (struct writer *)handle; WS_TYPE type; ULONG type_size, i; - HRESULT hr; + HRESULT hr = S_OK; TRACE( "%p %s %s %u %p %u %u %u %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), value_type, array, size, offset, count, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer) return E_INVALIDARG; - if (!writer->output_type) return WS_E_INVALID_OPERATION; - if (!localname || !ns || (type = map_value_type( value_type )) == ~0u) return E_INVALIDARG; + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (!writer->output_type) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } + + if (!localname || !ns || (type = map_value_type( value_type )) == ~0u) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } type_size = get_type_size( type, NULL ); - if (size % type_size || (offset + count) * type_size > size || (count && !array)) return E_INVALIDARG; + if (size % type_size || (offset + count) * type_size > size || (count && !array)) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } for (i = offset; i < count; i++) { const char *ptr = (const char *)array + (offset + i) * type_size; - if ((hr = write_element_node( writer, NULL, localname, ns )) != S_OK) return hr; + if ((hr = write_element_node( writer, NULL, localname, ns )) != S_OK) goto done; if ((hr = write_type( writer, WS_ELEMENT_TYPE_MAPPING, type, NULL, WS_WRITE_REQUIRED_POINTER, - &ptr, sizeof(ptr) )) != S_OK) return hr; - if ((hr = write_endelement_node( writer )) != S_OK) return hr; + &ptr, sizeof(ptr) )) != S_OK) goto done; + if ((hr = write_endelement_node( writer )) != S_OK) goto done; } - return S_OK; +done: + LeaveCriticalSection( &writer->cs ); + return hr; } /************************************************************************** @@ -2392,10 +2662,21 @@ if (!writer || !xmlbuf) return E_INVALIDARG; - if ((hr = write_flush( writer )) != S_OK) return hr; - if ((hr = write_grow_buffer( writer, xmlbuf->size )) != S_OK) return hr; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if ((hr = write_flush( writer )) != S_OK) goto done; + if ((hr = write_grow_buffer( writer, xmlbuf->size )) != S_OK) goto done; write_bytes( writer, xmlbuf->ptr, xmlbuf->size ); - return S_OK; + +done: + LeaveCriticalSection( &writer->cs ); + return hr; } /************************************************************************** @@ -2408,7 +2689,7 @@ { struct writer *writer = (struct writer *)handle; struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer; - HRESULT hr; + HRESULT hr = S_OK; char *buf; ULONG i; @@ -2424,18 +2705,32 @@ return E_NOTIMPL; } + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + for (i = 0; i < count; i++) { hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; } - if (!(buf = ws_alloc( heap, xmlbuf->size ))) return WS_E_QUOTA_EXCEEDED; - memcpy( buf, xmlbuf->ptr, xmlbuf->size ); - *bytes = buf; - *size = xmlbuf->size; - return S_OK; + if (!(buf = ws_alloc( heap, xmlbuf->size ))) hr = WS_E_QUOTA_EXCEEDED; + else + { + memcpy( buf, xmlbuf->ptr, xmlbuf->size ); + *bytes = buf; + *size = xmlbuf->size; + } + +done: + LeaveCriticalSection( &writer->cs ); + return hr; } /************************************************************************** @@ -2445,16 +2740,33 @@ const WS_XML_STRING *ns, BOOL single, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr = S_OK; TRACE( "%p %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(ns), single, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer || !ns) return E_INVALIDARG; - if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION; - if (namespace_in_scope( &writer->current->hdr, prefix, ns )) return S_OK; - return write_add_namespace_attribute( writer, prefix, ns, single ); + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (writer->state != WRITER_STATE_STARTELEMENT) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } + + if (!namespace_in_scope( &writer->current->hdr, prefix, ns )) + hr = write_add_namespace_attribute( writer, prefix, ns, single ); + + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_move_to( struct writer *writer, WS_MOVE_TO move, BOOL *found ) @@ -2534,14 +2846,31 @@ HRESULT WINAPI WsMoveWriter( WS_XML_WRITER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr; TRACE( "%p %u %p %p\n", handle, move, found, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer) return E_INVALIDARG; - if (!writer->output_type) return WS_E_INVALID_OPERATION; - return write_move_to( writer, move, found ); + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (!writer->output_type) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = write_move_to( writer, move, found ); + + LeaveCriticalSection( &writer->cs ); + return hr; } /************************************************************************** @@ -2555,10 +2884,25 @@ if (error) FIXME( "ignoring error parameter\n" ); if (!writer || !pos) return E_INVALIDARG; - if (!writer->output_type) return WS_E_INVALID_OPERATION; + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (!writer->output_type) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } pos->buffer = (WS_XML_BUFFER *)writer->output_buf; pos->node = writer->current; + + LeaveCriticalSection( &writer->cs ); return S_OK; } @@ -2572,10 +2916,25 @@ TRACE( "%p %p %p\n", handle, pos, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!writer || !pos || (struct xmlbuf *)pos->buffer != writer->output_buf) return E_INVALIDARG; - if (!writer->output_type) return WS_E_INVALID_OPERATION; + if (!writer || !pos) return E_INVALIDARG; + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC || (struct xmlbuf *)pos->buffer != writer->output_buf) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (!writer->output_type) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } writer->current = pos->node; + + LeaveCriticalSection( &writer->cs ); return S_OK; } @@ -2683,14 +3042,31 @@ HRESULT WINAPI WsWriteNode( WS_XML_WRITER *handle, const WS_XML_NODE *node, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; + HRESULT hr; TRACE( "%p %p %p\n", handle, node, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer || !node) return E_INVALIDARG; - if (!writer->output_type) return WS_E_INVALID_OPERATION; - return write_node( writer, node ); + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (!writer->output_type) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = write_node( writer, node ); + + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_tree_node( struct writer *writer ) @@ -2788,23 +3164,39 @@ HRESULT WINAPI WsCopyNode( WS_XML_WRITER *handle, WS_XML_READER *reader, WS_ERROR *error ) { struct writer *writer = (struct writer *)handle; - struct node *parent, *current = writer->current, *node = NULL; + struct node *parent, *current, *node = NULL; HRESULT hr; TRACE( "%p %p %p\n", handle, reader, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!writer) return E_INVALIDARG; - if (!(parent = find_parent( writer ))) return WS_E_INVALID_FORMAT; - if ((hr = copy_node( reader, &node )) != S_OK) return hr; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if (!(parent = find_parent( writer ))) + { + LeaveCriticalSection( &writer->cs ); + return WS_E_INVALID_FORMAT; + } + + if ((hr = copy_node( reader, &node )) != S_OK) goto done; + current = writer->current; write_insert_node( writer, parent, node ); write_rewind( writer ); - if ((hr = write_tree( writer )) != S_OK) return hr; - + if ((hr = write_tree( writer )) != S_OK) goto done; writer->current = current; - return S_OK; + +done: + LeaveCriticalSection( &writer->cs ); + return hr; } static HRESULT write_param( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const void *value ) @@ -2842,7 +3234,15 @@ if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG; - if ((hr = write_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK) return hr; + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + if ((hr = write_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK) goto done; for (i = 0; i < count; i++) { @@ -2850,20 +3250,25 @@ if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES) { FIXME( "messages type not supported\n" ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } - if ((hr = get_param_desc( desc_struct, params[i].inputMessageIndex, &desc_field )) != S_OK) return hr; + if ((hr = get_param_desc( desc_struct, params[i].inputMessageIndex, &desc_field )) != S_OK) goto done; if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL) { - if ((hr = write_param( writer, desc_field, args[i] )) != S_OK) return hr; + if ((hr = write_param( writer, desc_field, args[i] )) != S_OK) goto done; } else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY) { const void *ptr = *(const void **)args[i]; ULONG len = get_array_len( params, count, params[i].inputMessageIndex, args ); - if ((hr = write_param_array( writer, desc_field, ptr, len )) != S_OK) return hr; + if ((hr = write_param_array( writer, desc_field, ptr, len )) != S_OK) goto done; } } - return write_endelement_node( writer ); + hr = write_endelement_node( writer ); + +done: + LeaveCriticalSection( &writer->cs ); + return hr; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/arb_program_shader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/arb_program_shader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/arb_program_shader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/arb_program_shader.c 2017-03-21 14:02:57.000000000 +0000 @@ -3809,7 +3809,8 @@ } /* Base Shader Body */ - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; if(args->super.srgb_correction) { arbfp_add_sRGB_correction(buffer, fragcolor, srgbtmp[0], srgbtmp[1], srgbtmp[2], srgbtmp[3], @@ -4222,7 +4223,8 @@ /* The shader starts with the main function */ priv_ctx.in_main_func = TRUE; /* Base Shader Body */ - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return -1; if (!priv_ctx.footer_written) vshader_add_footer(&priv_ctx, shader_data, args, reg_maps, gl_info, buffer); @@ -5056,6 +5058,7 @@ /* WINED3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ NULL, /* WINED3DSIH_DCL_HS_MAX_TESSFACTOR */ NULL, /* WINED3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER */ NULL, + /* WINED3DSIH_DCL_INDEX_RANGE */ NULL, /* WINED3DSIH_DCL_INDEXABLE_TEMP */ NULL, /* WINED3DSIH_DCL_INPUT */ NULL, /* WINED3DSIH_DCL_INPUT_CONTROL_POINT_COUNT */ NULL, @@ -5244,6 +5247,7 @@ /* WINED3DSIH_ULT */ NULL, /* WINED3DSIH_UMAX */ NULL, /* WINED3DSIH_UMIN */ NULL, + /* WINED3DSIH_UMUL */ NULL, /* WINED3DSIH_USHR */ NULL, /* WINED3DSIH_UTOF */ NULL, /* WINED3DSIH_XOR */ NULL, @@ -5791,7 +5795,7 @@ /* TODO: Implement WINED3DTEXOPCAPS_PREMODULATE */ caps->MaxTextureBlendStages = MAX_TEXTURES; - caps->MaxSimultaneousTextures = min(gl_info->limits.fragment_samplers, MAX_TEXTURES); + caps->MaxSimultaneousTextures = min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_TEXTURES); } static DWORD arbfp_get_emul_mask(const struct wined3d_gl_info *gl_info) @@ -7785,21 +7789,15 @@ } } -static void arbfp_blit_surface(struct wined3d_device *device, enum wined3d_blit_op op, DWORD filter, - struct wined3d_surface *src_surface, const RECT *src_rect_in, - struct wined3d_surface *dst_surface, const RECT *dst_rect_in, - const struct wined3d_color_key *color_key) +static void arbfp_blit_surface(struct wined3d_device *device, enum wined3d_blit_op op, struct wined3d_context *context, + struct wined3d_surface *src_surface, const RECT *src_rect, + struct wined3d_surface *dst_surface, const RECT *dst_rect, + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) { - unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); struct wined3d_texture *src_texture = src_surface->container; struct wined3d_texture *dst_texture = dst_surface->container; - struct wined3d_context *context; - RECT src_rect = *src_rect_in; - RECT dst_rect = *dst_rect_in; struct wined3d_color_key alpha_test_key; - - /* Activate the destination context, set it up for blitting */ - context = context_acquire(device, dst_texture, dst_sub_resource_idx); + RECT s, d; /* Now load the surface */ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO @@ -7815,8 +7813,10 @@ * rectangle instead. */ surface_load_fb_texture(src_surface, FALSE, context); - src_rect.top = wined3d_texture_get_level_height(src_texture, src_surface->texture_level) - src_rect.top; - src_rect.bottom = wined3d_texture_get_level_height(src_texture, src_surface->texture_level) - src_rect.bottom; + s = *src_rect; + s.top = wined3d_texture_get_level_height(src_texture, src_surface->texture_level) - s.top; + s.bottom = wined3d_texture_get_level_height(src_texture, src_surface->texture_level) - s.bottom; + src_rect = &s; } else wined3d_texture_load(src_texture, context, FALSE); @@ -7824,7 +7824,11 @@ context_apply_blit_state(context, device); if (!wined3d_resource_is_offscreen(&dst_texture->resource)) - surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect); + { + d = *dst_rect; + surface_translate_drawable_coords(dst_surface, context->win_handle, &d); + dst_rect = &d; + } if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST) { @@ -7837,7 +7841,7 @@ arbfp_blit_set(device->blit_priv, context, src_surface, color_key); /* Draw a textured quad */ - draw_textured_quad(src_surface, context, &src_rect, &dst_rect, filter); + draw_textured_quad(src_surface, context, src_rect, dst_rect, filter); /* Leave the opengl state valid for blitting */ arbfp_blit_unset(context->gl_info); @@ -7845,11 +7849,6 @@ if (wined3d_settings.strict_draw_ordering || (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture))) context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ - - context_release(context); - - wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, dst_texture->resource.draw_binding); - wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~dst_texture->resource.draw_binding); } static HRESULT arbfp_blit_color_fill(struct wined3d_device *device, struct wined3d_rendertarget_view *view, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/ati_fragment_shader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/ati_fragment_shader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/ati_fragment_shader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/ati_fragment_shader.c 2017-03-21 14:02:57.000000000 +0000 @@ -53,7 +53,7 @@ struct ffp_frag_desc parent; GLuint shader; unsigned int num_textures_used; - enum atifs_constant_value constants[8]; + enum atifs_constant_value constants[MAX_TEXTURES]; }; struct atifs_private_data @@ -938,7 +938,7 @@ constants[ATIFS_CONST_TFACTOR - GL_CON_0_ATI] = ATIFS_CONSTANT_TFACTOR; /* Assign unused constants to avoid reloading due to unused <-> bump matrix switches. */ - for (stage = 0; stage < 8; ++stage) + for (stage = 0; stage < MAX_TEXTURES; ++stage) { if (constants[stage] == ATIFS_CONSTANT_UNUSED) constants[stage] = ATIFS_CONSTANT_BUMP; @@ -1024,7 +1024,8 @@ gen_ffp_frag_op(context, state, &settings, TRUE); desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings); - if(!desc) { + if (!desc) + { struct atifs_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*new_desc)); if (!new_desc) { @@ -1036,13 +1037,13 @@ { if (settings.op[i].cop == WINED3D_TOP_DISABLE) break; - new_desc->num_textures_used = i + 1; + ++new_desc->num_textures_used; } new_desc->parent.settings = settings; new_desc->shader = gen_ati_shader(settings.op, gl_info, new_desc->constants); add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent); - TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc); + TRACE("Allocated fixed function replacement shader descriptor %p.\n", new_desc); desc = new_desc; } @@ -1062,7 +1063,7 @@ GL_EXTCALL(glBindFragmentShaderATI(desc->shader)); ctx_priv->last_shader = desc; - for (i = 0; i < 8; i++) + for (i = 0; i < MAX_TEXTURES; i++) { if (last_shader && last_shader->constants[i] == desc->constants[i]) continue; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/context.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/context.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/context.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/context.c 2017-03-21 14:02:57.000000000 +0000 @@ -1525,6 +1525,9 @@ if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_textures.tex_cube); + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) + gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, device->dummy_textures.tex_cube_array); + if (gl_info->supported[EXT_TEXTURE_ARRAY]) gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_ARRAY, device->dummy_textures.tex_2d_array); @@ -1632,7 +1635,7 @@ HGLRC ctx, share_ctx; DWORD target_usage; int pixel_format; - unsigned int s; + unsigned int i; DWORD state; HDC hdc = 0; @@ -1686,20 +1689,40 @@ goto out; } - /* Initialize the texture unit mapping to a 1:1 mapping */ - for (s = 0; s < MAX_COMBINED_SAMPLERS; ++s) + for (i = 0; i < ARRAY_SIZE(ret->tex_unit_map); ++i) + ret->tex_unit_map[i] = WINED3D_UNMAPPED_STAGE; + for (i = 0; i < ARRAY_SIZE(ret->rev_tex_unit_map); ++i) + ret->rev_tex_unit_map[i] = WINED3D_UNMAPPED_STAGE; + if (gl_info->limits.graphics_samplers >= MAX_COMBINED_SAMPLERS) { - if (s < gl_info->limits.graphics_samplers) + /* Initialize the texture unit mapping to a 1:1 mapping. */ + unsigned int base, count; + + wined3d_gl_limits_get_texture_unit_range(&gl_info->limits, WINED3D_SHADER_TYPE_PIXEL, &base, &count); + if (base + MAX_FRAGMENT_SAMPLERS > ARRAY_SIZE(ret->rev_tex_unit_map)) { - ret->tex_unit_map[s] = s; - ret->rev_tex_unit_map[s] = s; + ERR("Unexpected texture unit base index %u.\n", base); + goto out; } - else + for (i = 0; i < min(count, MAX_FRAGMENT_SAMPLERS); ++i) { - ret->tex_unit_map[s] = WINED3D_UNMAPPED_STAGE; - ret->rev_tex_unit_map[s] = WINED3D_UNMAPPED_STAGE; + ret->tex_unit_map[i] = base + i; + ret->rev_tex_unit_map[base + i] = i; + } + + wined3d_gl_limits_get_texture_unit_range(&gl_info->limits, WINED3D_SHADER_TYPE_VERTEX, &base, &count); + if (base + MAX_VERTEX_SAMPLERS > ARRAY_SIZE(ret->rev_tex_unit_map)) + { + ERR("Unexpected texture unit base index %u.\n", base); + goto out; + } + for (i = 0; i < min(count, MAX_VERTEX_SAMPLERS); ++i) + { + ret->tex_unit_map[MAX_FRAGMENT_SAMPLERS + i] = base + i; + ret->rev_tex_unit_map[base + i] = MAX_FRAGMENT_SAMPLERS + i; } } + if (!(ret->texture_type = wined3d_calloc(gl_info->limits.combined_samplers, sizeof(*ret->texture_type)))) goto out; @@ -1915,11 +1938,11 @@ /* Set up the previous texture input for all shader units. This applies to bump mapping, and in d3d * the previous texture where to source the offset from is always unit - 1. */ - for (s = 1; s < gl_info->limits.textures; ++s) + for (i = 1; i < gl_info->limits.textures; ++i) { - context_active_texture(ret, gl_info, s); + context_active_texture(ret, gl_info, i); gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, - GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + s - 1); + GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + i - 1); checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ..."); } } @@ -1945,9 +1968,9 @@ if (gl_info->supported[ARB_POINT_SPRITE]) { - for (s = 0; s < gl_info->limits.textures; ++s) + for (i = 0; i < gl_info->limits.textures; ++i) { - context_active_texture(ret, gl_info, s); + context_active_texture(ret, gl_info, i); gl_info->gl_ops.gl.p_glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)"); } @@ -1966,13 +1989,19 @@ if (gl_info->supported[ARB_ES3_COMPATIBILITY]) { gl_info->gl_ops.gl.p_glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); - checkGLcall("Enable GL_PRIMITIVE_RESTART_FIXED_INDEX"); + checkGLcall("enable GL_PRIMITIVE_RESTART_FIXED_INDEX"); } else { FIXME("OpenGL implementation does not support GL_PRIMITIVE_RESTART_FIXED_INDEX.\n"); } } + if (!(d3d_info->wined3d_creation_flags & WINED3D_LEGACY_CUBEMAP_FILTERING) + && gl_info->supported[ARB_SEAMLESS_CUBE_MAP]) + { + gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + checkGLcall("enable seamless cube map filtering"); + } if (gl_info->supported[ARB_CLIP_CONTROL]) GL_EXTCALL(glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT)); device->shader_backend->shader_init_context_state(ret); @@ -2052,6 +2081,43 @@ if (destroy) HeapFree(GetProcessHeap(), 0, context); } +const DWORD *context_get_tex_unit_mapping(const struct wined3d_context *context, + const struct wined3d_shader_version *shader_version, unsigned int *base, unsigned int *count) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (!shader_version) + { + *base = 0; + *count = MAX_TEXTURES; + return context->tex_unit_map; + } + + if (shader_version->major >= 4) + { + wined3d_gl_limits_get_texture_unit_range(&gl_info->limits, shader_version->type, base, count); + return NULL; + } + + switch (shader_version->type) + { + case WINED3D_SHADER_TYPE_PIXEL: + *base = 0; + *count = MAX_FRAGMENT_SAMPLERS; + break; + case WINED3D_SHADER_TYPE_VERTEX: + *base = MAX_FRAGMENT_SAMPLERS; + *count = MAX_VERTEX_SAMPLERS; + break; + default: + ERR("Unhandled shader type %#x.\n", shader_version->type); + *base = 0; + *count = 0; + } + + return context->tex_unit_map; +} + /* Context activation is done by the caller. */ static void set_blit_dimension(const struct wined3d_gl_info *gl_info, UINT width, UINT height) { @@ -2419,7 +2485,7 @@ checkGLcall("glBindTexture"); break; case GL_TEXTURE_CUBE_MAP_ARRAY: - gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); + gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, device->dummy_textures.tex_cube_array); checkGLcall("glBindTexture"); break; case GL_TEXTURE_3D: @@ -3045,12 +3111,13 @@ } /* Context activation is done by the caller. */ -void context_stream_info_from_declaration(struct wined3d_context *context, - const struct wined3d_state *state, struct wined3d_stream_info *stream_info) +void wined3d_stream_info_from_declaration(struct wined3d_stream_info *stream_info, + const struct wined3d_state *state, const struct wined3d_gl_info *gl_info, + const struct wined3d_d3d_info *d3d_info) { /* We need to deal with frequency data! */ struct wined3d_vertex_declaration *declaration = state->vertex_declaration; - BOOL generic_attributes = context->d3d_info->ffp_generic_attributes; + BOOL generic_attributes = d3d_info->ffp_generic_attributes; BOOL use_vshader = use_vs(state); unsigned int i; @@ -3142,7 +3209,7 @@ stream_info->elements[idx].divisor = 0; } - if (!context->gl_info->supported[ARB_VERTEX_ARRAY_BGRA] + if (!gl_info->supported[ARB_VERTEX_ARRAY_BGRA] && element->format->id == WINED3DFMT_B8G8R8A8_UNORM) { stream_info->swizzle_map |= 1u << idx; @@ -3162,7 +3229,7 @@ unsigned int i; WORD map; - context_stream_info_from_declaration(context, state, stream_info); + wined3d_stream_info_from_declaration(stream_info, state, gl_info, d3d_info); stream_info->all_vbo = 1; context->num_buffer_queries = 0; @@ -3313,10 +3380,7 @@ entry = &shader->reg_maps.sampler_map.entries[j]; if (!(view = state->shader_resource_view[i][entry->resource_idx])) - { - WARN("No resource view bound at index %u, %u.\n", i, entry->resource_idx); continue; - } if (view->resource->type == WINED3D_RTYPE_BUFFER) wined3d_buffer_load(buffer_from_resource(view->resource), context, state); @@ -3327,21 +3391,24 @@ } static void context_bind_shader_resources(struct wined3d_context *context, - const struct wined3d_state *state, enum wined3d_shader_type shader_type, - unsigned int base_idx, unsigned int count) + const struct wined3d_state *state, enum wined3d_shader_type shader_type) { + unsigned int bind_idx, shader_sampler_count, base, count, i; const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_device *device = context->device; struct wined3d_shader_sampler_map_entry *entry; struct wined3d_shader_resource_view *view; - unsigned int shader_sampler_count, i; const struct wined3d_shader *shader; struct wined3d_sampler *sampler; + const DWORD *tex_unit_map; GLuint sampler_name; if (!(shader = state->shader[shader_type])) return; + tex_unit_map = context_get_tex_unit_mapping(context, + &shader->reg_maps.shader_version, &base, &count); + shader_sampler_count = shader->reg_maps.sampler_map.count; if (shader_sampler_count > count) FIXME("Shader %p needs %u samplers, but only %u are supported.\n", @@ -3351,6 +3418,9 @@ for (i = 0; i < count; ++i) { entry = &shader->reg_maps.sampler_map.entries[i]; + bind_idx = base + entry->bind_idx; + if (tex_unit_map) + bind_idx = tex_unit_map[bind_idx]; if (!(view = state->shader_resource_view[shader_type][entry->resource_idx])) { @@ -3365,35 +3435,13 @@ else sampler_name = device->null_sampler; - context_active_texture(context, gl_info, base_idx + entry->bind_idx); - GL_EXTCALL(glBindSampler(base_idx + entry->bind_idx, sampler_name)); + context_active_texture(context, gl_info, bind_idx); + GL_EXTCALL(glBindSampler(bind_idx, sampler_name)); checkGLcall("glBindSampler"); wined3d_shader_resource_view_bind(view, context); } } -static void context_bind_graphics_shader_resources(struct wined3d_context *context, - const struct wined3d_state *state) -{ - unsigned int i; - - static const struct - { - enum wined3d_shader_type type; - unsigned int base_idx; - unsigned int count; - } - shader_types[] = - { - {WINED3D_SHADER_TYPE_PIXEL, 0, MAX_FRAGMENT_SAMPLERS}, - {WINED3D_SHADER_TYPE_VERTEX, MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS}, - }; - - for (i = 0; i < ARRAY_SIZE(shader_types); ++i) - context_bind_shader_resources(context, state, shader_types[i].type, - shader_types[i].base_idx, shader_types[i].count); -} - static void context_load_unordered_access_resources(struct wined3d_context *context, const struct wined3d_shader *shader, struct wined3d_unordered_access_view * const *views) { @@ -3409,9 +3457,6 @@ for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i) { - if (!shader->reg_maps.uav_resource_info[i].type) - continue; - if (!(view = views[i])) continue; @@ -3446,12 +3491,10 @@ for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i) { - if (!shader->reg_maps.uav_resource_info[i].type) - continue; - if (!(view = views[i])) { - WARN("No unordered access view bound at index %u.\n", i); + if (shader->reg_maps.uav_resource_info[i].type) + WARN("No unordered access view bound at index %u.\n", i); GL_EXTCALL(glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R8)); continue; } @@ -3510,7 +3553,7 @@ context_load_unordered_access_resources(context, state->shader[WINED3D_SHADER_TYPE_PIXEL], state->unordered_access_view[WINED3D_PIPELINE_GRAPHICS]); /* TODO: Right now the dependency on the vertex shader is necessary - * since context_stream_info_from_declaration depends on the reg_maps of + * since wined3d_stream_info_from_declaration() depends on the reg_maps of * the current VS but maybe it's possible to relax the coupling in some * situations at least. */ if (isStateDirty(context, STATE_VDECL) || isStateDirty(context, STATE_STREAMSRC) @@ -3561,7 +3604,8 @@ if (context->update_shader_resource_bindings) { - context_bind_graphics_shader_resources(context, state); + for (i = 0; i < WINED3D_SHADER_TYPE_GRAPHICS_COUNT; ++i) + context_bind_shader_resources(context, state, i); context->update_shader_resource_bindings = 0; if (gl_info->limits.combined_samplers == gl_info->limits.graphics_samplers) context->update_compute_shader_resource_bindings = 1; @@ -3616,10 +3660,7 @@ if (context->update_compute_shader_resource_bindings) { - unsigned int base_idx, count; - wined3d_gl_limits_get_texture_unit_range(&gl_info->limits, - WINED3D_SHADER_TYPE_COMPUTE, &base_idx, &count); - context_bind_shader_resources(context, state, WINED3D_SHADER_TYPE_COMPUTE, base_idx, count); + context_bind_shader_resources(context, state, WINED3D_SHADER_TYPE_COMPUTE); context->update_compute_shader_resource_bindings = 0; if (gl_info->limits.combined_samplers == gl_info->limits.graphics_samplers) context->update_shader_resource_bindings = 1; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/cs.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/cs.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/cs.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/cs.c 2017-03-21 14:02:57.000000000 +0000 @@ -63,6 +63,8 @@ WINED3D_CS_OP_UNLOAD_RESOURCE, WINED3D_CS_OP_MAP, WINED3D_CS_OP_UNMAP, + WINED3D_CS_OP_BLT_SUB_RESOURCE, + WINED3D_CS_OP_UPDATE_SUB_RESOURCE, }; struct wined3d_cs_present @@ -344,6 +346,29 @@ HRESULT *hr; }; +struct wined3d_cs_blt_sub_resource +{ + enum wined3d_cs_op opcode; + struct wined3d_resource *dst_resource; + unsigned int dst_sub_resource_idx; + struct wined3d_box dst_box; + struct wined3d_resource *src_resource; + unsigned int src_sub_resource_idx; + struct wined3d_box src_box; + DWORD flags; + struct wined3d_blt_fx fx; + enum wined3d_texture_filter_type filter; +}; + +struct wined3d_cs_update_sub_resource +{ + enum wined3d_cs_op opcode; + struct wined3d_resource *resource; + unsigned int sub_resource_idx; + struct wined3d_box box; + struct wined3d_sub_resource_data data; +}; + static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_present *op = data; @@ -1647,6 +1672,153 @@ return hr; } +static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_blt_sub_resource *op = data; + + if (op->dst_resource->type == WINED3D_RTYPE_BUFFER) + { + if (FAILED(wined3d_buffer_copy(buffer_from_resource(op->dst_resource), op->dst_box.left, + buffer_from_resource(op->src_resource), op->src_box.left, + op->src_box.right - op->src_box.left))) + ERR("Failed to copy buffer.\n"); + } + else if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_2D) + { + struct wined3d_surface *dst_surface, *src_surface = NULL; + struct wined3d_texture *dst_texture, *src_texture; + RECT dst_rect, src_rect; + + dst_texture = texture_from_resource(op->dst_resource); + dst_surface = dst_texture->sub_resources[op->dst_sub_resource_idx].u.surface; + if (op->src_resource) + { + src_texture = texture_from_resource(op->src_resource); + src_surface = src_texture->sub_resources[op->src_sub_resource_idx].u.surface; + } + SetRect(&dst_rect, op->dst_box.left, op->dst_box.top, op->dst_box.right, op->dst_box.bottom); + SetRect(&src_rect, op->src_box.left, op->src_box.top, op->src_box.right, op->src_box.bottom); + + if (FAILED(wined3d_surface_blt(dst_surface, &dst_rect, src_surface, + &src_rect, op->flags, &op->fx, op->filter))) + FIXME("Blit failed.\n"); + } + else + { + FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(op->dst_resource->type)); + } + + if (op->src_resource) + wined3d_resource_release(op->src_resource); + wined3d_resource_release(op->dst_resource); +} + +void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *dst_resource, + unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, struct wined3d_resource *src_resource, + unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, DWORD flags, + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) +{ + struct wined3d_cs_blt_sub_resource *op; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_BLT_SUB_RESOURCE; + op->dst_resource = dst_resource; + op->dst_sub_resource_idx = dst_sub_resource_idx; + op->dst_box = *dst_box; + op->src_resource = src_resource; + op->src_sub_resource_idx = src_sub_resource_idx; + op->src_box = *src_box; + op->flags = flags; + if (fx) + op->fx = *fx; + op->filter = filter; + + wined3d_resource_acquire(dst_resource); + if (src_resource) + wined3d_resource_acquire(src_resource); + + cs->ops->submit(cs); +} + +static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_update_sub_resource *op = data; + const struct wined3d_box *box = &op->box; + unsigned int width, height, depth, level; + struct wined3d_const_bo_address addr; + struct wined3d_context *context; + struct wined3d_texture *texture; + + if (op->resource->type == WINED3D_RTYPE_BUFFER) + { + struct wined3d_buffer *buffer = buffer_from_resource(op->resource); + + context = context_acquire(op->resource->device, NULL, 0); + if (!wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER)) + { + ERR("Failed to load buffer location.\n"); + context_release(context); + goto done; + } + + wined3d_buffer_upload_data(buffer, context, box, op->data.data); + wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER); + context_release(context); + goto done; + } + + texture = wined3d_texture_from_resource(op->resource); + + level = op->sub_resource_idx % texture->level_count; + width = wined3d_texture_get_level_width(texture, level); + height = wined3d_texture_get_level_height(texture, level); + depth = wined3d_texture_get_level_depth(texture, level); + + addr.buffer_object = 0; + addr.addr = op->data.data; + + context = context_acquire(op->resource->device, NULL, 0); + + /* Only load the sub-resource for partial updates. */ + if (!box->left && !box->top && !box->front + && box->right == width && box->bottom == height && box->back == depth) + wined3d_texture_prepare_texture(texture, context, FALSE); + else + wined3d_texture_load_location(texture, op->sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_bind_and_dirtify(texture, context, FALSE); + + wined3d_texture_upload_data(texture, op->sub_resource_idx, context, + box, &addr, op->data.row_pitch, op->data.slice_pitch); + + context_release(context); + + wined3d_texture_validate_location(texture, op->sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); + +done: + wined3d_resource_release(op->resource); +} + +void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, + unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, + unsigned int slice_pitch) +{ + struct wined3d_cs_update_sub_resource *op; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; + op->resource = resource; + op->sub_resource_idx = sub_resource_idx; + op->box = *box; + op->data.row_pitch = row_pitch; + op->data.slice_pitch = slice_pitch; + op->data.data = data; + + wined3d_resource_acquire(resource); + + cs->ops->submit(cs); +} + static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, @@ -1686,6 +1858,8 @@ /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource, /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, + /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource, + /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, }; static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/device.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/device.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/device.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/device.c 2017-03-21 14:02:57.000000000 +0000 @@ -684,6 +684,24 @@ } } + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) + { + DWORD cube_array_data[6]; + + gl_info->gl_ops.gl.p_glGenTextures(1, &device->dummy_textures.tex_cube_array); + checkGLcall("glGenTextures"); + TRACE("Dummy cube array texture given name %u.\n", device->dummy_textures.tex_cube_array); + + gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, device->dummy_textures.tex_cube_array); + checkGLcall("glBindTexture"); + + for (i = 0; i < ARRAY_SIZE(cube_array_data); ++i) + cube_array_data[i] = color; + GL_EXTCALL(glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA8, 1, 1, 6, 0, + GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, cube_array_data)); + checkGLcall("glTexImage3D"); + } + if (gl_info->supported[EXT_TEXTURE_ARRAY]) { gl_info->gl_ops.gl.p_glGenTextures(1, &device->dummy_textures.tex_2d_array); @@ -735,6 +753,9 @@ if (gl_info->supported[EXT_TEXTURE_ARRAY]) gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_2d_array); + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) + gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_cube_array); + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_cube); @@ -2156,17 +2177,23 @@ wined3d_device_set_constant_buffer(device, WINED3D_SHADER_TYPE_VERTEX, idx, buffer); } -struct wined3d_buffer * CDECL wined3d_device_get_vs_cb(const struct wined3d_device *device, UINT idx) +static struct wined3d_buffer *wined3d_device_get_constant_buffer(const struct wined3d_device *device, + enum wined3d_shader_type shader_type, unsigned int idx) { - TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_CONSTANT_BUFFERS) { WARN("Invalid constant buffer index %u.\n", idx); return NULL; } - return device->state.cb[WINED3D_SHADER_TYPE_VERTEX][idx]; + return device->state.cb[shader_type][idx]; +} + +struct wined3d_buffer * CDECL wined3d_device_get_vs_cb(const struct wined3d_device *device, UINT idx) +{ + TRACE("device %p, idx %u.\n", device, idx); + + return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_VERTEX, idx); } static void wined3d_device_set_shader_resource_view(struct wined3d_device *device, @@ -2201,18 +2228,24 @@ wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_VERTEX, idx, view); } -struct wined3d_shader_resource_view * CDECL wined3d_device_get_vs_resource_view(const struct wined3d_device *device, - UINT idx) +static struct wined3d_shader_resource_view *wined3d_device_get_shader_resource_view( + const struct wined3d_device *device, enum wined3d_shader_type shader_type, unsigned int idx) { - TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_SHADER_RESOURCE_VIEWS) { WARN("Invalid view index %u.\n", idx); return NULL; } - return device->state.shader_resource_view[WINED3D_SHADER_TYPE_VERTEX][idx]; + return device->state.shader_resource_view[shader_type][idx]; +} + +struct wined3d_shader_resource_view * CDECL wined3d_device_get_vs_resource_view(const struct wined3d_device *device, + UINT idx) +{ + TRACE("device %p, idx %u.\n", device, idx); + + return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_VERTEX, idx); } static void wined3d_device_set_sampler(struct wined3d_device *device, @@ -2246,17 +2279,23 @@ wined3d_device_set_sampler(device, WINED3D_SHADER_TYPE_VERTEX, idx, sampler); } -struct wined3d_sampler * CDECL wined3d_device_get_vs_sampler(const struct wined3d_device *device, UINT idx) +static struct wined3d_sampler *wined3d_device_get_sampler(const struct wined3d_device *device, + enum wined3d_shader_type shader_type, unsigned int idx) { - TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_SAMPLER_OBJECTS) { WARN("Invalid sampler index %u.\n", idx); return NULL; } - return device->state.sampler[WINED3D_SHADER_TYPE_VERTEX][idx]; + return device->state.sampler[shader_type][idx]; +} + +struct wined3d_sampler * CDECL wined3d_device_get_vs_sampler(const struct wined3d_device *device, UINT idx) +{ + TRACE("device %p, idx %u.\n", device, idx); + + return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_VERTEX, idx); } HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device, @@ -2441,13 +2480,7 @@ { TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_CONSTANT_BUFFERS) - { - WARN("Invalid constant buffer index %u.\n", idx); - return NULL; - } - - return device->state.cb[WINED3D_SHADER_TYPE_PIXEL][idx]; + return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_PIXEL, idx); } void CDECL wined3d_device_set_ps_resource_view(struct wined3d_device *device, @@ -2463,13 +2496,7 @@ { TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_SHADER_RESOURCE_VIEWS) - { - WARN("Invalid view index %u.\n", idx); - return NULL; - } - - return device->state.shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][idx]; + return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_PIXEL, idx); } void CDECL wined3d_device_set_ps_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler) @@ -2483,13 +2510,7 @@ { TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_SAMPLER_OBJECTS) - { - WARN("Invalid sampler index %u.\n", idx); - return NULL; - } - - return device->state.sampler[WINED3D_SHADER_TYPE_PIXEL][idx]; + return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_PIXEL, idx); } HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device, @@ -2670,13 +2691,7 @@ { TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_CONSTANT_BUFFERS) - { - WARN("Invalid constant buffer index %u.\n", idx); - return NULL; - } - - return device->state.cb[WINED3D_SHADER_TYPE_GEOMETRY][idx]; + return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_GEOMETRY, idx); } void CDECL wined3d_device_set_gs_resource_view(struct wined3d_device *device, @@ -2692,13 +2707,7 @@ { TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_SHADER_RESOURCE_VIEWS) - { - WARN("Invalid view index %u.\n", idx); - return NULL; - } - - return device->state.shader_resource_view[WINED3D_SHADER_TYPE_GEOMETRY][idx]; + return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_GEOMETRY, idx); } void CDECL wined3d_device_set_gs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler) @@ -2712,13 +2721,7 @@ { TRACE("device %p, idx %u.\n", device, idx); - if (idx >= MAX_SAMPLER_OBJECTS) - { - WARN("Invalid sampler index %u.\n", idx); - return NULL; - } - - return device->state.sampler[WINED3D_SHADER_TYPE_GEOMETRY][idx]; + return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_GEOMETRY, idx); } void CDECL wined3d_device_set_compute_shader(struct wined3d_device *device, struct wined3d_shader *shader) @@ -2738,6 +2741,13 @@ wined3d_shader_decref(prev); } +struct wined3d_shader * CDECL wined3d_device_get_compute_shader(const struct wined3d_device *device) +{ + TRACE("device %p.\n", device); + + return device->state.shader[WINED3D_SHADER_TYPE_COMPUTE]; +} + void CDECL wined3d_device_set_cs_cb(struct wined3d_device *device, unsigned int idx, struct wined3d_buffer *buffer) { TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer); @@ -2745,6 +2755,13 @@ wined3d_device_set_constant_buffer(device, WINED3D_SHADER_TYPE_COMPUTE, idx, buffer); } +struct wined3d_buffer * CDECL wined3d_device_get_cs_cb(const struct wined3d_device *device, unsigned int idx) +{ + TRACE("device %p, idx %u.\n", device, idx); + + return wined3d_device_get_constant_buffer(device, WINED3D_SHADER_TYPE_COMPUTE, idx); +} + void CDECL wined3d_device_set_cs_resource_view(struct wined3d_device *device, unsigned int idx, struct wined3d_shader_resource_view *view) { @@ -2753,6 +2770,14 @@ wined3d_device_set_shader_resource_view(device, WINED3D_SHADER_TYPE_COMPUTE, idx, view); } +struct wined3d_shader_resource_view * CDECL wined3d_device_get_cs_resource_view(const struct wined3d_device *device, + unsigned int idx) +{ + TRACE("device %p, idx %u.\n", device, idx); + + return wined3d_device_get_shader_resource_view(device, WINED3D_SHADER_TYPE_COMPUTE, idx); +} + void CDECL wined3d_device_set_cs_sampler(struct wined3d_device *device, unsigned int idx, struct wined3d_sampler *sampler) { @@ -2761,6 +2786,13 @@ wined3d_device_set_sampler(device, WINED3D_SHADER_TYPE_COMPUTE, idx, sampler); } +struct wined3d_sampler * CDECL wined3d_device_get_cs_sampler(const struct wined3d_device *device, unsigned int idx) +{ + TRACE("device %p, idx %u.\n", device, idx); + + return wined3d_device_get_sampler(device, WINED3D_SHADER_TYPE_COMPUTE, idx); +} + static void wined3d_device_set_pipeline_unordered_access_view(struct wined3d_device *device, enum wined3d_pipeline pipeline, unsigned int idx, struct wined3d_unordered_access_view *uav) { @@ -3079,8 +3111,8 @@ { struct wined3d_state *state = &device->state; struct wined3d_stream_info stream_info; - const struct wined3d_gl_info *gl_info; - struct wined3d_context *context; + struct wined3d_resource *resource; + struct wined3d_box box = {0}; struct wined3d_shader *vs; unsigned int i; HRESULT hr; @@ -3094,13 +3126,9 @@ if (declaration) FIXME("Output vertex declaration not implemented yet.\n"); - /* Need any context to write to the vbo. */ - context = context_acquire(device, NULL, 0); - gl_info = context->gl_info; - vs = state->shader[WINED3D_SHADER_TYPE_VERTEX]; state->shader[WINED3D_SHADER_TYPE_VERTEX] = NULL; - context_stream_info_from_declaration(context, state, &stream_info); + wined3d_stream_info_from_declaration(&stream_info, state, &device->adapter->gl_info, &device->adapter->d3d_info); state->shader[WINED3D_SHADER_TYPE_VERTEX] = vs; /* We can't convert FROM a VBO, and vertex buffers used to source into @@ -3111,29 +3139,33 @@ for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i) { struct wined3d_stream_info_element *e; - struct wined3d_buffer *buffer; + struct wined3d_map_desc map_desc; if (!(map & 1)) continue; e = &stream_info.elements[i]; - buffer = state->streams[e->stream_idx].buffer; + resource = &state->streams[e->stream_idx].buffer->resource; + box.left = src_start_idx * e->stride; + box.right = box.left + vertex_count * e->stride; + if (FAILED(wined3d_resource_map(resource, 0, &map_desc, &box, WINED3D_MAP_READONLY))) + ERR("Failed to map resource.\n"); e->data.buffer_object = 0; - e->data.addr += (ULONG_PTR)wined3d_buffer_load_sysmem(buffer, context); - if (buffer->buffer_object) - { - GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object)); - buffer->buffer_object = 0; - wined3d_buffer_invalidate_location(buffer, WINED3D_LOCATION_BUFFER); - } - if (e->data.addr) - e->data.addr += e->stride * src_start_idx; + e->data.addr += (ULONG_PTR)map_desc.data; } hr = process_vertices_strided(device, dst_idx, vertex_count, &stream_info, dst_buffer, flags, dst_fvf); - context_release(context); + for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i) + { + if (!(map & 1)) + continue; + + resource = &state->streams[stream_info.elements[i].stream_idx].buffer->resource; + if (FAILED(wined3d_resource_unmap(resource, 0))) + ERR("Failed to unmap resource.\n"); + } return hr; } @@ -3808,9 +3840,8 @@ struct wined3d_resource *dst_resource, struct wined3d_resource *src_resource) { struct wined3d_texture *dst_texture, *src_texture; - RECT dst_rect, src_rect; + struct wined3d_box box; unsigned int i, j; - HRESULT hr; TRACE("device %p, dst_resource %p, src_resource %p.\n", device, dst_resource, src_resource); @@ -3848,10 +3879,15 @@ if (dst_resource->type == WINED3D_RTYPE_BUFFER) { - if (FAILED(hr = wined3d_buffer_copy(buffer_from_resource(dst_resource), 0, - buffer_from_resource(src_resource), 0, - dst_resource->size))) - ERR("Failed to copy buffer, hr %#x.\n", hr); + box.left = 0; + box.top = 0; + box.right = src_resource->size; + box.bottom = 1; + box.front = 0; + box.back = 1; + + wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, 0, &box, + src_resource, 0, &box, 0, NULL, WINED3D_TEXF_POINT); return; } @@ -3875,19 +3911,19 @@ for (i = 0; i < dst_texture->level_count; ++i) { - SetRect(&dst_rect, 0, 0, - wined3d_texture_get_level_width(dst_texture, i), - wined3d_texture_get_level_height(dst_texture, i)); - SetRect(&src_rect, 0, 0, - wined3d_texture_get_level_width(src_texture, i), - wined3d_texture_get_level_height(dst_texture, i)); + box.left = 0; + box.top = 0; + box.right = wined3d_texture_get_level_width(dst_texture, i); + box.bottom = wined3d_texture_get_level_height(dst_texture, i); + box.front = 0; + box.back = wined3d_texture_get_level_depth(dst_texture, i); + for (j = 0; j < dst_texture->layer_count; ++j) { unsigned int idx = j * dst_texture->level_count + i; - if (FAILED(hr = wined3d_texture_blt(dst_texture, idx, &dst_rect, - src_texture, idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT))) - ERR("Failed to blit, sub-resource %u, hr %#x.\n", idx, hr); + wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, idx, &box, + src_resource, idx, &box, 0, NULL, WINED3D_TEXF_POINT); } } } @@ -3897,23 +3933,13 @@ unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) { - struct wined3d_texture *dst_texture, *src_texture; - RECT dst_rect, src_rect; - HRESULT hr; + struct wined3d_box dst_box, b; TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, " "src_resource %p, src_sub_resource_idx %u, src_box %s.\n", device, dst_resource, dst_sub_resource_idx, dst_x, dst_y, dst_z, src_resource, src_sub_resource_idx, debug_box(src_box)); - if (src_box && (src_box->left >= src_box->right - || src_box->top >= src_box->bottom - || src_box->front >= src_box->back)) - { - WARN("Invalid box %s specified.\n", debug_box(src_box)); - return WINED3DERR_INVALIDCALL; - } - if (src_resource == dst_resource && src_sub_resource_idx == dst_sub_resource_idx) { WARN("Source and destination are the same sub-resource.\n"); @@ -3938,157 +3964,186 @@ if (dst_resource->type == WINED3D_RTYPE_BUFFER) { - unsigned int src_offset, size; - if (dst_sub_resource_idx) { WARN("Invalid dst_sub_resource_idx %u.\n", dst_sub_resource_idx); return WINED3DERR_INVALIDCALL; } + if (src_sub_resource_idx) { WARN("Invalid src_sub_resource_idx %u.\n", src_sub_resource_idx); return WINED3DERR_INVALIDCALL; } - if (src_box) + if (!src_box) { - src_offset = src_box->left; - size = src_box->right - src_box->left; - } - else + b.left = 0; + b.top = 0; + b.right = src_resource->size; + b.bottom = 1; + b.front = 0; + b.back = 1; + src_box = &b; + } + else if ((src_box->left >= src_box->right + || src_box->top >= src_box->bottom + || src_box->front >= src_box->back)) { - src_offset = 0; - size = src_resource->size; + WARN("Invalid box %s specified.\n", debug_box(src_box)); + return WINED3DERR_INVALIDCALL; } - if (src_offset > src_resource->size - || size > src_resource->size - src_offset - || dst_x > dst_resource->size - || size > dst_resource->size - dst_x) + if (src_box->right > src_resource->size || dst_x >= dst_resource->size + || src_box->right - src_box->left > dst_resource->size - dst_x) { WARN("Invalid range specified, dst_offset %u, src_offset %u, size %u.\n", - dst_x, src_offset, size); + dst_x, src_box->left, src_box->right - src_box->left); return WINED3DERR_INVALIDCALL; } - return wined3d_buffer_copy(buffer_from_resource(dst_resource), dst_x, - buffer_from_resource(src_resource), src_offset, size); - } + dst_box.left = dst_x; + dst_box.top = 0; + dst_box.right = dst_x + (src_box->right - src_box->left); + dst_box.bottom = 1; + dst_box.front = 0; + dst_box.back = 1; + } + else if (dst_resource->type == WINED3D_RTYPE_TEXTURE_2D) + { + struct wined3d_texture *dst_texture = texture_from_resource(dst_resource); + struct wined3d_texture *src_texture = texture_from_resource(src_resource); + unsigned int src_level = src_sub_resource_idx % src_texture->level_count; - if (dst_resource->type != WINED3D_RTYPE_TEXTURE_2D) - { - FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(dst_resource->type)); - return WINED3DERR_INVALIDCALL; - } + if (dst_sub_resource_idx >= dst_texture->level_count * dst_texture->layer_count) + { + WARN("Invalid destination sub-resource %u.\n", dst_sub_resource_idx); + return WINED3DERR_INVALIDCALL; + } - dst_texture = texture_from_resource(dst_resource); - src_texture = texture_from_resource(src_resource); + if (src_sub_resource_idx >= src_texture->level_count * src_texture->layer_count) + { + WARN("Invalid source sub-resource %u.\n", src_sub_resource_idx); + return WINED3DERR_INVALIDCALL; + } - if (src_box) - { - SetRect(&src_rect, src_box->left, src_box->top, src_box->right, src_box->bottom); + if (dst_texture->sub_resources[dst_sub_resource_idx].map_count) + { + WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx); + return WINED3DERR_INVALIDCALL; + } + + if (src_texture->sub_resources[src_sub_resource_idx].map_count) + { + WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx); + return WINED3DERR_INVALIDCALL; + } + + if (!src_box) + { + + b.left = 0; + b.top = 0; + b.right = wined3d_texture_get_level_width(src_texture, src_level); + b.bottom = wined3d_texture_get_level_height(src_texture, src_level); + b.front = 0; + b.back = 1; + src_box = &b; + } + else if (FAILED(wined3d_texture_check_box_dimensions(src_texture, src_level, src_box))) + { + WARN("Invalid source box %s.\n", debug_box(src_box)); + return WINED3DERR_INVALIDCALL; + } + + dst_box.left = dst_x; + dst_box.top = dst_y; + dst_box.right = dst_x + (src_box->right - src_box->left); + dst_box.bottom = dst_y + (src_box->bottom - src_box->top); + dst_box.front = 0; + dst_box.back = 1; + if (FAILED(wined3d_texture_check_box_dimensions(dst_texture, + dst_sub_resource_idx % dst_texture->level_count, &dst_box))) + { + WARN("Invalid destination box %s.\n", debug_box(&dst_box)); + return WINED3DERR_INVALIDCALL; + } } else { - unsigned int level = src_sub_resource_idx % src_texture->level_count; - - SetRect(&src_rect, 0, 0, wined3d_texture_get_level_width(src_texture, level), - wined3d_texture_get_level_height(src_texture, level)); + FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(dst_resource->type)); + return WINED3DERR_INVALIDCALL; } - SetRect(&dst_rect, dst_x, dst_y, dst_x + (src_rect.right - src_rect.left), - dst_y + (src_rect.bottom - src_rect.top)); + wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box, + src_resource, src_sub_resource_idx, src_box, 0, NULL, WINED3D_TEXF_POINT); - if (FAILED(hr = wined3d_texture_blt(dst_texture, dst_sub_resource_idx, &dst_rect, - src_texture, src_sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT))) - WARN("Failed to blit, hr %#x.\n", hr); - - return hr; + return WINED3D_OK; } void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, unsigned int depth_pitch) { - unsigned int width, height, depth, level; - struct wined3d_const_bo_address addr; - struct wined3d_context *context; - struct wined3d_texture *texture; + unsigned int width, height, depth; + struct wined3d_box b; TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u.\n", device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch); if (resource->type == WINED3D_RTYPE_BUFFER) { - struct wined3d_buffer *buffer = buffer_from_resource(resource); - if (sub_resource_idx > 0) { WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); return; } - context = context_acquire(resource->device, NULL, 0); - if (!wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER)) + width = resource->size; + height = 1; + depth = 1; + } + else if (resource->type == WINED3D_RTYPE_TEXTURE_2D || resource->type == WINED3D_RTYPE_TEXTURE_3D) + { + struct wined3d_texture *texture = texture_from_resource(resource); + unsigned int level; + + if (sub_resource_idx >= texture->level_count * texture->layer_count) { - ERR("Failed to load buffer location.\n"); - context_release(context); + WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); return; } - wined3d_buffer_upload_data(buffer, context, box, data); - wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER); - context_release(context); - - return; + level = sub_resource_idx % texture->level_count; + width = wined3d_texture_get_level_width(texture, level); + height = wined3d_texture_get_level_height(texture, level); + depth = wined3d_texture_get_level_depth(texture, level); } - - if (resource->type != WINED3D_RTYPE_TEXTURE_2D && resource->type != WINED3D_RTYPE_TEXTURE_3D) + else { FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); return; } - texture = texture_from_resource(resource); - if (sub_resource_idx >= texture->level_count * texture->layer_count) + if (!box) { - WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); - return; + b.left = 0; + b.top = 0; + b.right = width; + b.bottom = height; + b.front = 0; + b.back = depth; + box = &b; } - - level = sub_resource_idx % texture->level_count; - width = wined3d_texture_get_level_width(texture, level); - height = wined3d_texture_get_level_height(texture, level); - depth = wined3d_texture_get_level_depth(texture, level); - - if (box && (box->left >= box->right || box->right > width + else if (box->left >= box->right || box->right > width || box->top >= box->bottom || box->bottom > height - || box->front >= box->back || box->back > depth)) + || box->front >= box->back || box->back > depth) { WARN("Invalid box %s specified.\n", debug_box(box)); return; } - addr.buffer_object = 0; - addr.addr = data; - - context = context_acquire(resource->device, NULL, 0); - - /* Only load the sub-resource for partial updates. */ - if (!box || (!box->left && !box->top && !box->front - && box->right == width && box->bottom == height && box->back == depth)) - wined3d_texture_prepare_texture(texture, context, FALSE); - else - wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); - wined3d_texture_bind_and_dirtify(texture, context, FALSE); - - wined3d_texture_upload_data(texture, sub_resource_idx, context, box, &addr, row_pitch, depth_pitch); - - context_release(context); - - wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); - wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); + wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch); } HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/directx.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/directx.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/directx.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/directx.c 2017-03-21 14:02:57.000000000 +0000 @@ -147,6 +147,7 @@ {"GL_ARB_point_sprite", ARB_POINT_SPRITE }, {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX }, {"GL_ARB_sampler_objects", ARB_SAMPLER_OBJECTS }, + {"GL_ARB_seamless_cube_map", ARB_SEAMLESS_CUBE_MAP }, {"GL_ARB_shader_atomic_counters", ARB_SHADER_ATOMIC_COUNTERS }, {"GL_ARB_shader_bit_encoding", ARB_SHADER_BIT_ENCODING }, {"GL_ARB_shader_image_load_store", ARB_SHADER_IMAGE_LOAD_STORE }, @@ -1371,6 +1372,7 @@ {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX860M, "NVIDIA GeForce GTX 860M", DRIVER_NVIDIA_GEFORCE8, 2048}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX870M, "NVIDIA GeForce GTX 870M", DRIVER_NVIDIA_GEFORCE8, 3072}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX880M, "NVIDIA GeForce GTX 880M", DRIVER_NVIDIA_GEFORCE8, 4096}, + {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_940M, "NVIDIA GeForce 940M", DRIVER_NVIDIA_GEFORCE8, 4096}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX950, "NVIDIA GeForce GTX 950", DRIVER_NVIDIA_GEFORCE8, 2048}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX950M, "NVIDIA GeForce GTX 950M", DRIVER_NVIDIA_GEFORCE8, 4096}, {HW_VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX960, "NVIDIA GeForce GTX 960", DRIVER_NVIDIA_GEFORCE8, 4096}, @@ -1880,6 +1882,7 @@ {"GTX 960", CARD_NVIDIA_GEFORCE_GTX960}, /* GeForce 900 - midend high */ {"GTX 950M", CARD_NVIDIA_GEFORCE_GTX950M}, /* GeForce 900 - midend mobile */ {"GTX 950", CARD_NVIDIA_GEFORCE_GTX950}, /* GeForce 900 - midend */ + {"GeForce 940M", CARD_NVIDIA_GEFORCE_940M}, /* GeForce 900 - midend mobile */ {"GTX 880M", CARD_NVIDIA_GEFORCE_GTX880M}, /* GeForce 800 - mobile */ {"GTX 870M", CARD_NVIDIA_GEFORCE_GTX870M}, /* GeForce 800 - mobile */ {"GTX 860M", CARD_NVIDIA_GEFORCE_GTX860M}, /* GeForce 800 - mobile */ @@ -3392,8 +3395,8 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info) { + unsigned int i, sampler_count; GLfloat gl_floatv[2]; - unsigned int i; GLint gl_max; gl_info->limits.blends = 1; @@ -3401,11 +3404,12 @@ gl_info->limits.textures = 0; gl_info->limits.texture_coords = 0; for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i) + { gl_info->limits.uniform_blocks[i] = 0; - gl_info->limits.fragment_samplers = 1; - gl_info->limits.vertex_samplers = 0; - gl_info->limits.compute_samplers = 0; - gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers; + gl_info->limits.samplers[i] = 0; + } + gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL] = 1; + gl_info->limits.combined_samplers = gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL]; gl_info->limits.graphics_samplers = gl_info->limits.combined_samplers; gl_info->limits.vertex_attribs = 16; gl_info->limits.texture_buffer_offset_alignment = 1; @@ -3485,18 +3489,20 @@ if (gl_info->supported[ARB_FRAGMENT_PROGRAM] || gl_info->supported[ARB_FRAGMENT_SHADER]) { gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &gl_max); - gl_info->limits.fragment_samplers = gl_max; + gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL] = gl_max; } else { - gl_info->limits.fragment_samplers = gl_info->limits.textures; + gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL] = gl_info->limits.textures; } - TRACE("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers); + TRACE("Max fragment samplers: %d.\n", gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL]); if (gl_info->supported[ARB_VERTEX_SHADER]) { + unsigned int vertex_sampler_count; + gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &gl_max); - gl_info->limits.vertex_samplers = gl_max; + vertex_sampler_count = gl_info->limits.samplers[WINED3D_SHADER_TYPE_VERTEX] = gl_max; gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &gl_max); gl_info->limits.combined_samplers = gl_max; gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &gl_max); @@ -3516,26 +3522,26 @@ * * So this is just a check to check that our assumption holds true. If not, write a warning * and reduce the number of vertex samplers or probably disable vertex texture fetch. */ - if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12 - && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers) + if (vertex_sampler_count && gl_info->limits.combined_samplers < 12 + && MAX_TEXTURES + vertex_sampler_count > gl_info->limits.combined_samplers) { FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n", - gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers); + vertex_sampler_count, gl_info->limits.combined_samplers); FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n"); if (gl_info->limits.combined_samplers > MAX_TEXTURES) - gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES; + vertex_sampler_count = gl_info->limits.combined_samplers - MAX_TEXTURES; else - gl_info->limits.vertex_samplers = 0; + vertex_sampler_count = 0; + gl_info->limits.samplers[WINED3D_SHADER_TYPE_VERTEX] = vertex_sampler_count; } } else { - gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers; + gl_info->limits.combined_samplers = gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL]; } - TRACE("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers); + TRACE("Max vertex samplers: %u.\n", gl_info->limits.samplers[WINED3D_SHADER_TYPE_VERTEX]); TRACE("Max combined samplers: %u.\n", gl_info->limits.combined_samplers); TRACE("Max vertex attributes: %u.\n", gl_info->limits.vertex_attribs); - gl_info->limits.graphics_samplers = gl_info->limits.combined_samplers; } else { @@ -3617,6 +3623,9 @@ gl_info->limits.uniform_blocks[WINED3D_SHADER_TYPE_GEOMETRY] = min(gl_max, WINED3D_MAX_CBS); TRACE("Max geometry uniform blocks: %u (%d).\n", gl_info->limits.uniform_blocks[WINED3D_SHADER_TYPE_GEOMETRY], gl_max); + gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &gl_max); + gl_info->limits.samplers[WINED3D_SHADER_TYPE_GEOMETRY] = gl_max; + TRACE("Max geometry samplers: %u.\n", gl_info->limits.samplers[WINED3D_SHADER_TYPE_GEOMETRY]); } if (gl_info->supported[ARB_FRAGMENT_SHADER]) { @@ -3642,12 +3651,8 @@ TRACE("Max compute uniform blocks: %u (%d).\n", gl_info->limits.uniform_blocks[WINED3D_SHADER_TYPE_COMPUTE], gl_max); gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &gl_max); - gl_info->limits.compute_samplers = gl_max; - TRACE("Max compute samplers: %u.\n", gl_info->limits.compute_samplers); - /* A majority of OpenGL implementations allow to statically partition - * the set of texture bindings into six separate sets. */ - if (gl_info->limits.combined_samplers >= MAX_COMBINED_SAMPLERS + gl_info->limits.compute_samplers) - gl_info->limits.graphics_samplers -= gl_info->limits.compute_samplers; + gl_info->limits.samplers[WINED3D_SHADER_TYPE_COMPUTE] = gl_max; + TRACE("Max compute samplers: %u.\n", gl_info->limits.samplers[WINED3D_SHADER_TYPE_COMPUTE]); } if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT]) { @@ -3691,6 +3696,31 @@ gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_SAMPLES, &gl_max); gl_info->limits.samples = gl_max; } + + gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL] = + min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_GL_FRAGMENT_SAMPLERS); + sampler_count = 0; + for (i = 0; i < WINED3D_SHADER_TYPE_GRAPHICS_COUNT; ++i) + sampler_count += gl_info->limits.samplers[i]; + if (gl_info->supported[WINED3D_GL_VERSION_3_2] && gl_info->limits.combined_samplers < sampler_count) + { + /* The minimum value for GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS in OpenGL + * 3.2 is 48 (16 per stage). When tessellation shaders are supported + * the minimum value is increased to 80. */ + WARN("Graphics pipeline sampler count %u is greater than combined sampler count %u.\n", + sampler_count, gl_info->limits.combined_samplers); + for (i = 0; i < WINED3D_SHADER_TYPE_GRAPHICS_COUNT; ++i) + gl_info->limits.samplers[i] = min(gl_info->limits.samplers[i], 16); + } + + /* A majority of OpenGL implementations allow us to statically partition + * the set of texture bindings into six separate sets. */ + gl_info->limits.graphics_samplers = gl_info->limits.combined_samplers; + sampler_count = 0; + for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i) + sampler_count += gl_info->limits.samplers[i]; + if (gl_info->limits.combined_samplers >= sampler_count) + gl_info->limits.graphics_samplers -= gl_info->limits.samplers[WINED3D_SHADER_TYPE_COMPUTE]; } /* Context activation is done by the caller. */ @@ -3765,6 +3795,7 @@ * extension for core-only support. */ {ARB_FRAGMENT_COORD_CONVENTIONS, MAKEDWORD_VERSION(3, 2)}, {ARB_PROVOKING_VERTEX, MAKEDWORD_VERSION(3, 2)}, + {ARB_SEAMLESS_CUBE_MAP, MAKEDWORD_VERSION(3, 2)}, {ARB_SYNC, MAKEDWORD_VERSION(3, 2)}, {ARB_VERTEX_ARRAY_BGRA, MAKEDWORD_VERSION(3, 2)}, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/glsl_shader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/glsl_shader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/glsl_shader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/glsl_shader.c 2017-03-21 14:02:57.000000000 +0000 @@ -558,13 +558,45 @@ print_glsl_info_log(gl_info, program, TRUE); } +static BOOL shader_glsl_use_layout_binding_qualifier(const struct wined3d_gl_info *gl_info) +{ + return !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] && gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]; +} + +static void shader_glsl_init_uniform_block_bindings(const struct wined3d_gl_info *gl_info, + struct shader_glsl_priv *priv, GLuint program_id, + const struct wined3d_shader_reg_maps *reg_maps) +{ + const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); + struct wined3d_string_buffer *name; + unsigned int i, base, count; + GLuint block_idx; + + if (shader_glsl_use_layout_binding_qualifier(gl_info)) + return; + + name = string_buffer_get(&priv->string_buffers); + wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, reg_maps->shader_version.type, &base, &count); + for (i = 0; i < count; ++i) + { + if (!reg_maps->cb_sizes[i]) + continue; + + string_buffer_sprintf(name, "block_%s_cb%u", prefix, i); + block_idx = GL_EXTCALL(glGetUniformBlockIndex(program_id, name->buffer)); + GL_EXTCALL(glUniformBlockBinding(program_id, block_idx, base + i)); + } + checkGLcall("glUniformBlockBinding"); + string_buffer_release(&priv->string_buffers, name); +} + /* Context activation is done by the caller. */ -static void shader_glsl_load_samplers(const struct wined3d_gl_info *gl_info, - struct shader_glsl_priv *priv, const char *prefix, unsigned int base_idx, - unsigned int count, const DWORD *tex_unit_map, GLuint program_id) +static void shader_glsl_load_samplers_range(const struct wined3d_gl_info *gl_info, + struct shader_glsl_priv *priv, GLuint program_id, const char *prefix, + unsigned int base, unsigned int count, const DWORD *tex_unit_map) { struct wined3d_string_buffer *sampler_name = string_buffer_get(&priv->string_buffers); - unsigned int mapped_unit, i; + unsigned int i, mapped_unit; GLint name_loc; for (i = 0; i < count; ++i) @@ -574,7 +606,7 @@ if (name_loc == -1) continue; - mapped_unit = tex_unit_map ? tex_unit_map[base_idx + i] : base_idx + i; + mapped_unit = tex_unit_map ? tex_unit_map[base + i] : base + i; if (mapped_unit == WINED3D_UNMAPPED_STAGE || mapped_unit >= gl_info->limits.combined_samplers) { ERR("Trying to load sampler %s on unsupported unit %u.\n", sampler_name->buffer, mapped_unit); @@ -588,31 +620,48 @@ string_buffer_release(&priv->string_buffers, sampler_name); } +static unsigned int shader_glsl_map_tex_unit(const struct wined3d_context *context, + const struct wined3d_shader_version *shader_version, unsigned int sampler_idx) +{ + const DWORD *tex_unit_map; + unsigned int base, count; + + tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count); + if (sampler_idx >= count) + return WINED3D_UNMAPPED_STAGE; + if (!tex_unit_map) + return base + sampler_idx; + return tex_unit_map[base + sampler_idx]; +} + +static void shader_glsl_append_sampler_binding_qualifier(struct wined3d_string_buffer *buffer, + const struct wined3d_context *context, const struct wined3d_shader_version *shader_version, + unsigned int sampler_idx) +{ + unsigned int mapped_unit = shader_glsl_map_tex_unit(context, shader_version, sampler_idx); + if (mapped_unit != WINED3D_UNMAPPED_STAGE) + shader_addline(buffer, "layout(binding = %u)\n", mapped_unit); + else + ERR("Unmapped sampler %u.\n", sampler_idx); +} + /* Context activation is done by the caller. */ -static void shader_glsl_load_graphics_samplers(const struct wined3d_gl_info *gl_info, - struct shader_glsl_priv *priv, const DWORD *tex_unit_map, GLuint program_id) +static void shader_glsl_load_samplers(const struct wined3d_context *context, + struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps) { + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_shader_version *shader_version; + const DWORD *tex_unit_map; + unsigned int base, count; const char *prefix; - unsigned int i; - static const struct - { - enum wined3d_shader_type type; - unsigned int base_idx; - unsigned int count; - } - sampler_info[] = - { - {WINED3D_SHADER_TYPE_PIXEL, 0, MAX_FRAGMENT_SAMPLERS}, - {WINED3D_SHADER_TYPE_VERTEX, MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS}, - }; + if (shader_glsl_use_layout_binding_qualifier(gl_info)) + return; - for (i = 0; i < ARRAY_SIZE(sampler_info); ++i) - { - prefix = shader_glsl_get_prefix(sampler_info[i].type); - shader_glsl_load_samplers(gl_info, priv, prefix, - sampler_info[i].base_idx, sampler_info[i].count, tex_unit_map, program_id); - } + shader_version = reg_maps ? ®_maps->shader_version : NULL; + prefix = shader_glsl_get_prefix(shader_version ? shader_version->type : WINED3D_SHADER_TYPE_PIXEL); + tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count); + shader_glsl_load_samplers_range(gl_info, priv, program_id, prefix, base, count, tex_unit_map); } static void shader_glsl_load_icb(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv, @@ -639,11 +688,15 @@ static void shader_glsl_load_images(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps) { - struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers); const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); + struct wined3d_string_buffer *name; GLint location; unsigned int i; + if (shader_glsl_use_layout_binding_qualifier(gl_info)) + return; + + name = string_buffer_get(&priv->string_buffers); for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i) { if (!reg_maps->uav_resource_info[i].type) @@ -662,6 +715,19 @@ } /* Context activation is done by the caller. */ +static void shader_glsl_load_program_resources(const struct wined3d_context *context, + struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader) +{ + const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; + + shader_glsl_init_uniform_block_bindings(context->gl_info, priv, program_id, reg_maps); + shader_glsl_load_icb(context->gl_info, priv, program_id, reg_maps); + /* Texture unit mapping is set up to be the same each time the shader + * program is used so we can hardcode the sampler uniform values. */ + shader_glsl_load_samplers(context, priv, program_id, reg_maps); +} + +/* Context activation is done by the caller. */ static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const struct wined3d_vec4 *constants, const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) { @@ -1949,6 +2015,7 @@ const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_shader_indexable_temp *idx_temp_reg; + unsigned int uniform_block_base, uniform_block_count; unsigned int i, extra_constants_needed = 0; const struct wined3d_shader_lconst *lconst; const char *prefix; @@ -2049,11 +2116,17 @@ shader_addline(buffer, "uniform vec4 %s_icb[%u];\n", prefix, reg_maps->icb->vec4_count); /* Declare constant buffers */ - for (i = 0; i < WINED3D_MAX_CBS; ++i) + wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, version->type, + &uniform_block_base, &uniform_block_count); + for (i = 0; i < min(uniform_block_count, WINED3D_MAX_CBS); ++i) { if (reg_maps->cb_sizes[i]) + { + if (shader_glsl_use_layout_binding_qualifier(gl_info)) + shader_addline(buffer, "layout(binding = %u)\n", uniform_block_base + i); shader_addline(buffer, "layout(std140) uniform block_%s_cb%u { vec4 %s_cb%u[%u]; };\n", prefix, i, prefix, i, reg_maps->cb_sizes[i]); + } } /* Declare texture samplers */ @@ -2157,6 +2230,9 @@ FIXME("Unhandled resource type %#x.\n", reg_maps->resource_info[entry->resource_idx].type); break; } + + if (shader_glsl_use_layout_binding_qualifier(gl_info)) + shader_glsl_append_sampler_binding_qualifier(buffer, context, version, entry->bind_idx); shader_addline(buffer, "uniform %s%s %s_sampler%u;\n", sampler_type_prefix, sampler_type, prefix, entry->bind_idx); } @@ -2219,6 +2295,8 @@ break; } + if (shader_glsl_use_layout_binding_qualifier(gl_info)) + shader_addline(buffer, "layout(binding = %u)\n", i); if (reg_maps->uav_read_mask & (1u << i)) shader_addline(buffer, "layout(%s) uniform %s%s %s_image%u;\n", read_format, image_type_prefix, image_type, prefix, i); @@ -3206,7 +3284,7 @@ type_part = resource_type_info[resource_type].type_part; if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2D && texrect) type_part = "2DRect"; - if (!type_part[0]) + if (!type_part[0] && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY) FIXME("Unhandled resource type %#x.\n", resource_type); if (!lod && grad && !shader_glsl_has_core_grad(gl_info, &ctx->shader->reg_maps.shader_version)) @@ -3595,15 +3673,15 @@ shader_addline(ins->ctx->buffer, "%s%s);\n", op, src_param.param_str); } -static void shader_glsl_imul(const struct wined3d_shader_instruction *ins) +static void shader_glsl_mul_extended(const struct wined3d_shader_instruction *ins) { struct wined3d_string_buffer *buffer = ins->ctx->buffer; struct glsl_src_param src0_param; struct glsl_src_param src1_param; DWORD write_mask; - /* If we have ARB_gpu_shader5 or GLSL 4.0, we can use imulExtended(). If - * not, we can emulate it. */ + /* If we have ARB_gpu_shader5, we can use imulExtended() / umulExtended(). + * If not, we can emulate it. */ if (ins->dst[0].reg.type != WINED3DSPR_NULL) FIXME("64-bit integer multiplies not implemented.\n"); @@ -5389,6 +5467,70 @@ FIXME("Unhandled sync flags %#x.\n", sync_flags); } +static const struct wined3d_shader_resource_info *shader_glsl_get_resource_info( + const struct wined3d_shader_instruction *ins, const struct wined3d_shader_register *reg) +{ + const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; + unsigned int idx = reg->idx[0].offset; + + if (reg->type == WINED3DSPR_RESOURCE) + { + if (idx >= ARRAY_SIZE(reg_maps->resource_info)) + { + ERR("Invalid resource index %u.\n", idx); + return NULL; + } + return ®_maps->resource_info[idx]; + } + + if (reg->type == WINED3DSPR_UAV) + { + if (idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) + { + ERR("Invalid UAV index %u.\n", idx); + return NULL; + } + return ®_maps->uav_resource_info[idx]; + } + + FIXME("Unhandled register type %#x.\n", reg->type); + return NULL; +} + +static void shader_glsl_bufinfo(const struct wined3d_shader_instruction *ins) +{ + const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); + const struct wined3d_shader_resource_info *resource_info; + struct wined3d_string_buffer *buffer = ins->ctx->buffer; + unsigned int resource_idx; + char dst_swizzle[6]; + DWORD write_mask; + + write_mask = shader_glsl_append_dst(buffer, ins); + shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle); + + if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[0].reg))) + return; + resource_idx = ins->src[0].reg.idx[0].offset; + + shader_addline(buffer, "ivec2("); + if (ins->src[0].reg.type == WINED3DSPR_RESOURCE) + { + unsigned int bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, + resource_idx, WINED3D_SAMPLER_DEFAULT); + shader_addline(buffer, "textureSize(%s_sampler%u)", prefix, bind_idx); + } + else + { + shader_addline(buffer, "imageSize(%s_image%u)", prefix, resource_idx); + } + if (resource_info->stride) + shader_addline(buffer, " / %u", resource_info->stride); + else if (resource_info->flags & WINED3D_VIEW_BUFFER_RAW) + shader_addline(buffer, " * 4"); + shader_addline(buffer, ", %u)%s);\n", resource_info->stride, dst_swizzle); +} + static void shader_glsl_resinfo(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version; @@ -6693,9 +6835,7 @@ const struct wined3d_gl_info *gl_info = context->gl_info; struct shader_glsl_ctx_priv priv_ctx; BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]; - - /* Create the hw GLSL shader object and assign it as the shader->prgId */ - GLuint shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); + GLuint shader_id; memset(&priv_ctx, 0, sizeof(priv_ctx)); priv_ctx.cur_ps_args = args; @@ -6786,7 +6926,8 @@ shader_glsl_input_pack(shader, buffer, &shader->input_signature, reg_maps, args, gl_info); /* Base Shader Body */ - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ if (reg_maps->shader_version.major < 4) @@ -6794,6 +6935,7 @@ shader_addline(buffer, "}\n"); + shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); TRACE("Compiling shader object %u.\n", shader_id); shader_glsl_compile(gl_info, shader_id, buffer->buffer); @@ -6852,9 +6994,7 @@ struct wined3d_string_buffer *buffer = &priv->shader_buffer; const struct wined3d_gl_info *gl_info = context->gl_info; struct shader_glsl_ctx_priv priv_ctx; - - /* Create the hw GLSL shader program and assign it as the shader->prgId */ - GLuint shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); + GLuint shader_id; shader_glsl_add_version_declaration(buffer, gl_info, ®_maps->shader_version); @@ -6885,7 +7025,8 @@ shader_addline(buffer, "void main()\n{\n"); /* Base Shader Body */ - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ if (reg_maps->shader_version.major < 4) @@ -6893,6 +7034,7 @@ shader_addline(buffer, "}\n"); + shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); TRACE("Compiling shader object %u.\n", shader_id); shader_glsl_compile(gl_info, shader_id, buffer->buffer); @@ -6910,8 +7052,6 @@ struct shader_glsl_ctx_priv priv_ctx; GLuint shader_id; - shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER)); - shader_glsl_add_version_declaration(buffer, gl_info, ®_maps->shader_version); shader_glsl_enable_extensions(buffer, gl_info); @@ -6925,9 +7065,11 @@ shader_addline(buffer, "uniform vec4 pos_fixup;\n"); shader_glsl_generate_sm4_rasterizer_input_setup(priv, shader, args->ps_input_count, gl_info); shader_addline(buffer, "void main()\n{\n"); - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; shader_addline(buffer, "}\n"); + shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER)); TRACE("Compiling shader object %u.\n", shader_id); shader_glsl_compile(gl_info, shader_id, buffer->buffer); @@ -6969,8 +7111,6 @@ GLuint shader_id; unsigned int i; - shader_id = GL_EXTCALL(glCreateShader(GL_COMPUTE_SHADER)); - shader_glsl_add_version_declaration(buffer, gl_info, ®_maps->shader_version); shader_glsl_enable_extensions(buffer, gl_info); @@ -6994,6 +7134,7 @@ shader_generate_main(shader, buffer, reg_maps, &priv_ctx); shader_addline(buffer, "}\n"); + shader_id = GL_EXTCALL(glCreateShader(GL_COMPUTE_SHADER)); TRACE("Compiling shader object %u.\n", shader_id); shader_glsl_compile(gl_info, shader_id, buffer->buffer); @@ -7945,13 +8086,14 @@ /* Context activation is done by the caller. */ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *priv, - const struct ffp_frag_settings *settings, const struct wined3d_gl_info *gl_info) + const struct ffp_frag_settings *settings, const struct wined3d_context *context) { struct wined3d_string_buffer *tex_reg_name = string_buffer_get(&priv->string_buffers); enum wined3d_cmp_func alpha_test_func = settings->alpha_test_func + 1; - BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]; struct wined3d_string_buffer *buffer = &priv->shader_buffer; BYTE lum_map = 0, bump_map = 0, tex_map = 0, tss_const_map = 0; + const struct wined3d_gl_info *gl_info = context->gl_info; + BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]; BOOL tempreg_used = FALSE, tfactor_used = FALSE; UINT lowest_disabled_stage; GLuint shader_id; @@ -8023,6 +8165,8 @@ shader_glsl_add_version_declaration(buffer, gl_info, NULL); + if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]) + shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n"); if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n"); @@ -8037,6 +8181,8 @@ for (stage = 0; stage < MAX_TEXTURES; ++stage) { + const char *sampler_type; + if (tss_const_map & (1u << stage)) shader_addline(buffer, "uniform vec4 tss_const%u;\n", stage); @@ -8046,24 +8192,31 @@ switch (settings->op[stage].tex_type) { case WINED3D_GL_RES_TYPE_TEX_1D: - shader_addline(buffer, "uniform sampler1D ps_sampler%u;\n", stage); + sampler_type = "1D"; break; case WINED3D_GL_RES_TYPE_TEX_2D: - shader_addline(buffer, "uniform sampler2D ps_sampler%u;\n", stage); + sampler_type = "2D"; break; case WINED3D_GL_RES_TYPE_TEX_3D: - shader_addline(buffer, "uniform sampler3D ps_sampler%u;\n", stage); + sampler_type = "3D"; break; case WINED3D_GL_RES_TYPE_TEX_CUBE: - shader_addline(buffer, "uniform samplerCube ps_sampler%u;\n", stage); + sampler_type = "Cube"; break; case WINED3D_GL_RES_TYPE_TEX_RECT: - shader_addline(buffer, "uniform sampler2DRect ps_sampler%u;\n", stage); + sampler_type = "2DRect"; break; default: FIXME("Unhandled sampler type %#x.\n", settings->op[stage].tex_type); + sampler_type = NULL; break; } + if (sampler_type) + { + if (shader_glsl_use_layout_binding_qualifier(gl_info)) + shader_glsl_append_sampler_binding_qualifier(buffer, context, NULL, stage); + shader_addline(buffer, "uniform sampler%s ps_sampler%u;\n", sampler_type, stage); + } shader_addline(buffer, "vec4 tex%u;\n", stage); @@ -8389,7 +8542,7 @@ } static struct glsl_ffp_fragment_shader *shader_glsl_find_ffp_fragment_shader(struct shader_glsl_priv *priv, - const struct wined3d_gl_info *gl_info, const struct ffp_frag_settings *args) + const struct ffp_frag_settings *args, const struct wined3d_context *context) { struct glsl_ffp_fragment_shader *glsl_desc; const struct ffp_frag_desc *desc; @@ -8401,7 +8554,7 @@ return NULL; glsl_desc->entry.settings = *args; - glsl_desc->id = shader_glsl_generate_ffp_fragment_shader(priv, args, gl_info); + glsl_desc->id = shader_glsl_generate_ffp_fragment_shader(priv, args, context); list_init(&glsl_desc->linked_programs); add_ffp_frag_shader(&priv->ffp_fragment_shaders, &glsl_desc->entry); @@ -8552,35 +8705,11 @@ string_buffer_release(&priv->string_buffers, name); } -static void shader_glsl_init_uniform_block_bindings(const struct wined3d_gl_info *gl_info, - struct shader_glsl_priv *priv, GLuint program_id, - const struct wined3d_shader_reg_maps *reg_maps) -{ - struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers); - const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); - unsigned int i, base, count; - GLuint block_idx; - - wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, reg_maps->shader_version.type, &base, &count); - for (i = 0; i < count; ++i) - { - if (!reg_maps->cb_sizes[i]) - continue; - - string_buffer_sprintf(name, "block_%s_cb%u", prefix, i); - block_idx = GL_EXTCALL(glGetUniformBlockIndex(program_id, name->buffer)); - GL_EXTCALL(glUniformBlockBinding(program_id, block_idx, base + i)); - } - checkGLcall("glUniformBlockBinding"); - string_buffer_release(&priv->string_buffers, name); -} - /* Context activation is done by the caller. */ static void set_glsl_compute_shader_program(const struct wined3d_context *context, const struct wined3d_state *state, struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data) { const struct wined3d_gl_info *gl_info = context->gl_info; - unsigned int base_sampler_idx, sampler_count; struct glsl_shader_prog_link *entry = NULL; struct wined3d_shader *shader; struct glsl_program_key key; @@ -8636,13 +8765,8 @@ GL_EXTCALL(glUseProgram(program_id)); checkGLcall("glUseProgram"); - shader_glsl_init_uniform_block_bindings(gl_info, priv, program_id, &shader->reg_maps); - shader_glsl_load_icb(gl_info, priv, program_id, &shader->reg_maps); + shader_glsl_load_program_resources(context, priv, program_id, shader); shader_glsl_load_images(gl_info, priv, program_id, &shader->reg_maps); - wined3d_gl_limits_get_texture_unit_range(&gl_info->limits, WINED3D_SHADER_TYPE_COMPUTE, - &base_sampler_idx, &sampler_count); - shader_glsl_load_samplers(gl_info, priv, shader_glsl_get_prefix(WINED3D_SHADER_TYPE_COMPUTE), - base_sampler_idx, sampler_count, NULL, program_id); entry->constant_update_mask = 0; } @@ -8751,7 +8875,7 @@ struct ffp_frag_settings settings; gen_ffp_frag_op(context, state, &settings, FALSE); - ffp_shader = shader_glsl_find_ffp_fragment_shader(priv, gl_info, &settings); + ffp_shader = shader_glsl_find_ffp_fragment_shader(priv, &settings, context); ps_id = ffp_shader->id; ps_list = &ffp_shader->linked_programs; } @@ -8919,10 +9043,6 @@ GL_EXTCALL(glUseProgram(program_id)); checkGLcall("glUseProgram"); - /* Texture unit mapping is set up to be the same each time the shader - * program is used so we can hardcode the sampler uniform values. */ - shader_glsl_load_graphics_samplers(gl_info, priv, context->tex_unit_map, program_id); - entry->constant_update_mask = 0; if (vshader) { @@ -8934,8 +9054,7 @@ if (entry->vs.pos_fixup_location != -1) entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; - shader_glsl_init_uniform_block_bindings(gl_info, priv, program_id, &vshader->reg_maps); - shader_glsl_load_icb(gl_info, priv, program_id, &vshader->reg_maps); + shader_glsl_load_program_resources(context, priv, program_id, vshader); } else { @@ -8976,8 +9095,8 @@ { if (entry->gs.pos_fixup_location != -1) entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; - shader_glsl_init_uniform_block_bindings(gl_info, priv, program_id, &gshader->reg_maps); - shader_glsl_load_icb(gl_info, priv, program_id, &gshader->reg_maps); + + shader_glsl_load_program_resources(context, priv, program_id, gshader); } if (ps_id) @@ -8992,13 +9111,14 @@ if (entry->ps.ycorrection_location != -1) entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_Y_CORR; - shader_glsl_init_uniform_block_bindings(gl_info, priv, program_id, &pshader->reg_maps); - shader_glsl_load_icb(gl_info, priv, program_id, &pshader->reg_maps); + shader_glsl_load_program_resources(context, priv, program_id, pshader); shader_glsl_load_images(gl_info, priv, program_id, &pshader->reg_maps); } else { entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS; + + shader_glsl_load_samplers(context, priv, program_id, NULL); } for (i = 0; i < MAX_TEXTURES; ++i) @@ -9488,6 +9608,9 @@ caps->ps_version = min(wined3d_settings.max_sm_ps, shader_model); caps->cs_version = min(wined3d_settings.max_sm_cs, shader_model); + caps->vs_version = gl_info->supported[ARB_VERTEX_SHADER] ? caps->vs_version : 0; + caps->ps_version = gl_info->supported[ARB_FRAGMENT_SHADER] ? caps->ps_version : 0; + caps->vs_uniform_count = min(WINED3D_MAX_VS_CONSTS_F, gl_info->limits.glsl_vs_float_constants); caps->ps_uniform_count = min(WINED3D_MAX_PS_CONSTS_F, gl_info->limits.glsl_ps_float_constants); caps->varying_count = gl_info->limits.glsl_varyings; @@ -9555,7 +9678,7 @@ /* WINED3DSIH_BREAK */ shader_glsl_break, /* WINED3DSIH_BREAKC */ shader_glsl_breakc, /* WINED3DSIH_BREAKP */ shader_glsl_breakp, - /* WINED3DSIH_BUFINFO */ NULL, + /* WINED3DSIH_BUFINFO */ shader_glsl_bufinfo, /* WINED3DSIH_CALL */ shader_glsl_call, /* WINED3DSIH_CALLNZ */ shader_glsl_callnz, /* WINED3DSIH_CASE */ shader_glsl_case, @@ -9575,6 +9698,7 @@ /* WINED3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ NULL, /* WINED3DSIH_DCL_HS_MAX_TESSFACTOR */ NULL, /* WINED3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER */ shader_glsl_nop, + /* WINED3DSIH_DCL_INDEX_RANGE */ NULL, /* WINED3DSIH_DCL_INDEXABLE_TEMP */ shader_glsl_nop, /* WINED3DSIH_DCL_INPUT */ shader_glsl_nop, /* WINED3DSIH_DCL_INPUT_CONTROL_POINT_COUNT */ NULL, @@ -9667,7 +9791,7 @@ /* WINED3DSIH_IMM_ATOMIC_UMAX */ shader_glsl_atomic, /* WINED3DSIH_IMM_ATOMIC_UMIN */ shader_glsl_atomic, /* WINED3DSIH_IMM_ATOMIC_XOR */ shader_glsl_atomic, - /* WINED3DSIH_IMUL */ shader_glsl_imul, + /* WINED3DSIH_IMUL */ shader_glsl_mul_extended, /* WINED3DSIH_INE */ shader_glsl_relop, /* WINED3DSIH_INEG */ shader_glsl_unary_op, /* WINED3DSIH_ISHL */ shader_glsl_binop, @@ -9763,6 +9887,7 @@ /* WINED3DSIH_ULT */ shader_glsl_relop, /* WINED3DSIH_UMAX */ shader_glsl_map2gl, /* WINED3DSIH_UMIN */ shader_glsl_map2gl, + /* WINED3DSIH_UMUL */ shader_glsl_mul_extended, /* WINED3DSIH_USHR */ shader_glsl_binop, /* WINED3DSIH_UTOF */ shader_glsl_to_float, /* WINED3DSIH_XOR */ shader_glsl_binop, @@ -10351,7 +10476,7 @@ | WINED3DTEXOPCAPS_BUMPENVMAP | WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE; caps->MaxTextureBlendStages = MAX_TEXTURES; - caps->MaxSimultaneousTextures = min(gl_info->limits.fragment_samplers, MAX_TEXTURES); + caps->MaxSimultaneousTextures = min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_TEXTURES); } static DWORD glsl_fragment_pipe_get_emul_mask(const struct wined3d_gl_info *gl_info) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/shader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/shader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/shader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/shader.c 2017-03-21 14:02:57.000000000 +0000 @@ -78,6 +78,7 @@ /* WINED3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ "dcl_hs_join_phase_instance_count", /* WINED3DSIH_DCL_HS_MAX_TESSFACTOR */ "dcl_hs_max_tessfactor", /* WINED3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER */ "dcl_immediateConstantBuffer", + /* WINED3DSIH_DCL_INDEX_RANGE */ "dcl_index_range", /* WINED3DSIH_DCL_INDEXABLE_TEMP */ "dcl_indexableTemp", /* WINED3DSIH_DCL_INPUT */ "dcl_input", /* WINED3DSIH_DCL_INPUT_CONTROL_POINT_COUNT */ "dcl_input_control_point_count", @@ -266,6 +267,7 @@ /* WINED3DSIH_ULT */ "ult", /* WINED3DSIH_UMAX */ "umax", /* WINED3DSIH_UMIN */ "umin", + /* WINED3DSIH_UMUL */ "umul", /* WINED3DSIH_USHR */ "ushr", /* WINED3DSIH_UTOF */ "utof", /* WINED3DSIH_XOR */ "xor", @@ -884,7 +886,7 @@ register_idx + 1, sizeof(*reg_maps->tgsm))) return E_OUTOFMEMORY; - reg_maps->tgsm_count = register_idx + 1; + reg_maps->tgsm_count = max(register_idx + 1, reg_maps->tgsm_count); tgsm = ®_maps->tgsm[register_idx]; tgsm->size = size; tgsm->stride = stride; @@ -933,8 +935,8 @@ /* Unhandled opcode, and its parameters. */ if (ins.handler_idx == WINED3DSIH_TABLE_SIZE) { - TRACE("Skipping unrecognized instruction.\n"); - continue; + WARN("Encountered unrecognised or invalid instruction.\n"); + return WINED3DERR_INVALIDCALL; } /* Handle declarations. */ @@ -995,6 +997,8 @@ } reg_maps->uav_resource_info[reg_idx].type = semantic->resource_type; reg_maps->uav_resource_info[reg_idx].data_type = semantic->resource_data_type; + if (ins.flags) + FIXME("Ignoring typed UAV flags %#x.\n", ins.flags); break; default: @@ -1110,6 +1114,8 @@ ERR("Invalid UAV resource index %u.\n", reg_idx); break; } + if (ins.flags) + FIXME("Ignoring raw UAV flags %#x.\n", ins.flags); reg_maps->uav_resource_info[reg_idx].type = WINED3D_SHADER_RESOURCE_BUFFER; reg_maps->uav_resource_info[reg_idx].data_type = WINED3D_DATA_UINT; reg_maps->uav_resource_info[reg_idx].flags = WINED3D_VIEW_BUFFER_RAW; @@ -1382,6 +1388,7 @@ } else if ((WINED3DSIH_ATOMIC_AND <= ins.handler_idx && ins.handler_idx <= WINED3DSIH_ATOMIC_XOR) || (WINED3DSIH_IMM_ATOMIC_AND <= ins.handler_idx && ins.handler_idx <= WINED3DSIH_IMM_ATOMIC_XOR) + || (ins.handler_idx == WINED3DSIH_BUFINFO && ins.src[0].reg.type == WINED3DSPR_UAV) || ins.handler_idx == WINED3DSIH_LD_UAV_TYPED || (ins.handler_idx == WINED3DSIH_LD_RAW && ins.src[1].reg.type == WINED3DSPR_UAV) || (ins.handler_idx == WINED3DSIH_LD_STRUCTURED && ins.src[2].reg.type == WINED3DSPR_UAV)) @@ -1393,6 +1400,8 @@ reg_idx = ins.src[2].reg.idx[0].offset; else if (WINED3DSIH_ATOMIC_AND <= ins.handler_idx && ins.handler_idx <= WINED3DSIH_ATOMIC_XOR) reg_idx = ins.dst[0].reg.idx[0].offset; + else if (ins.handler_idx == WINED3DSIH_BUFINFO) + reg_idx = ins.src[0].reg.idx[0].offset; else reg_idx = ins.dst[1].reg.idx[0].offset; if (reg_idx >= MAX_UNORDERED_ACCESS_VIEWS) @@ -1446,6 +1455,11 @@ shader_record_sample(reg_maps, ins.src[1].reg.idx[0].offset, ins.src[2].reg.idx[0].offset, reg_maps->sampler_map.count); } + else if (ins.handler_idx == WINED3DSIH_BUFINFO && ins.src[0].reg.type == WINED3DSPR_RESOURCE) + { + shader_record_sample(reg_maps, ins.src[0].reg.idx[0].offset, + WINED3D_SAMPLER_DEFAULT, reg_maps->sampler_map.count); + } else if (ins.handler_idx == WINED3DSIH_LD || (ins.handler_idx == WINED3DSIH_LD_RAW && ins.src[1].reg.type == WINED3DSPR_RESOURCE) || (ins.handler_idx == WINED3DSIH_RESINFO && ins.src[1].reg.type == WINED3DSPR_RESOURCE)) @@ -1723,7 +1737,8 @@ } static void shader_dump_decl_usage(struct wined3d_string_buffer *buffer, - const struct wined3d_shader_semantic *semantic, const struct wined3d_shader_version *shader_version) + const struct wined3d_shader_semantic *semantic, unsigned int flags, + const struct wined3d_shader_version *shader_version) { shader_addline(buffer, "dcl"); @@ -1800,6 +1815,8 @@ shader_addline(buffer, "unknown"); break; } + if (semantic->reg.reg.type == WINED3DSPR_UAV) + shader_dump_uav_flags(buffer, flags); switch (semantic->resource_data_type) { case WINED3D_DATA_FLOAT: @@ -2274,7 +2291,7 @@ /* Shared code in order to generate the bulk of the shader string. * NOTE: A description of how to parse tokens can be found on MSDN. */ -void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, +HRESULT shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps, void *backend_ctx) { struct wined3d_device *device = shader->device; @@ -2312,8 +2329,8 @@ /* Unknown opcode and its parameters. */ if (ins.handler_idx == WINED3DSIH_TABLE_SIZE) { - TRACE("Skipping unrecognized instruction.\n"); - continue; + WARN("Encountered unrecognised or invalid instruction.\n"); + return WINED3DERR_INVALIDCALL; } if (ins.predicate) @@ -2322,6 +2339,8 @@ /* Call appropriate function for output target */ device->shader_backend->shader_handle_instruction(&ins); } + + return WINED3D_OK; } static void shader_dump_ins_modifiers(struct wined3d_string_buffer *buffer, @@ -2492,7 +2511,7 @@ if (ins.handler_idx == WINED3DSIH_DCL || ins.handler_idx == WINED3DSIH_DCL_UAV_TYPED) { - shader_dump_decl_usage(&buffer, &ins.declaration.semantic, &shader_version); + shader_dump_decl_usage(&buffer, &ins.declaration.semantic, ins.flags, &shader_version); shader_dump_ins_modifiers(&buffer, &ins.declaration.semantic.reg); shader_addline(&buffer, " "); shader_dump_dst_param(&buffer, &ins.declaration.semantic.reg, &shader_version); @@ -2537,6 +2556,12 @@ } shader_addline(&buffer, "}"); } + else if (ins.handler_idx == WINED3DSIH_DCL_INDEX_RANGE) + { + shader_addline(&buffer, "%s ", shader_opcode_names[ins.handler_idx]); + shader_dump_dst_param(&buffer, &ins.declaration.index_range.first_register, &shader_version); + shader_addline(&buffer, " %u", ins.declaration.index_range.last_register); + } else if (ins.handler_idx == WINED3DSIH_DCL_INDEXABLE_TEMP) { shader_addline(&buffer, "%s x[%u][%u], %u", shader_opcode_names[ins.handler_idx], diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/shader_sm4.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/shader_sm4.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/shader_sm4.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/shader_sm4.c 2017-03-21 14:02:57.000000000 +0000 @@ -67,8 +67,8 @@ #define WINED3D_SM5_FP_ARRAY_SIZE_SHIFT 16 #define WINED3D_SM5_FP_TABLE_COUNT_MASK 0xffffu -#define WINED3D_SM5_UAV_FLAGS_SHIFT 11 -#define WINED3D_SM5_UAV_FLAGS_MASK (0x8fffu << WINED3D_SM5_UAV_FLAGS_SHIFT) +#define WINED3D_SM5_UAV_FLAGS_SHIFT 15 +#define WINED3D_SM5_UAV_FLAGS_MASK (0x1ffu << WINED3D_SM5_UAV_FLAGS_SHIFT) #define WINED3D_SM5_SYNC_FLAGS_SHIFT 11 #define WINED3D_SM5_SYNC_FLAGS_MASK (0xffu << WINED3D_SM5_SYNC_FLAGS_SHIFT) @@ -191,6 +191,7 @@ WINED3D_SM4_OP_UDIV = 0x4e, WINED3D_SM4_OP_ULT = 0x4f, WINED3D_SM4_OP_UGE = 0x50, + WINED3D_SM4_OP_UMUL = 0x51, WINED3D_SM4_OP_UMAX = 0x53, WINED3D_SM4_OP_UMIN = 0x54, WINED3D_SM4_OP_USHR = 0x55, @@ -199,6 +200,7 @@ WINED3D_SM4_OP_DCL_RESOURCE = 0x58, WINED3D_SM4_OP_DCL_CONSTANT_BUFFER = 0x59, WINED3D_SM4_OP_DCL_SAMPLER = 0x5a, + WINED3D_SM4_OP_DCL_INDEX_RANGE = 0x5b, WINED3D_SM4_OP_DCL_OUTPUT_TOPOLOGY = 0x5c, WINED3D_SM4_OP_DCL_INPUT_PRIMITIVE = 0x5d, WINED3D_SM4_OP_DCL_VERTICES_OUT = 0x5e, @@ -546,6 +548,9 @@ { ins->declaration.semantic.resource_data_type = data_type_table[data_type]; } + + if (reg_data_type == WINED3D_DATA_UAV) + ins->flags = (opcode_token & WINED3D_SM5_UAV_FLAGS_MASK) >> WINED3D_SM5_UAV_FLAGS_SHIFT; } static void shader_sm4_read_dcl_constant_buffer(struct wined3d_shader_instruction *ins, @@ -567,6 +572,14 @@ shader_sm4_read_dst_param(priv, &tokens, WINED3D_DATA_SAMPLER, &ins->declaration.dst); } +static void shader_sm4_read_dcl_index_range(struct wined3d_shader_instruction *ins, + DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count, + struct wined3d_sm4_data *priv) +{ + shader_sm4_read_dst_param(priv, &tokens, WINED3D_DATA_OPAQUE, &ins->declaration.index_range.first_register); + ins->declaration.index_range.last_register = *tokens; +} + static void shader_sm4_read_dcl_output_topology(struct wined3d_shader_instruction *ins, DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count, struct wined3d_sm4_data *priv) @@ -893,6 +906,7 @@ {WINED3D_SM4_OP_UDIV, WINED3DSIH_UDIV, "uu", "uu"}, {WINED3D_SM4_OP_ULT, WINED3DSIH_ULT, "u", "uu"}, {WINED3D_SM4_OP_UGE, WINED3DSIH_UGE, "u", "uu"}, + {WINED3D_SM4_OP_UMUL, WINED3DSIH_UMUL, "uu", "uu"}, {WINED3D_SM4_OP_UMAX, WINED3DSIH_UMAX, "u", "uu"}, {WINED3D_SM4_OP_UMIN, WINED3DSIH_UMIN, "u", "uu"}, {WINED3D_SM4_OP_USHR, WINED3DSIH_USHR, "u", "uu"}, @@ -904,6 +918,8 @@ shader_sm4_read_dcl_constant_buffer}, {WINED3D_SM4_OP_DCL_SAMPLER, WINED3DSIH_DCL_SAMPLER, "", "", shader_sm4_read_dcl_sampler}, + {WINED3D_SM4_OP_DCL_INDEX_RANGE, WINED3DSIH_DCL_INDEX_RANGE, "", "", + shader_sm4_read_dcl_index_range}, {WINED3D_SM4_OP_DCL_OUTPUT_TOPOLOGY, WINED3DSIH_DCL_OUTPUT_TOPOLOGY, "", "", shader_sm4_read_dcl_output_topology}, {WINED3D_SM4_OP_DCL_INPUT_PRIMITIVE, WINED3DSIH_DCL_INPUT_PRIMITIVE, "", "", @@ -1504,16 +1520,36 @@ DWORD opcode_token, opcode, previous_token; struct wined3d_sm4_data *priv = data; unsigned int i, len; + SIZE_T remaining; const DWORD *p; list_move_head(&priv->src_free, &priv->src); + if (*ptr >= priv->end) + { + WARN("End of byte-code, failed to read opcode.\n"); + goto fail; + } + remaining = priv->end - *ptr; + opcode_token = *(*ptr)++; opcode = opcode_token & WINED3D_SM4_OPCODE_MASK; len = ((opcode_token & WINED3D_SM4_INSTRUCTION_LENGTH_MASK) >> WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT); if (!len) + { + if (remaining < 2) + { + WARN("End of byte-code, failed to read length token.\n"); + goto fail; + } len = **ptr; + } + if (!len || remaining < len) + { + WARN("Read invalid length %u (remaining %lu).\n", len, remaining); + goto fail; + } --len; if (TRACE_ON(d3d_bytecode)) @@ -1547,10 +1583,6 @@ p = *ptr; *ptr += len; - previous_token = opcode_token; - while (previous_token & WINED3D_SM4_INSTRUCTION_MODIFIER) - shader_sm4_read_instruction_modifier(previous_token = *p++, ins); - if (opcode_info->read_opcode_func) { opcode_info->read_opcode_func(ins, opcode, opcode_token, p, len, priv); @@ -1559,6 +1591,10 @@ { enum wined3d_shader_dst_modifier instruction_dst_modifier = WINED3DSPDM_NONE; + previous_token = opcode_token; + while (previous_token & WINED3D_SM4_INSTRUCTION_MODIFIER && p != *ptr) + shader_sm4_read_instruction_modifier(previous_token = *p++, ins); + ins->flags = (opcode_token & WINED3D_SM4_INSTRUCTION_FLAGS_MASK) >> WINED3D_SM4_INSTRUCTION_FLAGS_SHIFT; if (ins->flags & WINED3D_SM4_INSTRUCTION_FLAG_SATURATE) @@ -1586,6 +1622,13 @@ } } } + + return; + +fail: + *ptr = priv->end; + ins->handler_idx = WINED3DSIH_TABLE_SIZE; + return; } static BOOL shader_sm4_is_end(void *data, const DWORD **ptr) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/state.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/state.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/state.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/state.c 2017-03-21 14:02:57.000000000 +0000 @@ -3323,7 +3323,7 @@ return; } - if (mapped_stage >= min(gl_info->limits.fragment_samplers, MAX_FRAGMENT_SAMPLERS)) + if (mapped_stage >= min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_FRAGMENT_SAMPLERS)) { WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage); return; @@ -3489,7 +3489,9 @@ TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id); - if(!texture) return; + if (!texture) + return; + /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates * wined3d_texture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the * scaling is reapplied or removed, the texture matrix has to be reapplied @@ -3499,17 +3501,16 @@ */ if (sampler < MAX_TEXTURES) { - const BOOL texIsPow2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT); + const BOOL tex_is_pow2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT); - if (texIsPow2 || (context->lastWasPow2Texture & (1u << sampler))) + if (tex_is_pow2 || (context->lastWasPow2Texture & (1u << sampler))) { - if (texIsPow2) + if (tex_is_pow2) context->lastWasPow2Texture |= 1u << sampler; else context->lastWasPow2Texture &= ~(1u << sampler); - transform_texture(context, state, - STATE_TEXTURESTAGE(context->tex_unit_map[sampler], WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS)); + transform_texture(context, state, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS)); } } } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/surface.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/surface.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/surface.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/surface.c 2017-03-21 14:02:57.000000000 +0000 @@ -252,104 +252,6 @@ masks[2] = ((1u << format->blue_size) - 1) << format->blue_offset; } -void wined3d_surface_destroy_dc(struct wined3d_surface *surface) -{ - unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); - struct wined3d_texture *texture = surface->container; - struct wined3d_device *device = texture->resource.device; - const struct wined3d_gl_info *gl_info = NULL; - D3DKMT_DESTROYDCFROMMEMORY destroy_desc; - struct wined3d_context *context = NULL; - struct wined3d_bo_address data; - NTSTATUS status; - - if (!surface->dc) - { - ERR("Surface %p has no DC.\n", surface); - return; - } - - TRACE("dc %p, bitmap %p.\n", surface->dc, surface->bitmap); - - destroy_desc.hDc = surface->dc; - destroy_desc.hBitmap = surface->bitmap; - if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc))) - ERR("Failed to destroy dc, status %#x.\n", status); - surface->dc = NULL; - surface->bitmap = NULL; - - if (device->d3d_initialized) - { - context = context_acquire(device, NULL, 0); - gl_info = context->gl_info; - } - - wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); - wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER); - - if (context) - context_release(context); -} - -HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface) -{ - unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); - struct wined3d_texture *texture = surface->container; - const struct wined3d_format *format = texture->resource.format; - struct wined3d_device *device = texture->resource.device; - const struct wined3d_gl_info *gl_info = NULL; - struct wined3d_context *context = NULL; - unsigned int row_pitch, slice_pitch; - struct wined3d_bo_address data; - D3DKMT_CREATEDCFROMMEMORY desc; - NTSTATUS status; - - TRACE("surface %p.\n", surface); - - if (!format->ddi_format) - { - WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id)); - return WINED3DERR_INVALIDCALL; - } - - wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch); - - if (device->d3d_initialized) - { - context = context_acquire(device, NULL, 0); - gl_info = context->gl_info; - } - - wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); - desc.pMemory = wined3d_texture_map_bo_address(&data, texture->sub_resources[sub_resource_idx].size, - gl_info, GL_PIXEL_UNPACK_BUFFER, 0); - - if (context) - context_release(context); - - desc.Format = format->ddi_format; - desc.Width = wined3d_texture_get_level_width(texture, surface->texture_level); - desc.Height = wined3d_texture_get_level_height(texture, surface->texture_level); - desc.Pitch = row_pitch; - desc.hDeviceDc = CreateCompatibleDC(NULL); - desc.pColorTable = NULL; - - status = D3DKMTCreateDCFromMemory(&desc); - DeleteDC(desc.hDeviceDc); - if (status) - { - WARN("Failed to create DC, status %#x.\n", status); - return WINED3DERR_INVALIDCALL; - } - - surface->dc = desc.hDc; - surface->bitmap = desc.hBitmap; - - TRACE("Created DC %p, bitmap %p for surface %p.\n", surface->dc, surface->bitmap, surface); - - return WINED3D_OK; -} - static BOOL surface_is_full_rect(const struct wined3d_surface *surface, const RECT *r) { unsigned int t; @@ -1027,11 +929,11 @@ } } -static BOOL surface_check_block_align_rect(struct wined3d_surface *surface, const RECT *rect) +static BOOL wined3d_surface_check_rect_dimensions(struct wined3d_surface *surface, const RECT *rect) { struct wined3d_box box = {rect->left, rect->top, rect->right, rect->bottom, 0, 1}; - return wined3d_texture_check_block_align(surface->container, surface->texture_level, &box); + return SUCCEEDED(wined3d_texture_check_box_dimensions(surface->container, surface->texture_level, &box)); } HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point, @@ -1044,12 +946,10 @@ unsigned int src_row_pitch, src_slice_pitch; const struct wined3d_format *src_format; const struct wined3d_format *dst_format; - unsigned int src_fmt_flags, dst_fmt_flags; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; struct wined3d_bo_address data; UINT update_w, update_h; - UINT dst_w, dst_h; RECT r, dst_rect; POINT p; @@ -1059,8 +959,6 @@ src_format = src_texture->resource.format; dst_format = dst_texture->resource.format; - src_fmt_flags = src_texture->resource.format_flags; - dst_fmt_flags = dst_texture->resource.format_flags; if (src_format->id != dst_format->id) { @@ -1086,41 +984,26 @@ wined3d_texture_get_level_height(src_texture, src_surface->texture_level)); src_rect = &r; } - else if (src_rect->left < 0 || src_rect->top < 0 || IsRectEmpty(src_rect)) - { - WARN("Invalid source rectangle.\n"); - return WINED3DERR_INVALIDCALL; - } - - dst_w = wined3d_texture_get_level_width(dst_texture, dst_surface->texture_level); - dst_h = wined3d_texture_get_level_height(dst_texture, dst_surface->texture_level); - - update_w = src_rect->right - src_rect->left; - update_h = src_rect->bottom - src_rect->top; - - if (update_w > dst_w || dst_point->x > dst_w - update_w - || update_h > dst_h || dst_point->y > dst_h - update_h) - { - WARN("Destination out of bounds.\n"); - return WINED3DERR_INVALIDCALL; - } - if ((src_fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align_rect(src_surface, src_rect)) + if (!wined3d_surface_check_rect_dimensions(src_surface, src_rect)) { WARN("Source rectangle not block-aligned.\n"); return WINED3DERR_INVALIDCALL; } + update_w = src_rect->right - src_rect->left; + update_h = src_rect->bottom - src_rect->top; SetRect(&dst_rect, dst_point->x, dst_point->y, dst_point->x + update_w, dst_point->y + update_h); - if ((dst_fmt_flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align_rect(dst_surface, &dst_rect)) + if (!wined3d_surface_check_rect_dimensions(dst_surface, &dst_rect)) { WARN("Destination rectangle not block-aligned.\n"); return WINED3DERR_INVALIDCALL; } - /* Use wined3d_surface_blt() instead of uploading directly if we need conversion. */ + /* Use wined3d_texture_blt() instead of uploading directly if we need conversion. */ if (dst_format->convert || wined3d_format_get_color_key_conversion(dst_texture, FALSE)) - return wined3d_surface_blt(dst_surface, &dst_rect, src_surface, src_rect, 0, NULL, WINED3D_TEXF_POINT); + return wined3d_texture_blt(dst_texture, dst_sub_resource_idx, &dst_rect, + src_texture, src_sub_resource_idx, src_rect, 0, NULL, WINED3D_TEXF_POINT); context = context_acquire(dst_texture->resource.device, NULL, 0); gl_info = context->gl_info; @@ -1128,7 +1011,8 @@ /* Only load the surface for partial updates. For newly allocated texture * the texture wouldn't be the current location, and we'd upload zeroes * just to overwrite them again. */ - if (update_w == dst_w && update_h == dst_h) + if (update_w == wined3d_texture_get_level_width(dst_texture, dst_surface->texture_level) + && update_h == wined3d_texture_get_level_height(dst_texture, dst_surface->texture_level)) wined3d_texture_prepare_texture(dst_texture, context, FALSE); else wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); @@ -2896,16 +2780,13 @@ return WINED3D_OK; } -static void ffp_blit_blit_surface(struct wined3d_device *device, enum wined3d_blit_op op, DWORD filter, - struct wined3d_surface *src_surface, const RECT *src_rect, +static void ffp_blit_blit_surface(struct wined3d_device *device, enum wined3d_blit_op op, + struct wined3d_context *context, struct wined3d_surface *src_surface, const RECT *src_rect, struct wined3d_surface *dst_surface, const RECT *dst_rect, - const struct wined3d_color_key *color_key) + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) { - unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface); - struct wined3d_texture *dst_texture = dst_surface->container; struct wined3d_texture *src_texture = src_surface->container; - const struct wined3d_gl_info *gl_info; - struct wined3d_context *context; + const struct wined3d_gl_info *gl_info = context->gl_info; /* Blit from offscreen surface to render target */ struct wined3d_color_key old_blt_key = src_texture->async.src_blt_color_key; @@ -2915,9 +2796,6 @@ wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT, color_key); - context = context_acquire(device, dst_texture, dst_sub_resource_idx); - gl_info = context->gl_info; - if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST) gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST); @@ -2927,14 +2805,9 @@ if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST) gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST); - context_release(context); - /* Restore the color key parameters */ wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT, (old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_blt_key : NULL); - - wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, dst_texture->resource.draw_binding); - wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~dst_texture->resource.draw_binding); } const struct blit_shader ffp_blit = { @@ -3183,22 +3056,6 @@ goto release; } - if (!wined3d_texture_check_block_align(src_texture, - src_sub_resource_idx % src_texture->level_count, src_box)) - { - WARN("Source rectangle not block-aligned.\n"); - hr = WINED3DERR_INVALIDCALL; - goto release; - } - - if (!wined3d_texture_check_block_align(dst_texture, - dst_sub_resource_idx % dst_texture->level_count, dst_box)) - { - WARN("Destination rectangle not block-aligned.\n"); - hr = WINED3DERR_INVALIDCALL; - goto release; - } - hr = surface_cpu_blt_compressed(sbase, dbuf, src_map.row_pitch, dst_map.row_pitch, dst_width, dst_height, src_format, flags, fx); @@ -3598,10 +3455,10 @@ &box, NULL, 0, &src_box, WINED3D_BLT_DEPTH_FILL, &fx, WINED3D_TEXF_POINT); } -static void cpu_blit_blit_surface(struct wined3d_device *device, enum wined3d_blit_op op, DWORD filter, - struct wined3d_surface *src_surface, const RECT *src_rect, +static void cpu_blit_blit_surface(struct wined3d_device *device, enum wined3d_blit_op op, + struct wined3d_context *context, struct wined3d_surface *src_surface, const RECT *src_rect, struct wined3d_surface *dst_surface, const RECT *dst_rect, - const struct wined3d_color_key *color_key) + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) { /* FIXME: Remove error returns from surface_blt_cpu. */ ERR("Blit method not implemented by cpu_blit.\n"); @@ -3629,7 +3486,6 @@ struct wined3d_device *device = dst_texture->resource.device; struct wined3d_swapchain *src_swapchain, *dst_swapchain; struct wined3d_texture *src_texture = NULL; - unsigned int dst_w, dst_h, src_w, src_h; unsigned int src_sub_resource_idx = 0; DWORD src_ds_flags, dst_ds_flags; BOOL scale, convert; @@ -3666,38 +3522,6 @@ src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); } - if (dst_texture->sub_resources[dst_sub_resource_idx].map_count - || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count)) - { - WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n"); - return WINEDDERR_SURFACEBUSY; - } - - dst_w = wined3d_texture_get_level_width(dst_texture, dst_surface->texture_level); - dst_h = wined3d_texture_get_level_height(dst_texture, dst_surface->texture_level); - if (IsRectEmpty(dst_rect) || dst_rect->left > dst_w || dst_rect->left < 0 - || dst_rect->top > dst_h || dst_rect->top < 0 - || dst_rect->right > dst_w || dst_rect->right < 0 - || dst_rect->bottom > dst_h || dst_rect->bottom < 0) - { - WARN("The application gave us a bad destination rectangle.\n"); - return WINEDDERR_INVALIDRECT; - } - - if (src_texture) - { - src_w = wined3d_texture_get_level_width(src_texture, src_surface->texture_level); - src_h = wined3d_texture_get_level_height(src_texture, src_surface->texture_level); - if (IsRectEmpty(src_rect) || src_rect->left > src_w || src_rect->left < 0 - || src_rect->top > src_h || src_rect->top < 0 - || src_rect->right > src_w || src_rect->right < 0 - || src_rect->bottom > src_h || src_rect->bottom < 0) - { - WARN("The application gave us a bad source rectangle.\n"); - return WINEDDERR_INVALIDRECT; - } - } - if (!fx || !(fx->fx)) flags &= ~WINED3D_BLT_FX; @@ -3790,17 +3614,10 @@ if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, dst_rect, color.r))) return WINED3D_OK; } - else + else if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_texture->resource.draw_binding, + src_rect, dst_surface, dst_texture->resource.draw_binding, dst_rect))) { - if (src_ds_flags != dst_ds_flags) - { - WARN("Rejecting depth / stencil blit between incompatible formats.\n"); - return WINED3DERR_INVALIDCALL; - } - - if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_texture->resource.draw_binding, - src_rect, dst_surface, dst_texture->resource.draw_binding, dst_rect))) - return WINED3D_OK; + return WINED3D_OK; } } else @@ -3933,8 +3750,18 @@ dst_rect, dst_texture->resource.usage, dst_texture->resource.pool, dst_texture->resource.format); if (blitter) { - blitter->blit_surface(device, blit_op, filter, src_surface, - src_rect, dst_surface, dst_rect, color_key); + struct wined3d_context *context; + + context = context_acquire(device, dst_texture, dst_sub_resource_idx); + blitter->blit_surface(device, blit_op, context, src_surface, + src_rect, dst_surface, dst_rect, color_key, filter); + context_release(context); + + wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, + dst_texture->resource.draw_binding); + wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, + ~dst_texture->resource.draw_binding); + return WINED3D_OK; } } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/texture.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/texture.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/texture.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/texture.c 2017-03-21 14:02:57.000000000 +0000 @@ -435,16 +435,16 @@ static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture, unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info) { - GLuint *buffer_object; + GLuint *buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object; - buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object; GL_EXTCALL(glDeleteBuffers(1, buffer_object)); checkGLcall("glDeleteBuffers"); - wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); - *buffer_object = 0; TRACE("Deleted buffer object %u for texture %p, sub-resource %u.\n", *buffer_object, texture, sub_resource_idx); + + wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); + *buffer_object = 0; } static void wined3d_texture_update_map_binding(struct wined3d_texture *texture) @@ -815,7 +815,7 @@ * called from sampler() in state.c. This means we can't touch anything * other than whatever happens to be the currently active texture, or we * would risk marking already applied sampler states dirty again. */ - if (context->active_texture < MAX_COMBINED_SAMPLERS) + if (context->active_texture < ARRAY_SIZE(context->rev_tex_unit_map)) { DWORD active_sampler = context->rev_tex_unit_map[context->active_texture]; if (active_sampler != WINED3D_UNMAPPED_STAGE) @@ -1063,20 +1063,44 @@ return texture->resource.parent; } -static BOOL wined3d_texture_check_box_dimensions(const struct wined3d_texture *texture, +HRESULT wined3d_texture_check_box_dimensions(const struct wined3d_texture *texture, unsigned int level, const struct wined3d_box *box) { - if (box->left >= box->right - || box->top >= box->bottom - || box->front >= box->back) - return FALSE; + const struct wined3d_format *format = texture->resource.format; + unsigned int width_mask, height_mask, width, height, depth; - if (box->right > wined3d_texture_get_level_width(texture, level) - || box->bottom > wined3d_texture_get_level_height(texture, level) - || box->back > wined3d_texture_get_level_depth(texture, level)) - return FALSE; + width = wined3d_texture_get_level_width(texture, level); + height = wined3d_texture_get_level_height(texture, level); + depth = wined3d_texture_get_level_depth(texture, level); - return TRUE; + if (box->left >= box->right || box->right > width + || box->top >= box->bottom || box->bottom > height + || box->front >= box->back || box->back > depth) + { + WARN("Box %s is invalid.\n", debug_box(box)); + return WINEDDERR_INVALIDRECT; + } + + if (texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) + { + /* This assumes power of two block sizes, but NPOT block sizes would + * be silly anyway. + * + * This also assumes that the format's block depth is 1. */ + width_mask = format->block_width - 1; + height_mask = format->block_height - 1; + + if ((box->left & width_mask) || (box->top & height_mask) + || (box->right & width_mask && box->right != width) + || (box->bottom & height_mask && box->bottom != height)) + { + WARN("Box %s is misaligned for %ux%u blocks.\n", + debug_box(box), format->block_width, format->block_height); + return WINED3DERR_INVALIDCALL; + } + } + + return WINED3D_OK; } void CDECL wined3d_texture_get_pitch(const struct wined3d_texture *texture, @@ -1116,13 +1140,16 @@ if (texture->lod != lod) { + struct wined3d_device *device = texture->resource.device; + wined3d_resource_wait_idle(&texture->resource); texture->lod = lod; texture->texture_rgb.base_level = ~0u; texture->texture_srgb.base_level = ~0u; if (texture->resource.bind_count) - device_invalidate_state(texture->resource.device, STATE_SAMPLER(texture->sampler)); + wined3d_cs_emit_set_sampler_state(device->cs, texture->sampler, WINED3D_SAMP_MAX_MIP_LEVEL, + device->state.sampler_states[texture->sampler][WINED3D_SAMP_MAX_MIP_LEVEL]); } return old; @@ -1185,6 +1212,114 @@ return WINED3D_OK; } +static void texture2d_create_dc(void *object) +{ + const struct wined3d_gl_info *gl_info = NULL; + struct wined3d_surface *surface = object; + struct wined3d_context *context = NULL; + const struct wined3d_format *format; + unsigned int row_pitch, slice_pitch; + struct wined3d_texture *texture; + struct wined3d_bo_address data; + D3DKMT_CREATEDCFROMMEMORY desc; + unsigned int sub_resource_idx; + struct wined3d_device *device; + NTSTATUS status; + + TRACE("surface %p.\n", surface); + + texture = surface->container; + sub_resource_idx = surface_get_sub_resource_idx(surface); + device = texture->resource.device; + + format = texture->resource.format; + if (!format->ddi_format) + { + WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id)); + return; + } + + if (device->d3d_initialized) + { + context = context_acquire(device, NULL, 0); + gl_info = context->gl_info; + } + + wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); + wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); + wined3d_texture_get_pitch(texture, surface->texture_level, &row_pitch, &slice_pitch); + wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); + desc.pMemory = wined3d_texture_map_bo_address(&data, texture->sub_resources[sub_resource_idx].size, + gl_info, GL_PIXEL_UNPACK_BUFFER, 0); + + if (context) + context_release(context); + + desc.Format = format->ddi_format; + desc.Width = wined3d_texture_get_level_width(texture, surface->texture_level); + desc.Height = wined3d_texture_get_level_height(texture, surface->texture_level); + desc.Pitch = row_pitch; + desc.hDeviceDc = CreateCompatibleDC(NULL); + desc.pColorTable = NULL; + + status = D3DKMTCreateDCFromMemory(&desc); + DeleteDC(desc.hDeviceDc); + if (status) + { + WARN("Failed to create DC, status %#x.\n", status); + return; + } + + surface->dc = desc.hDc; + surface->bitmap = desc.hBitmap; + + TRACE("Created DC %p, bitmap %p for surface %p.\n", surface->dc, surface->bitmap, surface); +} + +static void texture2d_destroy_dc(void *object) +{ + const struct wined3d_gl_info *gl_info = NULL; + struct wined3d_surface *surface = object; + D3DKMT_DESTROYDCFROMMEMORY destroy_desc; + struct wined3d_context *context = NULL; + struct wined3d_texture *texture; + struct wined3d_bo_address data; + unsigned int sub_resource_idx; + struct wined3d_device *device; + NTSTATUS status; + + texture = surface->container; + sub_resource_idx = surface_get_sub_resource_idx(surface); + device = texture->resource.device; + + if (!surface->dc) + { + ERR("Surface %p has no DC.\n", surface); + return; + } + + TRACE("dc %p, bitmap %p.\n", surface->dc, surface->bitmap); + + destroy_desc.hDc = surface->dc; + destroy_desc.hBitmap = surface->bitmap; + if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc))) + ERR("Failed to destroy dc, status %#x.\n", status); + surface->dc = NULL; + surface->bitmap = NULL; + + if (device->d3d_initialized) + { + context = context_acquire(device, NULL, 0); + gl_info = context->gl_info; + } + + wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); + wined3d_texture_unmap_bo_address(&data, gl_info, GL_PIXEL_UNPACK_BUFFER); + + if (context) + context_release(context); +} + HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT width, UINT height, enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type, UINT multisample_quality, void *mem, UINT pitch) @@ -1244,7 +1379,7 @@ surface = sub_resource->u.surface; if (surface->dc) { - wined3d_surface_destroy_dc(surface); + wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); create_dib = TRUE; } @@ -1305,7 +1440,7 @@ wined3d_texture_invalidate_location(texture, 0, ~valid_location); if (create_dib) - wined3d_surface_create_dc(surface); + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); return WINED3D_OK; } @@ -1656,7 +1791,7 @@ } if (surface->dc) - wined3d_surface_destroy_dc(surface); + texture2d_destroy_dc(surface); if (surface->overlay_dest) list_remove(&surface->overlay_entry); @@ -1788,19 +1923,11 @@ return E_INVALIDARG; texture_level = sub_resource_idx % texture->level_count; - if (box && !wined3d_texture_check_box_dimensions(texture, texture_level, box)) + if (box && FAILED(wined3d_texture_check_box_dimensions(texture, texture_level, box))) { WARN("Map box is invalid.\n"); - if (resource->type != WINED3D_RTYPE_TEXTURE_2D) - return WINED3DERR_INVALIDCALL; - } - - if ((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && box - && !wined3d_texture_check_block_align(texture, texture_level, box)) - { - WARN("Map box %s is misaligned for %ux%u blocks.\n", - debug_box(box), format->block_width, format->block_height); - if (resource->type != WINED3D_RTYPE_TEXTURE_2D || resource->pool == WINED3D_POOL_DEFAULT) + if (((fmt_flags & WINED3DFMT_FLAG_BLOCKS) && resource->pool == WINED3D_POOL_DEFAULT) + || resource->type != WINED3D_RTYPE_TEXTURE_2D) return WINED3DERR_INVALIDCALL; } @@ -2187,11 +2314,14 @@ TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface); - if (((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) - && FAILED(hr = wined3d_surface_create_dc(surface))) + if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) { - wined3d_texture_cleanup_sync(texture); - return hr; + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); + if (!surface->dc) + { + wined3d_texture_cleanup_sync(texture); + return WINED3DERR_INVALIDCALL; + } } } } @@ -2483,35 +2613,6 @@ texture3d_cleanup_sub_resources, }; -BOOL wined3d_texture_check_block_align(const struct wined3d_texture *texture, - unsigned int level, const struct wined3d_box *box) -{ - const struct wined3d_format *format = texture->resource.format; - unsigned int height = wined3d_texture_get_level_height(texture, level); - unsigned int width = wined3d_texture_get_level_width(texture, level); - unsigned int width_mask, height_mask; - - if ((box->left >= box->right) - || (box->top >= box->bottom) - || (box->right > width) - || (box->bottom > height)) - return FALSE; - - /* This assumes power of two block sizes, but NPOT block sizes would be - * silly anyway. - * - * This also assumes that the format's block depth is 1. */ - width_mask = format->block_width - 1; - height_mask = format->block_height - 1; - - if ((box->left & width_mask) || (box->top & height_mask) - || (box->right & width_mask && box->right != width) - || (box->bottom & height_mask && box->bottom != height)) - return FALSE; - - return TRUE; -} - static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, UINT layer_count, UINT level_count, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops) @@ -2640,26 +2741,62 @@ const RECT *dst_rect, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) { - struct wined3d_texture_sub_resource *dst_resource, *src_resource = NULL; + struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1}; + struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1}; + unsigned int dst_format_flags, src_format_flags = 0; + HRESULT hr; TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_rect %s, src_texture %p, " "src_sub_resource_idx %u, src_rect %s, flags %#x, fx %p, filter %s.\n", dst_texture, dst_sub_resource_idx, wine_dbgstr_rect(dst_rect), src_texture, src_sub_resource_idx, wine_dbgstr_rect(src_rect), flags, fx, debug_d3dtexturefiltertype(filter)); - if (!(dst_resource = wined3d_texture_get_sub_resource(dst_texture, dst_sub_resource_idx)) + if (dst_sub_resource_idx >= dst_texture->level_count * dst_texture->layer_count || dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_2D) return WINED3DERR_INVALIDCALL; + dst_format_flags = dst_texture->resource.format_flags; + if (FAILED(hr = wined3d_texture_check_box_dimensions(dst_texture, + dst_sub_resource_idx % dst_texture->level_count, &dst_box))) + return hr; + if (src_texture) { - if (!(src_resource = wined3d_texture_get_sub_resource(src_texture, src_sub_resource_idx)) + if (src_sub_resource_idx >= src_texture->level_count * src_texture->layer_count || src_texture->resource.type != WINED3D_RTYPE_TEXTURE_2D) return WINED3DERR_INVALIDCALL; + + src_format_flags = src_texture->resource.format_flags; + if (FAILED(hr = wined3d_texture_check_box_dimensions(src_texture, + src_sub_resource_idx % src_texture->level_count, &src_box))) + return hr; + } + + if (dst_texture->sub_resources[dst_sub_resource_idx].map_count + || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count)) + { + WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n"); + return WINEDDERR_SURFACEBUSY; + } + + if ((dst_format_flags & WINED3DFMT_FLAG_BLOCKS) && (flags & WINED3D_BLT_COLOR_FILL)) + { + WARN("Color fill not supported on block-based formats.\n"); + return WINED3DERR_INVALIDCALL; + } + + if ((src_format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) + != (dst_format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) + && !(flags & WINED3D_BLT_DEPTH_FILL)) + { + WARN("Rejecting depth/stencil blit between incompatible formats.\n"); + return WINED3DERR_INVALIDCALL; } - return wined3d_surface_blt(dst_resource->u.surface, dst_rect, - src_resource ? src_resource->u.surface : NULL, src_rect, flags, fx, filter); + wined3d_cs_emit_blt_sub_resource(dst_texture->resource.device->cs, &dst_texture->resource, dst_sub_resource_idx, + &dst_box, src_texture ? &src_texture->resource : NULL, src_sub_resource_idx, &src_box, flags, fx, filter); + + return WINED3D_OK; } HRESULT CDECL wined3d_texture_get_overlay_position(const struct wined3d_texture *texture, @@ -2958,9 +3095,7 @@ { struct wined3d_device *device = texture->resource.device; struct wined3d_texture_sub_resource *sub_resource; - struct wined3d_context *context = NULL; struct wined3d_surface *surface; - HRESULT hr = WINED3D_OK; TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc); @@ -2985,17 +3120,9 @@ if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) return WINED3DERR_INVALIDCALL; - if (device->d3d_initialized) - context = context_acquire(device, NULL, 0); - - wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); - wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); - if (!surface->dc) - hr = wined3d_surface_create_dc(surface); - if (context) - context_release(context); - if (FAILED(hr)) + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); + if (!surface->dc) return WINED3DERR_INVALIDCALL; if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) @@ -3006,7 +3133,7 @@ *dc = surface->dc; TRACE("Returning dc %p.\n", *dc); - return hr; + return WINED3D_OK; } HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc) @@ -3038,7 +3165,7 @@ } if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D)) - wined3d_surface_destroy_dc(surface); + wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); --sub_resource->map_count; if (!--texture->resource.map_count && texture->update_map_binding) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/utils.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/utils.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/utils.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/utils.c 2017-03-21 14:02:57.000000000 +0000 @@ -2759,7 +2759,7 @@ } else { - if (!gl_info->limits.vertex_samplers) + if (!gl_info->limits.samplers[WINED3D_SHADER_TYPE_VERTEX]) format_clear_flag(format, WINED3DFMT_FLAG_VTF); if (!(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING)) @@ -2803,6 +2803,7 @@ { if (gl_info->supported[ARB_INTERNALFORMAT_QUERY]) { + count = 0; GL_EXTCALL(glGetInternalformativ(GL_RENDERBUFFER, format->glInternal, GL_NUM_SAMPLE_COUNTS, 1, &count)); checkGLcall("glGetInternalformativ(GL_NUM_SAMPLE_COUNTS)"); @@ -5994,18 +5995,29 @@ void wined3d_gl_limits_get_texture_unit_range(const struct wined3d_gl_limits *gl_limits, enum wined3d_shader_type shader_type, unsigned int *base, unsigned int *count) { - if (shader_type != WINED3D_SHADER_TYPE_COMPUTE) + unsigned int i; + + if (shader_type == WINED3D_SHADER_TYPE_COMPUTE) { - *base = *count = 0; - ERR("Unhandled shader type %#x.\n", shader_type); + if (gl_limits->combined_samplers == gl_limits->graphics_samplers) + *base = 0; + else + *base = gl_limits->graphics_samplers; + *count = gl_limits->samplers[WINED3D_SHADER_TYPE_COMPUTE]; return; } - if (gl_limits->combined_samplers == gl_limits->graphics_samplers) - *base = 0; - else - *base = gl_limits->graphics_samplers - 1; - *count = gl_limits->compute_samplers; + *base = 0; + for (i = 0; i < WINED3D_SHADER_TYPE_GRAPHICS_COUNT; ++i) + { + *count = gl_limits->samplers[i]; + if (i == shader_type) + return; + *base += *count; + } + + ERR("Unrecognized shader type %#x.\n", shader_type); + *count = 0; } BOOL wined3d_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/wined3d_gl.h wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/wined3d_gl.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/wined3d_gl.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/wined3d_gl.h 2017-03-21 14:02:57.000000000 +0000 @@ -80,6 +80,7 @@ ARB_POINT_SPRITE, ARB_PROVOKING_VERTEX, ARB_SAMPLER_OBJECTS, + ARB_SEAMLESS_CUBE_MAP, ARB_SHADER_ATOMIC_COUNTERS, ARB_SHADER_BIT_ENCODING, ARB_SHADER_IMAGE_LOAD_STORE, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/wined3d_private.h wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/wined3d_private.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/wined3d_private.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/wined3d_private.h 2017-03-21 14:02:57.000000000 +0000 @@ -72,6 +72,49 @@ #define WINED3D_QUIRK_LIMITED_TEX_FILTERING 0x00000100 #define WINED3D_QUIRK_BROKEN_ARB_FOG 0x00000200 +enum wined3d_ffp_idx +{ + WINED3D_FFP_POSITION = 0, + WINED3D_FFP_BLENDWEIGHT = 1, + WINED3D_FFP_BLENDINDICES = 2, + WINED3D_FFP_NORMAL = 3, + WINED3D_FFP_PSIZE = 4, + WINED3D_FFP_DIFFUSE = 5, + WINED3D_FFP_SPECULAR = 6, + WINED3D_FFP_TEXCOORD0 = 7, + WINED3D_FFP_TEXCOORD1 = 8, + WINED3D_FFP_TEXCOORD2 = 9, + WINED3D_FFP_TEXCOORD3 = 10, + WINED3D_FFP_TEXCOORD4 = 11, + WINED3D_FFP_TEXCOORD5 = 12, + WINED3D_FFP_TEXCOORD6 = 13, + WINED3D_FFP_TEXCOORD7 = 14, + WINED3D_FFP_ATTRIBS_COUNT = 15, +}; + +enum wined3d_ffp_emit_idx +{ + WINED3D_FFP_EMIT_FLOAT1, + WINED3D_FFP_EMIT_FLOAT2, + WINED3D_FFP_EMIT_FLOAT3, + WINED3D_FFP_EMIT_FLOAT4, + WINED3D_FFP_EMIT_D3DCOLOR, + WINED3D_FFP_EMIT_UBYTE4, + WINED3D_FFP_EMIT_SHORT2, + WINED3D_FFP_EMIT_SHORT4, + WINED3D_FFP_EMIT_UBYTE4N, + WINED3D_FFP_EMIT_SHORT2N, + WINED3D_FFP_EMIT_SHORT4N, + WINED3D_FFP_EMIT_USHORT2N, + WINED3D_FFP_EMIT_USHORT4N, + WINED3D_FFP_EMIT_UDEC3, + WINED3D_FFP_EMIT_DEC3N, + WINED3D_FFP_EMIT_FLOAT16_2, + WINED3D_FFP_EMIT_FLOAT16_4, + WINED3D_FFP_EMIT_INVALID, + WINED3D_FFP_EMIT_COUNT, +}; + /* Texture format fixups */ enum fixup_channel_source @@ -110,6 +153,47 @@ }; #include +struct wined3d_d3d_limits +{ + unsigned int vs_version, hs_version, ds_version, gs_version, ps_version, cs_version; + DWORD vs_uniform_count; + DWORD ps_uniform_count; + unsigned int varying_count; + unsigned int ffp_textures; + unsigned int ffp_blend_stages; + unsigned int ffp_vertex_blend_matrices; + unsigned int active_light_count; +}; + +typedef void (WINE_GLAPI *wined3d_ffp_attrib_func)(const void *data); +typedef void (WINE_GLAPI *wined3d_ffp_texcoord_func)(GLenum unit, const void *data); +typedef void (WINE_GLAPI *wined3d_generic_attrib_func)(GLuint idx, const void *data); +extern wined3d_ffp_attrib_func specular_func_3ubv DECLSPEC_HIDDEN; + +struct wined3d_ffp_attrib_ops +{ + wined3d_ffp_attrib_func position[WINED3D_FFP_EMIT_COUNT]; + wined3d_ffp_attrib_func diffuse[WINED3D_FFP_EMIT_COUNT]; + wined3d_ffp_attrib_func specular[WINED3D_FFP_EMIT_COUNT]; + wined3d_ffp_attrib_func normal[WINED3D_FFP_EMIT_COUNT]; + wined3d_ffp_texcoord_func texcoord[WINED3D_FFP_EMIT_COUNT]; + wined3d_generic_attrib_func generic[WINED3D_FFP_EMIT_COUNT]; +}; + +struct wined3d_d3d_info +{ + struct wined3d_d3d_limits limits; + struct wined3d_ffp_attrib_ops ffp_attrib_ops; + BOOL xyzrhw; + BOOL emulated_flatshading; + BOOL ffp_generic_attributes; + BOOL vs_clipping; + BOOL shader_color_key; + DWORD valid_rt_mask; + DWORD wined3d_creation_flags; + BOOL shader_double_precision; +}; + static const struct color_fixup_desc COLOR_FIXUP_IDENTITY = {0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_W}; @@ -478,8 +562,8 @@ enum wined3d_shader_uav_flags { - WINED3DSUF_GLOBALLY_COHERENT = 0x20, - WINED3DSUF_ORDER_PRESERVING_COUNTER = 0x8000, + WINED3DSUF_GLOBALLY_COHERENT = 0x2, + WINED3DSUF_ORDER_PRESERVING_COUNTER = 0x100, }; enum wined3d_tessellator_domain @@ -611,6 +695,7 @@ WINED3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, WINED3DSIH_DCL_HS_MAX_TESSFACTOR, WINED3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER, + WINED3DSIH_DCL_INDEX_RANGE, WINED3DSIH_DCL_INDEXABLE_TEMP, WINED3DSIH_DCL_INPUT, WINED3DSIH_DCL_INPUT_CONTROL_POINT_COUNT, @@ -799,6 +884,7 @@ WINED3DSIH_ULT, WINED3DSIH_UMAX, WINED3DSIH_UMIN, + WINED3DSIH_UMUL, WINED3DSIH_USHR, WINED3DSIH_UTOF, WINED3DSIH_XOR, @@ -985,6 +1071,12 @@ enum wined3d_shader_src_modifier modifiers; }; +struct wined3d_shader_index_range +{ + struct wined3d_shader_dst_param first_register; + unsigned int last_register; +}; + struct wined3d_shader_semantic { enum wined3d_decl_usage usage; @@ -1073,6 +1165,7 @@ enum wined3d_tessellator_output_primitive tessellator_output_primitive; enum wined3d_tessellator_partitioning tessellator_partitioning; float max_tessellation_factor; + struct wined3d_shader_index_range index_range; struct wined3d_shader_indexable_temp indexable_temp; struct wined3d_shader_function_table_pointer fp; } declaration; @@ -1288,49 +1381,6 @@ #define checkGLcall(A) do {} while(0) #endif -enum wined3d_ffp_idx -{ - WINED3D_FFP_POSITION = 0, - WINED3D_FFP_BLENDWEIGHT = 1, - WINED3D_FFP_BLENDINDICES = 2, - WINED3D_FFP_NORMAL = 3, - WINED3D_FFP_PSIZE = 4, - WINED3D_FFP_DIFFUSE = 5, - WINED3D_FFP_SPECULAR = 6, - WINED3D_FFP_TEXCOORD0 = 7, - WINED3D_FFP_TEXCOORD1 = 8, - WINED3D_FFP_TEXCOORD2 = 9, - WINED3D_FFP_TEXCOORD3 = 10, - WINED3D_FFP_TEXCOORD4 = 11, - WINED3D_FFP_TEXCOORD5 = 12, - WINED3D_FFP_TEXCOORD6 = 13, - WINED3D_FFP_TEXCOORD7 = 14, - WINED3D_FFP_ATTRIBS_COUNT = 15, -}; - -enum wined3d_ffp_emit_idx -{ - WINED3D_FFP_EMIT_FLOAT1, - WINED3D_FFP_EMIT_FLOAT2, - WINED3D_FFP_EMIT_FLOAT3, - WINED3D_FFP_EMIT_FLOAT4, - WINED3D_FFP_EMIT_D3DCOLOR, - WINED3D_FFP_EMIT_UBYTE4, - WINED3D_FFP_EMIT_SHORT2, - WINED3D_FFP_EMIT_SHORT4, - WINED3D_FFP_EMIT_UBYTE4N, - WINED3D_FFP_EMIT_SHORT2N, - WINED3D_FFP_EMIT_SHORT4N, - WINED3D_FFP_EMIT_USHORT2N, - WINED3D_FFP_EMIT_USHORT4N, - WINED3D_FFP_EMIT_UDEC3, - WINED3D_FFP_EMIT_DEC3N, - WINED3D_FFP_EMIT_FLOAT16_2, - WINED3D_FFP_EMIT_FLOAT16_4, - WINED3D_FFP_EMIT_INVALID, - WINED3D_FFP_EMIT_COUNT -}; - struct wined3d_bo_address { GLuint buffer_object; @@ -1366,6 +1416,10 @@ WORD use_map; /* MAX_ATTRIBS, 16 */ }; +void wined3d_stream_info_from_declaration(struct wined3d_stream_info *stream_info, + const struct wined3d_state *state, const struct wined3d_gl_info *gl_info, + const struct wined3d_d3d_info *d3d_info) DECLSPEC_HIDDEN; + void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, int base_vertex_idx, unsigned int start_idx, unsigned int index_count, unsigned int start_instance, unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN; @@ -1575,6 +1629,8 @@ void context_alloc_timestamp_query(struct wined3d_context *context, struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN; void context_free_timestamp_query(struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN; +#define MAX_GL_FRAGMENT_SAMPLERS 32 + struct wined3d_context { const struct wined3d_gl_info *gl_info; @@ -1694,8 +1750,8 @@ struct wined3d_event_query *buffer_queries[MAX_ATTRIBS]; unsigned int num_buffer_queries; - DWORD tex_unit_map[MAX_COMBINED_SAMPLERS]; - DWORD rev_tex_unit_map[MAX_COMBINED_SAMPLERS]; + DWORD tex_unit_map[MAX_COMBINED_SAMPLERS]; + DWORD rev_tex_unit_map[MAX_GL_FRAGMENT_SAMPLERS + MAX_VERTEX_SAMPLERS]; /* Extension emulation */ GLint gl_fog_source; @@ -1824,10 +1880,10 @@ const RECT *rect, const struct wined3d_color *color); HRESULT (*depth_fill)(struct wined3d_device *device, struct wined3d_rendertarget_view *view, const RECT *rect, DWORD clear_flags, float depth, DWORD stencil); - void (*blit_surface)(struct wined3d_device *device, enum wined3d_blit_op op, DWORD filter, + void (*blit_surface)(struct wined3d_device *device, enum wined3d_blit_op op, struct wined3d_context *context, struct wined3d_surface *src_surface, const RECT *src_rect, struct wined3d_surface *dst_surface, const RECT *dst_rect, - const struct wined3d_color_key *color_key); + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter); }; extern const struct blit_shader ffp_blit DECLSPEC_HIDDEN; @@ -1870,6 +1926,8 @@ void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN; GLenum context_get_offscreen_gl_buffer(const struct wined3d_context *context) DECLSPEC_HIDDEN; +const DWORD *context_get_tex_unit_mapping(const struct wined3d_context *context, + const struct wined3d_shader_version *shader_version, unsigned int *base, unsigned int *count) DECLSPEC_HIDDEN; DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN; void context_gl_resource_released(struct wined3d_device *device, GLuint name, BOOL rb_namespace) DECLSPEC_HIDDEN; @@ -1887,8 +1945,6 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; void context_surface_update(struct wined3d_context *context, const struct wined3d_surface *surface) DECLSPEC_HIDDEN; -void context_stream_info_from_declaration(struct wined3d_context *context, - const struct wined3d_state *state, struct wined3d_stream_info *stream_info) DECLSPEC_HIDDEN; /***************************************************************************** * Internal representation of a light @@ -2092,6 +2148,7 @@ CARD_NVIDIA_GEFORCE_GTX860M = 0x1392, /* Other PCI ID 0x119a */ CARD_NVIDIA_GEFORCE_GTX870M = 0x1199, CARD_NVIDIA_GEFORCE_GTX880M = 0x1198, + CARD_NVIDIA_GEFORCE_940M = 0x1347, CARD_NVIDIA_GEFORCE_GTX950 = 0x1402, CARD_NVIDIA_GEFORCE_GTX950M = 0x139a, CARD_NVIDIA_GEFORCE_GTX960 = 0x1401, @@ -2218,9 +2275,7 @@ UINT textures; UINT texture_coords; unsigned int uniform_blocks[WINED3D_SHADER_TYPE_COUNT]; - unsigned int fragment_samplers; - unsigned int vertex_samplers; - unsigned int compute_samplers; + unsigned int samplers[WINED3D_SHADER_TYPE_COUNT]; unsigned int graphics_samplers; unsigned int combined_samplers; UINT general_combiners; @@ -2287,47 +2342,6 @@ DWORD version_low; }; -struct wined3d_d3d_limits -{ - unsigned int vs_version, hs_version, ds_version, gs_version, ps_version, cs_version; - DWORD vs_uniform_count; - DWORD ps_uniform_count; - UINT varying_count; - UINT ffp_textures; - UINT ffp_blend_stages; - UINT ffp_vertex_blend_matrices; - unsigned int active_light_count; -}; - -typedef void (WINE_GLAPI *wined3d_ffp_attrib_func)(const void *data); -typedef void (WINE_GLAPI *wined3d_ffp_texcoord_func)(GLenum unit, const void *data); -typedef void (WINE_GLAPI *wined3d_generic_attrib_func)(GLuint idx, const void *data); -extern wined3d_ffp_attrib_func specular_func_3ubv DECLSPEC_HIDDEN; - -struct wined3d_ffp_attrib_ops -{ - wined3d_ffp_attrib_func position[WINED3D_FFP_EMIT_COUNT]; - wined3d_ffp_attrib_func diffuse[WINED3D_FFP_EMIT_COUNT]; - wined3d_ffp_attrib_func specular[WINED3D_FFP_EMIT_COUNT]; - wined3d_ffp_attrib_func normal[WINED3D_FFP_EMIT_COUNT]; - wined3d_ffp_texcoord_func texcoord[WINED3D_FFP_EMIT_COUNT]; - wined3d_generic_attrib_func generic[WINED3D_FFP_EMIT_COUNT]; -}; - -struct wined3d_d3d_info -{ - struct wined3d_d3d_limits limits; - struct wined3d_ffp_attrib_ops ffp_attrib_ops; - BOOL xyzrhw; - BOOL emulated_flatshading; - BOOL ffp_generic_attributes; - BOOL vs_clipping; - BOOL shader_color_key; - DWORD valid_rt_mask; - DWORD wined3d_creation_flags; - BOOL shader_double_precision; -}; - /* The adapter structure */ struct wined3d_adapter { @@ -2668,6 +2682,7 @@ GLuint tex_rect; GLuint tex_3d; GLuint tex_cube; + GLuint tex_cube_array; GLuint tex_2d_array; GLuint tex_buffer; } dummy_textures; @@ -2936,7 +2951,7 @@ struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; void wined3d_texture_bind_and_dirtify(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; -BOOL wined3d_texture_check_block_align(const struct wined3d_texture *texture, +HRESULT wined3d_texture_check_box_dimensions(const struct wined3d_texture *texture, unsigned int level, const struct wined3d_box *box) DECLSPEC_HIDDEN; GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) DECLSPEC_HIDDEN; void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int sub_resource_idx, @@ -3046,8 +3061,6 @@ const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN; -HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface) DECLSPEC_HIDDEN; -void wined3d_surface_destroy_dc(struct wined3d_surface *surface) DECLSPEC_HIDDEN; void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, struct wined3d_context *context) DECLSPEC_HIDDEN; BOOL surface_load_location(struct wined3d_surface *surface, @@ -3210,6 +3223,10 @@ void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_destroy_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; +void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *dst_resource, + unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, struct wined3d_resource *src_resource, + unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, DWORD flags, + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, @@ -3269,6 +3286,9 @@ struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; +void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, + unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, + unsigned int slice_pitch) DECLSPEC_HIDDEN; void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx, @@ -3670,7 +3690,7 @@ void string_buffer_free(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN; unsigned int shader_find_free_input_register(const struct wined3d_shader_reg_maps *reg_maps, unsigned int max) DECLSPEC_HIDDEN; -void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, +HRESULT shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps, void *backend_ctx) DECLSPEC_HIDDEN; BOOL shader_match_semantic(const char *semantic_name, enum wined3d_decl_usage usage) DECLSPEC_HIDDEN; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/wined3d.spec wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/wined3d.spec --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wined3d/wined3d.spec 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wined3d/wined3d.spec 2017-03-21 14:02:57.000000000 +0000 @@ -51,7 +51,11 @@ @ cdecl wined3d_device_get_base_vertex_index(ptr) @ cdecl wined3d_device_get_clip_plane(ptr long ptr) @ cdecl wined3d_device_get_clip_status(ptr ptr) +@ cdecl wined3d_device_get_compute_shader(ptr) @ cdecl wined3d_device_get_creation_parameters(ptr ptr) +@ cdecl wined3d_device_get_cs_cb(ptr long) +@ cdecl wined3d_device_get_cs_resource_view(ptr long) +@ cdecl wined3d_device_get_cs_sampler(ptr long) @ cdecl wined3d_device_get_depth_stencil_view(ptr) @ cdecl wined3d_device_get_device_caps(ptr ptr) @ cdecl wined3d_device_get_display_mode(ptr long ptr ptr) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/winemac.drv/cocoa_window.h wine-staging-2.4.0~ubuntu16.04.1/dlls/winemac.drv/cocoa_window.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/winemac.drv/cocoa_window.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/winemac.drv/cocoa_window.h 2017-03-21 14:02:57.000000000 +0000 @@ -81,6 +81,8 @@ NSTimeInterval lastDockIconSnapshot; + BOOL allowKeyRepeats; + BOOL ignore_windowDeminiaturize; BOOL ignore_windowResize; BOOL fakingClose; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/winemac.drv/cocoa_window.m wine-staging-2.4.0~ubuntu16.04.1/dlls/winemac.drv/cocoa_window.m --- wine-staging-2.3.0~ubuntu16.04.1/dlls/winemac.drv/cocoa_window.m 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/winemac.drv/cocoa_window.m 2017-03-21 14:02:57.000000000 +0000 @@ -2424,7 +2424,18 @@ /* * ---------- NSResponder method overrides ---------- */ - - (void) keyDown:(NSEvent *)theEvent { [self postKeyEvent:theEvent]; } + - (void) keyDown:(NSEvent *)theEvent + { + if ([theEvent isARepeat]) + { + if (!allowKeyRepeats) + return; + } + else + allowKeyRepeats = YES; + + [self postKeyEvent:theEvent]; + } - (void) flagsChanged:(NSEvent *)theEvent { @@ -2461,6 +2472,9 @@ { BOOL pressed = (modifierFlags & modifiers[i].mask) != 0; + if (pressed) + allowKeyRepeats = NO; + if (i == last_changed) lastModifierFlags = modifierFlags; else diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wineps.drv/ps.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wineps.drv/ps.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wineps.drv/ps.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wineps.drv/ps.c 2017-03-21 14:02:57.000000000 +0000 @@ -50,6 +50,7 @@ }; static const char cups_collate_false[] = "%cupsJobTicket: collate=false\n"; static const char cups_collate_true[] = "%cupsJobTicket: collate=true\n"; +static const char cups_ap_d_inputslot[] = "%cupsJobTicket: AP_D_InputSlot=\n"; /* intentionally empty value */ static const char psheader[] = /* title llx lly urx ury orientation */ "%%%%Creator: Wine PostScript Driver\n" @@ -375,6 +376,10 @@ write_spool( dev, cups_collate_true, sizeof(cups_collate_true) - 1 ); } } + + if (!(physDev->Devmode->dmPublic.dmFields & DM_DEFAULTSOURCE) || + physDev->Devmode->dmPublic.u1.s1.dmDefaultSource == DMBIN_AUTO) + write_spool( dev, cups_ap_d_inputslot, sizeof(cups_ap_d_inputslot) - 1 ); } INT PSDRV_WriteHeader( PHYSDEV dev, LPCWSTR title ) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/ftp.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/ftp.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/ftp.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/ftp.c 2017-03-21 14:02:57.000000000 +0000 @@ -1184,7 +1184,8 @@ return INET_QueryOption(hdr, option, buffer, size, unicode); } -static DWORD FTPFILE_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read) +static DWORD FTPFILE_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read, + DWORD flags, DWORD_PTR context) { ftp_file_t *file = (ftp_file_t*)hdr; int res; @@ -1208,12 +1209,6 @@ return error; } -static DWORD FTPFILE_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWORD *ret_size, - DWORD flags, DWORD_PTR context) -{ - return FTPFILE_ReadFile(hdr, buf, size, ret_size); -} - static DWORD FTPFILE_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written) { ftp_file_t *lpwh = (ftp_file_t*) hdr; @@ -1300,7 +1295,6 @@ FTPFILE_QueryOption, INET_SetOption, FTPFILE_ReadFile, - FTPFILE_ReadFileEx, FTPFILE_WriteFile, FTPFILE_QueryDataAvailable, NULL, @@ -2404,7 +2398,6 @@ NULL, NULL, NULL, - NULL, NULL }; @@ -3543,7 +3536,6 @@ NULL, NULL, NULL, - NULL, FTPFINDNEXT_FindNextFileW }; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/http.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/http.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/http.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/http.c 2017-03-21 14:02:57.000000000 +0000 @@ -380,16 +380,9 @@ return ret; } -typedef enum { - BLOCKING_ALLOW, - BLOCKING_DISALLOW, - BLOCKING_WAITALL -} blocking_mode_t; - struct data_stream_vtbl_t { - DWORD (*get_avail_data)(data_stream_t*,http_request_t*); BOOL (*end_of_data)(data_stream_t*,http_request_t*); - DWORD (*read)(data_stream_t*,http_request_t*,BYTE*,DWORD,DWORD*,blocking_mode_t); + DWORD (*read)(data_stream_t*,http_request_t*,BYTE*,DWORD,DWORD*,BOOL); BOOL (*drain_content)(data_stream_t*,http_request_t*); void (*destroy)(data_stream_t*); }; @@ -446,12 +439,6 @@ BOOL end_of_data; } gzip_stream_t; -static DWORD gzip_get_avail_data(data_stream_t *stream, http_request_t *req) -{ - /* Allow reading only from read buffer */ - return 0; -} - static BOOL gzip_end_of_data(data_stream_t *stream, http_request_t *req) { gzip_stream_t *gzip_stream = (gzip_stream_t*)stream; @@ -460,7 +447,7 @@ } static DWORD gzip_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size, - DWORD *read, blocking_mode_t blocking_mode) + DWORD *read, BOOL allow_blocking) { gzip_stream_t *gzip_stream = (gzip_stream_t*)stream; z_stream *zstream = &gzip_stream->zstream; @@ -468,7 +455,7 @@ int zres; DWORD res = ERROR_SUCCESS; - TRACE("(%d %d)\n", size, blocking_mode); + TRACE("(%d %x)\n", size, allow_blocking); while(size && !gzip_stream->end_of_data) { if(!gzip_stream->buf_size) { @@ -478,16 +465,14 @@ gzip_stream->buf_pos = 0; } res = gzip_stream->parent_stream->vtbl->read(gzip_stream->parent_stream, req, gzip_stream->buf+gzip_stream->buf_size, - sizeof(gzip_stream->buf)-gzip_stream->buf_size, ¤t_read, blocking_mode); + sizeof(gzip_stream->buf)-gzip_stream->buf_size, ¤t_read, allow_blocking); gzip_stream->buf_size += current_read; if(res != ERROR_SUCCESS) break; if(!current_read) { - if(blocking_mode != BLOCKING_DISALLOW) { - WARN("unexpected end of data\n"); - gzip_stream->end_of_data = TRUE; - } + WARN("unexpected end of data\n"); + gzip_stream->end_of_data = TRUE; break; } } @@ -513,11 +498,13 @@ break; } - if(ret_read && blocking_mode == BLOCKING_ALLOW) - blocking_mode = BLOCKING_DISALLOW; + if(ret_read) + allow_blocking = FALSE; } TRACE("read %u bytes\n", ret_read); + if(ret_read) + res = ERROR_SUCCESS; *read = ret_read; return res; } @@ -540,7 +527,6 @@ } static const data_stream_vtbl_t gzip_stream_vtbl = { - gzip_get_avail_data, gzip_end_of_data, gzip_read, gzip_drain_content, @@ -2567,11 +2553,13 @@ return !req->read_size && req->data_stream->vtbl->end_of_data(req->data_stream, req); } -static DWORD read_http_stream(http_request_t *req, BYTE *buf, DWORD size, DWORD *read, blocking_mode_t blocking_mode) +static DWORD read_http_stream(http_request_t *req, BYTE *buf, DWORD size, DWORD *read, BOOL allow_blocking) { DWORD res; - res = req->data_stream->vtbl->read(req->data_stream, req, buf, size, read, blocking_mode); + res = req->data_stream->vtbl->read(req->data_stream, req, buf, size, read, allow_blocking); + if(res != ERROR_SUCCESS) + *read = 0; assert(*read <= size); if(req->hCacheFile) { @@ -2584,7 +2572,7 @@ FIXME("WriteFile failed: %u\n", GetLastError()); } - if(req->data_stream->vtbl->end_of_data(req->data_stream, req)) + if((res == ERROR_SUCCESS && !*read) || req->data_stream->vtbl->end_of_data(req->data_stream, req)) commit_cache_entry(req); } @@ -2592,7 +2580,7 @@ } /* fetch some more data into the read buffer (the read section must be held) */ -static DWORD refill_read_buffer(http_request_t *req, blocking_mode_t blocking_mode, DWORD *read_bytes) +static DWORD refill_read_buffer(http_request_t *req, BOOL allow_blocking, DWORD *read_bytes) { DWORD res, read=0; @@ -2606,7 +2594,10 @@ } res = read_http_stream(req, req->read_buf+req->read_size, sizeof(req->read_buf) - req->read_size, - &read, blocking_mode); + &read, allow_blocking); + if(res != ERROR_SUCCESS) + return res; + req->read_size += read; TRACE("read %u bytes, read_size %u\n", read, req->read_size); @@ -2615,33 +2606,6 @@ return res; } -/* return the size of data available to be read immediately (the read section must be held) */ -static DWORD get_avail_data( http_request_t *req ) -{ - DWORD avail = req->read_size; - - /* - * Different Windows versions have different limits of returned data, but all - * of them return no more than centrain amount. We use READ_BUFFER_SIZE as a limit. - */ - if(avail < READ_BUFFER_SIZE) - avail += req->data_stream->vtbl->get_avail_data(req->data_stream, req); - - return min(avail, READ_BUFFER_SIZE); -} - -static DWORD netconn_get_avail_data(data_stream_t *stream, http_request_t *req) -{ - netconn_stream_t *netconn_stream = (netconn_stream_t*)stream; - DWORD avail = 0; - - if(is_valid_netconn(req->netconn)) - NETCON_query_data_available(req->netconn, &avail); - return netconn_stream->content_length == ~0u - ? avail - : min(avail, netconn_stream->content_length-netconn_stream->content_read); -} - static BOOL netconn_end_of_data(data_stream_t *stream, http_request_t *req) { netconn_stream_t *netconn_stream = (netconn_stream_t*)stream; @@ -2649,31 +2613,24 @@ } static DWORD netconn_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size, - DWORD *read, blocking_mode_t blocking_mode) + DWORD *read, BOOL allow_blocking) { netconn_stream_t *netconn_stream = (netconn_stream_t*)stream; DWORD res = ERROR_SUCCESS; - int len = 0, ret = 0; + int ret = 0; size = min(size, netconn_stream->content_length-netconn_stream->content_read); if(size && is_valid_netconn(req->netconn)) { - while((res = NETCON_recv(req->netconn, buf+ret, size-ret, blocking_mode != BLOCKING_DISALLOW, &len)) == ERROR_SUCCESS) { - if(!len) { + res = NETCON_recv(req->netconn, buf, size, allow_blocking, &ret); + if(res == ERROR_SUCCESS) { + if(!ret) netconn_stream->content_length = netconn_stream->content_read; - break; - } - ret += len; - netconn_stream->content_read += len; - if(blocking_mode != BLOCKING_WAITALL || size == ret) - break; + netconn_stream->content_read += ret; } - - if(ret || (blocking_mode == BLOCKING_DISALLOW && res == WSAEWOULDBLOCK)) - res = ERROR_SUCCESS; } - TRACE("read %u bytes\n", ret); + TRACE("res %u read %u bytes\n", res, ret); *read = ret; return res; } @@ -2705,7 +2662,6 @@ } static const data_stream_vtbl_t netconn_stream_vtbl = { - netconn_get_avail_data, netconn_end_of_data, netconn_read, netconn_drain_content, @@ -2727,7 +2683,7 @@ } static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf, DWORD size, - DWORD *read, blocking_mode_t blocking_mode) + DWORD *read, BOOL allow_blocking) { chunked_stream_t *chunked_stream = (chunked_stream_t*)stream; DWORD ret_read = 0, res = ERROR_SUCCESS; @@ -2746,10 +2702,12 @@ case CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_DATA: case CHUNKED_STREAM_STATE_DISCARD_EOL_AT_END: chunked_stream->buf_pos = 0; - res = NETCON_recv(req->netconn, chunked_stream->buf, sizeof(chunked_stream->buf), blocking_mode != BLOCKING_DISALLOW, &read_bytes); + res = NETCON_recv(req->netconn, chunked_stream->buf, sizeof(chunked_stream->buf), allow_blocking, &read_bytes); if(res == ERROR_SUCCESS && read_bytes) { chunked_stream->buf_size += read_bytes; }else if(res == WSAEWOULDBLOCK) { + if(ret_read) + res = ERROR_SUCCESS; continue_read = FALSE; continue; }else { @@ -2808,7 +2766,7 @@ chunked_stream->buf_size -= read_bytes; }else { res = NETCON_recv(req->netconn, (char*)buf+ret_read, read_bytes, - blocking_mode != BLOCKING_DISALLOW, (int*)&read_bytes); + allow_blocking, (int*)&read_bytes); if(res != ERROR_SUCCESS) { continue_read = FALSE; break; @@ -2825,8 +2783,7 @@ ret_read += read_bytes; if(!chunked_stream->chunk_size) chunked_stream->state = CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_DATA; - if(blocking_mode == BLOCKING_ALLOW) - blocking_mode = BLOCKING_DISALLOW; + allow_blocking = FALSE; break; case CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_DATA: @@ -2853,7 +2810,7 @@ if(ret_read) res = ERROR_SUCCESS; - if(res != ERROR_SUCCESS && res != WSAEWOULDBLOCK) + if(res != ERROR_SUCCESS) return res; TRACE("read %d bytes\n", ret_read); @@ -2861,26 +2818,6 @@ return ERROR_SUCCESS; } -static DWORD chunked_get_avail_data(data_stream_t *stream, http_request_t *req) -{ - chunked_stream_t *chunked_stream = (chunked_stream_t*)stream; - DWORD avail = 0; - - if(chunked_stream->state != CHUNKED_STREAM_STATE_READING_CHUNK) { - DWORD res, read; - - /* try to process to the next chunk */ - res = chunked_read(stream, req, NULL, 0, &read, BLOCKING_DISALLOW); - if(res != ERROR_SUCCESS || chunked_stream->state != CHUNKED_STREAM_STATE_READING_CHUNK) - return 0; - } - - if(is_valid_netconn(req->netconn) && chunked_stream->buf_size < chunked_stream->chunk_size) - NETCON_query_data_available(req->netconn, &avail); - - return min(avail + chunked_stream->buf_size, chunked_stream->chunk_size); -} - static BOOL chunked_drain_content(data_stream_t *stream, http_request_t *req) { chunked_stream_t *chunked_stream = (chunked_stream_t*)stream; @@ -2894,7 +2831,6 @@ } static const data_stream_vtbl_t chunked_stream_vtbl = { - chunked_get_avail_data, chunked_end_of_data, chunked_read, chunked_drain_content, @@ -2985,49 +2921,39 @@ sizeof(INTERNET_ASYNC_RESULT)); } -static void HTTP_ReceiveRequestData(http_request_t *req, BOOL first_notif, DWORD *ret_size) +static void HTTP_ReceiveRequestData(http_request_t *req) { - DWORD res, read = 0, avail = 0; - blocking_mode_t mode; + DWORD res, read = 0; TRACE("%p\n", req); EnterCriticalSection( &req->read_section ); - mode = first_notif && req->read_size ? BLOCKING_DISALLOW : BLOCKING_ALLOW; - res = refill_read_buffer(req, mode, &read); + res = refill_read_buffer(req, FALSE, &read); if(res == ERROR_SUCCESS) - avail = get_avail_data(req); + read += req->read_size; LeaveCriticalSection( &req->read_section ); - if(res != ERROR_SUCCESS || (mode != BLOCKING_DISALLOW && !read)) { + if(res != WSAEWOULDBLOCK && (res != ERROR_SUCCESS || !read)) { WARN("res %u read %u, closing connection\n", res, read); http_release_netconn(req, FALSE); } - if(res != ERROR_SUCCESS) { + if(res != ERROR_SUCCESS && res != WSAEWOULDBLOCK) { send_request_complete(req, 0, res); return; } - if(ret_size) - *ret_size = avail; - if(first_notif) - avail = 0; - - send_request_complete(req, req->session->hdr.dwInternalFlags & INET_OPENURL ? (DWORD_PTR)req->hdr.hInternet : 1, avail); + send_request_complete(req, req->session->hdr.dwInternalFlags & INET_OPENURL ? (DWORD_PTR)req->hdr.hInternet : 1, 0); } /* read data from the http connection (the read section must be held) */ -static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read) +static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read, BOOL allow_blocking) { DWORD current_read = 0, ret_read = 0; - blocking_mode_t blocking_mode; DWORD res = ERROR_SUCCESS; - blocking_mode = req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC ? BLOCKING_ALLOW : BLOCKING_WAITALL; - EnterCriticalSection( &req->read_section ); if(req->read_size) { @@ -3035,13 +2961,15 @@ memcpy(buffer, req->read_buf+req->read_pos, ret_read); req->read_size -= ret_read; req->read_pos += ret_read; - if(blocking_mode == BLOCKING_ALLOW) - blocking_mode = BLOCKING_DISALLOW; + allow_blocking = FALSE; } if(ret_read < size) { - res = read_http_stream(req, (BYTE*)buffer+ret_read, size-ret_read, ¤t_read, blocking_mode); - ret_read += current_read; + res = read_http_stream(req, (BYTE*)buffer+ret_read, size-ret_read, ¤t_read, allow_blocking); + if(res == ERROR_SUCCESS) + ret_read += current_read; + else if(res == WSAEWOULDBLOCK && ret_read) + res = ERROR_SUCCESS; } LeaveCriticalSection( &req->read_section ); @@ -3049,7 +2977,7 @@ *read = ret_read; TRACE( "retrieved %u bytes (%u)\n", ret_read, req->contentLength ); - if(size && !ret_read) + if(res != WSAEWOULDBLOCK && (!ret_read || res != ERROR_SUCCESS)) http_release_netconn(req, res == ERROR_SUCCESS); return res; @@ -3074,7 +3002,7 @@ DWORD bytes_read, res; BYTE buf[4096]; - res = HTTPREQ_Read(req, buf, sizeof(buf), &bytes_read); + res = HTTPREQ_Read(req, buf, sizeof(buf), &bytes_read, TRUE); if(res != ERROR_SUCCESS) { ret = FALSE; break; @@ -3093,114 +3021,136 @@ task_header_t hdr; void *buf; DWORD size; + DWORD read_pos; DWORD *ret_read; -} read_file_ex_task_t; +} read_file_task_t; -static void AsyncReadFileExProc(task_header_t *hdr) +static void async_read_file_proc(task_header_t *hdr) { - read_file_ex_task_t *task = (read_file_ex_task_t*)hdr; + read_file_task_t *task = (read_file_task_t*)hdr; http_request_t *req = (http_request_t*)task->hdr.hdr; - DWORD res = ERROR_SUCCESS, read = 0, buffered = 0; + DWORD res = ERROR_SUCCESS, read = task->read_pos, complete_arg = 0; - TRACE("%p\n", req); + TRACE("req %p buf %p size %u read_pos %u ret_read %p\n", req, task->buf, task->size, task->read_pos, task->ret_read); + + if(task->buf) { + DWORD read_bytes; + while (read < task->size) { + res = HTTPREQ_Read(req, (char*)task->buf + read, task->size - read, &read_bytes, TRUE); + if (res != ERROR_SUCCESS || !read_bytes) + break; + read += read_bytes; + } + }else { + EnterCriticalSection(&req->read_section); + res = refill_read_buffer(req, TRUE, &read); + LeaveCriticalSection(&req->read_section); - if(task->ret_read) - res = HTTPREQ_Read(req, task->buf, task->size, &read); - if(res == ERROR_SUCCESS) - res = refill_read_buffer(req, task->ret_read ? BLOCKING_DISALLOW : BLOCKING_ALLOW, &buffered); - if (res == ERROR_SUCCESS) - { if(task->ret_read) - *task->ret_read = read; - read += buffered; - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, - &read, sizeof(read)); + complete_arg = read; /* QueryDataAvailable reports read bytes in request complete notification */ + if(res != ERROR_SUCCESS || !read) + http_release_netconn(req, drain_content(req, FALSE)); } - send_request_complete(req, res == ERROR_SUCCESS, res); + TRACE("res %u read %u\n", res, read); + + if(task->ret_read) + *task->ret_read = read; + + /* FIXME: We should report bytes transferred before decoding content. */ + INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, &read, sizeof(read)); + + if(res != ERROR_SUCCESS) + complete_arg = res; + send_request_complete(req, res == ERROR_SUCCESS, complete_arg); } -static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWORD *ret_read, - DWORD flags, DWORD_PTR context) +static DWORD async_read(http_request_t *req, void *buf, DWORD size, DWORD read_pos, DWORD *ret_read) { + read_file_task_t *task; + + task = alloc_async_task(&req->hdr, async_read_file_proc, sizeof(*task)); + if(!task) + return ERROR_OUTOFMEMORY; + + task->buf = buf; + task->size = size; + task->read_pos = read_pos; + task->ret_read = ret_read; + INTERNET_AsyncCall(&task->hdr); + return ERROR_IO_PENDING; +} + +static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buf, DWORD size, DWORD *ret_read, + DWORD flags, DWORD_PTR context) +{ http_request_t *req = (http_request_t*)hdr; - DWORD res, read, cread, error = ERROR_SUCCESS; + DWORD res = ERROR_SUCCESS, read = 0, cread, error = ERROR_SUCCESS; + BOOL allow_blocking, notify_received = FALSE; TRACE("(%p %p %u %x)\n", req, buf, size, flags); if (flags & ~(IRF_ASYNC|IRF_NO_WAIT)) FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT)); - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); - - if (req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - read_file_ex_task_t *task; + allow_blocking = !(req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC); - if (TryEnterCriticalSection( &req->read_section )) - { - if (get_avail_data(req) || end_of_read_data(req)) - { - res = HTTPREQ_Read(req, buf, size, &read); - LeaveCriticalSection( &req->read_section ); - goto done; + if(allow_blocking || TryEnterCriticalSection(&req->read_section)) { + if(allow_blocking) + EnterCriticalSection(&req->read_section); + if(hdr->dwError == ERROR_SUCCESS) + hdr->dwError = INTERNET_HANDLE_IN_USE; + else if(hdr->dwError == INTERNET_HANDLE_IN_USE) + hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; + + if(req->read_size) { + read = min(size, req->read_size); + memcpy(buf, req->read_buf + req->read_pos, read); + req->read_size -= read; + req->read_pos += read; + } + + if(read < size && (!read || !(flags & IRF_NO_WAIT)) && !end_of_read_data(req)) { + LeaveCriticalSection(&req->read_section); + INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); + EnterCriticalSection( &req->read_section ); + notify_received = TRUE; + + while(read < size) { + res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread, allow_blocking); + read += cread; + if (res != ERROR_SUCCESS || !cread) + break; } - LeaveCriticalSection( &req->read_section ); } - task = alloc_async_task(&req->hdr, AsyncReadFileExProc, sizeof(*task)); - task->buf = buf; - task->size = size; - task->ret_read = (flags & IRF_NO_WAIT) ? NULL : ret_read; - - INTERNET_AsyncCall(&task->hdr); - - return ERROR_IO_PENDING; - } - - read = 0; - - EnterCriticalSection( &req->read_section ); - if(hdr->dwError == ERROR_SUCCESS) - hdr->dwError = INTERNET_HANDLE_IN_USE; - else if(hdr->dwError == INTERNET_HANDLE_IN_USE) - hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; - - while(1) { - res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread); - if(res != ERROR_SUCCESS) - break; - - read += cread; - if(read == size || end_of_read_data(req)) - break; + if(hdr->dwError == INTERNET_HANDLE_IN_USE) + hdr->dwError = ERROR_SUCCESS; + else + error = hdr->dwError; LeaveCriticalSection( &req->read_section ); - - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, - &cread, sizeof(cread)); - INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, - INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); - - EnterCriticalSection( &req->read_section ); + }else { + res = WSAEWOULDBLOCK; } - if(hdr->dwError == INTERNET_HANDLE_IN_USE) - hdr->dwError = ERROR_SUCCESS; - else - error = hdr->dwError; - - LeaveCriticalSection( &req->read_section ); + if(res == WSAEWOULDBLOCK) { + if(!(flags & IRF_NO_WAIT)) + return async_read(req, buf, size, read, ret_read); + if(!read) + return async_read(req, NULL, 0, 0, NULL); + res = ERROR_SUCCESS; + } -done: *ret_read = read; - if (res == ERROR_SUCCESS) { + if (res != ERROR_SUCCESS) + return res; + + if(notify_received) INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, &read, sizeof(read)); - } - - return res==ERROR_SUCCESS ? error : res; + return error; } static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written) @@ -3219,99 +3169,60 @@ return res; } -static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read) -{ - http_request_t *req = (http_request_t*)hdr; - DWORD res; - - if (req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - read_file_ex_task_t *task; - - if (TryEnterCriticalSection( &req->read_section )) - { - if (get_avail_data(req) || end_of_read_data(req)) - { - res = HTTPREQ_Read(req, buffer, size, read); - LeaveCriticalSection( &req->read_section ); - return res; - } - LeaveCriticalSection( &req->read_section ); - } - - task = alloc_async_task(&req->hdr, AsyncReadFileExProc, sizeof(*task)); - task->buf = buffer; - task->size = size; - task->ret_read = read; - - *read = 0; - INTERNET_AsyncCall(&task->hdr); - - return ERROR_IO_PENDING; - } - - EnterCriticalSection( &req->read_section ); - if(hdr->dwError == INTERNET_HANDLE_IN_USE) - hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; - - res = HTTPREQ_Read(req, buffer, size, read); - if(res == ERROR_SUCCESS) - res = hdr->dwError; - LeaveCriticalSection( &req->read_section ); - - return res; -} - -typedef struct { - task_header_t hdr; - DWORD *ret_size; -} http_data_available_task_t; - -static void AsyncQueryDataAvailableProc(task_header_t *hdr) -{ - http_data_available_task_t *task = (http_data_available_task_t*)hdr; - - HTTP_ReceiveRequestData((http_request_t*)task->hdr.hdr, FALSE, task->ret_size); -} - static DWORD HTTPREQ_QueryDataAvailable(object_header_t *hdr, DWORD *available, DWORD flags, DWORD_PTR ctx) { http_request_t *req = (http_request_t*)hdr; + DWORD res = ERROR_SUCCESS, avail = 0, error = ERROR_SUCCESS; + BOOL allow_blocking, notify_received = FALSE; TRACE("(%p %p %x %lx)\n", req, available, flags, ctx); - if (req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) - { - http_data_available_task_t *task; + if (flags & ~(IRF_ASYNC|IRF_NO_WAIT)) + FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT)); - /* never wait, if we can't enter the section we queue an async request right away */ - if (TryEnterCriticalSection( &req->read_section )) - { - refill_read_buffer(req, BLOCKING_DISALLOW, NULL); - if ((*available = get_avail_data( req ))) goto done; - if (end_of_read_data( req )) goto done; - LeaveCriticalSection( &req->read_section ); - } + *available = 0; + allow_blocking = !(req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC); - task = alloc_async_task(&req->hdr, AsyncQueryDataAvailableProc, sizeof(*task)); - task->ret_size = available; - INTERNET_AsyncCall(&task->hdr); - return ERROR_IO_PENDING; - } + if(allow_blocking || TryEnterCriticalSection(&req->read_section)) { + if(allow_blocking) + EnterCriticalSection(&req->read_section); + if(hdr->dwError == ERROR_SUCCESS) + hdr->dwError = INTERNET_HANDLE_IN_USE; + else if(hdr->dwError == INTERNET_HANDLE_IN_USE) + hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; + + avail = req->read_size; + + if(!avail && !end_of_read_data(req)) { + LeaveCriticalSection(&req->read_section); + INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); + EnterCriticalSection( &req->read_section ); + notify_received = TRUE; - EnterCriticalSection( &req->read_section ); + res = refill_read_buffer(req, allow_blocking, &avail); + } - if (!(*available = get_avail_data( req )) && !end_of_read_data( req )) - { - refill_read_buffer( req, BLOCKING_ALLOW, NULL ); - *available = get_avail_data( req ); + if(hdr->dwError == INTERNET_HANDLE_IN_USE) + hdr->dwError = ERROR_SUCCESS; + else + error = hdr->dwError; + + LeaveCriticalSection( &req->read_section ); + }else { + res = WSAEWOULDBLOCK; } -done: - LeaveCriticalSection( &req->read_section ); + if(res == WSAEWOULDBLOCK) + return async_read(req, NULL, 0, 0, available); - TRACE( "returning %u\n", *available ); - return ERROR_SUCCESS; + if (res != ERROR_SUCCESS) + return res; + + *available = avail; + if(notify_received) + INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, + &avail, sizeof(avail)); + return error; } static DWORD HTTPREQ_LockRequestFile(object_header_t *hdr, req_file_t **ret) @@ -3335,7 +3246,6 @@ HTTPREQ_QueryOption, HTTPREQ_SetOption, HTTPREQ_ReadFile, - HTTPREQ_ReadFileEx, HTTPREQ_WriteFile, HTTPREQ_QueryDataAvailable, NULL, @@ -5226,7 +5136,7 @@ { if (res == ERROR_SUCCESS) { if(bEndRequest && request->contentLength && request->bytesWritten == request->bytesToWrite) - HTTP_ReceiveRequestData(request, TRUE, NULL); + HTTP_ReceiveRequestData(request); else send_request_complete(request, request->session->hdr.dwInternalFlags & INET_OPENURL ? (DWORD_PTR)request->hdr.hInternet : 1, 0); @@ -5333,7 +5243,7 @@ create_cache_entry(request); if (res == ERROR_SUCCESS && request->contentLength) - HTTP_ReceiveRequestData(request, TRUE, NULL); + HTTP_ReceiveRequestData(request); else send_request_complete(request, res == ERROR_SUCCESS, res); @@ -5823,7 +5733,6 @@ NULL, NULL, NULL, - NULL, NULL }; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/internet.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/internet.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/internet.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/internet.c 2017-03-21 14:02:57.000000000 +0000 @@ -982,7 +982,6 @@ APPINFO_SetOption, NULL, NULL, - NULL, NULL }; @@ -1182,11 +1181,7 @@ { TRACE("(%p, 0x%08x)\n", lpdwStatus, dwReserved); - if (lpdwStatus) { - WARN("always returning LAN connection.\n"); - *lpdwStatus = INTERNET_CONNECTION_LAN; - } - return TRUE; + return InternetGetConnectedStateExW(lpdwStatus, NULL, 0, dwReserved); } @@ -2170,8 +2165,11 @@ return FALSE; } - if(hdr->vtbl->ReadFile) - res = hdr->vtbl->ReadFile(hdr, lpBuffer, dwNumOfBytesToRead, pdwNumOfBytesRead); + if(hdr->vtbl->ReadFile) { + res = hdr->vtbl->ReadFile(hdr, lpBuffer, dwNumOfBytesToRead, pdwNumOfBytesRead, 0, 0); + if(res == ERROR_IO_PENDING) + *pdwNumOfBytesRead = 0; + } WININET_Release(hdr); @@ -2229,8 +2227,8 @@ return FALSE; } - if(hdr->vtbl->ReadFileEx) - res = hdr->vtbl->ReadFileEx(hdr, lpBuffersOut->lpvBuffer, lpBuffersOut->dwBufferLength, + if(hdr->vtbl->ReadFile) + res = hdr->vtbl->ReadFile(hdr, lpBuffersOut->lpvBuffer, lpBuffersOut->dwBufferLength, &lpBuffersOut->dwBufferLength, dwFlags, dwContext); WININET_Release(hdr); @@ -2267,8 +2265,8 @@ return FALSE; } - if(hdr->vtbl->ReadFileEx) - res = hdr->vtbl->ReadFileEx(hdr, lpBuffer->lpvBuffer, lpBuffer->dwBufferLength, &lpBuffer->dwBufferLength, + if(hdr->vtbl->ReadFile) + res = hdr->vtbl->ReadFile(hdr, lpBuffer->lpvBuffer, lpBuffer->dwBufferLength, &lpBuffer->dwBufferLength, dwFlags, dwContext); WININET_Release(hdr); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/internet.h wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/internet.h --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/internet.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/internet.h 2017-03-21 14:02:57.000000000 +0000 @@ -279,8 +279,7 @@ void (*CloseConnection)(object_header_t*); DWORD (*QueryOption)(object_header_t*,DWORD,void*,DWORD*,BOOL); DWORD (*SetOption)(object_header_t*,DWORD,void*,DWORD); - DWORD (*ReadFile)(object_header_t*,void*,DWORD,DWORD*); - DWORD (*ReadFileEx)(object_header_t*,void*,DWORD,DWORD*,DWORD,DWORD_PTR); + DWORD (*ReadFile)(object_header_t*,void*,DWORD,DWORD*,DWORD,DWORD_PTR); DWORD (*WriteFile)(object_header_t*,const void*,DWORD,DWORD*); DWORD (*QueryDataAvailable)(object_header_t*,DWORD*,DWORD,DWORD_PTR); DWORD (*FindNextFileW)(object_header_t*,void*); @@ -455,7 +454,6 @@ DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags, int *sent /* out */) DECLSPEC_HIDDEN; DWORD NETCON_recv(netconn_t*,void*,size_t,BOOL,int*) DECLSPEC_HIDDEN; -BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available) DECLSPEC_HIDDEN; BOOL NETCON_is_alive(netconn_t*) DECLSPEC_HIDDEN; LPCVOID NETCON_GetCert(netconn_t *connection) DECLSPEC_HIDDEN; int NETCON_GetCipherStrength(netconn_t*) DECLSPEC_HIDDEN; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/netconnection.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/netconnection.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/netconnection.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/netconnection.c 2017-03-21 14:02:57.000000000 +0000 @@ -869,32 +869,6 @@ } } -/****************************************************************************** - * NETCON_query_data_available - * Returns the number of bytes of peeked data plus the number of bytes of - * queued, but unread data. - */ -BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available) -{ - *available = 0; - - if(!connection->secure) - { - ULONG unread; - int retval = ioctlsocket(connection->socket, FIONREAD, &unread); - if (!retval) - { - TRACE("%d bytes of queued, but unread data\n", unread); - *available += unread; - } - } - else - { - *available = connection->peek_len; - } - return TRUE; -} - BOOL NETCON_is_alive(netconn_t *netconn) { int len; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/tests/http.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/tests/http.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/tests/http.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/tests/http.c 2017-03-21 14:02:57.000000000 +0000 @@ -1111,16 +1111,9 @@ inetbuffers.lpvBuffer = NULL; inetbuffers.dwOffsetHigh = 1234; inetbuffers.dwOffsetLow = 5678; - SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); - SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); rc = InternetReadFileExA(hor, &inetbuffers, 0, 0xdeadcafe); ok(rc, "InternetReadFileEx failed with error %u\n", GetLastError()); trace("read %i bytes\n", inetbuffers.dwBufferLength); - todo_wine - { - CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); - CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); - } rc = InternetReadFileExA(NULL, &inetbuffers, 0, 0xdeadcafe); ok(!rc && (GetLastError() == ERROR_INVALID_HANDLE), @@ -1167,10 +1160,8 @@ CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); if (inetbuffers.dwBufferLength) { - todo_wine { CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); - } } else { @@ -4463,7 +4454,6 @@ if (!ib.dwBufferLength) break; } - todo_wine ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads ); ok( !strcmp(buffer, page1), "unexpected buffer content\n" ); close_async_handle( ses, hCompleteEvent, 2 ); @@ -4530,7 +4520,6 @@ { ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() ); ok( bytes == 0, "expected 0, got %u\n", bytes ); - todo_wine CHECK_NOTIFIED( INTERNET_STATUS_RECEIVING_RESPONSE ); SET_EXPECT( INTERNET_STATUS_REQUEST_COMPLETE ); if (!pending_reads++) @@ -4553,7 +4542,6 @@ if (!bytes) break; } - todo_wine ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads ); ok( !strcmp(buffer, page1), "unexpected buffer content\n" ); close_async_handle( ses, hCompleteEvent, 2 ); @@ -4567,11 +4555,20 @@ send(server_socket, msg, strlen(msg), 0); } +static BOOL skip_receive_notification_tests; +static DWORD received_response_size; + static void WINAPI readex_callback(HINTERNET handle, DWORD_PTR context, DWORD status, void *info, DWORD info_size) { switch(status) { case INTERNET_STATUS_RECEIVING_RESPONSE: + if(!skip_receive_notification_tests) + callback(handle, context, status, info, info_size); + break; case INTERNET_STATUS_RESPONSE_RECEIVED: + if(!skip_receive_notification_tests) + callback(handle, context, status, info, info_size); + received_response_size = *(DWORD*)info; break; default: callback(handle, context, status, info, info_size); @@ -4602,12 +4599,13 @@ SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER); SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST); SET_EXPECT(INTERNET_STATUS_REQUEST_SENT); + if(!skip_receive_notification_tests) + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); SetLastError(0xdeadbeef); ret = HttpSendRequestA(req->request, NULL, 0, NULL, 0); ok(!ret, "HttpSendRequestA unexpectedly succeeded\n"); ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError()); - ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error); WaitForSingleObject(server_req_rec_event, INFINITE); @@ -4617,22 +4615,37 @@ CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER); CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST); + if(!skip_receive_notification_tests) { + SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); + received_response_size = 0xdeadbeef; + } SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE); server_send_string(response); WaitForSingleObject(hCompleteEvent, INFINITE); + if(!skip_receive_notification_tests) { + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); + CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); + todo_wine + ok(received_response_size == strlen(response), "received_response_size = %u\n", received_response_size); + } CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT); CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); + ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error); } -#define readex_expect_sync_data_len(a,b,c,d,e,f) _readex_expect_sync_data_len(__LINE__,a,b,c,d,e,f) +#define readex_expect_sync_data_len(a,b,c,d,e,f,g) _readex_expect_sync_data_len(__LINE__,a,b,c,d,e,f,g) static void _readex_expect_sync_data_len(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, - DWORD buf_size, const char *exdata, DWORD len) + DWORD buf_size, const char *exdata, DWORD len, BOOL expect_receive) { BOOL ret; - SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE); + if(!skip_receive_notification_tests && expect_receive) { + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); + SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); + received_response_size = 0xdeadbeef; + } memset(buf->lpvBuffer, 0xff, buf_size); buf->dwBufferLength = buf_size; @@ -4642,14 +4655,51 @@ if(len && exdata) ok_(__FILE__,line)(!memcmp(buf->lpvBuffer, exdata, len), "Unexpected data\n"); - CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); + if(!skip_receive_notification_tests && expect_receive) { + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); + CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); + ok_(__FILE__,line)(received_response_size == len, "received_response_size = %u\n", received_response_size); + } } -#define readex_expect_sync_data(a,b,c,d,e) _readex_expect_sync_data(__LINE__,a,b,c,d,e) +#define readex_expect_sync_data(a,b,c,d,e,f) _readex_expect_sync_data(__LINE__,a,b,c,d,e,f) static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, + DWORD buf_size, const char *exdata, DWORD expect_receive) +{ + _readex_expect_sync_data_len(line, req, flags, buf, buf_size, exdata, strlen(exdata), expect_receive); +} + +#define read_expect_sync_data_len(a,b,c,d,e) _read_expect_sync_data_len(__LINE__,a,b,c,d,e) +static void _read_expect_sync_data_len(unsigned line, HINTERNET req, void *buf, DWORD buf_size, + const char *exdata, DWORD len) +{ + DWORD ret_size = 0xdeadbeef; + BOOL ret; + + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); + SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); + SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE); + received_response_size = 0xdeadbeef; + + memset(buf, 0xff, buf_size); + ret = InternetReadFile(req, buf, buf_size, &ret_size); + ok_(__FILE__,line)(ret, "InternetReadFileExW failed: %u\n", GetLastError()); + ok_(__FILE__,line)(ret_size == len, "dwBufferLength = %u, expected %u\n", ret_size, len); + if(len && exdata) + ok_(__FILE__,line)(!memcmp(buf, exdata, len), "Unexpected data\n"); + + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); + CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); + CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); + ok_(__FILE__,line)(received_response_size == len, "received_response_size = %u\n", received_response_size); + ok_(__FILE__,line)(!req_error, "req_error = %u\n", req_error); +} + +#define read_expect_sync_data(a,b,c,d) _read_expect_sync_data(__LINE__,a,b,c,d) +static void _read_expect_sync_data(unsigned line, HINTERNET req, void *buf, DWORD buf_size, const char *exdata) { - _readex_expect_sync_data_len(line, req, flags, buf, buf_size, exdata, strlen(exdata)); + _read_expect_sync_data_len(line, req, buf, buf_size, exdata, strlen(exdata)); } static void close_connection(void) @@ -4659,10 +4709,13 @@ recv(server_socket, &c, 1, 0); } -static void send_response_and_wait(const char *response, BOOL do_close_connection, INTERNET_BUFFERSW *buf) +#define send_response_and_wait(a,b,c,d,e,f,g,h) _send_response_and_wait(__LINE__,a,b,c,d,e,f,g,h) +static void _send_response_and_wait(unsigned line, const char *response, BOOL do_close_connection, + void *buf, DWORD *ret_size, const char *exdata, + DWORD expected_size, DWORD expected_req_error, DWORD expected_receive_size) { - DWORD orig_size = buf->dwBufferLength; - + if(!skip_receive_notification_tests) + SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE); if(response) @@ -4673,11 +4726,31 @@ WaitForSingleObject(hCompleteEvent, INFINITE); + if(!skip_receive_notification_tests) + CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); + if(!skip_receive_notification_tests && expected_receive_size != -1) + todo_wine_if(received_response_size != expected_receive_size) /* FIXME! remove when wine is fixed */ + ok_(__FILE__,line)(received_response_size == expected_receive_size, + "received_response_size = %u\n", received_response_size); + ok_(__FILE__,line)(req_error == expected_req_error, "req_error = %u, expected %u\n", req_error, expected_req_error); /* If IRF_NO_WAIT is used, buffer is not changed. */ - ok(buf->dwBufferLength == orig_size, "dwBufferLength = %u\n", buf->dwBufferLength); - ok(!*(int*)buf->lpvBuffer, "buffer data changed\n"); + ok_(__FILE__,line)(*ret_size == expected_size, "dwBufferLength = %u\n", *ret_size); + if(exdata) + ok_(__FILE__,line)(!memcmp(buf, exdata, strlen(exdata)), "unexpected buffer data\n"); + else if(buf) + ok_(__FILE__,line)(!*(DWORD*)buf, "buffer data changed\n"); +} + +#define send_response_ex_and_wait(a,b,c,d,e,f) _send_response_ex_and_wait(__LINE__,a,b,c,d,e,f) +static void _send_response_ex_and_wait(unsigned line, const char *response, BOOL close_connection, + INTERNET_BUFFERSW *buf, const char *exdata, DWORD expected_req_error, + DWORD expected_receive_size) +{ + _send_response_and_wait(line, response, close_connection, buf->lpvBuffer, &buf->dwBufferLength, + exdata, exdata ? strlen(exdata) : buf->dwBufferLength, expected_req_error, + expected_receive_size); } static void send_response_len_and_wait(unsigned len, BOOL close_connection, INTERNET_BUFFERSW *buf) @@ -4687,20 +4760,59 @@ response = HeapAlloc(GetProcessHeap(), 0, len+1); memset(response, 'x', len); response[len] = 0; - send_response_and_wait(response, close_connection, buf); + send_response_ex_and_wait(response, close_connection, buf, NULL, 0, -1); HeapFree(GetProcessHeap(), 0, response); } -static void readex_expect_async(HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, DWORD buf_size) +#define readex_expect_async(a,b,c,d,e) _readex_expect_async(__LINE__,a,b,c,d,e) +static void _readex_expect_async(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, + DWORD buf_size, const char *exdata) { + unsigned len = 0; BOOL ret; + if(!skip_receive_notification_tests) + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); + memset(buf->lpvBuffer, 0, buf_size); buf->dwBufferLength = buf_size; ret = InternetReadFileExW(req, buf, flags, 0xdeadbeef); + ok_(__FILE__,line)(!ret && GetLastError() == ERROR_IO_PENDING, "InternetReadFileExW returned %x (%u)\n", ret, GetLastError()); + ok_(__FILE__,line)(buf->dwBufferLength == buf_size, "dwBufferLength = %u, expected %u\n", buf->dwBufferLength, buf_size); + if(exdata) { + len = strlen(exdata); + ok_(__FILE__,line)(!memcmp(buf->lpvBuffer, exdata, len), "unexpected buffer data\n"); + }else { + ok_(__FILE__,line)(!*(DWORD*)buf->lpvBuffer, "buffer data changed\n"); + } + + if(!skip_receive_notification_tests) + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); +} + +static void read_expect_async(HINTERNET req, void *buf, DWORD buf_size, DWORD *ret_size, const char *exdata) +{ + unsigned len = 0; + const char *p; + BOOL ret; + + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); + + *ret_size = 0xdeadbeef; + memset(buf, 0, buf_size); + ret = InternetReadFile(req, buf, buf_size, ret_size); ok(!ret && GetLastError() == ERROR_IO_PENDING, "InternetReadFileExW returned %x (%u)\n", ret, GetLastError()); - ok(buf->dwBufferLength == buf_size, "dwBufferLength = %u, expected %u\n", buf->dwBufferLength, buf_size); - ok(!*(int*)buf->lpvBuffer, "buffer data changed\n"); + ok(*ret_size == 0, "dwBufferLength = %u\n", *ret_size); + if(exdata) { + len = strlen(exdata); + ok(!memcmp(buf, exdata, len), "unexpected buffer data\n"); + } + for(p = (const char*)buf + len; p < (const char*)buf + buf_size; p++) { + if(*p) + ok(0, "buffer data changed\n"); + } + + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); } #define expect_data_available(a,b) _expect_data_available(__LINE__,a,b) @@ -4717,12 +4829,31 @@ return size; } +#define async_query_data_available(a,b) _async_query_data_available(__LINE__,a,b) +static void _async_query_data_available(unsigned line, HINTERNET req, DWORD *size) +{ + BOOL res; + + if(!skip_receive_notification_tests) + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); + + *size = 0xdeadbeef; + res = InternetQueryDataAvailable(req, size, 0, 0); + ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, + "InternetQueryDataAvailable returned: %x(%u)\n", res, GetLastError()); + ok_(__FILE__,line)(!*size, "size = %u\n", *size); + + if(!skip_receive_notification_tests) + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); +} + static void test_http_read(int port) { INTERNET_BUFFERSW ib; test_request_t req; + DWORD read_size; char buf[24000]; - DWORD avail; + DWORD avail, i; if(!is_ie7plus) return; @@ -4731,6 +4862,67 @@ conn_wait_event = CreateEventW(NULL, FALSE, FALSE, NULL); server_req_rec_event = CreateEventW(NULL, FALSE, FALSE, NULL); + memset(&ib, 0, sizeof(ib)); + ib.dwStructSize = sizeof(ib); + ib.lpvBuffer = buf; + + trace("Testing InternetReadFileExW with IRF_ASYNC flag...\n"); + + open_read_test_request(port, &req, + "HTTP/1.1 200 OK\r\n" + "Server: winetest\r\n" + "\r\n" + "xx"); + + readex_expect_async(req.request, IRF_ASYNC, &ib, 4, "xx"); + + send_response_ex_and_wait("yy1234567890", FALSE, &ib, "xxyy", 0, 2); + readex_expect_sync_data(req.request, IRF_ASYNC, &ib, 4, "1234", 4); + readex_expect_sync_data(req.request, IRF_ASYNC, &ib, 5, "56789", 5); + + readex_expect_async(req.request, IRF_ASYNC, &ib, sizeof(buf), "0"); + send_response_ex_and_wait("123", TRUE, &ib, "0123", 0, 4); + + close_async_handle(req.session, hCompleteEvent, 2); + + trace("Testing InternetReadFileExW with no flags...\n"); + + open_read_test_request(port, &req, + "HTTP/1.1 200 OK\r\n" + "Server: winetest\r\n" + "\r\n" + "xx"); + + readex_expect_async(req.request, 0, &ib, 4, "xx"); + + send_response_ex_and_wait("yy1234567890", FALSE, &ib, "xxyy", 0, 2); + readex_expect_sync_data(req.request, 0, &ib, 4, "1234", 4); + readex_expect_sync_data(req.request, 0, &ib, 5, "56789", 5); + + readex_expect_async(req.request, 0, &ib, sizeof(buf), "0"); + send_response_ex_and_wait("123", TRUE, &ib, "0123", 0, 4); + + close_async_handle(req.session, hCompleteEvent, 2); + + trace("Testing InternetReadFile...\n"); + + open_read_test_request(port, &req, + "HTTP/1.1 200 OK\r\n" + "Server: winetest\r\n" + "\r\n" + "xx"); + + read_expect_async(req.request, buf, 4, &read_size, "xx"); + + send_response_and_wait("yy1234567890", FALSE, buf, &read_size, "xxyy", 4, 0, 2); + read_expect_sync_data(req.request, buf, 4, "1234"); + read_expect_sync_data(req.request, buf, 5, "56789"); + + read_expect_async(req.request, buf, sizeof(buf), &read_size, "0"); + send_response_and_wait("123", TRUE, buf, &read_size, "0123", 4, 0, 4); + + close_async_handle(req.session, hCompleteEvent, 2); + trace("Testing InternetReadFileExW with IRF_NO_WAIT flag...\n"); open_read_test_request(port, &req, @@ -4739,22 +4931,26 @@ "\r\n" "xx"); - memset(&ib, 0, sizeof(ib)); - ib.dwStructSize = sizeof(ib); - ib.lpvBuffer = buf; + SET_OPTIONAL(INTERNET_STATUS_RECEIVING_RESPONSE); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "xx"); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "xx", 0); - readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf)); - send_response_and_wait("1234567890", FALSE, &ib); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, 5, "12345"); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "67890"); + if(notified[INTERNET_STATUS_RECEIVING_RESPONSE]) { + win_skip("Skipping receive notification tests on too old Windows.\n"); + skip_receive_notification_tests = TRUE; + } + CLEAR_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); - readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf)); - send_response_and_wait("12345", TRUE, &ib); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); + send_response_ex_and_wait("1234567890", FALSE, &ib, NULL, 0, 10); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, 5, "12345", 0); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "67890", 0); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "12345"); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), ""); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); + send_response_ex_and_wait("12345", TRUE, &ib, NULL, 0, 5); + + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "12345", 0); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", TRUE); close_async_handle(req.session, hCompleteEvent, 2); @@ -4764,24 +4960,24 @@ "Transfer-Encoding: chunked\r\n" "\r\n" "9\r\n123456789"); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123456789"); - readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf)); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123456789", 0); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); - send_response_and_wait("\r\n1\r\na\r\n1\r\nb\r", FALSE, &ib); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab"); - readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf)); - - send_response_and_wait("\n3\r\nab", FALSE, &ib); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab"); - readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf)); - - send_response_and_wait("c", FALSE, &ib); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "c"); - readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf)); - - send_response_and_wait("\r\n1\r\nx\r\n0\r\n\r\n", TRUE, &ib); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "x"); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), ""); + send_response_ex_and_wait("\r\n1\r\na\r\n1\r\nb\r", FALSE, &ib, NULL, 0, 13); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab", 0); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); + + send_response_ex_and_wait("\n3\r\nab", FALSE, &ib, NULL, 0, 6); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab", 0); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); + + send_response_ex_and_wait("c", FALSE, &ib, NULL, 0, 1); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "c", 0); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); + + send_response_ex_and_wait("\r\n1\r\nx\r\n0\r\n\r\n", TRUE, &ib, NULL, 0, 13); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "x", 0); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", 0); close_async_handle(req.session, hCompleteEvent, 2); @@ -4791,14 +4987,29 @@ "Transfer-Encoding: chunked\r\n" "\r\n" "3\r\n123\r\n"); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123"); - readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf)); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); - send_response_and_wait("0\r\n\r\n", TRUE, &ib); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), ""); + send_response_ex_and_wait("0\r\n\r\n", TRUE, &ib, NULL, 0, 5); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", 0); close_async_handle(req.session, hCompleteEvent, 2); + open_read_test_request(port, &req, + "HTTP/1.1 200 OK\r\n" + "Server: winetest\r\n" + "Connection: close\r\n" + "\r\n"); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); + send_response_ex_and_wait("123", TRUE, &ib, NULL, 0, 3); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0); + + SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION); + SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED); + close_async_handle(req.session, hCompleteEvent, 2); + CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION); + CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED); + trace("Testing InternetQueryDataAvailable...\n"); open_read_test_request(port, &req, @@ -4807,8 +5018,8 @@ "\r\n" "123"); expect_data_available(req.request, 3); - readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123"); - readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf)); + readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0); + readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL); send_response_len_and_wait(20000, TRUE, &ib); avail = expect_data_available(req.request, -1); @@ -4820,9 +5031,47 @@ todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION); todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED); + open_read_test_request(port, &req, + "HTTP/1.1 200 OK\r\n" + "Server: winetest\r\n" + "Connection: close\r\n" + "\r\n" + "123"); + + expect_data_available(req.request, 3); + readex_expect_sync_data(req.request, 0, &ib, 3, "123", 0); + + async_query_data_available(req.request, &read_size); + send_response_and_wait("1234567890", FALSE, NULL, &read_size, NULL, 10, 10, 10); + + readex_expect_sync_data(req.request, 0, &ib, 9, "123456789", 0); + expect_data_available(req.request, 1); + readex_expect_sync_data(req.request, 0, &ib, 1, "0", 0); + + async_query_data_available(req.request, &read_size); + send_response_and_wait("1234567890", FALSE, NULL, &read_size, NULL, 10, 10, 10); + expect_data_available(req.request, 10); + for(i = 0; i < 10; i++) + server_send_string("x"); + expect_data_available(req.request, 10); + + readex_expect_async(req.request, IRF_ASYNC, &ib, 21, "1234567890"); + send_response_ex_and_wait("X", FALSE, &ib, "1234567890xxxxxxxxxxX", 0, 11); + async_query_data_available(req.request, &read_size); + + SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION); + SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED); + send_response_and_wait(NULL, TRUE, NULL, &read_size, NULL, 0, 0, 0); + CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION); + CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED); + + close_async_handle(req.session, hCompleteEvent, 2); + CloseHandle(hCompleteEvent); CloseHandle(conn_wait_event); CloseHandle(server_req_rec_event); + + skip_receive_notification_tests = FALSE; } static void test_connection_break(int port) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/tests/internet.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/tests/internet.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wininet/tests/internet.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wininet/tests/internet.c 2017-03-21 14:02:57.000000000 +0000 @@ -1595,12 +1595,16 @@ return; } + flags = 0; + buffer[0] = 0; res = pInternetGetConnectedStateExA(&flags, buffer, sizeof(buffer), 0); + trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, buffer); +todo_wine + ok (flags & INTERNET_RAS_INSTALLED, "Missing RAS flag\n"); if(!res) { win_skip("InternetGetConnectedStateExA tests require a valid connection\n"); return; } - trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, buffer); res = pInternetGetConnectedStateExA(NULL, NULL, 0, 0); ok(res == TRUE, "Expected TRUE, got %d\n", res); @@ -1608,7 +1612,16 @@ flags = 0; res = pInternetGetConnectedStateExA(&flags, NULL, 0, 0); ok(res == TRUE, "Expected TRUE, got %d\n", res); - ok(flags, "Expected at least one flag set\n"); + if (flags & INTERNET_CONNECTION_CONFIGURED) + { + ok(flags & INTERNET_CONNECTION_MODEM, "Modem connection flag missing\n"); + ok(flags & ~INTERNET_CONNECTION_LAN, "Mixed Modem and LAN flags\n"); + } + else + { + ok(flags & INTERNET_CONNECTION_LAN, "LAN connection flag missing\n"); + ok(flags & ~INTERNET_CONNECTION_MODEM, "Mixed Modem and LAN flags\n"); + } buffer[0] = 0; flags = 0; @@ -1684,12 +1697,16 @@ return; } + flags = 0; + buffer[0] = 0; res = pInternetGetConnectedStateExW(&flags, buffer, sizeof(buffer) / sizeof(buffer[0]), 0); + trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, wine_dbgstr_w(buffer)); +todo_wine + ok (flags & INTERNET_RAS_INSTALLED, "Missing RAS flag\n"); if(!res) { win_skip("InternetGetConnectedStateExW tests require a valid connection\n"); return; } - trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, wine_dbgstr_w(buffer)); res = pInternetGetConnectedStateExW(NULL, NULL, 0, 0); ok(res == TRUE, "Expected TRUE, got %d\n", res); @@ -1697,7 +1714,16 @@ flags = 0; res = pInternetGetConnectedStateExW(&flags, NULL, 0, 0); ok(res == TRUE, "Expected TRUE, got %d\n", res); - ok(flags, "Expected at least one flag set\n"); + if (flags & INTERNET_CONNECTION_CONFIGURED) + { + ok(flags & INTERNET_CONNECTION_MODEM, "Modem connection flag missing\n"); + ok(flags & ~INTERNET_CONNECTION_LAN, "Mixed Modem and LAN flags\n"); + } + else + { + ok(flags & INTERNET_CONNECTION_LAN, "LAN connection flag missing\n"); + ok(flags & ~INTERNET_CONNECTION_MODEM, "Mixed Modem and LAN flags\n"); + } buffer[0] = 0; flags = 0; @@ -1731,14 +1757,20 @@ res = pInternetGetConnectedStateExW(&flags, buffer, sz, 0); ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(flags, "Expected at least one flag set\n"); - ok(sz - 1 == lstrlenW(buffer), "Expected %u bytes, got %u\n", sz - 1, lstrlenW(buffer)); + if (flags & INTERNET_CONNECTION_MODEM) + ok(!buffer[0], "Expected 0 bytes, got %u\n", lstrlenW(buffer)); + else + ok(sz - 1 == lstrlenW(buffer), "Expected %u bytes, got %u\n", sz - 1, lstrlenW(buffer)); buffer[0] = 0; flags = 0; res = pInternetGetConnectedStateExW(&flags, buffer, sz / 2, 0); ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(flags, "Expected at least one flag set\n"); - ok(sz / 2 - 1 == lstrlenW(buffer), "Expected %u bytes, got %u\n", sz / 2 - 1, lstrlenW(buffer)); + if (flags & INTERNET_CONNECTION_MODEM) + ok(!buffer[0], "Expected 0 bytes, got %u\n", lstrlenW(buffer)); + else + ok(sz / 2 - 1 == lstrlenW(buffer), "Expected %u bytes, got %u\n", sz / 2 - 1, lstrlenW(buffer)); buffer[0] = 0; flags = 0; @@ -1752,7 +1784,10 @@ res = pInternetGetConnectedStateExW(&flags, buffer, 2, 0); ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(flags, "Expected at least one flag set\n"); - ok(lstrlenW(buffer) == 1, "Expected 1 byte, got %u\n", lstrlenW(buffer)); + if (flags & INTERNET_CONNECTION_MODEM) + ok(!buffer[0], "Expected 0 bytes, got %u\n", lstrlenW(buffer)); + else + ok(lstrlenW(buffer) == 1, "Expected 1 byte, got %u\n", lstrlenW(buffer)); buffer[0] = 0xDEAD; flags = 0; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/winmm/mci.c wine-staging-2.4.0~ubuntu16.04.1/dlls/winmm/mci.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/winmm/mci.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/winmm/mci.c 2017-03-21 14:02:57.000000000 +0000 @@ -2063,13 +2063,18 @@ */ static DWORD MCI_Break(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms) { + DWORD dwRet; + if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; - FIXME("(%04x) vkey %04X stub\n", dwFlags, lpParms->nVirtKey); - if (dwFlags & MCI_NOTIFY) + TRACE("(%08x, %08X, vkey %04X, hwnd %p)\n", wDevID, dwFlags, + lpParms->nVirtKey, lpParms->hwndBreak); + + dwRet = MCI_SendCommandFrom32(wDevID, MCI_BREAK, dwFlags, (DWORD_PTR)lpParms); + if (!dwRet && (dwFlags & MCI_NOTIFY)) mciDriverNotify((HWND)lpParms->dwCallback, wDevID, MCI_NOTIFY_SUCCESSFUL); - return MMSYSERR_NOERROR; + return dwRet; } /************************************************************************** diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/wlanapi/tests/wlanapi.c wine-staging-2.4.0~ubuntu16.04.1/dlls/wlanapi/tests/wlanapi.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/wlanapi/tests/wlanapi.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/wlanapi/tests/wlanapi.c 2017-03-21 14:02:57.000000000 +0000 @@ -152,6 +152,7 @@ { skip("No wireless interfaces\n"); WlanCloseHandle(handle, NULL); + WlanFreeMemory(list); return; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/xmllite/reader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/xmllite/reader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/xmllite/reader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/xmllite/reader.c 2017-03-21 14:02:57.000000000 +0000 @@ -1,7 +1,7 @@ /* * IXmlReader implementation * - * Copyright 2010, 2012-2013, 2016 Nikolay Sivov + * Copyright 2010, 2012-2013, 2016-2017 Nikolay Sivov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -93,6 +93,8 @@ static const WCHAR commentW[] = {'<','!','-','-',0}; static const WCHAR piW[] = {'<','?',0}; +static BOOL is_namestartchar(WCHAR ch); + static const char *debugstr_nodetype(XmlNodeType nodetype) { static const char * const type_names[] = @@ -222,12 +224,27 @@ static const strval strval_xml = { xmlW, 3 }; static const strval strval_xmlns = { xmlnsW, 5 }; +struct reader_position +{ + UINT line_number; + UINT line_position; +}; + +enum attribute_flags +{ + ATTRIBUTE_NS_DEFINITION = 0x1, + ATTRIBUTE_DEFAULT_NS_DEFINITION = 0x2, +}; + struct attribute { struct list entry; strval prefix; strval localname; + strval qname; strval value; + struct reader_position position; + unsigned int flags; }; struct element @@ -236,6 +253,7 @@ strval prefix; strval localname; strval qname; + struct reader_position position; }; struct ns @@ -253,13 +271,14 @@ xmlreaderinput *input; IMalloc *imalloc; XmlReadState state; + HRESULT error; /* error set on XmlReadState_Error */ XmlReaderInternalState instate; XmlReaderResumeState resumestate; XmlNodeType nodetype; DtdProcessing dtdmode; IXmlResolver *resolver; IUnknown *mlang; - UINT line, pos; /* reader position in XML stream */ + struct reader_position position; struct list attrs; /* attributes list for current node */ struct attribute *attr; /* current attribute */ UINT attr_count; @@ -270,7 +289,8 @@ UINT depth; UINT max_depth; BOOL is_empty_element; - struct element empty_element; + struct element empty_element; /* used for empty elements without end tag , + and to keep prefix, 0, sizeof(attr->prefix)); attr->localname = *localname; + attr->qname = qname ? *qname : *localname; attr->value = *value; + attr->position = *position; + attr->flags = flags; list_add_tail(&reader->attrs, &attr->entry); reader->attr_count++; return S_OK; } +/* Returns current element, doesn't check if reader is actually positioned on it. */ +static struct element *reader_get_element(xmlreader *reader) +{ + if (reader->is_empty_element) + return &reader->empty_element; + + return LIST_ENTRY(list_head(&reader->elements), struct element, entry); +} + /* This one frees stored string value if needed */ static void reader_free_strvalued(xmlreader *reader, strval *v) { @@ -464,18 +497,20 @@ reader_free(reader, elem); } list_init(&reader->elements); + reader_free_strvalued(reader, &reader->empty_element.localname); + reader_free_strvalued(reader, &reader->empty_element.qname); reader->is_empty_element = FALSE; } static HRESULT reader_inc_depth(xmlreader *reader) { - if (++reader->depth > reader->max_depth) return SC_E_MAXELEMENTDEPTH; - return S_OK; + return (++reader->depth >= reader->max_depth && reader->max_depth) ? SC_E_MAXELEMENTDEPTH : S_OK; } static void reader_dec_depth(xmlreader *reader) { - if (reader->depth > 1) reader->depth--; + if (reader->depth) + reader->depth--; } static HRESULT reader_push_ns(xmlreader *reader, const strval *prefix, const strval *uri, BOOL def) @@ -534,38 +569,27 @@ } static HRESULT reader_push_element(xmlreader *reader, strval *prefix, strval *localname, - strval *qname) + strval *qname, const struct reader_position *position) { struct element *element; HRESULT hr; - if (!list_empty(&reader->elements)) - { - hr = reader_inc_depth(reader); - if (FAILED(hr)) - return hr; - } - element = reader_alloc_zero(reader, sizeof(*element)); - if (!element) { - hr = E_OUTOFMEMORY; - goto failed; - } + if (!element) + return E_OUTOFMEMORY; - if ((hr = reader_strvaldup(reader, prefix, &element->prefix)) != S_OK || - (hr = reader_strvaldup(reader, localname, &element->localname)) != S_OK || - (hr = reader_strvaldup(reader, qname, &element->qname)) != S_OK) - { - reader_free_element(reader, element); - goto failed; + if ((hr = reader_strvaldup(reader, prefix, &element->prefix)) == S_OK && + (hr = reader_strvaldup(reader, localname, &element->localname)) == S_OK && + (hr = reader_strvaldup(reader, qname, &element->qname)) == S_OK) + { + list_add_head(&reader->elements, &element->entry); + reader_mark_ns_nodes(reader, element); + reader->is_empty_element = FALSE; + element->position = *position; } + else + reader_free_element(reader, element); - list_add_head(&reader->elements, &element->entry); - reader_mark_ns_nodes(reader, element); - reader->is_empty_element = FALSE; - -failed: - reader_dec_depth(reader); return hr; } @@ -606,7 +630,6 @@ reader_pop_ns_nodes(reader, element); reader_free_element(reader, element); - reader_dec_depth(reader); /* It was a root element, the rest is expected as Misc */ if (list_empty(&reader->elements)) @@ -840,10 +863,9 @@ static HRESULT readerinput_detectencoding(xmlreaderinput *readerinput, xml_encoding *enc) { encoded_buffer *buffer = &readerinput->buffer->encoded; - static const WCHAR startW[] = {'<','?'}; - static const WCHAR commentW[] = {'<','!'}; static const char utf8bom[] = {0xef,0xbb,0xbf}; static const char utf16lebom[] = {0xff,0xfe}; + WCHAR *ptrW; *enc = XmlEncoding_Unknown; @@ -854,13 +876,17 @@ if (buffer->written <= 3) return MX_E_INPUTEND; } + ptrW = (WCHAR *)buffer->data; /* try start symbols if we have enough data to do that, input buffer should contain first chunk already */ if (readerinput_is_utf8(readerinput)) *enc = XmlEncoding_UTF8; - else if (!memcmp(buffer->data, startW, sizeof(startW)) || - !memcmp(buffer->data, commentW, sizeof(commentW))) - *enc = XmlEncoding_UTF16; + else if (*ptrW == '<') + { + ptrW++; + if (*ptrW == '?' || *ptrW == '!' || is_namestartchar(*ptrW)) + *enc = XmlEncoding_UTF16; + } /* try with BOM now */ else if (!memcmp(buffer->data, utf8bom, sizeof(utf8bom))) { @@ -1044,16 +1070,29 @@ return 0; } +static void reader_update_position(xmlreader *reader, WCHAR ch) +{ + if (ch == '\r') + reader->position.line_position = 1; + else if (ch == '\n') + { + reader->position.line_number++; + reader->position.line_position = 1; + } + else + reader->position.line_position++; +} + /* moves cursor n WCHARs forward */ static void reader_skipn(xmlreader *reader, int n) { encoded_buffer *buffer = &reader->input->buffer->utf16; - const WCHAR *ptr = reader_get_ptr(reader); + const WCHAR *ptr; - while (*ptr++ && n--) + while (*(ptr = reader_get_ptr(reader)) && n--) { + reader_update_position(reader, *ptr); buffer->cur++; - reader->pos++; } } @@ -1065,23 +1104,12 @@ /* [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ static int reader_skipspaces(xmlreader *reader) { - encoded_buffer *buffer = &reader->input->buffer->utf16; const WCHAR *ptr = reader_get_ptr(reader); UINT start = reader_get_cur(reader); while (is_wchar_space(*ptr)) { - if (*ptr == '\r') - reader->pos = 0; - else if (*ptr == '\n') - { - reader->line++; - reader->pos = 0; - } - else - reader->pos++; - - buffer->cur++; + reader_skipn(reader, 1); ptr = reader_get_ptr(reader); } @@ -1130,11 +1158,13 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader) { static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; + struct reader_position position; strval val, name; HRESULT hr; if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; + position = reader->position; if (reader_cmp(reader, versionW)) return WC_E_XMLDECL; reader_init_strvalue(reader_get_cur(reader), 7, &name); /* skip 'version' */ @@ -1157,7 +1187,7 @@ /* skip "'"|'"' */ reader_skipn(reader, 1); - return reader_add_attr(reader, NULL, &name, &val); + return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0); } /* ([A-Za-z0-9._] | '-') */ @@ -1204,11 +1234,13 @@ static HRESULT reader_parse_encdecl(xmlreader *reader) { static const WCHAR encodingW[] = {'e','n','c','o','d','i','n','g',0}; + struct reader_position position; strval name, val; HRESULT hr; if (!reader_skipspaces(reader)) return S_FALSE; + position = reader->position; if (reader_cmp(reader, encodingW)) return S_FALSE; name.str = reader_get_ptr(reader); name.start = reader_get_cur(reader); @@ -1233,7 +1265,7 @@ /* skip "'"|'"' */ reader_skipn(reader, 1); - return reader_add_attr(reader, NULL, &name, &val); + return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0); } /* [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) */ @@ -1242,12 +1274,14 @@ static const WCHAR standaloneW[] = {'s','t','a','n','d','a','l','o','n','e',0}; static const WCHAR yesW[] = {'y','e','s',0}; static const WCHAR noW[] = {'n','o',0}; + struct reader_position position; strval name, val; UINT start; HRESULT hr; if (!reader_skipspaces(reader)) return S_FALSE; + position = reader->position; if (reader_cmp(reader, standaloneW)) return S_FALSE; reader_init_strvalue(reader_get_cur(reader), 10, &name); /* skip 'standalone' */ @@ -1275,7 +1309,7 @@ /* skip "'"|'"' */ reader_skipn(reader, 1); - return reader_add_attr(reader, NULL, &name, &val); + return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0); } /* [23] XMLDecl ::= '' */ @@ -1283,12 +1317,16 @@ { static const WCHAR xmldeclW[] = {'<','?','x','m','l',' ',0}; static const WCHAR declcloseW[] = {'?','>',0}; + struct reader_position position; HRESULT hr; /* check if we have "position; + reader_skipn(reader, 3); hr = reader_parse_versioninfo(reader); if (FAILED(hr)) return hr; @@ -1302,14 +1340,16 @@ return hr; reader_skipspaces(reader); - if (reader_cmp(reader, declcloseW)) return WC_E_XMLDECL; + if (reader_cmp(reader, declcloseW)) + return WC_E_XMLDECL; + + /* skip '?>' */ reader_skipn(reader, 2); - reader_inc_depth(reader); reader->nodetype = XmlNodeType_XmlDeclaration; - reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); - reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); - reader_set_strvalue(reader, StringValue_Value, &strval_empty); + reader->empty_element.position = position; + reader_set_strvalue(reader, StringValue_LocalName, &strval_xml); + reader_set_strvalue(reader, StringValue_QualifiedName, &strval_xml); return S_OK; } @@ -1335,8 +1375,6 @@ reader->nodetype = XmlNodeType_Comment; reader->resume[XmlReadResume_Body] = start; reader->resumestate = XmlReadResumeState_Comment; - reader_set_strvalue(reader, StringValue_LocalName, NULL); - reader_set_strvalue(reader, StringValue_QualifiedName, NULL); reader_set_strvalue(reader, StringValue_Value, NULL); } @@ -1358,8 +1396,6 @@ /* skip rest of markup '->' */ reader_skipn(reader, 3); - reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); - reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); reader_set_strvalue(reader, StringValue_Value, &value); reader->resume[XmlReadResume_Body] = 0; reader->resumestate = XmlReadResumeState_Initial; @@ -1729,6 +1765,7 @@ { static WCHAR systemW[] = {'S','Y','S','T','E','M',0}; static WCHAR publicW[] = {'P','U','B','L','I','C',0}; + struct reader_position position = reader->position; strval name, sys; HRESULT hr; int cnt; @@ -1745,7 +1782,7 @@ if (FAILED(hr)) return hr; reader_init_cstrvalue(publicW, strlenW(publicW), &name); - hr = reader_add_attr(reader, NULL, &name, &pub); + hr = reader_add_attr(reader, NULL, &name, NULL, &pub, &position, 0); if (FAILED(hr)) return hr; cnt = reader_skipspaces(reader); @@ -1756,7 +1793,7 @@ if (FAILED(hr)) return S_OK; reader_init_cstrvalue(systemW, strlenW(systemW), &name); - hr = reader_add_attr(reader, NULL, &name, &sys); + hr = reader_add_attr(reader, NULL, &name, NULL, &sys, &position, 0); if (FAILED(hr)) return hr; return S_OK; @@ -1770,7 +1807,7 @@ if (FAILED(hr)) return hr; reader_init_cstrvalue(systemW, strlenW(systemW), &name); - return reader_add_attr(reader, NULL, &name, &sys); + return reader_add_attr(reader, NULL, &name, NULL, &sys, &position, 0); } return S_FALSE; @@ -1823,7 +1860,7 @@ } /* [11 NS] LocalPart ::= NCName */ -static HRESULT reader_parse_local(xmlreader *reader, strval *local) +static HRESULT reader_parse_local(xmlreader *reader, strval *local, BOOL check_for_separator) { WCHAR *ptr; UINT start; @@ -1845,6 +1882,9 @@ ptr = reader_get_ptr(reader); } + if (check_for_separator && *ptr == ':') + return NC_E_QNAMECOLON; + if (is_reader_pending(reader)) { reader->resume[XmlReadResume_Local] = start; @@ -1883,7 +1923,7 @@ if (reader->resume[XmlReadResume_Local]) { - hr = reader_parse_local(reader, local); + hr = reader_parse_local(reader, local, FALSE); if (FAILED(hr)) return hr; reader_init_strvalue(reader->resume[XmlReadResume_Name], @@ -1908,7 +1948,7 @@ /* skip ':' */ reader_skipn(reader, 1); - hr = reader_parse_local(reader, local); + hr = reader_parse_local(reader, local, TRUE); if (FAILED(hr)) return hr; } else @@ -2145,18 +2185,19 @@ [15 NS] Attribute ::= NSAttName Eq AttValue | QName Eq AttValue */ static HRESULT reader_parse_attribute(xmlreader *reader) { + struct reader_position position = reader->position; strval prefix, local, qname, value; - BOOL ns = FALSE, nsdef = FALSE; + enum attribute_flags flags = 0; HRESULT hr; hr = reader_parse_qname(reader, &prefix, &local, &qname); if (FAILED(hr)) return hr; if (strval_eq(reader, &prefix, &strval_xmlns)) - ns = TRUE; + flags |= ATTRIBUTE_NS_DEFINITION; if (strval_eq(reader, &qname, &strval_xmlns)) - ns = nsdef = TRUE; + flags |= ATTRIBUTE_DEFAULT_NS_DEFINITION; hr = reader_parse_eq(reader); if (FAILED(hr)) return hr; @@ -2164,38 +2205,45 @@ hr = reader_parse_attvalue(reader, &value); if (FAILED(hr)) return hr; - if (ns) - reader_push_ns(reader, nsdef ? &strval_xmlns : &local, &value, nsdef); + if (flags & (ATTRIBUTE_NS_DEFINITION | ATTRIBUTE_DEFAULT_NS_DEFINITION)) + reader_push_ns(reader, &local, &value, !!(flags & ATTRIBUTE_DEFAULT_NS_DEFINITION)); TRACE("%s=%s\n", debug_strval(reader, &local), debug_strval(reader, &value)); - return reader_add_attr(reader, &prefix, &local, &value); + return reader_add_attr(reader, &prefix, &local, &qname, &value, &position, flags); } /* [12 NS] STag ::= '<' QName (S Attribute)* S? '>' [14 NS] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' */ -static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname, int *empty) +static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname) { + struct reader_position position = reader->position; HRESULT hr; hr = reader_parse_qname(reader, prefix, local, qname); if (FAILED(hr)) return hr; - while (1) + for (;;) { static const WCHAR endW[] = {'/','>',0}; reader_skipspaces(reader); /* empty element */ - if ((*empty = !reader_cmp(reader, endW))) + if ((reader->is_empty_element = !reader_cmp(reader, endW))) { + struct element *element = &reader->empty_element; + /* skip '/>' */ reader_skipn(reader, 2); - reader->is_empty_element = TRUE; - reader->empty_element.prefix = *prefix; - reader->empty_element.localname = *local; - reader->empty_element.qname = *qname; - reader_mark_ns_nodes(reader, &reader->empty_element); + + reader_free_strvalued(reader, &element->qname); + reader_free_strvalued(reader, &element->localname); + + element->prefix = *prefix; + reader_strvaldup(reader, qname, &element->qname); + reader_strvaldup(reader, local, &element->localname); + element->position = position; + reader_mark_ns_nodes(reader, element); return S_OK; } @@ -2204,7 +2252,7 @@ { /* skip '>' */ reader_skipn(reader, 1); - return reader_push_element(reader, prefix, local, qname); + return reader_push_element(reader, prefix, local, qname, &position); } hr = reader_parse_attribute(reader); @@ -2233,16 +2281,15 @@ case XmlReadResumeState_STag: { strval qname, prefix, local; - int empty = 0; /* this handles empty elements too */ - hr = reader_parse_stag(reader, &prefix, &local, &qname, &empty); + hr = reader_parse_stag(reader, &prefix, &local, &qname); if (FAILED(hr)) return hr; /* FIXME: need to check for defined namespace to reject invalid prefix */ /* if we got empty element and stack is empty go straight to Misc */ - if (empty && list_empty(&reader->elements)) + if (reader->is_empty_element && list_empty(&reader->elements)) reader->instate = XmlReadInState_MiscEnd; else reader->instate = XmlReadInState_Content; @@ -2252,6 +2299,7 @@ reader_set_strvalue(reader, StringValue_Prefix, &prefix); reader_set_strvalue(reader, StringValue_LocalName, &local); reader_set_strvalue(reader, StringValue_QualifiedName, &qname); + reader_set_strvalue(reader, StringValue_Value, &strval_empty); break; } default: @@ -2264,13 +2312,15 @@ /* [13 NS] ETag ::= '' */ static HRESULT reader_parse_endtag(xmlreader *reader) { + struct reader_position position; strval prefix, local, qname; - struct element *elem; + struct element *element; HRESULT hr; /* skip 'position; hr = reader_parse_qname(reader, &prefix, &local, &qname); if (FAILED(hr)) return hr; @@ -2283,13 +2333,15 @@ /* Element stack should never be empty at this point, cause we shouldn't get to content parsing if it's empty. */ - elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry); - if (!strval_eq(reader, &elem->qname, &qname)) return WC_E_ELEMENTMATCH; + element = LIST_ENTRY(list_head(&reader->elements), struct element, entry); + if (!strval_eq(reader, &element->qname, &qname)) return WC_E_ELEMENTMATCH; + + /* update position stored for start tag, we won't be using it */ + element->position = position; reader->nodetype = XmlNodeType_EndElement; + reader->is_empty_element = FALSE; reader_set_strvalue(reader, StringValue_Prefix, &prefix); - reader_set_strvalue(reader, StringValue_LocalName, &local); - reader_set_strvalue(reader, StringValue_QualifiedName, &qname); return S_OK; } @@ -2318,8 +2370,6 @@ reader->nodetype = XmlNodeType_CDATA; reader->resume[XmlReadResume_Body] = start; reader->resumestate = XmlReadResumeState_CDATA; - reader_set_strvalue(reader, StringValue_LocalName, NULL); - reader_set_strvalue(reader, StringValue_QualifiedName, NULL); reader_set_strvalue(reader, StringValue_Value, NULL); } @@ -2335,8 +2385,6 @@ reader_skipn(reader, 3); TRACE("%s\n", debug_strval(reader, &value)); - reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); - reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); reader_set_strvalue(reader, StringValue_Value, &value); reader->resume[XmlReadResume_Body] = 0; reader->resumestate = XmlReadResumeState_Initial; @@ -2361,6 +2409,7 @@ /* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) */ static HRESULT reader_parse_chardata(xmlreader *reader) { + struct reader_position position; WCHAR *ptr; UINT start; @@ -2379,11 +2428,10 @@ reader->nodetype = is_wchar_space(*ptr) ? XmlNodeType_Whitespace : XmlNodeType_Text; reader->resume[XmlReadResume_Body] = start; reader->resumestate = XmlReadResumeState_CharData; - reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); - reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); reader_set_strvalue(reader, StringValue_Value, NULL); } + position = reader->position; while (*ptr) { static const WCHAR ampW[] = {'&',0}; @@ -2397,6 +2445,7 @@ { strval value; + reader->empty_element.position = position; reader_init_strvalue(start, reader_get_cur(reader)-start, &value); reader_set_strvalue(reader, StringValue_Value, &value); reader->resume[XmlReadResume_Body] = 0; @@ -2473,12 +2522,26 @@ reader_clear_attrs(reader); /* When moving from EndElement or empty element, pop its own namespace definitions */ - if (nodetype == XmlNodeType_Element && reader->is_empty_element) - reader_pop_ns_nodes(reader, &reader->empty_element); - else if (nodetype == XmlNodeType_EndElement) + switch (nodetype) + { + case XmlNodeType_Attribute: + reader_dec_depth(reader); + /* fallthrough */ + case XmlNodeType_Element: + if (reader->is_empty_element) + reader_pop_ns_nodes(reader, &reader->empty_element); + else if (FAILED(hr = reader_inc_depth(reader))) + return hr; + break; + case XmlNodeType_EndElement: reader_pop_element(reader); + reader_dec_depth(reader); + break; + default: + ; + } - while (1) + for (;;) { switch (reader->instate) { @@ -2490,9 +2553,13 @@ hr = readerinput_growraw(reader->input); if (FAILED(hr)) return hr; + reader->position.line_number = 1; + reader->position.line_position = 1; + /* try to detect encoding by BOM or data and set input code page */ hr = readerinput_detectencoding(reader->input, &enc); - TRACE("detected encoding %s, 0x%08x\n", debugstr_w(xml_encoding_map[enc].name), hr); + TRACE("detected encoding %s, 0x%08x\n", enc == XmlEncoding_Unknown ? "(unknown)" : + debugstr_w(xml_encoding_map[enc].name), hr); if (FAILED(hr)) return hr; /* always switch first time cause we have to put something in */ @@ -2546,7 +2613,11 @@ if (FAILED(hr)) return hr; if (hr == S_FALSE) + { reader->instate = XmlReadInState_Eof; + reader->state = XmlReadState_EndOfFile; + reader->nodetype = XmlNodeType_None; + } return hr; case XmlReadInState_Eof: return S_FALSE; @@ -2645,9 +2716,11 @@ This->input = NULL; } - This->line = This->pos = 0; + This->position.line_number = 0; + This->position.line_position = 0; reader_clear_elements(This); This->depth = 0; + This->nodetype = XmlNodeType_None; This->resumestate = XmlReadResumeState_Initial; memset(This->resume, 0, sizeof(This->resume)); @@ -2720,6 +2793,9 @@ case XmlReaderProperty_ReadState: *value = This->state; break; + case XmlReaderProperty_MaxElementDepth: + *value = This->max_depth; + break; default: FIXME("Unimplemented property (%u)\n", property); return E_NOTIMPL; @@ -2757,7 +2833,7 @@ This->dtdmode = value; break; case XmlReaderProperty_MaxElementDepth: - FIXME("Ignoring MaxElementDepth %ld\n", value); + This->max_depth = value; break; default: FIXME("Unimplemented property (%u)\n", property); @@ -2771,22 +2847,39 @@ { xmlreader *This = impl_from_IXmlReader(iface); XmlNodeType oldtype = This->nodetype; + XmlNodeType type; HRESULT hr; TRACE("(%p)->(%p)\n", This, nodetype); - if (This->state == XmlReadState_Closed) return S_FALSE; + if (!nodetype) + nodetype = &type; - hr = reader_parse_nextnode(This); - if (oldtype == XmlNodeType_None && This->nodetype != oldtype) - This->state = XmlReadState_Interactive; - if (hr == S_OK) + switch (This->state) { - TRACE("node type %s\n", debugstr_nodetype(This->nodetype)); - if (nodetype) - *nodetype = This->nodetype; + case XmlReadState_Closed: + hr = S_FALSE; + break; + case XmlReadState_Error: + hr = This->error; + break; + default: + hr = reader_parse_nextnode(This); + if (SUCCEEDED(hr) && oldtype == XmlNodeType_None && This->nodetype != oldtype) + This->state = XmlReadState_Interactive; + + if (FAILED(hr)) + { + This->state = XmlReadState_Error; + This->nodetype = XmlNodeType_None; + This->depth = 0; + This->error = hr; + } } + TRACE("node type %s\n", debugstr_nodetype(This->nodetype)); + *nodetype = This->nodetype; + return hr; } @@ -2808,9 +2901,13 @@ if (!reader->attr_count) return S_FALSE; + if (!reader->attr) + reader_inc_depth(reader); + reader->attr = LIST_ENTRY(list_head(&reader->attrs), struct attribute, entry); reader_set_strvalue(reader, StringValue_Prefix, &reader->attr->prefix); reader_set_strvalue(reader, StringValue_LocalName, &reader->attr->localname); + reader_set_strvalue(reader, StringValue_QualifiedName, &reader->attr->qname); reader_set_strvalue(reader, StringValue_Value, &reader->attr->value); return S_OK; @@ -2843,6 +2940,7 @@ This->attr = LIST_ENTRY(next, struct attribute, entry); reader_set_strvalue(This, StringValue_Prefix, &This->attr->prefix); reader_set_strvalue(This, StringValue_LocalName, &This->attr->localname); + reader_set_strvalue(This, StringValue_QualifiedName, &This->attr->qname); reader_set_strvalue(This, StringValue_Value, &This->attr->value); } @@ -2864,20 +2962,27 @@ TRACE("(%p)\n", This); if (!This->attr_count) return S_FALSE; + + if (This->attr) + reader_dec_depth(This); + This->attr = NULL; /* FIXME: support other node types with 'attributes' like DTD */ if (This->is_empty_element) { + reader_set_strvalue(This, StringValue_Prefix, &This->empty_element.prefix); reader_set_strvalue(This, StringValue_LocalName, &This->empty_element.localname); reader_set_strvalue(This, StringValue_QualifiedName, &This->empty_element.qname); } else { struct element *element = LIST_ENTRY(list_head(&This->elements), struct element, entry); if (element) { + reader_set_strvalue(This, StringValue_Prefix, &element->prefix); reader_set_strvalue(This, StringValue_LocalName, &element->localname); reader_set_strvalue(This, StringValue_QualifiedName, &element->qname); } } + reader_set_strvalue(This, StringValue_Value, &strval_empty); return S_OK; } @@ -2885,10 +2990,60 @@ static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *name, UINT *len) { xmlreader *This = impl_from_IXmlReader(iface); + struct attribute *attribute = This->attr; + struct element *element; + UINT length; TRACE("(%p)->(%p %p)\n", This, name, len); - *name = This->strvalues[StringValue_QualifiedName].str; - if (len) *len = This->strvalues[StringValue_QualifiedName].len; + + if (!len) + len = &length; + + switch (reader_get_nodetype(This)) + { + case XmlNodeType_Text: + case XmlNodeType_CDATA: + case XmlNodeType_Comment: + case XmlNodeType_Whitespace: + *name = emptyW; + *len = 0; + break; + case XmlNodeType_Element: + case XmlNodeType_EndElement: + element = reader_get_element(This); + if (element->prefix.len) + { + *name = element->qname.str; + *len = element->qname.len; + } + else + { + *name = element->localname.str; + *len = element->localname.len; + } + break; + case XmlNodeType_Attribute: + if (attribute->flags & ATTRIBUTE_DEFAULT_NS_DEFINITION) + { + *name = xmlnsW; + *len = 5; + } else if (attribute->prefix.len) + { + *name = This->strvalues[StringValue_QualifiedName].str; + *len = This->strvalues[StringValue_QualifiedName].len; + } + else + { + *name = This->strvalues[StringValue_LocalName].str; + *len = This->strvalues[StringValue_LocalName].len; + } + break; + default: + *name = This->strvalues[StringValue_QualifiedName].str; + *len = This->strvalues[StringValue_QualifiedName].len; + break; + } + return S_OK; } @@ -2983,6 +3138,15 @@ } } break; + case XmlNodeType_Text: + case XmlNodeType_CDATA: + case XmlNodeType_ProcessingInstruction: + case XmlNodeType_Comment: + case XmlNodeType_Whitespace: + case XmlNodeType_XmlDeclaration: + *uri = emptyW; + *len = 0; + break; default: FIXME("Unhandled node type %d\n", nodetype); return E_NOTIMPL; @@ -2994,45 +3158,111 @@ static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface, LPCWSTR *name, UINT *len) { xmlreader *This = impl_from_IXmlReader(iface); + struct element *element; + UINT length; TRACE("(%p)->(%p %p)\n", This, name, len); - *name = This->strvalues[StringValue_LocalName].str; - if (len) *len = This->strvalues[StringValue_LocalName].len; + + if (!len) + len = &length; + + switch (reader_get_nodetype(This)) + { + case XmlNodeType_Text: + case XmlNodeType_CDATA: + case XmlNodeType_Comment: + case XmlNodeType_Whitespace: + *name = emptyW; + *len = 0; + break; + case XmlNodeType_Element: + case XmlNodeType_EndElement: + element = reader_get_element(This); + *name = element->localname.str; + *len = element->localname.len; + break; + case XmlNodeType_Attribute: + if (This->attr->flags & ATTRIBUTE_DEFAULT_NS_DEFINITION) + { + *name = xmlnsW; + *len = 5; + } + else + { + *name = This->strvalues[StringValue_LocalName].str; + *len = This->strvalues[StringValue_LocalName].len; + } + break; + default: + *name = This->strvalues[StringValue_LocalName].str; + *len = This->strvalues[StringValue_LocalName].len; + break; + } + return S_OK; } -static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface, LPCWSTR *prefix, UINT *len) +static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface, const WCHAR **ret, UINT *len) { xmlreader *This = impl_from_IXmlReader(iface); + XmlNodeType nodetype; + UINT length; - TRACE("(%p)->(%p %p)\n", This, prefix, len); - *prefix = This->strvalues[StringValue_Prefix].str; - if (len) *len = This->strvalues[StringValue_Prefix].len; - return S_OK; -} + TRACE("(%p)->(%p %p)\n", This, ret, len); -static BOOL is_namespace_definition(xmlreader *reader) -{ - const strval *local = &reader->strvalues[StringValue_LocalName]; - const strval *prefix = &reader->strvalues[StringValue_Prefix]; + if (!len) + len = &length; + + *ret = emptyW; + *len = 0; - if (reader_get_nodetype(reader) != XmlNodeType_Attribute) - return FALSE; + switch ((nodetype = reader_get_nodetype(This))) + { + case XmlNodeType_Element: + case XmlNodeType_EndElement: + case XmlNodeType_Attribute: + { + const strval *prefix = &This->strvalues[StringValue_Prefix]; + struct ns *ns; + + if (strval_eq(This, prefix, &strval_xml)) + { + *ret = xmlW; + *len = 3; + } + else if (strval_eq(This, prefix, &strval_xmlns)) + { + *ret = xmlnsW; + *len = 5; + } + else if ((ns = reader_lookup_ns(This, prefix))) + { + *ret = ns->prefix.str; + *len = ns->prefix.len; + } + + break; + } + default: + ; + } - return ((strval_eq(reader, prefix, &strval_empty) && strval_eq(reader, local, &strval_xmlns)) || - strval_eq(reader, prefix, &strval_xmlns)); + return S_OK; } static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, const WCHAR **value, UINT *len) { xmlreader *reader = impl_from_IXmlReader(iface); strval *val = &reader->strvalues[StringValue_Value]; + UINT length; TRACE("(%p)->(%p %p)\n", reader, value, len); *value = NULL; + if (!len) + len = &length; - if ((reader->nodetype == XmlNodeType_Comment && !val->str) || is_reader_pending(reader)) + if ((reader->nodetype == XmlNodeType_Comment && !val->str && !val->len) || is_reader_pending(reader)) { XmlNodeType type; HRESULT hr; @@ -3044,29 +3274,44 @@ if (is_reader_pending(reader)) return E_PENDING; } - if (!val->str) + switch (reader_get_nodetype(reader)) { - WCHAR *ptr = reader_alloc(reader, (val->len+1)*sizeof(WCHAR)); - if (!ptr) return E_OUTOFMEMORY; - memcpy(ptr, reader_get_strptr(reader, val), val->len*sizeof(WCHAR)); - ptr[val->len] = 0; - val->str = ptr; - } + case XmlNodeType_XmlDeclaration: + *value = emptyW; + *len = 0; + break; + case XmlNodeType_Attribute: + { + const strval *local = &reader->strvalues[StringValue_LocalName]; - /* For namespace definition attributes return values from namespace list */ - if (is_namespace_definition(reader)) { - const strval *local = &reader->strvalues[StringValue_LocalName]; - struct ns *ns; + /* For namespace definition attributes return values from namespace list */ + if (reader->attr->flags & (ATTRIBUTE_NS_DEFINITION | ATTRIBUTE_DEFAULT_NS_DEFINITION)) + { + struct ns *ns; - ns = reader_lookup_ns(reader, local); - if (!ns) - ns = reader_lookup_nsdef(reader); + if (!(ns = reader_lookup_ns(reader, local))) + ns = reader_lookup_nsdef(reader); - val = &ns->uri; + *value = ns->uri.str; + *len = ns->uri.len; + break; + } + } + /* fallthrough */ + default: + if (!val->str) + { + WCHAR *ptr = reader_alloc(reader, (val->len+1)*sizeof(WCHAR)); + if (!ptr) return E_OUTOFMEMORY; + memcpy(ptr, reader_get_strptr(reader, val), val->len*sizeof(WCHAR)); + ptr[val->len] = 0; + val->str = ptr; + } + *value = val->str; + *len = val->len; + break; } - *value = val->str; - if (len) *len = val->len; return S_OK; } @@ -3116,30 +3361,68 @@ return (reader_get_nodetype(This) == XmlNodeType_Element) ? This->is_empty_element : FALSE; } -static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader* iface, UINT *lineNumber) +static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader* iface, UINT *line_number) { xmlreader *This = impl_from_IXmlReader(iface); + const struct element *element; - TRACE("(%p %p)\n", This, lineNumber); + TRACE("(%p %p)\n", This, line_number); - if (!lineNumber) return E_INVALIDARG; + if (!line_number) + return E_INVALIDARG; - *lineNumber = This->line; + switch (reader_get_nodetype(This)) + { + case XmlNodeType_Element: + case XmlNodeType_EndElement: + element = reader_get_element(This); + *line_number = element->position.line_number; + break; + case XmlNodeType_Attribute: + *line_number = This->attr->position.line_number; + break; + case XmlNodeType_Whitespace: + case XmlNodeType_XmlDeclaration: + *line_number = This->empty_element.position.line_number; + break; + default: + *line_number = This->position.line_number; + break; + } - return S_OK; + return This->state == XmlReadState_Closed ? S_FALSE : S_OK; } -static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePosition) +static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *line_position) { xmlreader *This = impl_from_IXmlReader(iface); + const struct element *element; - TRACE("(%p %p)\n", This, linePosition); + TRACE("(%p %p)\n", This, line_position); - if (!linePosition) return E_INVALIDARG; + if (!line_position) + return E_INVALIDARG; - *linePosition = This->pos; + switch (reader_get_nodetype(This)) + { + case XmlNodeType_Element: + case XmlNodeType_EndElement: + element = reader_get_element(This); + *line_position = element->position.line_position; + break; + case XmlNodeType_Attribute: + *line_position = This->attr->position.line_position; + break; + case XmlNodeType_Whitespace: + case XmlNodeType_XmlDeclaration: + *line_position = This->empty_element.position.line_position; + break; + default: + *line_position = This->position.line_position; + break; + } - return S_OK; + return This->state == XmlReadState_Closed ? S_FALSE : S_OK; } static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *count) @@ -3164,8 +3447,9 @@ static BOOL WINAPI xmlreader_IsEOF(IXmlReader* iface) { - FIXME("(%p): stub\n", iface); - return FALSE; + xmlreader *This = impl_from_IXmlReader(iface); + TRACE("(%p)\n", iface); + return This->state == XmlReadState_EndOfFile; } static const struct IXmlReaderVtbl xmlreader_vtbl = @@ -3275,31 +3559,24 @@ reader = IMalloc_Alloc(imalloc, sizeof(*reader)); else reader = heap_alloc(sizeof(*reader)); - if(!reader) return E_OUTOFMEMORY; + if (!reader) + return E_OUTOFMEMORY; + memset(reader, 0, sizeof(*reader)); reader->IXmlReader_iface.lpVtbl = &xmlreader_vtbl; reader->ref = 1; - reader->input = NULL; reader->state = XmlReadState_Closed; reader->instate = XmlReadInState_Initial; reader->resumestate = XmlReadResumeState_Initial; reader->dtdmode = DtdProcessing_Prohibit; - reader->resolver = NULL; - reader->mlang = NULL; - reader->line = reader->pos = 0; reader->imalloc = imalloc; if (imalloc) IMalloc_AddRef(imalloc); reader->nodetype = XmlNodeType_None; list_init(&reader->attrs); - reader->attr_count = 0; - reader->attr = NULL; list_init(&reader->nsdef); list_init(&reader->ns); list_init(&reader->elements); - reader->depth = 0; reader->max_depth = 256; - reader->is_empty_element = FALSE; - memset(reader->resume, 0, sizeof(reader->resume)); for (i = 0; i < StringValue_Last; i++) reader->strvalues[i] = strval_empty; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/xmllite/tests/reader.c wine-staging-2.4.0~ubuntu16.04.1/dlls/xmllite/tests/reader.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/xmllite/tests/reader.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/xmllite/tests/reader.c 2017-03-21 14:02:57.000000000 +0000 @@ -1,7 +1,7 @@ /* * IXmlReader tests * - * Copyright 2010, 2012-2013 Nikolay Sivov + * Copyright 2010, 2012-2013, 2016-2017 Nikolay Sivov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -49,7 +49,7 @@ static const char xmldecl_full[] = "\xef\xbb\xbf\n"; static const char xmldecl_short[] = ""; -static IStream *create_stream_on_data(const char *data, int size) +static IStream *create_stream_on_data(const void *data, unsigned int size) { IStream *stream = NULL; HGLOBAL hglobal; @@ -70,29 +70,28 @@ return stream; } -static void ok_pos_(IXmlReader *reader, int line, int pos, int line_broken, - int pos_broken, BOOL todo, int _line_) +static void test_reader_pos(IXmlReader *reader, UINT line, UINT pos, UINT line_broken, + UINT pos_broken, int _line_) { - UINT l, p; - HRESULT hr; + UINT l = ~0u, p = ~0u; BOOL broken_state; - hr = IXmlReader_GetLineNumber(reader, &l); - ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr); - hr = IXmlReader_GetLinePosition(reader, &p); - ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr); + IXmlReader_GetLineNumber(reader, &l); + IXmlReader_GetLinePosition(reader, &p); - if (line_broken == -1 && pos_broken == -1) + if (line_broken == ~0u && pos_broken == ~0u) broken_state = FALSE; else - broken_state = broken((line_broken == -1 ? line : line_broken) == l && - (pos_broken == -1 ? pos : pos_broken) == p); + broken_state = broken((line_broken == ~0u ? line : line_broken) == l && + (pos_broken == ~0u ? pos : pos_broken) == p); - todo_wine_if (todo) - ok_(__FILE__, _line_)((l == line && pos == p) || broken_state, - "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p); + ok_(__FILE__, _line_)((l == line && pos == p) || broken_state, + "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p); } -#define ok_pos(reader, l, p, l_brk, p_brk, todo) ok_pos_(reader, l, p, l_brk, p_brk, todo, __LINE__) +#define TEST_READER_POSITION(reader, line, pos) \ + test_reader_pos(reader, line, pos, ~0u, ~0u, __LINE__) +#define TEST_READER_POSITION2(reader, line, pos, line_broken, pos_broken) \ + test_reader_pos(reader, line, pos, line_broken, pos_broken, __LINE__) typedef struct input_iids_t { IID iids[10]; @@ -213,28 +212,26 @@ } } -static void test_read_state_(IXmlReader *reader, XmlReadState expected, - XmlReadState exp_broken, BOOL todo, int line) +static void test_read_state(IXmlReader *reader, XmlReadState expected, + XmlReadState exp_broken, int line) { - LONG_PTR state; - HRESULT hr; BOOL broken_state; + LONG_PTR state; - state = -1; /* invalid value */ - hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); - ok_(__FILE__, line)(hr == S_OK, "Expected S_OK, got %08x\n", hr); + state = -1; /* invalid state value */ + IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); if (exp_broken == -1) broken_state = FALSE; else broken_state = broken(exp_broken == state); - todo_wine_if (todo) - ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n", - state_to_str(expected), state_to_str(state)); + ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n", + state_to_str(expected), state_to_str(state)); } -#define test_read_state(reader, exp, brk, todo) test_read_state_(reader, exp, brk, todo, __LINE__) +#define TEST_READER_STATE(reader, state) test_read_state(reader, state, -1, __LINE__) +#define TEST_READER_STATE2(reader, state, brk) test_read_state(reader, state, brk, __LINE__) typedef struct _testinput { @@ -420,7 +417,7 @@ hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); nodetype = XmlNodeType_Element; hr = IXmlReader_GetNodeType(reader, &nodetype); @@ -470,7 +467,7 @@ hr = IXmlReader_SetInput(reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); /* test input interface selection sequence */ hr = testinput_createinstance((void**)&input); @@ -533,7 +530,7 @@ hr = IXmlReader_SetInput(reader, reader_input); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Initial); nodetype = XmlNodeType_Element; hr = IXmlReader_GetNodeType(reader, &nodetype); @@ -553,7 +550,7 @@ hr = IXmlReader_SetInput(reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); IXmlReader_Release(reader); @@ -611,7 +608,7 @@ ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr); ok_iids(&input_iids, setinput_readerinput, NULL, FALSE); - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); ref = IUnknown_AddRef(input); ok(ref == 3, "Expected 3, got %d\n", ref); @@ -647,8 +644,9 @@ static void test_reader_state(void) { - IXmlReader *reader; XmlNodeType nodetype; + IXmlReader *reader; + IStream *stream; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); @@ -659,16 +657,57 @@ ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); /* attempt to read on closed reader */ - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); + if (0) { - /* newer versions crash here, probably cause no input was set */ + /* newer versions crash here, probably because no input was set */ hr = IXmlReader_Read(reader, &nodetype); ok(hr == S_FALSE, "got %08x\n", hr); } + + stream = create_stream_on_data("xml", sizeof("xml")); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + TEST_READER_STATE(reader, XmlReadState_Initial); + + nodetype = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &nodetype); +todo_wine + ok(FAILED(hr), "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype); + +todo_wine + TEST_READER_STATE(reader, XmlReadState_Error); + + nodetype = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &nodetype); +todo_wine + ok(FAILED(hr), "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype); + + IStream_Release(stream); IXmlReader_Release(reader); } +static void test_reader_depth(IXmlReader *reader, UINT depth, UINT brk, int line) +{ + BOOL condition; + UINT d = ~0u; + + IXmlReader_GetDepth(reader, &d); + + condition = d == depth; + if (brk != ~0u) + condition |= broken(d == brk); + ok_(__FILE__, line)(condition, "Unexpected nesting depth %u, expected %u\n", d, depth); +} + +#define TEST_DEPTH(reader, depth) test_reader_depth(reader, depth, ~0u, __LINE__) +#define TEST_DEPTH2(reader, depth, brk) test_reader_depth(reader, depth, brk, __LINE__) + static void test_read_xmldeclaration(void) { static const WCHAR xmlW[] = {'x','m','l',0}; @@ -694,13 +733,6 @@ hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - /* position methods with Null args */ - hr = IXmlReader_GetLineNumber(reader, NULL); - ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); - - hr = IXmlReader_GetLinePosition(reader, NULL); - ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); - stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full)); hr = IXmlReader_SetInput(reader, (IUnknown*)stream); @@ -720,7 +752,7 @@ hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_FALSE, "got %08x\n", hr); - ok_pos(reader, 0, 0, -1, -1, FALSE); + TEST_READER_POSITION(reader, 0, 0); type = -1; hr = IXmlReader_Read(reader, &type); @@ -728,8 +760,10 @@ ok(type == XmlNodeType_XmlDeclaration, "Expected XmlNodeType_XmlDeclaration, got %s\n", type_to_str(type)); /* new version 1.2.x and 1.3.x properly update position for */ - ok_pos(reader, 1, 3, -1, 55, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, FALSE); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 55); + + TEST_DEPTH(reader, 0); + TEST_READER_STATE(reader, XmlReadState_Interactive); hr = IXmlReader_GetValue(reader, &val, NULL); ok(hr == S_OK, "got %08x\n", hr); @@ -739,12 +773,14 @@ hr = IXmlReader_MoveToNextAttribute(reader); ok(hr == S_OK, "got %08x\n", hr); + TEST_DEPTH(reader, 1); + type = XmlNodeType_None; hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - ok_pos(reader, 1, 7, -1, 55, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 55); /* try to move from last attribute */ hr = IXmlReader_MoveToNextAttribute(reader); @@ -761,7 +797,7 @@ hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_OK, "got %08x\n", hr); - ok_pos(reader, 1, 7, -1, 55, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 55); hr = IXmlReader_GetAttributeCount(reader, NULL); ok(hr == E_INVALIDARG, "got %08x\n", hr); @@ -788,12 +824,11 @@ ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr); } - hr = IXmlReader_GetDepth(reader, &count); - ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - ok(count == 1, "Expected 1, got %d\n", count); + TEST_DEPTH(reader, 1); hr = IXmlReader_MoveToElement(reader); ok(hr == S_OK, "got %08x\n", hr); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 55); type = XmlNodeType_None; hr = IXmlReader_GetNodeType(reader, &type); @@ -820,8 +855,8 @@ hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); ok(type == XmlNodeType_XmlDeclaration, "expected XmlDeclaration, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 3, 1, 21, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, TRUE); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 21); + TEST_READER_STATE(reader, XmlReadState_Interactive); hr = IXmlReader_GetAttributeCount(reader, &count); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); @@ -834,9 +869,14 @@ ok(hr == S_OK, "expected S_OK, got %08x\n", hr); ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); + val = NULL; hr = IXmlReader_GetLocalName(reader, &val, NULL); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); -todo_wine + ok(!lstrcmpW(val, xmlW), "got %s\n", wine_dbgstr_w(val)); + + val = NULL; + hr = IXmlReader_GetQualifiedName(reader, &val, NULL); + ok(hr == S_OK, "expected S_OK, got %08x\n", hr); ok(!lstrcmpW(val, xmlW), "got %s\n", wine_dbgstr_w(val)); /* check attributes */ @@ -847,7 +887,7 @@ hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - ok_pos(reader, 1, 7, 1, 21, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 21); /* try to move from last attribute */ hr = IXmlReader_MoveToNextAttribute(reader); @@ -857,8 +897,8 @@ hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); ok(type == XmlNodeType_Element, "expected Element, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 23, 1, 40, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, TRUE); + TEST_READER_POSITION2(reader, 1, 23, ~0u, 40); + TEST_READER_STATE(reader, XmlReadState_Interactive); hr = IXmlReader_GetAttributeCount(reader, &count); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); @@ -869,7 +909,6 @@ hr = IXmlReader_GetValue(reader, &val, NULL); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); -todo_wine ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); hr = IXmlReader_GetLocalName(reader, &val, NULL); @@ -880,10 +919,10 @@ hr = IXmlReader_Read(reader, &type); todo_wine ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr); + ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type)); + TEST_READER_POSITION(reader, 1, 41); todo_wine - ok(type == XmlNodeType_None, "expected None, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 41, -1, -1, TRUE); - test_read_state(reader, XmlReadState_Error, -1, TRUE); + TEST_READER_STATE(reader, XmlReadState_Error); IStream_Release(stream); IXmlReader_Release(reader); @@ -908,18 +947,47 @@ static void test_read_comment(void) { + static const char *teststr = "text"; struct test_entry *test = comment_tests; + static const XmlNodeType types[] = + { + XmlNodeType_Element, + XmlNodeType_Text, + XmlNodeType_Comment, + XmlNodeType_EndElement, + }; + unsigned int i = 0; IXmlReader *reader; + XmlNodeType type; + IStream *stream; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); - while (test->xml) + stream = create_stream_on_data(teststr, strlen(teststr)); + hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + ok(hr == S_OK, "got %08x\n", hr); + + while (IXmlReader_Read(reader, &type) == S_OK) { - XmlNodeType type; - IStream *stream; + const WCHAR *value; + + ok(type == types[i], "%d: unexpected node type %d\n", i, type); + + if (type == XmlNodeType_Text || type == XmlNodeType_Comment) + { + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(*value != 0, "Expected node value\n"); + } + i++; + } + IStream_Release(stream); + + while (test->xml) + { stream = create_stream_on_data(test->xml, strlen(test->xml)+1); hr = IXmlReader_SetInput(reader, (IUnknown*)stream); ok(hr == S_OK, "got %08x\n", hr); @@ -942,19 +1010,25 @@ str = NULL; hr = IXmlReader_GetLocalName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + + str = NULL; + hr = IXmlReader_GetLocalName(reader, &str, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); len = 1; str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); /* value */ len = 1; @@ -1118,9 +1192,8 @@ ok(hr == S_OK, "got %08x\n", hr); i = 0; - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - while (hr == S_OK) + type = ~0u; + while (IXmlReader_Read(reader, &type) == S_OK) { ok(test->types[i] != XmlNodeType_None, "%d: unexpected end of test data\n", i); if (test->types[i] == XmlNodeType_None) break; @@ -1134,7 +1207,6 @@ ok(hr == S_OK, "%d: GetValue failed 0x%08x\n", i, hr); ok(len > 0, "%d: wrong value length %d\n", i, len); } - hr = IXmlReader_Read(reader, &type); i++; } ok(test->types[i] == XmlNodeType_None, "incomplete sequence, got %d\n", test->types[i]); @@ -1239,9 +1311,10 @@ str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); +todo_wine { ok(len == lstrlenW(dtdnameW), "got %u\n", len); ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); - +} IStream_Release(stream); IXmlReader_Release(reader); } @@ -1319,9 +1392,10 @@ str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); +todo_wine { ok(len == lstrlenW(dtdnameW), "got %u\n", len); ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); - +} type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "got 0x%8x\n", hr); @@ -1341,17 +1415,28 @@ { "", "a", "", S_OK }, { "", "a", "", S_OK }, { "", NULL, NULL, NC_E_QNAMECHARACTER }, + { "", NULL, NULL, NC_E_QNAMECOLON }, + { "<:b:c />", NULL, NULL, NC_E_QNAMECHARACTER }, { NULL } }; static void test_read_element(void) { struct test_entry *test = element_tests; - static const char stag[] = ""; + static const char stag[] = + "" + "" + "text" + "" + "" + "" + ""; + static const UINT depths[] = { 0, 1, 2, 2, 2, 3, 2, 1 }; static const char mismatch[] = ""; IXmlReader *reader; XmlNodeType type; IStream *stream; + unsigned int i; UINT depth; HRESULT hr; @@ -1403,56 +1488,97 @@ /* test reader depth increment */ stream = create_stream_on_data(stag, sizeof(stag)); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); ok(hr == S_OK, "got %08x\n", hr); - depth = 1; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 0, "got %d\n", depth); + i = 0; + while (IXmlReader_Read(reader, &type) == S_OK) + { + UINT count; - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Element, "got %d\n", type); + ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement || + type == XmlNodeType_Text, "Unexpected node type %d\n", type); - depth = 1; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 0, "got %d\n", depth); + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]); - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Element, "got %d\n", type); + if (type == XmlNodeType_Element || type == XmlNodeType_EndElement) + { + const WCHAR *prefix; - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 1, "got %d\n", depth); + prefix = NULL; + hr = IXmlReader_GetPrefix(reader, &prefix, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(prefix != NULL, "got %p\n", prefix); - /* read end tag for inner element */ - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_EndElement, "got %d\n", type); + if (!*prefix) + { + const WCHAR *local, *qname; - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); -todo_wine - ok(depth == 2, "got %d\n", depth); + local = NULL; + hr = IXmlReader_GetLocalName(reader, &local, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(local != NULL, "got %p\n", local); + + qname = NULL; + hr = IXmlReader_GetQualifiedName(reader, &qname, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(qname != NULL, "got %p\n", qname); - /* read end tag for container element */ - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_EndElement, "got %d\n", type); + ok(local == qname, "expected same pointer\n"); + } + } - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 1, "got %d\n", depth); + if (type == XmlNodeType_EndElement) + { + count = 1; + hr = IXmlReader_GetAttributeCount(reader, &count); + ok(hr == S_OK, "got %08x\n", hr); + ok(count == 0, "got %u\n", count); + } + + if (type == XmlNodeType_Element) + { + count = 0; + hr = IXmlReader_GetAttributeCount(reader, &count); + ok(hr == S_OK, "got %08x\n", hr); + + /* moving to attributes increases depth */ + if (count) + { + const WCHAR *value; + + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(*value == 0, "Unexpected value %s\n", wine_dbgstr_w(value)); + + hr = IXmlReader_MoveToFirstAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(*value != 0, "Unexpected value %s\n", wine_dbgstr_w(value)); + + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i] + 1, "%u: got depth %u, expected %u\n", i, depth, depths[i] + 1); + + hr = IXmlReader_MoveToElement(reader); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(*value == 0, "Unexpected value %s\n", wine_dbgstr_w(value)); + + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]); + } + } + + i++; + } IStream_Release(stream); @@ -1469,8 +1595,8 @@ type = XmlNodeType_Element; hr = IXmlReader_Read(reader, &type); ok(hr == WC_E_ELEMENTMATCH, "got %08x\n", hr); -todo_wine ok(type == XmlNodeType_None, "got %d\n", type); + TEST_READER_STATE(reader, XmlReadState_Error); IStream_Release(stream); @@ -1500,6 +1626,7 @@ ok(hr == S_OK || broken(hr == E_PENDING), "got 0x%08x\n", hr); /* newer versions are happy when it's enough data to detect node type, older versions keep reading until it fails to read more */ +todo_wine ok(stream_readcall == 1 || broken(stream_readcall > 1), "got %d\n", stream_readcall); ok(type == XmlNodeType_Comment || broken(type == XmlNodeType_None), "got %d\n", type); @@ -1614,30 +1741,29 @@ ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml); - str_exp = a2w(test->name); - len = 1; str = NULL; hr = IXmlReader_GetLocalName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); str = NULL; hr = IXmlReader_GetLocalName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); len = 1; str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); /* value */ len = 1; @@ -1664,6 +1790,8 @@ static struct test_entry text_tests[] = { { "simple text", "", "simple text", S_OK }, { "text ]]> text", "", "", WC_E_CDSECTEND }, + { "\n \r\n \n\n text", "", "\n \n \n\n text", S_OK, S_OK, TRUE }, + { "\r \r\r\n \n\n text", "", "\n \n\n \n\n text", S_OK, S_OK, TRUE }, { NULL } }; @@ -1688,17 +1816,13 @@ type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); - /* read one more to get to CDATA */ + /* read one more to get to text node */ if (type == XmlNodeType_Element) { type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); } - - if (test->hr_broken) - ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml); - else - ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); + ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); if (hr == S_OK) { const WCHAR *str; @@ -1707,30 +1831,29 @@ ok(type == XmlNodeType_Text, "got %d for %s\n", type, test->xml); - str_exp = a2w(test->name); - len = 1; str = NULL; hr = IXmlReader_GetLocalName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); str = NULL; hr = IXmlReader_GetLocalName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); len = 1; str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); /* value */ len = 1; @@ -1875,12 +1998,11 @@ str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - todo_wine { ok(len == strlen(test->name), "got %u\n", len); str_exp = a2w(test->name); ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); free_str(str_exp); - } + /* value */ len = 1; str = NULL; @@ -1902,17 +2024,28 @@ static void test_reader_properties(void) { IXmlReader *reader; + LONG_PTR value; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); + value = 0; + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value); + ok(hr == S_OK, "GetProperty failed: %08x\n", hr); + ok(value == 256, "Unexpected default max depth value %ld\n", value); + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MultiLanguage, 0); ok(hr == S_OK, "SetProperty failed: %08x\n", hr); hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0); ok(hr == S_OK, "SetProperty failed: %08x\n", hr); + value = 256; + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value); + ok(hr == S_OK, "GetProperty failed: %08x\n", hr); + ok(value == 0, "Unexpected max depth value %ld\n", value); + IXmlReader_Release(reader); } @@ -1927,6 +2060,7 @@ } prefix_tests[] = { { "", "", "", "xml" }, + { "", "c", "xmlns", "xml" }, }; IXmlReader *reader; unsigned int i; @@ -1984,6 +2118,17 @@ wine_dbgstr_w(expected)); free_str(expected); + /* back to the element, check prefix */ + hr = IXmlReader_MoveToElement(reader); + ok(hr == S_OK, "MoveToElement() failed, %#x.\n", hr); + + expected = a2w(prefix_tests[i].prefix1); + hr = IXmlReader_GetPrefix(reader, &prefix, NULL); + ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr); + ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix), + wine_dbgstr_w(expected)); + free_str(expected); + IStream_Release(stream); } @@ -2008,6 +2153,18 @@ { "defns a", "ns r", "defns a" }}, { "", { "", "", "", "", "" }}, + { "text", + { "", "", "" }}, + { "\r\n", + { "", "", "" }}, + { "", + { "", "", "" }}, + { "", + { "", "" }}, + { "", + { "", "", "" }}, + { "", + { "", "", "" }}, }; IXmlReader *reader; XmlNodeType type; @@ -2024,17 +2181,49 @@ hr = IXmlReader_SetInput(reader, (IUnknown *)stream); ok(hr == S_OK, "got %08x\n", hr); + type = ~0u; while (IXmlReader_Read(reader, &type) == S_OK) { - const WCHAR *uri, *local; + const WCHAR *uri, *local, *qname; + UINT length, length2; WCHAR *uriW; - ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement, "Unexpected node type %d.\n", type); + ok(type == XmlNodeType_Element || + type == XmlNodeType_Text || + type == XmlNodeType_CDATA || + type == XmlNodeType_ProcessingInstruction || + type == XmlNodeType_Comment || + type == XmlNodeType_Whitespace || + type == XmlNodeType_EndElement || + type == XmlNodeType_XmlDeclaration, "Unexpected node type %d.\n", type); + + local = NULL; + length = 0; + hr = IXmlReader_GetLocalName(reader, &local, &length); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + ok(local != NULL, "Unexpected NULL local name pointer\n"); - hr = IXmlReader_GetLocalName(reader, &local, NULL); + qname = NULL; + length2 = 0; + hr = IXmlReader_GetQualifiedName(reader, &qname, &length2); ok(hr == S_OK, "S_OK, got %08x\n", hr); + ok(qname != NULL, "Unexpected NULL qualified name pointer\n"); + if (type == XmlNodeType_Element || + type == XmlNodeType_EndElement || + type == XmlNodeType_ProcessingInstruction || + type == XmlNodeType_XmlDeclaration) + { + ok(*local != 0, "Unexpected empty local name\n"); + ok(length > 0, "Unexpected local name length\n"); + + ok(*qname != 0, "Unexpected empty qualified name\n"); + ok(length2 > 0, "Unexpected qualified name length\n"); + } + + uri = NULL; hr = IXmlReader_GetNamespaceUri(reader, &uri, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); + ok(uri != NULL, "Unexpected NULL uri pointer\n"); uriW = a2w(uri_tests[i].uri[j]); ok(!lstrcmpW(uriW, uri), "%s: uri %s\n", wine_dbgstr_w(local), wine_dbgstr_w(uri)); @@ -2042,6 +2231,7 @@ j++; } + ok(type == XmlNodeType_None, "Unexpected node type %d\n", type); IStream_Release(stream); } @@ -2086,6 +2276,316 @@ IStream_Release(stream); } +static void test_encoding_detection(void) +{ + static const struct encoding_testW + { + WCHAR text[16]; + } + encoding_testsW[] = + { + { { '<','?','p','i',' ','?','>',0 } }, + { { '<','!','-','-',' ','c','-','-','>',0 } }, + { { 0xfeff,'<','a','/','>',0 } }, + { { '<','a','/','>',0 } }, + }; + static const char *encoding_testsA[] = + { + "", + "", + "\xef\xbb\xbf", /* UTF-8 BOM */ + "", + }; + IXmlReader *reader; + XmlNodeType type; + IStream *stream; + unsigned int i; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + /* there's no way to query detected encoding back, so just verify that document is browsable */ + + for (i = 0; i < sizeof(encoding_testsA)/sizeof(encoding_testsA[0]); i++) + { + stream = create_stream_on_data(encoding_testsA[i], strlen(encoding_testsA[i])); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type != XmlNodeType_None, "Unexpected node type %d\n", type); + + IStream_Release(stream); + } + + for (i = 0; i < sizeof(encoding_testsW)/sizeof(encoding_testsW[0]); i++) + { + stream = create_stream_on_data(encoding_testsW[i].text, lstrlenW(encoding_testsW[i].text) * sizeof(WCHAR)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "%u: got %08x\n", i, hr); + ok(type != XmlNodeType_None, "%u: unexpected node type %d\n", i, type); + + IStream_Release(stream); + } + + IXmlReader_Release(reader); +} + +static void test_eof_state(IXmlReader *reader, BOOL eof) +{ + LONG_PTR state; + HRESULT hr; + + ok(IXmlReader_IsEOF(reader) == eof, "Unexpected IsEOF() result\n"); + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); + ok(hr == S_OK, "GetProperty() failed, %#x\n", hr); + ok((state == XmlReadState_EndOfFile) == eof, "Unexpected EndOfFile state %ld\n", state); +} + +static void test_endoffile(void) +{ + static const char *xml = ""; + IXmlReader *reader; + XmlNodeType type; + IStream *stream; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + test_eof_state(reader, FALSE); + + stream = create_stream_on_data(xml, strlen(xml)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + test_eof_state(reader, FALSE); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %#x\n", hr); + ok(type == XmlNodeType_Element, "Unexpected type %d\n", type); + + test_eof_state(reader, FALSE); + + type = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(type == XmlNodeType_None, "Unexpected type %d\n", type); + + test_eof_state(reader, TRUE); + + hr = IXmlReader_SetInput(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + test_eof_state(reader, FALSE); + + IStream_Release(stream); + + IXmlReader_Release(reader); +} + +static void test_max_element_depth(void) +{ + static const char *xml = + "" + "" + "" + "" + "" + "" + ""; + XmlNodeType nodetype; + unsigned int count; + IXmlReader *reader; + IStream *stream; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + stream = create_stream_on_data(xml, strlen(xml)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 1); + TEST_READER_STATE(reader, XmlReadState_Interactive); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 10); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + IStream_Release(stream); + + /* test if stepping into attributes enforces depth limit too */ + stream = create_stream_on_data(xml, strlen(xml)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 1); + + hr = IXmlReader_MoveToFirstAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 2); + TEST_READER_STATE(reader, XmlReadState_Interactive); + + nodetype = 123; + hr = IXmlReader_Read(reader, &nodetype); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype); + + nodetype = 123; + hr = IXmlReader_Read(reader, &nodetype); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + + IStream_Release(stream); + + /* set max depth to 0, this disables depth limit */ + stream = create_stream_on_data(xml, strlen(xml)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0); + ok(hr == S_OK, "got %08x\n", hr); + + count = 0; + while (IXmlReader_Read(reader, NULL) == S_OK) + count++; + ok(count == 8, "Unexpected node number %u\n", count); + TEST_READER_STATE(reader, XmlReadState_EndOfFile); + + IStream_Release(stream); + + IXmlReader_Release(reader); +} + +static void test_reader_position(void) +{ + static const char *xml = "\n"; + IXmlReader *reader; + XmlNodeType type; + IStream *stream; + UINT position; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + TEST_READER_STATE(reader, XmlReadState_Closed); + + /* position methods with Null args */ + hr = IXmlReader_GetLineNumber(reader, NULL); + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); + + hr = IXmlReader_GetLinePosition(reader, NULL); + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); + + position = 123; + hr = IXmlReader_GetLinePosition(reader, &position); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(position == 0, "got %u\n", position); + + position = 123; + hr = IXmlReader_GetLineNumber(reader, &position); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(position == 0, "got %u\n", position); + + stream = create_stream_on_data(xml, strlen(xml)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_READER_STATE(reader, XmlReadState_Initial); + TEST_READER_POSITION(reader, 0, 0); + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Element, "got type %d\n", type); + TEST_READER_POSITION2(reader, 1, 2, ~0u, 34); + + hr = IXmlReader_MoveToNextAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + TEST_READER_POSITION2(reader, 1, 6, ~0u, 34); + + hr = IXmlReader_MoveToNextAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + TEST_READER_POSITION2(reader, 1, 24, ~0u, 34); + + hr = IXmlReader_MoveToElement(reader); + ok(hr == S_OK, "got %08x\n", hr); + TEST_READER_POSITION2(reader, 1, 2, ~0u, 34); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Whitespace, "got type %d\n", type); + TEST_READER_POSITION2(reader, 1, 35, 2, 6); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_EndElement, "got type %d\n", type); + TEST_READER_POSITION2(reader, 2, 3, 2, 6); + + IXmlReader_SetInput(reader, NULL); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); + TEST_READER_POSITION(reader, 0, 0); + + IStream_Release(stream); + IXmlReader_Release(reader); +} + START_TEST(reader) { test_reader_create(); @@ -2108,4 +2608,8 @@ test_prefix(); test_namespaceuri(); test_read_charref(); + test_encoding_detection(); + test_endoffile(); + test_max_element_depth(); + test_reader_position(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/dlls/xmllite/tests/writer.c wine-staging-2.4.0~ubuntu16.04.1/dlls/xmllite/tests/writer.c --- wine-staging-2.3.0~ubuntu16.04.1/dlls/xmllite/tests/writer.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/dlls/xmllite/tests/writer.c 2017-03-21 14:02:57.000000000 +0000 @@ -31,6 +31,15 @@ #include "initguid.h" DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a); +#define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__) +static void _expect_ref(IUnknown *obj, ULONG ref, int line) +{ + ULONG refcount; + IUnknown_AddRef(obj); + refcount = IUnknown_Release(obj); + ok_(__FILE__, line)(refcount == ref, "expected refcount %d, got %d\n", ref, refcount); +} + static void check_output(IStream *stream, const char *expected, BOOL todo, int line) { int len = strlen(expected), size; @@ -273,6 +282,7 @@ output = NULL; hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output); ok(hr == S_OK, "got %08x\n", hr); + EXPECT_REF(output, 1); IUnknown_Release(output); hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output); @@ -280,9 +290,13 @@ unk = NULL; hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk); ok(hr == S_OK, "got %08x\n", hr); - ok(unk != NULL, "got %p\n", unk); +todo_wine + ok(unk != NULL && unk != output, "got %p, output %p\n", unk, output); + EXPECT_REF(output, 2); /* releasing 'unk' crashes on native */ IUnknown_Release(output); + EXPECT_REF(output, 1); + IUnknown_Release(output); output = NULL; hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, ~0u, &output); @@ -297,6 +311,7 @@ ok(unk != NULL, "got %p\n", unk); /* releasing 'unk' crashes on native */ IUnknown_Release(output); + IUnknown_Release(output); } static void test_writestartdocument(void) diff -Nru wine-staging-2.3.0~ubuntu16.04.1/documentation/README.de wine-staging-2.4.0~ubuntu16.04.1/documentation/README.de --- wine-staging-2.3.0~ubuntu16.04.1/documentation/README.de 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/documentation/README.de 2017-03-21 14:02:57.000000000 +0000 @@ -3,32 +3,33 @@ Wine ist ein Programm, das es ermöglicht, Programme, die für Microsoft Windows geschrieben wurden (inklusive DOS-, Windows 3.x-, Win32- und Win64-Binärdateien), unter Unix auszuführen. Es besteht aus einem Programm- -Lader, der Microsoft Windows-Binärdateien lädt und ausführt, sowie -einer Library (Winelib genannt), die Aufrufe der Windows API unter +Lader, der Microsoft-Windows-Binärdateien lädt und ausführt, sowie +einer Programmbibliothek (Winelib genannt), die Aufrufe der Windows API unter Verwendung der entsprechenden Unix- oder X11-Gegenstücke implementiert. -Die Library kann auch benutzt werden, um Windows-Code nativ nach Unix +Winelib kann auch benutzt werden, um Windows-Code nativ nach Unix zu portieren. Wine ist Freie Software, die unter der GNU LGPL veröffentlicht wird; Bitte lesen Sie die Details in der Datei LICENSE nach. + 2. SCHNELLSTART -Um den Quelltext zu kompilieren, empfiehlt es sich immer, den Wine- -Installer für den Build und die Installation von Wine zu verwenden. -Rufen Sie dazu aus dem Wurzelverzeichnis des Wine-Quelltextes (das -diese Datei enthält) das folgende Kommando auf: +Rufen Sie aus dem Stammverzeichnis des Wine-Quelltextes (das die Datei README +enthält) folgende Befehle auf: -./tools/wineinstall +./configure +make -Starten Sie Programme mit "wine [Optionen] Programm". Weitere +Starten Sie Programme mit "wine Programmname". Weitere Informationen und Problemlösungen entnehmen Sie bitte dem Rest dieser Datei, der Man-Page von Wine und insbesondere der Vielzahl an Informationen, die Sie auf http://www.winehq.org finden. + 3. VORAUSSETZUNGEN -Um Wine kompilieren und ausführen zu können, brauchen Sie eines der +Um Wine kompilieren und ausführen zu können, benötigen Sie eines der folgenden Betriebssysteme: Linux version 2.0.36 oder neuer @@ -43,80 +44,80 @@ Umständen in der Zukunft unterstützt. FreeBSD-Info: - Wine läuft prinzipiell erst ab FreeBSD 8.0 richtig. Siehe dazu auch - http://wiki.freebsd.org/Wine für weitere Informationen. + Wine wird generell nicht korrekt unter FreeBSD vor 8.0 funktionieren. Für + weitere Informationen überprüfen Sie auch http://wiki.freebsd.org/Wine Solaris-Info: - Höchstwahrscheinlich müssen Sie den Wine-Build mit der GNU-Toolchain - (gcc, gas etc.) durchführen. Warnung: Die Installation von gas stellt nicht - sicher, dass es vom gcc auch verwendet wird. Den gcc neu zu kompilieren, nach - der Installation von gas, oder die Symbolischen Links von cc, as und ld - mit den GNU-Tools zu verknüpfen, soll ausreichend sein. + Höchstwahrscheinlich werden Sie Wine mit der GNU-Toolchain (gcc, gas etc.) + kompilieren müssen. Warnung: Die Installation von gas stellt *nicht* + sicher, dass es auch von gcc verwendet wird. Erneutes Kompilieren von gcc, + nach der Installation von gas, oder das symbolische Verlinken von cc, as und + ld auf die GNU-Tools ist vermutlich notwendig. NetBSD-Info: Stellen Sie sicher, dass Sie die Optionen USER_LDT, SYSVSHM, SYSVSEM und SYSVMSG in Ihrem Kernel aktiviert haben. Mac OS X Info: - Sie benötigen mindestens Xcode 2.4 um richtig unter x86 kompilieren zu können. - Der Mac Treiber benötigt mindestens OS X 10.6 und kompiliert nicht unter 10.5. + Sie benötigen mindestens Xcode 2.4 um richtig unter x86 kompilieren zu + können. Der Mac-Treiber benötigt mindestens OS X 10.6, unter 10.5 wird + dieser nicht mit kompiliert. Unterstützte Dateisysteme: Wine sollte auf den meisten Dateisystemen laufen. Kompatibilitätsprobleme wurden allerdings beim Dateizugriff über Samba gemeldet. Weiterhin bietet NTFS nicht alle Dateisystemfunktionen, die von einigen - Programmen benötigt werden. Ein natives Unix-Dateisystem wird empfohlen. + Programmen benötigt werden. Ein natives Unix-Dateisystem ist empfohlen. Grundsätzliche Voraussetzungen: - Sie müssen die Include-Dateien für X11-Entwicklung installiert haben + Sie müssen die Entwicklungsdateien für X11 installiert haben (Debian nennt diese xlib6g-dev, Red Hat XFree86-devel). - Natürlich benötigen Sie auch "make" (höchstwahrscheinlich GNU make). + Selbstverständlich benötigen Sie auch "make" (höchstwahrscheinlich GNU make). - Des Weiteren benötigen Sie flex in der Version 2.5.33 oder höher und bison. + Des Weiteren benötigen Sie flex (Version 2.5.33 oder höher) und bison. -Optionale Support-Bibliotheken: - Der ./configure Aufruf zeigt am Ende optionale Bibliotheken an, - die von Wine benutzt werden können, aber auf dem System nicht vorhanden - sind. Siehe http://wiki.winehq.org/Recommended_Package für Tipps zum - installieren fehlender Pakete. - - Auf 64-Bit Plattformen, falls Sie Wine als 32-Bit kompilieren (Standard), - benötigen Sie die 32-bit Versionen dieser Bibliotheken; - siehe dazu http://wiki.winehq.org/WineOn64bit - Für ein reines 64-Bit Wine (oder ein gemischtes 32-Bit und 64-Bit Wine Setup), +Optionale Bibliotheken: + Der Configure-Aufruf zeigt am Ende optionale Bibliotheken an, + die von Wine benutzt werden können, aber auf Ihrem System nicht gefunden + wurden. Tipps zum Installieren fehlender Pakete finden Sie unter: + http://wiki.winehq.org/Recommended_Packages + + Unter 64-Bit Plattformen, falls Sie Wine als 32-Bit kompilieren (Standard), + benötigen Sie die 32-Bit-Versionen dieser Bibliotheken; Details unter + http://wiki.winehq.org/WineOn64bit + Für ein reines 64-Bit Wine (oder ein gemischtes 32- und 64-Bit Wine-Setup), siehe http://wiki.winehq.org/Wine64 4. KOMPILIEREN -Wenn Sie sich dafür entscheiden, wineinstall nicht zu benutzen, führen Sie -bitte die folgenden Kommandos für den Build von Wine aus: +Um Wine zu kompilieren, führen Sie aus: ./configure make -Das erledigt den Build des Programms "wine" und verschiedener Support- -Libraries / -Binärdateien. -Das Programm "wine" lädt ausführbare Windows-Dateien und führt sie aus. -Die Library "libwine" ("WineLib") kann benutzt werden, um Windows-Quelltexte +Damit werden das Programm "wine" und diverse unterstützende Bibliotheken und +Binärdateien erstellt. Das Programm "wine" lädt ausführbare Windows-Dateien +und führt diese aus. +Die Bibliothek "libwine" ("Winelib") kann benutzt werden, um Windows-Quelltexte unter Unix zu kompilieren und zu verlinken. -Mit ./configure --help können Sie sich die Konfigurations-Optionen für -die Kompilierung anzeigen lassen. +Mit ./configure --help können Sie sich Konfigurations-Optionen für die +Kompilierung anzeigen lassen. 5. SETUP -Nachdem der Build von Wine korrekt durchgelaufen ist, können Sie das -Kommando "make install" aufrufen; Dadurch werden das Wine-Programme und -Bibliotheken, die Man-Page und andere benötigte Dateien installiert. - -Vergessen Sie nicht, erst alle früheren Wine-Installationen zu entfernen. -Führen Sie vor der Installation entweder "dpkg -r wine", "rpm -e wine" oder -"make uninstall" aus. - -Nach der Installation können Sie das "winecfg" Tool ausführen. -Die Konfigurations-Hinweise finden Sie im Support-Bereich -von http://www.winehq.org. +Nachdem Wine korrekt erstellt wurde, können Sie "make install" aufrufen; +Dadurch werden Wine-Programme und Bibliotheken, die Man-Page und andere nötige +Dateien installiert. + +Vergessen Sie nicht, zuerst frühere Wine-Installationen zu entfernen, die mit +der neuen in Konflikt stehen könnten. Versuchen Sie entweder "dpkg -r wine", +"rpm -e wine" oder "make uninstall" vor der Installation auszuführen. + +Nach der Installation können Sie das Tool "winecfg" starten. +Konfigurationshinweise finden Sie im Support-Bereich auf http://www.winehq.org/ + 6. AUSFÜHREN VON PROGRAMMEN @@ -125,23 +126,23 @@ Beispiel: Um Notepad auszuführen: - wine notepad (den Suchpfad, der in der Registry - wine notepad.exe angegeben wurde, benutzend) + wine notepad (wobei der Suchpfad, wie in der Registrierung + wine notepad.exe angegeben, benutzt wird) - wine c:\\windows\\notepad.exe (die Dateinamen-Syntax von DOS benutzend) + wine c:\\windows\\notepad.exe (mit Dateinamen-Syntax von DOS) - wine ~/.wine/drive_c/windows/notepad.exe (die Dateinamen-Syntax - von Unix benutzend) + wine ~/.wine/drive_c/windows/notepad.exe (mit Unix-Syntax) - wine notepad.exe liesmich.txt (Programmaufruf mit Parametern) + wine notepad.exe liesmich.txt (Programmaufruf mit Parametern) Wine ist nicht perfekt, daher können manche Programme abstürzen. In diesem Fall bekommen Sie einen Log vom Absturz, den Sie beifügen sollten, wenn Sie den Fehler melden. + 7. WEITERFÜHRENDE INFORMATIONEN -WWW: Eine große Anzahl an Informationen findet sich im WineHQ unter +WWW: Eine große Menge an Informationen findet sich im WineHQ unter http://www.winehq.org/ : Verschiedene Wine Guides, Applikations-Datenbank, Bugtracker. Das ist vermutlich der beste Ausgangspunkt. @@ -151,22 +152,22 @@ Wiki: Das Wine-Wiki finden Sie unter http://wiki.winehq.org Mailing-Listen: - Es gibt mehrere Mailing-Listen für die Wine-User und -Entwickler; - Schauen Sie sich bitte dazu http://www.winehq.org/forums an. + Es gibt mehrere Mailing-Listen für Wine-Anwender und -Entwickler; + Schauen Sie sich dazu bitte http://www.winehq.org/forums an. Fehler: Melden Sie Fehler bitte an Wine-Bugzilla unter http://bugs.winehq.org Schauen Sie bitte erst in der Bugzilla-Datenbank nach, ob Ihr Problem - bereits gemeldet oder behoben wurde, bevor Sie eine Fehlermeldung verfassen. + bereits bekannt ist oder sogar behoben wurde, bevor Sie eine Fehlermeldung + verfassen. -IRC: Online-Hilfe wird Ihnen im Chat-Kanal #WineHQ unter - irc.freenode.net gewährt. +IRC: Online-Hilfe ist im IRC-Kanal #WineHQ unter irc.freenode.net verfügbar. -Git: Der aktuelle Wine-Entwicklungs-Zweig ist über Git verfügbar. +Git: Der aktuelle Wine-Entwicklungsstand ist über Git verfügbar. Besuchen Sie http://www.winehq.org/git für weitere Informationen. -Wenn Sie etwas hinzufügen oder einen Fehler beheben, senden Sie den Patch bitte -(vorzugsweise mit git-format-patch) an die Liste wine-patches@winehq.org, um ihn -in die nächste Ausgabe aufnehmen zu können. +Wenn Sie etwas hinzufügen oder einen Fehler beheben, senden Sie bitte einen +Patch (vorzugsweise mit git-format-patch) an die Liste wine-patches@winehq.org, +damit dieser in die nächste Ausgabe aufgenommen werden kann. -- Alexandre Julliard diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/ddk/wdm.h wine-staging-2.4.0~ubuntu16.04.1/include/ddk/wdm.h --- wine-staging-2.3.0~ubuntu16.04.1/include/ddk/wdm.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/ddk/wdm.h 2017-03-21 14:02:57.000000000 +0000 @@ -1210,6 +1210,16 @@ UCHAR reserved[3]; } CALLBACK_OBJECT, *PCALLBACK_OBJECT; +typedef struct _KSPIN_LOCK_QUEUE { + struct _KSPIN_LOCK_QUEUE * volatile Next; + volatile PKSPIN_LOCK Lock; +} KSPIN_LOCK_QUEUE, *PKSPIN_LOCK_QUEUE; + +typedef struct _KLOCK_QUEUE_HANDLE { + KSPIN_LOCK_QUEUE LockQueue; + KIRQL OldIrql; +} KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE; + typedef NTSTATUS (NTAPI EX_CALLBACK_FUNCTION)(void *CallbackContext, void *Argument1, void *Argument2); typedef EX_CALLBACK_FUNCTION *PEX_CALLBACK_FUNCTION; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/iptypes.h wine-staging-2.4.0~ubuntu16.04.1/include/iptypes.h --- wine-staging-2.3.0~ubuntu16.04.1/include/iptypes.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/iptypes.h 2017-03-21 14:02:57.000000000 +0000 @@ -244,7 +244,21 @@ PWCHAR FriendlyName; BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; DWORD PhysicalAddressLength; - DWORD Flags; + union { + DWORD Flags; + struct { + DWORD DdnsEnabled : 1; + DWORD RegisterAdapterSuffix : 1; + DWORD Dhcpv4Enabled : 1; + DWORD ReceiveOnly : 1; + DWORD NoMulticast : 1; + DWORD Ipv6OtherStatefulConfig : 1; + DWORD NetbiosOverTcpipEnabled : 1; + DWORD Ipv4Enabled : 1; + DWORD Ipv6Enabled : 1; + DWORD Ipv6ManagedAddressConfigurationSupported : 1; + } DUMMYSTRUCTNAME1; + } DUMMYUNIONNAME1; DWORD Mtu; DWORD IfType; IF_OPER_STATUS OperStatus; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/Makefile.in wine-staging-2.4.0~ubuntu16.04.1/include/Makefile.in --- wine-staging-2.3.0~ubuntu16.04.1/include/Makefile.in 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/Makefile.in 2017-03-21 14:02:57.000000000 +0000 @@ -464,6 +464,7 @@ msidefs.h \ msiquery.h \ mssip.h \ + msstkppg.h \ mstcpip.h \ msvcrt/assert.h \ msvcrt/conio.h \ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/msstkppg.h wine-staging-2.4.0~ubuntu16.04.1/include/msstkppg.h --- wine-staging-2.3.0~ubuntu16.04.1/include/msstkppg.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/msstkppg.h 2017-03-21 14:02:57.000000000 +0000 @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 Alistair Leslie-Hughes + * + * 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 _MS_STOCK_PROP_PAGES_H_ +#define _MS_STOCK_PROP_PAGES_H_ + +DEFINE_GUID(CLSID_StockColorPage, 0x7ebdaae1, 0x8120, 0x11cf, 0x89, 0x9f, 0x0, 0xaa, 0x0, 0x68, 0x8b, 0x10); +DEFINE_GUID(CLSID_StockFontPage, 0x7ebdaae0, 0x8120, 0x11cf, 0x89, 0x9f, 0x0, 0xaa, 0x0, 0x68, 0x8b, 0x10); +DEFINE_GUID(CLSID_StockPicturePage, 0x7ebdaae2, 0x8120, 0x11cf, 0x89, 0x9f, 0x0, 0xaa, 0x0, 0x68, 0x8b, 0x10); + +#endif diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/netioapi.h wine-staging-2.4.0~ubuntu16.04.1/include/netioapi.h --- wine-staging-2.3.0~ubuntu16.04.1/include/netioapi.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/netioapi.h 2017-03-21 14:02:57.000000000 +0000 @@ -21,6 +21,14 @@ #include +typedef enum _MIB_NOTIFICATION_TYPE +{ + MibParameterNotification, + MibAddInstance, + MibDeleteInstance, + MibInitialNotification, +} MIB_NOTIFICATION_TYPE, *PMIB_NOTIFICATION_TYPE; + typedef struct _MIB_IF_ROW2 { NET_LUID InterfaceLuid; @@ -82,6 +90,45 @@ MIB_IF_ROW2 Table[1]; } MIB_IF_TABLE2, *PMIB_IF_TABLE2; +typedef struct _MIB_IPINTERFACE_ROW +{ + ADDRESS_FAMILY Family; + NET_LUID InterfaceLuid; + NET_IFINDEX InterfaceIndex; + ULONG MaxReassemblySize; + ULONG64 InterfaceIdentifier; + ULONG MinRouterAdvertisementInterval; + ULONG MaxRouterAdvertisementInterval; + BOOLEAN AdvertisingEnabled; + BOOLEAN ForwardingEnabled; + BOOLEAN WeakHostSend; + BOOLEAN WeakHostReceive; + BOOLEAN UseAutomaticMetric; + BOOLEAN UseNeighborUnreachabilityDetection; + BOOLEAN ManagedAddressConfigurationSupported; + BOOLEAN OtherStatefulConfigurationSupported; + BOOLEAN AdvertiseDefaultRoute; + NL_ROUTER_DISCOVERY_BEHAVIOR RouterDiscoveryBehavior; + ULONG DadTransmits; + ULONG BaseReachableTime; + ULONG RetransmitTime; + ULONG PathMtuDiscoveryTimeout; + NL_LINK_LOCAL_ADDRESS_BEHAVIOR LinkLocalAddressBehavior; + ULONG LinkLocalAddressTimeout; + ULONG ZoneIndices[ScopeLevelCount]; + ULONG SitePrefixLength; + ULONG Metric; + ULONG NlMtu; + BOOLEAN Connected; + BOOLEAN SupportsWakeUpPatterns; + BOOLEAN SupportsNeighborDiscovery; + BOOLEAN SupportsRouterDiscovery; + ULONG ReachableTime; + NL_INTERFACE_OFFLOAD_ROD TransmitOffload; + NL_INTERFACE_OFFLOAD_ROD ReceiveOffload; + BOOLEAN DisableDefaultRoutes; +} MIB_IPINTERFACE_ROW, *PMIB_IPINTERFACE_ROW; + typedef struct _MIB_UNICASTIPADDRESS_ROW { SOCKADDR_INET Address; @@ -98,6 +145,11 @@ LARGE_INTEGER CreationTimeStamp; } MIB_UNICASTIPADDRESS_ROW, *PMIB_UNICASTIPADDRESS_ROW; +typedef VOID (WINAPI *PIPINTERFACE_CHANGE_CALLBACK)(PVOID, PMIB_IPINTERFACE_ROW, + MIB_NOTIFICATION_TYPE); +typedef VOID (WINAPI *PUNICAST_IPADDRESS_CHANGE_CALLBACK)(PVOID, PMIB_UNICASTIPADDRESS_ROW, + 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-staging-2.3.0~ubuntu16.04.1/include/nldef.h wine-staging-2.4.0~ubuntu16.04.1/include/nldef.h --- wine-staging-2.3.0~ubuntu16.04.1/include/nldef.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/nldef.h 2017-03-21 14:02:57.000000000 +0000 @@ -48,6 +48,21 @@ IpDadStatePreferred, } NL_DAD_STATE; +typedef enum _NL_LINK_LOCAL_ADDRESS_BEHAVIOR +{ + LinkLocalAlwaysOff = 0, + LinkLocalDelayed, + LinkLocalAlwaysOn, + LinkLocalUnchanged = -1, +} NL_LINK_LOCAL_ADDRESS_BEHAVIOR; + +typedef enum _NL_ROUTER_DISCOVERY_BEHAVIOR +{ + RouterDiscoveryDisabled = 0, + RouterDiscoveryEnabled, + RouterDiscoveryDhcp, + RouterDiscoveryUnchanged = -1, +} NL_ROUTER_DISCOVERY_BEHAVIOR; typedef enum { @@ -75,5 +90,16 @@ MAKE_ROUTE_PROTOCOL(NT_STATIC_NON_DOD, 10007), } NL_ROUTE_PROTOCOL, *PNL_ROUTE_PROTOCOL; +typedef struct _NL_INTERFACE_OFFLOAD_ROD +{ + BOOLEAN NlChecksumSupported : 1; + BOOLEAN NlOptionsSupported : 1; + BOOLEAN TlDatagramChecksumSupported : 1; + BOOLEAN TlStreamChecksumSupported : 1; + BOOLEAN TlStreamOptionsSupported : 1; + BOOLEAN FastPathCompatible : 1; + BOOLEAN TlLargeSendOffloadSupported : 1; + BOOLEAN TlGiantSendOffloadSupported : 1; +} NL_INTERFACE_OFFLOAD_ROD, *PNL_INTERFACE_OFFLOAD_ROD; #endif /* __WINE_NLDEF_H */ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/winbase.h wine-staging-2.4.0~ubuntu16.04.1/include/winbase.h --- wine-staging-2.3.0~ubuntu16.04.1/include/winbase.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/winbase.h 2017-03-21 14:02:57.000000000 +0000 @@ -1819,6 +1819,7 @@ WINADVAPI BOOL WINAPI CreatePrivateObjectSecurityWithMultipleInheritance(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR*,GUID**,ULONG,BOOL,ULONG,HANDLE,PGENERIC_MAPPING); WINBASEAPI PTP_POOL WINAPI CreateThreadpool(PVOID); WINBASEAPI PTP_CLEANUP_GROUP WINAPI CreateThreadpoolCleanupGroup(void); +WINBASEAPI PTP_TIMER WINAPI CreateThreadpoolTimer(PTP_TIMER_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON); WINBASEAPI PTP_WAIT WINAPI CreateThreadpoolWait(PTP_WAIT_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON); WINBASEAPI PTP_WORK WINAPI CreateThreadpoolWork(PTP_WORK_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON); WINBASEAPI BOOL WINAPI CreateProcessA(LPCSTR,LPSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,LPVOID,LPCSTR,LPSTARTUPINFOA,LPPROCESS_INFORMATION); @@ -2559,6 +2560,7 @@ WINBASEAPI BOOL WINAPI SetThreadPriority(HANDLE,INT); WINBASEAPI BOOL WINAPI SetThreadPriorityBoost(HANDLE,BOOL); WINADVAPI BOOL WINAPI SetThreadToken(PHANDLE,HANDLE); +WINBASEAPI VOID WINAPI SetThreadpoolTimer(PTP_TIMER,FILETIME*,DWORD,DWORD); WINBASEAPI VOID WINAPI SetThreadpoolWait(PTP_WAIT,HANDLE,FILETIME *); WINBASEAPI HANDLE WINAPI SetTimerQueueTimer(HANDLE,WAITORTIMERCALLBACK,PVOID,DWORD,DWORD,BOOL); WINBASEAPI BOOL WINAPI SetTimeZoneInformation(const TIME_ZONE_INFORMATION *); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/wine/test.h wine-staging-2.4.0~ubuntu16.04.1/include/wine/test.h --- wine-staging-2.3.0~ubuntu16.04.1/include/wine/test.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/wine/test.h 2017-03-21 14:02:57.000000000 +0000 @@ -218,7 +218,7 @@ static LONG todo_failures; /* number of failures inside todo block */ /* The following data must be kept track of on a per-thread basis */ -typedef struct +struct tls_data { const char* current_file; /* file of current check */ int current_line; /* line of current check */ @@ -226,19 +226,19 @@ int todo_do_loop; char *str_pos; /* position in debug buffer */ char strings[2000]; /* buffer for debug strings */ -} tls_data; +}; static DWORD tls_index; -static tls_data* get_tls_data(void) +static struct tls_data *get_tls_data(void) { - tls_data* data; + struct tls_data *data; DWORD last_error; last_error=GetLastError(); data=TlsGetValue(tls_index); if (!data) { - data=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(tls_data)); + data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data)); data->str_pos = data->strings; TlsSetValue(tls_index,data); } @@ -249,7 +249,7 @@ /* allocate some tmp space for a string */ static char *get_temp_buffer( size_t n ) { - tls_data *data = get_tls_data(); + struct tls_data *data = get_tls_data(); char *res = data->str_pos; if (res + n >= &data->strings[sizeof(data->strings)]) res = data->strings; @@ -260,7 +260,7 @@ /* release extra space that we requested in get_temp_buffer() */ static void release_temp_buffer( char *ptr, size_t size ) { - tls_data *data = get_tls_data(); + struct tls_data *data = get_tls_data(); data->str_pos = ptr + size; } @@ -273,7 +273,7 @@ void winetest_set_location( const char* file, int line ) { - tls_data* data=get_tls_data(); + struct tls_data *data = get_tls_data(); data->current_file=strrchr(file,'/'); if (data->current_file==NULL) data->current_file=strrchr(file,'\\'); @@ -301,7 +301,7 @@ */ int winetest_vok( int condition, const char *msg, __winetest_va_list args ) { - tls_data* data=get_tls_data(); + struct tls_data *data = get_tls_data(); if (data->todo_level) { @@ -358,7 +358,7 @@ void __winetest_cdecl winetest_trace( const char *msg, ... ) { __winetest_va_list valist; - tls_data* data=get_tls_data(); + struct tls_data *data = get_tls_data(); if (winetest_debug > 0) { @@ -371,7 +371,7 @@ void winetest_vskip( const char *msg, __winetest_va_list args ) { - tls_data* data=get_tls_data(); + struct tls_data *data = get_tls_data(); printf( "%s:%d: Tests skipped: ", data->current_file, data->current_line ); vprintf(msg, args); @@ -399,14 +399,14 @@ void winetest_start_todo( int is_todo ) { - tls_data* data=get_tls_data(); + struct tls_data *data = get_tls_data(); data->todo_level = (data->todo_level << 1) | (is_todo != 0); data->todo_do_loop=1; } int winetest_loop_todo(void) { - tls_data* data=get_tls_data(); + struct tls_data *data = get_tls_data(); int do_loop=data->todo_do_loop; data->todo_do_loop=0; return do_loop; @@ -414,7 +414,7 @@ void winetest_end_todo(void) { - tls_data* data=get_tls_data(); + struct tls_data *data = get_tls_data(); data->todo_level >>= 1; } @@ -613,7 +613,7 @@ /* trap unhandled exceptions */ static LONG CALLBACK exc_filter( EXCEPTION_POINTERS *ptrs ) { - tls_data *data = get_tls_data(); + struct tls_data *data = get_tls_data(); if (data->current_file) printf( "%s:%d: this is the last test seen before the exception\n", diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/wine/wine_common_ver.rc wine-staging-2.4.0~ubuntu16.04.1/include/wine/wine_common_ver.rc --- wine-staging-2.3.0~ubuntu16.04.1/include/wine/wine_common_ver.rc 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/wine/wine_common_ver.rc 2017-03-21 14:02:57.000000000 +0000 @@ -48,6 +48,8 @@ #define WINE_VER_STRINGIZE2(x) #x #define WINE_VER_STRINGIZE(x) WINE_VER_STRINGIZE2(x) +#define WINE_VER_HEXPREFIX2(x) 0x ## x +#define WINE_VER_HEXPREFIX(x) WINE_VER_HEXPREFIX2(x) #ifndef WINE_FILEVERSION_STR #define WINE_FILEVERSION_STR WINE_VER_STRINGIZE(WINE_FILEVERSION_MAJOR.WINE_FILEVERSION_MINOR.WINE_FILEVERSION_BUILD.WINE_FILEVERSION_PLATFORMID) @@ -93,6 +95,22 @@ #define WINE_EXTRAVALUES #endif +#ifndef WINE_CODEPAGE +#ifdef _WIN32 +#define WINE_CODEPAGE 04B0 /* CP1200 (Unicode) */ +#else +#define WINE_CODEPAGE 04E4 /* CP1252 for Win16 */ +#endif +#endif + +#ifndef WINE_CODEPAGE_STR +#define WINE_CODEPAGE_STR WINE_VER_STRINGIZE(WINE_CODEPAGE) +#endif + +#ifndef WINE_CODEPAGE_HEX +#define WINE_CODEPAGE_HEX WINE_VER_HEXPREFIX(WINE_CODEPAGE) +#endif + VS_VERSION_INFO VERSIONINFO FILEVERSION WINE_FILEVERSION PRODUCTVERSION WINE_PRODUCTVERSION @@ -104,7 +122,8 @@ { BLOCK "StringFileInfo" { - BLOCK "040904E4" /* LANG_ENGLISH/SUBLANG_DEFAULT, CP 1252 */ + /* LANG_ENGLISH/SUBLANG_DEFAULT, WINE_CODEPAGE */ + BLOCK "0409" WINE_CODEPAGE_STR { VALUE "CompanyName", "Microsoft Corporation" /* GameGuard depends on this */ VALUE "FileDescription", WINE_FILEDESCRIPTION_STR @@ -119,6 +138,7 @@ } BLOCK "VarFileInfo" { - VALUE "Translation", 0x0409, 0x04E4 /* LANG_ENGLISH/SUBLANG_DEFAULT, CP 1252 */ + /* LANG_ENGLISH/SUBLANG_DEFAULT, WINE_CODEPAGE */ + VALUE "Translation", 0x0409, WINE_CODEPAGE_HEX } } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/wine/wined3d.h wine-staging-2.4.0~ubuntu16.04.1/include/wine/wined3d.h --- wine-staging-2.3.0~ubuntu16.04.1/include/wine/wined3d.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/wine/wined3d.h 2017-03-21 14:02:57.000000000 +0000 @@ -1279,6 +1279,7 @@ #define WINED3D_SRGB_READ_WRITE_CONTROL 0x00000200 #define WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR 0x00000400 #define WINED3D_NO_PRIMITIVE_RESTART 0x00000800 +#define WINED3D_LEGACY_CUBEMAP_FILTERING 0x00001000 #define WINED3D_RESZ_CODE 0x7fa05000 @@ -2162,8 +2163,13 @@ UINT plane_idx, struct wined3d_vec4 *plane); HRESULT __cdecl wined3d_device_get_clip_status(const struct wined3d_device *device, struct wined3d_clip_status *clip_status); +struct wined3d_shader * __cdecl wined3d_device_get_compute_shader(const struct wined3d_device *device); void __cdecl wined3d_device_get_creation_parameters(const struct wined3d_device *device, struct wined3d_device_creation_parameters *creation_parameters); +struct wined3d_buffer * __cdecl wined3d_device_get_cs_cb(const struct wined3d_device *device, unsigned int idx); +struct wined3d_shader_resource_view * __cdecl wined3d_device_get_cs_resource_view(const struct wined3d_device *device, + unsigned int idx); +struct wined3d_sampler * __cdecl wined3d_device_get_cs_sampler(const struct wined3d_device *device, unsigned int idx); struct wined3d_rendertarget_view * __cdecl wined3d_device_get_depth_stencil_view(const struct wined3d_device *device); HRESULT __cdecl wined3d_device_get_device_caps(const struct wined3d_device *device, WINED3DCAPS *caps); HRESULT __cdecl wined3d_device_get_display_mode(const struct wined3d_device *device, UINT swapchain_idx, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/wininet.h wine-staging-2.4.0~ubuntu16.04.1/include/wininet.h --- wine-staging-2.3.0~ubuntu16.04.1/include/wininet.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/wininet.h 2017-03-21 14:02:57.000000000 +0000 @@ -1708,10 +1708,13 @@ INTERNETAPI BOOL WINAPI InternetAutodialHangup(DWORD); INTERNETAPI BOOL WINAPI InternetGetConnectedState(LPDWORD ,DWORD); -#define INTERNET_CONNECTION_MODEM 1 -#define INTERNET_CONNECTION_LAN 2 -#define INTERNET_CONNECTION_PROXY 4 -#define INTERNET_CONNECTION_MODEM_BUSY 8 +#define INTERNET_CONNECTION_MODEM 0x01 +#define INTERNET_CONNECTION_LAN 0x02 +#define INTERNET_CONNECTION_PROXY 0x04 +#define INTERNET_CONNECTION_MODEM_BUSY 0x08 +#define INTERNET_RAS_INSTALLED 0x10 +#define INTERNET_CONNECTION_OFFLINE 0x20 +#define INTERNET_CONNECTION_CONFIGURED 0x40 typedef DWORD (CALLBACK *PFN_DIAL_HANDLER) (HWND,LPCSTR,DWORD,LPDWORD); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/include/ws2def.h wine-staging-2.4.0~ubuntu16.04.1/include/ws2def.h --- wine-staging-2.3.0~ubuntu16.04.1/include/ws2def.h 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/include/ws2def.h 2017-03-21 14:02:57.000000000 +0000 @@ -77,7 +77,8 @@ ScopeLevelAdmin = 4, ScopeLevelSite = 5, ScopeLevelOrganization = 8, - ScopeLevelGlobal = 14 + ScopeLevelGlobal = 14, + ScopeLevelCount = 16, } SCOPE_LEVEL; typedef struct diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/api-ms-win-Stub_DLLs/definition wine-staging-2.4.0~ubuntu16.04.1/patches/api-ms-win-Stub_DLLs/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/api-ms-win-Stub_DLLs/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/api-ms-win-Stub_DLLs/definition 2017-03-21 14:37:14.000000000 +0000 @@ -20,6 +20,5 @@ Fixes: Add iertutil dll Fixes: Add shcore dll Fixes: [40451] Add feclient dll -Depends: kernel32-GetCurrentPackageFamilyName Depends: combase-RoApi Depends: kernel32-UmsStubs diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,18 +1,18 @@ -From 489a67ec803b382248134be53f3449c206e208ff Mon Sep 17 00:00:00 2001 +From b05734fe9746e5dbbfcf248b2b892d6e09006956 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 19 Dec 2016 19:38:52 +0100 Subject: bcrypt: Add AES provider. --- dlls/bcrypt/bcrypt.spec | 10 +- - dlls/bcrypt/bcrypt_main.c | 347 ++++++++++++++++++++++++++++++++++++++++++++- + dlls/bcrypt/bcrypt_main.c | 353 ++++++++++++++++++++++++++++++++++++++++++++- dlls/bcrypt/tests/bcrypt.c | 18 +-- dlls/ncrypt/ncrypt.spec | 10 +- include/bcrypt.h | 3 + - 5 files changed, 357 insertions(+), 31 deletions(-) + 5 files changed, 361 insertions(+), 33 deletions(-) diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec -index e299fe0cce8..962953e509b 100644 +index a1cce4423dc..9ecd21d767c 100644 --- a/dlls/bcrypt/bcrypt.spec +++ b/dlls/bcrypt/bcrypt.spec @@ -5,15 +5,15 @@ @@ -27,7 +27,7 @@ -@ stub BCryptDestroyKey +@ stdcall BCryptDestroyKey(ptr) @ stub BCryptDestroySecret - @ stub BCryptDuplicateHash + @ stdcall BCryptDuplicateHash(ptr ptr ptr long long) @ stub BCryptDuplicateKey -@ stub BCryptEncrypt +@ stdcall BCryptEncrypt(ptr ptr long ptr ptr long ptr long ptr long) @@ -53,10 +53,10 @@ @ stub BCryptUnregisterConfigChangeNotify @ stub BCryptUnregisterProvider diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 6023c942e49..5867dbdc3fa 100644 +index 80d7ddb9466..247b3dc7327 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c -@@ -49,6 +49,10 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag); +@@ -51,6 +51,10 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag); static void *libgnutls_handle; #define MAKE_FUNCPTR(f) static typeof(f) * p##f @@ -67,7 +67,7 @@ MAKE_FUNCPTR(gnutls_global_deinit); MAKE_FUNCPTR(gnutls_global_init); MAKE_FUNCPTR(gnutls_global_set_log_function); -@@ -84,6 +88,10 @@ static BOOL gnutls_initialize(void) +@@ -80,6 +84,10 @@ static BOOL gnutls_initialize(void) goto fail; \ } @@ -78,7 +78,7 @@ LOAD_FUNCPTR(gnutls_global_deinit) LOAD_FUNCPTR(gnutls_global_init) LOAD_FUNCPTR(gnutls_global_set_log_function) -@@ -138,6 +146,7 @@ NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount, +@@ -128,6 +136,7 @@ NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount, #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0') #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H') @@ -86,7 +86,7 @@ struct object { ULONG magic; -@@ -145,6 +154,7 @@ struct object +@@ -135,6 +144,7 @@ struct object enum alg_id { @@ -94,15 +94,15 @@ ALG_ID_MD5, ALG_ID_RNG, ALG_ID_SHA1, -@@ -157,6 +167,7 @@ static const struct { - ULONG hash_length; +@@ -152,6 +162,7 @@ static const struct { + ULONG block_bits; const WCHAR *alg_name; } alg_props[] = { -+ /* ALG_ID_AES */ { 0, BCRYPT_AES_ALGORITHM }, - /* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM }, - /* ALG_ID_RNG */ { 0, BCRYPT_RNG_ALGORITHM }, - /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM }, -@@ -215,11 +226,10 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG c ++ /* ALG_ID_AES */ { 654, 0, 0, BCRYPT_AES_ALGORITHM }, + /* ALG_ID_MD5 */ { 274, 16, 512, BCRYPT_MD5_ALGORITHM }, + /* ALG_ID_RNG */ { 0, 0, 0, BCRYPT_RNG_ALGORITHM }, + /* ALG_ID_SHA1 */ { 278, 20, 512, BCRYPT_SHA1_ALGORITHM }, +@@ -210,11 +221,10 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG c NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags ) { @@ -115,7 +115,7 @@ TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags ); if (!handle || !id) return STATUS_INVALID_PARAMETER; -@@ -229,9 +239,10 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR +@@ -224,9 +234,10 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR return STATUS_NOT_IMPLEMENTED; } @@ -127,48 +127,36 @@ else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256; else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384; else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512; -@@ -430,7 +441,6 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) - static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) - { - CCHmacFinal( &hash->u.hmac_ctx, output ); -- - return STATUS_SUCCESS; - } - #elif defined(HAVE_GNUTLS_HASH) -@@ -586,12 +596,19 @@ static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) - } - #endif - -+#ifdef _WIN64 -+#define OBJECT_LENGTH_AES 654 -+#else -+#define OBJECT_LENGTH_AES 618 -+#endif - #define OBJECT_LENGTH_MD5 274 - #define OBJECT_LENGTH_SHA1 278 - #define OBJECT_LENGTH_SHA256 286 - #define OBJECT_LENGTH_SHA384 382 - #define OBJECT_LENGTH_SHA512 382 +@@ -388,6 +399,8 @@ struct hash + struct hash_impl inner; + }; +#define BLOCK_LENGTH_AES 16 + static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) { - if (!strcmpW( prop, BCRYPT_HASH_LENGTH )) -@@ -628,6 +645,34 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, - - switch (id) - { + if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) +@@ -432,9 +445,43 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, + NTSTATUS status; + + status = generic_alg_property( id, prop, buf, size, ret_size ); +- if (status == STATUS_NOT_IMPLEMENTED) +- FIXME( "unsupported property %s\n", debugstr_w(prop) ); +- return status; ++ if (status != STATUS_NOT_IMPLEMENTED) ++ return status; ++ ++ switch (id) ++ { + case ALG_ID_AES: + if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH )) + { -+ value = BLOCK_LENGTH_AES; -+ break; -+ } -+ if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) -+ { -+ value = OBJECT_LENGTH_AES; -+ break; ++ *ret_size = sizeof(ULONG); ++ if (size < sizeof(ULONG)) ++ return STATUS_BUFFER_TOO_SMALL; ++ if (buf) ++ *(ULONG *)buf = BLOCK_LENGTH_AES; ++ return STATUS_SUCCESS; + } + if (!strcmpW( prop, BCRYPT_CHAINING_MODE )) + { @@ -184,13 +172,18 @@ + return STATUS_BUFFER_TOO_SMALL; + } + } -+ FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) ); -+ return STATUS_NOT_IMPLEMENTED; ++ break; ++ ++ default: ++ break; ++ } + - case ALG_ID_MD5: - if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) - { -@@ -731,6 +776,13 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu ++ FIXME( "unsupported property %s\n", debugstr_w(prop) ); ++ return STATUS_NOT_IMPLEMENTED; + } + + static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) +@@ -474,6 +521,13 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu } } @@ -204,7 +197,7 @@ NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen, UCHAR *secret, ULONG secretlen, ULONG flags ) { -@@ -854,6 +906,293 @@ NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG se +@@ -632,6 +686,293 @@ NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG se return BCryptDestroyHash( handle ); } @@ -499,10 +492,10 @@ { switch (reason) diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c -index 422f2cfd340..d2df74ed919 100644 +index 42312b45b78..4d5891b461b 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c -@@ -780,7 +780,7 @@ static void test_aes(void) +@@ -704,7 +704,7 @@ static void test_aes(void) ULONG size, len; UCHAR mode[64]; NTSTATUS ret; @@ -511,7 +504,7 @@ alg = NULL; ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_AES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); -@@ -814,7 +814,6 @@ todo_wine { +@@ -738,7 +738,6 @@ todo_wine { ret = pBCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); } @@ -519,7 +512,7 @@ static void test_BCryptGenerateSymmetricKey(void) { -@@ -833,11 +832,6 @@ static void test_BCryptGenerateSymmetricKey(void) +@@ -757,11 +756,6 @@ static void test_BCryptGenerateSymmetricKey(void) NTSTATUS ret; ret = pBCryptOpenAlgorithmProvider(&aes, BCRYPT_AES_ALGORITHM, NULL, 0); @@ -531,7 +524,7 @@ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); len = size = 0xdeadbeef; -@@ -922,11 +916,6 @@ static void test_BCryptEncrypt(void) +@@ -846,11 +840,6 @@ static void test_BCryptEncrypt(void) NTSTATUS ret; ret = pBCryptOpenAlgorithmProvider(&aes, BCRYPT_AES_ALGORITHM, NULL, 0); @@ -543,7 +536,7 @@ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); len = 0xdeadbeef; -@@ -1013,11 +1002,6 @@ static void test_BCryptDecrypt(void) +@@ -937,11 +926,6 @@ static void test_BCryptDecrypt(void) NTSTATUS ret; ret = pBCryptOpenAlgorithmProvider(&aes, BCRYPT_AES_ALGORITHM, NULL, 0); @@ -556,7 +549,7 @@ len = 0xdeadbeef; diff --git a/dlls/ncrypt/ncrypt.spec b/dlls/ncrypt/ncrypt.spec -index 04127608d68..60b7eb37075 100644 +index 6e871a5d6b8..1a78853bf49 100644 --- a/dlls/ncrypt/ncrypt.spec +++ b/dlls/ncrypt/ncrypt.spec @@ -5,17 +5,17 @@ @@ -573,7 +566,7 @@ -@ stub BCryptDestroyKey +@ stdcall BCryptDestroyKey(ptr) bcrypt.BCryptDestroyKey @ stub BCryptDestroySecret - @ stub BCryptDuplicateHash + @ stdcall BCryptDuplicateHash(ptr ptr ptr long long) bcrypt.BCryptDuplicateHash @ stub BCryptDuplicateKey -@ stub BCryptEncrypt +@ stdcall BCryptEncrypt(ptr ptr long ptr ptr long ptr long ptr long) bcrypt.BCryptEncrypt diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,469 +0,0 @@ -From f527689b793100c79654ac5d6c1376d128ca3175 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Mon, 19 Dec 2016 23:58:52 +0100 -Subject: bcrypt: Directly implement hmac computation. - ---- - dlls/bcrypt/bcrypt_main.c | 277 +++++++++++++++++----------------------------- - 1 file changed, 104 insertions(+), 173 deletions(-) - -diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 937bdf7..af2314a 100644 ---- a/dlls/bcrypt/bcrypt_main.c -+++ b/dlls/bcrypt/bcrypt_main.c -@@ -60,9 +60,6 @@ MAKE_FUNCPTR(gnutls_global_set_log_level); - MAKE_FUNCPTR(gnutls_hash); - MAKE_FUNCPTR(gnutls_hash_deinit); - MAKE_FUNCPTR(gnutls_hash_init); --MAKE_FUNCPTR(gnutls_hmac); --MAKE_FUNCPTR(gnutls_hmac_deinit); --MAKE_FUNCPTR(gnutls_hmac_init); - MAKE_FUNCPTR(gnutls_perror); - #undef MAKE_FUNCPTR - -@@ -99,9 +96,6 @@ static BOOL gnutls_initialize(void) - LOAD_FUNCPTR(gnutls_hash); - LOAD_FUNCPTR(gnutls_hash_deinit); - LOAD_FUNCPTR(gnutls_hash_init); -- LOAD_FUNCPTR(gnutls_hmac); -- LOAD_FUNCPTR(gnutls_hmac_deinit); -- LOAD_FUNCPTR(gnutls_hmac_init); - LOAD_FUNCPTR(gnutls_perror) - #undef LOAD_FUNCPTR - -@@ -163,6 +157,8 @@ enum alg_id - ALG_ID_SHA512 - }; - -+#define MAX_HASH_OUTPUT_BYTES 64 -+ - static const struct { - ULONG hash_length; - const WCHAR *alg_name; -@@ -183,6 +179,19 @@ struct algorithm - BOOL hmac; - }; - -+#define MAX_HASH_BLOCK_BITS 1024 -+ -+int alg_block_bits[] = -+{ -+ /* ALG_ID_AES */ 0, -+ /* ALG_ID_MD5 */ 512, -+ /* ALG_ID_RNG */ 0, -+ /* ALG_ID_SHA1 */ 512, -+ /* ALG_ID_SHA256 */ 512, -+ /* ALG_ID_SHA384 */ 1024, -+ /* ALG_ID_SHA512 */ 1024 -+}; -+ - NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags) - { - const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG; -@@ -289,24 +298,20 @@ NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled) - } - - #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H --struct hash -+struct hash_impl - { -- struct object hdr; -- enum alg_id alg_id; -- BOOL hmac; - union - { - CC_MD5_CTX md5_ctx; - CC_SHA1_CTX sha1_ctx; - CC_SHA256_CTX sha256_ctx; - CC_SHA512_CTX sha512_ctx; -- CCHmacContext hmac_ctx; - } u; - }; - --static NTSTATUS hash_init( struct hash *hash ) -+static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) - { -- switch (hash->alg_id) -+ switch (alg_id) - { - case ALG_ID_MD5: - CC_MD5_Init( &hash->u.md5_ctx ); -@@ -329,50 +334,16 @@ static NTSTATUS hash_init( struct hash *hash ) - break; - - default: -- ERR( "unhandled id %u\n", hash->alg_id ); -+ ERR( "unhandled id %u\n", alg_id ); - return STATUS_NOT_IMPLEMENTED; - } - return STATUS_SUCCESS; - } - --static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) -+static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, -+ UCHAR *input, ULONG size ) - { -- CCHmacAlgorithm cc_algorithm; -- switch (hash->alg_id) -- { -- case ALG_ID_MD5: -- cc_algorithm = kCCHmacAlgMD5; -- break; -- -- case ALG_ID_SHA1: -- cc_algorithm = kCCHmacAlgSHA1; -- break; -- -- case ALG_ID_SHA256: -- cc_algorithm = kCCHmacAlgSHA256; -- break; -- -- case ALG_ID_SHA384: -- cc_algorithm = kCCHmacAlgSHA384; -- break; -- -- case ALG_ID_SHA512: -- cc_algorithm = kCCHmacAlgSHA512; -- break; -- -- default: -- ERR( "unhandled id %u\n", hash->alg_id ); -- return STATUS_NOT_IMPLEMENTED; -- } -- -- CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size ); -- return STATUS_SUCCESS; --} -- -- --static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) --{ -- switch (hash->alg_id) -+ switch (alg_id) - { - case ALG_ID_MD5: - CC_MD5_Update( &hash->u.md5_ctx, input, size ); -@@ -395,21 +366,16 @@ static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) - break; - - default: -- ERR( "unhandled id %u\n", hash->alg_id ); -+ ERR( "unhandled id %u\n", alg_id ); - return STATUS_NOT_IMPLEMENTED; - } - return STATUS_SUCCESS; - } - --static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) --{ -- CCHmacUpdate( &hash->u.hmac_ctx, input, size ); -- return STATUS_SUCCESS; --} -- --static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) -+static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, -+ UCHAR *output, ULONG size ) - { -- switch (hash->alg_id) -+ switch (alg_id) - { - case ALG_ID_MD5: - CC_MD5_Final( output, &hash->u.md5_ctx ); -@@ -432,37 +398,25 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) - break; - - default: -- ERR( "unhandled id %u\n", hash->alg_id ); -+ ERR( "unhandled id %u\n", alg_id ); - break; - } - return STATUS_SUCCESS; - } - --static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) --{ -- CCHmacFinal( &hash->u.hmac_ctx, output ); -- return STATUS_SUCCESS; --} - #elif defined(HAVE_GNUTLS_HASH) --struct hash -+struct hash_impl - { -- struct object hdr; -- enum alg_id alg_id; -- BOOL hmac; -- union -- { -- gnutls_hash_hd_t hash_handle; -- gnutls_hmac_hd_t hmac_handle; -- } u; -+ gnutls_hash_hd_t hash_handle; - }; - --static NTSTATUS hash_init( struct hash *hash ) -+static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) - { - gnutls_digest_algorithm_t alg; - - if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; - -- switch (hash->alg_id) -+ switch (alg_id) - { - case ALG_ID_MD5: - alg = GNUTLS_DIG_MD5; -@@ -484,117 +438,63 @@ static NTSTATUS hash_init( struct hash *hash ) - break; - - default: -- ERR( "unhandled id %u\n", hash->alg_id ); -- return STATUS_NOT_IMPLEMENTED; -- } -- -- if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR; -- return STATUS_SUCCESS; --} -- --static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) --{ -- gnutls_mac_algorithm_t alg; -- -- if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; -- -- switch (hash->alg_id) -- { -- case ALG_ID_MD5: -- alg = GNUTLS_MAC_MD5; -- break; -- case ALG_ID_SHA1: -- alg = GNUTLS_MAC_SHA1; -- break; -- -- case ALG_ID_SHA256: -- alg = GNUTLS_MAC_SHA256; -- break; -- -- case ALG_ID_SHA384: -- alg = GNUTLS_MAC_SHA384; -- break; -- -- case ALG_ID_SHA512: -- alg = GNUTLS_MAC_SHA512; -- break; -- -- default: -- ERR( "unhandled id %u\n", hash->alg_id ); -+ ERR( "unhandled id %u\n", alg_id ); - return STATUS_NOT_IMPLEMENTED; - } - -- if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR; -- return STATUS_SUCCESS; --} -- --static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) --{ -- if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR; -+ if (pgnutls_hash_init( &hash->hash_handle, alg )) return STATUS_INTERNAL_ERROR; - return STATUS_SUCCESS; - } - --static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) -+static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, -+ UCHAR *input, ULONG size ) - { -- if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR; -+ if (pgnutls_hash( hash->hash_handle, input, size )) return STATUS_INTERNAL_ERROR; - return STATUS_SUCCESS; - } - --static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) -+static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, -+ UCHAR *output, ULONG size ) - { -- pgnutls_hash_deinit( hash->u.hash_handle, output ); -+ pgnutls_hash_deinit( hash->hash_handle, output ); - return STATUS_SUCCESS; - } - --static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) --{ -- pgnutls_hmac_deinit( hash->u.hmac_handle, output ); -- return STATUS_SUCCESS; --} - #else --struct hash -+struct hash_impl - { -- struct object hdr; -- BOOL hmac; -- enum alg_id alg_id; --}; - --static NTSTATUS hash_init( struct hash *hash ) --{ -- ERR( "support for hashes not available at build time\n" ); -- return STATUS_NOT_IMPLEMENTED; --} -- --static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) --{ -- ERR( "support for hashes not available at build time\n" ); -- return STATUS_NOT_IMPLEMENTED; --} -+}; - --static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) -+static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) - { - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; - } - --static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) -+static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, -+ UCHAR *input, ULONG size ) - { - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; - } - --static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) -+static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, -+ UCHAR *output, ULONG size ) - { - ERR( "support for hashes not available at build time\n" ); - return STATUS_NOT_IMPLEMENTED; - } -+#endif - --static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) -+struct hash - { -- ERR( "support for hashes not available at build time\n" ); -- return STATUS_NOT_IMPLEMENTED; --} --#endif -+ struct object hdr; -+ enum alg_id alg_id; -+ BOOL hmac; -+ struct hash_impl outer; -+ struct hash_impl inner; -+}; - - #ifdef _WIN64 - #define OBJECT_LENGTH_AES 654 -@@ -787,8 +687,11 @@ NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDL - UCHAR *secret, ULONG secretlen, ULONG flags ) - { - struct algorithm *alg = algorithm; -+ UCHAR buffer[MAX_HASH_BLOCK_BITS / 8]; - struct hash *hash; -+ int block_bytes; - NTSTATUS status; -+ int i; - - TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen, - secret, secretlen, flags ); -@@ -806,17 +709,45 @@ NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDL - hash->alg_id = alg->id; - hash->hmac = alg->hmac; - -- if (hash->hmac) -+ status = hash_init( &hash->inner, hash->alg_id ); -+ if (status || !hash->hmac) goto end; -+ status = hash_init( &hash->outer, hash->alg_id ); -+ if (status) goto end; -+ -+ /* reduce key size if too big */ -+ block_bytes = alg_block_bits[hash->alg_id] / 8; -+ if (secretlen > block_bytes) - { -- status = hmac_init( hash, secret, secretlen ); -+ struct hash_impl temp; -+ status = hash_init( &temp, hash->alg_id ); -+ if (status) goto end; -+ status = hash_update( &temp, hash->alg_id, secret, secretlen ); -+ if (status) goto end; -+ memset( buffer, 0, block_bytes ); -+ status = hash_finish( &temp, hash->alg_id, buffer, alg_props[hash->alg_id].hash_length ); -+ if (status) goto end; - } - else - { -- status = hash_init( hash ); -+ memset( buffer, 0, block_bytes ); -+ memcpy( buffer, secret, secretlen ); - } - -+ /* initialize outer hash */ -+ for (i = 0; i < block_bytes; i++) -+ buffer[i] ^= 0x5c; -+ status = hash_update( &hash->outer, hash->alg_id, buffer, block_bytes ); -+ if (status) goto end; -+ -+ /* initialize inner hash */ -+ for (i = 0; i < block_bytes; i++) -+ buffer[i] ^= (0x5c ^ 0x36); -+ status = hash_update( &hash->inner, hash->alg_id, buffer, block_bytes ); -+ -+end: - if (status != STATUS_SUCCESS) - { -+ /* FIXME: call hash_finish to release resources */ - HeapFree( GetProcessHeap(), 0, hash ); - return status; - } -@@ -845,33 +776,33 @@ NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG s - if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; - if (!input) return STATUS_SUCCESS; - -- if (hash->hmac) -- { -- return hmac_update( hash, input, size ); -- } -- else -- { -- return hash_update( hash, input, size ); -- } -+ return hash_update( &hash->inner, hash->alg_id, input, size ); - } - - NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags ) - { -+ UCHAR buffer[MAX_HASH_OUTPUT_BYTES]; - struct hash *hash = handle; -+ NTSTATUS status; -+ int hash_size; - - TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags ); - - if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; - if (!output) return STATUS_INVALID_PARAMETER; - -- if (hash->hmac) -- { -- return hmac_finish( hash, output, size ); -- } -- else -- { -- return hash_finish( hash, output, size ); -- } -+ if (!hash->hmac) -+ return hash_finish( &hash->inner, hash->alg_id, output, size ); -+ -+ hash_size = alg_props[hash->alg_id].hash_length; -+ -+ status = hash_finish( &hash->inner, hash->alg_id, buffer, hash_size); -+ if (status) return status; -+ -+ status = hash_update( &hash->outer, hash->alg_id, buffer, hash_size); -+ if (status) return status; -+ -+ return hash_finish( &hash->outer, hash->alg_id, output, size); - } - - NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen, --- -2.9.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,673 +0,0 @@ -From 3439b4e5a1fd05c4fb68491c3814de2581e8a5aa Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Tue, 20 Dec 2016 02:36:57 +0100 -Subject: bcrypt: Add internal fallback implementation for hash calculations. - ---- - dlls/bcrypt/Makefile.in | 5 +- - dlls/bcrypt/bcrypt_internal.h | 79 +++++++++++++++++ - dlls/bcrypt/bcrypt_main.c | 101 ++++++++++++++++++++-- - dlls/bcrypt/sha256.c | 169 +++++++++++++++++++++++++++++++++++++ - dlls/bcrypt/sha384.c | 41 +++++++++ - dlls/bcrypt/sha512.c | 191 ++++++++++++++++++++++++++++++++++++++++++ - 6 files changed, 578 insertions(+), 8 deletions(-) - create mode 100644 dlls/bcrypt/bcrypt_internal.h - create mode 100644 dlls/bcrypt/sha256.c - create mode 100644 dlls/bcrypt/sha384.c - create mode 100644 dlls/bcrypt/sha512.c - -diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in -index ef9d7ead6bc..f54fc5cd482 100644 ---- a/dlls/bcrypt/Makefile.in -+++ b/dlls/bcrypt/Makefile.in -@@ -4,6 +4,9 @@ IMPORTLIB = bcrypt - EXTRAINCL = $(GNUTLS_CFLAGS) - - C_SRCS = \ -- bcrypt_main.c -+ bcrypt_main.c \ -+ sha256.c \ -+ sha384.c \ -+ sha512.c - - RC_SRCS = version.rc -diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h -new file mode 100644 -index 00000000000..8a8f6d170c4 ---- /dev/null -+++ b/dlls/bcrypt/bcrypt_internal.h -@@ -0,0 +1,79 @@ -+/* -+ * Copyright 2016 Michael Müller -+ * -+ * 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 __BCRYPT_INTERNAL_H -+#define __BCRYPT_INTERNAL_H -+ -+#include -+ -+#include "windef.h" -+#include "winbase.h" -+ -+typedef struct -+{ -+ ULONG64 len; -+ DWORD h[8]; -+ UCHAR buf[64]; -+} SHA256_CTX; -+ -+void sha256_init(SHA256_CTX *ctx); -+void sha256_update(SHA256_CTX *ctx, const UCHAR *buffer, ULONG len); -+void sha256_finalize(SHA256_CTX *ctx, UCHAR *buffer); -+ -+typedef struct -+{ -+ ULONG64 len; -+ ULONG64 h[8]; -+ UCHAR buf[128]; -+} SHA512_CTX; -+ -+void sha512_init(SHA512_CTX *ctx); -+void sha512_update(SHA512_CTX *ctx, const UCHAR *buffer, ULONG len); -+void sha512_finalize(SHA512_CTX *ctx, UCHAR *buffer); -+ -+void sha384_init(SHA512_CTX *ctx); -+#define sha384_update sha512_update -+void sha384_finalize(SHA512_CTX *ctx, UCHAR *buffer); -+ -+/* Definitions from advapi32 */ -+typedef struct -+{ -+ unsigned int i[2]; -+ unsigned int buf[4]; -+ unsigned char in[64]; -+ unsigned char digest[16]; -+} MD5_CTX; -+ -+VOID WINAPI MD5Init(MD5_CTX *ctx); -+VOID WINAPI MD5Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len); -+VOID WINAPI MD5Final(MD5_CTX *ctx); -+ -+typedef struct -+{ -+ ULONG Unknown[6]; -+ ULONG State[5]; -+ ULONG Count[2]; -+ UCHAR Buffer[64]; -+} SHA_CTX; -+ -+VOID WINAPI A_SHAInit(SHA_CTX *ctx); -+VOID WINAPI A_SHAUpdate(SHA_CTX *ctx, const UCHAR *buffer, UINT size); -+VOID WINAPI A_SHAFinal(SHA_CTX *ctx, PULONG result); -+ -+#endif /* __BCRYPT_INTERNAL_H */ -diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 1f22063dbda..fbaece21f47 100644 ---- a/dlls/bcrypt/bcrypt_main.c -+++ b/dlls/bcrypt/bcrypt_main.c -@@ -36,6 +36,8 @@ - #include "ntsecapi.h" - #include "bcrypt.h" - -+#include "bcrypt_internal.h" -+ - #include "wine/debug.h" - #include "wine/library.h" - #include "wine/unicode.h" -@@ -463,27 +465,112 @@ static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, - #else - struct hash_impl - { -- -+ union -+ { -+ MD5_CTX md5; -+ SHA_CTX sha1; -+ SHA256_CTX sha256; -+ SHA512_CTX sha512; -+ } u; - }; - - static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) - { -- ERR( "support for hashes not available at build time\n" ); -- return STATUS_NOT_IMPLEMENTED; -+ switch (alg_id) -+ { -+ case ALG_ID_MD5: -+ MD5Init(&hash->u.md5); -+ break; -+ -+ case ALG_ID_SHA1: -+ A_SHAInit(&hash->u.sha1); -+ break; -+ -+ case ALG_ID_SHA256: -+ sha256_init(&hash->u.sha256); -+ break; -+ -+ case ALG_ID_SHA384: -+ sha384_init(&hash->u.sha512); -+ break; -+ -+ case ALG_ID_SHA512: -+ sha512_init(&hash->u.sha512); -+ break; -+ -+ default: -+ ERR( "unhandled id %u\n", alg_id ); -+ return STATUS_NOT_IMPLEMENTED; -+ } -+ -+ return STATUS_SUCCESS; - } - - static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, - UCHAR *input, ULONG size ) - { -- ERR( "support for hashes not available at build time\n" ); -- return STATUS_NOT_IMPLEMENTED; -+ switch (alg_id) -+ { -+ case ALG_ID_MD5: -+ MD5Update(&hash->u.md5, input, size); -+ break; -+ -+ case ALG_ID_SHA1: -+ A_SHAUpdate(&hash->u.sha1, input, size); -+ break; -+ -+ case ALG_ID_SHA256: -+ sha256_update(&hash->u.sha256, input, size); -+ break; -+ -+ case ALG_ID_SHA384: -+ sha384_update(&hash->u.sha512, input, size); -+ break; -+ -+ case ALG_ID_SHA512: -+ sha512_update(&hash->u.sha512, input, size); -+ break; -+ -+ default: -+ ERR( "unhandled id %u\n", alg_id ); -+ return STATUS_NOT_IMPLEMENTED; -+ } -+ -+ return STATUS_SUCCESS; - } - - static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, - UCHAR *output, ULONG size ) - { -- ERR( "support for hashes not available at build time\n" ); -- return STATUS_NOT_IMPLEMENTED; -+ switch (alg_id) -+ { -+ case ALG_ID_MD5: -+ MD5Final(&hash->u.md5); -+ memcpy(output, hash->u.md5.digest, 16); -+ break; -+ -+ case ALG_ID_SHA1: -+ A_SHAFinal(&hash->u.sha1, (ULONG*)output); -+ break; -+ -+ case ALG_ID_SHA256: -+ sha256_finalize(&hash->u.sha256, output); -+ break; -+ -+ case ALG_ID_SHA384: -+ sha384_finalize(&hash->u.sha512, output); -+ break; -+ -+ case ALG_ID_SHA512: -+ sha512_finalize(&hash->u.sha512, output); -+ break; -+ -+ default: -+ ERR( "unhandled id %u\n", alg_id ); -+ return STATUS_NOT_IMPLEMENTED; -+ } -+ -+ return STATUS_SUCCESS; - } - #endif - -diff --git a/dlls/bcrypt/sha256.c b/dlls/bcrypt/sha256.c -new file mode 100644 -index 00000000000..48c4a48d031 ---- /dev/null -+++ b/dlls/bcrypt/sha256.c -@@ -0,0 +1,169 @@ -+/* -+ * Copyright 2016 Michael Müller -+ * -+ * 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 -+ * -+ */ -+ -+/* Based on public domain implementation from -+ https://git.musl-libc.org/cgit/musl/tree/src/crypt/crypt_sha256.c */ -+ -+#include "bcrypt_internal.h" -+ -+static DWORD ror(DWORD n, int k) { return (n >> k) | (n << (32-k)); } -+#define Ch(x,y,z) (z ^ (x & (y ^ z))) -+#define Maj(x,y,z) ((x & y) | (z & (x | y))) -+#define S0(x) (ror(x,2) ^ ror(x,13) ^ ror(x,22)) -+#define S1(x) (ror(x,6) ^ ror(x,11) ^ ror(x,25)) -+#define R0(x) (ror(x,7) ^ ror(x,18) ^ (x>>3)) -+#define R1(x) (ror(x,17) ^ ror(x,19) ^ (x>>10)) -+ -+static const DWORD K[64] = -+{ -+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, -+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, -+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, -+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, -+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, -+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, -+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, -+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -+}; -+ -+static void processblock(SHA256_CTX *ctx, const UCHAR *buffer) -+{ -+ DWORD W[64], t1, t2, a, b, c, d, e, f, g, h; -+ int i; -+ -+ for (i = 0; i < 16; i++) -+ { -+ W[i] = (DWORD)buffer[4*i]<<24; -+ W[i] |= (DWORD)buffer[4*i+1]<<16; -+ W[i] |= (DWORD)buffer[4*i+2]<<8; -+ W[i] |= buffer[4*i+3]; -+ } -+ -+ for (; i < 64; i++) -+ W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; -+ -+ a = ctx->h[0]; -+ b = ctx->h[1]; -+ c = ctx->h[2]; -+ d = ctx->h[3]; -+ e = ctx->h[4]; -+ f = ctx->h[5]; -+ g = ctx->h[6]; -+ h = ctx->h[7]; -+ -+ for (i = 0; i < 64; i++) -+ { -+ t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; -+ t2 = S0(a) + Maj(a,b,c); -+ h = g; -+ g = f; -+ f = e; -+ e = d + t1; -+ d = c; -+ c = b; -+ b = a; -+ a = t1 + t2; -+ } -+ -+ ctx->h[0] += a; -+ ctx->h[1] += b; -+ ctx->h[2] += c; -+ ctx->h[3] += d; -+ ctx->h[4] += e; -+ ctx->h[5] += f; -+ ctx->h[6] += g; -+ ctx->h[7] += h; -+} -+ -+static void pad(SHA256_CTX *ctx) -+{ -+ ULONG64 r = ctx->len % 64; -+ -+ ctx->buf[r++] = 0x80; -+ -+ if (r > 56) -+ { -+ memset(ctx->buf + r, 0, 64 - r); -+ r = 0; -+ processblock(ctx, ctx->buf); -+ } -+ -+ memset(ctx->buf + r, 0, 56 - r); -+ ctx->len *= 8; -+ ctx->buf[56] = ctx->len >> 56; -+ ctx->buf[57] = ctx->len >> 48; -+ ctx->buf[58] = ctx->len >> 40; -+ ctx->buf[59] = ctx->len >> 32; -+ ctx->buf[60] = ctx->len >> 24; -+ ctx->buf[61] = ctx->len >> 16; -+ ctx->buf[62] = ctx->len >> 8; -+ ctx->buf[63] = ctx->len; -+ -+ processblock(ctx, ctx->buf); -+} -+ -+void sha256_init(SHA256_CTX *ctx) -+{ -+ ctx->len = 0; -+ ctx->h[0] = 0x6a09e667; -+ ctx->h[1] = 0xbb67ae85; -+ ctx->h[2] = 0x3c6ef372; -+ ctx->h[3] = 0xa54ff53a; -+ ctx->h[4] = 0x510e527f; -+ ctx->h[5] = 0x9b05688c; -+ ctx->h[6] = 0x1f83d9ab; -+ ctx->h[7] = 0x5be0cd19; -+} -+ -+void sha256_update(SHA256_CTX *ctx, const UCHAR *buffer, ULONG len) -+{ -+ const UCHAR *p = buffer; -+ ULONG64 r = ctx->len % 64; -+ -+ ctx->len += len; -+ if (r) -+ { -+ if (len < 64 - r) -+ { -+ memcpy(ctx->buf + r, p, len); -+ return; -+ } -+ memcpy(ctx->buf + r, p, 64 - r); -+ len -= 64 - r; -+ p += 64 - r; -+ processblock(ctx, ctx->buf); -+ } -+ for (; len >= 64; len -= 64, p += 64) -+ processblock(ctx, p); -+ memcpy(ctx->buf, p, len); -+} -+ -+void sha256_finalize(SHA256_CTX *ctx, UCHAR *buffer) -+{ -+ int i; -+ -+ pad(ctx); -+ for (i = 0; i < 8; i++) -+ { -+ buffer[4*i] = ctx->h[i] >> 24; -+ buffer[4*i+1] = ctx->h[i] >> 16; -+ buffer[4*i+2] = ctx->h[i] >> 8; -+ buffer[4*i+3] = ctx->h[i]; -+ } -+} -diff --git a/dlls/bcrypt/sha384.c b/dlls/bcrypt/sha384.c -new file mode 100644 -index 00000000000..81e7e08fd07 ---- /dev/null -+++ b/dlls/bcrypt/sha384.c -@@ -0,0 +1,41 @@ -+/* -+ * Copyright 2016 Michael Müller -+ * -+ * 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 "bcrypt_internal.h" -+ -+void sha384_init(SHA512_CTX *ctx) -+{ -+ ctx->len = 0; -+ ctx->h[0] = 0xcbbb9d5dc1059ed8ULL; -+ ctx->h[1] = 0x629a292a367cd507ULL; -+ ctx->h[2] = 0x9159015a3070dd17ULL; -+ ctx->h[3] = 0x152fecd8f70e5939ULL; -+ ctx->h[4] = 0x67332667ffc00b31ULL; -+ ctx->h[5] = 0x8eb44a8768581511ULL; -+ ctx->h[6] = 0xdb0c2e0d64f98fa7ULL; -+ ctx->h[7] = 0x47b5481dbefa4fa4ULL; -+} -+ -+void sha384_finalize(SHA512_CTX *ctx, UCHAR *buffer) -+{ -+ UCHAR buffer512[64]; -+ -+ sha512_finalize(ctx, buffer512); -+ memcpy(buffer, buffer512, 48); -+} -diff --git a/dlls/bcrypt/sha512.c b/dlls/bcrypt/sha512.c -new file mode 100644 -index 00000000000..fdd7867eab7 ---- /dev/null -+++ b/dlls/bcrypt/sha512.c -@@ -0,0 +1,191 @@ -+/* -+ * Copyright 2016 Michael Müller -+ * -+ * 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 -+ * -+ */ -+ -+/* Based on public domain implementation from -+ https://git.musl-libc.org/cgit/musl/tree/src/crypt/crypt_sha512.c */ -+ -+#include "bcrypt_internal.h" -+ -+static ULONG64 ror(ULONG64 n, int k) { return (n >> k) | (n << (64-k)); } -+#define Ch(x,y,z) (z ^ (x & (y ^ z))) -+#define Maj(x,y,z) ((x & y) | (z & (x | y))) -+#define S0(x) (ror(x,28) ^ ror(x,34) ^ ror(x,39)) -+#define S1(x) (ror(x,14) ^ ror(x,18) ^ ror(x,41)) -+#define R0(x) (ror(x,1) ^ ror(x,8) ^ (x>>7)) -+#define R1(x) (ror(x,19) ^ ror(x,61) ^ (x>>6)) -+ -+static const ULONG64 K[80] = -+{ -+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, -+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, -+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, -+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, -+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, -+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, -+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, -+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, -+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, -+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, -+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, -+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, -+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, -+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, -+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, -+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, -+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, -+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, -+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, -+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL -+}; -+ -+static void processblock(SHA512_CTX *ctx, const UCHAR *buffer) -+{ -+ ULONG64 W[80], t1, t2, a, b, c, d, e, f, g, h; -+ int i; -+ -+ for (i = 0; i < 16; i++) -+ { -+ W[i] = (ULONG64)buffer[8*i]<<56; -+ W[i] |= (ULONG64)buffer[8*i+1]<<48; -+ W[i] |= (ULONG64)buffer[8*i+2]<<40; -+ W[i] |= (ULONG64)buffer[8*i+3]<<32; -+ W[i] |= (ULONG64)buffer[8*i+4]<<24; -+ W[i] |= (ULONG64)buffer[8*i+5]<<16; -+ W[i] |= (ULONG64)buffer[8*i+6]<<8; -+ W[i] |= buffer[8*i+7]; -+ } -+ -+ for (; i < 80; i++) -+ W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16]; -+ -+ a = ctx->h[0]; -+ b = ctx->h[1]; -+ c = ctx->h[2]; -+ d = ctx->h[3]; -+ e = ctx->h[4]; -+ f = ctx->h[5]; -+ g = ctx->h[6]; -+ h = ctx->h[7]; -+ -+ for (i = 0; i < 80; i++) -+ { -+ t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; -+ t2 = S0(a) + Maj(a,b,c); -+ h = g; -+ g = f; -+ f = e; -+ e = d + t1; -+ d = c; -+ c = b; -+ b = a; -+ a = t1 + t2; -+ } -+ -+ ctx->h[0] += a; -+ ctx->h[1] += b; -+ ctx->h[2] += c; -+ ctx->h[3] += d; -+ ctx->h[4] += e; -+ ctx->h[5] += f; -+ ctx->h[6] += g; -+ ctx->h[7] += h; -+} -+ -+static void pad(SHA512_CTX *ctx) -+{ -+ ULONG64 r = ctx->len % 128; -+ -+ ctx->buf[r++] = 0x80; -+ if (r > 112) -+ { -+ memset(ctx->buf + r, 0, 128 - r); -+ r = 0; -+ processblock(ctx, ctx->buf); -+ } -+ -+ memset(ctx->buf + r, 0, 120 - r); -+ ctx->len *= 8; -+ ctx->buf[120] = ctx->len >> 56; -+ ctx->buf[121] = ctx->len >> 48; -+ ctx->buf[122] = ctx->len >> 40; -+ ctx->buf[123] = ctx->len >> 32; -+ ctx->buf[124] = ctx->len >> 24; -+ ctx->buf[125] = ctx->len >> 16; -+ ctx->buf[126] = ctx->len >> 8; -+ ctx->buf[127] = ctx->len; -+ -+ processblock(ctx, ctx->buf); -+} -+ -+void sha512_init(SHA512_CTX *ctx) -+{ -+ ctx->len = 0; -+ ctx->h[0] = 0x6a09e667f3bcc908ULL; -+ ctx->h[1] = 0xbb67ae8584caa73bULL; -+ ctx->h[2] = 0x3c6ef372fe94f82bULL; -+ ctx->h[3] = 0xa54ff53a5f1d36f1ULL; -+ ctx->h[4] = 0x510e527fade682d1ULL; -+ ctx->h[5] = 0x9b05688c2b3e6c1fULL; -+ ctx->h[6] = 0x1f83d9abfb41bd6bULL; -+ ctx->h[7] = 0x5be0cd19137e2179ULL; -+} -+ -+void sha512_update(SHA512_CTX *ctx, const UCHAR *buffer, ULONG len) -+{ -+ const UCHAR *p = buffer; -+ unsigned r = ctx->len % 128; -+ -+ ctx->len += len; -+ if (r) -+ { -+ if (len < 128 - r) -+ { -+ memcpy(ctx->buf + r, p, len); -+ return; -+ } -+ memcpy(ctx->buf + r, p, 128 - r); -+ len -= 128 - r; -+ p += 128 - r; -+ processblock(ctx, ctx->buf); -+ } -+ -+ for (; len >= 128; len -= 128, p += 128) -+ processblock(ctx, p); -+ -+ memcpy(ctx->buf, p, len); -+} -+ -+void sha512_finalize(SHA512_CTX *ctx, UCHAR *buffer) -+{ -+ int i; -+ -+ pad(ctx); -+ -+ for (i = 0; i < 8; i++) -+ { -+ buffer[8*i] = ctx->h[i] >> 56; -+ buffer[8*i+1] = ctx->h[i] >> 48; -+ buffer[8*i+2] = ctx->h[i] >> 40; -+ buffer[8*i+3] = ctx->h[i] >> 32; -+ buffer[8*i+4] = ctx->h[i] >> 24; -+ buffer[8*i+5] = ctx->h[i] >> 16; -+ buffer[8*i+6] = ctx->h[i] >> 8; -+ buffer[8*i+7] = ctx->h[i]; -+ } -+} --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,216 +0,0 @@ -From ae04ece5f64a29a67e187d5aa32c6b8d3e399d61 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Tue, 20 Dec 2016 02:39:26 +0100 -Subject: bcrypt: Use hash fallback implementation as default and remove gnutls - / commoncrypto hash implemetation. - ---- - dlls/bcrypt/bcrypt_main.c | 171 ---------------------------------------------- - 1 file changed, 171 deletions(-) - -diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 9441cf0..3e2b22d 100644 ---- a/dlls/bcrypt/bcrypt_main.c -+++ b/dlls/bcrypt/bcrypt_main.c -@@ -59,9 +59,6 @@ MAKE_FUNCPTR(gnutls_global_deinit); - MAKE_FUNCPTR(gnutls_global_init); - MAKE_FUNCPTR(gnutls_global_set_log_function); - MAKE_FUNCPTR(gnutls_global_set_log_level); --MAKE_FUNCPTR(gnutls_hash); --MAKE_FUNCPTR(gnutls_hash_deinit); --MAKE_FUNCPTR(gnutls_hash_init); - MAKE_FUNCPTR(gnutls_perror); - #undef MAKE_FUNCPTR - -@@ -95,9 +92,6 @@ static BOOL gnutls_initialize(void) - LOAD_FUNCPTR(gnutls_global_init) - LOAD_FUNCPTR(gnutls_global_set_log_function) - LOAD_FUNCPTR(gnutls_global_set_log_level) -- LOAD_FUNCPTR(gnutls_hash); -- LOAD_FUNCPTR(gnutls_hash_deinit); -- LOAD_FUNCPTR(gnutls_hash_init); - LOAD_FUNCPTR(gnutls_perror) - #undef LOAD_FUNCPTR - -@@ -299,170 +293,6 @@ NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled) - return STATUS_SUCCESS; - } - --#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H --struct hash_impl --{ -- union -- { -- CC_MD5_CTX md5_ctx; -- CC_SHA1_CTX sha1_ctx; -- CC_SHA256_CTX sha256_ctx; -- CC_SHA512_CTX sha512_ctx; -- } u; --}; -- --static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) --{ -- switch (alg_id) -- { -- case ALG_ID_MD5: -- CC_MD5_Init( &hash->u.md5_ctx ); -- break; -- -- case ALG_ID_SHA1: -- CC_SHA1_Init( &hash->u.sha1_ctx ); -- break; -- -- case ALG_ID_SHA256: -- CC_SHA256_Init( &hash->u.sha256_ctx ); -- break; -- -- case ALG_ID_SHA384: -- CC_SHA384_Init( &hash->u.sha512_ctx ); -- break; -- -- case ALG_ID_SHA512: -- CC_SHA512_Init( &hash->u.sha512_ctx ); -- break; -- -- default: -- ERR( "unhandled id %u\n", alg_id ); -- return STATUS_NOT_IMPLEMENTED; -- } -- return STATUS_SUCCESS; --} -- --static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, -- UCHAR *input, ULONG size ) --{ -- switch (alg_id) -- { -- case ALG_ID_MD5: -- CC_MD5_Update( &hash->u.md5_ctx, input, size ); -- break; -- -- case ALG_ID_SHA1: -- CC_SHA1_Update( &hash->u.sha1_ctx, input, size ); -- break; -- -- case ALG_ID_SHA256: -- CC_SHA256_Update( &hash->u.sha256_ctx, input, size ); -- break; -- -- case ALG_ID_SHA384: -- CC_SHA384_Update( &hash->u.sha512_ctx, input, size ); -- break; -- -- case ALG_ID_SHA512: -- CC_SHA512_Update( &hash->u.sha512_ctx, input, size ); -- break; -- -- default: -- ERR( "unhandled id %u\n", alg_id ); -- return STATUS_NOT_IMPLEMENTED; -- } -- return STATUS_SUCCESS; --} -- --static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, -- UCHAR *output, ULONG size ) --{ -- switch (alg_id) -- { -- case ALG_ID_MD5: -- CC_MD5_Final( output, &hash->u.md5_ctx ); -- break; -- -- case ALG_ID_SHA1: -- CC_SHA1_Final( output, &hash->u.sha1_ctx ); -- break; -- -- case ALG_ID_SHA256: -- CC_SHA256_Final( output, &hash->u.sha256_ctx ); -- break; -- -- case ALG_ID_SHA384: -- CC_SHA384_Final( output, &hash->u.sha512_ctx ); -- break; -- -- case ALG_ID_SHA512: -- CC_SHA512_Final( output, &hash->u.sha512_ctx ); -- break; -- -- default: -- ERR( "unhandled id %u\n", alg_id ); -- break; -- } -- return STATUS_SUCCESS; --} -- --#elif defined(HAVE_GNUTLS_HASH) --struct hash_impl --{ -- gnutls_hash_hd_t hash_handle; --}; -- --static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) --{ -- gnutls_digest_algorithm_t alg; -- -- if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; -- -- switch (alg_id) -- { -- case ALG_ID_MD5: -- alg = GNUTLS_DIG_MD5; -- break; -- case ALG_ID_SHA1: -- alg = GNUTLS_DIG_SHA1; -- break; -- -- case ALG_ID_SHA256: -- alg = GNUTLS_DIG_SHA256; -- break; -- -- case ALG_ID_SHA384: -- alg = GNUTLS_DIG_SHA384; -- break; -- -- case ALG_ID_SHA512: -- alg = GNUTLS_DIG_SHA512; -- break; -- -- default: -- ERR( "unhandled id %u\n", alg_id ); -- return STATUS_NOT_IMPLEMENTED; -- } -- -- if (pgnutls_hash_init( &hash->hash_handle, alg )) return STATUS_INTERNAL_ERROR; -- return STATUS_SUCCESS; --} -- --static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, -- UCHAR *input, ULONG size ) --{ -- if (pgnutls_hash( hash->hash_handle, input, size )) return STATUS_INTERNAL_ERROR; -- return STATUS_SUCCESS; --} -- --static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, -- UCHAR *output, ULONG size ) --{ -- pgnutls_hash_deinit( hash->hash_handle, output ); -- return STATUS_SUCCESS; --} -- --#else - struct hash_impl - { - union -@@ -572,7 +402,6 @@ static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, - - return STATUS_SUCCESS; - } --#endif - - struct hash - { --- -2.9.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -From 3dc21336baced97a110773ac9e72db210a56af82 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Tue, 20 Dec 2016 03:59:19 +0100 -Subject: bcrypt: Implement BCryptDuplicateHash. - -FIXME: Should we check for NULL pointers? ---- - dlls/bcrypt/bcrypt.spec | 2 +- - dlls/bcrypt/bcrypt_main.c | 18 ++++++++++++++++++ - dlls/ncrypt/ncrypt.spec | 2 +- - 3 files changed, 20 insertions(+), 2 deletions(-) - -diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec -index 962953e509b..9ecd21d767c 100644 ---- a/dlls/bcrypt/bcrypt.spec -+++ b/dlls/bcrypt/bcrypt.spec -@@ -11,7 +11,7 @@ - @ stdcall BCryptDestroyHash(ptr) - @ stdcall BCryptDestroyKey(ptr) - @ stub BCryptDestroySecret --@ stub BCryptDuplicateHash -+@ stdcall BCryptDuplicateHash(ptr ptr ptr long long) - @ stub BCryptDuplicateKey - @ stdcall BCryptEncrypt(ptr ptr long ptr ptr long ptr long ptr long) - @ stdcall BCryptEnumAlgorithms(long ptr ptr long) -diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 4f09948096c..3eb0135b37c 100644 ---- a/dlls/bcrypt/bcrypt_main.c -+++ b/dlls/bcrypt/bcrypt_main.c -@@ -672,6 +672,24 @@ end: - return STATUS_SUCCESS; - } - -+NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HANDLE *handle_copy, -+ UCHAR *object, ULONG object_count, ULONG flags ) -+{ -+ struct hash *hash_orig = handle; -+ struct hash *hash_copy; -+ -+ TRACE( "%p, %p, %p, %u, %u\n", handle, handle_copy, object, object_count, flags ); -+ -+ if (!hash_orig || hash_orig->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; -+ if (!(hash_copy = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash_copy) ))) -+ return STATUS_NO_MEMORY; -+ -+ memcpy( hash_copy, hash_orig, sizeof(*hash_orig) ); -+ -+ *handle_copy = hash_copy; -+ return STATUS_SUCCESS; -+} -+ - NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle ) - { - struct hash *hash = handle; -diff --git a/dlls/ncrypt/ncrypt.spec b/dlls/ncrypt/ncrypt.spec -index 60b7eb37075..1a78853bf49 100644 ---- a/dlls/ncrypt/ncrypt.spec -+++ b/dlls/ncrypt/ncrypt.spec -@@ -13,7 +13,7 @@ - @ stdcall BCryptDestroyHash(ptr) bcrypt.BCryptDestroyHash - @ stdcall BCryptDestroyKey(ptr) bcrypt.BCryptDestroyKey - @ stub BCryptDestroySecret --@ stub BCryptDuplicateHash -+@ stdcall BCryptDuplicateHash(ptr ptr ptr long long) bcrypt.BCryptDuplicateHash - @ stub BCryptDuplicateKey - @ stdcall BCryptEncrypt(ptr ptr long ptr ptr long ptr long ptr long) bcrypt.BCryptEncrypt - @ stdcall BCryptEnumAlgorithms(long ptr ptr long) bcrypt.BCryptEnumAlgorithms --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -From 873d431347aa25effc70e47566e562c122a5edc8 Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Mon, 26 Dec 2016 04:23:31 +0100 -Subject: bcrypt: Handle NULL pointers in BCryptDuplicateHash and add tests. - ---- - dlls/bcrypt/bcrypt_main.c | 1 + - dlls/bcrypt/tests/bcrypt.c | 26 +++++++++++++++++++++++++- - 2 files changed, 26 insertions(+), 1 deletion(-) - -diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index a9006a4..d1516cc 100644 ---- a/dlls/bcrypt/bcrypt_main.c -+++ b/dlls/bcrypt/bcrypt_main.c -@@ -681,6 +681,7 @@ NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HAND - TRACE( "%p, %p, %p, %u, %u\n", handle, handle_copy, object, object_count, flags ); - - if (!hash_orig || hash_orig->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; -+ if (!handle_copy) return STATUS_INVALID_PARAMETER; - if (!(hash_copy = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash_copy) ))) - return STATUS_NO_MEMORY; - -diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c -index 997b298..bfe3a7e 100644 ---- a/dlls/bcrypt/tests/bcrypt.c -+++ b/dlls/bcrypt/tests/bcrypt.c -@@ -33,6 +33,7 @@ static NTSTATUS (WINAPI *pBCryptCreateHash)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDL - ULONG, ULONG); - static NTSTATUS (WINAPI *pBCryptHash)(BCRYPT_ALG_HANDLE, UCHAR *, ULONG, UCHAR *, ULONG, UCHAR *, ULONG); - static NTSTATUS (WINAPI *pBCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); -+static NTSTATUS (WINAPI *pBCryptDuplicateHash)(BCRYPT_HASH_HANDLE, BCRYPT_HASH_HANDLE *, UCHAR *, ULONG, ULONG); - static NTSTATUS (WINAPI *pBCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); - static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE); - static NTSTATUS (WINAPI *pBCryptGenRandom)(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, ULONG); -@@ -173,7 +174,7 @@ static void test_sha1(void) - static const char expected[] = "961fa64958818f767707072755d7018dcd278e94"; - static const char expected_hmac[] = "2472cf65d0e090618d769d3e46f0d9446cf212da"; - BCRYPT_ALG_HANDLE alg; -- BCRYPT_HASH_HANDLE hash; -+ BCRYPT_HASH_HANDLE hash, hash2; - UCHAR buf[512], buf_hmac[1024], sha1[20], sha1_hmac[20]; - ULONG size, len; - char str[41]; -@@ -260,6 +261,28 @@ static void test_sha1(void) - test_hash_length(hash, 20); - test_alg_name(hash, "SHA1"); - -+ ret = pBCryptDuplicateHash(NULL, &hash2, NULL, 0, 0); -+ ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); -+ -+ ret = pBCryptDuplicateHash(hash, NULL, NULL, 0, 0); -+ ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); -+ -+ hash2 = (void *)0xdeadbeef; -+ ret = pBCryptDuplicateHash(hash, &hash2, NULL, 0, 0); -+ ok(ret == STATUS_SUCCESS || broken(ret == STATUS_INVALID_PARAMETER) /* < Win 7 */, "got %08x\n", ret); -+ -+ if (ret == STATUS_SUCCESS) -+ { -+ memset(sha1_hmac, 0, sizeof(sha1_hmac)); -+ ret = pBCryptFinishHash(hash2, sha1_hmac, sizeof(sha1_hmac), 0); -+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); -+ format_hash( sha1_hmac, sizeof(sha1_hmac), str ); -+ ok(!strcmp(str, expected_hmac), "got %s\n", str); -+ -+ ret = pBCryptDestroyHash(hash2); -+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); -+ } -+ - memset(sha1_hmac, 0, sizeof(sha1_hmac)); - ret = pBCryptFinishHash(hash, sha1_hmac, sizeof(sha1_hmac), 0); - ok(ret == STATUS_SUCCESS, "got %08x\n", ret); -@@ -1179,6 +1202,7 @@ START_TEST(bcrypt) - pBCryptCreateHash = (void *)GetProcAddress(module, "BCryptCreateHash"); - pBCryptHash = (void *)GetProcAddress(module, "BCryptHash"); - pBCryptHashData = (void *)GetProcAddress(module, "BCryptHashData"); -+ pBCryptDuplicateHash = (void *)GetProcAddress(module, "BCryptDuplicateHash"); - pBCryptFinishHash = (void *)GetProcAddress(module, "BCryptFinishHash"); - pBCryptDestroyHash = (void *)GetProcAddress(module, "BCryptDestroyHash"); - pBCryptGenRandom = (void *)GetProcAddress(module, "BCryptGenRandom"); --- -2.9.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,17 +1,17 @@ -From 9f68ea60cf840c9366aefe1ab486e9d1ee192843 Mon Sep 17 00:00:00 2001 +From a93745453350f9eabcab0f49528c3f027a303c24 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Mon, 26 Dec 2016 06:18:01 +0100 Subject: bcrypt: Pass object to get_{alg,hash}_property instead of alg_id. --- - dlls/bcrypt/bcrypt_main.c | 32 ++++++++++++++++---------------- - 1 file changed, 16 insertions(+), 16 deletions(-) + dlls/bcrypt/bcrypt_main.c | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index d1516cc..8a5161b 100644 +index d0a1b074b50..deab6f28bd9 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c -@@ -450,16 +450,16 @@ static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR * +@@ -440,15 +440,15 @@ static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR * return STATUS_NOT_IMPLEMENTED; } @@ -19,7 +19,6 @@ +static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) { NTSTATUS status; - ULONG value; - status = generic_alg_property( id, prop, buf, size, ret_size ); + status = generic_alg_property( alg->id, prop, buf, size, ret_size ); @@ -31,17 +30,8 @@ { case ALG_ID_AES: if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH )) -@@ -540,7 +540,7 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, - return STATUS_NOT_IMPLEMENTED; - - default: -- FIXME( "unsupported algorithm %u\n", id ); -+ FIXME( "unsupported algorithm %u\n", alg->id ); - return STATUS_NOT_IMPLEMENTED; - } - -@@ -555,11 +555,11 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, - return STATUS_SUCCESS; +@@ -484,11 +484,11 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, + return STATUS_NOT_IMPLEMENTED; } -static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) @@ -54,7 +44,7 @@ if (status == STATUS_NOT_IMPLEMENTED) FIXME( "unsupported property %s\n", debugstr_w(prop) ); return status; -@@ -579,12 +579,12 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu +@@ -508,12 +508,12 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu case MAGIC_ALG: { const struct algorithm *alg = (const struct algorithm *)object; @@ -69,7 +59,7 @@ } default: WARN( "unknown magic %08x\n", object->magic ); -@@ -783,34 +783,34 @@ struct key +@@ -697,34 +697,34 @@ struct key ULONG secret_len; }; @@ -110,7 +100,7 @@ key->handle = 0; /* initialized on first use */ key->secret = buffer; key->secret_len = secret_len; -@@ -906,7 +906,7 @@ struct key +@@ -820,7 +820,7 @@ struct key ULONG block_size; }; @@ -119,7 +109,7 @@ { ERR( "support for keys not available at build time\n" ); return STATUS_NOT_IMPLEMENTED; -@@ -955,7 +955,7 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ +@@ -869,7 +869,7 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) ))) return STATUS_NO_MEMORY; key->hdr.magic = MAGIC_KEY; @@ -129,5 +119,5 @@ HeapFree( GetProcessHeap(), 0, key ); return status; -- -2.9.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0013-bcrypt-Implement-BCryptSetProperty-for-algorithms.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0013-bcrypt-Implement-BCryptSetProperty-for-algorithms.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0013-bcrypt-Implement-BCryptSetProperty-for-algorithms.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0013-bcrypt-Implement-BCryptSetProperty-for-algorithms.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 5313398cdabe97a17b21e2d9f25a191da7bd9434 Mon Sep 17 00:00:00 2001 +From 2f57d906c55bdc99f476b6547f67d864e7210f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 26 Dec 2016 06:08:33 +0100 Subject: bcrypt: Implement BCryptSetProperty for algorithms. @@ -9,7 +9,7 @@ 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 8a5161b..4757878 100644 +index deab6f28bd9..595d36d7dbe 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -153,6 +153,12 @@ enum alg_id @@ -23,9 +23,9 @@ +}; + #define MAX_HASH_OUTPUT_BYTES 64 + #define MAX_HASH_BLOCK_BITS 1024 - static const struct { -@@ -172,6 +178,7 @@ struct algorithm +@@ -175,6 +181,7 @@ struct algorithm { struct object hdr; enum alg_id id; @@ -33,7 +33,7 @@ BOOL hmac; }; -@@ -265,6 +272,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR +@@ -255,6 +262,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY; alg->hdr.magic = MAGIC_ALG; alg->id = alg_id; @@ -41,8 +41,8 @@ alg->hmac = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG; *handle = alg; -@@ -555,6 +563,40 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop - return STATUS_SUCCESS; +@@ -484,6 +492,40 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop + return STATUS_NOT_IMPLEMENTED; } +static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags ) @@ -82,7 +82,7 @@ static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) { NTSTATUS status; -@@ -595,8 +637,28 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu +@@ -524,8 +566,28 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags ) { @@ -114,10 +114,10 @@ NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen, diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c -index 699a995..d850738 100644 +index abf59c8404d..08a83aaf7a5 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c -@@ -889,7 +889,7 @@ static void test_BCryptGenerateSymmetricKey(void) +@@ -776,7 +776,7 @@ static void test_BCryptGenerateSymmetricKey(void) ret = pBCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0); @@ -126,7 +126,7 @@ size = 0xdeadbeef; ret = pBCryptEncrypt(key, NULL, 0, NULL, NULL, 0, NULL, 0, &size, 0); -@@ -1078,7 +1078,7 @@ static void test_BCryptEncrypt(void) +@@ -965,7 +965,7 @@ static void test_BCryptEncrypt(void) todo_wine ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret); ret = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); @@ -135,7 +135,7 @@ size = 0; ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, NULL, 0, &size, 0); -@@ -1306,7 +1306,7 @@ static void test_BCryptDecrypt(void) +@@ -1193,7 +1193,7 @@ static void test_BCryptDecrypt(void) ******************/ ret = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); @@ -145,5 +145,5 @@ buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret), 0); -- -2.9.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0014-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_CHAINI.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0014-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_CHAINI.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0014-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_CHAINI.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0014-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_CHAINI.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From f7749755c11e54d1e75cd05b6656d2c474ade8ae Mon Sep 17 00:00:00 2001 +From 6de382845ffbb12d514a0ece9483a72b34df852e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 26 Dec 2016 06:46:11 +0100 Subject: bcrypt: Implement BCryptGetProperty for BCRYPT_CHAINING_MODE. @@ -9,10 +9,10 @@ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 4757878..24dee8b 100644 +index 595d36d7dbe..3ab80a1a31a 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c -@@ -482,17 +482,18 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop +@@ -470,17 +470,18 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop } if (!strcmpW( prop, BCRYPT_CHAINING_MODE )) { @@ -38,13 +38,13 @@ + memcpy( buf, mode, (strlenW(mode) + 1) * sizeof(WCHAR) ); + return STATUS_SUCCESS; } - FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) ); - return STATUS_NOT_IMPLEMENTED; + break; + diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c -index d850738..bbf18c4 100644 +index 08a83aaf7a5..1a5523726dd 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c -@@ -842,7 +842,7 @@ static void test_aes(void) +@@ -729,7 +729,7 @@ static void test_aes(void) size = 0; ret = pBCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode) - 1, &size, 0); @@ -54,5 +54,5 @@ size = 0; -- -2.9.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0015-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_AUTH_T.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0015-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_AUTH_T.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0015-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_AUTH_T.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0015-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_AUTH_T.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 017f5d467e537e5159f9c14f703df97661a1453e Mon Sep 17 00:00:00 2001 +From 5f7f79f4ae52f87eeaaa04617a7cd9289dd655b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 26 Dec 2016 06:50:28 +0100 Subject: bcrypt: Implement BCryptGetProperty for BCRYPT_AUTH_TAG_LENGTH. @@ -9,10 +9,10 @@ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 24dee8b..dc5c798 100644 +index 3ab80a1a31a..0a990158361 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c -@@ -495,6 +495,20 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop +@@ -483,6 +483,20 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop memcpy( buf, mode, (strlenW(mode) + 1) * sizeof(WCHAR) ); return STATUS_SUCCESS; } @@ -30,14 +30,14 @@ + } + return STATUS_SUCCESS; + } - FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) ); - return STATUS_NOT_IMPLEMENTED; + break; + default: diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c -index bbf18c4..513d11f 100644 +index 1a5523726dd..50340566093 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c -@@ -1075,24 +1075,24 @@ static void test_BCryptEncrypt(void) +@@ -962,24 +962,24 @@ static void test_BCryptEncrypt(void) size = 0; ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, NULL, 0, &size, 0); @@ -71,5 +71,5 @@ len = 0xdeadbeef; size = sizeof(len); -- -2.9.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0022-bcrypt-Allow-to-call-BCryptSetProperty-on-key-object.patch wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0022-bcrypt-Allow-to-call-BCryptSetProperty-on-key-object.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/0022-bcrypt-Allow-to-call-BCryptSetProperty-on-key-object.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/0022-bcrypt-Allow-to-call-BCryptSetProperty-on-key-object.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 85c7ad0c67aa6cc57e93f2160922305f80d49b4c Mon Sep 17 00:00:00 2001 +From bdebe07119a6ab2d3d3ba87f1d31ab0c4d998417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 26 Dec 2016 08:41:31 +0100 Subject: bcrypt: Allow to call BCryptSetProperty on key objects. @@ -9,11 +9,11 @@ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index a07250e..3638c77 100644 +index 5ca0c85e9ee..75b9765a602 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c -@@ -215,6 +215,9 @@ int alg_block_bits[] = - /* ALG_ID_SHA512 */ 1024 +@@ -204,6 +204,9 @@ struct algorithm + BOOL hmac; }; +struct key; @@ -22,7 +22,7 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags) { const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG; -@@ -685,8 +688,8 @@ NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHA +@@ -671,8 +674,8 @@ NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHA } case MAGIC_KEY: { @@ -33,7 +33,7 @@ } default: WARN( "unknown magic %08x\n", object->magic ); -@@ -933,6 +936,31 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) +@@ -903,6 +906,31 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) return STATUS_SUCCESS; } @@ -65,7 +65,7 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key ) { switch (key->alg_id) -@@ -1050,6 +1078,12 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) +@@ -1023,6 +1051,12 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) return STATUS_NOT_IMPLEMENTED; } @@ -79,10 +79,10 @@ { ERR( "support for keys not available at build time\n" ); diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c -index a55d9a9..62f0ca7 100644 +index f458ab5ce56..e00245556f4 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c -@@ -903,6 +903,10 @@ static void test_BCryptGenerateSymmetricKey(void) +@@ -889,6 +889,10 @@ static void test_BCryptGenerateSymmetricKey(void) sizeof(BCRYPT_CHAIN_MODE_CBC), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); @@ -94,5 +94,5 @@ ret = pBCryptEncrypt(key, NULL, 0, NULL, NULL, 0, NULL, 0, &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); -- -2.9.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/definition wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/bcrypt-Improvements/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/bcrypt-Improvements/definition 2017-03-21 14:37:14.000000000 +0000 @@ -1,3 +1,2 @@ -Fixes: [41951] Implement bcrypt.BCryptDuplicateHash Fixes: [40418] Implement BCrypt AES provider Fixes: [42553] Implement BCrypt ECB chaining mode diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/cabinet-iFolder/0001-cabinet-Set-index-of-folder-in-FDICopy-callback.patch wine-staging-2.4.0~ubuntu16.04.1/patches/cabinet-iFolder/0001-cabinet-Set-index-of-folder-in-FDICopy-callback.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/cabinet-iFolder/0001-cabinet-Set-index-of-folder-in-FDICopy-callback.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/cabinet-iFolder/0001-cabinet-Set-index-of-folder-in-FDICopy-callback.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -From d98a585a7d809889d84a45546d7d259a9ab35356 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Thu, 27 Oct 2016 01:33:34 +0200 -Subject: cabinet: Set index of folder in FDICopy callback. - ---- - dlls/cabinet/fdi.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/dlls/cabinet/fdi.c b/dlls/cabinet/fdi.c -index fdff0bf..758133e 100644 ---- a/dlls/cabinet/fdi.c -+++ b/dlls/cabinet/fdi.c -@@ -2640,6 +2640,7 @@ BOOL __cdecl FDICopy( - fdin.date = file->date; - fdin.time = file->time; - fdin.attribs = file->attribs; -+ fdin.iFolder = file->index; - if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) { - set_error( fdi, FDIERROR_USER_ABORT, 0 ); - filehf = 0; -@@ -2765,6 +2766,7 @@ BOOL __cdecl FDICopy( - fdin.date = file->date; - fdin.time = file->time; - fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */ -+ fdin.iFolder = file->index; - ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin)); - filehf = 0; - --- -2.9.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/cabinet-iFolder/definition wine-staging-2.4.0~ubuntu16.04.1/patches/cabinet-iFolder/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/cabinet-iFolder/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/cabinet-iFolder/definition 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Fixes: [10858] Set index of folder in FDICopy callback diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/d3dx9_36-FindNextValidTechnique/0001-d3dx9_36-Implement-ID3DXEffect_FindNextValidTechniqu.patch wine-staging-2.4.0~ubuntu16.04.1/patches/d3dx9_36-FindNextValidTechnique/0001-d3dx9_36-Implement-ID3DXEffect_FindNextValidTechniqu.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/d3dx9_36-FindNextValidTechnique/0001-d3dx9_36-Implement-ID3DXEffect_FindNextValidTechniqu.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/d3dx9_36-FindNextValidTechnique/0001-d3dx9_36-Implement-ID3DXEffect_FindNextValidTechniqu.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 29ccadcb0e716255ac5e43b8784d129f3fc2a441 Mon Sep 17 00:00:00 2001 +From caafb5926a24065e96350fc255ea92c0863c2730 Mon Sep 17 00:00:00 2001 From: Christian Costa Date: Fri, 19 Dec 2014 22:31:46 +0100 Subject: d3dx9_36: Implement ID3DXEffect_FindNextValidTechnique + add tests. @@ -9,7 +9,7 @@ 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c -index 7772406..00c486c 100644 +index 42f5aea966b..7c1d1787bf1 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -3538,13 +3538,41 @@ static HRESULT WINAPI ID3DXEffectImpl_ValidateTechnique(ID3DXEffect* iface, D3DX @@ -58,10 +58,10 @@ static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func, diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c -index 41db494..efc991e 100644 +index 56d9fe627be..1b9bea6a55c 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c -@@ -4275,6 +4275,65 @@ static void test_effect_isparameterused(IDirect3DDevice9 *device) +@@ -4413,6 +4413,65 @@ static void test_effect_out_of_bounds_selector(IDirect3DDevice9 *device) effect->lpVtbl->Release(effect); } @@ -127,14 +127,14 @@ START_TEST(effect) { HWND wnd; -@@ -4318,6 +4377,7 @@ START_TEST(effect) - test_effect_preshader(device); +@@ -4457,6 +4516,7 @@ START_TEST(effect) test_effect_preshader_ops(device); test_effect_isparameterused(device); + test_effect_out_of_bounds_selector(device); + test_effect_technique_validation(device); count = IDirect3DDevice9_Release(device); ok(count == 0, "The device was not properly freed: refcount %u\n", count); -- -2.8.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ddraw-Device_Caps/0003-ddraw-Set-ddsOldCaps-correctly-in-ddraw7_GetCaps.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ddraw-Device_Caps/0003-ddraw-Set-ddsOldCaps-correctly-in-ddraw7_GetCaps.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ddraw-Device_Caps/0003-ddraw-Set-ddsOldCaps-correctly-in-ddraw7_GetCaps.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ddraw-Device_Caps/0003-ddraw-Set-ddsOldCaps-correctly-in-ddraw7_GetCaps.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 336cf41969e853ca0044261f00ed55ac6f668ff1 Mon Sep 17 00:00:00 2001 +From 93267b9dc171775f908aa0f0dde65cc5a60c3b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Fri, 4 Mar 2016 22:22:42 +0100 Subject: ddraw: Set ddsOldCaps correctly in ddraw7_GetCaps. @@ -12,7 +12,7 @@ 5 files changed, 106 insertions(+) diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c -index fb91722943e..4b9d9fbf876 100644 +index 8a33ccd4c7..3330b9ce32 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1554,6 +1554,8 @@ static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DD @@ -25,10 +25,10 @@ if(DriverCaps) diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c -index 278b9c60069..e1a7a1a4d1c 100644 +index 4f53ee1059..538ab656e3 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c -@@ -10163,6 +10163,31 @@ static void test_texture_load(void) +@@ -10683,6 +10683,31 @@ done: DestroyWindow(window); } @@ -60,18 +60,18 @@ START_TEST(ddraw1) { IDirectDraw *ddraw; -@@ -10249,4 +10274,5 @@ START_TEST(ddraw1) - test_display_mode_surface_pixel_format(); +@@ -10770,4 +10795,5 @@ START_TEST(ddraw1) test_surface_desc_size(); test_texture_load(); + test_ck_operation(); + test_caps(); } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c -index db09e5d8975..53279059105 100644 +index be950d8034..b72fffb51e 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c -@@ -11487,6 +11487,31 @@ static void test_surface_desc_size(void) - ok(!refcount, "DirectDraw has %u references left.\n", refcount); +@@ -12021,6 +12021,31 @@ done: + DestroyWindow(window); } +static void test_caps(void) @@ -102,17 +102,17 @@ START_TEST(ddraw2) { IDirectDraw2 *ddraw; -@@ -11581,4 +11606,5 @@ START_TEST(ddraw2) - test_transform_vertices(); +@@ -12116,4 +12141,5 @@ START_TEST(ddraw2) test_display_mode_surface_pixel_format(); test_surface_desc_size(); + test_ck_operation(); + test_caps(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c -index 830da89bba2..7ba77be3406 100644 +index 2f92a70f4c..1381b498de 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c -@@ -12885,6 +12885,31 @@ static void test_get_surface_from_dc(void) +@@ -13551,6 +13551,31 @@ static void test_compute_sphere_visibility(void) DestroyWindow(window); } @@ -144,17 +144,17 @@ START_TEST(ddraw4) { IDirectDraw4 *ddraw; -@@ -12988,4 +13013,5 @@ START_TEST(ddraw4) - test_display_mode_surface_pixel_format(); - test_surface_desc_size(); - test_get_surface_from_dc(); +@@ -13657,4 +13682,5 @@ START_TEST(ddraw4) + test_ck_operation(); + test_vb_refcount(); + test_compute_sphere_visibility(); + test_caps(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c -index ba0e4a96e0f..be70456555e 100644 +index 29dd246d91..206c90ca3d 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c -@@ -12576,6 +12576,31 @@ static void test_get_surface_from_dc(void) +@@ -13251,6 +13251,31 @@ static void test_compute_sphere_visibility(void) DestroyWindow(window); } @@ -186,10 +186,10 @@ START_TEST(ddraw7) { HMODULE module = GetModuleHandleA("ddraw.dll"); -@@ -12689,4 +12714,5 @@ START_TEST(ddraw7) - test_display_mode_surface_pixel_format(); - test_surface_desc_size(); - test_get_surface_from_dc(); +@@ -13367,4 +13392,5 @@ START_TEST(ddraw7) + test_ck_operation(); + test_vb_refcount(); + test_compute_sphere_visibility(); + test_caps(); } -- diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ddraw-Silence_FIXMEs/0001-ddraw-Silence-noisy-FIXME-about-unimplemented-D3DPRO.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ddraw-Silence_FIXMEs/0001-ddraw-Silence-noisy-FIXME-about-unimplemented-D3DPRO.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ddraw-Silence_FIXMEs/0001-ddraw-Silence-noisy-FIXME-about-unimplemented-D3DPRO.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ddraw-Silence_FIXMEs/0001-ddraw-Silence-noisy-FIXME-about-unimplemented-D3DPRO.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,29 @@ +From ff117878cb3a0c74a50355ca64ac36c5fe6cee67 Mon Sep 17 00:00:00 2001 +From: Christian Costa +Date: Fri, 10 Mar 2017 22:07:37 +0100 +Subject: ddraw: Silence noisy FIXME about unimplemented + D3DPROCESSVERTICES_UPDATEEXTENTS. + +--- + dlls/ddraw/executebuffer.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c +index 393c52c1e2..9b64c687d3 100644 +--- a/dlls/ddraw/executebuffer.c ++++ b/dlls/ddraw/executebuffer.c +@@ -302,7 +302,10 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, + ci->wStart, ci->wDest, ci->dwCount, ci->dwFlags); + + if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS) +- FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n"); ++ { ++ static int once; ++ if (!once++) FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n"); ++ } + if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR) + FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n"); + +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/gdi32-GetCharacterPlacement/0001-gdi32-Treat-lpResults-as-optional-in-GetCharacterPla.patch wine-staging-2.4.0~ubuntu16.04.1/patches/gdi32-GetCharacterPlacement/0001-gdi32-Treat-lpResults-as-optional-in-GetCharacterPla.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/gdi32-GetCharacterPlacement/0001-gdi32-Treat-lpResults-as-optional-in-GetCharacterPla.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/gdi32-GetCharacterPlacement/0001-gdi32-Treat-lpResults-as-optional-in-GetCharacterPla.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,97 @@ +From 1f4a7bc3ed8ede33a6e623bf49067550cee433d8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sun, 19 Mar 2017 15:52:42 +0100 +Subject: gdi32: Treat lpResults as optional in GetCharacterPlacement. + +--- + dlls/gdi32/font.c | 13 ++++++++++++- + dlls/gdi32/tests/font.c | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 44 insertions(+), 1 deletion(-) + +diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c +index ddd0051ab6..fcc24d8645 100644 +--- a/dlls/gdi32/font.c ++++ b/dlls/gdi32/font.c +@@ -3201,10 +3201,18 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount, + TRACE("%s, %d, %d, 0x%08x\n", + debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags); + ++ lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp); ++ ++ if (!lpResults) ++ { ++ ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, NULL, dwFlags); ++ HeapFree(GetProcessHeap(), 0, lpStringW); ++ return ret; ++ } ++ + /* both structs are equal in size */ + memcpy(&resultsW, lpResults, sizeof(resultsW)); + +- lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp); + if(lpResults->lpOutString) + resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW); + +@@ -3259,6 +3267,9 @@ GetCharacterPlacementW( + TRACE("%s, %d, %d, 0x%08x\n", + debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags); + ++ if (!lpResults) ++ return GetTextExtentPoint32W(hdc, lpString, uCount, &size) ? MAKELONG(size.cx, size.cy) : 0; ++ + TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n" + "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n", + lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder, +diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c +index fb27f8e005..974b471462 100644 +--- a/dlls/gdi32/tests/font.c ++++ b/dlls/gdi32/tests/font.c +@@ -4910,6 +4910,37 @@ static void test_GetTextMetrics2(const char *fontname, int font_height) + ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio); + } + ++static void test_GetCharacterPlacement(void) ++{ ++ GCP_RESULTSA result; ++ DWORD size, size2; ++ WCHAR glyphs[20]; ++ HDC hdc; ++ ++ hdc = CreateCompatibleDC(0); ++ ok(!!hdc, "CreateCompatibleDC failed\n"); ++ ++ memset(&result, 0, sizeof(result)); ++ result.lStructSize = sizeof(result); ++ result.lpGlyphs = glyphs; ++ result.nGlyphs = 20; ++ ++ size = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, &result, 0); ++ ok(size, "GetCharacterPlacementA failed!\n"); ++ ++ size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, NULL, 0); ++ ok(size2, "GetCharacterPlacementA failed!\n"); ++ ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size); ++ ++ size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, NULL, GCP_REORDER); ++ ok(size2, "GetCharacterPlacementA failed!\n"); ++ ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size); ++ ++ size = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, &result, GCP_REORDER); ++ ok(size, "GetCharacterPlacementA failed!\n"); ++ ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size); ++} ++ + static void test_CreateFontIndirect(void) + { + LOGFONTA lf, getobj_lf; +@@ -6682,6 +6713,7 @@ START_TEST(font) + test_GetTextMetrics2("Arial", -11); + test_GetTextMetrics2("Arial", -55); + test_GetTextMetrics2("Arial", -110); ++ test_GetCharacterPlacement(); + test_CreateFontIndirect(); + test_CreateFontIndirectEx(); + test_oemcharset(); +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/gdi32-GetCharacterPlacement/definition wine-staging-2.4.0~ubuntu16.04.1/patches/gdi32-GetCharacterPlacement/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/gdi32-GetCharacterPlacement/definition 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/gdi32-GetCharacterPlacement/definition 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1 @@ +Fixes: [42669] Treat lpResults as optional in gdi32.GetCharacterPlacement diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/0001-gdiplus-Change-the-order-of-x-y-loops-in-the-scaler.patch wine-staging-2.4.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/0001-gdiplus-Change-the-order-of-x-y-loops-in-the-scaler.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/0001-gdiplus-Change-the-order-of-x-y-loops-in-the-scaler.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/0001-gdiplus-Change-the-order-of-x-y-loops-in-the-scaler.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,29 @@ +From f7c317dac3581075e75168ce50c4523973422384 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Sun, 5 Mar 2017 12:55:51 +0800 +Subject: gdiplus: Change the order of x/y loops in the scaler. + +This improves performance by about 5%. +--- + dlls/gdiplus/graphics.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c +index 142b68115e..02d699b00b 100644 +--- a/dlls/gdiplus/graphics.c ++++ b/dlls/gdiplus/graphics.c +@@ -3043,9 +3043,9 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image + y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X; + y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y; + +- for (x=dst_area.left; x +Date: Sun, 5 Mar 2017 13:07:43 +0800 +Subject: gdiplus: Change multiplications by additions in the x/y scaler loops. + +This should imrove performance when floating point math will be replaced +by fixed point calculations. +--- + dlls/gdiplus/graphics.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c +index 02d699b00b..ef26887d14 100644 +--- a/dlls/gdiplus/graphics.c ++++ b/dlls/gdiplus/graphics.c +@@ -3026,6 +3026,8 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image + + if (do_resampling) + { ++ REAL delta_xx, delta_xy, delta_yx, delta_yy; ++ + /* Transform the bits as needed to the destination. */ + dst_data = dst_dyn_data = heap_alloc_zero(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top)); + if (!dst_data) +@@ -3043,15 +3045,21 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image + y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X; + y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y; + ++ delta_yy = dst_area.top * y_dy; ++ delta_yx = dst_area.top * y_dx; ++ + for (y=dst_area.top; y +Date: Sun, 5 Mar 2017 13:18:21 +0800 +Subject: gdiplus: Remove ceilf/floorf calls from bilinear scaler. (v2) + +This improves performance by about 55%. +--- + dlls/gdiplus/graphics.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c +index ef26887d14..58cfebb923 100644 +--- a/dlls/gdiplus/graphics.c ++++ b/dlls/gdiplus/graphics.c +@@ -526,7 +526,7 @@ static ARGB blend_colors(ARGB start, ARGB end, REAL position) + INT start_a, end_a, final_a; + INT pos; + +- pos = gdip_round(position * 0xff); ++ pos = (INT)(position * 255.0f + 0.5f); + + start_a = ((start >> 24) & 0xff) * (pos ^ 0xff); + end_a = ((end >> 24) & 0xff) * pos; +@@ -928,6 +928,11 @@ static ARGB sample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT wi + return ((DWORD*)(bits))[(x - src_rect->X) + (y - src_rect->Y) * src_rect->Width]; + } + ++static FORCEINLINE int positive_ceilf(float f) ++{ ++ return f - (int)f > 0.0f ? f + 1.0f : f; ++} ++ + static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width, + UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes, + InterpolationMode interpolation, PixelOffsetMode offset_mode) +@@ -948,12 +953,12 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT + ARGB top, bottom; + float x_offset; + +- leftxf = floorf(point->X); +- leftx = (INT)leftxf; +- rightx = (INT)ceilf(point->X); +- topyf = floorf(point->Y); +- topy = (INT)topyf; +- bottomy = (INT)ceilf(point->Y); ++ leftx = (INT)point->X; ++ leftxf = (REAL)leftx; ++ rightx = positive_ceilf(point->X); ++ topy = (INT)point->Y; ++ topyf = (REAL)topy; ++ bottomy = positive_ceilf(point->Y); + + if (leftx == rightx && topy == bottomy) + return sample_bitmap_pixel(src_rect, bits, width, height, +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/0004-gdiplus-Prefer-using-pre-multiplied-ARGB-data-in-the.patch wine-staging-2.4.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/0004-gdiplus-Prefer-using-pre-multiplied-ARGB-data-in-the.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/0004-gdiplus-Prefer-using-pre-multiplied-ARGB-data-in-the.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/0004-gdiplus-Prefer-using-pre-multiplied-ARGB-data-in-the.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,140 @@ +From 37b9499d8da295cd8819d85e9a563629ef13f22e Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Sun, 5 Mar 2017 14:34:51 +0800 +Subject: gdiplus: Prefer using pre-multiplied ARGB data in the scaler. + +This further improves performance by about 20%. +--- + dlls/gdiplus/graphics.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 91 insertions(+), 3 deletions(-) + +diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c +index 58cfebb923..bdee2e8318 100644 +--- a/dlls/gdiplus/graphics.c ++++ b/dlls/gdiplus/graphics.c +@@ -521,6 +521,17 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, + return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL, fmt); + } + ++/* NOTE: start and end pixels must be in pre-multiplied ARGB format */ ++static FORCEINLINE ARGB blend_colors_premult(ARGB start, ARGB end, REAL position) ++{ ++ UINT pos = position * 255.0f + 0.5f; ++ return ++ (((((start >> 24) ) << 8) + (((end >> 24) ) - ((start >> 24) )) * pos) >> 8) << 24 | ++ (((((start >> 16) & 0xff) << 8) + (((end >> 16) & 0xff) - ((start >> 16) & 0xff)) * pos) >> 8) << 16 | ++ (((((start >> 8) & 0xff) << 8) + (((end >> 8) & 0xff) - ((start >> 8) & 0xff)) * pos) >> 8) << 8 | ++ (((((start ) & 0xff) << 8) + (((end ) & 0xff) - ((start ) & 0xff)) * pos) >> 8); ++} ++ + static ARGB blend_colors(ARGB start, ARGB end, REAL position) + { + INT start_a, end_a, final_a; +@@ -1002,6 +1013,75 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT + } + } + ++static ARGB resample_bitmap_pixel_premult(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width, ++ UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes, ++ InterpolationMode interpolation, PixelOffsetMode offset_mode) ++{ ++ static int fixme; ++ ++ switch (interpolation) ++ { ++ default: ++ if (!fixme++) ++ FIXME("Unimplemented interpolation %i\n", interpolation); ++ /* fall-through */ ++ case InterpolationModeBilinear: ++ { ++ REAL leftxf, topyf; ++ INT leftx, rightx, topy, bottomy; ++ ARGB topleft, topright, bottomleft, bottomright; ++ ARGB top, bottom; ++ float x_offset; ++ ++ leftx = (INT)point->X; ++ leftxf = (REAL)leftx; ++ rightx = positive_ceilf(point->X); ++ topy = (INT)point->Y; ++ topyf = (REAL)topy; ++ bottomy = positive_ceilf(point->Y); ++ ++ if (leftx == rightx && topy == bottomy) ++ return sample_bitmap_pixel(src_rect, bits, width, height, ++ leftx, topy, attributes); ++ ++ topleft = sample_bitmap_pixel(src_rect, bits, width, height, ++ leftx, topy, attributes); ++ topright = sample_bitmap_pixel(src_rect, bits, width, height, ++ rightx, topy, attributes); ++ bottomleft = sample_bitmap_pixel(src_rect, bits, width, height, ++ leftx, bottomy, attributes); ++ bottomright = sample_bitmap_pixel(src_rect, bits, width, height, ++ rightx, bottomy, attributes); ++ ++ x_offset = point->X - leftxf; ++ top = blend_colors_premult(topleft, topright, x_offset); ++ bottom = blend_colors_premult(bottomleft, bottomright, x_offset); ++ ++ return blend_colors_premult(top, bottom, point->Y - topyf); ++ } ++ case InterpolationModeNearestNeighbor: ++ { ++ FLOAT pixel_offset; ++ switch (offset_mode) ++ { ++ default: ++ case PixelOffsetModeNone: ++ case PixelOffsetModeHighSpeed: ++ pixel_offset = 0.5; ++ break; ++ ++ case PixelOffsetModeHalf: ++ case PixelOffsetModeHighQuality: ++ pixel_offset = 0.0; ++ break; ++ } ++ return sample_bitmap_pixel(src_rect, bits, width, height, ++ floorf(point->X + pixel_offset), point->Y + pixel_offset, attributes); ++ } ++ ++ } ++} ++ + static REAL intersect_line_scanline(const GpPointF *p1, const GpPointF *p2, REAL y) + { + return (p1->X - p2->X) * (p2->Y - y) / (p2->Y - p1->Y) + p2->X; +@@ -3010,8 +3090,10 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image + lockeddata.Scan0 = src_data; + if (!do_resampling && bitmap->format == PixelFormat32bppPARGB) + lockeddata.PixelFormat = apply_image_attributes(imageAttributes, NULL, 0, 0, 0, ColorAdjustTypeBitmap, bitmap->format); +- else ++ else if (imageAttributes != &defaultImageAttributes) + lockeddata.PixelFormat = PixelFormat32bppARGB; ++ else ++ lockeddata.PixelFormat = PixelFormat32bppPARGB; + + stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf, + lockeddata.PixelFormat, &lockeddata); +@@ -3069,8 +3151,14 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image + dst_color = (ARGB*)(dst_data + dst_stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left)); + + if (src_pointf.X >= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight) +- *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf, +- imageAttributes, interpolation, offset_mode); ++ { ++ if (lockeddata.PixelFormat != PixelFormat32bppPARGB) ++ *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf, ++ imageAttributes, interpolation, offset_mode); ++ else ++ *dst_color = resample_bitmap_pixel_premult(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf, ++ imageAttributes, interpolation, offset_mode); ++ } + else + *dst_color = 0; + +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/definition wine-staging-2.4.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/definition 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/gdiplus-Performance-Improvements/definition 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1 @@ +Fixes: Improve performance of bilinear bitmap scaling diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/0001-kernel32-Add-stub-for-GetCurrentPackageFamilyName-an.patch wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/0001-kernel32-Add-stub-for-GetCurrentPackageFamilyName-an.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/0001-kernel32-Add-stub-for-GetCurrentPackageFamilyName-an.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/0001-kernel32-Add-stub-for-GetCurrentPackageFamilyName-an.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,160 +0,0 @@ -From 1696ec4c67d39495d63673137e25d11878c44c8c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Fri, 15 Jan 2016 13:23:02 +0100 -Subject: kernel32: Add stub for GetCurrentPackageFamilyName and add related - functions to spec file. - ---- - .../api-ms-win-appmodel-runtime-l1-1-1.spec | 2 +- - dlls/kernel32/kernel32.spec | 35 ++++++++++++++++++++++ - dlls/kernel32/version.c | 9 ++++++ - 3 files changed, 45 insertions(+), 1 deletion(-) - -diff --git a/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec b/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec -index 1eb8327..af7774d 100644 ---- a/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec -+++ b/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec -@@ -3,7 +3,7 @@ - @ stub FormatApplicationUserModelId - @ stub GetApplicationUserModelId - @ stub GetCurrentApplicationUserModelId --@ stub GetCurrentPackageFamilyName -+@ stdcall GetCurrentPackageFamilyName(ptr ptr) kernel32.GetCurrentPackageFamilyName - @ stub GetCurrentPackageFullName - @ stdcall GetCurrentPackageId(ptr ptr) kernel32.GetCurrentPackageId - @ stub GetCurrentPackageInfo -diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec -index 3c25286..3c1cb23 100644 ---- a/dlls/kernel32/kernel32.spec -+++ b/dlls/kernel32/kernel32.spec -@@ -225,6 +225,7 @@ - @ stdcall ClearCommError(long ptr ptr) - @ stdcall CloseConsoleHandle(long) - @ stdcall CloseHandle(long) -+@ stub ClosePackageInfo - # @ stub ClosePrivateNamespace - @ stdcall CloseProfileUserMapping() - @ stub CloseSystemHandle -@@ -506,6 +507,7 @@ - @ stdcall FindNextVolumeW(long ptr long) - # @ stub FindNLSString - # @ stub FindNLSStringEx -+@ stub FindPackagesByPackageFamily - @ stdcall FindResourceA(long str str) - @ stdcall FindResourceExA(long str str long) - @ stdcall FindResourceExW(long wstr wstr long) -@@ -524,6 +526,7 @@ - @ stdcall FlushViewOfFile(ptr long) - @ stdcall FoldStringA(long str long ptr long) - @ stdcall FoldStringW(long wstr long ptr long) -+@ stub FormatApplicationUserModelId - @ stdcall FormatMessageA(long ptr long long ptr long ptr) - @ stdcall FormatMessageW(long ptr long long ptr long ptr) - @ stdcall FreeConsole() -@@ -544,6 +547,8 @@ - # @ stub GetActiveProcessorGroupCount - # @ stub GetApplicationRecoveryCallback - # @ stub GetApplicationRestartSettings -+@ stub GetApplicationUserModelId -+@ stub GetApplicationUserModelIdFromToken - @ stdcall GetAtomNameA(long ptr long) - @ stdcall GetAtomNameW(long ptr long) - @ stdcall GetBinaryType(str ptr) GetBinaryTypeA -@@ -624,11 +629,16 @@ - # @ stub GetCurrencyFormatEx - @ stdcall GetCurrencyFormatW(long long str ptr str long) - @ stdcall GetCurrentActCtx(ptr) -+@ stub GetCurrentApplicationUserModelId - @ stdcall GetCurrentConsoleFont(long long ptr) - # @ stub GetCurrentConsoleFontEx - @ stdcall GetCurrentDirectoryA(long ptr) - @ stdcall GetCurrentDirectoryW(long ptr) -+@ stdcall GetCurrentPackageFamilyName(ptr ptr) -+@ stub GetCurrentPackageFullName - @ stdcall GetCurrentPackageId(ptr ptr) -+@ stub GetCurrentPackageInfo -+@ stub GetCurrentPackagePath - @ stdcall -norelay GetCurrentProcess() - @ stdcall -norelay GetCurrentProcessId() - @ stdcall GetCurrentProcessorNumber() ntdll.NtGetCurrentProcessorNumber -@@ -759,6 +769,16 @@ - @ stdcall GetOEMCP() - @ stdcall GetOverlappedResult(long ptr ptr long) - @ stdcall GetUserPreferredUILanguages(long ptr ptr ptr) -+@ stub GetPackageApplicationIds -+@ stub GetPackageFamilyName -+@ stub GetPackageFamilyNameFromToken -+@ stub GetPackageFullName -+@ stub GetPackageFullNameFromToken -+@ stub GetPackageId -+@ stub GetPackageInfo -+@ stub GetPackagePath -+@ stub GetPackagePathByFullName -+@ stub GetPackagesByPackageFamily - @ stdcall GetPhysicallyInstalledSystemMemory(ptr) - @ stdcall GetPriorityClass(long) - @ stdcall GetPrivateProfileIntA(str str long str) -@@ -805,6 +825,8 @@ - @ stub -i386 GetSLCallbackTemplate - @ stdcall GetShortPathNameA(str ptr long) - @ stdcall GetShortPathNameW(wstr ptr long) -+@ stub GetStagedPackageOrigin -+@ stub GetStagedPackagePathByFullName - @ stdcall GetStartupInfoA(ptr) - @ stdcall GetStartupInfoW(ptr) - @ stdcall GetStdHandle(long) -@@ -1118,6 +1140,8 @@ - @ stdcall OpenJobObjectW(long long wstr) - @ stdcall OpenMutexA(long long str) - @ stdcall OpenMutexW(long long wstr) -+@ stub OpenPackageInfoByFullName -+@ stub OpenPackageInfoByFullNameForUser - # @ stub OpenPrivateNamespaceA - # @ stub OpenPrivateNamespaceW - @ stdcall OpenProcess(long long long) -@@ -1132,6 +1156,12 @@ - @ stdcall OpenWaitableTimerW(long long wstr) - @ stdcall OutputDebugStringA(str) - @ stdcall OutputDebugStringW(wstr) -+@ stub PackageFamilyNameFromFullName -+@ stub PackageFamilyNameFromId -+@ stub PackageFullNameFromId -+@ stub PackageIdFromFullName -+@ stub PackageNameAndPublisherIdFromFamilyName -+@ stub ParseApplicationUserModelId - @ stdcall PeekConsoleInputA(ptr ptr long ptr) - @ stdcall PeekConsoleInputW(ptr ptr long ptr) - @ stdcall PeekNamedPipe(long ptr long ptr ptr ptr) -@@ -1548,7 +1578,12 @@ - @ stdcall VerLanguageNameA(long str long) - @ stdcall VerLanguageNameW(long wstr long) - @ stdcall -ret64 VerSetConditionMask(long long long long) ntdll.VerSetConditionMask -+@ stub VerifyApplicationUserModelId - @ stdcall VerifyConsoleIoHandle(long) -+@ stub VerifyPackageFamilyName -+@ stub VerifyPackageFullName -+@ stub VerifyPackageId -+@ stub VerifyPackageRelativeApplicationId - # @ stub VerifyScripts - @ stdcall VerifyVersionInfoA(long long int64) - @ stdcall VerifyVersionInfoW(long long int64) -diff --git a/dlls/kernel32/version.c b/dlls/kernel32/version.c -index b9d13e4..53f594e 100644 ---- a/dlls/kernel32/version.c -+++ b/dlls/kernel32/version.c -@@ -207,3 +207,12 @@ LONG WINAPI GetCurrentPackageId(UINT32 *len, BYTE *buffer) - FIXME("(%p %p): stub\n", len, buffer); - return APPMODEL_ERROR_NO_PACKAGE; - } -+ -+/*********************************************************************** -+ * GetCurrentPackageFamilyName (KERNEL32.@) -+ */ -+LONG WINAPI GetCurrentPackageFamilyName(UINT32 *length, PWSTR name) -+{ -+ FIXME("(%p %p): stub\n", length, name); -+ return APPMODEL_ERROR_NO_PACKAGE; -+} --- -2.9.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/0002-kernel32-add-stub-for-GetCurrentPackageFullName.patch wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/0002-kernel32-add-stub-for-GetCurrentPackageFullName.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/0002-kernel32-add-stub-for-GetCurrentPackageFullName.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/0002-kernel32-add-stub-for-GetCurrentPackageFullName.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -From bcbbde0daf2dd0fed6f41a455dae61b2aac6e376 Mon Sep 17 00:00:00 2001 -From: Louis Lenders -Date: Sat, 4 Mar 2017 11:05:52 +0100 -Subject: kernel32: add stub for GetCurrentPackageFullName - -See bug https://bugs.winehq.org/show_bug.cgi?id=42586 - -Signed-off-by: Louis Lenders ---- - .../api-ms-win-appmodel-runtime-l1-1-1.spec | 2 +- - dlls/kernel32/kernel32.spec | 2 +- - dlls/kernel32/version.c | 9 +++++++++ - 3 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec b/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec -index af7774d3679..50f8594785f 100644 ---- a/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec -+++ b/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec -@@ -4,7 +4,7 @@ - @ stub GetApplicationUserModelId - @ stub GetCurrentApplicationUserModelId - @ stdcall GetCurrentPackageFamilyName(ptr ptr) kernel32.GetCurrentPackageFamilyName --@ stub GetCurrentPackageFullName -+@ stdcall GetCurrentPackageFullName(ptr ptr) kernel32.GetCurrentPackageFullName - @ stdcall GetCurrentPackageId(ptr ptr) kernel32.GetCurrentPackageId - @ stub GetCurrentPackageInfo - @ stub GetCurrentPackagePath -diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec -index be514a32371..c240d1fb9ea 100644 ---- a/dlls/kernel32/kernel32.spec -+++ b/dlls/kernel32/kernel32.spec -@@ -635,7 +635,7 @@ - @ stdcall GetCurrentDirectoryA(long ptr) - @ stdcall GetCurrentDirectoryW(long ptr) - @ stdcall GetCurrentPackageFamilyName(ptr ptr) --@ stub GetCurrentPackageFullName -+@ stdcall GetCurrentPackageFullName(ptr ptr) - @ stdcall GetCurrentPackageId(ptr ptr) - @ stub GetCurrentPackageInfo - @ stub GetCurrentPackagePath -diff --git a/dlls/kernel32/version.c b/dlls/kernel32/version.c -index 53f594eccab..ddaccacbaa7 100644 ---- a/dlls/kernel32/version.c -+++ b/dlls/kernel32/version.c -@@ -216,3 +216,12 @@ LONG WINAPI GetCurrentPackageFamilyName(UINT32 *length, PWSTR name) - FIXME("(%p %p): stub\n", length, name); - return APPMODEL_ERROR_NO_PACKAGE; - } -+ -+/*********************************************************************** -+ * GetCurrentPackageFullName (KERNEL32.@) -+ */ -+LONG WINAPI GetCurrentPackageFullName(UINT32 *length, PWSTR name) -+{ -+ FIXME("(%p %p): stub\n", length, name); -+ return APPMODEL_ERROR_NO_PACKAGE; -+} --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/definition wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetCurrentPackageFamilyName/definition 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -Fixes: Add stub for kernel32.GetCurrentPackageFamilyName -Fixes: [42586] Add stub for kernel32.GetCurrentPackageFullName diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetPackageFullName/0001-kernel32-Add-stub-for-GetPackageFullName.patch wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetPackageFullName/0001-kernel32-Add-stub-for-GetPackageFullName.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetPackageFullName/0001-kernel32-Add-stub-for-GetPackageFullName.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetPackageFullName/0001-kernel32-Add-stub-for-GetPackageFullName.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,17 +1,17 @@ -From 21c71f172c52f18692e2601e40ae5e8d050de4a8 Mon Sep 17 00:00:00 2001 +From 594e57c855592fe07e73003926c09520bc357416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Thu, 2 Feb 2017 20:49:15 +0100 Subject: kernel32: Add stub for GetPackageFullName. --- .../api-ms-win-appmodel-runtime-l1-1-1.spec | 2 +- - dlls/kernel32/kernel32.spec | 2 +- + dlls/kernel32/kernel32.spec | 1 + dlls/kernel32/version.c | 9 +++++++++ dlls/kernelbase/kernelbase.spec | 2 +- - 4 files changed, 12 insertions(+), 3 deletions(-) + 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec b/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec -index af7774d3679..066a674f8f5 100644 +index 50f8594785f..4d2edd60f5a 100644 --- a/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec +++ b/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec @@ -10,7 +10,7 @@ @@ -24,23 +24,22 @@ @ stub GetPackageInfo @ stub GetPackagePath diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec -index 31811281e61..efb2bdddf32 100644 +index 2668386bf84..f2fcf109715 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec -@@ -772,7 +772,7 @@ - @ stub GetPackageApplicationIds - @ stub GetPackageFamilyName - @ stub GetPackageFamilyNameFromToken --@ stub GetPackageFullName +@@ -761,6 +761,7 @@ + @ stdcall GetOEMCP() + @ stdcall GetOverlappedResult(long ptr ptr long) + @ stdcall GetUserPreferredUILanguages(long ptr ptr ptr) +@ stdcall GetPackageFullName(long ptr ptr) - @ stub GetPackageFullNameFromToken - @ stub GetPackageId - @ stub GetPackageInfo + @ stdcall GetPhysicallyInstalledSystemMemory(ptr) + @ stdcall GetPriorityClass(long) + @ stdcall GetPrivateProfileIntA(str str long str) diff --git a/dlls/kernel32/version.c b/dlls/kernel32/version.c -index 53f594eccab..72d1152d20f 100644 +index 5a233efe56f..3cca2ae68ee 100644 --- a/dlls/kernel32/version.c +++ b/dlls/kernel32/version.c -@@ -216,3 +216,12 @@ LONG WINAPI GetCurrentPackageFamilyName(UINT32 *length, PWSTR name) +@@ -228,3 +228,12 @@ LONG WINAPI GetCurrentPackageFullName(UINT32 *length, PWSTR name) FIXME("(%p %p): stub\n", length, name); return APPMODEL_ERROR_NO_PACKAGE; } @@ -54,7 +53,7 @@ + return APPMODEL_ERROR_NO_PACKAGE; +} diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec -index a4951f1baa3..bdfc067cf6d 100644 +index 12f36c5ede3..daba198bec5 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -569,7 +569,7 @@ diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetPackageFullName/definition wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetPackageFullName/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-GetPackageFullName/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-GetPackageFullName/definition 2017-03-21 14:37:14.000000000 +0000 @@ -1,3 +1,2 @@ Fixes: Add stub for kernel32.GetPackageFullName -Depends: kernel32-GetCurrentPackageFamilyName Depends: api-ms-win-Stub_DLLs diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-Processor_Group/0001-kernel32-Implement-some-processor-group-functions.patch wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-Processor_Group/0001-kernel32-Implement-some-processor-group-functions.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/kernel32-Processor_Group/0001-kernel32-Implement-some-processor-group-functions.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/kernel32-Processor_Group/0001-kernel32-Implement-some-processor-group-functions.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From ea7ab1f3cb71ed5b80a0c67215b3470465f82f39 Mon Sep 17 00:00:00 2001 +From caf89ae3ed2f1ff8e2fb16cc1c80f101a2897722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sat, 4 Feb 2017 16:20:37 +0100 Subject: kernel32: Implement some processor group functions. @@ -88,10 +88,10 @@ + return system_info.NumberOfProcessors; +} diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec -index efb2bdddf32..8348621136f 100644 +index 2668386bf84..e6081aeb04a 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec -@@ -543,8 +543,8 @@ +@@ -540,8 +540,8 @@ @ stdcall GenerateConsoleCtrlEvent(long long) @ stdcall -i386 -private Get16DLLAddress(long str) krnl386.exe16.Get16DLLAddress @ stdcall GetACP() @@ -101,8 +101,8 @@ +@ stdcall GetActiveProcessorGroupCount() # @ stub GetApplicationRecoveryCallback # @ stub GetApplicationRestartSettings - @ stub GetApplicationUserModelId -@@ -724,8 +724,8 @@ + @ stdcall GetAtomNameA(long ptr long) +@@ -716,8 +716,8 @@ # @ stub GetLongPathNameTransactedW @ stdcall GetLongPathNameW (wstr long long) @ stdcall GetMailslotInfo(long ptr ptr ptr ptr) @@ -114,7 +114,7 @@ @ stdcall GetModuleFileNameW(long ptr long) @ stdcall GetModuleHandleA(str) diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c -index f66ab45b90e..b4370ca8922 100644 +index 68d6b648252..5e5346af749 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -91,6 +91,7 @@ static SIZE_T (WINAPI *pGetLargePageMinimum)(void); @@ -169,10 +169,10 @@ test_ProcThreadAttributeList(); diff --git a/include/winnt.h b/include/winnt.h -index 9e611c555a4..5cdd8a3a22f 100644 +index 5bd1b1b4a83..2fc4a190e48 100644 --- a/include/winnt.h +++ b/include/winnt.h -@@ -5873,6 +5873,8 @@ typedef struct _GROUP_AFFINITY +@@ -5855,6 +5855,8 @@ typedef struct _GROUP_AFFINITY WORD Reserved[3]; } GROUP_AFFINITY, *PGROUP_AFFINITY; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/msvcr120-_SetWinRTOutOfMemoryExceptionCallback/0001-msvcr120-Add-stub-for-_SetWinRTOutOfMemoryExceptionC.patch wine-staging-2.4.0~ubuntu16.04.1/patches/msvcr120-_SetWinRTOutOfMemoryExceptionCallback/0001-msvcr120-Add-stub-for-_SetWinRTOutOfMemoryExceptionC.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/msvcr120-_SetWinRTOutOfMemoryExceptionCallback/0001-msvcr120-Add-stub-for-_SetWinRTOutOfMemoryExceptionC.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/msvcr120-_SetWinRTOutOfMemoryExceptionCallback/0001-msvcr120-Add-stub-for-_SetWinRTOutOfMemoryExceptionC.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From e10eaddb1261c79cb80fc99172e1f53b1b7daf53 Mon Sep 17 00:00:00 2001 +From 0d26f0fea6b78f147597477a4a8a90ac82a1f4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Fri, 15 Jan 2016 12:58:17 +0100 Subject: msvcr120: Add stub for _SetWinRTOutOfMemoryExceptionCallback. @@ -10,7 +10,7 @@ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec -index 461b529..67c7fc4 100644 +index 84edf51369..139acab465 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -844,7 +844,7 @@ @@ -21,9 +21,9 @@ +@ cdecl -arch=i386,x86_64,arm _SetWinRTOutOfMemoryExceptionCallback(ptr) MSVCR120__SetWinRTOutOfMemoryExceptionCallback @ stub -arch=win64 _SetImageBase @ stub -arch=win64 _SetThrowImageBase - @ cdecl _Strftime(str long str ptr ptr) + @ cdecl _Strftime(ptr long str ptr ptr) diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec -index 425c839..ff71998 100644 +index 46a76da1c8..d9a1e46359 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -838,7 +838,7 @@ @@ -34,14 +34,14 @@ +@ cdecl -arch=i386,x86_64,arm _SetWinRTOutOfMemoryExceptionCallback(ptr) msvcr120._SetWinRTOutOfMemoryExceptionCallback @ stub -arch=win64 _SetImageBase @ stub -arch=win64 _SetThrowImageBase - @ cdecl _Strftime(str long str ptr ptr) msvcr120._Strftime + @ cdecl _Strftime(ptr long str ptr ptr) msvcr120._Strftime diff --git a/dlls/msvcrt/misc.c b/dlls/msvcrt/misc.c -index c1510ef..6842f1e 100644 +index 767972f893..fbbdfcf148 100644 --- a/dlls/msvcrt/misc.c +++ b/dlls/msvcrt/misc.c -@@ -506,3 +506,11 @@ void CDECL MSVCRT__crt_debugger_hook(int reserved) - { - WARN("(%x)\n", reserved); +@@ -542,3 +542,11 @@ LONG CDECL MSVCRT__crtUnhandledException(EXCEPTION_POINTERS *ep) + SetUnhandledExceptionFilter(NULL); + return UnhandledExceptionFilter(ep); } + +/********************************************************************* @@ -52,5 +52,5 @@ + FIXME("(%p): stub\n", callback); +} -- -2.6.4 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-FileAccessInformation/0001-ntdll-Implement-FileAccessInformation-class-in-NtQue.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-FileAccessInformation/0001-ntdll-Implement-FileAccessInformation-class-in-NtQue.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-FileAccessInformation/0001-ntdll-Implement-FileAccessInformation-class-in-NtQue.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-FileAccessInformation/0001-ntdll-Implement-FileAccessInformation-class-in-NtQue.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -From f9538d02d978180bbf563f14cf265b0eac8d71c5 Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Sun, 5 Mar 2017 21:48:27 +0100 -Subject: ntdll: Implement FileAccessInformation class in - NtQueryInformationFile. - ---- - dlls/ntdll/file.c | 13 +++++++++++++ - dlls/ntdll/tests/file.c | 24 ++++++++++++++++++++++++ - 2 files changed, 37 insertions(+) - -diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c -index 88ecb2a2f04..d92db6b7db9 100644 ---- a/dlls/ntdll/file.c -+++ b/dlls/ntdll/file.c -@@ -2852,6 +2852,19 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io, - info->EaSize = 0; - } - break; -+ case FileAccessInformation: -+ { -+ FILE_ACCESS_INFORMATION *info = ptr; -+ SERVER_START_REQ( get_object_info ) -+ { -+ req->handle = wine_server_obj_handle( hFile ); -+ io->u.Status = wine_server_call( req ); -+ if (io->u.Status == STATUS_SUCCESS) -+ info->AccessFlags = reply->access; -+ } -+ SERVER_END_REQ; -+ } -+ break; - case FileEndOfFileInformation: - if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus(); - else fill_file_info( &st, attr, ptr, class ); -diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 9cbbdba55e0..05c5454871c 100644 ---- a/dlls/ntdll/tests/file.c -+++ b/dlls/ntdll/tests/file.c -@@ -3509,6 +3509,29 @@ static void test_file_id_information(void) - CloseHandle( h ); - } - -+static void test_file_access_information(void) -+{ -+ FILE_ACCESS_INFORMATION info; -+ IO_STATUS_BLOCK io; -+ NTSTATUS status; -+ HANDLE h; -+ -+ if (!(h = create_temp_file(0))) return; -+ -+ status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAccessInformation ); -+ ok( status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status ); -+ -+ status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAccessInformation ); -+ ok( status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status ); -+ -+ memset(&info, 0x11, sizeof(info)); -+ status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAccessInformation ); -+ ok( status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status ); -+ ok( info.AccessFlags == 0x13019f, "got %08x\n", info.AccessFlags ); -+ -+ CloseHandle( h ); -+} -+ - static void test_query_volume_information_file(void) - { - NTSTATUS status; -@@ -4912,6 +4935,7 @@ START_TEST(file) - test_file_disposition_information(); - test_file_completion_information(); - test_file_id_information(); -+ test_file_access_information(); - test_query_volume_information_file(); - test_query_attribute_information_file(); - test_ioctl(); --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-FileAccessInformation/definition wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-FileAccessInformation/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-FileAccessInformation/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-FileAccessInformation/definition 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Fixes: [42550] Implement FileAccessInformation class diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-Hide_Wine_Exports/0001-ntdll-Add-support-for-hiding-wine-version-informatio.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-Hide_Wine_Exports/0001-ntdll-Add-support-for-hiding-wine-version-informatio.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-Hide_Wine_Exports/0001-ntdll-Add-support-for-hiding-wine-version-informatio.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-Hide_Wine_Exports/0001-ntdll-Add-support-for-hiding-wine-version-informatio.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From d804ddb4f49172915b88eb048cfe532a96eb41df Mon Sep 17 00:00:00 2001 +From 41a15135b0c1894724c1c91311faa255ad96d732 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sat, 30 May 2015 02:23:15 +0200 Subject: ntdll: Add support for hiding wine version information from @@ -10,7 +10,7 @@ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index 130d154..d84e156 100644 +index b95b8852aa..1c0ba6161d 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -63,9 +63,12 @@ WINE_DECLARE_DEBUG_CHANNEL(pid); @@ -26,7 +26,7 @@ static const char * const reason_names[] = { -@@ -1543,6 +1546,96 @@ NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG_PTR magic ) +@@ -1456,6 +1459,96 @@ NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG_PTR magic ) } @@ -123,7 +123,7 @@ /****************************************************************** * LdrGetProcedureAddress (NTDLL.@) */ -@@ -1563,7 +1656,7 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, +@@ -1476,7 +1569,7 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, LPCWSTR load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer; void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, load_path ) : find_ordinal_export( module, exports, exp_size, ord - exports->Base, load_path ); @@ -132,7 +132,7 @@ { *address = proc; ret = STATUS_SUCCESS; -@@ -3198,6 +3291,7 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2, +@@ -3099,6 +3192,7 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2, if (!peb->ProcessParameters->WindowTitle.Buffer) peb->ProcessParameters->WindowTitle = wm->ldr.FullDllName; version_init( wm->ldr.FullDllName.Buffer ); @@ -141,10 +141,10 @@ LdrQueryImageFileExecutionOptions( &peb->ProcessParameters->ImagePathName, globalflagW, diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index 5e4c39e..723c3d8 100644 +index 443c86000d..ba4adff249 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h -@@ -266,4 +266,9 @@ extern HANDLE keyed_event DECLSPEC_HIDDEN; +@@ -266,6 +266,11 @@ extern HANDLE keyed_event DECLSPEC_HIDDEN; NTSTATUS WINAPI RtlHashUnicodeString(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*); @@ -153,7 +153,9 @@ +extern const char * CDECL NTDLL_wine_get_build_id(void); +extern void CDECL NTDLL_wine_get_host_version( const char **sysname, const char **release ); + - #endif + /* process / thread time */ + extern BOOL read_process_time(int unix_pid, int unix_tid, unsigned long clk_tck, + LARGE_INTEGER *kernel, LARGE_INTEGER *user) DECLSPEC_HIDDEN; -- -2.8.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-Hide_Wine_Exports/definition wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-Hide_Wine_Exports/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-Hide_Wine_Exports/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-Hide_Wine_Exports/definition 2017-03-21 14:37:14.000000000 +0000 @@ -1,2 +1,3 @@ Fixes: [38656] Add support for hiding wine version information from applications Depends: ntdll-Attach_Process_DLLs +Depends: ntdll-ThreadTime diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-Interrupt-0x2e/0001-ntdll-Catch-windows-int-0x2e-syscall-on-i386.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-Interrupt-0x2e/0001-ntdll-Catch-windows-int-0x2e-syscall-on-i386.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-Interrupt-0x2e/0001-ntdll-Catch-windows-int-0x2e-syscall-on-i386.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-Interrupt-0x2e/0001-ntdll-Catch-windows-int-0x2e-syscall-on-i386.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,56 @@ +From 40f4e264b0c957eafe187bc0de597c3aa18dc6be Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sun, 19 Mar 2017 19:08:34 +0100 +Subject: ntdll: Catch windows int 0x2e syscall on i386. + +--- + dlls/ntdll/signal_i386.c | 13 +++++++++++++ + include/wine/exception.h | 1 + + 2 files changed, 14 insertions(+) + +diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c +index d76fe95dfa..93d9418527 100644 +--- a/dlls/ntdll/signal_i386.c ++++ b/dlls/ntdll/signal_i386.c +@@ -1572,6 +1572,14 @@ static inline BOOL handle_interrupt( unsigned int interrupt, EXCEPTION_RECORD *r + rec->ExceptionInformation[1] = context->Ecx; + rec->ExceptionInformation[2] = context->Edx; + return TRUE; ++ case 0x2e: ++ context->Eip += 2; ++ rec->ExceptionCode = EXCEPTION_WINE_SYSCALL; ++ rec->ExceptionAddress = (void *)context->Eip; ++ rec->NumberParameters = 2; ++ rec->ExceptionInformation[0] = context->Eax; ++ rec->ExceptionInformation[1] = context->Edx; ++ return TRUE; + default: + return FALSE; + } +@@ -1953,6 +1961,11 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context + } + } + break; ++ case EXCEPTION_WINE_SYSCALL: ++ FIXME("unimplemented syscall handler for 0x%lx, stack 0x%lx\n", ++ rec->ExceptionInformation[0], rec->ExceptionInformation[1]); ++ context->Eax = STATUS_INVALID_SYSTEM_SERVICE; ++ goto done; + } + status = NtRaiseException( rec, context, TRUE ); + raise_status( status, rec ); +diff --git a/include/wine/exception.h b/include/wine/exception.h +index f275568f4d..b8aeb3b866 100644 +--- a/include/wine/exception.h ++++ b/include/wine/exception.h +@@ -259,6 +259,7 @@ static inline EXCEPTION_REGISTRATION_RECORD *__wine_get_frame(void) + + #define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */ + #define EXCEPTION_WINE_ASSERTION 0x80000101 /* assertion failed */ ++#define EXCEPTION_WINE_SYSCALL 0x80000103 + + /* unhandled return status from vm86 mode */ + #define EXCEPTION_VM86_INTx 0x80000110 +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-Interrupt-0x2e/definition wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-Interrupt-0x2e/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-Interrupt-0x2e/definition 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-Interrupt-0x2e/definition 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1 @@ +Fixes: [42647] Implement stub handler for int 0x2e diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-LdrEnumerateLoadedModules/0001-ntdll-Implement-LdrEnumerateLoadedModules.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-LdrEnumerateLoadedModules/0001-ntdll-Implement-LdrEnumerateLoadedModules.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-LdrEnumerateLoadedModules/0001-ntdll-Implement-LdrEnumerateLoadedModules.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-LdrEnumerateLoadedModules/0001-ntdll-Implement-LdrEnumerateLoadedModules.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From eafb8e1b84a5ee717d5b0e22686303494fc5ccd3 Mon Sep 17 00:00:00 2001 +From 7221933818afc91b76f6b12ead544570d8ff336a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Fri, 3 Feb 2017 00:05:10 +0100 Subject: ntdll: Implement LdrEnumerateLoadedModules. @@ -10,10 +10,10 @@ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index c0703f008a7..15acf0e197d 100644 +index cf758505a4c..0b507da9a08 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c -@@ -1523,6 +1523,37 @@ NTSTATUS WINAPI LdrFindEntryForAddress(const void* addr, PLDR_MODULE* pmod) +@@ -1393,6 +1393,37 @@ NTSTATUS WINAPI LdrFindEntryForAddress(const void* addr, PLDR_MODULE* pmod) return STATUS_NO_MORE_ENTRIES; } @@ -52,10 +52,10 @@ * LdrLockLoaderLock (NTDLL.@) * diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 81767ede7d7..9921b4cb1cc 100644 +index b4269a679fc..66ecb7d0f37 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -63,7 +63,7 @@ +@@ -62,7 +62,7 @@ # @ stub LdrDestroyOutOfProcessImage @ stdcall LdrDisableThreadCalloutsForDll(long) @ stub LdrEnumResources @@ -65,10 +65,10 @@ @ stdcall LdrFindEntryForAddress(ptr ptr) @ stdcall LdrFindResourceDirectory_U(long ptr long ptr) diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c -index d96ced64cb0..cfff3f5ec49 100644 +index 940c44a05bd..873437e7f4b 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c -@@ -111,6 +111,7 @@ static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *); +@@ -102,6 +102,7 @@ static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *); static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION *); static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG); static NTSTATUS (WINAPI *pRtlQueryPackageIdentity)(HANDLE, WCHAR*, SIZE_T*, WCHAR*, SIZE_T*, BOOLEAN*); @@ -76,7 +76,7 @@ static HMODULE hkernel32 = 0; static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); -@@ -173,6 +174,7 @@ static void InitFunctionPtrs(void) +@@ -156,6 +157,7 @@ static void InitFunctionPtrs(void) pRtlIsCriticalSectionLockedByThread = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLockedByThread"); pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx"); pRtlQueryPackageIdentity = (void *)GetProcAddress(hntdll, "RtlQueryPackageIdentity"); @@ -84,7 +84,7 @@ } hkernel32 = LoadLibraryA("kernel32.dll"); ok(hkernel32 != 0, "LoadLibrary failed\n"); -@@ -3230,6 +3232,57 @@ done: +@@ -2228,6 +2230,57 @@ done: CoUninitialize(); } @@ -142,9 +142,9 @@ START_TEST(rtl) { InitFunctionPtrs(); -@@ -3267,4 +3320,5 @@ START_TEST(rtl) - test_RtlIsCriticalSectionLocked(); +@@ -2261,4 +2314,5 @@ START_TEST(rtl) test_RtlInitializeCriticalSectionEx(); + test_RtlLeaveCriticalSection(); test_RtlQueryPackageIdentity(); + test_LdrEnumerateLoadedModules(); } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-LDR_MODULE/0001-ntdll-Mark-LDR-data-as-initialized.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-LDR_MODULE/0001-ntdll-Mark-LDR-data-as-initialized.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-LDR_MODULE/0001-ntdll-Mark-LDR-data-as-initialized.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-LDR_MODULE/0001-ntdll-Mark-LDR-data-as-initialized.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,24 @@ +From f30fb4fe4ef931b592f1a7edcc3609b9819158ff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 7 Mar 2017 04:59:41 +0100 +Subject: ntdll: Mark LDR data as initialized. + +--- + dlls/ntdll/thread.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c +index c9a5da6226..0506f6bc10 100644 +--- a/dlls/ntdll/thread.c ++++ b/dlls/ntdll/thread.c +@@ -259,6 +259,7 @@ HANDLE thread_init(void) + params.CurrentDirectory.DosPath.MaximumLength = sizeof(current_dir); + params.wShowWindow = 1; /* SW_SHOWNORMAL */ + ldr.Length = sizeof(ldr); ++ ldr.Initialized = TRUE; + RtlInitializeBitMap( &tls_bitmap, peb->TlsBitmapBits, sizeof(peb->TlsBitmapBits) * 8 ); + RtlInitializeBitMap( &tls_expansion_bitmap, peb->TlsExpansionBitmapBits, + sizeof(peb->TlsExpansionBitmapBits) * 8 ); +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-LDR_MODULE/0002-include-Update-LDR_MODULE-to-more-recent-windows-ver.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-LDR_MODULE/0002-include-Update-LDR_MODULE-to-more-recent-windows-ver.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-LDR_MODULE/0002-include-Update-LDR_MODULE-to-more-recent-windows-ver.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-LDR_MODULE/0002-include-Update-LDR_MODULE-to-more-recent-windows-ver.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,30 @@ +From 4b74342ce0dd261a93f5a2d30140078696b5a46d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 7 Mar 2017 15:26:50 +0100 +Subject: include: Update LDR_MODULE to more recent windows versions. + +--- + include/winternl.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/include/winternl.h b/include/winternl.h +index 5cd1664f1f..ef9a5bad1c 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -2103,6 +2103,13 @@ typedef struct _LDR_MODULE + ULONG CheckSum; + ULONG TimeDateStamp; + HANDLE ActivationContext; ++ PVOID PatchInformation; ++ LIST_ENTRY ForwarderLinks; ++ LIST_ENTRY ServiceTagLinks; ++ LIST_ENTRY StaticLinks; ++ PVOID ContextInformation; ++ ULONG_PTR OriginalBase; ++ LARGE_INTEGER LoadTime; + } LDR_MODULE, *PLDR_MODULE; + + /* those defines are (some of the) regular LDR_MODULE.Flags values */ +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-NtQueryVirtualMemory/0003-ntdll-Fix-error-code-when-querying-too-large-memory-.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-NtQueryVirtualMemory/0003-ntdll-Fix-error-code-when-querying-too-large-memory-.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-NtQueryVirtualMemory/0003-ntdll-Fix-error-code-when-querying-too-large-memory-.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-NtQueryVirtualMemory/0003-ntdll-Fix-error-code-when-querying-too-large-memory-.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,65 @@ +From 103ff9d293f7ffd9a96fb8801057ecc781352efc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 7 Mar 2017 04:58:57 +0100 +Subject: ntdll: Fix error code when querying too large memory address. + +--- + dlls/ntdll/tests/info.c | 23 +++++++++++++++++++++++ + dlls/ntdll/virtual.c | 2 +- + 2 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c +index 448bc64c28..407d230cfd 100644 +--- a/dlls/ntdll/tests/info.c ++++ b/dlls/ntdll/tests/info.c +@@ -2013,6 +2013,26 @@ static void test_query_data_alignment(void) + ok(value == 64, "Expected 64, got %u\n", value); + } + ++static void test_working_set_limit(void) ++{ ++ DWORD_PTR lower = 0, upper = ~(DWORD_PTR)0; ++ MEMORY_BASIC_INFORMATION mbi; ++ SIZE_T readcount; ++ NTSTATUS status; ++ ++ while (lower != upper) ++ { ++ DWORD_PTR check = (lower >> 1) + (upper >> 1) + (lower & upper & 1); ++ status = pNtQueryVirtualMemory(NtCurrentProcess(), (void *)check, MemoryBasicInformation, ++ &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount); ++ if (status == STATUS_INVALID_PARAMETER) upper = check; ++ else lower = check + 1; ++ } ++ ++ trace("working set limit is %p\n", (void *)upper); ++ ok(upper != ~(DWORD_PTR)0, "expected != ~(DWORD_PTR)0\n"); ++} ++ + START_TEST(info) + { + char **argv; +@@ -2148,4 +2168,7 @@ START_TEST(info) + + trace("Starting test_query_data_alignment()\n"); + test_query_data_alignment(); ++ ++ trace("Starting test_working_set_limit()\n"); ++ test_working_set_limit(); + } +diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c +index e826fa03c0..a6297115fe 100644 +--- a/dlls/ntdll/virtual.c ++++ b/dlls/ntdll/virtual.c +@@ -2306,7 +2306,7 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr, + + base = ROUND_ADDR( addr, page_mask ); + +- if (is_beyond_limit( base, 1, working_set_limit )) return STATUS_WORKING_SET_LIMIT_RANGE; ++ if (is_beyond_limit( base, 1, working_set_limit )) return STATUS_INVALID_PARAMETER; + + /* Find the view containing the address */ + +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ProcessImageFileNameWin32/0001-ntdll-Implement-ProcessImageFileNameWin32-in-NtQuery.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ProcessImageFileNameWin32/0001-ntdll-Implement-ProcessImageFileNameWin32-in-NtQuery.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ProcessImageFileNameWin32/0001-ntdll-Implement-ProcessImageFileNameWin32-in-NtQuery.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ProcessImageFileNameWin32/0001-ntdll-Implement-ProcessImageFileNameWin32-in-NtQuery.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,53 @@ +From 02c1bbeb9c610518d282c65aaa6f9563c3d80b73 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 7 Mar 2017 01:57:42 +0100 +Subject: ntdll: Implement ProcessImageFileNameWin32 in + NtQueryInformationProcess. + +--- + dlls/ntdll/process.c | 1 + + include/winternl.h | 16 ++++++++++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c +index a14b6707167..39cd8be6019 100644 +--- a/dlls/ntdll/process.c ++++ b/dlls/ntdll/process.c +@@ -498,6 +498,7 @@ NTSTATUS WINAPI NtQueryInformationProcess( + case ProcessImageFileName: + /* FIXME: this will return a DOS path. Windows returns an NT path. Changing this would require also changing kernel32.QueryFullProcessImageName. + * The latter may be harder because of the lack of RtlNtPathNameToDosPathName. */ ++ case ProcessImageFileNameWin32: + SERVER_START_REQ(get_dll_info) + { + UNICODE_STRING *image_file_name_str = ProcessInformation; +diff --git a/include/winternl.h b/include/winternl.h +index 8acb7fd3e11..4a137f42b49 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -829,6 +829,22 @@ typedef enum _PROCESSINFOCLASS { + ProcessDebugFlags = 31, + ProcessHandleTracing = 32, + ProcessExecuteFlags = 34, ++ ProcessTlsInformation = 35, ++ ProcessCookie = 36, ++ ProcessImageInformation = 37, ++ ProcessCycleTime = 38, ++ ProcessPagePriority = 39, ++ ProcessInstrumentationCallback = 40, ++ ProcessThreadStackAllocation = 41, ++ ProcessWorkingSetWatchEx = 42, ++ ProcessImageFileNameWin32 = 43, ++ ProcessImageFileMapping = 44, ++ ProcessAffinityUpdateMode = 45, ++ ProcessMemoryAllocationMode = 46, ++ ProcessGroupInformation = 47, ++ ProcessTokenVirtualizationEnabled = 48, ++ ProcessConsoleHostProcess = 49, ++ ProcessWindowInformation = 50, + MaxProcessInfoClass + } PROCESSINFOCLASS, PROCESS_INFORMATION_CLASS; + +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ProcessImageFileNameWin32/definition wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ProcessImageFileNameWin32/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ProcessImageFileNameWin32/definition 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ProcessImageFileNameWin32/definition 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1 @@ +Fixes: Implement ProcessImageFileNameWin32 info class diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-raise_func_trampoline/0001-ntdll-Save-rdi-and-rsi-in-raise_func_trampoline.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-raise_func_trampoline/0001-ntdll-Save-rdi-and-rsi-in-raise_func_trampoline.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-raise_func_trampoline/0001-ntdll-Save-rdi-and-rsi-in-raise_func_trampoline.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-raise_func_trampoline/0001-ntdll-Save-rdi-and-rsi-in-raise_func_trampoline.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -From 7a4b334d01cc105418fb29baa6662ab566c06a42 Mon Sep 17 00:00:00 2001 -From: Andrew Wesie -Date: Sun, 12 Feb 2017 16:41:22 -0600 -Subject: ntdll: Save rdi and rsi in raise_func_trampoline. - -On Windows, RDI and RSI are callee-saved registers, but on Linux -they are caller-saved registers. As such, raise_func_trampoline -needs to explicitly unwind them. - -Signed-off-by: Andrew Wesie ---- - dlls/ntdll/signal_x86_64.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c -index f33fe4cbfd6..61bb2ddce6f 100644 ---- a/dlls/ntdll/signal_x86_64.c -+++ b/dlls/ntdll/signal_x86_64.c -@@ -2066,9 +2066,11 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) - extern void raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func ); - __ASM_GLOBAL_FUNC( raise_func_trampoline, - __ASM_CFI(".cfi_signal_frame\n\t") -- __ASM_CFI(".cfi_def_cfa %rbp,144\n\t") /* red zone + rip + rbp */ -- __ASM_CFI(".cfi_rel_offset %rip,8\n\t") -- __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") -+ __ASM_CFI(".cfi_def_cfa %rbp,160\n\t") /* red zone + rip + rbp + rdi + rsi */ -+ __ASM_CFI(".cfi_rel_offset %rip,24\n\t") -+ __ASM_CFI(".cfi_rel_offset %rbp,16\n\t") -+ __ASM_CFI(".cfi_rel_offset %rdi,8\n\t") -+ __ASM_CFI(".cfi_rel_offset %rsi,0\n\t") - "call *%rdx\n\t" - "int $3") - -@@ -2085,6 +2087,8 @@ static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func fun - { - CONTEXT context; - EXCEPTION_RECORD rec; -+ ULONG64 rsi; -+ ULONG64 rdi; - ULONG64 rbp; - ULONG64 rip; - ULONG64 red_zone[16]; -@@ -2154,6 +2158,8 @@ static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func fun - rsp_ptr = (ULONG64 *)RSP_sig(sigcontext) - 16; - *(--rsp_ptr) = RIP_sig(sigcontext); - *(--rsp_ptr) = RBP_sig(sigcontext); -+ *(--rsp_ptr) = RDI_sig(sigcontext); -+ *(--rsp_ptr) = RSI_sig(sigcontext); - - /* now modify the sigcontext to return to the raise function */ - RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-raise_func_trampoline/definition wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-raise_func_trampoline/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-raise_func_trampoline/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-raise_func_trampoline/definition 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Fixes: Save rdi and rsi in raise_func_trampoline on x86_64 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-RtlQueryPackageIdentity/0003-ntdll-tests-Add-basic-tests-for-RtlQueryPackageIdent.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-RtlQueryPackageIdentity/0003-ntdll-tests-Add-basic-tests-for-RtlQueryPackageIdent.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-RtlQueryPackageIdentity/0003-ntdll-tests-Add-basic-tests-for-RtlQueryPackageIdent.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-RtlQueryPackageIdentity/0003-ntdll-tests-Add-basic-tests-for-RtlQueryPackageIdent.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 733ae7526f2498282b42254b867e5c2d278b379a Mon Sep 17 00:00:00 2001 +From 1ad505d34d229476373ba4f3422934f0440f2fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sun, 17 Jan 2016 00:50:50 +0100 Subject: ntdll/tests: Add basic tests for RtlQueryPackageIdentity. @@ -9,7 +9,7 @@ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in -index fc352dd..0de4fe8 100644 +index fc352dd22be..0de4fe8f207 100644 --- a/dlls/ntdll/tests/Makefile.in +++ b/dlls/ntdll/tests/Makefile.in @@ -1,5 +1,5 @@ @@ -20,7 +20,7 @@ C_SRCS = \ atom.c \ diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c -index 1b17a7e..95b58c3 100644 +index b18cccf4f35..940c44a05bd 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -25,6 +25,9 @@ @@ -33,7 +33,7 @@ #ifndef __WINE_WINTERNL_H -@@ -99,6 +102,7 @@ static NTSTATUS (WINAPI *pRtlCompressBuffer)(USHORT, const UCHAR*, ULONG, PUCHA +@@ -98,6 +101,7 @@ static NTSTATUS (WINAPI *pRtlCompressBuffer)(USHORT, const UCHAR*, ULONG, PUCHA static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *); static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION *); static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG); @@ -41,7 +41,7 @@ static HMODULE hkernel32 = 0; static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); -@@ -153,6 +157,7 @@ static void InitFunctionPtrs(void) +@@ -151,6 +155,7 @@ static void InitFunctionPtrs(void) pRtlIsCriticalSectionLocked = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLocked"); pRtlIsCriticalSectionLockedByThread = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLockedByThread"); pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx"); @@ -49,8 +49,8 @@ } hkernel32 = LoadLibraryA("kernel32.dll"); ok(hkernel32 != 0, "LoadLibrary failed\n"); -@@ -2091,6 +2096,76 @@ static void test_RtlInitializeCriticalSectionEx(void) - RtlDeleteCriticalSection(&cs); +@@ -2153,6 +2158,76 @@ static void test_RtlLeaveCriticalSection(void) + ok(!status, "RtlDeleteCriticalSection failed: %x\n", status); } +static void test_RtlQueryPackageIdentity(void) @@ -126,12 +126,12 @@ START_TEST(rtl) { InitFunctionPtrs(); -@@ -2122,4 +2197,5 @@ START_TEST(rtl) - test_RtlDecompressBuffer(); +@@ -2185,4 +2260,5 @@ START_TEST(rtl) test_RtlIsCriticalSectionLocked(); test_RtlInitializeCriticalSectionEx(); + test_RtlLeaveCriticalSection(); + test_RtlQueryPackageIdentity(); } -- -2.7.1 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0002-ntdll-Set-correct-thread-creation-time-for-SystemPro.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0002-ntdll-Set-correct-thread-creation-time-for-SystemPro.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0002-ntdll-Set-correct-thread-creation-time-for-SystemPro.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0002-ntdll-Set-correct-thread-creation-time-for-SystemPro.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,74 @@ +From e6832d1b0f923e7589424ade7571cc67dc768c4d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 9 Mar 2017 00:00:46 +0100 +Subject: ntdll: Set correct thread creation time for SystemProcessInformation + in NtQuerySystemInformation. + +--- + dlls/ntdll/nt.c | 2 +- + server/protocol.def | 1 + + server/snapshot.c | 11 ++++++----- + server/thread.h | 1 + + 4 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index 86beb031e9c..fc8e3b1eb4e 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -2012,7 +2012,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + + memset(&spi->ti[i], 0, sizeof(spi->ti)); + +- spi->ti[i].CreateTime.QuadPart = 0xdeadbeef; ++ spi->ti[i].CreateTime.QuadPart = reply->creation_time; + spi->ti[i].ClientId.UniqueProcess = UlongToHandle(reply->pid); + spi->ti[i].ClientId.UniqueThread = UlongToHandle(reply->tid); + spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri; +diff --git a/server/protocol.def b/server/protocol.def +index 60865a6ffc2..15adc51462f 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -1783,6 +1783,7 @@ enum char_info_mode + int count; /* thread usage count */ + process_id_t pid; /* process id */ + thread_id_t tid; /* thread id */ ++ timeout_t creation_time; /* thread creation time */ + int base_pri; /* base priority */ + int delta_pri; /* delta priority */ + @END +diff --git a/server/snapshot.c b/server/snapshot.c +index e35588a136c..858fca898a7 100644 +--- a/server/snapshot.c ++++ b/server/snapshot.c +@@ -144,11 +144,12 @@ static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_r + return 0; + } + ptr = &snapshot->threads[snapshot->thread_pos++]; +- reply->count = ptr->count; +- reply->pid = get_process_id( ptr->thread->process ); +- reply->tid = get_thread_id( ptr->thread ); +- reply->base_pri = ptr->priority; +- reply->delta_pri = 0; /* FIXME */ ++ reply->count = ptr->count; ++ reply->pid = get_process_id( ptr->thread->process ); ++ reply->tid = get_thread_id( ptr->thread ); ++ reply->creation_time = get_thread_creation_time( ptr->thread ); ++ reply->base_pri = ptr->priority; ++ reply->delta_pri = 0; /* FIXME */ + return 1; + } + +diff --git a/server/thread.h b/server/thread.h +index 282199149e6..2098c76a472 100644 +--- a/server/thread.h ++++ b/server/thread.h +@@ -145,5 +145,6 @@ static inline void clear_error(void) { set_error(0); } + static inline void set_win32_error( unsigned int err ) { set_error( 0xc0010000 | err ); } + + static inline thread_id_t get_thread_id( struct thread *thread ) { return thread->id; } ++static inline timeout_t get_thread_creation_time( struct thread *thread ) { return thread->creation_time; } + + #endif /* __WINE_SERVER_THREAD_H */ +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0003-ntdll-Fill-process-kernel-and-user-time.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0003-ntdll-Fill-process-kernel-and-user-time.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0003-ntdll-Fill-process-kernel-and-user-time.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0003-ntdll-Fill-process-kernel-and-user-time.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,159 @@ +From 2578dfb02f0a8781970f5c7d967b1d07ae433e2f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 9 Mar 2017 16:27:23 +0100 +Subject: ntdll: Fill process kernel and user time. + +--- + dlls/ntdll/nt.c | 6 +++- + dlls/ntdll/ntdll_misc.h | 3 ++ + dlls/ntdll/thread.c | 84 ++++++++++++++++++++++++++++--------------------- + 3 files changed, 56 insertions(+), 37 deletions(-) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index fc8e3b1eb4..6b67397471 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -1922,6 +1922,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + { + SYSTEM_PROCESS_INFORMATION* spi = SystemInformation; + SYSTEM_PROCESS_INFORMATION* last = NULL; ++ unsigned long clk_tck = sysconf(_SC_CLK_TCK); + HANDLE hSnap = 0; + WCHAR procname[1024]; + WCHAR* exename; +@@ -1959,7 +1960,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + + if (Length >= len + procstructlen) + { +- /* ftCreationTime, ftUserTime, ftKernelTime; ++ /* ftCreationTime; + * vmCounters, ioCounters + */ + +@@ -1977,6 +1978,9 @@ NTSTATUS WINAPI NtQuerySystemInformation( + + /* spi->ti will be set later on */ + ++ if (reply->unix_pid != -1) ++ read_process_time(reply->unix_pid, -1, clk_tck, ++ &spi->KernelTime, &spi->UserTime); + } + len += procstructlen; + } +diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h +index 5e4c39e8bd..443c86000d 100644 +--- a/dlls/ntdll/ntdll_misc.h ++++ b/dlls/ntdll/ntdll_misc.h +@@ -266,4 +266,7 @@ extern HANDLE keyed_event DECLSPEC_HIDDEN; + + NTSTATUS WINAPI RtlHashUnicodeString(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*); + ++/* process / thread time */ ++extern BOOL read_process_time(int unix_pid, int unix_tid, unsigned long clk_tck, ++ LARGE_INTEGER *kernel, LARGE_INTEGER *user) DECLSPEC_HIDDEN; + #endif +diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c +index 91a59517b3..29b6513f38 100644 +--- a/dlls/ntdll/thread.c ++++ b/dlls/ntdll/thread.c +@@ -71,6 +71,53 @@ static RTL_BITMAP tls_expansion_bitmap; + static RTL_BITMAP fls_bitmap; + static int nb_threads = 1; + ++ ++BOOL read_process_time(int unix_pid, int unix_tid, unsigned long clk_tck, ++ LARGE_INTEGER *kernel, LARGE_INTEGER *user) ++{ ++#ifdef __linux__ ++ unsigned long usr, sys; ++ char buf[512], *pos; ++ FILE *fp; ++ int i; ++ ++ /* based on https://github.com/torvalds/linux/blob/master/fs/proc/array.c */ ++ if (unix_tid != -1) ++ sprintf( buf, "/proc/%u/task/%u/stat", unix_pid, unix_tid ); ++ else ++ sprintf( buf, "/proc/%u/stat", unix_pid ); ++ if ((fp = fopen( buf, "r" ))) ++ { ++ pos = fgets( buf, sizeof(buf), fp ); ++ fclose( fp ); ++ ++ /* format of first chunk is "%d (%s) %c" - we have to skip to the last ')' ++ * to avoid misinterpreting the string. */ ++ if (pos) pos = strrchr( pos, ')' ); ++ if (pos) pos = strchr( pos + 1, ' ' ); ++ if (pos) pos++; ++ ++ /* skip over the following fields: state, ppid, pgid, sid, tty_nr, tty_pgrp, ++ * task->flags, min_flt, cmin_flt, maj_flt, cmaj_flt */ ++ for (i = 0; (i < 11) && pos; i++) ++ { ++ pos = strchr( pos + 1, ' ' ); ++ if (pos) pos++; ++ } ++ ++ /* the next two values are user and system time */ ++ if (pos && (sscanf( pos, "%lu %lu", &usr, &sys ) == 2)) ++ { ++ kernel->QuadPart = (ULONGLONG)sys * 10000000 / clk_tck; ++ user->QuadPart = (ULONGLONG)usr * 10000000 / clk_tck; ++ return TRUE; ++ } ++ } ++#endif ++ return FALSE; ++} ++ ++ + /*********************************************************************** + * get_unicode_string + * +@@ -1009,42 +1056,7 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class, + #ifdef __linux__ + /* only /proc provides exact values for a specific thread */ + if (unix_pid != -1 && unix_tid != -1) +- { +- unsigned long usr, sys; +- char buf[512], *pos; +- FILE *fp; +- int i; +- +- /* based on https://github.com/torvalds/linux/blob/master/fs/proc/array.c */ +- sprintf( buf, "/proc/%u/task/%u/stat", unix_pid, unix_tid ); +- if ((fp = fopen( buf, "r" ))) +- { +- pos = fgets( buf, sizeof(buf), fp ); +- fclose( fp ); +- +- /* format of first chunk is "%d (%s) %c" - we have to skip to the last ')' +- * to avoid misinterpreting the string. */ +- if (pos) pos = strrchr( pos, ')' ); +- if (pos) pos = strchr( pos + 1, ' ' ); +- if (pos) pos++; +- +- /* skip over the following fields: state, ppid, pgid, sid, tty_nr, tty_pgrp, +- * task->flags, min_flt, cmin_flt, maj_flt, cmaj_flt */ +- for (i = 0; (i < 11) && pos; i++) +- { +- pos = strchr( pos + 1, ' ' ); +- if (pos) pos++; +- } +- +- /* the next two values are user and system time */ +- if (pos && (sscanf( pos, "%lu %lu", &usr, &sys ) == 2)) +- { +- kusrt.KernelTime.QuadPart = (ULONGLONG)sys * 10000000 / clk_tck; +- kusrt.UserTime.QuadPart = (ULONGLONG)usr * 10000000 / clk_tck; +- filled_times = TRUE; +- } +- } +- } ++ filled_times = read_process_time(unix_pid, unix_tid, clk_tck, &kusrt.KernelTime, &kusrt.UserTime); + #endif + + /* get values for current process instead */ +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0004-ntdll-Set-process-start-time.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0004-ntdll-Set-process-start-time.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0004-ntdll-Set-process-start-time.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0004-ntdll-Set-process-start-time.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,64 @@ +From e048ad0cd3879fb8f752af7e2eeda770864f9982 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 9 Mar 2017 16:32:59 +0100 +Subject: ntdll: Set process start time. + +--- + dlls/ntdll/nt.c | 1 + + server/protocol.def | 1 + + server/snapshot.c | 15 ++++++++------- + 3 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index 03cfd032bc..45572cb393 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -2058,6 +2058,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + spi->UniqueProcessId = UlongToHandle(reply->pid); + spi->ParentProcessId = UlongToHandle(reply->ppid); + spi->HandleCount = reply->handles; ++ spi->CreationTime.QuadPart = reply->start_time; + + /* spi->ti will be set later on */ + +diff --git a/server/protocol.def b/server/protocol.def +index 320e34384a..1347defe70 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -1808,6 +1808,7 @@ enum char_info_mode + int priority; /* process priority */ + int handles; /* number of handles */ + int unix_pid; /* Unix pid */ ++ timeout_t start_time; /* start time */ + VARARG(filename,unicode_str); /* file name of main exe */ + @END + +diff --git a/server/snapshot.c b/server/snapshot.c +index f2903d522e..e509e0aca9 100644 +--- a/server/snapshot.c ++++ b/server/snapshot.c +@@ -114,13 +114,14 @@ static int snapshot_next_process( struct snapshot *snapshot, struct next_process + return 0; + } + ptr = &snapshot->processes[snapshot->process_pos++]; +- reply->count = ptr->count; +- reply->pid = get_process_id( ptr->process ); +- reply->ppid = ptr->process->parent_id; +- reply->threads = ptr->threads; +- reply->priority = ptr->priority; +- reply->handles = ptr->handles; +- reply->unix_pid = ptr->process->unix_pid; ++ reply->count = ptr->count; ++ reply->pid = get_process_id( ptr->process ); ++ reply->ppid = ptr->process->parent_id; ++ reply->threads = ptr->threads; ++ reply->priority = ptr->priority; ++ reply->handles = ptr->handles; ++ reply->unix_pid = ptr->process->unix_pid; ++ reply->start_time = ptr->process->start_time; + if ((exe_module = get_process_exe_module( ptr->process )) && exe_module->filename) + { + data_size_t len = min( exe_module->namelen, get_reply_max_size() ); +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0005-ntdll-Fill-out-thread-times-in-process-enumeration.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0005-ntdll-Fill-out-thread-times-in-process-enumeration.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0005-ntdll-Fill-out-thread-times-in-process-enumeration.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0005-ntdll-Fill-out-thread-times-in-process-enumeration.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,82 @@ +From 6c3b7e0065c239b488bb224c1c67ff971562fdca Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 9 Mar 2017 21:14:13 +0100 +Subject: ntdll: Fill out thread times in process enumeration. + +--- + dlls/ntdll/nt.c | 6 ++++++ + server/protocol.def | 1 + + server/snapshot.c | 1 + + server/thread.h | 1 + + 4 files changed, 9 insertions(+) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index 8c54e7edfb..8b84cd865b 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -1928,6 +1928,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + WCHAR* exename; + DWORD wlen = 0; + DWORD procstructlen = 0; ++ int unix_pid = -1; + + SERVER_START_REQ( create_snapshot ) + { +@@ -1982,6 +1983,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + if (reply->unix_pid != -1) + read_process_time(reply->unix_pid, -1, clk_tck, + &spi->KernelTime, &spi->UserTime); ++ unix_pid = reply->unix_pid; + } + len += procstructlen; + } +@@ -2022,6 +2024,10 @@ NTSTATUS WINAPI NtQuerySystemInformation( + spi->ti[i].ClientId.UniqueThread = UlongToHandle(reply->tid); + spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri; + spi->ti[i].dwBasePriority = reply->base_pri; ++ ++ if (unix_pid != -1 && reply->unix_tid != -1) ++ read_process_time(unix_pid, reply->unix_tid, clk_tck, ++ &spi->ti[i].KernelTime, &spi->ti[i].UserTime); + i++; + } + } +diff --git a/server/protocol.def b/server/protocol.def +index b0b837cb93..542060decd 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -1789,6 +1789,7 @@ enum char_info_mode + timeout_t creation_time; /* thread creation time */ + int base_pri; /* base priority */ + int delta_pri; /* delta priority */ ++ int unix_tid; /* Unix tid */ + @END + + +diff --git a/server/snapshot.c b/server/snapshot.c +index cc8a9be1b5..a32207c720 100644 +--- a/server/snapshot.c ++++ b/server/snapshot.c +@@ -151,6 +151,7 @@ static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_r + reply->creation_time = get_thread_creation_time( ptr->thread ); + reply->base_pri = ptr->priority; + reply->delta_pri = 0; /* FIXME */ ++ reply->unix_tid = get_thread_unix_tid( ptr->thread ); + return 1; + } + +diff --git a/server/thread.h b/server/thread.h +index 2098c76a47..9614e2140d 100644 +--- a/server/thread.h ++++ b/server/thread.h +@@ -145,6 +145,7 @@ static inline void clear_error(void) { set_error(0); } + static inline void set_win32_error( unsigned int err ) { set_error( 0xc0010000 | err ); } + + static inline thread_id_t get_thread_id( struct thread *thread ) { return thread->id; } ++static inline int get_thread_unix_tid( struct thread *thread ) { return thread->unix_tid; } + static inline timeout_t get_thread_creation_time( struct thread *thread ) { return thread->creation_time; } + + #endif /* __WINE_SERVER_THREAD_H */ +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0006-ntdll-Fill-process-virtual-memory-counters-in-NtQuer.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0006-ntdll-Fill-process-virtual-memory-counters-in-NtQuer.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0006-ntdll-Fill-process-virtual-memory-counters-in-NtQuer.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/0006-ntdll-Fill-process-virtual-memory-counters-in-NtQuer.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,119 @@ +From 16d6f502dc86d2356b476ef0449b38353e3abc73 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 9 Mar 2017 22:56:45 +0100 +Subject: ntdll: Fill process virtual memory counters in + NtQuerySystemInformation. + +--- + dlls/ntdll/nt.c | 3 +++ + dlls/ntdll/ntdll_misc.h | 1 + + dlls/ntdll/process.c | 2 +- + dlls/ntdll/tests/info.c | 5 +---- + dlls/ntdll/thread.c | 36 ++++++++++++++++++++++++++++++++++++ + 5 files changed, 42 insertions(+), 5 deletions(-) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index 1dd890c4bd..a793b57221 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -2077,8 +2077,11 @@ NTSTATUS WINAPI NtQuerySystemInformation( + /* spi->ti will be set later on */ + + if (reply->unix_pid != -1) ++ { + read_process_time(reply->unix_pid, -1, clk_tck, + &spi->KernelTime, &spi->UserTime); ++ read_process_memory_stats(reply->unix_pid, &spi->vmCounters); ++ } + unix_pid = reply->unix_pid; + } + len += procstructlen; +diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h +index 0ecc099133..d556a21ee6 100644 +--- a/dlls/ntdll/ntdll_misc.h ++++ b/dlls/ntdll/ntdll_misc.h +@@ -289,4 +289,5 @@ extern void CDECL NTDLL_wine_get_host_version( const char **sysname, const char + /* process / thread time */ + extern BOOL read_process_time(int unix_pid, int unix_tid, unsigned long clk_tck, + LARGE_INTEGER *kernel, LARGE_INTEGER *user) DECLSPEC_HIDDEN; ++extern BOOL read_process_memory_stats(int unix_pid, VM_COUNTERS *pvmi) DECLSPEC_HIDDEN; + #endif +diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c +index 39cd8be601..993d90290d 100644 +--- a/dlls/ntdll/process.c ++++ b/dlls/ntdll/process.c +@@ -135,7 +135,7 @@ static void fill_VM_COUNTERS(VM_COUNTERS* pvmi) + + static void fill_VM_COUNTERS(VM_COUNTERS* pvmi) + { +- /* FIXME : real data */ ++ read_process_memory_stats(getpid(), pvmi); + } + + #endif +diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c +index c65a74bf5e..b9c44267a9 100644 +--- a/dlls/ntdll/tests/info.c ++++ b/dlls/ntdll/tests/info.c +@@ -1134,10 +1134,7 @@ static void test_query_process_vm(void) + + /* Check if we have some return values */ + trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize); +- todo_wine +- { +- ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n"); +- } ++ ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n"); + } + + static void test_query_process_io(void) +diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c +index 28ce2a1362..ccbc41d6ac 100644 +--- a/dlls/ntdll/thread.c ++++ b/dlls/ntdll/thread.c +@@ -117,6 +117,42 @@ BOOL read_process_time(int unix_pid, int unix_tid, unsigned long clk_tck, + return FALSE; + } + ++BOOL read_process_memory_stats(int unix_pid, VM_COUNTERS *pvmi) ++{ ++ BOOL ret = FALSE; ++#ifdef __linux__ ++ unsigned long size, resident, shared, trs, drs, lrs, dt; ++ char buf[512]; ++ FILE *fp; ++ ++ sprintf( buf, "/proc/%u/statm", unix_pid ); ++ if ((fp = fopen( buf, "r" ))) ++ { ++ if (fscanf( fp, "%lu %lu %lu %lu %lu %lu %lu", ++ &size, &resident, &shared, &trs, &drs, &lrs, &dt ) == 7) ++ { ++ pvmi->VirtualSize = size * page_size; ++ pvmi->WorkingSetSize = resident * page_size; ++ pvmi->PrivatePageCount = size - shared; ++ ++ /* these values are not available through /proc/pid/statm */ ++ pvmi->PeakVirtualSize = pvmi->VirtualSize; ++ pvmi->PageFaultCount = 0; ++ pvmi->PeakWorkingSetSize = pvmi->WorkingSetSize; ++ pvmi->QuotaPagedPoolUsage = pvmi->VirtualSize; ++ pvmi->QuotaPeakPagedPoolUsage = pvmi->QuotaPagedPoolUsage; ++ pvmi->QuotaPeakNonPagedPoolUsage = 0; ++ pvmi->QuotaNonPagedPoolUsage = 0; ++ pvmi->PagefileUsage = 0; ++ pvmi->PeakPagefileUsage = 0; ++ ++ ret = TRUE; ++ } ++ fclose( fp ); ++ } ++#endif ++ return ret; ++} + + /*********************************************************************** + * get_unicode_string +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/definition wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntdll-ThreadTime/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntdll-ThreadTime/definition 2017-03-21 14:37:14.000000000 +0000 @@ -1 +1,3 @@ Fixes: [20230] Return correct values for GetThreadTimes function +Fixes: Return correct thread creation time in SystemProcessInformation +Fixes: Fill process virtual memory counters in NtQuerySystemInformation diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/0001-ntoskrnl.exe-add-KeAcquireInStackQueuedSpinLock-stub.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/0001-ntoskrnl.exe-add-KeAcquireInStackQueuedSpinLock-stub.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/0001-ntoskrnl.exe-add-KeAcquireInStackQueuedSpinLock-stub.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/0001-ntoskrnl.exe-add-KeAcquireInStackQueuedSpinLock-stub.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -From d41ae9a2e8182b9a57a9b110905a4ffb0dd81e8f Mon Sep 17 00:00:00 2001 -From: Austin English -Date: Thu, 9 Feb 2017 16:51:25 -0600 -Subject: ntoskrnl.exe: add KeAcquireInStackQueuedSpinLock stub (try 2) - -Signed-off-by: Austin English ---- - dlls/hal/hal.spec | 2 +- - dlls/ntoskrnl.exe/ntoskrnl.c | 13 +++++++++++++ - dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + - include/ddk/wdm.h | 10 ++++++++++ - tools/make_specfiles | 4 ++++ - 5 files changed, 29 insertions(+), 1 deletion(-) - -diff --git a/dlls/hal/hal.spec b/dlls/hal/hal.spec -index bd6bc35736a..f441ac5271f 100644 ---- a/dlls/hal/hal.spec -+++ b/dlls/hal/hal.spec -@@ -4,7 +4,7 @@ - @ stub HalClearSoftwareInterrupt - @ stub HalRequestSoftwareInterrupt - @ stub HalSystemVectorDispatchEntry --@ stub KeAcquireInStackQueuedSpinLock -+@ stdcall -norelay KeAcquireInStackQueuedSpinLock(ptr ptr) ntoskrnl.exe.KeAcquireInStackQueuedSpinLock - @ stub KeAcquireInStackQueuedSpinLockRaiseToSynch - @ stub KeAcquireQueuedSpinLock - @ stub KeAcquireQueuedSpinLockRaiseToSynch -diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c -index 06320d03cc9..b8f6a25714a 100644 ---- a/dlls/ntoskrnl.exe/ntoskrnl.c -+++ b/dlls/ntoskrnl.exe/ntoskrnl.c -@@ -3188,3 +3188,16 @@ VOID WINAPI KeClearEvent(PRKEVENT event) - { - FIXME("stub: %p\n", event); - } -+ -+/*********************************************************************** -+ * KeAcquireInStackQueuedSpinLock (NTOSKRNL.EXE.@) -+ */ -+#ifdef DEFINE_FASTCALL2_ENTRYPOINT -+DEFINE_FASTCALL2_ENTRYPOINT( KeAcquireInStackQueuedSpinLock ) -+void WINAPI __regs_KeAcquireInStackQueuedSpinLock(KSPIN_LOCK *spinlock, KLOCK_QUEUE_HANDLE *handle) -+#else -+void WINAPI KeAcquireInStackQueuedSpinLock(KSPIN_LOCK *spinlock, KLOCK_QUEUE_HANDLE *handle) -+#endif -+{ -+ FIXME( "stub: %p %p\n", spinlock, handle); -+} -diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -index 62c7fb496cf..ba18200c503 100644 ---- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -@@ -41,6 +41,7 @@ - @ stub IoWritePartitionTable - @ stdcall -norelay IofCallDriver(ptr ptr) - @ stdcall -norelay IofCompleteRequest(ptr long) -+@ stdcall -norelay KeAcquireInStackQueuedSpinLock(ptr ptr) - @ stub KeAcquireInStackQueuedSpinLockAtDpcLevel - @ stub KeReleaseInStackQueuedSpinLockFromDpcLevel - @ stub KeSetTimeUpdateNotifyRoutine -diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h -index 4c696f776dd..61374a7ed43 100644 ---- a/include/ddk/wdm.h -+++ b/include/ddk/wdm.h -@@ -1210,6 +1210,16 @@ typedef struct _CALLBACK_OBJECT - UCHAR reserved[3]; - } CALLBACK_OBJECT, *PCALLBACK_OBJECT; - -+typedef struct _KSPIN_LOCK_QUEUE { -+ struct _KSPIN_LOCK_QUEUE * volatile Next; -+ volatile PKSPIN_LOCK Lock; -+} KSPIN_LOCK_QUEUE, *PKSPIN_LOCK_QUEUE; -+ -+typedef struct _KLOCK_QUEUE_HANDLE { -+ KSPIN_LOCK_QUEUE LockQueue; -+ KIRQL OldIrql; -+} KLOCK_QUEUE_HANDLE, *PKLOCK_QUEUE_HANDLE; -+ - typedef NTSTATUS (NTAPI EX_CALLBACK_FUNCTION)(void *CallbackContext, void *Argument1, void *Argument2); - typedef EX_CALLBACK_FUNCTION *PEX_CALLBACK_FUNCTION; - -diff --git a/tools/make_specfiles b/tools/make_specfiles -index 1e2400e4c7f..505bdf1e791 100755 ---- a/tools/make_specfiles -+++ b/tools/make_specfiles -@@ -338,6 +338,10 @@ my @dll_groups = - "bcrypt", - "ncrypt", - ], -+ [ -+ "ntoskrnl.exe", -+ "hal", -+ ] - ); - - my $update_flags = 0; --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/0002-ntoskrnl.exe-Add-KeReleaseInStackQueuedSpinLock-stub.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/0002-ntoskrnl.exe-Add-KeReleaseInStackQueuedSpinLock-stub.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/0002-ntoskrnl.exe-Add-KeReleaseInStackQueuedSpinLock-stub.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/0002-ntoskrnl.exe-Add-KeReleaseInStackQueuedSpinLock-stub.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -From 15bd72533dd2d899e18c2201dd73ccfd2fb495c0 Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Sun, 5 Mar 2017 19:28:08 +0100 -Subject: ntoskrnl.exe: Add KeReleaseInStackQueuedSpinLock stub. - ---- - dlls/hal/hal.spec | 2 +- - dlls/ntoskrnl.exe/ntoskrnl.c | 13 +++++++++++++ - dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + - 3 files changed, 15 insertions(+), 1 deletion(-) - -diff --git a/dlls/hal/hal.spec b/dlls/hal/hal.spec -index f441ac5271f..414e49bfec9 100644 ---- a/dlls/hal/hal.spec -+++ b/dlls/hal/hal.spec -@@ -9,7 +9,7 @@ - @ stub KeAcquireQueuedSpinLock - @ stub KeAcquireQueuedSpinLockRaiseToSynch - @ stub KeAcquireSpinLockRaiseToSynch --@ stub KeReleaseInStackQueuedSpinLock -+@ stdcall -norelay KeReleaseInStackQueuedSpinLock(ptr) ntoskrnl.exe.KeReleaseInStackQueuedSpinLock - @ stub KeReleaseQueuedSpinLock - @ stub KeTryToAcquireQueuedSpinLock - @ stub KeTryToAcquireQueuedSpinLockRaiseToSynch -diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c -index b8f6a25714a..8cda7b70388 100644 ---- a/dlls/ntoskrnl.exe/ntoskrnl.c -+++ b/dlls/ntoskrnl.exe/ntoskrnl.c -@@ -3201,3 +3201,16 @@ void WINAPI KeAcquireInStackQueuedSpinLock(KSPIN_LOCK *spinlock, KLOCK_QUEUE_HAN - { - FIXME( "stub: %p %p\n", spinlock, handle); - } -+ -+/*********************************************************************** -+ * KeReleaseInStackQueuedSpinLock (NTOSKRNL.EXE.@) -+ */ -+#ifdef DEFINE_FASTCALL2_ENTRYPOINT -+DEFINE_FASTCALL2_ENTRYPOINT( KeReleaseInStackQueuedSpinLock ) -+void WINAPI __regs_KeReleaseInStackQueuedSpinLock(KLOCK_QUEUE_HANDLE *handle) -+#else -+void WINAPI KeReleaseInStackQueuedSpinLock(KLOCK_QUEUE_HANDLE *handle) -+#endif -+{ -+ FIXME( "stub: %p\n", handle); -+} -diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -index ba18200c503..e223eadc1a8 100644 ---- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -@@ -43,6 +43,7 @@ - @ stdcall -norelay IofCompleteRequest(ptr long) - @ stdcall -norelay KeAcquireInStackQueuedSpinLock(ptr ptr) - @ stub KeAcquireInStackQueuedSpinLockAtDpcLevel -+@ stdcall -norelay KeReleaseInStackQueuedSpinLock(ptr) - @ stub KeReleaseInStackQueuedSpinLockFromDpcLevel - @ stub KeSetTimeUpdateNotifyRoutine - @ stub KefAcquireSpinLockAtDpcLevel --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/definition wine-staging-2.4.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntoskrnl-InStackQueuedSpinLock/definition 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Fixes: [41472] Add stubs for Ke{Aquire,Release}InStackQueuedSpinLock functions diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/ntoskrnl-Stubs/0001-ntoskrnl.exe-add-KeWaitForMultipleObjects-stub.patch wine-staging-2.4.0~ubuntu16.04.1/patches/ntoskrnl-Stubs/0001-ntoskrnl.exe-add-KeWaitForMultipleObjects-stub.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/ntoskrnl-Stubs/0001-ntoskrnl.exe-add-KeWaitForMultipleObjects-stub.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/ntoskrnl-Stubs/0001-ntoskrnl.exe-add-KeWaitForMultipleObjects-stub.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -From 3b325b1efd31f5162d119b7f7cef2edc06f3d627 Mon Sep 17 00:00:00 2001 -From: Austin English -Date: Wed, 24 Dec 2014 15:35:23 -0600 -Subject: ntoskrnl.exe: add KeWaitForMultipleObjects stub - ---- - dlls/ntoskrnl.exe/ntoskrnl.c | 14 ++++++++++++++ - dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- - 2 files changed, 15 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c -index 7c35d14..7ffae6e 100644 ---- a/dlls/ntoskrnl.exe/ntoskrnl.c -+++ b/dlls/ntoskrnl.exe/ntoskrnl.c -@@ -30,6 +30,7 @@ - - #include "ntstatus.h" - #define WIN32_NO_STATUS -+#include "ntdef.h" - #include "windef.h" - #include "winsvc.h" - #include "winternl.h" -@@ -1918,6 +1919,19 @@ NTSTATUS WINAPI KeWaitForSingleObject(PVOID Object, - } - - /*********************************************************************** -+ * KeWaitForMultipleObjects (NTOSKRNL.EXE.@) -+ */ -+NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG Count, PVOID Object[], WAIT_TYPE WaitType, -+ KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode, -+ BOOLEAN Alertable, PLARGE_INTEGER Timeout, -+ PKWAIT_BLOCK WaitBlockArray) -+{ -+ FIXME( "stub: %u, %p, %d, %d, %d, %d, %p, %p\n", Count, Object, WaitType, WaitReason, WaitMode, -+ Alertable, Timeout, WaitBlockArray ); -+ return STATUS_NOT_IMPLEMENTED; -+} -+ -+/*********************************************************************** - * IoRegisterFileSystem (NTOSKRNL.EXE.@) - */ - VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject) -diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -index 119d406..059f49c 100644 ---- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec -@@ -627,7 +627,7 @@ - @ stub KeUpdateRunTime - @ stub KeUpdateSystemTime - @ stub KeUserModeCallback --@ stub KeWaitForMultipleObjects -+@ stdcall KeWaitForMultipleObjects(long ptr long long long long ptr ptr) - @ stdcall KeWaitForMutexObject(ptr long long long ptr) - @ stdcall KeWaitForSingleObject(ptr long long long ptr) - @ stub KiBugCheckData --- -2.9.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/patchinstall.sh wine-staging-2.4.0~ubuntu16.04.1/patches/patchinstall.sh --- wine-staging-2.3.0~ubuntu16.04.1/patches/patchinstall.sh 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/patchinstall.sh 2017-03-21 14:37:14.000000000 +0000 @@ -52,13 +52,13 @@ # Get the upstream commit sha upstream_commit() { - echo "a2460b2424163bbf5b885db6a5423c3d98f883e0" + echo "6a05069a43f1a8f0e69c4cedd134f8d7400b8a95" } # Show version information version() { - echo "Wine Staging 2.3" + echo "Wine Staging 2.4" echo "Copyright (C) 2014-2017 the Wine Staging project authors." echo "" echo "Patchset to be applied on upstream Wine:" @@ -97,7 +97,6 @@ enable_avifile_dll16_AVIStreamGetFrame="$1" enable_bcrypt_Improvements="$1" enable_browseui_Progress_Dialog="$1" - enable_cabinet_iFolder="$1" enable_combase_RoApi="$1" enable_comctl32_Button_Theming="$1" enable_comctl32_Listview_DrawItem="$1" @@ -140,6 +139,7 @@ enable_ddraw_FlipToGDISurface="$1" enable_ddraw_IDirect3DTexture2_Load="$1" enable_ddraw_Rendering_Targets="$1" + enable_ddraw_Silence_FIXMEs="$1" enable_ddraw_Write_Vtable="$1" enable_devenum_AudioCompressorCategory="$1" enable_dinput_Initialize="$1" @@ -156,12 +156,14 @@ enable_explorer_Video_Registry_Key="$1" enable_fonts_Missing_Fonts="$1" enable_fsutil_Stub_Program="$1" + enable_gdi32_GetCharacterPlacement="$1" enable_gdi32_Lazy_Font_Initialization="$1" enable_gdi32_MultiMonitor="$1" enable_gdi32_Path_Metafile="$1" enable_gdi32_Symbol_Truetype_Font="$1" enable_gdiplus_DC_Handling="$1" enable_gdiplus_Grayscale_PNG="$1" + enable_gdiplus_Performance_Improvements="$1" enable_hal_KeQueryPerformanceCounter="$1" enable_hnetcfg_INetFwAuthorizedApplication="$1" enable_ieframe_IViewObject_Draw="$1" @@ -178,7 +180,6 @@ enable_kernel32_Cwd_Startup_Info="$1" enable_kernel32_Debugger="$1" enable_kernel32_FindFirstFile="$1" - enable_kernel32_GetCurrentPackageFamilyName="$1" enable_kernel32_GetPackageFullName="$1" enable_kernel32_GetShortPathName="$1" enable_kernel32_K32GetPerformanceInfo="$1" @@ -227,7 +228,6 @@ enable_ntdll_DllOverrides_WOW64="$1" enable_ntdll_DllRedirects="$1" enable_ntdll_Exception="$1" - enable_ntdll_FileAccessInformation="$1" enable_ntdll_FileDispositionInformation="$1" enable_ntdll_FileFsFullSizeInformation="$1" enable_ntdll_FileFsVolumeInformation="$1" @@ -235,7 +235,9 @@ enable_ntdll_Grow_Virtual_Heap="$1" enable_ntdll_Heap_FreeLists="$1" enable_ntdll_Hide_Wine_Exports="$1" + enable_ntdll_Interrupt_0x2e="$1" enable_ntdll_Junction_Points="$1" + enable_ntdll_LDR_MODULE="$1" enable_ntdll_LdrEnumerateLoadedModules="$1" enable_ntdll_LdrGetDllHandle="$1" enable_ntdll_Loader_Machine_Type="$1" @@ -247,6 +249,7 @@ enable_ntdll_NtSetInformationToken="$1" enable_ntdll_NtSetLdtEntries="$1" enable_ntdll_Pipe_SpecialCharacters="$1" + enable_ntdll_ProcessImageFileNameWin32="$1" enable_ntdll_ProcessPriorityClass="$1" enable_ntdll_ProcessQuotaLimits="$1" enable_ntdll_Purist_Mode="$1" @@ -271,9 +274,7 @@ enable_ntdll_Zero_mod_name="$1" enable_ntdll__aulldvrm="$1" enable_ntdll_call_thread_func_wrapper="$1" - enable_ntdll_raise_func_trampoline="$1" enable_ntoskrnl_DriverTest="$1" - enable_ntoskrnl_InStackQueuedSpinLock="$1" enable_ntoskrnl_Stubs="$1" enable_nvapi_Stub_DLL="$1" enable_nvcuda_CUDA_Support="$1" @@ -298,7 +299,6 @@ enable_qcap_O_CLOEXEC="$1" enable_quartz_MediaSeeking_Positions="$1" enable_quartz_Silence_FIXMEs="$1" - enable_rasapi32_RasEnumDevicesA="$1" enable_riched20_Class_Tests="$1" enable_riched20_IText_Interface="$1" enable_secur32_Zero_Buffer_Length="$1" @@ -312,6 +312,7 @@ enable_server_LABEL_SECURITY_INFORMATION="$1" enable_server_Map_EXDEV_Error="$1" enable_server_Misc_ACL="$1" + enable_server_Object_Types="$1" enable_server_PeekMessage="$1" enable_server_Pipe_ObjectName="$1" enable_server_Realtime_Priority="$1" @@ -372,6 +373,7 @@ enable_user32_PNG_Support="$1" enable_user32_Refresh_MDI_Menus="$1" enable_user32_ScrollWindowEx="$1" + enable_user32_Sorted_Listbox="$1" enable_user32_WM_MEASUREITEM="$1" enable_user32_lpCreateParams="$1" enable_uxtheme_CloseThemeClass="$1" @@ -514,9 +516,6 @@ browseui-Progress_Dialog) enable_browseui_Progress_Dialog="$2" ;; - cabinet-iFolder) - enable_cabinet_iFolder="$2" - ;; combase-RoApi) enable_combase_RoApi="$2" ;; @@ -643,6 +642,9 @@ ddraw-Rendering_Targets) enable_ddraw_Rendering_Targets="$2" ;; + ddraw-Silence_FIXMEs) + enable_ddraw_Silence_FIXMEs="$2" + ;; ddraw-Write_Vtable) enable_ddraw_Write_Vtable="$2" ;; @@ -691,6 +693,9 @@ fsutil-Stub_Program) enable_fsutil_Stub_Program="$2" ;; + gdi32-GetCharacterPlacement) + enable_gdi32_GetCharacterPlacement="$2" + ;; gdi32-Lazy_Font_Initialization) enable_gdi32_Lazy_Font_Initialization="$2" ;; @@ -709,6 +714,9 @@ gdiplus-Grayscale_PNG) enable_gdiplus_Grayscale_PNG="$2" ;; + gdiplus-Performance-Improvements) + enable_gdiplus_Performance_Improvements="$2" + ;; hal-KeQueryPerformanceCounter) enable_hal_KeQueryPerformanceCounter="$2" ;; @@ -757,9 +765,6 @@ kernel32-FindFirstFile) enable_kernel32_FindFirstFile="$2" ;; - kernel32-GetCurrentPackageFamilyName) - enable_kernel32_GetCurrentPackageFamilyName="$2" - ;; kernel32-GetPackageFullName) enable_kernel32_GetPackageFullName="$2" ;; @@ -904,9 +909,6 @@ ntdll-Exception) enable_ntdll_Exception="$2" ;; - ntdll-FileAccessInformation) - enable_ntdll_FileAccessInformation="$2" - ;; ntdll-FileDispositionInformation) enable_ntdll_FileDispositionInformation="$2" ;; @@ -928,9 +930,15 @@ ntdll-Hide_Wine_Exports) enable_ntdll_Hide_Wine_Exports="$2" ;; + ntdll-Interrupt-0x2e) + enable_ntdll_Interrupt_0x2e="$2" + ;; ntdll-Junction_Points) enable_ntdll_Junction_Points="$2" ;; + ntdll-LDR_MODULE) + enable_ntdll_LDR_MODULE="$2" + ;; ntdll-LdrEnumerateLoadedModules) enable_ntdll_LdrEnumerateLoadedModules="$2" ;; @@ -964,6 +972,9 @@ ntdll-Pipe_SpecialCharacters) enable_ntdll_Pipe_SpecialCharacters="$2" ;; + ntdll-ProcessImageFileNameWin32) + enable_ntdll_ProcessImageFileNameWin32="$2" + ;; ntdll-ProcessPriorityClass) enable_ntdll_ProcessPriorityClass="$2" ;; @@ -1036,15 +1047,9 @@ ntdll-call_thread_func_wrapper) enable_ntdll_call_thread_func_wrapper="$2" ;; - ntdll-raise_func_trampoline) - enable_ntdll_raise_func_trampoline="$2" - ;; ntoskrnl-DriverTest) enable_ntoskrnl_DriverTest="$2" ;; - ntoskrnl-InStackQueuedSpinLock) - enable_ntoskrnl_InStackQueuedSpinLock="$2" - ;; ntoskrnl-Stubs) enable_ntoskrnl_Stubs="$2" ;; @@ -1117,9 +1122,6 @@ quartz-Silence_FIXMEs) enable_quartz_Silence_FIXMEs="$2" ;; - rasapi32-RasEnumDevicesA) - enable_rasapi32_RasEnumDevicesA="$2" - ;; riched20-Class_Tests) enable_riched20_Class_Tests="$2" ;; @@ -1159,6 +1161,9 @@ server-Misc_ACL) enable_server_Misc_ACL="$2" ;; + server-Object_Types) + enable_server_Object_Types="$2" + ;; server-PeekMessage) enable_server_PeekMessage="$2" ;; @@ -1339,6 +1344,9 @@ user32-ScrollWindowEx) enable_user32_ScrollWindowEx="$2" ;; + user32-Sorted_Listbox) + enable_user32_Sorted_Listbox="$2" + ;; user32-WM_MEASUREITEM) enable_user32_WM_MEASUREITEM="$2" ;; @@ -2110,6 +2118,13 @@ enable_ntdll_DllRedirects=1 fi +if test "$enable_user32_Sorted_Listbox" -eq 1; then + if test "$enable_user32_WM_MEASUREITEM" -gt 1; then + abort "Patchset user32-WM_MEASUREITEM disabled, but user32-Sorted_Listbox depends on that." + fi + enable_user32_WM_MEASUREITEM=1 +fi + if test "$enable_user32_MessageBox_WS_EX_TOPMOST" -eq 1; then if test "$enable_user32_lpCreateParams" -gt 1; then abort "Patchset user32-lpCreateParams disabled, but user32-MessageBox_WS_EX_TOPMOST depends on that." @@ -2142,6 +2157,31 @@ enable_shell32_SHFileOperation_Move=1 fi +if test "$enable_server_Realtime_Priority" -eq 1; then + if test "$enable_ntdll_ThreadTime" -gt 1; then + abort "Patchset ntdll-ThreadTime disabled, but server-Realtime_Priority depends on that." + fi + enable_ntdll_ThreadTime=1 +fi + +if test "$enable_server_Pipe_ObjectName" -eq 1; then + if test "$enable_kernel32_Named_Pipe" -gt 1; then + abort "Patchset kernel32-Named_Pipe disabled, but server-Pipe_ObjectName depends on that." + fi + enable_kernel32_Named_Pipe=1 +fi + +if test "$enable_server_Object_Types" -eq 1; then + if test "$enable_server_Misc_ACL" -gt 1; then + abort "Patchset server-Misc_ACL disabled, but server-Object_Types depends on that." + fi + if test "$enable_server_Shared_Memory" -gt 1; then + abort "Patchset server-Shared_Memory disabled, but server-Object_Types depends on that." + fi + enable_server_Misc_ACL=1 + enable_server_Shared_Memory=1 +fi + if test "$enable_server_Shared_Memory" -eq 1; then if test "$enable_ntdll_Threading" -gt 1; then abort "Patchset ntdll-Threading disabled, but server-Shared_Memory depends on that." @@ -2165,13 +2205,6 @@ enable_server_Signal_Thread=1 fi -if test "$enable_server_Pipe_ObjectName" -eq 1; then - if test "$enable_kernel32_Named_Pipe" -gt 1; then - abort "Patchset kernel32-Named_Pipe disabled, but server-Pipe_ObjectName depends on that." - fi - enable_kernel32_Named_Pipe=1 -fi - if test "$enable_server_LABEL_SECURITY_INFORMATION" -eq 1; then if test "$enable_advapi32_GetExplicitEntriesFromAclW" -gt 1; then abort "Patchset advapi32-GetExplicitEntriesFromAclW disabled, but server-LABEL_SECURITY_INFORMATION depends on that." @@ -2297,7 +2330,11 @@ if test "$enable_ntdll_Attach_Process_DLLs" -gt 1; then abort "Patchset ntdll-Attach_Process_DLLs disabled, but ntdll-Hide_Wine_Exports depends on that." fi + if test "$enable_ntdll_ThreadTime" -gt 1; then + abort "Patchset ntdll-ThreadTime disabled, but ntdll-Hide_Wine_Exports depends on that." + fi enable_ntdll_Attach_Process_DLLs=1 + enable_ntdll_ThreadTime=1 fi if test "$enable_ntdll_DllRedirects" -eq 1; then @@ -2347,11 +2384,7 @@ if test "$enable_api_ms_win_Stub_DLLs" -gt 1; then abort "Patchset api-ms-win-Stub_DLLs disabled, but kernel32-GetPackageFullName depends on that." fi - if test "$enable_kernel32_GetCurrentPackageFamilyName" -gt 1; then - abort "Patchset kernel32-GetCurrentPackageFamilyName disabled, but kernel32-GetPackageFullName depends on that." - fi enable_api_ms_win_Stub_DLLs=1 - enable_kernel32_GetCurrentPackageFamilyName=1 fi if test "$enable_kernel32_CopyFileEx" -eq 1; then @@ -2440,14 +2473,10 @@ if test "$enable_combase_RoApi" -gt 1; then abort "Patchset combase-RoApi disabled, but api-ms-win-Stub_DLLs depends on that." fi - if test "$enable_kernel32_GetCurrentPackageFamilyName" -gt 1; then - abort "Patchset kernel32-GetCurrentPackageFamilyName disabled, but api-ms-win-Stub_DLLs depends on that." - fi if test "$enable_kernel32_UmsStubs" -gt 1; then abort "Patchset kernel32-UmsStubs disabled, but api-ms-win-Stub_DLLs depends on that." fi enable_combase_RoApi=1 - enable_kernel32_GetCurrentPackageFamilyName=1 enable_kernel32_UmsStubs=1 fi @@ -2733,24 +2762,6 @@ ) >> "$patchlist" fi -# Patchset kernel32-GetCurrentPackageFamilyName -# | -# | This patchset fixes the following Wine bugs: -# | * [#42586] Add stub for kernel32.GetCurrentPackageFullName -# | -# | Modified files: -# | * dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec, dlls/kernel32/kernel32.spec, -# | dlls/kernel32/version.c -# | -if test "$enable_kernel32_GetCurrentPackageFamilyName" -eq 1; then - patch_apply kernel32-GetCurrentPackageFamilyName/0001-kernel32-Add-stub-for-GetCurrentPackageFamilyName-an.patch - patch_apply kernel32-GetCurrentPackageFamilyName/0002-kernel32-add-stub-for-GetCurrentPackageFullName.patch - ( - printf '%s\n' '+ { "Michael Müller", "kernel32: Add stub for GetCurrentPackageFamilyName and add related functions to spec file.", 1 },'; - printf '%s\n' '+ { "Louis Lenders", "kernel32: Add stub for GetCurrentPackageFullName.", 1 },'; - ) >> "$patchlist" -fi - # Patchset kernel32-UmsStubs # | # | Modified files: @@ -2769,7 +2780,7 @@ # Patchset api-ms-win-Stub_DLLs # | # | This patchset has the following (direct or indirect) dependencies: -# | * combase-RoApi, kernel32-GetCurrentPackageFamilyName, kernel32-UmsStubs +# | * combase-RoApi, kernel32-UmsStubs # | # | This patchset fixes the following Wine bugs: # | * [#40451] Add feclient dll @@ -2893,25 +2904,18 @@ # Patchset bcrypt-Improvements # | # | This patchset fixes the following Wine bugs: -# | * [#41951] Implement bcrypt.BCryptDuplicateHash # | * [#40418] Implement BCrypt AES provider # | * [#42553] Implement BCrypt ECB chaining mode # | # | Modified files: -# | * dlls/bcrypt/Makefile.in, dlls/bcrypt/bcrypt.spec, dlls/bcrypt/bcrypt_internal.h, dlls/bcrypt/bcrypt_main.c, -# | dlls/bcrypt/sha256.c, dlls/bcrypt/sha384.c, dlls/bcrypt/sha512.c, dlls/bcrypt/tests/bcrypt.c, dlls/ncrypt/ncrypt.spec, +# | * dlls/bcrypt/bcrypt.spec, dlls/bcrypt/bcrypt_main.c, dlls/bcrypt/tests/bcrypt.c, dlls/ncrypt/ncrypt.spec, # | include/bcrypt.h, include/ntstatus.h # | if test "$enable_bcrypt_Improvements" -eq 1; then patch_apply bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch - patch_apply bcrypt-Improvements/0002-bcrypt-Directly-implement-hmac-computation.patch - patch_apply bcrypt-Improvements/0003-bcrypt-Add-internal-fallback-implementation-for-hash.patch - patch_apply bcrypt-Improvements/0004-bcrypt-Use-hash-fallback-implementation-as-default-a.patch - patch_apply bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch patch_apply bcrypt-Improvements/0006-bcrypt-Fix-handling-of-padding-when-input-size-equal.patch patch_apply bcrypt-Improvements/0007-bcrypt-Properly-handle-padding-in-AES-decryption.patch patch_apply bcrypt-Improvements/0008-bcrypt-Fix-use-after-free-in-key_init.patch - patch_apply bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch patch_apply bcrypt-Improvements/0010-bcrypt-tests-Add-test-for-bugs-in-BCryptGetProperty.patch patch_apply bcrypt-Improvements/0011-bcrypt-tests-Add-tests-for-AES-GCM-mode.patch patch_apply bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch @@ -2931,14 +2935,9 @@ patch_apply bcrypt-Improvements/0026-bcrypt-Implement-support-for-ECB-chain-mode.patch ( printf '%s\n' '+ { "Hans Leidekker", "bcrypt: Add AES provider.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "bcrypt: Directly implement hmac computation.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "bcrypt: Add internal fallback implementation for hash calculations.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "bcrypt: Use hash fallback implementation as default and remove gnutls / commoncrypto hash implemetation.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "bcrypt: Implement BCryptDuplicateHash.", 1 },'; printf '%s\n' '+ { "Michael Müller", "bcrypt: Fix handling of padding when input size equals block size for AES.", 1 },'; printf '%s\n' '+ { "Michael Müller", "bcrypt: Properly handle padding in AES decryption.", 1 },'; printf '%s\n' '+ { "Michael Müller", "bcrypt: Fix use-after-free in key_init.", 1 },'; - printf '%s\n' '+ { "Sebastian Lackner", "bcrypt: Handle NULL pointers in BCryptDuplicateHash and add tests.", 1 },'; printf '%s\n' '+ { "Sebastian Lackner", "bcrypt/tests: Add test for bugs in BCryptGetProperty.", 1 },'; printf '%s\n' '+ { "Michael Müller", "bcrypt/tests: Add tests for AES GCM mode.", 1 },'; printf '%s\n' '+ { "Sebastian Lackner", "bcrypt: Pass object to get_{alg,hash}_property instead of alg_id.", 1 },'; @@ -2973,21 +2972,6 @@ ) >> "$patchlist" fi -# Patchset cabinet-iFolder -# | -# | This patchset fixes the following Wine bugs: -# | * [#10858] Set index of folder in FDICopy callback -# | -# | Modified files: -# | * dlls/cabinet/fdi.c -# | -if test "$enable_cabinet_iFolder" -eq 1; then - patch_apply cabinet-iFolder/0001-cabinet-Set-index-of-folder-in-FDICopy-callback.patch - ( - printf '%s\n' '+ { "Michael Müller", "cabinet: Set index of folder in FDICopy callback.", 1 },'; - ) >> "$patchlist" -fi - # Patchset comctl32-Button_Theming # | # | This patchset fixes the following Wine bugs: @@ -3759,6 +3743,18 @@ ) >> "$patchlist" fi +# Patchset ddraw-Silence_FIXMEs +# | +# | Modified files: +# | * dlls/ddraw/executebuffer.c +# | +if test "$enable_ddraw_Silence_FIXMEs" -eq 1; then + patch_apply ddraw-Silence_FIXMEs/0001-ddraw-Silence-noisy-FIXME-about-unimplemented-D3DPRO.patch + ( + printf '%s\n' '+ { "Christian Costa", "ddraw: Silence noisy FIXME about unimplemented D3DPROCESSVERTICES_UPDATEEXTENTS.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ddraw-Write_Vtable # | # | This patchset fixes the following Wine bugs: @@ -4089,6 +4085,21 @@ ) >> "$patchlist" fi +# Patchset gdi32-GetCharacterPlacement +# | +# | This patchset fixes the following Wine bugs: +# | * [#42669] Treat lpResults as optional in gdi32.GetCharacterPlacement +# | +# | Modified files: +# | * dlls/gdi32/font.c, dlls/gdi32/tests/font.c +# | +if test "$enable_gdi32_GetCharacterPlacement" -eq 1; then + patch_apply gdi32-GetCharacterPlacement/0001-gdi32-Treat-lpResults-as-optional-in-GetCharacterPla.patch + ( + printf '%s\n' '+ { "Michael Müller", "gdi32: Treat lpResults as optional in GetCharacterPlacement.", 1 },'; + ) >> "$patchlist" +fi + # Patchset gdi32-Lazy_Font_Initialization # | # | Modified files: @@ -4195,6 +4206,24 @@ ) >> "$patchlist" fi +# Patchset gdiplus-Performance-Improvements +# | +# | Modified files: +# | * dlls/gdiplus/graphics.c +# | +if test "$enable_gdiplus_Performance_Improvements" -eq 1; then + patch_apply gdiplus-Performance-Improvements/0001-gdiplus-Change-the-order-of-x-y-loops-in-the-scaler.patch + patch_apply gdiplus-Performance-Improvements/0002-gdiplus-Change-multiplications-by-additions-in-the-x.patch + patch_apply gdiplus-Performance-Improvements/0003-gdiplus-Remove-ceilf-floorf-calls-from-bilinear-scal.patch + patch_apply gdiplus-Performance-Improvements/0004-gdiplus-Prefer-using-pre-multiplied-ARGB-data-in-the.patch + ( + printf '%s\n' '+ { "Dmitry Timoshkov", "gdiplus: Change the order of x/y loops in the scaler.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "gdiplus: Change multiplications by additions in the x/y scaler loops.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "gdiplus: Remove ceilf/floorf calls from bilinear scaler.", 2 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "gdiplus: Prefer using pre-multiplied ARGB data in the scaler.", 1 },'; + ) >> "$patchlist" +fi + # Patchset hal-KeQueryPerformanceCounter # | # | This patchset fixes the following Wine bugs: @@ -4493,7 +4522,7 @@ # Patchset kernel32-GetPackageFullName # | # | This patchset has the following (direct or indirect) dependencies: -# | * combase-RoApi, kernel32-GetCurrentPackageFamilyName, kernel32-UmsStubs, api-ms-win-Stub_DLLs +# | * combase-RoApi, kernel32-UmsStubs, api-ms-win-Stub_DLLs # | # | Modified files: # | * dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec, dlls/kernel32/kernel32.spec, @@ -4736,7 +4765,7 @@ # Patchset kernel32-Processor_Group # | # | This patchset has the following (direct or indirect) dependencies: -# | * combase-RoApi, kernel32-GetCurrentPackageFamilyName, kernel32-UmsStubs, api-ms-win-Stub_DLLs +# | * combase-RoApi, kernel32-UmsStubs, api-ms-win-Stub_DLLs # | # | Modified files: # | * dlls/api-ms-win-core-kernel32-legacy-l1-1-0/api-ms-win-core-kernel32-legacy-l1-1-0.spec, dlls/api-ms-win-core- @@ -5356,21 +5385,6 @@ ) >> "$patchlist" fi -# Patchset ntdll-FileAccessInformation -# | -# | This patchset fixes the following Wine bugs: -# | * [#42550] Implement FileAccessInformation class -# | -# | Modified files: -# | * dlls/ntdll/file.c, dlls/ntdll/tests/file.c -# | -if test "$enable_ntdll_FileAccessInformation" -eq 1; then - patch_apply ntdll-FileAccessInformation/0001-ntdll-Implement-FileAccessInformation-class-in-NtQue.patch - ( - printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Implement FileAccessInformation class in NtQueryInformationFile.", 1 },'; - ) >> "$patchlist" -fi - # Patchset ntdll-FileFsFullSizeInformation # | # | Modified files: @@ -5440,10 +5454,36 @@ ) >> "$patchlist" fi +# Patchset ntdll-ThreadTime +# | +# | This patchset fixes the following Wine bugs: +# | * [#20230] Return correct values for GetThreadTimes function +# | +# | Modified files: +# | * dlls/ntdll/nt.c, dlls/ntdll/ntdll_misc.h, dlls/ntdll/process.c, dlls/ntdll/tests/info.c, dlls/ntdll/thread.c, +# | server/protocol.def, server/snapshot.c, server/thread.c, server/thread.h +# | +if test "$enable_ntdll_ThreadTime" -eq 1; then + patch_apply ntdll-ThreadTime/0001-ntdll-Return-correct-values-in-GetThreadTimes-for-al.patch + patch_apply ntdll-ThreadTime/0002-ntdll-Set-correct-thread-creation-time-for-SystemPro.patch + patch_apply ntdll-ThreadTime/0003-ntdll-Fill-process-kernel-and-user-time.patch + patch_apply ntdll-ThreadTime/0004-ntdll-Set-process-start-time.patch + patch_apply ntdll-ThreadTime/0005-ntdll-Fill-out-thread-times-in-process-enumeration.patch + patch_apply ntdll-ThreadTime/0006-ntdll-Fill-process-virtual-memory-counters-in-NtQuer.patch + ( + printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Return correct values in GetThreadTimes() for all threads.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Set correct thread creation time for SystemProcessInformation in NtQuerySystemInformation.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Fill process kernel and user time.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Set process start time.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Fill out thread times in process enumeration.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Fill process virtual memory counters in NtQuerySystemInformation.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ntdll-Hide_Wine_Exports # | # | This patchset has the following (direct or indirect) dependencies: -# | * ntdll-Attach_Process_DLLs +# | * ntdll-Attach_Process_DLLs, ntdll-ThreadTime # | # | This patchset fixes the following Wine bugs: # | * [#38656] Add support for hiding wine version information from applications @@ -5458,6 +5498,21 @@ ) >> "$patchlist" fi +# Patchset ntdll-Interrupt-0x2e +# | +# | This patchset fixes the following Wine bugs: +# | * [#42647] Implement stub handler for int 0x2e +# | +# | Modified files: +# | * dlls/ntdll/signal_i386.c, include/wine/exception.h +# | +if test "$enable_ntdll_Interrupt_0x2e" -eq 1; then + patch_apply ntdll-Interrupt-0x2e/0001-ntdll-Catch-windows-int-0x2e-syscall-on-i386.patch + ( + printf '%s\n' '+ { "Michael Müller", "ntdll: Catch windows int 0x2e syscall on i386.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ntdll-NtQueryEaFile # | # | This patchset has the following (direct or indirect) dependencies: @@ -5504,6 +5559,20 @@ ) >> "$patchlist" fi +# Patchset ntdll-LDR_MODULE +# | +# | Modified files: +# | * dlls/ntdll/thread.c, include/winternl.h +# | +if test "$enable_ntdll_LDR_MODULE" -eq 1; then + patch_apply ntdll-LDR_MODULE/0001-ntdll-Mark-LDR-data-as-initialized.patch + patch_apply ntdll-LDR_MODULE/0002-include-Update-LDR_MODULE-to-more-recent-windows-ver.patch + ( + printf '%s\n' '+ { "Michael Müller", "ntdll: Mark LDR data as initialized.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "include: Update LDR_MODULE to more recent windows versions.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ntdll-RtlQueryPackageIdentity # | # | Modified files: @@ -5602,9 +5671,11 @@ if test "$enable_ntdll_NtQueryVirtualMemory" -eq 1; then patch_apply ntdll-NtQueryVirtualMemory/0001-ntdll-Implement-NtQueryVirtualMemory-MemorySectionNa.patch patch_apply ntdll-NtQueryVirtualMemory/0002-kernel32-Implement-K32GetMappedFileName.-v2.patch + patch_apply ntdll-NtQueryVirtualMemory/0003-ntdll-Fix-error-code-when-querying-too-large-memory-.patch ( printf '%s\n' '+ { "Dmitry Timoshkov", "ntdll: Implement NtQueryVirtualMemory(MemorySectionName).", 2 },'; printf '%s\n' '+ { "Dmitry Timoshkov", "kernel32: Implement K32GetMappedFileName.", 2 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Fix error code when querying too large memory address.", 1 },'; ) >> "$patchlist" fi @@ -5652,6 +5723,18 @@ ) >> "$patchlist" fi +# Patchset ntdll-ProcessImageFileNameWin32 +# | +# | Modified files: +# | * dlls/ntdll/process.c, include/winternl.h +# | +if test "$enable_ntdll_ProcessImageFileNameWin32" -eq 1; then + patch_apply ntdll-ProcessImageFileNameWin32/0001-ntdll-Implement-ProcessImageFileNameWin32-in-NtQuery.patch + ( + printf '%s\n' '+ { "Michael Müller", "ntdll: Implement ProcessImageFileNameWin32 in NtQueryInformationProcess.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ntdll-ProcessPriorityClass # | # | Modified files: @@ -5850,21 +5933,6 @@ ) >> "$patchlist" fi -# Patchset ntdll-ThreadTime -# | -# | This patchset fixes the following Wine bugs: -# | * [#20230] Return correct values for GetThreadTimes function -# | -# | Modified files: -# | * dlls/ntdll/thread.c, server/protocol.def, server/thread.c -# | -if test "$enable_ntdll_ThreadTime" -eq 1; then - patch_apply ntdll-ThreadTime/0001-ntdll-Return-correct-values-in-GetThreadTimes-for-al.patch - ( - printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Return correct values in GetThreadTimes() for all threads.", 1 },'; - ) >> "$patchlist" -fi - # Patchset ntdll-Threading # | # | Modified files: @@ -6005,18 +6073,6 @@ ) >> "$patchlist" fi -# Patchset ntdll-raise_func_trampoline -# | -# | Modified files: -# | * dlls/ntdll/signal_x86_64.c -# | -if test "$enable_ntdll_raise_func_trampoline" -eq 1; then - patch_apply ntdll-raise_func_trampoline/0001-ntdll-Save-rdi-and-rsi-in-raise_func_trampoline.patch - ( - printf '%s\n' '+ { "Andrew Wesie", "ntdll: Save rdi and rsi in raise_func_trampoline.", 1 },'; - ) >> "$patchlist" -fi - # Patchset ntoskrnl-DriverTest # | # | Modified files: @@ -6036,24 +6092,6 @@ ) >> "$patchlist" fi -# Patchset ntoskrnl-InStackQueuedSpinLock -# | -# | This patchset fixes the following Wine bugs: -# | * [#41472] Add stubs for Ke{Aquire,Release}InStackQueuedSpinLock functions -# | -# | Modified files: -# | * dlls/hal/hal.spec, dlls/ntoskrnl.exe/ntoskrnl.c, dlls/ntoskrnl.exe/ntoskrnl.exe.spec, include/ddk/wdm.h, -# | tools/make_specfiles -# | -if test "$enable_ntoskrnl_InStackQueuedSpinLock" -eq 1; then - patch_apply ntoskrnl-InStackQueuedSpinLock/0001-ntoskrnl.exe-add-KeAcquireInStackQueuedSpinLock-stub.patch - patch_apply ntoskrnl-InStackQueuedSpinLock/0002-ntoskrnl.exe-Add-KeReleaseInStackQueuedSpinLock-stub.patch - ( - printf '%s\n' '+ { "Austin English", "ntoskrnl.exe: Add KeAcquireInStackQueuedSpinLock stub.", 2 },'; - printf '%s\n' '+ { "Sebastian Lackner", "ntoskrnl.exe: Add KeReleaseInStackQueuedSpinLock stub.", 1 },'; - ) >> "$patchlist" -fi - # Patchset ntoskrnl-Stubs # | # | This patchset fixes the following Wine bugs: @@ -6063,7 +6101,6 @@ # | * dlls/ntoskrnl.exe/ntoskrnl.c, dlls/ntoskrnl.exe/ntoskrnl.exe.spec, include/ddk/wdm.h # | if test "$enable_ntoskrnl_Stubs" -eq 1; then - patch_apply ntoskrnl-Stubs/0001-ntoskrnl.exe-add-KeWaitForMultipleObjects-stub.patch patch_apply ntoskrnl-Stubs/0003-ntoskrnl.exe-Add-stubs-for-ExAcquireFastMutexUnsafe-.patch patch_apply ntoskrnl-Stubs/0004-ntoskrnl.exe-Add-stubs-for-ObReferenceObjectByPointe.patch patch_apply ntoskrnl-Stubs/0005-ntoskrnl.exe-Improve-KeReleaseMutex-stub.patch @@ -6074,7 +6111,6 @@ patch_apply ntoskrnl-Stubs/0010-ntoskrnl.exe-Implement-KeInitializeMutex.patch patch_apply ntoskrnl-Stubs/0011-ntoskrnl.exe-Add-IoGetDeviceAttachmentBaseRef-stub.patch ( - printf '%s\n' '+ { "Austin English", "ntoskrnl.exe: Add KeWaitForMultipleObjects stub.", 1 },'; printf '%s\n' '+ { "Alexander Morozov", "ntoskrnl.exe: Add stubs for ExAcquireFastMutexUnsafe and ExReleaseFastMutexUnsafe.", 1 },'; printf '%s\n' '+ { "Alexander Morozov", "ntoskrnl.exe: Add stub for ObReferenceObjectByPointer.", 1 },'; printf '%s\n' '+ { "Alexander Morozov", "ntoskrnl.exe: Improve KeReleaseMutex stub.", 1 },'; @@ -6523,21 +6559,6 @@ ) >> "$patchlist" fi -# Patchset rasapi32-RasEnumDevicesA -# | -# | This patchset fixes the following Wine bugs: -# | * [#30378] Initialize *lpcDevices in RasEnumDevicesA -# | -# | Modified files: -# | * dlls/rasapi32/rasapi.c, dlls/rasapi32/tests/rasapi.c -# | -if test "$enable_rasapi32_RasEnumDevicesA" -eq 1; then - patch_apply rasapi32-RasEnumDevicesA/0001-rasapi32-Set-lpcDevices-in-RasEnumDevicesA.patch - ( - printf '%s\n' '+ { "Sebastian Lackner", "rasapi32: Set *lpcDevices in RasEnumDevicesA.", 1 },'; - ) >> "$patchlist" -fi - # Patchset riched20-Class_Tests # | # | Modified files: @@ -6750,47 +6771,6 @@ ) >> "$patchlist" fi -# Patchset server-Pipe_ObjectName -# | -# | This patchset has the following (direct or indirect) dependencies: -# | * server-Desktop_Refcount, kernel32-Named_Pipe -# | -# | Modified files: -# | * dlls/ntdll/tests/om.c, server/named_pipe.c, server/object.c, server/object.h -# | -if test "$enable_server_Pipe_ObjectName" -eq 1; then - patch_apply server-Pipe_ObjectName/0001-server-Store-a-reference-to-the-parent-object-for-pi.patch - ( - printf '%s\n' '+ { "Sebastian Lackner", "server: Store a reference to the parent object for pipe servers.", 2 },'; - ) >> "$patchlist" -fi - -# Patchset server-Realtime_Priority -# | -# | Modified files: -# | * server/Makefile.in, server/main.c, server/scheduler.c, server/thread.c, server/thread.h -# | -if test "$enable_server_Realtime_Priority" -eq 1; then - patch_apply server-Realtime_Priority/0001-wineserver-Draft-to-implement-priority-levels-throug.patch - ( - printf '%s\n' '+ { "Joakim Hernberg", "wineserver: Draft to implement priority levels through POSIX scheduling policies on linux.", 1 },'; - ) >> "$patchlist" -fi - -# Patchset server-Registry_Notifications -# | -# | Modified files: -# | * dlls/ntdll/tests/reg.c, server/registry.c -# | -if test "$enable_server_Registry_Notifications" -eq 1; then - patch_apply server-Registry_Notifications/0001-server-Allow-multiple-registry-notifications-for-the.patch - patch_apply server-Registry_Notifications/0002-server-Introduce-refcounting-for-registry-notificati.patch - ( - printf '%s\n' '+ { "Sebastian Lackner", "server: Allow multiple registry notifications for the same key.", 1 },'; - printf '%s\n' '+ { "Sebastian Lackner", "server: Introduce refcounting for registry notifications.", 1 },'; - ) >> "$patchlist" -fi - # Patchset server-Signal_Thread # | # | Modified files: @@ -6837,6 +6817,88 @@ ) >> "$patchlist" fi +# Patchset server-Object_Types +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * server-Misc_ACL, ntdll-Threading, server-ClipCursor, server-Key_State, server-PeekMessage, server-Signal_Thread, server- +# | Shared_Memory +# | +# | Modified files: +# | * dlls/ntdll/nt.c, dlls/ntdll/om.c, dlls/ntdll/tests/info.c, dlls/ntdll/tests/om.c, include/winternl.h, +# | server/completion.c, server/directory.c, server/event.c, server/file.c, server/handle.c, server/mailslot.c, +# | server/main.c, server/mapping.c, server/mutex.c, server/named_pipe.c, server/object.c, server/object.h, +# | server/process.c, server/protocol.def, server/registry.c, server/semaphore.c, server/symlink.c, server/thread.c, +# | server/timer.c, server/token.c, server/winstation.c +# | +if test "$enable_server_Object_Types" -eq 1; then + patch_apply server-Object_Types/0001-ntdll-Implement-SystemExtendedHandleInformation-in-N.patch + patch_apply server-Object_Types/0002-ntdll-Implement-ObjectTypesInformation-in-NtQueryObj.patch + patch_apply server-Object_Types/0003-server-Register-types-during-startup.patch + patch_apply server-Object_Types/0004-server-Rename-ObjectType-to-Type.patch + patch_apply server-Object_Types/0005-server-Add-type-Token.patch + patch_apply server-Object_Types/0006-server-Add-type-Process.patch + patch_apply server-Object_Types/0007-server-Add-type-Thread.patch + patch_apply server-Object_Types/0008-ntdll-Set-TypeIndex-for-ObjectTypeInformation-in-NtQ.patch + patch_apply server-Object_Types/0009-ntdll-Set-object-type-for-System-Extended-HandleInfo.patch + patch_apply server-Object_Types/0010-ntdll-Mimic-object-type-behavior-for-different-windo.patch + ( + printf '%s\n' '+ { "Michael Müller", "ntdll: Implement SystemExtendedHandleInformation in NtQuerySystemInformation.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Implement ObjectTypesInformation in NtQueryObject.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "server: Register types during startup.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "server: Rename ObjectType to Type.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "server: Add type Token.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "server: Add type Process.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "server: Add type Thread.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Set TypeIndex for ObjectTypeInformation in NtQueryObject.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Set object type for System(Extended)HandleInformation in NtQuerySystemInformation.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Mimic object type behavior for different windows versions.", 1 },'; + ) >> "$patchlist" +fi + +# Patchset server-Pipe_ObjectName +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * server-Desktop_Refcount, kernel32-Named_Pipe +# | +# | Modified files: +# | * dlls/ntdll/tests/om.c, server/named_pipe.c, server/object.c, server/object.h +# | +if test "$enable_server_Pipe_ObjectName" -eq 1; then + patch_apply server-Pipe_ObjectName/0001-server-Store-a-reference-to-the-parent-object-for-pi.patch + ( + printf '%s\n' '+ { "Sebastian Lackner", "server: Store a reference to the parent object for pipe servers.", 2 },'; + ) >> "$patchlist" +fi + +# Patchset server-Realtime_Priority +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * ntdll-ThreadTime +# | +# | Modified files: +# | * server/Makefile.in, server/main.c, server/scheduler.c, server/thread.c, server/thread.h +# | +if test "$enable_server_Realtime_Priority" -eq 1; then + patch_apply server-Realtime_Priority/0001-wineserver-Draft-to-implement-priority-levels-throug.patch + ( + printf '%s\n' '+ { "Joakim Hernberg", "wineserver: Draft to implement priority levels through POSIX scheduling policies on linux.", 1 },'; + ) >> "$patchlist" +fi + +# Patchset server-Registry_Notifications +# | +# | Modified files: +# | * dlls/ntdll/tests/reg.c, server/registry.c +# | +if test "$enable_server_Registry_Notifications" -eq 1; then + patch_apply server-Registry_Notifications/0001-server-Allow-multiple-registry-notifications-for-the.patch + patch_apply server-Registry_Notifications/0002-server-Introduce-refcounting-for-registry-notificati.patch + ( + printf '%s\n' '+ { "Sebastian Lackner", "server: Allow multiple registry notifications for the same key.", 1 },'; + printf '%s\n' '+ { "Sebastian Lackner", "server: Introduce refcounting for registry notifications.", 1 },'; + ) >> "$patchlist" +fi + # Patchset server-Timestamp_Compat # | # | Modified files: @@ -7397,10 +7459,12 @@ patch_apply taskmgr-Memory_Usage/0002-ntdll-Report-system-information-SystemPerformanceInf.patch patch_apply taskmgr-Memory_Usage/0003-taskmgr-Use-system-font-instead-of-special-bitmap-fo.patch patch_apply taskmgr-Memory_Usage/0004-taskmgr-Use-different-units-depending-on-memory-usag.patch + patch_apply taskmgr-Memory_Usage/0005-ntdll-Implement-basic-IO-stats-for-SystemPerformance.patch ( printf '%s\n' '+ { "Michael Müller", "ntdll: Report system information SystemPerformanceInformation info class.", 2 },'; printf '%s\n' '+ { "Michael Müller", "taskmgr: Use system font instead of special bitmap font.", 1 },'; printf '%s\n' '+ { "Michael Müller", "taskmgr: Use different units depending on memory usage.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "ntdll: Implement basic IO stats for SystemPerformanceInformation in NtQuerySystemInformation.", 1 },'; ) >> "$patchlist" fi @@ -7769,6 +7833,30 @@ ) >> "$patchlist" fi +# Patchset user32-Sorted_Listbox +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * user32-WM_MEASUREITEM +# | +# | This patchset fixes the following Wine bugs: +# | * [#42602] Multiple fixes for owner-drawn and sorted listbox +# | +# | Modified files: +# | * dlls/user32/listbox.c, dlls/user32/tests/msg.c +# | +if test "$enable_user32_Sorted_Listbox" -eq 1; then + patch_apply user32-Sorted_Listbox/0001-user32-tests-Add-a-message-test-for-an-owner-drawn-s.patch + patch_apply user32-Sorted_Listbox/0002-user32-Fix-order-of-items-passed-in-WM_COMPAREITEM-d.patch + patch_apply user32-Sorted_Listbox/0003-user32-Fix-the-listbox-sorting-algorithm.patch + patch_apply user32-Sorted_Listbox/0004-user32-For-an-owner-drawn-listbox-without-strings-WM.patch + ( + printf '%s\n' '+ { "Dmitry Timoshkov", "user32/tests: Add a message test for an owner-drawn sorted listbox.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "user32: Fix order of items passed in WM_COMPAREITEM data.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "user32: Fix the listbox sorting algorithm.", 1 },'; + printf '%s\n' '+ { "Dmitry Timoshkov", "user32: For an owner-drawn listbox without strings WM_MEASUREITEM still needs correct itemData.", 1 },'; + ) >> "$patchlist" +fi + # Patchset uxtheme-CloseThemeClass # | # | This patchset fixes the following Wine bugs: @@ -7951,11 +8039,13 @@ patch_apply wbemprox-Win32_VideoController/0002-wbemprox-Add-Status-for-Win32_VideoController.patch patch_apply wbemprox-Win32_VideoController/0003-wbemprox-Add-InstalledDisplayDrivers-for-Win32_Video.patch patch_apply wbemprox-Win32_VideoController/0004-wbemprox-Add-DriverDate-for-Win32_VideoController.patch + patch_apply wbemprox-Win32_VideoController/0005-wbemprox-Add-Vendor-field-in-Win32_ComputerSystemPro.patch ( printf '%s\n' '+ { "Michael Müller", "wbemprox: Add ConfigManagerErrorCode for Win32_VideoController.", 1 },'; printf '%s\n' '+ { "Michael Müller", "wbemprox: Add Status for Win32_VideoController.", 1 },'; printf '%s\n' '+ { "Michael Müller", "wbemprox: Add InstalledDisplayDrivers for Win32_VideoController.", 1 },'; printf '%s\n' '+ { "Michael Müller", "wbemprox: Add DriverDate for Win32_VideoController.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "wbemprox: Add Vendor field in Win32_ComputerSystemProduct.", 1 },'; ) >> "$patchlist" fi @@ -8436,7 +8526,7 @@ # Patchset wined3d-Revert_Buffer_Upload # | # | Modified files: -# | * dlls/wined3d/buffer.c, dlls/wined3d/device.c, dlls/wined3d/wined3d_private.h +# | * dlls/wined3d/buffer.c, dlls/wined3d/cs.c, dlls/wined3d/wined3d_private.h # | if test "$enable_wined3d_Revert_Buffer_Upload" -eq 1; then patch_apply wined3d-Revert_Buffer_Upload/0001-Revert-wined3d-Implement-wined3d_buffer_upload_data-.patch @@ -8593,18 +8683,12 @@ printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Send render target view clears through the command stream.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Get rid of the end_scene flush and finish.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Send update_texture calls through the CS.", 1 },'; - printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Send update_sub_resource calls through the command stream.", 1 },'; - printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Send getdc and releasedc through the command stream.", 1 },'; printf '%s\n' '+ { "Sebastian Lackner", "wined3d: Send query_poll through the command stream.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Update the swap interval through the CS in reset.", 1 },'; - printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Create initial DCs through the CS.", 1 },'; printf '%s\n' '+ { "Nils Kuhnhenn", "wined3d: Fix context_acquire not being called from the command thread in wined3d_texture_add_dirty_region.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Wrap GL BOs in a structure.", 1 },'; - printf '%s\n' '+ { "Sebastian Lackner", "wined3d: Send buffer update subresource requests through CS.", 1 },'; - printf '%s\n' '+ { "Sebastian Lackner", "wined3d: Send buffer copy requests through CS.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Avoid destroying views in color and depth fills.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Add a separate variable to check if queries are started.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "wined3d: Map vertex buffers through cs.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Wait for the cs to finish before destroying the device.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Add swapchain waits.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Hackily introduce a multithreaded command stream.", 1 },'; @@ -8614,7 +8698,6 @@ printf '%s\n' '+ { "Sebastian Lackner", "wined3d: Use priority queue for query polls.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Don'\''t call glFinish before swapping.", 1 },'; printf '%s\n' '+ { "Stefan Dösinger", "wined3d: Use an event to block the worker thread when it is idle.", 1 },'; - printf '%s\n' '+ { "Sebastian Lackner", "wined3d: Use priority queue for get_dc / release_dc.", 1 },'; printf '%s\n' '+ { "Sebastian Lackner", "wined3d: Do not immediately submit stateblock updates.", 1 },'; printf '%s\n' '+ { "Sebastian Lackner", "wined3d: Use priority queue for update_sub_resource.", 1 },'; printf '%s\n' '+ { "Michael Müller", "wined3d: Use spin lock for cs list critical sections.", 1 },'; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/rasapi32-RasEnumDevicesA/0001-rasapi32-Set-lpcDevices-in-RasEnumDevicesA.patch wine-staging-2.4.0~ubuntu16.04.1/patches/rasapi32-RasEnumDevicesA/0001-rasapi32-Set-lpcDevices-in-RasEnumDevicesA.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/rasapi32-RasEnumDevicesA/0001-rasapi32-Set-lpcDevices-in-RasEnumDevicesA.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/rasapi32-RasEnumDevicesA/0001-rasapi32-Set-lpcDevices-in-RasEnumDevicesA.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -From 8377389407d8ab624c79cbb072e7c6e5c1b4a8d5 Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Sun, 28 Jun 2015 03:58:23 +0200 -Subject: rasapi32: Set *lpcDevices in RasEnumDevicesA. - -Based on a patch by Qian Hong. ---- - dlls/rasapi32/rasapi.c | 2 ++ - dlls/rasapi32/tests/rasapi.c | 21 +++++++++++++++++++++ - 2 files changed, 23 insertions(+) - -diff --git a/dlls/rasapi32/rasapi.c b/dlls/rasapi32/rasapi.c -index 235ab65..c2a4b55 100644 ---- a/dlls/rasapi32/rasapi.c -+++ b/dlls/rasapi32/rasapi.c -@@ -254,6 +254,8 @@ DWORD WINAPI RasEnumDevicesA(LPRASDEVINFOA lpRasDevinfo, LPDWORD lpcb, LPDWORD l - if(lpRasDevinfo && lpRasDevinfo->dwSize != sizeof(RASDEVINFOA)) - return ERROR_INVALID_SIZE; - -+ *lpcDevices = 1; -+ - if (!lpRasDevinfo || (*lpcb < sizeof(RASDEVINFOA))) { - *lpcb = sizeof(RASDEVINFOA); - return ERROR_BUFFER_TOO_SMALL; -diff --git a/dlls/rasapi32/tests/rasapi.c b/dlls/rasapi32/tests/rasapi.c -index e0ff25f..5171bb2 100644 ---- a/dlls/rasapi32/tests/rasapi.c -+++ b/dlls/rasapi32/tests/rasapi.c -@@ -77,54 +77,71 @@ static void test_rasenum(void) - - /* test first parameter */ - cb = bufsize; -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(NULL, &cb, &cDevices); -+ ok(0 < cDevices && cDevices < 32, "expected 0 < cDevices < 32, got %u\n", cDevices); - ok(result == ERROR_BUFFER_TOO_SMALL || - result == ERROR_INVALID_USER_BUFFER, /* win98 */ - "Expected ERROR_BUFFER_TOO_SMALL, got %08d\n", result); - - rasDevInfo[0].dwSize = 0; - cb = bufsize; -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); -+ ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); - ok(result == ERROR_INVALID_SIZE || - result == ERROR_INVALID_USER_BUFFER, /* win98 */ - "Expected ERROR_INVALID_SIZE, got %08d\n", result); - - rasDevInfo[0].dwSize = sizeof(RASDEVINFOA) -1; - cb = bufsize; -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); -+ ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); - ok(result == ERROR_INVALID_SIZE || - result == ERROR_INVALID_USER_BUFFER, /* win98 */ - "Expected ERROR_INVALID_SIZE, got %08d\n", result); - - rasDevInfo[0].dwSize = sizeof(RASDEVINFOA) +1; - cb = bufsize; -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); -+ ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); - ok(result == ERROR_INVALID_SIZE || - result == ERROR_INVALID_USER_BUFFER, /* win98 */ - "Expected ERROR_INVALID_SIZE, got %08d\n", result); - - /* test second parameter */ - rasDevInfo[0].dwSize = sizeof(RASDEVINFOA); -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(rasDevInfo, NULL, &cDevices); -+ ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); - ok(result == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %08d\n", result); - - rasDevInfo[0].dwSize = sizeof(RASDEVINFOA); - cb = 0; -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); -+ todo_wine -+ ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); - ok(result == ERROR_BUFFER_TOO_SMALL || - result == ERROR_INVALID_SIZE, /* vista, 2k8 */ - "Expected ERROR_BUFFER_TOO_SMALL/ERROR_INVALID_SIZE, got %08d\n", result); - - rasDevInfo[0].dwSize = sizeof(RASDEVINFOA); - cb = bufsize -1; -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); -+ ok(0 < cDevices && cDevices < 32, "expected 0 < cDevices < 32, got %u\n", cDevices); - ok(result == ERROR_BUFFER_TOO_SMALL, - "Expected ERROR_BUFFER_TOO_SMALL, got %08d\n", result); - - rasDevInfo[0].dwSize = sizeof(RASDEVINFOA); - cb = bufsize +1; -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); -+ ok(0 < cDevices && cDevices < 32, "expected 0 < cDevices < 32, got %u\n", cDevices); - ok(result == ERROR_SUCCESS, - "Expected ERROR_SUCCESS, got %08d\n", result); - -@@ -136,7 +153,9 @@ static void test_rasenum(void) - "Expected ERROR_INVALID_PARAMETER, got %08d\n", result); - - /* test combinations of invalid parameters */ -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(NULL, NULL, &cDevices); -+ ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); - ok(result == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %08d\n", result); - -@@ -147,7 +166,9 @@ static void test_rasenum(void) - - cb = 0; - rasDevInfo[0].dwSize = 0; -+ cDevices = 0xdeadbeef; - result = pRasEnumDevicesA(rasDevInfo, &cb, &cDevices); -+ ok(cDevices == 0xdeadbeef, "expected cDevices = 0xdeadbeef, got %u\n", cDevices); - ok(result == ERROR_INVALID_SIZE || - broken(result == ERROR_BUFFER_TOO_SMALL), /* win98 */ - "Expected ERROR_INVALID_SIZE, got %08d\n", result); --- -2.4.3 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/rasapi32-RasEnumDevicesA/definition wine-staging-2.4.0~ubuntu16.04.1/patches/rasapi32-RasEnumDevicesA/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/rasapi32-RasEnumDevicesA/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/rasapi32-RasEnumDevicesA/definition 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Fixes: [30378] Initialize *lpcDevices in RasEnumDevicesA diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0001-ntdll-Implement-SystemExtendedHandleInformation-in-N.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0001-ntdll-Implement-SystemExtendedHandleInformation-in-N.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0001-ntdll-Implement-SystemExtendedHandleInformation-in-N.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0001-ntdll-Implement-SystemExtendedHandleInformation-in-N.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,187 @@ +From 0384d32afa328e76bff7f8e508201ce2535ee763 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 7 Mar 2017 18:30:33 +0100 +Subject: ntdll: Implement SystemExtendedHandleInformation in + NtQuerySystemInformation. + +--- + dlls/ntdll/nt.c | 51 +++++++++++++++++++++++++++++++++++++++++ + dlls/ntdll/tests/info.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ + include/winternl.h | 21 +++++++++++++++++ + 3 files changed, 132 insertions(+) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index de8f16f9a0..a939298d19 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -2294,6 +2294,57 @@ NTSTATUS WINAPI NtQuerySystemInformation( + RtlFreeHeap( GetProcessHeap(), 0, info ); + } + break; ++ case SystemExtendedHandleInformation: ++ { ++ struct handle_info *info; ++ DWORD i, num_handles; ++ ++ if (Length < sizeof(SYSTEM_HANDLE_INFORMATION_EX)) ++ { ++ ret = STATUS_INFO_LENGTH_MISMATCH; ++ break; ++ } ++ ++ if (!SystemInformation) ++ { ++ ret = STATUS_ACCESS_VIOLATION; ++ break; ++ } ++ ++ num_handles = (Length - FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handle )); ++ num_handles /= sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX); ++ if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*info) * num_handles ))) ++ return STATUS_NO_MEMORY; ++ ++ SERVER_START_REQ( get_system_handles ) ++ { ++ wine_server_set_reply( req, info, sizeof(*info) * num_handles ); ++ if (!(ret = wine_server_call( req ))) ++ { ++ SYSTEM_HANDLE_INFORMATION_EX *shi = SystemInformation; ++ shi->Count = wine_server_reply_size( req ) / sizeof(*info); ++ shi->Reserved = 0; ++ len = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handle[shi->Count] ); ++ for (i = 0; i < shi->Count; i++) ++ { ++ memset( &shi->Handle[i], 0, sizeof(shi->Handle[i]) ); ++ shi->Handle[i].UniqueProcessId = info[i].owner; ++ shi->Handle[i].HandleValue = info[i].handle; ++ shi->Handle[i].GrantedAccess = info[i].access; ++ /* FIXME: Fill out remaining fields */ ++ } ++ } ++ else if (ret == STATUS_BUFFER_TOO_SMALL) ++ { ++ len = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handle[reply->count] ); ++ ret = STATUS_INFO_LENGTH_MISMATCH; ++ } ++ } ++ SERVER_END_REQ; ++ ++ RtlFreeHeap( GetProcessHeap(), 0, info ); ++ } ++ break; + case SystemCacheInformation: + { + SYSTEM_CACHE_INFORMATION sci; +diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c +index 32cb4f5a5d..c65a74bf5e 100644 +--- a/dlls/ntdll/tests/info.c ++++ b/dlls/ntdll/tests/info.c +@@ -561,6 +561,62 @@ done: + HeapFree( GetProcessHeap(), 0, shi); + } + ++static void test_query_handle_ex(void) ++{ ++ NTSTATUS status; ++ ULONG ExpectedLength, ReturnLength; ++ ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION_EX); ++ SYSTEM_HANDLE_INFORMATION_EX* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength); ++ HANDLE EventHandle; ++ BOOL found; ++ INT i; ++ ++ EventHandle = CreateEventA(NULL, FALSE, FALSE, NULL); ++ ok( EventHandle != NULL, "CreateEventA failed %u\n", GetLastError() ); ++ ++ ReturnLength = 0xdeadbeef; ++ status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength); ++ ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status); ++ ok( ReturnLength != 0xdeadbeef, "Expected valid ReturnLength\n" ); ++ ++ SystemInformationLength = ReturnLength; ++ shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength); ++ memset(shi, 0x55, SystemInformationLength); ++ ++ ReturnLength = 0xdeadbeef; ++ status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength); ++ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status ); ++ ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handle[shi->Count]); ++ ok( ReturnLength == ExpectedLength, "Expected length %u, got %u\n", ExpectedLength, ReturnLength ); ++ ok( shi->Count > 1, "Expected more than 1 handle, got %u\n", (DWORD)shi->Count ); ++ ++ for (i = 0, found = FALSE; i < shi->Count && !found; i++) ++ found = (shi->Handle[i].UniqueProcessId == GetCurrentProcessId()) && ++ ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle); ++ ok( found, "Expected to find event handle %p (pid %x) in handle list\n", EventHandle, GetCurrentProcessId() ); ++ ++ if (!found) ++ { ++ for (i = 0; i < shi->Count; i++) ++ trace( "%d: handle %x pid %x\n", i, (DWORD)shi->Handle[i].HandleValue, (DWORD)shi->Handle[i].UniqueProcessId ); ++ } ++ ++ CloseHandle(EventHandle); ++ ++ ReturnLength = 0xdeadbeef; ++ status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength); ++ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status ); ++ for (i = 0, found = FALSE; i < shi->Count && !found; i++) ++ found = (shi->Handle[i].UniqueProcessId == GetCurrentProcessId()) && ++ ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle); ++ ok( !found, "Unexpectedly found event handle in handle list\n" ); ++ ++ status = pNtQuerySystemInformation(SystemExtendedHandleInformation, NULL, SystemInformationLength, &ReturnLength); ++ ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status ); ++ ++ HeapFree( GetProcessHeap(), 0, shi); ++} ++ + static void test_query_cache(void) + { + NTSTATUS status; +@@ -2147,6 +2203,10 @@ START_TEST(info) + trace("Starting test_query_handle()\n"); + test_query_handle(); + ++ /* 0x40 SystemHandleInformation */ ++ trace("Starting test_query_handle_ex()\n"); ++ test_query_handle_ex(); ++ + /* 0x15 SystemCacheInformation */ + trace("Starting test_query_cache()\n"); + test_query_cache(); +diff --git a/include/winternl.h b/include/winternl.h +index 87b2c4d253..7ffe4f6c81 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -1442,6 +1442,27 @@ typedef struct _SYSTEM_HANDLE_INFORMATION { + SYSTEM_HANDLE_ENTRY Handle[1]; + } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + ++/* System Information Class 0x40 */ ++ ++typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX ++{ ++ PVOID Object; ++ ULONG_PTR UniqueProcessId; ++ ULONG_PTR HandleValue; ++ ULONG GrantedAccess; ++ USHORT CreatorBackTraceIndex; ++ USHORT ObjectTypeIndex; ++ ULONG HandleAttributes; ++ ULONG Reserved; ++} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; ++ ++typedef struct _SYSTEM_HANDLE_INFORMATION_EX ++{ ++ ULONG_PTR Count; ++ ULONG_PTR Reserved; ++ SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handle[1]; ++} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; ++ + /* System Information Class 0x15 */ + + typedef struct _SYSTEM_CACHE_INFORMATION { +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0002-ntdll-Implement-ObjectTypesInformation-in-NtQueryObj.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0002-ntdll-Implement-ObjectTypesInformation-in-NtQueryObj.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0002-ntdll-Implement-ObjectTypesInformation-in-NtQueryObj.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0002-ntdll-Implement-ObjectTypesInformation-in-NtQueryObj.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,278 @@ +From b3286b1c7ea9b507918c96f901d8e2c1311a4a1c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 02:12:37 +0100 +Subject: ntdll: Implement ObjectTypesInformation in NtQueryObject. + +--- + dlls/ntdll/om.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ + dlls/ntdll/tests/om.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ + include/winternl.h | 30 +++++++++++++++++++++++++-- + server/directory.c | 19 ++++++++++++++++- + server/protocol.def | 9 ++++++++ + 5 files changed, 163 insertions(+), 3 deletions(-) + +diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c +index 0f21800df6..8911a28b20 100644 +--- a/dlls/ntdll/om.c ++++ b/dlls/ntdll/om.c +@@ -43,6 +43,7 @@ + + WINE_DEFAULT_DEBUG_CHANNEL(ntdll); + ++#define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) + + /* + * Generic object functions +@@ -188,6 +189,56 @@ NTSTATUS WINAPI NtQueryObject(IN HANDLE handle, + SERVER_END_REQ; + } + break; ++ case ObjectTypesInformation: ++ { ++ OBJECT_TYPES_INFORMATION *p = ptr; ++ OBJECT_TYPE_INFORMATION *type = (OBJECT_TYPE_INFORMATION *)(p + 1); ++ ULONG count, type_len, req_len = sizeof(OBJECT_TYPES_INFORMATION); ++ ++ for (count = 0, status = STATUS_SUCCESS; !status; count++) ++ { ++ SERVER_START_REQ( get_object_type_by_index ) ++ { ++ req->index = count; ++ if (len > sizeof(*type)) ++ wine_server_set_reply( req, type + 1, len - sizeof(*type) ); ++ status = wine_server_call( req ); ++ if (status == STATUS_SUCCESS) ++ { ++ type_len = sizeof(*type); ++ if (reply->total) ++ type_len += ROUND_UP( reply->total + sizeof(WCHAR), sizeof(DWORD_PTR) ); ++ req_len += type_len; ++ } ++ if (status == STATUS_SUCCESS && len >= req_len) ++ { ++ ULONG res = wine_server_reply_size( reply ); ++ memset( type, 0, sizeof(*type) ); ++ if (reply->total) ++ { ++ type->TypeName.Buffer = (WCHAR *)(type + 1); ++ type->TypeName.Length = res; ++ type->TypeName.MaximumLength = res + sizeof(WCHAR); ++ type->TypeName.Buffer[res / sizeof(WCHAR)] = 0; ++ } ++ type->TypeIndex = count; ++ type = (OBJECT_TYPE_INFORMATION *)((char *)type + type_len); ++ } ++ } ++ SERVER_END_REQ; ++ } ++ ++ if (status != STATUS_NO_MORE_ENTRIES) ++ return status; ++ ++ if (used_len) *used_len = req_len; ++ if (len < req_len) ++ return STATUS_INFO_LENGTH_MISMATCH; ++ ++ p->NumberOfTypes = count - 1; ++ status = STATUS_SUCCESS; ++ } ++ break; + case ObjectDataInformation: + { + OBJECT_DATA_INFORMATION* p = ptr; +diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c +index 9a1ba670ab..534cb514f9 100644 +--- a/dlls/ntdll/tests/om.c ++++ b/dlls/ntdll/tests/om.c +@@ -74,6 +74,21 @@ static NTSTATUS (WINAPI *pNtOpenIoCompletion)( PHANDLE, ACCESS_MASK, POBJECT_ATT + #define KEYEDEVENT_WAKE 0x0002 + #define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x0003) + ++#define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) ++ ++static LPCSTR wine_dbgstr_us( const UNICODE_STRING *us ) ++{ ++ if (!us) return "(null)"; ++ return wine_dbgstr_wn(us->Buffer, us->Length / sizeof(WCHAR)); ++} ++ ++static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n ) ++{ ++ if (n <= 0) return 0; ++ while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; } ++ return *str1 - *str2; ++} ++ + static void test_case_sensitive (void) + { + static const WCHAR buffer1[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\\','t','e','s','t',0}; +@@ -1524,6 +1539,47 @@ static void test_query_object(void) + pRtlFreeUnicodeString( &session ); + } + ++static void test_query_object_types(void) ++{ ++ static const WCHAR typeW[] = {'T','y','p','e'}; ++ OBJECT_TYPES_INFORMATION *buffer; ++ OBJECT_TYPE_INFORMATION *type; ++ NTSTATUS status; ++ ULONG len, i; ++ ++ buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(OBJECT_TYPES_INFORMATION) ); ++ ok( buffer != NULL, "Failed to allocate memory\n" ); ++ ++ status = pNtQueryObject( NULL, ObjectTypesInformation, buffer, sizeof(OBJECT_TYPES_INFORMATION), &len ); ++ ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status ); ++ ok( len, "len is zero\n"); ++ ++ buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, len ); ++ ok( buffer != NULL, "Failed to allocate memory\n" ); ++ ++ memset( buffer, 0, len ); ++ status = pNtQueryObject( NULL, ObjectTypesInformation, buffer, len, &len ); ++ ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status ); ++ ok( buffer->NumberOfTypes, "NumberOfTypes is zero\n" ); ++ ++ type = (OBJECT_TYPE_INFORMATION *)(buffer + 1); ++ for (i = 0; i < buffer->NumberOfTypes; i++) ++ { ++ USHORT length = type->TypeName.MaximumLength; ++ trace( "Type %u: %s\n", i, wine_dbgstr_us(&type->TypeName) ); ++ ++ if (i == 0) ++ { ++ todo_wine ok( type->TypeName.Length == sizeof(typeW) && !strncmpW(typeW, type->TypeName.Buffer, 4), ++ "Expected 'Type' as first type, got %s\n", wine_dbgstr_us(&type->TypeName) ); ++ } ++ ++ type = (OBJECT_TYPE_INFORMATION *)ROUND_UP( (DWORD_PTR)(type + 1) + length, sizeof(DWORD_PTR) ); ++ } ++ ++ HeapFree( GetProcessHeap(), 0, buffer ); ++} ++ + static void test_type_mismatch(void) + { + HANDLE h; +@@ -2036,6 +2092,7 @@ START_TEST(om) + test_directory(); + test_symboliclink(); + test_query_object(); ++ test_query_object_types(); + test_type_mismatch(); + test_event(); + test_mutant(); +diff --git a/include/winternl.h b/include/winternl.h +index 7ffe4f6c81..0a2e323c5b 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -790,7 +790,7 @@ typedef enum _OBJECT_INFORMATION_CLASS { + ObjectBasicInformation, + ObjectNameInformation, + ObjectTypeInformation, +- ObjectAllInformation, ++ ObjectTypesInformation, + ObjectDataInformation + } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS; + +@@ -1208,9 +1208,35 @@ typedef struct _OBJECT_NAME_INFORMATION { + + typedef struct __OBJECT_TYPE_INFORMATION { + UNICODE_STRING TypeName; +- ULONG Reserved [22]; ++ ULONG TotalNumberOfObjects; ++ ULONG TotalNumberOfHandles; ++ ULONG TotalPagedPoolUsage; ++ ULONG TotalNonPagedPoolUsage; ++ ULONG TotalNamePoolUsage; ++ ULONG TotalHandleTableUsage; ++ ULONG HighWaterNumberOfObjects; ++ ULONG HighWaterNumberOfHandles; ++ ULONG HighWaterPagedPoolUsage; ++ ULONG HighWaterNonPagedPoolUsage; ++ ULONG HighWaterNamePoolUsage; ++ ULONG HighWaterHandleTableUsage; ++ ULONG InvalidAttributes; ++ GENERIC_MAPPING GenericMapping; ++ ULONG ValidAccessMask; ++ BOOLEAN SecurityRequired; ++ BOOLEAN MaintainHandleCount; ++ UCHAR TypeIndex; ++ CHAR Reserved; ++ ULONG PoolType; ++ ULONG DefaultPagedPoolCharge; ++ ULONG DefaultNonPagedPoolCharge; + } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + ++typedef struct _OBJECT_TYPES_INFORMATION ++{ ++ ULONG NumberOfTypes; ++} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION; ++ + typedef struct _PROCESS_BASIC_INFORMATION { + #ifdef __WINESRC__ + DWORD_PTR ExitStatus; +diff --git a/server/directory.c b/server/directory.c +index d903ff283c..ebec63e6c6 100644 +--- a/server/directory.c ++++ b/server/directory.c +@@ -72,6 +72,8 @@ static const struct object_ops object_type_ops = + no_destroy /* destroy */ + }; + ++static struct object_type *object_type_list[64]; ++static unsigned int object_type_count; + + struct directory + { +@@ -238,7 +240,8 @@ struct object_type *get_object_type( const struct unicode_str *name ) + { + if (get_error() != STATUS_OBJECT_NAME_EXISTS) + { +- grab_object( type ); ++ assert( object_type_count < sizeof(object_type_list)/sizeof(object_type_list[0]) ); ++ object_type_list[ object_type_count++ ] = (struct object_type *)grab_object( type ); + make_object_static( &type->obj ); + } + clear_error(); +@@ -531,3 +534,17 @@ DECL_HANDLER(get_object_type) + } + release_object( obj ); + } ++ ++/* query object type name information by index */ ++DECL_HANDLER(get_object_type_by_index) ++{ ++ struct object_type *type; ++ const WCHAR *name; ++ ++ if (req->index < object_type_count && (type = object_type_list[ req->index ])) ++ { ++ if ((name = get_object_name( &type->obj, &reply->total ))) ++ set_reply_data( name, min( reply->total, get_reply_max_size() ) ); ++ } ++ else set_error( STATUS_NO_MORE_ENTRIES ); ++} +diff --git a/server/protocol.def b/server/protocol.def +index 071129723f..98c4c58a4e 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -3548,6 +3548,15 @@ struct handle_info + @END + + ++/* Query object type name information */ ++@REQ(get_object_type_by_index) ++ unsigned int index; /* index of the type */ ++@REPLY ++ data_size_t total; /* needed size for type name */ ++ VARARG(type,unicode_str); /* type name */ ++@END ++ ++ + /* Unlink a named object */ + @REQ(unlink_object) + obj_handle_t handle; /* handle to the object */ +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0003-server-Register-types-during-startup.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0003-server-Register-types-during-startup.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0003-server-Register-types-during-startup.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0003-server-Register-types-during-startup.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,342 @@ +From 35a8bfa127fa1195bbb6454a79d8ff1a794ee9d9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 03:32:43 +0100 +Subject: server: Register types during startup. + +--- + server/completion.c | 3 +-- + server/directory.c | 6 ++---- + server/event.c | 6 ++---- + server/file.c | 3 +-- + server/mailslot.c | 3 +-- + server/main.c | 1 + + server/mapping.c | 3 +-- + server/mutex.c | 3 +-- + server/named_pipe.c | 3 +-- + server/object.c | 36 ++++++++++++++++++++++++++++++++++++ + server/object.h | 21 +++++++++++++++++++++ + server/process.c | 3 +-- + server/registry.c | 3 +-- + server/semaphore.c | 3 +-- + server/symlink.c | 3 +-- + server/timer.c | 3 +-- + server/winstation.c | 6 ++---- + 17 files changed, 75 insertions(+), 34 deletions(-) + +diff --git a/server/completion.c b/server/completion.c +index 72dbc5b821..af4a3f74e1 100644 +--- a/server/completion.c ++++ b/server/completion.c +@@ -110,8 +110,7 @@ static void completion_dump( struct object *obj, int verbose ) + + static struct object_type *completion_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'I','o','C','o','m','p','l','e','t','i','o','n'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_IoCompletion, sizeof(type_IoCompletion) }; + return get_object_type( &str ); + } + +diff --git a/server/directory.c b/server/directory.c +index ebec63e6c6..98dd2defa3 100644 +--- a/server/directory.c ++++ b/server/directory.c +@@ -121,8 +121,7 @@ static void object_type_dump( struct object *obj, int verbose ) + + static struct object_type *object_type_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'O','b','j','e','c','t','T','y','p','e'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_ObjectType, sizeof(type_ObjectType) }; + return get_object_type( &str ); + } + +@@ -133,8 +132,7 @@ static void directory_dump( struct object *obj, int verbose ) + + static struct object_type *directory_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'D','i','r','e','c','t','o','r','y'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Directory, sizeof(type_Directory) }; + return get_object_type( &str ); + } + +diff --git a/server/event.c b/server/event.c +index 608fafb94d..04ebda60a5 100644 +--- a/server/event.c ++++ b/server/event.c +@@ -161,8 +161,7 @@ static void event_dump( struct object *obj, int verbose ) + + static struct object_type *event_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'E','v','e','n','t'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Event, sizeof(type_Event) }; + return get_object_type( &str ); + } + +@@ -231,8 +230,7 @@ static void keyed_event_dump( struct object *obj, int verbose ) + + static struct object_type *keyed_event_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'K','e','y','e','d','E','v','e','n','t'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_KeyedEvent, sizeof(type_KeyedEvent) }; + return get_object_type( &str ); + } + +diff --git a/server/file.c b/server/file.c +index babbcc6a63..5c3ae775b3 100644 +--- a/server/file.c ++++ b/server/file.c +@@ -456,8 +456,7 @@ static void file_dump( struct object *obj, int verbose ) + + static struct object_type *file_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'F','i','l','e'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_File, sizeof(type_File) }; + return get_object_type( &str ); + } + +diff --git a/server/mailslot.c b/server/mailslot.c +index 04c4b9f50c..b69c957595 100644 +--- a/server/mailslot.c ++++ b/server/mailslot.c +@@ -349,8 +349,7 @@ static void mailslot_device_dump( struct object *obj, int verbose ) + + static struct object_type *mailslot_device_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'D','e','v','i','c','e'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ const struct unicode_str str = { type_Device, sizeof(type_Device) }; + return get_object_type( &str ); + } + +diff --git a/server/main.c b/server/main.c +index 313039a308..13af3b9feb 100644 +--- a/server/main.c ++++ b/server/main.c +@@ -148,6 +148,7 @@ int main( int argc, char *argv[] ) + init_directories(); + init_registry(); + init_shared_memory(); ++ init_types(); + main_loop(); + return 0; + } +diff --git a/server/mapping.c b/server/mapping.c +index 44fbe63793..9691dd832c 100644 +--- a/server/mapping.c ++++ b/server/mapping.c +@@ -728,8 +728,7 @@ static void mapping_dump( struct object *obj, int verbose ) + + static struct object_type *mapping_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'S','e','c','t','i','o','n'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Section, sizeof(type_Section) }; + return get_object_type( &str ); + } + +diff --git a/server/mutex.c b/server/mutex.c +index a2a0a24bdc..7ca41316ab 100644 +--- a/server/mutex.c ++++ b/server/mutex.c +@@ -142,8 +142,7 @@ static void mutex_dump( struct object *obj, int verbose ) + + static struct object_type *mutex_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'M','u','t','a','n','t'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Mutant, sizeof(type_Mutant) }; + return get_object_type( &str ); + } + +diff --git a/server/named_pipe.c b/server/named_pipe.c +index bc4b6f08fd..e3ebb4571e 100644 +--- a/server/named_pipe.c ++++ b/server/named_pipe.c +@@ -524,8 +524,7 @@ static void named_pipe_device_dump( struct object *obj, int verbose ) + + static struct object_type *named_pipe_device_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'D','e','v','i','c','e'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ const struct unicode_str str = { type_Device, sizeof(type_Device) }; + return get_object_type( &str ); + } + +diff --git a/server/object.c b/server/object.c +index 7281ef82ec..e6d20196a9 100644 +--- a/server/object.c ++++ b/server/object.c +@@ -710,3 +710,39 @@ int no_close_handle( struct object *obj, struct process *process, obj_handle_t h + void no_destroy( struct object *obj ) + { + } ++ ++static const struct unicode_str type_array[] = ++{ ++ {type_ObjectType, sizeof(type_ObjectType)}, ++ {type_Directory, sizeof(type_Directory)}, ++ {type_SymbolicLink, sizeof(type_SymbolicLink)}, ++ /* Token */ ++ {type_Job, sizeof(type_Job)}, ++ /* Process */ ++ /* Thread */ ++ {type_Event, sizeof(type_Event)}, ++ {type_Mutant, sizeof(type_Mutant)}, ++ {type_Semaphore, sizeof(type_Semaphore)}, ++ {type_Timer, sizeof(type_Timer)}, ++ {type_KeyedEvent, sizeof(type_KeyedEvent)}, ++ {type_WindowStation, sizeof(type_WindowStation)}, ++ {type_Desktop, sizeof(type_Desktop)}, ++ {type_Device, sizeof(type_Device)}, ++ /* Driver */ ++ {type_IoCompletion, sizeof(type_IoCompletion)}, ++ {type_File, sizeof(type_File)}, ++ {type_Section, sizeof(type_Section)}, ++ {type_Key, sizeof(type_Key)}, ++}; ++ ++void init_types(void) ++{ ++ struct object_type *type; ++ unsigned int i; ++ ++ for (i = 0; i < sizeof(type_array) / sizeof(type_array[0]); i++) ++ { ++ type = get_object_type(&type_array[i]); ++ if (type) release_object(type); ++ } ++} +diff --git a/server/object.h b/server/object.h +index 498186bc92..be71c705c5 100644 +--- a/server/object.h ++++ b/server/object.h +@@ -241,6 +241,27 @@ extern struct object_type *get_object_type( const struct unicode_str *name ); + extern int directory_link_name( struct object *obj, struct object_name *name, struct object *parent ); + extern void init_directories(void); + ++/* type functions */ ++ ++static const WCHAR type_Desktop[] = {'D','e','s','k','t','o','p'}; ++static const WCHAR type_Device[] = {'D','e','v','i','c','e'}; ++static const WCHAR type_Directory[] = {'D','i','r','e','c','t','o','r','y'}; ++static const WCHAR type_Event[] = {'E','v','e','n','t'}; ++static const WCHAR type_File[] = {'F','i','l','e'}; ++static const WCHAR type_IoCompletion[] = {'I','o','C','o','m','p','l','e','t','i','o','n'}; ++static const WCHAR type_Job[] = {'J','o','b'}; ++static const WCHAR type_Key[] = {'K','e','y'}; ++static const WCHAR type_KeyedEvent[] = {'K','e','y','e','d','E','v','e','n','t'}; ++static const WCHAR type_Mutant[] = {'M','u','t','a','n','t'}; ++static const WCHAR type_ObjectType[] = {'O','b','j','e','c','t','T','y','p','e'}; ++static const WCHAR type_Section[] = {'S','e','c','t','i','o','n'}; ++static const WCHAR type_Semaphore[] = {'S','e','m','a','p','h','o','r','e'}; ++static const WCHAR type_SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k'}; ++static const WCHAR type_Timer[] = {'T','i','m','e','r'}; ++static const WCHAR type_WindowStation[] = {'W','i','n','d','o','w','S','t','a','t','i','o','n'}; ++ ++extern void init_types(void); ++ + /* symbolic link functions */ + + extern struct object *create_obj_symlink( struct object *root, const struct unicode_str *name, +diff --git a/server/process.c b/server/process.c +index a59be6cfad..df1e9f1b0d 100644 +--- a/server/process.c ++++ b/server/process.c +@@ -214,8 +214,7 @@ static struct job *get_job_obj( struct process *process, obj_handle_t handle, un + + static struct object_type *job_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'J','o','b'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Job, sizeof(type_Job) }; + return get_object_type( &str ); + }; + +diff --git a/server/registry.c b/server/registry.c +index 368a56abcf..3a45f4f081 100644 +--- a/server/registry.c ++++ b/server/registry.c +@@ -314,8 +314,7 @@ static void key_dump( struct object *obj, int verbose ) + + static struct object_type *key_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'K','e','y'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Key, sizeof(type_Key) }; + return get_object_type( &str ); + } + +diff --git a/server/semaphore.c b/server/semaphore.c +index 15e7392513..60940aaa76 100644 +--- a/server/semaphore.c ++++ b/server/semaphore.c +@@ -128,8 +128,7 @@ static void semaphore_dump( struct object *obj, int verbose ) + + static struct object_type *semaphore_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'S','e','m','a','p','h','o','r','e'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Semaphore, sizeof(type_Semaphore) }; + return get_object_type( &str ); + } + +diff --git a/server/symlink.c b/server/symlink.c +index ecc0e4300c..33efdaa699 100644 +--- a/server/symlink.c ++++ b/server/symlink.c +@@ -87,8 +87,7 @@ static void symlink_dump( struct object *obj, int verbose ) + + static struct object_type *symlink_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'S','y','m','b','o','l','i','c','L','i','n','k'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_SymbolicLink, sizeof(type_SymbolicLink) }; + return get_object_type( &str ); + } + +diff --git a/server/timer.c b/server/timer.c +index 23c613b3cb..cb686b90f9 100644 +--- a/server/timer.c ++++ b/server/timer.c +@@ -190,8 +190,7 @@ static void timer_dump( struct object *obj, int verbose ) + + static struct object_type *timer_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'T','i','m','e','r'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Timer, sizeof(type_Timer) }; + return get_object_type( &str ); + } + +diff --git a/server/winstation.c b/server/winstation.c +index 39131d538e..d449ec667d 100644 +--- a/server/winstation.c ++++ b/server/winstation.c +@@ -166,8 +166,7 @@ static void winstation_dump( struct object *obj, int verbose ) + + static struct object_type *winstation_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'W','i','n','d','o','w','S','t','a','t','i','o','n'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_WindowStation, sizeof(type_WindowStation) }; + return get_object_type( &str ); + } + +@@ -271,8 +270,7 @@ static void desktop_dump( struct object *obj, int verbose ) + + static struct object_type *desktop_get_type( struct object *obj ) + { +- static const WCHAR name[] = {'D','e','s','k','t','o','p'}; +- static const struct unicode_str str = { name, sizeof(name) }; ++ static const struct unicode_str str = { type_Desktop, sizeof(type_Desktop) }; + return get_object_type( &str ); + } + +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0004-server-Rename-ObjectType-to-Type.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0004-server-Rename-ObjectType-to-Type.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0004-server-Rename-ObjectType-to-Type.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0004-server-Rename-ObjectType-to-Type.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,71 @@ +From 0498c01e0c379ccf5874b07fbbf3ec86b34f97ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 03:44:19 +0100 +Subject: server: Rename ObjectType to Type. + +--- + dlls/ntdll/tests/om.c | 2 +- + server/directory.c | 2 +- + server/object.c | 2 +- + server/object.h | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c +index 534cb514f9..02d83016e2 100644 +--- a/dlls/ntdll/tests/om.c ++++ b/dlls/ntdll/tests/om.c +@@ -1570,7 +1570,7 @@ static void test_query_object_types(void) + + if (i == 0) + { +- todo_wine ok( type->TypeName.Length == sizeof(typeW) && !strncmpW(typeW, type->TypeName.Buffer, 4), ++ ok( type->TypeName.Length == sizeof(typeW) && !strncmpW(typeW, type->TypeName.Buffer, 4), + "Expected 'Type' as first type, got %s\n", wine_dbgstr_us(&type->TypeName) ); + } + +diff --git a/server/directory.c b/server/directory.c +index 98dd2defa3..b4f53e2edf 100644 +--- a/server/directory.c ++++ b/server/directory.c +@@ -121,7 +121,7 @@ static void object_type_dump( struct object *obj, int verbose ) + + static struct object_type *object_type_get_type( struct object *obj ) + { +- static const struct unicode_str str = { type_ObjectType, sizeof(type_ObjectType) }; ++ static const struct unicode_str str = { type_Type, sizeof(type_Type) }; + return get_object_type( &str ); + } + +diff --git a/server/object.c b/server/object.c +index e6d20196a9..960422df1c 100644 +--- a/server/object.c ++++ b/server/object.c +@@ -713,7 +713,7 @@ void no_destroy( struct object *obj ) + + static const struct unicode_str type_array[] = + { +- {type_ObjectType, sizeof(type_ObjectType)}, ++ {type_Type, sizeof(type_Type)}, + {type_Directory, sizeof(type_Directory)}, + {type_SymbolicLink, sizeof(type_SymbolicLink)}, + /* Token */ +diff --git a/server/object.h b/server/object.h +index be71c705c5..0ed46b159d 100644 +--- a/server/object.h ++++ b/server/object.h +@@ -253,11 +253,11 @@ static const WCHAR type_Job[] = {'J','o','b'}; + static const WCHAR type_Key[] = {'K','e','y'}; + static const WCHAR type_KeyedEvent[] = {'K','e','y','e','d','E','v','e','n','t'}; + static const WCHAR type_Mutant[] = {'M','u','t','a','n','t'}; +-static const WCHAR type_ObjectType[] = {'O','b','j','e','c','t','T','y','p','e'}; + static const WCHAR type_Section[] = {'S','e','c','t','i','o','n'}; + static const WCHAR type_Semaphore[] = {'S','e','m','a','p','h','o','r','e'}; + static const WCHAR type_SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k'}; + static const WCHAR type_Timer[] = {'T','i','m','e','r'}; ++static const WCHAR type_Type[] = {'T','y','p','e'}; + static const WCHAR type_WindowStation[] = {'W','i','n','d','o','w','S','t','a','t','i','o','n'}; + + extern void init_types(void); +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0005-server-Add-type-Token.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0005-server-Add-type-Token.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0005-server-Add-type-Token.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0005-server-Add-type-Token.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,73 @@ +From b4ba31df8d342f736a590977ba950d6f07f2377c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 03:48:02 +0100 +Subject: server: Add type Token. + +--- + server/object.c | 2 +- + server/object.h | 1 + + server/token.c | 9 ++++++++- + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/server/object.c b/server/object.c +index 960422df1c..c2c877f692 100644 +--- a/server/object.c ++++ b/server/object.c +@@ -716,7 +716,7 @@ static const struct unicode_str type_array[] = + {type_Type, sizeof(type_Type)}, + {type_Directory, sizeof(type_Directory)}, + {type_SymbolicLink, sizeof(type_SymbolicLink)}, +- /* Token */ ++ {type_Token, sizeof(type_Token)}, + {type_Job, sizeof(type_Job)}, + /* Process */ + /* Thread */ +diff --git a/server/object.h b/server/object.h +index 0ed46b159d..46a9f770ca 100644 +--- a/server/object.h ++++ b/server/object.h +@@ -257,6 +257,7 @@ static const WCHAR type_Section[] = {'S','e','c','t','i','o','n'}; + static const WCHAR type_Semaphore[] = {'S','e','m','a','p','h','o','r','e'}; + static const WCHAR type_SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k'}; + static const WCHAR type_Timer[] = {'T','i','m','e','r'}; ++static const WCHAR type_Token[] = {'T','o','k','e','n'}; + static const WCHAR type_Type[] = {'T','y','p','e'}; + static const WCHAR type_WindowStation[] = {'W','i','n','d','o','w','S','t','a','t','i','o','n'}; + +diff --git a/server/token.c b/server/token.c +index 3b5c498147..f0afb95868 100644 +--- a/server/token.c ++++ b/server/token.c +@@ -150,6 +150,7 @@ struct group + }; + + static void token_dump( struct object *obj, int verbose ); ++static struct object_type *token_get_type( struct object *obj ); + static unsigned int token_map_access( struct object *obj, unsigned int access ); + static void token_destroy( struct object *obj ); + +@@ -157,7 +158,7 @@ static const struct object_ops token_ops = + { + sizeof(struct token), /* size */ + token_dump, /* dump */ +- no_get_type, /* get_type */ ++ token_get_type, /* get_type */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ +@@ -183,6 +184,12 @@ static void token_dump( struct object *obj, int verbose ) + /* FIXME: dump token members */ + } + ++static struct object_type *token_get_type( struct object *obj ) ++{ ++ static const struct unicode_str str = { type_Token, sizeof(type_Token) }; ++ return get_object_type( &str ); ++} ++ + static unsigned int token_map_access( struct object *obj, unsigned int access ) + { + if (access & GENERIC_READ) access |= TOKEN_READ; +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0006-server-Add-type-Process.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0006-server-Add-type-Process.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0006-server-Add-type-Process.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0006-server-Add-type-Process.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,73 @@ +From 97057ab129833bd9fdcf683e05a44c0d06330edd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 03:52:47 +0100 +Subject: server: Add type Process. + +--- + server/object.c | 2 +- + server/object.h | 1 + + server/process.c | 9 ++++++++- + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/server/object.c b/server/object.c +index c2c877f692..f7c249689f 100644 +--- a/server/object.c ++++ b/server/object.c +@@ -718,7 +718,7 @@ static const struct unicode_str type_array[] = + {type_SymbolicLink, sizeof(type_SymbolicLink)}, + {type_Token, sizeof(type_Token)}, + {type_Job, sizeof(type_Job)}, +- /* Process */ ++ {type_Process, sizeof(type_Process)}, + /* Thread */ + {type_Event, sizeof(type_Event)}, + {type_Mutant, sizeof(type_Mutant)}, +diff --git a/server/object.h b/server/object.h +index 46a9f770ca..cca12b6cf0 100644 +--- a/server/object.h ++++ b/server/object.h +@@ -253,6 +253,7 @@ static const WCHAR type_Job[] = {'J','o','b'}; + static const WCHAR type_Key[] = {'K','e','y'}; + static const WCHAR type_KeyedEvent[] = {'K','e','y','e','d','E','v','e','n','t'}; + static const WCHAR type_Mutant[] = {'M','u','t','a','n','t'}; ++static const WCHAR type_Process[] = {'P','r','o','c','e','s','s'}; + static const WCHAR type_Section[] = {'S','e','c','t','i','o','n'}; + static const WCHAR type_Semaphore[] = {'S','e','m','a','p','h','o','r','e'}; + static const WCHAR type_SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k'}; +diff --git a/server/process.c b/server/process.c +index df1e9f1b0d..de3e926717 100644 +--- a/server/process.c ++++ b/server/process.c +@@ -60,6 +60,7 @@ static int shutdown_stage; /* current stage in the shutdown process */ + /* process operations */ + + static void process_dump( struct object *obj, int verbose ); ++static struct object_type *process_get_type( struct object *obj ); + static int process_signaled( struct object *obj, struct wait_queue_entry *entry ); + static unsigned int process_map_access( struct object *obj, unsigned int access ); + static struct security_descriptor *process_get_sd( struct object *obj ); +@@ -71,7 +72,7 @@ static const struct object_ops process_ops = + { + sizeof(struct process), /* size */ + process_dump, /* dump */ +- no_get_type, /* get_type */ ++ process_get_type, /* get_type */ + add_queue, /* add_queue */ + remove_queue, /* remove_queue */ + process_signaled, /* signaled */ +@@ -655,6 +656,12 @@ static void process_dump( struct object *obj, int verbose ) + fprintf( stderr, "Process id=%04x handles=%p\n", process->id, process->handles ); + } + ++static struct object_type *process_get_type( struct object *obj ) ++{ ++ static const struct unicode_str str = { type_Process, sizeof(type_Process) }; ++ return get_object_type( &str ); ++} ++ + static int process_signaled( struct object *obj, struct wait_queue_entry *entry ) + { + struct process *process = (struct process *)obj; +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0007-server-Add-type-Thread.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0007-server-Add-type-Thread.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0007-server-Add-type-Thread.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0007-server-Add-type-Thread.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,73 @@ +From ef0142aadbcbd3e36ff3e2473dca76e68ba5ecba Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 03:56:00 +0100 +Subject: server: Add type Thread. + +--- + server/object.c | 2 +- + server/object.h | 1 + + server/thread.c | 9 ++++++++- + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/server/object.c b/server/object.c +index f7c249689f..37ac0adce6 100644 +--- a/server/object.c ++++ b/server/object.c +@@ -719,7 +719,7 @@ static const struct unicode_str type_array[] = + {type_Token, sizeof(type_Token)}, + {type_Job, sizeof(type_Job)}, + {type_Process, sizeof(type_Process)}, +- /* Thread */ ++ {type_Thread, sizeof(type_Thread)}, + {type_Event, sizeof(type_Event)}, + {type_Mutant, sizeof(type_Mutant)}, + {type_Semaphore, sizeof(type_Semaphore)}, +diff --git a/server/object.h b/server/object.h +index cca12b6cf0..3ba3f4b431 100644 +--- a/server/object.h ++++ b/server/object.h +@@ -257,6 +257,7 @@ static const WCHAR type_Process[] = {'P','r','o','c','e','s','s'}; + static const WCHAR type_Section[] = {'S','e','c','t','i','o','n'}; + static const WCHAR type_Semaphore[] = {'S','e','m','a','p','h','o','r','e'}; + static const WCHAR type_SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k'}; ++static const WCHAR type_Thread[] = {'T','h','r','e','a','d'}; + static const WCHAR type_Timer[] = {'T','i','m','e','r'}; + static const WCHAR type_Token[] = {'T','o','k','e','n'}; + static const WCHAR type_Type[] = {'T','y','p','e'}; +diff --git a/server/thread.c b/server/thread.c +index 53e94fda42..108444ebc5 100644 +--- a/server/thread.c ++++ b/server/thread.c +@@ -129,6 +129,7 @@ static const struct object_ops thread_apc_ops = + /* thread operations */ + + static void dump_thread( struct object *obj, int verbose ); ++static struct object_type *thread_get_type( struct object *obj ); + static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ); + static unsigned int thread_map_access( struct object *obj, unsigned int access ); + static void thread_poll_event( struct fd *fd, int event ); +@@ -138,7 +139,7 @@ static const struct object_ops thread_ops = + { + sizeof(struct thread), /* size */ + dump_thread, /* dump */ +- no_get_type, /* get_type */ ++ thread_get_type, /* get_type */ + add_queue, /* add_queue */ + remove_queue, /* remove_queue */ + thread_signaled, /* signaled */ +@@ -344,6 +345,12 @@ static void dump_thread( struct object *obj, int verbose ) + thread->id, thread->unix_pid, thread->unix_tid, thread->state ); + } + ++static struct object_type *thread_get_type( struct object *obj ) ++{ ++ static const struct unicode_str str = { type_Thread, sizeof(type_Thread) }; ++ return get_object_type( &str ); ++} ++ + static int thread_signaled( struct object *obj, struct wait_queue_entry *entry ) + { + struct thread *mythread = (struct thread *)obj; +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0008-ntdll-Set-TypeIndex-for-ObjectTypeInformation-in-NtQ.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0008-ntdll-Set-TypeIndex-for-ObjectTypeInformation-in-NtQ.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0008-ntdll-Set-TypeIndex-for-ObjectTypeInformation-in-NtQ.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0008-ntdll-Set-TypeIndex-for-ObjectTypeInformation-in-NtQ.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,71 @@ +From 1e3e93483b223c6e0e9d712fff4a8874c503c973 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 17:41:11 +0100 +Subject: ntdll: Set TypeIndex for ObjectTypeInformation in NtQueryObject. + +--- + dlls/ntdll/om.c | 4 ++++ + server/directory.c | 5 ++++- + server/protocol.def | 1 + + 3 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c +index 8911a28b20..8f54d4f49f 100644 +--- a/dlls/ntdll/om.c ++++ b/dlls/ntdll/om.c +@@ -184,6 +184,10 @@ NTSTATUS WINAPI NtQueryObject(IN HANDLE handle, + p->TypeName.Buffer[res / sizeof(WCHAR)] = 0; + if (used_len) *used_len = sizeof(*p) + p->TypeName.MaximumLength; + } ++ if (status == STATUS_SUCCESS) ++ { ++ p->TypeIndex = reply->index; ++ } + } + } + SERVER_END_REQ; +diff --git a/server/directory.c b/server/directory.c +index b4f53e2edf..59c8194d09 100644 +--- a/server/directory.c ++++ b/server/directory.c +@@ -44,6 +44,7 @@ + struct object_type + { + struct object obj; /* object header */ ++ unsigned int index; /* type index */ + }; + + static void object_type_dump( struct object *obj, int verbose ); +@@ -239,7 +240,8 @@ struct object_type *get_object_type( const struct unicode_str *name ) + if (get_error() != STATUS_OBJECT_NAME_EXISTS) + { + assert( object_type_count < sizeof(object_type_list)/sizeof(object_type_list[0]) ); +- object_type_list[ object_type_count++ ] = (struct object_type *)grab_object( type ); ++ type->index = object_type_count++; ++ object_type_list[ type->index ] = (struct object_type *)grab_object( type ); + make_object_static( &type->obj ); + } + clear_error(); +@@ -528,6 +530,7 @@ DECL_HANDLER(get_object_type) + { + if ((name = get_object_name( &type->obj, &reply->total ))) + set_reply_data( name, min( reply->total, get_reply_max_size() ) ); ++ reply->index = type->index; + release_object( type ); + } + release_object( obj ); +diff --git a/server/protocol.def b/server/protocol.def +index 98c4c58a4e..d6847f8d55 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -3543,6 +3543,7 @@ struct handle_info + @REQ(get_object_type) + obj_handle_t handle; /* handle to the object */ + @REPLY ++ unsigned int index; /* type index */ + data_size_t total; /* needed size for type name */ + VARARG(type,unicode_str); /* type name */ + @END +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0009-ntdll-Set-object-type-for-System-Extended-HandleInfo.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0009-ntdll-Set-object-type-for-System-Extended-HandleInfo.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0009-ntdll-Set-object-type-for-System-Extended-HandleInfo.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0009-ntdll-Set-object-type-for-System-Extended-HandleInfo.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,108 @@ +From ba10e334a375c7dde7cd890554fbbade1be81a9d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 17:44:17 +0100 +Subject: ntdll: Set object type for System(Extended)HandleInformation in + NtQuerySystemInformation. + +--- + dlls/ntdll/nt.c | 4 +++- + server/directory.c | 6 ++++++ + server/handle.c | 10 ++++++++++ + server/object.h | 1 + + server/protocol.def | 1 + + 5 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index a939298d19..211b67f98b 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -2280,7 +2280,8 @@ NTSTATUS WINAPI NtQuerySystemInformation( + shi->Handle[i].OwnerPid = info[i].owner; + shi->Handle[i].HandleValue = info[i].handle; + shi->Handle[i].AccessMask = info[i].access; +- /* FIXME: Fill out ObjectType, HandleFlags, ObjectPointer */ ++ shi->Handle[i].ObjectType = info[i].type; ++ /* FIXME: Fill out HandleFlags, ObjectPointer */ + } + } + else if (ret == STATUS_BUFFER_TOO_SMALL) +@@ -2331,6 +2332,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + shi->Handle[i].UniqueProcessId = info[i].owner; + shi->Handle[i].HandleValue = info[i].handle; + shi->Handle[i].GrantedAccess = info[i].access; ++ shi->Handle[i].ObjectTypeIndex = info[i].type; + /* FIXME: Fill out remaining fields */ + } + } +diff --git a/server/directory.c b/server/directory.c +index 59c8194d09..f61a5cecf1 100644 +--- a/server/directory.c ++++ b/server/directory.c +@@ -249,6 +249,12 @@ struct object_type *get_object_type( const struct unicode_str *name ) + return type; + } + ++/* retrieve the object type index */ ++unsigned int type_get_index( struct object_type *type ) ++{ ++ return type->index; ++} ++ + /* Global initialization */ + + static void create_session( unsigned int id ) +diff --git a/server/handle.c b/server/handle.c +index 0e909ff27e..e29cead46b 100644 +--- a/server/handle.c ++++ b/server/handle.c +@@ -971,6 +971,7 @@ static int enum_handles( struct process *process, void *user ) + struct handle_table *table = process->handles; + struct handle_entry *entry; + struct handle_info *handle; ++ struct object_type *type; + unsigned int i; + + if (!table) +@@ -989,6 +990,15 @@ static int enum_handles( struct process *process, void *user ) + handle->owner = process->id; + handle->handle = index_to_handle(i); + handle->access = entry->access & ~RESERVED_ALL; ++ ++ if ((type = entry->ptr->ops->get_type(entry->ptr))) ++ { ++ handle->type = type_get_index(type); ++ release_object(type); ++ } ++ else ++ handle->type = 0; ++ + info->count--; + } + +diff --git a/server/object.h b/server/object.h +index 3ba3f4b431..4a5d282a47 100644 +--- a/server/object.h ++++ b/server/object.h +@@ -264,6 +264,7 @@ static const WCHAR type_Type[] = {'T','y','p','e'}; + static const WCHAR type_WindowStation[] = {'W','i','n','d','o','w','S','t','a','t','i','o','n'}; + + extern void init_types(void); ++extern unsigned int type_get_index( struct object_type *type ); + + /* symbolic link functions */ + +diff --git a/server/protocol.def b/server/protocol.def +index d6847f8d55..35730d60cb 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -3433,6 +3433,7 @@ struct handle_info + process_id_t owner; + obj_handle_t handle; + unsigned int access; ++ unsigned int type; + }; + + /* Return a list of all opened handles */ +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0010-ntdll-Mimic-object-type-behavior-for-different-windo.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0010-ntdll-Mimic-object-type-behavior-for-different-windo.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/0010-ntdll-Mimic-object-type-behavior-for-different-windo.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/0010-ntdll-Mimic-object-type-behavior-for-different-windo.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,180 @@ +From c157e1ed4e1a3f373471bb49f1a8c536ea0ce2cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 19:39:29 +0100 +Subject: ntdll: Mimic object type behavior for different windows versions. + +--- + dlls/ntdll/nt.c | 17 ++++++++++++-- + dlls/ntdll/om.c | 5 +++- + dlls/ntdll/tests/om.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 83 insertions(+), 4 deletions(-) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index 211b67f98b..1dd890c4bd 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -70,6 +70,19 @@ + + WINE_DEFAULT_DEBUG_CHANNEL(ntdll); + ++static DWORD translate_object_index(DWORD index) ++{ ++ WORD version = MAKEWORD(NtCurrentTeb()->Peb->OSMinorVersion, NtCurrentTeb()->Peb->OSMajorVersion); ++ ++ /* Process Hacker depends on this logic */ ++ if (version >= 0x0602) ++ return index; ++ else if (version == 0x0601) ++ return index + 2; ++ else ++ return index + 1; ++} ++ + /* + * Token + */ +@@ -2280,7 +2293,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + shi->Handle[i].OwnerPid = info[i].owner; + shi->Handle[i].HandleValue = info[i].handle; + shi->Handle[i].AccessMask = info[i].access; +- shi->Handle[i].ObjectType = info[i].type; ++ shi->Handle[i].ObjectType = translate_object_index(info[i].type); + /* FIXME: Fill out HandleFlags, ObjectPointer */ + } + } +@@ -2332,7 +2345,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( + shi->Handle[i].UniqueProcessId = info[i].owner; + shi->Handle[i].HandleValue = info[i].handle; + shi->Handle[i].GrantedAccess = info[i].access; +- shi->Handle[i].ObjectTypeIndex = info[i].type; ++ shi->Handle[i].ObjectTypeIndex = translate_object_index(info[i].type); + /* FIXME: Fill out remaining fields */ + } + } +diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c +index 8f54d4f49f..92fc654448 100644 +--- a/dlls/ntdll/om.c ++++ b/dlls/ntdll/om.c +@@ -186,7 +186,10 @@ NTSTATUS WINAPI NtQueryObject(IN HANDLE handle, + } + if (status == STATUS_SUCCESS) + { +- p->TypeIndex = reply->index; ++ WORD version = MAKEWORD(NtCurrentTeb()->Peb->OSMinorVersion, ++ NtCurrentTeb()->Peb->OSMajorVersion); ++ if (version >= 0x0602) ++ p->TypeIndex = reply->index; + } + } + } +diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c +index 02d83016e2..84b783b80a 100644 +--- a/dlls/ntdll/tests/om.c ++++ b/dlls/ntdll/tests/om.c +@@ -69,6 +69,7 @@ static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, c + static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * ); + static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG); + static NTSTATUS (WINAPI *pNtOpenIoCompletion)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES ); ++static NTSTATUS (WINAPI *pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); + + #define KEYEDEVENT_WAIT 0x0001 + #define KEYEDEVENT_WAKE 0x0002 +@@ -1539,13 +1540,31 @@ static void test_query_object(void) + pRtlFreeUnicodeString( &session ); + } + ++static BOOL winver_equal_or_newer(WORD major, WORD minor) ++{ ++ OSVERSIONINFOEXW info = {sizeof(info)}; ++ ULONGLONG mask = 0; ++ ++ info.dwMajorVersion = major; ++ info.dwMinorVersion = minor; ++ ++ VER_SET_CONDITION(mask, VER_MAJORVERSION, VER_GREATER_EQUAL); ++ VER_SET_CONDITION(mask, VER_MINORVERSION, VER_GREATER_EQUAL); ++ ++ return VerifyVersionInfoW(&info, VER_MAJORVERSION | VER_MINORVERSION, mask); ++} ++ + static void test_query_object_types(void) + { + static const WCHAR typeW[] = {'T','y','p','e'}; ++ static const WCHAR eventW[] = {'E','v','e','n','t'}; ++ SYSTEM_HANDLE_INFORMATION_EX *shi; + OBJECT_TYPES_INFORMATION *buffer; + OBJECT_TYPE_INFORMATION *type; + NTSTATUS status; +- ULONG len, i; ++ HANDLE handle; ++ BOOL found; ++ ULONG len, i, event_type_index = 0; + + buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(OBJECT_TYPES_INFORMATION) ); + ok( buffer != NULL, "Failed to allocate memory\n" ); +@@ -1573,11 +1592,54 @@ static void test_query_object_types(void) + ok( type->TypeName.Length == sizeof(typeW) && !strncmpW(typeW, type->TypeName.Buffer, 4), + "Expected 'Type' as first type, got %s\n", wine_dbgstr_us(&type->TypeName) ); + } ++ if (type->TypeName.Length == sizeof(eventW) && !strncmpW(eventW, type->TypeName.Buffer, 5)) ++ { ++ if (winver_equal_or_newer( 6, 2 )) ++ event_type_index = type->TypeIndex; ++ else ++ event_type_index = winver_equal_or_newer( 6, 1 ) ? i + 2 : i + 1; ++ } + + type = (OBJECT_TYPE_INFORMATION *)ROUND_UP( (DWORD_PTR)(type + 1) + length, sizeof(DWORD_PTR) ); + } + + HeapFree( GetProcessHeap(), 0, buffer ); ++ ++ ok( event_type_index, "Could not find object type for events\n" ); ++ ++ handle = CreateEventA( NULL, FALSE, FALSE, NULL ); ++ ok( handle != NULL, "Failed to create event\n" ); ++ ++ shi = HeapAlloc( GetProcessHeap(), 0, sizeof(*shi) ); ++ ok( shi != NULL, "Failed to allocate memory\n" ); ++ ++ status = pNtQuerySystemInformation( SystemExtendedHandleInformation, shi, sizeof(*shi), &len ); ++ ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status ); ++ ++ shi = HeapReAlloc( GetProcessHeap(), 0, shi, len ); ++ ok( shi != NULL, "Failed to allocate memory\n" ); ++ ++ status = pNtQuerySystemInformation( SystemExtendedHandleInformation, shi, len, &len ); ++ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status ); ++ ++ found = FALSE; ++ for (i = 0; i < shi->Count; i++) ++ { ++ if (shi->Handle[i].UniqueProcessId != GetCurrentProcessId()) ++ continue; ++ if ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue != handle) ++ continue; ++ ++ ok( shi->Handle[i].ObjectTypeIndex == event_type_index, "Event type does not match: %u vs %u\n", ++ shi->Handle[i].ObjectTypeIndex, event_type_index ); ++ ++ found = TRUE; ++ break; ++ } ++ ok( found, "Expected to find event handle %p (pid %x) in handle list\n", handle, GetCurrentProcessId() ); ++ ++ HeapFree( GetProcessHeap(), 0, shi ); ++ CloseHandle( handle ); + } + + static void test_type_mismatch(void) +@@ -2084,6 +2146,7 @@ START_TEST(om) + pNtReleaseKeyedEvent = (void *)GetProcAddress(hntdll, "NtReleaseKeyedEvent"); + pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion"); + pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion"); ++ pNtQuerySystemInformation = (void *)GetProcAddress(hntdll, "NtQuerySystemInformation"); + + test_case_sensitive(); + test_namespace_pipe(); +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/definition wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Object_Types/definition 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Object_Types/definition 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,3 @@ +Fixes: Implement querying for object types and their indices +Depends: server-Shared_Memory +Depends: server-Misc_ACL diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Realtime_Priority/0001-wineserver-Draft-to-implement-priority-levels-throug.patch wine-staging-2.4.0~ubuntu16.04.1/patches/server-Realtime_Priority/0001-wineserver-Draft-to-implement-priority-levels-throug.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Realtime_Priority/0001-wineserver-Draft-to-implement-priority-levels-throug.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Realtime_Priority/0001-wineserver-Draft-to-implement-priority-levels-throug.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From c7c204c978e86e796091166249bcf077835efab2 Mon Sep 17 00:00:00 2001 +From 25c2aa22c5e33bfe2860d54a4edc50afd357505b Mon Sep 17 00:00:00 2001 From: Joakim Hernberg Date: Tue, 31 Mar 2015 20:58:20 +0200 Subject: wineserver: Draft to implement priority levels through POSIX @@ -19,7 +19,7 @@ create mode 100644 server/scheduler.c diff --git a/server/Makefile.in b/server/Makefile.in -index 75ba199..e539110 100644 +index 75ba1997c8..e539110cf3 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -30,6 +30,7 @@ C_SRCS = \ @@ -31,7 +31,7 @@ serial.c \ signal.c \ diff --git a/server/main.c b/server/main.c -index 7aed338..ee8cadd 100644 +index 7aed338e96..ee8cadde5d 100644 --- a/server/main.c +++ b/server/main.c @@ -44,6 +44,7 @@ int foreground = 0; @@ -52,7 +52,7 @@ init_registry(); diff --git a/server/scheduler.c b/server/scheduler.c new file mode 100644 -index 0000000..2fca966 +index 0000000000..2fca966192 --- /dev/null +++ b/server/scheduler.c @@ -0,0 +1,163 @@ @@ -220,10 +220,10 @@ + +#endif diff --git a/server/thread.c b/server/thread.c -index 5f8405b..b1c6616 100644 +index 4a1c99838c..754b6fbd27 100644 --- a/server/thread.c +++ b/server/thread.c -@@ -491,7 +491,10 @@ static void set_thread_info( struct thread *thread, +@@ -490,7 +490,10 @@ static void set_thread_info( struct thread *thread, if ((req->priority >= min && req->priority <= max) || req->priority == THREAD_PRIORITY_IDLE || req->priority == THREAD_PRIORITY_TIME_CRITICAL) @@ -235,12 +235,12 @@ set_error( STATUS_INVALID_PARAMETER ); } diff --git a/server/thread.h b/server/thread.h -index 2821991..92a0ba9 100644 +index 9614e2140d..8d075dacb6 100644 --- a/server/thread.h +++ b/server/thread.h -@@ -146,4 +146,9 @@ static inline void set_win32_error( unsigned int err ) { set_error( 0xc0010000 | - - static inline thread_id_t get_thread_id( struct thread *thread ) { return thread->id; } +@@ -148,4 +148,9 @@ static inline thread_id_t get_thread_id( struct thread *thread ) { return thread + static inline int get_thread_unix_tid( struct thread *thread ) { return thread->unix_tid; } + static inline timeout_t get_thread_creation_time( struct thread *thread ) { return thread->creation_time; } +/* scheduler functions */ + @@ -249,5 +249,5 @@ + #endif /* __WINE_SERVER_THREAD_H */ -- -2.8.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/server-Realtime_Priority/definition wine-staging-2.4.0~ubuntu16.04.1/patches/server-Realtime_Priority/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/server-Realtime_Priority/definition 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/server-Realtime_Priority/definition 2017-03-21 14:37:14.000000000 +0000 @@ -1 +1,2 @@ Fixes: Support for linux priority levels for faster performance +Depends: ntdll-ThreadTime diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/taskmgr-Memory_Usage/0005-ntdll-Implement-basic-IO-stats-for-SystemPerformance.patch wine-staging-2.4.0~ubuntu16.04.1/patches/taskmgr-Memory_Usage/0005-ntdll-Implement-basic-IO-stats-for-SystemPerformance.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/taskmgr-Memory_Usage/0005-ntdll-Implement-basic-IO-stats-for-SystemPerformance.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/taskmgr-Memory_Usage/0005-ntdll-Implement-basic-IO-stats-for-SystemPerformance.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,52 @@ +From 02cb8d6b85421c1f302a706803249cc574f48cdc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Wed, 8 Mar 2017 23:09:54 +0100 +Subject: ntdll: Implement basic IO stats for SystemPerformanceInformation in + NtQuerySystemInformation. + +--- + dlls/ntdll/nt.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c +index 9e61bd96022..947ecc73f32 100644 +--- a/dlls/ntdll/nt.c ++++ b/dlls/ntdll/nt.c +@@ -1943,6 +1943,34 @@ NTSTATUS WINAPI NtQuerySystemInformation( + } + #endif + ++ if ((fp = fopen("/proc/diskstats", "r"))) ++ { ++ unsigned long long reads, reads_merged, sectors_read, read_time; ++ unsigned long long writes, writes_merged, sectors_written, write_time; ++ unsigned long long io_time, weighted_io_time, current_io; ++ unsigned int major, minor; ++ char dev[30], buffer[256]; ++ ++ /* the exact size (32 or 64 bits) depends on the kernel */ ++ while (fscanf(fp, "%u %u %s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", ++ &major, &minor, dev, &reads, &reads_merged, §ors_read, &read_time, ++ &writes, &writes_merged, §ors_written, &write_time, ++ ¤t_io, &io_time, &weighted_io_time) == 14) ++ { ++ /* we have to ignore partitions as their I/O is also included in the block device */ ++ sprintf(buffer, "/sys/dev/block/%u:%u/device", major, minor); ++ if (access(buffer, F_OK) != 0) ++ continue; ++ ++ spi.ReadTransferCount.QuadPart += sectors_read * 512; ++ spi.WriteTransferCount.QuadPart += sectors_written * 512; ++ spi.ReadOperationCount += reads; ++ spi.WriteOperationCount += writes; ++ } ++ ++ fclose(fp); ++ } ++ + if (Length >= len) + { + if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION; +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/taskmgr-Memory_Usage/definition wine-staging-2.4.0~ubuntu16.04.1/patches/taskmgr-Memory_Usage/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/taskmgr-Memory_Usage/definition 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/taskmgr-Memory_Usage/definition 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1 @@ +Fixes: Implement IO stats for SystemPerformanceInformation in NtQuerySystemInformation diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0001-user32-tests-Add-a-message-test-for-an-owner-drawn-s.patch wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0001-user32-tests-Add-a-message-test-for-an-owner-drawn-s.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0001-user32-tests-Add-a-message-test-for-an-owner-drawn-s.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0001-user32-tests-Add-a-message-test-for-an-owner-drawn-s.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,160 @@ +From 726802175f5249d2313620f488a55ffa391c56ce Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 8 Mar 2017 16:33:41 +0800 +Subject: user32/tests: Add a message test for an owner-drawn sorted listbox. + +--- + dlls/user32/tests/msg.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 88 insertions(+), 3 deletions(-) + +diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c +index a742f670ab..3a492b37bd 100644 +--- a/dlls/user32/tests/msg.c ++++ b/dlls/user32/tests/msg.c +@@ -2232,18 +2232,61 @@ static void add_message_(int line, const struct recvd_message *msg) + { + MEASURE_ITEM_STRUCT mi; + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)msg->lParam; ++ BOOL is_unicode_data = TRUE; + + sprintf( seq->output, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx", + msg->descr, msg->hwnd, mis->CtlType, mis->CtlID, + mis->itemID, mis->itemData); + ++ if (mis->CtlType == ODT_LISTBOX) ++ { ++ HWND ctrl = GetDlgItem(msg->hwnd, mis->CtlID); ++ is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; ++ } ++ + mi.u.wp = 0; + mi.u.item.CtlType = mis->CtlType; + mi.u.item.CtlID = mis->CtlID; + mi.u.item.itemID = mis->itemID; + mi.u.item.wParam = msg->wParam; + seq->wParam = mi.u.wp; +- seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0; ++ if (is_unicode_data) ++ seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0; ++ else ++ seq->lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0; ++ break; ++ } ++ ++ case WM_COMPAREITEM: ++ { ++ COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)msg->lParam; ++ HWND ctrl = GetDlgItem(msg->hwnd, cis->CtlID); ++ BOOL is_unicode_data = TRUE; ++ ++ ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam); ++ ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem); ++todo_wine ++ ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1); ++todo_wine ++ ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2); ++ ++ sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx", ++ msg->descr, msg->hwnd, cis->CtlType, cis->CtlID, ++ cis->itemID1, cis->itemData1, cis->itemID2, cis->itemData2); ++ ++ if (cis->CtlType == ODT_LISTBOX) ++ is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; ++ ++ if (is_unicode_data) ++ { ++ seq->wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0; ++ seq->lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0; ++ } ++ else ++ { ++ seq->wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0; ++ seq->lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0; ++ } + break; + } + +@@ -9261,7 +9304,7 @@ static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam + message == WM_PARENTNOTIFY || message == WM_CANCELMODE || + message == WM_SETFOCUS || message == WM_KILLFOCUS || + message == WM_ENABLE || message == WM_ENTERIDLE || +- message == WM_DRAWITEM || message == WM_MEASUREITEM || ++ message == WM_DRAWITEM || message == WM_MEASUREITEM || message == WM_COMPAREITEM || + message == WM_COMMAND || message == WM_IME_SETCONTEXT) + { + switch (message) +@@ -9309,7 +9352,7 @@ static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam + ret = DefWindowProcA(hwnd, message, wParam, lParam); + defwndproc_counter--; + +- return ret; ++ return message == WM_COMPAREITEM ? -1 : ret; + } + + static INT_PTR CALLBACK StopQuitMsgCheckProcA(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) +@@ -14430,6 +14473,19 @@ static const struct message wm_lb_addstring[] = + { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, + { 0 } + }; ++static const struct message wm_lb_addstring_sort[] = ++{ ++ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, ++ { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, ++ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, ++ { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ee }, ++ { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, ++ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, ++ { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ef }, ++ { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ee, 0xf30604ef }, ++ { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, ++ { 0 } ++}; + + #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__) + +@@ -14495,6 +14551,7 @@ static void test_listbox_messages(void) + + parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); ++ /* with LBS_HASSTRINGS */ + listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, + WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE, + 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); +@@ -14576,6 +14633,34 @@ static void test_listbox_messages(void) + log_all_parent_messages--; + + DestroyWindow(listbox); ++ ++ /* with LBS_SORT and without LBS_HASSTRINGS */ ++ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, ++ WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE, ++ 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); ++ listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc); ++ ++ check_lb_state(listbox, 0, LB_ERR, 0, 0); ++ ++ flush_sequence(); ++ ++ log_all_parent_messages++; ++ ++ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); ++ ok(ret == 0, "expected 0, got %ld\n", ret); ++ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); ++todo_wine ++ ok(ret == 1, "expected 1, got %ld\n", ret); ++ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); ++todo_wine ++ ok(ret == 2, "expected 2, got %ld\n", ret); ++ ++ ok_sequence(wm_lb_addstring_sort, "LB_ADDSTRING", TRUE); ++ check_lb_state(listbox, 3, LB_ERR, 0, 0); ++ ++ log_all_parent_messages--; ++ ++ DestroyWindow(listbox); + DestroyWindow(parent); + } + +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0002-user32-Fix-order-of-items-passed-in-WM_COMPAREITEM-d.patch wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0002-user32-Fix-order-of-items-passed-in-WM_COMPAREITEM-d.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0002-user32-Fix-order-of-items-passed-in-WM_COMPAREITEM-d.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0002-user32-Fix-order-of-items-passed-in-WM_COMPAREITEM-d.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,63 @@ +From 25f564b7d279386c882c144fd6591d012049dcb7 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 8 Mar 2017 16:48:26 +0800 +Subject: user32: Fix order of items passed in WM_COMPAREITEM data. + +--- + dlls/user32/listbox.c | 10 +++++----- + dlls/user32/tests/msg.c | 4 ---- + 2 files changed, 5 insertions(+), 9 deletions(-) + +diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c +index 689cb106c4..4269ef0717 100644 +--- a/dlls/user32/listbox.c ++++ b/dlls/user32/listbox.c +@@ -858,15 +858,15 @@ static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact ) + cis.hwndItem = descr->self; + /* note that some application (MetaStock) expects the second item + * to be in the listbox */ +- cis.itemID1 = -1; +- cis.itemData1 = (ULONG_PTR)str; +- cis.itemID2 = index; +- cis.itemData2 = descr->items[index].data; ++ cis.itemID1 = index; ++ cis.itemData1 = descr->items[index].data; ++ cis.itemID2 = -1; ++ cis.itemData2 = (ULONG_PTR)str; + cis.dwLocaleId = descr->locale; + res = SendMessageW( descr->owner, WM_COMPAREITEM, id, (LPARAM)&cis ); + } + if (!res) return index; +- if (res < 0) max = index; ++ if (res > 0) max = index; + else min = index + 1; + } + return exact ? -1 : max; +diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c +index 3a492b37bd..f806e5366e 100644 +--- a/dlls/user32/tests/msg.c ++++ b/dlls/user32/tests/msg.c +@@ -2265,9 +2265,7 @@ static void add_message_(int line, const struct recvd_message *msg) + + ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam); + ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem); +-todo_wine + ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1); +-todo_wine + ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2); + + sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx", +@@ -14649,10 +14647,8 @@ static void test_listbox_messages(void) + ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); + ok(ret == 0, "expected 0, got %ld\n", ret); + ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); +-todo_wine + ok(ret == 1, "expected 1, got %ld\n", ret); + ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); +-todo_wine + ok(ret == 2, "expected 2, got %ld\n", ret); + + ok_sequence(wm_lb_addstring_sort, "LB_ADDSTRING", TRUE); +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0003-user32-Fix-the-listbox-sorting-algorithm.patch wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0003-user32-Fix-the-listbox-sorting-algorithm.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0003-user32-Fix-the-listbox-sorting-algorithm.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0003-user32-Fix-the-listbox-sorting-algorithm.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,44 @@ +From 29128bbe18f85edc8f7760262c6b598bd789ffb0 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 8 Mar 2017 17:48:58 +0800 +Subject: user32: Fix the listbox sorting algorithm. + +--- + dlls/user32/listbox.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c +index 4269ef0717..5eb266b15a 100644 +--- a/dlls/user32/listbox.c ++++ b/dlls/user32/listbox.c +@@ -840,10 +840,11 @@ static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact ) + { + INT index, min, max, res; + +- if (!(descr->style & LBS_SORT)) return -1; /* Add it at the end */ ++ if (!descr->nb_items || !(descr->style & LBS_SORT)) return -1; /* Add it at the end */ ++ + min = 0; +- max = descr->nb_items; +- while (min != max) ++ max = descr->nb_items - 1; ++ while (min <= max) + { + index = (min + max) / 2; + if (HAS_STRINGS(descr)) +@@ -866,10 +867,10 @@ static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact ) + res = SendMessageW( descr->owner, WM_COMPAREITEM, id, (LPARAM)&cis ); + } + if (!res) return index; +- if (res > 0) max = index; ++ if (res > 0) max = index - 1; + else min = index + 1; + } +- return exact ? -1 : max; ++ return exact ? -1 : min; + } + + +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0004-user32-For-an-owner-drawn-listbox-without-strings-WM.patch wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0004-user32-For-an-owner-drawn-listbox-without-strings-WM.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0004-user32-For-an-owner-drawn-listbox-without-strings-WM.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/0004-user32-For-an-owner-drawn-listbox-without-strings-WM.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,40 @@ +From 3a44891b4f5f206363492fc3ff91e8a97a70857d Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 8 Mar 2017 17:52:10 +0800 +Subject: user32: For an owner-drawn listbox without strings WM_MEASUREITEM + still needs correct itemData. + +--- + dlls/user32/listbox.c | 2 +- + dlls/user32/tests/msg.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c +index 5eb266b15a..4572b81bf3 100644 +--- a/dlls/user32/listbox.c ++++ b/dlls/user32/listbox.c +@@ -1566,7 +1566,7 @@ static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index, + mis.CtlType = ODT_LISTBOX; + mis.CtlID = id; + mis.itemID = index; +- mis.itemData = (ULONG_PTR)str; ++ mis.itemData = str ? (ULONG_PTR)str : data; + mis.itemHeight = descr->item_height; + TRACE("owner=%p CtlID=%08x, itemID=%08x, itemData=%08lx\n", + descr->owner, mis.CtlID, mis.itemID, mis.itemData); +diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c +index f806e5366e..34385bd266 100644 +--- a/dlls/user32/tests/msg.c ++++ b/dlls/user32/tests/msg.c +@@ -14651,7 +14651,7 @@ static void test_listbox_messages(void) + ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); + ok(ret == 2, "expected 2, got %ld\n", ret); + +- ok_sequence(wm_lb_addstring_sort, "LB_ADDSTRING", TRUE); ++ ok_sequence(wm_lb_addstring_sort, "LB_ADDSTRING", FALSE); + check_lb_state(listbox, 3, LB_ERR, 0, 0); + + log_all_parent_messages--; +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/definition wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/definition --- wine-staging-2.3.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/definition 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/user32-Sorted_Listbox/definition 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,2 @@ +Fixes: [42602] Multiple fixes for owner-drawn and sorted listbox +Depends: user32-WM_MEASUREITEM diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wbemprox-Win32_VideoController/0005-wbemprox-Add-Vendor-field-in-Win32_ComputerSystemPro.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wbemprox-Win32_VideoController/0005-wbemprox-Add-Vendor-field-in-Win32_ComputerSystemPro.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wbemprox-Win32_VideoController/0005-wbemprox-Add-Vendor-field-in-Win32_ComputerSystemPro.patch 1970-01-01 00:00:00.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wbemprox-Win32_VideoController/0005-wbemprox-Add-Vendor-field-in-Win32_ComputerSystemPro.patch 2017-03-21 14:37:14.000000000 +0000 @@ -0,0 +1,60 @@ +From eae806b2918bb7e417c0deeca518102434eb7041 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sun, 19 Mar 2017 21:42:24 +0100 +Subject: wbemprox: Add Vendor field in Win32_ComputerSystemProduct. + +--- + dlls/wbemprox/builtin.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c +index ffcffaa621..70907bf1d4 100644 +--- a/dlls/wbemprox/builtin.c ++++ b/dlls/wbemprox/builtin.c +@@ -391,6 +391,8 @@ static const WCHAR prop_varianttypeW[] = + {'V','a','r','i','a','n','t','T','y','p','e',0}; + static const WCHAR prop_versionW[] = + {'V','e','r','s','i','o','n',0}; ++static const WCHAR prop_vendorW[] = ++ {'V','e','n','d','o','r',0}; + static const WCHAR prop_videoarchitectureW[] = + {'V','i','d','e','o','A','r','c','h','i','t','e','c','t','u','r','e',0}; + static const WCHAR prop_videomemorytypeW[] = +@@ -452,7 +454,8 @@ static const struct column col_compsys[] = + static const struct column col_compsysproduct[] = + { + { prop_identifyingnumberW, CIM_STRING|COL_FLAG_KEY }, +- { prop_uuidW, CIM_STRING|COL_FLAG_DYNAMIC } ++ { prop_uuidW, CIM_STRING|COL_FLAG_DYNAMIC }, ++ { prop_vendorW, CIM_STRING }, + }; + static const struct column col_datafile[] = + { +@@ -760,6 +763,8 @@ static const WCHAR compsysproduct_identifyingnumberW[] = + static const WCHAR compsysproduct_uuidW[] = + {'d','e','a','d','d','e','a','d','-','d','e','a','d','-','d','e','a','d','-','d','e','a','d','-', + 'd','e','a','d','d','e','a','d','d','e','a','d',0}; ++static const WCHAR compsysproduct_vendorW[] = ++ {'W','i','n','e',0}; + static const WCHAR diskdrive_interfacetypeW[] = + {'I','D','E',0}; + static const WCHAR diskdrive_manufacturerW[] = +@@ -854,6 +859,7 @@ struct record_computersystemproduct + { + const WCHAR *identifyingnumber; + const WCHAR *uuid; ++ const WCHAR *vendor; + }; + struct record_datafile + { +@@ -1448,6 +1454,7 @@ static enum fill_status fill_compsysproduct( struct table *table, const struct e + rec = (struct record_computersystemproduct *)table->data; + rec->identifyingnumber = compsysproduct_identifyingnumberW; + rec->uuid = get_compsysproduct_uuid(); ++ rec->vendor = compsysproduct_vendorW; + if (!match_row( table, row, cond, &status )) free_row_values( table, row ); + else row++; + +-- +2.11.0 + diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/windowscodecs-TIFF_Support/0016-gdiplus-Add-support-for-more-image-color-formats.patch wine-staging-2.4.0~ubuntu16.04.1/patches/windowscodecs-TIFF_Support/0016-gdiplus-Add-support-for-more-image-color-formats.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/windowscodecs-TIFF_Support/0016-gdiplus-Add-support-for-more-image-color-formats.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/windowscodecs-TIFF_Support/0016-gdiplus-Add-support-for-more-image-color-formats.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From a2ad6b7fb8674d821659685d838690d9637d5844 Mon Sep 17 00:00:00 2001 +From d1795154072c2b4c358e3f11d641b95db347632c Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Fri, 16 Dec 2016 18:09:55 +0800 Subject: gdiplus: Add support for more image color formats. @@ -8,7 +8,7 @@ 1 file changed, 6 insertions(+) diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c -index ac17104..aa1ff10 100644 +index bff0cdc836..ce2194317f 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -55,13 +55,19 @@ static const struct @@ -17,7 +17,6 @@ { &GUID_WICPixelFormat1bppIndexed, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW }, + { &GUID_WICPixelFormat4bppIndexed, PixelFormat4bppIndexed, WICBitmapPaletteTypeFixedHalftone8 }, { &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 }, -+ { &GUID_WICPixelFormat32bppGrayFloat, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedGray256 }, { &GUID_WICPixelFormat8bppIndexed, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat16bppBGR555, PixelFormat16bppRGB555, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat24bppBGR, PixelFormat24bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, @@ -26,11 +25,12 @@ { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 }, + { &GUID_WICPixelFormat32bppCMYK, PixelFormat32bppCMYK, WICBitmapPaletteTypeFixedHalftone256 }, ++ { &GUID_WICPixelFormat32bppGrayFloat, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedGray256 }, + { &GUID_WICPixelFormat64bppCMYK, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, + { &GUID_WICPixelFormat64bppRGBA, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { NULL } }; -- -2.9.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-1DTextures/0001-wined3d-Create-dummy-1d-textures.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-1DTextures/0001-wined3d-Create-dummy-1d-textures.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-1DTextures/0001-wined3d-Create-dummy-1d-textures.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-1DTextures/0001-wined3d-Create-dummy-1d-textures.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 6a1701127f6f8f1c885cb787249496179a69b06b Mon Sep 17 00:00:00 2001 +From 16e895f9770039a4d9129d577698c8dcec90334e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Tue, 23 Aug 2016 22:54:14 +0200 Subject: wined3d: Create dummy 1d textures. @@ -10,10 +10,10 @@ 3 files changed, 40 insertions(+) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c -index cd0057e1591..a4820d337c0 100644 +index a423fac2079..65853209864 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c -@@ -1531,6 +1531,7 @@ void context_bind_dummy_textures(const struct wined3d_device *device, const stru +@@ -1514,6 +1514,7 @@ void context_bind_dummy_textures(const struct wined3d_device *device, const stru GL_EXTCALL(glActiveTexture(GL_TEXTURE0 + i)); checkGLcall("glActiveTexture"); @@ -21,8 +21,8 @@ gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, device->dummy_textures.tex_2d); if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) -@@ -1543,7 +1544,10 @@ void context_bind_dummy_textures(const struct wined3d_device *device, const stru - gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_textures.tex_cube); +@@ -1529,7 +1530,10 @@ void context_bind_dummy_textures(const struct wined3d_device *device, const stru + gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, device->dummy_textures.tex_cube_array); if (gl_info->supported[EXT_TEXTURE_ARRAY]) + { @@ -32,7 +32,7 @@ if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT]) gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_BUFFER, device->dummy_textures.tex_buffer); -@@ -2426,6 +2430,14 @@ void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint +@@ -2411,6 +2415,14 @@ void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint case GL_NONE: /* nothing to do */ break; @@ -48,10 +48,10 @@ gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, device->dummy_textures.tex_2d); checkGLcall("glBindTexture"); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 7898527f6c0..b5a42905d33 100644 +index eef9818affd..5b598e2f3a4 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -624,6 +624,17 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_ +@@ -628,6 +628,17 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_ * to each texture stage when the currently set D3D texture is NULL. */ context_active_texture(context, gl_info, 0); @@ -69,7 +69,7 @@ gl_info->gl_ops.gl.p_glGenTextures(1, &device->dummy_textures.tex_2d); checkGLcall("glGenTextures"); TRACE("Dummy 2D texture given name %u.\n", device->dummy_textures.tex_2d); -@@ -682,6 +693,17 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_ +@@ -704,6 +715,17 @@ static void create_dummy_textures(struct wined3d_device *device, struct wined3d_ if (gl_info->supported[EXT_TEXTURE_ARRAY]) { @@ -87,7 +87,7 @@ gl_info->gl_ops.gl.p_glGenTextures(1, &device->dummy_textures.tex_2d_array); checkGLcall("glGenTextures"); TRACE("Dummy 2D array texture given name %u.\n", device->dummy_textures.tex_2d_array); -@@ -729,7 +751,10 @@ static void destroy_dummy_textures(struct wined3d_device *device, struct wined3d +@@ -751,7 +773,10 @@ static void destroy_dummy_textures(struct wined3d_device *device, struct wined3d gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_buffer); if (gl_info->supported[EXT_TEXTURE_ARRAY]) @@ -96,9 +96,9 @@ + gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_1d_array); + } - if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) - gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_cube); -@@ -741,6 +766,7 @@ static void destroy_dummy_textures(struct wined3d_device *device, struct wined3d + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) + gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_cube_array); +@@ -766,6 +791,7 @@ static void destroy_dummy_textures(struct wined3d_device *device, struct wined3d gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_rect); gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->dummy_textures.tex_2d); @@ -107,10 +107,10 @@ checkGLcall("Delete dummy textures"); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 051836c7414..a71ea9e73ef 100644 +index cdc240058a2..34d8f18d698 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -2582,10 +2582,12 @@ struct wined3d_device +@@ -2666,11 +2666,13 @@ struct wined3d_device /* Textures for when no other textures are mapped */ struct { @@ -119,6 +119,7 @@ GLuint tex_rect; GLuint tex_3d; GLuint tex_cube; + GLuint tex_cube_array; + GLuint tex_1d_array; GLuint tex_2d_array; GLuint tex_buffer; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-1DTextures/0006-wined3d-Implement-uploading-for-1d-textures.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-1DTextures/0006-wined3d-Implement-uploading-for-1d-textures.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-1DTextures/0006-wined3d-Implement-uploading-for-1d-textures.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-1DTextures/0006-wined3d-Implement-uploading-for-1d-textures.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 736b314e18e7e4d3c7dc7732e2e38c6b8de7ddfd Mon Sep 17 00:00:00 2001 +From 227c20d336bca247834d85e6ddb6002680d3d700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sat, 27 Aug 2016 22:25:20 +0200 Subject: wined3d: Implement uploading for 1d textures. @@ -9,24 +9,24 @@ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 150f18f..c87b325 100644 +index bd08c352794..53ada28b11b 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -4140,7 +4140,8 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - return; +@@ -4055,7 +4055,8 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str + height = 1; + depth = 1; } - -- if (resource->type != WINED3D_RTYPE_TEXTURE_2D && resource->type != WINED3D_RTYPE_TEXTURE_3D) -+ if (resource->type != WINED3D_RTYPE_TEXTURE_1D && -+ resource->type != WINED3D_RTYPE_TEXTURE_2D && resource->type != WINED3D_RTYPE_TEXTURE_3D) +- else if (resource->type == WINED3D_RTYPE_TEXTURE_2D || resource->type == WINED3D_RTYPE_TEXTURE_3D) ++ else if (resource->type == WINED3D_RTYPE_TEXTURE_1D || ++ resource->type == WINED3D_RTYPE_TEXTURE_2D || resource->type == WINED3D_RTYPE_TEXTURE_3D) { - FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); - return; + struct wined3d_texture *texture = texture_from_resource(resource); + unsigned int level; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c -index 2b66b68..614b4cf 100644 +index 296ca898f81..a3f90773904 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c -@@ -1456,8 +1456,74 @@ static void texture1d_upload_data(struct wined3d_texture *texture, unsigned int +@@ -1581,8 +1581,74 @@ static void texture1d_upload_data(struct wined3d_texture *texture, unsigned int const struct wined3d_context *context, const struct wined3d_box *box, const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch) { @@ -103,5 +103,5 @@ /* Context activation is done by the caller. */ -- -2.9.0 +2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0001-wined3d-Add-additional-synchronization-CS-ops.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0001-wined3d-Add-additional-synchronization-CS-ops.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0001-wined3d-Add-additional-synchronization-CS-ops.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0001-wined3d-Add-additional-synchronization-CS-ops.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,18 +1,19 @@ -From cc2cafc81cc50bcd93c20b887838dd663c190ef7 Mon Sep 17 00:00:00 2001 +From d8e7bb3cf2730686403c387bb3ed9b79e513294f Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 19 Feb 2017 00:57:12 +0100 Subject: wined3d: Add additional synchronization CS ops. --- - dlls/wined3d/cs.c | 51 ++++++++++++++++++++++++++++++++++++++++-- + dlls/wined3d/cs.c | 53 +++++++++++++++++++++++++++++++++++++++--- dlls/wined3d/device.c | 2 ++ dlls/wined3d/swapchain.c | 2 ++ + dlls/wined3d/texture.c | 11 +++++++++ dlls/wined3d/view.c | 6 +++++ dlls/wined3d/wined3d_private.h | 3 +++ - 5 files changed, 62 insertions(+), 2 deletions(-) + 6 files changed, 74 insertions(+), 3 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 8afa7313a02..b27a083007b 100644 +index f5bf70d2ee..8c0abf449f 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -26,6 +26,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); @@ -24,8 +25,8 @@ WINED3D_CS_OP_PRESENT, WINED3D_CS_OP_CLEAR, WINED3D_CS_OP_DISPATCH, -@@ -65,6 +67,16 @@ enum wined3d_cs_op - WINED3D_CS_OP_UNMAP, +@@ -67,6 +69,16 @@ enum wined3d_cs_op + WINED3D_CS_OP_UPDATE_SUB_RESOURCE, }; +struct wined3d_cs_sync @@ -41,8 +42,8 @@ struct wined3d_cs_present { enum wined3d_cs_op opcode; -@@ -344,6 +356,38 @@ struct wined3d_cs_unmap - HRESULT *hr; +@@ -369,6 +381,38 @@ struct wined3d_cs_update_sub_resource + struct wined3d_sub_resource_data data; }; +static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) @@ -80,7 +81,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_present *op = data; -@@ -1618,7 +1662,7 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, +@@ -1643,7 +1687,7 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, op->flags = flags; op->hr = &hr; @@ -89,7 +90,7 @@ return hr; } -@@ -1642,13 +1686,15 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc +@@ -1667,7 +1711,7 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc op->sub_resource_idx = sub_resource_idx; op->hr = &hr; @@ -98,6 +99,13 @@ return hr; } +@@ -1809,11 +1853,13 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r + + wined3d_resource_acquire(resource); + +- cs->ops->submit(cs); ++ cs->ops->submit_and_wait(cs); + } static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { @@ -106,7 +114,7 @@ /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch, -@@ -1779,6 +1825,7 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = +@@ -1946,6 +1992,7 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = { wined3d_cs_st_require_space, wined3d_cs_st_submit, @@ -115,10 +123,10 @@ }; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index e812567b067..be6d784bddf 100644 +index 94879b5de1..e328f32403 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -1008,6 +1008,7 @@ static void wined3d_device_delete_opengl_contexts_cs(void *object) +@@ -1029,6 +1029,7 @@ static void wined3d_device_delete_opengl_contexts_cs(void *object) static void wined3d_device_delete_opengl_contexts(struct wined3d_device *device) { wined3d_cs_destroy_object(device->cs, wined3d_device_delete_opengl_contexts_cs, device); @@ -126,7 +134,7 @@ } static void wined3d_device_create_primary_opengl_context_cs(void *object) -@@ -1043,6 +1044,7 @@ static void wined3d_device_create_primary_opengl_context_cs(void *object) +@@ -1064,6 +1065,7 @@ static void wined3d_device_create_primary_opengl_context_cs(void *object) static HRESULT wined3d_device_create_primary_opengl_context(struct wined3d_device *device) { wined3d_cs_init_object(device->cs, wined3d_device_create_primary_opengl_context_cs, device); @@ -135,7 +143,7 @@ return E_FAIL; diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c -index 25deaeb1ae9..bd23999fb1e 100644 +index 25deaeb1ae..bd23999fb1 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -66,6 +66,7 @@ static void swapchain_cleanup(struct wined3d_swapchain *swapchain) @@ -154,11 +162,64 @@ if (!swapchain->context[0]) { +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 91f0cc36ed..0197f6daae 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -1391,6 +1391,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT + if (surface->dc) + { + wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); ++ wined3d_cs_emit_sync(device->cs); + create_dib = TRUE; + } + +@@ -1451,7 +1452,10 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT + wined3d_texture_invalidate_location(texture, 0, ~valid_location); + + if (create_dib) ++ { + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); ++ wined3d_cs_emit_sync(device->cs); ++ } + + return WINED3D_OK; + } +@@ -2856,6 +2860,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 + if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) + { + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); ++ wined3d_cs_emit_sync(device->cs); + if (!surface->dc) + { + wined3d_texture_cleanup_sync(texture); +@@ -3653,7 +3658,10 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i + return WINED3DERR_INVALIDCALL; + + if (!surface->dc) ++ { + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); ++ wined3d_cs_emit_sync(device->cs); ++ } + if (!surface->dc) + return WINED3DERR_INVALIDCALL; + +@@ -3697,7 +3705,10 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign + } + + if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D)) ++ { + wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); ++ wined3d_cs_emit_sync(device->cs); ++ } + + --sub_resource->map_count; + if (!--texture->resource.map_count && texture->update_map_binding) diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c -index 02964e4a96b..21aa8720e65 100644 +index 3cd20ea8fa..9b9e7eef4c 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c -@@ -598,6 +598,8 @@ static void wined3d_shader_resource_view_cs_init(void *object) +@@ -594,6 +594,8 @@ static void wined3d_shader_resource_view_cs_init(void *object) debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id)); } } @@ -167,7 +228,7 @@ } static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view, -@@ -614,6 +616,7 @@ static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_ +@@ -610,6 +612,7 @@ static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_ wined3d_resource_incref(view->resource = resource); @@ -175,7 +236,7 @@ wined3d_cs_init_object(resource->device->cs, wined3d_shader_resource_view_cs_init, view); return WINED3D_OK; -@@ -760,6 +763,8 @@ static void wined3d_unordered_access_view_cs_init(void *object) +@@ -786,6 +789,8 @@ static void wined3d_unordered_access_view_cs_init(void *object) desc, texture, view->format); } } @@ -184,7 +245,7 @@ } static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view, -@@ -776,6 +781,7 @@ static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_acces +@@ -805,6 +810,7 @@ static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_acces wined3d_resource_incref(view->resource = resource); @@ -193,10 +254,10 @@ return WINED3D_OK; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index d45e19b0224..d0385a5e90a 100644 +index 987f3dc70b..9918f13f08 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3193,6 +3193,7 @@ struct wined3d_cs_ops +@@ -3209,6 +3209,7 @@ struct wined3d_cs_ops { void *(*require_space)(struct wined3d_cs *cs, size_t size); void (*submit)(struct wined3d_cs *cs); @@ -204,7 +265,7 @@ void (*push_constants)(struct wined3d_cs *cs, enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants); }; -@@ -3219,6 +3220,7 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, +@@ -3239,6 +3240,7 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base_vertex_idx, unsigned int start_idx, unsigned int index_count, unsigned int start_instance, unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN; @@ -212,14 +273,14 @@ void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags) DECLSPEC_HIDDEN; -@@ -3270,6 +3272,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined +@@ -3290,6 +3292,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; +void wined3d_cs_emit_sync(struct wined3d_cs *cs); void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; - void wined3d_cs_init_object(struct wined3d_cs *cs, - void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; + void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, + unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, -- 2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0002-wined3d-Send-push_constants-through-the-CS.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0002-wined3d-Send-push_constants-through-the-CS.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0002-wined3d-Send-push_constants-through-the-CS.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0002-wined3d-Send-push_constants-through-the-CS.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From e565d8dfb0453633c53c6a74f5f204e99231729a Mon Sep 17 00:00:00 2001 +From 9e6e4d61e56980850bbbc340d510e9a57f9d5627 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Mon, 6 Feb 2017 05:50:11 +0100 Subject: wined3d: Send push_constants through the CS. @@ -10,19 +10,19 @@ 3 files changed, 77 insertions(+), 58 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 990cb6735d7..4612244ce0c 100644 +index 8c0abf449f2..0d74ea806a9 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -63,6 +63,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_UNLOAD_RESOURCE, - WINED3D_CS_OP_MAP, +@@ -67,6 +67,7 @@ enum wined3d_cs_op WINED3D_CS_OP_UNMAP, + WINED3D_CS_OP_BLT_SUB_RESOURCE, + WINED3D_CS_OP_UPDATE_SUB_RESOURCE, + WINED3D_CS_OP_PUSH_CONSTANTS, }; struct wined3d_cs_sync -@@ -340,6 +341,15 @@ struct wined3d_cs_unmap - HRESULT *hr; +@@ -381,6 +382,15 @@ struct wined3d_cs_update_sub_resource + struct wined3d_sub_resource_data data; }; +struct wined3d_cs_push_constants @@ -37,8 +37,8 @@ static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) { } -@@ -1579,6 +1589,64 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc - return hr; +@@ -1856,6 +1866,64 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r + cs->ops->submit_and_wait(cs); } +static const struct @@ -102,15 +102,15 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -1618,6 +1686,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource, - /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, +@@ -1899,6 +1967,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, + /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource, + /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, + /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants, }; static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) -@@ -1664,55 +1733,11 @@ static void wined3d_cs_st_submit(struct wined3d_cs *cs) +@@ -1945,55 +2014,11 @@ static void wined3d_cs_st_submit(struct wined3d_cs *cs) HeapFree(GetProcessHeap(), 0, data); } @@ -167,10 +167,10 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index b449225d2e9..5e17ba185de 100644 +index e328f32403f..c3a10a2d13a 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -2347,7 +2347,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device, +@@ -2376,7 +2376,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device, } else { @@ -179,7 +179,7 @@ } return WINED3D_OK; -@@ -2396,7 +2396,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device, +@@ -2425,7 +2425,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device, } else { @@ -188,7 +188,7 @@ } return WINED3D_OK; -@@ -2441,7 +2441,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device, +@@ -2470,7 +2470,7 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device, memset(&device->recording->changed.vs_consts_f[start_idx], 1, count * sizeof(*device->recording->changed.vs_consts_f)); else @@ -197,7 +197,7 @@ return WINED3D_OK; } -@@ -2580,7 +2580,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device, +@@ -2591,7 +2591,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device, } else { @@ -206,7 +206,7 @@ } return WINED3D_OK; -@@ -2629,7 +2629,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device, +@@ -2640,7 +2640,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device, } else { @@ -215,7 +215,7 @@ } return WINED3D_OK; -@@ -2675,7 +2675,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device, +@@ -2686,7 +2686,7 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device, memset(&device->recording->changed.ps_consts_f[start_idx], 1, count * sizeof(*device->recording->changed.ps_consts_f)); else @@ -225,10 +225,10 @@ return WINED3D_OK; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 46ca81b4e77..df05dcb8fc8 100644 +index 2922caaa412..9c68628ed6c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3169,8 +3169,6 @@ struct wined3d_cs_ops +@@ -3200,8 +3200,6 @@ struct wined3d_cs_ops void *(*require_space)(struct wined3d_cs *cs, size_t size); void (*submit)(struct wined3d_cs *cs); void (*submit_and_wait)(struct wined3d_cs *cs); @@ -237,7 +237,7 @@ }; struct wined3d_cs -@@ -3198,6 +3196,8 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; +@@ -3234,6 +3232,8 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags) DECLSPEC_HIDDEN; @@ -246,7 +246,7 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, -@@ -3253,12 +3253,6 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, +@@ -3294,12 +3294,6 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx) DECLSPEC_HIDDEN; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0008-wined3d-Send-blits-through-the-command-stream.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0008-wined3d-Send-blits-through-the-command-stream.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0008-wined3d-Send-blits-through-the-command-stream.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0008-wined3d-Send-blits-through-the-command-stream.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From c300fbe493da45c4767a7ebe73f9854a9a1101e8 Mon Sep 17 00:00:00 2001 +From 706645d08ae7ebd9175f91532077694b988aef7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Mon, 29 Apr 2013 18:49:53 +0200 Subject: wined3d: Send blits through the command stream. @@ -6,507 +6,60 @@ This needs more work. This patch breaks error handling, and the split between surface_blt and surface_blt_ugly isn't particularly nice. --- - dlls/wined3d/cs.c | 52 +++++++++ - dlls/wined3d/device.c | 26 +++++ - dlls/wined3d/surface.c | 240 ++++++++++++++++++++++++----------------- - dlls/wined3d/wined3d_private.h | 7 ++ - 4 files changed, 228 insertions(+), 97 deletions(-) + dlls/wined3d/device.c | 18 +++++++++--------- + dlls/wined3d/texture.c | 9 +++++++-- + 2 files changed, 16 insertions(+), 11 deletions(-) -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index ee3d9a79da0..1517df9da95 100644 ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -66,6 +66,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_MAP, - WINED3D_CS_OP_UNMAP, - WINED3D_CS_OP_PUSH_CONSTANTS, -+ WINED3D_CS_OP_BLT, - }; - - struct wined3d_cs_sync -@@ -366,6 +367,18 @@ struct wined3d_cs_push_constants - BYTE constants[1]; - }; - -+struct wined3d_cs_blt -+{ -+ enum wined3d_cs_op opcode; -+ struct wined3d_surface *dst_surface; -+ RECT dst_rect; -+ struct wined3d_surface *src_surface; -+ RECT src_rect; -+ DWORD flags; -+ struct wined3d_blt_fx fx; -+ enum wined3d_texture_filter_type filter; -+}; -+ - static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) - { - } -@@ -1776,6 +1789,44 @@ void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_con - cs->ops->submit(cs); - } - -+static void wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_blt *op = data; -+ -+ surface_blt_ugly(op->dst_surface, &op->dst_rect, -+ op->src_surface, &op->src_rect, -+ op->flags, &op->fx, op->filter); -+ -+ wined3d_resource_release(&op->dst_surface->container->resource); -+ if (op->src_surface && op->src_surface != op->dst_surface) -+ wined3d_resource_release(&op->src_surface->container->resource); -+} -+ -+void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surface, -+ const RECT *dst_rect, struct wined3d_surface *src_surface, -+ const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, -+ enum wined3d_texture_filter_type filter) -+{ -+ struct wined3d_cs_blt *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_BLT; -+ op->dst_surface = dst_surface; -+ op->dst_rect = *dst_rect; -+ op->src_surface = src_surface; -+ op->src_rect = *src_rect; -+ op->flags = flags; -+ op->filter = filter; -+ if (fx) -+ op->fx = *fx; -+ -+ wined3d_resource_acquire(&dst_surface->container->resource); -+ if (src_surface && src_surface != dst_surface) -+ wined3d_resource_acquire(&src_surface->container->resource); -+ -+ cs->ops->submit(cs); -+} -+ - static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = - { - /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -1818,6 +1869,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, - /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, - /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants, -+ /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, - }; - - static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 01f7f1b6d84..7644e2aa250 100644 +index c3a10a2d13a..31453ed0ff8 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -4027,6 +4027,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev - struct wined3d_texture *dst_texture, *src_texture; - RECT dst_rect, src_rect; - HRESULT hr; -+ struct wined3d_box dst_box; - - TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, " - "src_resource %p, src_sub_resource_idx %u, src_box %s.\n", -@@ -4114,6 +4115,14 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev - - if (src_box) - { -+ if ((src_texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) -+ && !wined3d_texture_check_block_align(src_texture, -+ src_sub_resource_idx % src_texture->level_count, src_box)) -+ { -+ WARN("Source box not block-aligned.\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ - SetRect(&src_rect, src_box->left, src_box->top, src_box->right, src_box->bottom); - } - else -@@ -4127,6 +4136,23 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev - SetRect(&dst_rect, dst_x, dst_y, dst_x + (src_rect.right - src_rect.left), - dst_y + (src_rect.bottom - src_rect.top)); - -+ if (dst_texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) -+ { -+ dst_box.left = dst_rect.left; -+ dst_box.top = dst_rect.top; -+ dst_box.front = 0; -+ dst_box.right = dst_rect.right; -+ dst_box.bottom = dst_rect.bottom; -+ dst_box.back = 1; -+ -+ if(!wined3d_texture_check_block_align(dst_texture, -+ dst_sub_resource_idx % dst_texture->level_count, &dst_box)) -+ { -+ WARN("Destination box not block-aligned.\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ } -+ - if (FAILED(hr = wined3d_texture_blt(dst_texture, dst_sub_resource_idx, &dst_rect, - src_texture, src_sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT))) - WARN("Failed to blit, hr %#x.\n", hr); -diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c -index 347a8097484..c0b34e20b83 100644 ---- a/dlls/wined3d/surface.c -+++ b/dlls/wined3d/surface.c -@@ -3772,7 +3772,7 @@ const struct blit_shader cpu_blit = { - cpu_blit_blit_surface, - }; - --HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect, -+void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect, - struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, - const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) - { -@@ -3782,9 +3782,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - struct wined3d_texture *dst_texture = dst_surface->container; - struct wined3d_device *device = dst_texture->resource.device; - struct wined3d_swapchain *src_swapchain, *dst_swapchain; -- struct wined3d_texture *src_texture = NULL; -- unsigned int dst_w, dst_h, src_w, src_h; -- unsigned int src_sub_resource_idx = 0; -+ struct wined3d_texture *src_texture; -+ unsigned int src_sub_resource_idx; - DWORD src_ds_flags, dst_ds_flags; - BOOL scale, convert; - -@@ -3797,84 +3796,17 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - | WINED3D_BLT_DO_NOT_WAIT - | WINED3D_BLT_ALPHA_TEST; - -- TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", -- dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), -- flags, fx, debug_d3dtexturefiltertype(filter)); -- TRACE("Usage is %s.\n", debug_d3dusage(dst_texture->resource.usage)); -- -- if (fx) -- { -- TRACE("fx %#x.\n", fx->fx); -- TRACE("fill_color 0x%08x.\n", fx->fill_color); -- TRACE("dst_color_key {0x%08x, 0x%08x}.\n", -- fx->dst_color_key.color_space_low_value, -- fx->dst_color_key.color_space_high_value); -- TRACE("src_color_key {0x%08x, 0x%08x}.\n", -- fx->src_color_key.color_space_low_value, -- fx->src_color_key.color_space_high_value); -- } -- - if (src_surface) - { - src_texture = src_surface->container; - src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); -+ src_swapchain = src_texture->swapchain; - } -- -- if (dst_texture->sub_resources[dst_sub_resource_idx].map_count -- || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count)) -- { -- WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n"); -- return WINEDDERR_SURFACEBUSY; -- } -- -- dst_w = wined3d_texture_get_level_width(dst_texture, dst_surface->texture_level); -- dst_h = wined3d_texture_get_level_height(dst_texture, dst_surface->texture_level); -- if (IsRectEmpty(dst_rect) || dst_rect->left > dst_w || dst_rect->left < 0 -- || dst_rect->top > dst_h || dst_rect->top < 0 -- || dst_rect->right > dst_w || dst_rect->right < 0 -- || dst_rect->bottom > dst_h || dst_rect->bottom < 0) -- { -- WARN("The application gave us a bad destination rectangle.\n"); -- return WINEDDERR_INVALIDRECT; -- } -- -- if (src_texture) -- { -- src_w = wined3d_texture_get_level_width(src_texture, src_surface->texture_level); -- src_h = wined3d_texture_get_level_height(src_texture, src_surface->texture_level); -- if (IsRectEmpty(src_rect) || src_rect->left > src_w || src_rect->left < 0 -- || src_rect->top > src_h || src_rect->top < 0 -- || src_rect->right > src_w || src_rect->right < 0 -- || src_rect->bottom > src_h || src_rect->bottom < 0) -- { -- WARN("The application gave us a bad source rectangle.\n"); -- return WINEDDERR_INVALIDRECT; -- } -- } -- -- if (!fx || !(fx->fx)) -- flags &= ~WINED3D_BLT_FX; -- -- if (flags & WINED3D_BLT_WAIT) -- flags &= ~WINED3D_BLT_WAIT; -- -- if (flags & WINED3D_BLT_ASYNC) -- { -- static unsigned int once; -- -- if (!once++) -- FIXME("Can't handle WINED3D_BLT_ASYNC flag.\n"); -- flags &= ~WINED3D_BLT_ASYNC; -- } -- -- /* WINED3D_BLT_DO_NOT_WAIT appeared in DX7. */ -- if (flags & WINED3D_BLT_DO_NOT_WAIT) -+ else - { -- static unsigned int once; -- -- if (!once++) -- FIXME("Can't handle WINED3D_BLT_DO_NOT_WAIT flag.\n"); -- flags &= ~WINED3D_BLT_DO_NOT_WAIT; -+ src_texture = NULL; -+ src_sub_resource_idx = 0; -+ src_swapchain = NULL; - } - - if (!device->d3d_initialized) -@@ -3899,11 +3831,6 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - goto fallback; - } - -- if (src_texture) -- src_swapchain = src_texture->swapchain; -- else -- src_swapchain = NULL; -- - dst_swapchain = dst_texture->swapchain; - - /* This isn't strictly needed. FBO blits for example could deal with -@@ -3939,22 +3866,16 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - TRACE("Depth fill.\n"); - - if (!wined3d_format_convert_color_to_float(dst_texture->resource.format, NULL, fx->fill_color, &color)) -- return WINED3DERR_INVALIDCALL; -+ return; - - if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, dst_rect, color.r))) -- return WINED3D_OK; -+ return; +@@ -4154,16 +4154,16 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev + return WINED3DERR_INVALIDCALL; } - else - { -- if (src_ds_flags != dst_ds_flags) -- { -- WARN("Rejecting depth / stencil blit between incompatible formats.\n"); -- return WINED3DERR_INVALIDCALL; -- } -- - if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_texture->resource.draw_binding, - src_rect, dst_surface, dst_texture->resource.draw_binding, dst_rect))) -- return WINED3D_OK; -+ return; - } - } - else -@@ -3990,7 +3911,7 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - goto fallback; - if (SUCCEEDED(surface_color_fill(dst_surface, dst_rect, &color))) -- return WINED3D_OK; -+ return; - } - else +- if (dst_texture->sub_resources[dst_sub_resource_idx].map_count) ++ if (dst_texture->sub_resources[dst_sub_resource_idx].map_count || ++ src_texture->sub_resources[src_sub_resource_idx].map_count) { -@@ -4034,7 +3955,7 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - context, dst_texture->resource.draw_binding); - context_release(context); - } -- return WINED3D_OK; -+ return; - } - } - } -@@ -4058,7 +3979,7 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, 0); - dst_swapchain->desc.swap_effect = swap_effect; - -- return WINED3D_OK; -+ return; - } - - if (fbo_blit_supported(&device->adapter->gl_info, blit_op, -@@ -4079,7 +4000,7 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, - ~dst_texture->resource.draw_binding); - -- return WINED3D_OK; -+ return; - } - - blitter = wined3d_select_blitter(&device->adapter->gl_info, &device->adapter->d3d_info, blit_op, -@@ -4089,7 +4010,7 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - { - blitter->blit_surface(device, blit_op, filter, src_surface, - src_rect, dst_surface, dst_rect, color_key); -- return WINED3D_OK; -+ return; - } +- WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx); +- return WINED3DERR_INVALIDCALL; +- } +- +- if (src_texture->sub_resources[src_sub_resource_idx].map_count) +- { +- WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx); +- return WINED3DERR_INVALIDCALL; ++ wined3d_cs_emit_sync(dst_texture->resource.device->cs); ++ if (dst_texture->sub_resources[dst_sub_resource_idx].map_count || ++ src_texture->sub_resources[src_sub_resource_idx].map_count) ++ { ++ WARN("Destination or source sub-resource is mapped.\n"); ++ return WINEDDERR_SURFACEBUSY; ++ } } - } -@@ -4097,9 +4018,134 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - fallback: - /* Special cases for render targets. */ - if (SUCCEEDED(surface_blt_special(dst_surface, dst_rect, src_surface, src_rect, flags, fx, filter))) -- return WINED3D_OK; -+ return; - cpu: -- return surface_cpu_blt(dst_texture, dst_sub_resource_idx, &dst_box, -+ surface_cpu_blt(dst_texture, dst_sub_resource_idx, &dst_box, - src_texture, src_sub_resource_idx, &src_box, flags, fx, filter); - } -+ -+HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect, -+ struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, -+ const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) -+{ -+ struct wined3d_texture *dst_texture = dst_surface->container; -+ struct wined3d_device *device = dst_texture->resource.device; -+ unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface), src_sub_resource_idx; -+ struct wined3d_texture_sub_resource *dst_sub_resource = -+ &dst_texture->sub_resources[dst_sub_resource_idx]; -+ struct wined3d_texture_sub_resource *src_sub_resource = NULL; -+ unsigned int dst_w, dst_h, src_w, src_h; -+ DWORD src_ds_flags, dst_ds_flags; -+ -+ TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", -+ dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), -+ flags, fx, debug_d3dtexturefiltertype(filter)); -+ TRACE("Usage is %s.\n", debug_d3dusage(dst_texture->resource.usage)); -+ -+ if (fx) -+ { -+ TRACE("fx %#x.\n", fx->fx); -+ TRACE("fill_color 0x%08x.\n", fx->fill_color); -+ TRACE("dst_color_key {0x%08x, 0x%08x}.\n", -+ fx->dst_color_key.color_space_low_value, -+ fx->dst_color_key.color_space_high_value); -+ TRACE("src_color_key {0x%08x, 0x%08x}.\n", -+ fx->src_color_key.color_space_low_value, -+ fx->src_color_key.color_space_high_value); -+ } -+ -+ if (src_surface) -+ { -+ src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); -+ src_sub_resource = &src_surface->container->sub_resources[src_sub_resource_idx]; -+ } -+ -+ if (dst_sub_resource->map_count || (src_sub_resource && src_sub_resource->map_count)) -+ { -+ wined3d_cs_emit_sync(device->cs); -+ if (dst_sub_resource->map_count || (src_sub_resource && src_sub_resource->map_count)) + if (!src_box) +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 60e53f55463..9d0909852cd 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -3189,8 +3189,13 @@ HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned + if (dst_texture->sub_resources[dst_sub_resource_idx].map_count + || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count)) + { +- WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n"); +- return WINEDDERR_SURFACEBUSY; ++ wined3d_cs_emit_sync(dst_texture->resource.device->cs); ++ if (dst_texture->sub_resources[dst_sub_resource_idx].map_count ++ || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count)) + { -+ WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n"); ++ WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n"); + return WINEDDERR_SURFACEBUSY; + } -+ } -+ -+ dst_w = wined3d_texture_get_level_width(dst_texture, dst_surface->texture_level); -+ dst_h = wined3d_texture_get_level_height(dst_texture, dst_surface->texture_level); -+ if (IsRectEmpty(dst_rect) || dst_rect->left > dst_w || dst_rect->left < 0 -+ || dst_rect->top > dst_h || dst_rect->top < 0 -+ || dst_rect->right > dst_w || dst_rect->right < 0 -+ || dst_rect->bottom > dst_h || dst_rect->bottom < 0) -+ { -+ WARN("The application gave us a bad destination rectangle.\n"); -+ return WINEDDERR_INVALIDRECT; -+ } -+ -+ if (src_surface) -+ { -+ src_w = wined3d_texture_get_level_width(src_surface->container, src_surface->texture_level); -+ src_h = wined3d_texture_get_level_height(src_surface->container, src_surface->texture_level); -+ if (IsRectEmpty(src_rect) || src_rect->left > src_w || src_rect->left < 0 -+ || src_rect->top > src_h || src_rect->top < 0 -+ || src_rect->right > src_w || src_rect->right < 0 -+ || src_rect->bottom > src_h || src_rect->bottom < 0) -+ { -+ WARN("The application gave us a bad source rectangle.\n"); -+ return WINEDDERR_INVALIDRECT; -+ } -+ } -+ -+ dst_ds_flags = dst_texture->resource.format_flags -+ & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); -+ if (src_surface) -+ src_ds_flags = src_surface->container->resource.format_flags -+ & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); -+ else -+ src_ds_flags = 0; -+ -+ if (!(flags & WINED3D_BLT_DEPTH_FILL) && (src_ds_flags != dst_ds_flags)) -+ { -+ WARN("Rejecting depth / stencil blit between incompatible formats.\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ /* FIXME: We should select the blitter in the main thread, that way we can return an error if the blit -+ * is unsupported without duplicating all the checks... */ -+ if (flags & WINED3D_BLT_COLOR_FILL && (dst_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)) -+ { -+ WARN("Block color fill, returning WINED3DERR_INVALIDCALL\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ if (!fx || !(fx->fx)) -+ flags &= ~WINED3D_BLT_FX; -+ -+ if (flags & WINED3D_BLT_WAIT) -+ flags &= ~WINED3D_BLT_WAIT; -+ -+ if (flags & WINED3D_BLT_ASYNC) -+ { -+ static unsigned int once; -+ -+ if (!once++) -+ FIXME("Can't handle WINED3D_BLT_ASYNC flag.\n"); -+ flags &= ~WINED3D_BLT_ASYNC; -+ } -+ -+ /* WINED3D_BLT_DO_NOT_WAIT appeared in DX7. */ -+ if (flags & WINED3D_BLT_DO_NOT_WAIT) -+ { -+ static unsigned int once; -+ -+ if (!once++) -+ FIXME("Can't handle WINED3D_BLT_DO_NOT_WAIT flag.\n"); -+ flags &= ~WINED3D_BLT_DO_NOT_WAIT; -+ } -+ -+ TRACE("Emitting blit %p <== %p\n", dst_surface, src_surface); -+ wined3d_cs_emit_blt(device->cs, dst_surface, dst_rect, src_surface, src_rect, -+ flags, fx, filter); -+ -+ return WINED3D_OK; -+} -diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index c62c64e7d3d..62f9c484287 100644 ---- a/dlls/wined3d/wined3d_private.h -+++ b/dlls/wined3d/wined3d_private.h -@@ -3048,6 +3048,9 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P - void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, - const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point, - BOOL srgb, const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN; -+void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_in, -+ struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags, -+ const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + } - void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context, - const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; -@@ -3199,6 +3202,10 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HID - void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN; - void wined3d_cs_destroy_object(struct wined3d_cs *cs, - void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; -+void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surface, -+ const RECT *dst_rect, struct wined3d_surface *src_surface, -+ const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, -+ enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; - void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, - DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; - void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, + if ((dst_format_flags & WINED3DFMT_FLAG_BLOCKS) && (flags & WINED3D_BLT_COLOR_FILL)) -- 2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0009-wined3d-Send-render-target-view-clears-through-the-c.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0009-wined3d-Send-render-target-view-clears-through-the-c.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0009-wined3d-Send-render-target-view-clears-through-the-c.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0009-wined3d-Send-render-target-view-clears-through-the-c.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 71236080e419dcf33176b5f8f54bbaf2dbefb630 Mon Sep 17 00:00:00 2001 +From b880794502fe7d805e3f49b61c8a8b6664cbd187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 4 Jul 2013 21:10:16 +0200 Subject: wined3d: Send render target view clears through the command stream @@ -24,19 +24,19 @@ * supported as offscreen plain surfaces and do not support D3DUSAGE_RENDERTARGET * when created as texture. */ diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 1517df9da95..ebc4e4f15e5 100644 +index bf1b63b897b..b8c99985af4 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -67,6 +67,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_UNMAP, +@@ -68,6 +68,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_BLT_SUB_RESOURCE, + WINED3D_CS_OP_UPDATE_SUB_RESOURCE, WINED3D_CS_OP_PUSH_CONSTANTS, - WINED3D_CS_OP_BLT, + WINED3D_CS_OP_CLEAR_RTV, }; struct wined3d_cs_sync -@@ -379,6 +380,18 @@ struct wined3d_cs_blt - enum wined3d_texture_filter_type filter; +@@ -391,6 +392,18 @@ struct wined3d_cs_push_constants + BYTE constants[1]; }; +struct wined3d_cs_clear_rtv @@ -54,7 +54,7 @@ static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) { } -@@ -1827,6 +1840,41 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf +@@ -1940,6 +1953,41 @@ void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_con cs->ops->submit(cs); } @@ -96,19 +96,19 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -1870,6 +1918,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, +@@ -1984,6 +2032,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource, + /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants, - /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, + /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, }; static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 7644e2aa250..35c57ff7b94 100644 +index c3a10a2d13a..728e5570777 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -4283,10 +4283,8 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi +@@ -4320,10 +4320,8 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi return WINED3DERR_INVALIDCALL; } @@ -122,11 +122,11 @@ struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(const struct wined3d_device *device, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 62f9c484287..334cdf0fb8b 100644 +index 8a07bb98523..f69cead4d1c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3208,6 +3208,9 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf - enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; +@@ -3225,6 +3225,9 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; +void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0011-wined3d-Send-update_texture-calls-through-the-CS.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0011-wined3d-Send-update_texture-calls-through-the-CS.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0011-wined3d-Send-update_texture-calls-through-the-CS.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0011-wined3d-Send-update_texture-calls-through-the-CS.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 91f8e688a10e60bf4240ec172bc4a56d6c2f59d9 Mon Sep 17 00:00:00 2001 +From 8f9e2da3bc48abffee005b95c2b996352db2de16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 1 Aug 2013 00:33:48 +0200 Subject: wined3d: Send update_texture calls through the CS @@ -11,18 +11,18 @@ 3 files changed, 141 insertions(+), 75 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index ebc4e4f15e5..461ef30f17a 100644 +index b8c99985af4..bbea6bbb454 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -68,6 +68,7 @@ enum wined3d_cs_op +@@ -69,6 +69,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_UPDATE_SUB_RESOURCE, WINED3D_CS_OP_PUSH_CONSTANTS, - WINED3D_CS_OP_BLT, WINED3D_CS_OP_CLEAR_RTV, + WINED3D_CS_OP_UPDATE_TEXTURE, }; struct wined3d_cs_sync -@@ -392,6 +393,12 @@ struct wined3d_cs_clear_rtv +@@ -404,6 +405,12 @@ struct wined3d_cs_clear_rtv const struct blit_shader *blitter; }; @@ -35,7 +35,7 @@ static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) { } -@@ -1875,6 +1882,35 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge +@@ -1988,6 +1995,35 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge cs->ops->submit(cs); } @@ -71,19 +71,19 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -1919,6 +1955,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void +@@ -2033,6 +2069,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants, - /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, + /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, }; static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 72cf63af27f..8f7640cadc2 100644 +index 364eac4411e..d0e1fe6e9d7 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -3627,34 +3627,17 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device +@@ -3659,34 +3659,17 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device start_idx, index_count, start_instance, instance_count, TRUE); } @@ -122,7 +122,7 @@ /* Only a prepare, since we're uploading entire volumes. */ wined3d_texture_prepare_texture(dst_texture, context, FALSE); -@@ -3662,32 +3645,89 @@ static HRESULT wined3d_device_update_texture_3d(struct wined3d_device *device, +@@ -3694,32 +3677,89 @@ static HRESULT wined3d_device_update_texture_3d(struct wined3d_device *device, for (i = 0; i < level_count; ++i) { @@ -222,7 +222,7 @@ TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture); -@@ -3724,63 +3764,48 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, +@@ -3756,63 +3796,48 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, return WINED3DERR_INVALIDCALL; } @@ -316,10 +316,10 @@ HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 334cdf0fb8b..81bcadc927f 100644 +index f69cead4d1c..fcefe12d226 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -2683,6 +2683,8 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL +@@ -2703,6 +2703,8 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; @@ -328,10 +328,10 @@ static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) { -@@ -3272,6 +3274,8 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, - void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; - void wined3d_cs_emit_sync(struct wined3d_cs *cs); - void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; +@@ -3292,6 +3294,8 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou + void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, + unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, + unsigned int slice_pitch) DECLSPEC_HIDDEN; +void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, + struct wined3d_texture *dst) DECLSPEC_HIDDEN; void wined3d_cs_init_object(struct wined3d_cs *cs, diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0012-wined3d-Send-update_sub_resource-calls-through-the-c.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0012-wined3d-Send-update_sub_resource-calls-through-the-c.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0012-wined3d-Send-update_sub_resource-calls-through-the-c.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0012-wined3d-Send-update_sub_resource-calls-through-the-c.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,190 +0,0 @@ -From 816ad331869dde6ef0c3326e010ef672e55e8b9a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Stefan=20D=C3=B6singer?= -Date: Fri, 4 Sep 2015 15:22:49 +0200 -Subject: wined3d: Send update_sub_resource calls through the command stream. - ---- - dlls/wined3d/cs.c | 67 ++++++++++++++++++++++++++++++++++++++++++ - dlls/wined3d/device.c | 22 +------------- - dlls/wined3d/texture.c | 2 +- - dlls/wined3d/wined3d_private.h | 5 ++++ - 4 files changed, 74 insertions(+), 22 deletions(-) - -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 6ffdd920403..ac9e09345dd 100644 ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -70,6 +70,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_BLT, - WINED3D_CS_OP_CLEAR_RTV, - WINED3D_CS_OP_UPDATE_TEXTURE, -+ WINED3D_CS_OP_UPDATE_SUB_RESOURCE, - }; - - struct wined3d_cs_sync -@@ -405,6 +406,15 @@ struct wined3d_cs_update_texture - struct wined3d_texture *src, *dst; - }; - -+struct wined3d_cs_update_sub_resource -+{ -+ enum wined3d_cs_op opcode; -+ struct wined3d_resource *resource; -+ unsigned int sub_resource_idx, row_pitch, depth_pitch; -+ const struct wined3d_box *box; -+ const void *data; -+}; -+ - static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) - { - } -@@ -1928,6 +1938,62 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur - cs->ops->submit(cs); - } - -+static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_update_sub_resource *op = data; -+ struct wined3d_const_bo_address addr; -+ struct wined3d_context *context; -+ struct wined3d_texture *texture; -+ unsigned int width, height, depth, level; -+ -+ texture = wined3d_texture_from_resource(op->resource); -+ -+ level = op->sub_resource_idx % texture->level_count; -+ width = wined3d_texture_get_level_width(texture, level); -+ height = wined3d_texture_get_level_height(texture, level); -+ depth = wined3d_texture_get_level_depth(texture, level); -+ -+ addr.buffer_object = 0; -+ addr.addr = op->data; -+ -+ context = context_acquire(texture->resource.device, NULL, 0); -+ -+ /* Only load the sub-resource for partial updates. */ -+ if (!op->box || (!op->box->left && !op->box->top && !op->box->front -+ && op->box->right == width && op->box->bottom == height && op->box->back == depth)) -+ wined3d_texture_prepare_texture(texture, context, FALSE); -+ else -+ wined3d_texture_load_location(texture, op->sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); -+ wined3d_texture_bind_and_dirtify(texture, context, FALSE); -+ -+ wined3d_texture_upload_data(texture, op->sub_resource_idx, context, op->box, &addr, op->row_pitch, op->depth_pitch); -+ -+ context_release(context); -+ -+ wined3d_texture_validate_location(texture, op->sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); -+ wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); -+} -+ -+void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, -+ unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, -+ unsigned int depth_pitch) -+{ -+ struct wined3d_cs_update_sub_resource *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; -+ op->resource = resource; -+ op->sub_resource_idx = sub_resource_idx; -+ op->box = box; -+ op->data = data; -+ op->row_pitch = row_pitch; -+ op->depth_pitch = depth_pitch; -+ -+ /* The data pointer may go away, need to wait until the data is read. Copying the data may be faster. -+ * Don't forget to copy box as well in this case. */ -+ cs->ops->submit_and_wait(cs); -+} -+ - static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = - { - /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -1974,6 +2040,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, - /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, - /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, -+ /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, - }; - - static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) -diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 6e7d4f800b3..86b1808463e 100644 ---- a/dlls/wined3d/device.c -+++ b/dlls/wined3d/device.c -@@ -4171,8 +4171,6 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - unsigned int depth_pitch) - { - unsigned int width, height, depth, level; -- struct wined3d_const_bo_address addr; -- struct wined3d_context *context; - struct wined3d_texture *texture; - - TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u.\n", -@@ -4222,25 +4220,7 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - return; - } - -- addr.buffer_object = 0; -- addr.addr = data; -- -- context = context_acquire(resource->device, NULL, 0); -- -- /* Only load the sub-resource for partial updates. */ -- if (!box || (!box->left && !box->top && !box->front -- && box->right == width && box->bottom == height && box->back == depth)) -- wined3d_texture_prepare_texture(texture, context, FALSE); -- else -- wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); -- wined3d_texture_bind_and_dirtify(texture, context, FALSE); -- -- wined3d_texture_upload_data(texture, sub_resource_idx, context, box, &addr, row_pitch, depth_pitch); -- -- context_release(context); -- -- wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); -- wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); -+ wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch); - } - - HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device, -diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c -index 74b1ca2c546..5673a93f791 100644 ---- a/dlls/wined3d/texture.c -+++ b/dlls/wined3d/texture.c -@@ -1498,7 +1498,7 @@ void CDECL wined3d_texture_generate_mipmaps(struct wined3d_texture *texture) - FIXME("texture %p stub!\n", texture); - } - --static struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct wined3d_texture *texture, -+struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct wined3d_texture *texture, - unsigned int sub_resource_idx) - { - UINT sub_count = texture->level_count * texture->layer_count; -diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 9e2c272eeda..17cb43771d8 100644 ---- a/dlls/wined3d/wined3d_private.h -+++ b/dlls/wined3d/wined3d_private.h -@@ -2919,6 +2919,8 @@ BOOL wined3d_texture_check_block_align(const struct wined3d_texture *texture, - GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) DECLSPEC_HIDDEN; - void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_bo_address *data, DWORD locations) DECLSPEC_HIDDEN; -+struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) DECLSPEC_HIDDEN; - void wined3d_texture_invalidate_location(struct wined3d_texture *texture, - unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN; - void wined3d_texture_load(struct wined3d_texture *texture, -@@ -3264,6 +3266,9 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, - void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; - void wined3d_cs_emit_sync(struct wined3d_cs *cs); - void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, -+ unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, -+ unsigned int depth_pitch) DECLSPEC_HIDDEN; - void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, - struct wined3d_texture *dst) DECLSPEC_HIDDEN; - void wined3d_cs_init_object(struct wined3d_cs *cs, --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0013-wined3d-Send-getdc-and-releasedc-through-the-command.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0013-wined3d-Send-getdc-and-releasedc-through-the-command.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0013-wined3d-Send-getdc-and-releasedc-through-the-command.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0013-wined3d-Send-getdc-and-releasedc-through-the-command.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,260 +0,0 @@ -From 5cde9b1eaee021e59d3a7b17bfdc69270771003d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Stefan=20D=C3=B6singer?= -Date: Sun, 16 Mar 2014 14:13:42 +0100 -Subject: wined3d: Send getdc and releasedc through the command stream. - -Another hacky patch to avoid using GL outside the worker thread. ---- - dlls/wined3d/cs.c | 60 +++++++++++++++++++++++++++++++ - dlls/wined3d/texture.c | 81 +++++++++++++++++++++++++++--------------- - dlls/wined3d/wined3d_private.h | 7 ++++ - 3 files changed, 119 insertions(+), 29 deletions(-) - -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index e2b756eecb9..86ae7eb89c8 100644 ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -70,6 +70,8 @@ enum wined3d_cs_op - WINED3D_CS_OP_CLEAR_RTV, - WINED3D_CS_OP_UPDATE_TEXTURE, - WINED3D_CS_OP_UPDATE_SUB_RESOURCE, -+ WINED3D_CS_OP_GET_DC, -+ WINED3D_CS_OP_RELEASE_DC, - }; - - struct wined3d_cs_sync -@@ -409,6 +411,14 @@ struct wined3d_cs_update_sub_resource - const void *data; - }; - -+struct wined3d_cs_get_release_dc -+{ -+ enum wined3d_cs_op opcode; -+ struct wined3d_texture *texture; -+ unsigned int sub_resource_idx; -+ HRESULT *hr; -+}; -+ - static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) - { - } -@@ -1977,6 +1987,54 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r - cs->ops->submit_and_wait(cs); - } - -+static void wined3d_cs_exec_get_dc(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_get_release_dc *op = data; -+ -+ *op->hr = wined3d_texture_get_dc_cs(op->texture, op->sub_resource_idx); -+} -+ -+HRESULT wined3d_cs_emit_get_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) -+{ -+ struct wined3d_cs_get_release_dc *op; -+ HRESULT hr; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_GET_DC; -+ op->texture = texture; -+ op->sub_resource_idx = sub_resource_idx; -+ op->hr = &hr; -+ -+ cs->ops->submit_and_wait(cs); -+ -+ return hr; -+} -+ -+static void wined3d_cs_exec_release_dc(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_get_release_dc *op = data; -+ -+ *op->hr = wined3d_texture_release_dc_cs(op->texture, op->sub_resource_idx); -+} -+ -+HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) -+{ -+ struct wined3d_cs_get_release_dc *op; -+ HRESULT hr; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_RELEASE_DC; -+ op->texture = texture; -+ op->sub_resource_idx = sub_resource_idx; -+ op->hr = &hr; -+ -+ cs->ops->submit_and_wait(cs); -+ -+ return hr; -+} -+ - static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = - { - /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -2023,6 +2081,8 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, - /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, - /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, -+ /* WINED3D_CS_OP_GET_DC */ wined3d_cs_exec_get_dc, -+ /* WINED3D_CS_OP_RELEASE_DC */ wined3d_cs_exec_release_dc, - }; - - static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) -diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c -index 65777aad7be..644637696ea 100644 ---- a/dlls/wined3d/texture.c -+++ b/dlls/wined3d/texture.c -@@ -3486,13 +3486,41 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct - return WINED3D_OK; - } - -+HRESULT wined3d_texture_get_dc_cs(struct wined3d_texture *texture, unsigned int sub_resource_idx) -+{ -+ struct wined3d_device *device = texture->resource.device; -+ struct wined3d_context *context = NULL; -+ struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; -+ struct wined3d_surface *surface = sub_resource->u.surface; -+ HRESULT hr = WINED3D_OK; -+ -+ if (device->d3d_initialized) -+ context = context_acquire(device, NULL, 0); -+ -+ wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); -+ wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); -+ -+ if (!surface->dc) -+ hr = wined3d_surface_create_dc(surface); -+ if (context) -+ context_release(context); -+ if (FAILED(hr)) -+ return hr; -+ -+ if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) -+ texture->flags |= WINED3D_TEXTURE_DC_IN_USE; -+ ++texture->resource.map_count; -+ ++sub_resource->map_count; -+ -+ return hr; -+} -+ - HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC *dc) - { - struct wined3d_device *device = texture->resource.device; - struct wined3d_texture_sub_resource *sub_resource; -- struct wined3d_context *context = NULL; - struct wined3d_surface *surface; -- HRESULT hr = WINED3D_OK; -+ HRESULT hr; - - TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc); - -@@ -3517,28 +3545,32 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i - if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) - return WINED3DERR_INVALIDCALL; - -- if (device->d3d_initialized) -- context = context_acquire(device, NULL, 0); -- -- wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); -- wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); -- -- if (!surface->dc) -- hr = wined3d_surface_create_dc(surface); -- if (context) -- context_release(context); -+ hr = wined3d_cs_emit_get_dc(device->cs, texture, sub_resource_idx); - if (FAILED(hr)) -- return WINED3DERR_INVALIDCALL; -- -- if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) -- texture->flags |= WINED3D_TEXTURE_DC_IN_USE; -- ++texture->resource.map_count; -- ++sub_resource->map_count; -+ return hr; - - *dc = surface->dc; - TRACE("Returning dc %p.\n", *dc); - -- return hr; -+ return WINED3D_OK; -+} -+ -+HRESULT wined3d_texture_release_dc_cs(struct wined3d_texture *texture, unsigned int sub_resource_idx) -+{ -+ struct wined3d_device *device = texture->resource.device; -+ struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; -+ struct wined3d_surface *surface = sub_resource->u.surface; -+ -+ if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D)) -+ wined3d_surface_destroy_dc(surface); -+ -+ --sub_resource->map_count; -+ if (!--texture->resource.map_count && texture->update_map_binding) -+ wined3d_texture_update_map_binding(texture); -+ if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) -+ texture->flags &= ~WINED3D_TEXTURE_DC_IN_USE; -+ -+ return WINED3D_OK; - } - - HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc) -@@ -3569,14 +3601,5 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign - return WINED3DERR_INVALIDCALL; - } - -- if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D)) -- wined3d_surface_destroy_dc(surface); -- -- --sub_resource->map_count; -- if (!--texture->resource.map_count && texture->update_map_binding) -- wined3d_texture_update_map_binding(texture); -- if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) -- texture->flags &= ~WINED3D_TEXTURE_DC_IN_USE; -- -- return WINED3D_OK; -+ return wined3d_cs_emit_release_dc(device->cs, texture, sub_resource_idx); - } -diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 9cd5c2e316a..822d951b80f 100644 ---- a/dlls/wined3d/wined3d_private.h -+++ b/dlls/wined3d/wined3d_private.h -@@ -2928,6 +2928,7 @@ void wined3d_texture_bind_and_dirtify(struct wined3d_texture *texture, - struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; - BOOL wined3d_texture_check_block_align(const struct wined3d_texture *texture, - unsigned int level, const struct wined3d_box *box) DECLSPEC_HIDDEN; -+HRESULT wined3d_texture_get_dc_cs(struct wined3d_texture *texture, unsigned int sub_resource_idx) DECLSPEC_HIDDEN; - GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) DECLSPEC_HIDDEN; - void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_bo_address *data, DWORD locations) DECLSPEC_HIDDEN; -@@ -2945,6 +2946,8 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned - struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; - void wined3d_texture_prepare_texture(struct wined3d_texture *texture, - struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; -+HRESULT wined3d_texture_release_dc_cs(struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) DECLSPEC_HIDDEN; - void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN; - void wined3d_texture_set_swapchain(struct wined3d_texture *texture, - struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -@@ -3220,6 +3223,8 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, - void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base_vertex_idx, - unsigned int start_idx, unsigned int index_count, unsigned int start_instance, - unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN; -+HRESULT wined3d_cs_emit_get_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) DECLSPEC_HIDDEN; - void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; - void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; - void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, -@@ -3227,6 +3232,8 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw - void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_constants p, - unsigned int start_idx, unsigned int count, const void *constants) DECLSPEC_HIDDEN; - void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; -+HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) DECLSPEC_HIDDEN; - void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; - void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, - const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN; --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0014-wined3d-Send-query_poll-through-the-command-stream.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0014-wined3d-Send-query_poll-through-the-command-stream.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0014-wined3d-Send-query_poll-through-the-command-stream.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0014-wined3d-Send-query_poll-through-the-command-stream.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 9708948e10b9272abae5a4ffdad1b2e1be4b2dd4 Mon Sep 17 00:00:00 2001 +From 644d2723fdf8d547bf5a0a4c43d119b6801dac77 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 19 Feb 2017 01:58:25 +0100 Subject: wined3d: Send query_poll through the command stream. @@ -10,10 +10,10 @@ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 29b27176d34..81deae77363 100644 +index bbea6bbb45..6d01424bda 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -59,6 +59,7 @@ enum wined3d_cs_op +@@ -61,6 +61,7 @@ enum wined3d_cs_op WINED3D_CS_OP_RESET_STATE, WINED3D_CS_OP_CALLBACK, WINED3D_CS_OP_QUERY_ISSUE, @@ -21,7 +21,7 @@ WINED3D_CS_OP_PRELOAD_RESOURCE, WINED3D_CS_OP_UNLOAD_RESOURCE, WINED3D_CS_OP_MAP, -@@ -319,6 +320,14 @@ struct wined3d_cs_query_issue +@@ -330,6 +331,14 @@ struct wined3d_cs_query_issue DWORD flags; }; @@ -36,7 +36,7 @@ struct wined3d_cs_preload_resource { enum wined3d_cs_op opcode; -@@ -1584,6 +1593,30 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu +@@ -1665,6 +1674,30 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu cs->ops->submit(cs); } @@ -67,7 +67,7 @@ static void wined3d_cs_exec_preload_resource(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_preload_resource *op = data; -@@ -2087,6 +2120,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void +@@ -2061,6 +2094,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback, /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, @@ -76,7 +76,7 @@ /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource, /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c -index bc3b15f30dd..15935ab4469 100644 +index bc3b15f30d..15935ab446 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -350,7 +350,7 @@ HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query, @@ -89,17 +89,17 @@ if (data) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index da3ee393739..91b2215f287 100644 +index 9301d10999..9d25bae822 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3220,6 +3220,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw +@@ -3252,6 +3252,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants) DECLSPEC_HIDDEN; void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; +BOOL wined3d_cs_emit_query_poll(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; - HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, - unsigned int sub_resource_idx) DECLSPEC_HIDDEN; void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, + const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN; -- 2.11.0 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0016-wined3d-Update-the-swap-interval-through-the-CS-in-r.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0016-wined3d-Update-the-swap-interval-through-the-CS-in-r.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0016-wined3d-Update-the-swap-interval-through-the-CS-in-r.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0016-wined3d-Update-the-swap-interval-through-the-CS-in-r.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 207bfb3829ccd61de999f5d1797fabee9cb44e4c Mon Sep 17 00:00:00 2001 +From d3e3b9bf7f27aa281a7e930f70018006ca20258e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Sat, 7 May 2016 21:58:06 +0100 Subject: wined3d: Update the swap interval through the CS in reset. @@ -10,19 +10,19 @@ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index eaa9267e5ba..770760f78c7 100644 +index 6d01424bda..1da3addcdd 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -73,6 +73,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_UPDATE_SUB_RESOURCE, - WINED3D_CS_OP_GET_DC, - WINED3D_CS_OP_RELEASE_DC, +@@ -71,6 +71,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_PUSH_CONSTANTS, + WINED3D_CS_OP_CLEAR_RTV, + WINED3D_CS_OP_UPDATE_TEXTURE, + WINED3D_CS_OP_UPDATE_SWAP_INTERVAL, }; struct wined3d_cs_sync -@@ -428,6 +429,12 @@ struct wined3d_cs_get_release_dc - HRESULT *hr; +@@ -420,6 +421,12 @@ struct wined3d_cs_update_texture + struct wined3d_texture *src, *dst; }; +struct wined3d_cs_update_swap_interval @@ -34,8 +34,8 @@ static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) { } -@@ -2067,6 +2074,24 @@ HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture - return hr; +@@ -2057,6 +2064,24 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur + cs->ops->submit(cs); } +static void wined3d_cs_exec_update_swap_interval(struct wined3d_cs *cs, const void *data) @@ -59,19 +59,19 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -2116,6 +2141,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, - /* WINED3D_CS_OP_GET_DC */ wined3d_cs_exec_get_dc, - /* WINED3D_CS_OP_RELEASE_DC */ wined3d_cs_exec_release_dc, +@@ -2104,6 +2129,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants, + /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, + /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, + /* WINED3D_CS_OP_UPDATE_SWAP_INTERVAL */ wined3d_cs_exec_update_swap_interval, }; static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 03361548a89..3870ecf3f0d 100644 +index eb8c86f954..bf48c71564 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -4850,7 +4850,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, +@@ -4907,7 +4907,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, { if (reset_state) hr = wined3d_device_create_primary_opengl_context(device); @@ -81,13 +81,13 @@ /* All done. There is no need to reload resources or shaders, this will happen automatically on the diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 667b66f8231..6e215b8f2c4 100644 +index 9d25bae822..b5a27dcbac 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3301,6 +3301,7 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou +@@ -3305,6 +3305,7 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, - unsigned int depth_pitch) DECLSPEC_HIDDEN; + unsigned int slice_pitch) DECLSPEC_HIDDEN; +void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, struct wined3d_texture *dst) DECLSPEC_HIDDEN; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0017-wined3d-Create-initial-DCs-through-the-CS.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0017-wined3d-Create-initial-DCs-through-the-CS.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0017-wined3d-Create-initial-DCs-through-the-CS.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0017-wined3d-Create-initial-DCs-through-the-CS.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -From 2aadab885c6dca2c21e7c7e598205d5e771f6538 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Stefan=20D=C3=B6singer?= -Date: Sat, 7 May 2016 22:31:28 +0100 -Subject: wined3d: Create initial DCs through the CS. - ---- - dlls/wined3d/texture.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - -diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c -index 2360c589902..70c4590f74a 100644 ---- a/dlls/wined3d/texture.c -+++ b/dlls/wined3d/texture.c -@@ -1314,7 +1314,11 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT - wined3d_texture_invalidate_location(texture, 0, ~valid_location); - - if (create_dib) -- wined3d_surface_create_dc(surface); -+ { -+ HDC dc; -+ wined3d_texture_get_dc(texture, 0, &dc); -+ wined3d_texture_release_dc(texture, 0, dc); -+ } - - return WINED3D_OK; - } -@@ -2729,11 +2733,15 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 - - TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface); - -- if (((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) -- && FAILED(hr = wined3d_surface_create_dc(surface))) -+ if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) - { -- wined3d_texture_cleanup_sync(texture); -- return hr; -+ HDC dc; -+ if (FAILED(hr = wined3d_texture_get_dc(texture, idx, &dc))) -+ { -+ wined3d_texture_cleanup_sync(texture); -+ return hr; -+ } -+ wined3d_texture_release_dc(texture, idx, dc); - } - } - } --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0018-wined3d-Fix-context_acquire-not-being-called-from-th.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0018-wined3d-Fix-context_acquire-not-being-called-from-th.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0018-wined3d-Fix-context_acquire-not-being-called-from-th.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0018-wined3d-Fix-context_acquire-not-being-called-from-th.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From d8510f1a77606628c1868332f11f5dd8ec90f82e Mon Sep 17 00:00:00 2001 +From b3788f5f7f5a57baeb565e5d3a08cfaf263de01e Mon Sep 17 00:00:00 2001 From: Nils Kuhnhenn Date: Fri, 5 Aug 2016 20:28:46 +0200 Subject: wined3d: Fix context_acquire not being called from the command thread @@ -11,18 +11,18 @@ 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 770760f78c7..8b13ca2f792 100644 +index 1da3addcdd..d0c0d94537 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -74,6 +74,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_GET_DC, - WINED3D_CS_OP_RELEASE_DC, +@@ -72,6 +72,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_CLEAR_RTV, + WINED3D_CS_OP_UPDATE_TEXTURE, WINED3D_CS_OP_UPDATE_SWAP_INTERVAL, + WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION, }; struct wined3d_cs_sync -@@ -435,6 +436,13 @@ struct wined3d_cs_update_swap_interval +@@ -427,6 +428,13 @@ struct wined3d_cs_update_swap_interval struct wined3d_swapchain *swapchain; }; @@ -36,7 +36,7 @@ static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) { } -@@ -2092,6 +2100,45 @@ void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_ +@@ -2082,6 +2090,45 @@ void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_ cs->ops->submit_and_wait(cs); } @@ -82,19 +82,19 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -2142,6 +2189,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_GET_DC */ wined3d_cs_exec_get_dc, - /* WINED3D_CS_OP_RELEASE_DC */ wined3d_cs_exec_release_dc, +@@ -2130,6 +2177,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, + /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, /* WINED3D_CS_OP_UPDATE_SWAP_INTERVAL */ wined3d_cs_exec_update_swap_interval, + /* WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION */ wined3d_cs_exec_texture_add_dirty_region, }; static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c -index baecda0b9ed..4c6a8e96611 100644 +index 41da65112d..7edb214c2a 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c -@@ -1523,7 +1523,6 @@ struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct win +@@ -1658,7 +1658,6 @@ static struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(str HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, UINT layer, const struct wined3d_box *dirty_region) { @@ -102,7 +102,7 @@ unsigned int sub_resource_idx; TRACE("texture %p, layer %u, dirty_region %s.\n", texture, layer, debug_box(dirty_region)); -@@ -1535,19 +1534,7 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, +@@ -1670,19 +1669,7 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, } sub_resource_idx = layer * texture->level_count; @@ -124,10 +124,10 @@ } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 6e215b8f2c4..efa3b879098 100644 +index b5a27dcbac..c846148069 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3296,6 +3296,8 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined +@@ -3300,6 +3300,8 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0019-wined3d-Wrap-GL-BOs-in-a-structure.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0019-wined3d-Wrap-GL-BOs-in-a-structure.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0019-wined3d-Wrap-GL-BOs-in-a-structure.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0019-wined3d-Wrap-GL-BOs-in-a-structure.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 966ef73fc86a013fafb0ed3491d6347e4224b504 Mon Sep 17 00:00:00 2001 +From 5fab8a00429f7e67ac09cd82a6b168c5f0abb590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Fri, 30 Aug 2013 17:00:35 +0200 Subject: wined3d: Wrap GL BOs in a structure @@ -6,17 +6,17 @@ The idea is to use those structures for mapping through the command stream and caching them for DISCARD maps. --- - dlls/wined3d/device.c | 53 +++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/device.c | 53 +++++++++++++++++++++++++++++++++++++ dlls/wined3d/surface.c | 2 +- - dlls/wined3d/texture.c | 57 ++++++++++++++++++------------------------ - dlls/wined3d/wined3d_private.h | 14 ++++++++++- - 4 files changed, 92 insertions(+), 34 deletions(-) + dlls/wined3d/texture.c | 59 +++++++++++++++++++----------------------- + dlls/wined3d/wined3d_private.h | 14 +++++++++- + 4 files changed, 93 insertions(+), 35 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 1c424d517bb..18695774bc8 100644 +index bf48c71564..a7dd944dab 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -5169,3 +5169,56 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL +@@ -5222,3 +5222,56 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL else return CallWindowProcA(proc, window, message, wparam, lparam); } @@ -74,10 +74,10 @@ + wined3d_device_destroy_bo(device, context, bo); +} diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c -index 8c5624c8787..e641dcc8b80 100644 +index cd82d46a00..59c1f55455 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c -@@ -2801,7 +2801,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, +@@ -2773,7 +2773,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface, /* Don't use PBOs for converted surfaces. During PBO conversion we look at * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is * getting called. */ @@ -87,7 +87,7 @@ TRACE("Removing the pbo attached to surface %p.\n", surface); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c -index 7dc0f096f77..2d3d51f0489 100644 +index 05dc506716..5abd80eae1 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -337,7 +337,7 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su @@ -106,20 +106,21 @@ - unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info) + unsigned int sub_resource_idx, struct wined3d_context *context) { -- GLuint *buffer_object; +- GLuint *buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object; + struct wined3d_gl_bo *buffer = texture->sub_resources[sub_resource_idx].buffer; + GLuint name = buffer->name; -- buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object; - GL_EXTCALL(glDeleteBuffers(1, buffer_object)); - checkGLcall("glDeleteBuffers"); + wined3d_device_release_bo(texture->resource.device, buffer, context); + texture->sub_resources[sub_resource_idx].buffer = NULL; - wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); -- *buffer_object = 0; ++ wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); TRACE("Deleted buffer object %u for texture %p, sub-resource %u.\n", - *buffer_object, texture, sub_resource_idx); +- +- wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); +- *buffer_object = 0; + name, texture, sub_resource_idx); } @@ -167,7 +168,7 @@ } if (context) context_release(context); -@@ -1327,22 +1323,19 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT +@@ -1351,22 +1347,19 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT /* Context activation is done by the caller. */ static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *texture, @@ -195,7 +196,7 @@ } static void wined3d_texture_force_reload(struct wined3d_texture *texture) -@@ -1468,7 +1461,7 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned +@@ -1492,7 +1485,7 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned return TRUE; case WINED3D_LOCATION_BUFFER: @@ -204,7 +205,7 @@ return TRUE; case WINED3D_LOCATION_TEXTURE_RGB: -@@ -1768,7 +1761,7 @@ static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned in +@@ -1792,7 +1785,7 @@ static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned in } else if (sub_resource->locations & WINED3D_LOCATION_BUFFER) { @@ -213,7 +214,7 @@ wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); texture1d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch); -@@ -1813,7 +1806,7 @@ static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned in +@@ -1837,7 +1830,7 @@ static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned in case WINED3D_LOCATION_BUFFER: if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { @@ -222,7 +223,7 @@ if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) wined3d_texture_bind_and_dirtify(texture, context, FALSE); -@@ -2107,8 +2100,8 @@ static void wined3d_texture_unload(struct wined3d_resource *resource) +@@ -2131,8 +2124,8 @@ static void wined3d_texture_unload(struct wined3d_resource *resource) wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_DISCARDED); } @@ -233,7 +234,7 @@ if (resource->type == WINED3D_RTYPE_TEXTURE_2D) { -@@ -2906,7 +2899,7 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in +@@ -2917,7 +2910,7 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in } else if (sub_resource->locations & WINED3D_LOCATION_BUFFER) { @@ -242,7 +243,7 @@ wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); -@@ -2952,7 +2945,7 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in +@@ -2963,7 +2956,7 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in case WINED3D_LOCATION_BUFFER: if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { @@ -252,10 +253,10 @@ if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) wined3d_texture_bind_and_dirtify(texture, context, FALSE); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 834a681f6a4..6204fc3915d 100644 +index 91e0bfb313..6114e5b88a 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -2571,6 +2571,14 @@ struct wined3d_state +@@ -2606,6 +2606,14 @@ struct wined3d_state struct wined3d_rasterizer_state *rasterizer_state; }; @@ -270,7 +271,7 @@ #define WINED3D_UNMAPPED_STAGE ~0u /* Multithreaded flag. Removed from the public header to signal that -@@ -2684,6 +2692,10 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso +@@ -2720,6 +2728,10 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; void device_exec_update_texture(struct wined3d_context *context, struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture) DECLSPEC_HIDDEN; @@ -281,7 +282,7 @@ static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) { -@@ -2874,7 +2886,7 @@ struct wined3d_texture +@@ -2910,7 +2922,7 @@ struct wined3d_texture unsigned int map_count; DWORD locations; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0020-wined3d-Send-buffer-update-subresource-requests-thro.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0020-wined3d-Send-buffer-update-subresource-requests-thro.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0020-wined3d-Send-buffer-update-subresource-requests-thro.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0020-wined3d-Send-buffer-update-subresource-requests-thro.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -From 6f933585f6c0fb35a9e3ef65645c86f8ecb6f4da Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Tue, 7 Feb 2017 14:01:52 +0100 -Subject: wined3d: Send buffer update subresource requests through CS. - ---- - dlls/wined3d/cs.c | 11 +++++++++++ - dlls/wined3d/device.c | 7 +------ - 2 files changed, 12 insertions(+), 6 deletions(-) - -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 5b529d000f4..7e032d8ec05 100644 ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -2012,6 +2012,17 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi - struct wined3d_texture *texture; - unsigned int width, height, depth, level; - -+ if (op->resource->type == WINED3D_RTYPE_BUFFER) -+ { -+ struct wined3d_buffer *buffer = buffer_from_resource(op->resource); -+ HRESULT hr; -+ -+ if (FAILED(hr = wined3d_buffer_upload_data(buffer, op->box, op->data))) -+ WARN("Failed to update buffer data, hr %#x.\n", hr); -+ -+ return; -+ } -+ - texture = wined3d_texture_from_resource(op->resource); - - level = op->sub_resource_idx % texture->level_count; -diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index bd3a132c496..bf647d5241c 100644 ---- a/dlls/wined3d/device.c -+++ b/dlls/wined3d/device.c -@@ -4178,18 +4178,13 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - - if (resource->type == WINED3D_RTYPE_BUFFER) - { -- struct wined3d_buffer *buffer = buffer_from_resource(resource); -- HRESULT hr; -- - if (sub_resource_idx > 0) - { - WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); - return; - } - -- if (FAILED(hr = wined3d_buffer_upload_data(buffer, box, data))) -- WARN("Failed to update buffer data, hr %#x.\n", hr); -- -+ wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch); - return; - } - --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0021-wined3d-Send-buffer-copy-requests-through-CS.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0021-wined3d-Send-buffer-copy-requests-through-CS.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0021-wined3d-Send-buffer-copy-requests-through-CS.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0021-wined3d-Send-buffer-copy-requests-through-CS.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,132 +0,0 @@ -From 3bf5f63ec62c705afb14d485df3e2d0bd799d7dd Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Tue, 7 Feb 2017 14:37:07 +0100 -Subject: wined3d: Send buffer copy requests through CS. - ---- - dlls/wined3d/cs.c | 44 ++++++++++++++++++++++++++++++++++++++++++ - dlls/wined3d/device.c | 8 ++++---- - dlls/wined3d/wined3d_private.h | 3 +++ - 3 files changed, 51 insertions(+), 4 deletions(-) - -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index be7e041b86c..51ac0c2b000 100644 ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -75,6 +75,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_RELEASE_DC, - WINED3D_CS_OP_UPDATE_SWAP_INTERVAL, - WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION, -+ WINED3D_CS_OP_BUFFER_COPY, - }; - - struct wined3d_cs_sync -@@ -443,6 +444,16 @@ struct wined3d_cs_texture_add_dirty_region - unsigned int sub_resource_idx; - }; - -+struct wined3d_cs_buffer_copy -+{ -+ enum wined3d_cs_op opcode; -+ struct wined3d_buffer *dst_buffer; -+ unsigned int dst_offset; -+ struct wined3d_buffer *src_buffer; -+ unsigned int src_offset; -+ unsigned int size; -+}; -+ - static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) - { - } -@@ -2150,6 +2161,38 @@ void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, - cs->ops->submit(cs); - } - -+static void wined3d_cs_exec_buffer_copy(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_buffer_copy *op = data; -+ HRESULT hr; -+ -+ if (FAILED(hr = wined3d_buffer_copy(op->dst_buffer, op->dst_offset, op->src_buffer, op->src_offset, op->size))) -+ ERR("Failed to copy buffer, hr %#x.\n", hr); -+ -+ wined3d_resource_release(&op->dst_buffer->resource); -+ wined3d_resource_release(&op->src_buffer->resource); -+} -+ -+void wined3d_cs_emit_buffer_copy(struct wined3d_cs *cs, struct wined3d_buffer *dst_buffer, -+ unsigned int dst_offset, struct wined3d_buffer *src_buffer, unsigned int src_offset, -+ unsigned int size) -+{ -+ struct wined3d_cs_buffer_copy *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_BUFFER_COPY; -+ op->dst_buffer = dst_buffer; -+ op->dst_offset = dst_offset; -+ op->src_buffer = src_buffer; -+ op->src_offset = src_offset; -+ op->size = size; -+ -+ wined3d_resource_acquire(&dst_buffer->resource); -+ wined3d_resource_acquire(&src_buffer->resource); -+ -+ cs->ops->submit(cs); -+} -+ - static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = - { - /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -2201,6 +2244,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_RELEASE_DC */ wined3d_cs_exec_release_dc, - /* WINED3D_CS_OP_UPDATE_SWAP_INTERVAL */ wined3d_cs_exec_update_swap_interval, - /* WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION */ wined3d_cs_exec_texture_add_dirty_region, -+ /* WINED3D_CS_OP_BUFFER_COPY */ wined3d_cs_exec_buffer_copy, - }; - - static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) -diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 749ba9ca19c..a8ca7cbaf56 100644 ---- a/dlls/wined3d/device.c -+++ b/dlls/wined3d/device.c -@@ -3991,10 +3991,9 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device, - - if (dst_resource->type == WINED3D_RTYPE_BUFFER) - { -- if (FAILED(hr = wined3d_buffer_copy(buffer_from_resource(dst_resource), 0, -+ wined3d_cs_emit_buffer_copy(device->cs, buffer_from_resource(dst_resource), 0, - buffer_from_resource(src_resource), 0, -- dst_resource->size))) -- ERR("Failed to copy buffer, hr %#x.\n", hr); -+ dst_resource->size); - return; - } - -@@ -4116,8 +4115,9 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev - return WINED3DERR_INVALIDCALL; - } - -- return wined3d_buffer_copy(buffer_from_resource(dst_resource), dst_x, -+ wined3d_cs_emit_buffer_copy(device->cs, buffer_from_resource(dst_resource), dst_x, - buffer_from_resource(src_resource), src_offset, size); -+ return WINED3D_OK; - } - - if (dst_resource->type != WINED3D_RTYPE_TEXTURE_2D) -diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index d45c45c09dc..708091f573b 100644 ---- a/dlls/wined3d/wined3d_private.h -+++ b/dlls/wined3d/wined3d_private.h -@@ -3239,6 +3239,9 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf - const RECT *dst_rect, struct wined3d_surface *src_surface, - const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, - enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; -+void wined3d_cs_emit_buffer_copy(struct wined3d_cs *cs, struct wined3d_buffer *dst_buffer, -+ unsigned int dst_offset, struct wined3d_buffer *src_buffer, unsigned int src_offset, -+ unsigned int size) DECLSPEC_HIDDEN; - void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, - DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; - void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0026-wined3d-Map-vertex-buffers-through-cs.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0026-wined3d-Map-vertex-buffers-through-cs.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0026-wined3d-Map-vertex-buffers-through-cs.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0026-wined3d-Map-vertex-buffers-through-cs.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,206 +0,0 @@ -From 24eb775d29ee3563667d35b3319dddcb7830eddf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Tue, 7 Feb 2017 22:37:58 +0100 -Subject: wined3d: Map vertex buffers through cs. - ---- - dlls/wined3d/cs.c | 71 ++++++++++++++++++++++++++++++++++++++++++ - dlls/wined3d/device.c | 45 +------------------------- - dlls/wined3d/wined3d_private.h | 2 ++ - 3 files changed, 74 insertions(+), 44 deletions(-) - -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 54b81f74f64..b5c7432fec3 100644 ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -78,6 +78,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_UPDATE_SWAP_INTERVAL, - WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION, - WINED3D_CS_OP_BUFFER_COPY, -+ WINED3D_CS_OP_MAP_VERTEX_BUFFERS, - }; - - struct wined3d_cs_sync -@@ -468,6 +469,13 @@ struct wined3d_cs_buffer_copy - unsigned int size; - }; - -+struct wined3d_cs_map_vertex_buffers -+{ -+ enum wined3d_cs_op opcode; -+ UINT src_start_idx; -+ struct wined3d_stream_info *stream_info; -+}; -+ - static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) - { - } -@@ -2243,6 +2251,68 @@ void wined3d_cs_emit_buffer_copy(struct wined3d_cs *cs, struct wined3d_buffer *d - cs->ops->submit(cs); - } - -+static void wined3d_cs_exec_map_vertex_buffers(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_map_vertex_buffers *op = data; -+ struct wined3d_state *state = &cs->device->state; -+ const struct wined3d_gl_info *gl_info; -+ struct wined3d_context *context; -+ struct wined3d_shader *vs; -+ unsigned int i; -+ WORD map; -+ -+ /* Need any context to write to the vbo. */ -+ context = context_acquire(cs->device, NULL, 0); -+ gl_info = context->gl_info; -+ -+ vs = state->shader[WINED3D_SHADER_TYPE_VERTEX]; -+ state->shader[WINED3D_SHADER_TYPE_VERTEX] = NULL; -+ context_stream_info_from_declaration(context, state, op->stream_info); -+ state->shader[WINED3D_SHADER_TYPE_VERTEX] = vs; -+ -+ /* We can't convert FROM a VBO, and vertex buffers used to source into -+ * process_vertices() are unlikely to ever be used for drawing. Release -+ * VBOs in those buffers and fix up the stream_info structure. -+ * -+ * Also apply the start index. */ -+ for (i = 0, map = op->stream_info->use_map; map; map >>= 1, ++i) -+ { -+ struct wined3d_stream_info_element *e; -+ struct wined3d_buffer *buffer; -+ -+ if (!(map & 1)) -+ continue; -+ -+ e = &op->stream_info->elements[i]; -+ buffer = state->streams[e->stream_idx].buffer; -+ e->data.buffer_object = 0; -+ e->data.addr += (ULONG_PTR)wined3d_buffer_load_sysmem(buffer, context); -+ if (buffer->buffer_object) -+ { -+ GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object)); -+ buffer->buffer_object = 0; -+ wined3d_buffer_invalidate_location(buffer, WINED3D_LOCATION_BUFFER); -+ } -+ if (e->data.addr) -+ e->data.addr += e->stride * op->src_start_idx; -+ } -+ -+ context_release(context); -+} -+ -+void wined3d_cs_emit_map_vertex_buffers(struct wined3d_cs *cs, UINT src_start_idx, -+ struct wined3d_stream_info *stream_info) -+{ -+ struct wined3d_cs_map_vertex_buffers *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op)); -+ op->opcode = WINED3D_CS_OP_MAP_VERTEX_BUFFERS; -+ op->src_start_idx = src_start_idx; -+ op->stream_info = stream_info; -+ -+ cs->ops->submit_and_wait(cs); -+} -+ - static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = - { - /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, -@@ -2297,6 +2367,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_UPDATE_SWAP_INTERVAL */ wined3d_cs_exec_update_swap_interval, - /* WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION */ wined3d_cs_exec_texture_add_dirty_region, - /* WINED3D_CS_OP_BUFFER_COPY */ wined3d_cs_exec_buffer_copy, -+ /* WINED3D_CS_OP_MAP_VERTEX_BUFFERS */ wined3d_cs_exec_map_vertex_buffers, - }; - - static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) -diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 32d25cd1d0f..cd0ffbe32f7 100644 ---- a/dlls/wined3d/device.c -+++ b/dlls/wined3d/device.c -@@ -2811,7 +2811,6 @@ void CDECL wined3d_device_set_unordered_access_view(struct wined3d_device *devic - wined3d_device_set_pipeline_unordered_access_view(device, WINED3D_PIPELINE_GRAPHICS, idx, uav); - } - --/* Context activation is done by the caller. */ - #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) - static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount, - const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD flags, -@@ -3087,14 +3086,8 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device, - UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer, - const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf) - { -- struct wined3d_state *state = &device->state; - struct wined3d_stream_info stream_info; -- const struct wined3d_gl_info *gl_info; -- struct wined3d_context *context; -- struct wined3d_shader *vs; -- unsigned int i; - HRESULT hr; -- WORD map; - - TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, " - "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n", -@@ -3104,47 +3097,11 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device, - if (declaration) - FIXME("Output vertex declaration not implemented yet.\n"); - -- /* Need any context to write to the vbo. */ -- context = context_acquire(device, NULL, 0); -- gl_info = context->gl_info; -- -- vs = state->shader[WINED3D_SHADER_TYPE_VERTEX]; -- state->shader[WINED3D_SHADER_TYPE_VERTEX] = NULL; -- context_stream_info_from_declaration(context, state, &stream_info); -- state->shader[WINED3D_SHADER_TYPE_VERTEX] = vs; -- -- /* We can't convert FROM a VBO, and vertex buffers used to source into -- * process_vertices() are unlikely to ever be used for drawing. Release -- * VBOs in those buffers and fix up the stream_info structure. -- * -- * Also apply the start index. */ -- for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i) -- { -- struct wined3d_stream_info_element *e; -- struct wined3d_buffer *buffer; -- -- if (!(map & 1)) -- continue; -- -- e = &stream_info.elements[i]; -- buffer = state->streams[e->stream_idx].buffer; -- e->data.buffer_object = 0; -- e->data.addr += (ULONG_PTR)wined3d_buffer_load_sysmem(buffer, context); -- if (buffer->buffer_object) -- { -- GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object)); -- buffer->buffer_object = 0; -- wined3d_buffer_invalidate_location(buffer, WINED3D_LOCATION_BUFFER); -- } -- if (e->data.addr) -- e->data.addr += e->stride * src_start_idx; -- } -+ wined3d_cs_emit_map_vertex_buffers(device->cs, src_start_idx, &stream_info); - - hr = process_vertices_strided(device, dst_idx, vertex_count, - &stream_info, dst_buffer, flags, dst_fvf); - -- context_release(context); -- - return hr; - } - -diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 9fa4d00c24f..38693a52b29 100644 ---- a/dlls/wined3d/wined3d_private.h -+++ b/dlls/wined3d/wined3d_private.h -@@ -3328,6 +3328,8 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags) DECLSPEC_HIDDEN; - HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource, - unsigned int sub_resource_idx) DECLSPEC_HIDDEN; -+void wined3d_cs_emit_map_vertex_buffers(struct wined3d_cs *cs, UINT src_start_idx, -+ struct wined3d_stream_info *stream_info) DECLSPEC_HIDDEN; - - /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other - * fixed function semantics as D3DCOLOR or FLOAT16 */ --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0029-wined3d-Hackily-introduce-a-multithreaded-command-st.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0029-wined3d-Hackily-introduce-a-multithreaded-command-st.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0029-wined3d-Hackily-introduce-a-multithreaded-command-st.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0029-wined3d-Hackily-introduce-a-multithreaded-command-st.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,21 +1,21 @@ -From aaef68da7d9a0734e4827036aa561b0e67c70606 Mon Sep 17 00:00:00 2001 +From 64dd5bb16beb1eafba1cceda4b2ab8edcc5145e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Tue, 1 Oct 2013 14:31:56 +0200 Subject: wined3d: Hackily introduce a multithreaded command stream --- dlls/wined3d/context.c | 3 + - dlls/wined3d/cs.c | 443 ++++++++++++++++++++++++++++++++++++----- + dlls/wined3d/cs.c | 424 ++++++++++++++++++++++++++++++++++++----- dlls/wined3d/device.c | 2 +- dlls/wined3d/wined3d_main.c | 10 + - dlls/wined3d/wined3d_private.h | 33 ++- - 5 files changed, 430 insertions(+), 61 deletions(-) + dlls/wined3d/wined3d_private.h | 33 +++- + 5 files changed, 416 insertions(+), 56 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c -index 9e0805e822d..226d655b83a 100644 +index 9fa12e0c70..9bce86f775 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c -@@ -3722,6 +3722,9 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, +@@ -3766,6 +3766,9 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx); @@ -26,7 +26,7 @@ current_context = NULL; diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 93a80f2887e..35f6a5889fb 100644 +index d0c0d94537..94de259603 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -18,6 +18,7 @@ @@ -37,16 +37,16 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); -@@ -77,6 +78,7 @@ enum wined3d_cs_op +@@ -73,6 +74,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_UPDATE_TEXTURE, + WINED3D_CS_OP_UPDATE_SWAP_INTERVAL, WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION, - WINED3D_CS_OP_BUFFER_COPY, - WINED3D_CS_OP_MAP_VERTEX_BUFFERS, + WINED3D_CS_OP_STOP, }; struct wined3d_cs_sync -@@ -462,8 +464,14 @@ struct wined3d_cs_map_vertex_buffers - struct wined3d_stream_info *stream_info; +@@ -435,8 +437,14 @@ struct wined3d_cs_texture_add_dirty_region + unsigned int sub_resource_idx; }; -static void wined3d_cs_exec_sync(struct wined3d_cs *cs, const void *data) @@ -61,7 +61,7 @@ } void wined3d_cs_emit_sync(struct wined3d_cs *cs) -@@ -476,12 +484,14 @@ void wined3d_cs_emit_sync(struct wined3d_cs *cs) +@@ -449,12 +457,14 @@ void wined3d_cs_emit_sync(struct wined3d_cs *cs) cs->ops->submit_and_wait(cs); } @@ -77,7 +77,7 @@ } void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) -@@ -494,7 +504,7 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) +@@ -467,7 +477,7 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) cs->ops->submit_and_wait(cs); } @@ -86,7 +86,7 @@ { const struct wined3d_cs_present *op = data; struct wined3d_swapchain *swapchain; -@@ -512,6 +522,8 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) +@@ -485,6 +495,8 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) { wined3d_resource_release(&swapchain->back_buffers[i]->resource); } @@ -95,7 +95,7 @@ } void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, -@@ -551,13 +563,14 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw +@@ -524,13 +536,14 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0); } @@ -111,7 +111,7 @@ device = cs->device; wined3d_get_draw_rect(state, &draw_rect); -@@ -575,6 +588,8 @@ static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) +@@ -548,6 +561,8 @@ static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) } if (op->flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) wined3d_resource_release(state->fb->depth_stencil->resource); @@ -120,7 +120,7 @@ } void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, -@@ -713,7 +728,7 @@ static void release_unordered_access_resources(const struct wined3d_shader *shad +@@ -686,7 +701,7 @@ static void release_unordered_access_resources(const struct wined3d_shader *shad } } @@ -129,7 +129,7 @@ { const struct wined3d_cs_dispatch *op = data; struct wined3d_state *state = &cs->state; -@@ -724,6 +739,8 @@ static void wined3d_cs_exec_dispatch(struct wined3d_cs *cs, const void *data) +@@ -697,6 +712,8 @@ static void wined3d_cs_exec_dispatch(struct wined3d_cs *cs, const void *data) release_shader_resources(state, 1u << WINED3D_SHADER_TYPE_COMPUTE); release_unordered_access_resources(state->shader[WINED3D_SHADER_TYPE_COMPUTE], state->unordered_access_view[WINED3D_PIPELINE_COMPUTE]); @@ -138,7 +138,7 @@ } void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, -@@ -745,7 +762,7 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, +@@ -718,7 +735,7 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, cs->ops->submit(cs); } @@ -147,7 +147,7 @@ { struct wined3d_state *state = &cs->state; const struct wined3d_cs_draw *op = data; -@@ -790,6 +807,8 @@ static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) +@@ -763,6 +780,8 @@ static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) release_shader_resources(state, ~(1u << WINED3D_SHADER_TYPE_COMPUTE)); release_unordered_access_resources(state->shader[WINED3D_SHADER_TYPE_PIXEL], state->unordered_access_view[WINED3D_PIPELINE_GRAPHICS]); @@ -156,7 +156,7 @@ } void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base_vertex_idx, unsigned int start_idx, -@@ -835,12 +854,14 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base +@@ -808,12 +827,14 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base cs->ops->submit(cs); } @@ -172,7 +172,7 @@ } void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value) -@@ -855,12 +876,14 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query +@@ -828,12 +849,14 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query cs->ops->submit(cs); } @@ -188,7 +188,7 @@ } void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) -@@ -874,12 +897,14 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi +@@ -847,12 +870,14 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi cs->ops->submit(cs); } @@ -204,7 +204,7 @@ } void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) -@@ -893,12 +918,14 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) +@@ -866,12 +891,14 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) cs->ops->submit(cs); } @@ -220,7 +220,7 @@ } void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx, -@@ -914,7 +941,7 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v +@@ -887,7 +914,7 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v cs->ops->submit(cs); } @@ -229,7 +229,7 @@ { const struct wined3d_cs_set_depth_stencil_view *op = data; struct wined3d_device *device = cs->device; -@@ -949,6 +976,8 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const +@@ -922,6 +949,8 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const } device_invalidate_state(device, STATE_FRAMEBUFFER); @@ -238,7 +238,7 @@ } void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) -@@ -962,12 +991,14 @@ void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3 +@@ -935,12 +964,14 @@ void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3 cs->ops->submit(cs); } @@ -254,7 +254,7 @@ } void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) -@@ -981,7 +1012,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3 +@@ -954,7 +985,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3 cs->ops->submit(cs); } @@ -263,7 +263,7 @@ { const struct wined3d_cs_set_stream_source *op = data; struct wined3d_stream_state *stream; -@@ -999,6 +1030,8 @@ static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void +@@ -972,6 +1003,8 @@ static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_STREAMSRC); @@ -272,7 +272,7 @@ } void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, -@@ -1016,7 +1049,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, +@@ -989,7 +1022,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, cs->ops->submit(cs); } @@ -281,7 +281,7 @@ { const struct wined3d_cs_set_stream_source_freq *op = data; struct wined3d_stream_state *stream; -@@ -1026,6 +1059,8 @@ static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const +@@ -999,6 +1032,8 @@ static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const stream->flags = op->flags; device_invalidate_state(cs->device, STATE_STREAMSRC); @@ -290,7 +290,7 @@ } void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags) -@@ -1041,7 +1076,7 @@ void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_i +@@ -1014,7 +1049,7 @@ void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_i cs->ops->submit(cs); } @@ -299,7 +299,7 @@ { const struct wined3d_cs_set_stream_output *op = data; struct wined3d_stream_output *stream; -@@ -1056,6 +1091,8 @@ static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void +@@ -1029,6 +1064,8 @@ static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void InterlockedIncrement(&op->buffer->resource.bind_count); if (prev) InterlockedDecrement(&prev->resource.bind_count); @@ -308,7 +308,7 @@ } void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, -@@ -1072,7 +1109,7 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, +@@ -1045,7 +1082,7 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, cs->ops->submit(cs); } @@ -317,7 +317,7 @@ { const struct wined3d_cs_set_index_buffer *op = data; struct wined3d_buffer *prev; -@@ -1088,6 +1125,8 @@ static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void * +@@ -1061,6 +1098,8 @@ static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void * InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_INDEXBUFFER); @@ -326,7 +326,7 @@ } void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, -@@ -1104,7 +1143,7 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff +@@ -1077,7 +1116,7 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff cs->ops->submit(cs); } @@ -335,7 +335,7 @@ { const struct wined3d_cs_set_constant_buffer *op = data; struct wined3d_buffer *prev; -@@ -1118,6 +1157,7 @@ static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const voi +@@ -1091,6 +1130,7 @@ static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const voi InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type)); @@ -343,7 +343,7 @@ } void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, -@@ -1134,7 +1174,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha +@@ -1107,7 +1147,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha cs->ops->submit(cs); } @@ -352,7 +352,7 @@ { const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info; const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info; -@@ -1211,6 +1251,8 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) +@@ -1184,6 +1224,8 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) if (new_use_color_key) device_invalidate_state(cs->device, STATE_COLOR_KEY); @@ -361,7 +361,7 @@ } void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture) -@@ -1225,7 +1267,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined +@@ -1198,7 +1240,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined cs->ops->submit(cs); } @@ -370,7 +370,7 @@ { const struct wined3d_cs_set_shader_resource_view *op = data; struct wined3d_shader_resource_view *prev; -@@ -1242,6 +1284,8 @@ static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, cons +@@ -1215,6 +1257,8 @@ static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, cons device_invalidate_state(cs->device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); else device_invalidate_state(cs->device, STATE_COMPUTE_SHADER_RESOURCE_BINDING); @@ -379,7 +379,7 @@ } void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type, -@@ -1258,7 +1302,7 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 +@@ -1231,7 +1275,7 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 cs->ops->submit(cs); } @@ -388,7 +388,7 @@ { const struct wined3d_cs_set_unordered_access_view *op = data; struct wined3d_unordered_access_view *prev; -@@ -1272,6 +1316,8 @@ static void wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs *cs, con +@@ -1245,6 +1289,8 @@ static void wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs *cs, con InterlockedDecrement(&prev->resource->bind_count); device_invalidate_state(cs->device, STATE_UNORDERED_ACCESS_VIEW_BINDING(op->pipeline)); @@ -397,7 +397,7 @@ } void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined3d_pipeline pipeline, -@@ -1288,7 +1334,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined +@@ -1261,7 +1307,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined cs->ops->submit(cs); } @@ -406,7 +406,7 @@ { const struct wined3d_cs_set_sampler *op = data; -@@ -1297,6 +1343,8 @@ static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data) +@@ -1270,6 +1316,8 @@ static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data) device_invalidate_state(cs->device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); else device_invalidate_state(cs->device, STATE_COMPUTE_SHADER_RESOURCE_BINDING); @@ -415,7 +415,7 @@ } void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type, -@@ -1313,7 +1361,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type +@@ -1286,7 +1334,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type cs->ops->submit(cs); } @@ -424,7 +424,7 @@ { const struct wined3d_cs_set_shader *op = data; -@@ -1323,6 +1371,8 @@ static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) +@@ -1296,6 +1344,8 @@ static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) device_invalidate_state(cs->device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); else device_invalidate_state(cs->device, STATE_COMPUTE_SHADER_RESOURCE_BINDING); @@ -433,7 +433,7 @@ } void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader) -@@ -1337,12 +1387,14 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type +@@ -1310,12 +1360,14 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type cs->ops->submit(cs); } @@ -449,7 +449,7 @@ } void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, -@@ -1357,12 +1409,14 @@ void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, +@@ -1330,12 +1382,14 @@ void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, cs->ops->submit(cs); } @@ -465,7 +465,7 @@ } void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value) -@@ -1377,12 +1431,14 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render +@@ -1350,12 +1404,14 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render cs->ops->submit(cs); } @@ -481,7 +481,7 @@ } void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, -@@ -1399,12 +1455,14 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, +@@ -1372,12 +1428,14 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, cs->ops->submit(cs); } @@ -497,7 +497,7 @@ } void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, -@@ -1421,13 +1479,15 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, +@@ -1394,13 +1452,15 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, cs->ops->submit(cs); } @@ -514,7 +514,7 @@ } void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state, -@@ -1443,12 +1503,14 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform +@@ -1416,12 +1476,14 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform cs->ops->submit(cs); } @@ -530,7 +530,7 @@ } void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane) -@@ -1463,7 +1525,7 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const +@@ -1436,7 +1498,7 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const cs->ops->submit(cs); } @@ -539,7 +539,7 @@ { const struct wined3d_cs_set_color_key *op = data; struct wined3d_texture *texture = op->texture; -@@ -1524,6 +1586,8 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat +@@ -1497,6 +1559,8 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat break; } } @@ -548,7 +548,7 @@ } void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture, -@@ -1546,12 +1610,14 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture +@@ -1519,12 +1583,14 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture cs->ops->submit(cs); } @@ -564,7 +564,7 @@ } void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material) -@@ -1565,7 +1631,7 @@ void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_ma +@@ -1538,7 +1604,7 @@ void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_ma cs->ops->submit(cs); } @@ -573,7 +573,7 @@ { const struct wined3d_cs_set_light *op = data; struct wined3d_light_info *light_info; -@@ -1579,7 +1645,7 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) +@@ -1552,7 +1618,7 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) if (!(light_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*light_info)))) { ERR("Failed to allocate light info.\n"); @@ -582,7 +582,7 @@ } hash_idx = LIGHTMAP_HASHFUNC(light_idx); -@@ -1600,6 +1666,8 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) +@@ -1573,6 +1639,8 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) light_info->direction = op->light.direction; light_info->exponent = op->light.exponent; light_info->cutoff = op->light.cutoff; @@ -591,7 +591,7 @@ } void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light_info *light) -@@ -1613,7 +1681,7 @@ void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light +@@ -1586,7 +1654,7 @@ void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light cs->ops->submit(cs); } @@ -600,7 +600,7 @@ { const struct wined3d_cs_set_light_enable *op = data; struct wined3d_device *device = cs->device; -@@ -1623,7 +1691,7 @@ static void wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void * +@@ -1596,7 +1664,7 @@ static void wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void * if (!(light_info = wined3d_state_get_light(&cs->state, op->idx))) { ERR("Light doesn't exist.\n"); @@ -609,7 +609,7 @@ } prev_idx = light_info->glIndex; -@@ -1633,6 +1701,8 @@ static void wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void * +@@ -1606,6 +1674,8 @@ static void wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void * device_invalidate_state(device, STATE_LIGHT_TYPE); device_invalidate_state(device, STATE_ACTIVELIGHT(op->enable ? light_info->glIndex : prev_idx)); } @@ -618,7 +618,7 @@ } void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, unsigned int idx, BOOL enable) -@@ -1647,7 +1717,7 @@ void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, unsigned int idx, B +@@ -1620,7 +1690,7 @@ void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, unsigned int idx, B cs->ops->submit(cs); } @@ -627,7 +627,7 @@ { struct wined3d_adapter *adapter = cs->device->adapter; -@@ -1655,6 +1725,8 @@ static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) +@@ -1628,6 +1698,8 @@ static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) memset(&cs->state, 0, sizeof(cs->state)); state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info, WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT); @@ -636,7 +636,7 @@ } void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) -@@ -1667,11 +1739,13 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) +@@ -1640,11 +1712,13 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) cs->ops->submit(cs); } @@ -651,7 +651,7 @@ } static void wined3d_cs_emit_callback(struct wined3d_cs *cs, void (*callback)(void *object), void *object) -@@ -1696,12 +1770,14 @@ void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object +@@ -1669,12 +1743,14 @@ void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object wined3d_cs_emit_callback(cs, callback, object); } @@ -667,7 +667,7 @@ } void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) -@@ -1716,12 +1792,14 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu +@@ -1689,12 +1765,14 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu cs->ops->submit(cs); } @@ -683,7 +683,7 @@ } BOOL wined3d_cs_emit_query_poll(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) -@@ -1740,13 +1818,15 @@ BOOL wined3d_cs_emit_query_poll(struct wined3d_cs *cs, struct wined3d_query *que +@@ -1713,13 +1791,15 @@ BOOL wined3d_cs_emit_query_poll(struct wined3d_cs *cs, struct wined3d_query *que return ret; } @@ -700,7 +700,7 @@ } void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) -@@ -1762,13 +1842,15 @@ void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_reso +@@ -1735,13 +1815,15 @@ void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_reso cs->ops->submit(cs); } @@ -717,7 +717,7 @@ } void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) -@@ -1784,13 +1866,15 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou +@@ -1757,13 +1839,15 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou cs->ops->submit(cs); } @@ -734,7 +734,7 @@ } HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx, -@@ -1813,12 +1897,14 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, +@@ -1786,12 +1870,14 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, return hr; } @@ -750,7 +750,42 @@ } HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx) -@@ -1859,10 +1945,11 @@ push_constant_info[] = +@@ -1810,7 +1896,7 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc + return hr; + } + +-static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *data) ++static UINT wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_blt_sub_resource *op = data; + +@@ -1849,6 +1935,8 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * + if (op->src_resource) + wined3d_resource_release(op->src_resource); + wined3d_resource_release(op->dst_resource); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *dst_resource, +@@ -1878,7 +1966,7 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) ++static UINT wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_update_sub_resource *op = data; + const struct wined3d_box *box = &op->box; +@@ -1928,6 +2016,7 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi + + done: + wined3d_resource_release(op->resource); ++ return sizeof(*op); + } + + void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, +@@ -1972,10 +2061,11 @@ push_constant_info[] = {FIELD_OFFSET(struct wined3d_state, ps_consts_b), sizeof(BOOL), WINED3D_SHADER_CONST_PS_B}, }; @@ -763,7 +798,7 @@ unsigned int context_count; unsigned int i; size_t offset; -@@ -1878,6 +1965,8 @@ static void wined3d_cs_exec_push_constants(struct wined3d_cs *cs, const void *da +@@ -1991,6 +2081,8 @@ static void wined3d_cs_exec_push_constants(struct wined3d_cs *cs, const void *da { device->contexts[i]->constant_update_mask |= push_constant_info[op->p].mask; } @@ -772,25 +807,7 @@ } void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_constants p, -@@ -1895,7 +1984,7 @@ void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_con - cs->ops->submit(cs); - } - --static void wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) -+static UINT wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) - { - const struct wined3d_cs_blt *op = data; - -@@ -1906,6 +1995,8 @@ static void wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) - wined3d_resource_release(&op->dst_surface->container->resource); - if (op->src_surface && op->src_surface != op->dst_surface) - wined3d_resource_release(&op->src_surface->container->resource); -+ -+ return sizeof(*op); - } - - void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surface, -@@ -1933,7 +2024,7 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf +@@ -2008,7 +2100,7 @@ void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_con cs->ops->submit(cs); } @@ -799,7 +816,7 @@ { const struct wined3d_cs_clear_rtv *op = data; struct wined3d_device *device = cs->device; -@@ -1944,6 +2035,8 @@ static void wined3d_cs_exec_clear_rtv(struct wined3d_cs *cs, const void *data) +@@ -2019,6 +2111,8 @@ static void wined3d_cs_exec_clear_rtv(struct wined3d_cs *cs, const void *data) op->blitter->depth_fill(device, op->view, &op->rect, op->flags, op->depth, op->stencil); wined3d_resource_release(op->view->resource); @@ -808,7 +825,7 @@ } void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, -@@ -1968,7 +2061,7 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge +@@ -2043,7 +2137,7 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge cs->ops->submit(cs); } @@ -817,7 +834,7 @@ { const struct wined3d_cs_update_texture *op = data; struct wined3d_context *context; -@@ -1979,6 +2072,8 @@ static void wined3d_cs_exec_update_texture(struct wined3d_cs *cs, const void *da +@@ -2054,6 +2148,8 @@ static void wined3d_cs_exec_update_texture(struct wined3d_cs *cs, const void *da wined3d_resource_release(&op->src->resource); wined3d_resource_release(&op->dst->resource); @@ -826,67 +843,10 @@ } void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, -@@ -1997,7 +2092,7 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur +@@ -2072,11 +2168,13 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur cs->ops->submit(cs); } --static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) -+static UINT wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) - { - const struct wined3d_cs_update_sub_resource *op = data; - struct wined3d_const_bo_address addr; -@@ -2013,7 +2108,7 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi - if (FAILED(hr = wined3d_buffer_upload_data(buffer, op->box, op->data))) - WARN("Failed to update buffer data, hr %#x.\n", hr); - -- return; -+ return sizeof(*op); - } - - texture = wined3d_texture_from_resource(op->resource); -@@ -2042,6 +2137,8 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi - - wined3d_texture_validate_location(texture, op->sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); - wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); -+ -+ return sizeof(*op); - } - - void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, -@@ -2064,11 +2161,13 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r - cs->ops->submit_and_wait(cs); - } - --static void wined3d_cs_exec_get_dc(struct wined3d_cs *cs, const void *data) -+static UINT wined3d_cs_exec_get_dc(struct wined3d_cs *cs, const void *data) - { - const struct wined3d_cs_get_release_dc *op = data; - - *op->hr = wined3d_texture_get_dc_cs(op->texture, op->sub_resource_idx); -+ -+ return sizeof(*op); - } - - HRESULT wined3d_cs_emit_get_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -@@ -2088,11 +2187,13 @@ HRESULT wined3d_cs_emit_get_dc(struct wined3d_cs *cs, struct wined3d_texture *te - return hr; - } - --static void wined3d_cs_exec_release_dc(struct wined3d_cs *cs, const void *data) -+static UINT wined3d_cs_exec_release_dc(struct wined3d_cs *cs, const void *data) - { - const struct wined3d_cs_get_release_dc *op = data; - - *op->hr = wined3d_texture_release_dc_cs(op->texture, op->sub_resource_idx); -+ -+ return sizeof(*op); - } - - HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -@@ -2112,11 +2213,13 @@ HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture - return hr; - } - -static void wined3d_cs_exec_update_swap_interval(struct wined3d_cs *cs, const void *data) +static UINT wined3d_cs_exec_update_swap_interval(struct wined3d_cs *cs, const void *data) { @@ -898,7 +858,7 @@ } void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain) -@@ -2130,7 +2233,7 @@ void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_ +@@ -2090,7 +2188,7 @@ void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_ cs->ops->submit_and_wait(cs); } @@ -907,7 +867,7 @@ { const struct wined3d_cs_texture_add_dirty_region *op = data; struct wined3d_texture *texture = op->texture; -@@ -2148,6 +2251,8 @@ static void wined3d_cs_exec_texture_add_dirty_region(struct wined3d_cs *cs, cons +@@ -2108,6 +2206,8 @@ static void wined3d_cs_exec_texture_add_dirty_region(struct wined3d_cs *cs, cons context_release(context); wined3d_resource_release(&texture->resource); @@ -916,52 +876,16 @@ } void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, -@@ -2169,7 +2274,7 @@ void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, +@@ -2129,7 +2229,7 @@ void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, cs->ops->submit(cs); } --static void wined3d_cs_exec_buffer_copy(struct wined3d_cs *cs, const void *data) -+static UINT wined3d_cs_exec_buffer_copy(struct wined3d_cs *cs, const void *data) - { - const struct wined3d_cs_buffer_copy *op = data; - HRESULT hr; -@@ -2179,6 +2284,8 @@ static void wined3d_cs_exec_buffer_copy(struct wined3d_cs *cs, const void *data) - - wined3d_resource_release(&op->dst_buffer->resource); - wined3d_resource_release(&op->src_buffer->resource); -+ -+ return sizeof(*op); - } - - void wined3d_cs_emit_buffer_copy(struct wined3d_cs *cs, struct wined3d_buffer *dst_buffer, -@@ -2201,7 +2308,7 @@ void wined3d_cs_emit_buffer_copy(struct wined3d_cs *cs, struct wined3d_buffer *d - cs->ops->submit(cs); - } - --static void wined3d_cs_exec_map_vertex_buffers(struct wined3d_cs *cs, const void *data) -+static UINT wined3d_cs_exec_map_vertex_buffers(struct wined3d_cs *cs, const void *data) - { - const struct wined3d_cs_map_vertex_buffers *op = data; - struct wined3d_state *state = &cs->device->state; -@@ -2248,6 +2355,8 @@ static void wined3d_cs_exec_map_vertex_buffers(struct wined3d_cs *cs, const void - } - - context_release(context); -+ -+ return sizeof(*op); - } - - void wined3d_cs_emit_map_vertex_buffers(struct wined3d_cs *cs, UINT src_start_idx, -@@ -2263,7 +2372,7 @@ void wined3d_cs_emit_map_vertex_buffers(struct wined3d_cs *cs, UINT src_start_id - cs->ops->submit_and_wait(cs); - } - -static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = +static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, /* WINED3D_CS_OP_GLFINISH */ wined3d_cs_exec_glfinish, -@@ -2369,6 +2478,201 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = +@@ -2231,6 +2331,201 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = wined3d_cs_st_submit, }; @@ -1163,7 +1087,7 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; -@@ -2398,12 +2702,41 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) +@@ -2260,12 +2555,41 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) return NULL; } @@ -1206,10 +1130,10 @@ HeapFree(GetProcessHeap(), 0, cs->data); HeapFree(GetProcessHeap(), 0, cs); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index 7df7ba41888..2c691796426 100644 +index b271e72c98..abfdcb1cd0 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -1289,7 +1289,7 @@ UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device +@@ -1310,7 +1310,7 @@ UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device /* We can not acquire the context unless there is a swapchain. */ if (device->swapchains && gl_info->supported[NVX_GPU_MEMORY_INFO] && @@ -1219,7 +1143,7 @@ GLint vram_free_kb; UINT64 vram_free; diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c -index 1ce5937f173..4ef747ca89a 100644 +index aaced215de..473a7550bd 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -90,6 +90,7 @@ struct wined3d_settings wined3d_settings = @@ -1249,10 +1173,10 @@ if (hkey) RegCloseKey( hkey ); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 0c46eba6200..3e14ae56508 100644 +index 5cdb7f1ea5..4e8fca716e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -307,6 +307,7 @@ struct wined3d_settings +@@ -391,6 +391,7 @@ struct wined3d_settings unsigned int max_sm_ps; unsigned int max_sm_cs; BOOL no_3d; @@ -1260,7 +1184,7 @@ }; extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN; -@@ -2787,11 +2788,6 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource) +@@ -2805,11 +2806,6 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource) InterlockedDecrement(&resource->access_count); } @@ -1272,7 +1196,7 @@ void resource_cleanup(struct wined3d_resource *resource) DECLSPEC_HIDDEN; HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device, enum wined3d_resource_type type, const struct wined3d_format *format, -@@ -3212,6 +3208,21 @@ enum wined3d_push_constants +@@ -3220,6 +3216,21 @@ enum wined3d_push_constants WINED3D_PUSH_CONSTANTS_PS_B, }; @@ -1294,7 +1218,7 @@ struct wined3d_cs_ops { void *(*require_space)(struct wined3d_cs *cs, size_t size); -@@ -3229,9 +3240,21 @@ struct wined3d_cs +@@ -3237,9 +3248,21 @@ struct wined3d_cs size_t data_size, start, end; void *data; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0031-wined3d-Introduce-a-separate-priority-queue.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0031-wined3d-Introduce-a-separate-priority-queue.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0031-wined3d-Introduce-a-separate-priority-queue.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0031-wined3d-Introduce-a-separate-priority-queue.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,18 +1,18 @@ -From ec468210c7846be779fe5e81d6340a2862870574 Mon Sep 17 00:00:00 2001 +From 980a986cec394b6fc4a577cbf0efc6147191b084 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 8 Feb 2017 00:12:31 +0100 Subject: wined3d: Introduce a separate priority queue. --- - dlls/wined3d/cs.c | 129 ++++++++++++++++++++++------------------- + dlls/wined3d/cs.c | 121 ++++++++++++++++++++++------------------- dlls/wined3d/wined3d_private.h | 4 +- - 2 files changed, 72 insertions(+), 61 deletions(-) + 2 files changed, 68 insertions(+), 57 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 53a09a8cf8c..7b5c99b9e21 100644 +index 310ddd108f..d7604e5d7c 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -478,7 +478,7 @@ void wined3d_cs_emit_sync(struct wined3d_cs *cs) +@@ -451,7 +451,7 @@ void wined3d_cs_emit_sync(struct wined3d_cs *cs) { struct wined3d_cs_sync *op; @@ -21,7 +21,7 @@ op->opcode = WINED3D_CS_OP_SYNC; cs->ops->submit_and_wait(cs); -@@ -498,7 +498,7 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) +@@ -471,7 +471,7 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) { struct wined3d_cs_glfinish *op; @@ -30,7 +30,7 @@ op->opcode = WINED3D_CS_OP_GLFINISH; cs->ops->submit_and_wait(cs); -@@ -533,7 +533,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw +@@ -506,7 +506,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw unsigned int i; LONG pending; @@ -39,7 +39,7 @@ op->opcode = WINED3D_CS_OP_PRESENT; op->dst_window_override = dst_window_override; op->swapchain = swapchain; -@@ -599,7 +599,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * +@@ -572,7 +572,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * struct wined3d_cs_clear *op; unsigned int i; @@ -48,7 +48,7 @@ op->opcode = WINED3D_CS_OP_CLEAR; op->flags = flags; op->color = *color; -@@ -749,7 +749,7 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, +@@ -722,7 +722,7 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, const struct wined3d_state *state = &cs->device->state; struct wined3d_cs_dispatch *op; @@ -57,7 +57,7 @@ op->opcode = WINED3D_CS_OP_DISPATCH; op->group_count_x = group_count_x; op->group_count_y = group_count_y; -@@ -818,7 +818,7 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base +@@ -791,7 +791,7 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base struct wined3d_cs_draw *op; unsigned int i; @@ -66,7 +66,7 @@ op->opcode = WINED3D_CS_OP_DRAW; op->primitive_type = primitive_type; op->base_vertex_idx = base_vertex_idx; -@@ -868,7 +868,7 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query +@@ -841,7 +841,7 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query { struct wined3d_cs_set_predication *op; @@ -75,7 +75,7 @@ op->opcode = WINED3D_CS_OP_SET_PREDICATION; op->predicate = predicate; op->value = value; -@@ -890,7 +890,7 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi +@@ -863,7 +863,7 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi { struct wined3d_cs_set_viewport *op; @@ -84,7 +84,7 @@ op->opcode = WINED3D_CS_OP_SET_VIEWPORT; op->viewport = *viewport; -@@ -911,7 +911,7 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) +@@ -884,7 +884,7 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) { struct wined3d_cs_set_scissor_rect *op; @@ -93,7 +93,7 @@ op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT; op->rect = *rect; -@@ -933,7 +933,7 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v +@@ -906,7 +906,7 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v { struct wined3d_cs_set_rendertarget_view *op; @@ -102,7 +102,7 @@ op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW; op->view_idx = view_idx; op->view = view; -@@ -984,7 +984,7 @@ void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3 +@@ -957,7 +957,7 @@ void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3 { struct wined3d_cs_set_depth_stencil_view *op; @@ -111,7 +111,7 @@ op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW; op->view = view; -@@ -1005,7 +1005,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3 +@@ -978,7 +978,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3 { struct wined3d_cs_set_vertex_declaration *op; @@ -120,7 +120,7 @@ op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION; op->declaration = declaration; -@@ -1039,7 +1039,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, +@@ -1012,7 +1012,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, { struct wined3d_cs_set_stream_source *op; @@ -129,7 +129,7 @@ op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE; op->stream_idx = stream_idx; op->buffer = buffer; -@@ -1067,7 +1067,7 @@ void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_i +@@ -1040,7 +1040,7 @@ void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_i { struct wined3d_cs_set_stream_source_freq *op; @@ -138,7 +138,7 @@ op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ; op->stream_idx = stream_idx; op->frequency = frequency; -@@ -1100,7 +1100,7 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, +@@ -1073,7 +1073,7 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, { struct wined3d_cs_set_stream_output *op; @@ -147,7 +147,7 @@ op->opcode = WINED3D_CS_OP_SET_STREAM_OUTPUT; op->stream_idx = stream_idx; op->buffer = buffer; -@@ -1134,7 +1134,7 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff +@@ -1107,7 +1107,7 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff { struct wined3d_cs_set_index_buffer *op; @@ -156,7 +156,7 @@ op->opcode = WINED3D_CS_OP_SET_INDEX_BUFFER; op->buffer = buffer; op->format_id = format_id; -@@ -1165,7 +1165,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha +@@ -1138,7 +1138,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha { struct wined3d_cs_set_constant_buffer *op; @@ -165,7 +165,7 @@ op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER; op->type = type; op->cb_idx = cb_idx; -@@ -1259,7 +1259,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined +@@ -1232,7 +1232,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined { struct wined3d_cs_set_texture *op; @@ -174,7 +174,7 @@ op->opcode = WINED3D_CS_OP_SET_TEXTURE; op->stage = stage; op->texture = texture; -@@ -1293,7 +1293,7 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 +@@ -1266,7 +1266,7 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 { struct wined3d_cs_set_shader_resource_view *op; @@ -183,7 +183,7 @@ op->opcode = WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW; op->type = type; op->view_idx = view_idx; -@@ -1325,7 +1325,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined +@@ -1298,7 +1298,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined { struct wined3d_cs_set_unordered_access_view *op; @@ -192,7 +192,7 @@ op->opcode = WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW; op->pipeline = pipeline; op->view_idx = view_idx; -@@ -1352,7 +1352,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type +@@ -1325,7 +1325,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type { struct wined3d_cs_set_sampler *op; @@ -201,7 +201,7 @@ op->opcode = WINED3D_CS_OP_SET_SAMPLER; op->type = type; op->sampler_idx = sampler_idx; -@@ -1379,7 +1379,7 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type +@@ -1352,7 +1352,7 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type { struct wined3d_cs_set_shader *op; @@ -210,7 +210,7 @@ op->opcode = WINED3D_CS_OP_SET_SHADER; op->type = type; op->shader = shader; -@@ -1402,7 +1402,7 @@ void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, +@@ -1375,7 +1375,7 @@ void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, { struct wined3d_cs_set_rasterizer_state *op; @@ -219,7 +219,7 @@ op->opcode = WINED3D_CS_OP_SET_RASTERIZER_STATE; op->state = rasterizer_state; -@@ -1423,7 +1423,7 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render +@@ -1396,7 +1396,7 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render { struct wined3d_cs_set_render_state *op; @@ -228,7 +228,7 @@ op->opcode = WINED3D_CS_OP_SET_RENDER_STATE; op->state = state; op->value = value; -@@ -1446,7 +1446,7 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, +@@ -1419,7 +1419,7 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, { struct wined3d_cs_set_texture_state *op; @@ -237,7 +237,7 @@ op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE; op->stage = stage; op->state = state; -@@ -1470,7 +1470,7 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, +@@ -1443,7 +1443,7 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, { struct wined3d_cs_set_sampler_state *op; @@ -246,7 +246,7 @@ op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE; op->sampler_idx = sampler_idx; op->state = state; -@@ -1495,7 +1495,7 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform +@@ -1468,7 +1468,7 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform { struct wined3d_cs_set_transform *op; @@ -255,7 +255,7 @@ op->opcode = WINED3D_CS_OP_SET_TRANSFORM; op->state = state; op->matrix = *matrix; -@@ -1517,7 +1517,7 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const +@@ -1490,7 +1490,7 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const { struct wined3d_cs_set_clip_plane *op; @@ -264,7 +264,7 @@ op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE; op->plane_idx = plane_idx; op->plane = *plane; -@@ -1595,7 +1595,7 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture +@@ -1568,7 +1568,7 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture { struct wined3d_cs_set_color_key *op; @@ -273,7 +273,7 @@ op->opcode = WINED3D_CS_OP_SET_COLOR_KEY; op->texture = texture; op->flags = flags; -@@ -1624,7 +1624,7 @@ void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_ma +@@ -1597,7 +1597,7 @@ void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_ma { struct wined3d_cs_set_material *op; @@ -282,7 +282,7 @@ op->opcode = WINED3D_CS_OP_SET_MATERIAL; op->material = *material; -@@ -1674,7 +1674,7 @@ void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light +@@ -1647,7 +1647,7 @@ void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light { struct wined3d_cs_set_light *op; @@ -291,7 +291,7 @@ op->opcode = WINED3D_CS_OP_SET_LIGHT; op->light = *light; -@@ -1709,7 +1709,7 @@ void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, unsigned int idx, B +@@ -1682,7 +1682,7 @@ void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, unsigned int idx, B { struct wined3d_cs_set_light_enable *op; @@ -300,7 +300,7 @@ op->opcode = WINED3D_CS_OP_SET_LIGHT_ENABLE; op->idx = idx; op->enable = enable; -@@ -1733,7 +1733,7 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) +@@ -1706,7 +1706,7 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) { struct wined3d_cs_reset_state *op; @@ -309,7 +309,7 @@ op->opcode = WINED3D_CS_OP_RESET_STATE; cs->ops->submit(cs); -@@ -1752,7 +1752,7 @@ static void wined3d_cs_emit_callback(struct wined3d_cs *cs, void (*callback)(voi +@@ -1725,7 +1725,7 @@ static void wined3d_cs_emit_callback(struct wined3d_cs *cs, void (*callback)(voi { struct wined3d_cs_callback *op; @@ -318,7 +318,7 @@ op->opcode = WINED3D_CS_OP_CALLBACK; op->callback = callback; op->object = object; -@@ -1784,7 +1784,7 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu +@@ -1757,7 +1757,7 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu { struct wined3d_cs_query_issue *op; @@ -327,7 +327,7 @@ op->opcode = WINED3D_CS_OP_QUERY_ISSUE; op->query = query; op->flags = flags; -@@ -1807,7 +1807,7 @@ BOOL wined3d_cs_emit_query_poll(struct wined3d_cs *cs, struct wined3d_query *que +@@ -1780,7 +1780,7 @@ BOOL wined3d_cs_emit_query_poll(struct wined3d_cs *cs, struct wined3d_query *que struct wined3d_cs_query_poll *op; BOOL ret; @@ -336,7 +336,7 @@ op->opcode = WINED3D_CS_OP_QUERY_POLL; op->query = query; op->flags = flags; -@@ -1833,7 +1833,7 @@ void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_reso +@@ -1806,7 +1806,7 @@ void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_reso { struct wined3d_cs_preload_resource *op; @@ -345,7 +345,7 @@ op->opcode = WINED3D_CS_OP_PRELOAD_RESOURCE; op->resource = resource; -@@ -1857,7 +1857,7 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou +@@ -1830,7 +1830,7 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou { struct wined3d_cs_unload_resource *op; @@ -354,7 +354,7 @@ op->opcode = WINED3D_CS_OP_UNLOAD_RESOURCE; op->resource = resource; -@@ -1883,7 +1883,7 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, +@@ -1856,7 +1856,7 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, struct wined3d_cs_map *op; HRESULT hr; @@ -363,7 +363,7 @@ op->opcode = WINED3D_CS_OP_MAP; op->resource = resource; op->sub_resource_idx = sub_resource_idx; -@@ -1912,7 +1912,7 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc +@@ -1885,7 +1885,7 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc struct wined3d_cs_unmap *op; HRESULT hr; @@ -372,7 +372,25 @@ op->opcode = WINED3D_CS_OP_UNMAP; op->resource = resource; op->sub_resource_idx = sub_resource_idx; -@@ -1974,7 +1974,7 @@ void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_con +@@ -1946,7 +1946,7 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso + { + struct wined3d_cs_blt_sub_resource *op; + +- op = cs->ops->require_space(cs, sizeof(*op)); ++ op = cs->ops->require_space(cs, sizeof(*op), 0); + op->opcode = WINED3D_CS_OP_BLT_SUB_RESOURCE; + op->dst_resource = dst_resource; + op->dst_sub_resource_idx = dst_sub_resource_idx; +@@ -2025,7 +2025,7 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r + { + struct wined3d_cs_update_sub_resource *op; + +- op = cs->ops->require_space(cs, sizeof(*op)); ++ op = cs->ops->require_space(cs, sizeof(*op), 0); + op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; + op->resource = resource; + op->sub_resource_idx = sub_resource_idx; +@@ -2090,7 +2090,7 @@ void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_con { struct wined3d_cs_push_constants *op; @@ -381,16 +399,7 @@ op->opcode = WINED3D_CS_OP_PUSH_CONSTANTS; op->p = p; op->start_idx = start_idx; -@@ -2006,7 +2006,7 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf - { - struct wined3d_cs_blt *op; - -- op = cs->ops->require_space(cs, sizeof(*op)); -+ op = cs->ops->require_space(cs, sizeof(*op), 0); - op->opcode = WINED3D_CS_OP_BLT; - op->dst_surface = dst_surface; - op->dst_rect = *dst_rect; -@@ -2045,7 +2045,7 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge +@@ -2121,7 +2121,7 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge { struct wined3d_cs_clear_rtv *op; @@ -399,7 +408,7 @@ op->opcode = WINED3D_CS_OP_CLEAR_RTV; op->view = view; op->rect = *rect; -@@ -2081,7 +2081,7 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur +@@ -2157,7 +2157,7 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur { struct wined3d_cs_update_texture *op; @@ -408,34 +417,7 @@ op->opcode = WINED3D_CS_OP_UPDATE_TEXTURE; op->src = src; op->dst = dst; -@@ -2147,7 +2147,7 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r - { - struct wined3d_cs_update_sub_resource *op; - -- op = cs->ops->require_space(cs, sizeof(*op)); -+ op = cs->ops->require_space(cs, sizeof(*op), 0); - op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; - op->resource = resource; - op->sub_resource_idx = sub_resource_idx; -@@ -2176,7 +2176,7 @@ HRESULT wined3d_cs_emit_get_dc(struct wined3d_cs *cs, struct wined3d_texture *te - struct wined3d_cs_get_release_dc *op; - HRESULT hr; - -- op = cs->ops->require_space(cs, sizeof(*op)); -+ op = cs->ops->require_space(cs, sizeof(*op), 0); - op->opcode = WINED3D_CS_OP_GET_DC; - op->texture = texture; - op->sub_resource_idx = sub_resource_idx; -@@ -2202,7 +2202,7 @@ HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture - struct wined3d_cs_get_release_dc *op; - HRESULT hr; - -- op = cs->ops->require_space(cs, sizeof(*op)); -+ op = cs->ops->require_space(cs, sizeof(*op), 0); - op->opcode = WINED3D_CS_OP_RELEASE_DC; - op->texture = texture; - op->sub_resource_idx = sub_resource_idx; -@@ -2226,7 +2226,7 @@ void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_ +@@ -2181,7 +2181,7 @@ void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_ { struct wined3d_cs_update_swap_interval *op; @@ -444,7 +426,7 @@ op->opcode = WINED3D_CS_OP_UPDATE_SWAP_INTERVAL; op->swapchain = swapchain; -@@ -2264,7 +2264,7 @@ void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, +@@ -2219,7 +2219,7 @@ void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, if (dirty_region) WARN("Ignoring dirty_region %s.\n", debug_box(dirty_region)); @@ -453,26 +435,8 @@ op->opcode = WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION; op->texture = texture; op->sub_resource_idx = sub_resource_idx; -@@ -2294,7 +2294,7 @@ void wined3d_cs_emit_buffer_copy(struct wined3d_cs *cs, struct wined3d_buffer *d - { - struct wined3d_cs_buffer_copy *op; - -- op = cs->ops->require_space(cs, sizeof(*op)); -+ op = cs->ops->require_space(cs, sizeof(*op), 0); - op->opcode = WINED3D_CS_OP_BUFFER_COPY; - op->dst_buffer = dst_buffer; - op->dst_offset = dst_offset; -@@ -2364,7 +2364,7 @@ void wined3d_cs_emit_map_vertex_buffers(struct wined3d_cs *cs, UINT src_start_id - { - struct wined3d_cs_map_vertex_buffers *op; - -- op = cs->ops->require_space(cs, sizeof(*op)); -+ op = cs->ops->require_space(cs, sizeof(*op), 0); - op->opcode = WINED3D_CS_OP_MAP_VERTEX_BUFFERS; - op->src_start_idx = src_start_idx; - op->stream_info = stream_info; -@@ -2427,7 +2427,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_MAP_VERTEX_BUFFERS */ wined3d_cs_exec_map_vertex_buffers, +@@ -2280,7 +2280,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION */ wined3d_cs_exec_texture_add_dirty_region, }; -static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) @@ -480,7 +444,7 @@ { if (size > (cs->data_size - cs->end)) { -@@ -2511,6 +2511,8 @@ static struct wined3d_cs_block *wined3d_cs_dequeue_command(struct wined3d_cs *cs +@@ -2364,6 +2364,8 @@ static struct wined3d_cs_block *wined3d_cs_dequeue_command(struct wined3d_cs *cs /* FIXME: Use an event to wait after a couple of spins. */ for (;;) { @@ -489,7 +453,7 @@ if ((block = wined3d_cs_list_dequeue(&cs->exec_list))) return block; } -@@ -2538,7 +2540,7 @@ static void wined3d_cs_list_cleanup(struct wined3d_cs_list *list) +@@ -2391,7 +2393,7 @@ static void wined3d_cs_list_cleanup(struct wined3d_cs_list *list) DeleteCriticalSection(&list->lock); } @@ -498,7 +462,7 @@ { struct wined3d_cs_block *block; -@@ -2552,26 +2554,28 @@ static struct wined3d_cs_block *wined3d_cs_get_block(struct wined3d_cs *cs) +@@ -2405,26 +2407,28 @@ static struct wined3d_cs_block *wined3d_cs_get_block(struct wined3d_cs *cs) } block->pos = 0; @@ -531,7 +495,7 @@ cs->current_block = block; } -@@ -2583,10 +2587,13 @@ static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) +@@ -2436,10 +2440,13 @@ static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) static void wined3d_cs_mt_submit(struct wined3d_cs *cs) { @@ -546,7 +510,7 @@ cs->current_block = NULL; } -@@ -2600,7 +2607,7 @@ static void wined3d_cs_mt_submit_and_wait(struct wined3d_cs *cs) +@@ -2453,7 +2460,7 @@ static void wined3d_cs_mt_submit_and_wait(struct wined3d_cs *cs) block = cs->current_block; block->fence = &fence; @@ -555,7 +519,7 @@ cs->current_block = NULL; /* A busy wait should be fine, we're not supposed to have to wait very -@@ -2622,7 +2629,7 @@ static void wined3d_cs_mt_emit_stop(struct wined3d_cs *cs) +@@ -2475,7 +2482,7 @@ static void wined3d_cs_mt_emit_stop(struct wined3d_cs *cs) assert(cs->thread_id != GetCurrentThreadId()); assert(cs->ops == &wined3d_cs_mt_ops); @@ -564,7 +528,7 @@ op->opcode = WINED3D_CS_OP_STOP; cs->ops->submit(cs); -@@ -2708,6 +2715,7 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) +@@ -2561,6 +2568,7 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) wined3d_cs_list_init(&cs->free_list); wined3d_cs_list_init(&cs->exec_list); @@ -572,7 +536,7 @@ if (!(cs->thread = CreateThread(NULL, 0, wined3d_cs_run, cs, 0, &cs->thread_id))) { -@@ -2733,6 +2741,7 @@ void wined3d_cs_destroy(struct wined3d_cs *cs) +@@ -2586,6 +2594,7 @@ void wined3d_cs_destroy(struct wined3d_cs *cs) WaitForSingleObject(cs->thread, INFINITE); CloseHandle(cs->thread); @@ -581,10 +545,10 @@ wined3d_cs_list_cleanup(&cs->free_list); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 3e14ae56508..b6f84e1a36b 100644 +index 4e8fca716e..a6a51fea0a 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3219,13 +3219,14 @@ struct wined3d_cs_block +@@ -3227,13 +3227,14 @@ struct wined3d_cs_block { struct list entry; UINT pos; @@ -600,7 +564,7 @@ void (*submit)(struct wined3d_cs *cs); void (*submit_and_wait)(struct wined3d_cs *cs); }; -@@ -3245,6 +3246,7 @@ struct wined3d_cs +@@ -3253,6 +3254,7 @@ struct wined3d_cs struct wined3d_cs_block *current_block; struct wined3d_cs_list free_list; struct wined3d_cs_list exec_list; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0037-wined3d-Use-priority-queue-for-get_dc-release_dc.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0037-wined3d-Use-priority-queue-for-get_dc-release_dc.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0037-wined3d-Use-priority-queue-for-get_dc-release_dc.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0037-wined3d-Use-priority-queue-for-get_dc-release_dc.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -From 125cc8384a0f759df49cbf0e753877c3057ba2d1 Mon Sep 17 00:00:00 2001 -From: Sebastian Lackner -Date: Wed, 8 Feb 2017 11:57:52 +0100 -Subject: wined3d: Use priority queue for get_dc / release_dc. - ---- - dlls/wined3d/cs.c | 4 ++-- - dlls/wined3d/texture.c | 4 ++++ - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 1c9d8e1d192..1d2d9d7b990 100644 ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -2210,7 +2210,7 @@ HRESULT wined3d_cs_emit_get_dc(struct wined3d_cs *cs, struct wined3d_texture *te - struct wined3d_cs_get_release_dc *op; - HRESULT hr; - -- op = cs->ops->require_space(cs, sizeof(*op), 0); -+ op = cs->ops->require_space(cs, sizeof(*op), 1); - op->opcode = WINED3D_CS_OP_GET_DC; - op->texture = texture; - op->sub_resource_idx = sub_resource_idx; -@@ -2236,7 +2236,7 @@ HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture - struct wined3d_cs_get_release_dc *op; - HRESULT hr; - -- op = cs->ops->require_space(cs, sizeof(*op), 0); -+ op = cs->ops->require_space(cs, sizeof(*op), 1); - op->opcode = WINED3D_CS_OP_RELEASE_DC; - op->texture = texture; - op->sub_resource_idx = sub_resource_idx; -diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c -index bff7452e773..18ae2ae23cf 100644 ---- a/dlls/wined3d/texture.c -+++ b/dlls/wined3d/texture.c -@@ -3536,6 +3536,8 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i - if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) - return WINED3DERR_INVALIDCALL; - -+ wined3d_resource_wait_idle(&texture->resource); -+ - hr = wined3d_cs_emit_get_dc(device->cs, texture, sub_resource_idx); - if (FAILED(hr)) - return hr; -@@ -3592,5 +3594,7 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign - return WINED3DERR_INVALIDCALL; - } - -+ wined3d_resource_wait_idle(&texture->resource); -+ - return wined3d_cs_emit_release_dc(device->cs, texture, sub_resource_idx); - } --- -2.11.0 - diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0038-wined3d-Do-not-immediately-submit-stateblock-updates.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0038-wined3d-Do-not-immediately-submit-stateblock-updates.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0038-wined3d-Do-not-immediately-submit-stateblock-updates.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0038-wined3d-Do-not-immediately-submit-stateblock-updates.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 66849c6928010aa02b9d9d049fcc43c5a3823b0c Mon Sep 17 00:00:00 2001 +From ec94556fda1517b698ed180ebd06f20bf59d2438 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 8 Feb 2017 12:32:55 +0100 Subject: wined3d: Do not immediately submit stateblock updates. @@ -9,10 +9,10 @@ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 705d30b2879..25f833dfdce 100644 +index 75907ff6146..ffea25e50c0 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -882,7 +882,7 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query +@@ -856,7 +856,7 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query op->predicate = predicate; op->value = value; @@ -21,7 +21,7 @@ } static UINT wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) -@@ -903,7 +903,7 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi +@@ -877,7 +877,7 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi op->opcode = WINED3D_CS_OP_SET_VIEWPORT; op->viewport = *viewport; @@ -30,7 +30,7 @@ } static UINT wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data) -@@ -924,7 +924,7 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) +@@ -898,7 +898,7 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT; op->rect = *rect; @@ -39,7 +39,7 @@ } static UINT wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data) -@@ -947,7 +947,7 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v +@@ -921,7 +921,7 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v op->view_idx = view_idx; op->view = view; @@ -48,7 +48,7 @@ } static UINT wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const void *data) -@@ -997,7 +997,7 @@ void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3 +@@ -971,7 +971,7 @@ void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3 op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW; op->view = view; @@ -57,7 +57,7 @@ } static UINT wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data) -@@ -1018,7 +1018,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3 +@@ -992,7 +992,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3 op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION; op->declaration = declaration; @@ -66,7 +66,7 @@ } static UINT wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data) -@@ -1055,7 +1055,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, +@@ -1029,7 +1029,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, op->offset = offset; op->stride = stride; @@ -75,7 +75,7 @@ } static UINT wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data) -@@ -1082,7 +1082,7 @@ void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_i +@@ -1056,7 +1056,7 @@ void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_i op->frequency = frequency; op->flags = flags; @@ -84,7 +84,7 @@ } static UINT wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data) -@@ -1115,7 +1115,7 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, +@@ -1089,7 +1089,7 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, op->buffer = buffer; op->offset = offset; @@ -93,7 +93,7 @@ } static UINT wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data) -@@ -1149,7 +1149,7 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff +@@ -1123,7 +1123,7 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff op->format_id = format_id; op->offset = offset; @@ -102,7 +102,7 @@ } static UINT wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data) -@@ -1180,7 +1180,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha +@@ -1154,7 +1154,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha op->cb_idx = cb_idx; op->buffer = buffer; @@ -111,7 +111,7 @@ } static UINT wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) -@@ -1273,7 +1273,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined +@@ -1247,7 +1247,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined op->stage = stage; op->texture = texture; @@ -120,7 +120,7 @@ } static UINT wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data) -@@ -1308,7 +1308,7 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 +@@ -1282,7 +1282,7 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 op->view_idx = view_idx; op->view = view; @@ -129,7 +129,7 @@ } static UINT wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs *cs, const void *data) -@@ -1340,7 +1340,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined +@@ -1314,7 +1314,7 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined op->view_idx = view_idx; op->view = view; @@ -138,7 +138,7 @@ } static UINT wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data) -@@ -1367,7 +1367,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type +@@ -1341,7 +1341,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type op->sampler_idx = sampler_idx; op->sampler = sampler; @@ -147,7 +147,7 @@ } static UINT wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) -@@ -1393,7 +1393,7 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type +@@ -1367,7 +1367,7 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type op->type = type; op->shader = shader; @@ -156,7 +156,7 @@ } static UINT wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs *cs, const void *data) -@@ -1415,7 +1415,7 @@ void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, +@@ -1389,7 +1389,7 @@ void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, op->opcode = WINED3D_CS_OP_SET_RASTERIZER_STATE; op->state = rasterizer_state; @@ -165,7 +165,7 @@ } static UINT wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data) -@@ -1437,7 +1437,7 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render +@@ -1411,7 +1411,7 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render op->state = state; op->value = value; @@ -174,7 +174,7 @@ } static UINT wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data) -@@ -1461,7 +1461,7 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, +@@ -1435,7 +1435,7 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, op->state = state; op->value = value; @@ -183,7 +183,7 @@ } static UINT wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data) -@@ -1485,7 +1485,7 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, +@@ -1459,7 +1459,7 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, op->state = state; op->value = value; @@ -192,7 +192,7 @@ } static UINT wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data) -@@ -1509,7 +1509,7 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform +@@ -1483,7 +1483,7 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform op->state = state; op->matrix = *matrix; @@ -201,7 +201,7 @@ } static UINT wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data) -@@ -1531,7 +1531,7 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const +@@ -1505,7 +1505,7 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const op->plane_idx = plane_idx; op->plane = *plane; @@ -210,7 +210,7 @@ } static UINT wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *data) -@@ -1616,7 +1616,7 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture +@@ -1590,7 +1590,7 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture else op->set = 0; @@ -219,7 +219,7 @@ } static UINT wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data) -@@ -1637,7 +1637,7 @@ void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_ma +@@ -1611,7 +1611,7 @@ void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_ma op->opcode = WINED3D_CS_OP_SET_MATERIAL; op->material = *material; @@ -228,7 +228,7 @@ } static UINT wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) -@@ -1687,7 +1687,7 @@ void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light +@@ -1661,7 +1661,7 @@ void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light op->opcode = WINED3D_CS_OP_SET_LIGHT; op->light = *light; @@ -237,7 +237,7 @@ } static UINT wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void *data) -@@ -1723,7 +1723,7 @@ void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, unsigned int idx, B +@@ -1697,7 +1697,7 @@ void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, unsigned int idx, B op->idx = idx; op->enable = enable; @@ -246,7 +246,7 @@ } static UINT wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) -@@ -1745,7 +1745,7 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) +@@ -1719,7 +1719,7 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) op = cs->ops->require_space(cs, sizeof(*op), 0); op->opcode = WINED3D_CS_OP_RESET_STATE; @@ -255,7 +255,7 @@ } static UINT wined3d_cs_exec_callback(struct wined3d_cs *cs, const void *data) -@@ -1994,7 +1994,7 @@ void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_con +@@ -2111,7 +2111,7 @@ void wined3d_cs_emit_push_constants(struct wined3d_cs *cs, enum wined3d_push_con op->count = count; memcpy(op->constants, constants, count * push_constant_info[p].size); @@ -263,8 +263,8 @@ + cs->ops->submit_delayed(cs); } - static UINT wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) -@@ -2514,6 +2514,7 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = + static UINT wined3d_cs_exec_clear_rtv(struct wined3d_cs *cs, const void *data) +@@ -2397,6 +2397,7 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = wined3d_cs_st_require_space, wined3d_cs_st_submit, wined3d_cs_st_submit, @@ -272,7 +272,7 @@ }; static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) -@@ -2690,11 +2691,17 @@ static void wined3d_cs_mt_submit_and_wait(struct wined3d_cs *cs) +@@ -2573,11 +2574,17 @@ static void wined3d_cs_mt_submit_and_wait(struct wined3d_cs *cs) while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); } @@ -291,10 +291,10 @@ static void wined3d_cs_mt_emit_stop(struct wined3d_cs *cs) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index e71dfbb2ca8..b8c14275406 100644 +index 893768527b1..367e17fb7a7 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3216,6 +3216,7 @@ struct wined3d_cs_ops +@@ -3231,6 +3231,7 @@ struct wined3d_cs_ops void *(*require_space)(struct wined3d_cs *cs, size_t size, int priority); void (*submit)(struct wined3d_cs *cs); void (*submit_and_wait)(struct wined3d_cs *cs); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0045-wined3d-Improve-wined3d_cs_emit_update_sub_resource.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0045-wined3d-Improve-wined3d_cs_emit_update_sub_resource.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0045-wined3d-Improve-wined3d_cs_emit_update_sub_resource.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/0045-wined3d-Improve-wined3d_cs_emit_update_sub_resource.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,96 +1,62 @@ -From 65c46cb888fd621f85b2ea35f011bbdb5042ba22 Mon Sep 17 00:00:00 2001 +From 399b96f2a004f607fe917225e390a6efff7169b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 20 Feb 2017 00:27:25 +0100 Subject: wined3d: Improve wined3d_cs_emit_update_sub_resource. --- - dlls/wined3d/cs.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++--- + dlls/wined3d/cs.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- dlls/wined3d/device.c | 2 -- - 2 files changed, 78 insertions(+), 6 deletions(-) + 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 67d6b736dab..b43130b0ab0 100644 +index d3bcc49e6ee..94f46d289a6 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c -@@ -427,10 +427,13 @@ struct wined3d_cs_update_texture +@@ -380,10 +380,12 @@ struct wined3d_cs_unmap struct wined3d_cs_update_sub_resource { enum wined3d_cs_op opcode; + unsigned int size; struct wined3d_resource *resource; - unsigned int sub_resource_idx, row_pitch, depth_pitch; - const struct wined3d_box *box; - const void *data; -+ struct wined3d_box copy_box; + unsigned int sub_resource_idx; + struct wined3d_box box; + struct wined3d_sub_resource_data data; + BYTE copy_data[1]; }; - struct wined3d_cs_get_release_dc -@@ -2146,7 +2149,9 @@ static UINT wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi - if (FAILED(hr = wined3d_buffer_upload_data(buffer, op->box, op->data))) - WARN("Failed to update buffer data, hr %#x.\n", hr); - -- return sizeof(*op); -+ wined3d_resource_release(op->resource); -+ -+ return op->size; - } - - texture = wined3d_texture_from_resource(op->resource); -@@ -2176,7 +2181,9 @@ static UINT wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi - wined3d_texture_validate_location(texture, op->sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); - wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); + struct wined3d_cs_push_constants +@@ -1973,7 +1975,7 @@ static UINT wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi + done: + wined3d_resource_release(op->resource); - return sizeof(*op); -+ wined3d_resource_release(op->resource); -+ + return op->size; } void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, -@@ -2184,9 +2191,76 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r - unsigned int depth_pitch) +@@ -1981,9 +1983,54 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r + unsigned int slice_pitch) { struct wined3d_cs_update_sub_resource *op; -+ unsigned int update_w, update_h, update_d; + size_t data_size, size; + + if (resource->type != WINED3D_RTYPE_BUFFER && resource->format_flags & WINED3DFMT_FLAG_BLOCKS) + goto no_async; + -+ if (box) -+ { -+ update_w = box->right - box->left; -+ update_h = box->bottom - box->top; -+ update_d = box->back - box->front; -+ } -+ else if (resource->type != WINED3D_RTYPE_BUFFER) -+ { -+ struct wined3d_texture *texture = wined3d_texture_from_resource(resource); -+ unsigned int level = sub_resource_idx % texture->level_count; -+ update_w = wined3d_texture_get_level_width(texture, level); -+ update_h = wined3d_texture_get_level_height(texture, level); -+ update_d = wined3d_texture_get_level_depth(texture, level); -+ } -+ else -+ { -+ update_w = resource->size; -+ } -+ + data_size = 0; + switch (resource->type) + { + case WINED3D_RTYPE_TEXTURE_3D: -+ data_size += max(update_d - 1, 0) * depth_pitch; ++ data_size += (box->back - box->front - 1) * slice_pitch; + /* fall-through */ + case WINED3D_RTYPE_TEXTURE_2D: -+ data_size += max(update_h - 1, 0) * row_pitch; ++ data_size += (box->bottom - box->top - 1) * row_pitch; + /* fall-through */ + case WINED3D_RTYPE_TEXTURE_1D: -+ data_size += update_w * resource->format->byte_count; ++ data_size += (box->right - box->left) * resource->format->byte_count; + break; + case WINED3D_RTYPE_BUFFER: -+ data_size = update_w; ++ data_size = box->right - box->left; + break; + } + @@ -103,12 +69,10 @@ + op->size = size; + op->resource = resource; + op->sub_resource_idx = sub_resource_idx; -+ op->box = box ? &op->copy_box : NULL; -+ op->data = op->copy_data; -+ op->row_pitch = row_pitch; -+ op->depth_pitch = depth_pitch; -+ -+ if (box) op->copy_box = *box; ++ op->box = *box; ++ op->data.row_pitch = row_pitch; ++ op->data.slice_pitch = slice_pitch; ++ op->data.data = op->copy_data; + memcpy(op->copy_data, data, data_size); + + wined3d_resource_acquire(resource); @@ -124,23 +88,12 @@ + op->size = sizeof(*op); op->resource = resource; op->sub_resource_idx = sub_resource_idx; - op->box = box; -@@ -2194,8 +2268,8 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r - op->row_pitch = row_pitch; - op->depth_pitch = depth_pitch; - -- /* The data pointer may go away, need to wait until the data is read. Copying the data may be faster. -- * Don't forget to copy box as well in this case. */ -+ wined3d_resource_acquire(resource); -+ - cs->ops->submit_and_wait(cs); - } - + op->box = *box; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index c32d967df88..1b77fa7d09d 100644 +index b413de95858..0efd687b747 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -4112,8 +4112,6 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str +@@ -4163,8 +4163,6 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u.\n", device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/9999-IfDefined.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/9999-IfDefined.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/9999-IfDefined.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-CSMT_Main/9999-IfDefined.patch 2017-03-21 14:37:14.000000000 +0000 @@ -54,7 +54,7 @@ diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c -@@ -3725,6 +3725,11 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, +@@ -3766,6 +3766,11 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx); @@ -90,7 +90,7 @@ WINED3D_CS_OP_PRESENT, WINED3D_CS_OP_CLEAR, WINED3D_CS_OP_DISPATCH, -@@ -59,10 +66,37 @@ enum wined3d_cs_op +@@ -59,12 +66,33 @@ enum wined3d_cs_op WINED3D_CS_OP_RESET_STATE, WINED3D_CS_OP_CALLBACK, WINED3D_CS_OP_QUERY_ISSUE, @@ -101,18 +101,14 @@ WINED3D_CS_OP_UNLOAD_RESOURCE, WINED3D_CS_OP_MAP, WINED3D_CS_OP_UNMAP, + WINED3D_CS_OP_BLT_SUB_RESOURCE, + WINED3D_CS_OP_UPDATE_SUB_RESOURCE, +#if defined(STAGING_CSMT) + WINED3D_CS_OP_PUSH_CONSTANTS, -+ WINED3D_CS_OP_BLT, + WINED3D_CS_OP_CLEAR_RTV, + WINED3D_CS_OP_UPDATE_TEXTURE, -+ WINED3D_CS_OP_UPDATE_SUB_RESOURCE, -+ WINED3D_CS_OP_GET_DC, -+ WINED3D_CS_OP_RELEASE_DC, + WINED3D_CS_OP_UPDATE_SWAP_INTERVAL, + WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION, -+ WINED3D_CS_OP_BUFFER_COPY, -+ WINED3D_CS_OP_MAP_VERTEX_BUFFERS, + WINED3D_CS_OP_STOP, +}; + @@ -128,7 +124,7 @@ }; struct wined3d_cs_present -@@ -313,6 +347,16 @@ struct wined3d_cs_query_issue +@@ -315,6 +343,16 @@ struct wined3d_cs_query_issue DWORD flags; }; @@ -145,13 +141,25 @@ struct wined3d_cs_preload_resource { enum wined3d_cs_op opcode; -@@ -344,7 +388,140 @@ struct wined3d_cs_unmap - HRESULT *hr; +@@ -363,13 +401,103 @@ struct wined3d_cs_blt_sub_resource + struct wined3d_cs_update_sub_resource + { + enum wined3d_cs_op opcode; ++#if defined(STAGING_CSMT) ++ unsigned int size; ++#endif /* STAGING_CSMT */ + struct wined3d_resource *resource; + unsigned int sub_resource_idx; + struct wined3d_box box; + struct wined3d_sub_resource_data data; ++#if !defined(STAGING_CSMT) }; -+#if !defined(STAGING_CSMT) static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) +#else /* STAGING_CSMT */ ++ BYTE copy_data[1]; ++}; ++ +struct wined3d_cs_push_constants +{ + enum wined3d_cs_op opcode; @@ -161,18 +169,6 @@ + BYTE constants[1]; +}; + -+struct wined3d_cs_blt -+{ -+ enum wined3d_cs_op opcode; -+ struct wined3d_surface *dst_surface; -+ RECT dst_rect; -+ struct wined3d_surface *src_surface; -+ RECT src_rect; -+ DWORD flags; -+ struct wined3d_blt_fx fx; -+ enum wined3d_texture_filter_type filter; -+}; -+ +struct wined3d_cs_clear_rtv +{ + enum wined3d_cs_op opcode; @@ -191,26 +187,6 @@ + struct wined3d_texture *src, *dst; +}; + -+struct wined3d_cs_update_sub_resource -+{ -+ enum wined3d_cs_op opcode; -+ unsigned int size; -+ struct wined3d_resource *resource; -+ unsigned int sub_resource_idx, row_pitch, depth_pitch; -+ const struct wined3d_box *box; -+ const void *data; -+ struct wined3d_box copy_box; -+ BYTE copy_data[1]; -+}; -+ -+struct wined3d_cs_get_release_dc -+{ -+ enum wined3d_cs_op opcode; -+ struct wined3d_texture *texture; -+ unsigned int sub_resource_idx; -+ HRESULT *hr; -+}; -+ +struct wined3d_cs_update_swap_interval +{ + enum wined3d_cs_op opcode; @@ -224,23 +200,6 @@ + unsigned int sub_resource_idx; +}; + -+struct wined3d_cs_buffer_copy -+{ -+ enum wined3d_cs_op opcode; -+ struct wined3d_buffer *dst_buffer; -+ unsigned int dst_offset; -+ struct wined3d_buffer *src_buffer; -+ unsigned int src_offset; -+ unsigned int size; -+}; -+ -+struct wined3d_cs_map_vertex_buffers -+{ -+ enum wined3d_cs_op opcode; -+ UINT src_start_idx; -+ struct wined3d_stream_info *stream_info; -+}; -+ +struct wined3d_cs_stop +{ + enum wined3d_cs_op opcode; @@ -286,7 +245,7 @@ { const struct wined3d_cs_present *op = data; struct wined3d_swapchain *swapchain; -@@ -355,11 +532,19 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) +@@ -380,11 +508,19 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->flags); @@ -306,7 +265,7 @@ } void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, -@@ -367,8 +552,14 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw +@@ -392,8 +528,14 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw { struct wined3d_cs_present *op; unsigned int i; @@ -321,7 +280,7 @@ op->opcode = WINED3D_CS_OP_PRESENT; op->dst_window_override = dst_window_override; op->swapchain = swapchain; -@@ -382,16 +573,39 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw +@@ -407,16 +549,39 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw wined3d_resource_acquire(&swapchain->back_buffers[i]->resource); } @@ -361,7 +320,7 @@ device = cs->device; wined3d_get_draw_rect(state, &draw_rect); -@@ -409,6 +623,10 @@ static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) +@@ -434,6 +599,10 @@ static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) } if (op->flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) wined3d_resource_release(state->fb->depth_stencil->resource); @@ -372,7 +331,7 @@ } void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, -@@ -418,7 +636,11 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * +@@ -443,7 +612,11 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * struct wined3d_cs_clear *op; unsigned int i; @@ -384,7 +343,7 @@ op->opcode = WINED3D_CS_OP_CLEAR; op->flags = flags; op->color = *color; -@@ -547,7 +769,11 @@ static void release_unordered_access_resources(const struct wined3d_shader *shad +@@ -572,7 +745,11 @@ static void release_unordered_access_resources(const struct wined3d_shader *shad } } @@ -396,7 +355,7 @@ { const struct wined3d_cs_dispatch *op = data; struct wined3d_state *state = &cs->state; -@@ -558,6 +784,10 @@ static void wined3d_cs_exec_dispatch(struct wined3d_cs *cs, const void *data) +@@ -583,6 +760,10 @@ static void wined3d_cs_exec_dispatch(struct wined3d_cs *cs, const void *data) release_shader_resources(state, 1u << WINED3D_SHADER_TYPE_COMPUTE); release_unordered_access_resources(state->shader[WINED3D_SHADER_TYPE_COMPUTE], state->unordered_access_view[WINED3D_PIPELINE_COMPUTE]); @@ -407,7 +366,7 @@ } void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, -@@ -566,7 +796,11 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, +@@ -591,7 +772,11 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, const struct wined3d_state *state = &cs->device->state; struct wined3d_cs_dispatch *op; @@ -419,7 +378,7 @@ op->opcode = WINED3D_CS_OP_DISPATCH; op->group_count_x = group_count_x; op->group_count_y = group_count_y; -@@ -579,7 +813,11 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, +@@ -604,7 +789,11 @@ void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, cs->ops->submit(cs); } @@ -431,7 +390,7 @@ { struct wined3d_state *state = &cs->state; const struct wined3d_cs_draw *op = data; -@@ -624,6 +862,10 @@ static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) +@@ -649,6 +838,10 @@ static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) release_shader_resources(state, ~(1u << WINED3D_SHADER_TYPE_COMPUTE)); release_unordered_access_resources(state->shader[WINED3D_SHADER_TYPE_PIXEL], state->unordered_access_view[WINED3D_PIPELINE_GRAPHICS]); @@ -442,7 +401,7 @@ } void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base_vertex_idx, unsigned int start_idx, -@@ -633,7 +875,11 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base +@@ -658,7 +851,11 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base struct wined3d_cs_draw *op; unsigned int i; @@ -454,7 +413,7 @@ op->opcode = WINED3D_CS_OP_DRAW; op->primitive_type = primitive_type; op->base_vertex_idx = base_vertex_idx; -@@ -669,70 +915,123 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base +@@ -694,70 +891,123 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base cs->ops->submit(cs); } @@ -578,7 +537,7 @@ } void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx, -@@ -740,15 +1039,26 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v +@@ -765,15 +1015,26 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v { struct wined3d_cs_set_rendertarget_view *op; @@ -605,7 +564,7 @@ { const struct wined3d_cs_set_depth_stencil_view *op = data; struct wined3d_device *device = cs->device; -@@ -783,39 +1093,69 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const +@@ -808,39 +1069,69 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const } device_invalidate_state(device, STATE_FRAMEBUFFER); @@ -675,7 +634,7 @@ { const struct wined3d_cs_set_stream_source *op = data; struct wined3d_stream_state *stream; -@@ -833,6 +1173,10 @@ static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void +@@ -858,6 +1149,10 @@ static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_STREAMSRC); @@ -686,7 +645,7 @@ } void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, -@@ -840,17 +1184,28 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, +@@ -865,17 +1160,28 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, { struct wined3d_cs_set_stream_source *op; @@ -715,7 +674,7 @@ { const struct wined3d_cs_set_stream_source_freq *op = data; struct wined3d_stream_state *stream; -@@ -860,22 +1215,37 @@ static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const +@@ -885,22 +1191,37 @@ static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const stream->flags = op->flags; device_invalidate_state(cs->device, STATE_STREAMSRC); @@ -753,7 +712,7 @@ { const struct wined3d_cs_set_stream_output *op = data; struct wined3d_stream_output *stream; -@@ -890,6 +1260,10 @@ static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void +@@ -915,6 +1236,10 @@ static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void InterlockedIncrement(&op->buffer->resource.bind_count); if (prev) InterlockedDecrement(&prev->resource.bind_count); @@ -764,7 +723,7 @@ } void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, -@@ -897,16 +1271,27 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, +@@ -922,16 +1247,27 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, { struct wined3d_cs_set_stream_output *op; @@ -792,7 +751,7 @@ { const struct wined3d_cs_set_index_buffer *op = data; struct wined3d_buffer *prev; -@@ -922,6 +1307,10 @@ static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void * +@@ -947,6 +1283,10 @@ static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void * InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_INDEXBUFFER); @@ -803,7 +762,7 @@ } void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, -@@ -929,16 +1318,27 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff +@@ -954,16 +1294,27 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff { struct wined3d_cs_set_index_buffer *op; @@ -831,7 +790,7 @@ { const struct wined3d_cs_set_constant_buffer *op = data; struct wined3d_buffer *prev; -@@ -952,6 +1352,9 @@ static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const voi +@@ -977,6 +1328,9 @@ static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const voi InterlockedDecrement(&prev->resource.bind_count); device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type)); @@ -841,7 +800,7 @@ } void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, -@@ -959,16 +1362,27 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha +@@ -984,16 +1338,27 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha { struct wined3d_cs_set_constant_buffer *op; @@ -869,7 +828,7 @@ { const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info; const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info; -@@ -1045,21 +1459,36 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) +@@ -1070,21 +1435,36 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) if (new_use_color_key) device_invalidate_state(cs->device, STATE_COLOR_KEY); @@ -906,7 +865,7 @@ { const struct wined3d_cs_set_shader_resource_view *op = data; struct wined3d_shader_resource_view *prev; -@@ -1076,6 +1505,10 @@ static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, cons +@@ -1101,6 +1481,10 @@ static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, cons device_invalidate_state(cs->device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); else device_invalidate_state(cs->device, STATE_COMPUTE_SHADER_RESOURCE_BINDING); @@ -917,7 +876,7 @@ } void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type, -@@ -1083,16 +1516,27 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 +@@ -1108,16 +1492,27 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 { struct wined3d_cs_set_shader_resource_view *op; @@ -945,7 +904,7 @@ { const struct wined3d_cs_set_unordered_access_view *op = data; struct wined3d_unordered_access_view *prev; -@@ -1106,6 +1550,10 @@ static void wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs *cs, con +@@ -1131,6 +1526,10 @@ static void wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs *cs, con InterlockedDecrement(&prev->resource->bind_count); device_invalidate_state(cs->device, STATE_UNORDERED_ACCESS_VIEW_BINDING(op->pipeline)); @@ -956,7 +915,7 @@ } void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined3d_pipeline pipeline, -@@ -1113,16 +1561,27 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined +@@ -1138,16 +1537,27 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined { struct wined3d_cs_set_unordered_access_view *op; @@ -984,7 +943,7 @@ { const struct wined3d_cs_set_sampler *op = data; -@@ -1131,6 +1590,10 @@ static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data) +@@ -1156,6 +1566,10 @@ static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data) device_invalidate_state(cs->device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); else device_invalidate_state(cs->device, STATE_COMPUTE_SHADER_RESOURCE_BINDING); @@ -995,7 +954,7 @@ } void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type, -@@ -1138,16 +1601,27 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type +@@ -1163,16 +1577,27 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type { struct wined3d_cs_set_sampler *op; @@ -1023,7 +982,7 @@ { const struct wined3d_cs_set_shader *op = data; -@@ -1157,26 +1631,45 @@ static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) +@@ -1182,26 +1607,45 @@ static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) device_invalidate_state(cs->device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); else device_invalidate_state(cs->device, STATE_COMPUTE_SHADER_RESOURCE_BINDING); @@ -1069,7 +1028,7 @@ } void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, -@@ -1184,39 +1677,69 @@ void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, +@@ -1209,39 +1653,69 @@ void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs, { struct wined3d_cs_set_rasterizer_state *op; @@ -1139,7 +1098,7 @@ } void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, -@@ -1224,21 +1747,36 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, +@@ -1249,21 +1723,36 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, { struct wined3d_cs_set_texture_state *op; @@ -1176,7 +1135,7 @@ } void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, -@@ -1246,22 +1784,37 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, +@@ -1271,22 +1760,37 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, { struct wined3d_cs_set_sampler_state *op; @@ -1214,7 +1173,7 @@ } void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state, -@@ -1269,35 +1822,61 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform +@@ -1294,35 +1798,61 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform { struct wined3d_cs_set_transform *op; @@ -1276,7 +1235,7 @@ { const struct wined3d_cs_set_color_key *op = data; struct wined3d_texture *texture = op->texture; -@@ -1358,6 +1937,10 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat +@@ -1383,6 +1913,10 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat break; } } @@ -1287,7 +1246,7 @@ } void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture, -@@ -1365,7 +1948,11 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture +@@ -1390,7 +1924,11 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture { struct wined3d_cs_set_color_key *op; @@ -1299,7 +1258,7 @@ op->opcode = WINED3D_CS_OP_SET_COLOR_KEY; op->texture = texture; op->flags = flags; -@@ -1377,29 +1964,51 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture +@@ -1402,29 +1940,51 @@ void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture else op->set = 0; @@ -1351,7 +1310,7 @@ { const struct wined3d_cs_set_light *op = data; struct wined3d_light_info *light_info; -@@ -1413,7 +2022,11 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) +@@ -1438,7 +1998,11 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) if (!(light_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*light_info)))) { ERR("Failed to allocate light info.\n"); @@ -1363,7 +1322,7 @@ } hash_idx = LIGHTMAP_HASHFUNC(light_idx); -@@ -1434,20 +2047,35 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) +@@ -1459,20 +2023,35 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) light_info->direction = op->light.direction; light_info->exponent = op->light.exponent; light_info->cutoff = op->light.cutoff; @@ -1399,7 +1358,7 @@ { const struct wined3d_cs_set_light_enable *op = data; struct wined3d_device *device = cs->device; -@@ -1457,7 +2085,11 @@ static void wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void * +@@ -1482,7 +2061,11 @@ static void wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void * if (!(light_info = wined3d_state_get_light(&cs->state, op->idx))) { ERR("Light doesn't exist.\n"); @@ -1411,7 +1370,7 @@ } prev_idx = light_info->glIndex; -@@ -1467,21 +2099,36 @@ static void wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void * +@@ -1492,21 +2075,36 @@ static void wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void * device_invalidate_state(device, STATE_LIGHT_TYPE); device_invalidate_state(device, STATE_ACTIVELIGHT(op->enable ? light_info->glIndex : prev_idx)); } @@ -1448,7 +1407,7 @@ { struct wined3d_adapter *adapter = cs->device->adapter; -@@ -1489,12 +2136,17 @@ static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) +@@ -1514,12 +2112,17 @@ static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) memset(&cs->state, 0, sizeof(cs->state)); state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info, WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT); @@ -1466,7 +1425,7 @@ op = cs->ops->require_space(cs, sizeof(*op)); op->opcode = WINED3D_CS_OP_RESET_STATE; -@@ -1502,17 +2154,34 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) +@@ -1527,17 +2130,34 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) } static void wined3d_cs_exec_callback(struct wined3d_cs *cs, const void *data) @@ -1501,7 +1460,7 @@ op->opcode = WINED3D_CS_OP_CALLBACK; op->callback = callback; op->object = object; -@@ -1530,40 +2199,103 @@ void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object +@@ -1555,40 +2175,103 @@ void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object wined3d_cs_emit_callback(cs, callback, object); } @@ -1514,12 +1473,12 @@ const struct wined3d_cs_query_issue *op = data; struct wined3d_query *query = op->query; +#if !defined(STAGING_CSMT) - - query->query_ops->query_issue(query, op->flags); -+#else /* STAGING_CSMT */ -+ struct wined3d_context *context; + + query->query_ops->query_issue(query, op->flags); ++#else /* STAGING_CSMT */ ++ struct wined3d_context *context; + + query->query_ops->query_issue(query, op->flags); + + InterlockedDecrement(&query->pending); + @@ -1605,7 +1564,7 @@ op->opcode = WINED3D_CS_OP_PRELOAD_RESOURCE; op->resource = resource; -@@ -1572,20 +2304,32 @@ void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_reso +@@ -1597,20 +2280,32 @@ void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_reso cs->ops->submit(cs); } @@ -1638,7 +1597,7 @@ op->opcode = WINED3D_CS_OP_UNLOAD_RESOURCE; op->resource = resource; -@@ -1594,13 +2338,21 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou +@@ -1619,13 +2314,21 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou cs->ops->submit(cs); } @@ -1660,7 +1619,7 @@ } HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx, -@@ -1609,7 +2361,11 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, +@@ -1634,7 +2337,11 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, struct wined3d_cs_map *op; HRESULT hr; @@ -1672,7 +1631,7 @@ op->opcode = WINED3D_CS_OP_MAP; op->resource = resource; op->sub_resource_idx = sub_resource_idx; -@@ -1618,17 +2374,29 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, +@@ -1643,17 +2350,29 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, op->flags = flags; op->hr = &hr; @@ -1702,7 +1661,7 @@ } HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx) -@@ -1636,19 +2404,554 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc +@@ -1661,18 +2380,30 @@ HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resourc struct wined3d_cs_unmap *op; HRESULT hr; @@ -1720,10 +1679,133 @@ cs->ops->submit(cs); +#else /* STAGING_CSMT */ + cs->ops->submit_and_wait(cs); ++#endif /* STAGING_CSMT */ return hr; } ++#if !defined(STAGING_CSMT) + static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *data) ++#else /* STAGING_CSMT */ ++static UINT wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *data) ++#endif /* STAGING_CSMT */ + { + const struct wined3d_cs_blt_sub_resource *op = data; + +@@ -1711,6 +2442,10 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * + if (op->src_resource) + wined3d_resource_release(op->src_resource); + wined3d_resource_release(op->dst_resource); ++#if defined(STAGING_CSMT) ++ ++ return sizeof(*op); ++#endif /* STAGING_CSMT */ + } + + void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *dst_resource, +@@ -1720,7 +2455,11 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso + { + struct wined3d_cs_blt_sub_resource *op; + ++#if !defined(STAGING_CSMT) + op = cs->ops->require_space(cs, sizeof(*op)); ++#else /* STAGING_CSMT */ ++ op = cs->ops->require_space(cs, sizeof(*op), 0); ++#endif /* STAGING_CSMT */ + op->opcode = WINED3D_CS_OP_BLT_SUB_RESOURCE; + op->dst_resource = dst_resource; + op->dst_sub_resource_idx = dst_sub_resource_idx; +@@ -1740,7 +2479,11 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso + cs->ops->submit(cs); + } + ++#if !defined(STAGING_CSMT) + static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) ++#else /* STAGING_CSMT */ ++static UINT wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) ++#endif /* STAGING_CSMT */ + { + const struct wined3d_cs_update_sub_resource *op = data; + const struct wined3d_box *box = &op->box; +@@ -1790,6 +2533,9 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi + + done: + wined3d_resource_release(op->resource); ++#if defined(STAGING_CSMT) ++ return op->size; ++#endif /* STAGING_CSMT */ + } + + void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, +@@ -1797,9 +2543,60 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r + unsigned int slice_pitch) + { + struct wined3d_cs_update_sub_resource *op; ++#if !defined(STAGING_CSMT) + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; ++#else /* STAGING_CSMT */ ++ size_t data_size, size; ++ ++ if (resource->type != WINED3D_RTYPE_BUFFER && resource->format_flags & WINED3DFMT_FLAG_BLOCKS) ++ goto no_async; ++ ++ data_size = 0; ++ switch (resource->type) ++ { ++ case WINED3D_RTYPE_TEXTURE_3D: ++ data_size += (box->back - box->front - 1) * slice_pitch; ++ /* fall-through */ ++ case WINED3D_RTYPE_TEXTURE_2D: ++ data_size += (box->bottom - box->top - 1) * row_pitch; ++ /* fall-through */ ++ case WINED3D_RTYPE_TEXTURE_1D: ++ data_size += (box->right - box->left) * resource->format->byte_count; ++ break; ++ case WINED3D_RTYPE_BUFFER: ++ data_size = box->right - box->left; ++ break; ++ } ++ ++ size = FIELD_OFFSET(struct wined3d_cs_update_sub_resource, copy_data[data_size]); ++ if (size > sizeof(cs->current_block->data)) ++ goto no_async; ++ ++ op = cs->ops->require_space(cs, size, 0); ++ op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; ++ op->size = size; ++ op->resource = resource; ++ op->sub_resource_idx = sub_resource_idx; ++ op->box = *box; ++ op->data.row_pitch = row_pitch; ++ op->data.slice_pitch = slice_pitch; ++ op->data.data = op->copy_data; ++ memcpy(op->copy_data, data, data_size); ++ ++ wined3d_resource_acquire(resource); ++ ++ cs->ops->submit(cs); ++ return; ++ ++no_async: ++ wined3d_resource_wait_idle(resource); ++ ++ op = cs->ops->require_space(cs, sizeof(*op), 1); ++ op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; ++ op->size = sizeof(*op); ++#endif /* STAGING_CSMT */ + op->resource = resource; + op->sub_resource_idx = sub_resource_idx; + op->box = *box; +@@ -1809,11 +2606,210 @@ void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_r + + wined3d_resource_acquire(resource); + ++#if defined(STAGING_CSMT) ++ cs->ops->submit_and_wait(cs); ++} ++ +static const struct +{ + size_t offset; @@ -1785,46 +1867,6 @@ + cs->ops->submit_delayed(cs); +} + -+static UINT wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_blt *op = data; -+ -+ surface_blt_ugly(op->dst_surface, &op->dst_rect, -+ op->src_surface, &op->src_rect, -+ op->flags, &op->fx, op->filter); -+ -+ wined3d_resource_release(&op->dst_surface->container->resource); -+ if (op->src_surface && op->src_surface != op->dst_surface) -+ wined3d_resource_release(&op->src_surface->container->resource); -+ -+ return sizeof(*op); -+} -+ -+void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surface, -+ const RECT *dst_rect, struct wined3d_surface *src_surface, -+ const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, -+ enum wined3d_texture_filter_type filter) -+{ -+ struct wined3d_cs_blt *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op), 0); -+ op->opcode = WINED3D_CS_OP_BLT; -+ op->dst_surface = dst_surface; -+ op->dst_rect = *dst_rect; -+ op->src_surface = src_surface; -+ op->src_rect = *src_rect; -+ op->flags = flags; -+ op->filter = filter; -+ if (fx) -+ op->fx = *fx; -+ -+ wined3d_resource_acquire(&dst_surface->container->resource); -+ if (src_surface && src_surface != dst_surface) -+ wined3d_resource_acquire(&src_surface->container->resource); -+ -+ cs->ops->submit(cs); -+} -+ +static UINT wined3d_cs_exec_clear_rtv(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_clear_rtv *op = data; @@ -1859,9 +1901,9 @@ + + wined3d_resource_acquire(view->resource); + -+ cs->ops->submit(cs); -+} -+ + cs->ops->submit(cs); + } + +static UINT wined3d_cs_exec_update_texture(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_update_texture *op = data; @@ -1890,366 +1932,76 @@ + wined3d_resource_acquire(&op->src->resource); + wined3d_resource_acquire(&op->dst->resource); + ++#endif /* STAGING_CSMT */ + cs->ops->submit(cs); +} + -+static UINT wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const void *data) ++#if !defined(STAGING_CSMT) + static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { ++#else /* STAGING_CSMT */ ++static UINT wined3d_cs_exec_update_swap_interval(struct wined3d_cs *cs, const void *data) +{ -+ const struct wined3d_cs_update_sub_resource *op = data; -+ struct wined3d_const_bo_address addr; -+ struct wined3d_context *context; -+ struct wined3d_texture *texture; -+ unsigned int width, height, depth, level; -+ -+ if (op->resource->type == WINED3D_RTYPE_BUFFER) -+ { -+ struct wined3d_buffer *buffer = buffer_from_resource(op->resource); -+ HRESULT hr; -+ -+ if (FAILED(hr = wined3d_buffer_upload_data(buffer, op->box, op->data))) -+ WARN("Failed to update buffer data, hr %#x.\n", hr); -+ -+ wined3d_resource_release(op->resource); -+ -+ return op->size; -+ } -+ -+ texture = wined3d_texture_from_resource(op->resource); -+ -+ level = op->sub_resource_idx % texture->level_count; -+ width = wined3d_texture_get_level_width(texture, level); -+ height = wined3d_texture_get_level_height(texture, level); -+ depth = wined3d_texture_get_level_depth(texture, level); -+ -+ addr.buffer_object = 0; -+ addr.addr = op->data; -+ -+ context = context_acquire(texture->resource.device, NULL, 0); -+ -+ /* Only load the sub-resource for partial updates. */ -+ if (!op->box || (!op->box->left && !op->box->top && !op->box->front -+ && op->box->right == width && op->box->bottom == height && op->box->back == depth)) -+ wined3d_texture_prepare_texture(texture, context, FALSE); -+ else -+ wined3d_texture_load_location(texture, op->sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); -+ wined3d_texture_bind_and_dirtify(texture, context, FALSE); ++ const struct wined3d_cs_update_swap_interval *op = data; + -+ wined3d_texture_upload_data(texture, op->sub_resource_idx, context, op->box, &addr, op->row_pitch, op->depth_pitch); ++ swapchain_update_swap_interval(op->swapchain); + -+ context_release(context); ++ return sizeof(*op); ++} + -+ wined3d_texture_validate_location(texture, op->sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); -+ wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); ++void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain) ++{ ++ struct wined3d_cs_update_swap_interval *op; + -+ wined3d_resource_release(op->resource); ++ op = cs->ops->require_space(cs, sizeof(*op), 0); ++ op->opcode = WINED3D_CS_OP_UPDATE_SWAP_INTERVAL; ++ op->swapchain = swapchain; + -+ return op->size; ++ cs->ops->submit_and_wait(cs); +} + -+void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, -+ unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, -+ unsigned int depth_pitch) ++static UINT wined3d_cs_exec_texture_add_dirty_region(struct wined3d_cs *cs, const void *data) +{ -+ struct wined3d_cs_update_sub_resource *op; -+ unsigned int update_w, update_h, update_d; -+ size_t data_size, size; -+ -+ if (resource->type != WINED3D_RTYPE_BUFFER && resource->format_flags & WINED3DFMT_FLAG_BLOCKS) -+ goto no_async; ++ const struct wined3d_cs_texture_add_dirty_region *op = data; ++ struct wined3d_texture *texture = op->texture; ++ struct wined3d_context *context; + -+ if (box) -+ { -+ update_w = box->right - box->left; -+ update_h = box->bottom - box->top; -+ update_d = box->back - box->front; -+ } -+ else if (resource->type != WINED3D_RTYPE_BUFFER) ++ context = context_acquire(cs->device, NULL, 0); ++ if (!wined3d_texture_load_location(texture, op->sub_resource_idx, context, texture->resource.map_binding)) + { -+ struct wined3d_texture *texture = wined3d_texture_from_resource(resource); -+ unsigned int level = sub_resource_idx % texture->level_count; -+ update_w = wined3d_texture_get_level_width(texture, level); -+ update_h = wined3d_texture_get_level_height(texture, level); -+ update_d = wined3d_texture_get_level_depth(texture, level); ++ ERR("Failed to load location %s.\n", wined3d_debug_location(texture->resource.map_binding)); + } + else + { -+ update_w = resource->size; -+ } -+ -+ data_size = 0; -+ switch (resource->type) -+ { -+ case WINED3D_RTYPE_TEXTURE_3D: -+ data_size += max(update_d - 1, 0) * depth_pitch; -+ /* fall-through */ -+ case WINED3D_RTYPE_TEXTURE_2D: -+ data_size += max(update_h - 1, 0) * row_pitch; -+ /* fall-through */ -+ case WINED3D_RTYPE_TEXTURE_1D: -+ data_size += update_w * resource->format->byte_count; -+ break; -+ case WINED3D_RTYPE_BUFFER: -+ data_size = update_w; -+ break; ++ wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~texture->resource.map_binding); + } ++ context_release(context); + -+ size = FIELD_OFFSET(struct wined3d_cs_update_sub_resource, copy_data[data_size]); -+ if (size > sizeof(cs->current_block->data)) -+ goto no_async; -+ -+ op = cs->ops->require_space(cs, size, 0); -+ op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; -+ op->size = size; -+ op->resource = resource; -+ op->sub_resource_idx = sub_resource_idx; -+ op->box = box ? &op->copy_box : NULL; -+ op->data = op->copy_data; -+ op->row_pitch = row_pitch; -+ op->depth_pitch = depth_pitch; -+ -+ if (box) op->copy_box = *box; -+ memcpy(op->copy_data, data, data_size); ++ wined3d_resource_release(&texture->resource); + -+ wined3d_resource_acquire(resource); ++ return sizeof(*op); ++} + -+ cs->ops->submit(cs); -+ return; ++void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, ++ struct wined3d_texture *texture, unsigned int sub_resource_idx, ++ const struct wined3d_box *dirty_region) ++{ ++ struct wined3d_cs_texture_add_dirty_region *op; + -+no_async: -+ wined3d_resource_wait_idle(resource); ++ if (dirty_region) ++ WARN("Ignoring dirty_region %s.\n", debug_box(dirty_region)); + -+ op = cs->ops->require_space(cs, sizeof(*op), 1); -+ op->opcode = WINED3D_CS_OP_UPDATE_SUB_RESOURCE; -+ op->size = sizeof(*op); -+ op->resource = resource; ++ op = cs->ops->require_space(cs, sizeof(*op), 0); ++ op->opcode = WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION; ++ op->texture = texture; + op->sub_resource_idx = sub_resource_idx; -+ op->box = box; -+ op->data = data; -+ op->row_pitch = row_pitch; -+ op->depth_pitch = depth_pitch; + -+ wined3d_resource_acquire(resource); ++ wined3d_resource_acquire(&texture->resource); + -+ cs->ops->submit_and_wait(cs); ++ cs->ops->submit(cs); +} + -+static UINT wined3d_cs_exec_get_dc(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_get_release_dc *op = data; -+ -+ *op->hr = wined3d_texture_get_dc_cs(op->texture, op->sub_resource_idx); -+ -+ return sizeof(*op); -+} -+ -+HRESULT wined3d_cs_emit_get_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) -+{ -+ struct wined3d_cs_get_release_dc *op; -+ HRESULT hr; -+ -+ op = cs->ops->require_space(cs, sizeof(*op), 1); -+ op->opcode = WINED3D_CS_OP_GET_DC; -+ op->texture = texture; -+ op->sub_resource_idx = sub_resource_idx; -+ op->hr = &hr; -+ -+ cs->ops->submit_and_wait(cs); -+#endif /* STAGING_CSMT */ -+ -+ return hr; -+} -+ -+#if !defined(STAGING_CSMT) - static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = - { -+#else /* STAGING_CSMT */ -+static UINT wined3d_cs_exec_release_dc(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_get_release_dc *op = data; -+ -+ *op->hr = wined3d_texture_release_dc_cs(op->texture, op->sub_resource_idx); -+ -+ return sizeof(*op); -+} -+ -+HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) -+{ -+ struct wined3d_cs_get_release_dc *op; -+ HRESULT hr; -+ -+ op = cs->ops->require_space(cs, sizeof(*op), 1); -+ op->opcode = WINED3D_CS_OP_RELEASE_DC; -+ op->texture = texture; -+ op->sub_resource_idx = sub_resource_idx; -+ op->hr = &hr; -+ -+ cs->ops->submit_and_wait(cs); -+ -+ return hr; -+} -+ -+static UINT wined3d_cs_exec_update_swap_interval(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_update_swap_interval *op = data; -+ -+ swapchain_update_swap_interval(op->swapchain); -+ -+ return sizeof(*op); -+} -+ -+void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain) -+{ -+ struct wined3d_cs_update_swap_interval *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op), 0); -+ op->opcode = WINED3D_CS_OP_UPDATE_SWAP_INTERVAL; -+ op->swapchain = swapchain; -+ -+ cs->ops->submit_and_wait(cs); -+} -+ -+static UINT wined3d_cs_exec_texture_add_dirty_region(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_texture_add_dirty_region *op = data; -+ struct wined3d_texture *texture = op->texture; -+ struct wined3d_context *context; -+ -+ context = context_acquire(cs->device, NULL, 0); -+ if (!wined3d_texture_load_location(texture, op->sub_resource_idx, context, texture->resource.map_binding)) -+ { -+ ERR("Failed to load location %s.\n", wined3d_debug_location(texture->resource.map_binding)); -+ } -+ else -+ { -+ wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~texture->resource.map_binding); -+ } -+ context_release(context); -+ -+ wined3d_resource_release(&texture->resource); -+ -+ return sizeof(*op); -+} -+ -+void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, -+ struct wined3d_texture *texture, unsigned int sub_resource_idx, -+ const struct wined3d_box *dirty_region) -+{ -+ struct wined3d_cs_texture_add_dirty_region *op; -+ -+ if (dirty_region) -+ WARN("Ignoring dirty_region %s.\n", debug_box(dirty_region)); -+ -+ op = cs->ops->require_space(cs, sizeof(*op), 0); -+ op->opcode = WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION; -+ op->texture = texture; -+ op->sub_resource_idx = sub_resource_idx; -+ -+ wined3d_resource_acquire(&texture->resource); -+ -+ cs->ops->submit(cs); -+} -+ -+static UINT wined3d_cs_exec_buffer_copy(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_buffer_copy *op = data; -+ HRESULT hr; -+ -+ if (FAILED(hr = wined3d_buffer_copy(op->dst_buffer, op->dst_offset, op->src_buffer, op->src_offset, op->size))) -+ ERR("Failed to copy buffer, hr %#x.\n", hr); -+ -+ wined3d_resource_release(&op->dst_buffer->resource); -+ wined3d_resource_release(&op->src_buffer->resource); -+ -+ return sizeof(*op); -+} -+ -+void wined3d_cs_emit_buffer_copy(struct wined3d_cs *cs, struct wined3d_buffer *dst_buffer, -+ unsigned int dst_offset, struct wined3d_buffer *src_buffer, unsigned int src_offset, -+ unsigned int size) -+{ -+ struct wined3d_cs_buffer_copy *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op), 0); -+ op->opcode = WINED3D_CS_OP_BUFFER_COPY; -+ op->dst_buffer = dst_buffer; -+ op->dst_offset = dst_offset; -+ op->src_buffer = src_buffer; -+ op->src_offset = src_offset; -+ op->size = size; -+ -+ wined3d_resource_acquire(&dst_buffer->resource); -+ wined3d_resource_acquire(&src_buffer->resource); -+ -+ cs->ops->submit(cs); -+} -+ -+static UINT wined3d_cs_exec_map_vertex_buffers(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_map_vertex_buffers *op = data; -+ struct wined3d_state *state = &cs->device->state; -+ const struct wined3d_gl_info *gl_info; -+ struct wined3d_context *context; -+ struct wined3d_shader *vs; -+ unsigned int i; -+ WORD map; -+ -+ /* Need any context to write to the vbo. */ -+ context = context_acquire(cs->device, NULL, 0); -+ gl_info = context->gl_info; -+ -+ vs = state->shader[WINED3D_SHADER_TYPE_VERTEX]; -+ state->shader[WINED3D_SHADER_TYPE_VERTEX] = NULL; -+ context_stream_info_from_declaration(context, state, op->stream_info); -+ state->shader[WINED3D_SHADER_TYPE_VERTEX] = vs; -+ -+ /* We can't convert FROM a VBO, and vertex buffers used to source into -+ * process_vertices() are unlikely to ever be used for drawing. Release -+ * VBOs in those buffers and fix up the stream_info structure. -+ * -+ * Also apply the start index. */ -+ for (i = 0, map = op->stream_info->use_map; map; map >>= 1, ++i) -+ { -+ struct wined3d_stream_info_element *e; -+ struct wined3d_buffer *buffer; -+ -+ if (!(map & 1)) -+ continue; -+ -+ e = &op->stream_info->elements[i]; -+ buffer = state->streams[e->stream_idx].buffer; -+ e->data.buffer_object = 0; -+ e->data.addr += (ULONG_PTR)wined3d_buffer_load_sysmem(buffer, context); -+ if (buffer->buffer_object) -+ { -+ GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object)); -+ buffer->buffer_object = 0; -+ wined3d_buffer_invalidate_location(buffer, WINED3D_LOCATION_BUFFER); -+ } -+ if (e->data.addr) -+ e->data.addr += e->stride * op->src_start_idx; -+ } -+ -+ context_release(context); -+ -+ return sizeof(*op); -+} -+ -+void wined3d_cs_emit_map_vertex_buffers(struct wined3d_cs *cs, UINT src_start_idx, -+ struct wined3d_stream_info *stream_info) -+{ -+ struct wined3d_cs_map_vertex_buffers *op; -+ -+ op = cs->ops->require_space(cs, sizeof(*op), 0); -+ op->opcode = WINED3D_CS_OP_MAP_VERTEX_BUFFERS; -+ op->src_start_idx = src_start_idx; -+ op->stream_info = stream_info; -+ -+ cs->ops->submit_and_wait(cs); -+} -+ -+static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = ++static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = +{ + /* WINED3D_CS_OP_SYNC */ wined3d_cs_exec_sync, + /* WINED3D_CS_OP_GLFINISH */ wined3d_cs_exec_glfinish, @@ -2257,7 +2009,7 @@ /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch, -@@ -1682,13 +2985,33 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void +@@ -1847,15 +2843,29 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback, /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, @@ -2268,22 +2020,18 @@ /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource, /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, + /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource, + /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, +#if !defined(STAGING_CSMT) }; static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +#else /* STAGING_CSMT */ + /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants, -+ /* WINED3D_CS_OP_BLT */ wined3d_cs_exec_blt, + /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, + /* WINED3D_CS_OP_UPDATE_TEXTURE */ wined3d_cs_exec_update_texture, -+ /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, -+ /* WINED3D_CS_OP_GET_DC */ wined3d_cs_exec_get_dc, -+ /* WINED3D_CS_OP_RELEASE_DC */ wined3d_cs_exec_release_dc, + /* WINED3D_CS_OP_UPDATE_SWAP_INTERVAL */ wined3d_cs_exec_update_swap_interval, + /* WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION */ wined3d_cs_exec_texture_add_dirty_region, -+ /* WINED3D_CS_OP_BUFFER_COPY */ wined3d_cs_exec_buffer_copy, -+ /* WINED3D_CS_OP_MAP_VERTEX_BUFFERS */ wined3d_cs_exec_map_vertex_buffers, +}; + +static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size, int priority) @@ -2291,7 +2039,7 @@ { if (size > (cs->data_size - cs->end)) { -@@ -1732,6 +3055,7 @@ static void wined3d_cs_st_submit(struct wined3d_cs *cs) +@@ -1899,6 +2909,7 @@ static void wined3d_cs_st_submit(struct wined3d_cs *cs) HeapFree(GetProcessHeap(), 0, data); } @@ -2299,7 +2047,7 @@ static void wined3d_cs_st_push_constants(struct wined3d_cs *cs, enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants) { -@@ -1772,15 +3096,271 @@ static void wined3d_cs_st_push_constants(struct wined3d_cs *cs, enum wined3d_pus +@@ -1939,15 +2950,271 @@ static void wined3d_cs_st_push_constants(struct wined3d_cs *cs, enum wined3d_pus for (i = 0, context_count = device->context_count; i < context_count; ++i) { device->contexts[i]->constant_update_mask |= push_constant_info[p].mask; @@ -2571,7 +2319,7 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) { -@@ -1811,12 +3391,57 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) +@@ -1978,12 +3245,57 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) return NULL; } @@ -2632,7 +2380,7 @@ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c -@@ -1008,6 +1008,9 @@ static void wined3d_device_delete_opengl_contexts_cs(void *object) +@@ -1029,6 +1029,9 @@ static void wined3d_device_delete_opengl_contexts_cs(void *object) static void wined3d_device_delete_opengl_contexts(struct wined3d_device *device) { wined3d_cs_destroy_object(device->cs, wined3d_device_delete_opengl_contexts_cs, device); @@ -2642,7 +2390,7 @@ } static void wined3d_device_create_primary_opengl_context_cs(void *object) -@@ -1043,6 +1046,9 @@ static void wined3d_device_create_primary_opengl_context_cs(void *object) +@@ -1064,6 +1067,9 @@ static void wined3d_device_create_primary_opengl_context_cs(void *object) static HRESULT wined3d_device_create_primary_opengl_context(struct wined3d_device *device) { wined3d_cs_init_object(device->cs, wined3d_device_create_primary_opengl_context_cs, device); @@ -2652,7 +2400,7 @@ if (!device->swapchains[0]->num_contexts) return E_FAIL; -@@ -1187,6 +1193,10 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) +@@ -1208,6 +1214,10 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) if (!device->d3d_initialized) return WINED3DERR_INVALIDCALL; @@ -2663,7 +2411,7 @@ if (device->logo_texture) wined3d_texture_decref(device->logo_texture); if (device->cursor_texture) -@@ -1196,6 +1206,9 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) +@@ -1217,6 +1227,9 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) wine_rb_clear(&device->samplers, device_free_sampler, NULL); @@ -2673,7 +2421,7 @@ wined3d_device_delete_opengl_contexts(device); if (device->fb.depth_stencil) -@@ -1285,7 +1298,11 @@ UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device +@@ -1306,7 +1319,11 @@ UINT CDECL wined3d_device_get_available_texture_mem(const struct wined3d_device /* We can not acquire the context unless there is a swapchain. */ if (device->swapchains && gl_info->supported[NVX_GPU_MEMORY_INFO] && @@ -2685,7 +2433,7 @@ { GLint vram_free_kb; UINT64 vram_free; -@@ -2335,7 +2352,11 @@ HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device, +@@ -2374,7 +2391,11 @@ HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device, } else { @@ -2697,7 +2445,7 @@ } return WINED3D_OK; -@@ -2384,7 +2405,11 @@ HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device, +@@ -2423,7 +2444,11 @@ HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device, } else { @@ -2709,7 +2457,7 @@ } return WINED3D_OK; -@@ -2429,7 +2454,11 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device, +@@ -2468,7 +2493,11 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device, memset(&device->recording->changed.vs_consts_f[start_idx], 1, count * sizeof(*device->recording->changed.vs_consts_f)); else @@ -2721,7 +2469,7 @@ return WINED3D_OK; } -@@ -2568,7 +2597,11 @@ HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device, +@@ -2589,7 +2618,11 @@ HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device, } else { @@ -2733,7 +2481,7 @@ } return WINED3D_OK; -@@ -2617,7 +2650,11 @@ HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device, +@@ -2638,7 +2671,11 @@ HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device, } else { @@ -2745,7 +2493,7 @@ } return WINED3D_OK; -@@ -2663,7 +2700,11 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device, +@@ -2684,7 +2721,11 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device, memset(&device->recording->changed.ps_consts_f[start_idx], 1, count * sizeof(*device->recording->changed.ps_consts_f)); else @@ -2757,62 +2505,7 @@ return WINED3D_OK; } -@@ -2850,7 +2891,9 @@ void CDECL wined3d_device_set_unordered_access_view(struct wined3d_device *devic - wined3d_device_set_pipeline_unordered_access_view(device, WINED3D_PIPELINE_GRAPHICS, idx, uav); - } - -+#if !defined(STAGING_CSMT) - /* Context activation is done by the caller. */ -+#endif /* STAGING_CSMT */ - #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) - static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount, - const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD flags, -@@ -3126,6 +3169,7 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device, - UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer, - const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf) - { -+#if !defined(STAGING_CSMT) - struct wined3d_state *state = &device->state; - struct wined3d_stream_info stream_info; - const struct wined3d_gl_info *gl_info; -@@ -3134,6 +3178,10 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device, - unsigned int i; - HRESULT hr; - WORD map; -+#else /* STAGING_CSMT */ -+ struct wined3d_stream_info stream_info; -+ HRESULT hr; -+#endif /* STAGING_CSMT */ - - TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, " - "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n", -@@ -3143,6 +3191,7 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device, - if (declaration) - FIXME("Output vertex declaration not implemented yet.\n"); - -+#if !defined(STAGING_CSMT) - /* Need any context to write to the vbo. */ - context = context_acquire(device, NULL, 0); - gl_info = context->gl_info; -@@ -3178,12 +3227,17 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device, - if (e->data.addr) - e->data.addr += e->stride * src_start_idx; - } -+#else /* STAGING_CSMT */ -+ wined3d_cs_emit_map_vertex_buffers(device->cs, src_start_idx, &stream_info); -+#endif /* STAGING_CSMT */ - - hr = process_vertices_strided(device, dst_idx, vertex_count, - &stream_info, dst_buffer, flags, dst_fvf); - -+#if !defined(STAGING_CSMT) - context_release(context); - -+#endif /* STAGING_CSMT */ - return hr; - } - -@@ -3470,8 +3524,10 @@ HRESULT CDECL wined3d_device_begin_scene(struct wined3d_device *device) +@@ -3502,8 +3543,10 @@ HRESULT CDECL wined3d_device_begin_scene(struct wined3d_device *device) HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) { @@ -2823,7 +2516,7 @@ TRACE("device %p.\n", device); if (!device->inScene) -@@ -3480,6 +3536,7 @@ HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) +@@ -3512,6 +3555,7 @@ HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) return WINED3DERR_INVALIDCALL; } @@ -2831,7 +2524,7 @@ context = context_acquire(device, NULL, 0); /* We only have to do this if we need to read the, swapbuffers performs a flush for us */ context->gl_info->gl_ops.gl.p_glFlush(); -@@ -3487,6 +3544,7 @@ HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) +@@ -3519,6 +3563,7 @@ HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) * fails. */ context_release(context); @@ -2839,7 +2532,7 @@ device->inScene = FALSE; return WINED3D_OK; } -@@ -3634,11 +3692,17 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device +@@ -3666,11 +3711,17 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device start_idx, index_count, start_instance, instance_count, TRUE); } @@ -2857,7 +2550,7 @@ struct wined3d_context *context; struct wined3d_map_desc src; HRESULT hr = WINED3D_OK; -@@ -3662,6 +3726,13 @@ static HRESULT wined3d_device_update_texture_3d(struct wined3d_device *device, +@@ -3694,6 +3745,13 @@ static HRESULT wined3d_device_update_texture_3d(struct wined3d_device *device, } context = context_acquire(device, NULL, 0); @@ -2871,7 +2564,7 @@ /* Only a prepare, since we're uploading entire volumes. */ wined3d_texture_prepare_texture(dst_texture, context, FALSE); -@@ -3669,15 +3740,22 @@ static HRESULT wined3d_device_update_texture_3d(struct wined3d_device *device, +@@ -3701,15 +3759,22 @@ static HRESULT wined3d_device_update_texture_3d(struct wined3d_device *device, for (i = 0; i < level_count; ++i) { @@ -2894,7 +2587,7 @@ if (FAILED(hr = wined3d_resource_unmap(&src_texture->resource, src_level + i))) goto done; } -@@ -3685,16 +3763,89 @@ static HRESULT wined3d_device_update_texture_3d(struct wined3d_device *device, +@@ -3717,16 +3782,89 @@ static HRESULT wined3d_device_update_texture_3d(struct wined3d_device *device, done: context_release(context); return hr; @@ -2984,7 +2677,7 @@ TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture); -@@ -3731,6 +3882,7 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, +@@ -3763,6 +3901,7 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, return WINED3DERR_INVALIDCALL; } @@ -2992,7 +2685,7 @@ level_count = min(wined3d_texture_get_level_count(src_texture), wined3d_texture_get_level_count(dst_texture)); -@@ -3753,9 +3905,21 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, +@@ -3785,9 +3924,21 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, context_release(context); /* Update every surface level of the texture. */ @@ -3014,7 +2707,7 @@ { unsigned int src_levels = src_texture->level_count; unsigned int dst_levels = dst_texture->level_count; -@@ -3788,6 +3952,38 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, +@@ -3820,6 +3971,38 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, FIXME("Unsupported texture type %#x.\n", type); return WINED3DERR_INVALIDCALL; } @@ -3053,146 +2746,34 @@ } HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device, DWORD *num_passes) -@@ -3973,10 +4169,16 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device, - - if (dst_resource->type == WINED3D_RTYPE_BUFFER) - { -+#if !defined(STAGING_CSMT) - if (FAILED(hr = wined3d_buffer_copy(buffer_from_resource(dst_resource), 0, - buffer_from_resource(src_resource), 0, - dst_resource->size))) - ERR("Failed to copy buffer, hr %#x.\n", hr); -+#else /* STAGING_CSMT */ -+ wined3d_cs_emit_buffer_copy(device->cs, buffer_from_resource(dst_resource), 0, -+ buffer_from_resource(src_resource), 0, -+ dst_resource->size); -+#endif /* STAGING_CSMT */ - return; - } - -@@ -4025,6 +4227,9 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev - struct wined3d_texture *dst_texture, *src_texture; - RECT dst_rect, src_rect; - HRESULT hr; -+#if defined(STAGING_CSMT) -+ struct wined3d_box dst_box; -+#endif /* STAGING_CSMT */ - - TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, " - "src_resource %p, src_sub_resource_idx %u, src_box %s.\n", -@@ -4097,8 +4302,14 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev +@@ -4152,6 +4335,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev return WINED3DERR_INVALIDCALL; } +#if !defined(STAGING_CSMT) - return wined3d_buffer_copy(buffer_from_resource(dst_resource), dst_x, - buffer_from_resource(src_resource), src_offset, size); + if (dst_texture->sub_resources[dst_sub_resource_idx].map_count) + { + WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx); +@@ -4162,6 +4346,18 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev + { + WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx); + return WINED3DERR_INVALIDCALL; +#else /* STAGING_CSMT */ -+ wined3d_cs_emit_buffer_copy(device->cs, buffer_from_resource(dst_resource), dst_x, -+ buffer_from_resource(src_resource), src_offset, size); -+ return WINED3D_OK; -+#endif /* STAGING_CSMT */ - } - - if (dst_resource->type != WINED3D_RTYPE_TEXTURE_2D) -@@ -4112,6 +4323,16 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev - - if (src_box) - { -+#if defined(STAGING_CSMT) -+ if ((src_texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) -+ && !wined3d_texture_check_block_align(src_texture, -+ src_sub_resource_idx % src_texture->level_count, src_box)) ++ if (dst_texture->sub_resources[dst_sub_resource_idx].map_count || ++ src_texture->sub_resources[src_sub_resource_idx].map_count) + { -+ WARN("Source box not block-aligned.\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+#endif /* STAGING_CSMT */ - SetRect(&src_rect, src_box->left, src_box->top, src_box->right, src_box->bottom); - } - else -@@ -4125,6 +4346,25 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev - SetRect(&dst_rect, dst_x, dst_y, dst_x + (src_rect.right - src_rect.left), - dst_y + (src_rect.bottom - src_rect.top)); - -+#if defined(STAGING_CSMT) -+ if (dst_texture->resource.format_flags & WINED3DFMT_FLAG_BLOCKS) -+ { -+ dst_box.left = dst_rect.left; -+ dst_box.top = dst_rect.top; -+ dst_box.front = 0; -+ dst_box.right = dst_rect.right; -+ dst_box.bottom = dst_rect.bottom; -+ dst_box.back = 1; -+ -+ if(!wined3d_texture_check_block_align(dst_texture, -+ dst_sub_resource_idx % dst_texture->level_count, &dst_box)) -+ { -+ WARN("Destination box not block-aligned.\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ } -+ -+#endif /* STAGING_CSMT */ - if (FAILED(hr = wined3d_texture_blt(dst_texture, dst_sub_resource_idx, &dst_rect, - src_texture, src_sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT))) - WARN("Failed to blit, hr %#x.\n", hr); -@@ -4137,8 +4377,10 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - unsigned int depth_pitch) - { - unsigned int width, height, depth, level; -+#if !defined(STAGING_CSMT) - struct wined3d_const_bo_address addr; - struct wined3d_context *context; -+#endif /* STAGING_CSMT */ - struct wined3d_texture *texture; - - TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u.\n", -@@ -4146,18 +4388,24 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - - if (resource->type == WINED3D_RTYPE_BUFFER) - { -+#if !defined(STAGING_CSMT) - struct wined3d_buffer *buffer = buffer_from_resource(resource); - HRESULT hr; - ++ wined3d_cs_emit_sync(dst_texture->resource.device->cs); ++ if (dst_texture->sub_resources[dst_sub_resource_idx].map_count || ++ src_texture->sub_resources[src_sub_resource_idx].map_count) ++ { ++ WARN("Destination or source sub-resource is mapped.\n"); ++ return WINEDDERR_SURFACEBUSY; ++ } +#endif /* STAGING_CSMT */ - if (sub_resource_idx > 0) - { - WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); - return; } -+#if !defined(STAGING_CSMT) - if (FAILED(hr = wined3d_buffer_upload_data(buffer, box, data))) - WARN("Failed to update buffer data, hr %#x.\n", hr); - -+#else /* STAGING_CSMT */ -+ wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch); -+#endif /* STAGING_CSMT */ - return; - } - -@@ -4188,6 +4436,7 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - return; - } - -+#if !defined(STAGING_CSMT) - addr.buffer_object = 0; - addr.addr = data; - -@@ -4207,6 +4456,9 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - - wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); - wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB); -+#else /* STAGING_CSMT */ -+ wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch); -+#endif /* STAGING_CSMT */ - } - - HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device, -@@ -4255,10 +4507,15 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi + if (!src_box) +@@ -4318,10 +4514,15 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi return WINED3DERR_INVALIDCALL; } @@ -3208,7 +2789,7 @@ } struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(const struct wined3d_device *device, -@@ -4828,7 +5085,11 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, +@@ -4891,7 +5092,11 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, { if (reset_state) hr = wined3d_device_create_primary_opengl_context(device); @@ -3220,7 +2801,7 @@ } /* All done. There is no need to reload resources or shaders, this will happen automatically on the -@@ -5143,3 +5404,58 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL +@@ -5206,3 +5411,58 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL else return CallWindowProcA(proc, window, message, wparam, lparam); } @@ -3383,7 +2964,7 @@ diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c -@@ -645,8 +645,12 @@ static HRESULT wined3d_surface_depth_fill(struct wined3d_surface *surface, const +@@ -547,8 +547,12 @@ static HRESULT wined3d_surface_depth_fill(struct wined3d_surface *surface, const { struct wined3d_resource *resource = &surface->container->resource; struct wined3d_device *device = resource->device; @@ -3396,7 +2977,7 @@ const struct blit_shader *blitter; HRESULT hr; -@@ -657,6 +661,7 @@ static HRESULT wined3d_surface_depth_fill(struct wined3d_surface *surface, const +@@ -559,6 +563,7 @@ static HRESULT wined3d_surface_depth_fill(struct wined3d_surface *surface, const return WINED3DERR_INVALIDCALL; } @@ -3404,7 +2985,7 @@ view_desc.format_id = resource->format->id; view_desc.flags = 0; view_desc.u.texture.level_idx = surface->texture_level; -@@ -672,6 +677,19 @@ static HRESULT wined3d_surface_depth_fill(struct wined3d_surface *surface, const +@@ -574,6 +579,19 @@ static HRESULT wined3d_surface_depth_fill(struct wined3d_surface *surface, const hr = blitter->depth_fill(device, view, rect, WINED3DCLEAR_ZBUFFER, depth, 0); wined3d_rendertarget_view_decref(view); @@ -3424,7 +3005,7 @@ return hr; } -@@ -2450,8 +2468,12 @@ HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const st +@@ -2334,8 +2352,12 @@ HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const st { struct wined3d_resource *resource = &s->container->resource; struct wined3d_device *device = resource->device; @@ -3437,7 +3018,7 @@ const struct blit_shader *blitter; HRESULT hr; -@@ -2462,6 +2484,7 @@ HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const st +@@ -2346,6 +2368,7 @@ HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const st return WINED3DERR_INVALIDCALL; } @@ -3445,7 +3026,7 @@ view_desc.format_id = resource->format->id; view_desc.flags = 0; view_desc.u.texture.level_idx = s->texture_level; -@@ -2477,6 +2500,19 @@ HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const st +@@ -2361,6 +2384,19 @@ HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const st hr = blitter->color_fill(device, view, rect, color); wined3d_rendertarget_view_decref(view); @@ -3465,7 +3046,7 @@ return hr; } -@@ -2791,7 +2827,11 @@ static BOOL surface_load_texture(struct wined3d_surface *surface, +@@ -2675,7 +2711,11 @@ static BOOL surface_load_texture(struct wined3d_surface *surface, /* Don't use PBOs for converted surfaces. During PBO conversion we look at * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is * getting called. */ @@ -3477,321 +3058,6 @@ { TRACE("Removing the pbo attached to surface %p.\n", surface); -@@ -3772,7 +3812,11 @@ const struct blit_shader cpu_blit = { - cpu_blit_blit_surface, - }; - -+#if !defined(STAGING_CSMT) - HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect, -+#else /* STAGING_CSMT */ -+void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect, -+#endif /* STAGING_CSMT */ - struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, - const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) - { -@@ -3782,9 +3826,14 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - struct wined3d_texture *dst_texture = dst_surface->container; - struct wined3d_device *device = dst_texture->resource.device; - struct wined3d_swapchain *src_swapchain, *dst_swapchain; -+#if !defined(STAGING_CSMT) - struct wined3d_texture *src_texture = NULL; - unsigned int dst_w, dst_h, src_w, src_h; - unsigned int src_sub_resource_idx = 0; -+#else /* STAGING_CSMT */ -+ struct wined3d_texture *src_texture; -+ unsigned int src_sub_resource_idx; -+#endif /* STAGING_CSMT */ - DWORD src_ds_flags, dst_ds_flags; - BOOL scale, convert; - -@@ -3797,6 +3846,7 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - | WINED3D_BLT_DO_NOT_WAIT - | WINED3D_BLT_ALPHA_TEST; - -+#if !defined(STAGING_CSMT) - TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", - dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), - flags, fx, debug_d3dtexturefiltertype(filter)); -@@ -3814,10 +3864,12 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - fx->src_color_key.color_space_high_value); - } - -+#endif /* STAGING_CSMT */ - if (src_surface) - { - src_texture = src_surface->container; - src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); -+#if !defined(STAGING_CSMT) - } - - if (dst_texture->sub_resources[dst_sub_resource_idx].map_count -@@ -3875,6 +3927,15 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - if (!once++) - FIXME("Can't handle WINED3D_BLT_DO_NOT_WAIT flag.\n"); - flags &= ~WINED3D_BLT_DO_NOT_WAIT; -+#else /* STAGING_CSMT */ -+ src_swapchain = src_texture->swapchain; -+ } -+ else -+ { -+ src_texture = NULL; -+ src_sub_resource_idx = 0; -+ src_swapchain = NULL; -+#endif /* STAGING_CSMT */ - } - - if (!device->d3d_initialized) -@@ -3899,11 +3960,13 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - goto fallback; - } - -+#if !defined(STAGING_CSMT) - if (src_texture) - src_swapchain = src_texture->swapchain; - else - src_swapchain = NULL; - -+#endif /* STAGING_CSMT */ - dst_swapchain = dst_texture->swapchain; - - /* This isn't strictly needed. FBO blits for example could deal with -@@ -3939,13 +4002,21 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - TRACE("Depth fill.\n"); - - if (!wined3d_format_convert_color_to_float(dst_texture->resource.format, NULL, fx->fill_color, &color)) -+#if !defined(STAGING_CSMT) - return WINED3DERR_INVALIDCALL; - - if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, dst_rect, color.r))) - return WINED3D_OK; -+#else /* STAGING_CSMT */ -+ return; -+ -+ if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, dst_rect, color.r))) -+ return; -+#endif /* STAGING_CSMT */ - } - else - { -+#if !defined(STAGING_CSMT) - if (src_ds_flags != dst_ds_flags) - { - WARN("Rejecting depth / stencil blit between incompatible formats.\n"); -@@ -3955,6 +4026,11 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_texture->resource.draw_binding, - src_rect, dst_surface, dst_texture->resource.draw_binding, dst_rect))) - return WINED3D_OK; -+#else /* STAGING_CSMT */ -+ if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_texture->resource.draw_binding, -+ src_rect, dst_surface, dst_texture->resource.draw_binding, dst_rect))) -+ return; -+#endif /* STAGING_CSMT */ - } - } - else -@@ -3990,7 +4066,11 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - goto fallback; - - if (SUCCEEDED(surface_color_fill(dst_surface, dst_rect, &color))) -+#if !defined(STAGING_CSMT) - return WINED3D_OK; -+#else /* STAGING_CSMT */ -+ return; -+#endif /* STAGING_CSMT */ - } - else - { -@@ -4034,7 +4114,11 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - context, dst_texture->resource.draw_binding); - context_release(context); - } -+#if !defined(STAGING_CSMT) - return WINED3D_OK; -+#else /* STAGING_CSMT */ -+ return; -+#endif /* STAGING_CSMT */ - } - } - } -@@ -4058,7 +4142,11 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, 0); - dst_swapchain->desc.swap_effect = swap_effect; - -+#if !defined(STAGING_CSMT) - return WINED3D_OK; -+#else /* STAGING_CSMT */ -+ return; -+#endif /* STAGING_CSMT */ - } - - if (fbo_blit_supported(&device->adapter->gl_info, blit_op, -@@ -4079,7 +4167,11 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, - ~dst_texture->resource.draw_binding); - -+#if !defined(STAGING_CSMT) - return WINED3D_OK; -+#else /* STAGING_CSMT */ -+ return; -+#endif /* STAGING_CSMT */ - } - - blitter = wined3d_select_blitter(&device->adapter->gl_info, &device->adapter->d3d_info, blit_op, -@@ -4089,7 +4181,11 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - { - blitter->blit_surface(device, blit_op, filter, src_surface, - src_rect, dst_surface, dst_rect, color_key); -+#if !defined(STAGING_CSMT) - return WINED3D_OK; -+#else /* STAGING_CSMT */ -+ return; -+#endif /* STAGING_CSMT */ - } - } - } -@@ -4097,9 +4193,142 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst - fallback: - /* Special cases for render targets. */ - if (SUCCEEDED(surface_blt_special(dst_surface, dst_rect, src_surface, src_rect, flags, fx, filter))) -+#if !defined(STAGING_CSMT) - return WINED3D_OK; - - cpu: - return surface_cpu_blt(dst_texture, dst_sub_resource_idx, &dst_box, - src_texture, src_sub_resource_idx, &src_box, flags, fx, filter); -+#else /* STAGING_CSMT */ -+ return; -+ -+cpu: -+ surface_cpu_blt(dst_texture, dst_sub_resource_idx, &dst_box, -+ src_texture, src_sub_resource_idx, &src_box, flags, fx, filter); -+} -+ -+HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect, -+ struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, -+ const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) -+{ -+ struct wined3d_texture *dst_texture = dst_surface->container; -+ struct wined3d_device *device = dst_texture->resource.device; -+ unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface), src_sub_resource_idx; -+ struct wined3d_texture_sub_resource *dst_sub_resource = -+ &dst_texture->sub_resources[dst_sub_resource_idx]; -+ struct wined3d_texture_sub_resource *src_sub_resource = NULL; -+ unsigned int dst_w, dst_h, src_w, src_h; -+ DWORD src_ds_flags, dst_ds_flags; -+ -+ TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", -+ dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), -+ flags, fx, debug_d3dtexturefiltertype(filter)); -+ TRACE("Usage is %s.\n", debug_d3dusage(dst_texture->resource.usage)); -+ -+ if (fx) -+ { -+ TRACE("fx %#x.\n", fx->fx); -+ TRACE("fill_color 0x%08x.\n", fx->fill_color); -+ TRACE("dst_color_key {0x%08x, 0x%08x}.\n", -+ fx->dst_color_key.color_space_low_value, -+ fx->dst_color_key.color_space_high_value); -+ TRACE("src_color_key {0x%08x, 0x%08x}.\n", -+ fx->src_color_key.color_space_low_value, -+ fx->src_color_key.color_space_high_value); -+ } -+ -+ if (src_surface) -+ { -+ src_sub_resource_idx = surface_get_sub_resource_idx(src_surface); -+ src_sub_resource = &src_surface->container->sub_resources[src_sub_resource_idx]; -+ } -+ -+ if (dst_sub_resource->map_count || (src_sub_resource && src_sub_resource->map_count)) -+ { -+ wined3d_cs_emit_sync(device->cs); -+ if (dst_sub_resource->map_count || (src_sub_resource && src_sub_resource->map_count)) -+ { -+ WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n"); -+ return WINEDDERR_SURFACEBUSY; -+ } -+ } -+ -+ dst_w = wined3d_texture_get_level_width(dst_texture, dst_surface->texture_level); -+ dst_h = wined3d_texture_get_level_height(dst_texture, dst_surface->texture_level); -+ if (IsRectEmpty(dst_rect) || dst_rect->left > dst_w || dst_rect->left < 0 -+ || dst_rect->top > dst_h || dst_rect->top < 0 -+ || dst_rect->right > dst_w || dst_rect->right < 0 -+ || dst_rect->bottom > dst_h || dst_rect->bottom < 0) -+ { -+ WARN("The application gave us a bad destination rectangle.\n"); -+ return WINEDDERR_INVALIDRECT; -+ } -+ -+ if (src_surface) -+ { -+ src_w = wined3d_texture_get_level_width(src_surface->container, src_surface->texture_level); -+ src_h = wined3d_texture_get_level_height(src_surface->container, src_surface->texture_level); -+ if (IsRectEmpty(src_rect) || src_rect->left > src_w || src_rect->left < 0 -+ || src_rect->top > src_h || src_rect->top < 0 -+ || src_rect->right > src_w || src_rect->right < 0 -+ || src_rect->bottom > src_h || src_rect->bottom < 0) -+ { -+ WARN("The application gave us a bad source rectangle.\n"); -+ return WINEDDERR_INVALIDRECT; -+ } -+ } -+ -+ dst_ds_flags = dst_texture->resource.format_flags -+ & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); -+ if (src_surface) -+ src_ds_flags = src_surface->container->resource.format_flags -+ & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); -+ else -+ src_ds_flags = 0; -+ -+ if (!(flags & WINED3D_BLT_DEPTH_FILL) && (src_ds_flags != dst_ds_flags)) -+ { -+ WARN("Rejecting depth / stencil blit between incompatible formats.\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ /* FIXME: We should select the blitter in the main thread, that way we can return an error if the blit -+ * is unsupported without duplicating all the checks... */ -+ if (flags & WINED3D_BLT_COLOR_FILL && (dst_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)) -+ { -+ WARN("Block color fill, returning WINED3DERR_INVALIDCALL\n"); -+ return WINED3DERR_INVALIDCALL; -+ } -+ -+ if (!fx || !(fx->fx)) -+ flags &= ~WINED3D_BLT_FX; -+ -+ if (flags & WINED3D_BLT_WAIT) -+ flags &= ~WINED3D_BLT_WAIT; -+ -+ if (flags & WINED3D_BLT_ASYNC) -+ { -+ static unsigned int once; -+ -+ if (!once++) -+ FIXME("Can't handle WINED3D_BLT_ASYNC flag.\n"); -+ flags &= ~WINED3D_BLT_ASYNC; -+ } -+ -+ /* WINED3D_BLT_DO_NOT_WAIT appeared in DX7. */ -+ if (flags & WINED3D_BLT_DO_NOT_WAIT) -+ { -+ static unsigned int once; -+ -+ if (!once++) -+ FIXME("Can't handle WINED3D_BLT_DO_NOT_WAIT flag.\n"); -+ flags &= ~WINED3D_BLT_DO_NOT_WAIT; -+ } -+ -+ TRACE("Emitting blit %p <== %p\n", dst_surface, src_surface); -+ wined3d_cs_emit_blt(device->cs, dst_surface, dst_rect, src_surface, src_rect, -+ flags, fx, filter); -+ -+ return WINED3D_OK; -+#endif /* STAGING_CSMT */ - } diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -3894,11 +3160,11 @@ +#if !defined(STAGING_CSMT) unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info) { - GLuint *buffer_object; + GLuint *buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object; @@ -450,6 +455,19 @@ static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture - TRACE("Deleted buffer object %u for texture %p, sub-resource %u.\n", - *buffer_object, texture, sub_resource_idx); + wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); + *buffer_object = 0; +#else /* STAGING_CSMT */ + unsigned int sub_resource_idx, struct wined3d_context *context) +{ @@ -3974,17 +3240,26 @@ } if (context) context_release(context); -@@ -1316,18 +1356,31 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT +@@ -1391,6 +1431,9 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT + if (surface->dc) + { + wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); ++#if defined(STAGING_CSMT) ++ wined3d_cs_emit_sync(device->cs); ++#endif /* STAGING_CSMT */ + create_dib = TRUE; + } + +@@ -1451,18 +1494,30 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT wined3d_texture_invalidate_location(texture, 0, ~valid_location); if (create_dib) +#if !defined(STAGING_CSMT) - wined3d_surface_create_dc(surface); + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); +#else /* STAGING_CSMT */ + { -+ HDC dc; -+ wined3d_texture_get_dc(texture, 0, &dc); -+ wined3d_texture_release_dc(texture, 0, dc); ++ wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); ++ wined3d_cs_emit_sync(device->cs); + } +#endif /* STAGING_CSMT */ @@ -4006,7 +3281,7 @@ if (sub_resource->buffer_object) return; -@@ -1339,6 +1392,16 @@ static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *textur +@@ -1474,6 +1529,16 @@ static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *textur TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", sub_resource->buffer_object, texture, sub_resource_idx); @@ -4023,7 +3298,7 @@ } static void wined3d_texture_force_reload(struct wined3d_texture *texture) -@@ -1464,7 +1527,11 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned +@@ -1599,7 +1664,11 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned return TRUE; case WINED3D_LOCATION_BUFFER: @@ -4035,19 +3310,7 @@ return TRUE; case WINED3D_LOCATION_TEXTURE_RGB: -@@ -1500,7 +1567,11 @@ void CDECL wined3d_texture_generate_mipmaps(struct wined3d_texture *texture) - FIXME("texture %p stub!\n", texture); - } - -+#if !defined(STAGING_CSMT) - static struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct wined3d_texture *texture, -+#else /* STAGING_CSMT */ -+struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct wined3d_texture *texture, -+#endif /* STAGING_CSMT */ - unsigned int sub_resource_idx) - { - UINT sub_count = texture->level_count * texture->layer_count; -@@ -1519,7 +1590,9 @@ static struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(str +@@ -1654,7 +1723,9 @@ static struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(str HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, UINT layer, const struct wined3d_box *dirty_region) { @@ -4057,7 +3320,7 @@ unsigned int sub_resource_idx; TRACE("texture %p, layer %u, dirty_region %s.\n", texture, layer, debug_box(dirty_region)); -@@ -1531,6 +1604,7 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, +@@ -1666,6 +1737,7 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, } sub_resource_idx = layer * texture->level_count; @@ -4065,7 +3328,7 @@ if (dirty_region) WARN("Ignoring dirty_region %s.\n", debug_box(dirty_region)); -@@ -1544,6 +1618,9 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, +@@ -1679,6 +1751,9 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); context_release(context); @@ -4075,7 +3338,7 @@ return WINED3D_OK; } -@@ -1777,7 +1854,11 @@ static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned in +@@ -1912,7 +1987,11 @@ static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned in } else if (sub_resource->locations & WINED3D_LOCATION_BUFFER) { @@ -4087,7 +3350,7 @@ wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); texture1d_upload_data(texture, sub_resource_idx, context, NULL, &data, row_pitch, slice_pitch); -@@ -1822,7 +1903,11 @@ static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned in +@@ -1957,7 +2036,11 @@ static BOOL texture1d_load_location(struct wined3d_texture *texture, unsigned in case WINED3D_LOCATION_BUFFER: if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { @@ -4099,7 +3362,7 @@ if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) wined3d_texture_bind_and_dirtify(texture, context, FALSE); -@@ -2116,8 +2201,13 @@ static void wined3d_texture_unload(struct wined3d_resource *resource) +@@ -2251,8 +2334,13 @@ static void wined3d_texture_unload(struct wined3d_resource *resource) wined3d_texture_invalidate_location(texture, i, ~WINED3D_LOCATION_DISCARDED); } @@ -4113,31 +3376,17 @@ if (resource->type == WINED3D_RTYPE_TEXTURE_2D) { -@@ -2726,11 +2816,23 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 - - TRACE("Created surface level %u, layer %u @ %p.\n", i, j, surface); - -+#if !defined(STAGING_CSMT) - if (((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) - && FAILED(hr = wined3d_surface_create_dc(surface))) +@@ -2856,6 +2944,9 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 + if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) { - wined3d_texture_cleanup_sync(texture); - return hr; -+#else /* STAGING_CSMT */ -+ if ((desc->usage & WINED3DUSAGE_OWNDC) || (device->wined3d->flags & WINED3D_NO3D)) -+ { -+ HDC dc; -+ if (FAILED(hr = wined3d_texture_get_dc(texture, idx, &dc))) -+ { -+ wined3d_texture_cleanup_sync(texture); -+ return hr; -+ } -+ wined3d_texture_release_dc(texture, idx, dc); + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); ++#if defined(STAGING_CSMT) ++ wined3d_cs_emit_sync(device->cs); +#endif /* STAGING_CSMT */ - } - } - } -@@ -2906,7 +3008,11 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in + if (!surface->dc) + { + wined3d_texture_cleanup_sync(texture); +@@ -3036,7 +3127,11 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in } else if (sub_resource->locations & WINED3D_LOCATION_BUFFER) { @@ -4149,7 +3398,7 @@ wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); wined3d_texture_get_pitch(texture, sub_resource_idx, &row_pitch, &slice_pitch); -@@ -2952,7 +3058,11 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in +@@ -3082,7 +3177,11 @@ static BOOL texture3d_load_location(struct wined3d_texture *texture, unsigned in case WINED3D_LOCATION_BUFFER: if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { @@ -4161,123 +3410,55 @@ if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) wined3d_texture_bind_and_dirtify(texture, context, FALSE); -@@ -3486,13 +3596,49 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct - return WINED3D_OK; - } - -+#if defined(STAGING_CSMT) -+HRESULT wined3d_texture_get_dc_cs(struct wined3d_texture *texture, unsigned int sub_resource_idx) -+{ -+ struct wined3d_device *device = texture->resource.device; -+ struct wined3d_context *context = NULL; -+ struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; -+ struct wined3d_surface *surface = sub_resource->u.surface; -+ HRESULT hr = WINED3D_OK; -+ -+ if (device->d3d_initialized) -+ context = context_acquire(device, NULL, 0); -+ -+ wined3d_texture_load_location(texture, sub_resource_idx, context, texture->resource.map_binding); -+ wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); -+ -+ if (!surface->dc) -+ hr = wined3d_surface_create_dc(surface); -+ if (context) -+ context_release(context); -+ if (FAILED(hr)) -+ return hr; -+ -+ if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) -+ texture->flags |= WINED3D_TEXTURE_DC_IN_USE; -+ ++texture->resource.map_count; -+ ++sub_resource->map_count; -+ -+ return hr; -+} -+ -+#endif /* STAGING_CSMT */ - HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC *dc) - { - struct wined3d_device *device = texture->resource.device; - struct wined3d_texture_sub_resource *sub_resource; +@@ -3303,8 +3402,18 @@ HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned + if (dst_texture->sub_resources[dst_sub_resource_idx].map_count + || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count)) + { +#if !defined(STAGING_CSMT) - struct wined3d_context *context = NULL; - struct wined3d_surface *surface; - HRESULT hr = WINED3D_OK; + WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n"); + return WINEDDERR_SURFACEBUSY; +#else /* STAGING_CSMT */ -+ struct wined3d_surface *surface; -+ HRESULT hr; ++ wined3d_cs_emit_sync(dst_texture->resource.device->cs); ++ if (dst_texture->sub_resources[dst_sub_resource_idx].map_count ++ || (src_texture && src_texture->sub_resources[src_sub_resource_idx].map_count)) ++ { ++ WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n"); ++ return WINEDDERR_SURFACEBUSY; ++ } +#endif /* STAGING_CSMT */ + } - TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture, sub_resource_idx, dc); - -@@ -3517,6 +3663,7 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i - if (texture->resource.map_count && !(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) + if ((dst_format_flags & WINED3DFMT_FLAG_BLOCKS) && (flags & WINED3D_BLT_COLOR_FILL)) +@@ -3653,7 +3762,14 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i return WINED3DERR_INVALIDCALL; + if (!surface->dc) +#if !defined(STAGING_CSMT) - if (device->d3d_initialized) - context = context_acquire(device, NULL, 0); - -@@ -3534,11 +3681,40 @@ HRESULT CDECL wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned i - texture->flags |= WINED3D_TEXTURE_DC_IN_USE; - ++texture->resource.map_count; - ++sub_resource->map_count; + wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); +#else /* STAGING_CSMT */ -+ wined3d_resource_wait_idle(&texture->resource); -+ -+ hr = wined3d_cs_emit_get_dc(device->cs, texture, sub_resource_idx); -+ if (FAILED(hr)) -+ return hr; -+#endif /* STAGING_CSMT */ - - *dc = surface->dc; - TRACE("Returning dc %p.\n", *dc); - -+#if !defined(STAGING_CSMT) - return hr; -+#else /* STAGING_CSMT */ -+ return WINED3D_OK; -+} -+ -+HRESULT wined3d_texture_release_dc_cs(struct wined3d_texture *texture, unsigned int sub_resource_idx) -+{ -+ struct wined3d_device *device = texture->resource.device; -+ struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; -+ struct wined3d_surface *surface = sub_resource->u.surface; -+ -+ if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D)) -+ wined3d_surface_destroy_dc(surface); -+ -+ --sub_resource->map_count; -+ if (!--texture->resource.map_count && texture->update_map_binding) -+ wined3d_texture_update_map_binding(texture); -+ if (!(texture->flags & WINED3D_TEXTURE_GET_DC_LENIENT)) -+ texture->flags &= ~WINED3D_TEXTURE_DC_IN_USE; -+ -+ return WINED3D_OK; ++ { ++ wined3d_cs_init_object(device->cs, texture2d_create_dc, surface); ++ wined3d_cs_emit_sync(device->cs); ++ } +#endif /* STAGING_CSMT */ - } - - HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC dc) -@@ -3569,6 +3745,7 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign + if (!surface->dc) return WINED3DERR_INVALIDCALL; + +@@ -3697,7 +3813,14 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign } -+#if !defined(STAGING_CSMT) if (!(texture->resource.usage & WINED3DUSAGE_OWNDC) && !(device->wined3d->flags & WINED3D_NO3D)) - wined3d_surface_destroy_dc(surface); - -@@ -3579,4 +3756,9 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign - texture->flags &= ~WINED3D_TEXTURE_DC_IN_USE; - - return WINED3D_OK; ++#if !defined(STAGING_CSMT) + wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); +#else /* STAGING_CSMT */ -+ wined3d_resource_wait_idle(&texture->resource); -+ -+ return wined3d_cs_emit_release_dc(device->cs, texture, sub_resource_idx); ++ { ++ wined3d_cs_destroy_object(device->cs, texture2d_destroy_dc, surface); ++ wined3d_cs_emit_sync(device->cs); ++ } +#endif /* STAGING_CSMT */ - } + + --sub_resource->map_count; + if (!--texture->resource.map_count && texture->update_map_binding) diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -4360,7 +3541,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -307,6 +307,9 @@ struct wined3d_settings +@@ -391,6 +391,9 @@ struct wined3d_settings unsigned int max_sm_ps; unsigned int max_sm_cs; BOOL no_3d; @@ -4370,7 +3551,7 @@ }; extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN; -@@ -1519,6 +1522,10 @@ struct wined3d_query +@@ -1573,6 +1576,10 @@ struct wined3d_query const void *data; DWORD data_size; const struct wined3d_query_ops *query_ops; @@ -4381,7 +3562,7 @@ }; union wined3d_gl_query_object -@@ -1560,6 +1567,9 @@ struct wined3d_occlusion_query +@@ -1614,6 +1621,9 @@ struct wined3d_occlusion_query GLuint id; struct wined3d_context *context; UINT64 samples; @@ -4391,7 +3572,7 @@ }; struct wined3d_timestamp_query -@@ -2589,6 +2599,16 @@ struct wined3d_state +@@ -2603,6 +2613,16 @@ struct wined3d_state struct wined3d_rasterizer_state *rasterizer_state; }; @@ -4408,7 +3589,7 @@ #define WINED3D_UNMAPPED_STAGE ~0u /* Multithreaded flag. Removed from the public header to signal that -@@ -2700,6 +2720,14 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL +@@ -2715,6 +2735,14 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; @@ -4423,7 +3604,7 @@ static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) { -@@ -2775,11 +2803,13 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource) +@@ -2790,11 +2818,13 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource) InterlockedDecrement(&resource->access_count); } @@ -4437,7 +3618,7 @@ void resource_cleanup(struct wined3d_resource *resource) DECLSPEC_HIDDEN; HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device, enum wined3d_resource_type type, const struct wined3d_format *format, -@@ -2890,7 +2920,11 @@ struct wined3d_texture +@@ -2905,7 +2935,11 @@ struct wined3d_texture unsigned int map_count; DWORD locations; @@ -4449,47 +3630,7 @@ } sub_resources[1]; }; -@@ -2943,9 +2977,16 @@ void wined3d_texture_bind_and_dirtify(struct wined3d_texture *texture, - struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; - BOOL wined3d_texture_check_block_align(const struct wined3d_texture *texture, - unsigned int level, const struct wined3d_box *box) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) -+HRESULT wined3d_texture_get_dc_cs(struct wined3d_texture *texture, unsigned int sub_resource_idx) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) DECLSPEC_HIDDEN; - void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int sub_resource_idx, - struct wined3d_bo_address *data, DWORD locations) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) -+struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - void wined3d_texture_invalidate_location(struct wined3d_texture *texture, - unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN; - void wined3d_texture_load(struct wined3d_texture *texture, -@@ -2958,6 +2999,10 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned - struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; - void wined3d_texture_prepare_texture(struct wined3d_texture *texture, - struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) -+HRESULT wined3d_texture_release_dc_cs(struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN; - void wined3d_texture_set_swapchain(struct wined3d_texture *texture, - struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -@@ -3065,6 +3110,11 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P - void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, - const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point, - BOOL srgb, const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN; -+#if defined(STAGING_CSMT) -+void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_in, -+ struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags, -+ const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ - - void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context, - const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; -@@ -3192,6 +3242,7 @@ enum wined3d_push_constants +@@ -3205,6 +3239,7 @@ enum wined3d_push_constants WINED3D_PUSH_CONSTANTS_PS_B, }; @@ -4497,7 +3638,7 @@ struct wined3d_cs_ops { void *(*require_space)(struct wined3d_cs *cs, size_t size); -@@ -3199,6 +3250,33 @@ struct wined3d_cs_ops +@@ -3212,6 +3247,33 @@ struct wined3d_cs_ops void (*push_constants)(struct wined3d_cs *cs, enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants); }; @@ -4531,12 +3672,12 @@ struct wined3d_cs { -@@ -3209,23 +3287,75 @@ struct wined3d_cs +@@ -3222,8 +3284,31 @@ struct wined3d_cs size_t data_size, start, end; void *data; +#if !defined(STAGING_CSMT) - }; ++}; +#else /* STAGING_CSMT */ + + HANDLE thread; @@ -4551,32 +3692,23 @@ + + HANDLE event; + BOOL waiting_for_event; -+}; -+ + }; + +static inline void wined3d_resource_wait_idle(struct wined3d_resource *resource) +{ + if (resource->device->cs->thread_id == GetCurrentThreadId()) return; + while (InterlockedCompareExchange(&resource->access_count, 0, 0)); +} +#endif /* STAGING_CSMT */ - ++ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; void wined3d_cs_destroy(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_destroy_object(struct wined3d_cs *cs, - void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; -+#if !defined(STAGING_CSMT) -+void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, -+ DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ -+void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surface, -+ const RECT *dst_rect, struct wined3d_surface *src_surface, -+ const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, -+ enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; -+void wined3d_cs_emit_buffer_copy(struct wined3d_cs *cs, struct wined3d_buffer *dst_buffer, -+ unsigned int dst_offset, struct wined3d_buffer *src_buffer, unsigned int src_offset, -+ unsigned int size) DECLSPEC_HIDDEN; +@@ -3234,15 +3319,30 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) +void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, + const RECT *rect, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil, + const struct blit_shader *blitter) DECLSPEC_HIDDEN; @@ -4587,8 +3719,6 @@ unsigned int start_idx, unsigned int index_count, unsigned int start_instance, unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN; +#if defined(STAGING_CSMT) -+HRESULT wined3d_cs_emit_get_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) DECLSPEC_HIDDEN; +void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; +#endif /* STAGING_CSMT */ void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; @@ -4601,26 +3731,24 @@ + unsigned int start_idx, unsigned int count, const void *constants) DECLSPEC_HIDDEN; void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; +BOOL wined3d_cs_emit_query_poll(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; -+HRESULT wined3d_cs_emit_release_dc(struct wined3d_cs *cs, struct wined3d_texture *texture, -+ unsigned int sub_resource_idx) DECLSPEC_HIDDEN; +#endif /* STAGING_CSMT */ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN; -@@ -3273,19 +3403,37 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined +@@ -3290,10 +3390,20 @@ void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; -+#if !defined(STAGING_CSMT) -+void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+#else /* STAGING_CSMT */ ++#if defined(STAGING_CSMT) +void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, struct wined3d_texture *texture, + unsigned int sub_resource_idx, const struct wined3d_box *dirty_region) DECLSPEC_HIDDEN; +void wined3d_cs_emit_sync(struct wined3d_cs *cs); ++#endif /* STAGING_CSMT */ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; -+void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, -+ unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, -+ unsigned int depth_pitch) DECLSPEC_HIDDEN; + void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, + unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, + unsigned int slice_pitch) DECLSPEC_HIDDEN; ++#if defined(STAGING_CSMT) +void wined3d_cs_emit_update_swap_interval(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; +void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, + struct wined3d_texture *dst) DECLSPEC_HIDDEN; @@ -4628,20 +3756,18 @@ void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags) DECLSPEC_HIDDEN; +@@ -3301,12 +3411,14 @@ HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx) DECLSPEC_HIDDEN; -+#if !defined(STAGING_CSMT) ++#if !defined(STAGING_CSMT) static inline void wined3d_cs_push_constants(struct wined3d_cs *cs, enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants) { cs->ops->push_constants(cs, p, start_idx, count, constants); } -+#else /* STAGING_CSMT */ -+void wined3d_cs_emit_map_vertex_buffers(struct wined3d_cs *cs, UINT src_start_idx, -+ struct wined3d_stream_info *stream_info) DECLSPEC_HIDDEN; -+#endif /* STAGING_CSMT */ ++#endif /* STAGING_CSMT */ /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other * fixed function semantics as D3DCOLOR or FLOAT16 */ + enum wined3d_buffer_conversion_type diff -Nru wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-Revert_Buffer_Upload/0001-Revert-wined3d-Implement-wined3d_buffer_upload_data-.patch wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-Revert_Buffer_Upload/0001-Revert-wined3d-Implement-wined3d_buffer_upload_data-.patch --- wine-staging-2.3.0~ubuntu16.04.1/patches/wined3d-Revert_Buffer_Upload/0001-Revert-wined3d-Implement-wined3d_buffer_upload_data-.patch 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/patches/wined3d-Revert_Buffer_Upload/0001-Revert-wined3d-Implement-wined3d_buffer_upload_data-.patch 2017-03-21 14:37:14.000000000 +0000 @@ -1,4 +1,4 @@ -From 77e96719b681f37950972bd78478c1c08a5faebc Mon Sep 17 00:00:00 2001 +From 331d0798182a0e5fab1fe59e6503d5e8597ff403 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 8 Feb 2017 19:35:36 +0100 Subject: Revert "wined3d: Implement wined3d_buffer_upload_data() on top of @@ -7,15 +7,15 @@ This reverts commit e2dbbec1af8ae2ea8813148d56e14c8c211ee334. --- dlls/wined3d/buffer.c | 30 +++++++++++++++++++----------- - dlls/wined3d/device.c | 14 +++----------- + dlls/wined3d/cs.c | 13 +++---------- dlls/wined3d/wined3d_private.h | 2 +- - 3 files changed, 23 insertions(+), 23 deletions(-) + 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c -index fa3e3a7380a..5cf7b1068f9 100644 +index c584147717b..18933d1f6df 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c -@@ -532,7 +532,7 @@ ULONG CDECL wined3d_buffer_incref(struct wined3d_buffer *buffer) +@@ -525,7 +525,7 @@ ULONG CDECL wined3d_buffer_incref(struct wined3d_buffer *buffer) /* Context activation is done by the caller. */ static void wined3d_buffer_upload_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context, @@ -24,7 +24,7 @@ { const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_map_range *range; -@@ -543,7 +543,7 @@ static void wined3d_buffer_upload_ranges(struct wined3d_buffer *buffer, struct w +@@ -536,7 +536,7 @@ static void wined3d_buffer_upload_ranges(struct wined3d_buffer *buffer, struct w { range = &ranges[range_count]; GL_EXTCALL(glBufferSubData(buffer->buffer_type_hint, @@ -33,7 +33,7 @@ } checkGLcall("glBufferSubData"); } -@@ -599,7 +599,7 @@ static void buffer_conversion_upload(struct wined3d_buffer *buffer, struct wined +@@ -592,7 +592,7 @@ static void buffer_conversion_upload(struct wined3d_buffer *buffer, struct wined } } @@ -42,7 +42,7 @@ HeapFree(GetProcessHeap(), 0, data); } -@@ -683,7 +683,7 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, +@@ -676,7 +676,7 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, case WINED3D_LOCATION_BUFFER: if (!buffer->conversion_map) wined3d_buffer_upload_ranges(buffer, context, buffer->resource.heap_memory, @@ -51,7 +51,7 @@ else buffer_conversion_upload(buffer, context); break; -@@ -1267,23 +1267,31 @@ HRESULT wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_ +@@ -1261,23 +1261,31 @@ HRESULT wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_ return WINED3D_OK; } @@ -90,43 +90,37 @@ } static ULONG buffer_resource_incref(struct wined3d_resource *resource) -diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c -index a7ee5bc099d..a3adf3255f1 100644 ---- a/dlls/wined3d/device.c -+++ b/dlls/wined3d/device.c -@@ -4127,6 +4127,7 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - if (resource->type == WINED3D_RTYPE_BUFFER) +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 9f3de815be5..39071faef32 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1669,18 +1669,11 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi + if (op->resource->type == WINED3D_RTYPE_BUFFER) { - struct wined3d_buffer *buffer = buffer_from_resource(resource); + struct wined3d_buffer *buffer = buffer_from_resource(op->resource); + HRESULT hr; - if (sub_resource_idx > 0) - { -@@ -4134,17 +4135,8 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str - return; - } - -- context = context_acquire(resource->device, NULL, 0); +- context = context_acquire(op->resource->device, NULL, 0); - if (!wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER)) - { - ERR("Failed to load buffer location.\n"); - context_release(context); -- return; +- goto done; - } -- -- wined3d_buffer_upload_data(buffer, context, box, data); -- wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER); -- context_release(context); -+ if (FAILED(hr = wined3d_buffer_upload_data(buffer, box, data))) ++ if (FAILED(hr = wined3d_buffer_upload_data(buffer, box, op->data.data))) + WARN("Failed to update buffer data, hr %#x.\n", hr); - return; +- wined3d_buffer_upload_data(buffer, context, box, op->data.data); +- wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER); +- context_release(context); + goto done; } + diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 50b7c93cad8..30de702098a 100644 +index 48f2f368d20..3883792f6fe 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -3300,7 +3300,7 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, +@@ -3343,7 +3343,7 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) DECLSPEC_HIDDEN; HRESULT wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_offset, struct wined3d_buffer *src_buffer, unsigned int src_offset, unsigned int size) DECLSPEC_HIDDEN; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/po/de.po wine-staging-2.4.0~ubuntu16.04.1/po/de.po --- wine-staging-2.3.0~ubuntu16.04.1/po/de.po 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/po/de.po 2017-03-21 14:02:57.000000000 +0000 @@ -5,7 +5,7 @@ "Project-Id-Version: Wine\n" "Report-Msgid-Bugs-To: http://bugs.winehq.org\n" "POT-Creation-Date: N/A\n" -"PO-Revision-Date: 2016-11-22 12:35+0100\n" +"PO-Revision-Date: 2017-03-06 16:05+0100\n" "Last-Translator: Julian Rüger\n" "Language-Team: German\n" "Language: de\n" @@ -8376,10 +8376,8 @@ msgstr "Wine-Systemsteuerung" #: shell32.rc:195 -#, fuzzy -#| msgid "Unable to display Run File dialog box (internal error)" msgid "Unable to display Run dialog box (internal error)" -msgstr "Konnte Ausführen-Dialog nicht anzeigen (interner Fehler)" +msgstr "Ausführen-Dialog konnte nicht angezeigt werden (interner Fehler)" #: shell32.rc:196 msgid "Unable to display Browse dialog box (internal error)" @@ -9398,10 +9396,8 @@ msgstr "Vertraulichkeit erforderlich" #: wldap32.rc:46 -#, fuzzy -#| msgid "Shutdown in progress.\n" msgid "SASL Bind in Progress" -msgstr "Herunterfahren im Gange.\n" +msgstr "SASL-Bindung im Gange" #: wldap32.rc:48 msgid "No Such Attribute" @@ -11980,67 +11976,57 @@ msgstr "(unbekannt %d)" #: regedit.rc:214 -#, fuzzy -#| msgid "regedit: Unable to open the registry key '%1'.\n" msgid "Unable to modify the selected registry value." -msgstr "regedit: Der Schlüssel '%1' konnte nicht geöffnet werden.\n" +msgstr "Der ausgewählte Wert konnte nicht geändert werden." #: regedit.rc:215 -#, fuzzy -#| msgid "regedit: Unable to open the registry key '%1'.\n" msgid "Unable to create a new registry key." -msgstr "regedit: Der Schlüssel '%1' konnte nicht geöffnet werden.\n" +msgstr "Es konnte kein neuer Schlüssel angelegt werden." #: regedit.rc:216 -#, fuzzy -#| msgid "regedit: Unable to open the registry key '%1'.\n" msgid "Unable to create a new registry value." -msgstr "regedit: Der Schlüssel '%1' konnte nicht geöffnet werden.\n" +msgstr "Es konnte kein neuer Wert angelegt werden." #: regedit.rc:217 msgid "" "Unable to rename the key '%1'.\n" "The specified key name already exists." msgstr "" +"Der Schlüssel '%1' konnte nicht umbenannt werden.\n" +"Der angegebene Schlüsselname ist bereits vorhanden." #: regedit.rc:218 msgid "" "Unable to rename the value '%1'.\n" "The specified value name already exists." msgstr "" +"Der Wert '%1' konnte nicht umbenannt werden.\n" +"Der angegebene Name ist bereits vorhanden." #: regedit.rc:219 -#, fuzzy -#| msgid "regedit: Unable to open the registry key '%1'.\n" msgid "Unable to delete the selected registry key." -msgstr "regedit: Der Schlüssel '%1' konnte nicht geöffnet werden.\n" +msgstr "Der ausgewählte Schlüssel konnte nicht gelöscht werden." #: regedit.rc:220 -#, fuzzy -#| msgid "regedit: Unable to open the registry key '%1'.\n" msgid "Unable to rename the selected registry key." -msgstr "regedit: Der Schlüssel '%1' konnte nicht geöffnet werden.\n" +msgstr "Der ausgewählte Schlüssel konnte nicht umbenannt werden." #: regedit.rc:221 -#, fuzzy -#| msgid "regedit: Unable to open the registry key '%1'.\n" msgid "Unable to rename the selected registry value." -msgstr "regedit: Der Schlüssel '%1' konnte nicht geöffnet werden.\n" +msgstr "Der ausgewählte Wert konnte nicht umbenannt werden." #: regedit.rc:222 msgid "" "The keys and values contained in %1 were successfully added to the registry." msgstr "" +"Die in %1 enthaltenen Schlüssel und Werte wurden erfolgreich zur " +"Registrierung hinzugefügt." #: regedit.rc:223 -#, fuzzy -#| msgid "" -#| "regedit: Unable to export '%1'. The specified registry key was not " -#| "found.\n" msgid "Unable to import %1. The specified file is not a valid registry file." msgstr "" -"regedit: '%1' konnte nicht exportiert werden. Der angegebene Schlüssel wurde " -"nicht gefunden.\n" +"%1 konnte nicht importiert werden. Die angegebene Datei ist keine gültige " +"Registrierungsdatei." #: regedit.rc:375 msgid "" @@ -12274,32 +12260,24 @@ msgstr "Zeigt Programminformationen, Version und Copyright an" #: regedit.rc:181 -#, fuzzy -#| msgid "regedit: Unable to open the registry key '%1'.\n" msgid "Unable to query the registry value '%1'." -msgstr "regedit: Der Schlüssel '%1' konnte nicht geöffnet werden.\n" +msgstr "Der Wert '%1' konnte nicht abgefragt werden." #: regedit.rc:182 -#, fuzzy -#| msgid "Can't edit keys of this type (%u)" msgid "Unable to edit registry keys of this type (%1!u!)." -msgstr "Schlüssel von diesem Typ (%u) können nicht geändert werden" +msgstr "Schlüssel von diesem Typ (%1!u!) können nicht bearbeitet werden." #: regedit.rc:183 -#, fuzzy -#| msgid "Value is too big (%u)" msgid "The value is too big (%1!u!)." -msgstr "Der Wert ist zu groß (%u)" +msgstr "Der Wert ist zu groß (%1!u!)." #: regedit.rc:184 msgid "Confirm Value Delete" -msgstr "Bitte bestätigen" +msgstr "Löschen des Wertes bestätigen" #: regedit.rc:191 -#, fuzzy -#| msgid "Search string '%s' not found" msgid "Search complete. The string '%1' was not found." -msgstr "Suchfolge '%s' wurde nicht gefunden" +msgstr "Suche abgeschlossen. Die Zeichenfolge '%1' wurde nicht gefunden." #: regedit.rc:186 msgid "Are you sure you want to delete these values?" @@ -12314,10 +12292,8 @@ msgstr "Neuer Wert #%d" #: regedit.rc:180 -#, fuzzy -#| msgid "regedit: Unable to open the registry key '%1'.\n" msgid "Unable to query the registry key '%1'." -msgstr "regedit: Der Schlüssel '%1' konnte nicht geöffnet werden.\n" +msgstr "Der Schlüssel '%1' konnte nicht abgefragt werden." #: regedit.rc:152 msgid "Adds a new multi-string value" @@ -12325,20 +12301,18 @@ #: regedit.rc:174 msgid "Exports selected branch of the registry to a text file" -msgstr "Exportiert den ausgewählten Zweig der Registry in eine Textdatei" +msgstr "Exportiert den ausgewählten Zweig der Registrierung in eine Textdatei" #: regedit.rc:187 -#, fuzzy -#| msgid "Confirm Value Delete" msgid "Confirm Key Delete" -msgstr "Bitte bestätigen" +msgstr "Löschen des Schlüssels bestätigen" #: regedit.rc:188 -#, fuzzy -#| msgid "Are you sure you want to delete the registry key '%1'?" msgid "" "Are you sure you want to delete the registry key '%1' and all of its subkeys?" -msgstr "Sind Sie sicher, dass Sie den Schlüssel '%1' löschen möchten?" +msgstr "" +"Sind Sie sicher, dass Sie den Schlüssel '%1' und alle Unterschlüssel löschen " +"möchten?" #: regsvr32.rc:32 msgid "" diff -Nru wine-staging-2.3.0~ubuntu16.04.1/programs/iexplore/main.c wine-staging-2.4.0~ubuntu16.04.1/programs/iexplore/main.c --- wine-staging-2.3.0~ubuntu16.04.1/programs/iexplore/main.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/programs/iexplore/main.c 2017-03-21 14:02:57.000000000 +0000 @@ -34,14 +34,19 @@ LPWSTR file_desc; UINT bytes; void* buf; - BOOL ret; + BOOL ret = TRUE; + LPWORD translation; static const WCHAR browseui_dllW[] = {'b','r','o','w','s','e','u','i','.','d','l','l',0}; static const WCHAR wineW[] = {'W','i','n','e',0}; - static const WCHAR file_desc_strW[] = + static const WCHAR translationW[] = + {'\\','V','a','r','F','i','l','e','I','n','f','o', + '\\','T','r','a','n','s','l','a','t','i','o','n',0}; + static const WCHAR file_desc_fmtW[] = {'\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o', - '\\','0','4','0','9','0','4','e','4', + '\\','%','0','4','x','%','0','4','x', '\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0}; + WCHAR file_desc_strW[48]; size = GetFileVersionInfoSizeW(browseui_dllW, &handle); if(!size) @@ -49,8 +54,11 @@ buf = HeapAlloc(GetProcessHeap(), 0, size); GetFileVersionInfoW(browseui_dllW, 0, size,buf); - - ret = !VerQueryValueW(buf, file_desc_strW, (void**)&file_desc, &bytes) || !strstrW(file_desc, wineW); + if (VerQueryValueW(buf, translationW, (void **)&translation, &bytes)) + { + wsprintfW(file_desc_strW, file_desc_fmtW, translation[0], translation[1]); + ret = !VerQueryValueW(buf, file_desc_strW, (void**)&file_desc, &bytes) || !strstrW(file_desc, wineW); + } HeapFree(GetProcessHeap(), 0, buf); return ret; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/programs/iexplore/Makefile.in wine-staging-2.4.0~ubuntu16.04.1/programs/iexplore/Makefile.in --- wine-staging-2.3.0~ubuntu16.04.1/programs/iexplore/Makefile.in 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/programs/iexplore/Makefile.in 2017-03-21 14:02:57.000000000 +0000 @@ -1,7 +1,7 @@ MODULE = iexplore.exe APPMODE = -mwindows -municode -Wl,--large-address-aware IMPORTS = ieframe -DELAYIMPORTS = advpack version +DELAYIMPORTS = advpack version user32 C_SRCS = \ main.c diff -Nru wine-staging-2.3.0~ubuntu16.04.1/programs/regedit/tests/regedit.c wine-staging-2.4.0~ubuntu16.04.1/programs/regedit/tests/regedit.c --- wine-staging-2.3.0~ubuntu16.04.1/programs/regedit/tests/regedit.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/programs/regedit/tests/regedit.c 2017-03-21 14:02:57.000000000 +0000 @@ -471,6 +471,31 @@ "\"Test11\"=\"Value\"\n"); verify_reg_nonexist(hkey, "Test11"); + /* Test multi-line import with incorrect comma placement */ + exec_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line1\"=hex(7):4c,69,6e,65,20\\\n" + ",63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n"); + todo_wine verify_reg_nonexist(hkey, "Multi-Line1"); + + exec_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line2\"=hex(7):4c,69,6e,65,20\\\n" + " ,63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n"); + verify_reg_nonexist(hkey, "Multi-Line2"); + + exec_import_str("Windows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line3\"=hex(7):4c,69,6e,65,20\\\n" + ",63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n"); + todo_wine verify_reg_nonexist(hkey, "Multi-Line3"); + + exec_import_str("Windows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line4\"=hex(7):4c,69,6e,65,20\\\n" + " ,63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n"); + verify_reg_nonexist(hkey, "Multi-Line4"); + RegCloseKey(hkey); lr = RegDeleteKeyA(HKEY_CURRENT_USER, KEY_BASE); diff -Nru wine-staging-2.3.0~ubuntu16.04.1/server/object.c wine-staging-2.4.0~ubuntu16.04.1/server/object.c --- wine-staging-2.3.0~ubuntu16.04.1/server/object.c 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/server/object.c 2017-03-21 14:02:57.000000000 +0000 @@ -28,6 +28,9 @@ #include #include #include +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include +#endif #include "ntstatus.h" #define WIN32_NO_STATUS @@ -92,11 +95,22 @@ /*****************************************************************/ +/* mark a block of memory as uninitialized for debugging purposes */ +static inline void mark_block_uninitialized( void *ptr, size_t size ) +{ + memset( ptr, 0x55, size ); +#if defined(VALGRIND_MAKE_MEM_UNDEFINED) + VALGRIND_DISCARD( VALGRIND_MAKE_MEM_UNDEFINED( ptr, size )); +#elif defined(VALGRIND_MAKE_WRITABLE) + VALGRIND_DISCARD( VALGRIND_MAKE_WRITABLE( ptr, size )); +#endif +} + /* malloc replacement */ void *mem_alloc( size_t size ) { void *ptr = malloc( size ); - if (ptr) memset( ptr, 0x55, size ); + if (ptr) mark_block_uninitialized( ptr, size ); else set_error( STATUS_NO_MEMORY ); return ptr; } diff -Nru wine-staging-2.3.0~ubuntu16.04.1/staging/VERSION wine-staging-2.4.0~ubuntu16.04.1/staging/VERSION --- wine-staging-2.3.0~ubuntu16.04.1/staging/VERSION 2017-03-06 21:22:20.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/staging/VERSION 2017-03-21 14:37:14.000000000 +0000 @@ -1 +1 @@ -Wine Staging 2.3 +Wine Staging 2.4 diff -Nru wine-staging-2.3.0~ubuntu16.04.1/tools/make_specfiles wine-staging-2.4.0~ubuntu16.04.1/tools/make_specfiles --- wine-staging-2.3.0~ubuntu16.04.1/tools/make_specfiles 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/tools/make_specfiles 2017-03-21 14:02:57.000000000 +0000 @@ -338,6 +338,10 @@ "bcrypt", "ncrypt", ], + [ + "ntoskrnl.exe", + "hal", + ], ); my $update_flags = 0; diff -Nru wine-staging-2.3.0~ubuntu16.04.1/VERSION wine-staging-2.4.0~ubuntu16.04.1/VERSION --- wine-staging-2.3.0~ubuntu16.04.1/VERSION 2017-03-06 20:56:07.000000000 +0000 +++ wine-staging-2.4.0~ubuntu16.04.1/VERSION 2017-03-21 14:02:57.000000000 +0000 @@ -1 +1 @@ -Wine version 2.3 +Wine version 2.4