diff -Nru wine-devel-2.3.0~ubuntu15.04.1/ANNOUNCE wine-devel-2.4.0~ubuntu15.04.1/ANNOUNCE --- wine-devel-2.3.0~ubuntu15.04.1/ANNOUNCE 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/ANNOUNCE 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/configure wine-devel-2.4.0~ubuntu15.04.1/configure --- wine-devel-2.3.0~ubuntu15.04.1/configure 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/configure 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/debian/bzr-builder.manifest wine-devel-2.4.0~ubuntu15.04.1/debian/bzr-builder.manifest --- wine-devel-2.3.0~ubuntu15.04.1/debian/bzr-builder.manifest 2017-03-06 21:43:15.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/debian/bzr-builder.manifest 2017-03-20 22:03:17.000000000 +0000 @@ -1,3 +1,3 @@ -# bzr-builder format 0.4 deb-version 2.3.0 -lp:wine revid:git-v1:a2460b2424163bbf5b885db6a5423c3d98f883e0 -merge wine-build-development lp:~wine/wine/build-development revid:sebastian@fds-team.de-20170306204721-28o7c19b15z28kbz +# bzr-builder format 0.4 deb-version 2.4.0 +lp:wine revid:git-v1:6a05069a43f1a8f0e69c4cedd134f8d7400b8a95 +merge wine-build-development lp:~wine/wine/build-development revid:sebastian@fds-team.de-20170320211700-wqbox6ehl68votfz diff -Nru wine-devel-2.3.0~ubuntu15.04.1/debian/changelog wine-devel-2.4.0~ubuntu15.04.1/debian/changelog --- wine-devel-2.3.0~ubuntu15.04.1/debian/changelog 2017-03-06 21:43:15.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/debian/changelog 2017-03-20 22:03:17.000000000 +0000 @@ -1,9 +1,9 @@ -wine-devel (2.3.0~ubuntu15.04.1) vivid; urgency=low +wine-devel (2.4.0~ubuntu15.04.1) vivid; urgency=low * Auto build. - -- Sebastian Lackner Mon, 06 Mar 2017 21:43:15 +0000 + -- Sebastian Lackner Mon, 20 Mar 2017 22:03:17 +0000 -wine-devel (2.3.0) unstable; urgency=low +wine-devel (2.4.0) unstable; urgency=low * Auto build. - -- Michael Müller Mon, 06 Mar 2017 20:40:03 -0000 + -- Michael Müller Mon, 20 Mar 2017 21:04:09 -0000 diff -Nru wine-devel-2.3.0~ubuntu15.04.1/dlls/advapi32/tests/service.c wine-devel-2.4.0~ubuntu15.04.1/dlls/advapi32/tests/service.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/advapi32/tests/service.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/advapi32/tests/service.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/api-ms-win-appmodel-runtime-l1-1-1/api-ms-win-appmodel-runtime-l1-1-1.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/api-ms-win-crt-time-l1-1-0/api-ms-win-crt-time-l1-1-0.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/api-ms-win-crt-time-l1-1-0/api-ms-win-crt-time-l1-1-0.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/api-ms-win-crt-time-l1-1-0/api-ms-win-crt-time-l1-1-0.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/api-ms-win-crt-time-l1-1-0/api-ms-win-crt-time-l1-1-0.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/appwiz.cpl/addons.c wine-devel-2.4.0~ubuntu15.04.1/dlls/appwiz.cpl/addons.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/appwiz.cpl/addons.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/appwiz.cpl/addons.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/bcrypt_internal.h wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/bcrypt_internal.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/bcrypt_internal.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/bcrypt_internal.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/bcrypt_main.c wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/bcrypt_main.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/bcrypt_main.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/bcrypt_main.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/bcrypt.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/bcrypt.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/bcrypt.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/bcrypt.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/Makefile.in wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/Makefile.in --- wine-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/Makefile.in 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/Makefile.in 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/sha256.c wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/sha256.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/sha256.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/sha256.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/sha512.c wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/sha512.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/sha512.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/sha512.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/tests/bcrypt.c wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/tests/bcrypt.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/bcrypt/tests/bcrypt.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/bcrypt/tests/bcrypt.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/cabinet/fdi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/cabinet/fdi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/cabinet/fdi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/cabinet/fdi.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/cabinet/tests/fdi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/cabinet/tests/fdi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/cabinet/tests/fdi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/cabinet/tests/fdi.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/commctrl.c wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/commctrl.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/commctrl.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/commctrl.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/Makefile.in wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/Makefile.in --- wine-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/Makefile.in 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/Makefile.in 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/taskdialog.c wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/taskdialog.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/taskdialog.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/taskdialog.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/tests/Makefile.in wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/tests/Makefile.in --- wine-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/tests/Makefile.in 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/tests/Makefile.in 2017-03-20 21:19:48.000000000 +0000 @@ -22,6 +22,7 @@ subclass.c \ syslink.c \ tab.c \ + taskdialog.c \ toolbar.c \ tooltips.c \ trackbar.c \ diff -Nru wine-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/tests/misc.c wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/tests/misc.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/tests/misc.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/tests/misc.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/tests/taskdialog.c wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/tests/taskdialog.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/comctl32/tests/taskdialog.c 1970-01-01 00:00:00.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/comctl32/tests/taskdialog.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/comdlg32/filedlg.c wine-devel-2.4.0~ubuntu15.04.1/dlls/comdlg32/filedlg.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/comdlg32/filedlg.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/comdlg32/filedlg.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/concrt140/concrt140.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/concrt140/concrt140.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/concrt140/concrt140.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/concrt140/concrt140.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/crtdll/crtdll.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/crtdll/crtdll.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/crtdll/crtdll.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/crtdll/crtdll.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/crypt32/tests/crl.c wine-devel-2.4.0~ubuntu15.04.1/dlls/crypt32/tests/crl.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/crypt32/tests/crl.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/crypt32/tests/crl.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d10core/tests/device.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d10core/tests/device.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d10core/tests/device.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d10core/tests/device.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d11/device.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d11/device.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d11/device.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d11/device.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d11/tests/d3d11.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d11/tests/d3d11.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d11/tests/d3d11.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d11/tests/d3d11.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d8/directx.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d8/directx.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d8/directx.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d8/directx.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/device.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/device.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/device.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/device.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/directx.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/directx.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/directx.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/directx.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/tests/d3d9ex.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/tests/d3d9ex.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/tests/d3d9ex.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/tests/d3d9ex.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/tests/device.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/tests/device.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/tests/device.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/tests/device.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/tests/visual.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/tests/visual.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3d9/tests/visual.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3d9/tests/visual.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3dx9_36/d3dx9_private.h wine-devel-2.4.0~ubuntu15.04.1/dlls/d3dx9_36/d3dx9_private.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3dx9_36/d3dx9_private.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3dx9_36/d3dx9_private.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3dx9_36/effect.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3dx9_36/effect.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3dx9_36/effect.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3dx9_36/effect.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/d3dx9_36/tests/effect.c wine-devel-2.4.0~ubuntu15.04.1/dlls/d3dx9_36/tests/effect.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/d3dx9_36/tests/effect.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/d3dx9_36/tests/effect.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/ddraw.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/ddraw.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/ddraw.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/ddraw.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/ddraw_private.h wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/ddraw_private.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/ddraw_private.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/ddraw_private.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/device.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/device.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/device.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/device.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/surface.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/surface.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/surface.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/surface.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/d3d.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/d3d.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/d3d.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/d3d.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw1.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw1.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw1.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw1.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw2.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw2.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw2.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw2.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw4.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw4.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw4.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw4.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw7.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw7.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw7.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/ddraw7.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/dsurface.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/dsurface.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/tests/dsurface.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/tests/dsurface.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/vertexbuffer.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/vertexbuffer.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ddraw/vertexbuffer.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ddraw/vertexbuffer.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/devenum/mediacatenum.c wine-devel-2.4.0~ubuntu15.04.1/dlls/devenum/mediacatenum.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/devenum/mediacatenum.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/devenum/mediacatenum.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/devenum/tests/devenum.c wine-devel-2.4.0~ubuntu15.04.1/dlls/devenum/tests/devenum.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/devenum/tests/devenum.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/devenum/tests/devenum.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dhcpcsvc/dhcpcsvc.c wine-devel-2.4.0~ubuntu15.04.1/dlls/dhcpcsvc/dhcpcsvc.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dhcpcsvc/dhcpcsvc.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dhcpcsvc/dhcpcsvc.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dhcpcsvc/dhcpcsvc.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/dhcpcsvc/dhcpcsvc.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dhcpcsvc/dhcpcsvc.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dhcpcsvc/dhcpcsvc.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dplayx/dplobby.c wine-devel-2.4.0~ubuntu15.04.1/dlls/dplayx/dplobby.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dplayx/dplobby.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dplayx/dplobby.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dplayx/tests/dplayx.c wine-devel-2.4.0~ubuntu15.04.1/dlls/dplayx/tests/dplayx.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dplayx/tests/dplayx.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dplayx/tests/dplayx.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dpnet/tests/client.c wine-devel-2.4.0~ubuntu15.04.1/dlls/dpnet/tests/client.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dpnet/tests/client.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dpnet/tests/client.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dpnet/tests/thread.c wine-devel-2.4.0~ubuntu15.04.1/dlls/dpnet/tests/thread.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dpnet/tests/thread.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dpnet/tests/thread.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dwrite/dwrite_private.h wine-devel-2.4.0~ubuntu15.04.1/dlls/dwrite/dwrite_private.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dwrite/dwrite_private.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dwrite/dwrite_private.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dwrite/font.c wine-devel-2.4.0~ubuntu15.04.1/dlls/dwrite/font.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dwrite/font.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dwrite/font.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/dwrite/freetype.c wine-devel-2.4.0~ubuntu15.04.1/dlls/dwrite/freetype.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/dwrite/freetype.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/dwrite/freetype.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/bitblt.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/bitblt.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/bitblt.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/bitblt.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/dib.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/dib.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/dib.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/dib.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/dibdrv/bitblt.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/dibdrv/bitblt.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/dibdrv/bitblt.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/dibdrv/bitblt.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/dibdrv/primitives.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/dibdrv/primitives.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/dibdrv/primitives.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/dibdrv/primitives.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/freetype.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/freetype.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/freetype.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/freetype.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/gdi_private.h wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/gdi_private.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/gdi_private.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/gdi_private.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/tests/dib.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/tests/dib.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/tests/dib.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/tests/dib.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/tests/font.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/tests/font.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/tests/font.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/tests/font.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/tests/wine_test.sfd wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/tests/wine_test.sfd --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/tests/wine_test.sfd 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/tests/wine_test.sfd 2017-03-20 21:19:48.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/tmpeuvGah/fkkr8MoF8d/wine-devel-2.3.0~ubuntu15.04.1/dlls/gdi32/tests/wine_test.ttf and /tmp/tmpeuvGah/SIR7X7uGny/wine-devel-2.4.0~ubuntu15.04.1/dlls/gdi32/tests/wine_test.ttf differ diff -Nru wine-devel-2.3.0~ubuntu15.04.1/dlls/gdiplus/font.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdiplus/font.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdiplus/font.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdiplus/font.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/gdiplus/tests/font.c wine-devel-2.4.0~ubuntu15.04.1/dlls/gdiplus/tests/font.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/gdiplus/tests/font.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/gdiplus/tests/font.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/hal/hal.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/hal/hal.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/hal/hal.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/hal/hal.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/inetcomm/tests/mimeole.c wine-devel-2.4.0~ubuntu15.04.1/dlls/inetcomm/tests/mimeole.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/inetcomm/tests/mimeole.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/inetcomm/tests/mimeole.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/iphlpapi/iphlpapi_main.c wine-devel-2.4.0~ubuntu15.04.1/dlls/iphlpapi/iphlpapi_main.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/iphlpapi/iphlpapi_main.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/iphlpapi/iphlpapi_main.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/iphlpapi/iphlpapi.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/iphlpapi/iphlpapi.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/iphlpapi/iphlpapi.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/iphlpapi/iphlpapi.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/iphlpapi/tests/iphlpapi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/iphlpapi/tests/iphlpapi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/iphlpapi/tests/iphlpapi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/iphlpapi/tests/iphlpapi.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/kernel32/kernel32.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/kernel32/kernel32.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/kernel32/kernel32.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/kernel32/kernel32.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/kernel32/tests/format_msg.c wine-devel-2.4.0~ubuntu15.04.1/dlls/kernel32/tests/format_msg.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/kernel32/tests/format_msg.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/kernel32/tests/format_msg.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/kernel32/version.c wine-devel-2.4.0~ubuntu15.04.1/dlls/kernel32/version.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/kernel32/version.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/kernel32/version.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/krnl386.exe16/dma.c wine-devel-2.4.0~ubuntu15.04.1/dlls/krnl386.exe16/dma.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/krnl386.exe16/dma.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/krnl386.exe16/dma.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/krnl386.exe16/int21.c wine-devel-2.4.0~ubuntu15.04.1/dlls/krnl386.exe16/int21.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/krnl386.exe16/int21.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/krnl386.exe16/int21.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/mciavi32/mciavi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/mciavi32/mciavi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/mciavi32/mciavi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/mciavi32/mciavi.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/mciavi32/private_mciavi.h wine-devel-2.4.0~ubuntu15.04.1/dlls/mciavi32/private_mciavi.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/mciavi32/private_mciavi.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/mciavi32/private_mciavi.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/mciavi32/wnd.c wine-devel-2.4.0~ubuntu15.04.1/dlls/mciavi32/wnd.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/mciavi32/wnd.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/mciavi32/wnd.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/mscoree/mscoree_main.c wine-devel-2.4.0~ubuntu15.04.1/dlls/mscoree/mscoree_main.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/mscoree/mscoree_main.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/mscoree/mscoree_main.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msctf/tests/inputprocessor.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msctf/tests/inputprocessor.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msctf/tests/inputprocessor.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msctf/tests/inputprocessor.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msi/install.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msi/install.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msi/install.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msi/install.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcp140/msvcp140.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcp140/msvcp140.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcp140/msvcp140.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcp140/msvcp140.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcp140/tests/msvcp140.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcp140/tests/msvcp140.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcp140/tests/msvcp140.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcp140/tests/msvcp140.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcp90/misc.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcp90/misc.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcp90/misc.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcp90/misc.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcr100/msvcr100.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr100/msvcr100.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcr100/msvcr100.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr100/msvcr100.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcr110/msvcr110.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr110/msvcr110.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcr110/msvcr110.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr110/msvcr110.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcr120/msvcr120.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr120/msvcr120.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcr120/msvcr120.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr120/msvcr120.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcr120_app/msvcr120_app.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr120_app/msvcr120_app.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcr120_app/msvcr120_app.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr120_app/msvcr120_app.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcr70/msvcr70.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr70/msvcr70.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcr70/msvcr70.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr70/msvcr70.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcr71/msvcr71.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr71/msvcr71.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcr71/msvcr71.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr71/msvcr71.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcr80/msvcr80.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr80/msvcr80.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcr80/msvcr80.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr80/msvcr80.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcr90/msvcr90.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr90/msvcr90.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcr90/msvcr90.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcr90/msvcr90.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/lock.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/lock.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/lock.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/lock.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/misc.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/misc.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/misc.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/misc.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/msvcrt.h wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/msvcrt.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/msvcrt.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/msvcrt.h 2017-03-20 21:19:48.000000000 +0000 @@ -1181,6 +1181,8 @@ #define UCRTBASE_SCANF_MASK (0x0007) +#define COOPERATIVE_WAIT_TIMEOUT ~0 + typedef enum { _FpCodeUnspecified, _FpCodeAdd, diff -Nru wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/msvcrt.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/msvcrt.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/msvcrt.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/msvcrt.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/time.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/time.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt/time.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt/time.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt20/msvcrt20.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt20/msvcrt20.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt20/msvcrt20.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt20/msvcrt20.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt40/msvcrt40.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt40/msvcrt40.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrt40/msvcrt40.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrt40/msvcrt40.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msvcrtd/msvcrtd.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrtd/msvcrtd.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msvcrtd/msvcrtd.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msvcrtd/msvcrtd.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msxml3/saxreader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msxml3/saxreader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msxml3/saxreader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msxml3/saxreader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msxml3/tests/domdoc.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msxml3/tests/domdoc.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msxml3/tests/domdoc.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msxml3/tests/domdoc.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/msxml3/tests/saxreader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/msxml3/tests/saxreader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/msxml3/tests/saxreader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/msxml3/tests/saxreader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ncrypt/ncrypt.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/ncrypt/ncrypt.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ncrypt/ncrypt.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ncrypt/ncrypt.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/npmshtml/rsrc.rc wine-devel-2.4.0~ubuntu15.04.1/dlls/npmshtml/rsrc.rc --- wine-devel-2.3.0~ubuntu15.04.1/dlls/npmshtml/rsrc.rc 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/npmshtml/rsrc.rc 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/critsection.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/critsection.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/critsection.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/critsection.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/file.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/file.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/file.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/file.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/server.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/server.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/server.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/server.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/signal_x86_64.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/signal_x86_64.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/signal_x86_64.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/signal_x86_64.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/tests/file.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/tests/file.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/tests/file.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/tests/file.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/tests/rtl.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/tests/rtl.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ntdll/tests/rtl.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ntdll/tests/rtl.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ntoskrnl.exe/ntoskrnl.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ntoskrnl.exe/ntoskrnl.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ntoskrnl.exe/ntoskrnl.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ntoskrnl.exe/ntoskrnl.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ntoskrnl.exe/ntoskrnl.exe.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/ntoskrnl.exe/ntoskrnl.exe.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ntoskrnl.exe/ntoskrnl.exe.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ntoskrnl.exe/ntoskrnl.exe.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/odbccp32/odbccp32.c wine-devel-2.4.0~ubuntu15.04.1/dlls/odbccp32/odbccp32.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/odbccp32/odbccp32.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/odbccp32/odbccp32.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/odbccp32/tests/misc.c wine-devel-2.4.0~ubuntu15.04.1/dlls/odbccp32/tests/misc.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/odbccp32/tests/misc.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/odbccp32/tests/misc.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ole32/tests/compobj.c wine-devel-2.4.0~ubuntu15.04.1/dlls/ole32/tests/compobj.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ole32/tests/compobj.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ole32/tests/compobj.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/oledb32/convert.c wine-devel-2.4.0~ubuntu15.04.1/dlls/oledb32/convert.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/oledb32/convert.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/oledb32/convert.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/oledb32/dslocator.c wine-devel-2.4.0~ubuntu15.04.1/dlls/oledb32/dslocator.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/oledb32/dslocator.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/oledb32/dslocator.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/oledb32/tests/convert.c wine-devel-2.4.0~ubuntu15.04.1/dlls/oledb32/tests/convert.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/oledb32/tests/convert.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/oledb32/tests/convert.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/oledb32/tests/database.c wine-devel-2.4.0~ubuntu15.04.1/dlls/oledb32/tests/database.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/oledb32/tests/database.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/oledb32/tests/database.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/opencl/opencl.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/opencl/opencl.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/opencl/opencl.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/opencl/opencl.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/rasapi32/rasapi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/rasapi32/rasapi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/rasapi32/rasapi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/rasapi32/rasapi.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/rasapi32/tests/rasapi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/rasapi32/tests/rasapi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/rasapi32/tests/rasapi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/rasapi32/tests/rasapi.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/rpcrt4/rpc_server.c wine-devel-2.4.0~ubuntu15.04.1/dlls/rpcrt4/rpc_server.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/rpcrt4/rpc_server.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/rpcrt4/rpc_server.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/rpcrt4/tests/rpc.c wine-devel-2.4.0~ubuntu15.04.1/dlls/rpcrt4/tests/rpc.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/rpcrt4/tests/rpc.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/rpcrt4/tests/rpc.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/rpcrt4/tests/server.c wine-devel-2.4.0~ubuntu15.04.1/dlls/rpcrt4/tests/server.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/rpcrt4/tests/server.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/rpcrt4/tests/server.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/schedsvc/schedsvc.c wine-devel-2.4.0~ubuntu15.04.1/dlls/schedsvc/schedsvc.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/schedsvc/schedsvc.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/schedsvc/schedsvc.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/schedsvc/schedsvc_private.h wine-devel-2.4.0~ubuntu15.04.1/dlls/schedsvc/schedsvc_private.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/schedsvc/schedsvc_private.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/schedsvc/schedsvc_private.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/schedsvc/svc_main.c wine-devel-2.4.0~ubuntu15.04.1/dlls/schedsvc/svc_main.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/schedsvc/svc_main.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/schedsvc/svc_main.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/schedsvc/tests/rpcapi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/schedsvc/tests/rpcapi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/schedsvc/tests/rpcapi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/schedsvc/tests/rpcapi.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/scrobj/scrobj.c wine-devel-2.4.0~ubuntu15.04.1/dlls/scrobj/scrobj.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/scrobj/scrobj.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/scrobj/scrobj.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/setupapi/setupapi.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/setupapi/setupapi.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/setupapi/setupapi.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/setupapi/setupapi.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/setupapi/stubs.c wine-devel-2.4.0~ubuntu15.04.1/dlls/setupapi/stubs.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/setupapi/stubs.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/setupapi/stubs.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/shell32/tests/shlfolder.c wine-devel-2.4.0~ubuntu15.04.1/dlls/shell32/tests/shlfolder.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/shell32/tests/shlfolder.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/shell32/tests/shlfolder.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/ucrtbase/ucrtbase.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/ucrtbase/ucrtbase.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/ucrtbase/ucrtbase.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/ucrtbase/ucrtbase.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/user32/tests/win.c wine-devel-2.4.0~ubuntu15.04.1/dlls/user32/tests/win.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/user32/tests/win.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/user32/tests/win.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/usp10/bidi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/bidi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/usp10/bidi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/bidi.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/usp10/breaking.c wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/breaking.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/usp10/breaking.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/breaking.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/usp10/indic.c wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/indic.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/usp10/indic.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/indic.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/usp10/opentype.c wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/opentype.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/usp10/opentype.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/opentype.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/usp10/shape.c wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/shape.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/usp10/shape.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/shape.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/usp10/tests/usp10.c wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/tests/usp10.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/usp10/tests/usp10.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/tests/usp10.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/usp10/usp10.c wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/usp10.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/usp10/usp10.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/usp10.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/usp10/usp10_internal.h wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/usp10_internal.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/usp10/usp10_internal.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/usp10/usp10_internal.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/vcomp/tests/vcomp.c wine-devel-2.4.0~ubuntu15.04.1/dlls/vcomp/tests/vcomp.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/vcomp/tests/vcomp.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/vcomp/tests/vcomp.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/version/tests/info.c wine-devel-2.4.0~ubuntu15.04.1/dlls/version/tests/info.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/version/tests/info.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/version/tests/info.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/webservices/channel.c wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/channel.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/webservices/channel.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/channel.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/webservices/msg.c wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/msg.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/webservices/msg.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/msg.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/webservices/proxy.c wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/proxy.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/webservices/proxy.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/proxy.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/webservices/reader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/reader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/webservices/reader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/reader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/webservices/tests/reader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/tests/reader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/webservices/tests/reader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/tests/reader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/webservices/writer.c wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/writer.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/webservices/writer.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/webservices/writer.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/arb_program_shader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/arb_program_shader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/arb_program_shader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/arb_program_shader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/ati_fragment_shader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/ati_fragment_shader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/ati_fragment_shader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/ati_fragment_shader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/context.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/context.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/context.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/context.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/cs.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/cs.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/cs.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/cs.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/device.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/device.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/device.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/device.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/directx.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/directx.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/directx.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/directx.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/glsl_shader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/glsl_shader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/glsl_shader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/glsl_shader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/shader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/shader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/shader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/shader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/shader_sm4.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/shader_sm4.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/shader_sm4.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/shader_sm4.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/state.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/state.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/state.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/state.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/surface.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/surface.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/surface.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/surface.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/texture.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/texture.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/texture.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/texture.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/utils.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/utils.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/utils.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/utils.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/wined3d_gl.h wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/wined3d_gl.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/wined3d_gl.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/wined3d_gl.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/wined3d_private.h wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/wined3d_private.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/wined3d_private.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/wined3d_private.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/wined3d.spec wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/wined3d.spec --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wined3d/wined3d.spec 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wined3d/wined3d.spec 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/winemac.drv/cocoa_window.h wine-devel-2.4.0~ubuntu15.04.1/dlls/winemac.drv/cocoa_window.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/winemac.drv/cocoa_window.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/winemac.drv/cocoa_window.h 2017-03-20 21:19:48.000000000 +0000 @@ -81,6 +81,8 @@ NSTimeInterval lastDockIconSnapshot; + BOOL allowKeyRepeats; + BOOL ignore_windowDeminiaturize; BOOL ignore_windowResize; BOOL fakingClose; diff -Nru wine-devel-2.3.0~ubuntu15.04.1/dlls/winemac.drv/cocoa_window.m wine-devel-2.4.0~ubuntu15.04.1/dlls/winemac.drv/cocoa_window.m --- wine-devel-2.3.0~ubuntu15.04.1/dlls/winemac.drv/cocoa_window.m 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/winemac.drv/cocoa_window.m 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wineps.drv/ps.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wineps.drv/ps.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wineps.drv/ps.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wineps.drv/ps.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wininet/ftp.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/ftp.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wininet/ftp.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/ftp.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wininet/http.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/http.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wininet/http.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/http.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wininet/internet.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/internet.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wininet/internet.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/internet.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wininet/internet.h wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/internet.h --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wininet/internet.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/internet.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wininet/netconnection.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/netconnection.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wininet/netconnection.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/netconnection.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wininet/tests/http.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/tests/http.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wininet/tests/http.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/tests/http.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wininet/tests/internet.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/tests/internet.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wininet/tests/internet.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wininet/tests/internet.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/winmm/mci.c wine-devel-2.4.0~ubuntu15.04.1/dlls/winmm/mci.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/winmm/mci.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/winmm/mci.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/wlanapi/tests/wlanapi.c wine-devel-2.4.0~ubuntu15.04.1/dlls/wlanapi/tests/wlanapi.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/wlanapi/tests/wlanapi.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/wlanapi/tests/wlanapi.c 2017-03-20 21:19:48.000000000 +0000 @@ -152,6 +152,7 @@ { skip("No wireless interfaces\n"); WlanCloseHandle(handle, NULL); + WlanFreeMemory(list); return; } diff -Nru wine-devel-2.3.0~ubuntu15.04.1/dlls/xmllite/reader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/xmllite/reader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/xmllite/reader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/xmllite/reader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/xmllite/tests/reader.c wine-devel-2.4.0~ubuntu15.04.1/dlls/xmllite/tests/reader.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/xmllite/tests/reader.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/xmllite/tests/reader.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/dlls/xmllite/tests/writer.c wine-devel-2.4.0~ubuntu15.04.1/dlls/xmllite/tests/writer.c --- wine-devel-2.3.0~ubuntu15.04.1/dlls/xmllite/tests/writer.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/dlls/xmllite/tests/writer.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/documentation/README.de wine-devel-2.4.0~ubuntu15.04.1/documentation/README.de --- wine-devel-2.3.0~ubuntu15.04.1/documentation/README.de 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/documentation/README.de 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/ddk/wdm.h wine-devel-2.4.0~ubuntu15.04.1/include/ddk/wdm.h --- wine-devel-2.3.0~ubuntu15.04.1/include/ddk/wdm.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/ddk/wdm.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/iptypes.h wine-devel-2.4.0~ubuntu15.04.1/include/iptypes.h --- wine-devel-2.3.0~ubuntu15.04.1/include/iptypes.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/iptypes.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/Makefile.in wine-devel-2.4.0~ubuntu15.04.1/include/Makefile.in --- wine-devel-2.3.0~ubuntu15.04.1/include/Makefile.in 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/Makefile.in 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/msstkppg.h wine-devel-2.4.0~ubuntu15.04.1/include/msstkppg.h --- wine-devel-2.3.0~ubuntu15.04.1/include/msstkppg.h 1970-01-01 00:00:00.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/msstkppg.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/netioapi.h wine-devel-2.4.0~ubuntu15.04.1/include/netioapi.h --- wine-devel-2.3.0~ubuntu15.04.1/include/netioapi.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/netioapi.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/nldef.h wine-devel-2.4.0~ubuntu15.04.1/include/nldef.h --- wine-devel-2.3.0~ubuntu15.04.1/include/nldef.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/nldef.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/winbase.h wine-devel-2.4.0~ubuntu15.04.1/include/winbase.h --- wine-devel-2.3.0~ubuntu15.04.1/include/winbase.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/winbase.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/wine/test.h wine-devel-2.4.0~ubuntu15.04.1/include/wine/test.h --- wine-devel-2.3.0~ubuntu15.04.1/include/wine/test.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/wine/test.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/wine/wine_common_ver.rc wine-devel-2.4.0~ubuntu15.04.1/include/wine/wine_common_ver.rc --- wine-devel-2.3.0~ubuntu15.04.1/include/wine/wine_common_ver.rc 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/wine/wine_common_ver.rc 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/wine/wined3d.h wine-devel-2.4.0~ubuntu15.04.1/include/wine/wined3d.h --- wine-devel-2.3.0~ubuntu15.04.1/include/wine/wined3d.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/wine/wined3d.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/wininet.h wine-devel-2.4.0~ubuntu15.04.1/include/wininet.h --- wine-devel-2.3.0~ubuntu15.04.1/include/wininet.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/wininet.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/include/ws2def.h wine-devel-2.4.0~ubuntu15.04.1/include/ws2def.h --- wine-devel-2.3.0~ubuntu15.04.1/include/ws2def.h 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/include/ws2def.h 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/po/de.po wine-devel-2.4.0~ubuntu15.04.1/po/de.po --- wine-devel-2.3.0~ubuntu15.04.1/po/de.po 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/po/de.po 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/programs/iexplore/main.c wine-devel-2.4.0~ubuntu15.04.1/programs/iexplore/main.c --- wine-devel-2.3.0~ubuntu15.04.1/programs/iexplore/main.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/programs/iexplore/main.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/programs/iexplore/Makefile.in wine-devel-2.4.0~ubuntu15.04.1/programs/iexplore/Makefile.in --- wine-devel-2.3.0~ubuntu15.04.1/programs/iexplore/Makefile.in 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/programs/iexplore/Makefile.in 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/programs/regedit/tests/regedit.c wine-devel-2.4.0~ubuntu15.04.1/programs/regedit/tests/regedit.c --- wine-devel-2.3.0~ubuntu15.04.1/programs/regedit/tests/regedit.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/programs/regedit/tests/regedit.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/server/object.c wine-devel-2.4.0~ubuntu15.04.1/server/object.c --- wine-devel-2.3.0~ubuntu15.04.1/server/object.c 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/server/object.c 2017-03-20 21:19:48.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-devel-2.3.0~ubuntu15.04.1/tools/make_specfiles wine-devel-2.4.0~ubuntu15.04.1/tools/make_specfiles --- wine-devel-2.3.0~ubuntu15.04.1/tools/make_specfiles 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/tools/make_specfiles 2017-03-20 21:19:48.000000000 +0000 @@ -338,6 +338,10 @@ "bcrypt", "ncrypt", ], + [ + "ntoskrnl.exe", + "hal", + ], ); my $update_flags = 0; diff -Nru wine-devel-2.3.0~ubuntu15.04.1/VERSION wine-devel-2.4.0~ubuntu15.04.1/VERSION --- wine-devel-2.3.0~ubuntu15.04.1/VERSION 2017-03-06 20:52:59.000000000 +0000 +++ wine-devel-2.4.0~ubuntu15.04.1/VERSION 2017-03-20 21:19:48.000000000 +0000 @@ -1 +1 @@ -Wine version 2.3 +Wine version 2.4