From 85c30fd466e54edcf7c06571e294ebde656d17d6 Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Sat, 20 Jun 2009 22:58:58 +0200 Subject: [PATCH] push 390edd058cbebc9f7cb21f639a52f5acd36a8bf3 --- ANNOUNCE | 1219 +++++++++--------- VERSION | 2 +- aclocal.m4 | 2 +- configure | 243 +++- configure.ac | 59 +- dlls/advapi32/lsa.c | 2 + dlls/advapi32/security.c | 16 +- dlls/advapi32/tests/lsa.c | 45 +- dlls/advapi32/tests/security.c | 9 +- dlls/appwiz.cpl/Ja.rc | 6 +- dlls/comctl32/comboex.c | 2 + dlls/comctl32/listview.c | 140 ++- dlls/comctl32/tests/listview.c | 288 ++++- dlls/comctl32/tests/rebar.c | 16 +- dlls/comdlg32/filedlg.c | 6 +- dlls/comdlg32/tests/filedlg.c | 134 +- dlls/comdlg32/tests/rsrc.rc | 16 + dlls/crypt32/context.c | 4 +- dlls/crypt32/crypt32_private.h | 2 +- dlls/crypt32/encode.c | 6 +- dlls/crypt32/msg.c | 6 +- dlls/crypt32/object.c | 6 +- dlls/crypt32/str.c | 2 +- dlls/crypt32/tests/encode.c | 3 +- dlls/cryptdlg/cryptdlg_De.rc | 2 +- dlls/cryptui/cryptui_De.rc | 2 +- dlls/d3d8/cubetexture.c | 23 +- dlls/d3d8/d3d8_private.h | 18 +- dlls/d3d8/device.c | 123 +- dlls/d3d8/surface.c | 23 +- dlls/d3d8/tests/device.c | 12 + dlls/d3d8/tests/visual.c | 6 +- dlls/d3d8/texture.c | 23 +- dlls/d3d9/cubetexture.c | 27 +- dlls/d3d9/device.c | 25 +- dlls/d3d9/surface.c | 27 +- dlls/d3d9/tests/visual.c | 53 +- dlls/d3d9/texture.c | 30 +- dlls/d3dx9_36/d3dx9_36.spec | 2 +- dlls/d3dx9_36/mesh.c | 52 + dlls/d3dx9_36/tests/Makefile.in | 1 + dlls/d3dx9_36/tests/mesh.c | 97 ++ dlls/dbghelp/dbghelp_private.h | 8 +- dlls/dbghelp/storage.c | 20 +- dlls/ddraw/ddraw.c | 43 +- dlls/ddraw/device.c | 13 +- dlls/ddraw/executebuffer.c | 8 +- dlls/dmime/Makefile.in | 2 - dlls/dmime/dmime_private.h | 26 - dlls/dmime/patterntrack.c | 106 -- dlls/dmime/tool.c | 134 -- dlls/gdi32/driver.c | 11 + dlls/gdi32/gdi32.spec | 1 + dlls/gdi32/tests/clipping.c | 14 +- dlls/gdi32/tests/metafile.c | 72 +- dlls/gdiplus/graphics.c | 2 +- dlls/gphoto2.ds/gphoto2_i.h | 3 + dlls/hal/hal.c | 8 +- dlls/hhctrl.ocx/Lt.rc | 63 + dlls/hhctrl.ocx/hhctrl.rc | 1 + dlls/jscript/date.c | 341 +++++- dlls/jscript/tests/api.js | 32 +- dlls/kernel32/console.c | 11 +- dlls/kernel32/heap.c | 2 +- dlls/kernel32/ne_module.c | 16 +- dlls/kernel32/process.c | 4 +- dlls/kernel32/selector.c | 18 +- dlls/kernel32/sync.c | 10 +- dlls/kernel32/thread.c | 8 +- dlls/kernel32/thunk.c | 2 +- dlls/mapi32/tests/imalloc.c | 6 + dlls/mapi32/tests/prop.c | 46 +- dlls/mapi32/tests/util.c | 14 +- dlls/mlang/mlang.c | 12 +- dlls/mlang/tests/mlang.c | 58 +- dlls/msctf/compartmentmgr.c | 184 ++- dlls/msctf/context.c | 19 +- dlls/msctf/documentmgr.c | 4 +- dlls/msctf/msctf.c | 1 + dlls/msctf/msctf_internal.h | 5 +- dlls/msctf/tests/inputprocessor.c | 13 +- dlls/msctf/threadmgr.c | 25 +- dlls/mshtml/tests/dom.c | 2 +- dlls/mshtml/tests/script.c | 2 +- dlls/msi/tests/automation.c | 49 +- dlls/msi/tests/source.c | 2 +- dlls/msvcirt/msvcirt.c | 10 +- dlls/msvcrt/cpp.c | 72 +- dlls/msvcrtd/tests/debug.c | 2 +- dlls/ntdll/ntdll_misc.h | 2 + dlls/ntdll/relay.c | 58 +- dlls/ntdll/resource.c | 2 +- dlls/ntdll/rtl.c | 4 +- dlls/ntdll/sec.c | 242 ++-- dlls/ntdll/signal_i386.c | 44 +- dlls/ntdll/signal_powerpc.c | 25 + dlls/ntdll/signal_sparc.c | 25 + dlls/ntdll/signal_x86_64.c | 1369 +++++++++++++++++---- dlls/ntdll/thread.c | 133 +- dlls/ntoskrnl.exe/ntoskrnl.c | 142 ++- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 24 +- dlls/oleacc/oleacc.rc | 1 + dlls/oleacc/oleacc_Lt.rc | 95 ++ dlls/oleaut32/olepicture.c | 3 + dlls/oleaut32/tests/tmarshal.c | 53 +- dlls/oleaut32/tests/tmarshal.idl | 6 + dlls/oleaut32/tests/tmarshal_dispids.h | 1 + dlls/riched20/txthost.c | 190 +-- dlls/riched20/txtsrv.c | 44 +- dlls/riched32/tests/editor.c | 12 +- dlls/rpcrt4/cproxy.c | 2 +- dlls/rpcrt4/ndr_marshall.c | 16 +- dlls/rpcrt4/tests/ndr_marshall.c | 45 +- dlls/rpcrt4/tests/server.c | 16 +- dlls/setupapi/misc.c | 62 +- dlls/shdocvw/taskbarlist.c | 17 +- dlls/shell32/shell32.spec | 2 +- dlls/shell32/shellord.c | 74 +- dlls/shell32/tests/appbar.c | 17 +- dlls/shell32/tests/shlfolder.c | 60 +- dlls/urlmon/tests/Makefile.in | 1 + dlls/urlmon/tests/misc.c | 271 ---- dlls/urlmon/tests/protocol.c | 18 +- dlls/urlmon/tests/sec_mgr.c | 335 +++++ dlls/user32/button.c | 1 + dlls/user32/tests/msg.c | 113 +- dlls/wined3d/arb_program_shader.c | 1772 +++++++++++++++++++++++---- dlls/wined3d/baseshader.c | 6 + dlls/wined3d/basetexture.c | 22 +- dlls/wined3d/device.c | 189 +-- dlls/wined3d/directx.c | 49 +- dlls/wined3d/drawprim.c | 29 +- dlls/wined3d/glsl_shader.c | 3 +- dlls/wined3d/stateblock.c | 22 +- dlls/wined3d/surface.c | 429 +++++-- dlls/wined3d/surface_base.c | 38 +- dlls/wined3d/surface_gdi.c | 50 +- dlls/wined3d/utils.c | 17 +- dlls/wined3d/wined3d_gl.h | 13 +- dlls/wined3d/wined3d_private.h | 50 +- dlls/winedos/dosexe.h | 2 - dlls/winedos/int21.c | 2 +- dlls/winedos/int31.c | 6 - dlls/winedos/timer.c | 21 - dlls/winedos/vga.c | 65 +- dlls/winedos/vga.h | 1 - dlls/wineesd.drv/audio.c | 25 +- dlls/winex11.drv/opengl.c | 41 +- dlls/winex11.drv/xdnd.c | 6 +- dlls/wininet/http.c | 72 +- dlls/wininet/rsrc.rc | 1 + dlls/wininet/tests/http.c | 27 +- dlls/wininet/urlcache.c | 6 +- dlls/wininet/wininet_Lt.rc | 49 + dlls/wintrust/softpub.c | 17 +- dlls/wintrust/wintrust_main.c | 3 +- dlls/wldap32/tests/parse.c | 9 +- documentation/README.de | 30 +- documentation/README.fr | 421 +++---- include/Makefile.in | 1 + include/commctrl.h | 2 + include/config.h.in | 16 +- include/d3dx9mesh.h | 1 + include/ddk/wdm.h | 6 + dlls/oleacc/oleacc.rc => include/ddrawgdi.h | 27 +- include/shlobj.h | 1 + include/wine/exception.h | 40 +- include/wine/wined3d.idl | 18 +- include/wininet.h | 6 + libs/wine/port.c | 57 +- programs/cmd/batch.c | 7 +- programs/cmd/builtins.c | 2 +- programs/cmd/wcmd.h | 1 + programs/cmd/wcmdmain.c | 84 +- programs/regedit/regproc.c | 14 +- programs/winecfg/Es.rc | 20 +- programs/winemenubuilder/winemenubuilder.c | 144 ++- server/ptrace.c | 93 +- server/thread.c | 12 +- tools/widl/typegen.c | 25 +- tools/widl/write_msft.c | 10 +- tools/winapi/c_parser.pm | 18 +- tools/wine.inf.in | 3 +- tools/winebuild/import.c | 41 +- tools/winebuild/main.c | 80 +- tools/winebuild/relay.c | 77 +- tools/winebuild/spec32.c | 16 +- tools/winebuild/winebuild.man.in | 4 + tools/winegcc/winegcc.c | 9 + 189 files changed, 8268 insertions(+), 3870 deletions(-) rewrite ANNOUNCE (96%) create mode 100644 dlls/d3dx9_36/tests/mesh.c delete mode 100644 dlls/dmime/patterntrack.c delete mode 100644 dlls/dmime/tool.c create mode 100644 dlls/hhctrl.ocx/Lt.rc create mode 100644 dlls/oleacc/oleacc_Lt.rc create mode 100644 dlls/urlmon/tests/sec_mgr.c create mode 100644 dlls/wininet/wininet_Lt.rc rewrite documentation/README.fr (75%) copy dlls/oleacc/oleacc.rc => include/ddrawgdi.h (69%) diff --git a/ANNOUNCE b/ANNOUNCE dissimilarity index 96% index 63f3da1391c..15c808e95be 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,659 +1,560 @@ -The Wine development release 1.1.23 is now available. - -What's new in this release (see below for details): - - Support for registering MIME types with the Linux desktop. - - FBO mode is now the default for Direct3D. - - Support for COM proxy delegation. - - Improved support for the Mingw cross-compile. - - Proper fullscreen mode for the virtual desktop. - - Various bug fixes. - -The source is available from the following locations: - - http://ibiblio.org/pub/linux/system/emulators/wine/wine-1.1.23.tar.bz2 - http://prdownloads.sourceforge.net/wine/wine-1.1.23.tar.bz2 - -Binary packages for various distributions will be available from: - - http://www.winehq.org/site/download - -You will find documentation on http://www.winehq.org/site/documentation - -You can also get the current source directly from the git -repository. Check http://www.winehq.org/site/git for details. - -Wine is available thanks to the work of many people. See the file -AUTHORS in the distribution for the complete list. - ----------------------------------------------------------------- - -Bugs fixed in 1.1.23: - - 3235 Redraw problem: Spurious blue selection when changing order of listview - 3800 Rotated Text became invisible in Corel Draw 9 - 4372 listview: cannot drag several items - 5131 FlashFXP hangs - 8126 'Rayman 2 - The Great Escape' doesn't start - 8241 Unable to open a new document in graphpad prism5 - 8748 Memory leak with Steam and Gecko - 10656 EQ2 Fullscreen Crash - 10862 Hitman bloody money crashes by entering the main menu - 11225 Unimplemented Functions: GdipLoadImageFromFile, GdipLoadImageFromFileICM and GdipMeasureCharacterRanges - 11251 Adobe Photoshop CS2 update process funky - 11281 CJK input: cannot type in legacy applications - 11578 Windows Messenger 5.1 doesn't run (infinite loop) - 12033 Need for Speed III crash on startup - 12312 EVE Patch fails to download as BITS_IBackgroundCopyJob_SetPriority is not implemented - 12484 Photoshop CS2: freezes when trying to save for web - 12554 Unsupported format: WINED3DFMT_R16F - 12673 Medieval 2: Total War demo graphics are all blue and lack detail - 12806 Crysis: segmentation fault at startup - 12844 Very dark graphics in Mafia, Guild Wars, Sim City 4 on ATI cards - 12873 Microsoft 3D Movie Maker demo installer fails - 13107 Belote crashes - 13758 Adobe Photoshop 7: sliders not shown - 13768 SpellForce starts very slow and the land is black in the beginning - 13850 InstallShield (Assasin's Creed) window ordering issue - 14247 One click works like 2x click - 14248 CTRL + Tab in Firefox 3 is intepreted as CTRL + B (dogfood) - 14375 Mouse cursor flickers in Myst IV - Revelation - 14423 GTA III (Grand Theft Auto 3) doesn't run in Wine 1.1.1 (due to "unhandled exception") - 14719 Assassin's Creed breaks after intro videos - 14778 Unusual characters in player names crashes Team Fortress 2 - 14985 virtual desktop window should be fullscreen when it's as big as the screen - 15249 MINITAB 15 standard demo installer fails during installation - 15401 Cannot copy/paste inside powerpoint 2003 - 15463 Heroes of Might and Magic install fails if initial music still playing - 15777 "Need For Speed 4 - High Stakes" does not start - 15983 WoW Wotlk installer (retail dvd eu) crash - 16027 MSN 5 crashes on startup - 16116 PureEdge Viewer (ICS Viewer) 6.0 unhandled page fault - 16132 Uninstall of ICS Viewer 6.0 fails with "An error occured while checking for running applications." - 16139 Dragon NaturallySpeaking 10 crashes with X-window error - 16170 Call of Duty 5 and MotoGP08 crash - 16173 Cannot launch EVE Online - 16178 alt.binz: memory leak. Regression since 1.1.7. - 16220 World of Warcraft does not work in D3D mode - 16416 IL2: alsa-sound stutters much - 17102 Crashday: no textures anymore in 1.1.13 - 17132 No music plays in game Iji - 17386 Command and Conquer 3: Tiberium Wars - fails to start - 17404 MSN Messenger 7.0 does not sign-in - 17536 DirectX 9 launcher causes Atari Scrabble Online installation to fail - 17563 Crash when using TTM_GETTEXT + LPSTR_CALLBACK - 17668 Eve online autoupdater won't update - 17837 eCleaner: rich-edit related crash - 17880 Mirror's Edge: Crashes after logo animations - 17976 Encompass installer crashes on startup - 18063 CombineUrl adding incorrect slash at end of url. - 18082 CyberBilling XP - listview is empty - 18162 dlls/comctl32/tests/treeview.c: value computed is not used - 18520 error loading I.E6 within wine - 18529 Two directX bugs in XNA-based games (Infiniminer/Paddles) - 18558 d3d9/visual: tests fail with fbo or +heap enabled - 18568 MacOS X: png.h/libpng is not detected - 18601 Google Sketchup 7 crashes early in wine's imm.dll - 18628 Dwarf section in Ubuntu 9.04 libc debug package fails to parse. - 18637 Nokia Map Loader 2.0 (.NET 3.0 app) needs DisableProcessWindowsGhosting stub - 18639 .NET 3.0 WPF needs NtSecureConnectPort stub - 18676 Infiminer (xna-based game) crashes, apparently in shader_cleanup - 18690 CTRL + Shift + Tab in Firefox 3 does nothing (dogfood) - 18696 Eve Online rendering problem - 18717 .NET 3.x needs ntdll.dll.RtlEnumerateGenericTableWithoutSplaying (WPF + MILCore driver) - 18729 Slingplayer 2.0 setup exits silently in Vista mode - 18758 LsaGetLogonSessionData unconditionally returns STATUS_SUCCESS - 18760 Recent version of ProjectTorque crashes wine calling gdiplus.dll.GdipDrawImagePointRectI - ----------------------------------------------------------------- - -Changes since 1.1.22: - -Alexandre Julliard (71): - msvcrt: Add explicit 32- and 64-bit versions of the time functions. - msvcrt: Add explicit 32- and 64-bit versions of the utime functions. - msvcrt: Fix the stat and finddata structures for 64-bit. - msvcrt/tests: Make all msvcrt function pointers cdecl. - include/msvcrt: Add explicit msvcrt_long types to replace long for 64-bit compatibility. - msvcrt: Replace long by MSVCRT_long. - wineboot: Compain loudly if we can't find wine.inf. - oleaut32/tests: Fix a test broken on XP 64. - kernel32: Remove the file parameter check again in LoadLibraryExW since some broken apps pass garbage here. - kernel32/tests: Run file tests in the temp directory if we don't have access to the drive root. - rpcrt4: Internal functions don't need to be WINAPI. - ntdll: Try any address in map_image no matter what the failure was for a fixed address. - include: Fix the packing of the MIDL_STUB_MESSAGE structure on 64-bit. - rpcrt4/tests: Fix a number of 64-bit issues in the ndr_marshall test. - rpcrt4: Fix the PSFactoryBuffer proxy refcounting, with tests. - rpcrt4/tests: Comment out a couple of tests that crash on older Windows versions. - rpcrt4/tests: Enable some tests that no longer crash Wine. - rpcrt4: Implement NdrPointerMemorySize and enable the corresponding tests. - rpcrt4: Fix compiler warnings on 64-bit. - opengl32: Generate the correct trace arguments for UINT64 types. - winedump: Fix a printf format warning on 64-bit. - comctl32/tests: Replace a listview macro by an explicit SendMessage. - ole32: Fix some pointer conversion warnings on 64-bit. - user32/tests: Fix some pointer conversion warnings on 64-bit. - gphoto2.ds: Fix a pointer conversion warning on 64-bit. - sane.ds: Fix a pointer conversion warning on 64-bit. - msacm32: Fix a pointer conversion warning on 64-bit. - msvfw32: Fix a pointer conversion warning on 64-bit. - rpcrt4/tests: Mark some stub message tests broken for older Windows versions. - rpcrt4/tests: Remove tests for v1 memory list, the layout is wrong and we don't care about it anyway. - rpcrt4/tests: Disable some tests that crash on Windows. - wininet: Add a critical section to protect the read-ahead buffer. - dbghelp: Try to avoid crashing on unrecognized attributes. - tools: Upgrade the config.guess/config.sub scripts. - winegcc: Don't pass the as/ld/nm tool names to winebuild. - winegcc: Add support for the --sysroot option to allow out-of-tree cross-compiling. - winegcc: Add support for building PE executables using Mingw. - configure: Add checks for fnmatch support. - d3d9/tests: Skip CheckDeviceMultiSampleType test if not available. - rpcrt4/tests: Fix a few more broken tests on NT4. - user32/tests: Remove tests for internal DDE handle format, we don't care how the handles are implemented. - user32/tests: Make some sysparams registry key optional, and fix some other failures on old Windows platforms. - rpcrt4: Change the allocation of delegated stub methods so that we never need to free them. - rpcrt4: Allocate the delegated stubs vtbl only once it is really needed. - rpcrt4: Return the stack size from the ObjectStubless function so that the thunks are independent from the number of arguments. - rpcrt4: Use the same allocation technique as delegated stubs for the stubless thunks. - rpcrt4: Retrieve the stubless information for the thunks directly from the virtual table pointer. - riched32: Fix the extra window bytes count for 64-bit. - user32/tests: Fix the listbox delete test on NT4. - user32/tests: Only check the foreground window when it belongs to the current thread. - winebuild: Add a --resources mode that compiles multiple resource files into a single object. - winebuild: Add detection of duplicate resources. - winegcc: Transparently compile resource files for the Windows build. - makefiles: Remove special handling of .res.o files now that winegcc takes care of this. - server: Reset events on the message queue fd to avoid busy looping when the thread is suspended. - server: Hide a window before destroying it if it was still visible. - user32: Use a simplified sequence to destroy windows at thread exit, since we don't want to send messages. - user32/tests: Add tests for message sequence of window destruction at thread exit. - makefiles: Use winegcc to build the crosstests too. - makefiles: Add resource files to the standard object files list. - clock: Build resource files separately instead of including them all from a global file. - rpcrt4: Split the vtbl initialization in NdrDllGetClassObject to a separate function. - rpcrt4: Add support for proxy delegation. - rpcrt4/tests: Add tests for the contents of virtual table for delegated proxies. - rpcrt4: Add checks for the number of methods being larger than what we support. - user32/tests: Add more synchronization in the exit thread test to avoid races. - user32/tests: More systematically ignore the messages we don't care about. - winegcc: Link against winecrt0 for the Mingw build too. - winegcc: Create a stub main to work around the lack of Unicode support in Mingw. - comctl32/tests: Avoid size_t in traces. - winedbg: Add wrappers for Read/WriteProcessMemory to fix the mingw build. - -Andrew Eikum (11): - gdiplus: Stubs for GdipAddPathString and GdipAddPathStringI. - gdiplus: Stubs for GdipBeginContainer and GdipBeginContainerI. - gdiplus: Stub for GdipCloneBitmapArea. - gdiplus: Stub for GdipComment. - gdiplus: Stubs for GdipCreateMetafileFromFile, GdipCreateMetafileFromStream. - gdiplus: Stub for GdipDeleteEffect. - gdiplus: Stubs for GdipDrawImagePointRect and GdipDrawImagePointRectI. - gdiplus: Stub for GdipEmfToWmfBits. - gdiplus: Stubs for GdipDrawImagePoints and GdipDrawImagePointsI. - gdiplus: Stub for GdipBitmapApplyEffect. - gdiplus: Stub for GdipBitmapCreateApplyEffect. - -Andrew Nguyen (1): - rundll32: Load the 16-bit kernel32 exports by ordinal. - -Andrew Talbot (5): - avifil32: Constify a variable. - cabinet: Constify a variable. - comctl32: Constify some variables. - comctl32: Various const qualifier fixes. - comctl32: Constify some variables. - -André Hentschel (7): - comctl32: Add ListView_SetCheckState and ListView_GetCheckState. - comdlg32: Improve the German Find and FindReplace dialogs. - winex11: Fix Ctrl+Tab translation. - winedbg: Add German translation. - appwiz.cpl: Add German translation. - winex11: Fix Ctrl+Shift+Tab translation. - winemaker: Port vcproject parser from XML-Simple to libXML. - -Aric Stewart (9): - msctf: Implement ITextStoreACPSink::OnStatusChange. - msctf: Implement ITfRange::Collapse. - msctf: Framework for ITfInsertAtSelection in ITfContext. - advapi: Correct buffer length in LookupAccountNameW. - msctf: Define compartment guids. - shlwapi: Simplify UrlCombine case 2 with tests. - msctf: Implement ITfInsertAtSelection::InsertTextAtSelection. - msctf: Implement ITfContext::SetSelection. - msctf: Define ITfCompartmentMgr and ITfCompartment. - -Aurimas Fišeras (3): - kernel32/nls: Add missing translations for lth.nls. - winedbg: Add Lithuanian translation. - kernel32/nls: Switch to UTF-8 encoding for lth.nls. - -Austin English (1): - user32: Downgrade a FIXME to a WARN. - -Austin Lund (2): - riched20: If DataObjectImpl_EnumFormatEtc returns E_NOTIMPL then ensure that returned pointers are nulled. - riched20/test: Added a test for TxDraw. - -Ben Klein (1): - mountmgr.sys: Add tracking of fixed harddisk devices. - -Chris Robinson (3): - wined3d: Prevent erroneous FIXMEs on newer cards. - wined3d: Decrement fbo_entry_count when one is removed from the list. - quartz: Release enumpins when done with it. - -Damjan Jovanovic (5): - winemenubuilder: Add MIME types to freedesktop. - winemenubuilder: Only add mime types that aren't already in freedesktop. - winemenubuilder: Ignore wine.desktop managed file types. - winemenubuilder: Associate file open applications with freedesktop. - winemenubuilder: Track, update and clean up file open associations. - -Daniel Santos (1): - make_requests: Correct comment in header (minor patch). - -Detlef Riekenberg (18): - mlang/tests: Use a table for testing GetLcidFromRfc1766. - mlang/tests: Initial tests for Rfc1766ToLcid. - mlang/tests: Return correct result in Rfc1766ToLcidA on failure. - mlang/tests: Rfc1766ToLcid must not touch the LCID output on failure. - mlang: Use a case independent compare for the RFC1766 name. - mlang/tests: Make the tests more silent. - kernel32/nls: Translation-fix for deu.nls. - kernel32/nls: Add missing translations for des.nls. - kernel32/nls: Add missing translations for dea.nls. - kernel32/nls: Add missing translations for del.nls. - kernel32/nls: Add missing translations for dec.nls. - mlang: Return HRESULT from lcid_to_rfc1766 helper. - mlang: Suppress country data in rfc1766, with tests. - mlang: Check output pointer for NULL. - mlang/tests: Add tests for LcidToRfc1766. - mlang: Avoid unneeded HeapReAlloc. - kernel32/tests: Add tests for GetLocaleInfo with SUBLANG_NEUTRAL. - kernel32/tests: Fix failures on localized Windows versions. - -Dmitry Timoshkov (1): - winex11.drv: Avoid a crash if not in a desktop mode. - -Eric Pouech (11): - winedbg: Pass NULL for some optionals parameters to MinidumpReadDumpStream. - winhlp32: Properly handle a syntax error inside a macro. - winhlp32: NoShow macro has NS as shortcut. - winhlp32: Force the handling of a current help window while processing a macro. - winhlp32: Make use of the hlpfile for the running macro to handle correctly some macro implementations. - winhlp32: Use current file when no file is specified in JumpHash. - winhlp32: Window name lookup is supposed to be insensitive. - winhlp32: Remove the lpszName field from the window structure, as it's given by the window info. - winhlp32: Now manage windows with refcounts. - winhlp32: Correctly set the window's title when no window information is present. - winhlp32: Fix typo in color init. - -Eric van Beurden (2): - wininet: Check for bad allocation in HeapReAlloc. - wininet: Rearrange invalid header checks. - -Francois Gouget (18): - winapi_fixup: There is not much point for this tool so remove it. - winapi_cleanup: There is not much point for this tool so remove it. - dplayx: DPLAYX_SetLocalSession() and DPLAYX_CopyIntoSessionDesc2A() are unused so remove them. - rsaenh: Make the mpi functions static, remove mp_signed_bin_size() as it is unused. - oleaut32: Tweak a comment to make it more explicit. - msi/tests: Tweak the get_user_sid() functions to simplify their use. - riched20: Make ME_GetCursorCoordinates() static and remove ME_MustBeWrapped() as it is unused. - riched20: RTF{G,S}et{In,Out}putName() are unused so remove them as well as the corresponding _RTF_Info fields. - riched20: RTFPeekToken(), RTFExpandStyle() and RTFHexToChar() are unused so remove them. - riched20: Make some functions static. - winex11.drv: Replace an strdup() with HeapAlloc() in the OpenGL code. - winex11: Also define X11DRV_OpenGL_Cleanup() when OpenGL is not supported. - ntdll/tests: Fix the trailing '\n' of a skip() call. - winedbg & appwiz.cpl: Use SUBLANG_NEUTRAL for German. - winapi_extract: --spec-files has been broken for a long time and does not seem to be useful so remove it. - winapi_extract: The old C parser is not needed anymore so remove it. - rpcrt4/tests: Make dummy_Release() static. - ole32/tests: Make test_readonly() static. - -Frans Kool (1): - cryptui: Added Dutch translations. - -Ge van Geldorp (1): - winetest: Use wininet if available. - -Gerald Pfeifer (7): - dsound: Clarify statement in DSOUND_capture_callback. - user32/tests: Fix MODIFIED macro. - winmm/tests: Fix test in wave_out_test_deviceOut(). - gphoto2.ds: Only provide GPHOTO2_StrDup() when we have HAVE_GPHOTO2. - user32/tests: Remove unused SAME macro. - msxml3: Tweak two assertions. - d3d9: Use WINED3DPOOL_DEFAULT instead of D3DPOOL_DEFAULT as appropriate. - -Guy Albertelli (2): - kernel32: Fix GetVolumeNameForVolumeMountPointW to match Mountmgr. - kernel32/tests: Add tests for CreateFile errors and opening volumes. - -Hans Leidekker (13): - kernel32: Improve the GetSystemPowerStatus stub. - include: Sync definition of CERT_CHAIN_PARA and SCHANNEL_CRED with the latest SDK. - msi: Constify some parameters. - msi: Don't duplicate the table name in CREATE_CreateView. - msi: Consistently use the parser allocator when parsing a query. - msi: Fix some memory leaks. - msi: The assembly file version field is optional. - crypt32: Initialize salt correctly. - msi: Don't trace an out parameter. - msi: Initialize some variables. - msi: Add tests for importing a _SummaryInformation table. - msi: Add more tests for MsiGetSourcePath. - msi/tests: Ignore case when comparing file names. - -Henri Verbeet (50): - secur32: Initialize cbBuffer to 0 for NULL buffers. - wined3d: Remove some unnecessary forward declarations. - wined3d: Remove some apparently leftover debug code. - wined3d: Fix debug_d3dusage() to handle combinations of flags. - wined3d: Fix debug_d3dusagequery() to handle combinations of flags. - wined3d: Pass a proper format desc to resource_init() in IWineD3DDeviceImpl_CreateBuffer(). - wined3d: Split the info log into separate lines. - wined3d: Add the output signature to IWineD3DDevice_CreateVertexShader(). - d3d10core: Implement ID3D10Device::CreateVertexShader(). - wined3d: Use SM3 shader limits for SM4. - wined3d: Make "packed_input" a bitmap. - wined3d: Use the "input_registers" bitmap for vertex shader attributes as well. - wined3d: Make "packed_output" a bitmap. - wined3d: Use a separate structure for vertex shader attributes. - wined3d: Use strings for shader input/output semantics. - wined3d: Use the output signature to setup SM4 vertex shader output semantics. - wined3d: Match the d3d10 name for WINED3DDECLUSAGE_POSITION. - d3d10core: Implement ID3D10Device::VSSetShader(). - d3d10core: Don't complain as much about setting a NULL geometry shader. - wined3d: Remove the "declaration" parameter to IWineD3DDeviceImpl_CreateVertexShader(). - wined3d: Add missing ActivateContext calls to shader_destroy() implementations. - wined3d: Remove ResourceReleased() from the public device interface. - wined3d: Add device resources from resource_init(). - d3d9: Having a NULL rendertarget isn't a failure. - wined3d: Use the proper OUT swizzle in handle_ps3_input(). - wined3d: Partially revert 7433eb76b5f05ae54702fe9e57ba315407ed651b. - wined3d: Call resource_init() from basetexture_init(). - wined3d: Create a texture_cleanup() function. - wined3d: Introduce texture_init() to handle most of the 2D texture initialization. - wined3d: Introduce cubetexture_cleanup(). - wined3d: Introduce cubetexture_init() to handle most of the cube texture initialization. - wined3d: Introduce volumetexture_cleanup(). - wined3d: Introduce volumetexture_init() to handle most of the volume texture initialization. - include: Add a generic red-black tree. - wined3d: Replace the wined3d hash table with the generic red-black tree. - wined3d: Free priv->stack in shader_glsl_free(). - wined3d: Remove entries without an internal format from the GL formats template. - wined3d: Remove WINED3DFMT_R16G16B16A16_SNORM from the GL formats template. - wined3d: Check FBO compatibility after the fixups are applied. - wined3d: Add a proper enum value for "no extension". - wined3d: Check the result from wine_rb_get() before using it in WINE_RB_ENTRY_VALUE. - wined3d: Don't use the vertex/pixel shader when we're not supposed to. - wined3d: Add extension detection for ARB_depth_texture. - wined3d: Add extension detection to the GL format template table. - wined3d: Set texture filtering to NEAREST in check_fbo_compat(). - wined3d: Check FBO compatibility on all formats with a GL format. - wined3d: Only use stretch_rect_fbo() on surfaces that are FBO attachable. - wined3d: Use FBOs for offscreen rendering by default. - wined3d: Add support for EXT_packed_depth_stencil. - wined3d: Use GL_DEPTH24_STENCIL8_EXT for depth stencil formats. - -Hib Eris (10): - msi/tests: Add tests for binary OBJECTS. - msi: Add support for binary OBJECTS. - msi: Support transforms with binary OBJECTS. - msi/tests: Add test for importing binary OBJECTS. - msi: Add support for importing binary OBJECTS. - msi: Initialize a variable. - msi/tests: Add test for merging tables with string primary keys. - msi: Fix merging tables with string primary keys. - msi/tests: Add test for merging tables that are not in target database. - msi: Add support for merging tables that are not in target database. - -Huw Davies (7): - ole32/tests: Fix tests on systems without IE installed. - comdlg32/tests: PrintDlgExW returns E_NOTIMPL on some versions of winME. - ole32: Rename a parameter to better reflect its use. - ole32: Store the creation flag - STGM_SIMPLE depends on this. - ole32: In simple mode, CreateStream with the STGM_CREATE flag should fail. - ole32: In simple create mode the size returned by IStream_Stat is actually the current stream position. - ole32: In simple mode keep the stream size above the small block limit. - -Hwang YunSong (3): - regedit: Updated Korean resource. - shell32: Updated Korean resource. - reg: Updated Korean resource. - -Jacek Caban (11): - urlmon: Use TLS_OUT_OF_INDEXES as invalid TLS value. - mshtml: Use TLS_OUT_OF_INDEXES as invalid TLS value. - wininet.h: Added more error codes. - wininet: Move strings to avoid duplications. - wininet: Always set path in HttpOpenRequest. - wininet: Change read_buf type to BYTE. - wininet: Added support for decompressing gzip encoded content. - wininet: Test gzip encoded read. - wininet: Fixed tests on Windows. - urlmon: Set INTERNET_OPTION_HTTP_DECODING option in http protocol handler. - urlmon: Use a copy of PROTOCOLDATA in Switch/Continue implementation. - -Jeff Zaroyko (1): - dmsynth: Fix a typo. - -Joerg-Cyril.Hoehle@t-systems.com (1): - configure: Find libpng in /usr/X11 on MacOS. - -Kai Blin (2): - advapi32: Fix output of GetUserNameW when joined to a domain. - secur32: Don't return STATUS_SUCCESS from LsaGetLogonSessionData stub. - -Ken Sharp (1): - shell32: Add stub for InitNetworkAddressControl. - -Louis Lenders (5): - wined3d: Match device name string to windows one. - d3d9/tests: Add simple test to show that QualityLevels is not zero, when we call CheckDeviceMultiSampleType with D3DMULTISAMPLE_NONE. - wined3d: Fix CheckDeviceMultiSampleType when queried with D3DMULTISAMPLE_NONE. - ntdll: Add stub for NtSecureConnectPort. - ntdll: Add stub for RtlEnumerateGenericTableWithoutSplaying. - -Marcus Meissner (2): - winegcc: Free two new strlists (Coverity). - msi: Check the correct pointers for allocation failure (Coverity). - -Michael Stefaniuc (11): - imm32: Use a simpler comparison of a pointer with NULL. - msvcrtd: Use size_t instead of unsigned long. - msvcrt: Replace size_t with MSVCRT_size_t. - msvcrt: Avoid using size_t when not neededed. - notepad: Rename the SIZEOF macro to the more descriptive ARRAY_SIZE. - notepad: Use the ARRAY_SIZE() macro if we already have it. - gdi32: Avoid using long when not needed. - kernel32: Switch to UTF-8 encoding for rom.nls. - kernel32: Update the Romanian(Romania) NLS file. - crypt32: Replace long with a better type. - mshtml: Replace long with LONG. - -Nicolas Le Cam (3): - winetest: Only call GetTempPath once. - winetest: Add option -d to specify tests output directory. - winetest: Add a missing carriage return in help message. - -Nikolay Sivov (43): - comctl32/listview: Draw focus rectangle only when visible. - comctl32/listview: Fix returning LVHT_ONITEMSTATEICON flag on hittesting. - comctl32/treeview: Use message return values in TreeView tests. - comctl32/toolbar: Don't free Toolbar control data too early. - comctl32/hotkey: Remove useless line. - comctl32/toolbar: Retrieve Tooltips control data once at WinProc. - comctl32/listview: Remove duplicated expression. - comctl32/listview: Reuse cached control style. - comctl32/listview: Simplify key selection handler a bit. - comctl32/listview: Don't hittest when it's not needed. - comctl32/mru: Check for NULL handles in MRU calls. - comctl32/mru: Fix test failures on Win9x. - comctl32/listview: Basic LVM_GETVIEWRECT tests. - comctl32/listview: LVM_GETVIEWRECT is unsupported on LVS_REPORT style. - comctl32/listview: A couple of LVM_GETITEMPOSITION tests. - comctl32/listview: Improve item position calculating in LVS_REPORT. - comctl32/listview: Some LVM_GETITEMRECT tests. - comctl32/listview: Fix some LVM_GETVIEWRECT test failures on different platforms. - comctl32/listview: LVM_GETITEMRECT: don't offset to item position on LVS_REPORT querying LVIR_BOUNDS. - comctl32/listview: Move item position calculation out of subitem loop. - user32: Add a stub for DisableProcessWindowsGhosting. - comctl32/ipaddress: Skip test on Win95 with common controls 4.70. - comctl32/tooltips: Move parameter cast to WinProc. - comctl32/tooltips: Fix callback tip text retrieval. - comctl32/listview: Use NMITEMACTIVATE instead of NMLISTVIEW for NM_*CLICK notifications. - comctl32/listview: Fix regression on LVIR_BOUNDS request - y offset still needed. - comctl32/listview: A bunch of LVM_GETSUBITEMRECT tests. - comctl32/listview: Don't offset subitem rectangles with item padding returned by LVM_GETSUBITEMRECT. - comctl32/listview: Item horizontal position isn't applied for any item bounds on LVS_REPORT. - comctl32/listview: Fix item bounds calculation for LVS_REPORT style. - comctl32/listview: Some tests for LVM_EDITLABEL. - comctl32/listview: Block LVM_EDITLABEL when control is unfocused and no label created. - comctl32/listview: EN_KILLFOCUS handling test. - comctl32/listview: Handle EN_KILLFOCUS in WM_COMMAND message handler. - comctl32/listview: Implement LVM_GETVIEW. - comctl32/listview: Implement LVM_SETVIEW. - comctl32/listview: Some tests for LVS_SORT[A,DE]SCENDING, remove these styles from TODOs. - comctl32/listview: Improve item visibility calculation for report view. - comctl32/listview: Improve grid drawing on LVS_EX_GRIDLINES style. - comctl32/listview: Partially revert commit 43d982fde6b363199c95037935e0f5446df8f733. - comctl32/listview: Improve column scrolling. - ntdll: Make NtCreateFile and NtOpenFile thin wrappers over an internal function. - ntdll: Make NtQueryFullAttributesFile and NtQueryAttributesFile thin wrappers over an internal function. - -Paul Vriens (30): - kernel32: Use Polish translations. - kernel32/tests: Fix comment. - mshtml/tests: Fix some test failures on IE8. - kernel32/tests: Fix some test failures on Vista. - msi/tests: Prevent crash when ConvertSidToStringSidA is not available. - mshtml: Match IE8 implementation. - msi/tests: Remove unused variable. - oleaut32/tests: Spelling fixes. - oleacc: Fix Dutch translations. - appwiz.cpl: Fix Dutch translations. - shell32: Fix Dutch translations. - user32: Fix Dutch translations. - winmm/tests: Remove an unreliable test. - oleaut32/tests: Fix some intermittent test failures on W98 and NT4. - wininet/tests: Fix a few typos. - ole32/tests: Move common variables to the top. - ole32/tests: Run more tests on Win9x by using A-functions. - ole32/tests: Fix a crash on NT4 and below. - riched32/tests: Change the test to facilitate adding a broken(). - riched32/tests: Fix a few test failures on NT4 and below. - ole32/tests: Fix remaining test failures on NT4 and below. - kernel32/tests: Skip WritePrivateProfileString tests on Win9x/WinME. - user32/tests: Remove a trace() message. - user32/tests: Fix a test failure on Win95. - shell32/tests: Fix test failure on NT4. - riched32/tests: Fix a test failure on NT4 and below. - kernel32/tests: Fix a test failure on Win9x/WinMe. - msctf: Fix a possible NULL dereference (Coverity). - shell32/tests: Fix test failures on Win95. - shell32/tests: Make sure all created files can be removed. - -Peter Hedlund (1): - kernel32: Mask out obsolete flags in GlobalAlloc. - -Piotr Caban (19): - jscript: Added Math_SQRT2 implementation and tests. - jscript: Added Math_SQRT1_2 implementations and tests. - jscript: Added Math_acos implementation and tests. - jscript: Added Math_LN10 implementation and tests. - jscript: Added implementation of Math_asin. - jscript: Added implementation of Math_atan. - jscript: Added Math_atan2 implementation. - jscript: Added implementation of Math_exp. - jscript: Added implementation of Math_log. - jscript: Added Math_sin implementation. - jscript: Added implementation of Math_sqrt. - jscript: Added Math_tan implementation. - jscript: Fix integer/double parsing. - jscript: Fixed memory leak. - jscript: Added implementation of Math_pow with less then 2 arguments. - jscript: Fix parse_double_literal implementation. - jscript: Remove NaN related FIXMEs. - jscript: Fix DateConstr_value (with no argument) implementation. - jscript: Added Date_setTime implementation. - -Rico Schüller (2): - d3d10: Improve parse_fx10. - d3d10: Replace a few more unknown in parse_fx10. - -Stefan Dösinger (28): - wined3d: Implement DSX in ARB. - wined3d: Replace a few hardcoded Tx registers with proper name getters. - wined3d: Get rid of Tx hardcoding in texbem. - wined3d: Put some ARB declarations in the right place. - wined3d: sincos for vertex shaders. - wined3d: Work around an ARBFP vs GLSL bug in Mac OS. - wined3d: Store the compile args in the compile context, not the shader. - wined3d: Make find_gl_pshader backend private. - wined3d: Remove the forward declaration added in the last patch. - wined3d: Make find_gl_vshader backend specific. - wined3d: Manage ps_compiled_shader in the backends. - wined3d: Manage vs_compile_args in the backends. - wined3d: Add a function around the handler table. - wined3d: Emulate if(bool) in ARB shaders. - wined3d: Allocate the proper size for the lconst map. - wined3d: Remove a MESA hack. - wined3d: Use DP2A or X2D for dp2add if available. - wined3d: Avoid the TMP_COLOR mov in some cases. - wined3d: Use NRM from GL_NV_fragment_program2 if available. - wined3d: Use Rx registers for sRGB correction if possible. - wined3d: Revert "WineD3D: use CMP instead of SLT and SGE in sRGB correction". - wined3d: Write result.color in one mov. - wined3d: Don't enable the NV frag extensions if we don't need them. - wined3d: Add a comment about texbem and X2D. - wined3d: Handle LRP in vertex shaders. - wined3d: Use condition code for sRGB write correction if available. - wined3d: Update clipplanes on a shader-fixed function switch. - wined3d: Implement clipplanes in the ARB backend. - -Stefan Leichter (2): - kernel32: Fix spec of QueryFullProcessImageNameW. - kernel32: Added missing newline to win_skip. - -Stefan Stranz (1): - winhlp32: Fix crash on launch. - -Stephan Rose (1): - gdiplus: Add support for vertical string alignment to GdipDrawString. - -Tony Wasserka (4): - d3dx9: Add stubs for the D3DXGetImageInfo function group. - d3dx9: Add utility functions for loading files and resources into memory. - d3dx9: Redirect D3DXGetImageInfo functions to the FromFileInMemory variant. - d3dx9: Test return codes of the D3DXGetImageInfo functions. - -Vincent Povirk (8): - winex11: Set the fullscreen state of virtual desktops based on size. - gdiplus: Stub GdipCreateHICONFromBitmap. - ole32: Add some tests for read only storage objects. - ole32: Fix crash when calling CreateStream on read only storage. - ole32: Fix crash when calling CreateStorage on read only storage. - ole32: Fix return code of DeleteStorage for read only storage. - ole32: Don't ignore a failure to delete the old element in CreateStorage. - winex11.drv: Don't use XEvents uninitialized when waits time out. - -Vitaliy Margolen (1): - winecfg: Update WinXP version to SP3. - -Vitaly Perov (1): - mpr: Don't set LastError if no error occured. - -Vladimir Pankratov (1): - winedbg: Add Russian translation. - -Yuriy Kaminskiy (1): - dsound: Fix segv on use-after-free in IDirectSoundNotifyImpl_Release. - --- -Alexandre Julliard -julliard@winehq.org +The Wine development release 1.1.24 is now available. + +What's new in this release (see below for details): + - Support for freedesktop file associations. + - Support for exception handling on 64-bit. + - Improved ARB shaders. + - Fixes for the FBO mode. + - Many listview improvements. + - Various bug fixes. + +The source is available from the following locations: + + http://ibiblio.org/pub/linux/system/emulators/wine/wine-1.1.24.tar.bz2 + http://prdownloads.sourceforge.net/wine/wine-1.1.24.tar.bz2 + +Binary packages for various distributions will be available from: + + http://www.winehq.org/site/download + +You will find documentation on http://www.winehq.org/site/documentation + +You can also get the current source directly from the git +repository. Check http://www.winehq.org/site/git for details. + +Wine is available thanks to the work of many people. See the file +AUTHORS in the distribution for the complete list. + +---------------------------------------------------------------- + +Bugs fixed in 1.1.24: + + 2720 File open dialog crashes in Micrographic designer + 9042 Paradise Poker Client gives black desktop background - bug + 10551 When emulating Sprint-Layout the mouse doesn't catch obejects + 10981 Anti-Grain Geometry GDI Demo does not run + 11030 JIT fails to launch + 11942 Trouble with actor's shadow in "Journey to the Center of the Earth" + 12137 Test Drive: Unlimited slow performance + 12169 Supreme Commander: Black bar obscuring screen when fidelity >low + 12183 EVE Premium 4.10.51200 does not render correctly with shadows on + 12380 Support fd.o file type associations + 12405 Crash at starting WISO Sparbuch 2008 + 13266 ArchiCad 11 installer: Crashes after extraction (Java related?) + 13705 keyboard does not work in Trackmania Nations Forever + 13917 Supreme Commander won't let me select high fidelity + 13922 configure script produces misleading warning about libhal + 14767 WGL_SWAP_METHOD_ARB attribute not implemented + 15206 Trouble with symbolic stack dumps and Chromium + 15371 HDR not rendered correctly (e.g. in Rainbow 6 Vegas) + 15377 1.1.5 breaks d3d game that worked in 1.1.4 + 15457 Languages dialog is empty in inetcpl.cpl (IMultiLanguage2_GetRfc1766Info) + 15878 Dogfood: Gimp 2.6 will not open images. + 15925 World of Warcraft: Extreme FPS drop since 3.0.2 + 16115 jscript: field with has wrong type + 16195 GetKeyNameTextW returns a wrong length + 16267 Vista Winetest24112008 MSItest loop + 16331 inetcomm: possible null pointer dereferences + 16385 Photoshop CS4 interface doesn't load + 16506 some GUI feedback is needed when wine crashes + 16521 With separate x-screens, windowed applications in the secondary screen are limited to resolution of primary screen + 16609 Wine's XDnD should support text/uri-list lines not ending in \r\n + 16681 Adobe Photoshop CS4 fails to start, complains "Some of the application components are missing..." + 17433 Photoshop CS4 crash in unimplemented function gdiplus.dll.GdipMeasureDriverString + 17437 ATI and EVE Premium: no models display / crashes on startup + 17591 WISO MeinBuero 2009 trial segfaults in wintrust.dll + 17600 MSOffice installer (XP, 2003, 2007) : msi crash in custom action + 17681 mcm2 Help immediately exists (Motocross Madness 2) + 17914 Using \n rather then \r\n breaks HTTP RFC with HTTP_AddRequestHeadersW + 18202 Programs show unhandled exception dialog on every run + 18256 Quicktime 2 Unimplemented function olesvr32.dll.OleRevokeServer on exit + 18516 Goldwave 5.25 File Save dialog no longer has options for file format... + 18610 Quicken 2009 crashes + 18617 Regedit can't import registry from standard input + 18638 .NET 3.0 apps abort with: Call from to unimplemented function GDI32.dll.GdiEntry13, aborting + 18641 Adobe Lightroom 2.3 crashes on unimplemented function gdiplus.dll.GdipCreateHICONFromBitmap + 18735 Photoshop CS4 crash in unimplemented function GdipGetVisibleClipBoundsI + 18736 Photoshop CS4 crash in unimplemented function GdipDrawDriverString + 18742 WoW: Icons under d3d are incorrectly desaturated + 18797 CATIAV5R19: Fails to install on Wine higher than 1.1.18 + 18798 Neuro-Programmer v2.5 unable to start + 18809 Dragon NaturallySpeaking 10 no longer installs + 18811 Lexware: wine crashes during .Net 2.0 SP1 Installation + 18824 Thief 3 crashes when starting a new game + 18841 Ghost Recon Installer Crashes + 18882 Allow windows links (.lnk) to be handled by Wine + 18895 Thief 3 crashes on closing. + 18900 Wineserver crashes starting Team Fortress 2 + 18915 FAR Manager: crashes shortly after startup + 18916 Thief 2 crashes when bringing up in-game menu + 18925 OS X build broken + +---------------------------------------------------------------- + +Changes since 1.1.23: + +Alexander Nicolaysen Sørnes (1): + regedit: Fix reading from stdin. + +Alexandre Julliard (47): + wininet: Always use a full URL for redirects, even with an absolute path. + user32: Disable assert() for the mingw build since mingw gets confused trying to import MessageBoxA. + kernel32: Fix handling of %ws format for Unicode. + comctl32: Avoid repainting a NULL link. + widl: Don't make the proxy virtual tables const if they use delegation. + server: Avoid a crash when trying to wait on a disconnected pipe client. + ole32: Get rid of line feeds and tabs in traces. + kernel32: Forward RtlUnwindEx to ntdll for x86_64. + winebuild: Properly restore %rax and %rbx in call_from_regs on x86_64. + rpcrt4: Adjust the start of the proxy virtual table for stubless proxies. + opengl32: Make the script default to version 1.1. Remove the glGetLevelParameter stubs. + configure: Detect the appropriate form for the __ASM_GLOBAL_FUNC macro. + configure: Add .cfi_startproc/endproc directives to assembly functions if supported. + riched20: Move the textHostVtbl definition to work around Mac OS X breakage with __ASM_GLOBAL_FUNC. + server: Restart at the head of the wait queue when we woke a thread, since this can modify the queue. + configure: Make sure that gcc is recent enough for building 64-bit code. + configure: Add a macro to define an stdcall suffix in assembly code. + configure: Add a macro to define an stdcall function in assembly. + msvcrt: Add appropriate stdcall decorations to assembly functions. + riched20: Add appropriate stdcall decorations to assembly functions. + rpcrt4: Add appropriate stdcall decorations to assembly functions. + hal: Add appropriate stdcall decorations to assembly functions. + ntoskrnl.exe: Add appropriate stdcall decorations to assembly functions. + kernel32: Add appropriate stdcall decorations to assembly functions. + ntdll: Add appropriate stdcall decorations to assembly functions. + advapi32/tests: Avoid accessing an uninitialized pointer. + advapi32: Fix self-relative security descriptor creation for 64-bit. + ntdll: Fix handling of self-relative security descriptors for 64-bit. + msvcrtd/tests: Fix calling convention for operator_new_dbg. + libwine: Add unwind annotations to the stack switching functions for x86_64. + ntdll: Add unwind annotations to the call_entry_point function for x86_64. + winebuild: Add unwind annotations to all the generated functions for x86_64. + ntdll: Handle x86_64 signals on a separate signal stack. + winebuild: Implement a --large-address-aware flag. + winegcc: Add support for the -Wl,--large-address-aware option. + ntdll: Implement stack unwinding for x86_64 builtin modules based on the Dwarf data. + include: Add a target address for unwinding for platforms that need it. + ntdll: Add support for calling the TEB exception chain handlers on x86_64. + server: The ptrace interfaces uses longs, not ints. + kernel32: Fix the HGLOBAL header size for 64-bit. + ntdll: Simplify the thread startup routine and make it CPU-specific. + ntdll: Move all thread exit processing to exit_thread(), and make RtlExitUserThread() CPU-specific. + configure: Don't accept mingw32 as target name, we need an explicit CPU specification. + rpcrt4/tests: Fix the marshalling test for Win64. + rpcrt4/tests: Fix the marshalling test for Win9x. + rpcrt4: Fix memory sizes of marshalled pointers on 64-bit. + urlmon/tests: Avoid comparing uninitialized structure data. + +Anders Jonsson (8): + ntoskrnl.exe: Stub for KeInitializeMutex. + ntoskrnl.exe: Stub for KeWaitForSingleObject. + ntoskrnl.exe: Stub for IoInitializeTimer. + ntoskrnl.exe: Stub for IoStartTimer. + ntoskrnl.exe: Stub for ExInitializeResourceLite. + ntoskrnl.exe: Stub for ExInitializeZone. + ntoskrnl.exe: Stub for PsTerminateSystemThread. + ntoskrnl.exe: Stub for ExInitializeNPagedLookasideList. + +Andrew Eikum (1): + gdiplus: Test cases and parameter checks for GdipDrawCurve. + +Andrew Talbot (8): + comctl32: Constify some variables. + comctl32: Constify some variables. + comdlg32: Constify some variables. + credui: Constify a variable. + crypt32: Constify some variables. + crypt32: Constify some variables. + crypt32: Constify some variables. + crypt32: Constify some variables. + +André Hentschel (10): + shell32/tests: Fix error messages. + wordpad: Add German translation. + shell32: Add German translation. + setupapi: Add German translation. + oleacc: Add German translation. + winedbg: Fix comment header. + cryptui: Add German translation. + cryptdlg: Add German translation. + cryptui: Improve German translation. + documentation: Keep README.de in sync. + +Aric Stewart (11): + msctf: Framework for ITfCompartmentMgr. + msctf: Define ITfCompartmentMgr for ThreadMgr. + msctf: Add ITfComponentMgr to documentmgr. + msctf: Define ITfCompartmentMgr for Context. + msctf: Setup global CompartmentMgr. + msctf: Implement ITfContext::GetDocumentMgr. + msctf: Implement ITfThreadMgr::IsThreadFocus. + msctf: Contexts have a default DocumentMgr of the one that creates them. + msctf: Implement ITfCompartmentMgr::ClearCompartment. + msctf: Implement ITfCompartmentMgr::EnumCompartments. + comctl32: In COMBOEX_FindStringExact do not try to get text from invalid items. + +Aurimas Fišeras (4): + winemine: Add Lithuanian translation. + wininet: Add Lithuanian translation. + hhctrl.ocx: Add Lithuanian translation. + oleacc: Add Lithuanian translation. + +Austin English (10): + mshtml: Make the wine-gecko warning more clear. + winex11: Return correct length for GetKeyNameText. + wine.desktop: Allow start to execute lnk files. + kernel32: GetConsoleAliasW is a stub, make sure it acts like one. + configure: Fix mach-o/dyld_images.h detection on OS X. + configure: Add a note about missing dbus if libhal is missing. + oleaut32: Fix a compiler warning for libjpeg includes. + gphoto2.ds: Fix a compiler warning for libjpeg includes. + wine.inf: Fix incorrect entry for hh.exe. + wine.inf: Add placeholder exe for wordpad.exe. + +Damjan Jovanovic (6): + winemenubuilder: Generate icons for Wine's MIME types. + start.exe: Add infrastructure to launch windows file open associations from freedesktop. + wine.inf: Update file type associations on startup. + shell32: Update file type associations when requested. + winex11.drv: Fix file drops on KDE4 and XFCE. + winemenubuilder: Log where freedesktop menu files are created, and provide an option to clean them up. + +Detlef Riekenberg (12): + mlang/tests: Fix failures with IE 5.5 and below. + mlang: Implement IMultiLanguage2_GetRfc1766Info. + mlang/tests: Add tests for IMultiLanguage2_GetRfc1766Info. + mlang/tests: Fix a failure on win98 with mlang 4.72. + mlang/tests: Store the expected results for GetRfc1766Info as Unicode. + shlwapi: Forward DnsRecordSetCompare to dnsapi. + mlang: Implement IMultiLanguage_GetRfc1766Info. + urlmon/tests: Move SecurityManager and ZoneManager tests to a separate file. + setupapi: Move IsUserAdmin to shell32.IsUserAnAdmin. + urlmon/tests: Fix a typo in an ok message. + mlang/tests: Some old IE versions truncate one character too short. + mlang: Implement IMultiLanguage_GetNumberOfCodePageInfo, with test. + +Dmitry Timoshkov (4): + wine.inf: Add kernel32.48/kernel32.49 (ReleaseThunkLock/RestoreThunkLock) to the RelayExclude list. + user32: Add support for SPI_GETFOCUSBORDERWIDTH and SPI_GETFOCUSBORDERHEIGHT. + user32: Add a test for PeekMessage((HWND)-1), make it pass under Wine. + user32: Invalidate button on WM_KILLFOCUS, like Windows does. + +Eric Pouech (1): + dbghelp: Improve speed of our hashtable implementation by remembering the last element added to every bucket. + +Francois Gouget (19): + cryptdlg & cryptui: Use SUBLANG_NEUTRAL for German. + winedos: Move VGA_SetGraphicMode() up a bit and make it static. VGA_GetModeInfoList() is unused so remove it. + winedos: DPMI_FreeInternalRMCB() is not used so remove it. + winedos: DOSVM_GetTimer() is not used so remove it. + gdi32/tests: Small indentation fix. + msctf/tests: Make EditSession_Constructor() static. + msctf: Make the CompartmentMgr functions static. + gdiplus: Remove spaces before '\n's. + winapi/c_parser: Remove some dead code. + rpcrt4/tests: Replace malloc() with HeapAlloc(). + cmd: Introduce a WCMD_strsubstW() function to simplify string substitutions. + cmd: Replace malloc() with HeapAlloc(). + comctl32: Extend the LVTILEINFO structure. + winapi: Fix a $blevel / $plevel mismatch. + wineesd.drv: Initialize the stream name before using it. + winweesd.drv: Make sure esd_all_info is always initialized and freed when needed. + wineesd.drv: Remove a redundant assignment. + dmime: Remove patterntrack.c and tool.c as they are unused and don't correspond to objects. + comctl32/tests: Make DummyCompareEx() static. + +Frank Richter (1): + d3d9: Fix bitmask for A2R10G10B10 format. + +Frédéric Delanoy (1): + documentation: Keep README.fr in sync. + +Ge van Geldorp (1): + advapi32: Set values to 0 in LsaEnumerateAccountRights. + +Gerald Pfeifer (7): + user32: Fix logic condition in SPY_DumpStructure(). + winmm: Use & instead of && for bit test in wave_out_test_deviceOut(). + wined3d: Use & instead of && for bit test in IWineD3DDeviceImpl_CreateSurface(). + wined3d: Fix (and simplify) the ATI case in IWineD3DImpl_FillGLCaps. + d3d9: Use correct constant types (WINED3DPOOL_DEFAULT instead of D3DPOOL_DEFAULT and WINED3DRTYPE_SURFACE instead of D3DRTYPE_SURFACE). + cmd.exe: Fix incorrect check in WCMD_HandleTildaModifiers(). + crypt32: Fix incorrect logic condition in test_decodePKCSAttribute(). + +Guy Albertelli (2): + kernel32/tests: Fix tests when GetVolumeNameForVolumeMountPoint fails. + kernel32/tests: Fix tests to pass on Win9x and WinME. + +Hans Leidekker (5): + msi: Add some reinstall tests. + wintrust: Add stub implementations of HTTPSCertificateTrust and HTTPSFinalProv. + wininet: Always create a URL cache entry. + wininet: Don't fail if dwReserved is set in CreateUrlCacheEntryW. + wininet: Implement InternetQueryOption(INTERNET_OPTION_CACHE_TIMESTAMPS). + +Henri Verbeet (51): + wined3d: Add support for the ARB_depth_buffer_float extension. + wined3d: Use GL_DEPTH_COMPONENT32F for WINED3DFMT_D32F_LOCKABLE. + wined3d: Use GL_DEPTH32F_STENCIL8 for WINED3DFMT_D24FS8. + wined3d: Use context_attach_depth_stencil_fbo() to clear FBO depth attachments. + wined3d: Set FBO stencil attachments for relevant depth stencil formats. + wined3d: Avoid comparing shader compile args if the relevant shader isn't present. + wined3d: Simplify some code in set_glsl_shader_program(). + wined3d: Don't modify the internal format in d3dfmt_get_conv(). + wined3d: Get rid of the silly pointers in WINED3DVOLUME_DESC. + wined3d: Add some FIXMEs about blitting with unsupported fixups. + wined3d: Set explicitly sized internal formats for color key conversion in d3dfmt_get_conv(). + wined3d: Check the correct extensions in d3dfmt_get_conv(). + wined3d: Round rows up to whole blocks for compressed surface blits in BltFast(). + wined3d: Store compression information about compressed formats. + wined3d: Use the format info for doing compressed surface blits in BltFast(). + wined3d: Remove some redundant s3tc extension checks. + wined3d: Improve some TRACEs in init_format_fbo_compat_info(). + wined3d: Use the format info to calculate compressed surface size in IWineD3DDeviceImpl_CreateSurface(). + wined3d: Use the format info to calculate compressed surface size in IWineD3DBaseSurfaceImpl_SetFormat(). + wined3d: Use the format info to calculate compressed surface pitch in IWineD3DBaseSurfaceImpl_GetPitch(). + wined3d: Use the compressed format info in IWineD3DBaseSurfaceImpl_LockRect(). + wined3d: Use WINED3DFMT_FLAG_COMPRESSED instead of checking for specific formats. + wined3d: Remove the useless "resource_type" parameter from IWineD3DDevice::CreateSurface(). + wined3d: Respect the "srgb" parameter to IWineD3DSurfaceImpl_BindTexture(). + wined3d: Avoid checking depth/stencil and compressed formats in init_format_fbo_compat_info(). + wined3d: Introduce surface_cleanup(). + wined3d: Introduce surface_gdi_cleanup(). + wined3d: Introduce surface_init() to handle most of the surface initialization. + wined3d: Introduce surface_calculate_size(). + wined3d: Get rid of the pointers in WINED3DSURFACE_DESC. + shdocvw: Take the riid parameter to TaskbarList_Create() into account. + shdocvw: Add SHDOCVW_LockModule()/SHDOCVW_UnlockModule() calls to ITaskbarList. + d3d8: Do some more verification on handles. + d3d8: Deleting an invalid pixel shader handle should return D3D_OK. + d3d8: Add tests for deleting invalid shader handles. + wined3d: Add format conversions for some depth stencil formats. + wined3d: Fix a typo. + wined3d: Fall back to backbuffer offscreen rendering if FBOs are unavailable. + wined3d: Only initialize unused components of varyings that are read. + wined3d: Avoid some unneeded depthstencil copies. + wined3d: Avoid some unneeded rendertarget copies. + wined3d: Make sure we have a context in stretch_rect_fbo(). + wined3d: Reuse the FBO for check_fbo_compat(). + wined3d: Remove some useless code in IWineD3DDeviceImpl_SetLightEnable(). + wined3d: Simplify IWineD3DSurfaceImpl_LockRect() a bit. + wined3d: Remove a redundant ActivateContext() call in IWineD3DSurfaceImpl_UnlockRect(). + d3d8: Add WINED3DFMT_W11V11U10 <=> D3DFMT_W11V11U10 conversion. + wined3d: Don't load a rendertarget just because alpha test is enabled. + d3dx9_36: Implement D3DXGetDeclVertexSize(). + d3dx9_36: Add a test for D3DXGetDeclVertexSize(). + d3d9: Use color_match() in the fog test. + +Hib Eris (1): + msi: Fix a crash when freeing memory. + +Huw Davies (6): + widl: Add support for the lcid parameter attribute. + widl: Fix typelib lcid fields to match those produced by midl. + oleaut32: TLibAttr.lcid is read from the second lcid field in the header. Confirmed by manually editing a tlb file. + oleaut32: Calling SetLcid with LOCALE_NEUTRAL is a special case which sets the first header lcid to US English and the second one to 0. + tools/widl: Fix behaviour when both lcid and retval arguments are present. + oleaut32/tests: Add some tests for [lcid] parameters. + +Jacek Caban (2): + wininet: Fixed gzip decoding on chunked stream. + urlmon: Fixed test on IE8. + +Jonathan Ernst (8): + crypt32: Updated French translation. + mshtml: Updated French translation. + notepad: Updated French translation. + regedit: Updated French translation. + setupapi: Updated French translation. + wordpad: Updated French translation. + reg: Updated French translation. + shell32: Updated French translation. + +Joris Huizer (1): + winemenubuilder: reg_get_val[AW]: Fix memory leak. + +José Manuel Ferrer Ortiz (1): + winecfg: Spanish resources update. + +Juan Lang (3): + wintrust: Only check the pgKnownSubject member if the struct includes it. + wintrust: Check for the presence of required members of WINTRUST_BLOB_INFO rather than requiring callers to be compiled with the same SDK version. + wintrust: Check for the presence of required members of WINTRUST_CERT_INFO rather than requiring callers to be compiled with the same SDK version. + +Ken Sharp (6): + gdiplus: Add stubs for GdipGetVisibleClipBoundsI, GdipDrawDriverString & GdipMeasureDriverString. + olesvr32: Add OleRevokeServer stub. + ntoskrnl: Add ObfReferenceObject stub. + ntoskrnl: Add IoRegisterFileSystem stub. + ntoskrnl: Add IoUnregisterFileSystem stub. + ntoskrnl: Add FsRtlRegisterUncProvider stub. + +Louis Lenders (1): + gdi32: Add stub for GdiEntry13. + +Marcus Meissner (2): + widl: ifdef some not always present LANG_*. + ddraw: Use correct union member. + +Michael Abbott (1): + wined3d: Remove division from inner loop. + +Mike Kaplinskiy (4): + msi: Store temporary rows in the same place as persistent rows, just with a flag. + msi: Add a test to insert a null primary key temporary row and check its order. + wininet: Make \r and \n valid header separators. + wininet/test: Test malformed header separators. + +Mikio Idneuma (1): + appwiz.cpl: Update Japanese translation. + +Nikolay Sivov (25): + ntdll: Call NtCreateSection with NULL attributes loading native dll. + comctl32/listview: Edit box should be destroyed on invalid index too (LVM_EDITLABEL). + comctl32/listview: Test showing that Edit box should be positioned after LVN_BEGINLABELEDIT. + comctl32/listview: Position edit box after notification. + comctl32/listview: Defaulting to NFR_ANSI on query failure. + comctl32/listview: Use LV_VIEW_* constants instead of style. + comctl32/listview: Revert column scrolling recent change, it should be handled differently. + comctl32/listview: Fix item count tests to be dpi aware. + comctl32/listview: Remove outdated todo entries. + comctl32/listview: Test for indentation callback. + comctl32/listview: Implement callback functionality for item indentation. + comctl32/listview: Update some ListView structures with recently added members. + comctl32/listview: Make item width calculation not rely on column order for LV_VIEW_DETAILS. + comctl32/listview: Don't use special value (1) for item width to represent both zero and one pixel width. + comctl32/header: Update some Header flags and structures. + comctl32/listview: Don't offset item box to item position on LVS_EX_FULLROWSELECT if item isn't in leftmost column. + comctl32/listview: Fix some hittest problems on LVS_EX_FULLROWSELECT. + comctl32/listview: Don't offset subitems on painting. + comctl32/listview: Get rid of Header_* macros. + comctl32/listview: Setting item text to callback stub value already having it raises item-change notifications. + comctl32/listview: Block header items drag if LVS_EX_HEADERDRAGDROP isn't set. + comctl32/listview: Forward HDN_DIVIDERDBLCLICK to parent. + comctl32/listview: Convert forwarded header notifications to ANSI if NFR_ANSI is current format. + comctl32/listview: Fix test crashes on comctl32 <5.80. + comctl32/listview: Add ability to test comctl32 version 6. Add basic LVM_[G,S]ETVIEW test. + +Paul Vriens (36): + mshtml/tests: Correct a test and show a Wine bug. + mshtml/tests: Use lstrcmpA in a helper function to make it work correctly on Win98. + mshtml/tests: Correct another test. + mshtml/tests: Use strcmp_wa instead of lstrcmpW to test correctly on Win98. + kernel32/tests: Only report unimplemented functions once. + winecfg: Fix Dutch translations. + setupapi/tests: pSetupGetField returns A or W string depending on OS. + msi/tests: Make sure we only create one logfile. + riched32/tests: Fix some test failures on Win9x/WinME/NT4. + riched32/tests: Fix a few test failures on Win9x, WinME and NT4. + riched32/tests: Correct a test to better show the behavior. + riched32/tests: Fix a few test failures on Win9x/WinME/NT4. + riched32/tests: Cater for differences between platforms. + riched32/tests: Fix test failures on Win9x, WinMe and NT4. + mlang/tests: Fix a test failure on Win95. + user32/tests: Skip some tests on Win9x/WinME. + shell32/tests: Fix a test failure on some Win95 boxes and NT4. + gdi32/tests: Fix several test failures on Win9x/WinME/NT4. + gdi32/tests: Fix some test failures on NT4. + gdi32/tests: Fix the last test failure on NT4. + shell32/tests: Fix some test failures on NT4 (and some Win95 boxes). + comdlg32/tests: Fix some typos. + comctl32/tests: Fix some typos (copy-paste). + shell32/tests: Fix a test failure on Vista. + shell32/tests: Fix a test failure on Vista. + shell32/tests: Fix a test failure on Vista and higher. + shell32/tests: Fix some test failures on Vista and higher. + wldap32/tests: Skip a test on older versions of wldap32 to prevent a crash. + shell32/tests: Fix a test failure on Vista and higher. + shell32/tests: Fix some test failures on Vista and higher. + msi/tests: Fix test (logical || with non-zero constant). + d3d8/tests: Fix some tests (logical || with non-zero constant). + msi/tests: Fix some test failures on Win95 by using more A-functions. + mapi32/tests: Don't run tests if ScInitMapiUtil() fails. + mapi32/tests: Don't run tests if ScInitMapiUtil() fails. + mapi32/tests: Don't run tests if ScInitMapiUtil() fails. + +Piotr Caban (13): + jscript: Added Date_getFullYear and Date_getUTCFullYear implementation. + jscript: Added Date_getMonth and Date_getUTCMonth implementation. + jscript: Added Date_getDate and Date_getUTCDate implementation. + jscript: Added Date_getDay and Date_getUTCDay implementation. + jscript: Added Date_getHours and Date_getUTCHours implementation. + jscript: Fixed hour_from_time and week_day functions. + jscript: Added Date_getUTCMinutes and Date_getMinutes implementation. + jscript: Added Date_getUTCSeconds and Date_getSeconds implementation. + jscript: Added Date_getUTCMilliseconds and Date_getMilliseconds implementation. + jscript: Added Date_setUTCMilliseconds and Date_setMilliseconds implementation. + jscript: Added Date_setUTCSeconds and Date_setSeconds implementation. + jscript: Added Date_setUTCMinutes and Date_setMinutes implementation. + jscript: Added Date_setUTCHours and Date_setHours implementation. + +Rein Klazes (4): + gdi32: Fix RectInRegion() if right < left or bottom < top. + winedos: int21, function 32h returns data in DS:BX, not DS:DX. + comdlg32: Delay setting the initial size of resizable file dialog until the CDN_INITDONE notification has been processed. + comdlg32/tests: Fix file dialog resize failures on NT4 and with tiny desktops. + +Rico Schüller (1): + wined3d: Don't allow a negative lock_count in buffer_Unmap. + +Robert Key (1): + wined3d: Add missing HD 3400 renderer string. + +Roderick Colenbrander (3): + opengl32: Sync with the latest opengl 3.1 extensions and don't export opengl32 1.2 functions. + opengl32: Get rid of glext.h. + wgl: Get rid of glXQueryDrawable because officially it only works on GLXDrawables. + +Stefan Doesinger (20): + wined3d: Unroll loops in ARB if needed. + wined3d: Implement break and breakc. + wined3d: Implement IFC in ARB. + wined3d: Use flags instead of bools to control shader_hw_sample. + wined3d: Implement texldd in ARB. + wined3d: Implement texldl in ARB. + wined3d: Implement vpos and vface. + wined3d: Use bitfields for reg_maps uses* members. + d3d9: Accept an alternative oFog->ps_3_0 handling. + wined3d: Fix texm3x3pad. + wined3d: Add modifier support to tex and friends. + wined3d: Implement D3DSPDM_PARTIALPRECISION support. + wined3d: Deal with instructions that do not support _SAT. + wined3d: Properly free srgb textures. + wined3d: Properly load the y correction. + wined3d: Handle SM 3.0 varyings in ARB. + wined3d: Don't run out of varyings because of clipplanes. + wined3d: Implement vertex texture fetch in ARB. + wined3d: Emulate clipplanes in ARB if the NV extensions are not available. + wined3d: Implement EvictManagedResources. + +Stefan Dösinger (5): +  wined3d: Store the bumpmap ARB constants in ARB structures. + wined3d: Implement loops with the NV extensions. + wined3d: Implement dsy in ARB. + wined3d: A small atifs bump map improvement. + wined3d: Don't set unloaded arrays to zero. + +Stefan Leichter (1): + kernel32: Implement QueryFullProcessImageNameA. + +Stefan Stranz (1): + c2man: Add xml documentation creation. + +Vincent Povirk (7): + windowscodecs: Add stub dll. + include: Add wincodec.idl. + include: Extend TVITEMEX and add NMTVDISPINFOEX. + comctl32: Use NMTVDISPINFOEX in the TVN_GETDISPINFO notification. + kernel32/tests: Test waiting on a disconnected client pipe. + gdiplus: Stub GdipSetPathGradientPresetBlend. + include: Add definitions needed for image decoding to wincodec.idl. + +Vladimir Pankratov (1): + advpack: Add stub for ExtractFilesW. + +Yann Droneaud (1): + wined3d: Improved ATI Radeon HD 4xxx detection. + +-- +Alexandre Julliard +julliard@winehq.org diff --git a/VERSION b/VERSION index 2c34f674351..502a10b9125 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Wine version 1.1.23 +Wine version 1.1.24 diff --git a/aclocal.m4 b/aclocal.m4 index e73b9341344..90e166d3ace 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -141,7 +141,7 @@ dnl AC_DEFUN([WINE_CHECK_MINGW_PROG], [AC_CHECK_PROGS([$1], m4_foreach([ac_wine_prefix], - [$host_cpu-pc-mingw32, i586-mingw32msvc, i386-mingw32msvc, i686-mingw32, i586-mingw32, i486-mingw32, i386-mingw32, mingw32, i686-pc-mingw32, mingw], + [$host_cpu-pc-mingw32, i586-mingw32msvc, i386-mingw32msvc, i686-mingw32, i586-mingw32, i486-mingw32, i386-mingw32, i686-pc-mingw32], [ac_wine_prefix-$2 ]), [$3],[$4])]) diff --git a/configure b/configure index e6ad3a9a3a2..d317c6a307c 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for Wine 1.1.23. +# Generated by GNU Autoconf 2.61 for Wine 1.1.24. # # Report bugs to . # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='Wine' PACKAGE_TARNAME='wine' -PACKAGE_VERSION='1.1.23' -PACKAGE_STRING='Wine 1.1.23' +PACKAGE_VERSION='1.1.24' +PACKAGE_STRING='Wine 1.1.24' PACKAGE_BUGREPORT='wine-devel@winehq.org' ac_unique_file="server/atom.c" @@ -1301,7 +1301,7 @@ if test "$ac_init_help" = "long"; then # 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 1.1.23 to adapt to many kinds of systems. +\`configure' configures Wine 1.1.24 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1370,7 +1370,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Wine 1.1.23:";; + short | recursive ) echo "Configuration of Wine 1.1.24:";; esac cat <<\_ACEOF @@ -1503,7 +1503,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Wine configure 1.1.23 +Wine configure 1.1.24 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1517,7 +1517,7 @@ cat >config.log <<_ACEOF 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 1.1.23, which was +It was created by Wine $as_me 1.1.24, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -3748,6 +3748,57 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ enable_win16=${enable_win16:-yes} else + if test "x${GCC}" = "xyes" + then + { echo "$as_me:$LINENO: checking whether $CC supports __builtin_ms_va_list" >&5 +echo $ECHO_N "checking whether $CC supports __builtin_ms_va_list... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +void func(__builtin_ms_va_list *args); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: You need gcc >= 4.4 to build Wine as 64-bit." >&5 +echo "$as_me: error: You need gcc >= 4.4 to build Wine as 64-bit." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi TARGETFLAGS="-m64" fi @@ -5590,7 +5641,6 @@ for ac_header in \ linux/serial.h \ linux/types.h \ linux/ucdrom.h \ - mach-o/dyld_images.h \ mach-o/nlist.h \ mach/mach.h \ mach/machine.h \ @@ -5617,6 +5667,7 @@ for ac_header in \ scsi/scsi_ioctl.h \ scsi/sg.h \ soundcard.h \ + stdbool.h \ stdint.h \ strings.h \ stropts.h \ @@ -6221,6 +6272,70 @@ done +for ac_header in mach-o/dyld_images.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef HAVE_STDBOOL_H + # include + #endif + #ifdef HAVE_STDINT_H + # include + #endif + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + for ac_header in resolv.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` @@ -7871,7 +7986,7 @@ fi if test "$cross_compiling" = "no" -a "$LIBEXT" != "dll" then - for ac_prog in $host_cpu-pc-mingw32-gcc i586-mingw32msvc-gcc i386-mingw32msvc-gcc i686-mingw32-gcc i586-mingw32-gcc i486-mingw32-gcc i386-mingw32-gcc mingw32-gcc i686-pc-mingw32-gcc mingw-gcc + for ac_prog in $host_cpu-pc-mingw32-gcc i586-mingw32msvc-gcc i386-mingw32msvc-gcc i686-mingw32-gcc i586-mingw32-gcc i486-mingw32-gcc i386-mingw32-gcc i686-pc-mingw32-gcc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -7914,7 +8029,7 @@ fi done test -n "$CROSSCC" || CROSSCC="false" - for ac_prog in $host_cpu-pc-mingw32-dlltool i586-mingw32msvc-dlltool i386-mingw32msvc-dlltool i686-mingw32-dlltool i586-mingw32-dlltool i486-mingw32-dlltool i386-mingw32-dlltool mingw32-dlltool i686-pc-mingw32-dlltool mingw-dlltool + for ac_prog in $host_cpu-pc-mingw32-dlltool i586-mingw32msvc-dlltool i386-mingw32msvc-dlltool i686-mingw32-dlltool i586-mingw32-dlltool i486-mingw32-dlltool i386-mingw32-dlltool i686-pc-mingw32-dlltool do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -7957,7 +8072,7 @@ fi done test -n "$DLLTOOL" || DLLTOOL="false" - for ac_prog in $host_cpu-pc-mingw32-ar i586-mingw32msvc-ar i386-mingw32msvc-ar i686-mingw32-ar i586-mingw32-ar i486-mingw32-ar i386-mingw32-ar mingw32-ar i686-pc-mingw32-ar mingw-ar + for ac_prog in $host_cpu-pc-mingw32-ar i586-mingw32msvc-ar i386-mingw32msvc-ar i686-mingw32-ar i586-mingw32-ar i486-mingw32-ar i386-mingw32-ar i686-pc-mingw32-ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -12462,11 +12577,11 @@ fi fi if test "x$ac_cv_lib_soname_hal" = "x"; then case "x$with_hal" in - x) wine_notices="$wine_notices|libhal ${notice_platform}development files not found, no dynamic device support." ;; + x) wine_notices="$wine_notices|libhal/libdbus ${notice_platform}development files not found, no dynamic device support." ;; xno) ;; - *) { { echo "$as_me:$LINENO: error: libhal ${notice_platform}development files not found, no dynamic device support. + *) { { echo "$as_me:$LINENO: error: libhal/libdbus ${notice_platform}development files not found, no dynamic device support. This is an error since --with-hal was requested." >&5 -echo "$as_me: error: libhal ${notice_platform}development files not found, no dynamic device support. +echo "$as_me: error: libhal/libdbus ${notice_platform}development files not found, no dynamic device support. This is an error since --with-hal was requested." >&2;} { (exit 1); exit 1; }; } ;; esac @@ -16920,6 +17035,65 @@ fi { echo "$as_me:$LINENO: result: $ac_cv_c_extern_prefix" >&5 echo "${ECHO_T}$ac_cv_c_extern_prefix" >&6; } +case $host_cpu in + *i[3456789]86*) + { echo "$as_me:$LINENO: checking whether external symbols need stdcall decoration" >&5 +echo $ECHO_N "checking whether external symbols need stdcall decoration... $ECHO_C" >&6; } +if test "${ac_cv_c_stdcall_suffix+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifndef _MSC_VER +#define __stdcall __attribute__((__stdcall__)) +#endif +int __stdcall ac_test(int i) { return i; } +int +main () +{ +asm("jmp _ac_test@4"); if (ac_test(1)) return 1 + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_c_stdcall_suffix="yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_stdcall_suffix="no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_stdcall_suffix" >&5 +echo "${ECHO_T}$ac_cv_c_stdcall_suffix" >&6; } ;; + *) ac_cv_c_stdcall_suffix="no" ;; +esac + if test "$ac_cv_c_extern_prefix" = "yes" @@ -16938,6 +17112,21 @@ _ACEOF fi + +if test "$ac_cv_c_stdcall_suffix" = "yes" +then + cat >>confdefs.h <<\_ACEOF +#define __ASM_STDCALL(args) "@" #args +_ACEOF + +else + cat >>confdefs.h <<\_ACEOF +#define __ASM_STDCALL(args) "" +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking how to define a function in assembly code" >&5 echo $ECHO_N "checking how to define a function in assembly code... $ECHO_C" >&6; } if test "${ac_cv_asm_func_def+set}" = set; then @@ -17082,19 +17271,19 @@ case "$ac_cv_asm_func_def" in #define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef" _ACEOF - asm_func_header=".def $asm_name_prefix\" #name \"; .scl 2; .type 32; .endef" ;; + asm_func_header=".def $asm_name_prefix\" #name suffix \"; .scl 2; .type 32; .endef" ;; ".type @function") cat >>confdefs.h <<\_ACEOF #define __ASM_FUNC(name) ".type " __ASM_NAME(name) ",@function" _ACEOF - asm_func_header=".type $asm_name_prefix\" #name \",@function" ;; + asm_func_header=".type $asm_name_prefix\" #name suffix \",@function" ;; ".type 2") cat >>confdefs.h <<\_ACEOF #define __ASM_FUNC(name) ".type " __ASM_NAME(name) ",2" _ACEOF - asm_func_header=".type $asm_name_prefix\" #name \",2" ;; + asm_func_header=".type $asm_name_prefix\" #name suffix \",2" ;; *) cat >>confdefs.h <<\_ACEOF #define __ASM_FUNC(name) "" @@ -17255,7 +17444,7 @@ fi { echo "$as_me:$LINENO: result: $ac_cv_c_cfi_support" >&5 echo "${ECHO_T}$ac_cv_c_cfi_support" >&6; } -asm_func_header=".globl $asm_name_prefix\" #name \"\\n\\t$asm_func_header\\n$asm_name_prefix\" #name \":\\n\\t" +asm_func_header=".globl $asm_name_prefix\" #name suffix \"\\n\\t$asm_func_header\\n$asm_name_prefix\" #name suffix \":\\n\\t" asm_func_trailer="" if test "$ac_cv_c_dot_previous" = "yes" then @@ -17274,16 +17463,26 @@ asm_func_code="$asm_func_header\" code \"$asm_func_trailer" if test "$ac_cv_c_asm_outside_funcs" = "yes" then cat >>confdefs.h <<_ACEOF -#define __ASM_GLOBAL_FUNC(name,code) asm(".text\n\t.align 4\n\t$asm_func_code"); +#define __ASM_DEFINE_FUNC(name,suffix,code) asm(".text\n\t.align 4\n\t$asm_func_code"); _ACEOF else cat >>confdefs.h <<_ACEOF -#define __ASM_GLOBAL_FUNC(name,code) void __asm_dummy_##name(void) { asm(".text\n\t.align 4\n\t$asm_func_code"); } +#define __ASM_DEFINE_FUNC(name,suffix,code) void __asm_dummy_##name(void) { asm(".text\n\t.align 4\n\t$asm_func_code"); } _ACEOF fi +cat >>confdefs.h <<\_ACEOF +#define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(name,"",code) +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define __ASM_STDCALL_FUNC(name,args,code) __ASM_DEFINE_FUNC(name,__ASM_STDCALL(args),code) +_ACEOF + + LDPATH="" @@ -27535,7 +27734,7 @@ exec 6>&1 # 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 1.1.23, which was +This file was extended by Wine $as_me 1.1.24, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -27588,7 +27787,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -Wine config.status 1.1.23 +Wine config.status 1.1.24 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.ac b/configure.ac index 24a9b070357..3b0e958651c 100644 --- a/configure.ac +++ b/configure.ac @@ -140,6 +140,14 @@ case $host in AC_SUBST(TARGETFLAGS,"-m32") enable_win16=${enable_win16:-yes} else + if test "x${GCC}" = "xyes" + then + AC_MSG_CHECKING([whether $CC supports __builtin_ms_va_list]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void func(__builtin_ms_va_list *args);]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([You need gcc >= 4.4 to build Wine as 64-bit.])]) + fi AC_SUBST(TARGETFLAGS,"-m64") fi ;; @@ -302,7 +310,6 @@ AC_CHECK_HEADERS(\ linux/serial.h \ linux/types.h \ linux/ucdrom.h \ - mach-o/dyld_images.h \ mach-o/nlist.h \ mach/mach.h \ mach/machine.h \ @@ -329,6 +336,7 @@ AC_CHECK_HEADERS(\ scsi/scsi_ioctl.h \ scsi/sg.h \ soundcard.h \ + stdbool.h \ stdint.h \ strings.h \ stropts.h \ @@ -479,6 +487,14 @@ AC_CHECK_HEADERS([linux/ipx.h],,, # include #endif]) +AC_CHECK_HEADERS([mach-o/dyld_images.h],,, + [#ifdef HAVE_STDBOOL_H + # include + #endif + #ifdef HAVE_STDINT_H + # include + #endif]) + AC_CHECK_HEADERS([resolv.h],,, [#include #ifdef HAVE_SYS_SOCKET_H @@ -991,7 +1007,7 @@ then CPPFLAGS="$ac_save_CPPFLAGS" fi WINE_NOTICE_WITH(hal,[test "x$ac_cv_lib_soname_hal" = "x"], - [libhal ${notice_platform}development files not found, no dynamic device support.]) + [libhal/libdbus ${notice_platform}development files not found, no dynamic device support.]) dnl **** Check for libgnutls **** if test "x$with_gnutls" != "xno" @@ -1411,6 +1427,19 @@ AC_CACHE_CHECK([whether external symbols need an underscore prefix], ac_cv_c_ext [if (ac_test) return 1], ac_cv_c_extern_prefix="yes",ac_cv_c_extern_prefix="no")) +case $host_cpu in + *i[[3456789]]86*) + AC_CACHE_CHECK([whether external symbols need stdcall decoration], ac_cv_c_stdcall_suffix, + WINE_TRY_ASM_LINK(["jmp _ac_test@4"], +[#ifndef _MSC_VER +#define __stdcall __attribute__((__stdcall__)) +#endif +int __stdcall ac_test(int i) { return i; }], + [if (ac_test(1)) return 1], + ac_cv_c_stdcall_suffix="yes",ac_cv_c_stdcall_suffix="no")) ;; + *) ac_cv_c_stdcall_suffix="no" ;; +esac + AH_TEMPLATE(__ASM_NAME,[Define to a macro to generate an assembly name from a C symbol]) if test "$ac_cv_c_extern_prefix" = "yes" then @@ -1421,6 +1450,14 @@ else asm_name_prefix="" fi +AH_TEMPLATE(__ASM_STDCALL,[Define to a macro to generate an stdcall suffix]) +if test "$ac_cv_c_stdcall_suffix" = "yes" +then + AC_DEFINE([__ASM_STDCALL(args)],["@" #args]) +else + AC_DEFINE([__ASM_STDCALL(args)],[""]) +fi + dnl **** Check how to define a function in assembly code **** AC_CACHE_CHECK([how to define a function in assembly code], ac_cv_asm_func_def, @@ -1437,13 +1474,13 @@ AH_TEMPLATE(__ASM_FUNC,[Define to a macro to generate an assembly function direc case "$ac_cv_asm_func_def" in ".def") AC_DEFINE([__ASM_FUNC(name)], [".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef"]) - asm_func_header=".def $asm_name_prefix\" #name \"; .scl 2; .type 32; .endef" ;; + asm_func_header=".def $asm_name_prefix\" #name suffix \"; .scl 2; .type 32; .endef" ;; ".type @function") AC_DEFINE([__ASM_FUNC(name)], [".type " __ASM_NAME(name) ",@function"]) - asm_func_header=".type $asm_name_prefix\" #name \",@function" ;; + asm_func_header=".type $asm_name_prefix\" #name suffix \",@function" ;; ".type 2") AC_DEFINE([__ASM_FUNC(name)], [".type " __ASM_NAME(name) ",2"]) - asm_func_header=".type $asm_name_prefix\" #name \",2" ;; + asm_func_header=".type $asm_name_prefix\" #name suffix \",2" ;; *) AC_DEFINE([__ASM_FUNC(name)], [""]) asm_func_header="" ;; @@ -1461,7 +1498,7 @@ AC_CACHE_CHECK([whether CFI directives are supported in assembly code], ac_cv_c_ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[asm(".text\nac_test:\t.cfi_startproc\n\t.long 0\n\t.cfi_endproc");]])], ac_cv_c_cfi_support="yes",ac_cv_c_cfi_support="no")) -asm_func_header=".globl $asm_name_prefix\" #name \"\\n\\t$asm_func_header\\n$asm_name_prefix\" #name \":\\n\\t" +asm_func_header=".globl $asm_name_prefix\" #name suffix \"\\n\\t$asm_func_header\\n$asm_name_prefix\" #name suffix \":\\n\\t" asm_func_trailer="" if test "$ac_cv_c_dot_previous" = "yes" then @@ -1475,13 +1512,17 @@ fi asm_func_code="$asm_func_header\" code \"$asm_func_trailer" -AH_TEMPLATE(__ASM_GLOBAL_FUNC,[Define to a macro to generate an assembly function]) +AH_TEMPLATE(__ASM_DEFINE_FUNC,[Define to a macro to define an assembly function]) if test "$ac_cv_c_asm_outside_funcs" = "yes" then - AC_DEFINE_UNQUOTED([__ASM_GLOBAL_FUNC(name,code)],[asm(".text\n\t.align 4\n\t$asm_func_code");]) + AC_DEFINE_UNQUOTED([__ASM_DEFINE_FUNC(name,suffix,code)],[asm(".text\n\t.align 4\n\t$asm_func_code");]) else - AC_DEFINE_UNQUOTED([__ASM_GLOBAL_FUNC(name,code)],[void __asm_dummy_##name(void) { asm(".text\n\t.align 4\n\t$asm_func_code"); }]) + AC_DEFINE_UNQUOTED([__ASM_DEFINE_FUNC(name,suffix,code)],[void __asm_dummy_##name(void) { asm(".text\n\t.align 4\n\t$asm_func_code"); }]) fi +AC_DEFINE([__ASM_GLOBAL_FUNC(name,code)],[__ASM_DEFINE_FUNC(name,"",code)], + [Define to a macro to generate an assembly function with C calling convention]) +AC_DEFINE([__ASM_STDCALL_FUNC(name,args,code)],[__ASM_DEFINE_FUNC(name,__ASM_STDCALL(args),code)], + [Define to a macro to generate an assembly function with stdcall calling convention]) dnl **** Platform-specific checks **** diff --git a/dlls/advapi32/lsa.c b/dlls/advapi32/lsa.c index cb1a6f3c2af..315cce99237 100644 --- a/dlls/advapi32/lsa.c +++ b/dlls/advapi32/lsa.c @@ -177,6 +177,8 @@ NTSTATUS WINAPI LsaEnumerateAccountRights( PULONG count) { FIXME("(%p,%p,%p,%p) stub\n", policy, sid, rights, count); + *rights = 0; + *count = 0; return STATUS_OBJECT_NAME_NOT_FOUND; } diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index 0aa92ce319e..773a839104b 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -54,7 +54,7 @@ static BYTE ParseAceStringType(LPCWSTR* StringAcl); static DWORD ParseAceStringRights(LPCWSTR* StringAcl); static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( LPCWSTR StringSecurityDescriptor, - SECURITY_DESCRIPTOR* SecurityDescriptor, + SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor, LPDWORD cBytes); static DWORD ParseAclStringFlags(LPCWSTR* StringAcl); @@ -4060,7 +4060,7 @@ lerr: */ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( LPCWSTR StringSecurityDescriptor, - SECURITY_DESCRIPTOR* SecurityDescriptor, + SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor, LPDWORD cBytes) { BOOL bret = FALSE; @@ -4073,7 +4073,7 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( *cBytes = sizeof(SECURITY_DESCRIPTOR); if (SecurityDescriptor) - lpNext = ((LPBYTE) SecurityDescriptor) + sizeof(SECURITY_DESCRIPTOR); + lpNext = (LPBYTE)(SecurityDescriptor + 1); while (*StringSecurityDescriptor) { @@ -4111,7 +4111,7 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( if (SecurityDescriptor) { - SecurityDescriptor->Owner = (PSID)(lpNext - (LPBYTE)SecurityDescriptor); + SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor; lpNext += bytes; /* Advance to next token */ } @@ -4129,7 +4129,7 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( if (SecurityDescriptor) { - SecurityDescriptor->Group = (PSID)(lpNext - (LPBYTE)SecurityDescriptor); + SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor; lpNext += bytes; /* Advance to next token */ } @@ -4149,7 +4149,7 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( if (SecurityDescriptor) { SecurityDescriptor->Control |= SE_DACL_PRESENT | flags; - SecurityDescriptor->Dacl = (PACL)(lpNext - (LPBYTE)SecurityDescriptor); + SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor; lpNext += bytes; /* Advance to next token */ } @@ -4169,7 +4169,7 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( if (SecurityDescriptor) { SecurityDescriptor->Control |= SE_SACL_PRESENT | flags; - SecurityDescriptor->Sacl = (PACL)(lpNext - (LPBYTE)SecurityDescriptor); + SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor; lpNext += bytes; /* Advance to next token */ } @@ -4265,7 +4265,7 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW( psd->Control |= SE_SELF_RELATIVE; if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor, - psd, &cBytes)) + (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes)) { LocalFree(psd); goto lend; diff --git a/dlls/advapi32/tests/lsa.c b/dlls/advapi32/tests/lsa.c index 39c91d38123..e69e4e1b563 100644 --- a/dlls/advapi32/tests/lsa.c +++ b/dlls/advapi32/tests/lsa.c @@ -37,6 +37,7 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); static HMODULE hadvapi32; static NTSTATUS (WINAPI *pLsaClose)(LSA_HANDLE); +static NTSTATUS (WINAPI *pLsaEnumerateAccountRights)(LSA_HANDLE,PSID,PLSA_UNICODE_STRING*,PULONG); static NTSTATUS (WINAPI *pLsaFreeMemory)(PVOID); static NTSTATUS (WINAPI *pLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE); static NTSTATUS (WINAPI *pLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*); @@ -47,12 +48,13 @@ static BOOL init(void) hadvapi32 = GetModuleHandle("advapi32.dll"); pLsaClose = (void*)GetProcAddress(hadvapi32, "LsaClose"); + pLsaEnumerateAccountRights = (void*)GetProcAddress(hadvapi32, "LsaEnumerateAccountRights"); pLsaFreeMemory = (void*)GetProcAddress(hadvapi32, "LsaFreeMemory"); pLsaOpenPolicy = (void*)GetProcAddress(hadvapi32, "LsaOpenPolicy"); pLsaQueryInformationPolicy = (void*)GetProcAddress(hadvapi32, "LsaQueryInformationPolicy"); pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA"); - if (pLsaClose && pLsaFreeMemory && pLsaOpenPolicy && pLsaQueryInformationPolicy && pConvertSidToStringSidA) + if (pLsaClose && pLsaEnumerateAccountRights && pLsaFreeMemory && pLsaOpenPolicy && pLsaQueryInformationPolicy && pConvertSidToStringSidA) return TRUE; return FALSE; @@ -73,9 +75,9 @@ static void test_lsa(void) /* try a more restricted access mask if necessary */ if (status == STATUS_ACCESS_DENIED) { - trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n"); - status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle); - ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status); + trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION|POLICY_LOOKUP_NAMES\n"); + status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION|POLICY_LOOKUP_NAMES, &handle); + ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION|POLICY_LOOKUP_NAMES) returned 0x%08x\n", status); } if (status == STATUS_SUCCESS) { @@ -83,6 +85,8 @@ static void test_lsa(void) PPOLICY_PRIMARY_DOMAIN_INFO primary_domain_info; PPOLICY_ACCOUNT_DOMAIN_INFO account_domain_info; PPOLICY_DNS_DOMAIN_INFO dns_domain_info; + HANDLE token; + BOOL ret; status = pLsaQueryInformationPolicy(handle, PolicyAuditEventsInformation, (PVOID*)&audit_events_info); if (status == STATUS_ACCESS_DENIED) @@ -174,6 +178,39 @@ static void test_lsa(void) pLsaFreeMemory((LPVOID)dns_domain_info); } + /* We need a valid SID to pass to LsaEnumerateAccountRights */ + ret = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &token ); + ok(ret, "Unable to obtain process token, error %u\n", GetLastError( )); + if (ret) { + char buffer[64]; + DWORD len; + TOKEN_USER *token_user = (TOKEN_USER *) buffer; + ret = GetTokenInformation( token, TokenUser, (LPVOID) token_user, sizeof(buffer), &len ); + ok(ret || GetLastError( ) == ERROR_INSUFFICIENT_BUFFER, "Unable to obtain token information, error %u\n", GetLastError( )); + if (! ret && GetLastError( ) == ERROR_INSUFFICIENT_BUFFER) { + trace("Resizing buffer to %u.\n", len); + token_user = LocalAlloc( 0, len ); + if (token_user != NULL) + ret = GetTokenInformation( token, TokenUser, (LPVOID) token_user, len, &len ); + } + + if (ret) { + PLSA_UNICODE_STRING rights; + ULONG rights_count; + rights = (PLSA_UNICODE_STRING) 0xdeadbeaf; + rights_count = 0xcafecafe; + status = pLsaEnumerateAccountRights(handle, token_user->User.Sid, &rights, &rights_count); + ok(status == STATUS_SUCCESS || status == STATUS_OBJECT_NAME_NOT_FOUND, "Unexpected status 0x%x\n", status); + if (status == STATUS_SUCCESS) + pLsaFreeMemory( rights ); + else + ok(rights == NULL && rights_count == 0, "Expected rights and rights_count to be set to 0 on failure\n"); + } + if (token_user != NULL && token_user != (TOKEN_USER *) buffer) + LocalFree( token_user ); + CloseHandle( token ); + } + status = pLsaClose(handle); ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status); } diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index b68629d3916..af52a3acf05 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -1237,10 +1237,11 @@ static void test_token_attr(void) Domain[0] = '\0'; ret = LookupAccountSid(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse); if (ret) - trace("\t%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes); - else - trace("\t%s, attr: 0x%08x LookupAccountSid failed with error %d\n", SidString, Groups->Groups[i].Attributes, GetLastError()); - LocalFree(SidString); + { + trace("%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes); + LocalFree(SidString); + } + else trace("attr: 0x%08x LookupAccountSid failed with error %d\n", Groups->Groups[i].Attributes, GetLastError()); } HeapFree(GetProcessHeap(), 0, Groups); diff --git a/dlls/appwiz.cpl/Ja.rc b/dlls/appwiz.cpl/Ja.rc index b0d5717a56a..0dd3fdd21f6 100644 --- a/dlls/appwiz.cpl/Ja.rc +++ b/dlls/appwiz.cpl/Ja.rc @@ -27,11 +27,11 @@ LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT STRINGTABLE { IDS_CPL_TITLE, "プログラムの追加と削除" - IDS_CPL_DESC, "Allows you to install new software, or remove existing software from your computer." + IDS_CPL_DESC, "新しいソフトウェアをインストールするか、既存のソフトウェアを削除することができます。" IDS_TAB1_TITLE, "アプリケーション" - IDS_UNINSTALL_FAILED, "Unable to execute the uninstaller, '%s'. Do you want to remove the uninstall entry for this program from the registry?" - IDS_NOT_SPECIFIED, "Not specified" + IDS_UNINSTALL_FAILED, "アンインストーラーを起動することができません。 '%s'. レジストリからアンインストールできるプログラム登録を削除しますか?" + IDS_NOT_SPECIFIED, "指定されません" IDS_COLUMN_NAME, "名前" IDS_COLUMN_PUBLISHER, "発行元" diff --git a/dlls/comctl32/comboex.c b/dlls/comctl32/comboex.c index 8a0652cdd1f..2156896fe92 100644 --- a/dlls/comctl32/comboex.c +++ b/dlls/comctl32/comboex.c @@ -860,10 +860,12 @@ COMBOEX_FindStringExact (COMBOEX_INFO *infoPtr, INT start, LPCWSTR str) /* now search from after starting loc and wrapping back to start */ for(i=start+1; ihwndNotify, WM_NOTIFY, - (WPARAM)lpnmh->hdr.idFrom, (LPARAM)lpnmh); + NMHEADERA nmhA; + HDITEMA hditema; + HD_TEXTFILTERA textfilter; + LPSTR text = NULL, filter = NULL; + LRESULT ret; + + /* on unicode format exit earlier */ + if (infoPtr->notifyFormat == NFR_UNICODE) + return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, + (WPARAM)lpnmh->hdr.idFrom, (LPARAM)lpnmh); + + /* header always supplies unicode notifications, + all we have to do is to convert strings to ANSI */ + nmhA = *(NMHEADERA*)lpnmh; + if (lpnmh->pitem) + { + hditema = *(HDITEMA*)lpnmh->pitem; + nmhA.pitem = &hditema; + /* convert item text */ + if (lpnmh->pitem->mask & HDI_TEXT) + { + Str_SetPtrWtoA(&hditema.pszText, lpnmh->pitem->pszText); + text = hditema.pszText; + } + /* convert filter text */ + if ((lpnmh->pitem->mask & HDI_FILTER) && (lpnmh->pitem->type == HDFT_ISSTRING) && + lpnmh->pitem->pvFilter) + { + hditema.pvFilter = &textfilter; + textfilter = *(HD_TEXTFILTERA*)(lpnmh->pitem->pvFilter); + Str_SetPtrWtoA(&textfilter.pszText, ((HD_TEXTFILTERW*)lpnmh->pitem->pvFilter)->pszText); + filter = textfilter.pszText; + } + } + nmhA.hdr.code = get_ansi_notification(lpnmh->hdr.code); + + ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, + (WPARAM)nmhA.hdr.idFrom, (LPARAM)&nmhA); + + /* cleanup */ + Free(text); + Free(filter); + + return ret; } static LRESULT notify_hdr(const LISTVIEW_INFO *infoPtr, INT code, LPNMHDR pnmh) @@ -804,22 +872,6 @@ static BOOL notify_deleteitem(const LISTVIEW_INFO *infoPtr, INT nItem) return IsWindow(hwnd); } -static int get_ansi_notification(UINT unicodeNotificationCode) -{ - switch (unicodeNotificationCode) - { - case LVN_BEGINLABELEDITW: return LVN_BEGINLABELEDITA; - case LVN_ENDLABELEDITW: return LVN_ENDLABELEDITA; - case LVN_GETDISPINFOW: return LVN_GETDISPINFOA; - case LVN_SETDISPINFOW: return LVN_SETDISPINFOA; - case LVN_ODFINDITEMW: return LVN_ODFINDITEMA; - case LVN_GETINFOTIPW: return LVN_GETINFOTIPA; - } - ERR("unknown notification %x\n", unicodeNotificationCode); - assert(FALSE); - return 0; -} - /* Send notification. depends on dispinfoW having same structure as dispinfoA. @@ -2249,7 +2301,13 @@ static void LISTVIEW_GetItemBox(const LISTVIEW_INFO *infoPtr, INT nItem, LPRECT } LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprcBox, 0, 0, 0, 0); - OffsetRect(lprcBox, Position.x + Origin.x, Position.y + Origin.y); + if (infoPtr->uView == LV_VIEW_DETAILS && infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT && + SendMessageW(infoPtr->hwndHeader, HDM_ORDERTOINDEX, 0, 0)) + { + OffsetRect(lprcBox, Origin.x, Position.y + Origin.y); + } + else + OffsetRect(lprcBox, Position.x + Origin.x, Position.y + Origin.y); } @@ -3721,12 +3779,11 @@ static BOOL set_sub_item(const LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, *bChanged = TRUE; } - if (lpLVItem->mask & LVIF_TEXT) - if (lpSubItem->hdr.pszText != lpLVItem->pszText) - { - textsetptrT(&lpSubItem->hdr.pszText, lpLVItem->pszText, isW); - *bChanged = TRUE; - } + if ((lpLVItem->mask & LVIF_TEXT) && textcmpWT(lpSubItem->hdr.pszText, lpLVItem->pszText, isW)) + { + textsetptrT(&lpSubItem->hdr.pszText, lpLVItem->pszText, isW); + *bChanged = TRUE; + } return TRUE; } @@ -4145,15 +4202,16 @@ static void LISTVIEW_RefreshReport(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, while(iterator_next(i)) { LISTVIEW_GetItemOrigin(infoPtr, i->nItem, &Position); - Position.x += Origin.x; Position.y += Origin.y; /* iterate through the invalidated columns */ while(iterator_next(&j)) { + LISTVIEW_GetHeaderRect(infoPtr, j.nItem, &rcItem); + Position.x = (j.nItem == 0) ? rcItem.left + Origin.x : Origin.x; + if (rgntype == COMPLEXREGION && !((infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) && j.nItem == 0)) { - LISTVIEW_GetHeaderRect(infoPtr, j.nItem, &rcItem); rcItem.top = 0; rcItem.bottom = infoPtr->nItemHeight; OffsetRect(&rcItem, Position.x, Position.y); @@ -6637,6 +6695,8 @@ static INT LISTVIEW_HitTest(const LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht, /* for top/bottom only */ bounds.left = LVIR_BOUNDS; LISTVIEW_GetItemRect(infoPtr, iItem, &bounds); + opt.x = lpht->pt.x - Origin.x; + opt.y = lpht->pt.y; for (j = 0; j < DPA_GetPtrCount(infoPtr->hdpaColumns); j++) { @@ -6644,7 +6704,7 @@ static INT LISTVIEW_HitTest(const LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht, bounds.left = pRect->left; bounds.right = pRect->right; - if (PtInRect(&bounds, lpht->pt)) + if (PtInRect(&bounds, opt)) { lpht->iSubItem = j; break; @@ -6670,7 +6730,11 @@ static INT LISTVIEW_HitTest(const LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht, opt.y = lpht->pt.y - Position.y - Origin.y; if (infoPtr->uView == LV_VIEW_DETAILS) + { rcBounds = rcBox; + if (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) + opt.x = lpht->pt.x - Origin.x; + } else { UnionRect(&rcBounds, &rcIcon, &rcLabel); @@ -7181,7 +7245,7 @@ static BOOL LISTVIEW_SetColumnT(const LISTVIEW_INFO *infoPtr, INT nColumn, { hdi.mask |= HDI_FORMAT; hdiget.mask = HDI_FORMAT; - if (Header_GetItemW(infoPtr->hwndHeader, nColumn, &hdiget)) + if (SendMessageW(infoPtr->hwndHeader, HDM_GETITEMW, nColumn, (LPARAM)&hdiget)) hdi.fmt = hdiget.fmt & HDF_STRING; } column_fill_hditem(infoPtr, &hdi, nColumn, lpColumn, isW); @@ -7317,7 +7381,7 @@ static BOOL LISTVIEW_SetColumnWidth(LISTVIEW_INFO *infoPtr, INT nColumn, INT cx) hdi.mask = HDI_TEXT; hdi.cchTextMax = DISP_TEXT_SIZE; hdi.pszText = szDispText; - if (Header_GetItemW(infoPtr->hwndHeader, nColumn, &hdi)) + if (SendMessageW(infoPtr->hwndHeader, HDM_GETITEMW, nColumn, (LPARAM)&hdi)) { HDC hdc = GetDC(infoPtr->hwndSelf); HFONT old_font = SelectObject(hdc, (HFONT)SendMessageW(infoPtr->hwndHeader, WM_GETFONT, 0, 0)); @@ -7339,7 +7403,7 @@ static BOOL LISTVIEW_SetColumnWidth(LISTVIEW_INFO *infoPtr, INT nColumn, INT cx) hdi.mask = HDI_WIDTH; hdi.cxy = cx; TRACE("hdi.cxy=%d\n", hdi.cxy); - return Header_SetItemW(infoPtr->hwndHeader, nColumn, &hdi); + return SendMessageW(infoPtr->hwndHeader, HDM_SETITEMW, nColumn, (LPARAM)&hdi); } /*** @@ -9221,11 +9285,16 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE LISTVIEW_DrawTrackLine(infoPtr); infoPtr->xTrackLine = -1; break; - + + case HDN_BEGINDRAG: + notify_forward_header(infoPtr, lpnmh); + return (infoPtr->dwLvExStyle & LVS_EX_HEADERDRAGDROP) == 0; + case HDN_ENDDRAG: FIXME("Changing column order not implemented\n"); + notify_forward_header(infoPtr, lpnmh); return TRUE; - + case HDN_ITEMCHANGINGW: case HDN_ITEMCHANGINGA: return notify_forward_header(infoPtr, lpnmh); @@ -9245,7 +9314,7 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE HDITEMW hdi; hdi.mask = HDI_WIDTH; - if (!Header_GetItemW(infoPtr->hwndHeader, lpnmh->iItem, &hdi)) return 0; + if (!SendMessageW(infoPtr->hwndHeader, HDM_GETITEMW, lpnmh->iItem, (LPARAM)&hdi)) return 0; cxy = hdi.cxy; } else @@ -9325,6 +9394,7 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE case HDN_DIVIDERDBLCLICKW: case HDN_DIVIDERDBLCLICKA: LISTVIEW_SetColumnWidth(infoPtr, lpnmh->iItem, LVSCW_AUTOSIZE); + notify_forward_header(infoPtr, lpnmh); break; } diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c index 3895bea378c..2c3ab64dba0 100644 --- a/dlls/comctl32/tests/listview.c +++ b/dlls/comctl32/tests/listview.c @@ -39,6 +39,40 @@ #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \ "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2) +#ifdef __i386__ +#define ARCH "x86" +#elif defined __x86_64__ +#define ARCH "amd64" +#else +#define ARCH "none" +#endif + +static const CHAR manifest_name[] = "cc6.manifest"; + +static const CHAR manifest[] = + "\n" + "\n" + " \n" + "Wine comctl32 test suite\n" + "\n" + " \n" + " \n" + "\n" + "\n" + "\n"; + static const WCHAR testparentclassW[] = {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0}; @@ -48,6 +82,8 @@ BOOL blockEdit; /* format reported to control: -1 falls to defproc, anything else returned */ INT notifyFormat; +/* indicates we're running < 5.80 version */ +BOOL g_is_below_5; static HWND subclass_editbox(HWND hwndListview); @@ -1118,7 +1154,7 @@ static void test_items(void) expect(TRUE, r); ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq, - "check callback text comparison rule", TRUE); + "check callback text comparison rule", FALSE); DestroyWindow(hwnd); } @@ -2244,21 +2280,28 @@ static void test_ownerdata(void) LVITEMA item; /* it isn't possible to set LVS_OWNERDATA after creation */ - hwnd = create_listview_control(0); - ok(hwnd != NULL, "failed to create a listview window\n"); - style = GetWindowLongPtrA(hwnd, GWL_STYLE); - ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n"); + if (g_is_below_5) + { + win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n"); + } + else + { + hwnd = create_listview_control(0); + ok(hwnd != NULL, "failed to create a listview window\n"); + style = GetWindowLongPtrA(hwnd, GWL_STYLE); + ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n"); - flush_sequences(sequences, NUM_MSG_SEQUENCES); + flush_sequences(sequences, NUM_MSG_SEQUENCES); - ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA); - ok(ret == style, "Expected set GWL_STYLE to succeed\n"); - ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, + ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA); + ok(ret == style, "Expected set GWL_STYLE to succeed\n"); + ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, "try to switch to LVS_OWNERDATA seq", FALSE); - style = GetWindowLongPtrA(hwnd, GWL_STYLE); - ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n"); - DestroyWindow(hwnd); + style = GetWindowLongPtrA(hwnd, GWL_STYLE); + ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n"); + DestroyWindow(hwnd); + } /* try to set LVS_OWNERDATA after creation just having it */ hwnd = create_listview_control(LVS_OWNERDATA); @@ -2275,20 +2318,27 @@ static void test_ownerdata(void) DestroyWindow(hwnd); /* try to remove LVS_OWNERDATA after creation just having it */ - hwnd = create_listview_control(LVS_OWNERDATA); - ok(hwnd != NULL, "failed to create a listview window\n"); - style = GetWindowLongPtrA(hwnd, GWL_STYLE); - ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n"); + if (g_is_below_5) + { + win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n"); + } + else + { + hwnd = create_listview_control(LVS_OWNERDATA); + ok(hwnd != NULL, "failed to create a listview window\n"); + style = GetWindowLongPtrA(hwnd, GWL_STYLE); + ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n"); - flush_sequences(sequences, NUM_MSG_SEQUENCES); + flush_sequences(sequences, NUM_MSG_SEQUENCES); - ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA); - ok(ret == style, "Expected set GWL_STYLE to succeed\n"); - ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, + ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA); + ok(ret == style, "Expected set GWL_STYLE to succeed\n"); + ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, "try to switch to LVS_OWNERDATA seq", FALSE); - style = GetWindowLongPtrA(hwnd, GWL_STYLE); - ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n"); - DestroyWindow(hwnd); + style = GetWindowLongPtrA(hwnd, GWL_STYLE); + ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n"); + DestroyWindow(hwnd); + } /* try select an item */ hwnd = create_listview_control(LVS_OWNERDATA); @@ -3177,7 +3227,7 @@ static void test_editbox(void) static void test_notifyformat(void) { - HWND hwnd; + HWND hwnd, header; DWORD r; hwnd = create_listview_control(0); @@ -3212,8 +3262,12 @@ static void test_notifyformat(void) notifyFormat = 0; hwnd = create_listview_control(0); ok(hwnd != NULL, "failed to create a listview window\n"); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "expected header to be created\n"); r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); + r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0); + expect(1, r); r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY); ok(r != 0, "Expected valid format\n"); @@ -3222,12 +3276,16 @@ static void test_notifyformat(void) expect(NFR_UNICODE, r); r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(1, r); + r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0); + expect(1, r); notifyFormat = NFR_ANSI; r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY); expect(NFR_ANSI, r); r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); + r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0); + expect(1, r); DestroyWindow(hwnd); @@ -3245,36 +3303,56 @@ static void test_notifyformat(void) notifyFormat = -1; hwnd = create_listview_controlW(0, hwndparentW); ok(hwnd != NULL, "failed to create a listview window\n"); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(1, r); + r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0); + expect(1, r); DestroyWindow(hwnd); /* recieving error code defaulting to ansi */ notifyFormat = 0; hwnd = create_listview_controlW(0, hwndparentW); ok(hwnd != NULL, "failed to create a listview window\n"); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); + r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0); + expect(1, r); DestroyWindow(hwnd); /* recieving ansi code from unicode window, use it */ notifyFormat = NFR_ANSI; hwnd = create_listview_controlW(0, hwndparentW); ok(hwnd != NULL, "failed to create a listview window\n"); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); + r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0); + expect(1, r); DestroyWindow(hwnd); /* unicode listview with ansi parent window */ notifyFormat = -1; hwnd = create_listview_controlW(0, hwndparent); ok(hwnd != NULL, "failed to create a listview window\n"); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); + r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0); + expect(1, r); DestroyWindow(hwnd); /* unicode listview with ansi parent window, return error code */ notifyFormat = 0; hwnd = create_listview_controlW(0, hwndparent); ok(hwnd != NULL, "failed to create a listview window\n"); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); + r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0); + expect(1, r); DestroyWindow(hwnd); DestroyWindow(hwndparentW); @@ -3309,11 +3387,160 @@ static void test_indentation(void) DestroyWindow(hwnd); } +static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param) +{ + return 0; +} + +static BOOL is_below_comctl_5(void) +{ + HWND hwnd; + BOOL ret; + + hwnd = create_listview_control(0); + ok(hwnd != NULL, "failed to create a listview window\n"); + insert_item(hwnd, 0); + + ret = SendMessage(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx); + + DestroyWindow(hwnd); + + return !ret; +} + +static BOOL load_v6_module(ULONG_PTR *pcookie) +{ + HANDLE hKernel32; + HANDLE (WINAPI *pCreateActCtxA)(ACTCTXA*); + BOOL (WINAPI *pActivateActCtx)(HANDLE, ULONG_PTR*); + + ACTCTXA ctx; + HANDLE hCtx; + BOOL ret; + HANDLE file; + DWORD written; + + hKernel32 = GetModuleHandleA("kernel32.dll"); + pCreateActCtxA = (void*)GetProcAddress(hKernel32, "CreateActCtxA"); + pActivateActCtx = (void*)GetProcAddress(hKernel32, "ActivateActCtx"); + if (!(pCreateActCtxA && pActivateActCtx)) + { + win_skip("Activation contexts unsupported. No version 6 tests possible.\n"); + return FALSE; + } + + /* create manifest */ + file = CreateFileA( manifest_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL ); + if (file != INVALID_HANDLE_VALUE) + { + ret = (WriteFile( file, manifest, sizeof(manifest)-1, &written, NULL ) && + written == sizeof(manifest)-1); + CloseHandle( file ); + if (!ret) + { + DeleteFileA( manifest_name ); + skip("Failed to fill manifest file. Skipping comctl32 V6 tests.\n"); + return FALSE; + } + else + trace("created %s\n", manifest_name); + } + else + { + skip("Failed to create manifest file. Skipping comctl32 V6 tests.\n"); + return FALSE; + } + + memset(&ctx, 0, sizeof(ctx)); + ctx.cbSize = sizeof(ctx); + ctx.lpSource = manifest_name; + + hCtx = pCreateActCtxA(&ctx); + ok(hCtx != 0, "Expected context handle\n"); + + ret = pActivateActCtx(hCtx, pcookie); + expect(TRUE, ret); + + if (!ret) + { + win_skip("A problem during context activation occured.\n"); + DeleteFileA(manifest_name); + } + + return ret; +} + +static void unload_v6_module(ULONG_PTR cookie) +{ + HANDLE hKernel32; + BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR); + + hKernel32 = GetModuleHandleA("kernel32.dll"); + pDeactivateActCtx = (void*)GetProcAddress(hKernel32, "DeactivateActCtx"); + if (!pDeactivateActCtx) + { + win_skip("Activation contexts unsupported\n"); + return; + } + + pDeactivateActCtx(0, cookie); + + DeleteFileA(manifest_name); +} + +static void test_get_set_view(void) +{ + HWND hwnd; + DWORD ret; + DWORD_PTR style; + + /* test style->view mapping */ + hwnd = create_listview_control(0); + ok(hwnd != NULL, "failed to create a listview window\n"); + + ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0); + expect(LV_VIEW_DETAILS, ret); + + style = GetWindowLongPtr(hwnd, GWL_STYLE); + /* LVS_ICON == 0 */ + SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_REPORT); + ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0); + expect(LV_VIEW_ICON, ret); + + style = GetWindowLongPtr(hwnd, GWL_STYLE); + SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_SMALLICON); + ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0); + expect(LV_VIEW_SMALLICON, ret); + + style = GetWindowLongPtr(hwnd, GWL_STYLE); + SetWindowLongPtr(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST); + ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0); + expect(LV_VIEW_LIST, ret); + + /* switching view doesn't touch window style */ + ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0); + expect(1, ret); + style = GetWindowLongPtr(hwnd, GWL_STYLE); + ok(style & LVS_LIST, "Expected style to be preserved\n"); + ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0); + expect(1, ret); + style = GetWindowLongPtr(hwnd, GWL_STYLE); + ok(style & LVS_LIST, "Expected style to be preserved\n"); + ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0); + expect(1, ret); + style = GetWindowLongPtr(hwnd, GWL_STYLE); + ok(style & LVS_LIST, "Expected style to be preserved\n"); + + DestroyWindow(hwnd); +} + START_TEST(listview) { HMODULE hComctl32; BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); + ULONG_PTR ctx_cookie; + hComctl32 = GetModuleHandleA("comctl32.dll"); pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); if (pInitCommonControlsEx) @@ -3333,6 +3560,8 @@ START_TEST(listview) ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent window", TRUE); flush_sequences(sequences, NUM_MSG_SEQUENCES); + g_is_below_5 = is_below_comctl_5(); + test_images(); test_checkboxes(); test_items(); @@ -3361,5 +3590,16 @@ START_TEST(listview) test_notifyformat(); test_indentation(); + if (!load_v6_module(&ctx_cookie)) + { + DestroyWindow(hwndparent); + return; + } + + /* comctl32 version 6 tests start here */ + test_get_set_view(); + + unload_v6_module(ctx_cookie); + DestroyWindow(hwndparent); } diff --git a/dlls/comctl32/tests/rebar.c b/dlls/comctl32/tests/rebar.c index d055d8aec8f..c819bc78f9b 100644 --- a/dlls/comctl32/tests/rebar.c +++ b/dlls/comctl32/tests/rebar.c @@ -104,7 +104,7 @@ static HWND build_toolbar(int nr, HWND hParent) case 1: iBitmapId = IDB_VIEW_SMALL_COLOR; break; case 2: iBitmapId = IDB_STD_SMALL_COLOR; break; } - ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGE failed\n"); + ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGES failed\n"); ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n"); return hToolbar; } @@ -310,7 +310,7 @@ static int rbsize_numtests = 0; count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \ compare(count, res->nBands, "%d"); \ for (i=0; inBands); i++) { \ - ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_ITEMRECT\n"); \ + ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_GETRECT\n"); \ if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \ check_rect("band", rc, res->bands[i].rc); \ rbi.cbSize = sizeof(REBARBANDINFO); \ @@ -790,12 +790,12 @@ static void bandinfo_test(void) rb.cyChild = 30; rb.cyMaxChild = 20; rb.cyIntegral = 10; - ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n"); + ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n"); expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0); rb.fMask = RBBIM_TEXT; rb.lpText = szABC; - ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n"); + ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n"); expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35); rb.cbSize = sizeof(REBARBANDINFO); @@ -806,21 +806,21 @@ static void bandinfo_test(void) rb.fMask = RBBIM_HEADERSIZE; rb.cxHeader = 50; - ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n"); + ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n"); expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50); rb.cxHeader = 5; - ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n"); + ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n"); expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5); rb.fMask = RBBIM_TEXT; rb.lpText = szABCD; - ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n"); + ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n"); expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5); rb.fMask = RBBIM_STYLE | RBBIM_TEXT; rb.fStyle = RBBS_VARIABLEHEIGHT; rb.lpText = szABC; - ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n"); + ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n"); expect_band_content(0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40); DestroyWindow(hRebar); diff --git a/dlls/comdlg32/filedlg.c b/dlls/comdlg32/filedlg.c index b8206243c19..6e7f985dbc9 100644 --- a/dlls/comdlg32/filedlg.c +++ b/dlls/comdlg32/filedlg.c @@ -1111,7 +1111,7 @@ static LRESULT FILEDLG95_OnWMSize(HWND hwnd, WPARAM wParam, LPARAM lParam) INT_PTR CALLBACK FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { #if 0 - TRACE("0x%04x 0x%04x\n", hwnd, uMsg); + TRACE("%p 0x%04x\n", hwnd, uMsg); #endif switch(uMsg) @@ -1146,6 +1146,9 @@ INT_PTR CALLBACK FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l FILEDLG95_ResizeControls(hwnd, wParam, lParam); FILEDLG95_FillControls(hwnd, wParam, lParam); + if(fodInfos->ofnInfos->Flags & OFN_EXPLORER) + SendCustomDlgNotificationMessage(hwnd,CDN_INITDONE); + if (fodInfos->ofnInfos->Flags & OFN_ENABLESIZING) { GetWindowRect( hwnd, &rc); @@ -1162,7 +1165,6 @@ INT_PTR CALLBACK FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l if(fodInfos->ofnInfos->Flags & OFN_EXPLORER) { - SendCustomDlgNotificationMessage(hwnd,CDN_INITDONE); SendCustomDlgNotificationMessage(hwnd,CDN_FOLDERCHANGE); SendCustomDlgNotificationMessage(hwnd,CDN_SELCHANGE); } diff --git a/dlls/comdlg32/tests/filedlg.c b/dlls/comdlg32/tests/filedlg.c index 9714dda1fe3..0cd1e634e7a 100644 --- a/dlls/comdlg32/tests/filedlg.c +++ b/dlls/comdlg32/tests/filedlg.c @@ -241,7 +241,7 @@ static void test_create_view_window2(void) ofn.lStructSize = sizeof(ofn); ofn.lpstrFile = filename; - ofn.nMaxFile = 1042; + ofn.nMaxFile = 1024; ofn.lpfnHook = create_view_window2_hook; ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; ret = GetOpenFileNameA(&ofn); @@ -258,7 +258,7 @@ static void test_create_view_template(void) ofn.lStructSize = sizeof(ofn); ofn.lpstrFile = filename; - ofn.nMaxFile = 1042; + ofn.nMaxFile = 1024; ofn.lpfnHook = (LPOFNHOOKPROC)template_hook; ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER| OFN_ENABLETEMPLATE; ofn.hInstance = GetModuleHandleA(NULL); @@ -270,9 +270,139 @@ static void test_create_view_template(void) ok(!ret, "CommDlgExtendedError returned %#x\n", ret); } +/* test cases for resizing of the file dialog */ +struct { + DWORD flags; + int resize_init; /* change in CDN_INITDONE handler */ + int resize_folderchg; /* change in CDN_FOLDERCHANGE handler */ + int resize_timer1; /* change in first WM_TIMER handler */ + int resize_check; /* expected change (in second WM_TIMER handler) */ + BOOL todo; /* mark that test todo_wine */ +} resize_testcases[] = { + { 0 , 10, 10, 10, 30,FALSE}, /* 0 */ + { 0 ,-10,-10,-10,-30,FALSE}, + { OFN_ENABLESIZING , 0, 0, 0, 0,FALSE}, + { OFN_ENABLESIZING , 0, 0,-10, 0,FALSE}, + { OFN_ENABLESIZING , 0, 0, 10, 10,FALSE}, + { OFN_ENABLESIZING , 0,-10, 0, 10, TRUE}, /* 5 */ + { OFN_ENABLESIZING , 0, 10, 0, 10,FALSE}, + { OFN_ENABLESIZING ,-10, 0, 0, 10, TRUE}, + { OFN_ENABLESIZING , 10, 0, 0, 10,FALSE}, + /* mark the end */ + { 0xffffffff } +}; + +static LONG_PTR WINAPI resize_template_hook(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static RECT initrc, rc; + static int index, count; + HWND parent = GetParent( dlg); + int resize; + switch( msg) + { + case WM_INITDIALOG: + { + DWORD style; + + index = ((OPENFILENAME*)lParam)->lCustData; + count = 0; + /* test style */ + style = GetWindowLong( parent, GWL_STYLE); + if( resize_testcases[index].flags & OFN_ENABLESIZING) + if( !(style & WS_SIZEBOX)) { + win_skip( "OFN_ENABLESIZING flag not supported.\n"); + PostMessage( parent, WM_COMMAND, IDCANCEL, 0); + } else + ok( style & WS_SIZEBOX, + "testid %d: dialog should have a WS_SIZEBOX style.\n", index); + else + ok( !(style & WS_SIZEBOX), + "testid %d: dialog should not have a WS_SIZEBOX style.\n", index); + break; + } + case WM_NOTIFY: + { + if(( (LPNMHDR)lParam)->code == CDN_INITDONE){ + GetWindowRect( parent, &initrc); + if( (resize = resize_testcases[index].resize_init)){ + MoveWindow( parent, initrc.left,initrc.top, initrc.right - initrc.left + resize, + initrc.bottom - initrc.top + resize, TRUE); + } + } else if(( (LPNMHDR)lParam)->code == CDN_FOLDERCHANGE){ + if( (resize = resize_testcases[index].resize_folderchg)){ + GetWindowRect( parent, &rc); + MoveWindow( parent, rc.left,rc.top, rc.right - rc.left + resize, + rc.bottom - rc.top + resize, TRUE); + } + SetTimer( dlg, 0, 100, 0); + } + break; + } + case WM_TIMER: + { + if( count == 0){ + if( (resize = resize_testcases[index].resize_timer1)){ + GetWindowRect( parent, &rc); + MoveWindow( parent, rc.left,rc.top, rc.right - rc.left + resize, + rc.bottom - rc.top + resize, TRUE); + } + } else if( count == 1){ + resize = resize_testcases[index].resize_check; + GetWindowRect( parent, &rc); + if( resize_testcases[index].todo){ + todo_wine { + ok( resize == rc.right - rc.left - initrc.right + initrc.left, + "testid %d size-x change %d expected %d\n", index, + rc.right - rc.left - initrc.right + initrc.left, resize); + ok( resize == rc.bottom - rc.top - initrc.bottom + initrc.top, + "testid %d size-y change %d expected %d\n", index, + rc.bottom - rc.top - initrc.bottom + initrc.top, resize); + } + }else{ + ok( resize == rc.right - rc.left - initrc.right + initrc.left, + "testid %d size-x change %d expected %d\n", index, + rc.right - rc.left - initrc.right + initrc.left, resize); + ok( resize == rc.bottom - rc.top - initrc.bottom + initrc.top, + "testid %d size-y change %d expected %d\n", index, + rc.bottom - rc.top - initrc.bottom + initrc.top, resize); + } + KillTimer( dlg, 0); + PostMessage( parent, WM_COMMAND, IDCANCEL, 0); + } + count++; + } + break; + } + return 0; +} + +static void test_resize(void) +{ + OPENFILENAME ofn = { sizeof(OPENFILENAME)}; + char filename[1024] = {0}; + DWORD ret; + int i; + + ofn.lpstrFile = filename; + ofn.nMaxFile = 1024; + ofn.lpfnHook = (LPOFNHOOKPROC) resize_template_hook; + ofn.hInstance = GetModuleHandle(NULL); + ofn.lpTemplateName = "template_sz"; + for( i = 0; resize_testcases[i].flags != 0xffffffff; i++) { + ofn.lCustData = i; + ofn.Flags = resize_testcases[i].flags | + OFN_ENABLEHOOK | OFN_EXPLORER| OFN_ENABLETEMPLATE ; + ret = GetOpenFileName(&ofn); + ok(!ret, "GetOpenFileName returned %#x\n", ret); + ret = CommDlgExtendedError(); + ok(!ret, "CommDlgExtendedError returned %#x\n", ret); + } +} + START_TEST(filedlg) { test_DialogCancel(); test_create_view_window2(); test_create_view_template(); + test_resize(); } diff --git a/dlls/comdlg32/tests/rsrc.rc b/dlls/comdlg32/tests/rsrc.rc index 51415fddb26..9600d85f14f 100644 --- a/dlls/comdlg32/tests/rsrc.rc +++ b/dlls/comdlg32/tests/rsrc.rc @@ -32,3 +32,19 @@ FONT 8, "MS Shell Dlg" LTEXT "",-1,28,16,204,31 EDITTEXT 56,65,2,200,12,ES_AUTOHSCROLL } + +/* Used by the resize file dialog tests. + * Keep this template small or get failures + * resizing on small desk tops. + * This will work with 640x480 pixels + */ +TEMPLATE_SZ DIALOG LOADONCALL MOVEABLE DISCARDABLE 5, 43, 300, 40 +STYLE WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +{ + LTEXT "Path:",-1,28,4,36,8 + LTEXT "Text1",-1,4,16,20,40 + LTEXT "Text2",-1,232,20,65,8 + LTEXT "",-1,28,16,204,31 + EDITTEXT 56,65,2,200,12,ES_AUTOHSCROLL +} diff --git a/dlls/crypt32/context.c b/dlls/crypt32/context.c index f7ebebb1c48..bb877995a1d 100644 --- a/dlls/crypt32/context.c +++ b/dlls/crypt32/context.c @@ -201,7 +201,7 @@ struct ContextList *ContextList_Create( return list; } -static inline struct list *ContextList_ContextToEntry(struct ContextList *list, +static inline struct list *ContextList_ContextToEntry(const struct ContextList *list, const void *context) { struct list *ret; @@ -213,7 +213,7 @@ static inline struct list *ContextList_ContextToEntry(struct ContextList *list, return ret; } -static inline void *ContextList_EntryToContext(struct ContextList *list, +static inline void *ContextList_EntryToContext(const struct ContextList *list, struct list *entry) { return (LPBYTE)entry - sizeof(LINK_CONTEXT) - list->contextSize; diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index 46d4797b680..07c63825b58 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -79,7 +79,7 @@ typedef struct _CRYPT_DIGESTED_DATA CRYPT_HASH_BLOB hash; } CRYPT_DIGESTED_DATA; -BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData, +BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData, void *pvData, DWORD *pcbData); typedef struct _CRYPT_SIGNED_INFO diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c index 14d193fb3a6..67a0155e584 100644 --- a/dlls/crypt32/encode.c +++ b/dlls/crypt32/encode.c @@ -1078,7 +1078,7 @@ static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType, } static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType, - CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc, + const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded, DWORD *pcbEncoded) { DWORD bytesNeeded = 0, lenBytes, size; @@ -1268,7 +1268,7 @@ static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType, return ret; } -static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn, +static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn, CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded, DWORD *pcbEncoded) { @@ -1881,7 +1881,7 @@ static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal( cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded); } -BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData, +BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData, void *pvData, DWORD *pcbData) { struct AsnEncodeSequenceItem items[] = { diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index a16eef12cf8..0b4027d17b0 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -1340,7 +1340,7 @@ static BOOL CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, } static HCRYPTMSG CSignedEncodeMsg_Open(DWORD dwFlags, - const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID, + const void *pvMsgEncodeInfo, LPCSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo) { const CMSG_SIGNED_ENCODE_INFO_WITH_CMS *info = pvMsgEncodeInfo; @@ -1553,7 +1553,7 @@ static BOOL CDecodeMsg_CopyData(CRYPT_DATA_BLOB *blob, const BYTE *pbData, return ret; } -static BOOL CDecodeMsg_DecodeDataContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob) +static BOOL CDecodeMsg_DecodeDataContent(CDecodeMsg *msg, const CRYPT_DER_BLOB *blob) { BOOL ret; CRYPT_DATA_BLOB *data; @@ -1613,7 +1613,7 @@ static inline void CRYPT_FixUpAlgorithmID(CRYPT_ALGORITHM_IDENTIFIER *id) } static BOOL CDecodeMsg_DecodeHashedContent(CDecodeMsg *msg, - CRYPT_DER_BLOB *blob) + const CRYPT_DER_BLOB *blob) { BOOL ret; CRYPT_DIGESTED_DATA *digestedData; diff --git a/dlls/crypt32/object.c b/dlls/crypt32/object.c index e880f089090..f505b7d804d 100644 --- a/dlls/crypt32/object.c +++ b/dlls/crypt32/object.c @@ -1080,7 +1080,7 @@ static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType, return ret; } -static BOOL CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB *blob, int id, +static BOOL CRYPT_FormatHexStringWithPrefix(const CRYPT_DATA_BLOB *blob, int id, LPWSTR str, DWORD *pcbStr) { WCHAR buf[MAX_STRING_RESOURCE_LEN]; @@ -1114,13 +1114,13 @@ static BOOL CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB *blob, int id, return ret; } -static BOOL CRYPT_FormatKeyId(CRYPT_DATA_BLOB *keyId, LPWSTR str, +static BOOL CRYPT_FormatKeyId(const CRYPT_DATA_BLOB *keyId, LPWSTR str, DWORD *pcbStr) { return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr); } -static BOOL CRYPT_FormatCertSerialNumber(CRYPT_DATA_BLOB *serialNum, LPWSTR str, +static BOOL CRYPT_FormatCertSerialNumber(const CRYPT_DATA_BLOB *serialNum, LPWSTR str, DWORD *pcbStr) { return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER, diff --git a/dlls/crypt32/str.c b/dlls/crypt32/str.c index d3bca2b7c0a..c0b76779a0a 100644 --- a/dlls/crypt32/str.c +++ b/dlls/crypt32/str.c @@ -341,7 +341,7 @@ static DWORD CRYPT_AddPrefixW(LPCWSTR prefix, LPWSTR psz, DWORD csz) static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 }; DWORD cert_name_to_str_with_indent(DWORD dwCertEncodingType, DWORD indentLevel, - PCERT_NAME_BLOB pName, DWORD dwStrType, LPWSTR psz, DWORD csz) + const CERT_NAME_BLOB *pName, DWORD dwStrType, LPWSTR psz, DWORD csz) { static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index e40619492a7..3e99800638c 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -5843,7 +5843,8 @@ static void test_decodePKCSAttribute(DWORD dwEncoding) * I doubt an app depends on that. */ ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || - GetLastError() == CRYPT_E_ASN1_CORRUPT || OSS_MORE_INPUT /* Win9x */), + GetLastError() == CRYPT_E_ASN1_CORRUPT || + GetLastError() == OSS_MORE_INPUT /* Win9x */), "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n", GetLastError()); ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, diff --git a/dlls/cryptdlg/cryptdlg_De.rc b/dlls/cryptdlg/cryptdlg_De.rc index 9e948fe5bfe..647171d8983 100644 --- a/dlls/cryptdlg/cryptdlg_De.rc +++ b/dlls/cryptdlg/cryptdlg_De.rc @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT +LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE { diff --git a/dlls/cryptui/cryptui_De.rc b/dlls/cryptui/cryptui_De.rc index e9c81822ae5..dcd7ac8e443 100644 --- a/dlls/cryptui/cryptui_De.rc +++ b/dlls/cryptui/cryptui_De.rc @@ -20,7 +20,7 @@ #pragma code_page(65001) -LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT +LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE { diff --git a/dlls/d3d8/cubetexture.c b/dlls/d3d8/cubetexture.c index 32511d6569c..84a1e412bad 100644 --- a/dlls/d3d8/cubetexture.c +++ b/dlls/d3d8/cubetexture.c @@ -201,22 +201,21 @@ static HRESULT WINAPI IDirect3DCubeTexture8Impl_GetLevelDesc(LPDIRECT3DCUBETEXTU TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = (WINED3DFORMAT *)&pDesc->Format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &pDesc->Size; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.MultiSampleQuality = NULL; /* DirectX9 only */ - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - EnterCriticalSection(&d3d8_cs); hr = IWineD3DCubeTexture_GetLevelDesc(This->wineD3DCubeTexture, Level, &wined3ddesc); LeaveCriticalSection(&d3d8_cs); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(pDesc->Format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->Size = wined3ddesc.size; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index c38d8cc8b30..9fa830d028d 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -166,10 +166,24 @@ extern const IWineD3DDeviceParentVtbl d3d8_wined3d_device_parent_vtbl; #define D3D8_INITIAL_HANDLE_TABLE_SIZE 64 #define D3D8_INVALID_HANDLE ~0U +enum d3d8_handle_type +{ + D3D8_HANDLE_FREE, + D3D8_HANDLE_VS, + D3D8_HANDLE_PS, + D3D8_HANDLE_SB, +}; + +struct d3d8_handle_entry +{ + void *object; + enum d3d8_handle_type type; +}; + struct d3d8_handle_table { - void **entries; - void **free_entries; + struct d3d8_handle_entry *entries; + struct d3d8_handle_entry *free_entries; UINT table_size; UINT entry_count; }; diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index eb7cc1610d4..ee41ab48049 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -69,6 +69,7 @@ D3DFORMAT d3dformat_from_wined3dformat(WINED3DFORMAT format) case WINED3DFMT_X8L8V8U8: return D3DFMT_X8L8V8U8; case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8; case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16; + case WINED3DFMT_W11V11U10: return D3DFMT_W11V11U10; case WINED3DFMT_A2W10V10U10: return D3DFMT_A2W10V10U10; case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE; case WINED3DFMT_D32: return D3DFMT_D32; @@ -119,6 +120,7 @@ WINED3DFORMAT wined3dformat_from_d3dformat(D3DFORMAT format) case D3DFMT_X8L8V8U8: return WINED3DFMT_X8L8V8U8; case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM; case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM; + case D3DFMT_W11V11U10: return WINED3DFMT_W11V11U10; case D3DFMT_A2W10V10U10: return WINED3DFMT_A2W10V10U10; case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE; case D3DFMT_D32: return WINED3DFMT_D32; @@ -163,14 +165,23 @@ static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, U } /* Handle table functions */ -static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object) +static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enum d3d8_handle_type type) { + struct d3d8_handle_entry *entry; + if (t->free_entries) { /* Use a free handle */ - void **entry = t->free_entries; - t->free_entries = *entry; - *entry = object; + entry = t->free_entries; + if (entry->type != D3D8_HANDLE_FREE) + { + ERR("Handle %u(%p) is in the free list, but has type %#x.\n", (entry - t->entries), entry, entry->type); + return D3D8_INVALID_HANDLE; + } + t->free_entries = entry->object; + entry->object = object; + entry->type = type; + return entry - t->entries; } @@ -178,34 +189,68 @@ static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object) { /* Grow the table */ UINT new_size = t->table_size + (t->table_size >> 1); - void **new_entries = HeapReAlloc(GetProcessHeap(), 0, t->entries, new_size * sizeof(void *)); - if (!new_entries) return D3D8_INVALID_HANDLE; + struct d3d8_handle_entry *new_entries = HeapReAlloc(GetProcessHeap(), + 0, t->entries, new_size * sizeof(*t->entries)); + if (!new_entries) + { + ERR("Failed to grow the handle table.\n"); + return D3D8_INVALID_HANDLE; + } t->entries = new_entries; t->table_size = new_size; } - t->entries[t->entry_count] = object; + entry = &t->entries[t->entry_count]; + entry->object = object; + entry->type = type; + return t->entry_count++; } -static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle) +static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type) { - void **entry, *object; + struct d3d8_handle_entry *entry; + void *object; - if (handle >= t->entry_count) return NULL; + if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count) + { + WARN("Invalid handle %u passed.\n", handle); + return NULL; + } entry = &t->entries[handle]; - object = *entry; - *entry = t->free_entries; + if (entry->type != type) + { + WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type); + return NULL; + } + + object = entry->object; + entry->object = t->free_entries; + entry->type = D3D8_HANDLE_FREE; t->free_entries = entry; return object; } -static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle) +static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type) { - if (handle >= t->entry_count) return NULL; - return t->entries[handle]; + struct d3d8_handle_entry *entry; + + if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count) + { + WARN("Invalid handle %u passed.\n", handle); + return NULL; + } + + entry = &t->entries[handle]; + if (entry->type != type) + { + WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type); + return NULL; + } + + return entry->object; } /* IDirect3D IUnknown parts follow: */ @@ -893,20 +938,18 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, ID /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */ - memset(&winedesc, 0, sizeof(winedesc)); - winedesc.Format = &srcFormat; - winedesc.Width = &srcWidth; - winedesc.Height = &srcHeight; - winedesc.Size = &srcSize; EnterCriticalSection(&d3d8_cs); IWineD3DSurface_GetDesc(Source->wineD3DSurface, &winedesc); + srcFormat = winedesc.format; + srcWidth = winedesc.width; + srcHeight = winedesc.height; + srcSize = winedesc.size; - winedesc.Format = &destFormat; - winedesc.Width = &destWidth; - winedesc.Height = &destHeight; - winedesc.Size = NULL; IWineD3DSurface_GetDesc(Dest->wineD3DSurface, &winedesc); + destFormat = winedesc.format; + destWidth = winedesc.width; + destHeight = winedesc.height; /* Check that the source and destination formats match */ if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) { @@ -1288,7 +1331,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface object->wineD3DStateBlock = wineD3DStateBlock; - *pToken = d3d8_allocate_handle(&This->handle_table, object); + *pToken = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_SB); LeaveCriticalSection(&d3d8_cs); if (*pToken == D3D8_INVALID_HANDLE) @@ -1312,7 +1355,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 ifa TRACE("(%p) %#x Relay\n", This, Token); EnterCriticalSection(&d3d8_cs); - pSB = d3d8_get_object(&This->handle_table, Token - 1); + pSB = d3d8_get_object(&This->handle_table, Token - 1, D3D8_HANDLE_SB); if (!pSB) { WARN("Invalid handle (%#x) passed.\n", Token); @@ -1332,7 +1375,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 i TRACE("(%p) %#x Relay\n", This, Token); EnterCriticalSection(&d3d8_cs); - pSB = d3d8_get_object(&This->handle_table, Token - 1); + pSB = d3d8_get_object(&This->handle_table, Token - 1, D3D8_HANDLE_SB); if (!pSB) { WARN("Invalid handle (%#x) passed.\n", Token); @@ -1351,7 +1394,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 if TRACE("(%p) Relay\n", This); EnterCriticalSection(&d3d8_cs); - pSB = d3d8_free_handle(&This->handle_table, Token - 1); + pSB = d3d8_free_handle(&This->handle_table, Token - 1, D3D8_HANDLE_SB); LeaveCriticalSection(&d3d8_cs); if (!pSB) @@ -1406,7 +1449,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(IDirect3DDevice8 *if return hr; } - *handle = d3d8_allocate_handle(&This->handle_table, object); + *handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_SB); LeaveCriticalSection(&d3d8_cs); if (*handle == D3D8_INVALID_HANDLE) @@ -1773,7 +1816,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 } EnterCriticalSection(&d3d8_cs); - handle = d3d8_allocate_handle(&This->handle_table, object); + handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_VS); if (handle == D3D8_INVALID_HANDLE) { ERR("Failed to allocate shader handle\n"); @@ -1799,7 +1842,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 { /* free up object */ FIXME("Call to IWineD3DDevice_CreateVertexShader failed\n"); - d3d8_free_handle(&This->handle_table, handle); + d3d8_free_handle(&This->handle_table, handle, D3D8_HANDLE_VS); IDirect3DVertexDeclaration8_Release(object->vertex_declaration); HeapFree(GetProcessHeap(), 0, object); *ppShader = 0; @@ -1906,7 +1949,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 ifa TRACE("Setting shader\n"); EnterCriticalSection(&d3d8_cs); - shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pShader); @@ -1972,7 +2015,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE EnterCriticalSection(&d3d8_cs); - shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pShader); @@ -2041,7 +2084,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3D EnterCriticalSection(&d3d8_cs); - shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); LeaveCriticalSection(&d3d8_cs); if (!shader) { @@ -2077,7 +2120,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEV EnterCriticalSection(&d3d8_cs); - shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pVertexShader); @@ -2180,7 +2223,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 i return hr; } - handle = d3d8_allocate_handle(&This->handle_table, object); + handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_PS); LeaveCriticalSection(&d3d8_cs); if (handle == D3D8_INVALID_HANDLE) { @@ -2211,7 +2254,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 ifac return hr; } - shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pShader); @@ -2262,12 +2305,12 @@ static HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 i EnterCriticalSection(&d3d8_cs); - shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pShader); LeaveCriticalSection(&d3d8_cs); - return D3DERR_INVALIDCALL; + return D3D_OK; } IWineD3DDevice_GetPixelShader(This->WineD3DDevice, &cur); @@ -2318,7 +2361,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVI TRACE("(%p) : pPixelShader %#x, pData %p, pSizeOfData %p\n", This, pPixelShader, pData, pSizeOfData); EnterCriticalSection(&d3d8_cs); - shader = d3d8_get_object(&This->handle_table, pPixelShader - (VS_HIGHESTFIXEDFXF + 1)); + shader = d3d8_get_object(&This->handle_table, pPixelShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS); if (!shader) { WARN("Invalid handle (%#x) passed.\n", pPixelShader); diff --git a/dlls/d3d8/surface.c b/dlls/d3d8/surface.c index 4b382ecbc98..c3aa11aef47 100644 --- a/dlls/d3d8/surface.c +++ b/dlls/d3d8/surface.c @@ -159,22 +159,21 @@ static HRESULT WINAPI IDirect3DSurface8Impl_GetDesc(LPDIRECT3DSURFACE8 iface, D3 HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - memset(&wined3ddesc, 0, sizeof(wined3ddesc)); - wined3ddesc.Format = (WINED3DFORMAT *)&pDesc->Format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &pDesc->Size; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - EnterCriticalSection(&d3d8_cs); hr = IWineD3DSurface_GetDesc(This->wineD3DSurface, &wined3ddesc); LeaveCriticalSection(&d3d8_cs); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(pDesc->Format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->Size = wined3ddesc.size; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index 0cd741d0558..f039a1b102f 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -1061,6 +1061,12 @@ static void test_shader(void) ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader); hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader); ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr); + + /* Check for double delete. */ + hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2); + ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr); + hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader); + ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr); } else { @@ -1083,6 +1089,12 @@ static void test_shader(void) hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader); ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr); + /* Check for double delete. */ + hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2); + ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr); + hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader); + ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr); + cleanup: if(pD3d) IDirect3D8_Release(pD3d); if(pDevice) IDirect3D8_Release(pDevice); diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index 19bf497f3d6..1850b838db3 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -645,11 +645,11 @@ static void offscreen_test(IDirect3DDevice8 *device) ok(hr == D3D_OK, "Clear failed, hr = %#08x\n", hr); hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture); - ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr); if(!offscreenTexture) { trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n"); hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture); - ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr); if(!offscreenTexture) { skip("Cannot create an offscreen render target\n"); goto out; @@ -776,7 +776,7 @@ static void alpha_test(IDirect3DDevice8 *device) ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr); hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture); - ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr); hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depthstencil); ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr = %#08x\n", hr); diff --git a/dlls/d3d8/texture.c b/dlls/d3d8/texture.c index c1bb91ece65..cbfc95a1bbf 100644 --- a/dlls/d3d8/texture.c +++ b/dlls/d3d8/texture.c @@ -200,22 +200,21 @@ static HRESULT WINAPI IDirect3DTexture8Impl_GetLevelDesc(LPDIRECT3DTEXTURE8 ifac WINED3DSURFACE_DESC wined3ddesc; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - memset(&wined3ddesc, 0, sizeof(wined3ddesc)); - wined3ddesc.Format = (WINED3DFORMAT *)&pDesc->Format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &pDesc->Size; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - EnterCriticalSection(&d3d8_cs); hr = IWineD3DTexture_GetLevelDesc(This->wineD3DTexture, Level, &wined3ddesc); LeaveCriticalSection(&d3d8_cs); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(pDesc->Format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->Size = wined3ddesc.size; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } diff --git a/dlls/d3d9/cubetexture.c b/dlls/d3d9/cubetexture.c index bbd171ea62a..90c174c2815 100644 --- a/dlls/d3d9/cubetexture.c +++ b/dlls/d3d9/cubetexture.c @@ -232,29 +232,26 @@ static void WINAPI IDirect3DCubeTexture9Impl_GenerateMipSubLevels(LPDIRECT3DCUBE /* IDirect3DCubeTexture9 Interface follow: */ static HRESULT WINAPI IDirect3DCubeTexture9Impl_GetLevelDesc(LPDIRECT3DCUBETEXTURE9 iface, UINT Level, D3DSURFACE_DESC* pDesc) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - WINED3DSURFACE_DESC wined3ddesc; - UINT tmpInt = -1; - WINED3DFORMAT format; + WINED3DSURFACE_DESC wined3ddesc; HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = &format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *) &pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - EnterCriticalSection(&d3d9_cs); hr = IWineD3DCubeTexture_GetLevelDesc(This->wineD3DCubeTexture, Level, &wined3ddesc); LeaveCriticalSection(&d3d9_cs); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->MultiSampleQuality = wined3ddesc.multisample_quality; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 9d02539a982..9d1c72e36f0 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -430,27 +430,15 @@ static HRESULT WINAPI reset_enum_callback(IWineD3DResource *resource, void *data WINED3DVOLUME_DESC volume_desc; D3DINDEXBUFFER_DESC index_desc; D3DVERTEXBUFFER_DESC vertex_desc; - WINED3DFORMAT dummy_format; - WINED3DMULTISAMPLE_TYPE dummy_multisampletype; - DWORD dummy_dword; - WINED3DPOOL pool = WINED3DPOOL_SCRATCH; /* a harmless pool */ + WINED3DPOOL pool; IDirect3DResource9 *parent; IWineD3DResource_GetParent(resource, (IUnknown **) &parent); type = IDirect3DResource9_GetType(parent); switch(type) { case D3DRTYPE_SURFACE: - surface_desc.Format = &dummy_format; - surface_desc.Type = &type; - surface_desc.Usage = &dummy_dword; - surface_desc.Pool = &pool; - surface_desc.Size = &dummy_dword; - surface_desc.MultiSampleType = &dummy_multisampletype; - surface_desc.MultiSampleQuality = &dummy_dword; - surface_desc.Width = &dummy_dword; - surface_desc.Height = &dummy_dword; - IWineD3DSurface_GetDesc((IWineD3DSurface *) resource, &surface_desc); + pool = surface_desc.pool; break; case D3DRTYPE_VOLUME: @@ -472,6 +460,7 @@ static HRESULT WINAPI reset_enum_callback(IWineD3DResource *resource, void *data * is a D3DPOOL_DEFAULT surface or volume as well */ default: + pool = WINED3DPOOL_SCRATCH; /* a harmless pool */ break; } @@ -791,13 +780,11 @@ static HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(LPDIRECT3DDEVICE9EX iface HRESULT hr; TRACE("(%p) Relay\n" , This); - memset(&desc, 0, sizeof(desc)); - desc.Usage = &usage; - desc.Pool = &pool; - desc.Type = &restype; - EnterCriticalSection(&d3d9_cs); IWineD3DSurface_GetDesc(surface->wineD3DSurface, &desc); + usage = desc.usage; + pool = desc.pool; + restype = desc.resource_type; /* This method is only allowed with surfaces that are render targets, or offscreen plain surfaces * in D3DPOOL_DEFAULT diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c index f95c387d560..70444b2a9f4 100644 --- a/dlls/d3d9/surface.c +++ b/dlls/d3d9/surface.c @@ -205,28 +205,25 @@ static HRESULT WINAPI IDirect3DSurface9Impl_GetContainer(LPDIRECT3DSURFACE9 ifac static HRESULT WINAPI IDirect3DSurface9Impl_GetDesc(LPDIRECT3DSURFACE9 iface, D3DSURFACE_DESC* pDesc) { IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; - WINED3DSURFACE_DESC wined3ddesc; - UINT tmpInt = -1; - WINED3DFORMAT format; + WINED3DSURFACE_DESC wined3ddesc; HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = &format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - EnterCriticalSection(&d3d9_cs); hr = IWineD3DSurface_GetDesc(This->wineD3DSurface, &wined3ddesc); LeaveCriticalSection(&d3d9_cs); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->MultiSampleQuality = wined3ddesc.multisample_quality; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 07a3531d3df..44ae50e2a7c 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -774,8 +774,7 @@ struct sVertexT { static void fog_test(IDirect3DDevice9 *device) { HRESULT hr; - DWORD color; - BYTE r, g, b; + D3DCOLOR color; float start = 0.0f, end = 1.0f; D3DCAPS9 caps; int i; @@ -909,13 +908,13 @@ static void fog_test(IDirect3DDevice9 *device) color = getPixelColor(device, 160, 360); ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color); color = getPixelColor(device, 160, 120); - ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with linear vertex fog has color %08x\n", color); + ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with linear vertex fog has color %08x\n", color); color = getPixelColor(device, 480, 120); ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color); if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) { color = getPixelColor(device, 480, 360); - ok(color == 0x0000FF00 || color == 0x0000FE00, "Transformed vertex with linear table fog has color %08x\n", color); + ok(color_match(color, 0x0000ff00, 1), "Transformed vertex with linear table fog has color %08x\n", color); } else { @@ -979,9 +978,9 @@ static void fog_test(IDirect3DDevice9 *device) } IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); color = getPixelColor(device, 160, 360); - ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color); + ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color); color = getPixelColor(device, 160, 120); - ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color); + ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color); color = getPixelColor(device, 480, 120); ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color); @@ -1026,21 +1025,16 @@ static void fog_test(IDirect3DDevice9 *device) } IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); color = getPixelColor(device, 160, 360); - ok(color == 0x0000FF00 || color == 0x0000FE00, "Reversed %s fog: z=0.1 has color 0x%08x, expected 0x0000ff00 or 0x0000fe00\n", mode, color); + ok(color_match(color, 0x0000ff00, 1), + "Reversed %s fog: z=0.1 has color 0x%08x, expected 0x0000ff00 or 0x0000fe00\n", mode, color); color = getPixelColor(device, 160, 120); - r = (color & 0x00ff0000) >> 16; - g = (color & 0x0000ff00) >> 8; - b = (color & 0x000000ff); - ok(r == 0x00 && g >= 0x29 && g <= 0x2d && b >= 0xd2 && b <= 0xd6, - "Reversed %s fog: z=0.7 has color 0x%08x\n", mode, color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x2b, 0xd4), 2), + "Reversed %s fog: z=0.7 has color 0x%08x\n", mode, color); color = getPixelColor(device, 480, 120); - r = (color & 0x00ff0000) >> 16; - g = (color & 0x0000ff00) >> 8; - b = (color & 0x000000ff); - ok(r == 0x00 && g >= 0xa8 && g <= 0xac && b >= 0x53 && b <= 0x57, - "Reversed %s fog: z=0.4 has color 0x%08x\n", mode, color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xaa, 0x55), 2), + "Reversed %s fog: z=0.4 has color 0x%08x\n", mode, color); color = getPixelColor(device, 480, 360); ok(color == 0x000000ff, "Reversed %s fog: z=0.9 has color 0x%08x, expected 0x000000ff\n", mode, color); @@ -5594,12 +5588,25 @@ static void vshader_version_varying_test(IDirect3DDevice9 *device) { color = getPixelColor(device, 160, 120); ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x1a, 0x34, 0x67), 1), "vs_3_0 returned color 0x%08x, expected 0x00193366\n", color); + /* Accept two ways of oFog handling: + * + * oFog is supposed to be a scalar. The pixel shader declares a vec4 oFog input and reads all components. + * The vertex shader writes oFog without a writemask. There are two ways windows drivers deal with this: + * + * 1) Keep oFog a scalar, and assign v4 = {oFog, 0, 0, 0}. oFog = 0x33, so the result color is 004d0067. + * This happens with software vertex processing and on Intel cards + * + * 2) Make oFog a vec4, and assign v4 = {oFog.x, oFog.y, oFog.z, oFog.w}. This way the result color is + * 0x004d339a. This happens on Nvidia Geforce 6+ cards + */ color = getPixelColor(device, 160, 360); - ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x00, 0x67), 1), + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x00, 0x67), 1) || + color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x33, 0x9a), 1), "vs_1_1 returned color 0x%08x, expected 0x004c0066\n", color); color = getPixelColor(device, 480, 360); - ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x00, 0x67), 1), - "vs_2_0 returned color 0x%08x, expected 0x004c0066\n", color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x00, 0x67), 1) || + color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x33, 0x9a), 1), + "vs_2_0 returned color 0x%08x, expected 0x004d0067 or 0x004d33a0\n", color); /* cleanup */ hr = IDirect3DDevice9_SetPixelShader(device, NULL); @@ -6666,7 +6673,7 @@ static void fog_srgbwrite_test(IDirect3DDevice9 *device) 1.0, 1.0, 0.1 }; HRESULT hr; - DWORD color; + D3DCOLOR color; IDirect3DDevice9_GetDirect3D(device, &d3d); /* Ask for srgb writing on D3DRTYPE_TEXTURE. Some Windows drivers do not report it on surfaces. @@ -6734,8 +6741,8 @@ static void fog_srgbwrite_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr); color = getPixelColor(device, 160, 360); - ok(color == 0x00808080 || color == 0x007f7f7f || color == 0x00818181, - "Fog with D3DRS_SRGBWRITEENABLE returned color 0x%08x, expected 0x00808080\n", color); + ok(color_match(color, 0x00808080, 1), + "Fog with D3DRS_SRGBWRITEENABLE returned color 0x%08x, expected 0x00808080\n", color); } static void alpha_test(IDirect3DDevice9 *device) diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index f0a9c38ad7e..10dd4984b88 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -229,30 +229,26 @@ static void WINAPI IDirect3DTexture9Impl_GenerateMipSubLevels(LPDIRECT3DTEXTURE9 /* IDirect3DTexture9 Interface follow: */ static HRESULT WINAPI IDirect3DTexture9Impl_GetLevelDesc(LPDIRECT3DTEXTURE9 iface, UINT Level, D3DSURFACE_DESC* pDesc) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - - WINED3DSURFACE_DESC wined3ddesc; - UINT tmpInt = -1; - HRESULT hr; - WINED3DFORMAT format; + WINED3DSURFACE_DESC wined3ddesc; + HRESULT hr; TRACE("(%p) Relay\n", This); - /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ - wined3ddesc.Format = &format; - wined3ddesc.Type = (WINED3DRESOURCETYPE *)&pDesc->Type; - wined3ddesc.Usage = &pDesc->Usage; - wined3ddesc.Pool = (WINED3DPOOL *) &pDesc->Pool; - wined3ddesc.Size = &tmpInt; /* required for d3d8 */ - wined3ddesc.MultiSampleType = (WINED3DMULTISAMPLE_TYPE *) &pDesc->MultiSampleType; - wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; - wined3ddesc.Width = &pDesc->Width; - wined3ddesc.Height = &pDesc->Height; - EnterCriticalSection(&d3d9_cs); hr = IWineD3DTexture_GetLevelDesc(This->wineD3DTexture, Level, &wined3ddesc); LeaveCriticalSection(&d3d9_cs); - if (SUCCEEDED(hr)) pDesc->Format = d3dformat_from_wined3dformat(format); + if (SUCCEEDED(hr)) + { + pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format); + pDesc->Type = wined3ddesc.resource_type; + pDesc->Usage = wined3ddesc.usage; + pDesc->Pool = wined3ddesc.pool; + pDesc->MultiSampleType = wined3ddesc.multisample_type; + pDesc->MultiSampleQuality = wined3ddesc.multisample_quality; + pDesc->Width = wined3ddesc.width; + pDesc->Height = wined3ddesc.height; + } return hr; } diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index 1c8eecbf77c..9721fc4141e 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -148,7 +148,7 @@ @ stub D3DXGenerateOutputDecl @ stdcall D3DXGeneratePMesh(ptr ptr ptr ptr long long ptr) d3dx8.D3DXGeneratePMesh @ stub D3DXGetDeclLength -@ stub D3DXGetDeclVertexSize +@ stdcall D3DXGetDeclVertexSize(ptr long) @ stdcall D3DXGetDriverLevel(ptr) @ stdcall D3DXGetFVFVertexSize(long) @ stdcall D3DXGetImageInfoFromFileA(str ptr) diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c index 0d3eb2ced1f..9b54ce03492 100644 --- a/dlls/d3dx9_36/mesh.c +++ b/dlls/d3dx9_36/mesh.c @@ -19,10 +19,13 @@ */ #include "config.h" +#include "wine/port.h" +#include "wine/debug.h" #include "windef.h" #include "wingdi.h" #include "d3dx9.h" +WINE_DEFAULT_DEBUG_CHANNEL(d3dx); /************************************************************************* * D3DXComputeBoundingBox @@ -128,6 +131,55 @@ UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF) } /************************************************************************* + * D3DXGetFVFVertexSize + */ +UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx) +{ + const D3DVERTEXELEMENT9 *element; + UINT size = 0; + + TRACE("decl %p, stream_idx %u\n", decl, stream_idx); + + if (!decl) return 0; + + for (element = decl; element->Stream != 0xff; ++element) + { + UINT type_size; + + if (element->Stream != stream_idx) continue; + + switch (element->Type) + { + case D3DDECLTYPE_FLOAT1: type_size = 1 * 4; break; + case D3DDECLTYPE_FLOAT2: type_size = 2 * 4; break; + case D3DDECLTYPE_FLOAT3: type_size = 3 * 4; break; + case D3DDECLTYPE_FLOAT4: type_size = 4 * 4; break; + case D3DDECLTYPE_D3DCOLOR: type_size = 4 * 1; break; + case D3DDECLTYPE_UBYTE4: type_size = 4 * 1; break; + case D3DDECLTYPE_SHORT2: type_size = 2 * 2; break; + case D3DDECLTYPE_SHORT4: type_size = 4 * 2; break; + case D3DDECLTYPE_UBYTE4N: type_size = 4 * 1; break; + case D3DDECLTYPE_SHORT2N: type_size = 2 * 2; break; + case D3DDECLTYPE_SHORT4N: type_size = 4 * 2; break; + case D3DDECLTYPE_USHORT2N: type_size = 2 * 2; break; + case D3DDECLTYPE_USHORT4N: type_size = 4 * 2; break; + case D3DDECLTYPE_UDEC3: type_size = 4; break; /* 3 * 10 bits + 2 padding */ + case D3DDECLTYPE_DEC3N: type_size = 4; break; + case D3DDECLTYPE_FLOAT16_2: type_size = 2 * 2; break; + case D3DDECLTYPE_FLOAT16_4: type_size = 4 * 2; break; + default: + FIXME("Unhandled element type %#x, size will be incorrect.\n", element->Type); + type_size = 0; + break; + } + + if (element->Offset + type_size > size) size = element->Offset + type_size; + } + + return size; +} + +/************************************************************************* * D3DXIntersectTri */ BOOL WINAPI D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist) diff --git a/dlls/d3dx9_36/tests/Makefile.in b/dlls/d3dx9_36/tests/Makefile.in index 5780d2a7d34..708287b31d8 100644 --- a/dlls/d3dx9_36/tests/Makefile.in +++ b/dlls/d3dx9_36/tests/Makefile.in @@ -8,6 +8,7 @@ IMPORTS = d3dx9 d3d9 user32 kernel32 CTESTS = \ core.c \ math.c \ + mesh.c \ shader.c \ texture.c diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c new file mode 100644 index 00000000000..d3d69943d1d --- /dev/null +++ b/dlls/d3dx9_36/tests/mesh.c @@ -0,0 +1,97 @@ +/* + * Copyright 2009 Henri Verbeet for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/test.h" +#include "d3dx9.h" + +static void test_get_decl_vertex_size(void) +{ + static const D3DVERTEXELEMENT9 declaration1[] = + { + {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + static const D3DVERTEXELEMENT9 declaration2[] = + { + {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + static const UINT sizes1[] = + { + 4, 8, 12, 16, + 4, 4, 4, 8, + 4, 4, 8, 4, + 4, 4, 8, 0, + }; + static const UINT sizes2[] = + { + 12, 16, 20, 24, + 12, 12, 16, 16, + }; + unsigned int i; + UINT size; + + size = D3DXGetDeclVertexSize(NULL, 0); + ok(size == 0, "Got size %#x, expected 0.\n", size); + + for (i = 0; i < 16; ++i) + { + size = D3DXGetDeclVertexSize(declaration1, i); + ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]); + } + + for (i = 0; i < 8; ++i) + { + size = D3DXGetDeclVertexSize(declaration2, i); + ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]); + } +} + +START_TEST(mesh) +{ + test_get_decl_vertex_size(); +} diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index e1941bef05f..9f8a612c374 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -80,11 +80,17 @@ struct hash_table_elt struct hash_table_elt* next; }; +struct hash_table_bucket +{ + struct hash_table_elt* first; + struct hash_table_elt* last; +}; + struct hash_table { unsigned num_elts; unsigned num_buckets; - struct hash_table_elt** buckets; + struct hash_table_bucket* buckets; struct pool* pool; }; diff --git a/dlls/dbghelp/storage.c b/dlls/dbghelp/storage.c index d6878625b90..4e62f114cb0 100644 --- a/dlls/dbghelp/storage.c +++ b/dlls/dbghelp/storage.c @@ -378,20 +378,26 @@ void hash_table_destroy(struct hash_table* ht) void hash_table_add(struct hash_table* ht, struct hash_table_elt* elt) { unsigned hash = hash_table_hash(elt->name, ht->num_buckets); - struct hash_table_elt** p; if (!ht->buckets) { - ht->buckets = pool_alloc(ht->pool, ht->num_buckets * sizeof(struct hash_table_elt*)); + ht->buckets = pool_alloc(ht->pool, ht->num_buckets * sizeof(struct hash_table_bucket)); assert(ht->buckets); - memset(ht->buckets, 0, ht->num_buckets * sizeof(struct hash_table_elt*)); + memset(ht->buckets, 0, ht->num_buckets * sizeof(struct hash_table_bucket)); } /* in some cases, we need to get back the symbols of same name in the order * in which they've been inserted. So insert new elements at the end of the list. */ - for (p = &ht->buckets[hash]; *p; p = &((*p)->next)); - *p = elt; + if (!ht->buckets[hash].first) + { + ht->buckets[hash].first = elt; + } + else + { + ht->buckets[hash].last->next = elt; + } + ht->buckets[hash].last = elt; elt->next = NULL; ht->num_elts++; } @@ -415,10 +421,10 @@ void hash_table_iter_init(const struct hash_table* ht, void* hash_table_iter_up(struct hash_table_iter* hti) { - if(!hti->ht->buckets) return NULL; + if (!hti->ht->buckets) return NULL; if (hti->element) hti->element = hti->element->next; while (!hti->element && hti->index < hti->last) - hti->element = hti->ht->buckets[++hti->index]; + hti->element = hti->ht->buckets[++hti->index].first; return hti->element; } diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index bfd716d0638..bd96418a578 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1664,10 +1664,8 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, WINED3DSURFACE_DESC Desc; WINED3DFORMAT Format; - WINED3DRESOURCETYPE Type; DWORD Usage; WINED3DPOOL Pool; - UINT Size; WINED3DMULTISAMPLE_TYPE MultiSampleType; DWORD MultiSampleQuality; @@ -1702,19 +1700,17 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, IWineD3DSurface_GetClipper(wineD3DSurface, &clipper); /* Get the surface properties */ - Desc.Format = &Format; - Desc.Type = &Type; - Desc.Usage = &Usage; - Desc.Pool = &Pool; - Desc.Size = &Size; - Desc.MultiSampleType = &MultiSampleType; - Desc.MultiSampleQuality = &MultiSampleQuality; - Desc.Width = &Width; - Desc.Height = &Height; - hr = IWineD3DSurface_GetDesc(wineD3DSurface, &Desc); if(hr != D3D_OK) return hr; + Format = Desc.format; + Usage = Desc.usage; + Pool = Desc.pool; + MultiSampleType = Desc.multisample_type; + MultiSampleQuality = Desc.multisample_quality; + Width = Desc.width; + Height = Desc.height; + if(swapchain) { /* If there's a swapchain, it owns the IParent interface. Create a new one for the * new surface @@ -1840,9 +1836,8 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, UINT level) { HRESULT hr; - UINT Width = 0, Height = 0; + UINT Width, Height; WINED3DFORMAT Format = WINED3DFMT_UNKNOWN; - WINED3DRESOURCETYPE ResType; DWORD Usage = 0; WINED3DSURFTYPE ImplType = This->ImplType; WINED3DSURFACE_DESC Desc; @@ -1850,12 +1845,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, IParentImpl *parImpl = NULL; WINED3DPOOL Pool = WINED3DPOOL_DEFAULT; - /* Dummies for GetDesc */ - WINED3DPOOL dummy_d3dpool; - WINED3DMULTISAMPLE_TYPE dummy_mst; - UINT dummy_uint; - DWORD dummy_dword; - if (TRACE_ON(ddraw)) { TRACE(" (%p) Requesting surface desc :\n", This); @@ -2058,16 +2047,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, * Don't use the Format choosen above, WineD3D might have * changed it */ - Desc.Format = &Format; - Desc.Type = &ResType; - Desc.Usage = &Usage; - Desc.Pool = &dummy_d3dpool; - Desc.Size = &dummy_uint; - Desc.MultiSampleType = &dummy_mst; - Desc.MultiSampleQuality = &dummy_dword; - Desc.Width = &Width; - Desc.Height = &Height; - (*ppSurf)->surface_desc.dwFlags |= DDSD_PIXELFORMAT; hr = IWineD3DSurface_GetDesc((*ppSurf)->WineD3DSurface, &Desc); if(hr != D3D_OK) @@ -2077,6 +2056,10 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, return hr; } + Format = Desc.format; + Width = Desc.width; + Height = Desc.height; + if(Format == WINED3DFMT_UNKNOWN) { FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN\n"); diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index bb3f4793ca0..261d6e399da 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -2558,7 +2558,6 @@ IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface, BOOL tex_alpha = FALSE; IWineD3DBaseTexture *tex = NULL; WINED3DSURFACE_DESC desc; - WINED3DFORMAT fmt; DDPIXELFORMAT ddfmt; hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, @@ -2567,13 +2566,11 @@ IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface, if(hr == WINED3D_OK && tex) { - memset(&desc, 0, sizeof(desc)); - desc.Format = &fmt; hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc); if (SUCCEEDED(hr)) { ddfmt.dwSize = sizeof(ddfmt); - PixelFormat_WineD3DtoDD(&ddfmt, fmt); + PixelFormat_WineD3DtoDD(&ddfmt, desc.format); if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE; } @@ -2833,7 +2830,6 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, BOOL tex_alpha = FALSE; IWineD3DBaseTexture *tex = NULL; WINED3DSURFACE_DESC desc; - WINED3DFORMAT fmt; DDPIXELFORMAT ddfmt; hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, @@ -2843,12 +2839,11 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, if(hr == WINED3D_OK && tex) { memset(&desc, 0, sizeof(desc)); - desc.Format = &fmt; hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc); if (SUCCEEDED(hr)) { ddfmt.dwSize = sizeof(ddfmt); - PixelFormat_WineD3DtoDD(&ddfmt, fmt); + PixelFormat_WineD3DtoDD(&ddfmt, desc.format); if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE; } @@ -4648,7 +4643,6 @@ IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface, BOOL tex_alpha = FALSE; IWineD3DBaseTexture *tex = NULL; WINED3DSURFACE_DESC desc; - WINED3DFORMAT fmt; DDPIXELFORMAT ddfmt; HRESULT result; @@ -4659,12 +4653,11 @@ IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface, if(result == WINED3D_OK && tex) { memset(&desc, 0, sizeof(desc)); - desc.Format = &fmt; result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc); if (SUCCEEDED(result)) { ddfmt.dwSize = sizeof(ddfmt); - PixelFormat_WineD3DtoDD(&ddfmt, fmt); + PixelFormat_WineD3DtoDD(&ddfmt, desc.format); if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE; } diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c index 3ff794d93b8..73e06579871 100644 --- a/dlls/ddraw/executebuffer.c +++ b/dlls/ddraw/executebuffer.c @@ -227,14 +227,14 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This, } else if(lpDevice->Handles[ci->u2.dwArg[0] - 1].type != DDrawHandle_Matrix) { ERR("Handle %d is not a matrix handle\n", ci->u2.dwArg[0]); } else { - if(ci->u1.drstRenderStateType == D3DTRANSFORMSTATE_WORLD) + if(ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_WORLD) lpDevice->world = ci->u2.dwArg[0]; - if(ci->u1.drstRenderStateType == D3DTRANSFORMSTATE_VIEW) + if(ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_VIEW) lpDevice->view = ci->u2.dwArg[0]; - if(ci->u1.drstRenderStateType == D3DTRANSFORMSTATE_PROJECTION) + if(ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_PROJECTION) lpDevice->proj = ci->u2.dwArg[0]; IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)lpDevice, - ci->u1.drstRenderStateType, (LPD3DMATRIX)lpDevice->Handles[ci->u2.dwArg[0] - 1].ptr); + ci->u1.dtstTransformStateType, (LPD3DMATRIX)lpDevice->Handles[ci->u2.dwArg[0] - 1].ptr); } instr += size; } diff --git a/dlls/dmime/Makefile.in b/dlls/dmime/Makefile.in index 9efdd080a54..1248e022741 100644 --- a/dlls/dmime/Makefile.in +++ b/dlls/dmime/Makefile.in @@ -13,7 +13,6 @@ C_SRCS = \ lyricstrack.c \ markertrack.c \ paramcontroltrack.c \ - patterntrack.c \ performance.c \ regsvr.c \ segment.c \ @@ -23,7 +22,6 @@ C_SRCS = \ sysextrack.c \ tempotrack.c \ timesigtrack.c \ - tool.c \ wavetrack.c RC_SRCS = version.rc diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index 308c2c8f46b..d3ad0e5956b 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -51,8 +51,6 @@ typedef struct IDirectMusicSegment8Impl IDirectMusicSegment8Impl; typedef struct IDirectMusicSegmentState8Impl IDirectMusicSegmentState8Impl; typedef struct IDirectMusicGraphImpl IDirectMusicGraphImpl; typedef struct IDirectMusicAudioPathImpl IDirectMusicAudioPathImpl; -typedef struct IDirectMusicTool8Impl IDirectMusicTool8Impl; -typedef struct IDirectMusicPatternTrackImpl IDirectMusicPatternTrackImpl; typedef struct IDirectMusicLyricsTrack IDirectMusicLyricsTrack; typedef struct IDirectMusicMarkerTrack IDirectMusicMarkerTrack; @@ -72,8 +70,6 @@ extern HRESULT WINAPI DMUSIC_CreateDirectMusicSegmentImpl (LPCGUID lpcGUID, LPVO extern HRESULT WINAPI DMUSIC_CreateDirectMusicSegmentStateImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter); extern HRESULT WINAPI DMUSIC_CreateDirectMusicGraphImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter); extern HRESULT WINAPI DMUSIC_CreateDirectMusicAudioPathImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DMUSIC_CreateDirectMusicToolImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DMUSIC_CreateDirectMusicPatternTrackImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter); extern HRESULT WINAPI DMUSIC_CreateDirectMusicLyricsTrack (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter); extern HRESULT WINAPI DMUSIC_CreateDirectMusicMarkerTrack (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter); @@ -237,28 +233,6 @@ struct IDirectMusicAudioPathImpl { }; /***************************************************************************** - * IDirectMusicTool8Impl implementation structure - */ -struct IDirectMusicTool8Impl { - /* IUnknown fields */ - const IDirectMusicTool8Vtbl *lpVtbl; - LONG ref; - - /* IDirectMusicTool8Impl fields */ -}; - -/***************************************************************************** - * IDirectMusicPatternTrackImpl implementation structure - */ -struct IDirectMusicPatternTrackImpl { - /* IUnknown fields */ - const IDirectMusicPatternTrackVtbl *lpVtbl; - LONG ref; - - /* IDirectMusicPatternTrackImpl fields */ -}; - -/***************************************************************************** * IDirectMusicLyricsTrack implementation structure */ struct IDirectMusicLyricsTrack diff --git a/dlls/dmime/patterntrack.c b/dlls/dmime/patterntrack.c deleted file mode 100644 index c8ed574db29..00000000000 --- a/dlls/dmime/patterntrack.c +++ /dev/null @@ -1,106 +0,0 @@ -/* IDirectMusicPatternTrack Implementation - * - * Copyright (C) 2003-2004 Rok Mandeljc - * - * This program 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 program 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 program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "dmime_private.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dmime); - -/* IDirectMusicPatternTrack IUnknown parts follow: */ -static HRESULT WINAPI IDirectMusicPatternTrackImpl_QueryInterface (LPDIRECTMUSICPATTERNTRACK iface, REFIID riid, LPVOID *ppobj) { - IDirectMusicPatternTrackImpl *This = (IDirectMusicPatternTrackImpl *)iface; - TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj); - - if (IsEqualIID (riid, &IID_IUnknown) || - IsEqualIID (riid, &IID_IDirectMusicPatternTrack)) { - IUnknown_AddRef(iface); - *ppobj = This; - return S_OK; - } - - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); - return E_NOINTERFACE; -} - -static ULONG WINAPI IDirectMusicPatternTrackImpl_AddRef (LPDIRECTMUSICPATTERNTRACK iface) { - IDirectMusicPatternTrackImpl *This = (IDirectMusicPatternTrackImpl *)iface; - ULONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p): AddRef from %d\n", This, ref - 1); - - DMIME_LockModule(); - - return ref; -} - -static ULONG WINAPI IDirectMusicPatternTrackImpl_Release (LPDIRECTMUSICPATTERNTRACK iface) { - IDirectMusicPatternTrackImpl *This = (IDirectMusicPatternTrackImpl *)iface; - ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p): ReleaseRef to %d\n", This, ref); - - if (ref == 0) { - HeapFree(GetProcessHeap(), 0, This); - } - - DMIME_UnlockModule(); - - return ref; -} - -/* IDirectMusicPatternTrack Interface follow: */ -static HRESULT WINAPI IDirectMusicPatternTrackImpl_CreateSegment (LPDIRECTMUSICPATTERNTRACK iface, IDirectMusicStyle* pStyle, IDirectMusicSegment** ppSegment) { - IDirectMusicPatternTrackImpl *This = (IDirectMusicPatternTrackImpl *)iface; - FIXME("(%p, %p, %p): stub\n", This, pStyle, ppSegment); - return S_OK; -} - -static HRESULT WINAPI IDirectMusicPatternTrackImpl_SetVariation (LPDIRECTMUSICPATTERNTRACK iface, IDirectMusicSegmentState* pSegState, DWORD dwVariationFlags, DWORD dwPart) { - IDirectMusicPatternTrackImpl *This = (IDirectMusicPatternTrackImpl *)iface; - FIXME("(%p, %p, %d, %d): stub\n", This, pSegState, dwVariationFlags, dwPart); - return S_OK; -} - -static HRESULT WINAPI IDirectMusicPatternTrackImpl_SetPatternByName (LPDIRECTMUSICPATTERNTRACK iface, IDirectMusicSegmentState* pSegState, WCHAR* wszName, IDirectMusicStyle* pStyle, DWORD dwPatternType, DWORD* pdwLength) { - IDirectMusicPatternTrackImpl *This = (IDirectMusicPatternTrackImpl *)iface; - FIXME("(%p, %p, %p, %p, %d, %p): stub\n", This, pSegState, wszName, pStyle, dwPatternType, pdwLength); - return S_OK; -} - -static const IDirectMusicPatternTrackVtbl DirectMusicPatternTrack_Vtbl = { - IDirectMusicPatternTrackImpl_QueryInterface, - IDirectMusicPatternTrackImpl_AddRef, - IDirectMusicPatternTrackImpl_Release, - IDirectMusicPatternTrackImpl_CreateSegment, - IDirectMusicPatternTrackImpl_SetVariation, - IDirectMusicPatternTrackImpl_SetPatternByName -}; - -/* for ClassFactory */ -HRESULT WINAPI DMUSIC_CreateDirectMusicPatternTrackImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) { - IDirectMusicPatternTrackImpl* track; - - track = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicPatternTrackImpl)); - if (NULL == track) { - *ppobj = NULL; - return E_OUTOFMEMORY; - } - track->lpVtbl = &DirectMusicPatternTrack_Vtbl; - track->ref = 0; /* will be inited by QueryInterface */ - - return IDirectMusicPatternTrackImpl_QueryInterface ((LPDIRECTMUSICPATTERNTRACK)track, lpcGUID, ppobj); -} diff --git a/dlls/dmime/tool.c b/dlls/dmime/tool.c deleted file mode 100644 index 1654bb8026e..00000000000 --- a/dlls/dmime/tool.c +++ /dev/null @@ -1,134 +0,0 @@ -/* IDirectMusicTool8 Implementation - * - * Copyright (C) 2003-2004 Rok Mandeljc - * - * This program 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 program 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 program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "dmime_private.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dmime); - -/* IDirectMusicTool8Impl IUnknown part: */ -static HRESULT WINAPI IDirectMusicTool8Impl_QueryInterface (LPDIRECTMUSICTOOL8 iface, REFIID riid, LPVOID *ppobj) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj); - if (IsEqualIID (riid, &IID_IUnknown) || - IsEqualIID (riid, &IID_IDirectMusicTool) || - IsEqualIID (riid, &IID_IDirectMusicTool8)) { - IUnknown_AddRef(iface); - *ppobj = This; - return S_OK; - } - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); - return E_NOINTERFACE; -} - -static ULONG WINAPI IDirectMusicTool8Impl_AddRef (LPDIRECTMUSICTOOL8 iface) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - ULONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p) : AddRef from %d\n", This, ref - 1); - - DMIME_LockModule(); - - return ref; -} - -static ULONG WINAPI IDirectMusicTool8Impl_Release (LPDIRECTMUSICTOOL8 iface) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) : ReleaseRef to %d\n", This, ref); - - if (ref == 0) { - HeapFree(GetProcessHeap(), 0, This); - } - - DMIME_UnlockModule(); - - return ref; -} - -/* IDirectMusicTool8Impl IDirectMusicTool part: */ -static HRESULT WINAPI IDirectMusicTool8Impl_Init (LPDIRECTMUSICTOOL8 iface, IDirectMusicGraph* pGraph) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - FIXME("(%p, %p): stub\n", This, pGraph); - return S_OK; -} - -static HRESULT WINAPI IDirectMusicTool8Impl_GetMsgDeliveryType (LPDIRECTMUSICTOOL8 iface, DWORD* pdwDeliveryType) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - FIXME("(%p, %p): stub\n", This, pdwDeliveryType); - return S_OK; -} - -static HRESULT WINAPI IDirectMusicTool8Impl_GetMediaTypeArraySize (LPDIRECTMUSICTOOL8 iface, DWORD* pdwNumElements) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - FIXME("(%p, %p): stub\n", This, pdwNumElements); - return S_OK; -} - -static HRESULT WINAPI IDirectMusicTool8Impl_GetMediaTypes (LPDIRECTMUSICTOOL8 iface, DWORD** padwMediaTypes, DWORD dwNumElements) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - FIXME("(%p, %p, %d): stub\n", This, padwMediaTypes, dwNumElements); - return S_OK; -} - -static HRESULT WINAPI IDirectMusicTool8Impl_ProcessPMsg (LPDIRECTMUSICTOOL8 iface, IDirectMusicPerformance* pPerf, DMUS_PMSG* pPMSG) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - FIXME("(%p, %p, %p): stub\n", This, pPerf, pPMSG); - return S_OK; -} - -static HRESULT WINAPI IDirectMusicTool8Impl_Flush (LPDIRECTMUSICTOOL8 iface, IDirectMusicPerformance* pPerf, DMUS_PMSG* pPMSG, REFERENCE_TIME rtTime) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - FIXME("(%p, %p, %p, 0x%s): stub\n", This, pPerf, pPMSG, wine_dbgstr_longlong(rtTime)); - return S_OK; -} - -/* IDirectMusicTool8Impl IDirectMusicTool8 part: */ -static HRESULT WINAPI IDirectMusicTool8Impl_Clone (LPDIRECTMUSICTOOL8 iface, IDirectMusicTool** ppTool) { - IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; - FIXME("(%p, %p): stub\n", This, ppTool); - return S_OK; -} - -static const IDirectMusicTool8Vtbl DirectMusicTool8_Vtbl = { - IDirectMusicTool8Impl_QueryInterface, - IDirectMusicTool8Impl_AddRef, - IDirectMusicTool8Impl_Release, - IDirectMusicTool8Impl_Init, - IDirectMusicTool8Impl_GetMsgDeliveryType, - IDirectMusicTool8Impl_GetMediaTypeArraySize, - IDirectMusicTool8Impl_GetMediaTypes, - IDirectMusicTool8Impl_ProcessPMsg, - IDirectMusicTool8Impl_Flush, - IDirectMusicTool8Impl_Clone -}; - -/* for ClassFactory */ -HRESULT WINAPI DMUSIC_CreateDirectMusicobjImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) { - IDirectMusicTool8Impl* obj; - - obj = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicTool8Impl)); - if (NULL == obj) { - *ppobj = NULL; - return E_OUTOFMEMORY; - } - obj->lpVtbl = &DirectMusicTool8_Vtbl; - obj->ref = 0; /* will be inited by QueryInterface */ - - return IDirectMusicTool8Impl_QueryInterface ((LPDIRECTMUSICTOOL8)obj, lpcGUID, ppobj); -} diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index 20d3f36ca88..ec5de204b08 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -28,6 +28,7 @@ #include "windef.h" #include "winbase.h" #include "winreg.h" +#include "ddrawgdi.h" #include "gdi_private.h" #include "wine/unicode.h" @@ -741,3 +742,13 @@ INT WINAPI NamedEscape( HDC hdc, LPCWSTR pDriver, INT nEscape, INT cbInput, LPCS lpszOutData); return 0; } + +/******************************************************************* + * DdQueryDisplaySettingsUniqueness [GDI32.@] + * GdiEntry13 [GDI32.@] + */ +ULONG WINAPI DdQueryDisplaySettingsUniqueness(VOID) +{ + FIXME("stub\n"); + return 0; +} diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec index 36a8fb142ec..6a67f44c7eb 100644 --- a/dlls/gdi32/gdi32.spec +++ b/dlls/gdi32/gdi32.spec @@ -174,6 +174,7 @@ # @ stub GdiDrawStream # @ stub GdiEndDocEMF # @ stub GdiEndPageEMF +@ stdcall GdiEntry13() # @ stub GdiFixUpHandle @ stdcall GdiFlush() # @ stub GdiFullscreenControl diff --git a/dlls/gdi32/tests/clipping.c b/dlls/gdi32/tests/clipping.c index eff87c3c463..06cb22a03c5 100644 --- a/dlls/gdi32/tests/clipping.c +++ b/dlls/gdi32/tests/clipping.c @@ -189,13 +189,13 @@ static void test_ExtCreateRegion(void) HRGN hrgn; XFORM xform; -if (0) /* crashes under Win9x */ -{ - SetLastError(0xdeadbeef); - hrgn = ExtCreateRegion(NULL, 0, NULL); - ok(!hrgn, "ExtCreateRegion should fail\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); -} + if (0) /* crashes under Win9x */ + { + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(NULL, 0, NULL); + ok(!hrgn, "ExtCreateRegion should fail\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + } rgn.data.rdh.dwSize = 0; rgn.data.rdh.iType = 0; diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c index 077977ec0de..6164050cbb4 100644 --- a/dlls/gdi32/tests/metafile.c +++ b/dlls/gdi32/tests/metafile.c @@ -1277,6 +1277,26 @@ static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr HeapFree(GetProcessHeap(), 0, eto1); HeapFree(GetProcessHeap(), 0, eto2); } + else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping")) + { + /* We have to take care of NT4 differences here */ + diff = memcmp(emr1, emr2, emr1->nSize); + if (diff) + { + ENHMETARECORD *emr_nt4; + + emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize); + memcpy(emr_nt4, emr2, emr2->nSize); + /* Correct the nRgnSize field */ + emr_nt4->dParm[5] = sizeof(RECT); + + diff = memcmp(emr1, emr_nt4, emr1->nSize); + if (!diff) + win_skip("Catered for NT4 differences\n"); + + HeapFree(GetProcessHeap(), 0, emr_nt4); + } + } else diff = memcmp(emr1, emr2, emr1->nSize); @@ -1302,15 +1322,22 @@ static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits, BOOL ignore_scaling) { unsigned char buf[MF_BUFSIZE]; - UINT mfsize, offset; + UINT mfsize, offset1, offset2, diff_nt4, diff_9x; const ENHMETAHEADER *emh1, *emh2; mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf); ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError()); + /* ENHMETAHEADER size could differ, depending on platform */ + diff_nt4 = sizeof(SIZEL); + diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD); + if (mfsize < MF_BUFSIZE) { - ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize); + ok(mfsize == bsize || + broken(mfsize == bsize - diff_nt4) || /* NT4 */ + broken(mfsize == bsize - diff_9x), /* Win9x/WinME */ + "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize); } else ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n", @@ -1325,23 +1352,32 @@ static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits, ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature); ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType); - ok(emh1->nSize == emh2->nSize, "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize); + ok(emh1->nSize == emh2->nSize || + broken(emh1->nSize - diff_nt4 == emh2->nSize) || + broken(emh1->nSize - diff_9x == emh2->nSize), + "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize); ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature); - ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes); - ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords); - - offset = emh1->nSize; - while (offset < emh1->nBytes) + ok(emh1->nBytes == emh2->nBytes || + broken(emh1->nBytes - diff_nt4 == emh2->nBytes) || + broken(emh1->nBytes - diff_9x == emh2->nBytes), + "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes); + ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords); + + offset1 = emh1->nSize; + offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */ + while (offset1 < emh1->nBytes) { - const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset); - const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset); + const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1); + const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2); - trace("EMF record %u, size %u/record %u, size %u\n", - emr1->iType, emr1->nSize, emr2->iType, emr2->nSize); + trace("%s: EMF record %u, size %u/record %u, size %u\n", + desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize); if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1; - offset += emr1->nSize; + /* We have already bailed out if iType or nSize don't match */ + offset1 += emr1->nSize; + offset2 += emr2->nSize; } return 0; } @@ -1793,7 +1829,9 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize); ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType); ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount); - ok(rgn1->data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize); + ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) || + broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */ + "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize); hrgn = CreateRectRgn(0, 0, 0, 0); @@ -1812,7 +1850,7 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs); ret = GetClipRgn(hdc, hrgn); - ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret); + ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret); /* Win9x returns empty clipping region */ if (is_win9x) return 1; @@ -1846,7 +1884,9 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize); ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType); ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount); - ok(rgn2.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize); + ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) || + broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */ + "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize); DeleteObject(hrgn); } diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 85ecf43646b..a9adac1637d 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -3875,6 +3875,6 @@ GpStatus WINGDIPAPI GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix ) { - FIXME("(%p %p %d %p %p %p %d %p): stub \n", graphics, text, length, font, brush, positions, flags, matrix); + FIXME("(%p %p %d %p %p %p %d %p): stub\n", graphics, text, length, font, brush, positions, flags, matrix); return NotImplemented; } diff --git a/dlls/gphoto2.ds/gphoto2_i.h b/dlls/gphoto2.ds/gphoto2_i.h index 2af61f4e5d8..517f794e181 100644 --- a/dlls/gphoto2.ds/gphoto2_i.h +++ b/dlls/gphoto2.ds/gphoto2_i.h @@ -44,7 +44,10 @@ # define UINT8 JPEG_UINT8 # define UINT16 JPEG_UINT16 # undef FAR +# undef HAVE_STDLIB_H # include +# undef HAVE_STDLIB_H +# define HAVE_STDLIB_H 1 # undef UINT16 #endif diff --git a/dlls/hal/hal.c b/dlls/hal/hal.c index 82ba80ca442..ed38e6c39a7 100644 --- a/dlls/hal/hal.c +++ b/dlls/hal/hal.c @@ -38,18 +38,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl); #ifdef __i386__ #define DEFINE_FASTCALL1_ENTRYPOINT( name ) \ - __ASM_GLOBAL_FUNC( name, \ + __ASM_STDCALL_FUNC( name, 4, \ "popl %eax\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME("__regs_") #name ) + "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(4)) #define DEFINE_FASTCALL2_ENTRYPOINT( name ) \ - __ASM_GLOBAL_FUNC( name, \ + __ASM_STDCALL_FUNC( name, 8, \ "popl %eax\n\t" \ "pushl %edx\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME("__regs_") #name ) + "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(8)) #endif diff --git a/dlls/hhctrl.ocx/Lt.rc b/dlls/hhctrl.ocx/Lt.rc new file mode 100644 index 00000000000..fed6b40e400 --- /dev/null +++ b/dlls/hhctrl.ocx/Lt.rc @@ -0,0 +1,63 @@ +/* + * HTML Help resources + * Lithuanian Language Support + * + * Copyright 2009 Aurimas Fišeras + * + * 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 + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_LITHUANIAN, SUBLANG_NEUTRAL + +STRINGTABLE +BEGIN + IDS_CONTENTS "&Turinys" + IDS_INDEX "&Rodyklė" + IDS_SEARCH "&Paieška" + IDS_FAVORITES "&Adresynas" +END + +STRINGTABLE +BEGIN + IDTB_EXPAND "Rodyti" + IDTB_CONTRACT "Slėpti" + IDTB_STOP "Stabdyti" + IDTB_REFRESH "Atnaujinti" + IDTB_BACK "Atgal" + IDTB_HOME "Į pradžią" + IDTB_SYNC "Sinchronizuoti" + IDTB_PRINT "Spausdinti" + IDTB_OPTIONS "Parinktys" + IDTB_FORWARD "Pirmyn" + IDTB_NOTES "IDTB_NOTES" + IDTB_BROWSE_FWD "IDTB_BROWSE_FWD" + IDTB_BROWSE_BACK "IDT_BROWSE_BACK" + IDTB_CONTENTS "IDTB_CONTENTS" + IDTB_INDEX "IDTB_INDEX" + IDTB_SEARCH "IDTB_SEARCH" + IDTB_HISTORY "IDTB_HISTORY" + IDTB_FAVORITES "IDTB_FAVORITES" + IDTB_JUMP1 "Nukreipimas1" + IDTB_JUMP2 "Nukreipimas2" + IDTB_CUSTOMIZE "Adaptuoti" + IDTB_ZOOM "Keisti mastelį" + IDTB_TOC_NEXT "IDTB_TOC_NEXT" + IDTB_TOC_PREV "IDTB_TOC_PREV" +END + +#pragma code_page(default) diff --git a/dlls/hhctrl.ocx/hhctrl.rc b/dlls/hhctrl.ocx/hhctrl.rc index e6dc1126418..8618819ed12 100644 --- a/dlls/hhctrl.ocx/hhctrl.rc +++ b/dlls/hhctrl.ocx/hhctrl.rc @@ -38,6 +38,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #include "Fi.rc" #include "Hu.rc" #include "Ko.rc" +#include "Lt.rc" #include "Nl.rc" #include "No.rc" #include "Pl.rc" diff --git a/dlls/jscript/date.c b/dlls/jscript/date.c index 1dd9b964937..3fd856eaebb 100644 --- a/dlls/jscript/date.c +++ b/dlls/jscript/date.c @@ -64,18 +64,18 @@ static const WCHAR getMinutesW[] = {'g','e','t','M','i','n','u','t','e','s',0}; static const WCHAR getUTCMinutesW[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0}; static const WCHAR getSecondsW[] = {'g','e','t','S','e','c','o','n','d','s',0}; static const WCHAR getUTCSecondsW[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0}; -static const WCHAR getMilisecondsW[] = {'g','e','t','M','i','l','i','s','e','c','o','n','d','s',0}; -static const WCHAR getUTCMilisecondsW[] = {'g','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0}; +static const WCHAR getMillisecondsW[] = {'g','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0}; +static const WCHAR getUTCMillisecondsW[] = {'g','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0}; static const WCHAR getTimezoneOffsetW[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0}; static const WCHAR setTimeW[] = {'s','e','t','T','i','m','e',0}; -static const WCHAR setMilisecondsW[] = {'s','e','t','M','i','l','i','s','e','c','o','n','d','s',0}; -static const WCHAR setUTCMilisecondsW[] = {'s','e','t','U','T','C','M','i','l','i','s','e','c','o','n','d','s',0}; +static const WCHAR setMillisecondsW[] = {'s','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0}; +static const WCHAR setUTCMillisecondsW[] = {'s','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0}; static const WCHAR setSecondsW[] = {'s','e','t','S','e','c','o','n','d','s',0}; static const WCHAR setUTCSecondsW[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0}; static const WCHAR setMinutesW[] = {'s','e','t','M','i','n','u','t','e','s',0}; static const WCHAR setUTCMinutesW[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0}; static const WCHAR setHoursW[] = {'s','e','t','H','o','u','r','s',0}; -static const WCHAR setUTCHoursW[] = {'s','e','t','H','o','u','r','s',0}; +static const WCHAR setUTCHoursW[] = {'s','e','t','U','T','C','H','o','u','r','s',0}; static const WCHAR setDateW[] = {'s','e','t','D','a','t','e',0}; static const WCHAR setUTCDateW[] = {'s','e','t','U','T','C','D','a','t','e',0}; static const WCHAR setMonthW[] = {'s','e','t','M','o','n','t','h',0}; @@ -210,19 +210,71 @@ static inline DOUBLE date_from_time(DOUBLE time) /* ECMA-262 3th Edition 15.9.1.6 */ static inline DOUBLE week_day(DOUBLE time) { + DOUBLE ret; + if(isnan(time)) return ret_nan(); - return (int)(day(time)+4) % 7; + ret = fmod(day(time)+4, 7); + if(ret<0) ret += 7; + + return ret; } /* ECMA-262 3th Edition 15.9.1.10 */ static inline DOUBLE hour_from_time(DOUBLE time) { + DOUBLE ret; + + if(isnan(time)) + return ret_nan(); + + ret = fmod(floor(time/MS_PER_HOUR), 24); + if(ret<0) ret += 24; + + return ret; +} + +/* ECMA-262 3th Edition 15.9.1.10 */ +static inline DOUBLE min_from_time(DOUBLE time) +{ + DOUBLE ret; + + if(isnan(time)) + return ret_nan(); + + ret = fmod(floor(time/MS_PER_MINUTE), 60); + if(ret<0) ret += 60; + + return ret; +} + +/* ECMA-262 3th Edition 15.9.1.10 */ +static inline DOUBLE sec_from_time(DOUBLE time) +{ + DOUBLE ret; + if(isnan(time)) return ret_nan(); - return (int)floor(time/MS_PER_HOUR) % 24; + ret = fmod(floor(time/1000), 60); + if(ret<0) ret += 60; + + return ret; +} + +/* ECMA-262 3th Edition 15.9.1.10 */ +static inline DOUBLE ms_from_time(DOUBLE time) +{ + DOUBLE ret; + + if(isnan(time)) + return ret_nan(); + + ret = fmod(time, 1000); + if(ret<0) ret += 1000; + + return ret; } /* ECMA-262 3rd Edition 15.9.1.14 */ @@ -520,46 +572,118 @@ static HRESULT Date_getUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPP return S_OK; } +/* ECMA-262 3th Edition 15.9.1.10 */ static HRESULT Date_getMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(retv) { + DateInstance *date = (DateInstance*)dispex; + DOUBLE time = date->time - date->bias*MS_PER_MINUTE; + + num_set_val(retv, min_from_time(time)); + } + return S_OK; } +/* ECMA-262 3th Edition 15.9.1.10 */ static HRESULT Date_getUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(retv) { + DateInstance *date = (DateInstance*)dispex; + num_set_val(retv, min_from_time(date->time)); + } + return S_OK; } +/* ECMA-262 3th Edition 15.9.1.10 */ static HRESULT Date_getSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(retv) { + DateInstance *date = (DateInstance*)dispex; + DOUBLE time = date->time - date->bias*MS_PER_MINUTE; + + num_set_val(retv, sec_from_time(time)); + } + return S_OK; } +/* ECMA-262 3th Edition 15.9.1.10 */ static HRESULT Date_getUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(retv) { + DateInstance *date = (DateInstance*)dispex; + num_set_val(retv, sec_from_time(date->time)); + } + return S_OK; } -static HRESULT Date_getMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, +/* ECMA-262 3th Edition 15.9.1.10 */ +static HRESULT Date_getMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(retv) { + DateInstance *date = (DateInstance*)dispex; + DOUBLE time = date->time - date->bias*MS_PER_MINUTE; + + num_set_val(retv, ms_from_time(time)); + } + return S_OK; } -static HRESULT Date_getUTCMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, +/* ECMA-262 3th Edition 15.9.1.10 */ +static HRESULT Date_getUTCMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(retv) { + DateInstance *date = (DateInstance*)dispex; + num_set_val(retv, ms_from_time(date->time)); + } + return S_OK; } static HRESULT Date_getTimezoneOffset(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, @@ -584,6 +708,7 @@ static HRESULT Date_setTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM } if(!arg_cnt(dp)) { + FIXME("throw ArgumentNotOptional\n"); if(retv) num_set_nan(retv); return S_OK; } @@ -601,60 +726,190 @@ static HRESULT Date_setTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM return S_OK; } -static HRESULT Date_setMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, +static HRESULT Date_setMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + VARIANT v; + HRESULT hres; + DateInstance *date; + + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(!arg_cnt(dp)) { + FIXME("throw ArgumentNotOptional\n"); + if(retv) num_set_nan(retv); + return S_OK; + } + + hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v); + if(FAILED(hres)) + return hres; + + date = (DateInstance*)dispex; + date->time = time_clip(date->time - ms_from_time(date->time) + num_val(&v)); + + if(retv) + num_set_val(retv, date->time); + + return S_OK; } -static HRESULT Date_setUTCMiliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, +static HRESULT Date_setUTCMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + return Date_setMilliseconds(dispex, lcid, flags, dp, retv, ei, caller); } static HRESULT Date_setSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + VARIANT v; + HRESULT hres; + DateInstance *date; + + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(!arg_cnt(dp)) { + FIXME("throw ArgumentNotOptional\n"); + if(retv) num_set_nan(retv); + return S_OK; + } + + hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v); + if(FAILED(hres)) + return hres; + + date = (DateInstance*)dispex; + date->time = time_clip(date->time - (sec_from_time(date->time) - num_val(&v))*1000.0); + + if(retv) + num_set_val(retv, date->time); + + return S_OK; } static HRESULT Date_setUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + return Date_setSeconds(dispex, lcid, flags, dp, retv, ei, caller); } static HRESULT Date_setMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + VARIANT v; + HRESULT hres; + DateInstance *date; + + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(!arg_cnt(dp)) { + FIXME("throw ArgumentNotOptional\n"); + if(retv) num_set_nan(retv); + return S_OK; + } + + hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v); + if(FAILED(hres)) + return hres; + + date = (DateInstance*)dispex; + date->time = time_clip(date->time - (min_from_time(date->time) - num_val(&v))*MS_PER_MINUTE); + + if(retv) + num_set_val(retv, date->time); + + return S_OK; } static HRESULT Date_setUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + return Date_setMinutes(dispex, lcid, flags, dp, retv, ei, caller); } static HRESULT Date_setHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + VARIANT v; + HRESULT hres; + DateInstance *date; + + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(!arg_cnt(dp)) { + FIXME("throw ArgumentNotOptional\n"); + if(retv) num_set_nan(retv); + return S_OK; + } + + hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v); + if(FAILED(hres)) + return hres; + + date = (DateInstance*)dispex; + date->time = time_clip(date->time + - (hour_from_time(date->time - date->bias*MS_PER_MINUTE) + - num_val(&v))*MS_PER_HOUR); + + if(retv) + num_set_val(retv, date->time); + + return S_OK; } static HRESULT Date_setUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + VARIANT v; + HRESULT hres; + DateInstance *date; + + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_DATE)) { + FIXME("throw TypeError\n"); + return E_FAIL; + } + + if(!arg_cnt(dp)) { + FIXME("throw ArgumentNotOptional\n"); + if(retv) num_set_nan(retv); + return S_OK; + } + + hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v); + if(FAILED(hres)) + return hres; + + date = (DateInstance*)dispex; + date->time = time_clip(date->time + - (hour_from_time(date->time) - num_val(&v))*MS_PER_HOUR); + + if(retv) + num_set_val(retv, date->time); + + return S_OK; } static HRESULT Date_setDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, @@ -711,7 +966,7 @@ static const builtin_prop_t Date_props[] = { {getDayW, Date_getDay, PROPF_METHOD}, {getFullYearW, Date_getFullYear, PROPF_METHOD}, {getHoursW, Date_getHours, PROPF_METHOD}, - {getMilisecondsW, Date_getMiliseconds, PROPF_METHOD}, + {getMillisecondsW, Date_getMilliseconds, PROPF_METHOD}, {getMinutesW, Date_getMinutes, PROPF_METHOD}, {getMonthW, Date_getMonth, PROPF_METHOD}, {getSecondsW, Date_getSeconds, PROPF_METHOD}, @@ -721,7 +976,7 @@ static const builtin_prop_t Date_props[] = { {getUTCDayW, Date_getUTCDay, PROPF_METHOD}, {getUTCFullYearW, Date_getUTCFullYear, PROPF_METHOD}, {getUTCHoursW, Date_getUTCHours, PROPF_METHOD}, - {getUTCMilisecondsW, Date_getUTCMiliseconds, PROPF_METHOD}, + {getUTCMillisecondsW, Date_getUTCMilliseconds, PROPF_METHOD}, {getUTCMinutesW, Date_getUTCMinutes, PROPF_METHOD}, {getUTCMonthW, Date_getUTCMonth, PROPF_METHOD}, {getUTCSecondsW, Date_getUTCSeconds, PROPF_METHOD}, @@ -731,7 +986,7 @@ static const builtin_prop_t Date_props[] = { {setDateW, Date_setDate, PROPF_METHOD}, {setFullYearW, Date_setFullYear, PROPF_METHOD}, {setHoursW, Date_setHours, PROPF_METHOD}, - {setMilisecondsW, Date_setMiliseconds, PROPF_METHOD}, + {setMillisecondsW, Date_setMilliseconds, PROPF_METHOD}, {setMinutesW, Date_setMinutes, PROPF_METHOD}, {setMonthW, Date_setMonth, PROPF_METHOD}, {setSecondsW, Date_setSeconds, PROPF_METHOD}, @@ -739,7 +994,7 @@ static const builtin_prop_t Date_props[] = { {setUTCDateW, Date_setUTCDate, PROPF_METHOD}, {setUTCFullYearW, Date_setUTCFullYear, PROPF_METHOD}, {setUTCHoursW, Date_setUTCHours, PROPF_METHOD}, - {setUTCMilisecondsW, Date_setUTCMiliseconds, PROPF_METHOD}, + {setUTCMillisecondsW, Date_setUTCMilliseconds, PROPF_METHOD}, {setUTCMinutesW, Date_setUTCMinutes, PROPF_METHOD}, {setUTCMonthW, Date_setUTCMonth, PROPF_METHOD}, {setUTCSecondsW, Date_setUTCSeconds, PROPF_METHOD}, diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index ceb314f2a99..ad4822c580e 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -951,25 +951,55 @@ ok(date.getUTCMonth() === 0, "date.getUTCMonth() = " + date.getUTCMonth()); ok(date.getUTCDate() === 1, "date.getUTCDate() = " + date.getUTCDate()); ok(date.getUTCDay() === 4, "date.getUTCDay() = " + date.getUTCDay()); ok(date.getUTCHours() === 0, "date.getUTCHours() = " + date.getUTCHours()); +ok(date.getUTCMinutes() === 0, "date.getUTCMinutes() = " + date.getUTCMinutes()); +ok(date.getUTCSeconds() === 0, "date.getUTCSeconds() = " + date.getUTCSeconds()); +ok(date.getUTCMilliseconds() === 0, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); date.setTime(60*24*60*60*1000); ok(date.getUTCFullYear() === 1970, "date.getUTCFullYear() = " + date.getUTCFullYear()); ok(date.getUTCMonth() === 2, "date.getUTCMonth() = " + date.getUTCMonth()); ok(date.getUTCDate() === 2, "date.getUTCDate() = " + date.getUTCDate()); ok(date.getUTCDay() === 1, "date.getUTCDay() = " + date.getUTCDay()); ok(date.getUTCHours() === 0, "date.getUTCHours() = " + date.getUTCHours()); -date.setTime(59*24*60*60*1000 + 4*365*24*60*60*1000 + 1000*60*60); +ok(date.getUTCMinutes() === 0, "date.getUTCMinutes() = " + date.getUTCMinutes()); +ok(date.getUTCSeconds() === 0, "date.getUTCSeconds() = " + date.getUTCSeconds()); +ok(date.getUTCMilliseconds() === 0, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); +date.setTime(59*24*60*60*1000 + 4*365*24*60*60*1000 + 60*60*1000 + 2*60*1000 + 2*1000 + 640); ok(date.getUTCFullYear() === 1974, "date.getUTCFullYear() = " + date.getUTCFullYear()); ok(date.getUTCMonth() === 1, "date.getUTCMonth() = " + date.getUTCMonth()); ok(date.getUTCMonth(123) === 1, "date.getUTCMonth() = " + date.getUTCMonth()); ok(date.getUTCDate() === 28, "date.getUTCDate() = " + date.getUTCDate()); ok(date.getUTCDay() === 4, "date.getUTCDay() = " + date.getUTCDay()); ok(date.getUTCHours() === 1, "date.getUTCHours() = " + date.getUTCHours()); +ok(date.getUTCMinutes() === 2, "date.getUTCMinutes() = " + date.getUTCMinutes()); +ok(date.getUTCSeconds() === 2, "date.getUTCSeconds() = " + date.getUTCSeconds()); +ok(date.getUTCMilliseconds() === 640, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); date.setTime(Infinity); ok(isNaN(date.getUTCFullYear()), "date.getUTCFullYear() is not NaN"); ok(isNaN(date.getUTCMonth()), "date.getUTCMonth() is not NaN"); ok(isNaN(date.getUTCDate()), "date.getUTCDate() is not NaN"); ok(isNaN(date.getUTCDay()), "date.getUTCDay() is not NaN"); ok(isNaN(date.getUTCHours()), "date.getUTCHours() is not NaN"); +ok(isNaN(date.getUTCMinutes()), "date.getUTCMinutes() is not NaN"); +ok(isNaN(date.getUTCSeconds()), "date.getUTCSeconds() is not NaN"); +ok(isNaN(date.getUTCMilliseconds()), "date.getUTCMilliseconds() is not NaN"); +ok(isNaN(date.setMilliseconds(0)), "date.setMilliseconds() is not NaN"); + +date.setTime(0); +date.setMilliseconds(-10, 2); +ok(date.getUTCMilliseconds() === 990, "date.getUTCMilliseconds() = " + date.getUTCMilliseconds()); +ok(date.setMilliseconds(10) === date.setUTCMilliseconds(10), "date.setUTCMilliseconds(10) !== date.setUTCMilliseconds(10)"); +date.setSeconds(-10); +ok(date.getUTCSeconds() === 50, "date.getUTCSeconds() = " + date.getUTCSeconds()); +ok(date.setSeconds(10) === date.setUTCSeconds(10), "date.setUTCSeconds(10) !== date.setUTCSeconds(10)"); +date.setMinutes(-10); +ok(date.getUTCMinutes() === 50, "date.getUTCMinutes() = " + date.getUTCMinutes()); +ok(date.setMinutes(10) === date.setUTCMinutes(10), "date.setUTCMinutes(10) !== date.setUTCMinutes(10)"); +date.setUTCHours(-10); +ok(date.getUTCHours() === 14, "date.getUTCHours() = " + date.getUTCHours()); +date.setUTCHours(-123); +ok(date.getTime() === -614989990, "date.getTime() = " + date.getTime()); +date.setHours(20); +ok(date.getHours() === 20, "date.getHours() = " + date.getHours()); ok(typeof(Math.PI) === "number", "typeof(Math.PI) = " + typeof(Math.PI)); ok(Math.floor(Math.PI*100) === 314, "Math.PI = " + Math.PI); diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c index 0caa0eadd17..34994af60c4 100644 --- a/dlls/kernel32/console.c +++ b/dlls/kernel32/console.c @@ -2680,14 +2680,7 @@ BOOL CONSOLE_GetEditionMode(HANDLE hConIn, int* mode) DWORD WINAPI GetConsoleAliasW(LPWSTR lpSource, LPWSTR lpTargetBuffer, DWORD TargetBufferLength, LPWSTR lpExename) { - static const WCHAR empty[] = {' ',0}; - FIXME("(%s,%p,%d,%s): stub\n", debugstr_w(lpSource), lpTargetBuffer, TargetBufferLength, debugstr_w(lpExename)); - - if(TargetBufferLength < sizeof(empty)/sizeof(WCHAR)) - return 0; - - lstrcpyW(lpTargetBuffer, empty); - - return 1; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; } diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index c78c7628f5c..93cf545308b 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -320,7 +320,7 @@ BOOL WINAPI HeapSetInformation( HANDLE heap, HEAP_INFORMATION_CLASS infoclass, P * size = 8*k, where k=1,2,3,... alloc's exactly the given size. * The Minolta DiMAGE Image Viewer heavily relies on this, corrupting * the output jpeg's > 1 MB if not */ -#define HGLOBAL_STORAGE 8 /* sizeof(HGLOBAL)*2 */ +#define HGLOBAL_STORAGE (sizeof(HGLOBAL)*2) #include "pshpack1.h" diff --git a/dlls/kernel32/ne_module.c b/dlls/kernel32/ne_module.c index 47c3f4dbe07..4b45e7bb654 100644 --- a/dlls/kernel32/ne_module.c +++ b/dlls/kernel32/ne_module.c @@ -2210,37 +2210,37 @@ void WINAPI MapHInstSL16( CONTEXT86 *context ) /*************************************************************************** * MapHInstLS (KERNEL32.@) */ -__ASM_GLOBAL_FUNC( MapHInstLS, +__ASM_STDCALL_FUNC( MapHInstLS, 0, "pushl %eax\n\t" - "call " __ASM_NAME("MapHModuleLS") "\n\t" + "call " __ASM_NAME("MapHModuleLS") __ASM_STDCALL(4) "\n\t" "ret" ) /*************************************************************************** * MapHInstSL (KERNEL32.@) */ -__ASM_GLOBAL_FUNC( MapHInstSL, +__ASM_STDCALL_FUNC( MapHInstSL, 0, "pushl %eax\n\t" - "call " __ASM_NAME("MapHModuleSL") "\n\t" + "call " __ASM_NAME("MapHModuleSL") __ASM_STDCALL(4) "\n\t" "ret" ) /*************************************************************************** * MapHInstLS_PN (KERNEL32.@) */ -__ASM_GLOBAL_FUNC( MapHInstLS_PN, +__ASM_STDCALL_FUNC( MapHInstLS_PN, 0, "testl %eax,%eax\n\t" "jz 1f\n\t" "pushl %eax\n\t" - "call " __ASM_NAME("MapHModuleLS") "\n" + "call " __ASM_NAME("MapHModuleLS") __ASM_STDCALL(4) "\n" "1:\tret" ) /*************************************************************************** * MapHInstSL_PN (KERNEL32.@) */ -__ASM_GLOBAL_FUNC( MapHInstSL_PN, +__ASM_STDCALL_FUNC( MapHInstSL_PN, 0, "andl $0xffff,%eax\n\t" "jz 1f\n\t" "pushl %eax\n\t" - "call " __ASM_NAME("MapHModuleSL") "\n" + "call " __ASM_NAME("MapHModuleSL") __ASM_STDCALL(4) "\n" "1:\tret" ) #endif /* __i386__ */ diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 31faf73244f..83d1aa5f68a 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -2215,13 +2215,13 @@ BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code ) * Nothing. */ #ifdef __i386__ -__ASM_GLOBAL_FUNC( ExitProcess, /* Shrinker depend on this particular ExitProcess implementation */ +__ASM_STDCALL_FUNC( ExitProcess, 4, /* Shrinker depend on this particular ExitProcess implementation */ "pushl %ebp\n\t" ".byte 0x8B, 0xEC\n\t" /* movl %esp, %ebp */ ".byte 0x6A, 0x00\n\t" /* pushl $0 */ ".byte 0x68, 0x00, 0x00, 0x00, 0x00\n\t" /* pushl $0 - 4 bytes immediate */ "pushl 8(%ebp)\n\t" - "call " __ASM_NAME("process_ExitProcess") "\n\t" + "call " __ASM_NAME("process_ExitProcess") __ASM_STDCALL(4) "\n\t" "leave\n\t" "ret $4" ) diff --git a/dlls/kernel32/selector.c b/dlls/kernel32/selector.c index c8841b1ad0b..4a642c04ca2 100644 --- a/dlls/kernel32/selector.c +++ b/dlls/kernel32/selector.c @@ -565,7 +565,7 @@ LPVOID WINAPI MapSLFix( SEGPTR sptr ) * Must not change EAX, hence defined as asm function. */ #ifdef __i386__ -__ASM_GLOBAL_FUNC( UnMapSLFixArray, "ret $8" ) +__ASM_STDCALL_FUNC( UnMapSLFixArray, 8, "ret $8" ) #endif @@ -595,22 +595,22 @@ BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldten /*********************************************************************** * SMapLS (KERNEL32.@) */ -__ASM_GLOBAL_FUNC( SMapLS, +__ASM_STDCALL_FUNC( SMapLS, 0, "xor %edx,%edx\n\t" "testl $0xffff0000,%eax\n\t" "jz 1f\n\t" "pushl %eax\n\t" - "call " __ASM_NAME("MapLS") "\n\t" + "call " __ASM_NAME("MapLS") __ASM_STDCALL(4) "\n\t" "movl %eax,%edx\n" "1:\tret" ) /*********************************************************************** * SUnMapLS (KERNEL32.@) */ -__ASM_GLOBAL_FUNC( SUnMapLS, +__ASM_STDCALL_FUNC( SUnMapLS, 0, "pushl %eax\n\t" /* preserve eax */ "pushl %eax\n\t" - "call " __ASM_NAME("UnMapLS") "\n\t" + "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t" "popl %eax\n\t" "ret" ) @@ -631,9 +631,9 @@ __ASM_GLOBAL_FUNC( SUnMapLS, * unravel them at SUnMapLS. We just store the segmented pointer there. */ #define DEFINE_SMapLS(n) \ - __ASM_GLOBAL_FUNC( SMapLS_IP_EBP_ ## n, \ + __ASM_STDCALL_FUNC( SMapLS_IP_EBP_ ## n, 0, \ "movl " #n "(%ebp),%eax\n\t" \ - "call " __ASM_NAME("SMapLS") "\n\t" \ + "call " __ASM_NAME("SMapLS") __ASM_STDCALL(4) "\n\t" \ "movl %edx," #n "(%ebp)\n\t" \ "ret" ) @@ -661,10 +661,10 @@ DEFINE_SMapLS(40) */ #define DEFINE_SUnMapLS(n) \ - __ASM_GLOBAL_FUNC( SUnMapLS_IP_EBP_ ## n, \ + __ASM_STDCALL_FUNC( SUnMapLS_IP_EBP_ ## n, 0, \ "pushl %eax\n\t" /* preserve eax */ \ "pushl " #n "(%ebp)\n\t" \ - "call " __ASM_NAME("UnMapLS") "\n\t" \ + "call " __ASM_NAME("UnMapLS") __ASM_STDCALL(4) "\n\t" \ "movl $0," #n "(%ebp)\n\t" \ "popl %eax\n\t" \ "ret" ) diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index ab596880afe..e45f1bcd556 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -2275,7 +2275,7 @@ BOOL WINAPI BindIoCompletionCallback( HANDLE FileHandle, LPOVERLAPPED_COMPLETION * InterlockedCompareExchange (KERNEL32.@) */ /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */ -__ASM_GLOBAL_FUNC(InterlockedCompareExchange, +__ASM_STDCALL_FUNC(InterlockedCompareExchange, 12, "movl 12(%esp),%eax\n\t" "movl 8(%esp),%ecx\n\t" "movl 4(%esp),%edx\n\t" @@ -2286,7 +2286,7 @@ __ASM_GLOBAL_FUNC(InterlockedCompareExchange, * InterlockedExchange (KERNEL32.@) */ /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */ -__ASM_GLOBAL_FUNC(InterlockedExchange, +__ASM_STDCALL_FUNC(InterlockedExchange, 8, "movl 8(%esp),%eax\n\t" "movl 4(%esp),%edx\n\t" "lock; xchgl %eax,(%edx)\n\t" @@ -2296,7 +2296,7 @@ __ASM_GLOBAL_FUNC(InterlockedExchange, * InterlockedExchangeAdd (KERNEL32.@) */ /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */ -__ASM_GLOBAL_FUNC(InterlockedExchangeAdd, +__ASM_STDCALL_FUNC(InterlockedExchangeAdd, 8, "movl 8(%esp),%eax\n\t" "movl 4(%esp),%edx\n\t" "lock; xaddl %eax,(%edx)\n\t" @@ -2306,7 +2306,7 @@ __ASM_GLOBAL_FUNC(InterlockedExchangeAdd, * InterlockedIncrement (KERNEL32.@) */ /* LONG WINAPI InterlockedIncrement( PLONG dest ); */ -__ASM_GLOBAL_FUNC(InterlockedIncrement, +__ASM_STDCALL_FUNC(InterlockedIncrement, 4, "movl 4(%esp),%edx\n\t" "movl $1,%eax\n\t" "lock; xaddl %eax,(%edx)\n\t" @@ -2316,7 +2316,7 @@ __ASM_GLOBAL_FUNC(InterlockedIncrement, /*********************************************************************** * InterlockedDecrement (KERNEL32.@) */ -__ASM_GLOBAL_FUNC(InterlockedDecrement, +__ASM_STDCALL_FUNC(InterlockedDecrement, 4, "movl 4(%esp),%edx\n\t" "movl $-1,%eax\n\t" "lock; xaddl %eax,(%edx)\n\t" diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c index 8cd2fb1e3e5..0b899c23ab6 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c @@ -568,7 +568,7 @@ HANDLE WINAPI GetCurrentThread(void) * SetLastError (KERNEL32.@) */ /* void WINAPI SetLastError( DWORD error ); */ -__ASM_GLOBAL_FUNC( SetLastError, +__ASM_STDCALL_FUNC( SetLastError, 4, "movl 4(%esp),%eax\n\t" ".byte 0x64\n\t" "movl %eax,0x34\n\t" @@ -579,21 +579,21 @@ __ASM_GLOBAL_FUNC( SetLastError, * GetLastError (KERNEL32.@) */ /* DWORD WINAPI GetLastError(void); */ -__ASM_GLOBAL_FUNC( GetLastError, ".byte 0x64\n\tmovl 0x34,%eax\n\tret" ) +__ASM_STDCALL_FUNC( GetLastError, 0, ".byte 0x64\n\tmovl 0x34,%eax\n\tret" ) /*********************************************************************** * GetCurrentProcessId (KERNEL.471) * GetCurrentProcessId (KERNEL32.@) */ /* DWORD WINAPI GetCurrentProcessId(void) */ -__ASM_GLOBAL_FUNC( GetCurrentProcessId, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" ) +__ASM_STDCALL_FUNC( GetCurrentProcessId, 0, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" ) /*********************************************************************** * GetCurrentThreadId (KERNEL.462) * GetCurrentThreadId (KERNEL32.@) */ /* DWORD WINAPI GetCurrentThreadId(void) */ -__ASM_GLOBAL_FUNC( GetCurrentThreadId, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" ) +__ASM_STDCALL_FUNC( GetCurrentThreadId, 0, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" ) #else /* __i386__ */ diff --git a/dlls/kernel32/thunk.c b/dlls/kernel32/thunk.c index 87856445bc5..be098b571fd 100644 --- a/dlls/kernel32/thunk.c +++ b/dlls/kernel32/thunk.c @@ -645,7 +645,7 @@ DEFINE_REGS_ENTRYPOINT( FT_Thunk, 0 ) "leave\n\t" #define DEFINE_FT_Exit(n) \ - __ASM_GLOBAL_FUNC( FT_Exit ## n, FT_EXIT_RESTORE_REGS "ret $" #n ) + __ASM_STDCALL_FUNC( FT_Exit ## n, 0, FT_EXIT_RESTORE_REGS "ret $" #n ) DEFINE_FT_Exit(0) DEFINE_FT_Exit(4) diff --git a/dlls/mapi32/tests/imalloc.c b/dlls/mapi32/tests/imalloc.c index 9ce94b0a04c..ec7557bc11f 100644 --- a/dlls/mapi32/tests/imalloc.c +++ b/dlls/mapi32/tests/imalloc.c @@ -106,6 +106,12 @@ START_TEST(imalloc) FreeLibrary(hMapi32); return; } + else if ((ret == E_FAIL) && (GetLastError() == ERROR_INVALID_HANDLE)) + { + win_skip("ScInitMapiUtil doesn't work on some Win98 and WinME systems\n"); + FreeLibrary(hMapi32); + return; + } test_IMalloc(); diff --git a/dlls/mapi32/tests/prop.c b/dlls/mapi32/tests/prop.c index 8226bead08a..8f4ff1ef050 100644 --- a/dlls/mapi32/tests/prop.c +++ b/dlls/mapi32/tests/prop.c @@ -239,7 +239,7 @@ static void test_UlPropSize(void) } res = pUlPropSize(&pv); - ok(res == exp || broken(!res) /* Win9x */, + ok(res == exp, "pt= %d: Expected %d, got %d\n", pt, exp, res); } } @@ -281,30 +281,30 @@ static void test_FPropContainsProp(void) pvRight.Value.lpszA = szFull; bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,full)[] match failed\n"); + ok(bRet == TRUE, "(full,full)[] match failed\n"); pvRight.Value.lpszA = szPrefix; bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); ok(bRet == FALSE, "(full,prefix)[] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); ok(bRet == TRUE, "(full,prefix)[PREFIX] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,prefix)[SUBSTRING] match failed\n"); + ok(bRet == TRUE, "(full,prefix)[SUBSTRING] match failed\n"); pvRight.Value.lpszA = szPrefixLower; bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); ok(bRet == FALSE, "(full,prefixlow)[PREFIX] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); ok(bRet == FALSE, "(full,prefixlow)[SUBSTRING] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n"); + ok(bRet == TRUE, "(full,prefixlow)[PREFIX|IGNORECASE] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n"); + ok(bRet == TRUE, "(full,prefixlow)[SUBSTRING|IGNORECASE] match failed\n"); pvRight.Value.lpszA = szSubstring; bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); ok(bRet == FALSE, "(full,substr)[] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); ok(bRet == FALSE, "(full,substr)[PREFIX] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,substr)[SUBSTRING] match failed\n"); + ok(bRet == TRUE, "(full,substr)[SUBSTRING] match failed\n"); pvRight.Value.lpszA = szSubstringLower; bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); ok(bRet == FALSE, "(full,substrlow)[PREFIX] match failed\n"); @@ -313,10 +313,10 @@ static void test_FPropContainsProp(void) bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX|FL_IGNORECASE); ok(bRet == FALSE, "(full,substrlow)[PREFIX|IGNORECASE] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING|FL_IGNORECASE); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n"); + ok(bRet == TRUE, "(full,substrlow)[SUBSTRING|IGNORECASE] match failed\n"); pvRight.Value.lpszA = szFullLower; bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING|FL_IGNORECASE); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "(full,fulllow)[IGNORECASE] match failed\n"); + ok(bRet == TRUE, "(full,fulllow)[IGNORECASE] match failed\n"); pvLeft.ulPropTag = pvRight.ulPropTag = PT_BINARY; pvLeft.Value.bin.lpb = (LPBYTE)szFull; @@ -324,15 +324,15 @@ static void test_FPropContainsProp(void) pvLeft.Value.bin.cb = pvRight.Value.bin.cb = strlen(szFull); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "bin(full,full)[] match failed\n"); + ok(bRet == TRUE, "bin(full,full)[] match failed\n"); pvRight.Value.bin.lpb = (LPBYTE)szPrefix; pvRight.Value.bin.cb = strlen(szPrefix); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_FULLSTRING); ok(bRet == FALSE, "bin(full,prefix)[] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "bin(full,prefix)[PREFIX] match failed\n"); + ok(bRet == TRUE, "bin(full,prefix)[PREFIX] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "bin(full,prefix)[SUBSTRING] match failed\n"); + ok(bRet == TRUE, "bin(full,prefix)[SUBSTRING] match failed\n"); pvRight.Value.bin.lpb = (LPBYTE)szPrefixLower; pvRight.Value.bin.cb = strlen(szPrefixLower); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); @@ -350,7 +350,7 @@ static void test_FPropContainsProp(void) bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); ok(bRet == FALSE, "bin(full,substr)[PREFIX] match failed\n"); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_SUBSTRING); - ok(bRet == TRUE || broken(!bRet) /* Win9x */, "bin(full,substr)[SUBSTRING] match failed\n"); + ok(bRet == TRUE, "bin(full,substr)[SUBSTRING] match failed\n"); pvRight.Value.bin.lpb = (LPBYTE)szSubstringLower; pvRight.Value.bin.cb = strlen(szSubstringLower); bRet = pFPropContainsProp(&pvLeft, &pvRight, FL_PREFIX); @@ -503,7 +503,7 @@ static void test_FPropCompareProp(void) } bRet = pFPropCompareProp(&pvLeft, FPCProp_Results[j].relOp, &pvRight); - ok(bRet == bExp || broken(!bRet) /* Win9x */, + ok(bRet == bExp, "pt %d (%d,%d,%s): expected %d, got %d\n", ptTypes[i], FPCProp_Results[j].lVal, FPCProp_Results[j].rVal, relops[FPCProp_Results[j].relOp], bExp, bRet); @@ -627,7 +627,7 @@ static void test_LPropCompareProp(void) } iRet = pLPropCompareProp(&pvLeft, &pvRight); - ok(iRet == iExp || broken(iRet == 0) /* Win9x */, + ok(iRet == iExp, "pt %d (%d,%d): expected %d, got %d\n", ptTypes[i], LPCProp_Results[j].lVal, LPCProp_Results[j].rVal, iExp, iRet); } @@ -649,7 +649,7 @@ static void test_PpropFindProp(void) pvProp.ulPropTag = ptTypes[i]; pRet = pPpropFindProp(&pvProp, 1u, ptTypes[i]); - ok(pRet == &pvProp || broken(pRet != &pvProp) /* Win9x */, + ok(pRet == &pvProp, "PpropFindProp[%d]: Didn't find existing propery\n", ptTypes[i]); @@ -886,7 +886,7 @@ static void test_LpValFindProp(void) pvProp.ulPropTag = PROP_TAG(ptTypes[i], 1u); pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 1u), 1u, &pvProp); - ok(pRet == &pvProp || broken(pRet != &pvProp) /* Win9x */, + ok(pRet == &pvProp, "LpValFindProp[%d]: Didn't find existing propery id/type\n", ptTypes[i]); @@ -899,7 +899,7 @@ static void test_LpValFindProp(void) ptTypes[i]); pRet = pLpValFindProp(PROP_TAG(PT_NULL, 1u), 1u, &pvProp); - ok(pRet == &pvProp || broken(pRet != &pvProp) /* Win9x */, + ok(pRet == &pvProp, "LpValFindProp[%d]: Didn't find existing propery id\n", ptTypes[i]); } @@ -996,7 +996,7 @@ static void test_FBadPropTag(void) if (bBad) ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt); else - ok(res == 0 || broken(res) /* Win9x */, + ok(res == 0, "pt= %d: Expected zero, got %d\n", pt, res); } } @@ -1086,7 +1086,7 @@ static void test_FBadProp(void) if (bBad) ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt); else - ok(res == 0 || broken(res) /* Win9x */, + ok(res == 0, "pt= %d: Expected zero, got %d\n", pt, res); } } @@ -1138,7 +1138,7 @@ static void test_FBadColumnSet(void) if (bBad) ok(res != 0, "pt= %d: Expected non-zero, got 0\n", pt); else - ok(res == 0 || broken(res) /* Win9x */, + ok(res == 0, "pt= %d: Expected zero, got %d\n", pt, res); } } @@ -1374,6 +1374,12 @@ START_TEST(prop) FreeLibrary(hMapi32); return; } + else if ((ret == E_FAIL) && (GetLastError() == ERROR_INVALID_HANDLE)) + { + win_skip("ScInitMapiUtil doesn't work on some Win98 and WinME systems\n"); + FreeLibrary(hMapi32); + return; + } test_PropCopyMore(); test_UlPropSize(); diff --git a/dlls/mapi32/tests/util.c b/dlls/mapi32/tests/util.c index 6cb77702039..af4fc57c7af 100644 --- a/dlls/mapi32/tests/util.c +++ b/dlls/mapi32/tests/util.c @@ -51,8 +51,7 @@ static void test_SwapPword(void) shorts[1] = 0x10ff; shorts[2] = 0x2001; pSwapPword(shorts, 2); - ok((shorts[0] == 0x01ff && shorts[1] == 0xff10 && shorts[2] == 0x2001) || - broken(shorts[0] == 0xff01 && shorts[1] == 0x10ff && shorts[2] == 0x2001) /* Win9x */, + ok((shorts[0] == 0x01ff && shorts[1] == 0xff10 && shorts[2] == 0x2001), "Expected {0x01ff,0xff10,0x2001}, got {0x%04x,0x%04x,0x%04x}\n", shorts[0], shorts[1], shorts[2]); } @@ -69,8 +68,7 @@ static void test_SwapPlong(void) longs[1] = 0x1000ffff; longs[2] = 0x20000001; pSwapPlong(longs, 2); - ok((longs[0] == 0x0100ffff && longs[1] == 0xffff0010 && longs[2] == 0x20000001) || - broken(longs[0] == 0xffff0001 && longs[1] == 0x1000ffff && longs[2] == 0x20000001) /* Win9x */, + ok((longs[0] == 0x0100ffff && longs[1] == 0xffff0010 && longs[2] == 0x20000001), "Expected {0x0100ffff,0xffff0010,0x20000001}, got {0x%08x,0x%08x,0x%08x}\n", longs[0], longs[1], longs[2]); } @@ -153,7 +151,7 @@ static void test_CbOfEncoded(void) memset(buff, '\0', sizeof(buff)); memset(buff, '?', i); ulRet = pCbOfEncoded(buff); - ok(ulRet == ulExpected || broken(ulRet == 0) /* Win9x */, + ok(ulRet == ulExpected, "CbOfEncoded(length %d): expected %d, got %d\n", i, ulExpected, ulRet); } @@ -193,6 +191,12 @@ START_TEST(util) FreeLibrary(hMapi32); return; } + else if ((ret == E_FAIL) && (GetLastError() == ERROR_INVALID_HANDLE)) + { + win_skip("ScInitMapiUtil doesn't work on some Win98 and WinME systems\n"); + FreeLibrary(hMapi32); + return; + } test_SwapPword(); test_SwapPlong(); diff --git a/dlls/mlang/mlang.c b/dlls/mlang/mlang.c index 4d3c2e58558..d762bacd5d8 100644 --- a/dlls/mlang/mlang.c +++ b/dlls/mlang/mlang.c @@ -2141,8 +2141,14 @@ static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo( IMultiLanguage* iface, UINT* pcCodePage) { - FIXME("\n"); - return E_NOTIMPL; + MLang_impl *This = impl_from_IMultiLanguage( iface ); + + TRACE("(%p, %p)\n", This, pcCodePage); + + if (!pcCodePage) return E_INVALIDARG; + + *pcCodePage = This->total_cp; + return S_OK; } static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo( @@ -2640,7 +2646,7 @@ static HRESULT WINAPI fnIMultiLanguage2_GetNumberOfCodePageInfo( TRACE("%p, %p\n", This, pcCodePage); - if (!pcCodePage) return S_FALSE; + if (!pcCodePage) return E_INVALIDARG; *pcCodePage = This->total_cp; return S_OK; diff --git a/dlls/mlang/tests/mlang.c b/dlls/mlang/tests/mlang.c index 6a871b89ed9..d4e39412a21 100644 --- a/dlls/mlang/tests/mlang.c +++ b/dlls/mlang/tests/mlang.c @@ -266,6 +266,17 @@ static int mylstrcmpW(const WCHAR* str1, const WCHAR* str2) return *str1-*str2; } +/* lstrcpyW is not supported on Win95 */ +static void mylstrcpyW(WCHAR* str1, const WCHAR* str2) +{ + while (str2 && *str2) { + *str1 = *str2; + str1++; + str2++; + } + *str1 = '\0'; +} + #define DEBUGSTR_W_MAXLEN 64 static CHAR * debugstr_w(const WCHAR * strW) @@ -1147,6 +1158,20 @@ static void test_Rfc1766ToLcid(void) } +static void test_GetNumberOfCodePageInfo(IMultiLanguage2 *iML2) +{ + HRESULT hr; + UINT value; + + value = 0xdeadbeef; + hr = IMultiLanguage2_GetNumberOfCodePageInfo(iML2, &value); + ok( (hr == S_OK) && value, + "got 0x%x with %d (expected S_OK with '!= 0')\n", hr, value); + + hr = IMultiLanguage2_GetNumberOfCodePageInfo(iML2, NULL); + ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr); + +} static void test_GetRfc1766FromLcid(IMultiLanguage2 *iML2) { @@ -1238,6 +1263,7 @@ static void test_LcidToRfc1766(void) static void test_GetRfc1766Info(IMultiLanguage2 *iML2) { + WCHAR short_broken_name[MAX_LOCALE_NAME]; CHAR rfc1766A[MAX_RFC1766_NAME + 1]; BYTE buffer[sizeof(RFC1766INFO) + 4]; PRFC1766INFO prfc = (RFC1766INFO *) buffer; @@ -1258,16 +1284,22 @@ static void test_GetRfc1766Info(IMultiLanguage2 *iML2) ok(!lstrcmpA(rfc1766A, info_table[i].rfc1766), "#%02d: got '%s' (expected '%s')\n", i, rfc1766A, info_table[i].rfc1766); + /* Some IE versions truncate an oversized name one character to short */ + mylstrcpyW(short_broken_name, info_table[i].broken_name); + short_broken_name[MAX_LOCALE_NAME - 2] = '\0'; + if (info_table[i].todo & TODO_NAME) { todo_wine ok( (!mylstrcmpW(prfc->wszLocaleName, info_table[i].localename)) || - broken(!mylstrcmpW(prfc->wszLocaleName, info_table[i].broken_name)), /* IE < 6.0 */ + broken(!mylstrcmpW(prfc->wszLocaleName, info_table[i].broken_name)) || /* IE < 6.0 */ + broken(!mylstrcmpW(prfc->wszLocaleName, short_broken_name)), "#%02d: got %s (expected %s)\n", i, debugstr_w(prfc->wszLocaleName), debugstr_w(info_table[i].localename)); } else ok( (!mylstrcmpW(prfc->wszLocaleName, info_table[i].localename)) || - broken(!mylstrcmpW(prfc->wszLocaleName, info_table[i].broken_name)), /* IE < 6.0 */ + broken(!mylstrcmpW(prfc->wszLocaleName, info_table[i].broken_name)) || /* IE < 6.0 */ + broken(!mylstrcmpW(prfc->wszLocaleName, short_broken_name)), "#%02d: got %s (expected %s)\n", i, debugstr_w(prfc->wszLocaleName), debugstr_w(info_table[i].localename)); @@ -1840,6 +1872,7 @@ static void test_GetScriptFontInfo(IMLangFontLink2 *font_link) START_TEST(mlang) { + IMultiLanguage *iML = NULL; IMultiLanguage2 *iML2 = NULL; IMLangFontLink *iMLFL = NULL; IMLangFontLink2 *iMLFL2 = NULL; @@ -1852,6 +1885,21 @@ START_TEST(mlang) test_Rfc1766ToLcid(); test_LcidToRfc1766(); + test_ConvertINetUnicodeToMultiByte(); + test_JapaneseConversion(); + + + trace("IMultiLanguage\n"); + ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, + &IID_IMultiLanguage, (void **)&iML); + if (ret != S_OK || !iML) return; + + test_GetNumberOfCodePageInfo((IMultiLanguage2 *)iML); + IMultiLanguage_Release(iML); + + + /* IMultiLanguage2 (IE5.0 and above) */ + trace("IMultiLanguage2\n"); ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, &IID_IMultiLanguage2, (void **)&iML2); if (ret != S_OK || !iML2) return; @@ -1860,6 +1908,7 @@ START_TEST(mlang) test_GetLcidFromRfc1766(iML2); test_GetRfc1766FromLcid(iML2); test_GetRfc1766Info(iML2); + test_GetNumberOfCodePageInfo(iML2); test_EnumCodePages(iML2, 0); test_EnumCodePages(iML2, MIMECONTF_MIME_LATEST); @@ -1883,10 +1932,8 @@ START_TEST(mlang) IMultiLanguage2_Release(iML2); - test_ConvertINetUnicodeToMultiByte(); - - test_JapaneseConversion(); + /* IMLangFontLink */ ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, &IID_IMLangFontLink, (void **)&iMLFL); if (ret != S_OK || !iMLFL) return; @@ -1894,6 +1941,7 @@ START_TEST(mlang) IMLangFontLink_Test(iMLFL); IMLangFontLink_Release(iMLFL); + /* IMLangFontLink2 */ ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, &IID_IMLangFontLink2, (void **)&iMLFL2); if (ret != S_OK || !iMLFL2) return; diff --git a/dlls/msctf/compartmentmgr.c b/dlls/msctf/compartmentmgr.c index 33369c29389..5342568cd79 100644 --- a/dlls/msctf/compartmentmgr.c +++ b/dlls/msctf/compartmentmgr.c @@ -33,6 +33,7 @@ #include "winerror.h" #include "objbase.h" #include "oleauto.h" +#include "olectl.h" #include "wine/unicode.h" #include "wine/list.h" @@ -58,6 +59,15 @@ typedef struct tagCompartmentMgr { struct list values; } CompartmentMgr; +typedef struct tagCompartmentEnumGuid { + const IEnumGUIDVtbl *Vtbl; + LONG refCount; + + struct list *values; + struct list *cursor; +} CompartmentEnumGuid; + +static HRESULT CompartmentEnumGuid_Constructor(struct list* values, IEnumGUID **ppOut); HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *iface) { @@ -129,7 +139,7 @@ static ULONG WINAPI CompartmentMgr_Release(ITfCompartmentMgr *iface) } } -HRESULT WINAPI CompartmentMgr_GetCompartment(ITfCompartmentMgr *iface, +static HRESULT WINAPI CompartmentMgr_GetCompartment(ITfCompartmentMgr *iface, REFGUID rguid, ITfCompartment **ppcomp) { CompartmentMgr *This = (CompartmentMgr *)iface; @@ -137,20 +147,38 @@ HRESULT WINAPI CompartmentMgr_GetCompartment(ITfCompartmentMgr *iface, return E_NOTIMPL; } -HRESULT WINAPI CompartmentMgr_ClearCompartment(ITfCompartmentMgr *iface, +static HRESULT WINAPI CompartmentMgr_ClearCompartment(ITfCompartmentMgr *iface, TfClientId tid, REFGUID rguid) { + struct list *cursor; CompartmentMgr *This = (CompartmentMgr *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + TRACE("(%p) %i %s\n",This,tid,debugstr_guid(rguid)); + + LIST_FOR_EACH(cursor, &This->values) + { + CompartmentValue* value = LIST_ENTRY(cursor,CompartmentValue,entry); + if (IsEqualGUID(rguid,&value->guid)) + { + if (value->owner && tid != value->owner) + return E_UNEXPECTED; + list_remove(cursor); + ITfCompartment_Release(value->compartment); + HeapFree(GetProcessHeap(),0,value); + return S_OK; + } + } + + return CONNECT_E_NOCONNECTION; } -HRESULT WINAPI CompartmentMgr_EnumCompartments(ITfCompartmentMgr *iface, +static HRESULT WINAPI CompartmentMgr_EnumCompartments(ITfCompartmentMgr *iface, IEnumGUID **ppEnum) { CompartmentMgr *This = (CompartmentMgr *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + TRACE("(%p) %p\n",This,ppEnum); + if (!ppEnum) + return E_INVALIDARG; + return CompartmentEnumGuid_Constructor(&This->values, ppEnum); } static const ITfCompartmentMgrVtbl CompartmentMgr_CompartmentMgrVtbl = @@ -197,3 +225,145 @@ HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown ** return hr; } } + +/************************************************** + * IEnumGUID implementaion for ITfCompartmentMgr::EnumCompartments + **************************************************/ +static void CompartmentEnumGuid_Destructor(CompartmentEnumGuid *This) +{ + TRACE("destroying %p\n", This); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI CompartmentEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut) +{ + CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI CompartmentEnumGuid_AddRef(IEnumGUID *iface) +{ + CompartmentEnumGuid *This = (CompartmentEnumGuid*)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI CompartmentEnumGuid_Release(IEnumGUID *iface) +{ + CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + CompartmentEnumGuid_Destructor(This); + return ret; +} + +/***************************************************** + * IEnumGuid functions + *****************************************************/ +static HRESULT WINAPI CompartmentEnumGuid_Next( LPENUMGUID iface, + ULONG celt, GUID *rgelt, ULONG *pceltFetched) +{ + CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; + ULONG fetched = 0; + + TRACE("(%p)\n",This); + + if (rgelt == NULL) return E_POINTER; + + while (fetched < celt && This->cursor) + { + CompartmentValue* value = LIST_ENTRY(This->cursor,CompartmentValue,entry); + if (!value) + break; + + This->cursor = list_next(This->values,This->cursor); + *rgelt = value->guid; + + ++fetched; + ++rgelt; + } + + if (pceltFetched) *pceltFetched = fetched; + return fetched == celt ? S_OK : S_FALSE; +} + +static HRESULT WINAPI CompartmentEnumGuid_Skip( LPENUMGUID iface, ULONG celt) +{ + CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; + TRACE("(%p)\n",This); + + This->cursor = list_next(This->values,This->cursor); + return S_OK; +} + +static HRESULT WINAPI CompartmentEnumGuid_Reset( LPENUMGUID iface) +{ + CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; + TRACE("(%p)\n",This); + This->cursor = list_head(This->values); + return S_OK; +} + +static HRESULT WINAPI CompartmentEnumGuid_Clone( LPENUMGUID iface, + IEnumGUID **ppenum) +{ + CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface; + HRESULT res; + + TRACE("(%p)\n",This); + + if (ppenum == NULL) return E_POINTER; + + res = CompartmentEnumGuid_Constructor(This->values, ppenum); + if (SUCCEEDED(res)) + { + CompartmentEnumGuid *new_This = (CompartmentEnumGuid *)*ppenum; + new_This->cursor = This->cursor; + } + return res; +} + +static const IEnumGUIDVtbl IEnumGUID_Vtbl ={ + CompartmentEnumGuid_QueryInterface, + CompartmentEnumGuid_AddRef, + CompartmentEnumGuid_Release, + + CompartmentEnumGuid_Next, + CompartmentEnumGuid_Skip, + CompartmentEnumGuid_Reset, + CompartmentEnumGuid_Clone +}; + +static HRESULT CompartmentEnumGuid_Constructor(struct list *values, IEnumGUID **ppOut) +{ + CompartmentEnumGuid *This; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CompartmentEnumGuid)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->Vtbl= &IEnumGUID_Vtbl; + This->refCount = 1; + + This->values = values; + This->cursor = list_head(values); + + TRACE("returning %p\n", This); + *ppOut = (IEnumGUID*)This; + return S_OK; +} diff --git a/dlls/msctf/context.c b/dlls/msctf/context.c index 2c7acb068bc..e5cf602fb97 100644 --- a/dlls/msctf/context.c +++ b/dlls/msctf/context.c @@ -74,6 +74,7 @@ typedef struct tagContext { TfClientId tidOwner; TfEditCookie defaultCookie; TS_STATUS documentStatus; + ITfDocumentMgr *manager; ITextStoreACP *pITextStoreACP; ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink; @@ -506,8 +507,15 @@ static HRESULT WINAPI Context_GetDocumentMgr (ITfContext *iface, ITfDocumentMgr **ppDm) { Context *This = (Context *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + TRACE("(%p) %p\n",This,ppDm); + + if (!ppDm) + return E_INVALIDARG; + + *ppDm = This->manager; + if (!This->manager) + return S_FALSE; + return S_OK; } static HRESULT WINAPI Context_CreateRangeBackup (ITfContext *iface, @@ -701,7 +709,7 @@ static const ITfInsertAtSelectionVtbl Context_InsertAtSelectionVtbl = InsertAtSelection_InsertEmbeddedAtSelection, }; -HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore) +HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore) { Context *This; EditCookie *cookie; @@ -725,6 +733,7 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **pp This->refCount = 1; This->tidOwner = tidOwner; This->connected = FALSE; + This->manager = mgr; CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr); @@ -758,7 +767,7 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **pp return S_OK; } -HRESULT Context_Initialize(ITfContext *iface) +HRESULT Context_Initialize(ITfContext *iface, ITfDocumentMgr *manager) { Context *This = (Context *)iface; @@ -769,6 +778,7 @@ HRESULT Context_Initialize(ITfContext *iface) (IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS); } This->connected = TRUE; + This->manager = manager; return S_OK; } @@ -783,6 +793,7 @@ HRESULT Context_Uninitialize(ITfContext *iface) This->pITextStoreACPSink = NULL; } This->connected = FALSE; + This->manager = NULL; return S_OK; } diff --git a/dlls/msctf/documentmgr.c b/dlls/msctf/documentmgr.c index 3d4dbe9066b..c7aa8209ee1 100644 --- a/dlls/msctf/documentmgr.c +++ b/dlls/msctf/documentmgr.c @@ -123,7 +123,7 @@ static HRESULT WINAPI DocumentMgr_CreateContext(ITfDocumentMgr *iface, { DocumentMgr *This = (DocumentMgr *)iface; TRACE("(%p) 0x%x 0x%x %p %p %p\n",This,tidOwner,dwFlags,punk,ppic,pecTextStore); - return Context_Constructor(tidOwner, punk, ppic, pecTextStore); + return Context_Constructor(tidOwner, punk, iface, ppic, pecTextStore); } static HRESULT WINAPI DocumentMgr_Push(ITfDocumentMgr *iface, ITfContext *pic) @@ -146,7 +146,7 @@ static HRESULT WINAPI DocumentMgr_Push(ITfDocumentMgr *iface, ITfContext *pic) This->contextStack[0] = check; ITfThreadMgrEventSink_OnPushContext(This->ThreadMgrSink,check); - Context_Initialize(check); + Context_Initialize(check, iface); return S_OK; } diff --git a/dlls/msctf/msctf.c b/dlls/msctf/msctf.c index 675e4d5954c..9729ef3952c 100644 --- a/dlls/msctf/msctf.c +++ b/dlls/msctf/msctf.c @@ -74,6 +74,7 @@ static UINT activated = 0; DWORD tlsIndex = 0; TfClientId processId = 0; +ITfCompartmentMgr *globalCompartmentMgr = NULL; const WCHAR szwSystemTIPKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F','\\','T','I','P',0}; diff --git a/dlls/msctf/msctf_internal.h b/dlls/msctf/msctf_internal.h index b4e74466e81..d2b1a2e182e 100644 --- a/dlls/msctf/msctf_internal.h +++ b/dlls/msctf/msctf_internal.h @@ -29,17 +29,18 @@ extern DWORD tlsIndex; extern TfClientId processId; +extern ITfCompartmentMgr *globalCompartmentMgr; extern HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); extern HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink*, ITfDocumentMgr **ppOut); -extern HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore); +extern HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore); extern HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); extern HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); extern HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut); extern HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut); extern HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *This); -extern HRESULT Context_Initialize(ITfContext *cxt); +extern HRESULT Context_Initialize(ITfContext *cxt, ITfDocumentMgr *manager); extern HRESULT Context_Uninitialize(ITfContext *cxt); extern HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp); diff --git a/dlls/msctf/tests/inputprocessor.c b/dlls/msctf/tests/inputprocessor.c index c4be695dd27..67d53c61b1b 100644 --- a/dlls/msctf/tests/inputprocessor.c +++ b/dlls/msctf/tests/inputprocessor.c @@ -1146,6 +1146,11 @@ static void test_startSession(void) hr = ITfDocumentMgr_CreateContext(g_dm, cid, 0, NULL, &cxt3, &editCookie); ok(SUCCEEDED(hr),"CreateContext Failed\n"); + hr = ITfContext_GetDocumentMgr(cxt,&dmtest); + ok(hr == S_OK, "ITfContext_GetDocumentMgr failed with %x\n",hr); + ok(dmtest == g_dm, "Wrong documentmgr\n"); + ITfDocumentMgr_Release(dmtest); + cnt = check_context_refcount(cxt); test_OnPushContext = SINK_EXPECTED; test_ACP_AdviseSink = SINK_EXPECTED; @@ -1215,6 +1220,11 @@ static void test_startSession(void) ok(check_context_refcount(cxt2) < cnt, "Ref count did not decrease\n"); ok(test_OnPopContext == SINK_FIRED, "OnPopContext sink not fired\n"); + dmtest = (void *)0xfeedface; + hr = ITfContext_GetDocumentMgr(cxt2,&dmtest); + ok(hr == S_FALSE, "ITfContext_GetDocumentMgr wrong rc %x\n",hr); + ok(dmtest == NULL,"returned documentmgr should be null\n"); + hr = ITfDocumentMgr_GetTop(g_dm, &cxtTest); ok(SUCCEEDED(hr),"GetTop Failed\n"); ok(cxtTest == cxt, "Wrong context on top\n"); @@ -1479,10 +1489,11 @@ static const ITfEditSessionVtbl EditSession_EditSessionVtbl = EditSession_DoEditSession }; -HRESULT EditSession_Constructor(ITfEditSession **ppOut) +static HRESULT EditSession_Constructor(ITfEditSession **ppOut) { EditSession *This; + *ppOut = NULL; This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EditSession)); if (This == NULL) return E_OUTOFMEMORY; diff --git a/dlls/msctf/threadmgr.c b/dlls/msctf/threadmgr.c index 490bfc6580b..b10910709bc 100644 --- a/dlls/msctf/threadmgr.c +++ b/dlls/msctf/threadmgr.c @@ -365,9 +365,12 @@ ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev) static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus) { + HWND focus; ThreadMgr *This = (ThreadMgr *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + TRACE("(%p) %p\n",This,pfThreadFocus); + focus = GetFocus(); + *pfThreadFocus = (focus == NULL); + return S_OK; } static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid, @@ -390,8 +393,22 @@ static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface, ITfCompartmentMgr **ppCompMgr) { ThreadMgr *This = (ThreadMgr *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + HRESULT hr; + TRACE("(%p) %p\n",This, ppCompMgr); + + if (!ppCompMgr) + return E_INVALIDARG; + + if (!globalCompartmentMgr) + { + hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr); + if (FAILED(hr)) + return hr; + } + + ITfCompartmentMgr_AddRef(globalCompartmentMgr); + *ppCompMgr = globalCompartmentMgr; + return S_OK; } static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl = diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 7e436930428..92b379b7523 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -4869,7 +4869,7 @@ static void gecko_installer_workaround(BOOL disable) } /* Check if Internet Explorer is configured to run in "Enhanced Security Configuration" (aka hardened mode) */ -/* Note: this code is duplicated in dlls/mshtml/tests/dom.c, dlls/mshtml/tests/script.c and dlls/urlmon/tests/misc.c */ +/* Note: this code is duplicated in dlls/mshtml/tests/dom.c, dlls/mshtml/tests/script.c and dlls/urlmon/tests/sec_mgr.c */ static BOOL is_ie_hardened(void) { HKEY zone_map; diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c index 4faf78aa9f3..db679fb8456 100644 --- a/dlls/mshtml/tests/script.c +++ b/dlls/mshtml/tests/script.c @@ -1152,7 +1152,7 @@ static void gecko_installer_workaround(BOOL disable) } /* Check if Internet Explorer is configured to run in "Enhanced Security Configuration" (aka hardened mode) */ -/* Note: this code is duplicated in dlls/mshtml/tests/dom.c, dlls/mshtml/tests/script.c and dlls/urlmon/tests/misc.c */ +/* Note: this code is duplicated in dlls/mshtml/tests/dom.c, dlls/mshtml/tests/script.c and dlls/urlmon/tests/sec_mgr.c */ static BOOL is_ie_hardened(void) { HKEY zone_map; diff --git a/dlls/msi/tests/automation.c b/dlls/msi/tests/automation.c index 88ce287ae26..df768ece935 100644 --- a/dlls/msi/tests/automation.c +++ b/dlls/msi/tests/automation.c @@ -364,14 +364,25 @@ static void delete_test_files(void) /* ok-like statement which takes two unicode strings or one unicode and one ANSI string as arguments */ static CHAR string1[MAX_PATH], string2[MAX_PATH]; +/* lstrcmpW is not supported on Win9x */ +static int strcmp_ww(const WCHAR* str1, const WCHAR* str2) +{ + CHAR str1A[MAX_PATH], str2A[MAX_PATH]; + + WideCharToMultiByte(CP_ACP, 0, str1, -1, str1A, MAX_PATH, NULL, NULL); \ + WideCharToMultiByte(CP_ACP, 0, str2, -1, str2A, MAX_PATH, NULL, NULL); \ + + return lstrcmpA(str1A, str2A); +} + #define ok_w2(format, szString1, szString2) \ \ - if (lstrcmpW(szString1, szString2) != 0) \ - { \ - WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \ - WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \ + do { \ + WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \ + WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \ + if (lstrcmpA(string1, string2) != 0) \ ok(0, format, string1, string2); \ - } + } while(0); #define ok_w2n(format, szString1, szString2, len) \ \ @@ -759,7 +770,9 @@ static HRESULT Installer_RegistryValueW(HKEY hkey, LPCWSTR szKey, LPCWSTR szValu V_BSTR(&vararg) = SysAllocString(szValue); hr = Installer_RegistryValue(hkey, szKey, vararg, &varresult, VT_BSTR); - if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult)); + if (V_BSTR(&varresult)) + /* lstrcpyW is not implemented on Win95 (lstrlenW is though) */ + memcpy(szString, V_BSTR(&varresult), (lstrlenW(V_BSTR(&varresult)) + 1) * sizeof(WCHAR)); VariantClear(&varresult); return hr; } @@ -775,7 +788,8 @@ static HRESULT Installer_RegistryValueI(HKEY hkey, LPCWSTR szKey, int iValue, LP V_I4(&vararg) = iValue; hr = Installer_RegistryValue(hkey, szKey, vararg, &varresult, vtResult); - if (SUCCEEDED(hr) && vtResult == VT_BSTR) lstrcpyW(szString, V_BSTR(&varresult)); + if (SUCCEEDED(hr) && vtResult == VT_BSTR) + memcpy(szString, V_BSTR(&varresult), (lstrlenW(V_BSTR(&varresult)) + 1) * sizeof(WCHAR)); VariantClear(&varresult); return hr; } @@ -866,7 +880,8 @@ static HRESULT Installer_ProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, LPW V_BSTR(&vararg[0]) = SysAllocString(szAttribute); hr = invoke(pInstaller, "ProductInfo", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); - if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult)); + if (V_BSTR(&varresult)) + memcpy(szString, V_BSTR(&varresult), (lstrlenW(V_BSTR(&varresult)) + 1) * sizeof(WCHAR)); VariantClear(&varresult); return hr; } @@ -905,7 +920,8 @@ static HRESULT Installer_VersionGet(LPWSTR szVersion) HRESULT hr; hr = invoke(pInstaller, "Version", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); - if (V_BSTR(&varresult)) lstrcpyW(szVersion, V_BSTR(&varresult)); + if (V_BSTR(&varresult)) + memcpy(szVersion, V_BSTR(&varresult), (lstrlenW(V_BSTR(&varresult)) + 1) * sizeof(WCHAR)); VariantClear(&varresult); return hr; } @@ -933,7 +949,8 @@ static HRESULT Session_PropertyGet(IDispatch *pSession, LPCWSTR szName, LPWSTR s V_BSTR(&vararg[0]) = SysAllocString(szName); hr = invoke(pSession, "Property", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); - if (V_BSTR(&varresult)) lstrcpyW(szReturn, V_BSTR(&varresult)); + if (V_BSTR(&varresult)) + memcpy(szReturn, V_BSTR(&varresult), (lstrlenW(V_BSTR(&varresult)) + 1) * sizeof(WCHAR)); VariantClear(&varresult); return hr; } @@ -1232,7 +1249,8 @@ static HRESULT Record_StringDataGet(IDispatch *pRecord, int iField, LPWSTR szStr V_I4(&vararg[0]) = iField; hr = invoke(pRecord, "StringData", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); - if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult)); + if (V_BSTR(&varresult)) + memcpy(szString, V_BSTR(&varresult), (lstrlenW(V_BSTR(&varresult)) + 1) * sizeof(WCHAR)); VariantClear(&varresult); return hr; } @@ -1309,7 +1327,8 @@ static HRESULT StringList_Item(IDispatch *pStringList, int iIndex, LPWSTR szStri V_I4(&vararg[0]) = iIndex; hr = invoke(pStringList, "Item", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); - if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult)); + if (V_BSTR(&varresult)) + memcpy(szString, V_BSTR(&varresult), (lstrlenW(V_BSTR(&varresult)) + 1) * sizeof(WCHAR)); VariantClear(&varresult); return hr; } @@ -1654,7 +1673,7 @@ static void test_Session(IDispatch *pSession) memset(stringw, 0, sizeof(stringw)); hr = Session_PropertyGet(pSession, szProductName, stringw); ok(hr == S_OK, "Session_PropertyGet failed, hresult 0x%08x\n", hr); - if (lstrcmpW(stringw, szMSITEST) != 0) + if (strcmp_ww(stringw, szMSITEST) != 0) { len = WideCharToMultiByte(CP_ACP, 0, stringw, -1, string, MAX_PATH, NULL, NULL); ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); @@ -1667,7 +1686,7 @@ static void test_Session(IDispatch *pSession) memset(stringw, 0, sizeof(stringw)); hr = Session_PropertyGet(pSession, szProductName, stringw); ok(hr == S_OK, "Session_PropertyGet failed, hresult 0x%08x\n", hr); - if (lstrcmpW(stringw, szProductName) != 0) + if (strcmp_ww(stringw, szProductName) != 0) { len = WideCharToMultiByte(CP_ACP, 0, stringw, -1, string, MAX_PATH, NULL, NULL); ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); @@ -2006,7 +2025,7 @@ static void test_Installer_Products(BOOL bProductInstalled) ok(iValue == INSTALLSTATE_DEFAULT || iValue == INSTALLSTATE_ADVERTISED, "Installer_ProductState returned %d, expected %d or %d\n", iValue, INSTALLSTATE_DEFAULT, INSTALLSTATE_ADVERTISED); /* Not found our product code yet? Check */ - if (!bProductFound && !lstrcmpW(szString, szProductCode)) + if (!bProductFound && !strcmp_ww(szString, szProductCode)) bProductFound = TRUE; /* IEnumVARIANT::Next */ diff --git a/dlls/msi/tests/source.c b/dlls/msi/tests/source.c index 4e94edae8d1..5a51c66c3f8 100644 --- a/dlls/msi/tests/source.c +++ b/dlls/msi/tests/source.c @@ -283,7 +283,7 @@ static void test_MsiSourceListGetInfo(void) size = MAX_PATH; r = pMsiSourceListGetInfoA(prodcode, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size); - ok(r == ERROR_UNKNOWN_PRODUCT || ERROR_INVALID_PARAMETER, + ok(r == ERROR_UNKNOWN_PRODUCT || r == ERROR_INVALID_PARAMETER, "Expected ERROR_UNKNOWN_PRODUCT or ERROR_INVALID_PARAMETER, got %d\n", r); lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index 6178aca0508..b2627181fdb 100644 --- a/dlls/msvcirt/msvcirt.c +++ b/dlls/msvcirt/msvcirt.c @@ -35,18 +35,18 @@ typedef struct { #define THISCALL(func) __thiscall_ ## func #define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func) -#define DEFINE_THISCALL_WRAPPER(func) \ +#define DEFINE_THISCALL_WRAPPER(func,args) \ extern void THISCALL(func)(); \ __ASM_GLOBAL_FUNC(__thiscall_ ## func, \ "popl %eax\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) ) + "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) #else /* __i386__ */ #define THISCALL(func) func #define THISCALL_NAME(func) __ASM_NAME(#func) -#define DEFINE_THISCALL_WRAPPER(func) /* nothing */ +#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ #endif /* __i386__ */ @@ -54,7 +54,7 @@ typedef struct { * ??6ostream@@QAEAAV0@H@Z (MSVCRTI.@) * class ostream & __thiscall ostream::operator<<(int) */ -DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_int) +DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_int,8) void * __stdcall MSVCIRT_operator_sl_int(class_ostream * _this, int integer) { FIXME("(%p)->(%d) stub\n", _this, integer); @@ -65,7 +65,7 @@ void * __stdcall MSVCIRT_operator_sl_int(class_ostream * _this, int integer) * ??6ostream@@QAEAAV0@PBD@Z (MSVCRTI.@) * class ostream & __thiscall ostream::operator<<(char const *) */ -DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_pchar) +DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_pchar,8) void * __stdcall MSVCIRT_operator_sl_pchar(class_ostream * _this, const char * string) { FIXME("(%p)->(%s) stub\n", _this, string); diff --git a/dlls/msvcrt/cpp.c b/dlls/msvcrt/cpp.c index 0ed28dd9910..b203e1c043c 100644 --- a/dlls/msvcrt/cpp.c +++ b/dlls/msvcrt/cpp.c @@ -73,18 +73,18 @@ typedef struct _rtti_object_locator #define THISCALL(func) __thiscall_ ## func #define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func) -#define DEFINE_THISCALL_WRAPPER(func) \ +#define DEFINE_THISCALL_WRAPPER(func,args) \ extern void THISCALL(func)(); \ __ASM_GLOBAL_FUNC(__thiscall_ ## func, \ "popl %eax\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) ) + "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) #else /* __i386__ */ #define THISCALL(func) func #define THISCALL_NAME(func) __ASM_NAME(#func) -#define DEFINE_THISCALL_WRAPPER(func) /* nothing */ +#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ #endif /* __i386__ */ @@ -151,7 +151,7 @@ static void EXCEPTION_ctor(exception *_this, const char** name) /****************************************************************** * ??0exception@@QAE@ABQBD@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8) exception * __stdcall MSVCRT_exception_ctor(exception * _this, const char ** name) { TRACE("(%p,%s)\n", _this, *name); @@ -162,7 +162,7 @@ exception * __stdcall MSVCRT_exception_ctor(exception * _this, const char ** nam /****************************************************************** * ??0exception@@QAE@ABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8) exception * __stdcall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs) { TRACE("(%p,%p)\n", _this, rhs); @@ -182,7 +182,7 @@ exception * __stdcall MSVCRT_exception_copy_ctor(exception * _this, const except /****************************************************************** * ??0exception@@QAE@XZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4) exception * __stdcall MSVCRT_exception_default_ctor(exception * _this) { static const char* empty = NULL; @@ -195,7 +195,7 @@ exception * __stdcall MSVCRT_exception_default_ctor(exception * _this) /****************************************************************** * ??1exception@@UAE@XZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4) void __stdcall MSVCRT_exception_dtor(exception * _this) { TRACE("(%p)\n", _this); @@ -206,7 +206,7 @@ void __stdcall MSVCRT_exception_dtor(exception * _this) /****************************************************************** * ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals) +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8) exception * __stdcall MSVCRT_exception_opequals(exception * _this, const exception * rhs) { TRACE("(%p %p)\n", _this, rhs); @@ -222,7 +222,7 @@ exception * __stdcall MSVCRT_exception_opequals(exception * _this, const excepti /****************************************************************** * ??_Eexception@@UAEPAXI@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8) void * __stdcall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); @@ -245,7 +245,7 @@ void * __stdcall MSVCRT_exception_vector_dtor(exception * _this, unsigned int fl /****************************************************************** * ??_Gexception@@UAEPAXI@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8) void * __stdcall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); @@ -257,7 +257,7 @@ void * __stdcall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int fl /****************************************************************** * ?what@exception@@UBEPBDXZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception) +DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4) const char * __stdcall MSVCRT_what_exception(exception * _this) { TRACE("(%p) returning %s\n", _this, _this->name); @@ -267,7 +267,7 @@ const char * __stdcall MSVCRT_what_exception(exception * _this) /****************************************************************** * ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8) bad_typeid * __stdcall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs) { TRACE("(%p %p)\n", _this, rhs); @@ -279,7 +279,7 @@ bad_typeid * __stdcall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad /****************************************************************** * ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8) bad_typeid * __stdcall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name) { TRACE("(%p %s)\n", _this, name); @@ -291,7 +291,7 @@ bad_typeid * __stdcall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * n /****************************************************************** * ??1bad_typeid@@UAE@XZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4) void __stdcall MSVCRT_bad_typeid_dtor(bad_typeid * _this) { TRACE("(%p)\n", _this); @@ -301,7 +301,7 @@ void __stdcall MSVCRT_bad_typeid_dtor(bad_typeid * _this) /****************************************************************** * ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8) bad_typeid * __stdcall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs) { TRACE("(%p %p)\n", _this, rhs); @@ -312,7 +312,7 @@ bad_typeid * __stdcall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_ /****************************************************************** * ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8) void * __stdcall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); @@ -335,7 +335,7 @@ void * __stdcall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int /****************************************************************** * ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8) void * __stdcall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); @@ -347,7 +347,7 @@ void * __stdcall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int /****************************************************************** * ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8) __non_rtti_object * __stdcall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this, const __non_rtti_object * rhs) { @@ -360,7 +360,7 @@ __non_rtti_object * __stdcall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_obje /****************************************************************** * ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8) __non_rtti_object * __stdcall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this, const char * name) { @@ -373,7 +373,7 @@ __non_rtti_object * __stdcall MSVCRT___non_rtti_object_ctor(__non_rtti_object * /****************************************************************** * ??1__non_rtti_object@@UAE@XZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4) void __stdcall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this) { TRACE("(%p)\n", _this); @@ -383,7 +383,7 @@ void __stdcall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this) /****************************************************************** * ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals) +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8) __non_rtti_object * __stdcall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this, const __non_rtti_object *rhs) { @@ -395,7 +395,7 @@ __non_rtti_object * __stdcall MSVCRT___non_rtti_object_opequals(__non_rtti_objec /****************************************************************** * ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8) void * __stdcall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); @@ -418,7 +418,7 @@ void * __stdcall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, /****************************************************************** * ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8) void * __stdcall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); @@ -430,7 +430,7 @@ void * __stdcall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, /****************************************************************** * ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8) bad_cast * __stdcall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name) { TRACE("(%p %s)\n", _this, *name); @@ -442,7 +442,7 @@ bad_cast * __stdcall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name) /****************************************************************** * ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8) bad_cast * __stdcall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs) { TRACE("(%p %p)\n", _this, rhs); @@ -454,7 +454,7 @@ bad_cast * __stdcall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast /****************************************************************** * ??1bad_cast@@UAE@XZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4) void __stdcall MSVCRT_bad_cast_dtor(bad_cast * _this) { TRACE("(%p)\n", _this); @@ -464,7 +464,7 @@ void __stdcall MSVCRT_bad_cast_dtor(bad_cast * _this) /****************************************************************** * ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8) bad_cast * __stdcall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs) { TRACE("(%p %p)\n", _this, rhs); @@ -475,7 +475,7 @@ bad_cast * __stdcall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * /****************************************************************** * ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8) void * __stdcall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); @@ -498,7 +498,7 @@ void * __stdcall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flag /****************************************************************** * ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8) void * __stdcall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); @@ -510,7 +510,7 @@ void * __stdcall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flag /****************************************************************** * ??8type_info@@QBEHABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals) +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8) int __stdcall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs) { int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1); @@ -521,7 +521,7 @@ int __stdcall MSVCRT_type_info_opequals_equals(type_info * _this, const type_inf /****************************************************************** * ??9type_info@@QBEHABV0@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals) +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8) int __stdcall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs) { int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1); @@ -532,7 +532,7 @@ int __stdcall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * /****************************************************************** * ?before@type_info@@QBEHABV1@@Z (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before) +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8) int __stdcall MSVCRT_type_info_before(type_info * _this, const type_info * rhs) { int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0; @@ -543,7 +543,7 @@ int __stdcall MSVCRT_type_info_before(type_info * _this, const type_info * rhs) /****************************************************************** * ??1type_info@@UAE@XZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4) void __stdcall MSVCRT_type_info_dtor(type_info * _this) { TRACE("(%p)\n", _this); @@ -553,7 +553,7 @@ void __stdcall MSVCRT_type_info_dtor(type_info * _this) /****************************************************************** * ?name@type_info@@QBEPBDXZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name) +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4) const char * __stdcall MSVCRT_type_info_name(type_info * _this) { if (!_this->name) @@ -594,7 +594,7 @@ const char * __stdcall MSVCRT_type_info_name(type_info * _this) /****************************************************************** * ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@) */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name) +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4) const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this) { TRACE("(%p) returning %s\n", _this, _this->mangled); @@ -602,7 +602,7 @@ const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this) } /* Unexported */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor) +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8) void * __stdcall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags) { TRACE("(%p %x)\n", _this, flags); diff --git a/dlls/msvcrtd/tests/debug.c b/dlls/msvcrtd/tests/debug.c index a7f7db1d82b..71f6e4c3966 100644 --- a/dlls/msvcrtd/tests/debug.c +++ b/dlls/msvcrtd/tests/debug.c @@ -30,7 +30,7 @@ /**********************************************************************/ -static void * (*pMSVCRTD_operator_new_dbg)(size_t, int, const char *, int) = NULL; +static void * (__cdecl *pMSVCRTD_operator_new_dbg)(size_t, int, const char *, int) = NULL; /* Some exports are only available in later versions */ #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hModule,y) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 3e54250da01..34ae2d62d55 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -48,6 +48,7 @@ extern void set_cpu_context( const CONTEXT *context ); extern void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ); extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ); extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ); +extern void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) DECLSPEC_NORETURN; /* debug helpers */ extern LPCSTR debugstr_us( const UNICODE_STRING *str ); @@ -77,6 +78,7 @@ extern size_t server_init_thread( void *entry_point ); extern void DECLSPEC_NORETURN server_protocol_error( const char *err, ... ); extern void DECLSPEC_NORETURN server_protocol_perror( const char *err ); extern void DECLSPEC_NORETURN abort_thread( int status ); +extern void DECLSPEC_NORETURN exit_thread( int status ); extern sigset_t server_block_set; extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ); extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ); diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c index 6eeb4534780..0f74c410846 100644 --- a/dlls/ntdll/relay.c +++ b/dlls/ntdll/relay.c @@ -342,30 +342,40 @@ __ASM_GLOBAL_FUNC( call_entry_point, "\tret" ) #else __ASM_GLOBAL_FUNC( call_entry_point, - "\tpushq %rbp\n" - "\tmovq %rsp,%rbp\n" - "\tpushq %rsi\n" - "\tpushq %rdi\n" - "\tmovq %rcx,%rax\n" - "\tmovq $4,%rcx\n" - "\tcmp %rcx,%rdx\n" - "\tcmovgq %rdx,%rcx\n" - "\tleaq 0(,%rcx,8),%rdx\n" - "\tsubq %rdx,%rsp\n" - "\tandq $~15,%rsp\n" - "\tmovq %rsp,%rdi\n" - "\tmovq %r8,%rsi\n" - "\trep; movsq\n" - "\tmovq 0(%rsp),%rcx\n" - "\tmovq 8(%rsp),%rdx\n" - "\tmovq 16(%rsp),%r8\n" - "\tmovq 24(%rsp),%r9\n" - "\tcallq *%rax\n" - "\tleaq -16(%rbp),%rsp\n" - "\tpopq %rdi\n" - "\tpopq %rsi\n" - "\tpopq %rbp\n" - "\tret\n" ) + "pushq %rbp\n\t" + ".cfi_adjust_cfa_offset 8\n\t" + ".cfi_rel_offset %rbp,0\n\t" + "movq %rsp,%rbp\n\t" + ".cfi_def_cfa_register %rbp\n\t" + "pushq %rsi\n\t" + ".cfi_rel_offset %rsi,-8\n\t" + "pushq %rdi\n\t" + ".cfi_rel_offset %rdi,-16\n\t" + "movq %rcx,%rax\n\t" + "movq $4,%rcx\n\t" + "cmp %rcx,%rdx\n\t" + "cmovgq %rdx,%rcx\n\t" + "leaq 0(,%rcx,8),%rdx\n\t" + "subq %rdx,%rsp\n\t" + "andq $~15,%rsp\n\t" + "movq %rsp,%rdi\n\t" + "movq %r8,%rsi\n\t" + "rep; movsq\n\t" + "movq 0(%rsp),%rcx\n\t" + "movq 8(%rsp),%rdx\n\t" + "movq 16(%rsp),%r8\n\t" + "movq 24(%rsp),%r9\n\t" + "callq *%rax\n\t" + "leaq -16(%rbp),%rsp\n\t" + "popq %rdi\n\t" + ".cfi_same_value %rdi\n\t" + "popq %rsi\n\t" + ".cfi_same_value %rsi\n\t" + ".cfi_def_cfa_register %rsp\n\t" + "popq %rbp\n\t" + ".cfi_adjust_cfa_offset -8\n\t" + ".cfi_same_value %rbp\n\t" + "ret") #endif diff --git a/dlls/ntdll/resource.c b/dlls/ntdll/resource.c index 5f3e845f673..b9d2a6b09b9 100644 --- a/dlls/ntdll/resource.c +++ b/dlls/ntdll/resource.c @@ -357,7 +357,7 @@ static inline NTSTATUS access_resource( HMODULE hmod, const IMAGE_RESOURCE_DATA_ * "call access_resource" instruction being there. */ #ifdef __i386__ -__ASM_GLOBAL_FUNC( LdrAccessResource, +__ASM_STDCALL_FUNC( LdrAccessResource, 16, "pushl %ebp\n\t" "movl %esp, %ebp\n\t" "subl $4,%esp\n\t" diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index 4959946ee54..16533b24178 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -405,7 +405,7 @@ RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *ObjectDescriptor ) * Glorified "enter xxxx". */ #ifdef __i386__ -__ASM_GLOBAL_FUNC( _chkstk, +__ASM_STDCALL_FUNC( _chkstk, 0, "negl %eax\n\t" "addl %esp,%eax\n\t" "xchgl %esp,%eax\n\t" @@ -420,7 +420,7 @@ __ASM_GLOBAL_FUNC( _chkstk, * Glorified "enter xxxx". */ #ifdef __i386__ -__ASM_GLOBAL_FUNC( _alloca_probe, +__ASM_STDCALL_FUNC( _alloca_probe, 0, "negl %eax\n\t" "addl %esp,%eax\n\t" "xchgl %esp,%eax\n\t" diff --git a/dlls/ntdll/sec.c b/dlls/ntdll/sec.c index e74aa8e38e8..950b9dd2b85 100644 --- a/dlls/ntdll/sec.c +++ b/dlls/ntdll/sec.c @@ -45,6 +45,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll); #define NT_SUCCESS(status) (status == STATUS_SUCCESS) +#define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field) + /* helper function to retrieve active length of an ACL */ static size_t acl_bytesInUse(PACL pAcl) { @@ -451,85 +453,74 @@ NTSTATUS WINAPI RtlCreateSecurityDescriptor( */ NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD) { - SECURITY_DESCRIPTOR *srcSD = pSourceSD; - SECURITY_DESCRIPTOR *destSD = pDestinationSD; PSID Owner, Group; PACL Dacl, Sacl; - BOOLEAN defaulted, present; DWORD length; - BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE; - - if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION) - return STATUS_UNKNOWN_REVISION; - - /* copy initial data */ - destSD->Revision = srcSD->Revision; - destSD->Sbz1 = srcSD->Sbz1; - destSD->Control = srcSD->Control; - /* copy Owner */ - RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted); - length = RtlLengthSid(Owner); - - if (isSelfRelative) + if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE) { - destSD->Owner = srcSD->Owner; - RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner); - } - else - { - destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length); - RtlCopySid(length, destSD->Owner, Owner); - } + SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD; + SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD; - /* copy Group */ - RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted); - length = RtlLengthSid(Group); + if (src->Revision != SECURITY_DESCRIPTOR_REVISION) + return STATUS_UNKNOWN_REVISION; - if (isSelfRelative) - { - destSD->Group = srcSD->Group; - RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group); + *dst = *src; + if (src->Owner) + { + Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner ); + length = RtlLengthSid( Owner ); + RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner); + } + if (src->Group) + { + Group = (PSID)SELF_RELATIVE_FIELD( src, Group ); + length = RtlLengthSid( Group ); + RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group); + } + if (src->Control & SE_SACL_PRESENT) + { + Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl ); + copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl); + } + if (src->Control & SE_DACL_PRESENT) + { + Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl ); + copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl); + } } else { - destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length); - RtlCopySid(length, destSD->Group, Group); - } + SECURITY_DESCRIPTOR *src = pSourceSD; + SECURITY_DESCRIPTOR *dst = pDestinationSD; - /* copy Dacl */ - if (srcSD->Control & SE_DACL_PRESENT) - { - RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted); - length = Dacl->AclSize; + if (src->Revision != SECURITY_DESCRIPTOR_REVISION) + return STATUS_UNKNOWN_REVISION; - if (isSelfRelative) + *dst = *src; + if (src->Owner) { - destSD->Dacl = srcSD->Dacl; - copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl); + length = RtlLengthSid( src->Owner ); + dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length); + RtlCopySid(length, dst->Owner, src->Owner); } - else + if (src->Group) { - destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length); - copy_acl(length, destSD->Dacl, Dacl); + length = RtlLengthSid( src->Group ); + dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length); + RtlCopySid(length, dst->Group, src->Group); } - } - - /* copy Sacl */ - if (srcSD->Control & SE_SACL_PRESENT) - { - RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted); - length = Sacl->AclSize; - - if (isSelfRelative) + if (src->Control & SE_SACL_PRESENT) { - destSD->Sacl = srcSD->Sacl; - copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl); + length = src->Sacl->AclSize; + dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length); + copy_acl(length, dst->Sacl, src->Sacl); } - else + if (src->Control & SE_DACL_PRESENT) { - destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length); - copy_acl(length, destSD->Sacl, Sacl); + length = src->Dacl->AclSize; + dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length); + copy_acl(length, dst->Dacl, src->Dacl); } } @@ -565,31 +556,32 @@ NTSTATUS WINAPI RtlValidSecurityDescriptor( ULONG WINAPI RtlLengthSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor) { - SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor; - ULONG_PTR offset = 0; - ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH; + ULONG size; - if ( lpsd == NULL ) + if ( pSecurityDescriptor == NULL ) return 0; - if ( lpsd->Control & SE_SELF_RELATIVE) - offset = (ULONG_PTR) lpsd; - - if ( lpsd->Owner != NULL ) - Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset)); - - if ( lpsd->Group != NULL ) - Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset)); - - if ( (lpsd->Control & SE_SACL_PRESENT) && - lpsd->Sacl != NULL ) - Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize; - - if ( (lpsd->Control & SE_DACL_PRESENT) && - lpsd->Dacl != NULL ) - Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize; - - return Size; + if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE) + { + SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor; + size = sizeof(*sd); + if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner)); + if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group)); + if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) + size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize; + if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) + size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize; + } + else + { + SECURITY_DESCRIPTOR *sd = pSecurityDescriptor; + size = sizeof(*sd); + if (sd->Owner) size += RtlLengthSid( sd->Owner ); + if (sd->Group) size += RtlLengthSid( sd->Group ); + if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize; + if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize; + } + return size; } /****************************************************************************** @@ -613,7 +605,7 @@ NTSTATUS WINAPI RtlGetDaclSecurityDescriptor( if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) ) { if ( SE_SELF_RELATIVE & lpsd->Control) - *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl); + *pDacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Dacl ); else *pDacl = lpsd->Dacl; @@ -682,13 +674,12 @@ NTSTATUS WINAPI RtlGetSaclSecurityDescriptor( if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) ) { if (SE_SELF_RELATIVE & lpsd->Control) - *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl); + *pSacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Sacl ); else *pSacl = lpsd->Sacl; *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0); } - return STATUS_SUCCESS; } @@ -738,16 +729,14 @@ NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor( else *OwnerDefaulted = FALSE; - if (lpsd->Owner != NULL) - { - if (lpsd->Control & SE_SELF_RELATIVE) - *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner); - else - *Owner = lpsd->Owner; - + if (lpsd->Control & SE_SELF_RELATIVE) + { + SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor; + if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner ); + else *Owner = NULL; } - else - *Owner = NULL; + else + *Owner = lpsd->Owner; return STATUS_SUCCESS; } @@ -816,15 +805,14 @@ NTSTATUS WINAPI RtlGetGroupSecurityDescriptor( else *GroupDefaulted = FALSE; - if (lpsd->Group != NULL) - { - if (lpsd->Control & SE_SELF_RELATIVE) - *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group); - else - *Group = lpsd->Group; - } - else - *Group = NULL; + if (lpsd->Control & SE_SELF_RELATIVE) + { + SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor; + if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group ); + else *Group = NULL; + } + else + *Group = lpsd->Group; return STATUS_SUCCESS; } @@ -837,10 +825,10 @@ NTSTATUS WINAPI RtlMakeSelfRelativeSD( IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, IN OUT LPDWORD lpdwBufferLength) { - ULONG_PTR offsetRel; + DWORD offsetRel; ULONG length; SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor; - SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor; + SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor; TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength, lpdwBufferLength ? *lpdwBufferLength: -1); @@ -868,52 +856,52 @@ NTSTATUS WINAPI RtlMakeSelfRelativeSD( pRel->Sbz1 = pAbs->Sbz1; pRel->Control = pAbs->Control | SE_SELF_RELATIVE; - offsetRel = sizeof(SECURITY_DESCRIPTOR); + offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE); if (pAbs->Owner) { - pRel->Owner = (PSID) offsetRel; + pRel->Owner = offsetRel; length = RtlLengthSid(pAbs->Owner); memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length); offsetRel += length; } else { - pRel->Owner = NULL; + pRel->Owner = 0; } if (pAbs->Group) { - pRel->Group = (PSID) offsetRel; + pRel->Group = offsetRel; length = RtlLengthSid(pAbs->Group); memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length); offsetRel += length; } else { - pRel->Group = NULL; + pRel->Group = 0; } if (pAbs->Sacl) { - pRel->Sacl = (PACL) offsetRel; + pRel->Sacl = offsetRel; length = pAbs->Sacl->AclSize; memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length); offsetRel += length; } else { - pRel->Sacl = NULL; + pRel->Sacl = 0; } if (pAbs->Dacl) { - pRel->Dacl = (PACL) offsetRel; + pRel->Dacl = offsetRel; length = pAbs->Dacl->AclSize; memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length); } else { - pRel->Dacl = NULL; + pRel->Dacl = 0; } return STATUS_SUCCESS; @@ -938,7 +926,7 @@ NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD( { NTSTATUS status = STATUS_SUCCESS; SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor; - SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor; + SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor; if (!pRel || !lpdwAbsoluteSecurityDescriptorSize || @@ -957,30 +945,30 @@ NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD( } if (pRel->Control & SE_DACL_PRESENT && - *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize) + *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize) { - *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize; + *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize; status = STATUS_BUFFER_TOO_SMALL; } if (pRel->Control & SE_SACL_PRESENT && - *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize) + *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize) { - *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize; + *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize; status = STATUS_BUFFER_TOO_SMALL; } if (pRel->Owner && - *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel))) + *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner))) { - *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)); + *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)); status = STATUS_BUFFER_TOO_SMALL; } if (pRel->Group && - *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel))) + *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group))) { - *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)); + *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)); status = STATUS_BUFFER_TOO_SMALL; } @@ -997,7 +985,7 @@ NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD( if (pRel->Control & SE_SACL_PRESENT) { - PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel); + PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl ); memcpy(pSacl, pAcl, pAcl->AclSize); pAbs->Sacl = pSacl; @@ -1005,21 +993,21 @@ NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD( if (pRel->Control & SE_DACL_PRESENT) { - PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel); + PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl ); memcpy(pDacl, pAcl, pAcl->AclSize); pAbs->Dacl = pDacl; } if (pRel->Owner) { - PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel); + PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner ); memcpy(pOwner, psid, RtlLengthSid(psid)); pAbs->Owner = pOwner; } if (pRel->Group) { - PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel); + PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group ); memcpy(pPrimaryGroup, psid, RtlLengthSid(psid)); pAbs->Group = pPrimaryGroup; } diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 13896f655fd..ff251fa3d0a 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -2264,20 +2264,58 @@ void WINAPI __regs_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context ) DEFINE_REGS_ENTRYPOINT( RtlRaiseException, 1 ) +/* wrapper for apps that don't declare the thread function correctly */ +extern void DECLSPEC_NORETURN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg ); +__ASM_GLOBAL_FUNC(call_thread_func, + "pushl %ebp\n\t" + "movl %esp,%ebp\n\t" + "subl $4,%esp\n\t" + "pushl 12(%ebp)\n\t" + "call *8(%ebp)\n\t" + "leal -4(%ebp),%esp\n\t" + "pushl %eax\n\t" + "call " __ASM_NAME("exit_thread") "\n\t" + "int $3" ) + +/*********************************************************************** + * call_thread_entry_point + */ +void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) +{ + __TRY + { + call_thread_func( entry, arg ); + } + __EXCEPT(unhandled_exception_filter) + { + NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY + abort(); /* should not be reached */ +} + +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} + /********************************************************************** * DbgBreakPoint (NTDLL.@) */ -__ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret") +__ASM_STDCALL_FUNC( DbgBreakPoint, 0, "int $3; ret") /********************************************************************** * DbgUserBreakPoint (NTDLL.@) */ -__ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret") +__ASM_STDCALL_FUNC( DbgUserBreakPoint, 0, "int $3; ret") /********************************************************************** * NtCurrentTeb (NTDLL.@) */ -__ASM_GLOBAL_FUNC( NtCurrentTeb, ".byte 0x64\n\tmovl 0x18,%eax\n\tret" ) +__ASM_STDCALL_FUNC( NtCurrentTeb, 0, ".byte 0x64\n\tmovl 0x18,%eax\n\tret" ) /********************************************************************** diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index 40b80619c14..92288ad558a 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -1086,6 +1086,31 @@ void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec ) if (status) raise_status( status, rec ); } +/*********************************************************************** + * call_thread_entry_point + */ +void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) +{ + __TRY + { + exit_thread( entry( arg )); + } + __EXCEPT(unhandled_exception_filter) + { + NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY + abort(); /* should not be reached */ +} + +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} + /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/signal_sparc.c b/dlls/ntdll/signal_sparc.c index a024d2e196e..55b2a791913 100644 --- a/dlls/ntdll/signal_sparc.c +++ b/dlls/ntdll/signal_sparc.c @@ -828,6 +828,31 @@ void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec ) if (status) raise_status( status, rec ); } +/*********************************************************************** + * call_thread_entry_point + */ +void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) +{ + __TRY + { + exit_thread( entry( arg )); + } + __EXCEPT(unhandled_exception_filter) + { + NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY + abort(); /* should not be reached */ +} + +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} + /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 1748221e63d..716efea3401 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -188,11 +188,18 @@ enum i386_trap_code TRAP_x86_CACHEFLT = 19 /* Cache flush exception */ }; +static const size_t teb_size = 0x2000; /* we reserve two pages for the TEB */ +static size_t signal_stack_size; + +typedef void (*raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context ); typedef int (*wine_signal_handler)(unsigned int sig); static wine_signal_handler handlers[256]; -/* definitions for unwind tables */ + +/*********************************************************************** + * Definitions for Win32 unwind tables + */ union handler_data { @@ -348,6 +355,607 @@ static void dump_scope_table( ULONG64 base, const SCOPE_TABLE *table ) base + table->ScopeRecord[i].JumpTarget ); } + +/*********************************************************************** + * Definitions for Dwarf unwind tables + */ + +enum dwarf_call_frame_info +{ + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + DW_CFA_nop = 0x00, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, +}; + +#define DW_EH_PE_native 0x00 +#define DW_EH_PE_leb128 0x01 +#define DW_EH_PE_data2 0x02 +#define DW_EH_PE_data4 0x03 +#define DW_EH_PE_data8 0x04 +#define DW_EH_PE_signed 0x08 +#define DW_EH_PE_abs 0x00 +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 +#define DW_EH_PE_indirect 0x80 +#define DW_EH_PE_omit 0xff + +struct dwarf_eh_bases +{ + void *tbase; + void *dbase; + void *func; +}; + +struct dwarf_cie +{ + unsigned int length; + int id; + unsigned char version; + unsigned char augmentation[1]; +}; + +struct dwarf_fde +{ + unsigned int length; + unsigned int cie_offset; +}; + +extern const struct dwarf_fde *_Unwind_Find_FDE (void *, struct dwarf_eh_bases *); + +static unsigned short dwarf_get_u2( const unsigned char **p ) +{ + unsigned int ret = (*p)[0] | ((*p)[1] << 8); + (*p) += 2; + return ret; +} + +static unsigned int dwarf_get_u4( const unsigned char **p ) +{ + unsigned int ret = (*p)[0] | ((*p)[1] << 8) | ((*p)[2] << 16) | ((*p)[3] << 24); + (*p) += 4; + return ret; +} + +static ULONG64 dwarf_get_u8( const unsigned char **p ) +{ + ULONG64 low = dwarf_get_u4( p ); + ULONG64 high = dwarf_get_u4( p ); + return low | (high << 32); +} + +static ULONG_PTR dwarf_get_uleb128( const unsigned char **p ) +{ + ULONG_PTR ret = 0; + unsigned int shift = 0; + unsigned char byte; + + do + { + byte = **p; + ret |= (ULONG_PTR)(byte & 0x7f) << shift; + shift += 7; + (*p)++; + } while (byte & 0x80); + return ret; +} + +static LONG_PTR dwarf_get_sleb128( const unsigned char **p ) +{ + ULONG_PTR ret = 0; + unsigned int shift = 0; + unsigned char byte; + + do + { + byte = **p; + ret |= (ULONG_PTR)(byte & 0x7f) << shift; + shift += 7; + (*p)++; + } while (byte & 0x80); + + if ((shift < 8 * sizeof(ret)) && (byte & 0x40)) ret |= -((ULONG_PTR)1 << shift); + return ret; +} + +static ULONG_PTR dwarf_get_ptr( const unsigned char **p, unsigned char encoding ) +{ + ULONG_PTR base; + + if (encoding == DW_EH_PE_omit) return 0; + + switch (encoding & 0xf0) + { + case DW_EH_PE_abs: + base = 0; + break; + case DW_EH_PE_pcrel: + base = (ULONG_PTR)*p; + break; + default: + FIXME( "unsupported encoding %02x\n", encoding ); + return 0; + } + + switch (encoding & 0x0f) + { + case DW_EH_PE_native: + return base + dwarf_get_u8( p ); + case DW_EH_PE_leb128: + return base + dwarf_get_uleb128( p ); + case DW_EH_PE_data2: + return base + dwarf_get_u2( p ); + case DW_EH_PE_data4: + return base + dwarf_get_u4( p ); + case DW_EH_PE_data8: + return base + dwarf_get_u8( p ); + case DW_EH_PE_signed|DW_EH_PE_leb128: + return base + dwarf_get_sleb128( p ); + case DW_EH_PE_signed|DW_EH_PE_data2: + return base + (signed short)dwarf_get_u2( p ); + case DW_EH_PE_signed|DW_EH_PE_data4: + return base + (signed int)dwarf_get_u4( p ); + case DW_EH_PE_signed|DW_EH_PE_data8: + return base + (LONG64)dwarf_get_u8( p ); + default: + FIXME( "unsupported encoding %02x\n", encoding ); + return 0; + } +} + +enum reg_rule +{ + RULE_UNSET, /* not set at all */ + RULE_UNDEFINED, /* undefined value */ + RULE_SAME, /* same value as previous frame */ + RULE_CFA_OFFSET, /* stored at cfa offset */ + RULE_OTHER_REG /* stored in other register */ +}; + +#define NB_FRAME_REGS 41 + +struct frame_info +{ + ULONG_PTR ip; + ULONG_PTR code_align; + LONG_PTR data_align; + ULONG_PTR cfa_offset; + unsigned char cfa_reg; + unsigned char retaddr_reg; + unsigned char fde_encoding; + unsigned char signal_frame; + enum reg_rule rules[NB_FRAME_REGS]; + ULONG64 regs[NB_FRAME_REGS]; +}; + +static const char *dwarf_reg_names[NB_FRAME_REGS] = +{ +/* 0-7 */ "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp", +/* 8-16 */ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rip", +/* 17-24 */ "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", +/* 25-32 */ "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15", +/* 33-40 */ "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7" +}; + +static int valid_reg( ULONG_PTR reg ) +{ + if (reg >= NB_FRAME_REGS) FIXME( "unsupported reg %lx\n", reg ); + return (reg < NB_FRAME_REGS); +} + +static void execute_cfa_instructions( const unsigned char *ptr, const unsigned char *end, + ULONG_PTR last_ip, struct frame_info *info ) +{ + while (ptr < end && info->ip < last_ip + info->signal_frame) + { + enum dwarf_call_frame_info op = *ptr++; + + if (op & 0xc0) + { + switch (op & 0xc0) + { + case DW_CFA_advance_loc: + { + ULONG_PTR offset = (op & 0x3f) * info->code_align; + TRACE( "%lx: DW_CFA_advance_loc %lu\n", info->ip, offset ); + info->ip += offset; + break; + } + case DW_CFA_offset: + { + ULONG_PTR reg = op & 0x3f; + LONG_PTR offset = dwarf_get_uleb128( &ptr ) * info->data_align; + if (!valid_reg( reg )) break; + TRACE( "%lx: DW_CFA_offset %s, %ld\n", info->ip, dwarf_reg_names[reg], offset ); + info->regs[reg] = offset; + info->rules[reg] = RULE_CFA_OFFSET; + break; + } + case DW_CFA_restore: + { + ULONG_PTR reg = op & 0x3f; + if (!valid_reg( reg )) break; + TRACE( "%lx: DW_CFA_restore %s\n", info->ip, dwarf_reg_names[reg] ); + info->rules[reg] = RULE_UNSET; + break; + } + } + } + else switch (op) + { + case DW_CFA_nop: + break; + case DW_CFA_set_loc: + { + ULONG_PTR loc = dwarf_get_ptr( &ptr, info->fde_encoding ); + TRACE( "%lx: DW_CFA_set_loc %lx\n", info->ip, loc ); + info->ip = loc; + break; + } + case DW_CFA_advance_loc1: + { + ULONG_PTR offset = *ptr++ * info->code_align; + TRACE( "%lx: DW_CFA_advance_loc1 %lu\n", info->ip, offset ); + info->ip += offset; + break; + } + case DW_CFA_advance_loc2: + { + ULONG_PTR offset = dwarf_get_u2( &ptr ) * info->code_align; + TRACE( "%lx: DW_CFA_advance_loc2 %lu\n", info->ip, offset ); + info->ip += offset; + break; + } + case DW_CFA_advance_loc4: + { + ULONG_PTR offset = dwarf_get_u4( &ptr ) * info->code_align; + TRACE( "%lx: DW_CFA_advance_loc4 %lu\n", info->ip, offset ); + info->ip += offset; + break; + } + case DW_CFA_offset_extended: + { + ULONG_PTR reg = dwarf_get_uleb128( &ptr ); + LONG_PTR offset = dwarf_get_uleb128( &ptr ) * info->data_align; + if (!valid_reg( reg )) break; + TRACE( "%lx: DW_CFA_offset_extended %s, %ld\n", info->ip, dwarf_reg_names[reg], offset ); + info->regs[reg] = offset; + info->rules[reg] = RULE_CFA_OFFSET; + break; + } + case DW_CFA_restore_extended: + { + ULONG_PTR reg = dwarf_get_uleb128( &ptr ); + if (!valid_reg( reg )) break; + TRACE( "%lx: DW_CFA_restore_extended %s\n", info->ip, dwarf_reg_names[reg] ); + info->rules[reg] = RULE_UNSET; + break; + } + case DW_CFA_undefined: + { + ULONG_PTR reg = dwarf_get_uleb128( &ptr ); + if (!valid_reg( reg )) break; + TRACE( "%lx: DW_CFA_undefined %s\n", info->ip, dwarf_reg_names[reg] ); + info->rules[reg] = RULE_UNDEFINED; + break; + } + case DW_CFA_same_value: + { + ULONG_PTR reg = dwarf_get_uleb128( &ptr ); + if (!valid_reg( reg )) break; + TRACE( "%lx: DW_CFA_same_value %s\n", info->ip, dwarf_reg_names[reg] ); + info->regs[reg] = reg; + info->rules[reg] = RULE_SAME; + break; + } + case DW_CFA_register: + { + ULONG_PTR reg = dwarf_get_uleb128( &ptr ); + ULONG_PTR reg2 = dwarf_get_uleb128( &ptr ); + if (!valid_reg( reg ) || !valid_reg( reg2 )) break; + TRACE( "%lx: DW_CFA_register %s == %s\n", info->ip, dwarf_reg_names[reg], dwarf_reg_names[reg2] ); + info->regs[reg] = reg2; + info->rules[reg] = RULE_OTHER_REG; + break; + } + case DW_CFA_remember_state: + FIXME( "%lx: DW_CFA_remember_state not implemented\n", info->ip ); + break; + case DW_CFA_restore_state: + FIXME( "%lx: DW_CFA_restore_state not implemented\n", info->ip ); + break; + case DW_CFA_def_cfa: + { + ULONG_PTR reg = dwarf_get_uleb128( &ptr ); + ULONG_PTR offset = dwarf_get_uleb128( &ptr ); + if (!valid_reg( reg )) break; + TRACE( "%lx: DW_CFA_def_cfa %s, %lu\n", info->ip, dwarf_reg_names[reg], offset ); + info->cfa_reg = reg; + info->cfa_offset = offset; + break; + } + case DW_CFA_def_cfa_register: + { + ULONG_PTR reg = dwarf_get_uleb128( &ptr ); + if (!valid_reg( reg )) break; + TRACE( "%lx: DW_CFA_def_cfa_register %s\n", info->ip, dwarf_reg_names[reg] ); + info->cfa_reg = reg; + break; + } + case DW_CFA_def_cfa_offset: + { + ULONG_PTR offset = dwarf_get_uleb128( &ptr ); + TRACE( "%lx: DW_CFA_def_cfa_offset %lu\n", info->ip, offset ); + info->cfa_offset = offset; + break; + } + default: + FIXME( "%lx: unknown CFA opcode %02x\n", info->ip, op ); + break; + } + } +} + +/* retrieve a context register from its dwarf number */ +static void *get_context_reg( CONTEXT *context, ULONG_PTR dw_reg ) +{ + switch (dw_reg) + { + case 0: return &context->Rax; + case 1: return &context->Rdx; + case 2: return &context->Rcx; + case 3: return &context->Rbx; + case 4: return &context->Rsi; + case 5: return &context->Rdi; + case 6: return &context->Rbp; + case 7: return &context->Rsp; + case 8: return &context->R8; + case 9: return &context->R9; + case 10: return &context->R10; + case 11: return &context->R11; + case 12: return &context->R12; + case 13: return &context->R13; + case 14: return &context->R14; + case 15: return &context->R15; + case 16: return &context->Rip; + case 17: return &context->u.s.Xmm0; + case 18: return &context->u.s.Xmm1; + case 19: return &context->u.s.Xmm2; + case 20: return &context->u.s.Xmm3; + case 21: return &context->u.s.Xmm4; + case 22: return &context->u.s.Xmm5; + case 23: return &context->u.s.Xmm6; + case 24: return &context->u.s.Xmm7; + case 25: return &context->u.s.Xmm8; + case 26: return &context->u.s.Xmm9; + case 27: return &context->u.s.Xmm10; + case 28: return &context->u.s.Xmm11; + case 29: return &context->u.s.Xmm12; + case 30: return &context->u.s.Xmm13; + case 31: return &context->u.s.Xmm14; + case 32: return &context->u.s.Xmm15; + case 33: return &context->u.s.Legacy[0]; + case 34: return &context->u.s.Legacy[1]; + case 35: return &context->u.s.Legacy[2]; + case 36: return &context->u.s.Legacy[3]; + case 37: return &context->u.s.Legacy[4]; + case 38: return &context->u.s.Legacy[5]; + case 39: return &context->u.s.Legacy[6]; + case 40: return &context->u.s.Legacy[7]; + default: return NULL; + } +} + +/* set a context register from its dwarf number */ +static void set_context_reg( CONTEXT *context, ULONG_PTR dw_reg, void *val ) +{ + switch (dw_reg) + { + case 0: context->Rax = *(ULONG64 *)val; break; + case 1: context->Rdx = *(ULONG64 *)val; break; + case 2: context->Rcx = *(ULONG64 *)val; break; + case 3: context->Rbx = *(ULONG64 *)val; break; + case 4: context->Rsi = *(ULONG64 *)val; break; + case 5: context->Rdi = *(ULONG64 *)val; break; + case 6: context->Rbp = *(ULONG64 *)val; break; + case 7: context->Rsp = *(ULONG64 *)val; break; + case 8: context->R8 = *(ULONG64 *)val; break; + case 9: context->R9 = *(ULONG64 *)val; break; + case 10: context->R10 = *(ULONG64 *)val; break; + case 11: context->R11 = *(ULONG64 *)val; break; + case 12: context->R12 = *(ULONG64 *)val; break; + case 13: context->R13 = *(ULONG64 *)val; break; + case 14: context->R14 = *(ULONG64 *)val; break; + case 15: context->R15 = *(ULONG64 *)val; break; + case 16: context->Rip = *(ULONG64 *)val; break; + case 17: context->u.s.Xmm0 = *(M128A *)val; break; + case 18: context->u.s.Xmm1 = *(M128A *)val; break; + case 19: context->u.s.Xmm2 = *(M128A *)val; break; + case 20: context->u.s.Xmm3 = *(M128A *)val; break; + case 21: context->u.s.Xmm4 = *(M128A *)val; break; + case 22: context->u.s.Xmm5 = *(M128A *)val; break; + case 23: context->u.s.Xmm6 = *(M128A *)val; break; + case 24: context->u.s.Xmm7 = *(M128A *)val; break; + case 25: context->u.s.Xmm8 = *(M128A *)val; break; + case 26: context->u.s.Xmm9 = *(M128A *)val; break; + case 27: context->u.s.Xmm10 = *(M128A *)val; break; + case 28: context->u.s.Xmm11 = *(M128A *)val; break; + case 29: context->u.s.Xmm12 = *(M128A *)val; break; + case 30: context->u.s.Xmm13 = *(M128A *)val; break; + case 31: context->u.s.Xmm14 = *(M128A *)val; break; + case 32: context->u.s.Xmm15 = *(M128A *)val; break; + case 33: context->u.s.Legacy[0] = *(M128A *)val; break; + case 34: context->u.s.Legacy[1] = *(M128A *)val; break; + case 35: context->u.s.Legacy[2] = *(M128A *)val; break; + case 36: context->u.s.Legacy[3] = *(M128A *)val; break; + case 37: context->u.s.Legacy[4] = *(M128A *)val; break; + case 38: context->u.s.Legacy[5] = *(M128A *)val; break; + case 39: context->u.s.Legacy[6] = *(M128A *)val; break; + case 40: context->u.s.Legacy[7] = *(M128A *)val; break; + } +} + +/* apply the computed frame info to the actual context */ +static void apply_frame_info( CONTEXT *context, struct frame_info *info, ULONG_PTR cfa ) +{ + unsigned int i; + + for (i = 0; i < NB_FRAME_REGS; i++) + { + switch (info->rules[i]) + { + case RULE_UNSET: + case RULE_UNDEFINED: + case RULE_SAME: + break; + case RULE_CFA_OFFSET: + set_context_reg( context, i, (char *)cfa + info->regs[i] ); + break; + case RULE_OTHER_REG: + FIXME( "other reg rule (%s == %s) not supported yet\n", + dwarf_reg_names[i], dwarf_reg_names[info->regs[i]] ); + break; + } + } + context->Rsp = cfa; +} + + +/*********************************************************************** + * dwarf_virtual_unwind + * + * Equivalent of RtlVirtualUnwind for builtin modules. + */ +static NTSTATUS dwarf_virtual_unwind( ULONG64 ip, ULONG64 *frame,CONTEXT *context, + const struct dwarf_fde *fde, const struct dwarf_eh_bases *bases, + PEXCEPTION_ROUTINE *handler, void **handler_data ) +{ + const struct dwarf_cie *cie; + const unsigned char *ptr, *augmentation, *end; + ULONG_PTR len, cfa, code_end; + struct frame_info info; + int aug_z_format = 0; + unsigned char lsda_encoding = DW_EH_PE_omit; + + memset( &info, 0, sizeof(info) ); + info.ip = (ULONG_PTR)bases->func; + *handler = NULL; + + cie = (const struct dwarf_cie *)((const char *)&fde->cie_offset - fde->cie_offset); + + /* parse the CIE first */ + + if (cie->version != 1) + { + FIXME( "unknown CIE version %u at %p\n", cie->version, cie ); + return STATUS_INVALID_DISPOSITION; + } + ptr = cie->augmentation + strlen((const char *)cie->augmentation) + 1; + + info.code_align = dwarf_get_uleb128( &ptr ); + info.data_align = dwarf_get_sleb128( &ptr ); + info.retaddr_reg = *ptr++; + + TRACE( "function %lx base %p cie %p len %x id %x version %x aug '%s' code_align %lu data_align %ld retaddr %s\n", + ip, bases->func, cie, cie->length, cie->id, cie->version, cie->augmentation, + info.code_align, info.data_align, dwarf_reg_names[info.retaddr_reg] ); + + end = NULL; + for (augmentation = cie->augmentation; *augmentation; augmentation++) + { + switch (*augmentation) + { + case 'z': + len = dwarf_get_uleb128( &ptr ); + end = ptr + len; + aug_z_format = 1; + continue; + case 'L': + lsda_encoding = *ptr++; + continue; + case 'P': + { + unsigned char encoding = *ptr++; + *handler = (void *)dwarf_get_ptr( &ptr, encoding ); + continue; + } + case 'R': + info.fde_encoding = *ptr++; + continue; + case 'S': + info.signal_frame = 1; + continue; + } + FIXME( "unknown augmentation '%c'\n", *augmentation ); + if (!end) return STATUS_INVALID_DISPOSITION; /* cannot continue */ + break; + } + if (end) ptr = end; + + end = (const unsigned char *)(&cie->length + 1) + cie->length; + execute_cfa_instructions( ptr, end, ip, &info ); + + ptr = (const unsigned char *)(fde + 1); + info.ip = dwarf_get_ptr( &ptr, info.fde_encoding ); /* fde code start */ + code_end = info.ip + dwarf_get_ptr( &ptr, info.fde_encoding & 0x0f ); /* fde code length */ + + if (aug_z_format) /* get length of augmentation data */ + { + len = dwarf_get_uleb128( &ptr ); + end = ptr + len; + } + else end = NULL; + + *handler_data = (void *)dwarf_get_ptr( &ptr, lsda_encoding ); + if (end) ptr = end; + + end = (const unsigned char *)(&fde->length + 1) + fde->length; + TRACE( "fde %p len %x personality %p lsda %p code %lx-%lx\n", + fde, fde->length, *handler, *handler_data, info.ip, code_end ); + execute_cfa_instructions( ptr, end, ip, &info ); + + *frame = cfa = *(ULONG_PTR *)get_context_reg( context, info.cfa_reg ) + info.cfa_offset; + if (cfa) apply_frame_info( context, &info, cfa ); + + TRACE( "next function rip=%016lx\n", context->Rip ); + TRACE( " rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", + context->Rax, context->Rbx, context->Rcx, context->Rdx ); + TRACE( " rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n", + context->Rsi, context->Rdi, context->Rbp, context->Rsp ); + TRACE( " r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n", + context->R8, context->R9, context->R10, context->R11 ); + TRACE( " r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", + context->R12, context->R13, context->R14, context->R15 ); + + return STATUS_SUCCESS; +} + + /*********************************************************************** * dispatch_signal */ @@ -358,6 +966,16 @@ static inline int dispatch_signal(unsigned int sig) } /*********************************************************************** + * get_signal_stack + * + * Get the base of the signal stack for the current thread. + */ +static inline void *get_signal_stack(void) +{ + return (char *)NtCurrentTeb() + teb_size; +} + +/*********************************************************************** * save_context * * Set the register values from a sigcontext. @@ -666,6 +1284,108 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) } +extern void raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func ); +__ASM_GLOBAL_FUNC( raise_func_trampoline, + ".cfi_signal_frame\n\t" + ".cfi_def_cfa %rbp,144\n\t" /* red zone + rip + rbp */ + ".cfi_rel_offset %rip,8\n\t" + ".cfi_rel_offset %rbp,0\n\t" + "call *%rdx\n\t" + "int $3") + +/*********************************************************************** + * setup_exception + * + * Setup a proper stack frame for the raise function, and modify the + * sigcontext so that the return from the signal handler will call + * the raise function. + */ +static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func func ) +{ + struct stack_layout + { + CONTEXT context; + EXCEPTION_RECORD rec; + ULONG64 rbp; + ULONG64 rip; + ULONG64 red_zone[16]; + } *stack; + ULONG64 *rsp_ptr; + DWORD exception_code = 0; + + stack = (struct stack_layout *)(RSP_sig(sigcontext) & ~15); + + /* stack sanity checks */ + + if ((char *)stack >= (char *)get_signal_stack() && + (char *)stack < (char *)get_signal_stack() + signal_stack_size) + { + ERR( "nested exception on signal stack in thread %04x eip %016lx esp %016lx stack %p-%p\n", + GetCurrentThreadId(), RIP_sig(sigcontext), RSP_sig(sigcontext), + NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase ); + abort_thread(1); + } + + if (stack - 1 > stack || /* check for overflow in subtraction */ + (char *)stack <= (char *)NtCurrentTeb()->DeallocationStack || + (char *)stack > (char *)NtCurrentTeb()->Tib.StackBase) + { + WARN( "exception outside of stack limits in thread %04x eip %016lx esp %016lx stack %p-%p\n", + GetCurrentThreadId(), RIP_sig(sigcontext), RSP_sig(sigcontext), + NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase ); + } + else if ((char *)(stack - 1) < (char *)NtCurrentTeb()->DeallocationStack + 4096) + { + /* stack overflow on last page, unrecoverable */ + UINT diff = (char *)NtCurrentTeb()->DeallocationStack + 4096 - (char *)(stack - 1); + ERR( "stack overflow %u bytes in thread %04x eip %016lx esp %016lx stack %p-%p-%p\n", + diff, GetCurrentThreadId(), RIP_sig(sigcontext), + RSP_sig(sigcontext), NtCurrentTeb()->DeallocationStack, + NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase ); + abort_thread(1); + } + else if ((char *)(stack - 1) < (char *)NtCurrentTeb()->Tib.StackLimit) + { + /* stack access below stack limit, may be recoverable */ + if (virtual_handle_stack_fault( stack - 1 )) exception_code = EXCEPTION_STACK_OVERFLOW; + else + { + UINT diff = (char *)NtCurrentTeb()->Tib.StackLimit - (char *)(stack - 1); + ERR( "stack overflow %u bytes in thread %04x eip %016lx esp %016lx stack %p-%p-%p\n", + diff, GetCurrentThreadId(), RIP_sig(sigcontext), + RSP_sig(sigcontext), NtCurrentTeb()->DeallocationStack, + NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase ); + abort_thread(1); + } + } + + stack--; /* push the stack_layout structure */ + stack->rec.ExceptionRecord = NULL; + stack->rec.ExceptionCode = exception_code; + stack->rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + stack->rec.ExceptionAddress = (void *)RIP_sig(sigcontext); + stack->rec.NumberParameters = 0; + save_context( &stack->context, sigcontext ); + + /* store return address and %rbp without aligning, so that the offset is fixed */ + rsp_ptr = (ULONG64 *)RSP_sig(sigcontext) - 16; + *(--rsp_ptr) = RIP_sig(sigcontext); + *(--rsp_ptr) = RBP_sig(sigcontext); + + /* now modify the sigcontext to return to the raise function */ + RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; + RDI_sig(sigcontext) = (ULONG_PTR)&stack->rec; + RSI_sig(sigcontext) = (ULONG_PTR)&stack->context; + RDX_sig(sigcontext) = (ULONG_PTR)func; + RBP_sig(sigcontext) = (ULONG_PTR)rsp_ptr; + RSP_sig(sigcontext) = (ULONG_PTR)stack; + /* clear single-step, direction, and align check flag */ + EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000); + + return &stack->rec; +} + + /********************************************************************** * find_function_info */ @@ -691,6 +1411,75 @@ static RUNTIME_FUNCTION *find_function_info( ULONG64 pc, HMODULE module, return NULL; } + +/********************************************************************** + * call_handler + * + * Call a single exception handler. + * FIXME: Handle nested exceptions. + */ +static NTSTATUS call_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch, CONTEXT *orig_context ) +{ + DWORD res; + + dispatch->ControlPc = dispatch->ContextRecord->Rip; + + TRACE( "calling handler %p (rec=%p, frame=0x%lx context=%p, dispatch=%p)\n", + dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); + res = dispatch->LanguageHandler( rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); + TRACE( "handler at %p returned %u\n", dispatch->LanguageHandler, res ); + + switch (res) + { + case ExceptionContinueExecution: + if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION; + *orig_context = *dispatch->ContextRecord; + return STATUS_SUCCESS; + case ExceptionContinueSearch: + break; + case ExceptionNestedException: + break; + default: + return STATUS_INVALID_DISPOSITION; + } + return STATUS_UNHANDLED_EXCEPTION; +} + + +/********************************************************************** + * call_teb_handler + * + * Call a single exception handler from the TEB chain. + * FIXME: Handle nested exceptions. + */ +static NTSTATUS call_teb_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch, + EXCEPTION_REGISTRATION_RECORD *teb_frame, CONTEXT *orig_context ) +{ + EXCEPTION_REGISTRATION_RECORD *dispatcher; + DWORD res; + + TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatcher=%p)\n", + teb_frame->Handler, rec, teb_frame, dispatch->ContextRecord, &dispatcher ); + res = teb_frame->Handler( rec, teb_frame, dispatch->ContextRecord, &dispatcher ); + TRACE( "handler at %p returned %u\n", teb_frame->Handler, res ); + + switch (res) + { + case ExceptionContinueExecution: + if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION; + *orig_context = *dispatch->ContextRecord; + return STATUS_SUCCESS; + case ExceptionContinueSearch: + break; + case ExceptionNestedException: + break; + default: + return STATUS_INVALID_DISPOSITION; + } + return STATUS_UNHANDLED_EXCEPTION; +} + + /********************************************************************** * call_stack_handlers * @@ -698,91 +1487,111 @@ static RUNTIME_FUNCTION *find_function_info( ULONG64 pc, HMODULE module, */ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) { - EXCEPTION_POINTERS ptrs; + EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; UNWIND_HISTORY_TABLE table; - ULONG64 frame; - RUNTIME_FUNCTION *dir, *info; - PEXCEPTION_ROUTINE handler; + RUNTIME_FUNCTION *dir; DISPATCHER_CONTEXT dispatch; CONTEXT context, new_context; LDR_MODULE *module; DWORD size; + NTSTATUS status; context = *orig_context; + dispatch.TargetIp = 0; + dispatch.ContextRecord = &context; + dispatch.HistoryTable = &table; + dispatch.ScopeIndex = 0; /* FIXME */ for (;;) { + new_context = context; + /* FIXME: should use the history table to make things faster */ - if (LdrFindEntryForAddress( (void *)context.Rip, &module )) + dir = NULL; + module = NULL; + dispatch.ImageBase = 0; + + if (!LdrFindEntryForAddress( (void *)context.Rip, &module )) { - ERR( "no module found for rip %p, can't dispatch exception\n", (void *)context.Rip ); - break; + if (!(dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, + IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size )) && + !(module->Flags & LDR_WINE_INTERNAL)) + { + ERR( "module %s doesn't contain exception data, can't dispatch exception\n", + debugstr_w(module->BaseDllName.Buffer) ); + break; + } + dispatch.ImageBase = (ULONG64)module->BaseAddress; } - if (!(dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, - IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size ))) + + if (!dir) { - ERR( "module %s doesn't contain exception data, can't dispatch exception\n", - debugstr_w(module->BaseDllName.Buffer) ); - break; + struct dwarf_eh_bases bases; + const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context.Rip - 1), &bases ); + if (!fde) + { + ERR( "no exception data found in %s for function %lx\n", + module ? debugstr_w(module->BaseDllName.Buffer) : "system library", context.Rip ); + break; + } + status = dwarf_virtual_unwind( context.Rip, &dispatch.EstablisherFrame, &new_context, + fde, &bases, &dispatch.LanguageHandler, &dispatch.HandlerData ); + if (status != STATUS_SUCCESS) return status; + dispatch.FunctionEntry = NULL; + if (dispatch.LanguageHandler && !module) + { + FIXME( "calling personality routine in system library not supported yet\n" ); + dispatch.LanguageHandler = NULL; + } } - if (!(info = find_function_info( context.Rip, module->BaseAddress, dir, size ))) + else { - /* leaf function */ - context.Rip = *(ULONG64 *)context.Rsp; - context.Rsp += sizeof(ULONG64); - continue; + if (!(dispatch.FunctionEntry = find_function_info( context.Rip, module->BaseAddress, + dir, size ))) + { + /* leaf function */ + context.Rip = *(ULONG64 *)context.Rsp; + context.Rsp += sizeof(ULONG64); + continue; + } + dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, dispatch.ImageBase, + context.Rip, dispatch.FunctionEntry, + &new_context, &dispatch.HandlerData, + &dispatch.EstablisherFrame, NULL ); } - new_context = context; - - handler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, (ULONG64)module->BaseAddress, context.Rip, - info, &new_context, &dispatch.HandlerData, &frame, NULL ); + if (!dispatch.EstablisherFrame) break; - if ((frame & 7) || - frame < (ULONG64)NtCurrentTeb()->Tib.StackLimit || - frame >= (ULONG64)NtCurrentTeb()->Tib.StackBase) + if ((dispatch.EstablisherFrame & 7) || + dispatch.EstablisherFrame < (ULONG64)NtCurrentTeb()->Tib.StackLimit || + dispatch.EstablisherFrame > (ULONG64)NtCurrentTeb()->Tib.StackBase) { - ERR( "invalid frame %lx\n", frame ); + ERR( "invalid frame %lx (%p-%p)\n", dispatch.EstablisherFrame, + NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase ); rec->ExceptionFlags |= EH_STACK_INVALID; break; } - if (handler) + if (dispatch.LanguageHandler) { - dispatch.ControlPc = context.Rip; - dispatch.ImageBase = (ULONG64)module->BaseAddress; - dispatch.FunctionEntry = info; - dispatch.EstablisherFrame = frame; - dispatch.TargetIp = 0; /* FIXME */ - dispatch.ContextRecord = &context; - dispatch.LanguageHandler = handler; - dispatch.HistoryTable = &table; - dispatch.ScopeIndex = 0; /* FIXME */ - - TRACE( "calling handler %p (rec=%p, frame=%lx context=%p, dispatch=%p)\n", - handler, rec, frame, &context, &dispatch ); - - switch( handler( rec, frame, &context, &dispatch )) - { - case ExceptionContinueExecution: - if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION; - *orig_context = context; - return STATUS_SUCCESS; - case ExceptionContinueSearch: - break; - case ExceptionNestedException: - break; - default: - return STATUS_INVALID_DISPOSITION; - } + status = call_handler( rec, &dispatch, orig_context ); + if (status != STATUS_UNHANDLED_EXCEPTION) return status; + } + /* hack: call wine handlers registered in the tib list */ + else while ((ULONG64)teb_frame < new_context.Rsp) + { + TRACE( "found wine frame %p rsp %lx handler %p\n", + teb_frame, new_context.Rsp, teb_frame->Handler ); + dispatch.EstablisherFrame = (ULONG64)teb_frame; + context = *orig_context; + status = call_teb_handler( rec, &dispatch, teb_frame, orig_context ); + if (status != STATUS_UNHANDLED_EXCEPTION) return status; + teb_frame = teb_frame->Prev; } + + if (new_context.Rsp == (ULONG64)NtCurrentTeb()->Tib.StackBase) break; context = new_context; } - - /* hack: call unhandled exception filter directly */ - ptrs.ExceptionRecord = rec; - ptrs.ContextRecord = orig_context; - unhandled_exception_filter( &ptrs ); return STATUS_UNHANDLED_EXCEPTION; } @@ -857,54 +1666,78 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f /********************************************************************** + * raise_segv_exception + */ +static void raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) +{ + NTSTATUS status; + + switch(rec->ExceptionCode) + { + case EXCEPTION_ACCESS_VIOLATION: + if (rec->NumberParameters == 2) + { + if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1], + rec->ExceptionInformation[0] ))) + set_cpu_context( context ); + } + break; + } + status = raise_exception( rec, context, TRUE ); + if (status) raise_status( status, rec ); +} + + +/********************************************************************** + * raise_generic_exception + * + * Generic raise function for exceptions that don't need special treatment. + */ +static void raise_generic_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) +{ + NTSTATUS status = raise_exception( rec, context, TRUE ); + if (status) raise_status( status, rec ); +} + + +/********************************************************************** * segv_handler * * Handler for SIGSEGV and related errors. */ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { - EXCEPTION_RECORD rec; - CONTEXT context; - NTSTATUS status; + EXCEPTION_RECORD *rec = setup_exception( sigcontext, raise_segv_exception ); ucontext_t *ucontext = sigcontext; - save_context( &context, ucontext ); - - rec.ExceptionRecord = NULL; - rec.ExceptionFlags = EXCEPTION_CONTINUABLE; - rec.ExceptionAddress = (LPVOID)context.Rip; - rec.NumberParameters = 0; - switch(TRAP_sig(ucontext)) { case TRAP_x86_OFLOW: /* Overflow exception */ - rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; + rec->ExceptionCode = EXCEPTION_INT_OVERFLOW; break; case TRAP_x86_BOUND: /* Bound range exception */ - rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + rec->ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; break; case TRAP_x86_PRIVINFLT: /* Invalid opcode exception */ - rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + rec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; break; case TRAP_x86_STKFLT: /* Stack fault */ - rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; + rec->ExceptionCode = EXCEPTION_STACK_OVERFLOW; break; case TRAP_x86_SEGNPFLT: /* Segment not present exception */ case TRAP_x86_PROTFLT: /* General protection fault */ case TRAP_x86_UNKNOWN: /* Unknown fault code */ - rec.ExceptionCode = ERROR_sig(ucontext) ? EXCEPTION_ACCESS_VIOLATION - : EXCEPTION_PRIV_INSTRUCTION; + rec->ExceptionCode = ERROR_sig(ucontext) ? EXCEPTION_ACCESS_VIOLATION : EXCEPTION_PRIV_INSTRUCTION; + rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION; break; case TRAP_x86_PAGEFLT: /* Page fault */ - rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION; - rec.NumberParameters = 2; - rec.ExceptionInformation[0] = (ERROR_sig(ucontext) & 2) != 0; - rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; - if (!(rec.ExceptionCode = virtual_handle_fault( siginfo->si_addr, rec.ExceptionInformation[0] ))) - goto done; + rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION; + rec->NumberParameters = 2; + rec->ExceptionInformation[0] = (ERROR_sig(ucontext) & 2) != 0; + rec->ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; break; case TRAP_x86_ALIGNFLT: /* Alignment check exception */ - rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; + rec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; break; default: ERR( "Got unexpected trap %ld\n", TRAP_sig(ucontext) ); @@ -915,14 +1748,9 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) case TRAP_x86_TSSFLT: /* Invalid TSS exception */ case TRAP_x86_MCHK: /* Machine check exception */ case TRAP_x86_CACHEFLT: /* Cache flush exception */ - rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + rec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; break; } - - status = raise_exception( &rec, &context, TRUE ); - if (status) raise_status( status, &rec ); -done: - restore_context( &context, ucontext ); } /********************************************************************** @@ -932,34 +1760,20 @@ done: */ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { - EXCEPTION_RECORD rec; - CONTEXT context; - NTSTATUS status; - ucontext_t *ucontext = sigcontext; - - save_context( &context, ucontext ); - rec.ExceptionFlags = EXCEPTION_CONTINUABLE; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = (LPVOID)context.Rip; - rec.NumberParameters = 0; + EXCEPTION_RECORD *rec = setup_exception( sigcontext, raise_generic_exception ); switch (siginfo->si_code) { case TRAP_TRACE: /* Single-step exception */ - rec.ExceptionCode = EXCEPTION_SINGLE_STEP; - EFL_sig(ucontext) &= ~0x100; /* clear single-step flag */ + rec->ExceptionCode = EXCEPTION_SINGLE_STEP; break; case TRAP_BRKPT: /* Breakpoint exception */ - rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1; /* back up over the int3 instruction */ + rec->ExceptionAddress = (char *)rec->ExceptionAddress - 1; /* back up over the int3 instruction */ /* fall through */ default: - rec.ExceptionCode = EXCEPTION_BREAKPOINT; + rec->ExceptionCode = EXCEPTION_BREAKPOINT; break; } - - status = raise_exception( &rec, &context, TRUE ); - if (status) raise_status( status, &rec ); - restore_context( &context, ucontext ); } /********************************************************************** @@ -967,50 +1781,38 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext ) * * Handler for SIGFPE. */ -static void fpe_handler( int signal, siginfo_t *siginfo, void *ucontext ) +static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { - EXCEPTION_RECORD rec; - CONTEXT context; - NTSTATUS status; - - save_context( &context, ucontext ); - rec.ExceptionFlags = EXCEPTION_CONTINUABLE; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = (LPVOID)context.Rip; - rec.NumberParameters = 0; + EXCEPTION_RECORD *rec = setup_exception( sigcontext, raise_generic_exception ); switch (siginfo->si_code) { case FPE_FLTSUB: - rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + rec->ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; break; case FPE_INTDIV: - rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; + rec->ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; break; case FPE_INTOVF: - rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; + rec->ExceptionCode = EXCEPTION_INT_OVERFLOW; break; case FPE_FLTDIV: - rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; + rec->ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; break; case FPE_FLTOVF: - rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW; + rec->ExceptionCode = EXCEPTION_FLT_OVERFLOW; break; case FPE_FLTUND: - rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW; + rec->ExceptionCode = EXCEPTION_FLT_UNDERFLOW; break; case FPE_FLTRES: - rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT; + rec->ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT; break; case FPE_FLTINV: default: - rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; + rec->ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; break; } - - status = raise_exception( &rec, &context, TRUE ); - if (status) raise_status( status, &rec ); - restore_context( &context, ucontext ); } /********************************************************************** @@ -1018,23 +1820,12 @@ static void fpe_handler( int signal, siginfo_t *siginfo, void *ucontext ) * * Handler for SIGINT. */ -static void int_handler( int signal, siginfo_t *siginfo, void *ucontext ) +static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { if (!dispatch_signal(SIGINT)) { - EXCEPTION_RECORD rec; - CONTEXT context; - NTSTATUS status; - - save_context( &context, ucontext ); - rec.ExceptionCode = CONTROL_C_EXIT; - rec.ExceptionFlags = EXCEPTION_CONTINUABLE; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = (LPVOID)context.Rip; - rec.NumberParameters = 0; - status = raise_exception( &rec, &context, TRUE ); - if (status) raise_status( status, &rec ); - restore_context( &context, ucontext ); + EXCEPTION_RECORD *rec = setup_exception( sigcontext, raise_generic_exception ); + rec->ExceptionCode = CONTROL_C_EXIT; } } @@ -1044,21 +1835,11 @@ static void int_handler( int signal, siginfo_t *siginfo, void *ucontext ) * * Handler for SIGABRT. */ -static void abrt_handler( int signal, siginfo_t *siginfo, void *ucontext ) +static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { - EXCEPTION_RECORD rec; - CONTEXT context; - NTSTATUS status; - - save_context( &context, ucontext ); - rec.ExceptionCode = EXCEPTION_WINE_ASSERTION; - rec.ExceptionFlags = EH_NONCONTINUABLE; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = (LPVOID)context.Rip; - rec.NumberParameters = 0; - status = raise_exception( &rec, &context, TRUE ); - if (status) raise_status( status, &rec ); - restore_context( &context, ucontext ); + EXCEPTION_RECORD *rec = setup_exception( sigcontext, raise_generic_exception ); + rec->ExceptionCode = EXCEPTION_WINE_ASSERTION; + rec->ExceptionFlags = EH_NONCONTINUABLE; } @@ -1096,8 +1877,15 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext ) */ size_t get_signal_stack_total_size(void) { - assert( sizeof(TEB) <= 2*getpagesize() ); - return 2*getpagesize(); /* this is just for the TEB, we don't need a signal stack */ + assert( sizeof(TEB) <= teb_size ); + if (!signal_stack_size) + { + size_t size = 8192, min_size = teb_size + max( MINSIGSTKSZ, 8192 ); + /* find the first power of two not smaller than min_size */ + while (size < min_size) size *= 2; + signal_stack_size = size - teb_size; + } + return signal_stack_size + teb_size; } @@ -1118,11 +1906,18 @@ int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh) */ void signal_init_thread( TEB *teb ) { + stack_t ss; + #ifdef __linux__ arch_prctl( ARCH_SET_GS, teb ); #else # error Please define setting %gs for your architecture #endif + + ss.ss_sp = (char *)teb + teb_size; + ss.ss_size = signal_stack_size; + ss.ss_flags = 0; + if (sigaltstack(&ss, NULL) == -1) perror( "sigaltstack" ); } /********************************************************************** @@ -1133,7 +1928,7 @@ void signal_init_process(void) struct sigaction sig_act; sig_act.sa_mask = server_block_set; - sig_act.sa_flags = SA_RESTART | SA_SIGINFO; + sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; sig_act.sa_sigaction = int_handler; if (sigaction( SIGINT, &sig_act, NULL ) == -1) goto error; @@ -1459,19 +2254,81 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc, } +/********************************************************************** + * call_unwind_handler + * + * Call a single unwind handler. + * FIXME: Handle nested exceptions. + */ +static void call_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch ) +{ + DWORD res; + + dispatch->ControlPc = dispatch->ContextRecord->Rip; + + TRACE( "calling handler %p (rec=%p, frame=0x%lx context=%p, dispatch=%p)\n", + dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); + res = dispatch->LanguageHandler( rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); + TRACE( "handler %p returned %x\n", dispatch->LanguageHandler, res ); + + switch (res) + { + case ExceptionContinueSearch: + break; + case ExceptionCollidedUnwind: + FIXME( "ExceptionCollidedUnwind not supported yet\n" ); + break; + default: + raise_status( STATUS_INVALID_DISPOSITION, rec ); + break; + } +} + + +/********************************************************************** + * call_teb_unwind_handler + * + * Call a single unwind handler from the TEB chain. + * FIXME: Handle nested exceptions. + */ +static void call_teb_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch, + EXCEPTION_REGISTRATION_RECORD *teb_frame ) +{ + EXCEPTION_REGISTRATION_RECORD *dispatcher; + DWORD res; + + TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatcher=%p)\n", + teb_frame->Handler, rec, teb_frame, dispatch->ContextRecord, &dispatcher ); + res = teb_frame->Handler( rec, teb_frame, dispatch->ContextRecord, &dispatcher ); + TRACE( "handler at %p returned %u\n", teb_frame->Handler, res ); + + switch (res) + { + case ExceptionContinueSearch: + break; + case ExceptionCollidedUnwind: + FIXME( "ExceptionCollidedUnwind not supported yet\n" ); + break; + default: + raise_status( STATUS_INVALID_DISPOSITION, rec ); + break; + } +} + + /******************************************************************* * RtlUnwindEx (NTDLL.@) */ void WINAPI RtlUnwindEx( ULONG64 end_frame, ULONG64 target_ip, EXCEPTION_RECORD *rec, - ULONG64 retval, CONTEXT *context, UNWIND_HISTORY_TABLE *table ) + ULONG64 retval, CONTEXT *orig_context, UNWIND_HISTORY_TABLE *table ) { + EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; EXCEPTION_RECORD record; - ULONG64 frame; - RUNTIME_FUNCTION *dir, *info; - PEXCEPTION_ROUTINE handler; + RUNTIME_FUNCTION *dir; DISPATCHER_CONTEXT dispatch; - CONTEXT new_context; + CONTEXT context, new_context; LDR_MODULE *module; + NTSTATUS status; DWORD size; /* build an exception record, if we do not have one */ @@ -1480,93 +2337,130 @@ void WINAPI RtlUnwindEx( ULONG64 end_frame, ULONG64 target_ip, EXCEPTION_RECORD record.ExceptionCode = STATUS_UNWIND; record.ExceptionFlags = 0; record.ExceptionRecord = NULL; - record.ExceptionAddress = (void *)context->Rip; + record.ExceptionAddress = (void *)orig_context->Rip; record.NumberParameters = 0; rec = &record; } rec->ExceptionFlags |= EH_UNWINDING | (end_frame ? 0 : EH_EXIT_UNWIND); - FIXME( "code=%x flags=%x end_frame=%lx target_ip=%lx\n", - rec->ExceptionCode, rec->ExceptionFlags, end_frame, target_ip ); + TRACE( "code=%x flags=%x end_frame=%lx target_ip=%lx rip=%016lx\n", + rec->ExceptionCode, rec->ExceptionFlags, end_frame, target_ip, orig_context->Rip ); + TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", + orig_context->Rax, orig_context->Rbx, orig_context->Rcx, orig_context->Rdx ); + TRACE(" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n", + orig_context->Rsi, orig_context->Rdi, orig_context->Rbp, orig_context->Rsp ); + TRACE(" r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n", + orig_context->R8, orig_context->R9, orig_context->R10, orig_context->R11 ); + TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", + orig_context->R12, orig_context->R13, orig_context->R14, orig_context->R15 ); + + context = *orig_context; + dispatch.EstablisherFrame = context.Rsp; + dispatch.TargetIp = target_ip; + dispatch.ContextRecord = &context; + dispatch.HistoryTable = table; - frame = context->Rsp; - while (frame != end_frame) + while (dispatch.EstablisherFrame != end_frame) { + new_context = context; + /* FIXME: should use the history table to make things faster */ - if (LdrFindEntryForAddress( (void *)context->Rip, &module )) + dir = NULL; + module = NULL; + dispatch.ImageBase = 0; + dispatch.ScopeIndex = 0; /* FIXME */ + + if (!LdrFindEntryForAddress( (void *)context.Rip, &module )) { - ERR( "no module found for rip %p, can't unwind exception\n", (void *)context->Rip ); - raise_status( STATUS_BAD_FUNCTION_TABLE, rec ); + if (!(dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, + IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size )) && + !(module->Flags & LDR_WINE_INTERNAL)) + { + ERR( "module %s doesn't contain exception data, can't unwind exception\n", + debugstr_w(module->BaseDllName.Buffer) ); + raise_status( STATUS_BAD_FUNCTION_TABLE, rec ); + } + dispatch.ImageBase = (ULONG64)module->BaseAddress; } - if (!(dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, - IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size ))) + + if (!dir) { - ERR( "module %s doesn't contain exception data, can't unwind exception\n", - debugstr_w(module->BaseDllName.Buffer) ); - raise_status( STATUS_BAD_FUNCTION_TABLE, rec ); + struct dwarf_eh_bases bases; + const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context.Rip - 1), &bases ); + if (!fde) + { + ERR( "no exception data found in %s for function %lx\n", + module ? debugstr_w(module->BaseDllName.Buffer) : "system library", context.Rip ); + raise_status( STATUS_BAD_FUNCTION_TABLE, rec ); + } + dispatch.FunctionEntry = NULL; + status = dwarf_virtual_unwind( context.Rip, &dispatch.EstablisherFrame, &new_context, fde, + &bases, &dispatch.LanguageHandler, &dispatch.HandlerData ); + if (status != STATUS_SUCCESS) raise_status( status, rec ); + if (dispatch.LanguageHandler && !module) + { + FIXME( "calling personality routine in system library not supported yet\n" ); + dispatch.LanguageHandler = NULL; + } } - if (!(info = find_function_info( context->Rip, module->BaseAddress, dir, size ))) + else { - /* leaf function */ - context->Rip = *(ULONG64 *)context->Rsp; - context->Rsp += sizeof(ULONG64); - continue; + if (!(dispatch.FunctionEntry = find_function_info( context.Rip, module->BaseAddress, + dir, size ))) + { + /* leaf function */ + context.Rip = *(ULONG64 *)context.Rsp; + context.Rsp += sizeof(ULONG64); + continue; + } + dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_UHANDLER, dispatch.ImageBase, + context.Rip, dispatch.FunctionEntry, + &new_context, &dispatch.HandlerData, + &dispatch.EstablisherFrame, NULL ); } - new_context = *context; + if (!dispatch.EstablisherFrame) break; - handler = RtlVirtualUnwind( UNW_FLAG_UHANDLER, (ULONG64)module->BaseAddress, context->Rip, - info, &new_context, &dispatch.HandlerData, &frame, NULL ); - - if ((frame & 7) || - frame < (ULONG64)NtCurrentTeb()->Tib.StackLimit || - frame >= (ULONG64)NtCurrentTeb()->Tib.StackBase) + if ((dispatch.EstablisherFrame & 7) || + dispatch.EstablisherFrame < (ULONG64)NtCurrentTeb()->Tib.StackLimit || + dispatch.EstablisherFrame > (ULONG64)NtCurrentTeb()->Tib.StackBase) { - ERR( "invalid frame %lx\n", frame ); - raise_status( STATUS_BAD_STACK, rec ); + ERR( "invalid frame %lx (%p-%p)\n", dispatch.EstablisherFrame, + NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase ); + rec->ExceptionFlags |= EH_STACK_INVALID; + break; } - if (end_frame && (frame > end_frame)) + if (dispatch.LanguageHandler) { - ERR( "invalid frame %lx/%lx\n", frame, end_frame ); - raise_status( STATUS_INVALID_UNWIND_TARGET, rec ); + if (end_frame && (dispatch.EstablisherFrame > end_frame)) + { + ERR( "invalid end frame %lx/%lx\n", dispatch.EstablisherFrame, end_frame ); + raise_status( STATUS_INVALID_UNWIND_TARGET, rec ); + } + call_unwind_handler( rec, &dispatch ); } - - if (handler) + else /* hack: call builtin handlers registered in the tib list */ { - dispatch.ControlPc = context->Rip; - dispatch.ImageBase = (ULONG64)module->BaseAddress; - dispatch.FunctionEntry = info; - dispatch.EstablisherFrame = frame; - dispatch.TargetIp = target_ip; - dispatch.ContextRecord = context; - dispatch.LanguageHandler = handler; - dispatch.HistoryTable = table; - dispatch.ScopeIndex = 0; /* FIXME */ - - TRACE( "calling handler %p (rec=%p, frame=%lx context=%p, dispatch=%p)\n", - handler, rec, frame, context, &dispatch ); - - switch( handler( rec, frame, context, &dispatch )) + while ((ULONG64)teb_frame < new_context.Rsp && (ULONG64)teb_frame < end_frame) { - case ExceptionContinueSearch: - break; - case ExceptionCollidedUnwind: - FIXME( "ExceptionCollidedUnwind not supported yet\n" ); - break; - default: - raise_status( STATUS_INVALID_DISPOSITION, rec ); - break; + TRACE( "found builtin frame %p handler %p\n", teb_frame, teb_frame->Handler ); + dispatch.EstablisherFrame = (ULONG64)teb_frame; + call_teb_unwind_handler( rec, &dispatch, teb_frame ); + teb_frame = __wine_pop_frame( teb_frame ); } + if ((ULONG64)teb_frame == end_frame && end_frame < new_context.Rsp) break; + dispatch.EstablisherFrame = new_context.Rsp; } - *context = new_context; + + context = new_context; } - context->Rax = retval; - context->Rip = target_ip; - TRACE( "returning to %lx stack %lx\n", context->Rip, context->Rsp ); - set_cpu_context( context ); + context.Rax = retval; + context.Rip = target_ip; + TRACE( "returning to %lx stack %lx\n", context.Rip, context.Rsp ); + set_cpu_context( &context ); } @@ -1657,6 +2551,33 @@ void WINAPI __regs_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context ) DEFINE_REGS_ENTRYPOINT( RtlRaiseException, 1 ) +/*********************************************************************** + * call_thread_entry_point + */ +void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) +{ + __TRY + { + exit_thread( entry( arg )); + } + __EXCEPT(unhandled_exception_filter) + { + NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY + abort(); /* should not be reached */ +} + + +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} + + /********************************************************************** * __wine_enter_vm86 (NTDLL.@) */ @@ -1668,11 +2589,11 @@ void __wine_enter_vm86( CONTEXT *context ) /********************************************************************** * DbgBreakPoint (NTDLL.@) */ -__ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret") +__ASM_STDCALL_FUNC( DbgBreakPoint, 0, "int $3; ret") /********************************************************************** * DbgUserBreakPoint (NTDLL.@) */ -__ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret") +__ASM_STDCALL_FUNC( DbgUserBreakPoint, 0, "int $3; ret") #endif /* __x86_64__ */ diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 1a5017ebb6e..0b924b2cf7e 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -353,11 +353,29 @@ void abort_thread( int status ) /*********************************************************************** * exit_thread */ -static void DECLSPEC_NORETURN exit_thread( int status ) +void exit_thread( int status ) { static void *prev_teb; TEB *teb; + if (status) /* send the exit code to the server (0 is already the default) */ + { + SERVER_START_REQ( terminate_thread ) + { + req->handle = wine_server_obj_handle( GetCurrentThread() ); + req->exit_code = status; + wine_server_call( req ); + } + SERVER_END_REQ; + } + + if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) + { + LdrShutdownProcess(); + exit( status ); + } + + LdrShutdownThread(); RtlAcquirePebLock(); RemoveEntryList( &NtCurrentTeb()->TlsLinks ); RtlReleasePebLock(); @@ -365,7 +383,6 @@ static void DECLSPEC_NORETURN exit_thread( int status ) RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); - if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) exit( status ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { @@ -388,66 +405,6 @@ static void DECLSPEC_NORETURN exit_thread( int status ) } -#ifdef __i386__ -/* wrapper for apps that don't declare the thread function correctly */ -extern DWORD call_thread_entry_point( PRTL_THREAD_START_ROUTINE entry, void *arg ); -__ASM_GLOBAL_FUNC(call_thread_entry_point, - "pushl %ebp\n\t" - "movl %esp,%ebp\n\t" - "subl $4,%esp\n\t" - "pushl 12(%ebp)\n\t" - "movl 8(%ebp),%eax\n\t" - "call *%eax\n\t" - "leave\n\t" - "ret" ) -#else -static inline DWORD call_thread_entry_point( PRTL_THREAD_START_ROUTINE entry, void *arg ) -{ - LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)entry; - return func( arg ); -} -#endif - -/*********************************************************************** - * call_thread_func - * - * Hack to make things compatible with the thread procedures used by kernel32.CreateThread. - */ -static void DECLSPEC_NORETURN call_thread_func( PRTL_THREAD_START_ROUTINE rtl_func, void *arg ) -{ - DWORD exit_code; - BOOL last; - - MODULE_DllThreadAttach( NULL ); - - if (TRACE_ON(relay)) - DPRINTF( "%04x:Starting thread proc %p (arg=%p)\n", GetCurrentThreadId(), rtl_func, arg ); - - exit_code = call_thread_entry_point( rtl_func, arg ); - - /* send the exit code to the server */ - SERVER_START_REQ( terminate_thread ) - { - req->handle = wine_server_obj_handle( GetCurrentThread() ); - req->exit_code = exit_code; - wine_server_call( req ); - last = reply->last; - } - SERVER_END_REQ; - - if (last) - { - LdrShutdownProcess(); - exit( exit_code ); - } - else - { - LdrShutdownThread(); - exit_thread( exit_code ); - } -} - - /*********************************************************************** * start_thread * @@ -474,22 +431,12 @@ static void start_thread( struct startup_info *info ) InsertHeadList( &tls_links, &teb->TlsLinks ); RtlReleasePebLock(); - /* NOTE: Windows does not have an exception handler around the call to - * the thread attach. We do for ease of debugging */ - if (unhandled_exception_filter) - { - __TRY - { - call_thread_func( func, arg ); - } - __EXCEPT(unhandled_exception_filter) - { - NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); - } - __ENDTRY - } - else - call_thread_func( func, arg ); + MODULE_DllThreadAttach( NULL ); + + if (TRACE_ON(relay)) + DPRINTF( "%04x:Starting thread proc %p (arg=%p)\n", GetCurrentThreadId(), func, arg ); + + call_thread_entry_point( (LPTHREAD_START_ROUTINE)func, arg ); } @@ -637,36 +584,6 @@ error: /*********************************************************************** - * RtlExitUserThread (NTDLL.@) - */ -void WINAPI RtlExitUserThread( ULONG status ) -{ - BOOL last; - - SERVER_START_REQ( terminate_thread ) - { - /* send the exit code to the server */ - req->handle = wine_server_obj_handle( GetCurrentThread() ); - req->exit_code = status; - wine_server_call( req ); - last = reply->last; - } - SERVER_END_REQ; - - if (last) - { - LdrShutdownProcess(); - exit( status ); - } - else - { - LdrShutdownThread(); - exit_thread( status ); - } -} - - -/*********************************************************************** * NtOpenThread (NTDLL.@) * ZwOpenThread (NTDLL.@) */ diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 6371d85a120..ab7cbbf9617 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -66,18 +66,25 @@ struct IrpInstance #ifdef __i386__ #define DEFINE_FASTCALL1_ENTRYPOINT( name ) \ - __ASM_GLOBAL_FUNC( name, \ + __ASM_STDCALL_FUNC( name, 4, \ "popl %eax\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME("__regs_") #name ) + "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(4)) #define DEFINE_FASTCALL2_ENTRYPOINT( name ) \ - __ASM_GLOBAL_FUNC( name, \ + __ASM_STDCALL_FUNC( name, 8, \ "popl %eax\n\t" \ "pushl %edx\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME("__regs_") #name ) + "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(8)) +#define DEFINE_FASTCALL3_ENTRYPOINT( name ) \ + __ASM_STDCALL_FUNC( name, 12, \ + "popl %eax\n\t" \ + "pushl %edx\n\t" \ + "pushl %ecx\n\t" \ + "pushl %eax\n\t" \ + "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(12)) #endif static inline LPCSTR debugstr_us( const UNICODE_STRING *us ) @@ -313,6 +320,27 @@ void WINAPI IoInitializeIrp( IRP *irp, USHORT size, CCHAR stack_size ) /*********************************************************************** + * IoInitializeTimer (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI IoInitializeTimer(PDEVICE_OBJECT DeviceObject, + PIO_TIMER_ROUTINE TimerRoutine, + PVOID Context) +{ + FIXME( "stub: %p, %p, %p\n", DeviceObject, TimerRoutine, Context ); + return STATUS_NOT_IMPLEMENTED; +} + + +/*********************************************************************** + * IoStartTimer (NTOSKRNL.EXE.@) + */ +void WINAPI IoStartTimer(PDEVICE_OBJECT DeviceObject) +{ + FIXME( "stub: %p\n", DeviceObject ); +} + + +/*********************************************************************** * IoAllocateIrp (NTOSKRNL.EXE.@) */ PIRP WINAPI IoAllocateIrp( CCHAR stack_size, BOOLEAN charge_quota ) @@ -745,8 +773,8 @@ void WINAPI IofCompleteRequest( IRP *irp, UCHAR priority_boost ) /*********************************************************************** * InterlockedCompareExchange (NTOSKRNL.EXE.@) */ -#ifdef DEFINE_FASTCALL2_ENTRYPOINT -DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedCompareExchange ) +#ifdef DEFINE_FASTCALL3_ENTRYPOINT +DEFINE_FASTCALL3_ENTRYPOINT( NTOSKRNL_InterlockedCompareExchange ) LONG WINAPI __regs_NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare ) #else LONG WINAPI NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare ) @@ -871,6 +899,53 @@ void WINAPI ExFreePoolWithTag( void *ptr, ULONG tag ) /*********************************************************************** + * ExInitializeResourceLite (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI ExInitializeResourceLite(PERESOURCE Resource) +{ + FIXME( "stub: %p\n", Resource ); + return STATUS_NOT_IMPLEMENTED; +} + + +/*********************************************************************** + * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@) + */ +void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside, + PALLOCATE_FUNCTION Allocate, + PFREE_FUNCTION Free, + ULONG Flags, + SIZE_T Size, + ULONG Tag, + USHORT Depth) +{ + FIXME( "stub: %p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth ); +} + + +/*********************************************************************** + * ExInitializeZone (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI ExInitializeZone(PZONE_HEADER Zone, + ULONG BlockSize, + PVOID InitialSegment, + ULONG InitialSegmentSize) +{ + FIXME( "stub: %p, %u, %p, %u\n", Zone, BlockSize, InitialSegment, InitialSegmentSize ); + return STATUS_NOT_IMPLEMENTED; +} + +/*********************************************************************** +* FsRtlRegisterUncProvider (NTOSKRNL.EXE.@) +*/ +NTSTATUS WINAPI FsRtlRegisterUncProvider(PHANDLE MupHandle, PUNICODE_STRING RedirDevName, + BOOLEAN MailslotsSupported) +{ + FIXME("(%p %p %d): stub\n", MupHandle, RedirDevName, MailslotsSupported); + return STATUS_NOT_IMPLEMENTED; +} + +/*********************************************************************** * KeInitializeEvent (NTOSKRNL.EXE.@) */ void WINAPI KeInitializeEvent( PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State ) @@ -879,6 +954,15 @@ void WINAPI KeInitializeEvent( PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State ) } + /*********************************************************************** + * KeInitializeMutex (NTOSKRNL.EXE.@) + */ +void WINAPI KeInitializeMutex(PRKMUTEX Mutex, ULONG Level) +{ + FIXME( "stub: %p, %u\n", Mutex, Level ); +} + + /*********************************************************************** * KeInitializeSpinLock (NTOSKRNL.EXE.@) */ @@ -971,6 +1055,35 @@ ULONG WINAPI KeQueryTimeIncrement(void) /*********************************************************************** + * KeWaitForSingleObject (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI KeWaitForSingleObject(PVOID Object, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout) +{ + FIXME( "stub: %p, %d, %d, %d, %p\n", Object, WaitReason, WaitMode, Alertable, Timeout ); + return STATUS_NOT_IMPLEMENTED; +} + +/*********************************************************************** + * IoRegisterFileSystem (NTOSKRNL.EXE.@) + */ +VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject) +{ + FIXME("(%p): stub\n", DeviceObject); +} + +/*********************************************************************** +* IoUnregisterFileSystem (NTOSKRNL.EXE.@) +*/ +VOID WINAPI IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject) +{ + FIXME("(%p): stub\n", DeviceObject); +} + +/*********************************************************************** * MmAllocateNonCachedMemory (NTOSKRNL.EXE.@) */ PVOID WINAPI MmAllocateNonCachedMemory( SIZE_T size ) @@ -1025,6 +1138,13 @@ void WINAPI MmResetDriverPaging(PVOID AddrInSection) TRACE("%p\n", AddrInSection); } +/*********************************************************************** + * ObfReferenceObject (NTOSKRNL.EXE.@) + */ +VOID WINAPI ObfReferenceObject(PVOID Object) +{ + FIXME("(%p): stub\n", Object); +} /*********************************************************************** * ObReferenceObjectByHandle (NTOSKRNL.EXE.@) @@ -1131,6 +1251,16 @@ NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE No /*********************************************************************** + * PsTerminateSystemThread (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI PsTerminateSystemThread(NTSTATUS ExitStatus) +{ + FIXME( "stub: %u\n", ExitStatus ); + return STATUS_NOT_IMPLEMENTED; +} + + +/*********************************************************************** * MmGetSystemRoutineAddress (NTOSKRNL.EXE.@) */ PVOID WINAPI MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 849dd518335..786de833d3d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -49,7 +49,7 @@ @ stub KiAcquireSpinLock @ stub KiReleaseSpinLock @ stdcall -norelay ObfDereferenceObject(ptr) -@ stub ObfReferenceObject +@ stdcall ObfReferenceObject(ptr) @ stub RtlPrefetchMemoryNonTemporal @ cdecl -i386 -norelay RtlUlongByteSwap() ntdll.RtlUlongByteSwap @ cdecl -ret64 RtlUlonglongByteSwap(double) ntdll.RtlUlonglongByteSwap @@ -139,10 +139,10 @@ @ stub ExGetExclusiveWaiterCount @ stub ExGetPreviousMode @ stub ExGetSharedWaiterCount -@ stub ExInitializeNPagedLookasideList +@ stdcall ExInitializeNPagedLookasideList(ptr ptr ptr long long long long) @ stub ExInitializePagedLookasideList -@ stub ExInitializeResourceLite -@ stub ExInitializeZone +@ stdcall ExInitializeResourceLite(ptr) +@ stdcall ExInitializeZone(ptr long ptr long) @ stub ExInterlockedAddLargeInteger @ stub ExInterlockedAddUlong @ stub ExInterlockedDecrementLong @@ -271,7 +271,7 @@ @ stub FsRtlPrivateLock @ stub FsRtlProcessFileLock @ stub FsRtlRegisterFileSystemFilterCallbacks -@ stub FsRtlRegisterUncProvider +@ stdcall FsRtlRegisterUncProvider(ptr ptr long) @ stub FsRtlReleaseFile @ stub FsRtlRemoveLargeMcbEntry @ stub FsRtlRemoveMcbEntry @@ -399,7 +399,7 @@ @ stub IoGetTopLevelIrp @ stdcall IoInitializeIrp(ptr long long) @ stub IoInitializeRemoveLockEx -@ stub IoInitializeTimer +@ stdcall IoInitializeTimer(ptr ptr ptr) @ stub IoInvalidateDeviceRelations @ stub IoInvalidateDeviceState @ stub IoIsFileOriginRemote @@ -427,7 +427,7 @@ @ stub IoRegisterBootDriverReinitialization @ stub IoRegisterDeviceInterface @ stdcall IoRegisterDriverReinitialization(ptr ptr ptr) -@ stub IoRegisterFileSystem +@ stdcall IoRegisterFileSystem(ptr) @ stub IoRegisterFsRegistrationChange @ stub IoRegisterLastChanceShutdownNotification @ stub IoRegisterPlugPlayNotification @@ -461,13 +461,13 @@ @ stub IoStartNextPacket @ stub IoStartNextPacketByKey @ stub IoStartPacket -@ stub IoStartTimer +@ stdcall IoStartTimer(ptr) @ stub IoStatisticsLock @ stub IoStopTimer @ stub IoSynchronousInvalidateDeviceRelations @ stub IoSynchronousPageWrite @ stub IoThreadToProcess -@ stub IoUnregisterFileSystem +@ stdcall IoUnregisterFileSystem(ptr) @ stub IoUnregisterFsRegistrationChange @ stub IoUnregisterPlugPlayNotification @ stub IoUnregisterShutdownNotification @@ -549,7 +549,7 @@ @ stdcall KeInitializeEvent(ptr long long) @ stub KeInitializeInterrupt @ stub KeInitializeMutant -@ stub KeInitializeMutex +@ stdcall KeInitializeMutex(ptr long) @ stub KeInitializeQueue @ stub KeInitializeSemaphore @ stdcall KeInitializeSpinLock(ptr) @@ -629,7 +629,7 @@ @ stub KeUserModeCallback @ stub KeWaitForMultipleObjects @ stub KeWaitForMutexObject -@ stub KeWaitForSingleObject +@ stdcall KeWaitForSingleObject(ptr long long long ptr) @ stub KiBugCheckData @ stub KiCoprocessorError @ stub KiDeliverApc @@ -919,7 +919,7 @@ @ stub PsSetProcessWindowStation @ stub PsSetThreadHardErrorsAreDisabled @ stub PsSetThreadWin32Thread -@ stub PsTerminateSystemThread +@ stdcall PsTerminateSystemThread(long) @ stub PsThreadType @ stub READ_REGISTER_BUFFER_UCHAR @ stub READ_REGISTER_BUFFER_ULONG diff --git a/dlls/oleacc/oleacc.rc b/dlls/oleacc/oleacc.rc index 3be579a746c..abcd7fb9943 100644 --- a/dlls/oleacc/oleacc.rc +++ b/dlls/oleacc/oleacc.rc @@ -25,5 +25,6 @@ #include "oleacc_En.rc" #include "oleacc_Fr.rc" #include "oleacc_Ko.rc" +#include "oleacc_Lt.rc" #include "oleacc_Nl.rc" #include "oleacc_Pl.rc" diff --git a/dlls/oleacc/oleacc_Lt.rc b/dlls/oleacc/oleacc_Lt.rc new file mode 100644 index 00000000000..5498e847532 --- /dev/null +++ b/dlls/oleacc/oleacc_Lt.rc @@ -0,0 +1,95 @@ +/* + * Lithuanian resources for oleacc + * + * Copyright 2009 Aurimas Fišeras + * + * 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 + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_LITHUANIAN, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + 0 "nežinomas objektas" /* undocumented */ + ROLE_SYSTEM_TITLEBAR "lango antraštės juosta" + ROLE_SYSTEM_MENUBAR "meniu juosta" + ROLE_SYSTEM_SCROLLBAR "slankjuostė" + ROLE_SYSTEM_GRIP "rankenėlė" + ROLE_SYSTEM_SOUND "garsas" + ROLE_SYSTEM_CURSOR "pelės žymeklis" + ROLE_SYSTEM_CARET "žymeklis" + ROLE_SYSTEM_ALERT "įspėjimas" + ROLE_SYSTEM_WINDOW "langas" + ROLE_SYSTEM_CLIENT "klientas" + ROLE_SYSTEM_MENUPOPUP "iškylantis meniu" + ROLE_SYSTEM_MENUITEM "meniu elementas" + ROLE_SYSTEM_TOOLTIP "paaiškinimas" + ROLE_SYSTEM_APPLICATION "programa" + ROLE_SYSTEM_DOCUMENT "dokumentas" + ROLE_SYSTEM_PANE "polangis" + ROLE_SYSTEM_CHART "diagrama" + ROLE_SYSTEM_DIALOG "dialogo langas" + ROLE_SYSTEM_BORDER "rėmelis" + ROLE_SYSTEM_GROUPING "grupavimas" + ROLE_SYSTEM_SEPARATOR "skirtukas" + ROLE_SYSTEM_TOOLBAR "įrankių juosta" + ROLE_SYSTEM_STATUSBAR "būsenos juosta" + ROLE_SYSTEM_TABLE "lentelė" + ROLE_SYSTEM_COLUMNHEADER "stulpelio antraštė" + ROLE_SYSTEM_ROWHEADER "eilutės antraštė" + ROLE_SYSTEM_COLUMN "stulpelis" + ROLE_SYSTEM_ROW "eilutė" + ROLE_SYSTEM_CELL "langelis" + ROLE_SYSTEM_LINK "nuoroda" + ROLE_SYSTEM_HELPBALLOON "pagalbos balionas" + ROLE_SYSTEM_CHARACTER "personažas" + ROLE_SYSTEM_LIST "sąrašas" + ROLE_SYSTEM_LISTITEM "sąrašo elementas" + ROLE_SYSTEM_OUTLINE "planas" + ROLE_SYSTEM_OUTLINEITEM "plano elementas" + ROLE_SYSTEM_PAGETAB "kortelė" + ROLE_SYSTEM_PROPERTYPAGE "savybių lapas" + ROLE_SYSTEM_INDICATOR "indikatorius" + ROLE_SYSTEM_GRAPHIC "grafika" + ROLE_SYSTEM_STATICTEXT "statinis tekstas" + ROLE_SYSTEM_TEXT "tekstas" + ROLE_SYSTEM_PUSHBUTTON "mygtukas" + ROLE_SYSTEM_CHECKBUTTON "žymimasis langelis" + ROLE_SYSTEM_RADIOBUTTON "akutė" + ROLE_SYSTEM_COMBOBOX "jungtinis langelis" + ROLE_SYSTEM_DROPLIST "išskleidžiamasis sąrašas" + ROLE_SYSTEM_PROGRESSBAR "eigos juosta" + ROLE_SYSTEM_DIAL "sukiojama rankenėlė" + ROLE_SYSTEM_HOTKEYFIELD "sparčiojo klavišo laukas" + ROLE_SYSTEM_SLIDER "šliaužiklis" + ROLE_SYSTEM_SPINBUTTON "suktukas" + ROLE_SYSTEM_DIAGRAM "schema" + ROLE_SYSTEM_ANIMATION "animacija" + ROLE_SYSTEM_EQUATION "lygtis" + ROLE_SYSTEM_BUTTONDROPDOWN "išskleidžiamasis mygtukas" + ROLE_SYSTEM_BUTTONMENU "meniu mygtukas" + ROLE_SYSTEM_BUTTONDROPDOWNGRID "tinklelio išskleidžiamasis mygtukas" + ROLE_SYSTEM_WHITESPACE "matomas tarpas" + ROLE_SYSTEM_PAGETABLIST "kortelių sąrašas" + ROLE_SYSTEM_CLOCK "laikrodis" + ROLE_SYSTEM_SPLITBUTTON "išskleidimo mygtukas" + ROLE_SYSTEM_IPADDRESS "IP adresas" + ROLE_SYSTEM_OUTLINEBUTTON "plano mygtukas" +} + +#pragma code_page(default) diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index adaad97def6..4409a150326 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -52,7 +52,10 @@ #define UINT8 JPEG_UINT8 #define UINT16 JPEG_UINT16 #define boolean jpeg_boolean +#undef HAVE_STDLIB_H # include +#undef HAVE_STDLIB_H +#define HAVE_STDLIB_H 1 #undef UINT8 #undef UINT16 #undef boolean diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index 2d23b48ed1c..ec23204ba4a 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -624,6 +624,24 @@ static HRESULT WINAPI Widget_CloneInterface( return S_OK; } +static HRESULT WINAPI Widget_put_prop_with_lcid( + IWidget* iface, LONG lcid, INT i) +{ + trace("put_prop_with_lcid(%08x, %x)\n", lcid, i); + ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid); + ok(i == 0xcafe, "got %08x\n", i); + return S_OK; +} + +static HRESULT WINAPI Widget_get_prop_with_lcid( + IWidget* iface, LONG lcid, INT *i) +{ + trace("get_prop_with_lcid(%08x, %p)\n", lcid, i); + ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid); + *i = lcid; + return S_OK; +} + static const struct IWidgetVtbl Widget_VTable = { Widget_QueryInterface, @@ -651,7 +669,9 @@ static const struct IWidgetVtbl Widget_VTable = Widget_VarArg, Widget_StructArgs, Widget_Error, - Widget_CloneInterface + Widget_CloneInterface, + Widget_put_prop_with_lcid, + Widget_get_prop_with_lcid }; static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject) @@ -1328,6 +1348,37 @@ static void test_typelibmarshal(void) hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL); ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr); + /* test propput with lcid */ + + /* the lcid passed to the function is the first lcid in the typelib header. + Since we don't explicitly set an lcid in the idl, it'll default to US English. */ + VariantInit(&vararg[0]); + V_VT(&vararg[0]) = VT_I4; + V_I4(&vararg[0]) = 0xcafe; + dispparams.cNamedArgs = 1; + dispparams.rgdispidNamedArgs = &dispidNamed; + dispparams.cArgs = 1; + dispparams.rgvarg = vararg; + VariantInit(&varresult); + hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL); +todo_wine + ok_ole_success(hr, ITypeInfo_Invoke); + VariantClear(&varresult); + + /* test propget with lcid */ + dispparams.cNamedArgs = 0; + dispparams.cArgs = 0; + dispparams.rgvarg = NULL; + dispparams.rgdispidNamedArgs = NULL; + hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL); +todo_wine +{ + ok_ole_success(hr, ITypeInfo_Invoke); + ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult)); + ok(V_I4(&varresult) == 0x409, "got %x\n", V_I4(&varresult)); +} + VariantClear(&varresult); + IDispatch_Release(pDispatch); IWidget_Release(pWidget); diff --git a/dlls/oleaut32/tests/tmarshal.idl b/dlls/oleaut32/tests/tmarshal.idl index 2b57ddd2aa1..ddf02b2b975 100644 --- a/dlls/oleaut32/tests/tmarshal.idl +++ b/dlls/oleaut32/tests/tmarshal.idl @@ -125,6 +125,12 @@ library TestTypelib [propget, id(DISPID_TM_CLONEINTERFACE)] HRESULT CloneInterface([out, retval] ISomethingFromDispatch **ppVal); + + [id(DISPID_TM_PROP_WITH_LCID), propput] + HRESULT prop_with_lcid([in,lcid] long lcid, [in] INT i); + + [id(DISPID_TM_PROP_WITH_LCID), propget] + HRESULT prop_with_lcid([in,lcid] long lcid, [out,retval] INT *i); } [ diff --git a/dlls/oleaut32/tests/tmarshal_dispids.h b/dlls/oleaut32/tests/tmarshal_dispids.h index 8fcf10909b9..10c2828c4fb 100644 --- a/dlls/oleaut32/tests/tmarshal_dispids.h +++ b/dlls/oleaut32/tests/tmarshal_dispids.h @@ -34,5 +34,6 @@ #define DISPID_TM_CLONEINTERFACE 15 #define DISPID_TM_TESTDUAL 16 #define DISPID_TM_STRUCTARGS 17 +#define DISPID_TM_PROP_WITH_LCID 18 #define DISPID_NOA_BSTRRET 1 diff --git a/dlls/riched20/txthost.c b/dlls/riched20/txthost.c index 8fabd8388d1..cd5a54f0ad7 100644 --- a/dlls/riched20/txthost.c +++ b/dlls/riched20/txthost.c @@ -528,60 +528,112 @@ HRESULT WINAPI ITextHostImpl_TxGetSelectionBarWidth(ITextHost *iface, #ifdef __i386__ /* thiscall functions are i386-specific */ #define THISCALL(func) __thiscall_ ## func -#define DEFINE_THISCALL_WRAPPER(func) \ +#define DEFINE_THISCALL_WRAPPER(func,args) \ extern typeof(func) THISCALL(func); \ - __ASM_GLOBAL_FUNC(__thiscall_ ## func, \ + __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \ "popl %eax\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) ) + "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) #else /* __i386__ */ #define THISCALL(func) func -#define DEFINE_THISCALL_WRAPPER(func) /* nothing */ +#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ #endif /* __i386__ */ -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetDC); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxReleaseDC); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowScrollBar); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxEnableScrollBar); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollRange); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollPos); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxInvalidateRect); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxViewChange); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxCreateCaret); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowCaret); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCaretPos); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetTimer); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxKillTimer); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScrollWindowEx); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCapture); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetFocus); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScreenToClient); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxClientToScreen); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxActivate); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDeactivate); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetCharFormat); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetParaFormat); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSysColor); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetBackStyle); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetMaxLength); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetScrollBars); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPasswordChar); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetAcceleratorPos); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetExtent); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxCharFormatChange); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxParaFormatChange); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPropertyBits); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxNotify); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmGetContext); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmReleaseContext); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSelectionBarWidth); +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetDC,4) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxReleaseDC,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowScrollBar,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxEnableScrollBar,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollRange,20) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollPos,16) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxInvalidateRect,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxViewChange,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxCreateCaret,16) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowCaret,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCaretPos,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetTimer,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxKillTimer,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScrollWindowEx,32) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCapture,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetFocus,4) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScreenToClient,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxClientToScreen,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxActivate,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDeactivate,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetCharFormat,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetParaFormat,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSysColor,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetBackStyle,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetMaxLength,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetScrollBars,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPasswordChar,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetAcceleratorPos,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetExtent,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxCharFormatChange,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxParaFormatChange,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPropertyBits,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxNotify,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmGetContext,4) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmReleaseContext,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSelectionBarWidth,8) + +#ifdef __i386__ /* thiscall functions are i386-specific */ + +#define STDCALL(func) __stdcall_ ## func +#define DEFINE_STDCALL_WRAPPER(num,func,args) \ + extern typeof(func) __stdcall_ ## func; \ + __ASM_STDCALL_FUNC(__stdcall_ ## func, args, \ + "popl %eax\n\t" \ + "popl %ecx\n\t" \ + "pushl %eax\n\t" \ + "movl (%ecx), %eax\n\t" \ + "jmp *(4*(" #num "))(%eax)" ) + +DEFINE_STDCALL_WRAPPER(3,ITextHostImpl_TxGetDC,4) +DEFINE_STDCALL_WRAPPER(4,ITextHostImpl_TxReleaseDC,8) +DEFINE_STDCALL_WRAPPER(5,ITextHostImpl_TxShowScrollBar,12) +DEFINE_STDCALL_WRAPPER(6,ITextHostImpl_TxEnableScrollBar,12) +DEFINE_STDCALL_WRAPPER(7,ITextHostImpl_TxSetScrollRange,20) +DEFINE_STDCALL_WRAPPER(8,ITextHostImpl_TxSetScrollPos,16) +DEFINE_STDCALL_WRAPPER(9,ITextHostImpl_TxInvalidateRect,12) +DEFINE_STDCALL_WRAPPER(10,ITextHostImpl_TxViewChange,8) +DEFINE_STDCALL_WRAPPER(11,ITextHostImpl_TxCreateCaret,16) +DEFINE_STDCALL_WRAPPER(12,ITextHostImpl_TxShowCaret,8) +DEFINE_STDCALL_WRAPPER(13,ITextHostImpl_TxSetCaretPos,12) +DEFINE_STDCALL_WRAPPER(14,ITextHostImpl_TxSetTimer,12) +DEFINE_STDCALL_WRAPPER(15,ITextHostImpl_TxKillTimer,8) +DEFINE_STDCALL_WRAPPER(16,ITextHostImpl_TxScrollWindowEx,32) +DEFINE_STDCALL_WRAPPER(17,ITextHostImpl_TxSetCapture,8) +DEFINE_STDCALL_WRAPPER(18,ITextHostImpl_TxSetFocus,4) +DEFINE_STDCALL_WRAPPER(19,ITextHostImpl_TxSetCursor,12) +DEFINE_STDCALL_WRAPPER(20,ITextHostImpl_TxScreenToClient,8) +DEFINE_STDCALL_WRAPPER(21,ITextHostImpl_TxClientToScreen,8) +DEFINE_STDCALL_WRAPPER(22,ITextHostImpl_TxActivate,8) +DEFINE_STDCALL_WRAPPER(23,ITextHostImpl_TxDeactivate,8) +DEFINE_STDCALL_WRAPPER(24,ITextHostImpl_TxGetClientRect,8) +DEFINE_STDCALL_WRAPPER(25,ITextHostImpl_TxGetViewInset,8) +DEFINE_STDCALL_WRAPPER(26,ITextHostImpl_TxGetCharFormat,8) +DEFINE_STDCALL_WRAPPER(27,ITextHostImpl_TxGetParaFormat,8) +DEFINE_STDCALL_WRAPPER(28,ITextHostImpl_TxGetSysColor,8) +DEFINE_STDCALL_WRAPPER(29,ITextHostImpl_TxGetBackStyle,8) +DEFINE_STDCALL_WRAPPER(30,ITextHostImpl_TxGetMaxLength,8) +DEFINE_STDCALL_WRAPPER(31,ITextHostImpl_TxGetScrollBars,8) +DEFINE_STDCALL_WRAPPER(32,ITextHostImpl_TxGetPasswordChar,8) +DEFINE_STDCALL_WRAPPER(33,ITextHostImpl_TxGetAcceleratorPos,8) +DEFINE_STDCALL_WRAPPER(34,ITextHostImpl_TxGetExtent,8) +DEFINE_STDCALL_WRAPPER(35,ITextHostImpl_OnTxCharFormatChange,8) +DEFINE_STDCALL_WRAPPER(36,ITextHostImpl_OnTxParaFormatChange,8) +DEFINE_STDCALL_WRAPPER(37,ITextHostImpl_TxGetPropertyBits,12) +DEFINE_STDCALL_WRAPPER(38,ITextHostImpl_TxNotify,12) +DEFINE_STDCALL_WRAPPER(39,ITextHostImpl_TxImmGetContext,4) +DEFINE_STDCALL_WRAPPER(40,ITextHostImpl_TxImmReleaseContext,8) +DEFINE_STDCALL_WRAPPER(41,ITextHostImpl_TxGetSelectionBarWidth,8) static ITextHostVtbl textHostVtbl = { ITextHostImpl_QueryInterface, @@ -628,58 +680,6 @@ static ITextHostVtbl textHostVtbl = { THISCALL(ITextHostImpl_TxGetSelectionBarWidth), }; -#ifdef __i386__ /* thiscall functions are i386-specific */ - -#define STDCALL(func) __stdcall_ ## func -#define DEFINE_STDCALL_WRAPPER(num,func) \ - extern typeof(func) __stdcall_ ## func; \ - __ASM_GLOBAL_FUNC(__stdcall_ ## func, \ - "popl %eax\n\t" \ - "popl %ecx\n\t" \ - "pushl %eax\n\t" \ - "movl (%ecx), %eax\n\t" \ - "jmp *(4*(" #num "))(%eax)" ) - -DEFINE_STDCALL_WRAPPER(3,ITextHostImpl_TxGetDC); -DEFINE_STDCALL_WRAPPER(4,ITextHostImpl_TxReleaseDC); -DEFINE_STDCALL_WRAPPER(5,ITextHostImpl_TxShowScrollBar); -DEFINE_STDCALL_WRAPPER(6,ITextHostImpl_TxEnableScrollBar); -DEFINE_STDCALL_WRAPPER(7,ITextHostImpl_TxSetScrollRange); -DEFINE_STDCALL_WRAPPER(8,ITextHostImpl_TxSetScrollPos); -DEFINE_STDCALL_WRAPPER(9,ITextHostImpl_TxInvalidateRect); -DEFINE_STDCALL_WRAPPER(10,ITextHostImpl_TxViewChange); -DEFINE_STDCALL_WRAPPER(11,ITextHostImpl_TxCreateCaret); -DEFINE_STDCALL_WRAPPER(12,ITextHostImpl_TxShowCaret); -DEFINE_STDCALL_WRAPPER(13,ITextHostImpl_TxSetCaretPos); -DEFINE_STDCALL_WRAPPER(14,ITextHostImpl_TxSetTimer); -DEFINE_STDCALL_WRAPPER(15,ITextHostImpl_TxKillTimer); -DEFINE_STDCALL_WRAPPER(16,ITextHostImpl_TxScrollWindowEx); -DEFINE_STDCALL_WRAPPER(17,ITextHostImpl_TxSetCapture); -DEFINE_STDCALL_WRAPPER(18,ITextHostImpl_TxSetFocus); -DEFINE_STDCALL_WRAPPER(19,ITextHostImpl_TxSetCursor); -DEFINE_STDCALL_WRAPPER(20,ITextHostImpl_TxScreenToClient); -DEFINE_STDCALL_WRAPPER(21,ITextHostImpl_TxClientToScreen); -DEFINE_STDCALL_WRAPPER(22,ITextHostImpl_TxActivate); -DEFINE_STDCALL_WRAPPER(23,ITextHostImpl_TxDeactivate); -DEFINE_STDCALL_WRAPPER(24,ITextHostImpl_TxGetClientRect); -DEFINE_STDCALL_WRAPPER(25,ITextHostImpl_TxGetViewInset); -DEFINE_STDCALL_WRAPPER(26,ITextHostImpl_TxGetCharFormat); -DEFINE_STDCALL_WRAPPER(27,ITextHostImpl_TxGetParaFormat); -DEFINE_STDCALL_WRAPPER(28,ITextHostImpl_TxGetSysColor); -DEFINE_STDCALL_WRAPPER(29,ITextHostImpl_TxGetBackStyle); -DEFINE_STDCALL_WRAPPER(30,ITextHostImpl_TxGetMaxLength); -DEFINE_STDCALL_WRAPPER(31,ITextHostImpl_TxGetScrollBars); -DEFINE_STDCALL_WRAPPER(32,ITextHostImpl_TxGetPasswordChar); -DEFINE_STDCALL_WRAPPER(33,ITextHostImpl_TxGetAcceleratorPos); -DEFINE_STDCALL_WRAPPER(34,ITextHostImpl_TxGetExtent); -DEFINE_STDCALL_WRAPPER(35,ITextHostImpl_OnTxCharFormatChange); -DEFINE_STDCALL_WRAPPER(36,ITextHostImpl_OnTxParaFormatChange); -DEFINE_STDCALL_WRAPPER(37,ITextHostImpl_TxGetPropertyBits); -DEFINE_STDCALL_WRAPPER(38,ITextHostImpl_TxNotify); -DEFINE_STDCALL_WRAPPER(39,ITextHostImpl_TxImmGetContext); -DEFINE_STDCALL_WRAPPER(40,ITextHostImpl_TxImmReleaseContext); -DEFINE_STDCALL_WRAPPER(41,ITextHostImpl_TxGetSelectionBarWidth); - ITextHostVtbl itextHostStdcallVtbl = { NULL, NULL, diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c index a6d81703528..1df9d02639a 100644 --- a/dlls/riched20/txtsrv.c +++ b/dlls/riched20/txtsrv.c @@ -37,17 +37,17 @@ #ifdef __i386__ /* thiscall functions are i386-specific */ #define THISCALL(func) __thiscall_ ## func -#define DEFINE_THISCALL_WRAPPER(func) \ +#define DEFINE_THISCALL_WRAPPER(func,args) \ extern typeof(func) THISCALL(func); \ - __ASM_GLOBAL_FUNC(__thiscall_ ## func, \ + __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \ "popl %eax\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) ) + "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) #else /* __i386__ */ #define THISCALL(func) func -#define DEFINE_THISCALL_WRAPPER(func) /* nothing */ +#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ #endif /* __i386__ */ @@ -387,24 +387,24 @@ HRESULT WINAPI fnTextSrv_TxGetCachedSize(ITextServices *iface, return E_NOTIMPL; } -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate,4) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12) static const ITextServicesVtbl textservices_Vtbl = { diff --git a/dlls/riched32/tests/editor.c b/dlls/riched32/tests/editor.c index 0d853a6e790..5cc269d855d 100644 --- a/dlls/riched32/tests/editor.c +++ b/dlls/riched32/tests/editor.c @@ -768,7 +768,9 @@ static void test_EM_POSFROMCHAR(void) if (i == 0) { ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y); - ok(pl.x == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + ok(pl.x == 1 || + broken(pl.x == 0), /* Win9x, WinME and NT4 */ + "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); xpos = pl.x; } else if (i == 1) @@ -829,7 +831,9 @@ static void test_EM_POSFROMCHAR(void) result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0); ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y); - ok(pl.x == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + ok(pl.x == 1 || + broken(pl.x == 0), /* Win9x, WinME and NT4 */ + "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); xpos = pl.x; SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0); @@ -838,7 +842,9 @@ static void test_EM_POSFROMCHAR(void) ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y); todo_wine { /* Fails on builtin because horizontal scrollbar is not being shown */ - ok(pl.x < xpos, "EM_POSFROMCHAR reports x=%hd, expected value less than %d\n", pl.x, xpos); + ok(pl.x < xpos || + broken(pl.x == xpos), /* Win9x, WinME and NT4 */ + "EM_POSFROMCHAR reports x=%hd, expected value less than %d\n", pl.x, xpos); } DestroyWindow(hwndRichEdit); } diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c index 5186ea6bda8..0887aa2399b 100644 --- a/dlls/rpcrt4/cproxy.c +++ b/dlls/rpcrt4/cproxy.c @@ -76,7 +76,7 @@ struct thunk { extern void call_stubless_func(void); __ASM_GLOBAL_FUNC(call_stubless_func, "pushl %esp\n\t" /* pointer to index */ - "call " __ASM_NAME("ObjectStubless") "\n\t" + "call " __ASM_NAME("ObjectStubless") __ASM_STDCALL(4) "\n\t" "popl %edx\n\t" /* args size */ "movl (%esp),%ecx\n\t" /* return address */ "addl %edx,%esp\n\t" diff --git a/dlls/rpcrt4/ndr_marshall.c b/dlls/rpcrt4/ndr_marshall.c index 0d12843d750..1777c49cc60 100644 --- a/dlls/rpcrt4/ndr_marshall.c +++ b/dlls/rpcrt4/ndr_marshall.c @@ -1562,7 +1562,7 @@ ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, ALIGN_POINTER(pStubMsg->Buffer, 4); safe_buffer_increment(pStubMsg, 4); } - ALIGN_LENGTH(pStubMsg->MemorySize, 4); + ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); return PointerMemorySize(pStubMsg, Buffer, pFormat); } @@ -2724,7 +2724,7 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, } TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer); pPointer += 4; - pMemory += 4; + pMemory += sizeof(void *); break; } case RPC_FC_ALIGNM4: @@ -2849,7 +2849,7 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ } pPointer += 4; - pMemory += 4; + pMemory += sizeof(void *); break; } case RPC_FC_ALIGNM4: @@ -2964,7 +2964,7 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, safe_buffer_length_increment(pStubMsg, 4); } pPointer += 4; - pMemory += 4; + pMemory += sizeof(void*); break; case RPC_FC_ALIGNM4: ALIGN_POINTER(pMemory, 4); @@ -3047,7 +3047,7 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_POINTER: NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer); pPointer += 4; - pMemory += 4; + pMemory += sizeof(void *); break; case RPC_FC_ALIGNM4: ALIGN_POINTER(pMemory, 4); @@ -3158,7 +3158,7 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ } pPointer += 4; - size += 4; + size += sizeof(void *); break; } case RPC_FC_ALIGNM4: @@ -5684,8 +5684,8 @@ static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg, ALIGN_POINTER(pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); - ALIGN_LENGTH(pStubMsg->MemorySize, 4); - pStubMsg->MemorySize += 4; + ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); + pStubMsg->MemorySize += sizeof(void *); if (!pStubMsg->IgnoreEmbeddedPointers) PointerMemorySize(pStubMsg, saved_buffer, pFormat); break; diff --git a/dlls/rpcrt4/tests/ndr_marshall.c b/dlls/rpcrt4/tests/ndr_marshall.c index c48f7debaf4..2aa814649fe 100644 --- a/dlls/rpcrt4/tests/ndr_marshall.c +++ b/dlls/rpcrt4/tests/ndr_marshall.c @@ -211,8 +211,16 @@ static void test_pointer_marshal(const unsigned char *formattypes, ptr = NdrPointerMarshall( &StubMsg, memsrc, formattypes ); ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); - ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); - ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled\n", msgpfx); + if (srcsize == 8 && wiredatalen == 16 && StubMsg.Buffer - StubMsg.BufferStart == 12) + { + /* win9x doesn't align 8-byte types properly */ + wiredatalen = 12; + } + else + { + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled\n", msgpfx); + } StubMsg.Buffer = StubMsg.BufferStart; StubMsg.MemorySize = 0; @@ -221,7 +229,7 @@ static void test_pointer_marshal(const unsigned char *formattypes, ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */) - ok(size == srcsize + 4, "%s: mem size %u\n", msgpfx, size); + ok(size == srcsize + sizeof(void *), "%s: mem size %u\n", msgpfx, size); else ok(size == srcsize, "%s: mem size %u\n", msgpfx, size); @@ -231,7 +239,7 @@ static void test_pointer_marshal(const unsigned char *formattypes, ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */) - ok(size == srcsize + 4 + 16, "%s: mem size %u\n", msgpfx, size); + ok(size == srcsize + sizeof(void *) + 16, "%s: mem size %u\n", msgpfx, size); else ok(size == srcsize + 16, "%s: mem size %u\n", msgpfx, size); @@ -241,9 +249,9 @@ static void test_pointer_marshal(const unsigned char *formattypes, ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */) - ok(size == srcsize + 4 + (srcsize == 8 ? 8 : 4), "%s: mem size %u\n", msgpfx, size); + ok(size == srcsize + sizeof(void *) + (srcsize == 8 ? 8 : sizeof(void *)), "%s: mem size %u\n", msgpfx, size); else - ok(size == srcsize + (srcsize == 8 ? 8 : 4), "%s: mem size %u\n", msgpfx, size); + ok(size == srcsize + (srcsize == 8 ? 8 : sizeof(void *)), "%s: mem size %u\n", msgpfx, size); size = srcsize; if(formattypes[1] & 0x10) size += 4; @@ -901,6 +909,25 @@ static void test_simple_struct(void) { 0x12, 0x0, /* FC_UP */ NdrFcShort( 0x2 ), /* Offset=2 */ +#ifdef _WIN64 + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ + NdrFcShort(0x18), /* [size 24] */ + NdrFcShort(0x0), + NdrFcShort(0x8), /* Offset= 8 (266) */ + 0x08, /* FC_LONG */ + 0x39, /* FC_ALIGNM8 */ + 0x36, /* FC_POINTER */ + 0x36, /* FC_POINTER */ + 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x08, /* FC_LONG */ + 0x5c, /* FC_PAD */ + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x02, /* FC_CHAR */ + 0x5c, /* FC_PAD */ +#else 0x16, 0x3, /* FC_PSTRUCT [align 4] */ NdrFcShort( 0xc ), /* [size 12] */ 0x4b, /* FC_PP */ @@ -925,7 +952,7 @@ static void test_simple_struct(void) 0x8, /* FC_LONG */ 0x5c, /* FC_PAD */ 0x5b, /* FC_END */ - +#endif }; /* zero the entire structure, including the holes */ @@ -949,6 +976,8 @@ static void test_simple_struct(void) memcpy(wiredata + 4, &s1, wiredatalen); test_pointer_marshal(fmtstr_simple_struct, &s1, 24, wiredata, 28, NULL, 0, "struct"); + if (sizeof(void *) == 8) return; /* it cannot be represented as a simple struct on Win64 */ + /* zero the entire structure, including the hole */ memset(&ps1, 0, sizeof(ps1)); @@ -1570,7 +1599,7 @@ todo_wine { } my_alloc_called = 0; - mem = mem_orig; + mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc)); StubMsg.Buffer = StubMsg.BufferStart; NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0); ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */ diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index 0d41a6278fc..34ef797e2cb 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -56,13 +56,13 @@ static void InitFunctionPointers(void) void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T n) { - return malloc(n); + return HeapAlloc(GetProcessHeap(), 0, n); } void __RPC_USER midl_user_free(void __RPC_FAR *p) { - free(p); + HeapFree(GetProcessHeap(), 0, p); } static char * @@ -1218,21 +1218,21 @@ array_tests(void) ok(sum_toplev_conf_cond(c, 5, 6, 1) == 10, "RPC sum_toplev_conf_cond\n"); ok(sum_toplev_conf_cond(c, 5, 6, 0) == 15, "RPC sum_toplev_conf_cond\n"); - dc = malloc(FIELD_OFFSET(doub_carr_t, a[2])); + dc = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(doub_carr_t, a[2])); dc->n = 2; - dc->a[0] = malloc(FIELD_OFFSET(doub_carr_1_t, a[3])); + dc->a[0] = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(doub_carr_1_t, a[3])); dc->a[0]->n = 3; dc->a[0]->a[0] = 5; dc->a[0]->a[1] = 1; dc->a[0]->a[2] = 8; - dc->a[1] = malloc(FIELD_OFFSET(doub_carr_1_t, a[2])); + dc->a[1] = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(doub_carr_1_t, a[2])); dc->a[1]->n = 2; dc->a[1]->a[0] = 2; dc->a[1]->a[1] = 3; ok(sum_doub_carr(dc) == 19, "RPC sum_doub_carr\n"); - free(dc->a[0]); - free(dc->a[1]); - free(dc); + HeapFree(GetProcessHeap(), 0, dc->a[0]); + HeapFree(GetProcessHeap(), 0, dc->a[1]); + HeapFree(GetProcessHeap(), 0, dc); dc = NULL; make_pyramid_doub_carr(4, &dc); diff --git a/dlls/setupapi/misc.c b/dlls/setupapi/misc.c index a9efa2add47..08c0c794fa7 100644 --- a/dlls/setupapi/misc.c +++ b/dlls/setupapi/misc.c @@ -30,6 +30,7 @@ #include "lzexpand.h" #include "softpub.h" #include "mscat.h" +#include "shlobj.h" #include "wine/unicode.h" #include "wine/debug.h" @@ -197,67 +198,8 @@ LONG WINAPI QueryRegistryValue(HKEY hKey, */ BOOL WINAPI IsUserAdmin(VOID) { - SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY}; - HANDLE hToken; - DWORD dwSize; - PTOKEN_GROUPS lpGroups; - PSID lpSid; - DWORD i; - BOOL bResult = FALSE; - TRACE("\n"); - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - { - return FALSE; - } - - if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) - { - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - { - CloseHandle(hToken); - return FALSE; - } - } - - lpGroups = MyMalloc(dwSize); - if (lpGroups == NULL) - { - CloseHandle(hToken); - return FALSE; - } - - if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize)) - { - MyFree(lpGroups); - CloseHandle(hToken); - return FALSE; - } - - CloseHandle(hToken); - - if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, - &lpSid)) - { - MyFree(lpGroups); - return FALSE; - } - - for (i = 0; i < lpGroups->GroupCount; i++) - { - if (EqualSid(lpSid, lpGroups->Groups[i].Sid)) - { - bResult = TRUE; - break; - } - } - - FreeSid(lpSid); - MyFree(lpGroups); - - return bResult; + return IsUserAnAdmin(); } diff --git a/dlls/shdocvw/taskbarlist.c b/dlls/shdocvw/taskbarlist.c index e0e063c5091..028169584f0 100644 --- a/dlls/shdocvw/taskbarlist.c +++ b/dlls/shdocvw/taskbarlist.c @@ -71,6 +71,7 @@ static ULONG STDMETHODCALLTYPE taskbar_list_Release(ITaskbarList *iface) if (!refcount) { HeapFree(GetProcessHeap(), 0, This); + SHDOCVW_UnlockModule(); } return refcount; @@ -130,12 +131,14 @@ static const struct ITaskbarListVtbl taskbar_list_vtbl = HRESULT TaskbarList_Create(IUnknown *outer, REFIID riid, void **taskbar_list) { struct taskbar_list *object; + HRESULT hr; TRACE("outer %p, riid %s, taskbar_list %p\n", outer, debugstr_guid(riid), taskbar_list); if (outer) { WARN("Aggregation not supported\n"); + *taskbar_list = NULL; return CLASS_E_NOAGGREGATION; } @@ -143,15 +146,23 @@ HRESULT TaskbarList_Create(IUnknown *outer, REFIID riid, void **taskbar_list) if (!object) { ERR("Failed to allocate taskbar list object memory\n"); + *taskbar_list = NULL; return E_OUTOFMEMORY; } object->lpVtbl = &taskbar_list_vtbl; - object->refcount = 1; - - *taskbar_list = object; + object->refcount = 0; TRACE("Created ITaskbarList %p\n", object); + hr = ITaskbarList_QueryInterface((ITaskbarList *)object, riid, taskbar_list); + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + SHDOCVW_LockModule(); + return S_OK; } diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec index 9d4808fc493..b50890b1a0e 100644 --- a/dlls/shell32/shell32.spec +++ b/dlls/shell32/shell32.spec @@ -251,7 +251,7 @@ 654 stdcall @(long long) shell32_654 # ReadCabinetState@8 660 stdcall -noname FileIconInit(long) - 680 stdcall -noname IsUserAdmin() + 680 stdcall -noname IsUserAnAdmin() 704 stdcall -noname GUIDFromStringW(wstr ptr) diff --git a/dlls/shell32/shellord.c b/dlls/shell32/shellord.c index 5eb45074019..2fef9408570 100644 --- a/dlls/shell32/shellord.c +++ b/dlls/shell32/shellord.c @@ -1279,13 +1279,79 @@ BOOL WINAPI FileIconInit(BOOL bFullInit) { FIXME("(%s)\n", bFullInit ? "true" : "false"); return 0; } + /************************************************************************* - * IsUserAdmin [SHELL32.680] NT 4.0 + * IsUserAnAdmin [SHELL32.680] NT 4.0 + * + * Checks whether the current user is a member of the Administrators group. * + * PARAMS + * None + * + * RETURNS + * Success: TRUE + * Failure: FALSE */ -HRESULT WINAPI IsUserAdmin(void) -{ FIXME("stub\n"); - return TRUE; +BOOL WINAPI IsUserAnAdmin(VOID) +{ + SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY}; + HANDLE hToken; + DWORD dwSize; + PTOKEN_GROUPS lpGroups; + PSID lpSid; + DWORD i; + BOOL bResult = FALSE; + + TRACE("\n"); + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + CloseHandle(hToken); + return FALSE; + } + } + + lpGroups = HeapAlloc(GetProcessHeap(), 0, dwSize); + if (lpGroups == NULL) + { + CloseHandle(hToken); + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize)) + { + HeapFree(GetProcessHeap(), 0, lpGroups); + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, + &lpSid)) + { + HeapFree(GetProcessHeap(), 0, lpGroups); + return FALSE; + } + + for (i = 0; i < lpGroups->GroupCount; i++) + { + if (EqualSid(lpSid, lpGroups->Groups[i].Sid)) + { + bResult = TRUE; + break; + } + } + + FreeSid(lpSid); + HeapFree(GetProcessHeap(), 0, lpGroups); + return bResult; } /************************************************************************* diff --git a/dlls/shell32/tests/appbar.c b/dlls/shell32/tests/appbar.c index e23d7283e01..73dc0b2d81a 100644 --- a/dlls/shell32/tests/appbar.c +++ b/dlls/shell32/tests/appbar.c @@ -36,6 +36,7 @@ struct testwindow_info { HWND hwnd; BOOL registered; + BOOL to_be_deleted; RECT desired_rect; UINT edge; RECT allocated_rect; @@ -58,6 +59,12 @@ static void testwindow_setpos(HWND hwnd) return; } + if (info->to_be_deleted) + { + win_skip("Some Win95 and NT4 systems send messages to removed taskbars\n"); + return; + } + abd.cbSize = sizeof(abd); abd.hWnd = hwnd; abd.uEdge = info->edge; @@ -221,6 +228,7 @@ static void test_setpos(void) /* dock windows[0] to the bottom of the screen */ windows[0].registered = TRUE; + windows[0].to_be_deleted = FALSE; windows[0].edge = ABE_BOTTOM; windows[0].desired_rect.left = 0; windows[0].desired_rect.right = screen_width; @@ -241,6 +249,7 @@ static void test_setpos(void) /* dock windows[1] to the bottom of the screen */ windows[1].registered = TRUE; + windows[1].to_be_deleted = FALSE; windows[1].edge = ABE_BOTTOM; windows[1].desired_rect.left = 0; windows[1].desired_rect.right = screen_width; @@ -272,6 +281,7 @@ static void test_setpos(void) /* dock windows[2] to the bottom of the screen */ windows[2].registered = TRUE; + windows[2].to_be_deleted = FALSE; windows[2].edge = ABE_BOTTOM; windows[2].desired_rect.left = 0; windows[2].desired_rect.right = screen_width; @@ -328,6 +338,7 @@ static void test_setpos(void) expected_bottom = max(windows[0].allocated_rect.bottom, windows[1].allocated_rect.bottom); abd.hWnd = windows[0].hwnd; + windows[0].to_be_deleted = TRUE; ret = SHAppBarMessage(ABM_REMOVE, &abd); ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret); windows[0].registered = FALSE; @@ -341,12 +352,14 @@ static void test_setpos(void) /* remove the other windows */ abd.hWnd = windows[1].hwnd; + windows[1].to_be_deleted = TRUE; ret = SHAppBarMessage(ABM_REMOVE, &abd); ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret); windows[1].registered = FALSE; DestroyWindow(windows[1].hwnd); abd.hWnd = windows[2].hwnd; + windows[2].to_be_deleted = TRUE; ret = SHAppBarMessage(ABM_REMOVE, &abd); ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret); windows[2].registered = FALSE; @@ -399,7 +412,9 @@ static void test_appbarget(void) if(ret) { ok(abd.hWnd == (HWND)0xcccccccc, "hWnd overwritten\n"); - ok(abd.uEdge <= ABE_BOTTOM, "uEdge not returned\n"); + ok(abd.uEdge <= ABE_BOTTOM || + broken(abd.uEdge == 0xcccccccc), /* Some Win95 and NT4 */ + "uEdge not returned\n"); ok(abd.rc.left != 0xcccccccc, "rc not updated\n"); } diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 790096682e9..74873765f00 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -81,6 +81,15 @@ static void init_function_pointers(void) ok(hr == S_OK, "SHGetMalloc failed %08x\n", hr); } +static const char *wine_dbgstr_w(LPCWSTR str) +{ + static char buf[512]; + if (!str) + return "(null)"; + WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL); + return buf; +} + static void test_ParseDisplayName(void) { HRESULT hr; @@ -265,13 +274,15 @@ static void test_EnumObjects(IShellFolder *iFolder) for (i = 0; i < 5; i++) { SFGAOF flags; +#define SFGAO_VISTA SFGAO_DROPTARGET | SFGAO_CANLINK | SFGAO_CANCOPY /* Native returns all flags no matter what we ask for */ flags = SFGAO_CANCOPY; hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags); flags &= SFGAO_testfor; ok(hr == S_OK, "GetAttributesOf returns %08x\n", hr); ok(flags == (attrs[i]) || - flags == (attrs[i] & ~SFGAO_FILESYSANCESTOR), /* Win9x, NT4 */ + flags == (attrs[i] & ~SFGAO_FILESYSANCESTOR) || /* Win9x, NT4 */ + flags == ((attrs[i] & ~SFGAO_CAPABILITYMASK) | SFGAO_VISTA), /* Vista and higher */ "GetAttributesOf[%i] got %08x, expected %08x\n", i, flags, attrs[i]); flags = SFGAO_testfor; @@ -469,7 +480,8 @@ static void test_GetDisplayName(void) } /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */ if (pidlLast->mkid.cb >= 76) { - ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName), + ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName) || + (pidlLast->mkid.cb >= 94 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[64], wszFileName)), /* Vista */ "Filename should be stored as wchar-string at this position!\n"); } @@ -478,6 +490,7 @@ static void test_GetDisplayName(void) hr = IShellFolder_BindToObject(psfDesktop, pidlTestFile, NULL, &IID_IUnknown, (VOID**)&psfFile); todo_wine ok (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || + hr == E_NOTIMPL || /* Vista */ broken(SUCCEEDED(hr)), /* Win9x, W2K */ "hr = %08x\n", hr); if (SUCCEEDED(hr)) { @@ -960,7 +973,9 @@ static void test_SHGetPathFromIDList(void) wszPath[1] = '\0'; result = pSHGetPathFromIDListW(pidlMyComputer, wszPath); ok (!result, "SHGetPathFromIDListW succeeded where it shouldn't!\n"); - ok (GetLastError()==0xdeadbeef, "SHGetPathFromIDListW shouldn't set last error! Last error: %u\n", GetLastError()); + ok (GetLastError()==0xdeadbeef || + GetLastError()==ERROR_SUCCESS, /* Vista and higher */ + "Unexpected last error from SHGetPathFromIDListW: %u\n", GetLastError()); ok (!wszPath[0], "Expected empty path\n"); if (result) { IShellFolder_Release(psfDesktop); @@ -1116,6 +1131,10 @@ static HRESULT WINAPI InitPropertyBag_IPropertyBag_Read(IPropertyBag *iface, LPC 'A','t','t','r','i','b','u','t','e','s',0 }; static const WCHAR wszResolveLinkFlags[] = { 'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 }; + static const WCHAR wszTargetKnownFolder[] = { + 'T','a','r','g','e','t','K','n','o','w','n','F','o','l','d','e','r',0 }; + static const WCHAR wszCLSID[] = { + 'C','L','S','I','D',0 }; if (!lstrcmpW(pszPropName, wszTargetSpecialFolder)) { ok(V_VT(pVar) == VT_I4 || @@ -1155,7 +1174,19 @@ static HRESULT WINAPI InitPropertyBag_IPropertyBag_Read(IPropertyBag *iface, LPC return S_OK; } - ok(FALSE, "PropertyBag was asked for unknown property (vt=%d)!\n", V_VT(pVar)); + if (!lstrcmpW(pszPropName, wszTargetKnownFolder)) { + ok(V_VT(pVar) == VT_BSTR, "Wrong variant type for 'TargetKnownFolder' property!\n"); + /* TODO */ + return E_INVALIDARG; + } + + if (!lstrcmpW(pszPropName, wszCLSID)) { + ok(V_VT(pVar) == VT_EMPTY, "Wrong variant type for 'CLSID' property!\n"); + /* TODO */ + return E_INVALIDARG; + } + + ok(FALSE, "PropertyBag was asked for unknown property %s (vt=%d)!\n", wine_dbgstr_w(pszPropName), V_VT(pVar)); return E_INVALIDARG; } @@ -1529,7 +1560,7 @@ static void testSHGetFolderPathAndSubDirA(void) static char toolongpath[MAX_PATH+1]; if(!pSHGetFolderPathA) { - skip("SHGetFolderPathA not present!\n"); + win_skip("SHGetFolderPathA not present!\n"); return; } if(FAILED(pSHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdata))) @@ -1551,16 +1582,13 @@ static void testSHGetFolderPathAndSubDirA(void) skip("RemoveDirectoryA(%s) failed with error %u\n", testpath, GetLastError()); return; } - for(i=0; i< MAX_PATH; i++) - toolongpath[i] = '0' + i % 10; - toolongpath[MAX_PATH] = '\0'; /* test invalid second parameter */ ret = pSHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | 0xff, NULL, SHGFP_TYPE_CURRENT, wine, testpath); ok(E_INVALIDARG == ret, "expected E_INVALIDARG, got %x\n", ret); - /* test invalid forth parameter */ - ret = pSHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, 2, wine, testpath); + /* test fourth parameter */ + ret = pSHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, 2, winetemp, testpath); switch(ret) { case S_OK: /* winvista */ ok(!strncmp(appdata, testpath, strlen(appdata)), @@ -1590,6 +1618,9 @@ static void testSHGetFolderPathAndSubDirA(void) ok(S_OK == ret, "expected S_OK, got %x\n", ret); ok(!lstrcmpA(appdata, testpath), "expected %s, got %s\n", appdata, testpath); + for(i=0; i< MAX_PATH; i++) + toolongpath[i] = '0' + i % 10; + toolongpath[MAX_PATH] = '\0'; ret = pSHGetFolderPathAndSubDirA(NULL, CSIDL_FLAG_DONT_VERIFY | CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, toolongpath, testpath); ok(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) == ret, "expected %x, got %x\n", HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE), ret); @@ -1622,15 +1653,6 @@ static void testSHGetFolderPathAndSubDirA(void) RemoveDirectoryA(testpath); } -static const char *wine_dbgstr_w(LPCWSTR str) -{ - static char buf[512]; - if (!str) - return "(null)"; - WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL); - return buf; -} - static void test_LocalizedNames(void) { static char cCurrDirA[MAX_PATH]; diff --git a/dlls/urlmon/tests/Makefile.in b/dlls/urlmon/tests/Makefile.in index ebf434c8f9d..525a54d98c9 100644 --- a/dlls/urlmon/tests/Makefile.in +++ b/dlls/urlmon/tests/Makefile.in @@ -9,6 +9,7 @@ CTESTS = \ generated.c \ misc.c \ protocol.c \ + sec_mgr.c \ stream.c \ url.c diff --git a/dlls/urlmon/tests/misc.c b/dlls/urlmon/tests/misc.c index 62df78888a0..443fd8295d6 100644 --- a/dlls/urlmon/tests/misc.c +++ b/dlls/urlmon/tests/misc.c @@ -715,274 +715,6 @@ static void test_FindMimeFromData(void) ok(hres == E_INVALIDARG, "FindMimeFromData failed: %08x, expected E_INVALIDARG\n", hres); } -static const BYTE secid1[] = {'f','i','l','e',':',0,0,0,0}; -static const BYTE secid5[] = {'h','t','t','p',':','w','w','w','.','w','i','n','e','h','q', - '.','o','r','g',3,0,0,0}; -static const BYTE secid6[] = {'a','b','o','u','t',':','b','l','a','n','k',3,0,0,0}; -static const BYTE secid7[] = {'f','t','p',':','w','i','n','e','h','q','.','o','r','g', - 3,0,0,0}; -static const BYTE secid10[] = - {'f','i','l','e',':','s','o','m','e','%','2','0','f','i','l','e','.','j','p','g',3,0,0,0}; -static const BYTE secid10_2[] = - {'f','i','l','e',':','s','o','m','e',' ','f','i','l','e','.','j','p','g',3,0,0,0}; - -static struct secmgr_test { - LPCWSTR url; - DWORD zone; - HRESULT zone_hres; - DWORD secid_size; - const BYTE *secid; - HRESULT secid_hres; -} secmgr_tests[] = { - {url1, 0, S_OK, sizeof(secid1), secid1, S_OK}, - {url2, 100, 0x80041001, 0, NULL, E_INVALIDARG}, - {url3, 0, S_OK, sizeof(secid1), secid1, S_OK}, - {url5, 3, S_OK, sizeof(secid5), secid5, S_OK}, - {url6, 3, S_OK, sizeof(secid6), secid6, S_OK}, - {url7, 3, S_OK, sizeof(secid7), secid7, S_OK} -}; - -static void test_SecurityManager(void) -{ - int i; - IInternetSecurityManager *secmgr = NULL; - BYTE buf[512]; - DWORD zone, size, policy; - HRESULT hres; - - hres = CoInternetCreateSecurityManager(NULL, &secmgr, 0); - ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres); - if(FAILED(hres)) - return; - - for(i=0; i < sizeof(secmgr_tests)/sizeof(secmgr_tests[0]); i++) { - zone = 100; - hres = IInternetSecurityManager_MapUrlToZone(secmgr, secmgr_tests[i].url, - &zone, 0); - ok(hres == secmgr_tests[i].zone_hres /* IE <=6 */ - || (FAILED(secmgr_tests[i].zone_hres) && hres == E_INVALIDARG), /* IE7 */ - "[%d] MapUrlToZone failed: %08x, expected %08x\n", - i, hres, secmgr_tests[i].zone_hres); - if(SUCCEEDED(hres)) - ok(zone == secmgr_tests[i].zone, "[%d] zone=%d, expected %d\n", i, zone, - secmgr_tests[i].zone); - else - ok(zone == secmgr_tests[i].zone || zone == -1, "[%d] zone=%d\n", i, zone); - - size = sizeof(buf); - memset(buf, 0xf0, sizeof(buf)); - hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[i].url, - buf, &size, 0); - ok(hres == secmgr_tests[i].secid_hres, - "[%d] GetSecurityId failed: %08x, expected %08x\n", - i, hres, secmgr_tests[i].secid_hres); - if(secmgr_tests[i].secid) { - ok(size == secmgr_tests[i].secid_size, "[%d] size=%d, expected %d\n", - i, size, secmgr_tests[i].secid_size); - ok(!memcmp(buf, secmgr_tests[i].secid, size), "[%d] wrong secid\n", i); - } - } - - zone = 100; - hres = IInternetSecurityManager_MapUrlToZone(secmgr, url10, &zone, 0); - ok(hres == S_OK, "MapUrlToZone failed: %08x, expected S_OK\n", hres); - ok(zone == 3, "zone=%d, expected 3\n", zone); - - /* win2k3 translates %20 into a space */ - size = sizeof(buf); - memset(buf, 0xf0, sizeof(buf)); - hres = IInternetSecurityManager_GetSecurityId(secmgr, url10, buf, &size, 0); - ok(hres == S_OK, "GetSecurityId failed: %08x, expected S_OK\n", hres); - ok(size == sizeof(secid10) || - size == sizeof(secid10_2), /* win2k3 */ - "size=%d\n", size); - ok(!memcmp(buf, secid10, size) || - !memcmp(buf, secid10_2, size), /* win2k3 */ - "wrong secid\n"); - - zone = 100; - hres = IInternetSecurityManager_MapUrlToZone(secmgr, NULL, &zone, 0); - ok(hres == E_INVALIDARG, "MapUrlToZone failed: %08x, expected E_INVALIDARG\n", hres); - ok(zone == 100 || zone == -1, "zone=%d\n", zone); - - size = sizeof(buf); - hres = IInternetSecurityManager_GetSecurityId(secmgr, NULL, buf, &size, 0); - ok(hres == E_INVALIDARG, - "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres); - hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[1].url, - NULL, &size, 0); - ok(hres == E_INVALIDARG, - "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres); - hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[1].url, - buf, NULL, 0); - ok(hres == E_INVALIDARG, - "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres); - - hres = IInternetSecurityManager_ProcessUrlAction(secmgr, NULL, URLACTION_SCRIPT_RUN, (BYTE*)&policy, - sizeof(WCHAR), NULL, 0, 0, 0); - ok(hres == E_INVALIDARG, "ProcessUrlAction failed: %08x, expected E_INVALIDARG\n", hres); - - IInternetSecurityManager_Release(secmgr); -} - -/* Check if Internet Explorer is configured to run in "Enhanced Security Configuration" (aka hardened mode) */ -/* Note: this code is duplicated in dlls/mshtml/tests/dom.c, dlls/mshtml/tests/script.c and dlls/urlmon/tests/misc.c */ -static BOOL is_ie_hardened(void) -{ - HKEY zone_map; - DWORD ie_harden, type, size; - - ie_harden = 0; - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap", - 0, KEY_QUERY_VALUE, &zone_map) == ERROR_SUCCESS) { - size = sizeof(DWORD); - if (RegQueryValueEx(zone_map, "IEHarden", NULL, &type, (LPBYTE) &ie_harden, &size) != ERROR_SUCCESS || - type != REG_DWORD) { - ie_harden = 0; - } - RegCloseKey(zone_map); - } - - return ie_harden != 0; -} - -static void test_url_action(IInternetSecurityManager *secmgr, IInternetZoneManager *zonemgr, DWORD action) -{ - DWORD res, size, policy, reg_policy; - char buf[10]; - HKEY hkey; - HRESULT hres; - - /* FIXME: HKEY_CURRENT_USER is most of the time the default but this can be changed on a system. - * The test should be changed to cope with that, if need be. - */ - res = RegOpenKeyA(HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3", &hkey); - if(res != ERROR_SUCCESS) { - ok(0, "Could not open zone key\n"); - return; - } - - wsprintf(buf, "%X", action); - size = sizeof(DWORD); - res = RegQueryValueExA(hkey, buf, NULL, NULL, (BYTE*)®_policy, &size); - RegCloseKey(hkey); - if(res != ERROR_SUCCESS || size != sizeof(DWORD)) { - policy = 0xdeadbeef; - hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy, - sizeof(WCHAR), NULL, 0, 0, 0); - ok(hres == E_FAIL, "ProcessUrlAction(%x) failed: %08x, expected E_FAIL\n", action, hres); - ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy); - - policy = 0xdeadbeef; - hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy, - sizeof(DWORD), URLZONEREG_DEFAULT); - ok(hres == E_FAIL, "GetZoneActionPolicy failed: %08x, expected E_FAIL\n", hres); - ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy); - return; - } - - policy = 0xdeadbeef; - hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy, - sizeof(DWORD), URLZONEREG_DEFAULT); - ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres); - ok(policy == reg_policy, "(%x) policy=%x, expected %x\n", action, policy, reg_policy); - - if(policy != URLPOLICY_QUERY) { - if(winetest_interactive || ! is_ie_hardened()) { - policy = 0xdeadbeef; - hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy, - sizeof(WCHAR), NULL, 0, 0, 0); - if(reg_policy == URLPOLICY_DISALLOW) - ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres); - else - ok(hres == S_OK, "ProcessUrlAction(%x) failed: %08x\n", action, hres); - ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy); - }else { - skip("IE running in Enhanced Security Configuration\n"); - } - } -} - -static void test_special_url_action(IInternetSecurityManager *secmgr, IInternetZoneManager *zonemgr, DWORD action) -{ - DWORD policy; - HRESULT hres; - - policy = 0xdeadbeef; - hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy, - sizeof(DWORD), URLZONEREG_DEFAULT); - ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres); - ok(policy == URLPOLICY_DISALLOW, "(%x) policy=%x, expected URLPOLIVY_DISALLOW\n", action, policy); - - policy = 0xdeadbeef; - hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url1, action, (BYTE*)&policy, - sizeof(WCHAR), NULL, 0, 0, 0); - ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres); -} - -static void test_polices(void) -{ - IInternetZoneManager *zonemgr = NULL; - IInternetSecurityManager *secmgr = NULL; - HRESULT hres; - - hres = CoInternetCreateSecurityManager(NULL, &secmgr, 0); - ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres); - hres = CoInternetCreateZoneManager(NULL, &zonemgr, 0); - ok(hres == S_OK, "CoInternetCreateZoneManager failed: %08x\n", hres); - - test_url_action(secmgr, zonemgr, URLACTION_SCRIPT_RUN); - test_url_action(secmgr, zonemgr, URLACTION_ACTIVEX_OVERRIDE_OBJECT_SAFETY); - test_url_action(secmgr, zonemgr, URLACTION_CHANNEL_SOFTDIST_PERMISSIONS); - test_url_action(secmgr, zonemgr, 0xdeadbeef); - - test_special_url_action(secmgr, zonemgr, URLACTION_SCRIPT_OVERRIDE_SAFETY); - - IInternetSecurityManager_Release(secmgr); - IInternetZoneManager_Release(zonemgr); -} - -static void test_ZoneManager(void) -{ - IInternetZoneManager *zonemgr = NULL; - BYTE buf[32]; - HRESULT hres; - DWORD action = URLACTION_CREDENTIALS_USE; /* Implemented on all IE versions */ - - hres = CoInternetCreateZoneManager(NULL, &zonemgr, 0); - ok(hres == S_OK, "CoInternetCreateZoneManager failed: %08x\n", hres); - if(FAILED(hres)) - return; - - hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, buf, - sizeof(DWORD), URLZONEREG_DEFAULT); - ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres); - ok(*(DWORD*)buf == URLPOLICY_CREDENTIALS_SILENT_LOGON_OK || - *(DWORD*)buf == URLPOLICY_CREDENTIALS_MUST_PROMPT_USER || - *(DWORD*)buf == URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT || - *(DWORD*)buf == URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY, - "unexpected policy=%d\n", *(DWORD*)buf); - - hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, NULL, - sizeof(DWORD), URLZONEREG_DEFAULT); - ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres); - - hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, buf, - 2, URLZONEREG_DEFAULT); - ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres); - - hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, 0x1fff, buf, - sizeof(DWORD), URLZONEREG_DEFAULT); - ok(hres == E_FAIL, "GetZoneActionPolicy failed: %08x, expected E_FAIL\n", hres); - - hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 13, action, buf, - sizeof(DWORD), URLZONEREG_DEFAULT); - ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres); - - IInternetZoneManager_Release(zonemgr); -} - static void register_protocols(void) { IInternetSession *session; @@ -1540,9 +1272,6 @@ START_TEST(misc) test_CoInternetCompareUrl(); test_CoInternetQueryInfo(); test_FindMimeFromData(); - test_SecurityManager(); - test_polices(); - test_ZoneManager(); test_NameSpace(); test_MimeFilter(); test_ReleaseBindInfo(); diff --git a/dlls/urlmon/tests/protocol.c b/dlls/urlmon/tests/protocol.c index 50820e8de9a..44276b11830 100644 --- a/dlls/urlmon/tests/protocol.c +++ b/dlls/urlmon/tests/protocol.c @@ -438,7 +438,14 @@ static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOL ok(pProtocolData != NULL, "pProtocolData == NULL\n"); if(binding_test) { ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n"); - ok(!memcmp(pProtocolData, &protocoldata, sizeof(PROTOCOLDATA)), "*pProtocolData != protocoldata\n"); + ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n", + pProtocolData->grfFlags, protocoldata.grfFlags ); + ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n", + pProtocolData->dwState, protocoldata.dwState ); + ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n", + pProtocolData->pData, protocoldata.pData ); + ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n", + pProtocolData->cbData, protocoldata.cbData ); } pdata = pProtocolData; @@ -1327,7 +1334,14 @@ static HRESULT WINAPI ProtocolEmul_Continue(IInternetProtocol *iface, return S_OK; if(binding_test) { ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n"); - ok(!memcmp(pProtocolData, &protocoldata, sizeof(PROTOCOLDATA)), "*pProtocolData != protocoldata\n"); + ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n", + pProtocolData->grfFlags, protocoldata.grfFlags ); + ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n", + pProtocolData->dwState, protocoldata.dwState ); + ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n", + pProtocolData->pData, protocoldata.pData ); + ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n", + pProtocolData->cbData, protocoldata.cbData ); } switch(prot_state) { diff --git a/dlls/urlmon/tests/sec_mgr.c b/dlls/urlmon/tests/sec_mgr.c new file mode 100644 index 00000000000..f90f5a5b96c --- /dev/null +++ b/dlls/urlmon/tests/sec_mgr.c @@ -0,0 +1,335 @@ +/* + * Copyright 2005-2006 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#define CONST_VTABLE +#define NONAMELESSUNION + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "ole2.h" +#include "urlmon.h" + +#include "initguid.h" + +static const WCHAR url1[] = {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l', + '/','b','l','a','n','k','.','h','t','m',0}; +static const WCHAR url2[] = {'i','n','d','e','x','.','h','t','m',0}; +static const WCHAR url3[] = {'f','i','l','e',':','/','/','c',':','\\','I','n','d','e','x','.','h','t','m',0}; +static const WCHAR url4[] = {'f','i','l','e',':','s','o','m','e','%','2','0','f','i','l','e', + '%','2','e','j','p','g',0}; +static const WCHAR url5[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q', + '.','o','r','g',0}; +static const WCHAR url6[] = {'a','b','o','u','t',':','b','l','a','n','k',0}; +static const WCHAR url7[] = {'f','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/', + 'f','i','l','e','.','t','e','s','t',0}; +static const WCHAR url8[] = {'t','e','s','t',':','1','2','3','a','b','c',0}; +static const WCHAR url9[] = + {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g', + '/','s','i','t','e','/','a','b','o','u','t',0}; +static const WCHAR url10[] = {'f','i','l','e',':','/','/','s','o','m','e','%','2','0','f','i','l','e', + '.','j','p','g',0}; + +static const WCHAR url4e[] = {'f','i','l','e',':','s','o','m','e',' ','f','i','l','e', + '.','j','p','g',0}; + + +static const BYTE secid1[] = {'f','i','l','e',':',0,0,0,0}; +static const BYTE secid5[] = {'h','t','t','p',':','w','w','w','.','w','i','n','e','h','q', + '.','o','r','g',3,0,0,0}; +static const BYTE secid6[] = {'a','b','o','u','t',':','b','l','a','n','k',3,0,0,0}; +static const BYTE secid7[] = {'f','t','p',':','w','i','n','e','h','q','.','o','r','g', + 3,0,0,0}; +static const BYTE secid10[] = + {'f','i','l','e',':','s','o','m','e','%','2','0','f','i','l','e','.','j','p','g',3,0,0,0}; +static const BYTE secid10_2[] = + {'f','i','l','e',':','s','o','m','e',' ','f','i','l','e','.','j','p','g',3,0,0,0}; + +static struct secmgr_test { + LPCWSTR url; + DWORD zone; + HRESULT zone_hres; + DWORD secid_size; + const BYTE *secid; + HRESULT secid_hres; +} secmgr_tests[] = { + {url1, 0, S_OK, sizeof(secid1), secid1, S_OK}, + {url2, 100, 0x80041001, 0, NULL, E_INVALIDARG}, + {url3, 0, S_OK, sizeof(secid1), secid1, S_OK}, + {url5, 3, S_OK, sizeof(secid5), secid5, S_OK}, + {url6, 3, S_OK, sizeof(secid6), secid6, S_OK}, + {url7, 3, S_OK, sizeof(secid7), secid7, S_OK} +}; + +static void test_SecurityManager(void) +{ + int i; + IInternetSecurityManager *secmgr = NULL; + BYTE buf[512]; + DWORD zone, size, policy; + HRESULT hres; + + hres = CoInternetCreateSecurityManager(NULL, &secmgr, 0); + ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres); + if(FAILED(hres)) + return; + + for(i=0; i < sizeof(secmgr_tests)/sizeof(secmgr_tests[0]); i++) { + zone = 100; + hres = IInternetSecurityManager_MapUrlToZone(secmgr, secmgr_tests[i].url, + &zone, 0); + ok(hres == secmgr_tests[i].zone_hres /* IE <=6 */ + || (FAILED(secmgr_tests[i].zone_hres) && hres == E_INVALIDARG), /* IE7 */ + "[%d] MapUrlToZone failed: %08x, expected %08x\n", + i, hres, secmgr_tests[i].zone_hres); + if(SUCCEEDED(hres)) + ok(zone == secmgr_tests[i].zone, "[%d] zone=%d, expected %d\n", i, zone, + secmgr_tests[i].zone); + else + ok(zone == secmgr_tests[i].zone || zone == -1, "[%d] zone=%d\n", i, zone); + + size = sizeof(buf); + memset(buf, 0xf0, sizeof(buf)); + hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[i].url, + buf, &size, 0); + ok(hres == secmgr_tests[i].secid_hres, + "[%d] GetSecurityId failed: %08x, expected %08x\n", + i, hres, secmgr_tests[i].secid_hres); + if(secmgr_tests[i].secid) { + ok(size == secmgr_tests[i].secid_size, "[%d] size=%d, expected %d\n", + i, size, secmgr_tests[i].secid_size); + ok(!memcmp(buf, secmgr_tests[i].secid, size), "[%d] wrong secid\n", i); + } + } + + zone = 100; + hres = IInternetSecurityManager_MapUrlToZone(secmgr, url10, &zone, 0); + ok(hres == S_OK, "MapUrlToZone failed: %08x, expected S_OK\n", hres); + ok(zone == 3, "zone=%d, expected 3\n", zone); + + /* win2k3 translates %20 into a space */ + size = sizeof(buf); + memset(buf, 0xf0, sizeof(buf)); + hres = IInternetSecurityManager_GetSecurityId(secmgr, url10, buf, &size, 0); + ok(hres == S_OK, "GetSecurityId failed: %08x, expected S_OK\n", hres); + ok(size == sizeof(secid10) || + size == sizeof(secid10_2), /* win2k3 */ + "size=%d\n", size); + ok(!memcmp(buf, secid10, size) || + !memcmp(buf, secid10_2, size), /* win2k3 */ + "wrong secid\n"); + + zone = 100; + hres = IInternetSecurityManager_MapUrlToZone(secmgr, NULL, &zone, 0); + ok(hres == E_INVALIDARG, "MapUrlToZone failed: %08x, expected E_INVALIDARG\n", hres); + ok(zone == 100 || zone == -1, "zone=%d\n", zone); + + size = sizeof(buf); + hres = IInternetSecurityManager_GetSecurityId(secmgr, NULL, buf, &size, 0); + ok(hres == E_INVALIDARG, + "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres); + hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[1].url, + NULL, &size, 0); + ok(hres == E_INVALIDARG, + "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres); + hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[1].url, + buf, NULL, 0); + ok(hres == E_INVALIDARG, + "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres); + + hres = IInternetSecurityManager_ProcessUrlAction(secmgr, NULL, URLACTION_SCRIPT_RUN, (BYTE*)&policy, + sizeof(WCHAR), NULL, 0, 0, 0); + ok(hres == E_INVALIDARG, "ProcessUrlAction failed: %08x, expected E_INVALIDARG\n", hres); + + IInternetSecurityManager_Release(secmgr); +} + +/* Check if Internet Explorer is configured to run in "Enhanced Security Configuration" (aka hardened mode) */ +/* Note: this code is duplicated in dlls/mshtml/tests/dom.c, dlls/mshtml/tests/script.c and dlls/urlmon/tests/sec_mgr.c */ +static BOOL is_ie_hardened(void) +{ + HKEY zone_map; + DWORD ie_harden, type, size; + + ie_harden = 0; + if(RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap", + 0, KEY_QUERY_VALUE, &zone_map) == ERROR_SUCCESS) { + size = sizeof(DWORD); + if (RegQueryValueExA(zone_map, "IEHarden", NULL, &type, (LPBYTE) &ie_harden, &size) != ERROR_SUCCESS || + type != REG_DWORD) { + ie_harden = 0; + } + RegCloseKey(zone_map); + } + + return ie_harden != 0; +} + +static void test_url_action(IInternetSecurityManager *secmgr, IInternetZoneManager *zonemgr, DWORD action) +{ + DWORD res, size, policy, reg_policy; + char buf[10]; + HKEY hkey; + HRESULT hres; + + /* FIXME: HKEY_CURRENT_USER is most of the time the default but this can be changed on a system. + * The test should be changed to cope with that, if need be. + */ + res = RegOpenKeyA(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3", &hkey); + if(res != ERROR_SUCCESS) { + ok(0, "Could not open zone key\n"); + return; + } + + wsprintf(buf, "%X", action); + size = sizeof(DWORD); + res = RegQueryValueExA(hkey, buf, NULL, NULL, (BYTE*)®_policy, &size); + RegCloseKey(hkey); + if(res != ERROR_SUCCESS || size != sizeof(DWORD)) { + policy = 0xdeadbeef; + hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy, + sizeof(WCHAR), NULL, 0, 0, 0); + ok(hres == E_FAIL, "ProcessUrlAction(%x) failed: %08x, expected E_FAIL\n", action, hres); + ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy); + + policy = 0xdeadbeef; + hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy, + sizeof(DWORD), URLZONEREG_DEFAULT); + ok(hres == E_FAIL, "GetZoneActionPolicy failed: %08x, expected E_FAIL\n", hres); + ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy); + return; + } + + policy = 0xdeadbeef; + hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy, + sizeof(DWORD), URLZONEREG_DEFAULT); + ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres); + ok(policy == reg_policy, "(%x) policy=%x, expected %x\n", action, policy, reg_policy); + + if(policy != URLPOLICY_QUERY) { + if(winetest_interactive || ! is_ie_hardened()) { + policy = 0xdeadbeef; + hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy, + sizeof(WCHAR), NULL, 0, 0, 0); + if(reg_policy == URLPOLICY_DISALLOW) + ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres); + else + ok(hres == S_OK, "ProcessUrlAction(%x) failed: %08x\n", action, hres); + ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy); + }else { + skip("IE running in Enhanced Security Configuration\n"); + } + } +} + +static void test_special_url_action(IInternetSecurityManager *secmgr, IInternetZoneManager *zonemgr, DWORD action) +{ + DWORD policy; + HRESULT hres; + + policy = 0xdeadbeef; + hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy, + sizeof(DWORD), URLZONEREG_DEFAULT); + ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres); + ok(policy == URLPOLICY_DISALLOW, "(%x) policy=%x, expected URLPOLICY_DISALLOW\n", action, policy); + + policy = 0xdeadbeef; + hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url1, action, (BYTE*)&policy, + sizeof(WCHAR), NULL, 0, 0, 0); + ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres); +} + +static void test_polices(void) +{ + IInternetZoneManager *zonemgr = NULL; + IInternetSecurityManager *secmgr = NULL; + HRESULT hres; + + hres = CoInternetCreateSecurityManager(NULL, &secmgr, 0); + ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres); + hres = CoInternetCreateZoneManager(NULL, &zonemgr, 0); + ok(hres == S_OK, "CoInternetCreateZoneManager failed: %08x\n", hres); + + test_url_action(secmgr, zonemgr, URLACTION_SCRIPT_RUN); + test_url_action(secmgr, zonemgr, URLACTION_ACTIVEX_OVERRIDE_OBJECT_SAFETY); + test_url_action(secmgr, zonemgr, URLACTION_CHANNEL_SOFTDIST_PERMISSIONS); + test_url_action(secmgr, zonemgr, 0xdeadbeef); + + test_special_url_action(secmgr, zonemgr, URLACTION_SCRIPT_OVERRIDE_SAFETY); + + IInternetSecurityManager_Release(secmgr); + IInternetZoneManager_Release(zonemgr); +} + +static void test_ZoneManager(void) +{ + IInternetZoneManager *zonemgr = NULL; + BYTE buf[32]; + HRESULT hres; + DWORD action = URLACTION_CREDENTIALS_USE; /* Implemented on all IE versions */ + + hres = CoInternetCreateZoneManager(NULL, &zonemgr, 0); + ok(hres == S_OK, "CoInternetCreateZoneManager failed: %08x\n", hres); + if(FAILED(hres)) + return; + + hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, buf, + sizeof(DWORD), URLZONEREG_DEFAULT); + ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres); + ok(*(DWORD*)buf == URLPOLICY_CREDENTIALS_SILENT_LOGON_OK || + *(DWORD*)buf == URLPOLICY_CREDENTIALS_MUST_PROMPT_USER || + *(DWORD*)buf == URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT || + *(DWORD*)buf == URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY, + "unexpected policy=%d\n", *(DWORD*)buf); + + hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, NULL, + sizeof(DWORD), URLZONEREG_DEFAULT); + ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres); + + hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, buf, + 2, URLZONEREG_DEFAULT); + ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres); + + hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, 0x1fff, buf, + sizeof(DWORD), URLZONEREG_DEFAULT); + ok(hres == E_FAIL, "GetZoneActionPolicy failed: %08x, expected E_FAIL\n", hres); + + hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 13, action, buf, + sizeof(DWORD), URLZONEREG_DEFAULT); + ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres); + + IInternetZoneManager_Release(zonemgr); +} + + + +START_TEST(sec_mgr) +{ + OleInitialize(NULL); + + test_SecurityManager(); + test_polices(); + test_ZoneManager(); + + OleUninitialize(); +} diff --git a/dlls/user32/button.c b/dlls/user32/button.c index f2097aa1d91..926563c98f2 100644 --- a/dlls/user32/button.c +++ b/dlls/user32/button.c @@ -446,6 +446,7 @@ static LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, if (style & BS_NOTIFY) BUTTON_NOTIFY_PARENT(hWnd, BN_KILLFOCUS); + InvalidateRect( hWnd, NULL, FALSE ); break; case WM_SYSCOLORCHANGE: diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 28b0420b8a0..580582f58ad 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -1775,6 +1775,7 @@ static BOOL ignore_message( UINT message ) message == WM_GETICON || message == WM_GETOBJECT || message == WM_TIMECHANGE || + message == WM_DISPLAYCHANGE || message == WM_DEVICECHANGE); } @@ -1870,7 +1871,10 @@ static void add_message_(int line, const struct recvd_message *msg) di.u.lp = 0; di.u.item.type = dis->CtlType; di.u.item.ctl_id = dis->CtlID; - di.u.item.item_id = dis->itemID; + if (dis->CtlType == ODT_LISTBOX || + dis->CtlType == ODT_COMBOBOX || + dis->CtlType == ODT_MENU) + di.u.item.item_id = dis->itemID; di.u.item.action = dis->itemAction; di.u.item.state = dis->itemState; @@ -5088,6 +5092,8 @@ todo_wine { } /****************** button message test *************************/ +#define ID_BUTTON 0x000e + static const struct message WmSetFocusButtonSeq[] = { { HCBT_SETFOCUS, hook }, @@ -5095,7 +5101,9 @@ static const struct message WmSetFocusButtonSeq[] = { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam, 0 }, - { WM_CTLCOLORBTN, sent|defwinproc }, + { WM_CTLCOLORBTN, sent|parent }, + { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, + { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 } }; static const struct message WmKillFocusButtonSeq[] = @@ -5103,9 +5111,13 @@ static const struct message WmKillFocusButtonSeq[] = { HCBT_SETFOCUS, hook }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|wparam, 0 }, - { WM_CTLCOLORBTN, sent|defwinproc }, + { WM_CTLCOLORBTN, sent|parent }, + { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_APP, sent|wparam|lparam, 0, 0 }, + { WM_PAINT, sent }, + { WM_CTLCOLORBTN, sent|parent }, { 0 } }; static const struct message WmSetFocusStaticSeq[] = @@ -5115,7 +5127,10 @@ static const struct message WmSetFocusStaticSeq[] = { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam, 0 }, - { WM_CTLCOLORSTATIC, sent|defwinproc }, + { WM_CTLCOLORSTATIC, sent|parent }, + { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, + { WM_COMMAND, sent|wparam|parent|optional, MAKEWPARAM(ID_BUTTON, BN_CLICKED) }, /* radio button */ + { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 } }; static const struct message WmKillFocusStaticSeq[] = @@ -5123,9 +5138,42 @@ static const struct message WmKillFocusStaticSeq[] = { HCBT_SETFOCUS, hook }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|wparam, 0 }, - { WM_CTLCOLORSTATIC, sent|defwinproc }, + { WM_CTLCOLORSTATIC, sent|parent }, + { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, + { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_APP, sent|wparam|lparam, 0, 0 }, + { WM_PAINT, sent }, + { WM_CTLCOLORSTATIC, sent|parent }, + { 0 } +}; +static const struct message WmSetFocusOwnerdrawSeq[] = +{ + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, + { WM_SETFOCUS, sent|wparam, 0 }, + { WM_CTLCOLORBTN, sent|parent }, + { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x001040e4 }, + { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, + { WM_APP, sent|wparam|lparam, 0, 0 }, + { 0 } +}; +static const struct message WmKillFocusOwnerdrawSeq[] = +{ + { HCBT_SETFOCUS, hook }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, + { WM_KILLFOCUS, sent|wparam, 0 }, + { WM_CTLCOLORBTN, sent|parent }, + { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000040e4 }, + { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_APP, sent|wparam|lparam, 0, 0 }, + { WM_PAINT, sent }, + { WM_CTLCOLORBTN, sent|parent }, + { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, { 0 } }; static const struct message WmLButtonDownSeq[] = @@ -5242,10 +5290,10 @@ static void test_button_messages(void) { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq }, { BS_OWNERDRAW, DLGC_BUTTON, - WmSetFocusButtonSeq, WmKillFocusButtonSeq } + WmSetFocusOwnerdrawSeq, WmKillFocusOwnerdrawSeq } }; unsigned int i; - HWND hwnd; + HWND hwnd, parent; DWORD dlg_code; HFONT zfont; @@ -5262,30 +5310,58 @@ static void test_button_messages(void) subclass_button(); + parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok(parent != 0, "Failed to create parent window\n"); + for (i = 0; i < sizeof(button)/sizeof(button[0]); i++) { - hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP, - 0, 0, 50, 14, 0, 0, 0, NULL); + MSG msg; + DWORD style; + + hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_CHILD | BS_NOTIFY, + 0, 0, 50, 14, parent, (HMENU)ID_BUTTON, 0, NULL); ok(hwnd != 0, "Failed to create button window\n"); + style = GetWindowLongA(hwnd, GWL_STYLE); + style &= ~(WS_CHILD | BS_NOTIFY); + /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */ + if (button[i].style == BS_USERBUTTON) + todo_wine ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style); + else + ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style); + dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); SetFocus(0); + flush_events(); flush_sequence(); + log_all_parent_messages++; + trace("button style %08x\n", button[i].style); + ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); SetFocus(hwnd); + SendMessage(hwnd, WM_APP, 0, 0); /* place a separator mark here */ + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg); ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE); SetFocus(0); + SendMessage(hwnd, WM_APP, 0, 0); /* place a separator mark here */ + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg); ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE); + log_all_parent_messages--; + + ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); DestroyWindow(hwnd); } + DestroyWindow(parent); + hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE, 0, 0, 50, 14, 0, 0, 0, NULL); ok(hwnd != 0, "Failed to create button window\n"); @@ -7169,7 +7245,7 @@ static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam message == WM_PARENTNOTIFY || message == WM_CANCELMODE || message == WM_SETFOCUS || message == WM_KILLFOCUS || message == WM_ENABLE || message == WM_ENTERIDLE || - message == WM_DRAWITEM || + message == WM_DRAWITEM || message == WM_COMMAND || message == WM_IME_SETCONTEXT) { switch (message) @@ -11612,8 +11688,15 @@ static void test_PostMessage(void) HWND hwnd; BOOL ret; MSG msg; + static const WCHAR staticW[] = {'s','t','a','t','i','c',0}; - hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); + SetLastError(0xdeadbeef); + hwnd = CreateWindowExW(0, staticW, NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); + if (!hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("Skipping some PostMessage tests on Win9x/WinMe\n"); + return; + } assert(hwnd); flush_events(); @@ -11631,13 +11714,13 @@ static void test_PostMessage(void) if (data[i].hwnd) ok(ret && msg.hwnd == 0 && msg.message == WM_USER+2 && msg.wParam == 0x5678 && msg.lParam == 0x1234, - "got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER/0x1234/0x5678\n", - ret, msg.hwnd, msg.message, msg.wParam, msg.lParam); + "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n", + i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam); else ok(ret && msg.hwnd == hwnd && msg.message == WM_USER+1 && msg.wParam == 0x1234 && msg.lParam == 0x5678, - "got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER/0x1234/0x5678\n", - ret, msg.hwnd, msg.message, msg.wParam, msg.lParam); + "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n", + i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam, msg.hwnd); } } diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index ac7ced4af9d..c886195f254 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -67,6 +67,11 @@ static unsigned int reserved_vs_const(IWineD3DBaseShader *shader, const WineD3D_ return ret; } +static inline BOOL ffp_clip_emul(IWineD3DStateBlockImpl *stateblock) +{ + return stateblock->lowest_disabled_stage < 7; +} + /* Internally used shader constants. Applications can use constants 0 to GL_LIMITS(vshader_constantsF) - 1, * so upload them above that */ @@ -76,16 +81,30 @@ static unsigned int reserved_vs_const(IWineD3DBaseShader *shader, const WineD3D_ /* ARB_program_shader private data */ struct control_frame { - struct list entry; - BOOL ifc; - BOOL muting; - unsigned int loop_no; + struct list entry; + enum + { + IF, + IFC, + LOOP, + REP + } type; + BOOL muting; + BOOL outer_loop; + union + { + unsigned int loop_no; + unsigned int ifc_no; + }; + DWORD loop_control[3]; + BOOL had_else; }; struct arb_ps_compile_args { struct ps_compile_args super; DWORD bools; /* WORD is enough, use DWORD for alignment */ + unsigned char loop_ctrl[MAX_CONST_I][3]; }; struct stb_const_desc @@ -109,7 +128,22 @@ struct arb_ps_compiled_shader struct arb_vs_compile_args { struct vs_compile_args super; - DWORD bools; /* WORD is enough, use DWORD for alignment */ + union + { + struct + { + WORD bools; + char clip_control[2]; + } boolclip; + DWORD boolclip_compare; + }; + DWORD ps_signature; + union + { + unsigned char vertex_samplers[4]; + DWORD vertex_samplers_compare; + }; + unsigned char loop_ctrl[MAX_CONST_I][3]; }; struct arb_vs_compiled_shader @@ -120,9 +154,17 @@ struct arb_vs_compiled_shader char num_int_consts; }; -struct shader_arb_ctx_priv { +struct recorded_instruction +{ + struct wined3d_shader_instruction ins; + struct list entry; +}; + +struct shader_arb_ctx_priv +{ char addr_reg[20]; - enum { + enum + { /* plain GL_ARB_vertex_program or GL_ARB_fragment_program */ ARB, /* GL_NV_vertex_progam2_option or GL_NV_fragment_program_option */ @@ -135,14 +177,35 @@ struct shader_arb_ctx_priv { const struct arb_ps_compile_args *cur_ps_args; const struct arb_ps_compiled_shader *compiled_fprog; const struct arb_vs_compiled_shader *compiled_vprog; - struct list control_frames; - BOOL muted; - unsigned int num_loops, loop_depth; + struct list control_frames; + struct list record; + BOOL recording; + BOOL muted; + unsigned int num_loops, loop_depth, num_ifcs; + int aL; + + /* For 3.0 vertex shaders */ + const char *vs_output[MAX_REG_OUTPUT]; + /* For 2.x and earlier vertex shaders */ + const char *texcrd_output[8], *color_output[2], *fog_output; + + /* 3.0 pshader input for compatibility with fixed function */ + const char *ps_input[MAX_REG_INPUT]; +}; + +struct ps_signature +{ + struct wined3d_shader_signature_element *sig; + DWORD idx; + struct wine_rb_entry entry; }; struct arb_pshader_private { struct arb_ps_compiled_shader *gl_shaders; UINT num_gl_shaders, shader_array_size; + BOOL has_signature_idx; + DWORD input_signature_idx; + DWORD clipplane_emulation; }; struct arb_vshader_private { @@ -160,6 +223,9 @@ struct shader_arb_priv GLuint depth_blt_fprogram_id[tex_type_count]; BOOL use_arbfp_fixed_func; struct wine_rb_tree fragment_shaders; + + struct wine_rb_tree signature_tree; + DWORD ps_sig_number; }; /******************************************************** @@ -306,6 +372,23 @@ static inline void shader_arb_ps_local_constants(IWineD3DDeviceImpl* deviceImpl) GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->luminanceconst[i].const_num, scale)); } } + checkGLcall("Load bumpmap consts\n"); + + if(gl_shader->ycorrection != WINED3D_CONST_NUM_UNUSED) + { + /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen). + * ycorrection.y: -1.0(onscreen), 1.0(offscreen) + * ycorrection.z: 1.0 + * ycorrection.w: 0.0 + */ + float val[4]; + val[0] = deviceImpl->render_offscreen ? 0.0 : ((IWineD3DSurfaceImpl *) deviceImpl->render_targets[0])->currentDesc.Height; + val[1] = deviceImpl->render_offscreen ? 1.0 : -1.0; + val[2] = 1.0; + val[3] = 0.0; + GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->ycorrection, val)); + checkGLcall("y correction loading\n"); + } if(gl_shader->num_int_consts == 0) return; @@ -322,22 +405,7 @@ static inline void shader_arb_ps_local_constants(IWineD3DDeviceImpl* deviceImpl) GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->int_consts[i], val)); } } - - if(gl_shader->ycorrection != WINED3D_CONST_NUM_UNUSED) - { - /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen). - * ycorrection.y: -1.0(onscreen), 1.0(offscreen) - * ycorrection.z: 1.0 - * ycorrection.w: 0.0 - */ - float val[4]; - val[0] = deviceImpl->render_offscreen ? 0.0 : ((IWineD3DSurfaceImpl *) deviceImpl->render_targets[0])->currentDesc.Height; - val[1] = deviceImpl->render_offscreen ? 1.0 : -1.0; - val[2] = 1.0; - val[3] = 0.0; - GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->ycorrection, val)); - checkGLcall("y correction loading\n"); - } + checkGLcall("Load ps int consts\n"); } static inline void shader_arb_vs_local_constants(IWineD3DDeviceImpl* deviceImpl) @@ -366,6 +434,7 @@ static inline void shader_arb_vs_local_constants(IWineD3DDeviceImpl* deviceImpl) GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->int_consts[i], val)); } } + checkGLcall("Load vs int consts\n"); } /** @@ -457,7 +526,8 @@ static DWORD *local_const_mapping(IWineD3DBaseShaderImpl *This) /* Generate the variable & register declarations for the ARB_vertex_program output target */ static DWORD shader_generate_arb_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps, - SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info, DWORD *lconst_map) + SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info, DWORD *lconst_map, DWORD *num_clipplanes, + struct shader_arb_ctx_priv *ctx) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; DWORD i, next_local = 0; @@ -479,10 +549,30 @@ static DWORD shader_generate_arb_declarations(IWineD3DBaseShader *iface, const s max_constantsF = GL_LIMITS(pshader_constantsF); } else { if(This->baseShader.reg_maps.usesrelconstF) { + DWORD highest_constf = 0, clip_limit; max_constantsF = GL_LIMITS(vshader_constantsF) - reserved_vs_const(iface, gl_info); - if(GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION)) max_constantsF -= GL_LIMITS(clipplanes); max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants); - } else { + + for(i = 0; i < This->baseShader.limits.constant_float; i++) + { + DWORD idx = i >> 5; + DWORD shift = i & 0x1f; + if(reg_maps->constf[idx] & (1 << shift)) highest_constf = i; + } + + clip_limit = GL_LIMITS(clipplanes); + if(ctx->target_version == ARB) clip_limit = min(clip_limit, 4); + *num_clipplanes = min(clip_limit, max_constantsF - highest_constf - 1); + max_constantsF -= *num_clipplanes; + if(*num_clipplanes < clip_limit) + { + WARN("Only %u clipplanes out of %u enabled\n", *num_clipplanes, GL_LIMITS(clipplanes)); + } + } + else + { + if(ctx->target_version >= NV2) *num_clipplanes = GL_LIMITS(clipplanes); + else *num_clipplanes = min(GL_LIMITS(clipplanes), 4); max_constantsF = GL_LIMITS(vshader_constantsF) - 1; } } @@ -642,8 +732,81 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction case WINED3DSPR_INPUT: if (pshader) { - if (reg->idx == 0) strcpy(register_name, "fragment.color.primary"); - else strcpy(register_name, "fragment.color.secondary"); + if(This->baseShader.reg_maps.shader_version.major < 3) + { + if (reg->idx == 0) strcpy(register_name, "fragment.color.primary"); + else strcpy(register_name, "fragment.color.secondary"); + } + else + { + if(reg->rel_addr) + { + char rel_reg[50]; + shader_arb_get_src_param(ins, reg->rel_addr, 0, rel_reg); + + if(strcmp(rel_reg, "**aL_emul**") == 0) + { + DWORD idx = ctx->aL + reg->idx; + if(idx < MAX_REG_INPUT) + { + strcpy(register_name, ctx->ps_input[idx]); + } + else + { + ERR("Pixel shader input register out of bounds: %u\n", idx); + sprintf(register_name, "out_of_bounds_%u", idx); + } + } + else if(This->baseShader.reg_maps.input_registers & 0x0300) + { + /* There are two ways basically: + * + * 1) Use the unrolling code that is used for loop emulation and unroll the loop. + * That means trouble if the loop also contains a breakc or if the control values + * aren't local constants. + * 2) Generate an if block that checks if aL.y < 8, == 8 or == 9 and selects the + * source dynamically. The trouble is that we cannot simply read aL.y because it + * is an ADDRESS register. We could however push it, load .zw with a value and use + * ADAC to load the condition code register and pop it again afterwards + */ + FIXME("Relative input register addressing with more than 8 registers\n"); + + /* This is better than nothing for now */ + sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx); + } + else if(ctx->cur_ps_args->super.vp_mode != vertexshader) + { + /* This is problematic because we'd have to consult the ctx->ps_input strings + * for where to find the varying. Some may be "0.0", others can be texcoords or + * colors. This needs either a pipeline replacement to make the vertex shader feed + * proper varyings, or loop unrolling + * + * For now use the texcoords and hope for the best + */ + FIXME("Non-vertex shader varying input with indirect addressing\n"); + sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx); + } + else + { + /* D3D supports indirect addressing only with aL in loop registers. The loop instruction + * pulls GL_NV_fragment_program2 in + */ + sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx); + } + } + else + { + if(reg->idx < MAX_REG_INPUT) + { + strcpy(register_name, ctx->ps_input[reg->idx]); + } + else + { + ERR("Pixel shader input register out of bounds: %u\n", reg->idx); + sprintf(register_name, "out_of_bounds_%u", reg->idx); + } + } + } } else { @@ -655,6 +818,7 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction case WINED3DSPR_CONST: if (!pshader && reg->rel_addr) { + BOOL aL = FALSE; char rel_reg[50]; UINT rel_offset = ((IWineD3DVertexShaderImpl *)This)->rel_offset; if(This->baseShader.reg_maps.shader_version.major < 2) { @@ -662,11 +826,17 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction } else { shader_arb_get_src_param(ins, reg->rel_addr, 0, rel_reg); if(ctx->target_version == ARB) { - shader_arb_request_a0(ins, rel_reg); - sprintf(rel_reg, "A0.x"); + if(strcmp(rel_reg, "**aL_emul**") == 0) { + aL = TRUE; + } else { + shader_arb_request_a0(ins, rel_reg); + sprintf(rel_reg, "A0.x"); + } } } - if (reg->idx >= rel_offset) + if(aL) + sprintf(register_name, "C[%u]", ctx->aL + reg->idx); + else if (reg->idx >= rel_offset) sprintf(register_name, "C[%s + %u]", rel_reg, reg->idx - rel_offset); else sprintf(register_name, "C[%s - %u]", rel_reg, -reg->idx + rel_offset); @@ -728,7 +898,8 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction break; case WINED3DSPR_RASTOUT: - sprintf(register_name, "%s", rastout_reg_names[reg->idx]); + if(reg->idx == 1) sprintf(register_name, "%s", ctx->fog_output); + else sprintf(register_name, "%s", rastout_reg_names[reg->idx]); break; case WINED3DSPR_DEPTHOUT: @@ -736,26 +907,68 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction break; case WINED3DSPR_ATTROUT: + /* case WINED3DSPR_OUTPUT: */ if (pshader) sprintf(register_name, "oD[%u]", reg->idx); - else if (reg->idx == 0) strcpy(register_name, "result.color.primary"); - else strcpy(register_name, "result.color.secondary"); + else strcpy(register_name, ctx->color_output[reg->idx]); break; case WINED3DSPR_TEXCRDOUT: - if (pshader) sprintf(register_name, "oT[%u]", reg->idx); - else sprintf(register_name, "result.texcoord[%u]", reg->idx); + if (pshader) + { + sprintf(register_name, "oT[%u]", reg->idx); + } + else + { + if(This->baseShader.reg_maps.shader_version.major < 3) + { + sprintf(register_name, ctx->texcrd_output[reg->idx]); + } + else + { + sprintf(register_name, ctx->vs_output[reg->idx]); + } + } break; case WINED3DSPR_LOOP: - /* Pshader has an implicitly declared loop index counter A0.x that cannot be renamed */ - if(pshader) sprintf(register_name, "A0.x"); - else sprintf(register_name, "aL.y"); + if(ctx->target_version >= NV2) + { + /* Pshader has an implicitly declared loop index counter A0.x that cannot be renamed */ + if(pshader) sprintf(register_name, "A0.x"); + else sprintf(register_name, "aL.y"); + } + else + { + /* Unfortunately this code cannot return the value of ctx->aL here. An immediate value + * would be valid, but if aL is used for indexing(its only use), there's likely an offset, + * thus the result would be something like C[15 + 30], which is not valid in the ARB program + * grammar. So return a marker for the emulated aL and intercept it in constant and varying + * indexing + */ + sprintf(register_name, "**aL_emul**"); + } + break; case WINED3DSPR_CONSTINT: sprintf(register_name, "I%u", reg->idx); break; + case WINED3DSPR_MISCTYPE: + if(reg->idx == 0) + { + sprintf(register_name, "vpos"); + } + else if(reg->idx == 1) + { + sprintf(register_name, "fragment.facing.x"); + } + else + { + FIXME("Unknown MISCTYPE register index %u\n", reg->idx); + } + break; + default: FIXME("Unhandled register type %#x[%u]\n", reg->type, reg->idx); sprintf(register_name, "unrecognized_register[%u]", reg->idx); @@ -845,8 +1058,50 @@ static void gen_color_correction(SHADER_BUFFER *buffer, const char *reg, DWORD d } } +static const char *shader_arb_get_modifier(const struct wined3d_shader_instruction *ins) +{ + DWORD mod; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + if (!ins->dst_count) return ""; + + mod = ins->dst[0].modifiers; + + /* Silently ignore PARTIALPRECISION if its not supported */ + if(priv->target_version == ARB) mod &= ~WINED3DSPDM_PARTIALPRECISION; + + if(mod & WINED3DSPDM_MSAMPCENTROID) + { + FIXME("Unhandled modifier WINED3DSPDM_MSAMPCENTROID\n"); + mod &= ~WINED3DSPDM_MSAMPCENTROID; + } + + switch(mod) + { + case WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION: + return "H_SAT"; + + case WINED3DSPDM_SATURATE: + return "_SAT"; + + case WINED3DSPDM_PARTIALPRECISION: + return "H"; + + case 0: + return ""; + + default: + FIXME("Unknown modifiers 0x%08x\n", mod); + return ""; + } +} + +#define TEX_PROJ 0x1 +#define TEX_BIAS 0x2 +#define TEX_LOD 0x4 +#define TEX_DERIV 0x10 + static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD sampler_idx, - const char *dst_str, const char *coord_reg, BOOL projected, BOOL bias) + const char *dst_str, const char *coord_reg, WORD flags, const char *dsx, const char *dsy) { SHADER_BUFFER *buffer = ins->ctx->buffer; DWORD sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx]; @@ -854,6 +1109,11 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + const char *mod; + BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type); + + /* D3D vertex shader sampler IDs are vertex samplers(0-3), not global d3d samplers */ + if(!pshader) sampler_idx += MAX_FRAGMENT_SAMPLERS; switch(sampler_type) { case WINED3DSTT_1D: @@ -889,18 +1149,49 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD tex_type = ""; } - if (bias) { + /* TEX, TXL, TXD and TXP do not support the "H" modifier, + * so don't use shader_arb_get_modifier + */ + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) mod = "_SAT"; + else mod = ""; + + /* Fragment samplers always have indentity mapping */ + if(sampler_idx >= MAX_FRAGMENT_SAMPLERS) + { + sampler_idx = priv->cur_vs_args->vertex_samplers[sampler_idx - MAX_FRAGMENT_SAMPLERS]; + } + + if (flags & TEX_DERIV) + { + if(flags & TEX_PROJ) FIXME("Projected texture sampling with custom derivates\n"); + if(flags & TEX_BIAS) FIXME("Biased texture sampling with custom derivates\n"); + shader_addline(buffer, "TXD%s %s, %s, %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, + dsx, dsy,sampler_idx, tex_type); + } + else if(flags & TEX_LOD) + { + if(flags & TEX_PROJ) FIXME("Projected texture sampling with explicit lod\n"); + if(flags & TEX_BIAS) FIXME("Biased texture sampling with explicit lod\n"); + shader_addline(buffer, "TXL%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, + sampler_idx, tex_type); + } + else if (flags & TEX_BIAS) + { /* Shouldn't be possible, but let's check for it */ - if(projected) FIXME("Biased and Projected texture sampling\n"); + if(flags & TEX_PROJ) FIXME("Biased and Projected texture sampling\n"); /* TXB takes the 4th component of the source vector automatically, as d3d. Nothing more to do */ - shader_addline(buffer, "TXB %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); - } else if (projected) { - shader_addline(buffer, "TXP %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); - } else { - shader_addline(buffer, "TEX %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); + shader_addline(buffer, "TXB%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); + } + else if (flags & TEX_PROJ) + { + shader_addline(buffer, "TXP%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); + } + else + { + shader_addline(buffer, "TEX%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); } - if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) + if (pshader) { gen_color_correction(buffer, dst_str, ins->dst[0].write_mask, "one", "coefmul.x", priv->cur_ps_args->super.color_fixup[sampler_idx]); @@ -991,31 +1282,6 @@ static void shader_arb_get_src_param(const struct wined3d_shader_instruction *in sprintf(outregstr, "T%c%s", 'A' + tmpreg, swzstr); } -static const char *shader_arb_get_modifier(const struct wined3d_shader_instruction *ins) -{ - DWORD mod; - const char *ret = ""; - if (!ins->dst_count) return ""; - - mod = ins->dst[0].modifiers; - if(mod & WINED3DSPDM_SATURATE) { - ret = "_SAT"; - mod &= ~WINED3DSPDM_SATURATE; - } - if(mod & WINED3DSPDM_PARTIALPRECISION) { - FIXME("Unhandled modifier WINED3DSPDM_PARTIALPRECISION\n"); - mod &= ~WINED3DSPDM_PARTIALPRECISION; - } - if(mod & WINED3DSPDM_MSAMPCENTROID) { - FIXME("Unhandled modifier WINED3DSPDM_MSAMPCENTROID\n"); - mod &= ~WINED3DSPDM_MSAMPCENTROID; - } - if(mod) { - FIXME("Unknown modifiers 0x%08x\n", mod); - } - return ret; -} - static void pshader_hw_bem(const struct wined3d_shader_instruction *ins) { const struct wined3d_shader_dst_param *dst = &ins->dst[0]; @@ -1050,6 +1316,7 @@ static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins) char src_name[3][50]; DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, ins->ctx->reg_maps->shader_version.minor); + BOOL is_color; shader_arb_get_dst_param(ins, dst, dst_name); shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); @@ -1062,8 +1329,15 @@ static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins) shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]); shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]); shader_addline(buffer, "ADD TA, -%s, coefdiv.x;\n", src_name[0]); - shader_addline(buffer, "CMP%s %s, TA, %s, %s;\n", - shader_arb_get_modifier(ins), dst_name, src_name[1], src_name[2]); + /* No modifiers supported on CMP */ + shader_addline(buffer, "CMP %s, TA, %s, %s;\n", dst_name, src_name[1], src_name[2]); + + /* _SAT on CMP doesn't make much sense, but it is not a pure NOP */ + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) + { + shader_arb_get_register_name(ins, &dst->reg, src_name[0], &is_color); + shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, dst_name); + } } } @@ -1073,6 +1347,7 @@ static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins) SHADER_BUFFER *buffer = ins->ctx->buffer; char dst_name[50]; char src_name[3][50]; + BOOL is_color; shader_arb_get_dst_param(ins, dst, dst_name); @@ -1081,8 +1356,15 @@ static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins) shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]); shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]); - shader_addline(buffer, "CMP%s %s, %s, %s, %s;\n", shader_arb_get_modifier(ins), dst_name, + /* No modifiers are supported on CMP */ + shader_addline(buffer, "CMP %s, %s, %s, %s;\n", dst_name, src_name[0], src_name[2], src_name[1]); + + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) + { + shader_arb_get_register_name(ins, &dst->reg, src_name[0], &is_color); + shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, src_name[0]); + } } /** Process the WINED3DSIO_DP2ADD instruction in ARB. @@ -1318,12 +1600,12 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins) const struct wined3d_shader_dst_param *dst = &ins->dst[0]; DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, ins->ctx->reg_maps->shader_version.minor); - BOOL projected = FALSE, bias = FALSE; struct wined3d_shader_src_param src; char reg_dest[40]; char reg_coord[40]; DWORD reg_sampler_code; + DWORD myflags = 0; /* All versions have a destination register */ shader_arb_get_dst_param(ins, dst, reg_dest); @@ -1359,7 +1641,7 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins) flags = deviceImpl->stateBlock->textureState[reg_sampler_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]; } if (flags & WINED3DTTFF_PROJECTED) { - projected = TRUE; + myflags |= TEX_PROJ; } } else if (shader_version < WINED3D_SHADER_VERSION(2,0)) @@ -1371,15 +1653,15 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins) */ shader_addline(ins->ctx->buffer, "SWZ TA, %s, x, y, z, z;\n", reg_coord); strcpy(reg_coord, "TA"); - projected = TRUE; + myflags |= TEX_PROJ; } else if(src_mod == WINED3DSPSM_DW) { - projected = TRUE; + myflags |= TEX_PROJ; } } else { - if (ins->flags & WINED3DSI_TEXLD_PROJECT) projected = TRUE; - if (ins->flags & WINED3DSI_TEXLD_BIAS) bias = TRUE; + if (ins->flags & WINED3DSI_TEXLD_PROJECT) myflags |= TEX_PROJ; + if (ins->flags & WINED3DSI_TEXLD_BIAS) myflags |= TEX_BIAS; } - shader_hw_sample(ins, reg_sampler_code, reg_dest, reg_coord, projected, bias); + shader_hw_sample(ins, reg_sampler_code, reg_dest, reg_coord, myflags, NULL, NULL); } static void pshader_hw_texcoord(const struct wined3d_shader_instruction *ins) @@ -1423,7 +1705,7 @@ static void pshader_hw_texreg2ar(const struct wined3d_shader_instruction *ins) shader_addline(buffer, "MOV TA.y, %s.x;\n", src_str); shader_addline(buffer, "MOV TA.x, %s.w;\n", src_str); flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg1, dst_str, "TA", flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg1, dst_str, "TA", flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); } static void pshader_hw_texreg2gb(const struct wined3d_shader_instruction *ins) @@ -1439,7 +1721,7 @@ static void pshader_hw_texreg2gb(const struct wined3d_shader_instruction *ins) shader_arb_get_src_param(ins, &ins->src[0], 0, src_str); shader_addline(buffer, "MOV TA.x, %s.y;\n", src_str); shader_addline(buffer, "MOV TA.y, %s.z;\n", src_str); - shader_hw_sample(ins, reg1, dst_str, "TA", FALSE, FALSE); + shader_hw_sample(ins, reg1, dst_str, "TA", 0, NULL, NULL); } static void pshader_hw_texreg2rgb(const struct wined3d_shader_instruction *ins) @@ -1451,7 +1733,7 @@ static void pshader_hw_texreg2rgb(const struct wined3d_shader_instruction *ins) /* Note that texreg2rg treats Tx as a temporary register, not as a varying */ shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); shader_arb_get_src_param(ins, &ins->src[0], 0, src_str); - shader_hw_sample(ins, reg1, dst_str, src_str, FALSE, FALSE); + shader_hw_sample(ins, reg1, dst_str, src_str, 0, NULL, NULL); } static void pshader_hw_texbem(const struct wined3d_shader_instruction *ins) @@ -1497,7 +1779,7 @@ static void pshader_hw_texbem(const struct wined3d_shader_instruction *ins) shader_addline(buffer, "ADD TA.xy, TA, %s;\n", reg_coord); } - shader_hw_sample(ins, reg_dest_code, dst_reg, "TA", FALSE, FALSE); + shader_hw_sample(ins, reg_dest_code, dst_reg, "TA", 0, NULL, NULL); if (ins->handler_idx == WINED3DSIH_TEXBEML) { @@ -1544,7 +1826,7 @@ static void pshader_hw_texm3x2tex(const struct wined3d_shader_instruction *ins) shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name); shader_addline(buffer, "DP3 %s.y, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); } static void pshader_hw_texm3x3pad(const struct wined3d_shader_instruction *ins) @@ -1565,8 +1847,8 @@ static void pshader_hw_texm3x3pad(const struct wined3d_shader_instruction *ins) shader_arb_get_register_name(ins, &tmp_reg, dst_name, &is_color); shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name); - shader_addline(buffer, "DP3 %s%u.%c, fragment.texcoord[%u], %s;\n", - dst_name, tmp_reg.idx, 'x' + current_state->current_row, reg, src0_name); + shader_addline(buffer, "DP3 %s.%c, fragment.texcoord[%u], %s;\n", + dst_name, 'x' + current_state->current_row, reg, src0_name); current_state->texcoord_w[current_state->current_row++] = reg; } @@ -1589,7 +1871,7 @@ static void pshader_hw_texm3x3tex(const struct wined3d_shader_instruction *ins) /* Sample the texture using the calculated coordinates */ shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg, dst_str, dst_name, flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg, dst_str, dst_name, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); current_state->current_row = 0; } @@ -1631,7 +1913,7 @@ static void pshader_hw_texm3x3vspec(const struct wined3d_shader_instruction *ins /* Sample the texture using the calculated coordinates */ shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); current_state->current_row = 0; } @@ -1673,7 +1955,7 @@ static void pshader_hw_texm3x3spec(const struct wined3d_shader_instruction *ins) /* Sample the texture using the calculated coordinates */ shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; - shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED, FALSE); + shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL); current_state->current_row = 0; } @@ -1720,7 +2002,7 @@ static void pshader_hw_texdp3tex(const struct wined3d_shader_instruction *ins) shader_addline(buffer, "DP3 TB.x, fragment.texcoord[%u], %s;\n", sampler_idx, src0); shader_arb_get_dst_param(ins, &ins->dst[0], dst_str); - shader_hw_sample(ins, sampler_idx, dst_str, "TB", FALSE /* Only one coord, can't be projected */, FALSE); + shader_hw_sample(ins, sampler_idx, dst_str, "TB", 0 /* Only one coord, can't be projected */, NULL, NULL); } /** Process the WINED3DSIO_TEXDP3 instruction in ARB: @@ -1930,8 +2212,14 @@ static void shader_hw_sincos(const struct wined3d_shader_instruction *ins) shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0); if(shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) { shader_arb_get_dst_param(ins, &ins->dst[0], dst_name); - shader_addline(buffer, "SCS%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, - src_name0); + /* No modifiers are supported on SCS */ + shader_addline(buffer, "SCS %s, %s;\n", dst_name, src_name0); + + if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) + { + shader_arb_get_register_name(ins, &dst->reg, src_name0, &is_color); + shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, src_name0); + } } else if(priv->target_version >= NV2) { shader_arb_get_register_name(ins, &dst->reg, dst_name, &is_color); @@ -2160,90 +2448,278 @@ static void shader_hw_endrep(const struct wined3d_shader_instruction *ins) } } -static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info) +static const struct control_frame *find_last_loop(const struct shader_arb_ctx_priv *priv) { - GLuint program_id = 0; - const char *blt_vprogram = - "!!ARBvp1.0\n" - "PARAM c[1] = { { 1, 0.5 } };\n" - "MOV result.position, vertex.position;\n" - "MOV result.color, c[0].x;\n" - "MOV result.texcoord[0], vertex.texcoord[0];\n" - "END\n"; - - GL_EXTCALL(glGenProgramsARB(1, &program_id)); - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, program_id)); - GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(blt_vprogram), blt_vprogram)); + struct control_frame *control_frame; - if (glGetError() == GL_INVALID_OPERATION) { - GLint pos; - glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); - FIXME("Vertex program error at position %d: %s\n", pos, - debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + LIST_FOR_EACH_ENTRY(control_frame, &priv->control_frames, struct control_frame, entry) + { + if(control_frame->type == LOOP || control_frame->type == REP) return control_frame; } - - return program_id; + ERR("Could not find loop for break\n"); + return NULL; } -/* GL locking is done by the caller */ -static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, enum tex_types tex_type) +static void shader_hw_break(const struct wined3d_shader_instruction *ins) { - GLuint program_id = 0; - static const char * const blt_fprograms[tex_type_count] = - { - /* tex_1d */ - NULL, - /* tex_2d */ - "!!ARBfp1.0\n" - "TEMP R0;\n" - "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n" - "MOV result.depth.z, R0.x;\n" - "END\n", - /* tex_3d */ - NULL, - /* tex_cube */ - "!!ARBfp1.0\n" - "TEMP R0;\n" - "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n" - "MOV result.depth.z, R0.x;\n" - "END\n", - /* tex_rect */ - "!!ARBfp1.0\n" - "TEMP R0;\n" - "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n" - "MOV result.depth.z, R0.x;\n" - "END\n", - }; + SHADER_BUFFER *buffer = ins->ctx->buffer; + const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data); + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); - if (!blt_fprograms[tex_type]) + if(vshader) { - FIXME("tex_type %#x not supported\n", tex_type); - tex_type = tex_2d; + shader_addline(buffer, "BRA loop_%u_end;\n", control_frame->loop_no); + } + else + { + shader_addline(buffer, "BRK;\n"); } +} - GL_EXTCALL(glGenProgramsARB(1, &program_id)); - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id)); - GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(blt_fprograms[tex_type]), blt_fprograms[tex_type])); +static void shader_hw_breakc(const struct wined3d_shader_instruction *ins) +{ + SHADER_BUFFER *buffer = ins->ctx->buffer; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data); + char src_name0[50]; + char src_name1[50]; + const char *comp; - if (glGetError() == GL_INVALID_OPERATION) { - GLint pos; - glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); - FIXME("Fragment program error at position %d: %s\n", pos, - debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0); + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1); + + switch (ins->flags) + { + case COMPARISON_GT: comp = "GT"; break; + case COMPARISON_EQ: comp = "EQ"; break; + case COMPARISON_GE: comp = "GE"; break; + case COMPARISON_LT: comp = "LT"; break; + case COMPARISON_NE: comp = "NE"; break; + case COMPARISON_LE: comp = "LE"; break; + default: + FIXME("Unrecognized comparison value: %u\n", ins->flags); + comp = "(\?\?)"; } - return program_id; + if(vshader) + { + /* SUBC CC, src0, src1" works only in pixel shaders, so use TA to throw + * away the subtraction result + */ + shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1); + shader_addline(buffer, "BRA loop_%u_end (%s.x);\n", control_frame->loop_no, comp); + } + else + { + shader_addline(buffer, "SUBC CC, %s, %s;\n", src_name0, src_name1); + shader_addline(buffer, "BRK (%s.x);\n", comp); + } } -static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcolor, const char *tmp1, - const char *tmp2, const char *tmp3, const char *tmp4, BOOL condcode) { - /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */ +static void shader_hw_ifc(const struct wined3d_shader_instruction *ins) +{ + SHADER_BUFFER *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + const char *comp; + char src_name0[50]; + char src_name1[50]; + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); - if(condcode) + /* Invert the flag. We jump to the else label if the condition is NOT true */ + switch(ins->flags) { - /* Sigh. MOVC CC doesn't work, so use one of the temps as dummy dest */ - shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.y;\n", tmp1, fragcolor); - /* Calculate the > 0.0031308 case */ + case COMPARISON_GT: comp = "LE"; break; + case COMPARISON_EQ: comp = "NE"; break; + case COMPARISON_GE: comp = "LT"; break; + case COMPARISON_LT: comp = "GE"; break; + case COMPARISON_NE: comp = "EQ"; break; + case COMPARISON_LE: comp = "GT"; break; + default: + FIXME("Unrecognized comparison value: %u\n", ins->flags); + comp = "\?\?"; + } + + shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0); + shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1); + + if(vshader) + { + shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1); + shader_addline(buffer, "BRA ifc_%u_endif (%s.x);\n", control_frame->ifc_no, comp); + } + else + { + shader_addline(buffer, "SUBC CC, %s, %s;\n", src_name0, src_name1); + shader_addline(buffer, "IF %s.x;\n", comp); + } +} + +static void shader_hw_else(const struct wined3d_shader_instruction *ins) +{ + SHADER_BUFFER *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + if(vshader) + { + shader_addline(buffer, "BRA ifc_%u_endif;\n", control_frame->ifc_no); + shader_addline(buffer, "ifc_%u_else:\n", control_frame->ifc_no); + control_frame->had_else = TRUE; + } + else + { + shader_addline(buffer, "ELSE;\n"); + } +} + +static void shader_hw_endif(const struct wined3d_shader_instruction *ins) +{ + SHADER_BUFFER *buffer = ins->ctx->buffer; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + struct list *e = list_head(&priv->control_frames); + struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry); + BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type); + + if(vshader) + { + if(control_frame->had_else) + { + shader_addline(buffer, "ifc_%u_endif:\n", control_frame->ifc_no); + } + else + { + shader_addline(buffer, "#No else branch. else is endif\n"); + shader_addline(buffer, "ifc_%u_else:\n", control_frame->ifc_no); + } + } + else + { + shader_addline(buffer, "ENDIF;\n"); + } +} + +static void shader_hw_texldd(const struct wined3d_shader_instruction *ins) +{ + DWORD sampler_idx = ins->src[1].reg.idx; + char reg_dest[40]; + char reg_src[3][40]; + DWORD flags = TEX_DERIV; + + shader_arb_get_dst_param(ins, &ins->dst[0], reg_dest); + shader_arb_get_src_param(ins, &ins->src[0], 0, reg_src[0]); + shader_arb_get_src_param(ins, &ins->src[2], 1, reg_src[1]); + shader_arb_get_src_param(ins, &ins->src[3], 2, reg_src[2]); + + if (ins->flags & WINED3DSI_TEXLD_PROJECT) flags |= TEX_PROJ; + if (ins->flags & WINED3DSI_TEXLD_BIAS) flags |= TEX_BIAS; + + shader_hw_sample(ins, sampler_idx, reg_dest, reg_src[0], flags, reg_src[1], reg_src[2]); +} + +static void shader_hw_texldl(const struct wined3d_shader_instruction *ins) +{ + DWORD sampler_idx = ins->src[1].reg.idx; + char reg_dest[40]; + char reg_coord[40]; + DWORD flags = TEX_LOD; + + shader_arb_get_dst_param(ins, &ins->dst[0], reg_dest); + shader_arb_get_src_param(ins, &ins->src[0], 0, reg_coord); + + if (ins->flags & WINED3DSI_TEXLD_PROJECT) flags |= TEX_PROJ; + if (ins->flags & WINED3DSI_TEXLD_BIAS) flags |= TEX_BIAS; + + shader_hw_sample(ins, sampler_idx, reg_dest, reg_coord, flags, NULL, NULL); +} + +static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info) +{ + GLuint program_id = 0; + const char *blt_vprogram = + "!!ARBvp1.0\n" + "PARAM c[1] = { { 1, 0.5 } };\n" + "MOV result.position, vertex.position;\n" + "MOV result.color, c[0].x;\n" + "MOV result.texcoord[0], vertex.texcoord[0];\n" + "END\n"; + + GL_EXTCALL(glGenProgramsARB(1, &program_id)); + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, program_id)); + GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(blt_vprogram), blt_vprogram)); + + if (glGetError() == GL_INVALID_OPERATION) { + GLint pos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); + FIXME("Vertex program error at position %d: %s\n", pos, + debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + } + + return program_id; +} + +/* GL locking is done by the caller */ +static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, enum tex_types tex_type) +{ + GLuint program_id = 0; + static const char * const blt_fprograms[tex_type_count] = + { + /* tex_1d */ + NULL, + /* tex_2d */ + "!!ARBfp1.0\n" + "TEMP R0;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + /* tex_3d */ + NULL, + /* tex_cube */ + "!!ARBfp1.0\n" + "TEMP R0;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + /* tex_rect */ + "!!ARBfp1.0\n" + "TEMP R0;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + }; + + if (!blt_fprograms[tex_type]) + { + FIXME("tex_type %#x not supported\n", tex_type); + tex_type = tex_2d; + } + + GL_EXTCALL(glGenProgramsARB(1, &program_id)); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id)); + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(blt_fprograms[tex_type]), blt_fprograms[tex_type])); + + if (glGetError() == GL_INVALID_OPERATION) { + GLint pos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); + FIXME("Fragment program error at position %d: %s\n", pos, + debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + } + + return program_id; +} + +static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcolor, const char *tmp1, + const char *tmp2, const char *tmp3, const char *tmp4, BOOL condcode) { + /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */ + + if(condcode) + { + /* Sigh. MOVC CC doesn't work, so use one of the temps as dummy dest */ + shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.y;\n", tmp1, fragcolor); + /* Calculate the > 0.0031308 case */ shader_addline(buffer, "POW %s.x (GE), %s.x, srgb_consts1.z;\n", fragcolor, fragcolor); shader_addline(buffer, "POW %s.y (GE), %s.y, srgb_consts1.z;\n", fragcolor, fragcolor); shader_addline(buffer, "POW %s.z (GE), %s.z, srgb_consts1.z;\n", fragcolor, fragcolor); @@ -2293,6 +2769,80 @@ static const DWORD *find_loop_control_values(IWineD3DBaseShaderImpl *This, DWORD return NULL; } +static void init_ps_input(const IWineD3DPixelShaderImpl *This, const struct arb_ps_compile_args *args, + struct shader_arb_ctx_priv *priv) +{ + const char *texcoords[8] = + { + "fragment.texcoord[0]", "fragment.texcoord[1]", "fragment.texcoord[2]", "fragment.texcoord[3]", + "fragment.texcoord[4]", "fragment.texcoord[5]", "fragment.texcoord[6]", "fragment.texcoord[7]" + }; + unsigned int i; + const struct wined3d_shader_signature_element *sig = This->input_signature; + const char *semantic_name; + DWORD semantic_idx; + + switch(args->super.vp_mode) + { + case pretransformed: + case fixedfunction: + /* The pixelshader has to collect the varyings on its own. In any case properly load + * color0 and color1. In the case of pretransformed vertices also load texcoords. Set + * other attribs to 0.0. + * + * For fixedfunction this behavior is correct, according to the tests. For pretransformed + * we'd either need a replacement shader that can load other attribs like BINORMAL, or + * load the texcoord attrib pointers to match the pixel shader signature + */ + for(i = 0; i < MAX_REG_INPUT; i++) + { + semantic_name = sig[i].semantic_name; + semantic_idx = sig[i].semantic_idx; + if(semantic_name == NULL) continue; + + if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + if(semantic_idx == 0) priv->ps_input[i] = "fragment.color.primary"; + else if(semantic_idx == 1) priv->ps_input[i] = "fragment.color.secondary"; + else priv->ps_input[i] = "0.0"; + } + else if(args->super.vp_mode == fixedfunction) + { + priv->ps_input[i] = "0.0"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + if(semantic_idx < 8) priv->ps_input[i] = texcoords[semantic_idx]; + else priv->ps_input[i] = "0.0"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG)) + { + if(semantic_idx == 0) priv->ps_input[i] = "fragment.fogcoord"; + else priv->ps_input[i] = "0.0"; + } + else + { + priv->ps_input[i] = "0.0"; + } + + TRACE("v%u, semantic %s%u is %s\n", i, semantic_name, semantic_idx, priv->ps_input[i]); + } + break; + + case vertexshader: + /* That one is easy. The vertex shaders provide v0-v7 in fragment.texcoord and v8 and v9 in + * fragment.color + */ + for(i = 0; i < 8; i++) + { + priv->ps_input[i] = texcoords[i]; + } + priv->ps_input[8] = "fragment.color.primary"; + priv->ps_input[9] = "fragment.color.secondary"; + break; + } +} + /* GL locking is done by the caller */ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, SHADER_BUFFER *buffer, const struct arb_ps_compile_args *args, struct arb_ps_compiled_shader *compiled) @@ -2307,6 +2857,7 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, struct shader_arb_ctx_priv priv_ctx; BOOL dcl_tmp = args->super.srgb_correction, dcl_td = FALSE; BOOL want_nv_prog = FALSE; + struct arb_pshader_private *shader_priv = This->backend_priv; char srgbtmp[4][4]; unsigned int i, found = 0; @@ -2351,6 +2902,7 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, memset(&priv_ctx, 0, sizeof(priv_ctx)); priv_ctx.cur_ps_args = args; priv_ctx.compiled_fprog = compiled; + init_ps_input(This, args, &priv_ctx); list_init(&priv_ctx.control_frames); /* Avoid enabling NV_fragment_program* if we do not need it. @@ -2364,7 +2916,8 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, * Testing shows no performance difference between OPTION NV_fragment_program2 and NV_fragment_program. * So enable the best we can get. */ - if(reg_maps->usesdsx || reg_maps->usesdsy || reg_maps->loop_depth > 0) + if(reg_maps->usesdsx || reg_maps->usesdsy || reg_maps->loop_depth > 0 || reg_maps->usestexldd || + reg_maps->usestexldl || reg_maps->usesfacing) { want_nv_prog = TRUE; } @@ -2441,7 +2994,8 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, } /* Base Declarations */ - next_local = shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map); + next_local = shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, + lconst_map, NULL, &priv_ctx); for(i = 0; i < (sizeof(reg_maps->bumpmat) / sizeof(reg_maps->bumpmat[0])); i++) { if(!reg_maps->bumpmat[i]) continue; @@ -2498,12 +3052,29 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, { compiled->ycorrection = next_local; shader_addline(buffer, "PARAM ycorrection = program.local[%u];\n", next_local++); + + if(reg_maps->vpos) + { + shader_addline(buffer, "TEMP vpos;\n"); + /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen). + * ycorrection.y: -1.0(onscreen), 1.0(offscreen) + * ycorrection.z: 1.0 + * ycorrection.w: 0.0 + */ + shader_addline(buffer, "MAD vpos, fragment.position, ycorrection.zyww, ycorrection.wxww;\n"); + shader_addline(buffer, "FLR vpos.xy, vpos;\n"); + } } else { compiled->ycorrection = WINED3D_CONST_NUM_UNUSED; } + if(shader_priv->clipplane_emulation) + { + shader_addline(buffer, "KIL fragment.texcoord[%u];\n", shader_priv->clipplane_emulation - 1); + } + /* Base Shader Body */ shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx); @@ -2547,6 +3118,238 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, return retval; } +static int compare_sig(const struct wined3d_shader_signature_element *sig1, const struct wined3d_shader_signature_element *sig2) +{ + unsigned int i; + int ret; + + for(i = 0; i < MAX_REG_INPUT; i++) + { + if(sig1[i].semantic_name == NULL || sig2[i].semantic_name == NULL) + { + /* Compare pointers, not contents. One string is NULL(element does not exist), the other one is not NULL */ + if(sig1[i].semantic_name != sig2[i].semantic_name) return sig1[i].semantic_name < sig2[i].semantic_name ? -1 : 1; + continue; + } + + ret = strcmp(sig1[i].semantic_name, sig2[i].semantic_name); + if(ret != 0) return ret; + if(sig1[i].semantic_idx != sig2[i].semantic_idx) return sig1[i].semantic_idx < sig2[i].semantic_idx ? -1 : 1; + if(sig1[i].sysval_semantic != sig2[i].sysval_semantic) return sig1[i].sysval_semantic < sig2[i].sysval_semantic ? -1 : 1; + if(sig1[i].component_type != sig2[i].component_type) return sig1[i].sysval_semantic < sig2[i].component_type ? -1 : 1; + if(sig1[i].register_idx != sig2[i].register_idx) return sig1[i].register_idx < sig2[i].register_idx ? -1 : 1; + if(sig1[i].mask != sig2->mask) return sig1[i].mask < sig2[i].mask ? -1 : 1; + } + return 0; +} + +static struct wined3d_shader_signature_element *clone_sig(const struct wined3d_shader_signature_element *sig) +{ + struct wined3d_shader_signature_element *new; + int i; + char *name; + + new = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*new) * MAX_REG_INPUT); + for(i = 0; i < MAX_REG_INPUT; i++) + { + if(sig[i].semantic_name == NULL) + { + continue; + } + + new[i] = sig[i]; + /* Clone the semantic string */ + name = HeapAlloc(GetProcessHeap(), 0, strlen(sig[i].semantic_name) + 1); + strcpy(name, sig[i].semantic_name); + new[i].semantic_name = name; + } + return new; +} + +static DWORD find_input_signature(struct shader_arb_priv *priv, const struct wined3d_shader_signature_element *sig) +{ + struct wine_rb_entry *entry = wine_rb_get(&priv->signature_tree, sig); + struct ps_signature *found_sig; + + if(entry != NULL) + { + found_sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry); + TRACE("Found existing signature %u\n", found_sig->idx); + return found_sig->idx; + } + found_sig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sig)); + found_sig->sig = clone_sig(sig); + found_sig->idx = priv->ps_sig_number++; + TRACE("New signature stored and assigned number %u\n", found_sig->idx); + if(wine_rb_put(&priv->signature_tree, sig, &found_sig->entry) == -1) + { + ERR("Failed to insert program entry.\n"); + } + return found_sig->idx; +} + +static void init_output_registers(IWineD3DVertexShaderImpl *shader, DWORD sig_num, struct shader_arb_ctx_priv *priv_ctx) +{ + unsigned int i, j; + static const char *texcoords[8] = + { + "result.texcoord[0]", "result.texcoord[1]", "result.texcoord[2]", "result.texcoord[3]", + "result.texcoord[4]", "result.texcoord[5]", "result.texcoord[6]", "result.texcoord[7]" + }; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) shader->baseShader.device; + const struct wined3d_shader_signature_element *sig; + const char *semantic_name; + DWORD semantic_idx, reg_idx; + + /* Write generic input varyings 0 to 7 to result.texcoord[], varying 8 to result.color.primary + * and varying 9 to result.color.secondary + */ + const char *decl_idx_to_string[MAX_REG_INPUT] = + { + texcoords[0], texcoords[1], texcoords[2], texcoords[3], + texcoords[4], texcoords[5], texcoords[6], texcoords[7], + "result.color.primary", "result.color.secondary" + }; + + if(sig_num == ~0) + { + TRACE("Pixel shader uses builtin varyings\n"); + /* Map builtins to builtins */ + for(i = 0; i < 8; i++) + { + priv_ctx->texcrd_output[i] = texcoords[i]; + } + priv_ctx->color_output[0] = "result.color.primary"; + priv_ctx->color_output[1] = "result.color.secondary"; + priv_ctx->fog_output = "result.fogcoord"; + + /* Map declared regs to builtins. Use "TA" to /dev/null unread output */ + for(i = 0; i < (sizeof(shader->output_signature) / sizeof(*shader->output_signature)); i++) + { + semantic_name = shader->output_signature[i].semantic_name; + if(semantic_name == NULL) continue; + + if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION)) + { + TRACE("o%u is TMP_OUT\n", i); + if(shader->output_signature[i].semantic_idx == 0) priv_ctx->vs_output[i] = "TMP_OUT"; + else priv_ctx->vs_output[i] = "TA"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE)) + { + TRACE("o%u is result.pointsize\n", i); + if(shader->output_signature[i].semantic_idx == 0) priv_ctx->vs_output[i] = "result.pointsize"; + else priv_ctx->vs_output[i] = "TA"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + TRACE("o%u is result.color.?, idx %u\n", i, shader->output_signature[i].semantic_idx); + if(shader->output_signature[i].semantic_idx == 0) priv_ctx->vs_output[i] = "result.color.primary"; + else if(shader->output_signature[i].semantic_idx == 1) priv_ctx->vs_output[i] = "result.color.secondary"; + else priv_ctx->vs_output[i] = "TA"; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + TRACE("o%u is %s\n", i, texcoords[shader->output_signature[i].semantic_idx]); + if(shader->output_signature[i].semantic_idx >= 8) priv_ctx->vs_output[i] = "TA"; + else priv_ctx->vs_output[i] = texcoords[shader->output_signature[i].semantic_idx]; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG)) + { + TRACE("o%u is result.fogcoord\n", i); + if(shader->output_signature[i].semantic_idx > 0) priv_ctx->vs_output[i] = "TA"; + else priv_ctx->vs_output[i] = "result.fogcoord"; + } + else + { + priv_ctx->vs_output[i] = "TA"; + } + } + return; + } + + /* Instead of searching for the signature in the signature list, read the one from the current pixel shader. + * Its maybe not the shader where the signature came from, but it is the same signature and faster to find + */ + sig = ((IWineD3DPixelShaderImpl *)device->stateBlock->pixelShader)->input_signature; + TRACE("Pixel shader uses declared varyings\n"); + + /* Map builtin to declared. /dev/null the results by default to the TA temp reg */ + for(i = 0; i < 8; i++) + { + priv_ctx->texcrd_output[i] = "TA"; + } + priv_ctx->color_output[0] = "TA"; + priv_ctx->color_output[1] = "TA"; + priv_ctx->fog_output = "TA"; + + for(i = 0; i < MAX_REG_INPUT; i++) + { + semantic_name = sig[i].semantic_name; + semantic_idx = sig[i].semantic_idx; + reg_idx = sig[i].register_idx; + if(semantic_name == NULL) continue; + + /* If a declared input register is not written by builtin arguments, don't write to it. + * GL_NV_vertex_program makes sure the input defaults to 0.0, which is correct with D3D + * + * Don't care about POSITION and PSIZE here - this is a builtin vertex shader, position goes + * to TMP_OUT in any case + */ + if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD)) + { + if(semantic_idx < 8) priv_ctx->texcrd_output[semantic_idx] = decl_idx_to_string[reg_idx]; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR)) + { + if(semantic_idx < 2) priv_ctx->color_output[semantic_idx] = decl_idx_to_string[reg_idx]; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG)) + { + if(semantic_idx == 0) priv_ctx->fog_output = decl_idx_to_string[reg_idx]; + } + } + + /* Map declared to declared */ + for(i = 0; i < (sizeof(shader->output_signature) / sizeof(*shader->output_signature)); i++) + { + /* Write unread output to TA to throw them away */ + priv_ctx->vs_output[i] = "TA"; + semantic_name = shader->output_signature[i].semantic_name; + if(semantic_name == NULL) + { + continue; + } + + if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION) && + shader->output_signature[i].semantic_idx == 0) + { + priv_ctx->vs_output[i] = "TMP_OUT"; + continue; + } + else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE) && + shader->output_signature[i].semantic_idx == 0) + { + priv_ctx->vs_output[i] = "result.pointsize"; + continue; + } + + for(j = 0; j < MAX_REG_INPUT; j++) + { + if(sig[j].semantic_name == NULL) + { + continue; + } + + if(strcmp(sig[j].semantic_name, semantic_name) == 0 && + sig[j].semantic_idx == shader->output_signature[i].semantic_idx) + { + priv_ctx->vs_output[i] = decl_idx_to_string[sig[j].register_idx]; + } + } + } +} + /* GL locking is done by the caller */ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled) @@ -2557,13 +3360,15 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, const WineD3D_GL_Info *gl_info = &device->adapter->gl_info; const local_constant *lconst; GLuint ret; - DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This), next_local; + DWORD next_local, *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This); struct shader_arb_ctx_priv priv_ctx; unsigned int i; + DWORD num_clipplanes = 0; memset(&priv_ctx, 0, sizeof(priv_ctx)); priv_ctx.cur_vs_args = args; list_init(&priv_ctx.control_frames); + init_output_registers(This, args->ps_signature, &priv_ctx); /* Create the hw ARB shader */ shader_addline(buffer, "!!ARBvp1.0\n"); @@ -2571,7 +3376,11 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, /* Always enable the NV extension if available. Unlike fragment shaders, there is no * mesurable performance penalty, and we can always make use of it for clipplanes. */ - if(GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION)) { + if(GL_SUPPORT(NV_VERTEX_PROGRAM3)) { + shader_addline(buffer, "OPTION NV_vertex_program3;\n"); + priv_ctx.target_version = NV3; + shader_addline(buffer, "ADDRESS aL;\n"); + } else if(GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION)) { shader_addline(buffer, "OPTION NV_vertex_program2;\n"); priv_ctx.target_version = NV2; shader_addline(buffer, "ADDRESS aL;\n"); @@ -2591,7 +3400,8 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, shader_addline(buffer, "TEMP TA;\n"); /* Base Declarations */ - next_local = shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, lconst_map); + next_local = shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, + lconst_map, &num_clipplanes, &priv_ctx); for(i = 0; i < MAX_CONST_I; i++) { @@ -2670,11 +3480,42 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, if(priv_ctx.target_version >= NV2) { - for(i = 0; i < GL_LIMITS(clipplanes); i++) + for(i = 0; i < num_clipplanes; i++) { shader_addline(buffer, "DP4 result.clip[%u].x, TMP_OUT, state.clip[%u].plane;\n", i, i); } } + else if(args->boolclip.clip_control[0]) + { + unsigned int cur_clip = 0; + char component[4] = {'x', 'y', 'z', 'w'}; + + for(i = 0; i < GL_LIMITS(clipplanes); i++) + { + if(args->boolclip.clip_control[1] & (1 << i)) + { + shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n", + component[cur_clip++], i); + } + } + switch(cur_clip) + { + case 0: + shader_addline(buffer, "MOV TA, -helper_const.w;\n"); + break; + case 1: + shader_addline(buffer, "MOV TA.yzw, -helper_const.w;\n"); + break; + case 2: + shader_addline(buffer, "MOV TA.zw, -helper_const.w;\n"); + break; + case 3: + shader_addline(buffer, "MOV TA.w, -helper_const.w;\n"); + break; + } + shader_addline(buffer, "MOV result.texcoord[%u], TA;\n", + args->boolclip.clip_control[0] - 1); + } /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c * and the glsl equivalent @@ -2781,10 +3622,15 @@ static struct arb_ps_compiled_shader *find_arb_pshader(IWineD3DPixelShaderImpl * } static inline BOOL vs_args_equal(const struct arb_vs_compile_args *stored, const struct arb_vs_compile_args *new, - const DWORD use_map) { + const DWORD use_map, BOOL skip_int) { if((stored->super.swizzle_map & use_map) != new->super.swizzle_map) return FALSE; if(stored->super.fog_src != new->super.fog_src) return FALSE; - return stored->bools == new->bools; + if(stored->boolclip_compare != new->boolclip_compare) return FALSE; + if(stored->ps_signature != new->ps_signature) return FALSE; + if(stored->vertex_samplers_compare != new->vertex_samplers_compare) return FALSE; + if(skip_int) return TRUE; + + return memcmp(stored->loop_ctrl, new->loop_ctrl, sizeof(stored->loop_ctrl)) == 0; } static struct arb_vs_compiled_shader *find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct arb_vs_compile_args *args) @@ -2796,6 +3642,7 @@ static struct arb_vs_compiled_shader *find_arb_vshader(IWineD3DVertexShaderImpl SHADER_BUFFER buffer; struct arb_vshader_private *shader_data; GLuint ret; + const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)shader->baseShader.device)->adapter->gl_info; if(!shader->backend_priv) { shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data)); @@ -2807,7 +3654,7 @@ static struct arb_vs_compiled_shader *find_arb_vshader(IWineD3DVertexShaderImpl * (cache coherency etc) */ for(i = 0; i < shader_data->num_gl_shaders; i++) { - if(vs_args_equal(&shader_data->gl_shaders[i].args, args, use_map)) { + if(vs_args_equal(&shader_data->gl_shaders[i].args, args, use_map, GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION))) { return &shader_data->gl_shaders[i]; } } @@ -2844,36 +3691,152 @@ static struct arb_vs_compiled_shader *find_arb_vshader(IWineD3DVertexShaderImpl return &shader_data->gl_shaders[shader_data->num_gl_shaders++]; } -static inline void find_arb_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, - struct arb_ps_compile_args *args) -{ - int i; - find_ps_compile_args(shader, stateblock, &args->super); +static inline void find_arb_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, + struct arb_ps_compile_args *args) +{ + int i; + WORD int_skip; + const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)shader->baseShader.device)->adapter->gl_info; + find_ps_compile_args(shader, stateblock, &args->super); + + /* This forces all local boolean constants to 1 to make them stateblock independent */ + args->bools = shader->baseShader.reg_maps.local_bool_consts; + + for(i = 0; i < MAX_CONST_B; i++) + { + if(stateblock->pixelShaderConstantB[i]) args->bools |= ( 1 << i); + } + + /* Skip if unused or local, or supported natively */ + int_skip = ~shader->baseShader.reg_maps.integer_constants | shader->baseShader.reg_maps.local_int_consts; + if(int_skip == 0xffff || GL_SUPPORT(NV_FRAGMENT_PROGRAM_OPTION)) + { + memset(&args->loop_ctrl, 0, sizeof(args->loop_ctrl)); + return; + } + + for(i = 0; i < MAX_CONST_I; i++) + { + if(int_skip & (1 << i)) + { + args->loop_ctrl[i][0] = 0; + args->loop_ctrl[i][1] = 0; + args->loop_ctrl[i][2] = 0; + } + else + { + args->loop_ctrl[i][0] = stateblock->pixelShaderConstantI[i * 4]; + args->loop_ctrl[i][1] = stateblock->pixelShaderConstantI[i * 4 + 1]; + args->loop_ctrl[i][2] = stateblock->pixelShaderConstantI[i * 4 + 2]; + } + } +} + +static inline void find_arb_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, + struct arb_vs_compile_args *args) +{ + int i; + WORD int_skip; + IWineD3DDeviceImpl *dev = (IWineD3DDeviceImpl *)shader->baseShader.device; + const WineD3D_GL_Info *gl_info = &dev->adapter->gl_info; + find_vs_compile_args(shader, stateblock, &args->super); + + /* This forces all local boolean constants to 1 to make them stateblock independent */ + args->boolclip.bools = shader->baseShader.reg_maps.local_bool_consts; + + if(use_ps(stateblock)) + { + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) stateblock->pixelShader; + struct arb_pshader_private *shader_priv = ps->backend_priv; + args->ps_signature = shader_priv->input_signature_idx; + + args->boolclip.clip_control[0] = shader_priv->clipplane_emulation; + } + else + { + args->ps_signature = ~0; + args->boolclip.clip_control[0] = ffp_clip_emul(stateblock) ? GL_LIMITS(texture_stages) : 0; + } + + if(args->boolclip.clip_control[0]) + { + if(stateblock->renderState[WINED3DRS_CLIPPING]) + { + args->boolclip.clip_control[1] = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]; + } + else + { + args->boolclip.clip_control[1] = 0; + } + } + + /* TODO: Figure out if it would be better to store bool constants as bitmasks in the stateblock */ + for(i = 0; i < MAX_CONST_B; i++) + { + if(stateblock->vertexShaderConstantB[i]) args->boolclip.bools |= ( 1 << i); + } - /* This forces all local boolean constants to 1 to make them stateblock independent */ - args->bools = shader->baseShader.reg_maps.local_bool_consts; + args->vertex_samplers[0] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 0]; + args->vertex_samplers[1] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 1]; + args->vertex_samplers[2] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 2]; + args->vertex_samplers[3] = 0; - for(i = 0; i < MAX_CONST_B; i++) + /* Skip if unused or local */ + int_skip = ~shader->baseShader.reg_maps.integer_constants | shader->baseShader.reg_maps.local_int_consts; + if(int_skip == 0xffff || GL_SUPPORT(NV_VERTEX_PROGRAM2_OPTION)) { - if(stateblock->pixelShaderConstantB[i]) args->bools |= ( 1 << i); + memset(&args->loop_ctrl, 0, sizeof(args->loop_ctrl)); + return; + } + + for(i = 0; i < MAX_CONST_I; i++) + { + if(int_skip & (1 << i)) + { + args->loop_ctrl[i][0] = 0; + args->loop_ctrl[i][1] = 0; + args->loop_ctrl[i][2] = 0; + } + else + { + args->loop_ctrl[i][0] = stateblock->vertexShaderConstantI[i * 4]; + args->loop_ctrl[i][1] = stateblock->vertexShaderConstantI[i * 4 + 1]; + args->loop_ctrl[i][2] = stateblock->vertexShaderConstantI[i * 4 + 2]; + } } } -static inline void find_arb_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, - struct arb_vs_compile_args *args) +static void find_clip_texcoord(IWineD3DPixelShaderImpl *ps, const WineD3D_GL_Info *gl_info) { + struct arb_pshader_private *shader_priv = ps->backend_priv; int i; - find_vs_compile_args(shader, stateblock, &args->super); - - /* This forces all local boolean constants to 1 to make them stateblock independent */ - args->bools = shader->baseShader.reg_maps.local_bool_consts; - /* TODO: Figure out if it would be better to store bool constants as bitmasks in the stateblock */ - for(i = 0; i < MAX_CONST_B; i++) + /* See if we can use fragment.texcoord[7] for clipplane emulation + * + * Don't do this if it is not supported, or fragment.texcoord[7] is used + */ + if(ps->baseShader.reg_maps.shader_version.major < 3) { - if(stateblock->vertexShaderConstantB[i]) args->bools |= ( 1 << i); + for(i = GL_LIMITS(texture_stages); i > 0; i--) + { + if(!ps->baseShader.reg_maps.texcoord[i - 1]) + { + shader_priv->clipplane_emulation = i; + break; + } + } + } + else + { + for(i = GL_LIMITS(texture_stages); i > 0; i--) + { + if(!ps->baseShader.reg_maps.input_registers & (1 << (i - 1))) + { + shader_priv->clipplane_emulation = i; + break; + } + } } - } /* GL locking is done by the caller */ @@ -2882,41 +3845,31 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { struct shader_arb_priv *priv = This->shader_priv; const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - if (useVS) { - struct arb_vs_compile_args compile_args; - struct arb_vs_compiled_shader *compiled; - - TRACE("Using vertex shader\n"); - find_arb_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args); - compiled = find_arb_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args); - priv->current_vprogram_id = compiled->prgId; - priv->compiled_vprog = compiled; - - /* Bind the vertex program */ - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id)); - checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);"); - - /* Enable OpenGL vertex programs */ - glEnable(GL_VERTEX_PROGRAM_ARB); - checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);"); - TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id); - shader_arb_vs_local_constants(This); - } else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) { - priv->current_vprogram_id = 0; - glDisable(GL_VERTEX_PROGRAM_ARB); - checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)"); - } - + /* Deal with pixel shaders first so the vertex shader arg function has the input signature ready */ if (usePS) { struct arb_ps_compile_args compile_args; struct arb_ps_compiled_shader *compiled; - TRACE("Using pixel shader\n"); - find_arb_ps_compile_args((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, This->stateBlock, &compile_args); - compiled = find_arb_pshader((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, - &compile_args); + struct arb_pshader_private *shader_priv; + IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader; + + TRACE("Using pixel shader %p\n", This->stateBlock->pixelShader); + find_arb_ps_compile_args(ps, This->stateBlock, &compile_args); + compiled = find_arb_pshader(ps, &compile_args); priv->current_fprogram_id = compiled->prgId; priv->compiled_fprog = compiled; + shader_priv = ps->backend_priv; + if(!shader_priv->has_signature_idx) + { + if(ps->baseShader.reg_maps.shader_version.major < 3) shader_priv->input_signature_idx = ~0; + else shader_priv->input_signature_idx = find_input_signature(priv, ps->input_signature); + + shader_priv->has_signature_idx = TRUE; + TRACE("Shader got assigned input signature index %u\n", shader_priv->input_signature_idx); + + if(!This->vs_clipping) find_clip_texcoord(ps, gl_info); + } + /* Bind the fragment program */ GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id)); checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);"); @@ -2931,13 +3884,38 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { shader_arb_ps_local_constants(This); } else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && !priv->use_arbfp_fixed_func) { /* Disable only if we're not using arbfp fixed function fragment processing. If this is used, - * keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function - * replacement shader - */ + * keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function + * replacement shader + */ glDisable(GL_FRAGMENT_PROGRAM_ARB); checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); priv->current_fprogram_id = 0; } + + if (useVS) { + struct arb_vs_compile_args compile_args; + struct arb_vs_compiled_shader *compiled; + + TRACE("Using vertex shader %p\n", This->stateBlock->vertexShader); + find_arb_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args); + compiled = find_arb_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args); + priv->current_vprogram_id = compiled->prgId; + priv->compiled_vprog = compiled; + + /* Bind the vertex program */ + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id)); + checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);"); + + /* Enable OpenGL vertex programs */ + glEnable(GL_VERTEX_PROGRAM_ARB); + checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);"); + TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id); + shader_arb_vs_local_constants(This); + } else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) { + priv->current_vprogram_id = 0; + glDisable(GL_VERTEX_PROGRAM_ARB); + checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)"); + } } /* GL locking is done by the caller */ @@ -3030,12 +4008,45 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) { } } +static int sig_tree_compare(const void *key, const struct wine_rb_entry *entry) +{ + struct ps_signature *e = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry); + return compare_sig(key, e->sig); +} + +struct wine_rb_functions sig_tree_functions = +{ + wined3d_rb_alloc, + wined3d_rb_realloc, + wined3d_rb_free, + sig_tree_compare +}; + static HRESULT shader_arb_alloc(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - This->shader_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv)); + struct shader_arb_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv)); + if(wine_rb_init(&priv->signature_tree, &sig_tree_functions) == -1) + { + ERR("RB tree init failed\n"); + HeapFree(GetProcessHeap(), 0, priv); + return E_OUTOFMEMORY; + } + This->shader_priv = priv; return WINED3D_OK; } +static void release_signature(struct wine_rb_entry *entry, void *context) +{ + struct ps_signature *sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry); + int i; + for(i = 0; i < MAX_REG_INPUT; i++) + { + HeapFree(GetProcessHeap(), 0, (char *) sig->sig[i].semantic_name); + } + HeapFree(GetProcessHeap(), 0, sig->sig); + HeapFree(GetProcessHeap(), 0, sig); +} + static void shader_arb_free(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; @@ -3053,6 +4064,7 @@ static void shader_arb_free(IWineD3DDevice *iface) { } LEAVE_GL(); + wine_rb_destroy(&priv->signature_tree, release_signature, NULL); HeapFree(GetProcessHeap(), 0, This->shader_priv); } @@ -3131,8 +4143,8 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_ABS */ shader_hw_map2gl, /* WINED3DSIH_ADD */ shader_hw_map2gl, /* WINED3DSIH_BEM */ pshader_hw_bem, - /* WINED3DSIH_BREAK */ NULL, - /* WINED3DSIH_BREAKC */ NULL, + /* WINED3DSIH_BREAK */ shader_hw_break, + /* WINED3DSIH_BREAKC */ shader_hw_breakc, /* WINED3DSIH_BREAKP */ NULL, /* WINED3DSIH_CALL */ NULL, /* WINED3DSIH_CALLNZ */ NULL, @@ -3149,15 +4161,15 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_DST */ shader_hw_map2gl, /* WINED3DSIH_DSX */ shader_hw_map2gl, /* WINED3DSIH_DSY */ shader_hw_dsy, - /* WINED3DSIH_ELSE */ NULL, - /* WINED3DSIH_ENDIF */ NULL, + /* WINED3DSIH_ELSE */ shader_hw_else, + /* WINED3DSIH_ENDIF */ shader_hw_endif, /* WINED3DSIH_ENDLOOP */ shader_hw_endloop, /* WINED3DSIH_ENDREP */ shader_hw_endrep, /* WINED3DSIH_EXP */ shader_hw_map2gl, /* WINED3DSIH_EXPP */ shader_hw_map2gl, /* WINED3DSIH_FRC */ shader_hw_map2gl, - /* WINED3DSIH_IF */ NULL, - /* WINED3DSIH_IFC */ NULL, + /* WINED3DSIH_IF */ NULL /* Hardcoded into the shader */, + /* WINED3DSIH_IFC */ shader_hw_ifc, /* WINED3DSIH_LABEL */ NULL, /* WINED3DSIH_LIT */ shader_hw_map2gl, /* WINED3DSIH_LOG */ shader_hw_map2gl, @@ -3197,8 +4209,8 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL /* WINED3DSIH_TEXDP3 */ pshader_hw_texdp3, /* WINED3DSIH_TEXDP3TEX */ pshader_hw_texdp3tex, /* WINED3DSIH_TEXKILL */ pshader_hw_texkill, - /* WINED3DSIH_TEXLDD */ NULL, - /* WINED3DSIH_TEXLDL */ NULL, + /* WINED3DSIH_TEXLDD */ shader_hw_texldd, + /* WINED3DSIH_TEXLDL */ shader_hw_texldl, /* WINED3DSIH_TEXM3x2DEPTH */ pshader_hw_texm3x2depth, /* WINED3DSIH_TEXM3x2PAD */ pshader_hw_texm3x2pad, /* WINED3DSIH_TEXM3x2TEX */ pshader_hw_texm3x2tex, @@ -3236,12 +4248,147 @@ static inline BOOL get_bool_const(const struct wined3d_shader_instruction *ins, } else { - if(vshader) bools = priv->cur_vs_args->bools; + if(vshader) bools = priv->cur_vs_args->boolclip.bools; else bools = priv->cur_ps_args->bools; return bools & flag; } } +static inline void get_int_const(const struct wined3d_shader_instruction *ins, IWineD3DBaseShaderImpl *This, DWORD idx, int *ret) +{ + BOOL vshader = shader_is_vshader_version(This->baseShader.reg_maps.shader_version.type); + WORD flag = (1 << idx); + const local_constant *constant; + struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; + + /* Integer constants can either be a local constant, or they can be stored in the shader + * type specific compile args + */ + if(This->baseShader.reg_maps.local_int_consts & flag) + { + LIST_FOR_EACH_ENTRY(constant, &This->baseShader.constantsI, local_constant, entry) + { + if (constant->idx == idx) + { + ret[0] = constant->value[0]; + ret[1] = constant->value[1]; + /* Step / stride is signed */ + ret[2] = (int) constant->value[2]; + return; + } + } + /* If this happens the flag was set incorrectly */ + ERR("Local constant not found\n"); + ret[0] = 0; + ret[1] = 0; + ret[2] = 0; + return; + } + else + { + if(vshader) + { + /* Count and aL start value are unsigned */ + ret[0] = priv->cur_vs_args->loop_ctrl[idx][0]; + ret[1] = priv->cur_vs_args->loop_ctrl[idx][1]; + /* The step/stride is signed */ + ret[2] = ((char) priv->cur_vs_args->loop_ctrl[idx][2]); + } + else + { + ret[0] = priv->cur_ps_args->loop_ctrl[idx][0]; + ret[1] = priv->cur_ps_args->loop_ctrl[idx][1]; + ret[2] = ((char) priv->cur_ps_args->loop_ctrl[idx][2]); + } + return; + } +} + +static void record_instruction(struct list *list, const struct wined3d_shader_instruction *ins) +{ + unsigned int i; + struct wined3d_shader_dst_param *dst_param = NULL; + struct wined3d_shader_src_param *src_param = NULL, *rel_addr = NULL; + struct recorded_instruction *rec = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rec)); + if(!rec) + { + ERR("Out of memory\n"); + return; + } + + rec->ins = *ins; + dst_param = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_param)); + if(!dst_param) goto free; + *dst_param = *ins->dst; + if(ins->dst->reg.rel_addr) + { + rel_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_param->reg.rel_addr)); + if(!rel_addr) goto free; + *rel_addr = *ins->dst->reg.rel_addr; + dst_param->reg.rel_addr = rel_addr; + } + rec->ins.dst = dst_param; + + src_param = HeapAlloc(GetProcessHeap(), 0, sizeof(*src_param) * ins->src_count); + if(!src_param) goto free; + for(i = 0; i < ins->src_count; i++) + { + src_param[i] = ins->src[i]; + if(ins->src[i].reg.rel_addr) + { + rel_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(*rel_addr)); + if(!rel_addr) goto free; + *rel_addr = *ins->src[i].reg.rel_addr; + src_param[i].reg.rel_addr = rel_addr; + } + } + rec->ins.src = src_param; + list_add_tail(list, &rec->entry); + return; + +free: + ERR("Out of memory\n"); + if(dst_param) + { + HeapFree(GetProcessHeap(), 0, (void *) dst_param->reg.rel_addr); + HeapFree(GetProcessHeap(), 0, dst_param); + } + if(src_param) + { + for(i = 0; i < ins->src_count; i++) + { + HeapFree(GetProcessHeap(), 0, (void *) src_param[i].reg.rel_addr); + } + HeapFree(GetProcessHeap(), 0, src_param); + } + HeapFree(GetProcessHeap(), 0, rec); +} + +static void free_recorded_instruction(struct list *list) +{ + struct recorded_instruction *rec_ins, *entry2; + unsigned int i; + + LIST_FOR_EACH_ENTRY_SAFE(rec_ins, entry2, list, struct recorded_instruction, entry) + { + list_remove(&rec_ins->entry); + if(rec_ins->ins.dst) + { + HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.dst->reg.rel_addr); + HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.dst); + } + if(rec_ins->ins.src) + { + for(i = 0; i < rec_ins->ins.src_count; i++) + { + HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.src[i].reg.rel_addr); + } + HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.src); + } + HeapFree(GetProcessHeap(), 0, rec_ins); + } +} + static void shader_arb_handle_instruction(const struct wined3d_shader_instruction *ins) { SHADER_HANDLER hw_fct; struct shader_arb_ctx_priv *priv = ins->ctx->backend_data; @@ -3249,11 +4396,131 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio struct control_frame *control_frame; SHADER_BUFFER *buffer = ins->ctx->buffer; + if(ins->handler_idx == WINED3DSIH_LOOP || ins->handler_idx == WINED3DSIH_REP) + { + control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame)); + list_add_head(&priv->control_frames, &control_frame->entry); + + if(ins->handler_idx == WINED3DSIH_LOOP) control_frame->type = LOOP; + if(ins->handler_idx == WINED3DSIH_REP) control_frame->type = REP; + + if(priv->target_version >= NV2) + { + control_frame->loop_no = priv->num_loops++; + priv->loop_depth++; + } + else + { + /* Don't bother recording when we're in a not used if branch */ + if(priv->muted) + { + return; + } + + if(!priv->recording) + { + int control_values[3]; + get_int_const(ins, This, ins->src[0].reg.idx, control_values); + list_init(&priv->record); + priv->recording = TRUE; + control_frame->outer_loop = TRUE; + control_frame->loop_control[0] = control_values[0]; + control_frame->loop_control[1] = control_values[1]; + control_frame->loop_control[2] = control_values[2]; + return; /* Instruction is handled */ + } + /* Record this loop in the outer loop's recording */ + } + } + else if(ins->handler_idx == WINED3DSIH_ENDLOOP || ins->handler_idx == WINED3DSIH_ENDREP) + { + if(priv->target_version >= NV2) + { + /* Nothing to do. The control frame is popped after the HW instr handler */ + } + else + { + struct list *e = list_head(&priv->control_frames); + control_frame = LIST_ENTRY(e, struct control_frame, entry); + list_remove(&control_frame->entry); + + if(control_frame->outer_loop) + { + int iteration, aL = 0; + struct list copy; + + /* Turn off recording before playback */ + priv->recording = FALSE; + + /* Move the recorded instructions to a separate list and get them out of the private data + * structure. If there are nested loops, the shader_arb_handle_instruction below will + * be recorded again, thus priv->record might be overwritten + */ + list_init(©); + list_move_tail(©, &priv->record); + list_init(&priv->record); + + if(ins->handler_idx == WINED3DSIH_ENDLOOP) + { + shader_addline(buffer, "#unrolling loop: %d iterations, aL=%d, inc %d\n", + control_frame->loop_control[0], control_frame->loop_control[1], + control_frame->loop_control[2]); + aL = control_frame->loop_control[1]; + } + else + { + shader_addline(buffer, "#unrolling rep: %d iterations\n", control_frame->loop_control[0]); + } + + for(iteration = 0; iteration < control_frame->loop_control[0]; iteration++) + { + struct recorded_instruction *rec_ins; + if(ins->handler_idx == WINED3DSIH_ENDLOOP) + { + priv->aL = aL; + shader_addline(buffer, "#Iteration %d, aL=%d\n", iteration, aL); + } + else + { + shader_addline(buffer, "#Iteration %d\n", iteration); + } + + LIST_FOR_EACH_ENTRY(rec_ins, ©, struct recorded_instruction, entry) + { + shader_arb_handle_instruction(&rec_ins->ins); + } + + if(ins->handler_idx == WINED3DSIH_ENDLOOP) + { + aL += control_frame->loop_control[2]; + } + } + shader_addline(buffer, "#end loop/rep\n"); + + free_recorded_instruction(©); + HeapFree(GetProcessHeap(), 0, control_frame); + return; /* Instruction is handled */ + } + else + { + /* This is a nested loop. Proceed to the normal recording function */ + HeapFree(GetProcessHeap(), 0, control_frame); + } + } + } + + if(priv->recording) + { + record_instruction(&priv->record, ins); + return; + } + /* boolean if */ if(ins->handler_idx == WINED3DSIH_IF) { control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame)); list_add_head(&priv->control_frames, &control_frame->entry); + control_frame->type = IF; if(!priv->muted && get_bool_const(ins, This, ins->src[0].reg.idx) == FALSE) { @@ -3269,7 +4536,8 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio { /* IF(bool) and if_cond(a, b) use the same ELSE and ENDIF tokens */ control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame)); - control_frame->ifc = TRUE; + control_frame->type = IFC; + control_frame->ifc_no = priv->num_ifcs++; list_add_head(&priv->control_frames, &control_frame->entry); } else if(ins->handler_idx == WINED3DSIH_ELSE) @@ -3277,7 +4545,7 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio struct list *e = list_head(&priv->control_frames); control_frame = LIST_ENTRY(e, struct control_frame, entry); - if(control_frame->ifc == FALSE) + if(control_frame->type == IF) { shader_addline(buffer, "#} else {\n"); if(!priv->muted && !control_frame->muting) @@ -3295,7 +4563,7 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio struct list *e = list_head(&priv->control_frames); control_frame = LIST_ENTRY(e, struct control_frame, entry); - if(!control_frame->ifc) + if(control_frame->type == IF) { shader_addline(buffer, "#} endif\n"); if(control_frame->muting) priv->muted = FALSE; @@ -3303,20 +4571,6 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio HeapFree(GetProcessHeap(), 0, control_frame); return; /* Instruction is handled */ } - else - { - list_remove(&control_frame->entry); - HeapFree(GetProcessHeap(), 0, control_frame); - /* ifc - generate a hw endif */ - } - } - else if(ins->handler_idx == WINED3DSIH_LOOP || ins->handler_idx == WINED3DSIH_REP) - { - control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame)); - list_add_head(&priv->control_frames, &control_frame->entry); - - control_frame->loop_no = priv->num_loops++; - priv->loop_depth++; } if(priv->muted) return; @@ -3340,6 +4594,15 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio HeapFree(GetProcessHeap(), 0, control_frame); priv->loop_depth--; } + else if(ins->handler_idx == WINED3DSIH_ENDIF) + { + /* Non-ifc ENDIFs don't reach that place because of the return in the if block above */ + struct list *e = list_head(&priv->control_frames); + control_frame = LIST_ENTRY(e, struct control_frame, entry); + list_remove(&control_frame->entry); + HeapFree(GetProcessHeap(), 0, control_frame); + } + shader_arb_add_instruction_modifiers(ins); } @@ -3816,6 +5079,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi BOOL tempreg_used = FALSE, tfactor_used = FALSE; BOOL op_equal; const char *final_combiner_src = "ret"; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; /* Find out which textures are read */ for(stage = 0; stage < MAX_TEXTURES; stage++) { @@ -3906,6 +5170,8 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi srgb_sub_high, 0.0, 0.0, 0.0); } + if(ffp_clip_emul(stateblock) && device->vs_clipping) shader_addline(&buffer, "KIL fragment.texcoord[7];\n"); + /* Generate texture sampling instructions) */ for(stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3DTOP_DISABLE; stage++) { if(!tex_read[stage]) continue; diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 1a34fa2e9db..d1c8a4bb0a6 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -287,6 +287,7 @@ static void shader_record_register_usage(IWineD3DBaseShaderImpl *This, struct sh case WINED3DSPR_MISCTYPE: if (pshader && reg->idx == 0) reg_maps->vpos = 1; + if (pshader && reg->idx == 1) reg_maps->usesfacing = 1; break; case WINED3DSPR_CONST: @@ -530,6 +531,7 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 pToken += 4; list_add_head(&This->baseShader.constantsI, &lconst->entry); + reg_maps->local_int_consts |= (1 << dst.reg.idx); } else if (ins.handler_idx == WINED3DSIH_DEFB) { @@ -691,6 +693,10 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3 { reg_maps->usestexldd = 1; } + else if(ins.handler_idx == WINED3DSIH_TEXLDL) + { + reg_maps->usestexldl = 1; + } else if(ins.handler_idx == WINED3DSIH_MOVA) { reg_maps->usesmova = 1; diff --git a/dlls/wined3d/basetexture.c b/dlls/wined3d/basetexture.c index aeec963e170..547ed1e1bb1 100644 --- a/dlls/wined3d/basetexture.c +++ b/dlls/wined3d/basetexture.c @@ -53,19 +53,7 @@ HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DR void basetexture_cleanup(IWineD3DBaseTexture *iface) { - IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - - TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName); - if (This->baseTexture.textureName != 0) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName); - glDeleteTextures(1, &This->baseTexture.textureName); - glDeleteTextures(1, &This->baseTexture.srgbTextureName); - LEAVE_GL(); - } - + basetexture_unload(iface); resource_cleanup((IWineD3DResource *)iface); } @@ -78,8 +66,14 @@ void basetexture_unload(IWineD3DBaseTexture *iface) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); ENTER_GL(); glDeleteTextures(1, &This->baseTexture.textureName); - glDeleteTextures(1, &This->baseTexture.srgbTextureName); This->baseTexture.textureName = 0; + LEAVE_GL(); + } + + if(This->baseTexture.srgbTextureName) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + glDeleteTextures(1, &This->baseTexture.srgbTextureName); This->baseTexture.srgbTextureName = 0; LEAVE_GL(); } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index df55962e888..04a453ee6d0 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -895,156 +895,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UI WINED3DSURFTYPE Impl, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */ - unsigned int Size = 1; - const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(Format, &GLINFO_LOCATION); + IWineD3DSurfaceImpl *object; HRESULT hr; TRACE("(%p) Create surface\n",This); - if(MultisampleQuality > 0) { - FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality); - MultisampleQuality=0; - } - - /** FIXME: Check that the format is supported - * by the device. - *******************************/ - - if (WINED3DFMT_UNKNOWN == Format) { - Size = 0; - } - else if (glDesc->Flags & WINED3DFMT_FLAG_COMPRESSED) - { - UINT row_block_count = (Width + glDesc->block_width - 1) / glDesc->block_width; - UINT row_count = (Height + glDesc->block_height - 1) / glDesc->block_height; - Size = row_count * row_block_count * glDesc->block_byte_count; - } - else + if (Impl == SURFACE_OPENGL && !This->adapter) { - /* The pitch is a multiple of 4 bytes */ - Size = ((Width * glDesc->byte_count) + This->surface_alignment - 1) & ~(This->surface_alignment - 1); - Size *= Height; + ERR("OpenGL surfaces are not available without OpenGL.\n"); + return WINED3DERR_NOTAVAILABLE; } - if(glDesc->heightscale != 0.0) Size *= glDesc->heightscale; - - /** Create and initialise the surface resource **/ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) { - ERR("Out of memory\n"); + ERR("Failed to allocate surface memory.\n"); *ppSurface = NULL; return WINED3DERR_OUTOFVIDEOMEMORY; } - /* Look at the implementation and set the correct Vtable */ - switch(Impl) - { - case SURFACE_OPENGL: - /* Check if a 3D adapter is available when creating gl surfaces */ - if (!This->adapter) - { - ERR("OpenGL surfaces are not available without opengl\n"); - HeapFree(GetProcessHeap(), 0, object); - return WINED3DERR_NOTAVAILABLE; - } - object->lpVtbl = &IWineD3DSurface_Vtbl; - break; - - case SURFACE_GDI: - object->lpVtbl = &IWineGDISurface_Vtbl; - break; - - default: - /* To be sure to catch this */ - ERR("Unknown requested surface implementation %d!\n", Impl); - HeapFree(GetProcessHeap(), 0, object); - return WINED3DERR_INVALIDCALL; - } - - hr = resource_init((IWineD3DResource *)object, WINED3DRTYPE_SURFACE, This, Size, Usage, glDesc, Pool, parent); + hr = surface_init(object, Impl, This->surface_alignment, Width, Height, Level, Lockable, + Discard, MultiSample, MultisampleQuality, This, Usage, Format, Pool, parent); if (FAILED(hr)) { - WARN("Failed to initialize resource, returning %#x\n", hr); + WARN("Failed to initialize surface, returning %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); *ppSurface = NULL; return hr; } - TRACE("(%p) : Created resource %p\n", This, object); + TRACE("(%p) : Created surface %p\n", This, object); *ppSurface = (IWineD3DSurface *)object; - /* "Standalone" surface */ - IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL); - - object->currentDesc.Width = Width; - object->currentDesc.Height = Height; - object->currentDesc.MultiSampleType = MultiSample; - object->currentDesc.MultiSampleQuality = MultisampleQuality; - object->glDescription.level = Level; - list_init(&object->overlays); - - /* Flags */ - object->Flags = SFLAG_NORMCOORD; /* Default to normalized coords */ - object->Flags |= Discard ? SFLAG_DISCARD : 0; - object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0; - object->Flags |= Lockable ? SFLAG_LOCKABLE : 0; - - TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM); - - /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly - * this function is too deep to need to care about things like this. - * Levels need to be checked too, and possibly Type since they all affect what can be done. - * ****************************************/ - switch(Pool) { - case WINED3DPOOL_SCRATCH: - if(!Lockable) - FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE " - "which are mutually exclusive, setting lockable to TRUE\n"); - Lockable = TRUE; - break; - case WINED3DPOOL_SYSTEMMEM: - if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, " - "this is acceptable but unexpected (I can't know how the surface can be usable!)\n"); - case WINED3DPOOL_MANAGED: - if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a " - "Usage of DYNAMIC which are mutually exclusive, not doing " - "anything just telling you.\n"); - break; - case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */ - if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET) - && !(Usage & WINED3DUSAGE_DEPTHSTENCIL ) && Lockable) - WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n"); - break; - default: - FIXME("(%p) Unknown pool %d\n", This, Pool); - break; - }; - - if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) { - FIXME("Trying to create a render target that isn't in the default pool\n"); - } - - /* mark the texture as dirty so that it gets loaded first time around*/ - surface_add_dirty_rect(*ppSurface, NULL); - TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", - This, Width, Height, Format, debug_d3dformat(Format), - (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size); - - list_init(&object->renderbuffers); - - /* Call the private setup routine */ - hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)object); - if (FAILED(hr)) - { - ERR("Private setup failed, returning %#x\n", hr); - IWineD3DSurface_Release(*ppSurface); - *ppSurface = NULL; - return hr; - } - return hr; } @@ -3064,9 +2947,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D struct list *e; TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable); - /* Tests show true = 128...not clear why */ - Enable = Enable? 128: 0; - LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) { lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry); if(lightInfo->OriginalIndex == Index) break; @@ -5865,21 +5745,19 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, WINED3DSURFACE_DESC winedesc; TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint); - memset(&winedesc, 0, sizeof(winedesc)); - winedesc.Width = &srcSurfaceWidth; - winedesc.Height = &srcSurfaceHeight; - winedesc.Pool = &srcPool; - winedesc.Format = &srcFormat; IWineD3DSurface_GetDesc(pSourceSurface, &winedesc); - - winedesc.Width = &destSurfaceWidth; - winedesc.Height = &destSurfaceHeight; - winedesc.Pool = &destPool; - winedesc.Format = &destFormat; - winedesc.Size = &destSize; + srcSurfaceWidth = winedesc.width; + srcSurfaceHeight = winedesc.height; + srcPool = winedesc.pool; + srcFormat = winedesc.format; IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc); + destSurfaceWidth = winedesc.width; + destSurfaceHeight = winedesc.height; + destPool = winedesc.pool; + destFormat = winedesc.format; + destSize = winedesc.size; if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){ WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface); @@ -6551,11 +6429,16 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED /* Attach src surface to src fbo */ src_swapchain = get_swapchain(src_surface); + dst_swapchain = get_swapchain(dst_surface); + + if (src_swapchain) ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD); + else if (dst_swapchain) ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD); + else ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + if (src_swapchain) { GLenum buffer = surface_get_gl_buffer(src_surface, src_swapchain); TRACE("Source surface %p is onscreen\n", src_surface); - ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD); /* Make sure the drawable is up to date. In the offscreen case * attach_surface_fbo() implicitly takes care of this. */ IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL); @@ -6590,12 +6473,10 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED LEAVE_GL(); /* Attach dst surface to dst fbo */ - dst_swapchain = get_swapchain(dst_surface); if (dst_swapchain) { GLenum buffer = surface_get_gl_buffer(dst_surface, dst_swapchain); TRACE("Destination surface %p is onscreen\n", dst_surface); - ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD); /* Make sure the drawable is up to date. In the offscreen case * attach_surface_fbo() implicitly takes care of this. */ IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL); @@ -6622,11 +6503,6 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED } else { TRACE("Destination surface %p is offscreen\n", dst_surface); - /* No src or dst swapchain? Make sure some context is active(multithreading) */ - if(!src_swapchain) { - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } - ENTER_GL(); context_bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->activeContext->dst_fbo); context_attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface); @@ -6980,14 +6856,21 @@ static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* return WINED3DERR_DRIVERINTERNALERROR; } +static HRESULT WINAPI evict_managed_resource(IWineD3DResource *resource, void *data) { + TRACE("checking resource %p for eviction\n", resource); + if(((IWineD3DResourceImpl *) resource)->resource.pool == WINED3DPOOL_MANAGED) { + TRACE("Evicting %p\n", resource); + IWineD3DResource_UnLoad(resource); + } + IWineD3DResource_Release(resource); + return S_OK; +} static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - /** FIXME: Resource tracking needs to be done, - * The closes we can do to this is set the priorities of all managed textures low - * and then reset them. - ***********************************************************/ - FIXME("(%p) : stub\n", This); + TRACE("(%p)\n", This); + + IWineD3DDevice_EnumResources(iface, evict_managed_resource, NULL); return WINED3D_OK; } diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 05443fc8215..28f07efabff 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1031,8 +1031,8 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { /* We can only use ORM_FBO when the hardware supports it. */ if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) { - WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n"); - wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER; + WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to backbuffer offscreen rendering mode.\n"); + wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER; } /* MRTs are currently only supported when FBOs are used. */ @@ -1272,16 +1272,43 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { } break; case VENDOR_ATI: + /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx + * + * beware: renderer string do not match exact card model, + * eg HD 4800 is returned for multiple card, even for RV790 based one + */ if(WINE_D3D9_CAPABLE(gl_info)) { /* Radeon R7xx HD4800 - highend */ - if (strstr(gl_info->gl_renderer, "HD 4800") || - strstr(gl_info->gl_renderer, "HD 4830") || - strstr(gl_info->gl_renderer, "HD 4850") || - strstr(gl_info->gl_renderer, "HD 4870") || - strstr(gl_info->gl_renderer, "HD 4890")) + if (strstr(gl_info->gl_renderer, "HD 4800") || /* Radeon RV7xx HD48xx generic renderer string */ + strstr(gl_info->gl_renderer, "HD 4830") || /* Radeon RV770 */ + strstr(gl_info->gl_renderer, "HD 4850") || /* Radeon RV770 */ + strstr(gl_info->gl_renderer, "HD 4870") || /* Radeon RV770 */ + strstr(gl_info->gl_renderer, "HD 4890")) /* Radeon RV790 */ { gl_info->gl_card = CARD_ATI_RADEON_HD4800; - vidmem = 512; /* HD4800 cards use 512-1024MB */ + vidmem = 512; /* note: HD4890 cards use 1024MB */ + } + /* Radeon R740 HD4700 - midend */ + else if (strstr(gl_info->gl_renderer, "HD 4700") || /* Radeon RV770 */ + strstr(gl_info->gl_renderer, "HD 4770")) /* Radeon RV740 */ + { + gl_info->gl_card = CARD_ATI_RADEON_HD4700; + vidmem = 512; + } + /* Radeon R730 HD4600 - midend */ + else if (strstr(gl_info->gl_renderer, "HD 4600") || /* Radeon RV730 */ + strstr(gl_info->gl_renderer, "HD 4650") || /* Radeon RV730 */ + strstr(gl_info->gl_renderer, "HD 4670")) /* Radeon RV730 */ + { + gl_info->gl_card = CARD_ATI_RADEON_HD4600; + vidmem = 512; + } + /* Radeon R710 HD4500/HD4350 - lowend */ + else if (strstr(gl_info->gl_renderer, "HD 4350") || /* Radeon RV710 */ + strstr(gl_info->gl_renderer, "HD 4550")) /* Radeon RV710 */ + { + gl_info->gl_card = CARD_ATI_RADEON_HD4350; + vidmem = 256; } /* Radeon R6xx HD2900/HD3800 - highend */ else if (strstr(gl_info->gl_renderer, "HD 2900") || @@ -1305,7 +1332,8 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { strstr(gl_info->gl_renderer, "HD 2400") || strstr(gl_info->gl_renderer, "HD 3470") || strstr(gl_info->gl_renderer, "HD 3450") || - strstr(gl_info->gl_renderer, "HD 3430")) + strstr(gl_info->gl_renderer, "HD 3430") || + strstr(gl_info->gl_renderer, "HD 3400")) { gl_info->gl_card = CARD_ATI_RADEON_HD2300; vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */ @@ -4023,6 +4051,9 @@ static const struct driver_version_information driver_version_table[] = { {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 }, {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 }, {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 6, 14, 10, 6764 }, {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 }, /* TODO: Add information about legacy ATI hardware, Intel and other cards */ diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index c92659faf8c..c644aa20d32 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -558,12 +558,17 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice if (!index_count) return; - /* Invalidate the back buffer memory so LockRect will read it the next time */ - for(i = 0; i < GL_LIMITS(buffers); i++) { - target = (IWineD3DSurfaceImpl *) This->render_targets[i]; - if (target) { - IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, TRUE); + if (This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE]) + { + /* Invalidate the back buffer memory so LockRect will read it the next time */ + for (i = 0; i < GL_LIMITS(buffers); ++i) + { + target = (IWineD3DSurfaceImpl *)This->render_targets[i]; + if (target) + { + IWineD3DSurface_LoadLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, NULL); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE); + } } } @@ -574,10 +579,16 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice if (This->stencilBufferTarget) { /* Note that this depends on the ActivateContext call above to set - * This->render_offscreen properly */ + * This->render_offscreen properly. We don't currently take the + * Z-compare function into account, but we could skip loading the + * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note + * that we never copy the stencil data.*/ DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; - surface_load_ds_location(This->stencilBufferTarget, location); - surface_modify_ds_location(This->stencilBufferTarget, location); + if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE] + || This->stateBlock->renderState[WINED3DRS_ZENABLE]) + surface_load_ds_location(This->stencilBufferTarget, location); + if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE]) + surface_modify_ds_location(This->stencilBufferTarget, location); } /* Ok, we will be updating the screen from here onwards so grab the lock */ diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 846044f7a8a..e065296d88d 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3423,7 +3423,8 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_in * input varyings are assigned above, if the optimizer works properly. */ for(i = 0; i < in_count + 2; i++) { - if(set[i] != WINED3DSP_WRITEMASK_ALL) { + if (set[i] && set[i] != WINED3DSP_WRITEMASK_ALL) + { unsigned int size = 0; memset(reg_mask, 0, sizeof(reg_mask)); if(!(set[i] & WINED3DSP_WRITEMASK_0)) { diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 1c9b5a8db9f..a8e53f09fc0 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -1087,9 +1087,6 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat unsigned int i; IWineD3DSwapChain *swapchain; IWineD3DSurface *backbuffer; - WINED3DSURFACE_DESC desc = {0}; - UINT width, height; - RECT scissorrect; HRESULT hr; /* Note this may have a large overhead but it should only be executed @@ -1292,28 +1289,27 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat This->textures[i] = NULL; } - /* Set the default scissor rect values */ - desc.Width = &width; - desc.Height = &height; - /* check the return values, because the GetBackBuffer call isn't valid for ddraw */ hr = IWineD3DDevice_GetSwapChain(device, 0, &swapchain); if( hr == WINED3D_OK && swapchain != NULL) { WINED3DVIEWPORT vp; hr = IWineD3DSwapChain_GetBackBuffer(swapchain, 0, WINED3DBACKBUFFER_TYPE_MONO, &backbuffer); - if( hr == WINED3D_OK && backbuffer != NULL) { + if (SUCCEEDED(hr) && backbuffer) + { + WINED3DSURFACE_DESC desc; + RECT scissorrect; + IWineD3DSurface_GetDesc(backbuffer, &desc); IWineD3DSurface_Release(backbuffer); + /* Set the default scissor rect values */ scissorrect.left = 0; - scissorrect.right = width; + scissorrect.right = desc.width; scissorrect.top = 0; - scissorrect.bottom = height; + scissorrect.bottom = desc.height; hr = IWineD3DDevice_SetScissorRect(device, &scissorrect); - if( hr != WINED3D_OK ) { - ERR("This should never happen, expect rendering issues!\n"); - } + if (FAILED(hr)) ERR("This should never happen, expect rendering issues!\n"); } /* Set the default viewport */ diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 116cff09186..c6eaa69168f 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -32,7 +32,212 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); WINE_DECLARE_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + +#define GLINFO_LOCATION (*gl_info) + +static void surface_cleanup(IWineD3DSurfaceImpl *This) +{ + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + const WineD3D_GL_Info *gl_info = &device->adapter->gl_info; + renderbuffer_entry_t *entry, *entry2; + + TRACE("(%p) : Cleaning up.\n", This); + + /* Need a context to destroy the texture. Use the currently active render + * target, but only if the primary render target exists. Otherwise + * lastActiveRenderTarget is garbage. When destroying the primary render + * target, Uninit3D() will activate a context before doing anything. */ + if (device->render_targets && device->render_targets[0]) + { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } + + ENTER_GL(); + + if (This->glDescription.textureName) + { + /* Release the OpenGL texture. */ + TRACE("Deleting texture %u.\n", This->glDescription.textureName); + glDeleteTextures(1, &This->glDescription.textureName); + } + + if (This->Flags & SFLAG_PBO) + { + /* Delete the PBO. */ + GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo)); + } + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) + { + GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id)); + HeapFree(GetProcessHeap(), 0, entry); + } + + LEAVE_GL(); + + if (This->Flags & SFLAG_DIBSECTION) + { + /* Release the DC. */ + SelectObject(This->hDC, This->dib.holdbitmap); + DeleteDC(This->hDC); + /* Release the DIB section. */ + DeleteObject(This->dib.DIBsection); + This->dib.bitmap_data = NULL; + This->resource.allocatedMemory = NULL; + } + + if (This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem((IWineD3DSurface *)This, NULL); + if (This->overlay_dest) list_remove(&This->overlay_entry); + + HeapFree(GetProcessHeap(), 0, This->palette9); + + resource_cleanup((IWineD3DResource *)This); +} + +UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT alignment, UINT width, UINT height) +{ + UINT size; + + if (format_desc->format == WINED3DFMT_UNKNOWN) + { + size = 0; + } + else if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) + { + UINT row_block_count = (width + format_desc->block_width - 1) / format_desc->block_width; + UINT row_count = (height + format_desc->block_height - 1) / format_desc->block_height; + size = row_count * row_block_count * format_desc->block_byte_count; + } + else + { + /* The pitch is a multiple of 4 bytes. */ + size = height * (((width * format_desc->byte_count) + alignment - 1) & ~(alignment - 1)); + } + + if (format_desc->heightscale != 0.0) size *= format_desc->heightscale; + + return size; +} + +HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment, + UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type, + UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, + WINED3DPOOL pool, IUnknown *parent) +{ + const WineD3D_GL_Info *gl_info = &device->adapter->gl_info; + const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, &GLINFO_LOCATION); + void (*cleanup)(IWineD3DSurfaceImpl *This); + unsigned int resource_size; + HRESULT hr; + + if (multisample_quality > 0) + { + FIXME("multisample_quality set to %u, substituting 0\n", multisample_quality); + multisample_quality = 0; + } + + /* FIXME: Check that the format is supported by the device. */ + + resource_size = surface_calculate_size(format_desc, alignment, width, height); + + /* Look at the implementation and set the correct Vtable. */ + switch (surface_type) + { + case SURFACE_OPENGL: + surface->lpVtbl = &IWineD3DSurface_Vtbl; + cleanup = surface_cleanup; + break; + + case SURFACE_GDI: + surface->lpVtbl = &IWineGDISurface_Vtbl; + cleanup = surface_gdi_cleanup; + break; + + default: + ERR("Requested unknown surface implementation %#x.\n", surface_type); + return WINED3DERR_INVALIDCALL; + } + + hr = resource_init((IWineD3DResource *)surface, WINED3DRTYPE_SURFACE, + device, resource_size, usage, format_desc, pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x.\n", hr); + return hr; + } + + /* "Standalone" surface. */ + IWineD3DSurface_SetContainer((IWineD3DSurface *)surface, NULL); + + surface->currentDesc.Width = width; + surface->currentDesc.Height = height; + surface->currentDesc.MultiSampleType = multisample_type; + surface->currentDesc.MultiSampleQuality = multisample_quality; + surface->glDescription.level = level; + list_init(&surface->overlays); + + /* Flags */ + surface->Flags = SFLAG_NORMCOORD; /* Default to normalized coords. */ + if (discard) surface->Flags |= SFLAG_DISCARD; + if (lockable || format == WINED3DFMT_D16_LOCKABLE) surface->Flags |= SFLAG_LOCKABLE; + + /* Quick lockable sanity check. + * TODO: remove this after surfaces, usage and lockability have been debugged properly + * this function is too deep to need to care about things like this. + * Levels need to be checked too, since they all affect what can be done. */ + switch (pool) + { + case WINED3DPOOL_SCRATCH: + if(!lockable) + { + FIXME("Called with a pool of SCRATCH and a lockable of FALSE " + "which are mutually exclusive, setting lockable to TRUE.\n"); + lockable = TRUE; + } + break; + + case WINED3DPOOL_SYSTEMMEM: + if (!lockable) + FIXME("Called with a pool of SYSTEMMEM and a lockable of FALSE, this is acceptable but unexpected.\n"); + break; + + case WINED3DPOOL_MANAGED: + if (usage & WINED3DUSAGE_DYNAMIC) + FIXME("Called with a pool of MANAGED and a usage of DYNAMIC which are mutually exclusive.\n"); + break; + + case WINED3DPOOL_DEFAULT: + if (lockable && !(usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) + WARN("Creating a lockable surface with a POOL of DEFAULT, that doesn't specify DYNAMIC usage.\n"); + break; + + default: + FIXME("Unknown pool %#x.\n", pool); + break; + }; + + if (usage & WINED3DUSAGE_RENDERTARGET && pool != WINED3DPOOL_DEFAULT) + { + FIXME("Trying to create a render target that isn't in the default pool.\n"); + } + + /* Mark the texture as dirty so that it gets loaded first time around. */ + surface_add_dirty_rect((IWineD3DSurface *)surface, NULL); + list_init(&surface->renderbuffers); + + TRACE("surface %p, memory %p, size %u\n", surface, surface->resource.allocatedMemory, surface->resource.size); + + /* Call the private setup routine */ + hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)surface); + if (FAILED(hr)) + { + ERR("Private setup failed, returning %#x\n", hr); + cleanup(surface); + return hr; + } + + return hr; +} static void surface_force_reload(IWineD3DSurface *iface) { @@ -132,6 +337,10 @@ static BOOL primary_render_target_is_p8(IWineD3DDeviceImpl *device) return FALSE; } +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info + /* This call just downloads data, the caller is responsible for activating the * right context and binding the correct texture. */ static void surface_download_data(IWineD3DSurfaceImpl *This) { @@ -540,59 +749,15 @@ static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; ULONG ref = InterlockedDecrement(&This->resource.ref); TRACE("(%p) : Releasing from %d\n", This, ref + 1); - if (ref == 0) { - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - renderbuffer_entry_t *entry, *entry2; - TRACE("(%p) : cleaning up\n", This); - /* Need a context to destroy the texture. Use the currently active render target, but only if - * the primary render target exists. Otherwise lastActiveRenderTarget is garbage, see above. - * When destroying the primary rt, Uninit3D will activate a context before doing anything - */ - if(device->render_targets && device->render_targets[0]) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - } - - ENTER_GL(); - if (This->glDescription.textureName != 0) { /* release the openGL texture.. */ - TRACE("Deleting texture %d\n", This->glDescription.textureName); - glDeleteTextures(1, &This->glDescription.textureName); - } - - if(This->Flags & SFLAG_PBO) { - /* Delete the PBO */ - GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo)); - } - - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) { - GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id)); - HeapFree(GetProcessHeap(), 0, entry); - } - LEAVE_GL(); - - if(This->Flags & SFLAG_DIBSECTION) { - /* Release the DC */ - SelectObject(This->hDC, This->dib.holdbitmap); - DeleteDC(This->hDC); - /* Release the DIB section */ - DeleteObject(This->dib.DIBsection); - This->dib.bitmap_data = NULL; - This->resource.allocatedMemory = NULL; - } - if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL); - - HeapFree(GetProcessHeap(), 0, This->palette9); - - resource_cleanup((IWineD3DResource *)iface); - - if(This->overlay_dest) { - list_remove(&This->overlay_entry); - } + if (!ref) + { + surface_cleanup(This); - TRACE("(%p) Released\n", This); + TRACE("(%p) Released.\n", This); HeapFree(GetProcessHeap(), 0, This); - } + return ref; } @@ -727,6 +892,8 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { ENTER_GL(); glDeleteTextures(1, &This->glDescription.textureName); This->glDescription.textureName = 0; + glDeleteTextures(1, &This->glDescription.srgbTextureName); + This->glDescription.srgbTextureName = 0; LEAVE_GL(); } else { IWineD3DBaseTexture_Release(texture); @@ -1129,6 +1296,7 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; + const RECT *pass_rect = pRect; TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory); @@ -1161,72 +1329,19 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED goto lock_end; } - /* Now download the surface content from opengl - * Use the render target readback if the surface is on a swapchain(=onscreen render target) or the current primary target - * Offscreen targets which are not active at the moment or are higher targets(FBOs) can be locked with the texture path - */ - if ((This->Flags & SFLAG_SWAPCHAIN) || iface == myDevice->render_targets[0]) + /* IWineD3DSurface_LoadLocation() does not check if the rectangle specifies + * the full surface. Most callers don't need that, so do it here. */ + if (pRect && pRect->top == 0 && pRect->left == 0 + && pRect->right == This->currentDesc.Width + && pRect->bottom == This->currentDesc.Height) { - const RECT *pass_rect = pRect; - - /* IWineD3DSurface_LoadLocation does not check if the rectangle specifies the full surfaces - * because most caller functions do not need that. So do that here - */ - if(pRect && - pRect->top == 0 && - pRect->left == 0 && - pRect->right == This->currentDesc.Width && - pRect->bottom == This->currentDesc.Height) { - pass_rect = NULL; - } - - switch(wined3d_settings.rendertargetlock_mode) { - case RTL_TEXDRAW: - case RTL_TEXTEX: - FIXME("Reading from render target with a texture isn't implemented yet, falling back to framebuffer reading\n"); -#if 0 - /* Disabled for now. LoadLocation prefers the texture over the drawable as the source. So if we copy to the - * texture first, then to sysmem, we'll avoid glReadPixels and use glCopyTexImage and glGetTexImage2D instead. - * This may be faster on some cards - */ - IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* No partial texture copy yet */); -#endif - /* drop through */ - - case RTL_AUTO: - case RTL_READDRAW: - case RTL_READTEX: - IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, pass_rect); - break; + pass_rect = NULL; + } - case RTL_DISABLE: - break; - } - } else if(iface == myDevice->stencilBufferTarget) { - /** the depth stencil in openGL has a format of GL_FLOAT - * which should be good for WINED3DFMT_D16_LOCKABLE - * and WINED3DFMT_D16 - * it is unclear what format the stencil buffer is in except. - * 'Each index is converted to fixed point... - * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their - * mappings in the table GL_PIXEL_MAP_S_TO_S. - * glReadPixels(This->lockedRect.left, - * This->lockedRect.bottom - j - 1, - * This->lockedRect.right - This->lockedRect.left, - * 1, - * GL_DEPTH_COMPONENT, - * type, - * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top))); - * - * Depth Stencil surfaces which are not the current depth stencil target should have their data in a - * gl texture(next path), or in local memory(early return because of set SFLAG_INSYSMEM above). If - * none of that is the case the problem is not in this function :-) - ********************************************/ - FIXME("Depth stencil locking not supported yet\n"); - } else { - /* This path is for normal surfaces, offscreen render targets and everything else that is in a gl texture */ - TRACE("locking an ordinary surface\n"); - IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */); + if (!(wined3d_settings.rendertargetlock_mode == RTL_DISABLE + && ((This->Flags & SFLAG_SWAPCHAIN) || iface == myDevice->render_targets[0]))) + { + IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, pass_rect); } lock_end: @@ -1433,7 +1548,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { switch(wined3d_settings.rendertargetlock_mode) { case RTL_READTEX: case RTL_TEXTEX: - ActivateContext(myDevice, iface, CTXUSAGE_BLIT); IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* partial texture loading not supported yet */); /* drop through */ @@ -1810,6 +1924,29 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ *target_bpp = 12; break; + case WINED3DFMT_D15S1: + if (GL_SUPPORT(EXT_PACKED_DEPTH_STENCIL)) + { + *convert = CONVERT_D15S1; + *target_bpp = 4; + } + break; + + case WINED3DFMT_D24X4S4: + if (GL_SUPPORT(EXT_PACKED_DEPTH_STENCIL)) + { + *convert = CONVERT_D24X4S4; + } + break; + + case WINED3DFMT_D24FS8: + if (GL_SUPPORT(ARB_DEPTH_BUFFER_FLOAT)) + { + *convert = CONVERT_D24FS8; + *target_bpp = 8; + } + break; + default: break; } @@ -2262,8 +2399,67 @@ static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UI break; } + case CONVERT_D15S1: + { + unsigned int x, y; + + for (y = 0; y < height; ++y) + { + const WORD *source = (const WORD *)(src + y * pitch); + DWORD *dest = (DWORD *)(dst + y * outpitch); + + for (x = 0; x < width; ++x) + { + /* The depth data is normalized, so needs to be scaled, + * the stencil data isn't. Scale depth data by + * (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */ + WORD d15 = source[x] >> 1; + DWORD d24 = (d15 << 9) + (d15 >> 6); + dest[x] = (d24 << 8) | (source[x] & 0x1); + } + } + break; + } + + case CONVERT_D24X4S4: + { + unsigned int x, y; + + for (y = 0; y < height; ++y) + { + const DWORD *source = (const DWORD *)(src + y * pitch); + DWORD *dest = (DWORD *)(dst + y * outpitch); + + for (x = 0; x < width; ++x) + { + /* Just need to clear out the X4 part. */ + dest[x] = source[x] & ~0xf0; + } + } + break; + } + + case CONVERT_D24FS8: + { + unsigned int x, y; + + for (y = 0; y < height; ++y) + { + const DWORD *source = (const DWORD *)(src + y * pitch); + float *dest_f = (float *)(dst + y * outpitch); + DWORD *dest_s = (DWORD *)(dst + y * outpitch); + + for (x = 0; x < width; ++x) + { + dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8); + dest_s[x * 2 + 1] = source[x] & 0xff; + } + } + break; + } + default: - ERR("Unsupported conversation type %d\n", convert); + ERR("Unsupported conversion type %#x.\n", convert); } return WINED3D_OK; } @@ -4599,6 +4795,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D surface_download_data(This); } else { + /* Note: It might be faster to download into a texture first. */ read_from_framebuffer(This, rect, This->resource.allocatedMemory, IWineD3DSurface_GetPitch(iface)); diff --git a/dlls/wined3d/surface_base.c b/dlls/wined3d/surface_base.c index e17f89253dd..d776785a018 100644 --- a/dlls/wined3d/surface_base.c +++ b/dlls/wined3d/surface_base.c @@ -181,15 +181,17 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSU IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; TRACE("(%p) : copying into %p\n", This, pDesc); - if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format_desc->format; - if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType; - if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage; - if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool; - if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */ - if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType; - if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality; - if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width; - if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height; + + pDesc->format = This->resource.format_desc->format; + pDesc->resource_type = This->resource.resourceType; + pDesc->usage = This->resource.usage; + pDesc->pool = This->resource.pool; + pDesc->size = This->resource.size; /* dx8 only */ + pDesc->multisample_type = This->currentDesc.MultiSampleType; + pDesc->multisample_quality = This->currentDesc.MultiSampleQuality; + pDesc->width = This->currentDesc.Width; + pDesc->height = This->currentDesc.Height; + return WINED3D_OK; } @@ -519,21 +521,9 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3D } TRACE("(%p) : Setting texture format to (%d,%s)\n", This, format, debug_d3dformat(format)); - if (format == WINED3DFMT_UNKNOWN) { - This->resource.size = 0; - } - else if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED) - { - UINT row_block_count = (This->pow2Width + format_desc->block_width - 1) / format_desc->block_width; - UINT row_count = (This->pow2Height + format_desc->block_height - 1) / format_desc->block_height; - This->resource.size = row_count * row_block_count * format_desc->block_byte_count; - } - else - { - unsigned char alignment = This->resource.wineD3DDevice->surface_alignment; - This->resource.size = ((This->pow2Width * format_desc->byte_count) + alignment - 1) & ~(alignment - 1); - This->resource.size *= This->pow2Height; - } + + This->resource.size = surface_calculate_size(format_desc, This->resource.wineD3DDevice->surface_alignment, + This->pow2Width, This->pow2Height); This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0; diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c index 0ad65e01a98..a1945691e6d 100644 --- a/dlls/wined3d/surface_gdi.c +++ b/dlls/wined3d/surface_gdi.c @@ -35,6 +35,29 @@ /* Use the d3d_surface debug channel to have one channel for all surfaces */ WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); +void surface_gdi_cleanup(IWineD3DSurfaceImpl *This) +{ + TRACE("(%p) : Cleaning up.\n", This); + + if (This->Flags & SFLAG_DIBSECTION) + { + /* Release the DC. */ + SelectObject(This->hDC, This->dib.holdbitmap); + DeleteDC(This->hDC); + /* Release the DIB section. */ + DeleteObject(This->dib.DIBsection); + This->dib.bitmap_data = NULL; + This->resource.allocatedMemory = NULL; + } + + if (This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem((IWineD3DSurface *)This, NULL); + if (This->overlay_dest) list_remove(&This->overlay_entry); + + HeapFree(GetProcessHeap(), 0, This->palette9); + + resource_cleanup((IWineD3DResource *)This); +} + /***************************************************************************** * IWineD3DSurface::Release, GDI version * @@ -46,32 +69,15 @@ static ULONG WINAPI IWineGDISurfaceImpl_Release(IWineD3DSurface *iface) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; ULONG ref = InterlockedDecrement(&This->resource.ref); TRACE("(%p) : Releasing from %d\n", This, ref + 1); - if (ref == 0) { - TRACE("(%p) : cleaning up\n", This); - if(This->Flags & SFLAG_DIBSECTION) { - /* Release the DC */ - SelectObject(This->hDC, This->dib.holdbitmap); - DeleteDC(This->hDC); - /* Release the DIB section */ - DeleteObject(This->dib.DIBsection); - This->dib.bitmap_data = NULL; - This->resource.allocatedMemory = NULL; - } - if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL); - - HeapFree(GetProcessHeap(), 0, This->palette9); - - resource_cleanup((IWineD3DResource *)iface); - - if(This->overlay_dest) { - list_remove(&This->overlay_entry); - } + if (!ref) + { + surface_gdi_cleanup(This); - TRACE("(%p) Released\n", This); + TRACE("(%p) Released.\n", This); HeapFree(GetProcessHeap(), 0, This); - } + return ref; } diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 1e3e3fb79f0..881736ee42d 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -559,8 +559,8 @@ static BOOL init_format_compression_info(WineD3D_GL_Info *gl_info) static BOOL check_fbo_compat(const WineD3D_GL_Info *gl_info, GLint internal_format, GLenum format, GLenum type) { - GLuint tex, fb; GLenum status; + GLuint tex; ENTER_GL(); @@ -571,12 +571,9 @@ static BOOL check_fbo_compat(const WineD3D_GL_Info *gl_info, GLint internal_form glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - GL_EXTCALL(glGenFramebuffersEXT(1, &fb)); - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb)); GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0)); status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); - GL_EXTCALL(glDeleteFramebuffersEXT(1, &fb)); glDeleteTextures(1, &tex); checkGLcall("Framebuffer format check"); @@ -589,6 +586,13 @@ static BOOL check_fbo_compat(const WineD3D_GL_Info *gl_info, GLint internal_form static void init_format_fbo_compat_info(WineD3D_GL_Info *gl_info) { unsigned int i; + GLuint fbo; + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + GL_EXTCALL(glGenFramebuffersEXT(1, &fbo)); + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo)); + } for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i) { @@ -652,6 +656,11 @@ static void init_format_fbo_compat_info(WineD3D_GL_Info *gl_info) desc->rtInternal = desc->glInternal; } } + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + GL_EXTCALL(glDeleteFramebuffersEXT(1, &fbo)); + } } static BOOL init_format_texture_info(WineD3D_GL_Info *gl_info) diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index aa598935b2a..9f508a8dafa 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -3326,7 +3326,18 @@ typedef enum _GL_Cards { CARD_ATI_RADEON_HD2600 = 0x9581, CARD_ATI_RADEON_HD2900 = 0x9400, CARD_ATI_RADEON_HD3200 = 0x9620, - CARD_ATI_RADEON_HD4800 = 0x944c, + CARD_ATI_RADEON_HD4350 = 0x954f, + CARD_ATI_RADEON_HD4550 = 0x9540, + CARD_ATI_RADEON_HD4600 = 0x9495, + CARD_ATI_RADEON_HD4650 = 0x9498, + CARD_ATI_RADEON_HD4670 = 0x9490, + CARD_ATI_RADEON_HD4700 = 0x944e, + CARD_ATI_RADEON_HD4770 = 0x94b3, + CARD_ATI_RADEON_HD4800 = 0x944c, /* picked one value between 9440,944c,9442,9460 */ + CARD_ATI_RADEON_HD4830 = 0x944c, + CARD_ATI_RADEON_HD4850 = 0x9442, + CARD_ATI_RADEON_HD4870 = 0x9440, + CARD_ATI_RADEON_HD4890 = 0x9460, CARD_NVIDIA_RIVA_128 = 0x0018, CARD_NVIDIA_RIVA_TNT = 0x0020, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1997792e763..b7c5592d09e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -205,6 +205,28 @@ static inline float float_16_to_32(const unsigned short *in) { } } +static inline float float_24_to_32(DWORD in) +{ + const float sgn = in & 0x800000 ? -1.0f : 1.0f; + const unsigned short e = (in & 0x780000) >> 19; + const unsigned short m = in & 0x7ffff; + + if (e == 0) + { + if (m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */ + else return sgn * pow(2, -6.0f) * ((float)m / 524288.0f); + } + else if (e < 15) + { + return sgn * pow(2, (float)e - 7.0f) * (1.0f + ((float)m / 524288.0f)); + } + else + { + if (m == 0) return sgn / 0.0; /* +INF / -INF */ + else return 0.0 / 0.0; /* NAN */ + } +} + /** * Settings */ @@ -602,19 +624,27 @@ typedef struct shader_reg_maps WORD output_registers; /* MAX_REG_OUTPUT, 12 */ WORD integer_constants; /* MAX_CONST_I, 16 */ WORD boolean_constants; /* MAX_CONST_B, 16 */ + WORD local_int_consts; /* MAX_CONST_I, 16 */ WORD local_bool_consts; /* MAX_CONST_B, 16 */ WINED3DSAMPLER_TEXTURE_TYPE sampler_type[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)]; BOOL bumpmat[MAX_TEXTURES], luminanceparams[MAX_TEXTURES]; - char usesnrm, vpos, usesdsx, usesdsy, usestexldd, usesmova; - char usesrelconstF; + + unsigned usesnrm : 1; + unsigned vpos : 1; + unsigned usesdsx : 1; + unsigned usesdsy : 1; + unsigned usestexldd : 1; + unsigned usesmova : 1; + unsigned usesfacing : 1; + unsigned usesrelconstF : 1; + unsigned fog : 1; + unsigned usestexldl : 1; + unsigned padding : 6; /* Whether or not loops are used in this shader, and nesting depth */ unsigned loop_depth; - /* Whether or not this shader uses fog */ - char fog; - } shader_reg_maps; struct wined3d_shader_context @@ -1920,6 +1950,13 @@ struct IWineD3DSurfaceImpl extern const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl; extern const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl; +UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT alignment, UINT width, UINT height); +void surface_gdi_cleanup(IWineD3DSurfaceImpl *This); +HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment, + UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type, + UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, + WINED3DPOOL pool, IUnknown *parent); + /* Predeclare the shared Surface functions */ HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj); ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface); @@ -2046,6 +2083,9 @@ typedef enum { CONVERT_G16R16, CONVERT_R16G16F, CONVERT_R32G32F, + CONVERT_D15S1, + CONVERT_D24X4S4, + CONVERT_D24FS8, } CONVERT_TYPES; HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp, BOOL srgb_mode); diff --git a/dlls/winedos/dosexe.h b/dlls/winedos/dosexe.h index 77eed9e5d20..a1be04abcde 100644 --- a/dlls/winedos/dosexe.h +++ b/dlls/winedos/dosexe.h @@ -363,7 +363,6 @@ extern DWORD WINAPI DOSVM_Loop( HANDLE hThread ); extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data ); extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val ); extern void WINAPI DOSVM_SetTimer( UINT ticks ); -extern UINT WINAPI DOSVM_GetTimer( void ); /* devices.c */ extern void DOSDEV_InstallDOSDevices(void); @@ -450,7 +449,6 @@ extern void WINAPI DOSVM_Int31Handler(CONTEXT86*); extern void WINAPI DOSVM_RawModeSwitchHandler(CONTEXT86*); extern BOOL DOSVM_IsDos32(void); extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC); -extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16); extern int DPMI_CallRMProc(CONTEXT86*,LPWORD,int,int); extern BOOL DOSVM_CheckWrappers(CONTEXT86*); diff --git a/dlls/winedos/int21.c b/dlls/winedos/int21.c index 79aa8ea568c..16b23598ad8 100644 --- a/dlls/winedos/int21.c +++ b/dlls/winedos/int21.c @@ -4592,7 +4592,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context ) if (INT21_FillDrivePB( drive )) { SET_AL( context, 0x00 ); /* success */ - SET_DX( context, offsetof( INT21_HEAP, misc_dpb_list[drive] ) ); + SET_BX( context, offsetof( INT21_HEAP, misc_dpb_list[drive] ) ); context->SegDs = INT21_GetHeapSelector( context ); } else diff --git a/dlls/winedos/int31.c b/dlls/winedos/int31.c index 9cc9e905b4e..905d7e6bf5e 100644 --- a/dlls/winedos/int31.c +++ b/dlls/winedos/int31.c @@ -705,12 +705,6 @@ static int DPMI_FreeRMCB( DWORD address ) } -void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc ) -{ - DPMI_FreeRMCB( (DWORD)proc ); -} - - /********************************************************************** * DOSVM_RawModeSwitchHandler * diff --git a/dlls/winedos/timer.c b/dlls/winedos/timer.c index 0a504af03e1..a7067aa8b0c 100644 --- a/dlls/winedos/timer.c +++ b/dlls/winedos/timer.c @@ -142,27 +142,6 @@ static void WINAPI TIMER_DoSetTimer( ULONG_PTR arg ) /*********************************************************************** - * DOSVM_GetTimer - */ -UINT WINAPI DOSVM_GetTimer( void ) -{ - if (!DOSVM_IsWin16()) - { - DWORD millis = GetTickCount() - TIMER_stamp; - INT ticks = MulDiv( millis, TIMER_FREQ, 1000 ); - - /* sanity check - tick wrap or suspended process or update race */ - if (ticks < 0 || ticks >= TIMER_ticks) - ticks = 0; - - return ticks; - } - - return 0; -} - - -/*********************************************************************** * DOSVM_SetTimer */ void WINAPI DOSVM_SetTimer( UINT ticks ) diff --git a/dlls/winedos/vga.c b/dlls/winedos/vga.c index 6c9085efc98..bc3f8c357d0 100644 --- a/dlls/winedos/vga.c +++ b/dlls/winedos/vga.c @@ -884,41 +884,7 @@ const VGA_MODE *VGA_GetModeInfo(WORD mode) return NULL; } -const VGA_MODE *VGA_GetModeInfoList(void) -{ - return VGA_modelist; -} - -int VGA_SetMode(WORD mode) -{ - const VGA_MODE *ModeInfo; - /* get info on VGA mode & set appropriately */ - VGA_CurrentMode = mode; - ModeInfo = VGA_GetModeInfo(VGA_CurrentMode); - - /* check if mode is supported */ - if (ModeInfo->Supported) - { - FIXME("Setting VGA mode %i - Supported mode - Improve reporting of missing capabilities for modes & modetypes.\n", mode); - } - else - { - FIXME("Setting VGA mode %i - Unsupported mode - Will doubtfully work at all, but we'll try anyways.\n", mode); - } - - /* set up graphic or text display */ - if (ModeInfo->ModeType == TEXT) - { - VGA_SetAlphaMode(ModeInfo->TextCols, ModeInfo->TextRows); - } - else - { - return VGA_SetGraphicMode(mode); - } - return 0; /* assume all good & return zero */ -} - -int VGA_SetGraphicMode(WORD mode) +static int VGA_SetGraphicMode(WORD mode) { ModeSet par; int newSize; @@ -1000,6 +966,35 @@ int VGA_SetGraphicMode(WORD mode) return par.ret; } +int VGA_SetMode(WORD mode) +{ + const VGA_MODE *ModeInfo; + /* get info on VGA mode & set appropriately */ + VGA_CurrentMode = mode; + ModeInfo = VGA_GetModeInfo(VGA_CurrentMode); + + /* check if mode is supported */ + if (ModeInfo->Supported) + { + FIXME("Setting VGA mode %i - Supported mode - Improve reporting of missing capabilities for modes & modetypes.\n", mode); + } + else + { + FIXME("Setting VGA mode %i - Unsupported mode - Will doubtfully work at all, but we'll try anyways.\n", mode); + } + + /* set up graphic or text display */ + if (ModeInfo->ModeType == TEXT) + { + VGA_SetAlphaMode(ModeInfo->TextCols, ModeInfo->TextRows); + } + else + { + return VGA_SetGraphicMode(mode); + } + return 0; /* assume all good & return zero */ +} + int VGA_GetMode(unsigned*Height,unsigned*Width,unsigned*Depth) { if (!lpddraw) return 1; diff --git a/dlls/winedos/vga.h b/dlls/winedos/vga.h index f3169f8a689..5d79567c1d7 100644 --- a/dlls/winedos/vga.h +++ b/dlls/winedos/vga.h @@ -55,7 +55,6 @@ const VGA_MODE *VGA_GetModeInfo(WORD mode); int VGA_SetMode(WORD mode); /* graphics mode */ -int VGA_SetGraphicMode(WORD mode); int VGA_GetMode(unsigned*Height,unsigned*Width,unsigned*Depth); void VGA_SetPalette(PALETTEENTRY*pal,int start,int len); void VGA_SetColor16(int reg,int color); diff --git a/dlls/wineesd.drv/audio.c b/dlls/wineesd.drv/audio.c index bb6aae01e94..a69949c7e6d 100644 --- a/dlls/wineesd.drv/audio.c +++ b/dlls/wineesd.drv/audio.c @@ -1176,11 +1176,15 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) out_rate = (int) wwo->waveFormat.Format.nSamplesPerSec; TRACE("esd output format = 0x%08x, rate = %d\n", out_format, out_rate); + wwo->stream_name = get_stream_name("out", wDevID); wwo->stream_fd = esd_play_stream(out_format, out_rate, NULL, wwo->stream_name); TRACE("wwo->stream_fd=%d\n", wwo->stream_fd); - if(wwo->stream_fd < 0) return MMSYSERR_ALLOCATED; + if(wwo->stream_fd < 0) + { + HeapFree(GetProcessHeap(), 0, wwo->stream_name); + return MMSYSERR_ALLOCATED; + } - wwo->stream_name = get_stream_name("out", wDevID); wwo->stream_id = 0; wwo->dwPlayedTotal = 0; wwo->dwWrittenTotal = 0; @@ -1412,6 +1416,7 @@ static esd_player_info_t* wod_get_player(WINE_WAVEOUT* wwo, esd_info_t** esd_all if (wwo->esd_fd < 0) { WARN("esd_open_sound() failed (%d)\n", errno); + *esd_all_info = NULL; return NULL; } } @@ -1461,10 +1466,9 @@ static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol) *lpdwVol = left + (right << 16); ret = MMSYSERR_NOERROR; } - else - ret = MMSYSERR_ERROR; - esd_free_all_info(esd_all_info); + if (esd_all_info) + esd_free_all_info(esd_all_info); return ret; } @@ -1489,7 +1493,8 @@ static DWORD wodSetVolume(WORD wDevID, DWORD dwParam) esd_info_t* esd_all_info; /* wod_get_player sets the stream_id as a side effect */ wod_get_player(wwo, &esd_all_info); - esd_free_all_info(esd_all_info); + if (esd_all_info) + esd_free_all_info(esd_all_info); } if (!wwo->stream_id) return MMSYSERR_ERROR; @@ -1899,14 +1904,18 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) in_rate = (int) wwi->waveFormat.Format.nSamplesPerSec; TRACE("esd input format = 0x%08x, rate = %d\n", in_format, in_rate); + wwi->stream_name = get_stream_name("in", wDevID); #ifdef WID_USE_ESDMON wwi->stream_fd = esd_monitor_stream(in_format, in_rate, NULL, wwi->stream_name); #else wwi->stream_fd = esd_record_stream(in_format, in_rate, NULL, wwi->stream_name); #endif TRACE("wwi->stream_fd=%d\n",wwi->stream_fd); - if(wwi->stream_fd < 0) return MMSYSERR_ALLOCATED; - wwi->stream_name = get_stream_name("in", wDevID); + if(wwi->stream_fd < 0) + { + HeapFree(GetProcessHeap(), 0, wwi->stream_name); + return MMSYSERR_ALLOCATED; + } wwi->state = WINE_WS_STOPPED; if (wwi->lpQueuePtr) { diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index f207a3217c5..f1557b65cd0 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -146,6 +146,7 @@ static const WineGLExtension *WineGLExtensionList[MAX_EXTENSIONS]; static int WineGLExtensionListSize; static void X11DRV_WineGL_LoadExtensions(void); +static WineGLPixelFormat* ConvertPixelFormatWGLtoGLX(Display *display, int iPixelFormat, BOOL AllowOffscreen, int *fmt_count); static BOOL glxRequireVersion(int requiredVersion); static BOOL glxRequireExtension(const char *requiredExtension); @@ -582,37 +583,23 @@ static int describeContext(Wine_GLContext* ctx) { return ctx_vis_id; } -static int describeDrawable(Wine_GLContext* ctx, Drawable drawable) { +static BOOL describeDrawable(X11DRV_PDEVICE *physDev) { int tmp; - int nElements; - int attribList[3] = { GLX_FBCONFIG_ID, 0, None }; - GLXFBConfig *fbCfgs; - - if (pglXQueryDrawable == NULL) { - /** glXQueryDrawable not available so returns not supported */ - return -1; - } - - TRACE(" Drawable %p have :\n", (void*) drawable); - pglXQueryDrawable(gdi_display, drawable, GLX_WIDTH, (unsigned int*) &tmp); - TRACE(" - WIDTH as %d\n", tmp); - pglXQueryDrawable(gdi_display, drawable, GLX_HEIGHT, (unsigned int*) &tmp); - TRACE(" - HEIGHT as %d\n", tmp); - pglXQueryDrawable(gdi_display, drawable, GLX_FBCONFIG_ID, (unsigned int*) &tmp); - TRACE(" - FBCONFIG_ID as 0x%x\n", tmp); + WineGLPixelFormat *fmt; + int fmt_count = 0; - attribList[1] = tmp; - fbCfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), attribList, &nElements); - if (fbCfgs == NULL) { - return -1; - } + fmt = ConvertPixelFormatWGLtoGLX(gdi_display, physDev->current_pf, TRUE /* Offscreen */, &fmt_count); + if(!fmt) return FALSE; - pglXGetFBConfigAttrib(gdi_display, fbCfgs[0], GLX_VISUAL_ID, &tmp); - TRACE(" - VISUAL_ID as 0x%x\n", tmp); + TRACE(" HDC %p has:\n", physDev->hdc); + TRACE(" - iPixelFormat %d\n", fmt->iPixelFormat); + TRACE(" - Drawable %p\n", (void*) get_glxdrawable(physDev)); + TRACE(" - FBCONFIG_ID 0x%x\n", fmt->fmt_id); - XFree(fbCfgs); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_VISUAL_ID, &tmp); + TRACE(" - VISUAL_ID 0x%x\n", tmp); - return tmp; + return TRUE; } static int ConvertAttribWGLtoGLX(const int* iWGLAttr, int* oGLXAttr, Wine_GLPBuffer* pbuf) { @@ -1842,7 +1829,7 @@ BOOL CDECL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) { if (ctx->ctx == NULL) { /* The describe lines below are for debugging purposes only */ if (TRACE_ON(wgl)) { - describeDrawable(ctx, drawable); + describeDrawable(physDev); describeContext(ctx); } diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c index 954284f8203..38687ecb56b 100644 --- a/dlls/winex11.drv/xdnd.c +++ b/dlls/winex11.drv/xdnd.c @@ -375,9 +375,7 @@ static int X11DRV_XDND_DeconstructTextURIList(int property, void* data, int len) { while (end < len && uriList[end] != '\r') ++end; - if (end == len) - break; - if (uriList[end+1] != '\n') + if (end < (len - 1) && uriList[end+1] != '\n') { WARN("URI list line doesn't end in \\r\\n\n"); break; @@ -412,7 +410,7 @@ static int X11DRV_XDND_DeconstructTextURIList(int property, void* data, int len) start = end + 2; end = start; } - if (out && end == len) + if (out && end >= len) { DROPFILES *dropFiles; dropFiles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DROPFILES) + size + 1); diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 8f9f404164f..e1a7ddc76d1 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -741,7 +741,7 @@ static BOOL HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr, while (*lpszEnd != '\0') { - if (*lpszEnd == '\r' && *(lpszEnd + 1) == '\n') + if (*lpszEnd == '\r' || *lpszEnd == '\n') break; lpszEnd++; } @@ -749,10 +749,10 @@ static BOOL HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr, if (*lpszStart == '\0') break; - if (*lpszEnd == '\r') + if (*lpszEnd == '\r' || *lpszEnd == '\n') { *lpszEnd = '\0'; - lpszEnd += 2; /* Jump over \r\n */ + lpszEnd++; /* Jump over newline */ } TRACE("interpreting header %s\n", debugstr_w(lpszStart)); if (*lpszStart == '\0') @@ -1568,6 +1568,20 @@ static void HTTPREQ_CloseConnection(WININETHANDLEHEADER *hdr) INTERNET_STATUS_CONNECTION_CLOSED, 0, 0); } +static BOOL HTTP_GetRequestURL(WININETHTTPREQW *req, LPWSTR buf) +{ + LPHTTPHEADERW host_header; + + static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0}; + + host_header = HTTP_GetHeader(req, hostW); + if(!host_header) + return FALSE; + + sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */ + return TRUE; +} + static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode) { WININETHTTPREQW *req = (WININETHTTPREQW*)hdr; @@ -1620,6 +1634,41 @@ static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *b } } + case INTERNET_OPTION_CACHE_TIMESTAMPS: { + INTERNET_CACHE_ENTRY_INFOW *info; + INTERNET_CACHE_TIMESTAMPS *ts = buffer; + WCHAR url[INTERNET_MAX_URL_LENGTH]; + DWORD nbytes, error; + BOOL ret; + + TRACE("INTERNET_OPTION_CACHE_TIMESTAMPS\n"); + + if (*size < sizeof(*ts)) + { + *size = sizeof(*ts); + return ERROR_INSUFFICIENT_BUFFER; + } + nbytes = 0; + HTTP_GetRequestURL(req, url); + ret = GetUrlCacheEntryInfoW(url, NULL, &nbytes); + error = GetLastError(); + if (!ret && error == ERROR_INSUFFICIENT_BUFFER) + { + if (!(info = HeapAlloc(GetProcessHeap(), 0, nbytes))) + return ERROR_OUTOFMEMORY; + + GetUrlCacheEntryInfoW(url, info, &nbytes); + + ts->ftExpires = info->ExpireTime; + ts->ftLastModified = info->LastModifiedTime; + + HeapFree(GetProcessHeap(), 0, info); + *size = sizeof(*ts); + return ERROR_SUCCESS; + } + return error; + } + case INTERNET_OPTION_DATAFILE_NAME: { DWORD req_size; @@ -3244,20 +3293,6 @@ BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders, return result; } -static BOOL HTTP_GetRequestURL(WININETHTTPREQW *req, LPWSTR buf) -{ - LPHTTPHEADERW host_header; - - static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0}; - - host_header = HTTP_GetHeader(req, hostW); - if(!host_header) - return FALSE; - - sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */ - return TRUE; -} - /*********************************************************************** * HTTP_GetRedirectURL (internal) */ @@ -3807,8 +3842,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, } while (loop_next); - /* FIXME: Better check, when we have to create the cache file */ - if(bSuccess && (lpwhr->hdr.dwFlags & INTERNET_FLAG_NEED_FILE)) { + if(bSuccess) { WCHAR url[INTERNET_MAX_URL_LENGTH]; WCHAR cacheFileName[MAX_PATH+1]; BOOL b; diff --git a/dlls/wininet/rsrc.rc b/dlls/wininet/rsrc.rc index 5a815116b03..fdf3692829f 100644 --- a/dlls/wininet/rsrc.rc +++ b/dlls/wininet/rsrc.rc @@ -53,6 +53,7 @@ #include "wininet_It.rc" #include "wininet_Ja.rc" #include "wininet_Ko.rc" +#include "wininet_Lt.rc" #include "wininet_Nl.rc" #include "wininet_No.rc" #include "wininet_Pl.rc" diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index 7aa35754473..ba72629428d 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -1163,11 +1163,11 @@ static void test_http_cache(void) size = sizeof(file_name); ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size); - todo_wine ok(ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) failed %u\n", GetLastError()); + ok(ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) failed %u\n", GetLastError()); file = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - todo_wine ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError()); + ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError()); CloseHandle(file); ok(InternetCloseHandle(request), "Close request handle failed\n"); @@ -1453,6 +1453,29 @@ static void HttpHeaders_test(void) ok(index == 1, "Index was not incremented\n"); ok(strcmp(buffer,"value")==0, "incorrect string was returned(%s)\n",buffer); + /* Ensure that malformed header separators are ignored and don't cause a failure */ + ok(HttpAddRequestHeaders(hRequest,"\r\rMalformedTest:value\n\nMalformedTestTwo: value2\rMalformedTestThree: value3\n\n\r\r\n",-1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE), + "Failed to add header with malformed entries in list\n"); + + index = 0; + len = sizeof(buffer); + strcpy(buffer,"MalformedTest"); + ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n"); + ok(index == 1, "Index was not incremented\n"); + ok(strcmp(buffer,"value")==0, "incorrect string was returned(%s)\n",buffer); + index = 0; + len = sizeof(buffer); + strcpy(buffer,"MalformedTestTwo"); + ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n"); + ok(index == 1, "Index was not incremented\n"); + ok(strcmp(buffer,"value2")==0, "incorrect string was returned(%s)\n",buffer); + index = 0; + len = sizeof(buffer); + strcpy(buffer,"MalformedTestThree"); + ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n"); + ok(index == 1, "Index was not incremented\n"); + ok(strcmp(buffer,"value3")==0, "incorrect string was returned(%s)\n",buffer); + ok(InternetCloseHandle(hRequest), "Close request handle failed\n"); done: ok(InternetCloseHandle(hConnect), "Close connect handle failed\n"); diff --git a/dlls/wininet/urlcache.c b/dlls/wininet/urlcache.c index f385c7e81cb..418f508f650 100644 --- a/dlls/wininet/urlcache.c +++ b/dlls/wininet/urlcache.c @@ -2222,11 +2222,7 @@ BOOL WINAPI CreateUrlCacheEntryW( dwReserved); if (dwReserved) - { - ERR("dwReserved != 0\n"); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + FIXME("dwReserved 0x%08x\n", dwReserved); lpszUrlEnd = lpszUrlName + strlenW(lpszUrlName); diff --git a/dlls/wininet/wininet_Lt.rc b/dlls/wininet/wininet_Lt.rc new file mode 100644 index 00000000000..bf5dbf2f212 --- /dev/null +++ b/dlls/wininet/wininet_Lt.rc @@ -0,0 +1,49 @@ +/* + * Copyright 2009 Aurimas Fišeras + * + * 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 + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_LITHUANIAN, SUBLANG_NEUTRAL + +IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Įveskite tinklo slaptažodį" +FONT 8, "MS Shell Dlg" +{ + LTEXT "Įveskite savo naudotojo vardą ir slaptažodį:", -1, 40, 6, 150, 15 + LTEXT "Įgaliot. serv.", -1, 40, 26, 50, 10 + LTEXT "Sritis", -1, 40, 46, 50, 10 + LTEXT "Naudotojas", -1, 40, 66, 50, 10 + LTEXT "Slaptažodis", -1, 40, 86, 50, 10 + LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0 + LTEXT "" IDC_REALM, 80, 46, 150, 14, 0 + EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP + EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD + CHECKBOX "Į&rašyti šį slaptažodį (nesaugu)", IDC_SAVEPASSWORD, + 80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Gerai", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON + PUSHBUTTON "Atsisakyti", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP +} + +STRINGTABLE DISCARDABLE +{ + IDS_LANCONNECTION "Vietinio tinklo ryšys" +} + +#pragma code_page(default) diff --git a/dlls/wintrust/softpub.c b/dlls/wintrust/softpub.c index 9c79fa8bcd3..7f5f86f5a5a 100644 --- a/dlls/wintrust/softpub.c +++ b/dlls/wintrust/softpub.c @@ -256,7 +256,8 @@ static BOOL SOFTPUB_LoadCertMessage(CRYPT_PROVIDER_DATA *data) BOOL ret; if (data->pWintrustData->u.pCert && - data->pWintrustData->u.pCert->cbStruct == sizeof(WINTRUST_CERT_INFO)) + WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_CERT_INFO, + data->pWintrustData->u.pCert->cbStruct, psCertContext)) { if (data->psPfns) { @@ -266,7 +267,9 @@ static BOOL SOFTPUB_LoadCertMessage(CRYPT_PROVIDER_DATA *data) /* Add a signer with nothing but the time to verify, so we can * add a cert to it */ - if (data->pWintrustData->u.pCert->psftVerifyAsOf) + if (WVT_ISINSTRUCT(WINTRUST_CERT_INFO, + data->pWintrustData->u.pCert->cbStruct, psftVerifyAsOf) && + data->pWintrustData->u.pCert->psftVerifyAsOf) data->sftSystemTime = signer.sftVerifyAsOf; else { @@ -280,10 +283,12 @@ static BOOL SOFTPUB_LoadCertMessage(CRYPT_PROVIDER_DATA *data) { ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0, data->pWintrustData->u.pCert->psCertContext); - for (i = 0; ret && i < data->pWintrustData->u.pCert->chStores; - i++) - ret = data->psPfns->pfnAddStore2Chain(data, - data->pWintrustData->u.pCert->pahStores[i]); + if (WVT_ISINSTRUCT(WINTRUST_CERT_INFO, + data->pWintrustData->u.pCert->cbStruct, pahStores)) + for (i = 0; + ret && i < data->pWintrustData->u.pCert->chStores; i++) + ret = data->psPfns->pfnAddStore2Chain(data, + data->pWintrustData->u.pCert->pahStores[i]); } } else diff --git a/dlls/wintrust/wintrust_main.c b/dlls/wintrust/wintrust_main.c index fa4da16434c..0a40fbab6f8 100644 --- a/dlls/wintrust/wintrust_main.c +++ b/dlls/wintrust/wintrust_main.c @@ -303,7 +303,8 @@ static HRESULT WINAPI WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA *data) { case WTD_CHOICE_BLOB: if (data->pWintrustData->u.pBlob && - data->pWintrustData->u.pBlob->cbStruct == sizeof(WINTRUST_BLOB_INFO) && + WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_BLOB_INFO, + data->pWintrustData->u.pBlob->cbStruct, pbMemObject) && data->pWintrustData->u.pBlob->cbMemObject == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) && data->pWintrustData->u.pBlob->pbMemObject) diff --git a/dlls/wldap32/tests/parse.c b/dlls/wldap32/tests/parse.c index d4b5de2fadf..0f22d238674 100644 --- a/dlls/wldap32/tests/parse.c +++ b/dlls/wldap32/tests/parse.c @@ -57,8 +57,13 @@ static void test_ldap_parse_sort_control( LDAP *ld ) ok( !ret, "ldap_search_ext_sA failed 0x%x\n", ret ); ok( res != NULL, "expected res != NULL\n" ); - ret = ldap_parse_resultA( NULL, res, &result, NULL, NULL, NULL, &server_ctrls, 1 ); - ok( ret == LDAP_PARAM_ERROR, "ldap_parse_resultA failed 0x%x\n", ret ); + if (GetProcAddress(GetModuleHandle("wldap32.dll"), "ber_init")) + { + ret = ldap_parse_resultA( NULL, res, &result, NULL, NULL, NULL, &server_ctrls, 1 ); + ok( ret == LDAP_PARAM_ERROR, "ldap_parse_resultA failed 0x%x\n", ret ); + } + else + win_skip("Test would crash on older wldap32 versions\n"); result = ~0u; ret = ldap_parse_resultA( ld, res, &result, NULL, NULL, NULL, &server_ctrls, 1 ); diff --git a/documentation/README.de b/documentation/README.de index ee07af0a9d3..332ab886115 100644 --- a/documentation/README.de +++ b/documentation/README.de @@ -64,6 +64,9 @@ 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. + Unterstützte Dateisysteme: Wine sollte auf den meisten Dateisystemen laufen. Jedoch wird Wine nicht starten, wenn umsdos für das Verzeichnis /tmp benutzt wird. Ein paar @@ -86,6 +89,9 @@ Optionale Support-Bibliotheken: die von Wine benutzt werden können, aber auf dem System nicht vorhanden sind. + Auf 64-Bit Plattformen benötigen Sie die 32-bit + Versionen dieser Bibliotheken; siehe dazu http://wiki.winehq.org/WineOn64bit + 4. KOMPILIEREN Wenn Sie sich dafür entscheiden, wineinstall nicht zu benutzen, führen Sie @@ -109,10 +115,10 @@ wechsen Sie erst mit cd in das Wurzelverzeichnis dieses Releases (das, welches diese README-Datei enthält). Geben Sie dann "make clean" ein und patchen Sie das Release mit dem Kommando: - gunzip -c patch-file | patch -p1 + bunzip2 -c Patch-Datei | patch -p1 -wobei "patch-file" der Name der Patch-Datei ist (etwas wie -Wine-yymmdd.diff.gz). Sie können dann erneut "./configure" und danach +wobei "Patch-Datei" der Name der Patch-Datei ist (sowas wie +wine-1.0.x.diff.bz2). Sie können dann erneut "./configure" und danach "make depend && make" aufrufen. 5. SETUP @@ -137,16 +143,16 @@ und f Wenn Sie Wine aufrufen, können Sie den vollständigen Pfad zur ausführbaren Datei angeben oder nur einen Dateinamen. -Beispiel: Um Solitaire auszuführen: +Beispiel: Um Notepad auszuführen: - wine sol (den Suchpfad, der in der Konfiguartions-Datei - wine sol.exe angegeben wurde, benutzend) + wine notepad (den Suchpfad, der in der Konfiguartions-Datei + wine notepad.exe angegeben wurde, benutzend) - wine c:\\windows\\sol.exe (die Dateinamen-Syntax von DOS benutzend) + wine c:\\windows\\notepad.exe (die Dateinamen-Syntax von DOS benutzend) - wine /usr/windows/sol.exe (die Dateinamen-Syntax von Unix benutzend) + wine ~/.wine/drive_c/windows/notepad.exe (die Dateinamen-Syntax von Unix benutzend) - wine sol.exe /parameter1 -parameter2 parameter3 + wine notepad.exe /parameter1 -parameter2 parameter3 (Programmaufruf mit Parametern) Hinweis: Der Pfad zur Datei wird auch zum Pfad hinzugefügt, wenn ein vollständiger @@ -188,13 +194,15 @@ Fehler: Melden Sie Fehler bitte an Wine-Bugzilla unter http://bugs.winehq.org IRC: Online-Hilfe wird Ihnen im Chat-Kanal #WineHQ unter irc.freenode.net gewährt. -CVS: Der aktuelle Wine-Entwicklungs-Tree ist über CVS verfügbar. - Besuchen Sie http://www.winehq.org/cvs für weitere Informationen. +GIT: Der aktuelle Wine-Entwicklungs-Zweig ist über GIT verfügbar. + Besuchen Sie http://www.winehq.org/site/git für weitere Informationen. Mailing-Listen: Es gibt mehrere Mailing-Listen für die Wine-Entwickler; Schauen Sie sich bitte dazu http://www.winehq.org/forums an. +Wiki: Das Wine-Wiki finden Sie unter http://wiki.winehq.org + Wenn Sie etwas hinzufügen oder einen Fehler beheben, senden Sie den Patch bitte (im 'diff -u'-Format) an die Liste wine-patches@winehq.org, um ihn in die nächste Ausgabe aufnehmen zu können. diff --git a/documentation/README.fr b/documentation/README.fr dissimilarity index 75% index 39081ee1c1e..3a51b8ed39e 100644 --- a/documentation/README.fr +++ b/documentation/README.fr @@ -1,219 +1,202 @@ -1. INTRODUCTION - -Wine est un programme qui permet d'exécuter les logiciels écrits -pour Microsoft Windows (comprenant les exécutables DOS, Windows 3.x -et Win32) sur un Unix. Il est composé d'un chargeur qui charge et -exécute un binaire Microsoft Windows, ainsi que d'une librairie (appelée -Winelib) qui implémente les appels de l'API de Windows par leur -équivalent Unix ou X11. Cette librairie peut également être utilisée -pour porter du code Win32 vers un exécutable Unix natifs. - -Wine est un logiciel libre, distribué sous GNU LGPL; lisez le fichier -LICENCE pour les détails. - -2. DÉMARRAGE RAPIDE - -Même si vous compilez à partir des sources, il est recommandé d'utiliser -l'Installateur de Wine pour construire et installer Wine. À partir du -répertoire le plus élevé des sources de Wine (qui contient ce fichier), -exécutez : - -./tools/wineinstall - -Pour exécuter les programmes, tapez "wine [options] programme". Pour des -informationS complémentaires et des résolutions de problèmes, lisez le -reste de ce fichier, les pages "man" de Wine, et surtout les nombreuses -informations que vous trouverez sur http://www.winehq.org. - -3. CONFIGURATION NÉCESSAIRE - -Pour compiler et exécuter Wine, vous devez avoir un des systèmes -d'exploitation qui suit : - - Linux version 2.0.36 ou supérieur - FreeBSD 4.x or FreeBSD 5-CURRENT ou supérieur - Solaris x86 2.5 ou supérieur - NetBSD-current - -Étant donné que Wine nécessite une implémentation des "threads" au niveau du -noyau, seuls les systèmes d'exploitation mentionnés ci-haut sont supportés. -D'autres systèmes d'exploitation qui implémentent les "threads" noyau peuvent -être supportés dans le futur. - -Information Linux : - Bien que Linux 2.2.x devrait encore fontionner et que Linux 2.0.x pourrait - encore marcher (des versions plus anciennes de 2.0.x avaient des plantages - dû aux "threads"), il est préférable d'avoir un noyau récent tel que 2.4.x. - -Information FreeBSD : - Wine devrait pouvoir être compilé sur FreeBSD 4.x et FreeBSD 5.x, mais les - versions antérieures à FreeBSD 5.3 ne fonctionneront généralement pas. - - Plus d'information est située dans l'arbre de ports : - ftp://ftp.freebsd.org/pub/FreeBSD/ports/ports/emulators/wine/ - -Information Solaris : - Il est plus que probable que vous devrez construire Wine avec la chaîne - d'outils GNU (gcc, gas, etc.). Avertissement : intaller gas n'assure pas - qu'il sera utilisé par gcc. Recompliler gcc après l'installation de gas - ou créer un lien symbolique de cc, as et ld vers les outils GNU semble - nécessaire. - -Information NetBSD : - Assurez-vous d'avoir les options USER_LDT, SYSVSHM, SYSVSEM, and SYSVMSG - enclanchées dans votre noyau. - -Systèmes de fichier supportés : - Wine devrait fonctionner sur la plupart des systèmes de fichier. Cependant - Wine s'arrêtera au démarrage si umsdos est utilisé pour le répertoire /tmp. - Quelques problèmes de compatibilité ont aussi été rapportés sur - l'utilisation des fichiers accédés au travers de Samba. Egalement, puisque - NTFS ne peut être utilisé en sécurité qu'avec un accès en lecture seul pour - le moment, nous recommandons de ne pas utiliser NTFS, parce que les - programmes Windows on besoin des accès en écriture presque partout. Si vous - avez des fichier NTFS, copiez les vers une localisation accessible en - écriture. - -Configuration requise de base : -Vous avez besoin d'avoir les fichiers "include" de X11 installés -(appelés xlib6g-dev pour Debian et XFree86-devel pour RedHat). - -Configuration requise des outils de compilation : -Sur les système x86, gcc >= 2.7.2 est nécessaire. Les versions inférieures à -la 2.7.2.3 peuvent créer des ennuis losrque certains fichiers sont compilés -avec l'optimisation, souvent dû à des problèmes de gestion d'en-tête de fichier. -pgcc ne fonctionne pas actuellement avec Wine. La cause de ce problème est -inconnue. - -Évidemment, vous aurez besoin de "make" (très probablement GNU make). - -Vous aurez également besoin de flex version 2.5 ou supérieure et bison. -Si vous utilisez RedHat ou Debian, installez les paquets flex et bison. - -Librairies optionnelles : - Si vous voulez un support d'impression à l'aide de CUPS, SVP installez à la - fois les packages cups et cups-devel. - -4. COMPILATION - -Au cas où vous choisissez de ne pas utiliser wineinstall, exécuter les com- -mandes suivantes pour construire Wine : - -./configure -make depend -make - -Cela va constuire le programme "wine" et de nombreux binaires/librairies de -support. -Le programme "wine" chargera et exécutera les exécutables Windows. -La librairie "libwine" ("Winelib") peut être utilisée pour compiler et lier -le code source Windows sous Unix. - -Pour voir les options de compilation, tapez ./configure --help. - -Pour mettre à jour une nouvelle version en utilisant les fichiers patch, tout -d'abord aller dans le répertoire de plus haut niveau de la version actuelle -(celui qui contient ce fichier README.fr). Ensuite faire un "make clean", et -patcher la version avec : - - gunzip -c patch-file | patch -p1 - -Avec "patch-file" qui est le nom du fichier de patche (quelque chose de -similaire à Wine-yymmdd.diff.gz). Vous pouvez réexécuter "./configure", et -ensuite taper "make depend && make". - -5. SETUP - -Un fois que Wine a été construit correctement, vous pouvez tapez "make install"; -cela installera l'exécutable wine, les pages man Wine et quelques autres fichiers -nécessaires. - -N'oubliez pas de désinsatller toutes les installations précédantes de wine. -Essayez soit "dpkg -r wine", "rpm -e wine" ou "make uninstall" avant -d'installer. - -Naviguez dans la section Support à http://www.winehq.org/ pour pd'astuces -de configuration. - -En cas d'erreur de chargement de librairie (par exemple -"Error while loading shared libraries: libntdll.so"), assurez vous d'ajouter -le chemin des librairies à /etc/ld.so.conf et exécuter ldconfig en tant que root. - -6. EXÉCUTER DES PROGRAMMES - -Lorsque l'on invoque Wine, vous pouvez spécifier le chemin entier vers -l'exécutable ou seulement le nom de fichier. - -Pour exécuter Solitaire par exemple : - - wine sol (en utilisant le chemin d'accès spécifié - wine sol.exe dans le fichier "config" pour localiser - le fichier) - - wine c:\\windows\\sol.exe (en utilisant la syntaxe de fichiers DOS) - - wine /usr/windows/sol.exe (en utilisant la syntaxe de fichiers Unix) - - wine sol.exe /parametre1 -parametre2 parametre3 - (en appelant le programme avec des paramètres) - -Note: le chemin du fichier sera également additionné au chemin par défaut - lorsque le nom entier est écrit sur la ligne de commande. - -Wine n'est pas encore complet, ainsi quelque programmes peuvent planter. Selon -que vous avez installé correctement winedbg d'après documentation/debugger.sgml, -vous entrerez dans le débogueur vous permettant d'enquêter et de résoudre le -problème. Pour plus d'information sur la manière de le faire, veuillez lire -le fichier documentation/debugging.sgml. - -Vous devriez sauvegarder tous vos fichier important auquels vous donnez accès -à Wine ou utiliser une copie spéciale pour Wine, puisque dans certain cas des -utilisateurs ont rapporté des corruptions de fichiers. Ne PAS -éxécuter l'Explorateur, par exemple, si vous n'avez pas une copie propre, -puisque il renomme/corrompt parfois plusieurs répertoires. Même certaines -application MS telle Messenger par exemple ne sont pas sûres puisqu'elle -peuvent lancer l'Explorateur dans certains cas. Certaines corruptions -particulières telle (!$!$!$!$.pfr) peut du moins être partiellement -fixée en utilisant la méthode décrite par -http://home.nexgo.de/andi.mohr/download/decorrupt_explorer - -7. OPTENIR PLUS D'INFORMATIONS - -WWW: Baucoup d'informations à propos de Wine sont disponibles sur WineHQ à - http://www.winehq.org/ : divers Guides Wine, base de donnée - d'applications, suivit de bogues. C'est probablement le meilleur point - de départ. - -FAQ: La Foire Aux Questions de Wine est localisée à : - http://www.winehq.org/FAQ - -Usenet: Vous pouvez parler des problèmes ou résolutions en relation avec Wine - ou optenir de l'aide sur comp.emulators.ms-windows.wine. - -Bugs: Rapportez les bogues à Wine Bugzilla à http://bugs.winehq.org - SVP cherchez tout d'abord dans la base de donnée de bugzilla - pour contrôler que le problème n'est pas déjà découvert avant - de poster un rapport de bogue. Vous pouvez également rapporter - des rapports de bogue à comp.emulators.ms-windows.wine. - SVP lisez le fichier documentation/bugs.sgml pour connaître les - informations nécessaires. - -IRC: L'aide en ligne est disponible sur le cannal #WineHQ sur - irc.freenode.net. - -CVS: L'arbre de développement actuel de Wine est disponible au travers - de CVS. - Allez sur http://www.winehq.org/cvs pour plus d'informations - -Mailing lists: - Il existe de multiples mailing lists pour les développeurs de Wine; - repportez-vous à http://www.winehq.org/forums pour de plus - amples informations. - -Si vous ajoutez quelquechose ou fixez un bogue, envoyez un patch (dans le -format 'diff -u' ) à la liste de diffusion wine-patches@winehq.org pour son -inclusion dans la prochaine version. - --- -Alexandre Julliard -julliard@winehq.org +1. INTRODUCTION + +Wine est un programme qui permet d'exécuter les logiciels écrits +pour Microsoft Windows (comprenant les exécutables DOS, Windows 3.x +et Win32) sur un Unix. Il est composé d'un chargeur qui charge et +exécute un binaire Microsoft Windows, ainsi que d'une bibliothèque (appelée +Winelib) qui implémente les appels de l'API de Windows par leur +équivalent Unix ou X11. Cette bibliothèque peut également être utilisée +pour porter du code Win32 vers un exécutable Unix natif. + +Wine est un logiciel libre, distribué sous GNU LGPL; lisez le fichier +LICENSE pour les détails. + +2. DÉMARRAGE RAPIDE + +Quand vous compilez à partir des sources, il est recommandé d'utiliser +l'Installateur de Wine pour construire et installer Wine. À partir du +répertoire racine des sources de Wine (qui contient ce fichier), +exécutez : + +./tools/wineinstall + +Pour exécuter un programme, tapez "wine [options] programme". Pour des +informations complémentaires et des résolutions de problèmes, lisez le +reste de ce fichier, les pages "man" de Wine, et surtout les nombreuses +informations que vous trouverez sur http://www.winehq.org. + +3. CONFIGURATION NÉCESSAIRE + +Pour compiler et exécuter Wine, vous devez avoir un des systèmes +d'exploitation qui suit : + + Linux version 2.0.36 ou ultérieur + FreeBSD 6.3 ou ultérieur + Solaris x86 9 ou ultérieur + NetBSD-current + Mac OS X 10.4 ou ultérieur + +Étant donné que Wine nécessite une implémentation des "threads" (processus +légers) au niveau du noyau, seuls les systèmes d'exploitation mentionnés +ci-haut sont supportés. D'autres systèmes d'exploitation implémentant les +threads noyau peuvent être pris en charge dans le futur. + +Information Linux : + Bien que Linux 2.2.x devrait encore fonctionner et que Linux 2.0.x pourrait + encore marcher (des versions plus anciennes de 2.0.x avaient des plantages + dus aux threads), il est préférable d'avoir un noyau récent tel que 2.4.x + ou 2.6.x. + +Information FreeBSD : + Wine ne fonctionnera généralement pas bien pour les versions FreeBSD + antérieures à 6.3 ou 7.0 (certains patches additionnels sont disponibles pour + FreeBSD 6.3). Voyez pour plus d'informations. + +Information Solaris : + Il est plus que probable que vous devrez construire Wine avec la chaîne + d'outils GNU (gcc, gas, etc.). Attention : installer gas n'assure pas + qu'il sera utilisé par gcc. Recompiler gcc après l'installation de gas + ou créer un lien symbolique de cc, as et ld vers les outils GNU semble + nécessaire. + +Information NetBSD : + Assurez-vous d'avoir les options USER_LDT, SYSVSHM, SYSVSEM et SYSVMSG + activées dans votre noyau. + +Information Mac OS X : + Xcode 2.4 ou ultérieur est nécessaire pour compiler Wine sous x86. + + +Systèmes de fichiers pris en charge : + Wine devrait fonctionner sur la plupart des systèmes de fichiers. Certains + problèmes de compatibilité ont été rapportés lors de l'utilisation de fichiers + accédés via Samba. De plus, NTFS ne fournit pas toutes les fonctionnalités de + système de fichiers nécessaires pour certains applications. L'utilisation d'un + système de fichiers Linux natif comme ext3 est recommandée. + +Configuration requise de base : + Les fichiers "include" de X11 (appelés xlib6g-dev sous Debian et XFree86-devel + sous RedHat) doivent être installés. + + Bien entendu, vous aurez besoin du programme "make" (très probablement GNU + make). + + Flex 2.5 ou ultérieur, ainsi que bison, sont également requis. + +Bibliothèques optionnelles : + "Configure" affichera des messages quand des bibliothèques optionnelles ne + sont pas détectées sur votre système. Consultez + http://wiki.winehq.org/Recommended_Packages (en anglais) pour des indications + sur les paquets logiciels que vous devriez installer. + + Sur les plates-formes 64 bits, vous devez installer les versions 32 bits de + ces bibliothèques. Voyez http://wiki.winehq.org/WineOn64bit (en anglais) pour + les détails. + +4. COMPILATION + +Au cas où vous choisiriez de ne pas utiliser wineinstall, exécutez les commandes +suivantes pour construire Wine : + +./configure +make depend +make + +Cela va construire le programme "wine" et de nombreux binaires/bibliothèques de +support. +Le programme "wine" chargera et exécutera les exécutables Windows. +La bibliothèque "libwine" ("Winelib") peut être utilisée pour compiler et lier +du code source Windows sous Unix. + +Pour voir les options de compilation, tapez ./configure --help. + +Pour mettre à jour vers une nouvelle version en utilisant les fichiers de mise à +niveau, tout d'abord aller dans le répertoire de plus haut niveau de la version +actuelle (celui qui contient ce fichier README.fr). Ensuite faire un "make +clean", et mettre à jour la version avec : + + bunzip2 -c fichier-patch | patch -p1 + +où "fichier-patch" est le nom du fichier de mise à niveau (quelque chose du +genre wine-1.0.x.diff.bz2). Vous pouvez ensuite réexécuter "./configure", et +taper ensuite "make depend && make". + +5. INSTALLATION + +Une fois Wine a été construit correctement, vous pouvez tapez "make install" : +cela installera l'exécutable wine, les pages man Wine et quelques autres +fichiers nécessaires. + +N'oubliez pas de désinstaller toutes les installations précédentes de wine. +Essayez soit "dpkg -r wine", "rpm -e wine" ou "make uninstall" avant +d'installer une nouvelle version. + +Une fois l'installation terminée, vous pouvez naviguer dans la section Support à +http://www.winehq.org/ pour obtenir des astuces de configuration. + + +6. EXÉCUTER DES PROGRAMMES + +Lorsque l'on invoque Wine, vous pouvez spécifier le chemin entier vers +l'exécutable ou seulement le nom de fichier. + +Pour exécuter le bloc-notes par exemple : + + wine notepad (en utilisant le chemin d'accès spécifié + wine notepad.exe dans le fichier "config" pour localiser + le fichier) + + wine c:\\windows\\notepad.exe (en utilisant la syntaxe de fichiers DOS) + + wine ~/.wine/drive_c/windows/notepad.exe (en utilisant la syntaxe Unix) + + wine notepad.exe /paramètre1 -paramètre2 paramètre3 + (en appelant le programme avec des paramètres) + +Wine n'est pas encore terminé ; ainsi quelques programmes peuvent planter. Quand +cela se produit, un débogueur est démarré à l'endroit du plantage pour que vous +puissiez essayer de résoudre le problème. Pour plus d'informations sur la +manière de faire, veuillez lire la section "déboguage" du Guide du développeur +Wine (Wine Developer's Guide). + + +7. INFORMATIONS COMPLÉMENTAIRES + +WWW Beaucoup d'informations à propos de Wine sont disponibles sur WineHQ à + http://www.winehq.org/ : divers guides Wine, base de données + d'applications, suivi de bogues. C'est probablement le meilleur point + de départ. + +FAQ La Foire Aux Questions de Wine se trouve sur http://www.winehq.org/FAQ + +Usenet Vous pouvez parler des problèmes en relation avec Wine + ou obtenir de l'aide sur comp.emulators.ms-windows.wine. + +Bogues Rapportez les bogues à Wine Bugzilla à http://bugs.winehq.org + SVP cherchez tout d'abord dans la base de données de bugzilla + pour contrôler que le problème n'est pas déjà découvert avant + de soumettre un rapport de bogue. Vous pouvez également rapporter + des rapports de bogue à comp.emulators.ms-windows.wine. + SVP lisez le fichier documentation/bugs.sgml pour connaître les + informations nécessaires. + +IRC L'aide en ligne est disponible sur le canal #WineHQ sur + irc.freenode.net. + +GIT L'arbre de développement actuel de Wine est disponible au travers de + GIT. Voyez http://www.winehq.org/site/git pour plus d'informations. + +Listes de diffusion + Il existe de multiples listes de diffusion pour les développeurs Wine ; + voyez http://www.winehq.org/forums pour de plus amples informations. + +Wiki Le wiki Wine est situé sur http://wiki.winehq.org + + +Si vous ajoutez quelque chose ou corrigez un bogue, envoyez un correctif (dans le +format 'diff -u' ) à la liste de diffusion wine-patches@winehq.org pour qu'il +soit inclus dans la prochaine version. + +-- +Alexandre Julliard +julliard@winehq.org diff --git a/include/Makefile.in b/include/Makefile.in index 3d80857af41..c62b85fbb06 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -176,6 +176,7 @@ SRCDIR_INCLUDES = \ ddk/winddiui.h \ ddk/winsplp.h \ ddraw.h \ + ddrawgdi.h \ ddrawi.h \ devenum.idl \ devguid.h \ diff --git a/include/commctrl.h b/include/commctrl.h index 6347dffc907..b064c01537d 100644 --- a/include/commctrl.h +++ b/include/commctrl.h @@ -3652,6 +3652,8 @@ typedef struct LVTILEINFO int iItem; UINT cColumns; PUINT puColumns; + /* (_WIN32_WINNT >= 0x0600) */ + int* piColFmt; } LVTILEINFO, *PLVTILEINFO; typedef struct LVTILEVIEWINFO diff --git a/include/config.h.in b/include/config.h.in index c94523ed0ea..c113fcb4662 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -699,6 +699,9 @@ /* Define to 1 if you have the `statvfs' function. */ #undef HAVE_STATVFS +/* Define to 1 if you have the header file. */ +#undef HAVE_STDBOOL_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H @@ -1188,15 +1191,26 @@ /* Define to 1 if the X Window System is missing or not being used. */ #undef X_DISPLAY_MISSING +/* Define to a macro to define an assembly function */ +#undef __ASM_DEFINE_FUNC + /* Define to a macro to generate an assembly function directive */ #undef __ASM_FUNC -/* Define to a macro to generate an assembly function */ +/* Define to a macro to generate an assembly function with C calling + convention */ #undef __ASM_GLOBAL_FUNC /* Define to a macro to generate an assembly name from a C symbol */ #undef __ASM_NAME +/* Define to a macro to generate an stdcall suffix */ +#undef __ASM_STDCALL + +/* Define to a macro to generate an assembly function with stdcall calling + convention */ +#undef __ASM_STDCALL_FUNC + /* Define to empty if `const' does not conform to ANSI C. */ #undef const diff --git a/include/d3dx9mesh.h b/include/d3dx9mesh.h index 39ad28a5d89..9e0b333024a 100644 --- a/include/d3dx9mesh.h +++ b/include/d3dx9mesh.h @@ -26,6 +26,7 @@ extern "C" { #endif HRESULT WINAPI D3DXCreateBuffer(DWORD, LPD3DXBUFFER*); +UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx); UINT WINAPI D3DXGetFVFVertexSize(DWORD); BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *); BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *,FLOAT,CONST D3DXVECTOR3 *,CONST D3DXVECTOR3 *); diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 3169153c6c5..ccdeca3f9a3 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -124,13 +124,19 @@ typedef enum _KWAIT_REASON MaximumWaitReason, } KWAIT_REASON; +typedef struct _ALLOCATE_FUNCTION *PALLOCATE_FUNCTION; typedef struct _IO_TIMER *PIO_TIMER; +typedef struct _IO_TIMER_ROUTINE *PIO_TIMER_ROUTINE; typedef struct _ETHREAD *PETHREAD; +typedef struct _FREE_FUNCTION *PFREE_FUNCTION; typedef struct _KTHREAD *PKTHREAD; typedef struct _EPROCESS *PEPROCESS; +typedef struct _ERESOURCE *PERESOURCE; typedef struct _IO_WORKITEM *PIO_WORKITEM; +typedef struct _NPAGED_LOOKASIDE_LIST *PNPAGED_LOOKASIDE_LIST; typedef struct _OBJECT_TYPE *POBJECT_TYPE; typedef struct _OBJECT_HANDLE_INFORMATION *POBJECT_HANDLE_INFORMATION; +typedef struct _ZONE_HEADER *PZONE_HEADER; typedef struct _FAST_MUTEX { diff --git a/dlls/oleacc/oleacc.rc b/include/ddrawgdi.h similarity index 69% copy from dlls/oleacc/oleacc.rc copy to include/ddrawgdi.h index 3be579a746c..9aea733df68 100644 --- a/dlls/oleacc/oleacc.rc +++ b/include/ddrawgdi.h @@ -1,7 +1,7 @@ /* - * Top level resource file for oleacc + * Ddrawgdi definitions * - * Copyright 2008 Nikolay Sivov + * Copyright (C) 2009 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,12 +18,19 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "windef.h" -#include "oleacc.h" +#ifndef __WINE_DDRAWGDI_H +#define __WINE_DDRAWGDI_H -#include "oleacc_De.rc" -#include "oleacc_En.rc" -#include "oleacc_Fr.rc" -#include "oleacc_Ko.rc" -#include "oleacc_Nl.rc" -#include "oleacc_Pl.rc" +#ifdef __cplusplus +extern "C" { +#endif + +#define DdQueryDisplaySettingsUniqueness GdiEntry13 + +ULONG APIENTRY DdQueryDisplaySettingsUniqueness(VOID); + +#ifdef __cplusplus +} +#endif + +#endif /* __WINE_DDRAWGDI_H */ diff --git a/include/shlobj.h b/include/shlobj.h index a608a7e359d..01f8368c0b7 100644 --- a/include/shlobj.h +++ b/include/shlobj.h @@ -77,6 +77,7 @@ VOID WINAPI SHUpdateImageW(LPCWSTR,INT,UINT,INT); #define SHUpdateImage WINELIB_NAME_AW(SHUpdateImage) int WINAPI RestartDialog(HWND,LPCWSTR,DWORD); int WINAPI RestartDialogEx(HWND,LPCWSTR,DWORD,DWORD); +BOOL WINAPI IsUserAnAdmin(void); #define SHFMT_ERROR 0xFFFFFFFFL /* Error on last format, drive may be formattable */ #define SHFMT_CANCEL 0xFFFFFFFEL /* Last format was cancelled */ diff --git a/include/wine/exception.h b/include/wine/exception.h index 007688f8784..7f013490a80 100644 --- a/include/wine/exception.h +++ b/include/wine/exception.h @@ -213,6 +213,18 @@ static inline EXCEPTION_REGISTRATION_RECORD *__wine_pop_frame( EXCEPTION_REGISTR #endif } +static inline EXCEPTION_REGISTRATION_RECORD *__wine_get_frame(void) +{ +#if defined(__GNUC__) && defined(__i386__) + EXCEPTION_REGISTRATION_RECORD *ret; + __asm__ __volatile__(".byte 0x64\n\tmovl (0),%0" : "=r" (ret) ); + return ret; +#else + NT_TIB *teb = (NT_TIB *)NtCurrentTeb(); + return teb->ExceptionList; +#endif +} + /* Exception handling flags - from OS/2 2.0 exception handling */ /* Win32 seems to use the same flags as ExceptionFlags in an EXCEPTION_RECORD */ @@ -238,26 +250,36 @@ extern void __wine_enter_vm86( CONTEXT *context ); NTSYSAPI void WINAPI RtlUnwind(PVOID,PVOID,PEXCEPTION_RECORD,PVOID); +static inline void DECLSPEC_NORETURN __wine_unwind_target(void) +{ + __WINE_FRAME *wine_frame = (__WINE_FRAME *)__wine_get_frame(); + __wine_pop_frame( &wine_frame->frame ); + siglongjmp( wine_frame->jmp, 1 ); +} + /* wrapper for RtlUnwind since it clobbers registers on Windows */ -static inline void __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame, EXCEPTION_RECORD *record ) +static inline void DECLSPEC_NORETURN __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame, + EXCEPTION_RECORD *record, + void (*target)(void) ) { #if defined(__GNUC__) && defined(__i386__) - int dummy1, dummy2, dummy3; + int dummy1, dummy2, dummy3, dummy4; __asm__ __volatile__("pushl %%ebp\n\t" "pushl %%ebx\n\t" "pushl $0\n\t" + "pushl %3\n\t" "pushl %2\n\t" - "pushl $0\n\t" "pushl %1\n\t" "call *%0\n\t" "popl %%ebx\n\t" "popl %%ebp" - : "=a" (dummy1), "=S" (dummy2), "=D" (dummy3) - : "0" (RtlUnwind), "1" (frame), "2" (record) - : "ecx", "edx", "memory" ); + : "=a" (dummy1), "=S" (dummy2), "=D" (dummy3), "=c" (dummy4) + : "0" (RtlUnwind), "1" (frame), "2" (target), "3" (record) + : "edx", "memory" ); #else - RtlUnwind( frame, 0, record, 0 ); + RtlUnwind( frame, target, record, 0 ); #endif + for (;;) target(); } static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *record, @@ -269,9 +291,7 @@ static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *reco wine_frame->ExceptionCode = record->ExceptionCode; wine_frame->ExceptionRecord = wine_frame; - __wine_rtl_unwind( frame, record ); - __wine_pop_frame( frame ); - siglongjmp( wine_frame->jmp, 1 ); + __wine_rtl_unwind( frame, record, __wine_unwind_target ); } static inline DWORD __wine_exception_handler( EXCEPTION_RECORD *record, diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl index 58550822f2b..31222f3c724 100644 --- a/include/wine/wined3d.idl +++ b/include/wine/wined3d.idl @@ -1724,15 +1724,15 @@ typedef struct _WINED3DPRESENT_PARAMETERS typedef struct _WINED3DSURFACE_DESC { - WINED3DFORMAT *Format; - WINED3DRESOURCETYPE *Type; - DWORD *Usage; - WINED3DPOOL *Pool; - UINT *Size; - WINED3DMULTISAMPLE_TYPE *MultiSampleType; - DWORD *MultiSampleQuality; - UINT *Width; - UINT *Height; + WINED3DFORMAT format; + WINED3DRESOURCETYPE resource_type; + DWORD usage; + WINED3DPOOL pool; + UINT size; + WINED3DMULTISAMPLE_TYPE multisample_type; + DWORD multisample_quality; + UINT width; + UINT height; } WINED3DSURFACE_DESC; typedef struct _WINED3DVOLUME_DESC diff --git a/include/wininet.h b/include/wininet.h index e37700af23c..fb6f31f879e 100644 --- a/include/wininet.h +++ b/include/wininet.h @@ -1536,6 +1536,12 @@ typedef struct _INTERNET_CACHE_ENTRY_INFOW { DECL_WINELIB_TYPE_AW(INTERNET_CACHE_ENTRY_INFO) DECL_WINELIB_TYPE_AW(LPINTERNET_CACHE_ENTRY_INFO) +typedef struct _INTERNET_CACHE_TIMESTAMPS +{ + FILETIME ftExpires; + FILETIME ftLastModified; +} INTERNET_CACHE_TIMESTAMPS, *LPINTERNET_CACHE_TIMESTAMPS; + BOOLAPI CreateUrlCacheEntryA(LPCSTR ,DWORD ,LPCSTR ,LPSTR ,DWORD); BOOLAPI CreateUrlCacheEntryW(LPCWSTR ,DWORD ,LPCWSTR ,LPWSTR ,DWORD); #define CreateUrlCacheEntry WINELIB_NAME_AW(CreateUrlCacheEntry) diff --git a/libs/wine/port.c b/libs/wine/port.c index 65f49123e11..63070693082 100644 --- a/libs/wine/port.c +++ b/libs/wine/port.c @@ -53,30 +53,7 @@ void wine_pthread_set_functions( const struct wine_pthread_functions *functions, * * Switch to the specified stack and call the function. */ -void DECLSPEC_NORETURN wine_switch_to_stack( void (*func)(void *), void *arg, void *stack ); -#if defined(__i386__) && defined(__GNUC__) -__ASM_GLOBAL_FUNC( wine_switch_to_stack, - "movl 4(%esp),%ecx\n\t" /* func */ - "movl 8(%esp),%edx\n\t" /* arg */ - "movl 12(%esp),%esp\n\t" /* stack */ - "andl $~15,%esp\n\t" - "subl $12,%esp\n\t" - "pushl %edx\n\t" - "xorl %ebp,%ebp\n\t" - "call *%ecx\n\t" - "int $3" /* we never return here */ ) -#elif defined(__i386__) && defined(_MSC_VER) -__declspec(naked) void wine_switch_to_stack( void (*func)(void *), void *arg, void *stack ) -{ - __asm mov ecx, 4[esp]; - __asm mov edx, 8[esp]; - __asm mov esp, 12[esp]; - __asm push edx; - __asm xor ebp, ebp; - __asm call [ecx]; - __asm int 3; -} -#elif defined(__sparc__) && defined(__GNUC__) +#if defined(__sparc__) && defined(__GNUC__) __ASM_GLOBAL_FUNC( wine_switch_to_stack, "mov %o0, %l0\n\t" /* store first argument */ "mov %o1, %l1\n\t" /* store second argument */ @@ -92,16 +69,6 @@ __ASM_GLOBAL_FUNC( wine_switch_to_stack, "subi r1,r1,0x100\n\t" /* adjust stack pointer */ "bctrl\n" /* call ctr */ "1:\tb 1b") /* loop */ -#elif defined(__powerpc__) && defined(__GNUC__) -__ASM_GLOBAL_FUNC( wine_switch_to_stack, - "mtctr 3\n\t" /* func -> ctr */ - "mr 3,4\n\t" /* args -> function param 1 (r3) */ - "mr 1,5\n\t" /* stack */ - "subi 1, 1, 16\n\t" /* allocate space for the callee */ - "li 0, 0\n\t" /* load zero */ - "stw 0, 0(1)\n\t" /* create a bottom stack frame */ - "bctrl\n\t" /* call ctr */ - "1:\tb 1b") /* loop */ #elif defined(__ALPHA__) && defined(__GNUC__) __ASM_GLOBAL_FUNC( wine_switch_to_stack, "mov $16,$0\n\t" /* func */ @@ -109,15 +76,6 @@ __ASM_GLOBAL_FUNC( wine_switch_to_stack, "mov $18,$30\n\t" /* stack */ "jsr $31,($0),0\n\t" /* call func */ "L1:\tbr $31,L1") /* loop */ -#elif defined(__x86_64__) && defined(__GNUC__) -__ASM_GLOBAL_FUNC( wine_switch_to_stack, - "movq %rdi,%rax\n\t" /* func */ - "movq %rsi,%rdi\n\t" /* arg */ - "andq $~15,%rdx\n\t" /* stack */ - "movq %rdx,%rsp\n\t" - "xorq %rbp,%rbp\n\t" - "callq *%rax\n\t" /* call func */ - "int $3") #else void DECLSPEC_NORETURN wine_switch_to_stack( void (*func)(void *), void *arg, void *stack ) { @@ -170,17 +128,20 @@ __declspec(naked) int wine_call_on_stack( int (*func)(void *), void *arg, void * #elif defined(__x86_64__) && defined(__GNUC__) __ASM_GLOBAL_FUNC( wine_call_on_stack, "pushq %rbp\n\t" - "pushq %rbx\n\t" - "movq %rsp,%rbx\n\t" + ".cfi_adjust_cfa_offset 8\n\t" + ".cfi_rel_offset %rbp,0\n\t" + "movq %rsp,%rbp\n\t" + ".cfi_def_cfa_register %rbp\n\t" "movq %rdi,%rax\n\t" /* func */ "movq %rsi,%rdi\n\t" /* arg */ "andq $~15,%rdx\n\t" /* stack */ "movq %rdx,%rsp\n\t" - "xorq %rbp,%rbp\n\t" "callq *%rax\n\t" /* call func */ - "movq %rbx,%rsp\n\t" - "popq %rbx\n\t" + "movq %rbp,%rsp\n\t" + ".cfi_def_cfa_register %rsp\n\t" "popq %rbp\n\t" + ".cfi_adjust_cfa_offset -8\n\t" + ".cfi_same_value %rbp\n\t" "ret") #elif defined(__powerpc__) && defined(__GNUC__) __ASM_GLOBAL_FUNC( wine_call_on_stack, diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 0044f70dcf0..157ad08071d 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -366,7 +366,7 @@ void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable, WCHAR *forValu WINE_TRACE("Looking backwards for parameter id: %s / %s\n", wine_dbgstr_w(lastModifier), wine_dbgstr_w(forVariable)); - if (!justFors && context && (*lastModifier >= '0' || *lastModifier <= '9')) { + if (!justFors && context && (*lastModifier >= '0' && *lastModifier <= '9')) { /* Its a valid parameter identifier - OK */ break; @@ -571,10 +571,7 @@ void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable, WCHAR *forValu if (!doneModifier) strcpyW(finaloutput, outputparam); /* Finish by inserting the replacement into the string */ - pos = WCMD_strdupW(lastModifier+1); - strcpyW(*start, finaloutput); - strcatW(*start, pos); - free(pos); + WCMD_strsubstW(*start, lastModifier+1, finaloutput, -1); } /******************************************************************* diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index bcdf840e7bc..0e99f52659b 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -1033,7 +1033,7 @@ void WCMD_part_execute(CMD_LIST **cmdList, WCHAR *firstcmd, WCHAR *variable, if (conditionTRUE && firstcmd && *firstcmd) { WCHAR *command = WCMD_strdupW(firstcmd); WCMD_execute (firstcmd, (*cmdList)->redirects, variable, value, cmdList); - free (command); + HeapFree(GetProcessHeap(), 0, command); } diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 67aab421efc..4d3bab6621a 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -101,6 +101,7 @@ void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable, WCHAR *forValu void WCMD_splitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext); WCHAR *WCMD_LoadMessage(UINT id); WCHAR *WCMD_strdupW(WCHAR *input); +void WCMD_strsubstW(WCHAR *start, WCHAR* next, WCHAR* insert, int len); BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars, LPDWORD charsRead, const LPOVERLAPPED unused); diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index c58077bd80d..d3aea6d6b5a 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -416,12 +416,27 @@ static void WCMD_show_prompt (void) { */ WCHAR *WCMD_strdupW(WCHAR *input) { int len=strlenW(input)+1; - /* Note: Use malloc not HeapAlloc to emulate strdup */ - WCHAR *result = malloc(len * sizeof(WCHAR)); + WCHAR *result = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); memcpy(result, input, len * sizeof(WCHAR)); return result; } +/************************************************************************* + * WCMD_strsubstW + * Replaces a portion of a Unicode string with the specified string. + * It's up to the caller to ensure there is enough space in the + * destination buffer. + */ +void WCMD_strsubstW(WCHAR* start, WCHAR* next, WCHAR* insert, int len) { + + if (len < 0) + len=insert ? lstrlenW(insert) : 0; + if (start+len != next) + memmove(start+len, next, (strlenW(next) + 1) * sizeof(*next)); + if (insert) + memcpy(start, insert, len * sizeof(*insert)); +} + /*************************************************************************** * WCMD_strtrim_leading_spaces * @@ -493,9 +508,7 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forVar, WCHAR *forVal) { /* In batch program, missing terminator for % and no following ':' just removes the '%' */ if (context) { - s = WCMD_strdupW(start + 1); - strcpyW (start, s); - free(s); + WCMD_strsubstW(start, start + 1, NULL, 0); return start; } else { @@ -608,24 +621,20 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forVar, WCHAR *forVal) { /* Command line - just ignore this */ if (context == NULL) return endOfVar+1; - s = WCMD_strdupW(endOfVar + 1); /* Batch - replace unknown env var with nothing */ if (colonpos == NULL) { - strcpyW (start, s); - + WCMD_strsubstW(start, endOfVar + 1, NULL, 0); } else { len = strlenW(thisVar); thisVar[len-1] = 0x00; /* If %:...% supplied, : is retained */ if (colonpos == thisVar+1) { - strcpyW (start, colonpos); + WCMD_strsubstW(start, endOfVar + 1, colonpos, -1); } else { - strcpyW (start, colonpos+1); + WCMD_strsubstW(start, endOfVar + 1, colonpos + 1, -1); } - strcatW (start, s); } - free (s); return start; } @@ -633,10 +642,7 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forVar, WCHAR *forVal) { /* See if we need to do complex substitution (any ':'s), if not then our work here is done */ if (colonpos == NULL) { - s = WCMD_strdupW(endOfVar + 1); - strcpyW (start, thisVarContents); - strcatW (start, s); - free(s); + WCMD_strsubstW(start, endOfVar + 1, thisVarContents, -1); return start; } @@ -664,8 +670,6 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forVar, WCHAR *forVal) { substrposition = atolW(colonpos+2); if (commapos) substrlength = atolW(commapos+1); - s = WCMD_strdupW(endOfVar + 1); - /* Check bounds */ if (substrposition >= 0) { startCopy = &thisVarContents[min(substrposition, len)]; @@ -674,21 +678,18 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forVar, WCHAR *forVal) { } if (commapos == NULL) { - strcpyW (start, startCopy); /* Copy the lot */ + /* Copy the lot */ + WCMD_strsubstW(start, endOfVar + 1, startCopy, -1); } else if (substrlength < 0) { int copybytes = (len+substrlength-1)-(startCopy-thisVarContents); if (copybytes > len) copybytes = len; else if (copybytes < 0) copybytes = 0; - memcpy (start, startCopy, copybytes * sizeof(WCHAR)); /* Copy the lot */ - start[copybytes] = 0x00; + WCMD_strsubstW(start, endOfVar + 1, startCopy, copybytes); } else { - memcpy (start, startCopy, substrlength * sizeof(WCHAR)); /* Copy the lot */ - start[substrlength] = 0x00; + WCMD_strsubstW(start, endOfVar + 1, startCopy, substrlength); } - strcatW (start, s); - free(s); return start; /* search and replace manipulation */ @@ -723,7 +724,7 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forVar, WCHAR *forVal) { strcatW(start, thisVarContents + (found-searchIn) + strlenW(searchFor+1)); strcatW(start, s); } else { - /* Copy as it */ + /* Copy as is */ strcpyW(start, thisVarContents); strcatW(start, s); } @@ -747,9 +748,9 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forVar, WCHAR *forVal) { thisVarContents + (lastFound-searchIn)); strcatW(outputposn, s); } - free(s); - free(searchIn); - free(searchFor); + HeapFree(GetProcessHeap(), 0, s); + HeapFree(GetProcessHeap(), 0, searchIn); + HeapFree(GetProcessHeap(), 0, searchFor); return start; } return start+1; @@ -772,7 +773,7 @@ static void handleExpansion(WCHAR *cmd, BOOL justFors, WCHAR *forVariable, WCHAR /* manual expansion of environment variables here */ WCHAR *p = cmd; - WCHAR *s, *t; + WCHAR *t; int i; while ((p = strchrW(p, '%'))) { @@ -784,9 +785,7 @@ static void handleExpansion(WCHAR *cmd, BOOL justFors, WCHAR *forVariable, WCHAR /* Don't touch %% unless its in Batch */ if (!justFors && *(p+1) == '%') { if (context) { - s = WCMD_strdupW(p+1); - strcpyW (p, s); - free (s); + WCMD_strsubstW(p, p+1, NULL, 0); } p+=1; @@ -797,21 +796,17 @@ static void handleExpansion(WCHAR *cmd, BOOL justFors, WCHAR *forVariable, WCHAR /* Replace use of %0...%9 if in batch program*/ } else if (!justFors && context && (i >= 0) && (i <= 9)) { - s = WCMD_strdupW(p+2); t = WCMD_parameter (context -> command, i + context -> shift_count[i], NULL); - strcpyW (p, t); - strcatW (p, s); - free (s); + WCMD_strsubstW(p, p+2, t, -1); /* Replace use of %* if in batch program*/ } else if (!justFors && context && *(p+1)=='*') { WCHAR *startOfParms = NULL; - s = WCMD_strdupW(p+2); t = WCMD_parameter (context -> command, 1, &startOfParms); - if (startOfParms != NULL) strcpyW (p, startOfParms); - else *p = 0x00; - strcatW (p, s); - free (s); + if (startOfParms != NULL) + WCMD_strsubstW(p, p+2, startOfParms, -1); + else + WCMD_strsubstW(p, p+2, NULL, 0); } else if (forVariable && (CompareString (LOCALE_USER_DEFAULT, @@ -819,10 +814,7 @@ static void handleExpansion(WCHAR *cmd, BOOL justFors, WCHAR *forVariable, WCHAR p, strlenW(forVariable), forVariable, -1) == 2)) { - s = WCMD_strdupW(p + strlenW(forVariable)); - strcpyW(p, forValue); - strcatW(p, s); - free(s); + WCMD_strsubstW(p, p + strlenW(forVariable), forValue, -1); } else if (!justFors) { p = WCMD_expand_envvar(p, forVariable, forValue); diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c index 55b0d5fbdc7..c46edc6b369 100644 --- a/programs/regedit/regproc.c +++ b/programs/regedit/regproc.c @@ -610,20 +610,29 @@ static void processRegEntry(WCHAR* stdInput, BOOL isUnicode) * * Parameters: * in - input stream to read from + * first_chars - beginning of stream, read due to Unicode check */ -static void processRegLinesA(FILE *in) +static void processRegLinesA(FILE *in, char* first_chars) { LPSTR line = NULL; /* line read from input stream */ ULONG lineSize = REG_VAL_BUF_SIZE; line = HeapAlloc(GetProcessHeap(), 0, lineSize); CHECK_ENOUGH_MEMORY(line); + memcpy(line, first_chars, 2); while (!feof(in)) { LPSTR s; /* The pointer into line for where the current fgets should read */ LPSTR check; WCHAR* lineW; s = line; + + if(first_chars) + { + s += 2; + first_chars = NULL; + } + for (;;) { size_t size_remaining; int size_to_get; @@ -1373,8 +1382,7 @@ BOOL import_registry_file(FILE* reg_file) processRegLinesW(reg_file); } else { - rewind(reg_file); - processRegLinesA(reg_file); + processRegLinesA(reg_file, (char*)s); } } return TRUE; diff --git a/programs/winecfg/Es.rc b/programs/winecfg/Es.rc index 6bf7df729a5..1505a223699 100644 --- a/programs/winecfg/Es.rc +++ b/programs/winecfg/Es.rc @@ -2,7 +2,7 @@ * WineCfg resources * Spanish Language Support * - * Copyright 2003-2008 José Manuel Ferrer Ortiz + * Copyright 2003-2009 José Manuel Ferrer Ortiz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -52,9 +52,9 @@ FONT 8, "MS Shell Dlg" BEGIN GROUPBOX " Configuración de aplicaciones ",IDC_STATIC, 8,4,244,240 LTEXT "Wine puede imitar distintas versiones de Windows para cada aplicación. Esta pestaña está enlazada a las de Librerías y Gráficos para poder cambiar en ellas la configuración global y/o la de por aplicación.", - IDC_STATIC,15,20,227,32 + IDC_STATIC,15,16,227,32 CONTROL "Aplicaciones",IDC_APP_LISTVIEW,"SysListView32",WS_BORDER | WS_TABSTOP | LVS_LIST | LVS_SINGLESEL | LVS_SHOWSELALWAYS, - 15,56,230,144 + 15,50,230,150 PUSHBUTTON "&Añadir aplicación...",IDC_APP_ADDAPP, 90,204,75,14 PUSHBUTTON "&Eliminar aplicación...",IDC_APP_REMOVEAPP, 170,204,75,14 LTEXT "&Versión a imitar:",IDC_STATIC,17,226,58,16 @@ -67,7 +67,7 @@ FONT 8, "MS Shell Dlg" BEGIN GROUPBOX " Configuración de ventanas ",IDC_STATIC,8,4,244,84 CONTROL "Permitir a los programas DirectX retener el ratón en sus ventanas",IDC_DX_MOUSE_GRAB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,20,230,8 - CONTROL "Allow the window manager to &decorate the windows",IDC_ENABLE_DECORATED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,32,230,8 + CONTROL "Permitir al gestor de ventanas decorar las ventanas",IDC_ENABLE_DECORATED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,32,230,8 CONTROL "Permitir al gestor de ventanas controlar las ventanas",IDC_ENABLE_MANAGED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,44,230,8 CONTROL "Emular un escritorio virtual",IDC_ENABLE_DESKTOP,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,15,56,230,8 @@ -81,11 +81,11 @@ BEGIN COMBOBOX IDC_D3D_VSHADER_MODE,100,108,145,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Permitir Pixel Shader (si hay soporte por hardware)",IDC_D3D_PSHADER_MODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,126,230,10 - GROUPBOX " Screen &Resolution ",IDC_STATIC,8,151,244,93 + GROUPBOX " Resolución de pantalla ",IDC_STATIC,8,151,244,93 CONTROL "", IDC_RES_TRACKBAR, "msctls_trackbar32",WS_TABSTOP,12,161,187,15 EDITTEXT IDC_RES_DPIEDIT,204,161,23,13,ES_NUMBER|WS_TABSTOP - LTEXT "dpi",IDC_STATIC,235,163,10,8 - LTEXT "This is a sample text using 10 point Tahoma",IDC_RES_FONT_PREVIEW,15,181,230,55 + LTEXT "ppp",IDC_STATIC,235,163,10,8 + LTEXT "Esto es un texto de ejemplo usando Tahoma de 10 puntos",IDC_RES_FONT_PREVIEW,15,181,230,55 END IDD_DLLCFG DIALOG DISCARDABLE 0, 0, 260, 250 @@ -124,12 +124,12 @@ STYLE WS_CHILD | WS_DISABLED FONT 8, "MS Shell Dlg" BEGIN GROUPBOX " Mapeos de unidad ",IDC_STATIC,8,4,244,240 - LTEXT "Failed to connect to the mount manager, the drive configuration cannot be edited.", IDC_STATIC_MOUNTMGR_ERROR, 15,30,220,76 + LTEXT "Conexión fallida al gestor de montaje, la configuración de unidades no se puede editar.", IDC_STATIC_MOUNTMGR_ERROR, 15,30,220,76 CONTROL "Listview",IDC_LIST_DRIVES,"SysListView32",LVS_REPORT | LVS_AUTOARRANGE | LVS_ALIGNLEFT | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP, 15,18,232,76 PUSHBUTTON "&Añadir...",IDC_BUTTON_ADD,15,98,37,14 PUSHBUTTON "&Eliminar",IDC_BUTTON_REMOVE,56,98,37,14 - PUSHBUTTON "Auto&detectar...",IDC_BUTTON_AUTODETECT,197,98,49,14 + PUSHBUTTON "Auto&detectar...",IDC_BUTTON_AUTODETECT,187,98,59,14 /* editing drive details */ LTEXT "&Ruta:",IDC_STATIC_PATH,15,123,20,9 @@ -317,7 +317,7 @@ BEGIN IDC_SYSPARAMS_BUTTON_DARK_SHADOW "Sombra oscura del control" IDC_SYSPARAMS_BUTTON_LIGHT "Parte iluminada del control" IDC_SYSPARAMS_BUTTON_ALTERNATE "Fondo alternativo del control" - IDC_SYSPARAMS_HOT_TRACKING "Elemento Hot Tracked" + IDC_SYSPARAMS_HOT_TRACKING "Elemento resaltado" IDC_SYSPARAMS_ACTIVE_TITLE_GRADIENT "Gradiente barra título activa" IDC_SYSPARAMS_INACTIVE_TITLE_GRADIENT "Gradiente barra título inactiva" IDC_SYSPARAMS_MENU_HILIGHT "Resaltado del menú" diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index fcdc356a2e7..cd3506bec0f 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -50,7 +50,8 @@ * shared location for an "All Users" entry then do so. As a suggestion the * shared menu Wine base could be writable to the wine group, or a wineadm * group. - * Clean up fd.o menus when they are deleted in Windows. + * Clean up fd.o menu icons and .directory files when the menu is deleted + * in Windows. * Generate icons for file open handlers to go into the "Open with..." * list. What does Windows use, the default icon for the .EXE file? It's * not in the registry. @@ -809,13 +810,23 @@ static char *extract_icon( LPCWSTR path, int index, BOOL bWait ) return xpm_path; } -static BOOL write_desktop_entry(const char *location, const char *linkname, const char *path, - const char *args, const char *descr, const char *workdir, - const char *icon) +static HKEY open_menus_reg_key(void) +{ + static const WCHAR Software_Wine_FileOpenAssociationsW[] = { + 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','M','e','n','u','F','i','l','e','s',0}; + HKEY assocKey; + if (RegCreateKeyW(HKEY_CURRENT_USER, Software_Wine_FileOpenAssociationsW, &assocKey) == ERROR_SUCCESS) + return assocKey; + return NULL; +} + +static BOOL write_desktop_entry(const char *unix_link, const char *location, const char *linkname, + const char *path, const char *args, const char *descr, + const char *workdir, const char *icon) { FILE *file; - WINE_TRACE("(%s,%s,%s,%s,%s,%s,%s)\n", wine_dbgstr_a(location), + WINE_TRACE("(%s,%s,%s,%s,%s,%s,%s,%s)\n", wine_dbgstr_a(unix_link), wine_dbgstr_a(location), wine_dbgstr_a(linkname), wine_dbgstr_a(path), wine_dbgstr_a(args), wine_dbgstr_a(descr), wine_dbgstr_a(workdir), wine_dbgstr_a(icon)); @@ -837,6 +848,19 @@ static BOOL write_desktop_entry(const char *location, const char *linkname, cons fprintf(file, "Icon=%s\n", icon); fclose(file); + + if (unix_link) + { + HKEY hkey = open_menus_reg_key(); + if (hkey) + { + RegSetValueExA(hkey, location, 0, REG_SZ, (BYTE*) unix_link, lstrlenA(unix_link) + 1); + RegCloseKey(hkey); + } + else + return FALSE; + } + return TRUE; } @@ -867,7 +891,7 @@ static BOOL write_directory_entry(const char *directory, const char *location) return TRUE; } -static BOOL write_menu_file(const char *filename) +static BOOL write_menu_file(const char *unix_link, const char *filename) { char *tempfilename; FILE *tempfile = NULL; @@ -958,12 +982,21 @@ end: if (!ret && tempfilename) remove(tempfilename); free(tempfilename); + if (ret) + { + HKEY hkey = open_menus_reg_key(); + if (hkey) + { + RegSetValueExA(hkey, menuPath, 0, REG_SZ, (BYTE*) unix_link, lstrlenA(unix_link) + 1); + RegCloseKey(hkey); + } + } HeapFree(GetProcessHeap(), 0, name); HeapFree(GetProcessHeap(), 0, menuPath); return ret; } -static BOOL write_menu_entry(const char *link, const char *path, const char *args, +static BOOL write_menu_entry(const char *unix_link, const char *link, const char *path, const char *args, const char *descr, const char *workdir, const char *icon) { const char *linkname; @@ -972,9 +1005,9 @@ static BOOL write_menu_entry(const char *link, const char *path, const char *arg char *filename = NULL; BOOL ret = TRUE; - WINE_TRACE("(%s, %s, %s, %s, %s, %s)\n", wine_dbgstr_a(link), wine_dbgstr_a(path), - wine_dbgstr_a(args), wine_dbgstr_a(descr), wine_dbgstr_a(workdir), - wine_dbgstr_a(icon)); + WINE_TRACE("(%s, %s, %s, %s, %s, %s, %s)\n", wine_dbgstr_a(unix_link), wine_dbgstr_a(link), + wine_dbgstr_a(path), wine_dbgstr_a(args), wine_dbgstr_a(descr), + wine_dbgstr_a(workdir), wine_dbgstr_a(icon)); linkname = strrchr(link, '/'); if (linkname == NULL) @@ -998,7 +1031,7 @@ static BOOL write_menu_entry(const char *link, const char *path, const char *arg goto end; } *desktopDir = '/'; - if (!write_desktop_entry(desktopPath, linkname, path, args, descr, workdir, icon)) + if (!write_desktop_entry(unix_link, desktopPath, linkname, path, args, descr, workdir, icon)) { WINE_WARN("couldn't make desktop entry %s\n", wine_dbgstr_a(desktopPath)); ret = FALSE; @@ -1006,7 +1039,7 @@ static BOOL write_menu_entry(const char *link, const char *path, const char *arg } filename = heap_printf("wine/%s.desktop", link); - if (!filename || !write_menu_file(filename)) + if (!filename || !write_menu_file(unix_link, filename)) { WINE_WARN("couldn't make menu file %s\n", wine_dbgstr_a(filename)); ret = FALSE; @@ -2014,6 +2047,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait ) int iIconId = 0, r = -1; DWORD csidl = -1; HANDLE hsem = NULL; + char *unix_link = NULL; if ( !link ) { @@ -2078,6 +2112,13 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait ) wine_dbgstr_w( szIconPath[0] ? szIconPath : szPath )); } + unix_link = wine_get_unix_file_name(link); + if (unix_link == NULL) + { + WINE_WARN("couldn't find unix path of %s\n", wine_dbgstr_w(link)); + goto cleanup; + } + /* check the path */ if( szPath[0] ) { @@ -2145,12 +2186,12 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait ) location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry); if (location) { - r = !write_desktop_entry(location, lastEntry, escaped_path, escaped_args, escaped_description, work_dir, icon_name); + r = !write_desktop_entry(NULL, location, lastEntry, escaped_path, escaped_args, escaped_description, work_dir, icon_name); HeapFree(GetProcessHeap(), 0, location); } } else - r = !write_menu_entry(link_name, escaped_path, escaped_args, escaped_description, work_dir, icon_name); + r = !write_menu_entry(unix_link, link_name, escaped_path, escaped_args, escaped_description, work_dir, icon_name); ReleaseSemaphore( hsem, 1, NULL ); @@ -2162,6 +2203,7 @@ cleanup: HeapFree( GetProcessHeap(), 0, escaped_args ); HeapFree( GetProcessHeap(), 0, escaped_path ); HeapFree( GetProcessHeap(), 0, escaped_description ); + HeapFree( GetProcessHeap(), 0, unix_link); if (r && !bWait) WINE_ERR("failed to build the menu\n" ); @@ -2179,6 +2221,7 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link HANDLE hSem = NULL; BOOL ret = TRUE; int r = -1; + char *unix_link = NULL; if ( !link ) { @@ -2207,6 +2250,13 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link } WINE_TRACE("path : %s\n", wine_dbgstr_w(urlPath)); + unix_link = wine_get_unix_file_name(link); + if (unix_link == NULL) + { + WINE_WARN("couldn't find unix path of %s\n", wine_dbgstr_w(link)); + goto cleanup; + } + escaped_urlPath = escape(urlPath); hSem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore"); @@ -2227,12 +2277,12 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry); if (location) { - r = !write_desktop_entry(location, lastEntry, "winebrowser", escaped_urlPath, NULL, NULL, NULL); + r = !write_desktop_entry(NULL, location, lastEntry, "winebrowser", escaped_urlPath, NULL, NULL, NULL); HeapFree(GetProcessHeap(), 0, location); } } else - r = !write_menu_entry(link_name, "winebrowser", escaped_urlPath, NULL, NULL, NULL); + r = !write_menu_entry(unix_link, link_name, "winebrowser", escaped_urlPath, NULL, NULL, NULL); ret = (r != 0); ReleaseSemaphore(hSem, 1, NULL); @@ -2242,6 +2292,7 @@ cleanup: HeapFree(GetProcessHeap(), 0, link_name); CoTaskMemFree( urlPath ); HeapFree(GetProcessHeap(), 0, escaped_urlPath); + HeapFree(GetProcessHeap(), 0, unix_link); return ret; } @@ -2508,6 +2559,62 @@ end: HeapFree(GetProcessHeap(), 0, applications_dir); } +static void cleanup_menus(void) +{ + HKEY hkey; + + hkey = open_menus_reg_key(); + if (hkey) + { + int i; + LSTATUS lret = ERROR_SUCCESS; + for (i = 0; lret == ERROR_SUCCESS; ) + { + char *value = NULL; + char *data = NULL; + DWORD valueSize = 4096; + DWORD dataSize = 4096; + while (1) + { + lret = ERROR_OUTOFMEMORY; + value = HeapAlloc(GetProcessHeap(), 0, valueSize); + if (value == NULL) + break; + data = HeapAlloc(GetProcessHeap(), 0, dataSize); + if (data == NULL) + break; + lret = RegEnumValueA(hkey, i, value, &valueSize, NULL, NULL, (BYTE*)data, &dataSize); + if (lret == ERROR_SUCCESS || lret != ERROR_MORE_DATA) + break; + valueSize *= 2; + dataSize *= 2; + HeapFree(GetProcessHeap(), 0, value); + HeapFree(GetProcessHeap(), 0, data); + value = data = NULL; + } + if (lret == ERROR_SUCCESS) + { + struct stat filestats; + if (stat(data, &filestats) < 0 && errno == ENOENT) + { + WINE_TRACE("removing menu related file %s\n", value); + remove(value); + RegDeleteValueA(hkey, value); + } + else + i++; + } + else if (lret != ERROR_NO_MORE_ITEMS) + WINE_WARN("error %d reading registry\n", lret); + HeapFree(GetProcessHeap(), 0, value); + HeapFree(GetProcessHeap(), 0, data); + } + RegCloseKey(hkey); + } + else + WINE_ERR("error opening registry key, menu cleanup failed\n"); +} + static CHAR *next_token( LPSTR *p ) { LPSTR token = NULL, t = *p; @@ -2609,6 +2716,11 @@ int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show RefreshFileTypeAssociations(); break; } + if( !lstrcmpA( token, "-r" ) ) + { + cleanup_menus(); + break; + } if( !lstrcmpA( token, "-w" ) ) bWait = TRUE; else if ( !lstrcmpA( token, "-u" ) ) diff --git a/server/ptrace.c b/server/ptrace.c index 72e2b441760..4fa48ecf17d 100644 --- a/server/ptrace.c +++ b/server/ptrace.c @@ -313,8 +313,8 @@ static int suspend_for_ptrace( struct thread *thread ) return 0; } -/* read an int from a thread address space */ -static int read_thread_int( struct thread *thread, int *addr, int *data ) +/* read a long from a thread address space */ +static long read_thread_long( struct thread *thread, long *addr, long *data ) { errno = 0; *data = ptrace( PTRACE_PEEKDATA, get_ptrace_pid(thread), (caddr_t)addr, 0 ); @@ -326,13 +326,13 @@ static int read_thread_int( struct thread *thread, int *addr, int *data ) return 0; } -/* write an int to a thread address space */ -static int write_thread_int( struct thread *thread, int *addr, int data, unsigned int mask ) +/* write a long to a thread address space */ +static long write_thread_long( struct thread *thread, long *addr, long data, unsigned long mask ) { - int res; + long res; if (mask != ~0u) { - if (read_thread_int( thread, addr, &res ) == -1) return -1; + if (read_thread_long( thread, addr, &res ) == -1) return -1; data = (data & mask) | (res & ~mask); } if ((res = ptrace( PTRACE_POKEDATA, get_ptrace_pid(thread), (caddr_t)addr, data )) == -1) @@ -358,7 +358,7 @@ int read_process_memory( struct process *process, client_ptr_t ptr, data_size_t { struct thread *thread = get_ptrace_thread( process ); unsigned int first_offset, last_offset, len; - int data, *addr; + long data, *addr; if (!thread) return 0; @@ -368,33 +368,33 @@ int read_process_memory( struct process *process, client_ptr_t ptr, data_size_t return 0; } - first_offset = ptr % sizeof(int); - last_offset = (size + first_offset) % sizeof(int); - if (!last_offset) last_offset = sizeof(int); + first_offset = ptr % sizeof(long); + last_offset = (size + first_offset) % sizeof(long); + if (!last_offset) last_offset = sizeof(long); - addr = (int *)(unsigned long)(ptr - first_offset); - len = (size + first_offset + sizeof(int) - 1) / sizeof(int); + addr = (long *)(unsigned long)(ptr - first_offset); + len = (size + first_offset + sizeof(long) - 1) / sizeof(long); if (suspend_for_ptrace( thread )) { if (len > 1) { - if (read_thread_int( thread, addr++, &data ) == -1) goto done; - memcpy( dest, (char *)&data + first_offset, sizeof(int) - first_offset ); - dest += sizeof(int) - first_offset; + if (read_thread_long( thread, addr++, &data ) == -1) goto done; + memcpy( dest, (char *)&data + first_offset, sizeof(long) - first_offset ); + dest += sizeof(long) - first_offset; first_offset = 0; len--; } while (len > 1) { - if (read_thread_int( thread, addr++, &data ) == -1) goto done; - memcpy( dest, &data, sizeof(int) ); - dest += sizeof(int); + if (read_thread_long( thread, addr++, &data ) == -1) goto done; + memcpy( dest, &data, sizeof(long) ); + dest += sizeof(long); len--; } - if (read_thread_int( thread, addr++, &data ) == -1) goto done; + if (read_thread_long( thread, addr++, &data ) == -1) goto done; memcpy( dest, (char *)&data + first_offset, last_offset - first_offset ); len--; @@ -406,28 +406,29 @@ int read_process_memory( struct process *process, client_ptr_t ptr, data_size_t /* make sure we can write to the whole address range */ /* len is the total size (in ints) */ -static int check_process_write_access( struct thread *thread, int *addr, data_size_t len ) +static int check_process_write_access( struct thread *thread, long *addr, data_size_t len ) { int page = get_page_size() / sizeof(int); for (;;) { - if (write_thread_int( thread, addr, 0, 0 ) == -1) return 0; + if (write_thread_long( thread, addr, 0, 0 ) == -1) return 0; if (len <= page) break; addr += page; len -= page; } - return (write_thread_int( thread, addr + len - 1, 0, 0 ) != -1); + return (write_thread_long( thread, addr + len - 1, 0, 0 ) != -1); } /* write data to a process memory space */ int write_process_memory( struct process *process, client_ptr_t ptr, data_size_t size, const char *src ) { struct thread *thread = get_ptrace_thread( process ); - int ret = 0, data = 0; + int ret = 0; + long data = 0; data_size_t len; - int *addr; - unsigned int first_mask, first_offset, last_mask, last_offset; + long *addr; + unsigned long first_mask, first_offset, last_mask, last_offset; if (!thread) return 0; @@ -437,19 +438,19 @@ int write_process_memory( struct process *process, client_ptr_t ptr, data_size_t return 0; } - /* compute the mask for the first int */ + /* compute the mask for the first long */ first_mask = ~0; - first_offset = ptr % sizeof(int); + first_offset = ptr % sizeof(long); memset( &first_mask, 0, first_offset ); - /* compute the mask for the last int */ - last_offset = (size + first_offset) % sizeof(int); - if (!last_offset) last_offset = sizeof(int); + /* compute the mask for the last long */ + last_offset = (size + first_offset) % sizeof(long); + if (!last_offset) last_offset = sizeof(long); last_mask = 0; memset( &last_mask, 0xff, last_offset ); - addr = (int *)(unsigned long)(ptr - first_offset); - len = (size + first_offset + sizeof(int) - 1) / sizeof(int); + addr = (long *)(unsigned long)(ptr - first_offset); + len = (size + first_offset + sizeof(long) - 1) / sizeof(long); if (suspend_for_ptrace( thread )) { @@ -461,9 +462,9 @@ int write_process_memory( struct process *process, client_ptr_t ptr, data_size_t /* first word is special */ if (len > 1) { - memcpy( (char *)&data + first_offset, src, sizeof(int) - first_offset ); - src += sizeof(int) - first_offset; - if (write_thread_int( thread, addr++, data, first_mask ) == -1) goto done; + memcpy( (char *)&data + first_offset, src, sizeof(long) - first_offset ); + src += sizeof(long) - first_offset; + if (write_thread_long( thread, addr++, data, first_mask ) == -1) goto done; first_offset = 0; len--; } @@ -471,15 +472,15 @@ int write_process_memory( struct process *process, client_ptr_t ptr, data_size_t while (len > 1) { - memcpy( &data, src, sizeof(int) ); - src += sizeof(int); - if (write_thread_int( thread, addr++, data, ~0 ) == -1) goto done; + memcpy( &data, src, sizeof(long) ); + src += sizeof(long); + if (write_thread_long( thread, addr++, data, ~0ul ) == -1) goto done; len--; } /* last word is special too */ memcpy( (char *)&data + first_offset, src, last_offset - first_offset ); - if (write_thread_int( thread, addr, data, last_mask ) == -1) goto done; + if (write_thread_long( thread, addr, data, last_mask ) == -1) goto done; ret = 1; done: @@ -504,13 +505,13 @@ void get_selector_entry( struct thread *thread, int entry, unsigned int *base, } if (suspend_for_ptrace( thread )) { - unsigned char flags_buf[4]; - int *addr = (int *)(unsigned long)thread->process->ldt_copy + entry; - if (read_thread_int( thread, addr, (int *)base ) == -1) goto done; - if (read_thread_int( thread, addr + 8192, (int *)limit ) == -1) goto done; - addr = (int *)(unsigned long)thread->process->ldt_copy + 2*8192 + (entry >> 2); - if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done; - *flags = flags_buf[entry & 3]; + unsigned char flags_buf[sizeof(long)]; + long *addr = (long *)(unsigned long)thread->process->ldt_copy + entry; + if (read_thread_long( thread, addr, (long *)base ) == -1) goto done; + if (read_thread_long( thread, addr + 8192, (long *)limit ) == -1) goto done; + addr = (long *)(unsigned long)thread->process->ldt_copy + 2*8192 + (entry / sizeof(long)); + if (read_thread_long( thread, addr, (long *)flags_buf ) == -1) goto done; + *flags = flags_buf[entry % sizeof(long)]; done: resume_after_ptrace( thread ); } diff --git a/server/thread.c b/server/thread.c index e931e81d093..2ea892913d4 100644 --- a/server/thread.c +++ b/server/thread.c @@ -712,15 +712,15 @@ done: /* attempt to wake threads sleeping on the object wait queue */ void wake_up( struct object *obj, int max ) { - struct list *ptr, *next; + struct list *ptr; - LIST_FOR_EACH_SAFE( ptr, next, &obj->wait_queue ) + LIST_FOR_EACH( ptr, &obj->wait_queue ) { struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry ); - if (wake_thread( entry->thread )) - { - if (max && !--max) break; - } + if (!wake_thread( entry->thread )) continue; + if (max && !--max) break; + /* restart at the head of the list since a wake up can change the object wait queue */ + ptr = &obj->wait_queue; } } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 1b7c79d8eaf..b60a53c105c 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -3989,6 +3989,19 @@ void write_exceptions( FILE *file ) fprintf( file, " __DECL_EXCEPTION_FRAME\n"); fprintf( file, "};\n"); fprintf( file, "\n"); + fprintf( file, "static inline void __widl_unwind_target(void)\n" ); + fprintf( file, "{\n"); + fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)__wine_get_frame();\n" ); + fprintf( file, " if (exc_frame->finally_level > exc_frame->filter_level)\n" ); + fprintf( file, " {\n"); + fprintf( file, " exc_frame->abnormal_termination = 1;\n"); + fprintf( file, " exc_frame->finally( exc_frame );\n"); + fprintf( file, " __wine_pop_frame( &exc_frame->frame );\n"); + fprintf( file, " }\n"); + fprintf( file, " exc_frame->filter_level = 0;\n"); + fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n"); + fprintf( file, "}\n"); + fprintf( file, "\n"); fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n"); fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); fprintf( file, " CONTEXT *context,\n"); @@ -4007,17 +4020,7 @@ void write_exceptions( FILE *file ) fprintf( file, " }\n" ); fprintf( file, " exc_frame->code = record->ExceptionCode;\n"); fprintf( file, " if (exc_frame->filter_level && exc_frame->filter( record, exc_frame ) == EXCEPTION_EXECUTE_HANDLER)\n" ); - fprintf( file, " {\n"); - fprintf( file, " __wine_rtl_unwind( frame, record );\n"); - fprintf( file, " if (exc_frame->finally_level > exc_frame->filter_level)\n" ); - fprintf( file, " {\n"); - fprintf( file, " exc_frame->abnormal_termination = 1;\n"); - fprintf( file, " exc_frame->finally( exc_frame );\n"); - fprintf( file, " __wine_pop_frame( frame );\n"); - fprintf( file, " }\n"); - fprintf( file, " exc_frame->filter_level = 0;\n"); - fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n"); - fprintf( file, " }\n"); + fprintf( file, " __wine_rtl_unwind( frame, record, __widl_unwind_target );\n"); fprintf( file, " return ExceptionContinueSearch;\n"); fprintf( file, "}\n"); fprintf( file, "\n"); diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 7a709bc2d57..5bbc95e0bb4 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -1515,15 +1515,15 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) paramdata[2] = paramflags; typedata[3] += decoded_size << 16; - if(lcid_retval_count == 1) - typedata[4] |= 0x4000; - else if(lcid_retval_count == 2) - typedata[4] |= 0x8000; - i++; } } + if(lcid_retval_count == 1) + typedata[4] |= 0x4000; + else if(lcid_retval_count == 2) + typedata[4] |= 0x8000; + if(typeinfo->funcs_allocated == 0) { typeinfo->funcs_allocated = 10; typeinfo->func_indices = xmalloc(typeinfo->funcs_allocated * sizeof(int)); diff --git a/tools/winapi/c_parser.pm b/tools/winapi/c_parser.pm index b93e4612502..1de62ee3afc 100644 --- a/tools/winapi/c_parser.pm +++ b/tools/winapi/c_parser.pm @@ -242,11 +242,6 @@ sub _parse_c_warning($$$$$$) { $current .= $lines[1] . "\n" if $lines[1]; } - if (0) { - (my $package, my $filename, my $line) = caller(0); - $output->write("*** caller ***: $filename:$line\n"); - } - if($current) { $output->write("$$file:$line." . ($column + 1) . ": $context: $message: \\\n$current"); } else { @@ -854,8 +849,6 @@ sub parse_c_file($$$$) { if($line != $previous_line) { &$$found_line($line); - } elsif(0 && $column == $previous_column) { - $self->_parse_c_error($_, $line, $column, "file", "no progress"); } else { # &$$found_line("$line.$column"); } @@ -1057,7 +1050,7 @@ sub parse_c_file($$$$) { $declaration .= $&; } elsif(s/^\)//) { $plevel--; - if($blevel <= 0) { + if($plevel <= 0) { $self->_parse_c_error($_, $line, $column, "file", ") without ("); } $declaration .= $&; @@ -1098,14 +1091,7 @@ sub parse_c_file($$$$) { } } elsif(s/^;//) { $declaration .= $&; - if(0 && $blevel == 1 && - $declaration !~ /^typedef/ && - $declaration !~ /^(?:const\s+|extern\s+|static\s+|volatile\s+)?(?:interface|struct|union)(?:\s+\w+)?\s*\{/s && - $declaration =~ /^(?:\w+(?:\s*\*)*\s+)*(\w+)\s*\(\s*(?:(?:\w+\s*,\s*)*(\w+))?\s*\)\s*(.*?);$/s && - $1 ne "ICOM_VTABLE" && defined($2) && $2 ne "void" && $3) # K&R - { - $self->_parse_c_warning("", $line, $column, "file", "function $1: warning: function has K&R format"); - } elsif($plevel == 1 && $blevel == 1) { + if($plevel == 1 && $blevel == 1) { $declaration =~ s/\s*;$//; if($declaration && !$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) { return 0; diff --git a/tools/wine.inf.in b/tools/wine.inf.in index 8fe41618276..4d2999ec86b 100644 --- a/tools/wine.inf.in +++ b/tools/wine.inf.in @@ -122,7 +122,7 @@ HKCR,.xml,,2,"xmlfile" HKCR,.xml,"Content Type",2,"text/xml" HKCR,.xsl,"Content Type",2,"text/xsl" HKCR,chm.file,,2,"Compiled HTML Help File" -HKCR,chm.file\shell\open\command,,2,"%11%\hh.exe %1" +HKCR,chm.file\shell\open\command,,2,"%10%\hh.exe %1" HKCR,cplfile,,2,"Control Panel Item" HKCR,cplfile\shell\cplopen,,2,"Open with Control Panel" HKCR,cplfile\shell\cplopen\command,,2,"rundll32.exe shell32.dll,Control_RunDLL ""%1"",%*" @@ -2519,6 +2519,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 11,,winspool.drv 11,,wintab32.dll 11,,winver.exe +11,,wordpad.exe 11,,ws2_32.dll 11,,wsock32.dll 12,,mountmgr.sys diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 65557a5ecf8..bb9d6d1d27c 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -668,7 +668,9 @@ static void output_import_thunk( const char *name, const char *table, int pos ) } break; case CPU_x86_64: + output( "\t.cfi_startproc\n" ); output( "\tjmpq *%s+%d(%%rip)\n", table, pos ); + output( "\t.cfi_endproc\n" ); break; case CPU_SPARC: if ( !UsePIC ) @@ -970,23 +972,27 @@ static void output_delayed_import_thunks( const DLLSPEC *spec ) output( "\tjmp *%%eax\n" ); break; case CPU_x86_64: - output( "\tpushq %%rdx\n" ); - output( "\tpushq %%rcx\n" ); - output( "\tpushq %%r8\n" ); - output( "\tpushq %%r9\n" ); - output( "\tpushq %%r10\n" ); - output( "\tpushq %%r11\n" ); - output( "\tsubq $40,%%rsp\n" ); + output( "\t.cfi_startproc\n" ); + output( "\tsubq $88,%%rsp\n" ); + output( "\t.cfi_adjust_cfa_offset 88\n" ); + output( "\tmovq %%rdx,80(%%rsp)\n" ); + output( "\tmovq %%rcx,72(%%rsp)\n" ); + output( "\tmovq %%r8,64(%%rsp)\n" ); + output( "\tmovq %%r9,56(%%rsp)\n" ); + output( "\tmovq %%r10,48(%%rsp)\n" ); + output( "\tmovq %%r11,40(%%rsp)\n" ); output( "\tmovq %%rax,%%rcx\n" ); output( "\tcall %s\n", asm_name("__wine_spec_delay_load") ); - output( "\taddq $40,%%rsp\n" ); - output( "\tpopq %%r11\n" ); - output( "\tpopq %%r10\n" ); - output( "\tpopq %%r9\n" ); - output( "\tpopq %%r8\n" ); - output( "\tpopq %%rcx\n" ); - output( "\tpopq %%rdx\n" ); + output( "\tmovq 40(%%rsp),%%r11\n" ); + output( "\tmovq 48(%%rsp),%%r10\n" ); + output( "\tmovq 56(%%rsp),%%r9\n" ); + output( "\tmovq 64(%%rsp),%%r8\n" ); + output( "\tmovq 72(%%rsp),%%rcx\n" ); + output( "\tmovq 80(%%rsp),%%rdx\n" ); + output( "\taddq $88,%%rsp\n" ); + output( "\t.cfi_adjust_cfa_offset -88\n" ); output( "\tjmp *%%rax\n" ); + output( "\t.cfi_endproc\n" ); break; case CPU_SPARC: output( "\tsave %%sp, -96, %%sp\n" ); @@ -1068,8 +1074,10 @@ static void output_delayed_import_thunks( const DLLSPEC *spec ) output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") ); break; case CPU_x86_64: + output( "\t.cfi_startproc\n" ); output( "\tmovq $%d,%%rax\n", (idx << 16) | j ); output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") ); + output( "\t.cfi_endproc\n" ); break; case CPU_SPARC: output( "\tset %d, %%g1\n", (idx << 16) | j ); @@ -1235,6 +1243,9 @@ void output_stubs( DLLSPEC *spec ) output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") ); break; case CPU_x86_64: + output( "\t.cfi_startproc\n" ); + output( "\tsubq $8,%%rsp\n" ); + output( "\t.cfi_adjust_cfa_offset 8\n" ); output( "\tleaq .L__wine_spec_file_name(%%rip),%%rdi\n" ); if (exp_name) { @@ -1243,8 +1254,8 @@ void output_stubs( DLLSPEC *spec ) } else output( "\tmovq $%d,%%rsi\n", odp->ordinal ); - output( "\tsubq $8,%%rsp\n" ); output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") ); + output( "\t.cfi_endproc\n" ); break; default: assert(0); diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index 10746361481..941923113db 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -207,44 +207,45 @@ static void exit_on_signal( int sig ) static const char usage_str[] = "Usage: winebuild [OPTIONS] [FILES]\n\n" "Options:\n" -" --as-cmd=AS Command to use for assembling (default: as)\n" -" -b, --target=TARGET Specify target CPU and platform for cross-compiling\n" -" -d, --delay-lib=LIB Import the specified library in delayed mode\n" -" -D SYM Ignored for C flags compatibility\n" -" -e, --entry=FUNC Set the DLL entry point function (default: DllMain)\n" -" -E, --export=FILE Export the symbols defined in the .spec or .def file\n" -" --external-symbols Allow linking to external symbols\n" -" -f FLAGS Compiler flags (only -fPIC is supported)\n" -" -F, --filename=DLLFILE Set the DLL filename (default: from input file name)\n" -" -h, --help Display this help message\n" -" -H, --heap=SIZE Set the heap size for a Win16 dll\n" -" -i, --ignore=SYM[,SYM] Ignore specified symbols when resolving imports\n" -" -I DIR Ignored for C flags compatibility\n" -" -k, --kill-at Kill stdcall decorations in generated .def files\n" -" -K, FLAGS Compiler flags (only -KPIC is supported)\n" -" --ld-cmd=LD Command to use for linking (default: ld)\n" -" -l, --library=LIB Import the specified library\n" -" -L, --library-path=DIR Look for imports libraries in DIR\n" -" -m32, -m64 Force building 32-bit resp. 64-bit code\n" -" -M, --main-module=MODULE Set the name of the main module for a Win16 dll\n" -" --nm-cmd=NM Command to use to get undefined symbols (default: nm)\n" -" --nxcompat=y|n Set the NX compatibility flag (default: yes)\n" -" -N, --dll-name=DLLNAME Set the DLL name (default: from input file name)\n" -" -o, --output=NAME Set the output file name (default: stdout)\n" -" -r, --res=RSRC.RES Load resources from RSRC.RES\n" -" --save-temps Do not delete the generated intermediate files\n" -" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n" -" -u, --undefined=SYMBOL Add an undefined reference to SYMBOL when linking\n" -" -v, --verbose Display the programs invoked\n" -" --version Print the version and exit\n" -" -w, --warnings Turn on warnings\n" +" --as-cmd=AS Command to use for assembling (default: as)\n" +" -b, --target=TARGET Specify target CPU and platform for cross-compiling\n" +" -d, --delay-lib=LIB Import the specified library in delayed mode\n" +" -D SYM Ignored for C flags compatibility\n" +" -e, --entry=FUNC Set the DLL entry point function (default: DllMain)\n" +" -E, --export=FILE Export the symbols defined in the .spec or .def file\n" +" --external-symbols Allow linking to external symbols\n" +" -f FLAGS Compiler flags (only -fPIC is supported)\n" +" -F, --filename=DLLFILE Set the DLL filename (default: from input file name)\n" +" -h, --help Display this help message\n" +" -H, --heap=SIZE Set the heap size for a Win16 dll\n" +" -i, --ignore=SYM[,SYM] Ignore specified symbols when resolving imports\n" +" -I DIR Ignored for C flags compatibility\n" +" -k, --kill-at Kill stdcall decorations in generated .def files\n" +" -K, FLAGS Compiler flags (only -KPIC is supported)\n" +" --large-address-aware Support an address space larger than 2Gb\n" +" --ld-cmd=LD Command to use for linking (default: ld)\n" +" -l, --library=LIB Import the specified library\n" +" -L, --library-path=DIR Look for imports libraries in DIR\n" +" -m32, -m64 Force building 32-bit resp. 64-bit code\n" +" -M, --main-module=MODULE Set the name of the main module for a Win16 dll\n" +" --nm-cmd=NM Command to use to get undefined symbols (default: nm)\n" +" --nxcompat=y|n Set the NX compatibility flag (default: yes)\n" +" -N, --dll-name=DLLNAME Set the DLL name (default: from input file name)\n" +" -o, --output=NAME Set the output file name (default: stdout)\n" +" -r, --res=RSRC.RES Load resources from RSRC.RES\n" +" --save-temps Do not delete the generated intermediate files\n" +" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n" +" -u, --undefined=SYMBOL Add an undefined reference to SYMBOL when linking\n" +" -v, --verbose Display the programs invoked\n" +" --version Print the version and exit\n" +" -w, --warnings Turn on warnings\n" "\nMode options:\n" -" --dll Build a .c file from a .spec or .def file\n" -" --def Build a .def file from a .spec file\n" -" --exe Build a .c file for an executable\n" -" --relay16 Build the 16-bit relay assembly routines\n" -" --relay32 Build the 32-bit relay assembly routines\n\n" -" --resources Build a .o file for the resource files\n\n" +" --dll Build a .c file from a .spec or .def file\n" +" --def Build a .def file from a .spec file\n" +" --exe Build a .c file for an executable\n" +" --relay16 Build the 16-bit relay assembly routines\n" +" --relay32 Build the 32-bit relay assembly routines\n\n" +" --resources Build a .o file for the resource files\n\n" "The mode options are mutually exclusive; you must specify one and only one.\n\n"; enum long_options_values @@ -254,6 +255,7 @@ enum long_options_values LONG_OPT_EXE, LONG_OPT_ASCMD, LONG_OPT_EXTERNAL_SYMS, + LONG_OPT_LARGE_ADDRESS_AWARE, LONG_OPT_LDCMD, LONG_OPT_NMCMD, LONG_OPT_NXCOMPAT, @@ -274,6 +276,7 @@ static const struct option long_options[] = { "exe", 0, 0, LONG_OPT_EXE }, { "as-cmd", 1, 0, LONG_OPT_ASCMD }, { "external-symbols", 0, 0, LONG_OPT_EXTERNAL_SYMS }, + { "large-address-aware", 0, 0, LONG_OPT_LARGE_ADDRESS_AWARE }, { "ld-cmd", 1, 0, LONG_OPT_LDCMD }, { "nm-cmd", 1, 0, LONG_OPT_NMCMD }, { "nxcompat", 1, 0, LONG_OPT_NXCOMPAT }, @@ -451,6 +454,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) case LONG_OPT_EXTERNAL_SYMS: link_ext_symbols = 1; break; + case LONG_OPT_LARGE_ADDRESS_AWARE: + spec->characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; + break; case LONG_OPT_LDCMD: ld_command = xstrdup( optarg ); break; diff --git a/tools/winebuild/relay.c b/tools/winebuild/relay.c index f049c9ef59d..3f955451562 100644 --- a/tools/winebuild/relay.c +++ b/tools/winebuild/relay.c @@ -987,55 +987,62 @@ void BuildRelays16(void) static void build_call_from_regs_x86_64(void) { static const int STACK_SPACE = 128 + 0x4d0; /* size of x86_64 context */ + int i; /* Function header */ function_header( "__wine_call_from_regs" ); + output( "\t.cfi_startproc\n" ); output( "\tsubq $%u,%%rsp\n", STACK_SPACE ); + output( "\t.cfi_adjust_cfa_offset %u\n", STACK_SPACE ); /* save registers into the context */ output( "\tmovq %%rax,0x78(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%rax,0x78\n" ); output( "\tmovq %u(%%rsp),%%rax\n", STACK_SPACE + 16 ); /* saved %rcx on stack */ output( "\tmovq %%rax,0x80(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%rcx,0x80\n" ); output( "\tmovq %u(%%rsp),%%rax\n", STACK_SPACE + 24 ); /* saved %rdx on stack */ + output( "\t.cfi_rel_offset %%rdx,0x88\n" ); output( "\tmovq %%rax,0x88(%%rsp)\n" ); output( "\tmovq %%rbx,0x90(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%rbx,0x90\n" ); output( "\tleaq %u(%%rsp),%%rax\n", STACK_SPACE + 16 ); output( "\tmovq %%rax,0x98(%%rsp)\n" ); output( "\tmovq %%rbp,0xa0(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%rbp,0xa0\n" ); output( "\tmovq %%rsi,0xa8(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%rsi,0xa8\n" ); output( "\tmovq %%rdi,0xb0(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%rdi,0xb0\n" ); output( "\tmovq %%r8,0xb8(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%r8,0xb8\n" ); output( "\tmovq %%r9,0xc0(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%r9,0xc0\n" ); output( "\tmovq %%r10,0xc8(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%r10,0xc8\n" ); output( "\tmovq %%r11,0xd0(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%r11,0xd0\n" ); output( "\tmovq %%r12,0xd8(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%r12,0xd8\n" ); output( "\tmovq %%r13,0xe0(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%r13,0xe0\n" ); output( "\tmovq %%r14,0xe8(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%r14,0xe8\n" ); output( "\tmovq %%r15,0xf0(%%rsp)\n" ); + output( "\t.cfi_rel_offset %%r15,0xf0\n" ); output( "\tmovq %u(%%rsp),%%rax\n", STACK_SPACE + 8 ); output( "\tmovq %%rax,0xf8(%%rsp)\n" ); output( "\tstmxcsr 0x34(%%rsp)\n" ); output( "\tfxsave 0x100(%%rsp)\n" ); - output( "\tmovdqa %%xmm0,0x1a0(%%rsp)\n" ); - output( "\tmovdqa %%xmm1,0x1b0(%%rsp)\n" ); - output( "\tmovdqa %%xmm2,0x1c0(%%rsp)\n" ); - output( "\tmovdqa %%xmm3,0x1d0(%%rsp)\n" ); - output( "\tmovdqa %%xmm4,0x1e0(%%rsp)\n" ); - output( "\tmovdqa %%xmm5,0x1f0(%%rsp)\n" ); - output( "\tmovdqa %%xmm6,0x200(%%rsp)\n" ); - output( "\tmovdqa %%xmm7,0x210(%%rsp)\n" ); - output( "\tmovdqa %%xmm8,0x220(%%rsp)\n" ); - output( "\tmovdqa %%xmm9,0x230(%%rsp)\n" ); - output( "\tmovdqa %%xmm10,0x240(%%rsp)\n" ); - output( "\tmovdqa %%xmm11,0x250(%%rsp)\n" ); - output( "\tmovdqa %%xmm12,0x260(%%rsp)\n" ); - output( "\tmovdqa %%xmm13,0x270(%%rsp)\n" ); - output( "\tmovdqa %%xmm14,0x280(%%rsp)\n" ); - output( "\tmovdqa %%xmm15,0x290(%%rsp)\n" ); + for (i = 0; i < 16; i++) + { + output( "\tmovdqa %%xmm%u,0x%x(%%rsp)\n", i, 0x1a0 + 16 * i ); + output( "\t.cfi_rel_offset %%xmm%u,0x%x\n", i, 0x1a0 + 16 * i ); + } output( "\tmovw %%cs,0x38(%%rsp)\n" ); output( "\tmovw %%ds,0x3a(%%rsp)\n" ); @@ -1058,6 +1065,7 @@ static void build_call_from_regs_x86_64(void) output( "\tcmpq %%rax,%%rcx\n" ); output( "\tcmovgq %%rcx,%%rax\n" ); output( "\tmovq %%rsp,%%rbx\n" ); + output( "\t.cfi_def_cfa_register %%rbx\n" ); output( "\tleaq 16(,%%rax,8),%%rax\n" ); /* add 8 for context arg and 8 for rounding */ output( "\tandq $~15,%%rax\n" ); output( "\tsubq %%rax,%%rsp\n" ); @@ -1079,35 +1087,37 @@ static void build_call_from_regs_x86_64(void) /* restore the context structure */ output( "1:\tmovq 0x80(%%rbx),%%rcx\n" ); + output( "\t.cfi_same_value %%rcx\n" ); output( "\tmovq 0x88(%%rbx),%%rdx\n" ); + output( "\t.cfi_same_value %%rdx\n" ); output( "\tmovq 0xa0(%%rbx),%%rbp\n" ); + output( "\t.cfi_same_value %%rbp\n" ); output( "\tmovq 0xa8(%%rbx),%%rsi\n" ); + output( "\t.cfi_same_value %%rsi\n" ); output( "\tmovq 0xb0(%%rbx),%%rdi\n" ); + output( "\t.cfi_same_value %%rdi\n" ); output( "\tmovq 0xb8(%%rbx),%%r8\n" ); + output( "\t.cfi_same_value %%r8\n" ); output( "\tmovq 0xc0(%%rbx),%%r9\n" ); + output( "\t.cfi_same_value %%r9\n" ); output( "\tmovq 0xc8(%%rbx),%%r10\n" ); + output( "\t.cfi_same_value %%r10\n" ); output( "\tmovq 0xd0(%%rbx),%%r11\n" ); + output( "\t.cfi_same_value %%r11\n" ); output( "\tmovq 0xd8(%%rbx),%%r12\n" ); + output( "\t.cfi_same_value %%r12\n" ); output( "\tmovq 0xe0(%%rbx),%%r13\n" ); + output( "\t.cfi_same_value %%r13\n" ); output( "\tmovq 0xe8(%%rbx),%%r14\n" ); + output( "\t.cfi_same_value %%r14\n" ); output( "\tmovq 0xf0(%%rbx),%%r15\n" ); + output( "\t.cfi_same_value %%r15\n" ); - output( "\tmovdqa 0x1a0(%%rbx),%%xmm0\n" ); - output( "\tmovdqa 0x1b0(%%rbx),%%xmm1\n" ); - output( "\tmovdqa 0x1c0(%%rbx),%%xmm2\n" ); - output( "\tmovdqa 0x1d0(%%rbx),%%xmm3\n" ); - output( "\tmovdqa 0x1e0(%%rbx),%%xmm4\n" ); - output( "\tmovdqa 0x1f0(%%rbx),%%xmm5\n" ); - output( "\tmovdqa 0x200(%%rbx),%%xmm6\n" ); - output( "\tmovdqa 0x210(%%rbx),%%xmm7\n" ); - output( "\tmovdqa 0x220(%%rbx),%%xmm8\n" ); - output( "\tmovdqa 0x230(%%rbx),%%xmm9\n" ); - output( "\tmovdqa 0x240(%%rbx),%%xmm10\n" ); - output( "\tmovdqa 0x250(%%rbx),%%xmm11\n" ); - output( "\tmovdqa 0x260(%%rbx),%%xmm12\n" ); - output( "\tmovdqa 0x270(%%rbx),%%xmm13\n" ); - output( "\tmovdqa 0x280(%%rbx),%%xmm14\n" ); - output( "\tmovdqa 0x290(%%rbx),%%xmm15\n" ); + for (i = 0; i < 16; i++) + { + output( "\tmovdqa 0x%x(%%rbx),%%xmm%u\n", 0x1a0 + 16 * i, i ); + output( "\t.cfi_same_value %%xmm%u\n", i ); + } output( "\tfxrstor 0x100(%%rbx)\n" ); output( "\tldmxcsr 0x34(%%rbx)\n" ); @@ -1124,12 +1134,15 @@ static void build_call_from_regs_x86_64(void) output( "\tmovq 0x78(%%rbx),%%rax\n" ); output( "\tmovq 0x90(%%rbx),%%rbx\n" ); output( "\tiretq\n" ); + output( "\t.cfi_endproc\n" ); output_function_size( "__wine_call_from_regs" ); function_header( "__wine_restore_regs" ); + output( "\t.cfi_startproc\n" ); output( "\tmovq %%rcx,%%rbx\n" ); output( "\tjmp 1b\n" ); + output( "\t.cfi_endproc\n" ); output_function_size( "__wine_restore_regs" ); } diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index aad52489bdf..e96f4b872ce 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -171,17 +171,21 @@ static void output_relay_debug( DLLSPEC *spec ) break; case CPU_x86_64: - output( "\tmovq %%rcx,8(%%rsp)\n" ); - output( "\tmovq %%rdx,16(%%rsp)\n" ); - output( "\tmovq %%r8,24(%%rsp)\n" ); - output( "\tmovq %%r9,32(%%rsp)\n" ); - output( "\tmovq %%rsp,%%r8\n" ); + output( "\t.cfi_startproc\n" ); + output( "\tsubq $40,%%rsp\n" ); + output( "\t.cfi_adjust_cfa_offset 40\n" ); + output( "\tmovq %%rcx,48(%%rsp)\n" ); + output( "\tmovq %%rdx,56(%%rsp)\n" ); + output( "\tmovq %%r8,64(%%rsp)\n" ); + output( "\tmovq %%r9,72(%%rsp)\n" ); + output( "\tleaq 40(%%rsp),%%r8\n" ); output( "\tmovq $%u,%%rdx\n", (flags << 24) | (args << 16) | (i - spec->base) ); output( "\tleaq .L__wine_spec_relay_descr(%%rip),%%rcx\n" ); - output( "\tsubq $40,%%rsp\n" ); output( "\tcallq *%u(%%rcx)\n", (odp->flags & FLAG_REGISTER) ? 16 : 8 ); output( "\taddq $40,%%rsp\n" ); + output( "\t.cfi_adjust_cfa_offset -40\n" ); output( "\tret\n" ); + output( "\t.cfi_endproc\n" ); break; default: diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in index 855bf4ad076..74728ce7b78 100644 --- a/tools/winebuild/winebuild.man.in +++ b/tools/winebuild/winebuild.man.in @@ -137,6 +137,10 @@ generated .def file. Only meaningful in \fB--def\fR mode. .BI \-K\ flags Ignored for compatibility with the C compiler. .TP +.BI \--large-address-aware +Set a flag in the executable to notify the loader that this +application supports address spaces larger than 2 gigabytes. +.TP .BI \--ld-cmd= ld-command Specify the command to use to link the object files; the default is \fBld\fR. diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index e9cd671d7f1..c2fb4f3d491 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -193,6 +193,7 @@ struct options int unicode_app; int compile_only; int force_pointer_size; + int large_address_aware; const char* wine_objdir; const char* output_name; const char* image_base; @@ -704,6 +705,8 @@ static void build(struct options* opts) if (opts->image_base) strarray_add(link_args, strmake("-Wl,--image-base,%s", opts->image_base)); + if (opts->large_address_aware) strarray_add( link_args, "-Wl,--large-address-aware" ); + if (opts->unicode_app && !opts->shared) strarray_add(link_args, mingw_unicode_hack(opts)); @@ -818,6 +821,7 @@ static void build(struct options* opts) strarray_add(spec_args, "--entry"); strarray_add(spec_args, "__wine_spec_exe_wentry"); } + if (opts->large_address_aware) strarray_add( spec_args, "--large-address-aware" ); } for ( j = 0; j < lib_dirs->size; j++ ) @@ -1271,6 +1275,11 @@ int main(int argc, char **argv) opts.section_align = strdup( Wl->base[++j] ); continue; } + if (!strcmp(Wl->base[j], "--large-address-aware")) + { + opts.large_address_aware = 1; + continue; + } if (!strcmp(Wl->base[j], "-static")) linking = -1; strarray_add(opts.linker_args, strmake("-Wl,%s",Wl->base[j])); } -- 2.11.4.GIT